First, let me explain what I mean by inversion of control and tell, don’t ask in this context. I have 3 objects ClassA, ClassB and ClassC. ClassA is a consumer of target object ClassB.
Inversion of control here means two things:
- passing in required arguments into each method on the target object ClassB
- assumes that target objects are made up of atomic methods to be controlled by either ClassA the consumer or public methods on ClassB
Tell, don’t ask here the following scenario:
- we have target task ClassC::d() and can either fetch arguments ClassB::E and ClassB::F on classA, then inject them into ClassC::d(). Or, the alternative that is instantiate ClassB inside ClassC. Then on ClassC::D(), we pull and modify the encapsulated ClassB instance and use it however we deem fit, be it by calling other local methods or what not ( utilize other classes), as opposed to returning a value after d’s atomic operation for it
Are these terms mutually exclusive? I got here by comparing both patterns. In pattern 1 which I appreciate atomic methods for their testability. I don’t have to bother about complex dependency chains.
However, in pattern 2, TDA ( given this understanding of it) is obviously cleaner and the consumer only ever worries about ClassC. This reveals pattern 1 equally creates a kind of dependency problem as regards testing. At what point is acceptable for an action in a class to be responsible for deciding what parameters it runs with.
One of my primary motives in all this is creation of an enabling environment for unit tests and a clear API (non-cluttered) for consumers