Java Omnibus
OOAD & Architecture / Design principles / Tell, Don’t Ask Principle in Java
Design Principles Java Order Management
Design Principles

Tell, Don’t Ask encourages behavior to live where the state and rules already belong.

Tell, Don’t Ask is a simple but powerful OOAD heuristic. Instead of pulling data out of an object and making decisions elsewhere, tell the object what outcome you need and let it decide how to act. The principle pushes behavior closer to the data and invariants it depends on.

Why This Topic Matters

Why it matters in real Java systems

In order-management domains, status transitions, inventory rules, refund eligibility, and shipment changes often leak outward into services. When that happens, objects become passive and services become procedural. Tell, Don’t Ask is one way to rebalance that responsibility.

Core Explanation

The design idea behind this topic

Tell, Don’t Ask does not forbid querying data. It becomes important when decision logic depends on internal state and domain rules. In those cases, a richer object often produces a more cohesive and maintainable design.

In Java systems, this principle often distinguishes a richer domain model from an anemic one. The more critical the invariant, the more likely the object itself should be told to do the thing rather than asked for fields that outside code manipulates.

The principle works best where business meaning is central, not where the type is merely a data carrier.

Concept Breakdown

Key ideas to hold onto

Concept

Behavior near state

The object that owns the state is often best positioned to make the decision.

Concept

Supports encapsulation

Callers need less internal detail when they ask for outcomes rather than raw data.

Concept

Improves cohesion

Domain behavior becomes more central to the model instead of scattered across services.

Java Example

Java example in the Order Management domain

Java example: tell the order to submit itself
package org.javaomnibus.ecommerce.principles;

import java.util.List;

public final class Order {
    private final List lines;
    private boolean submitted;

    public Order(List lines) {
        this.lines = List.copyOf(lines);
    }

    public void submit() {
        if (lines.isEmpty()) {
            throw new IllegalStateException("Order must contain at least one line");
        }
        this.submitted = true;
    }
}

record OrderLine(String sku, int quantity) {}
Code Walkthrough

Step by step

  1. The caller does not inspect line count and then decide whether to mark the order submitted.
  2. The order owns that rule because it already owns the relevant state.
  3. That keeps the invariant close to the model and reduces procedural leakage into services.
  4. Tell, Don’t Ask strengthens the object’s role as a business concept.
Real-World Usage

Where this shows up in practice

  • Status transitions and eligibility checks in domain models
  • Reducing procedural service logic around rich aggregates
  • Improving encapsulation in models that must defend important rules
Trade-Offs

When not to over-apply it

Not every object should become rich with behavior. Simple boundary DTOs are still fine. The principle is strongest for domain types where correctness depends on internal state and rules.

Common Mistakes

Frequent mistakes to watch for

  • Asking for fields and rebuilding the decision in many services
  • Applying the principle to DTOs that are only meant for transport
  • Confusing opaque APIs with good encapsulation
  • Leaving important invariants outside the model while claiming rich design
Related Pages

Related concepts


What To Read Next