I wonder whether this pattern that I have frequently used is common and has a name:
- an algorithm is a class
- its parameters are passed via the constructor of the class
- calling a parameter-less
run
method triggers the computation - the result(s) are fetched by calling getter methods
An example (in Python for simplicity):
class MyAlgorithm:
def __init__(self, input, param1, param2):
self.param1 = param1
self.param2 = param2
self.input = input
def run(self):
...
return self
def getResultA(self):
...
def getResultB(self):
...
As a second question: What are the pros and cons of this pattern? Is there a good reason to have a separate run
-method rather than having the constructor do the computation?
I suspect something like this is reasonably common. I've used it in my code, actually.
The main use case is where you have a bunch of data and you have a variety of transformations you want to do on it. For instance I may have a matrix of prices (open/high/low/close, so actually 4) and a matrix of earnings.
I want to construct outputs that take these ingredients and mix them in various ways. So for instance, one function produces the return between the open and close, and another produces the ratio of earnings to close prices. You could go on forever producing these outputs, and sometimes you want to turn some of them on or off, so it's nice to have a way to keep them separate.
So you do what you've demonstrated. You have a list of these algos in a file, and you pass them all references to all the data. You then loop over them and hit "run", and have a look at the outputs.
Pros: keep each algo separate from the others, ability to choose which to run.
Cons: Need to separate each algo into different units, not really worthwhile if you don't have several.
Why not do the calculation in the run method? It will still function, but normally we like to keep construction separate from calculation.
Sounds a bit like https://en.wikipedia.org/wiki/Command_pattern. I was looking for something containing the idea of a delegate.
First answer:
I have encounterd it widely, in several APIs. I didn't mind using when it was documented (you need to
run()
before youget()
the results, etc), though sometimes the input objects were many, and hard to setup properly. However very few documentations were complete, and if they are at all necessary, then it could be done better.However when I had to extend it, it proved very troublesome (required Ctor is messy, results sometimes hard to extend, Status unknown (has it
run()
yet?), some result objects might be unavailbable (for good reasons)...Second answer:
As others said, looks like Command Pattern.
Now for a few comments on extendability:
(Take with a grain of salt, may not apply to your application.)
That is good. (containment of an algorithm to an entity).
But that is not very extensible - only through inheritance, which is restrictive. Too many APIs force inheritance because they believe they are the heart of your application. What if I want to extend something else to do the job, like a
Map
?What would be better is:
solver
class can be interacted with through an interfacealgorithm
implementations of thesolver
When I want a solver instance, I can create one from scratch by extending the interface with complete freedom, or reuse some known implementation through (multiple) inheritance.
That's an implementation detail. Why force someone to handle objects, for which they may not care? How do you even enforce Constructors to have specific parameters? What if the initial state is complex and multi-faceted, and requires a Builder?
No pattern should require a specific constructor (except en empty one?). Also, beware, constructors shouldn't do too much computation.
getResult()
methods?null
-able (ugh), anOptionalResult
, or have aisAvailable()
method on it.Algorithm
instance afterwards? is it re-usable? Can Ireset()
it? I might have been costly to set up.I have found it it MUCH clearer everywhere I found it, to have (JAVA here):
In here, implementations can vary, each instance of solver has a completely internal state which may speed it up (like a cache) for later use, but is distinct from the SovlerResult object, which is what I wanted. The SolverInput can be created as I want, and SolverResult can be a specialized result class of the solver instance, capable of giving better insight (with additional
getComputationQuality()
,getConvergenceRate()
etc.).I think separating the input, the solver, and the output is much more flexible. Design-patterns should not be an enforcement tool, but more a facilitator tool. It even allows your design patter by implementing all three interfaces at once (not that I recommended it).
It is command pattern, where the intention is decoupling the implementation of the main operation of some classes(concrete Command classes) from its consumer(CommandHandler). In summary a client class who executes
someCommandObject.run();
is free of any method arguments, hence the method implementation inside that concrete class can freely implement any desired operation which is specific to that particular class. So the client class can freely executeanyCommandObject.run();
methods, since their method declarations are not rigid with any typed parameters.It is the same thing we are having in
Thread.run();
in Java Threads.Yes. The constructor should never have explicit calculations. The purpose of a constructor is simply construct the object, not to uncover any behaviors. If you want to expose them, that's why methods are there.
That is variation of command pattern.
The point is that you can pass the command to some other code for execution and then read the result back, without the execution code needing to know specific parameters/return types of the operation.
As for constructor doing the computation. Constructors shouldn't do any computation. Period.