DEV Community

ulalax
ulalax

Posted on

Understanding the "Tell,Dont ask" Principle

The 'Tell, Don't Ask' Principle: A Core Concept in Object-Oriented Programming

Introduction

'Tell, Don't Ask' is a crucial design principle in Object-Oriented Programming (OOP). This principle emphasizes that code should be written in a way where external objects request actions from other objects rather than querying their state directly. By adhering to this principle, the internal state of objects remains encapsulated and unexposed to the outside world, reducing coupling between objects and improving maintainability and reusability.

Game Development Example

To better understand this principle, let's examine an example in the context of game development.

Incorrect Approach (Violating the Principle)

In this example, the Player class checks the state of the Weapon object (specifically, the ammo count) before deciding whether to attack.

public class Weapon
{
    public int Ammo { get; private set; }

    public Weapon(int initialAmmo)
    {
        Ammo = initialAmmo;
    }

    public void Fire()
    {
        Ammo--;
        Console.WriteLine("Weapon fired! Remaining ammo: " + Ammo);
    }
}

public class Player
{
    public void Attack(Weapon weapon)
    {
        if (weapon.Ammo > 0)
        {
            weapon.Fire();
        }
        else
        {
            Console.WriteLine("Cannot attack: No ammo left!");
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Here, the Player class checks the Ammo state of the Weapon object before deciding on an action. This approach increases coupling between the two classes and breaks the encapsulation of the Weapon class.

Correct Approach (Following the Principle)

Now, let's look at how we can adhere to the 'Tell, Don't Ask' principle. In this example, the Player class simply requests the attack without querying the weapon's state.

public class Weapon
{
    private int _ammo;

    public Weapon(int initialAmmo)
    {
        _ammo = initialAmmo;
    }

    public void Fire()
    {
        if (_ammo > 0)
        {
            _ammo--;
            Console.WriteLine("Weapon fired! Remaining ammo: " + _ammo);
        }
        else
        {
            Console.WriteLine("No ammo left!");
        }
    }
}

public class Player
{
    public void Attack(Weapon weapon)
    {
        weapon.Fire(); // Simply request the action without asking about the state
    }
}
Enter fullscreen mode Exit fullscreen mode

In this correct approach, the Player class doesn't need to know anything about the Weapon object's internal state. The Weapon class manages its own state internally and decides on the appropriate action without exposing its state externally. This reduces coupling between the classes and maintains the encapsulation of the Weapon class.

Concept Explanation

  1. Enhanced Encapsulation: The Weapon class manages its own state internally without exposing it to the outside world. External objects only need to request actions, which is crucial for maintaining encapsulation.

  2. Reduced Coupling: The Player class no longer depends on the internal state of the Weapon class. This reduces coupling between the two classes, meaning changes in one class are less likely to affect the other.

  3. Improved Maintainability: Even if the internal logic of the Weapon class changes, the Player class remains unaffected. This makes the code easier to maintain and reduces the overall complexity of the system.

  4. Code Simplification: Instead of complex code that checks state and then decides on actions, we have simpler code that just requests actions, improving readability and simplicity.

Martin Fowler's Perspective

While the 'Tell, Don't Ask' principle is useful in many situations, it shouldn't be applied blindly in all cases. Martin Fowler, in his blog post "Tell, Don't Ask", emphasizes the importance of this principle but also cautions against applying it too rigidly.

Fowler argues that while following this principle in object-oriented design, it's crucial to maintain code clarity and readability. Sometimes, directly checking an object's state and deciding on actions based on that state can be clearer and easier to understand. For instance, it might be better to check state externally and make simple decisions rather than hiding overly complex logic within an object.

Therefore, when applying the 'Tell, Don't Ask' principle, it's important to approach it flexibly based on the situation. While considering object encapsulation and coupling, always keep in mind the readability and maintainability of the code.

Summary

The 'Tell, Don't Ask' principle is an important development tip that simplifies interactions between objects and improves code maintainability. In game development, adhering to this principle can lead to more flexible and efficient handling of interactions between objects like characters and weapons. This contributes to better software design and maintains higher code quality.

Top comments (0)