In this article, we are going to walkthrough a basic but one golden rule that most of us ignored in practice is “Tell, Don’t Ask”.
What Does “Tell, Don’t Ask” Mean?
“Tell an object what to do, don’t ask it for data and make decisions for it.”
In other words, delegate behavior to objects instead of pulling their data out and doing the work yourself. When you break this rule, you’re treating objects like mere data holders and pushing logic out into other places. Means Less Encapsulation.
The bad code:
if (user.getRole().equals("admin")) {
grantAdminAccess();
}
This example pulls out internal state from user
and makes a decision externally. The logic is duplicated, and any changes to roles affect all consumers.
Refactored: Telling Instead of Asking
if (user.isAdmin()) {
grantAdminAccess();
}
Move the verification into the object, Improved Encapsulation and Testability.
Why It Feels Familiar: The String Example
Why does this feel familiar? Because Java’s standard libraries, especially String
, List
, etc., follow this principle rigorously. We’ve been using “Tell, Don’t Ask” even if we didn’t consciously name it that way.
This also explains why domain models that mimic such behavior feel intuitive and easy to read.
Consider how we use the String
class in Java:
Instead of counting the characters we are using lengrth(), Instead of validating for null and length 0, we use isEmpty().
String message = "Hello World";
if (message.isEmpty()) {
System.out.println("Nothing to show");
}
if (message.length() == 0) {
System.out.println("Nothing to show");
}
Now, what if you do not use this principle? What code smell you will bring into your project?
A Common Violation: Anemic Domain Models
Anemic models are classes with only getters/setters and no real behavior. This often leads to external logic making decisions, violating “Tell, Don’t Ask”.
Anemic Domain Model:
class Patient {
private String name;
private int age;
public int getAge() { return age; }
}
if (patient.getAge() > 65) {
offerSeniorDiscount();
}
Rich Domain Model:
class Patient {
private int age;
public boolean isSenior() {
return age > 65;
}
}
if (patient.isSenior()) {
offerSeniorDiscount();
}
Key Takeaways:
Encapsulate basic business logic into the Domain Model classes – Which places the “Tell, Don’t Ask” principle in place.
Domain Model classes which only has getters and setters are nothing but just code smells as “Anemic Domain Model”.
The best example to think of is String.length(), method. Whenever you get confused about “Tell, Don’t Ask” think about this method that we do not need to count the characters of a string in a loop to get its length. 🙂