Hi,
I see the following situation quite often in system design and I feel it is an anti-
pattern, what is your take?
I call it the doAnything() method, where on an interface for a component much of the
detail of the contract of the component is hidden by having overly generalised
methods.
The extreme degenerate case of this is when the interface has one method called
something like "doStuff" that takes the most general parameter type available and
returns the most general parameter type possible, for e.g. in JAVA:
public Object doStuff(Object params)
If you see this on the interface it is also a good indicator that there may be poor
separation of concerns in the implementation with lots of conditional code.
Of course there are many degrees of this, and sometimes it is very slight e.g. the
method name might be very explanatory, the return parameter may well be very
explicit and there is only slight variability implicit in the definition:
public Transaction makePayment(boolean isCreditCard)
which could be:
public Transaction makePaymentWithCreditCard();
public Transaction makePaymentWithCash();
What I see underneath all of this is a general principle of needing to justify why
the explicitness of the contract is being traded off. I believe that any
generalisation of a contract adds a risk of Separation of Concerns being threatened.
So it needs to be done explicitly as it is a trade-off and what you get for it needs
to be worth what you have lost.
IT is interesting now to consider the following design concerns in this light:
The Command Pattern:
This can look a lot like a do anything method, but usually the individual command
instances are fairly explicit in how they work and it also doesn't usually imply
conditional code with poor separation of concerns.
Most importantly though is that usually there is a major functional gain such as Undo
being implemented. If this is not the case, then one should question why it is being
used.
Late Binding:
If the parameters are very generalised this implies much later binding, in JAVA it
will be done with RTTI for instance. This too is a cost.
Aspect like behaviour:
I have seen this technique used recetly to implement "Aspect Like Behaviour" in an
environment that did not have native support for that (calling Stored Procs in
Oracle). The doAnything() method in this case did logging and authentication and then
delegated the call on to the actual method (Stored Proc). So on the plus side somewhere in the design there is still a place to define the contract, although it is now bound much later.
Soap:
This is used for inter-component calls and in some sense it can be seen as a generic
method that takes XML, processes it and returns XML. However much mitigation has been
done to make the contract explicit with other mechanisms (WSDL), and here
late-binding is in fact desired as these are inter-component calls which should be
late bound to achieve independent replace-ability.
Shoo-wee, A bit of an essay hey.
Cheers A