【Code Complete2】
_Note-1 [启发式编程、管理复杂度、隐藏设计]
文章目录
- `【Code Complete2】`_Note-1 [启发式编程、管理复杂度、隐藏设计]
- 启发式编程
- 管理复杂度
- 隐藏设计--减少“改动所影响的代码量”
启发式编程
**设计是一个启发的过程,充满了不确定性,具有探索性。**当一个编程问题摆在面前的时候,心里不免会有一种想法,“要不试试,这样说不定可以”。
**没有任何工具是放之四海皆准的。**虽然是写程序就像是在搬砖,这里补一块,那边补一块,但是砖似乎也是千奇百怪的。我们有时候在网上clone
其他同行的开源代码,心里总是想着能不能在我这里直接编译成功,但是事情总是事与愿违,然后四处去找开源程序,结果不是让你交钱割韭菜,就是编不过的,最后在不懈的努力下,终于找到了可以编译的过的程序,这个课程设计作业也总算是完成了。相信大多数同学在上学的时候都经历过这个过程,这种事情做多了,我们便会想着去改开源程序,让他变成我们自己的东西,这个过程是充满挑战的,但是对我们也是帮助最大的,作为一个初学者,入门小白,我们不可能一开始就什么程序都自己写,搬砖式的学习,启发式的修改,似乎更值得我们去做。
**设计是自然而然形成的,通过我们不断的设计评估,非正式讨论,写实验代码,修改实验代码,不断地演化,完善。**写程序,第一件事是什么?毫无疑问是写个方案文档,我们一定要明确,没有任何一款程序方案文档是不经过几轮的迭代修改的,在写项目文档的时候,切记摒弃完美主义思想,你的第一版方案文档一定是有问题的,一定会在编码阶段,不断完善,不断修改的。
管理复杂度
软件的首要技术使命是管理复杂度
保存子程序的短小精悍,在最抽象的层次工作上,减少人脑负担。复杂度小,易维护,松散耦合,搞扇入、低扇出;这是代码是否写的优秀的关键。
如果说,我的既有程序写的不行,复杂度太高,怎么办?旧代码写的不行,可以在旧代码上写一层接口,来禁闭旧定义子系统之间的通信规则,把以前的“丑”,藏起来,以最大化减少复杂度,
无限制的子程序 | 有限制的子程序 |
---|---|
程序中不应该有任何环形关系
a ==> b ==> c ==> a==>..
隐藏设计–减少“改动所影响的代码量”
举个栗子,假设你有一个程序,其中的每个对象都是通过一个名为id
的成员变量来保存-种唯一的ID
。一种设计方法是用一个整数来表示ID
,同时用一个名为g_maxId
的全局变量来保存目前已分配的ID
的最大值。每当创建新的对象时,你只要在该对象的构造函数里简单地使用id=++g_maxId
这条语句,就肯定能获得一个唯一的ID值,这种做法会让对象在创建时执行的代码量最少。可这样设计可能有问题吗?
很多多地方都可能会出错。
如果你想把某些范围的
ID
留做它用该怎么办? 如果你想使用非连续ID
来提高安全性又该怎么办? 如果你想重新使用已销毁对象的ID
呢? 如果你想增加一个断言来确保所分配的ID
值不会超过预期的最大范围呢?
如果程序中到处都是id=++g_maxId
这种语句的话,一旦上面说的任何一种情况出现,你就需要修改所有这些语句。另外,如果你的程序是多线程的话,这种方法也不是线程安全的(thread-safe)。
创建新ID
的方法就是一种你应该隐藏起来的设计决策。如果你在程序中到处使用++g_max1d
的话,你就暴露了创建新ID
的方法,也就是通过简单递增g_maxId
。相反,如果你在程序中都使用语句id=NewId()
,那就把创建新ID的方法隐藏起来了。你可以在NewId()
子程序中仍然只用一行代码,return(++g_maxīd),
或者其他与之等价的方法。但如果日后你想把某些范围的ID
留做它用,或者重用旧的1D
时,只要对NewId()
子程序的内部加以改动即可,无须改动几十个甚至成百个id=NewId()
语句。无论 NewId()
内部做了多么复杂的改动,这些改动都不会影响到程序的其他部分。
int NewId(){return (++g_maxīd)
}
现在再假设你发现需要把 ID
的类型由整数改为字符串。如果你已经在程序内部大量地使用了int id
这样的变量声明的话,那么即使改用NewId()
子程序也无济于事。你还得深入到程序内部,进行几十次甚至几百次的修改。
因此,另一个需要隐藏的秘密就是ID的类型。对外界透露ID是个整型变量的做法,实质上是在鼓励程序员们对ID
使用针对整数的操作,如>、<、=
等等在C++
里,你可以简单地使用typedef
来把ID定义为 IdType
–一个可以解释为int
的用户自定义类型–而避免将其直接定义成int
类型。在 C++
和其他语言中,你也可以创建一个简单的 IdType
类。再强调一下,隐藏设计决策对于减少“改动所影响的代码量”而言是至关重要的。
int NewId(){return (++g_maxīd)
}
信息隐藏在设计的所有层次上都有很大作用–从用具名常量替代字面量,到创建数据类型,再到类的设计、子程序的设计以及子系统的设计等
那么,我要隐藏些什么?
- 易改变的区域;
- 对硬件依赖的区域;
- 困难的设计区域;
- 状态变量;
对于状态变量,使用枚举类型比较好;我们一开始可能会使用布尔变量**来定义出错状态,然后又发现用具有ErrorType_None、ErrorType_Warning
和ErrorType_Fatal
等值的枚举类型来表示该状态更好。
布尔变量:是一种数据类型,它只能有两个可能的值:真(true)和假(false)。
感谢阅读,欢迎大家一起交流讨论。