Out of 25 questions, you know how many
- How to understand the single responsibility principle?
- How do you determine if the responsibilities are simple enough?
- Are responsibilities as simple as possible?
- What is the open close principle?
- Does changing code necessarily mean violating the open close principle?
- What code changes are defined as extensions or modifications?
- How do I open for extensions and close for modifications?
- How to apply the open and close principle flexibly in a project?
- What is the dependency inversion principle?
- What are the concepts of high level modules and low level modules?
- How to understand the word inversion?
- What dependencies have been reversed?
- What is inversion of control
IOC
(Inversion Of Control
)? - What is dependency injection
DI
(Dependency Injection
)? IOC
和DI
What’s the difference?- Is fewer lines of code simpler?
- If the code is logically complex, it violates it
KISS
The principle? - How to write satisfaction
KISS
Code for principles? - How do I determine if I am satisfied
KISS
Principle? - Duplicate code is bound to be violated
DRY
? - How can you improve your code’s reusability?
- What is Demeter’s rule?
- What is the sense of high cohesion and loose coupling?
- What about high cohesion and loose coupling?
- How to use Demeter’s rule well?
Read these questions, is not excited, excited, that you want to progress and growth.
Writing style
Just say a few words to liven things up. Then, by asking questions, answering questions, and then combining life examples with code, the design principles are explained in all directions.
Why learn design principles
I gave you too much freedom
People need principles, so when you write code, do you talk about principles?
It’s time for the show to begin.
Gao Zan answer: bad consciousness, I have no principle.
Ha ha ha ha, then I can only say, you are light, you are electricity, you are the only myth.
The lower you go, the freer you are
Do you feel that way? No, it doesn’t matter. I’ll give you a couple of examples.
Here is an example:
- Product managers write product planning documents for development and testing, at least with a human face
- Interaction Design Writing interaction design documents for development products should at least be human
ui
The designer produces the design draft, gives the development product to look, must have the human appearance at least
Let’s look at the examples above.
When the proud front-end engineer finishes writing the code, then two days later. It’s embarrassing to discover that you don’t know the code you’ve written. However, I am glad that we are at the bottom of the stream after all, and there is no such thing as giving code to anyone to read. At most, we just go to code review.
This feeling is very dangerous when we are very downstream, also means we are very free, it has a lot of negative effects.
So, how do we constrain this freedom? This answer is what this article will elaborate on:
This freedom to overdo is constrained by design principles.
What are the design principles
Please look at the picture below:
The column of design principles in the figure covers all important design principles, such as SOLID, KISS, YANGI, DRY and LOD.
Live not to say, below everyone follow me, step by step to master the design principle!
Use good design principles for purpose
That’s why we need to learn design principles, so think again, what is the purpose of good design principles?
The purpose is to have code or projects that:
- readability
- scalability
- reusability
- maintainability
The bottom line: Reduce the complexity of software development and keep iterations within a reasonable range of difficulty.
OK, with that said, let’s go through these design principles one by one. Please read on.
Note: When I say classes, I also refer to modules, so I won’t write modules separately.
SOLID
This is the first introduction and the most important.
Important things three times:
Remember: In design principles,SOLID
Is the point, andSO
It’s the best of the best.
S
The name of the
- SRP: Single Responsibility Principle
- English: Single responsibility principle
QUESTION
How to understand the single responsibility principle?
A class is only responsible for one responsibility or function, do not design a large and complete class, to design small granularity, single function of the class, simply put, is to be small and beautiful. The purpose of the single responsibility principle is to achieve high cohesion and low coupling of code and improve the reusability, readability and maintainability of code.
How do you determine if the responsibilities are simple enough?
Here are 5 tips:
- Class has too many private methods
- It can be difficult to give a class a proper name
- Too many lines of code, functions, or attributes in a class
- A large number of methods in a class operate on a few properties of the class
- A class depends on too many other classes, or depends on too many other classes
Are responsibilities as simple as possible?
The single responsibility principle improves class cohesion by avoiding the design of large, all-in-one classes and coupling unrelated functions together. At the same time, the single responsibility of the class, it depends on and depends on other classes will also be less, so as to achieve high cohesion, loose coupling code.
Note: If you break it down too much, it actually does the opposite, reducing cohesion and the maintainability of your code.
Life examples
Social division of labor: People who write code don’t also write planning documents.
Code display
Example 1: Meet single responsibilities
useFuncA()
useFuncB()
Copy the code
The above function can be thought of as hooks, a function that does something.
Example 2: Different business layers may or may not conform to a single responsibility
const userInfo = {
userId: ' '.username: ' '.email: ' '.telephone: ' '.createTime: ' '.lastLoginTime: ' '.avatarUrl: ' '.provinceOfAddress: ' '.cityOfAddress: ' '.regionOfAddress: ' '.detailedAddress: ' '
}
Copy the code
- From the perspective of user business, the principle of single responsibility is satisfied.
- At the more granular business level, such as user presentation information, address information, login authentication information, the single responsibility principle is not satisfied.
Example 3: Meet single responsibilities
As you can see from the figure above, a function is done by only one module directory.
Example 4: Not meeting a single responsibility
function bindEvent(elem, type, selector, fn) {
if (fn == null) {
fn = selector
selector = null
}
}
bindEvent(elem, 'click'.'#div', fn)
bindEvent(elem, 'click', fn)
Copy the code
We find that the bindEvent function can pass many arguments and does not conform to the single responsibility principle. It is the embodiment of the appearance pattern idea.
PS:The appearance mode is as follows:
SRP summary
The answer to the above question is summarized, and here we add sentences:
SRP
To be combined with the business scene to look at, different angles, different results.
O
- OCP: Open Closed Principle
- English: Open and close principle
QUESTION
What is the open close principle?
Software entities (classes, modules, functions) should all be open to extension but closed to modification.
That is: adding a new feature should extend code (add modules, classes, methods, etc.) on existing code, not modify existing code.
Does changing code necessarily mean violating the open close principle?
Not necessarily. We have to be flexible about this:
- First: the open closed principle does not mean completely eliminate modification, but to complete the development of new features at the cost of minimal code modification
- Second: The same code change may be considered a change at coarse code granularity and an extension at fine code granularity
- Third: try to make the most core, the most complex part of the logic code to meet the open and closed principle
What code changes are defined as extensions or modifications?
In general, as long as it doesn’t break the original code, it doesn’t break the original unit tests, it’s considered open and closed. If broken, then we can consider it does not meet the open and close principle.
How do I open for extensions and close for modifications?
- Keep functions, classes, and modules in their current state, or close to their normal state (i.e., immutable)
- Use composition (avoiding inheritance) to extend existing classes, functions, or modules so that they may expose new features or functionality under different names
How to apply the open and close principle flexibly in a project?
Always have extended consciousness, abstract consciousness, encapsulation consciousness.
Life examples
College entrance examination paper: for example, tomorrow will be the college entrance examination, but the teacher found that can not distinguish high score students and low score students, must be in the paper to increase two more difficult questions, but tomorrow the college entrance examination, if now to modify the college entrance examination paper, obviously is not reasonable. On reflection, the best way is to add an additional question to the gaokao test paper.
code
Example 1: Middleware
app.use(A).use(B).use(C)
Copy the code
Example 2: Function Optional
fn(f1(),f2(),f3())
Copy the code
Example 3: Plug-ins
Vue.use(PluginA)
Vue.use(PluginB)
Copy the code
Example 4: Decorator
@get('/hello')
async hello() {
// ...
}
Copy the code
conclusion
There are two points:
- Open and close principle is the most important design principle, many design patterns are based on open and close principle
- At its core, it is designed to make code more extensible
L
- LSP: Liskov Substitution Principle
- English: Richter’s substitution principle
Well, why is that abbreviation a little funny, huh?
QUESTION
What is The Richter substitution principle?
Subclasses are designed to follow the behavior conventions (or agreements) of their parent classes. The parent class defines the behavior convention of a function. A subclass can change the internal implementation logic of a function, but cannot change the original behavior convention of a function.
The behavior conventions here include: what functions are declared to implement, conventions for inputs, outputs, exceptions, and even any special instructions listed in the comments.
How do you determine if you satisfy The Richter’s substitution principle?
Take the unit tests of the parent class to verify the code of the subclass. If some unit test runs fail, it is possible that the design implementation of the subclass does not fully comply with the convention of the parent class, and that the subclass may violate the Richter substitution principle.
Life examples
Pirated disc: the disc of original somebody else is legitimate, but now you got a pirated disc, we have two discs, put DVD inside, can run alone [pirated disc copies legitimate disc all over, subclass parent class behavior anticipates consistent]
code
Example 1: The code execution is repeated and does not comply with LSP rules
class People {
constructor(name, age) {
this.name = name
this.age = age
}
eat() {
// ...}}class Student extends People {
constructor(name, age) {
super(name, age)
}
eat() {
// ...}}const kuangXiangLu = new Student('KuangXiangLu'.10)
kuangXiangLu.eat()
Copy the code
Why not LSP? There are two reasons:
Class eat (People, eat); class eat (People, eat)
Second: the output is modified without following the design of the parent class
conclusion
At the heart of the Richter substitution principle is a principle that guides how subclasses should be designed in inheritance relationships, which is design by contract.
I
- ISP: Interface Segregation Principle
- 英 文 : Interface isolation principle
QUESTION
What is the interface isolation principle?
A caller or user of an interface should not be forced to rely on an interface it does not need.
What is an interface in the interface isolation principle?
Interfaces can be understood as three things: a collection of API interfaces, a single API interface or function, and the concept of an interface in OOP
Life examples
Car USB port: There are many ports on the car, but you want to plug in USB port, you want it to have USB function, but also want it to have three-line plug function, this is not scientific thing [each port should have its own role, only responsible for its own role].
code
Code 1:
const obj = {
login() {
// User login},delete() {
// Delete user information}}Copy the code
Delete is an uncommon and dangerous operation. If it is combined with login, it may be mistakenly invoked by services that do not need to delete, which violates ISP rules.
Code 2:
function main() {
// Handle addition
// handle subtraction
// handle multiplication
/ / processing...
}
Copy the code
There’s a lot of logic in one function, and it violates ISP rules.
conclusion
Brothers, fine taste, the most important is isolation.
D
- DIP: Dependency Inversion Principle
- The dependency inversion principle
QUESTION
What is the dependency inversion principle?
Don’t rely on low-level modules. High-level and low-level modules should depend on each other through abstractions. In addition, abstractions should not rely on details. Details should rely on abstractions.
What are the concepts of high level modules and low level modules?
In the call chain, the caller belongs to the higher level and the called belongs to the lower level.
How to understand the word inversion?
Inversion is when the programmer controls the execution of the entire program without using the framework. After using the framework, the execution flow of the whole program can be controlled by the framework.
Control of the process has shifted from the programmer to the framework.
What dependencies have been reversed?
High level modules have been reversed.
What is inversion of controlIOC (Inversion Of Control)
?
Inversion of control, control refers to the control of the execution process of the program. Before the inversion, the control is in the hands of the programmer, and after the inversion, the control is in the hands of the framework.
Inversion of control is not a specific implementation (coding) technique, but rather a general design idea that is used to guide frame-level design.
What is dependency injectionDI (Dependency Injection)
?
Instead of creating dependent class objects inside the class using new(), the dependent class objects are created outside the class and passed (or injected) to the class through constructors, function parameters, and so on.
Dependency injection is a concrete coding technique.
IOC
和 DI
What’s the difference?
IOC is a design idea, DI is a concrete (implementation) coding technique.
Life examples
- Three monks draw water: normal operation is to draw water from the well directly with the bucket, but now must add a link, first use the bucket to draw water from the well into the bucket, and then draw water from the bucket [do not need intermediate operation, directly with the bottom operation].
- CPU memory: hard disk are designed for the interface, if for the implementation of the design, memory will correspond to a specific brand of motherboard, obviously unreasonable.
code
The code and interpretation are shown below:
conclusion
DIP is an abstract design principle, as the Chinese names for IOC and DI suggest. When you use DIP, you need to understand the word inversion. Remember to give the process control to the framework and then implement it.
SOLID summary
The following table is the comparison of SOLID in different dimensions. You can have a look and taste it carefully based on the content described above.
The principle of | The coupling | Degree of cohesion | scalability | redundancy | maintainability | testability | adaptive | consistency |
---|---|---|---|---|---|---|---|---|
SRP | – | + | o | o | + | + | o | o |
OCP | o | o | + | – | + | o | + | o |
LSP | – | o | o | o | + | o | o | + |
ISP | – | + | o | – | o | o | + | o |
DIP | – | o | o | – | o | + | + | o |
+ means increase, – means decrease, and O means flat.
KISS
- English:Keep It Simple and Stupid
- English: Keep it simple and stupid
- Myth: Keep your code simple
QUESTION
Is fewer lines of code simpler?
Not necessarily, some long regular expressions, three-digit operators, all violate the KISS principle.
If the code is logically complex, it violates itKISS
The principle?
Not necessarily. If it is a complicated problem, it does not violate the KISS principle to solve it in a complicated way.
How to write satisfactionKISS
Code for principles?
- Don’t implement code using techniques your colleagues may not understand
- Don’t reinvent the wheel. Be good at using existing toollibraries
- Don’t over-optimize
How do I determine if I am satisfiedKISS
Principle?
KISS is a subjective evaluation, which can be done through code review. If most colleagues have many questions about your code, it basically means it is not KISS enough.
code
The following code does not comply with the KISS principle
let a = b ? c : d ? e : f
Copy the code
conclusion
- Focus on how
- When we do development, we must not over-design, do not think that simple things have no technical content. In fact, the more simple a solution to a complex problem is, the more capable a person is.
YANGI
- English:You Ain’t Gonna Need It
- Topic17, You won’t need it
- Myth: Don’t overdesign
Life examples
Double 11 chop hands: Oh my God, it’s so cheap, order, order, order, and… Imagine for yourself.
conclusion
- Never write code to implement a feature just because you expect it to be used
- Instead: Implement the feature only when you really need it
DRY
- English:
Don 't Repeat Yourself
- Topic17, Don’t repeat yourself
- Myth: Don’t write duplicate code
QUESTION
Duplicate code is bound to be violatedDRY
?
Repeating code doesn’t necessarily violate the DRY principle. There are three typical cases of code duplication:
- Implement logical repetition
- Functional semantic repetition
- Code execution repetition
How can you improve your code’s reusability?
Reduce code coupling, meet the single responsibility principle, modularity, separation of business and non-business logic, general-purpose code decoupling, abstraction and encapsulation, use of design patterns.
code
Example 1: Implementing logical repetition
Code 1:
function isValidUserName() {
// The content is the same
}
function isValidPassword() {
// The content is the same
}
function main() {
isValidUserName()
isValidPassword()
}
Copy the code
Code 2:
function isValidUserNameOrPassword() {
// The content is the same
}
function main() {
isValidUserNameOrPassword()
}
Copy the code
As you can see, both functions in code 1 have the same code, so we have code 2 by removing the duplication and making it a function. Here’s a question for you, do you think this violates DRY?
- Result: code
1
Don’t breakDRY
, the code2
Violates theDRY
In the first place. - Reason: Although logic repetition is implemented, semantics are not repeated. Functionally, they’re doing two very different things. After the merge, a function does two things that are violated
SRP
和ISP
。 - Improved: More fine-grained functions are abstracted
Example 2: Functional semantic repetition
function sayHello() {
//
}
function speakHello() {
//
}
Copy the code
The code is not repeated, but the semantics are repeated, violating DRY.
Example 3: Code execution repeats
function isLogin() {
//
}
function main() {
if (xxx) {
isLogin()
}
// code omitted...
if (yyy) {
isLogin()
}
}
Copy the code
Executing the same function more than once in a function violates DRY.
conclusion
No repetition does not mean reusable, dialectical thinking and flexible application.
LOD
Common solution: high cohesion, loose coupling
QUESTION
What is Demeter’s rule?
Don’t have dependencies between classes that shouldn’t have direct dependencies. Try to rely on only the necessary interfaces between classes that have dependencies
What is the sense of high cohesion and loose coupling?
- High cohesion means that similar functions should be placed in the same class, and unrelated functions should not be placed in the same class. Because similar functions are often modified at the same time, in the same class, the changes are more concentrated.
- Loose coupling means that the dependencies between classes are simple and clear in your code. Even if two classes have dependencies, code changes in one class will not or rarely result in code changes in the dependent class.
What about high cohesion and loose coupling?
Consider the following:
It is a general design idea that can be used to guide the design and development of different granular code, such as systems, modules, classes, and even functions, and can be applied to different development scenarios, such as microservices, frameworks, components, and class libraries.
How to use Demeter’s rule well?
Reduce code coupling, meet the single responsibility principle, modularity.
Life examples
Real life objects: You know a lot about your objects, but if you know a lot about other people’s objects, it’s a big deal.
code
As shown in the figure above: We use LerNA to develop a framework and put different functions of the framework into different packages for maintenance iterations, in line with LOD.
conclusion
High cohesion and loose coupling are very important design concepts, which can effectively improve the readability and maintainability of code and reduce the scope of code changes caused by functional changes.
Summary of Design Principles
Ok, see this, the design principle is basically elaborated, I carried on the elaboration to the main design principle, you will find that, although some design principles have different names, but their goals are similar and the same. Learning and mastering major design principles helps us better design, develop, and iterate software. Also for us to learn and master the design model to lay a solid foundation.
communication
In this article, there must be some improper design principles, there are wrong places, welcome friends to point out and exchange in the comments. You are also very welcome to add my wechat for technical exchanges.
Friends can also join the front end brainstorm group.