0

I want to know how can I check for pre-requisites of a routine when I call it, so that it might execute or notify its non-executability. Language is C#.

I am implementing a Pipeline design-pattern with a Controller object, a DataContainer object, and some Task objects. When the controller asks a task for execution, it is the responsibility of each task to check for its applicability. Specifically, it should check the DataContainer object for available data.

I could imagine some ways to do it in Python:

# 
if Task.can_run():
    Task.run()
else:
    Task.notify_controller()

# 
if Controller.check_runnability(Task):
    Task.run()
else:
    Controller.do_something_else()

# Task.can_run() throws exception instead of returning boolean:
try:
    Task.can_run();
except:
    Controller.do_something_else()  # or maybe Task.notify_controller()
else:
    Task.run()

# not sure about syntax for the following assertion, but you get the idea
assert (Task.can_run(), Task.notify_controller())
Task.run()

What I would like to know (and didn't find with Google) is the "canonical"/most-common/"right" C# idiom for starting a routine only if some pre-requisite is met.

heltonbiker
  • 26,657
  • 28
  • 137
  • 252
  • What is the controller meant to do with a task that say's it can't run? – Tony Hopkinson Feb 22 '13 at 14:58
  • @TonyHopkinson it would depend on higher level conditions, outside of Task or even Controller scope. For example, the Controller might call an alternative Task which uses a different algorithm, or just bubble up (to the GUI eventually) the information that some (and which) pre-requisite doesn't apply. – heltonbiker Feb 22 '13 at 17:02
  • Given that I'd eijther have controller call canrun, or simply pass couldn't run back from run. Can't see any value in making it more complex than that. – Tony Hopkinson Feb 22 '13 at 17:19

1 Answers1

1

The first example is the most common pattern. The second to me is just a variation of the first with a less semantic naming convention.

The third example I would stay away from. Exceptions shouldn't be used to direct the normal control of flow. http://msdn.microsoft.com/en-us/library/vstudio/ms229030(v=vs.100).aspx

EDIT: I take that back. The second example looked similar but instead it asks the controller to determine whether the task can run or not. If the "runability" is based solely on the content of the task object and not based on some state of the controller then I see no need to complicate things by putting the check in the controller. If the logic is similar enough I would use a base task class to keep things DRY.

EDIT: I'm not clear on your exact use case but so this could be off base completely but to me seems like the controller would ask the task if it is ready to run and if so it would run the task and if not it would do something else.

if (task.CanRun)
{
    controller.Run(task);
}

else
{
    //Do whatver.
}

Furthermore, if the logic is encapsulated within the controller regarding what should be done when a task cannot be run then perhaps the run method should return a boolean so the caller can do something additional if need be. In that scenario the caller just passes the task to the controller run method and inside there the controller check if the task can run or not and acts accordingly.

Sacrilege
  • 795
  • 9
  • 25
  • Interesting. According to the link I provided in the question, the task should pre-test itself when being called by the controller, which in turn just handles any exception in `Task.run()` (outside normal control flow). The examples are just suggestions, since I have never done that before, but apparently it is a good practice in production-quality code. – heltonbiker Feb 22 '13 at 17:09
  • 1
    (for the sake of "enlightenment" about this design-pattern, which Microsoft calls Pipes-And-Filters, the following post is absolutely worth reading: http://keyvan.io/pipes-and-filters-pattern-in-net) – heltonbiker Feb 22 '13 at 17:26