DEV Community

Cover image for "Tell, Don't Ask" Principle Explained in 100 Seconds
Dzung Nguyen
Dzung Nguyen

Posted on

"Tell, Don't Ask" Principle Explained in 100 Seconds

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.

Principle Image


👨‍👩‍👦 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; }
}
Enter fullscreen mode Exit fullscreen mode

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");
}
Enter fullscreen mode Exit fullscreen mode

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");
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

We use it like this:

TellMonitor monitor = new TellMonitor("Temperature Sensor", 100, alarm);
monitor.setValue(120);
Enter fullscreen mode Exit fullscreen mode

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" a Server 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)