Skip to main content

You wrote

I know the following is bad

and already here is 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 refactoring it to a.doYWhenX(); - or not. But before you decide about this refactoring, also check

  • whether doYWhenX() is a useful abstraction in your context

  • whether doYWhenX() has some reuse potential

  • whether it helps to make a.isX (or a.isX()) private

  • whether 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); or

  • to b.doYQWhenXP(a); or

  • to myService.doYQWhenXP(a,b), or

  • leave 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.

Doc Brown
  • 214k
  • 34
  • 394
  • 603