You wrote
I know the following is bad
and already here is already a misconception: thinking religiously in terms of good and bad about this. My interpretation of Tell-Don't-Ask is,: when you see a code snippet like
if(a.isX){
a.doY();
}
you may consider to refactorrefactoring it to a.doYWhenX();
- or not. But before you decide about this refactoring, also check
ifwhether
doYWhenX()
is a useful abstraction in your contextifwhether
doYWhenX()
has some reusagereuse potentialifwhether it helps to make
a.isX
(ora.isX()
) privateifwhether it makes the using code more readable
is it worth the hassle?
So my recommendation is to change your mindset about the "Tell-Don't-Ask principle" - it is a rough guideline, a rule-of-thumb design heuristic, nothing more.
Now apply this to your case with two objects:
if(a.isX && b.isP){
a.doY();
b.doQ();
}
Whether it it more suitable to refactor this
to
a.doYQWhenXP(b);
orto
b.doYQWhenXP(a);
orto
myService.doYQWhenXP(a,b)
, orleave the code as it is
depends heavily on the context,: which variant in your real world context creates highest readability, best reusability, most sensible abstraction, or best encapsulation. Meaningless names like doX
or isP
alone are not suitable for making such a decision.