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

Source: Internet
Author: User

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

Total returned directory

7 Introduce Null Object (introducing Null Object) Summary

You need to check whether an object is null again and again.

Replace null with a null object.

Motivation

When using functions related to an object, the system always checks whether the object is null. If it is not null, we will call its related methods to complete a logic. This kind of check appears many times in a system, and I believe that no designer is willing to see this situation. To solve this problem, we can introduce empty objects, so that we can get rid of a lot of stylized code and make a leap in code readability.

Example

In the following code, the Site class represents a location. Each location has a Customer at any time. The Customer information is expressed as Customer:

public class Site{    public Customer Customer { get; set; }}public class Customer{    public string Name { get; set; }    public BillingPlan Plan { get; set; }    public PaymentHistory History { get; set; }}public class BillingPlan{    public int BasicPay { get; set; }    public BillingPlan()    {        BasicPay = 0;    }    public BillingPlan(int pay)    {        BasicPay = pay;    }    public static BillingPlan Basic()    {        return new BillingPlan(100);    }}public class PaymentHistory{    public int GetWeekDelinquentInLastYear()    {        return 100;    }}

We may call:

Site site = new Site();Customer customer = site.Customer;BillingPlan plan;if (customer == null){    plan = BillingPlan.Basic();}else{    plan = customer.Plan;}string customerName;if (customer == null){    customerName = "occupant";}else{    customerName = customer.Name;}int weeksDelinquent;if (customer == null){    weeksDelinquent = 0;}else{    weeksDelinquent = customer.History.GetWeekDelinquentInLastYear();}

In this system, there may be many places where Site and Customer objects are used. They must both check whether the Customer object is equal to null, and such a check is completely repeated. The following uses empty objects for refactoring.

Create a new NullCustomer and modify the Customer to support the check of "whether the object is null:

public class Customer {    public virtual bool IsNull()    {        return false;    }}
class NullCustomer : Customer{    public override bool IsNull()    {        return true;    }}

Next, add a function to the Customer to create the NullCustomer object. In this way, the user does not have to know the existence of the null object:

public class Customer{     public static Customer NewNull()    {        return new NullCustomer();    }}

Modify all the places where Customer objects are provided so that they cannot return null, but return an NullCustomer object.

public class Site{    private Customer _customer;    public Customer Customer    {        get => _customer ?? Customer.NewNull();        set => _customer = value;    }}

In addition, you need to modify all the places where Customer objects are used so that they can be checked using the IsNull () function. The = null check method is no longer used.

Site site = new Site();Customer customer = site.Customer;BillingPlan plan;if (customer.IsNull()){    plan = BillingPlan.Basic();}else{    plan = customer.Plan;}string customerName;if (customer.IsNull()){    customerName = "occupant";}else{    customerName = customer.Name;}int weeksDelinquent;if (customer.IsNull()){    weeksDelinquent = 0;}else{    weeksDelinquent = customer.History.GetWeekDelinquentInLastYear();}

So far, using the IsNull () function has not brought any benefits. Next we will move the related behavior to NullCustomer and remove the conditional expression.

First, add a proper function for NullCustomer to obtain the Customer name. Therefore, change the attribute in Customer to virtual attribute, so that the sub-class can be rewritten as follows:

class NullCustomer : Customer{    public override string Name => "occupant";

public override bool IsNull() { return true; }}

Now, we can remove the conditional code when calling it. The following code:

if (customer.IsNull()){    customerName = "occupant";}else{    customerName = customer.Name;}

Now it is called like this:

string customerName=customer.Name;

Next, we will process other functions in the same way so that they can make the most appropriate response to the corresponding query. So the following client program:

BillingPlan plan;if (customer.IsNull()){    plan = BillingPlan.Basic();}else{    plan = customer.Plan;}

It becomes like this:

BillingPlan plan = customer.Plan;
class NullCustomer : Customer{    public override BillingPlan Plan => BillingPlan.Basic();}

Note: Only whenMajorityThe Customer Code requires the use of null objects to make the same response, such behavior migration makes sense. Note that it is "majority" instead of "all ". If you need a blank object to make different responses, you can still use the IsNull () function for testing. As long as most clients require Null objects to make the same response, the default Null behavior can be called.

The following code is slightly different in the above example:

 int weeksDelinquent; if (customer.IsNull()) {     weeksDelinquent = 0; } else {     weeksDelinquent = customer.History.GetWeekDelinquentInLastYear(); }

We can create a new NullPaymentHistory class to handle this situation:

class NullPaymentHistory : PaymentHistory{    public override int GetWeekDelinquentInLastYear()    {        return 0;    }}
public class PaymentHistory{    public virtual int GetWeekDelinquentInLastYear()    {        return 100;    }    public static PaymentHistory NewNull()    {        return new NullPaymentHistory();    }}

Modify NullCustomer to return an NullPaymentHistory object:

class NullCustomer : Customer{    public override string Name => "occupant";    public override BillingPlan Plan => BillingPlan.Basic();    public override PaymentHistory History => PaymentHistory.NewNull();    public override bool IsNull()    {        return true;    }}

Then, you can delete this row of conditional code:

int weeksDelinquent = customer.History.GetWeekDelinquentInLastYear();

As you can see, when a Null object is used, the code structure is clear and the amount of code is greatly reduced.

Summary

Empty objects are replaced by isNull = null, which is more elegant and easy to understand. They do not rely on the Client to ensure the stable operation of the entire system, but can also achieve customized control over empty objects, master the initiative to process empty objects.

Stage Summary

The conditional logic may be very complex. Therefore, the simplified conditional expression Section 1-7 provides a refactoring method to simplify them. One core reconstruction is Decompose Conditional, which can divide a complex Conditional logic into several small pieces. This refactoring is important because it separates "branch logic" from "Operation Details.

If the Code has the same results for multiple tests, the repeated lidate Conditional Expression should be implemented. If the Conditional code has any duplicates, you can use the repeated lidate Duplicate Conditional Fragments to remove the Duplicate components.

If the program developer adheres to the "Single Exit" principle, in order for the conditional expression to follow this principle, the program developer will usually add control labels in it, replace Nested Conditional with Guard clses can be used to identify special situations and Remove the annoying Control Flag using the Remove Control Flag.

If a switch statement appears in an object-oriented program, you can use Replace Conditional with Polymorphism to Replace it with Polymorphism.

Polymorphism also has a very useful but little-known purpose: to use Introduce Null Object to remove null values.

 

 

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.