Preface
This article is translated from <How I explained OOD to my wife> In CodeProject. This article ranks 3rd in the Top Articles. After reading this article, I think it is very good, for the reference of students who do not want to read English.
The wife of the author (Shubho), Farhana, plans to become a new software engineer (she was born and gave up later ), so the author tried to help her learn object-oriented design (OOD) based on her experience in software development and design ).
Since the author started software development, the author often noticed that no matter how complicated the technical questions appear, it would be easier to explain from the perspective of real life and discuss them in a correct way. Now they share some fruitful conversations with OOD, and you may find it an interesting way to learn OOD.
The following is their conversation:
About OOD
Shubho: Dear, let's start learning about OOD. Do you understand the object-oriented principle?
Farhana: Do you mean encapsulation, inheritance, and polymorphism? I know.
Shubho: Well, I hope you know how to use classes and objects. Today we are studying OOD.
Farhana: Wait. Is the object-oriented principle not enough for Object-Oriented Programming (OOP? I mean, I will define classes and encapsulate attributes and methods. I can also define the layers between them based on the relationship between classes. If so, what else?
Shubho: Good question. The object-oriented principle and OOD are actually two different aspects. Let me give you an example in real life to help you understand.
When you were a child, you first learned the alphabet, right?
Farhana: Well
ShubhoGood. You also learned words and how to create words according to the alphabet. Later, you learned some syntax for making sentences. For example, tenses, prepositions, hyphens, and other sentences that allow you to make correct syntaxes. For example:
"I" (pronoun) "want" (verb) "to" (prefix) "learn" (verb) "OOD" (noun ).
Look, you have combined words according to certain rules, and you have chosen correct words with some meanings to end the sentence.
Farhana: OK. What does this mean?
Shubho: The object-oriented principle is similar to this. OOP refers to the basic principles and core ideas of object-oriented programming. Here, OOP can be compared to basic English syntaxes, which teach you how to construct meaningful and correct sentences with words. OOP teaches you to construct classes in code generation, encapsulate attributes and methods in the class and construct the hierarchical relationship between them.
Farhana: Well, I feel a little bit. Is there good here?
Shubho: There will be an answer immediately. Now suppose you need to write several articles or essays on some topics. You also want to write a few books that you are good. It is not enough to know how to make sentences for writing articles/essays or books, right? To help readers understand what you are talking about, you need to write more content and learn to explain it in a better way.
Farhana: It seems a little interesting... continue.
Shubho: Now
If you want to write a book on a topic, such as learning OOD, you know how to divide a topic into several subtopics. You need to write several chapters for these questions, and you also need to write the preface, introduction, and examples in these chapters.
And other paragraphs. You need to write a general framework and learn some good writing skills so that readers can easily understand what you want to say. This is the overall planning.
In software development, OOD is the overall idea. To some extent, when designing software, your classes and code must be modularized, reusable, and flexible. These good guiding principles do not need to be re-invented. There are indeed some principles that you have used in your classes and objects, right?
Farhana: Well, I have a rough impression, but I need to continue to explore it.
Shubho: Don't worry. You will learn it soon. We will continue our discussion.
Why OOD?
Shubho: This is a very important issue. Why do we need to care about OOD when we can quickly design some classes to complete development and release? Isn't that enough?
Farhana: Well, I didn't know good. I have been developing and releasing projects. So what is the key?
Shubho: Okay. Let me give you a famous saying:
Walking on the frozen river without wet shoes, and projects with unchanged development requirements are unobstructed (Walking on water and developing software from a specification are easy if both are frozen)
-Edward V. Berard
Farhana: What do you mean is the software development specification changing?
Shubho: Very correct! The only truth in software development is that "software will change ". Why?
Because your software solves business problems in real life, business processes are constantly changing in real life.
Suppose your software works well today. But does it support "change" flexibly? If not, you will not have a software with agile design.
Farhana: Well, please explain "Agile Software Design ".
Shubho: "A software with agile design can easily cope with changes, be scalable, and be reused. "
The Application of "Object-Oriented Design" is the key to agile design. So when can you say that you have applied OOD well in the code?
Farhana: This is my problem.
Shubho: If your code can do the following:
- Object-oriented
- Reuse
- Meeting changes at minimal cost
- You do not need to change the existing code to meet the scaling requirements.
Farhana: And?
Shubho: We are not isolated. Many people have thought a lot about this issue and have made great efforts. They are trying to do a good job, and points out several basic principles for OOD (those inspiration you can use for your OOD ). They finally summed up some general design patterns (based on Basic Principles ).
Farhana: How many can you say?
Shubho: Of course. There are many principles involved here, but the most basic is the SOLID 5 principle (thanks to Uncle Bob, great OOD Mentor ).
S = Single Responsibility Principle Single Responsibility PrincipleO = open and Closed Principle Opened Closed Principle L = Liscov replacement Principle Liscov Substitution PrincipleI = Interface isolation Principle Interface Segregation PrincipleD = Dependency Inversion Principle
Next, we will discuss every principle carefully.
Single Responsibility Principle
Shubho: I will show you a poster first. We should thank you for making this poster. It is very interesting.
Single Responsibility Principle poster
It said, "it's not because you can, you should do it ". Why? In the long run, it will cause many management problems.
From the object-oriented perspective :"There will never be more than one cause of class changes."
Or "one class has only one responsibility ".
Farhana: Can you explain it?
Shubho: Of course, this principle means that if your class has more than one reason, it will lead to changes (or more than one responsibility ), you need to share their responsibilities to split the class into multiple classes.
Farhana: Well... does this mean that there cannot be multiple methods in a class?
Shubho: No. Of course, you can include multiple methods in a class. The problem is that they are all for one purpose. Why is splitting important today?
This is because:
- Each responsibility is subject to an axial change;
- If the class contains multiple responsibilities, the code will become coupled;
Farhana: Can you give me an example?
Shubho: Of course, look at the class hierarchy under the category. Of course, this example is from Uncle Bob. Thank you again.
Class Structure Diagram in violation of the single Responsibility Principle
Here, the Rectangle class does the following two things:
- Calculates the rectangular area;
- Draw a rectangle on the interface;
In addition, two applications use the Rectangle class:
- This class is used to calculate the area of Geometric Applications;
- The graphics program uses this class to draw a rectangle on the interface;
This violates SRP (single responsibility principle );
Farhana: How does one violate the rules?
Shubho: You see, the Rectangle class does two things. In one method, it calculates the area, and in another method it returns a GUI that represents a rectangle. This will bring about some interesting questions:
The GUI must be included in the computing ry application. That is, when developing ry applications, we must reference the GUI library;
Changes in the Rectangle class in graphic applications may lead to changes in computational ry, compilation, and testing, and vice versa;
Farhana: Interesting. So I guess we should split this class according to our responsibilities, right?
Shubho: Very correct. Guess what we should do?
Farhana: Of course, I will try it. Below is what we may do:
Split responsibilities into two different classes, for example:
- Rectangle: This class should define the area () method;
- Rectangleui: This class should inherit the rectangle class and define the draw () method.
Shubho: Very good. Here, the Rectangle class is used by computational ry applications, while the RectangleUI is used by graphic applications. We can even separate these classes into two independent DLL classes, which allows us to implement them without having to care about the other one during changes.
Farhana: Thank you. I think I understand SRP. SRP seems to separate things into molecular parts for reuse and centralized management. Nor can we use SRP at the method level? I mean, we can write some methods that contain code that does a lot of things. These methods may violate SRP, right?
Shubho: You understand. You should break down your methods so that each method can only do one job. This allows you to reuse methods, and once there is a change, you can purchase the code that meets the change with the minimum modification.
Opening and Closing principles
Shubho: Here is the Opening and Closing principles of posters.
Opening and Closing principles poster
From the perspective of object-oriented design, it can say :"Software entities (classes, modules, functions, etc.) should be open to extensions and closed to modifications."
In general, it means that you should be able to expand the behavior of a class without modifying the class. It's like I don't need to change my body and I can wear my clothes.
Farhana: Interesting. You can change your face by wearing different clothes as you wish, instead of modifying your body. You are open to expansion, right?
Shubho: Yes. In OOD, extended development means that the behavior of classes or modules can be changed. When demand changes, we can change modules in new and different ways, or meet the requirements in the new application.
Farhana: And your body is closed for modification. I like this example. The source code of the core class or module should not be changed when changes are required. Can you explain it with some examples?
Shubho: Of course, let's look at the example below. It does not support the "open and closed" principle.
Class structure that violates the development closure Principle
As you can see, the client and service segment are coupled. As long as there is any change, the server changes, and the client needs to change.
Farhana: Understanding. If a browser is implemented by a specified server (such as IIS) in a tightly coupled manner, if the server is replaced by another server (such as APACHE) for some reason, the browser also needs to be modified or replaced. This is really terrible!
Shubho: Yes. The following is the correct design.
Class structure following the open and closed principles
In this example, an abstract server class is added, and the client contains an abstract class reference. The specific service class implements the abstract service class. Therefore, the client does not need to change the service implementation for any reason.
Here, the abstract service class is closed for modification, and the implementation of the entity class is open for extension.
Farhana: I understand that abstraction is the key, right?
Shubho: Yes. Basically, what you abstract is the core content of your system. If you abstract it well, it is very likely that it does not need any
How to modify (like a service is an abstract concept ). If abstract things (such as services implemented by the IIS server) are defined in the implementation, the code should be based on abstract (Service) as much as possible. This will allow you to expand
Define a new implementation (such as an Apache server) without modifying any client code.
Liskov's replacement principle
Shubho: "Liskov's replacement principle (LSP)" sounds very difficult, but it is a very useful basic concept. Take a look at this interesting poster:
Liskov replacement principle poster
This principle means :"Child types must be able to replace their base types."
Or another way :"A function referenced by a base class must be able to use an object that inherits the class without having to know it."
Farhana: Sorry, it sounds a bit confusing. I think this is one of the basic principles of OOP. That is, polymorphism, right? Why do we need to say this in an object-oriented principle?
Shubho: Yes. This is your answer:
In the basic object-oriented principle, "inheritance" is usually"Is. If "Developer" is a "softwareprofessional", the "Developer" class should inherit the "softwareprofessional" class. In class design"Is"The relationship is very important, but it is easy to get confused, and incorrect inheritance causes incorrect design.
"Liskov replacement principle"It is the method that ensures that inheritance can be used correctly.
Farhana: I understand. Interesting.
Shubho: Yes, dear, indeed. Let's look at an example:
Structure of the liskov replacement principle class
Here, the kingfisher class extends the bird base class and inherits the fly () method, which looks okay.
Now let's look at the following example:
Class Structure Diagram in violation of the liskov replacement principle
Ostrich (Ostrich) is a bird (apparently) that inherits from the bird class. Can it fly? No, this design violates LSP.
Therefore, even if it seems that there is no problem in reality, in class design, ostrich should not inherit from the bird class. Here we should separate a non-flying class from the bird, ostrich should inherit from it.
Farhana: OK, see. So let me try to figure out why LSP is so important:
- Without LSP, class inheritance will be chaotic; if the subclass is passed to the method as a parameter, unknown behavior will occur;
- If no LSP exists, unit tests applicable to the base class cannot be successfully used for the test subclass;
Right?
Shubho: Very correct. You can design objects and use LSP as a check to test whether the inheritance is correct.
Interface separation principle
Shubho: Today we are going to learn "interface separation principles". Here is the poster:
Poster of interface separation principle
Farhana: What does this mean?
Shubho: It means: "clients should not be forced to rely on interfaces they do not use. "
Farhana: Please explain.
Shubho: Of course, this is an explanation:
Suppose you want to buy a TV set. You have two options. There are a lot of switches and buttons, they look messy, and it seems unnecessary for you. The other has only a few switches and buttons. They are friendly and suitable for you. If the two TVs provide the same function, Which one will you choose?
Farhana: Of course, there are only a few switches and the second button.
Shubho: Yes, but why?
Farhana: I don't need any switches or buttons that seem messy and useless to me.
Shubho: So that the external can know which functions are available for these classes, and the client code can also be designed according to the interface. at present, if the interface is too large and contains many exposed methods, it may seem confusing to the outside world. an Interface contains too many methods to reduce its availability. For example, a "Fat interface" containing useless methods will increase coupling between classes. you expose the functions of the class through the interface. similarly, suppose you have some classes,
This also causes other problems. If a class wants to implement this interface,So it needs to implement all the methods, although some of them may be completely useless.Therefore, this will introduce unnecessary complexity in the system,Reduces maintainability or robustness.
The interface isolation principle ensures that the Implemented interfaces have their common responsibilities and they are clear,Easy to understand and reusable.
Farhana: You mean that the interface should only contain the necessary methods, rather than other methods. I understand.
Shubho: Very correct. Let's take a look at the example.
The following is a fat interface that violates the interface isolation principle.
Note that the IBird Interface contains many bird behaviors, including Fly () behavior.If a Bird class (such as Ostrich) implements this interface,Then it needs to implement unnecessary Fly () behavior (Ostrich will not Fly).
Farhana: Indeed. So this interface must be split?
Shubho: Yes. This "Fat interface" should split not two different interfaces,IBird and IFlyingBird,IFlyingBird inherits from IBird.
If a bird does not fly (such as Ostrich ),Then it implements the IBird interface. If a bird can fly (Such as KingFisher), then it implements IFlyingBird.
Farhana:So let's look back at the examples of TV sets that contain many switches and buttons,The TV manufacturer should have a TV set drawing,Both the switch and button are in this solution. Anytime,If they want to reuse the drawing when they are making a new TV,They will need to add more switches and buttons in this solution.So they won't be able to reuse this scheme, right?
Shubho: Yes.
Farhana: If they do need to reuse the solution,They should make a smaller part of the TV's drawings,This small part can be reused when new TV sets are needed.
Shubho: You understand.
Dependency inversion principle
Shubho: This is the last principle in the SOLID principle. This is a poster.
It means:The high-level module should not depend on the underlying module, both of which should depend on its abstraction.
Shubho: Consider a real-world example. Your car is powered by many engines,Wheels, air conditioners, and other components, right?
Farhana: Yes
Shubho: Well, none of them are strictly built into a single unit;In other words, they are all pluggable, so when an engine or wheel goes wrong,You can repair it (without having to repair other parts), or even change it.
During replacement, you only need to ensure that the engine or wheel meets the design of the car (For example, a car can use any cc engine or any 18-inch wheel ).
Of course,The car may also allow you to install a 2000CC in the area of the 1500CC engine.The engine is actually the same for some manufacturers (such as Toyota.
What is the difference if your auto parts are not pluggable?
Farhana: That would be terrible! Because if a car's engine fails,You may need to repair the entire car or buy a new one.
Shubho: Yes. How can we achieve "pluggable?
Farhana: Abstraction is the key, right?
Shubho: Yes. In reality, a car is an advanced module or entity,It depends on low-level modules or entities, such as engines or wheels.
Compared to directly relying on engines or wheels,Cars should rely on certain abstract engines or wheels with specifications,So that if any engine or wheel is abstract, they can be combined into a car,Cars can also run.
Let's take a look at the class diagram below.
Shubho: Note that the above Car class has two attributes,They are all abstract types (interfaces ). The engine and wheel are pluggable,Because the car can accept any object that implements the declared interface,The Car class does not need to be modified.
Farhana: If Dependency inversion is not required in the code,We will face the following risks:
Using a low-level class will break through the advanced code;
When a low-level class changes, it takes a lot of time and cost to modify the advanced code;
Produce Low-reuse code;
Shubho: You have full control, dear!
Summary
Shubho: In addition to the SOLID principle, there are many other object-oriented principles.For example:
"Combination substitution inheritance": Compared with inheritance, combination is preferred;
"Dummit's Law": This is to say, "The less your class knows about other classes, the better ";
"The principle of joint closure": this is to say "related classes should be packaged together ";
"Stable abstraction principle": "The more stable the class, the more it should be composed of abstract classes ";
Farhana: Should I learn those principles?
Shubho: Of course. You can learn from the Internet.Just Google those principles and try to understand them.If necessary, ask me.
Farhana: I have heard of many design patterns based on those design principles.
Shubho: Yes.The design pattern is just some general design suggestions for some common scenarios.These inspirations mainly come from the object-oriented principle. You can regard the design pattern as a "Framework"The OOD principle is regarded as "normative ".
Farhana: Will I learn the design pattern next?
Shubho: Yes, dear.
Farhana: That would be interesting, right?
Shubho: Yes, that is really exciting.
Source: http://www.cnblogs.com/niyw/archive/2011/01/25/1940603.html