Tell, Don’t Ask is a principle that encourages telling objects what to do rather than querying their state and making decisions for them.

Core Concept

Instead of asking an object for data and then making decisions based on that data, tell the object what to do and let it make its own decisions based on its internal state.

Why It Matters

  • Encapsulation: Keeps business logic with the data it operates on
  • Cohesion: Related behavior stays together
  • Maintainability: Changes to logic happen in one place
  • Testability: Objects have clear responsibilities

Example

Ask (Anti-Pattern)

// BAD: Asking for state and making decisions externally
public class ShoppingCart
{
    public List<Item> Items { get; set; }
    public decimal Total { get; set; }
}
 
public class CheckoutService
{
    public void ProcessCheckout(ShoppingCart cart)
    {
        decimal total = 0;
        foreach (var item in cart.Items)
        {
            total += item.Price * item.Quantity;
        }
 
        if (total > 100)
        {
            total *= 0.9m; // 10% discount
        }
 
        cart.Total = total;
    }
}

Tell (Good Practice)

// GOOD: Telling the object what to do
public class ShoppingCart
{
    private List<Item> _items = new();
 
    public void AddItem(Item item) => _items.Add(item);
 
    public decimal CalculateTotal()
    {
        decimal total = _items.Sum(i => i.Price * i.Quantity);
 
        if (total > 100)
        {
            total *= 0.9m; // 10% discount logic stays with the cart
        }
 
        return total;
    }
}
 
public class CheckoutService
{
    public void ProcessCheckout(ShoppingCart cart)
    {
        decimal total = cart.CalculateTotal(); // Tell it to calculate, don't ask for items
        // Process payment with total...
    }
}

When to Break This Rule

Tell, Don’t Ask is a guideline, not an absolute rule. It’s okay to query state when:

  • Building read models or view models for display
  • Implementing pure functional approaches
  • Objects are simple data containers (DTOs, value objects)
  • Cross-object coordination truly requires external orchestration

Resources