The Tell, Don't Ask principle is a core concept in object-oriented programming (OOP) that encourages designing objects to contain both data and the behaviors that operate on that data. This principle helps create more maintainable and robust systems by promoting better encapsulation.
💡 What is "Tell, Don’t Ask"?
💢 Tell, Don’t Ask is a principle that reminds us to tell objects what to do rather than asking them for data and acting on it outside of the object. It emphasizes moving behavior into objects alongside their data, keeping logic and state together.
💢 Instead of extracting data from an object and making decisions EXTERNALLY, you tell the object to perform an action INTERNALLY. This approach simplifies code, reduces coupling, and makes systems easier to extend and maintain.
👨👩👦 Example: Monitoring a Value
Let’s consider an example where we need to monitor a sensor’s value and trigger an alarm if the value goes above a certain limit.
Asking for Data ("Ask" Style)
class AskMonitor {
private int value;
private int limit;
private String name;
private Alarm alarm;
public AskMonitor(String name, int limit, Alarm alarm) {
this.name = name;
this.limit = limit;
this.alarm = alarm;
}
public int getValue() { return value; }
public void setValue(int value) { this.value = value; }
public int getLimit() { return limit; }
public String getName() { return name; }
public Alarm getAlarm() { return alarm; }
}
We use it like this:
AskMonitor monitor = new AskMonitor("Temperature Sensor", 100, alarm);
monitor.setValue(120);
if (monitor.getValue() > monitor.getLimit()) {
monitor.getAlarm().warn(monitor.getName() + " is too high");
}
Telling the Object ("Tell" Style)
In "Tell, Don’t Ask," we move the behavior into the Monitor
class.
class TellMonitor {
private int value;
private int limit;
private String name;
private Alarm alarm;
public TellMonitor(String name, int limit, Alarm alarm) {
this.name = name;
this.limit = limit;
this.alarm = alarm;
}
public void setValue(int value) {
this.value = value;
if (this.value > this.limit) {
alarm.warn(name + " is too high");
}
}
}
We use it like this:
TellMonitor monitor = new TellMonitor("Temperature Sensor", 100, alarm);
monitor.setValue(120);
Notice how the "Tell" version eliminates external decision-making by embedding the logic directly into the setValue
method.
⭐ Benefits
✅ Encapsulation: Combines data and behavior, keeping them tightly related.
✅ Simplified Code: Reduces external logic by placing behavior inside relevant objects.
✅ Maintainability: Easier to update and extend functionality.
💎 Use "Tell" When:
✅ Encapsulating Behavior: When the object knows what it needs to do with its data and should act upon it directly to make it easier to maintain and avoid inconsistent states.
Example: A
Monitor
object has a limit for its value and should raise an alarm when the value exceeds that limit. Rather than asking the monitor for its value and then acting on it, you tell the monitor to take action when the value is set.
✅ State Changes Triggering Actions: When an update in one part of the object's state requires a follow-up action (like triggering a notification, logging, or updating other components), the object itself should manage those actions.
Example: A
UserProfile
object might automatically update a user’s activity log whenever their profile information is updated.
💎 Use "Ask" When:
✅ Queries for Data: When you need data from the object without altering its state or causing any action.
Example: Asking a
User
object for its email address or phone without needing any other action.
✅ External Decisions: When decisions depend on external data or logic that the object shouldn’t handle.
Example: You might ask a
Person
object for its name to decide externally how to greet the person (e.g., choosing between "Hello, Mr. X" or "Welcome back, Mr. X").
✅ Delegation of Responsibility: When objects collaborate and one object needs data from another to determine the next action, avoiding too much logic in a single object.
Example: In a network of objects, a
Router
might "ask" aServer
for its load and make decisions about traffic management based on the current state.
Ultimately, adopting Tell, Don’t Ask fosters better encapsulation and cleaner code. It allows for a more natural flow of interactions between objects, When implemented effectively, this principle contributes to building scalable and maintainable software systems.
📰 Others
Interested? 😃 Check out other posts from my programming principles series!
Follow me to stay updated with my future posts:
Top comments (0)