#5 Ways to Design Better Software and Replace If-Else. Beginner to Advanced Example
Let me just say this: If-Else is usually a poor choice.
It leads to complex designs, poor code readability, and may lead to difficulty in refactoring.
But it does make sense that If-Else has become the de facto code branching solution. This is the first thing that is taught to all aspiring developers. Unfortunately, many developers never move forward to a more appropriate branching strategy.
Some people’s mantra is: If-Else is a hammer, everything is a nail.
The inability to distinguish when to use a more appropriate method is one of the things that differentiates juniors from juniors.
I'm going to show you some tips and patterns that will put an end to this horrible practice.
The difficulty increases with each example.
This is perhaps one of the biggest sins that junior developers are guilty of. The example below is a great example of what happens when you are told that If-Else is great.
Simply remove the else` block to simplify this process.
Looks more professional, right?
You will often find that the other blocks are not actually needed at all. Like in this case, you want to perform some action and return immediately if a specific condition is met.
If you are assigning a new value to a variable based on some input provided, stop the If-Else nonsense - a more readable sexual method.
As simple as it is, it's terrible. First, If-Else can easily be replaced by a switch here. However, we can simplify this code further by removing else completely.
If else is not used, we are left with clean readable code. Note that I also changed the style to a fast return rather than a single return statement - there is no point in continuing to test for a value if the correct value has already been found.
Usually, I find that if a method provides an invalid value, there is no way to continue execution. meaningful.
Suppose we have the DefineGender method from before, which requires that the input value provided must always be 0 or 1.
It makes no sense to execute this method without value validation. Therefore, we need to check some prerequisites before allowing the method to continue execution.
Applying the guard clause defensive coding technique, you will check the input values of the method and then continue executing the method.
#At this point, we ensure that the main logic is only executed when 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.
Suppose you need to perform some operations that will select based on some conditions, We knew we would have to add more operations in the future.
Maybe someone prefers to use the tried and tested If-Else. If you add a new action, simply add something else. Very simple. However, this approach is not a good design in terms of maintenance.
Knowing that we need to add new operations in the future, we can refactor If-Else into a dictionary.
#Readability has been greatly improved and the code can be more easily inferred.
Note that the dictionary is placed inside the method for illustration purposes only. You may want to provide it from somewhere else.
This is a slightly more advanced example.
Know when to even eliminate Ifs entirely by replacing them with objects.
Often you will find yourself having to extend certain parts of your application. As a junior developer, you may be tempted to do this by adding additional If-Else (i.e. else-if) statements.
Give this illustrative example. Here we need to display the Order instance as a string. First, we only have two string representations: JSON and plain text. Using If-Else is not a big deal at this stage, if we can easily replace the others, just as mentioned earlier.
#Knowing that we need to extend this part of the application, this approach is absolutely unacceptable.
The above code not only violates the "open/close" principle, but also does not read well and can cause maintainability troubles.
The correct approach is one that follows the SOLID principles - we do this by implementing a dynamic type discovery process (in this case the Strategy pattern).
The process of refactoring this messy process is as follows:
· Extract each branch into a separate strategy class using a common interface
· Dynamically find all classes that implement the common interface
·Determine which strategy to execute based on the input
The code that replaces the above example is as follows. Yes, this is way more code. It requires you to understand how type discovery works. But dynamically scaling applications is an advanced topic.
I only show the exact part that will replace the If-Else example. If you want to see all the objects involved, check out this gist.
Let’s take a quick look at the code.
The method signature remains unchanged because the caller does not need to know about our refactoring.
First, get all types in the assembly that implement the general interface IOrderOutputStrategy. Then, we create a dictionary, the name of the displayName of the formatter is key, and the type is value.
Then select the formatter type from the dictionary and try to instantiate the policy object.
Finally, call ConvertOrderToString of the strategy object.
The above is the detailed content of How did our company completely eliminate 2,000 if-else in the project?. For more information, please follow other related articles on the PHP Chinese website!