473,320 Members | 1,859 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,320 software developers and data experts.

Do I need Delegates?

Folks,

I am confused as to how to implement the following solution.

I have a series of processing steps, each of which contains similar features
(forms, etc). Therefore, I create a base class, Step, and subclass from that
for specific steps. The Step class has a method, Execute(), which can return
either Success or Failure.

I have a Step Driver, which instantiates the first Step, calls its Execute()
method, and then, depending on the status, runs the approriate next Step.

How do I know what the approriate next step is? I could embed this in the
Step Driver by building some data structure that can be used to decide what
to do. But this is clumsy.

In fact, each Step should "know" what the next Step for Success is, and what
the next Step for Failure is. The Execute() method, instead of returning
Success or Failure, should simply return the approriate next Step.

My initial attempt resulted, not surprisingly, in immediately using up all
available memory. Futher attmpts resulted in compiler errors.

I need some assistance in implementing the following (pseudo) code. Thanks
in advance for all suggestions!

/Joel Finkel
fi****@sd-il.com

class Step : IDisposable {

string name;
Step SuccessStep; // do this is sucessful
Step NextStep; // handle failure

public Step {
}

public void ShowName() {
MessageBox.Show(name);
}

public Step Execute() {
return _execute();
}

public void Dispose() }
}

private Step _execute() {
// override for each sub class
}
}

class Step_1 : Step {

public Step_1 {
SuccessStep = Step_2; // do this is successful
FailureStep = Step_1a; // handle failure
}

private Step _execute() {
if (do some processing) {
return SuccessStep;
} else {
return FailureStep;
}
}
}

class Step_2 : Step {

public Step_2 {
SuccessStep = null; // this is the last step
FailureStep = Step_2a; // handle failure
}

private Step _execute() {
if (something) {
return SuccessStep;
} else {
return FailureStep;
}
}
}

class Step_Driver {

Step_Drvier() {
}

public void Main() {

Step nextStep;

Step thisStep = new Step_1();

// process steps until there ain't no more
while (thisStep != null) {
nextStep = thisStep.Execute();
thisStep.Dispose();
if (nextStep != null) {
thisStep = new nextStep();
}
}
}
}
Nov 17 '05 #1
16 2172
I don't know, Joel. Seems like you're working too hard here. I presume that
these "Steps" are executed one at a time, in a sequence, like the following:

1, 2, 3, 4, 5, 6, 7, 8

Am I correct? If so, doesn't that look an awful lot like an array or a
Collection, or a List?

--
HTH,

Kevin Spencer
Microsoft MVP
..Net Developer
A watched clock never boils.

"Joel Finkel" <Jo********@discussions.microsoft.com> wrote in message
news:05**********************************@microsof t.com...
Folks,

I am confused as to how to implement the following solution.

I have a series of processing steps, each of which contains similar
features
(forms, etc). Therefore, I create a base class, Step, and subclass from
that
for specific steps. The Step class has a method, Execute(), which can
return
either Success or Failure.

I have a Step Driver, which instantiates the first Step, calls its
Execute()
method, and then, depending on the status, runs the approriate next Step.

How do I know what the approriate next step is? I could embed this in the
Step Driver by building some data structure that can be used to decide
what
to do. But this is clumsy.

In fact, each Step should "know" what the next Step for Success is, and
what
the next Step for Failure is. The Execute() method, instead of returning
Success or Failure, should simply return the approriate next Step.

My initial attempt resulted, not surprisingly, in immediately using up all
available memory. Futher attmpts resulted in compiler errors.

I need some assistance in implementing the following (pseudo) code.
Thanks
in advance for all suggestions!

/Joel Finkel
fi****@sd-il.com

class Step : IDisposable {

string name;
Step SuccessStep; // do this is sucessful
Step NextStep; // handle failure

public Step {
}

public void ShowName() {
MessageBox.Show(name);
}

public Step Execute() {
return _execute();
}

public void Dispose() }
}

private Step _execute() {
// override for each sub class
}
}

class Step_1 : Step {

public Step_1 {
SuccessStep = Step_2; // do this is successful
FailureStep = Step_1a; // handle failure
}

private Step _execute() {
if (do some processing) {
return SuccessStep;
} else {
return FailureStep;
}
}
}

class Step_2 : Step {

public Step_2 {
SuccessStep = null; // this is the last step
FailureStep = Step_2a; // handle failure
}

private Step _execute() {
if (something) {
return SuccessStep;
} else {
return FailureStep;
}
}
}

class Step_Driver {

Step_Drvier() {
}

public void Main() {

Step nextStep;

Step thisStep = new Step_1();

// process steps until there ain't no more
while (thisStep != null) {
nextStep = thisStep.Execute();
thisStep.Dispose();
if (nextStep != null) {
thisStep = new nextStep();
}
}
}
}

Nov 17 '05 #2

"Joel Finkel" <Jo********@discussions.microsoft.com> wrote in message
news:05**********************************@microsof t.com...
Folks,

I am confused as to how to implement the following solution.

I have a series of processing steps, each of which contains similar
features
(forms, etc). Therefore, I create a base class, Step, and subclass from
that
for specific steps. The Step class has a method, Execute(), which can
return
either Success or Failure.

I have a Step Driver, which instantiates the first Step, calls its
Execute()
method, and then, depending on the status, runs the approriate next Step.

How do I know what the approriate next step is? I could embed this in the
Step Driver by building some data structure that can be used to decide
what
to do. But this is clumsy.

In fact, each Step should "know" what the next Step for Success is, and
what
the next Step for Failure is. The Execute() method, instead of returning
Success or Failure, should simply return the approriate next Step.

My initial attempt resulted, not surprisingly, in immediately using up all
available memory. Futher attmpts resulted in compiler errors.

I need some assistance in implementing the following (pseudo) code.
Thanks
in advance for all suggestions!


I agree with Kevin that if this is a static sequence, you should just use an
array of the steps you need to take and iterate it. However, if this is a
more complicated scenario where multiple steps might be taken your on the
right track. However, your code will not compile as is, you are missing
parentheses on your constructors(public Step_2() { ... }) and are
referencing type names instead of creating them (ie new Step_2();). Could
you build a short but complete example[1]?

1. http://www.yoda.arachsys.com/csharp/complete.html
Nov 17 '05 #3
> what the next Step for Success is, and what
the next Step for Failure is.
From his description it doesnt sound to me like a sequence of events, it
sounds more like a decision tree because we potentially would have different
next steps based on the current steps result. I agree with you that it would
be a poor design to have the next step(s) encapsulated within the step. Each
step should only contain the logic necessary to determine its truthality;
this will maximize steps reuseability.
The first big problem is that you are basing the steps method calls to a
class and not an interface, this will abstract yyour problem out and make it
more flexible to new classes.

public interface IStep
{
string Id;
bool Execute();
void Dispose();
}

next encapsulate the decision data, each step would need two of these, one
for true and one for false.
public strut Decision
{
bool Result;
string NextItemId;
}

I would say having an array of two items would be good; steps and the
relationships.

private Hashtable Relationships;
private NameValueCollection Steps;

Steps collection would contain ISteps.Id as the key and IStep as value. So
when you do a Steps["xyz"] you would get back an object of IStep with an Id
of xyz.

Relationships would have the keys of the current ID and would return a value
object Decision.

So how this works overall. After your relationships and steps are loaded
into the arrays. An example of how it would work: 'Step1' first to be
processed calls execute and returns true, iterates over the relationship
collection and acquires the NextItemId's for all decisions that are true. It
then takes these Id's and obtains the ISteps from the Steps collection,
calls execute method and the whole process starts over again. Actually the
process MUST be recursive.

You might also want to look up the Filter design pattern.

Joe
"Daniel O'Connell [C# MVP]" <onyxkirx@--NOSPAM--comcast.net> wrote in
message news:%2****************@tk2msftngp13.phx.gbl...
"Joel Finkel" <Jo********@discussions.microsoft.com> wrote in message
news:05**********************************@microsof t.com...
Folks,

I am confused as to how to implement the following solution.

I have a series of processing steps, each of which contains similar
features
(forms, etc). Therefore, I create a base class, Step, and subclass from
that
for specific steps. The Step class has a method, Execute(), which can
return
either Success or Failure.

I have a Step Driver, which instantiates the first Step, calls its
Execute()
method, and then, depending on the status, runs the approriate next Step.

How do I know what the approriate next step is? I could embed this in
the
Step Driver by building some data structure that can be used to decide
what
to do. But this is clumsy.

In fact, each Step should "know" what the next Step for Success is, and
what
the next Step for Failure is. The Execute() method, instead of returning
Success or Failure, should simply return the approriate next Step.

My initial attempt resulted, not surprisingly, in immediately using up
all
available memory. Futher attmpts resulted in compiler errors.

I need some assistance in implementing the following (pseudo) code.
Thanks
in advance for all suggestions!


I agree with Kevin that if this is a static sequence, you should just use
an array of the steps you need to take and iterate it. However, if this is
a more complicated scenario where multiple steps might be taken your on
the right track. However, your code will not compile as is, you are
missing parentheses on your constructors(public Step_2() { ... }) and are
referencing type names instead of creating them (ie new Step_2();). Could
you build a short but complete example[1]?

1. http://www.yoda.arachsys.com/csharp/complete.html

Nov 17 '05 #4
First of all, thanks for the responses!

Secondly, what I provided was pseudo code, simply to describe the solution I
was thinking about.

Thirdly, Joe, you are right, I need to make a decision as to which next step
to take based on the status of the previous step. It is always a binary
decision.

Since I posted this, I have thought that perhaps each step should actually
NOT encapsulate the decision. This informaiton should be a separate data
structure (object) that I can load from a configuration file.

I also came to the conclusion that a recursive solution is probably best.
My only concern is that the target is a Pocket PC, and I have to be extremely
mindful of memory usage.

Joe, I need to study the code you provide and think about it.

Once again, thanks so much for all your suggestions.

/Joel Finkel
fi****@sd-il.com

"Joe [MCAD]" wrote:
what the next Step for Success is, and what
the next Step for Failure is.


From his description it doesnt sound to me like a sequence of events, it
sounds more like a decision tree because we potentially would have different
next steps based on the current steps result. I agree with you that it would
be a poor design to have the next step(s) encapsulated within the step. Each
step should only contain the logic necessary to determine its truthality;
this will maximize steps reuseability.
The first big problem is that you are basing the steps method calls to a
class and not an interface, this will abstract yyour problem out and make it
more flexible to new classes.

public interface IStep
{
string Id;
bool Execute();
void Dispose();
}

next encapsulate the decision data, each step would need two of these, one
for true and one for false.
public strut Decision
{
bool Result;
string NextItemId;
}

I would say having an array of two items would be good; steps and the
relationships.

private Hashtable Relationships;
private NameValueCollection Steps;

Steps collection would contain ISteps.Id as the key and IStep as value. So
when you do a Steps["xyz"] you would get back an object of IStep with an Id
of xyz.

Relationships would have the keys of the current ID and would return a value
object Decision.

So how this works overall. After your relationships and steps are loaded
into the arrays. An example of how it would work: 'Step1' first to be
processed calls execute and returns true, iterates over the relationship
collection and acquires the NextItemId's for all decisions that are true. It
then takes these Id's and obtains the ISteps from the Steps collection,
calls execute method and the whole process starts over again. Actually the
process MUST be recursive.

You might also want to look up the Filter design pattern.

Joe
"Daniel O'Connell [C# MVP]" <onyxkirx@--NOSPAM--comcast.net> wrote in
message news:%2****************@tk2msftngp13.phx.gbl...

"Joel Finkel" <Jo********@discussions.microsoft.com> wrote in message
news:05**********************************@microsof t.com...
Folks,

I am confused as to how to implement the following solution.

I have a series of processing steps, each of which contains similar
features
(forms, etc). Therefore, I create a base class, Step, and subclass from
that
for specific steps. The Step class has a method, Execute(), which can
return
either Success or Failure.

I have a Step Driver, which instantiates the first Step, calls its
Execute()
method, and then, depending on the status, runs the approriate next Step.

How do I know what the approriate next step is? I could embed this in
the
Step Driver by building some data structure that can be used to decide
what
to do. But this is clumsy.

In fact, each Step should "know" what the next Step for Success is, and
what
the next Step for Failure is. The Execute() method, instead of returning
Success or Failure, should simply return the approriate next Step.

My initial attempt resulted, not surprisingly, in immediately using up
all
available memory. Futher attmpts resulted in compiler errors.

I need some assistance in implementing the following (pseudo) code.
Thanks
in advance for all suggestions!


I agree with Kevin that if this is a static sequence, you should just use
an array of the steps you need to take and iterate it. However, if this is
a more complicated scenario where multiple steps might be taken your on
the right track. However, your code will not compile as is, you are
missing parentheses on your constructors(public Step_2() { ... }) and are
referencing type names instead of creating them (ie new Step_2();). Could
you build a short but complete example[1]?

1. http://www.yoda.arachsys.com/csharp/complete.html


Nov 17 '05 #5

"Joel Finkel" wrote:
First of all, thanks for the responses!

Secondly, what I provided was pseudo code, simply to describe the
solution I was thinking about.

Thirdly, Joe, you are right, I need to make a decision as to which
next step to take based on the status of the previous step. It is
always a binary decision.
A decision table might be helpful.

http://en.wikipedia.org/wiki/Decision_table
Since I posted this, I have thought that perhaps each step should
actually NOT encapsulate the decision. This informaiton should be a
separate data structure (object) that I can load from a configuration
file.

I also came to the conclusion that a recursive solution is probably
best. My only concern is that the target is a Pocket PC, and I have to
be extremely mindful of memory usage.


I've written a small decision table toolkit in C# (which I haven't
released yet to the public). It does indeed use recursion. It also uses
delegates, so your initial question is in line, at least, with the way I
solved this problem. This is the recursive function for making a
"decision":

private int Decide(object[] args, int actionIndex, int conditionIndex)
{
#region Guards

if(conditionIndex >= conditions.Length)
{
return actionIndex;
}

#endregion

Condition c = conditions[conditionIndex];

if(c(args))
{
actionIndex |= 1 << conditionIndex;
}

return Decide(args, actionIndex, conditionIndex + 1);
}

Some explanation:

Decision tables are made up of four quadrants. The upper left corner
contains the rows of conditions. Here, conditions are represented by
delegates that return a boolean value. The 'conditions' variable is a
collection of condition delegates. The Decide function recursively calls
itself until it has reached the last condition.

Each condition is called and passed the 'args' variable, which could
represent anything. If the condition returns true, a flag is set into
the 'actionIndex'. When the Decide method finishes, the 'actionIndex'
will be used to determine which actions, also represented by delegates,
will be invoked. That part gets a little complicated, but not too much
so.

Anyway, if any of this sounds intriguing or useful, let me know, and I
can go into more detail.



Nov 17 '05 #6
Here is a solution that seems to work. The implementation of MyCollection is
not shown. Comments are appreciated. Thanks in advance.

/Joel Finkel
fi****@sd-il.com
public delegate bool myDelegate();

public class Step
{
public Step()
{
}

public bool Execute(myDelegate p_process)
{
// run the customized processing
return p_process();
}
}
public class StepProcess
/*
* This class contains customized code for all the steps we have defined.
* It also contains a standard form.
*/
{
// Most steps need access to a standard form
private StepForm _myForm;

public StepProcess()
{
// create an instance of the standard form
_myForm = new StepForm();
}

public void Dispose()
{
// cleanup
_myForm.Dispose();
}

public bool Step1()
{
_myForm.Text = "Step 1";
return _myForm.ShowDialog() == DialogResult.Yes;
}

public bool Step2()
{
_myForm.Text = "Step 2";
return _myForm.ShowDialog() == DialogResult.Yes;
}

public bool Step3()
{
MessageBox.Show("Hi, I am Step 3");
return true;
}
}
public class Decision
{
private string _successStep;
private string _failureStep;

public string successStep
{
get { return _successStep; }
}

public string failureStep
{
get { return _failureStep; }
}

public Decision(string p_successStep, string p_failureStep)
{
_successStep = p_successStep;
_failureStep = p_failureStep;
}
}
public class StepDriver
{
static void Main()
{
// create an instance of the object that has all the steps and the
standard form
StepProcess myStepProcess = new StepProcess();

/*
* TODO: this can probably be done through reflection
*/
// a bag of step procesees
MyCollection StepProcesses = new MyCollection();
StepProcesses.Add("Step1", new myDelegate(myStepProcess.Step1));
StepProcesses.Add("Step2", new myDelegate(myStepProcess.Step2));
StepProcesses.Add("Step3", new myDelegate(myStepProcess.Step3));

/*
* TODO: create this from a configuration file
*/
// a bag of decisions
MyCollection Decisions = new MyCollection();
Decisions.Add("Step1", new Decision("Step2", "Step1"));
Decisions.Add("Step2", new Decision("Step3", "Step1"));
Decisions.Add("Step3", new Decision("", "Step1"));

// status of steps' execution
bool stat;

// use this to decide what the next step is
Decision thisDecision;

// use this to hold the proper function
myDelegate thisProcess;

// use this to execute the function
Step myStep = new Step();

// start with Step 1
string thisStep = "Step1";

while (thisStep != "")
{
// get this step's decision from the bag
thisDecision = (Decision) Decisions[thisStep];

// get the step's process from the bag
thisProcess = (myDelegate) StepProcesses[thisStep];

// ececute the process
stat = myStep.Execute(thisProcess);

// do the right thing
if (stat)
{
thisStep = thisDecision.successStep;
}
else
{
thisStep = thisDecision.failureStep;
}
}

// cleanup
myStepProcess.Dispose();

// tell the user we are done
MessageBox.Show("Done");
}
}
Nov 17 '05 #7
I'm interested in the details. Please explain.

"Leslie Sanford" <ja**********@BiteMeHotmail.com> wrote in message
news:wN********************@comcast.com...

"Joel Finkel" wrote:
First of all, thanks for the responses!

Secondly, what I provided was pseudo code, simply to describe the
solution I was thinking about.

Thirdly, Joe, you are right, I need to make a decision as to which
next step to take based on the status of the previous step. It is
always a binary decision.


A decision table might be helpful.

http://en.wikipedia.org/wiki/Decision_table
Since I posted this, I have thought that perhaps each step should
actually NOT encapsulate the decision. This informaiton should be a
separate data structure (object) that I can load from a configuration
file.

I also came to the conclusion that a recursive solution is probably
best. My only concern is that the target is a Pocket PC, and I have to
be extremely mindful of memory usage.


I've written a small decision table toolkit in C# (which I haven't
released yet to the public). It does indeed use recursion. It also uses
delegates, so your initial question is in line, at least, with the way I
solved this problem. This is the recursive function for making a
"decision":

private int Decide(object[] args, int actionIndex, int conditionIndex)
{
#region Guards

if(conditionIndex >= conditions.Length)
{
return actionIndex;
}

#endregion

Condition c = conditions[conditionIndex];

if(c(args))
{
actionIndex |= 1 << conditionIndex;
}

return Decide(args, actionIndex, conditionIndex + 1);
}

Some explanation:

Decision tables are made up of four quadrants. The upper left corner
contains the rows of conditions. Here, conditions are represented by
delegates that return a boolean value. The 'conditions' variable is a
collection of condition delegates. The Decide function recursively calls
itself until it has reached the last condition.

Each condition is called and passed the 'args' variable, which could
represent anything. If the condition returns true, a flag is set into
the 'actionIndex'. When the Decide method finishes, the 'actionIndex'
will be used to determine which actions, also represented by delegates,
will be invoked. That part gets a little complicated, but not too much
so.

Anyway, if any of this sounds intriguing or useful, let me know, and I
can go into more detail.




Nov 17 '05 #8

"Joe [MCAD]" wrote:
I'm interested in the details. Please explain.


I wanted to write a small toolkit that implements decision tables:

http://en.wikipedia.org/wiki/Decision_table

I implemented the toolkit by writing a DecisionTable class that uses a
collection of delegates representing the conditions. In addition, it has
a collection of delegates representing the actions. The DecisionTable
has a Decide method. When the Decide method is called, the DecisionTable
recursively goes through its condition delegates, invoking each one.

If a condition returns true, a bitwise operation takes place setting a
bit in an index variable to 1. This bit is offset so that each bit in
the index variable represents the result of a specific condition. When
the Decide method finally finishes, it returns the index variable. It's
value is used to retrieve the actions to invoke from a collection. The
actions corresponds to the result of the conditions.

The toolkit is pretty basic right now. I need to spend some time with it
to polish it up.
Nov 17 '05 #9
You definitely got my attention. I have been working on
http://sourceforge.net/projects/sdsre because I needed (and still do) a way
to have rules in XML. On this current release I came to the conclusion that
execution of the rules shouldnt actually be contained in the rules
themselves, the associations between rules is becoming too complicated and
performance is slowing down on larger sets. From what I read so far I am
intereseted in implementing a decision table into SRE in its next rewrite,
mabey intergrate both of the projects. I had some questions i havent
understood yet, in a rule based system some rules are dependent on other
rules truthality, and some take priority over others. In SRE this has all
been internalized into the engine to make the rules simple (main goal of the
project). How would a decision table be optimized to evaluate only those
rules that could be executed in the current context. Another issue,
exaluating expressions are expensive and some rules are practally identical
to other rules except for maney an AND statement or two, would it be
possible to break down expressions into identical subexpressions and
evaluate only once. I would like to see your project

Joe
"Leslie Sanford" <ja**********@BiteMeHotmail.com> wrote in message
news:l5******************************@comcast.com. ..

"Joe [MCAD]" wrote:
I'm interested in the details. Please explain.


I wanted to write a small toolkit that implements decision tables:

http://en.wikipedia.org/wiki/Decision_table

I implemented the toolkit by writing a DecisionTable class that uses a
collection of delegates representing the conditions. In addition, it has a
collection of delegates representing the actions. The DecisionTable has a
Decide method. When the Decide method is called, the DecisionTable
recursively goes through its condition delegates, invoking each one.

If a condition returns true, a bitwise operation takes place setting a bit
in an index variable to 1. This bit is offset so that each bit in the
index variable represents the result of a specific condition. When the
Decide method finally finishes, it returns the index variable. It's value
is used to retrieve the actions to invoke from a collection. The actions
corresponds to the result of the conditions.

The toolkit is pretty basic right now. I need to spend some time with it
to polish it up.

Nov 17 '05 #10

"Joe [MCAD]" wrote:
You definitely got my attention. I have been working on
http://sourceforge.net/projects/sdsre because I needed (and still do)
a way to have rules in XML. On this current release I came to the
conclusion that execution of the rules shouldnt actually be contained
in the rules themselves, the associations between rules is becoming
too complicated and performance is slowing down on larger sets. From
what I read so far I am intereseted in implementing a decision table
into SRE in its next rewrite, mabey intergrate both of the projects. I
had some questions i havent understood yet, in a rule based system
some rules are dependent on other rules truthality, and some take
priority over others. In SRE this has all been internalized into the
engine to make the rules simple (main goal of the project). How would
a decision table be optimized to evaluate only those rules that could
be executed in the current context. Another issue, exaluating
expressions are expensive and some rules are practally identical to
other rules except for maney an AND statement or two, would it be
possible to break down expressions into identical subexpressions and
evaluate only once. I would like to see your project.


Hmm, I'm not entirely sure I understand your questions. Could be what
you're describing is over my head. :-) However, I'll attempt to give you
a hopefully useful answer.

As far as contexts go, you may wind up with a decision table for each
context. A decision table answers a specific question, e.g. Should I
refund this customer his/her money? You will have a decision table for
each question that needs answering.

I think when you say rule, what you are talking about are conditions.
Correct? If a condition is true, do such and such. In a decision table,
conditions are evaluated from top to bottom. So you can think of the
conditions as having descending levels of priority, i.e. the top
condition is the most important.

As far as optimization, the outcome of a condition does not necessarily
have to be true or false, it can be any number of values. Many decision
tables use three values, yes, no, and doesn't matter. Say one condition
in a decision table is true, based on this result, it does not matter
what the result of the next condition is, so you can skip evaluating it.
I guess you could look at this as a form of optimization.

My decision toolkit only deals with boolean values. I haven't explored
adding more than two values for the conditions.

Anyway, I hope some of this is informative and answers some of your
questions.

Nov 17 '05 #11
Joel,

I would attack this problem in one of two ways. I think that you're on
the right track with your Decision class, but it could be tighter
still:

public class Decision
{
public Step _step;
public Decision _success;
public Decision _failure;

public Decision(Step stepToRun, Decision success, Decision failure)
{
this._step = stepToRun;
this._success = success;
this._failure = failure;
}

public Decision ExecuteStep()
{
if (this._step.Execute())
{
return this._success;
}
else
{
return this._failure;
}
}
}

Now you build your decision tree from bottom to top:

Decision d3a = new Decision(new Step3a(), null, null);
Decision d3b = new Decision(new Step3b(), null, null);
Decision d3c = new Decision(new Step3c(), null, null);
Decision d3d = new Decision(new Step3d(), null, null);
Decision d2a = new Decision(new Step2a(), d3a, d3b);
Decision d2b = new Decision(new Step2b(), d3c, d3d);
Decision d1 = new Decision(new Step1(), d2a, d3b);

Now running through your decision tree requires no recursion. Recursion
is necessary only if you need to remember where you've been in case you
have to backtrack, or remember your past trail for some other reason.
The only place I think that you could use recursion is in building your
decision tree, possibly. Anyway, walking the tree requires no recursion
in your case because you never backtrack:

Decision currentDecision = d1;
while (currentDecision != null)
{
currentDecision = currentDecision.ExecuteStep();
}

Now, on the compact framework, the only drawback you have with this
approach is that you have to instantiate all of your Step objects when
you build your decision tree. If your Step objects have few or no
fields (object state) associated with them, this is no problem.
However, if your Step objects have associated with them lots of private
data, this could create memory shortages, because remember that a tree
of depth n contains n(n - 1) nodes, but you execute only n of them on
each pass. So, in the case that your Step objects each consumes a lot
of memory, you could trade speed for space and instantiate a Step only
when you're about to execute it:

public class Decision
{
public Type _stepType;
public Decision _success;
public Decision _failure;

public Decision(Type typeOfStep, Decision success, Decision
failure)
{
if (!typeOfStep.IsSubclassOf(typeof(Step)))
{
throw new ArgumentException(String.Format("Step type {0} is
not a type of Step", typeOfStep), "typeOfStep");
}
this._stepType; = typeOfStep;
this._success = success;
this._failure = failure;
}

public Decision ExecuteStep()
{
Step thisStep =
(Step)this._typeOfStep.GetConstructor(Type.EmptyTy pes).Invoke(null);
if (thisStep.Execute())
{
return this._success;
}
else
{
return this._failure;
}
}
}

Of course, this assumes that every Step object that you pass to your
Decision implements a constructor that takes no arguments, a
restriction that you didn't have in the first solution. This solution
using reflection is necessarily slower than the first solution. I would
use it only if your various Step classes have a lot of stored state
(fields) and allocating them all up front is impractical because of
memory limitations.

You could also, as Joe pointed out, create an IStep interface instead
of inheriting from a Step base class, but I disagree with Joe that
using a common ancestor class is a "big problem." An interface buys you
something only if you may want to make Steps out of diverse classes
from different parts of your class hierarchy. If your design has each
Step as encapsulating nothing but a step in your decision tree, and you
will never, for example, have an Employee who is also a type of Step,
or a PurchaseOrder that is also a type of Step, then creating an IStep
interface just makes things muddier and harder to understand and buys
you nothing in return. If, however, you think that you may want to take
various classes from different places in your class hierarchy and add
"Step" functionality to them, then an interface is definitely the way
to go.

Nov 17 '05 #12
Sorry. That should have been "a tree of depth n contains n(n + 1) / 2
nodes." I'm forgetting my grade 10 math here. :-)

Nov 17 '05 #13
Boy, I really am forgetting my math. That should have been "a tree of
depth n contains 2 ^ (n + 1) - 1 nodes," which is even worse than I
originally calculated.

Anyway, I thought about this some more last night, wondering if there
were some way to conserve space in the data structure. It is possible
to use a one-dimensional array to hold your Step objects, and use a
mathematical formula to decide which array entry to go to next based
upon the result of executing a step.

However, this data structure is much more complicated (because it
doesn't really represent your structure) and, if you have a ragged tree
of Decisions, doesn't really gain you anything. (The worst case is that
you have exactly one decision at the deepest level of the tree, in
which case you would allocate at least (2 ^ n) - 1 array entries for
nothing.) So, even though the Decision structure looks like it will use
up a lot of memory, it's still better than any alternative I can think
of.

Nov 17 '05 #14
I agree with you that using an interface does add another level of
complexity and if its known to always be of a certain type that that would
be the best choice. i would like to add that if it was determined that an
interface would be a better choice whether use of other types or concern for
future changes, I would argue that a decision table is probably radically
different from the application as a whole and should be seperated off into a
service.

"Bruce Wood" <br*******@canada.com> wrote in message
news:11**********************@g49g2000cwa.googlegr oups.com...
You could also, as Joe pointed out, create an IStep interface instead
of inheriting from a Step base class, but I disagree with Joe that
using a common ancestor class is a "big problem." An interface buys you
something only if you may want to make Steps out of diverse classes
from different parts of your class hierarchy. If your design has each
Step as encapsulating nothing but a step in your decision tree, and you
will never, for example, have an Employee who is also a type of Step,
or a PurchaseOrder that is also a type of Step, then creating an IStep
interface just makes things muddier and harder to understand and buys
you nothing in return. If, however, you think that you may want to take
various classes from different places in your class hierarchy and add
"Step" functionality to them, then an interface is definitely the way
to go.

Now you build your decision tree from bottom to top:

Decision d3a = new Decision(new Step3a(), null, null);
Decision d3b = new Decision(new Step3b(), null, null);
Decision d3c = new Decision(new Step3c(), null, null);
Decision d3d = new Decision(new Step3d(), null, null);
Decision d2a = new Decision(new Step2a(), d3a, d3b);
Decision d2b = new Decision(new Step2b(), d3c, d3d);
Decision d1 = new Decision(new Step1(), d2a, d3b);

Now running through your decision tree requires no recursion. Recursion
is necessary only if you need to remember where you've been in case you
have to backtrack, or remember your past trail for some other reason.
The only place I think that you could use recursion is in building your
decision tree, possibly. Anyway, walking the tree requires no recursion
in your case because you never backtrack:
Building the tree in this manner is going to be impossible if the tree at
all contains any kinds of loops or jumps ahead of other nodes. Using
delegates instead of instantiation in the Decision constructor will allow
for this. But yes, this will work.

Sorry. That should have been "a tree of depth n contains n(n + 1) / 2
nodes." I'm forgetting my grade 10 math here. :-)

I think its going to worse that that, might need a memory upgrade.
Nov 17 '05 #15
Hi Joel,

I've just read your post and think you could do something as follows. I
have not read all replies carefully, so sorry if it is out of sync.

public interface IStep
{
Result Execute();
}

public interface IStepNavigator
{
IStep GetNextStep(IStep source, Result sourseResult)
}

public class XmlStepNavigator
{
// get step navigation from xml file, app config file, DB, etc.
}

public class StepDriver
{
public ExecuteStep(IStep step, bool autoDispose)
{
IStepNavigator nav = someContextOrFactory.StepNavigator;
while( step != null )
{
Result r = step.Execute();

if (autoDispose)
{
IDisposable d = step as IDispoable;
if (d != null) d.Dispose();
}

step = nav.GetNextStep(r);
}
}

Regards,
Thi

Nov 17 '05 #16
Thanks to all who responded. I decided to simplify the code, which resulted
in a smaller and faster runtime package.

Rather than using delegates, I create a Step class that has private static
methods (one for each step that we have defined). The Step has one public
static method called "Run," which takes the name of the step as a string.
Using a switch statement, if calls the proper private method.

I save space and improve speed because no instance of Step has to be
created. Previosuly, I had to create an instance for each step and load them
into an array.

By backing off of OOP, I get simpler, smaller, and faster code.

Regards,
Joel
Nov 28 '05 #17

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

6
by: Jeffrey T. Smith | last post by:
Back when the new J2SE1.5 features were announced, there was a JavaLive community chat (http://java.sun.com/developer/community/chat/JavaLive/2003/jl0729.html) in which Neal Gafter explains the...
2
by: Jon Davis | last post by:
The garbage handler in the .NET framework is handy. When objects fall out of scope, they are automatically destroyed, and the programmer doesn't have to worry about deallocating the memory space...
4
by: Stephen | last post by:
I am new to C# and can't get my head round what delegates are and what they are for. can anyone enlighten me?
30
by: Burkhard | last post by:
Hi, I am new to C# (with long year experience in C++) and I am a bit confused by the language construct of events. What is it I can do with events that I cannot do with delegates? At the moment...
6
by: Jon Davis | last post by:
I've used delegates fairly heavily for several years in C# for event handling and for starting threads. Does anyone have any real-world scenarios where delegates were both extremely useful and...
0
by: bharathreddy | last post by:
Delegates Here in this article I will explain about delegates in brief. Some important points about delegates. This article is meant to only those who already know delegates, it will be a quick...
6
by: =?Utf-8?B?T2xkQ2FEb2c=?= | last post by:
My question is regarding the use of delegates in C#. I see how .Net uses delegates to wire event handlers to events. It’s an object created by a single line of code by the system and that makes...
7
by: Siegfried Heintze | last post by:
I'm studying the book "Microsoft Visual Basic.NET Language Reference" and I would like some clarify the difference between events and delegates. On page 156 I see a WinForms example of timer that...
5
by: puzzlecracker | last post by:
thanks
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: Vimpel783 | last post by:
Hello! Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
0
by: jfyes | last post by:
As a hardware engineer, after seeing that CEIWEI recently released a new tool for Modbus RTU Over TCP/UDP filtering and monitoring, I actively went to its official website to take a look. It turned...
0
by: ArrayDB | last post by:
The error message I've encountered is; ERROR:root:Error generating model response: exception: access violation writing 0x0000000000005140, which seems to be indicative of an access violation...
1
by: PapaRatzi | last post by:
Hello, I am teaching myself MS Access forms design and Visual Basic. I've created a table to capture a list of Top 30 singles and forms to capture new entries. The final step is a form (unbound)...
1
by: Shællîpôpï 09 | last post by:
If u are using a keypad phone, how do u turn on JavaScript, to access features like WhatsApp, Facebook, Instagram....
0
by: af34tf | last post by:
Hi Guys, I have a domain whose name is BytesLimited.com, and I want to sell it. Does anyone know about platforms that allow me to list my domain in auction for free. Thank you

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.