In this post, I'm going to talk about the design principle called "tell don't ask". So "tell don't ask" is a design principle whose intent is to reduce control coupling.
So firstly let's clarify what is control coupling. Control coupling is when one object is very concerned about controlling the control flow of another object. In other words when one object is really concerned about telling another object when it's supposed to do things. And in fact, that object could itself control when it should or should not do particular things. It's actually a very simple design principle that can have immensely positive consequences for the design of your code.
So this principle is probably most easily understood by considering an example. So let's say that you have an instance of class "Database" which has three members:
- database connection state
private connectionState: 'connected' | 'disconnected';
- method for checking if connection to database is establishedpublic isConnected(): boolean {
return this.connectionState === 'connected';
}
- and method for sending queries to databasepublic executeQuery(): any {
...
}
So then imagine that the user of "Database" class instance first calls "isConnected" and uses that in an if statement to switch over whether the connection is established and then depending on the answer decides whether to execute the query or not to execute. This is essentially control coupling. Because the user of the "Database" is very concerned about its internal state and uses that information to determine whether or not the "executeQuery" should be called. But "tell don't ask" design principle states, that "Database" should know whether the connection is established or not. So the "isConnected" method should not necessarily be called every time the "executeQuery" method is called.So if we are coupling "isConnected" and "executeQuery" method calls and using "isConnected" method result whether to call "executeQuery" or not, that's how we are breaking the "tell don't ask" principle. "tell don't ask" essentially says that we should do the opposite, we should simply tell the database object to execute query. And "executeQuery" method can use the "isConnected" method itself, so the connection state would be always checked internally.
public executeQuery(): any {
if (!this.isConnected) {
return null;
}
...
}
So to generalize consider it like this: whenever you are asking an object about its internal state and then using that internal state for making a decision how to use the object, you should ask yourself the question whether the decision that you want to make could be determined by the object itself. So in other words tell don't ask suggests to tell the object what to do instead of asking it something and then deciding what to do with this object in outer code. So this principle is very simple and it helps us to reduce the control coupling. There are many other forms of coupling besides "control coupling", but I am going to write about them in another posts.
Click to view an original video explanation for this topic