当前位置:网站首页>Alchemy (7): how to solve problems? Only reconstruction
Alchemy (7): how to solve problems? Only reconstruction
2022-06-28 00:19:00 【Phantom grey Dragon】

A lot of times , Sort through the code , Write the logic correctly , Straighten out dependencies ,BUG It's gone . One Bugly Legacy systems , Only thorough refactoring , Let the program be in 「 Good structure 」 state , Can be developed normally 、 Maintain and release versions . There is an essential problem , Is to let the code realize 「 High cohesion 、 Low coupling 」. Here are my refactoring notes .
work
I found the programming habits I used to take for granted , I wouldn't have written this messy coupling problem in the first place , So for a long time, I didn't feel that I should pay attention to writing code 「 High cohesion 、 Low coupling 」 Problem. . But this refactoring , Let me see what the spaghetti code is all about , But to take them apart , Step by step decoupling , Rewrite the code to 「 normal 」, I just 「 Feeling 」 To write code, you need 「 High cohesion 、 Low coupling 」 This matter , Many people need to learn and practice .
This refactoring proves once again 「 Global variables are the root of all evil 」, This man uses JavaScript Wrote a lot of classes , But what? , Each module returns one of this class 「 False single case 」, Further 「 Up 」「 Down 」, This false singleton is used in both the upper and lower layers , This leads to severe internal coupling on both sides 「 Class 」, This is equivalent to using a bunch of global variables directly . What's worse is , The member variables of these classes are directly exposed , Assign values everywhere , Expose all variables to 「 Without any encapsulation and protection 」 Under the 「 To modify at will 」.
I've been refactoring layer by layer these days :
- Uncouple in both directions , Between layers can only be
A<----B<---C<----DThis one-way dependency , Instead of relying on each other . Between layers in the program , One way dependency should be achieved , Can make the process clear , The structure is reasonable . - All variables are modified 「 encapsulation 」 Inside the class , All through the method to modify . On this basis , Modification of internal variables , Protect the internal state machine .
- carefully 、 Thoroughly clean up several important finite state machines (Finite State Machine), Draw the complete state transition diagram of state transition , There must be enterState Conversion method protection , Any error conversion will directly report an error . I think this is a direct reflection 「 Programming 」 Where is it , Do not understand finite state machine , It's not really programming . I see a lot of defining a bunch of States , But there is code that can jump between states , It's all like this Bugly The root of .
- Shrink a point where the class state is modified . A class defines a set of methods and properties , It should only be used in certain situations , All the places where this class is used , If you don't try to control it in a narrow range , Then the state modification is spreading , These dispersions not only make changes in state difficult to understand , It's not good for maintenance . Shrink the range step by step , according to 「 The correlation 」 Gradual analysis , What logic should be centralized in one place .
- Logic in functions , It shouldn't be a bunch of code that doesn't know what to do . Instead, it should be composed of a set of function calls that can be seen clearly at a glance , If not , Then you need to refactor this part of the logic , Let them form a suitable... In the right place , Function specific functions .
- Separate classes from different processes to different folders . Each process should only use classes in its own process , otherwise , You will encounter things like 「 I have clearly modified this variable , Why is it wrong 」 The problem of , Because what you modify and what you read are variables of two different processes , Although it looks like 「 Same class 」, If you have multithreaded code , It's similar . Specify which process each class belongs to . Physically separate them with meaningful folders . Each class should only be used by one process , Unless it is a stateless tool class . This further demonstrates that you should not use global variables , carelessly , You use it in two processes 「 The same variable 」 Of the two processes . Don't give yourself the chance to create this confusion .
- How to release
A<--->BThis kind of coupling ? Even though I was JavaScript Write the code , I still think about when to use 「 Interface 」, When to use 「 function 」 To decouple the problem . For many years , Based on object-oriented design patterns , Are telling you to face the interface to decouple , Is it true ?
For a long time , I've already Forgot to write an interface , Because dynamic languages don't need any direct interfaces . I thought about it carefully , If a class does have many different similar subtypes , It is natural to inherit at this time , for example ,B1,B2,B3 Inherit B. here A Yes B Dependence ,B It can be an abstract class , It can also be an interface IB, It makes no difference . conversely ,B Also can be IA rely on . This is basically what a series of design patterns are talking about .
however , Can I decouple without interface implementation ? Reasonable design of callback function can achieve . for example :
B.xxxxx(params, onXXXX, onYYYY) as long as B Define the appropriate callback function in the function parameters of the , Then I don't need B Internally call any A Methods ,A If you want to mix your own logic B Of xxxxx In the logic of the method , Just use B When , Processing these callbacks can :
b.xxxxx(params,(...)=>{
Add... Here A The logic of
},(...)=>{
Add... Here A The logic of
}); This is the time ,B If you want to be universal , Try to design appropriate parameters and callbacks .
further , You may be in A Internal use of B. such B Although the lifting of the right A Dependence , however A Yes B Our dependence is still , that , How can this coupling be further removed ? An abstract method is effective , Then use it again and again :
A.yyyyy(params, onXXXX, onYYYY); This is the time , hold A Logic and B The logic of is bound together to be the outer layer 「 responsibility 」,A and B be responsible for 「 Provision mechanism 」, Outer layer , for example C be responsible for 「 Use policy 」, So that 「 Separation of mechanism and strategy 」
C:
a ,b;
a.yyyyy(params, (...)=>{
// Other logic , Such as joining c The logic of
b.xxxxx(prams,(.....)=>{
// Join in A The logic of
}, (...)=>{
// Join in A The logic of
}
}, (...)=>{
// Other logic , Such as joining c The logic of
}); This may of course cause 「 Callback nested hell 」, in many instances , You can use the... Provided by the language layer async/await To make the code clearer . however async/await It is not a complete substitute for callback , It can only make the asynchronous callback of a single exit become 「 Pseudo synchronization 」 Code . for example :
xxx((ret)=>{
zzzz(ret)
});become :
let ret = await xxxx();
zzzz(ret);But this ability is more verbose
xxxx((ret)=>{
zzzz(ret);
},(ret)=>{
yyyy(ret);
}); To handle this multi exit callback , If xxx The interior is either in the 1 Callback ends , Or in the first 2 Callback ends , The return value can be used to determine what to do :
let {err,ret} = await xxxxx();
if(err){
zzzz(ret);
}else{
yyyy(ret);
} however , If xxxx The interior is in the 1 After a callback , It is also possible to call the... Again 2 A callback . Or any callback will call multiple times . This is the time to put xxxx The function becomes without callback async function , Logic will become more complex , It's not even possible .
All in all , This is a digression . My core point is , Through the design of function parameters and callbacks , You can get rid of it A<---->B This dependency . And let C The code where it is called 「 It can be seen at a glance A and B How to work together to complete the task 」, This is the key for me to consider where a lot of code should be written .
That's it , A function should be :
run(); // The mysterious task has been completed inside Or should it be :
if(a.init()){
a.xxxx();
a.zzzz();
}; Better? ? In my submission , At least at xxxx Where the upper level of the function is called , At that granularity provide intuitive this 「 What is the program doing 」 The intuitive logic of .
I think the decoupling of interfaces , There are many different scenarios for the same interface , But similar subclasses . And if not , that 「 Higher order function 」 The combination of is a better choice . This better is similar to 「 If not necessary , Wu Zeng entity 」 This kind of thinking , Or say 「 Omka razor 」 principle .
The above is the feeling of reconstruction , In refactoring projects , It also helps us understand what architecture is , Because in order to make the project achieve 「 Good structure 」, We have to understand a lot 「 Why? 」.
Speculation
I've been in the software industry for so long , One problem is , People often see the description of one aspect of a certain roast term , Just look at that term as worthless , It's not like that , A term is a hypothetical condition for its existence . And the reason why people roast , It's because these things have nothing that can be objectively measured , That is, unlike mathematics, which is a strict deductive system , Nor is it strictly random and double-blind like science , Most of the time, it is a lot of subjective behavior between creation and graffiti , So there are always people who do something wrong , Someone did the right thing , What people roast about is that they don't really understand the concept , And the phenomenon of doing best practices on it . Of course , In fact, we can use some indicators to measure your work to make the software run more stably , Provides better quality , Or become more unstable , It's getting worse .
For example, I changed the code this time , I don't have to say that this is 「 restructure 」、 In fact, I can just say 「 The program is not working properly now , The state machine inside doesn't work properly , I want to change this state machine to correct , Stable operation , At the same time, it is convenient to diagnose problems , There are good framework documents for others to read and find , Better not bother me again 」.
therefore , Do not look. 「 label 」 What is it? , And see if you are right , For example, if it's like the picture , To reconstruct such a stable system as the solar system ...
--end--
边栏推荐
- 现代编程语言:zig
- Sentinel
- 安全省油環保 駱駝AGM啟停電池魅力十足
- Eliminate gaps around El image images
- Mysql database tourism management system_ Jsp+mysql tourism management system based on SSM [easy to understand]
- 单片机之IIC通信协议「建议收藏」
- Character interception triplets of data warehouse: substrb, substr, substring
- Matlb| optimal configuration of microgrid in distribution system based on complex network
- golang使用mongo-driver操作——查(数组相关)
- 股市小白在网上股票开户安全吗?
猜你喜欢

Webserver flow chart -- understand the calling relationship between webserver modules

Sell notes | brief introduction to video text pre training

Sécurité, économie de carburant et protection de l'environnement chameau

Promise是什么
![[untitled]](/img/e4/7c65c6823559b8501a1777cc4eb7ba.jpg)
[untitled]

MATLB|改进的前推回代法求解低压配电网潮流

智慧风电 | 图扑软件数字孪生风机设备,3D 可视化智能运维

吴恩达《机器学习》课程总结(14)_降维

Comprehensive evaluation of free, easy-to-use and powerful open source note taking software

Matlb| improved forward push back method for solving power flow of low voltage distribution network
随机推荐
C语言malloc函数的功能及用法
flutter系列之:flutter中的变形金刚Transform
免费、好用、强大的开源笔记软件综合评测
RNA-seq入门实战(一):上游数据下载、格式转化和质控清洗
Golang uses Mongo driver operation - query (basic)
Systematic learning + active exploration is the most comfortable way to get started!
An analysis of C language functions
现代编程语言:Rust (铁锈,一文掌握钢铁是怎样生锈的)
Feign通过自定义注解实现路径的转义
Learning notes for qstringlist
Msp430f5529 MCU reads gy-906 infrared temperature sensor
Zero foundation self-study SQL course | case function
Is it safe for Huatai Securities to open an account online?
Super outline exercises
ASP. Net warehouse purchase, sales and inventory ERP management system source code ERP applet source code
golang使用mongo-driver操作——查(数组相关)
Transmitting and receiving antenna pattern
C language - date formatting [easy to understand]
Chenyun pytorch learning notes_ Build RESNET with 50 lines of code
RecyclerView实现分组效果,多种实现方式