Say Goodbye to Boolean Flags
Everyone knows domain models is at the heart of software. That being said, there is a lot to go wrong with the design process. One prevalent error is abusing Boolean flags in the domain models.
In this blog, I will try to simplify it with a real-world example for the software engineers, out there using an analogy so that we understand what is wrong when we have quite often ”use of Boolean flag” in our code. I will also show an example of how to design C# model to avoid Boolean as much as possible.
In this blog, I will try to simplify it with a real-world example for the software engineers, out there using an analogy so that we understand what is wrong when we have quite often ”use of Boolean flag” in our code. I will also show an example of how to design C# model to avoid Boolean as much as possible.
A Simple Task Management System
So, let’s try to imagine that you’re developing a task management system. Common scenario is that each task can be in one of three states: Not Started, In Progress, or Completed. A naive approach might be to represent these states using Boolean flags:
This design seems simple at first glance, but it can quickly become problematic.
An Analogy of The Pitfalls of Boolean Flags
Let’s try to make an analogy from real-world to better understand the problem. Imagine that you are organizing a some kind of dinner party where you have a checklist for the food. For each dish, you have three checkboxes:
Ingredients Not Purchased
Cooking In Progress
Dish Completed
OK let’s try to examinate one scenario. Let’s imagine if you’re not careful, you might accidentally check multiple boxes for the same dish. But hold on, what if you mark both “Cooking In Progress” and “Dish Completed” as true? This would lead for sure to confusion, which will make unclear whether the dish is ready to serve or still being prepared. A bit chaotic…
So as we can see using multiple Boolean flags to represent the state of a task can lead to conflicting or confusing states, making your code harder to manage and more prone to errors.
A Better Approach is Using an Enum and a State Pattern
A bit better approach in order to solve these issues is move the Booleans into Enum. So, let’s refactor the Task class by using an Enum which will represent the different states.
Start by defining an Enum to represent the task states:
Now the question is: what would be benefits of using an Enum?
Using an Enum clearly defines the possible states a task can be in, eliminating the risk of conflicting states. The state transitions are encapsulated within the Task class, making the logic easier to manage and understand. Adding new states, like “On Hold,” is straightforward with an Enum. The associated logic can be easily updated without introducing new Boolean flags.
Managing Complex Behavior with The State Pattern
Let’s now to extend previews analogy to explain and bring on the table the state pattern.
So, imagine you have a kitchen assistant who knows exactly how to handle a dish at each stage of preparation. When you say them, hey: start cooking, the assistant will know that he need to move from ingredients not purchased to cooking in progress. When you say finish, the assistant will move to dish completed. As you can see this specialized knowledge makes the process smooth and prevents mistakes.
Let’s back to the code, the kitchen assistant is like the state pattern, where each state knows how to transition to the next, keeping the logic clean and preventing errors.
Her is our updated C# code:
Following this design, now every state encapsulates its own behavior just like the kitchen assistant knows how to handle each dish state. Basically, this makes easier to manage complex logic and avoid potential mistakes.
Since the system will evolve, we can ensure that behavior of tasks changes in terms of state classes and this is always less likely to break anything.
State pattern provides more legible code and express the system in semantic rather than mechanical terms (the domain concepts) that helps new comer to understand business feature.
For the end
As we can saw, the state pattern with Enums can help us to create more reliable, maintainable and expressive domain models. This simplifies our code and makes it more maintainable in the long run.
Similar to our dinner party example where a concise, organized checklist eliminates chaos and confusion, similarly like in domain model stops code from becoming an out-of-control. This strategies will keep the codebase clean, clear and highly maintainable.
Cheers and Good Luck! 👋