Understanding the "Tell, Don't Ask" Principle Through Real-World Scenarios in C#
Understanding the "Tell, Don't Ask" Principle Through Real-World Scenarios in C#

Understanding the "Tell, Don't Ask" Principle Through Real-World Scenarios in C#

In today's article, I will cover one particular programming concept which would allow you to tidy up code, making it more effective. The concept is "Tell. Don't Ask". To do that, we would illustratively demonstrate the concept through a metaphor in the world of banking which should make understanding easy for you. I'll break it down in simple terms, and we'll explore diagrams and C# code snippets to make it all come alive.

What is Tell, Don't Ask?

It's sort of like training a dog. Instead of checking if the dog is sitting and then you say fetch, it would just be telling the dog fetch. Then the dog knows if it can fetch or not. This way, you're not micromanaging the dog's actions. You're trusting it to do its job.

What is "Tell, Don't Ask"?

Scenario with Banking Business

Let's say you're developing a banking application. You have a BankAccount class that contains information like balance, account number, and so on.

Traditional Approach - Ask, then Tell

In this method, you ask the BankAccount for its balance and then decide whether to proceed with the withdrawal or not.

public class BankAccount
{
    public decimal Balance { get; private set; }

    public void Withdraw(decimal amount)
    {
        if (Balance >= amount)
        {
            Balance -= amount;
        }
        else
        {
            throw new Exception("Insufficient funds");
        }
    }
}

// Client code
BankAccount account = new BankAccount();
if (account.Balance >= 100)
{
    account.Withdraw(100);
}        

Modern Approach - Tell, Don't Ask

Here, you directly tell the BankAccount to handle the withdrawal. The account itself is responsible for checking if it has sufficient funds.

public class BankAccount
{
    public decimal Balance { get; private set; }

    public void Withdraw(decimal amount)
    {
        if (CanWithdraw(amount))
        {
            Balance -= amount;
        }
        else
        {
            throw new Exception("Insufficient funds");
        }
    }

    private bool CanWithdraw(decimal amount)
    {
        return Balance >= amount;
    }
}

// Client code
BankAccount account = new BankAccount();
account.Withdraw(100);        
Modern Approach - Tell, Don't Ask

When should we consider the principle "Tell, Don't Ask"?

Encapsulation

When you follow the "Tell, Don't Ask" principle, fundamentally you're giving ownership of managing it's inner state to the object. This enhances encapsulation in the way you're not exposing the internals of the object. Instead, you are instructing the object to take care of its duties like a well-trained dog knowing when to sit, stay or fetch.

Readability

Code following the principle of "Tell, Don't Ask" usually is the one easy to read. Indeed, it reduces your cognitive load in order to understand what code will do next. You don't have to keep track of many conditions or states, you simply state what you want the object to do and it takes care of that on its own. It's like reading a well-written book the story flows naturally without having you jump back and forth between pages.

Maintainability

If the behavior is encapsulated into the object, any future changes made in that behavior will require changes to take place only at one location. This creates a codebase that can be maintained and fewer bugs occur. Imagine you have a car; if all the controls are in one place (the dashboard), it's easier to operate and fix. You do not have to go to different parts of the car to turn on the headlights, adjust the air condition or tune radio.

Reduced Complexity

By telling an object what to do, you localize the behavior and hence reduce the complexity. You don't have to write complex client code which has to handle various states and conditions. The object itself takes care of that making the overall system simpler.

For the end

The "Tell, Don't Ask" principle is handy as a guiding code rule that brings several benefits in the perspective of software development. It helps to have an exclusive way for enhancing the concept of encapsulation enabling objects to manage their own state as well as discouraging accessing internals. This thus results to a more readable and maintainable code, since you don't have to dig in the state of an object so as to understand its responsibility. Also, it invites the flexible code there is easy change and extension of the code in near future. Overall, adherence to "Tell, Don't Ask" can highly enhance your quality of code base.


Cheers! ??



Willem Boeré

Systems architect | Azure devops specialist | passion for development | loves .NET

1 年

This is a problem, what occurs in a lot of systems, where is the business logic defined; in this principle the responsiblity is clearly devided. Nice post!

Alex Choroshin

Driving Tech Innovation & Transforming Ideas into Market-ready Solutions | 15+ Years in Software Development

1 年

Thanks for sharing!

Nelia Kaminska

Business Development Manager at Scimus | Helping businesses to go from Good to Great through automation

1 年

Great analogy! Making the transition from 'asking' to 'telling' can really streamline any coding process. It's convenient to let an object manage its own state.

要查看或添加评论,请登录

Admir Mujkic的更多文章

社区洞察

其他会员也浏览了