Better Software Without If-Else by Nicklas Millard
One, foreword
When doing project development, I found that there would be a lot of if-else judgment in the project, especially the bank App, and the judgment of various dimensions and marks of users. In plain English, writing business code is if-else and CRUD. If-else leads to complex design, poor code readability, and possibly difficult refactoring. But it does make sense that if-else has become the de facto code-branching solution. This is the first thing taught to all aspiring developers. Unfortunately, many developers never make the leap to a more appropriate branching strategy.
Some people have a mantra: If-else is a hammer, everything is a nail. The inability to tell when to use a more appropriate method is one of the things that separates juniors from juniors.
Second, the purpose of
This article will show you some tips and patterns that will put an end to this horrible practice. 5 ways to Design better software to replace If-else From door to advanced examples, the difficulty of each example increases.
Three cases,
Completely unnecessary else blocks
This is probably one of the biggest SINS of junior developers. The following example is a good example of what happens when you think if-else is great.
Simple if-else
Removed else
Simply remove the ELSE block to simplify the process.
Does it look more professional? You’ll often find that you don’t really need the other blocks at all. As in this case, you want to do something and return immediately if certain conditions are met.
2. Value distribution
If you are assigning new values to variables based on some input provided, stop the if-else nonsense – a more readable approach.
Value assignment with if-else Simple as it is, it is bad. First, if-else is easily replaced by a switch here. However, we can further simplify this code by removing the else entirely.
If statements with fast return
If we don’t use else, we’ll be left with clean, readable code. Note that I also changed the style to a quick return statement rather than a single return statement, and there is no point in continuing to test a value if the correct value has already been found.
3. Check the prerequisites
Method without value checks
In general, I find that if a method provides an invalid value, it makes no sense to continue execution. Suppose we had the DefineGender method before, requiring that the input value supplied must always be 0 or 1.It makes no sense to perform this method without validation of value. Therefore, we need to check a few prerequisites before allowing the method to proceed.
Check preconditions with guard clauses
Using the protective clause defensive coding technique, you check the input value of the method and proceed with the method execution.At this point, we ensure that the main logic is executed only if the value falls within the expected range. Now, if has also been replaced by ternary, because there is no longer a need to return “unknown” by default at the end.
4. Convert if-else to a dictionary — avoid if-else altogether
Let’s say you need to perform some actions that will be selected based on some criteria, and we know we’ll have to add more later.
One might prefer the tried-and-true if-else. If you add a new operation, you can simply add something else. But in terms of maintenance, this approach is not a good design.
If we know we need to add new operations later, we can refactor if-else into a dictionary. Readability has improved significantly, and the code can be inferred more easily.
5. Extend the application — avoid if-else entirely
This is a slightly more advanced example.
By replacing them with objects, you know when to eliminate ifs altogether.
Often, you find yourself having to extend parts of your application. As a junior developer, you might be tempted to do this by adding additional if-else (that is, else-if) statements.
Take this illustrative example. We need to display the Order instance as a string. First, we only have two string representations: JSON and plain text. Using else-if is not a big deal at this stage, if we can easily replace something else, just as described.Knowing that we need to extend this part of the application, this approach is absolutely unacceptable.
The code above not only violates the “on/off” rule, but is poorly read and causes maintainability problems.
The right approach is one that follows SOLID principles — we do this by implementing a dynamic type discovery process (in this case, the policy pattern).
The process for refactoring this messy process is as follows:
- Extract each branch into a separate policy class using a common interface
- Dynamically find all classes that implement a common interface
- Decide which policy to implement based on the input
The code to replace the above example is shown below. Yes, that’s the way more code is. It requires you to understand how type discovery works. But dynamically extending applications is an advanced topic.
I only show the exact part of the if-else example that will be replaced. If you want to see all of the objects involved, look at this bullet point.
First, get all the types in the assembly that implements the generic interface IOrderOutputStrategy. Then, we create a dictionary with the formatter’s displayName as key and type value. Then select the formatter type from the dictionary and try to instantiate the policy object. Finally, the ConvertOrderToString of the policy object is called.
Iv. Introduction to the author
Nicklas Millard is a senior technical consultant in one of the top four Danish consulting firms. He primarily serves as lead developer and solution architect for client projects.
He has been developing software for commercial clients and government agencies such as the Ministry of Defence, the Ministry of Education, the Danish Ministry of Environment and Food, the National Police, the Danish Labour Market and Recruitment Agency and RSTAD.
(This article is translated from Better Software Without If-else by Nicklas Millard, medium.com/swlh/5-ways…)