怎样降低代码的复杂度?
“软件构建的核心就是管理复杂度”。
--《代码大全》
作者提到了下面三种方法:
- 分割
- 清晰理解
- 清晰表达
请大牛讲讲,具体该怎样实践?
Answers
软件发展到今天,现在最流行的就是OO,它的流行也正是因为OO通过一些约束和限制来降低了代码的复杂度。
一 针对代码层次的:
1.OCP:开放--封闭原则
2.LSP liskov 替代原则
3.SRP:单一职责原则
4.DIP 依赖倒置原则
5.ISP 接口隔离原则
二 针对包聚合方面的
1.发布重用等价原则The Release Reuse Equivalency Principle (REP)
重用的粒度就是发布的粒度
2.共同封闭原则The Common Closure Principle (CCP)
包中的所有类对于同一类型的变化应该是共同封闭的。一个变化若对一个包产生影响,则将对包中的所有类产生影响,而对于其他包不造成任何的影响。
3.共同重用原则The Common Reuse Principle (CRP)
一个包中的所有类应该是共同重用的,如果重用了包中的一个类,那么就要重用包中的所有类。
三 针对模块依赖方面的:
1.ADP 无环依赖原则
在包中的依赖关系中不允许存在环
2.稳定依赖原则 Stable Dependencies Principle (SDP)
朝着稳定的方向进行依赖
3 SAP 稳定抽象原则
包的抽象程度应该和其稳定程度一致
首先推荐几本书:
- 重构——重构改善既有代码的设计
- 编写可读代码的艺术
- 编程珠玑
- 代码大全(我没读过,但很多人推荐)
具体的做法:
要把代码分割成细粒度的函数,然后给这些函数起一个恰当的名字,这是最简单最有效的做法。写代码的时候可以先写成一个函数,然后在过程中,不断地把「不相干的子问题」抽取出来,变成一个单独的函数。
做到极致的效果就是,每个函数,别人只要看到名字和参数列表,就能知道这个函数是干什么的,而且可以自己实现出来。这样一来,代码的复杂度显然就降了下来;读代码的时候,其实大部分时候都是在读函数调用,都是在了解算法的逻辑,而不是细节。
举个简单的例子:
SegmentFault 的投票功能,当用户点 Up 的时候就加一票,点 Down 就减一票;而如果用户已经 Down 了,那么点 Up 的时候要加两票;不好的代码是这样的:
vote_action = function (old_vote, new_vote) {
var score = get_score();
if (new_vote !== old_vote) {
if (new_vote === 'Up')
score += (old_vote === 'Down' ? 2 : 1);
else if (new_vote === 'Down') {
score -= (old_vote === 'Up' ? 2 : 1);
else if (new_vote === '')
score += (old_vote === 'Up' ? -1 : 1);
}
set_score(score);
};
好的代码是这样的:
vote_action = function (old_vote, new_vote) {
var vote_value = function (vote) {
if (vote === 'Up')
return +1;
else (vote === 'Down')
return -1;
else
return 0;
};
var score = get_score();
score -= vote_value(old_vote); // remove the old vote
score += vote_value(new_vote); // add the new vote
set_score(score);
};
PS: 例子引自「编写可读代码的艺术」