Programmer's artistic temperament-SOLID Principle

Source: Internet
Author: User
Tags coding standards

Yesterday, Amazon gave a lecture in our school, mainly to share some experience with us: as a programmer, the coding hard technology and Working soft technology. Of course, they also have the purpose of recruiting talents in our school. They want to attract us to their company. For me, I certainly want to go to such a awesome company, I have certainly learned some knowledge about this lecture. Students without practical projects often cannot write beautiful Code (including coding specifications, annotations, design patterns, and performance), because they pay more attention to correctness, as long as the results come out and are correct, it is good code. I don't know how painful it will be for the company's project manager to show it! Well, no. As a student, I have to learn coding standards first. Every company has its own set of rules, so I will not talk about it. Secondly, it is the code design model, this is too big and requires constant learning and accumulation. As we all know, the most basic principle of Java programming is to pursue High Cohesion and low coupling solutions and code module design, here, I will first learn about the SOLID principle that programmers should have.

S.O.L. I. D is the abbreviation of several important coding principles (Programming Priciple) in object-oriented design and Programming (OOD & OOP.

SRP The Single Responsibility Principle Single Responsibility Principle
OCP The Open Closed Principle Open and closed Principle
LSP The Liskov Substitution Principle Rys replacement principle
ISP The Interface Segregation Principle Interface separation principle
DIP The Dependency Inversion Principle Dependency inversion principle

 

1. Single Responsibility Principle (SRP)
There is only one reason for modifying a class. In other words, let a class only take one type of responsibility. When this class needs to take responsibility for other types of responsibilities, it needs to be broken down. Classes are highly likely to be modified, so you should focus on a single function. If you place multiple functions in the same class, the functions are associated. If you change one function, you may abort another function, in this case, a new round of testing is required to avoid possible problems, which is time-consuming and labor-consuming.

Example:

Create a Rectangle class, which contains two methods: one for drawing a Rectangle on the screen and the other for calculating the area of the Rectangle.

 

The Rectangle class violates the SRP principle. The Rectangle class has two responsibilities: if one of the changes affects the changes of the two applications.

A good design is to separate two responsibilities into two different classes so that any change will not affect other applications.

2. Open and closed principles(OCP)
The software entity should be extensible and unchangeable. That is to say, it is open to extensions and closed to modifications. This principle is the most abstract and hard to understand among many object-oriented programming principles.

(1) Add code to Expand functions, rather than modifying existing code.
(2) If the customer module and the service module follow the same interface, the customer module can not care about the type of the service module, and the service module can easily expand the service (CODE ).
(3) OCP supports replacement services without modifying the customer module.

Example:

Public boolean sendByEmail (String addr, String title, String content) {} public boolean sendBySMS (String addr, String content) {} // call the above method to send the message sendByEmail (addr, title, content) elsewhere );
SendBySMS (addr, content );

If there is another method for sending information, for example, sending information via QQ, you need not only to add the sendByQQ () method, but also to modify it at the place where it is called, in violation of the OCP principle, the better way is

Public boolean send (int type, String addr, String title, String content) {if (type = 0) {// send in all ways} if (type = 1) {// send via Email} if (type = 2) {// send... send ...}} // call the above method to send messages (0, addr, title, content) elsewhere );

 

3. Lee's replacement principle(LSP)

When A subclass instance should be able to replace any of its superclasses, There is A is-A relationship between them.

The customer module should not care about how the service module works; the same interface between modules can be replaced without knowing the service module code. That is, where the interface or parent class appears, the class or subclass implementing the interface can be substituted.

Example:

Public class Rectangle {private double width; private double height; public void setWidth (double value) {this. width = value;} public double getWidth () {return this. width;} public void setHeight (double value) {this. width = value;} public double getHeight () {return this. height;} public double Area () {return this. width * this. height ;}} public class Square extends Rectangle {/* because the parent class Rectangle is not designed to be inherited by Square in the future, the width and height fields in the parent class are set to private, in the subclass Square, you can only call the attributes of the parent class to set/get, specifically omitting */} // test void TestRectangle (Rectangle r) {r. weight = 10; r. height = 20; Assert. areEqual (10, r. weight); Assert. areEqual (200, r. area) ;}// Rectangle r = new Rectangle (); TestRectangle (r); // now both Assert tests fail, Square s = new Square (); testRectangle (s );

LSP makes us come to a very important conclusion: If a model is isolated and does not have a true validity, the validity of the model can only be expressed through its customer program. For example, to view Rectangle and Squre in an isolated manner, they are self-compatible and valid. However, from the perspective of the customer program TestRectangle (Rectangle r) that makes reasonable assumptions on the base class Rectangle, this model is faulty.When considering whether a specific design was just at the time, we could not look at the solution in full isolation, but we had to examine it based on the reasonable assumptions made by the users of the design.

At present, there are also some technologies that support us to clarify reasonable assumptions, such as Test-Driven Development (TDD) and Design by Contract (DBC ). But who knows what reasonable assumptions the design users will make? Most of these assumptions are unpredictable. If we predict all the assumptions, the system we design may also be full of unnecessary complexity. The recommended practice is to only predict the most obvious violations of the LSP, and postpone the prediction of all other assumptions until the relevant vulnerability Smell (Bad Smell) occurs, to process them. I think this sentence is not straightforward enough. In Martin Fowler's Refactoring book, "Refused Bequest" (rejection legacy) describes in more detail: subclass inherits the methods and data of the parent class, however, subclasses only need part of the parent class Methods or data, rather than all methods and data. When this happens, it means that there is a problem with our inheritance system. For example, in the preceding Rectangle and Square, Square itself has the same length and width, and edge lengths are used to represent edges in the ry. In the Rectangle and width, Square has already Refused the Bequest of Rectangle, it is an unreasonable design to inherit Rectangle from Square.

Now back to the basic concept of object-oriented, subclass inherits the parent class to express a IS-A relationship, which is considered to be one of the basic technologies of Object-Oriented Analysis (OOA. But the square is indeed a rectangle, do they do not have a IS-A relationship between them? In this regard, the book Java and patterns explains that when we design an inheritance system,Subclass should be an alternative parent class, Is an alternative relationship, not just the relationship of IS-A; and the interpretation of PPP book is: From the Perspective of behavior, Square is not Rectangle, the behavior of objects is a real concern of the software. LSP clearly points out that,In the case of a IS-A relationship in OODThe customer program can make reasonable assumptions about the behavior mode. In fact, they both express the same meaning.


4.Interface separation principle(ISP)

Users cannot be forced to rely on interfaces they do not use. In other words, it is better to use multiple dedicated interfaces than to use a single total interface.

The customer module should not rely on large interfaces. It should be reduced to small interfaces for use by the customer module to reduce dependencies. For example, a class in Java implements multiple interfaces. Different interfaces are used by unused customer modules, rather than a large interface provided to the customer module.

Example:

Public interface Animal {
Public void eat (); // eat public void sleep (); // sleep public void crawl (); // crawl public void run (); // run} public class Snake implements Animal {public void eat () {} public void sleep () {} public void crawl () {} public void run () {}} public class Rabit implements Animal {public void eat () {}public void sleep () {} public void crawl () {} public void run (){}}

In the above example, Snake has no run behavior and Rabbit has no crawl behavior, but here they must implement such unnecessary methods. The better way is crawl () run () and run () are independent interfaces, which need to be adjusted according to the actual situation. Do not put all functions in a large interface anyway, these functions are not required by every class that inherits the interface.

5.Dependency injection or inversion principle(DIP)

1. High-level modules should not depend on low-level modules, both of which should depend on abstraction
2. abstraction should not depend on details, but on abstraction.

The highlight of this design principle is that any class injected by the DI framework can easily be tested and maintained using the mock object, because the client code is not chaotic when the object creation code is concentrated in the framework. There are many ways to implement Dependency inversion, such as the bytecode technology used by the AspectJ (Aspect Oriented programming) framework, or the proxy used by the Spring framework.

(1) The high-level module should not depend on the lower-level module;
(2). the high-level and low-level modules must depend on abstraction;
(3) Abstraction should not depend on specific implementations;
(4). The specific implementation depends on abstraction;
(5) abstract and interface separation of dependencies between modules.

First, let's look at it from a macro perspective. For example, we often use a macro architecture model-layer mode, through layer concept decomposition and architecture system, for example, it is common to have a three-tier architecture. The dependency relationship should be top-down, that is, the upper-layer module depends on the lower-layer module, and the lower-layer module does not depend on the upper-layer module, as shown in.
This should be easier to understand, because the lower-layer modules are relatively more stable and fewer changes are made. The higher the upper layer and the higher the requirement coupling, the more frequent changes will be made, therefore, the top-down dependency does not affect the lower layer when the upper layer changes. This reduces the risks caused by changes and ensures system stability. The above results are based on the overall architecture layer. from another perspective, we will analyze the details. Here, we only focus on the relationship between the UI and the service, what are the problems with dependencies like the following?
First, when we need to append a new service, we have to modify the UI Layer and add additional work. Second, this change may affect the UI and cause risks. Third, after the changes, both the UI Layer and the logic layer must re-Execute unit testing.
So how can we optimize the dependency to lower the coupling between modules or layers? Think about the OCP principles mentioned above. The viewpoint is similar. We can append an abstract layer to the service. The upper UI does not depend on the Service's details. The UI and service depend on the abstract layer of the service at the same time. This is the result of our improvement.
What are the benefits of this improvement? First, when the service is extended, the UI Layer is generally not affected and the UI does not need to be modified. Second, when the service is extended, the UI Layer does not need to perform unit testing again.

These principles are very basic and important object-oriented design principles. It is precisely because of the fundamentals of these principles that a great deal of experience and knowledge is required to understand and integrate these principles. The example may not be very relevant or accurate. You just need to understand it. In the future, you must follow these principles for internships, I cannot let the code I have written so that others can approve the code for nothing. Of course, there are other very important principles. I will continue to learn and share it later!

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.