A refactoring pattern for adding new requirements to old code

Source: Internet
Author: User

Application Scenarios

I believe you have encountered this scenario:
There are already a bunch of if-else or switch-case in the old code, and the product requires adding a new function to the process.

What do people do at this time?
My advice is to:

Refactor this piece of code. On the basis of refactoring, new functions are added.

Someone will say:

The duration of the original tense, and then re-construction of the old code, will not be more stretched?

This approach, which I've often used in practice, is what I call the "interface-distributor pattern." It can do most of the refactoring work while minimizing the refactoring effort.

Class diagram

interface-Dispatcher class diagram

Interface

This pattern first extracts the old code/function into an interface (Serviceinterface.java). The abstraction of this interface should be able to overwrite both the original logic in the old code and the functionality in the new requirements. In other words, both the new and the old code can be abstracted to the same interface.
If this is not possible, it is advisable to look back and think that these two logic should not be placed in the same abstraction.

For example, the interface I pulled in a refactoring:

public interface Requestapprover {void Approvebyid (Integer ID, Request requestinfo, UserInfo approver) thr oWS serviceexception;}


This interface is an abstraction of the approval operation on the request data (requests).
There are three types of request data (two of the old types, one for the new requirements), and there are three types of approval operations (again, two of the old types, one for the new requirements). In this way, there are up to nine approval logic (but only six in practice). These approval logic and code can be described with this interface.

Distribution Device

The Dispatcher (Servicedispatcher.java) is the gateway to the service. However, it does not provide any business services in its own right, but is only responsible for distributing the request to the actual service processing class.
From this point of view, the dispenser is actually much like a factory. That's true, but the focus of this dispatcher is "distribution," not "create."
In addition, hiding it under the external interface is because I understand this dispatcher as an implementation of an interface, which is in abstraction and does not need to be perceived by callers outside of abstraction. This is my personal preference.

Corresponding to the previous interface, I used the distributor is this.

Class requestapproverasdispatcher Requestapprover {    private requestapprover Approver4first4notlate;    private requestapprover approver4First4PseudoOver;     private requestapprover approver4final4notlate;    private  Requestapprover Approver4final4m1;    private requestapprover Approver4Final4PseudoOver ;      @Override     public void approvebyid (Integer ID, Request Requestinfo,            userinfo Approver)  throws serviceexception {        requestapprover requestapprover;        switch  (Some_field) {             case FIRST_APPROVED:             case first_rejected:                 requestapprover = xxx;                 break;              case approved:            case  REJECTED:                 requestapprover = yyy;                 break;            default:                 throw new  Unsupportedoperationexception ();        }         requestApprover.approvebyid (ID, requestinfo, approver);     }}
Specific service categories

The specific service class assumes the actual business logic. In the class diagram, they are represented as Service4scene1.java ~ Service4scene7.java. And, I specifically painted serviceasadapter.java and Serviceasskeleton.java to say: These specific service classes can also have their own way of organizing, apply their own application mode.

In my example above, I defined the template through a requestapproverasskeleton.java. In another requirement, I used a combination and an intermediary--at least I understood those classes as a mediation pattern.

Summary

Essentially, this so-called "interface-Distributor pattern" is a policy pattern. But it's a bit more than the strategy pattern--the dispenser. In addition, in practical applications, it cannot only be a strategy. In the "Specific service class" organization, almost will use more models.
On the other hand, in the application of the design pattern, there must be a factory in the strategy, there are almost a few factories have a single case, which seems to have become a "model."

Refactoring

So how does this "pattern" apply to refactoring?
It's simple--make old code and new code a member of a "specific service class," and be a different member.

Still, in the example above, I've arranged the old code and the new code in each of these two classes. Combined with the previous dispatcher, it was very simple to complete the refactoring and complete the new requirements at the same time.

The old code is in this class:

class requestapprover4first extends         Requestapproverasskeleton {     private static final logger Logger = Loggerfactory        .getlogger (Requestapprover4first.class);      private requestservice service;      @Override      protected void approve (Request requestinfo,             request Request)  throws invaliddataexception {             ......    }     @ Override    protected void reject (Request requestinfo,             request Request) {         //does not do the processing     }&NBsp;     @Override     protected void configrequest (Request Requestinfo,            request Request, UserInfo Approver) {            ......    }  }

And the new business is in this service:

class requestapprover4check extends         Requestapproverasskeleton {     private static final logger Logger = Loggerfactory        .getlogger (Requestapprover4check.class);       @Override     public void approvebyid (Integer ID, Request Requestinfo,            userinfo approver)   Throws serviceexception {        ......         //This method has additional processing     }      @Override      protected void approve (Request requestinfo,             request Request)  throws serviceexception {         ......    }      @Override     protected void reject ( Request Requestinfo,            request request) {         //does not do any operation     }       @Override     protected void configrequest (Request requestinfo,             request Request, UserInfo approver) {             ......    } }

Pros and cons

The advantages should be obvious: the new, the old logic and the code are separated, and the understanding of the coupling is complete. And later, if you want to add new requirements, you can easily isolate to the new service class. It is believed that friends who have inherited the old system and old code can understand the meaning.

In addition, the old code can be persisted, or simply copied into the corresponding service class. Therefore, the reconstruction workload is relatively small.


What are the drawbacks? One is easy to cause "class explosion". Although it doesn't have to be too much, the number of classes is definitely more than no pattern. Second, this pattern sometimes does not (and does not need) make any changes to the old code. In this way, the refactoring goal is not actually implemented.

Last additions

Before refactoring, be sure to have a test that validates the functionality of the old code and overwrite the process branch as much as possible.


This article is from the "Programming Capricorn Man" blog, make sure to keep this source http://winters1224.blog.51cto.com/3021203/1879788

A refactoring pattern for adding new requirements to old code

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.