preface

After looking at the refactoring code from the previous article, you might ask:

When adding the new alarm logic, change 2 (adding the new handler class) is done in an extension rather than a modification manner, but changes 1, 3, and 4 seem to be done not in an extension but in a modification manner.

Doesn’t that change one, three, four violate the open closed principle?

public class Alert { // The code is unchanged... }

public class ApiStatInfo {/ / to omit the constructor/getter/setter methods

  private String api;

  private long requestCount;

  private long errorCount;

  private long durationOfSeconds;

  private long timeoutCount; // Change 1: add a new field

}

public abstract class AlertHandler { // The code is unchanged... }

public class TpsAlertHandler extends AlertHandler {// The code is unchanged... }

public class ErrorAlertHandler extends AlertHandler {// The code is unchanged... }

// Change 2: add a new handler

public class TimeoutAlertHandler extends AlertHandler {// Omit the code... }

public class ApplicationContext {

  private AlertRule alertRule;

  private Notification notification;

  private Alert alert;



  public void initializeBeans(a) {

    alertRule = new AlertRule(/*. Omit parameters.*/); // Omit some initialization code

    notification = new Notification(/*. Omit parameters.*/); // Omit some initialization code

    alert = new Alert();

    alert.addAlertHandler(new TpsAlertHandler(alertRule, notification));

    alert.addAlertHandler(new ErrorAlertHandler(alertRule, notification));

    // Change 3: register handler

    alert.addAlertHandler(new TimeoutAlertHandler(alertRule, notification));

  }

  / /... Omit other unchanged code...

}

public class Demo {

  public static void main(String[] args) {

    ApiStatInfo apiStatInfo = new ApiStatInfo();

    / /... Omit the set field code for apiStatInfo

    apiStatInfo.setTimeoutCount(289); // Change 4: set tiemoutCount

    ApplicationContext.getInstance().getAlert().check(apiStatInfo);

}
Copy the code

Let’s first examine change one: adding a new property, timeoutCount, to the ApiStatInfo class.

  1. We not only added properties to the ApiStatInfo class, but also the corresponding getter/setter methods. The question then becomes: Does adding new properties and methods to a class count as a “modification” or an “extension”?

Again, recall the definition of the open closed principle: software entities (modules, classes, methods, etc.) should be “open for extension, closed for modification.”

From the definition, we can see that the open closed principle can be applied to different granularity of code, be it modules, classes, or methods (and their properties).

Similarly, a code change is considered a “modification” at coarse code granularity and an “extension” at fine code granularity.

  1. For example, change 1, adding properties and methods is equivalent to changing the class. At the class level, this code change is considered a “change.” However, this code change does not modify the existing properties and methods, and at the level of methods (and their properties), it can be considered an “extension.”

Let’s go back to how this principle was designed: as long as it doesn’t break the functioning of the original code and doesn’t break the original unit tests, we can say that it’s a qualified code change.

Next, look at change 3 and Change 4: In the initializeBeans () method of the ApplicationContext class, register the new timeoutAlertHandler in the Alert object; When we use the Alert class, we need to set the value of timeoutCount to the apiStatInfo object that is the incoming argument to check ().

  1. Both of these changes are internal to the method and are not “extensions” at any level (modules, classes, methods), but “modifications”.

  2. Some modifications, however, are inevitable and acceptable.

In the refactored Alert code, our core logic is concentrated in the Alert class and its individual handlers. When we add new alarm logic, the Alert class does not need to be modified at all, but only needs to be extended by a new handler class. If we consider the Alert class and the various handler classes together as a “module,” the module itself fully satisfies the open closed principle when adding new functionality.

Also, recognize that it is impossible to add a new feature without “modifying” the code of any module, class, or method. Classes need to be created, assembled, and initialized to build a running program, and this part of the code is bound to change. What we want to do is to make the modifications as concentrated, as few, and as high-level as possible, and try to make the core, the most complex part of the logic code satisfy the open closed principle.

More Java original reading: Javawu.com