Reconstruction Method-Simplified conditional expression [3], reconstruction expression

Source: Internet
Author: User

Reconstruction Method-Simplified conditional expression [3], reconstruction expression

Total returned directory

Directory of this section

  • Replace Nested Conditional with Guard clores (Replace Nested Conditional expressions with Guard statements)
  • Replace Conditional with Polymorphism (Replace Conditional expressions with Polymorphism)
5 Replace Nested Conditional with Guard Clauses (Replace Nested Conditional expressions with Guard statements) Summary

The conditional logic in the function makes it difficult for people to see the normal execution path.

Use the Wei statement to show all special cases.

Motivation

Conditional expressions are usually expressed in two forms. (1) All branches are normal; (2) only one of the answers provided by conditional expressions is normal, and others are uncommon.

If both branches are normal, you should use an if... else... if a condition is extremely rare, it should be checked separately and immediately returned from the function when the condition is true. Such a separate check is called a "Wei statement ".

The essence of this refactoring technique is to give a branch special attention.

Example

The following functions deal with the salaries of dead, foreign, and retired employees with special rules:

class Amount{    public bool IsDead { get; set; }    public bool IsSeparated { get; set; }    public bool IsRetired { get; set; }
public double GetPayAmount() { double result; if (IsDead) { result = DeadAmount(); } else { if (IsSeparated) { result = SeparatedAmount(); } else { if (IsRetired) { result = RetiredAmount(); } else { result = NormalAmount(); } } } return result; } private double DeadAmount() { return default(double); } private double SeparatedAmount() { return default(double); } private double RetiredAmount() { return default(double); } private double NormalAmount() { return default(double); }}

As we can see, exceptions in this Code mask normal checks, so we should replace these checks with guard statements to improve program clarity.

We start from the top condition action:

public double GetPayAmount(){    double result;    if (IsDead)    {        return DeadAmount();    }    if (IsSeparated)    {        result = SeparatedAmount();    }    else    {        if (IsRetired)        {            result = RetiredAmount();        }        else        {            result = NormalAmount();        }    }    return result;}

Then replace the following:

public double GetPayAmount(){    double result;    if (IsDead)    {        return DeadAmount();    }    if (IsSeparated)    {        return SeparatedAmount();    }    if (IsRetired)    {        result = RetiredAmount();    }    else    {        result = NormalAmount();    }    return result;}

Next is the last one:

public double GetPayAmount(){    double result;    if (IsDead)    {        return DeadAmount();    }    if (IsSeparated)    {        return SeparatedAmount();    }    if (IsRetired)    {        return RetiredAmount();    }    result = NormalAmount();    return result;}

At this point, the result variable is meaningless, so you can delete it. The final code is as follows:

class Amount{    public bool IsDead { get; set; }    public bool IsSeparated { get; set;     public bool IsRetired { get; set; }    public double GetPayAmount()    {        if (IsDead)        {            return DeadAmount();        }        if (IsSeparated)        {            return SeparatedAmount();        }        if (IsRetired)        {            return RetiredAmount();        }        return NormalAmount();    }    private double DeadAmount()    {        return default(double);    }    private double SeparatedAmount()    {        return default(double);    }    private double RetiredAmount()    {        return default(double);    }    private double NormalAmount()    {        return default(double);    }}
Example: reverse a condition
class AdjustedCapital{    public double Capital { get; set; }
public double IntRate { get; set; } public double Income { get; set; } public double Duration { get; set; } public double GetAdjustedCapital() { double result = 0; if (Capital > 0) { if (IntRate > 0 && Duration > 0) { result = Income / Duration; } } return result; }}

Similarly, we replace them one by one. However, when inserting a Wei statement, you need to reverse the condition:

public double GetAdjustedCapital(){    double result = 0;    if (Capital <= 0)    {        return result;    }    if (IntRate > 0 && Duration > 0)    {        result = Income / Duration;    }    return result;}

Replace the following one:

public double GetAdjustedCapital(){    double result = 0;    if (Capital <= 0)    {        return result;    }    if (IntRate <= 0 || Duration <= 0)    {        return result;    }    result = Income / Duration;    return result;}

Finally, we can delete the temporary variables:

public double GetAdjustedCapital(){    if (Capital <= 0)    {        return 0;    }    if (IntRate <= 0 || Duration <= 0)    {        return 0;    }    return Income / Duration;}
Summary

Many programmers have the idea that "each function can have only one entry and one exit ." Modern Programming Languages limit that functions have only one entry. However, "a function has only one exit" is not that useful.

There is a saying in the book: Nested condition branches are often written by programmers who believe that "each function can only have one exit. But in fact, if you are not interested in the rest of the function, you should exit immediately. Guiding readers to see useless else fragments only hinders their understanding of the program.

6 Replace Conditional with Polymorphism (Replace Conditional expressions with Polymorphism) Summary

You have a conditional expression that selects unused Behavior Based on the object type.

Place each branch of the conditional expression into the override function in a subclass, and declare the original function as an abstract function.

Motivation

If you need to take different actions based on different types of objects, you do not need to write obvious conditional expressions when using polymorphism.

There is a set of conditional expressions. To add a new type, you must search for and update all conditional expressions. To use polymorphism, you only need to create a new subclass and provide appropriate functions. This greatly reduces the dependency between various parts of the system and makes it easier to upgrade the system.

Example

The following code shows that the ProcessOrder method of the OrderProcessor class performs some operations based on the Customer type:

public abstract class Customer{}public class Employee : Customer{}public class NonEmployee : Customer{}public class Product{    public int Price { get; set; }}public class OrderProcessor{    public decimal ProcessOrder(Customer customer, IEnumerable<Product> products)    {        // do some processing of order        decimal orderTotal = products.Sum(p => p.Price);        Type customerType = customer.GetType();        if (customerType == typeof(Employee))        {            orderTotal -= orderTotal * 0.15m;        }        else if (customerType == typeof(NonEmployee))        {            orderTotal -= orderTotal * 0.05m;        }        return orderTotal;    }}

The restructured code is as follows. Each Customer subclass encapsulates its own algorithm, and the logic of the ProcessOrder method of the OrderProcessor class becomes simple and clear.

public abstract class Customer{    public abstract decimal DiscountPercentage { get; }}public class Employee : Customer{    public override decimal DiscountPercentage => 0.15m;}public class NonEmployee : Customer{    public override decimal DiscountPercentage => 0.05m;}public class Product{    public int Price { get; set; }}public class OrderProcessor{    public decimal ProcessOrder(Customer customer, IEnumerable<Product> products)    {        // do some processing of order        decimal orderTotal = products.Sum(p => p.Price);        orderTotal = orderTotal * customer.DiscountPercentage;        return orderTotal;    }}
Summary

The reconstruction of "replace conditional expressions with polymorphism" often appears in the design pattern (the shadows of common factory families and policy patterns can be seen ), because it can save a lot of conditional judgment, it can also simplify the responsibilities between code, category class and object.

 

 

To Be Continued ......

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.