读《代码大全2》笔记一
2007-05-12 23:43
106 查看
1、 架构师吃掉需求,而设计师吃掉架构,而程序员则消化设计;
2、 IBM和其他公司的研究发现,平均水平的项目在开发过程中,需求会有25%的变化;
3、 核对表(需求)
4、 检查表(架构)
5、 理想的设计特征
6、 用数据说话
当程序员用“使用了三年以上的语言”编写代码时,生产效率比“同等经验但使用新语言”的程序员高30%;
对编程语言有相当丰富经验的程序员的生产率比几乎没有经验的程序员高3倍;
7、 高级语言的语句和等效的C代码语句行数之比
8、 构建核对表
9、 理想的设计的特征
10、层次的设计
11、设计模式
12、自上而下策略和自下而上策略的最关键的区别在于,前者是一种分解策略,后者是一种合成策略;……150
自上而下策略和自下而上策略的最关键的区别在于,前者是一种分解策略,后者是一种合成策略;前者从一般性的问题出发,把该问题分解成可控的部分。后者从可控的部分出发,去构造一个通用的方案。这两种方法都有各自的强项和弱项。
13、记录设计成果
2、 IBM和其他公司的研究发现,平均水平的项目在开发过程中,需求会有25%的变化;
3、 核对表(需求)
针对功能需求 |
1) 是否详细定义了系统的全部输入,包括其来源、精度、取值范围、出现频率等; 2) 是否详细定义了系统的全部输出,包括目的地、精度、取值范围、出现频率、格式等; 3) 是否详细定义了所有输出格式(Web页面、报表,等等); 4) 是否详细定义了所有硬件及软件的外部接口; 5) 是否详细定义了全部外部接口,包括握手协议、纠错协议、通信协议等; 6) 是否列出了用户想要做的全部事情; 7) 是否详细定义了每个任务所用的数据,以及每个任务得到的数据; |
针对非功能的需求(质量需求) |
1) 是否为全部必要的操作,从用户的视角,详细描述了期望响应的时间? 2) 是否详细描述了其他与计时有关的考虑,例如处理时间、数据传输率、系统吞吐量? 3) 是否详细定义了安全级别? 4) 是否详细定义了可靠性,包括软件失灵的后果、发生故障时需要保护的至关重要的信息、错误检测与恢复的策略等? 5) 是否详细定义了机器内存和剩余磁盘空间的最小值? 6) 是否详细定义了系统的可维护性,包括适应特定功能的变更、操作环境的变更、与其他软件的接口的变更能力? 7) 是否包含对“成功”的定义?“失败”的定义? |
需求的质量 |
1) 需求是用用户的语言书写的吗?用户也这么认为吗? 2) 每条需求都不与其他需求冲突吗? 3) 是否详细定义了相互竞争的特性之间的权衡——例如,健壮性与正确性之间的权衡? 4) 是否避免在需求中规定设计(方案)? 5) 需求是否在详细程度上保持相当一致的水平?有些需求应该更详细描述吗?有些需求应该更粗略地描述吗? 6) 需求是否足够清晰,即使转交给一个独立的小组去构件,他们也能理解吗?开发者也这么想吗? 7) 每个条款都与待解决的问题及其解决方案相关吗?能从每个条款上溯到它在问题域中对应的根源吗? 8) 是否每条需求都是可测的?是否可能进行独立的测试,以检查满不满足各项需求? 9) 是否详细描述了所有可能的对需求的改动,包括各项改动的可能性? |
需求的完备 |
1) 对于在开始之前无法获得的信息,是否详细描述了信息不完全的区域? 2) 需求的完备度是否能达到这种程度:如果产品满足所有需求,那么它就是可接受的? 3) 你对全部需求都感到很舒服吗?你是否已经去掉了那些不可能实现的需求——那些只是为了安抚可户和老板的东西? |
4、 检查表(架构)
针对各架构主题 |
1、程序的整体组织结构是否清晰?是否包含一个良好的架构全局观(及其理由)? 2、是否明确定义了主要的构造块(包括每个构造块的职责范围及其他构造块的接口)? 3、是否明显涵盖了“需求”中列出的所有功能(每个功能对应的构造块不太多也不太少)? 4、是否描述并论证了那些最关键的类? 5、是否描述并论证了数据设计? 6、是否详细定义了数据库的组织结构和内容? 7、是否指出了所用的关键的业务规则,并描述其对系统的影响? 8、是否描述了用户界面设计的策略? 9、是否将用户界面模块化,使界面的变更不会影响程序其余部分? 10、是否描述并论证了处理I/O的策略? 11、是否估算了稀缺资源(如现程、数据库连接、句柄、网络带宽等)的使用量,是否描 12、述并论证了资源管理的策略? 13、是否描述了架构的安全需求? 14、架构是否为每个类、每个子系统、或每个功能域(functionality area)提出空间与时间预算? 15、架构是否描述了如何达到可伸缩性? 16、架构是否关注互操作性? 17、是否描述了国际化/本地化的策略? 18、是否提供了一套内聚的错误处理策略? 19、是否规定了容错的办法(如果需要)? 20、是否证实了系统各个部分的技术可行性? 21、是否详细描述了过度工程的方法? 22、是否包含了必要的“买 vs. 造”的决策? 23、架构是否描述了如何加工被复用的代码,使之符合其他架构目标? 24、是否将架构设计得能够适应很可能出现的变更? |
架构的总体质量 |
1) 架构是否解决了全部需求? 2) 有没有哪个部分是“过度设计”或“欠设计”? 3) 整个架构是否在概念上协调一致? 4) 顶层设计是否独立于用作实现它的机器和语言? 5) 是否说明了所有主要的决策的动机? |
5、 理想的设计特征
理想的设计特征 |
1、最小的复杂度(Minimal complexity) 设计的首要目标是让复杂度最小。要避免“聪明的”设计,因为“聪明的”设计常常都是难于理解的。应该做出简单且易于理解的设计。如果你的设计方案不能让你在专注于程序的一部分时安心地忽视其他部分的话,这一设计就没有什么作用了。 2、易于维护(Ease of maintenance) 意味着在设计时为做维护工作的程序员着想。请时刻想着维护程序员可能会就你写的代码而提出的问题。把这些程序员当成你的听众,进而设计出能自解释的系统来。 3、松散耦合(loose coupling) 意味着在设计时让程序的各个组成部分之间关联最小。通过应用类接口中的合理抽象、封装性及信息隐藏等原则,设计出相互关联尽可能最少的类。减少关联也就减少了集成、测试与维护工作量。 4、可扩展性(extensibility) 是说你能增强系统的功能而无须破坏其底层结构。你可以改动系统的某一部分而不会影响到其他部分。越是可能发生的改动,越不会给系统造成什么破坏。 5、可重用性(reusability) 意味着所设计的系统的组成部分能在其他系统中重复使用。 6、高扇入(high fan-in) 是说让大量的类使用某个给定的类。这意味着设计出的系统很好地利用了在较低层次上的工具类(utility classes)。 7、低扇出(low fan-out) 是说让一个类里少量或适中地使用其他的类。高扇出(超过约7个)说明一个类使用大量其他的类,因此可能变得过于复杂。 8、可移植性(portability) 设计出的系统应该很方便地移植到其他环境中。 9、精简性(cleanness) 设计出的系统没有多余的部分。任何多余的代码也需要开发、Review和测试,并且修改了其他代码后还要重新考虑这部分。 10、层次性(stratification) 意味着尽量保持系统各个分解层的层次性,是你能在任意的层面上观察系统,并得到某种具有一致性的看法。 11、标准技术(Standard techniques) 要尽量用标准化的、常用的方法,让整个系统给人一种熟悉的感觉。 |
6、 用数据说话
当程序员用“使用了三年以上的语言”编写代码时,生产效率比“同等经验但使用新语言”的程序员高30%;
对编程语言有相当丰富经验的程序员的生产率比几乎没有经验的程序员高3倍;
7、 高级语言的语句和等效的C代码语句行数之比
语言 | 相对于C语言的等级 |
C | 1 |
C++ | 2.5 |
Fortran 95 | 2 |
Java | 2.5 |
Perl | 6 |
Python | 6 |
Smalltalk | 6 |
VB | 4.5 |
8、 构建核对表
编码 |
1)你有没有确定,多少设计工作将要预先进行,多少设计工作在键盘上进行(在编写代码的同时)? 2)你有没有规定诸如名称、注释、代码格式等“编码约定”? 3)你有没有规定特定的由软件架构确定的编码实践,比如如何处理错误条件、如何处理安全性事项、对于类接口有哪些约定、可重用的代码遵循哪些标准、在编码时考虑多少性能因素等? 4)你有没有找到自己在技术浪潮中的位置,并相应调整自己的措施?如果必要,你是否知道如何“深入一种语言去编程”,而不受限于语言(仅仅“在一种语言上编程”) |
团队工作 |
1)你有没有定义一套集成工序——即,你有没有定义一套特定的步骤,规定程序员在把代码check in(签入)到主源码(代码库)中之前,必须履行这些步骤? 2)程序员是结对编程、还是独自编程,或者这二者的某种组合? |
质量保证 |
1)程序员在编写代码之前,是否先为之编写测试用例? 2)程序员会为自己的代码写单元测试吗(无论先写还是后写)? 3)程序员在check in代码之前,会用调试器单步跟踪整个代码流程吗? 4)程序员在check in代码之前,是否进行集成测试(integration-test)? 5)程序员会复审(review)或检查别人的代码吗? |
工具 |
1)你是否选用了某种版本控制工具? 2)你是否选定了一种语言,以及语言的版本或编译器版本? 3)你是否选择了某个编程框架(framework,如J2EE或Microsoft .NET),或者明确地决定不使用编程框架? 4)你是否决定允许使用非标准的语言特性? 5)你是否选定并拥有了其他将要用到的工具——编辑器、重构工具、调试器、测试框架(test framework)、语法检查器等? |
9、 理想的设计的特征
最小的复杂度:设计的首要目标就是要让复杂度最小。要避免做出“聪明的”设计,因为“聪明的”设计常常都是难以理解的。应该做出“简单”且“易于理解”的设计。如果你的设计方案不能让你在专注于程序的一部分时安心地忽视其他部分的话,这一设计就没有什么作用了。 |
易于维护:易于维护意味着在设计时为做维护工作的程序员着想。请时刻想着这些维护程序员可能会就你写的代码而提出的问题。把这些程序员当成你的听众,进而设计出能自明的(self-explanatory)系统来。 |
松散耦合:松散耦合(loose coupling)意味着在设计时让程序的各个组成部分之间关联最小。通过应用类接口中的合理抽象、封装性及信息隐藏等原则,设计出相互关联尽可能最少的类。减少关联也就减少了集成、测试与维护时的工作量。 |
可扩展性:可扩展性(extensibility)是说你能增强系统的功能而无须破坏其底层结构。你可以改动系统的某一部分而不会影响到其他部分。越是可能发生的改动,越不会给系统造成什么破坏。 |
可重用性:可重用性(reusability)意味着所设计的系统的组成部分能在其他系统中重复使用。 |
高扇入:高扇入(high fan-in)就是说让大量的类使用某个给定的类。这意味着设计出的系统很好地利用了在较低层次上的工具类(utility classes)。 |
低扇出:低扇出(low fan-out)就是说让一个类里少量或适中地使用其他的类。高扇出(超过约7个)说明一个类使用了大量其他的类,因此可能变得过于复杂。研究发现,无论考虑某个子程序调用其他子程序的量,还是考虑某个类使用其他类的量,低扇出的原则都是有益的(Card and Glass 1990; Basili, Briand, and Melo 1996)。 |
可移植性:可移植性(portability)是说应该这样设计系统,使它能很方便地移植到其他环境中。 |
精简性:精简性(leanness)意味着设计出的系统没有多余的部分(Wirth 1995, McConnell 1997)。 |
层次性:层次性(stratification)意味着尽量保持系统各个分解层的层次性,使你能在任意的层面上观察系统,并得到某种具有一致性的看法。设计出来的系统应该能在任意层次上观查而不需要进入其他层次。 |
标准技术:一个系统所依赖的外来的、古怪的东西越多,别人在第一次想要理解它的时候就越是头疼。要尽量用标准化的、常用的方法,让整个系统给人一种熟悉的感觉。 |
软件系统-->分解为子系统和包-->分解为包中的类-->分解为类中的数据和字程序-->子程序内部 |
11、设计模式
12、自上而下策略和自下而上策略的最关键的区别在于,前者是一种分解策略,后者是一种合成策略;……150
自上而下策略和自下而上策略的最关键的区别在于,前者是一种分解策略,后者是一种合成策略;前者从一般性的问题出发,把该问题分解成可控的部分。后者从可控的部分出发,去构造一个通用的方案。这两种方法都有各自的强项和弱项。
1)自上而下设计的强项是它很简单,因为人们是很善于把一些大的事物分解为小的组件,而程序员则更是精于此道。 2)自上而下设计的另一强项是你可以推迟构建的细节。软件系统常常会受到构建细节变化(例如文件结构或者报表格式的变化)的骚扰,因此,尽早知道应该把这些细节信息隐藏在继承体系的底层类中,是非常有益的。 3)自下而上设计的一个强项是通常能够较早找出所需的功能,从而带来紧凑的、结构合理的设计。如果类似的系统已经做过,那么自下而上设计让你能审视已有的系统,并提出“我能重用些什么?”一类的问题,由此出发开始新系统的设计。 4)自下而上设计的一个弱项是很难完全独立地使用它。大多数人都很善于把大概念分解为小概念,而不擅长从小概念中得出大概念。这就像在自己组装玩具:我想自己已经组装完了,可为什么盒子里还有零件呢?所幸的是,完全不必仅使用自下向上这一种设计方法。 5)自下而上设计的另一弱项是,有时候你发现自己无法使用手头已有的零件来构造整个系统。你不可能用砖块来建造飞机。你可能要先做高层设计,才能知道底层需要什么零件。 6)总而言之,自上而下设计通常比较容易上手,但是有时候会受底层复杂度的影响,这种影响甚至有时会使事情变得比实际的情况更复杂。自下而上设计开始起来比较复杂,但是在早期鉴别出系统的复杂度,却有助于设计出更好的高层类。当然这样做的前提是复杂度没有先把整个系统破坏掉!自上而下和自下而上设计并不是互相排斥的——你会受益于二者的相互协作。 |
13、记录设计成果
1)把设计文档插入到代码里:在代码注释中写明关键的设计决策,这种注释通常放在文件或者类的开始位置。如果你同时使用类似于JavaDoc这样的文档提取工具,那么这种方法会确保设计文档对于开发这部分代码的程序员来说是立等可取的,同时也有助于程序员保持代码和设计文档之间的相当不错的同步。 2)用Wiki来记录设计讨论和决策:把你们的设计讨论写到项目的Wiki里去(Wiki是指一组可以由项目组所有成员用网络浏览器轻松编辑的网页)。尽管文字录入要比交谈麻烦一些,但这样会自动地记录下你们的设计讨论和设计决策。如果使用Wiki,你可以用图片来弥补文字讨论的不足,并链接支持该设计决策的网站、白皮书及其他材料。如果你的开发团队在地理位置上是分布式的,那么这种技术会非常有帮助。 3) 写总结邮件:每次就设计展开讨论过后,请采取这种做法,即指派某人来写出刚才讨论的纲要——特别是那些决定下来的事项——然后发送给整个项目组。在项目的公共电子邮件文件夹里保留一份备份。 4)使用数码相机:在对设计进行文档化时有一个很常见的障碍,那就是用流行的画图工具画设计图表太麻烦。不过文档化可不仅限于“用漂亮的格式、正规的符号来记录设计”和“不做任何设计文档”这两种选择。把白板上画出的图表照成相片然后嵌入到传统的文档里,这样做可以带来事半功倍的效果,因为它的工作量只是用画图工具画设计图表的1%,而它的收益却能达到保存设计图表的80%。 5)保留设计挂图:如果你把设计记录在大的挂图上,那么你只需把这些挂图保存在方便的地方即可,或者采用更好的做法,把它们张帖在项目工作区域的墙上,让大家能够很容易地随时查阅和修改。 6)使用CRC(类、职责、合作者)卡片:另外一种技术含量较低的文档记录方案是使用索引卡片。在每张卡片上,设计者写下类的名称、职责和合作者(与这个类合作的其他类)。一个设计团队便按照这些卡片的内容展开工作,直到他们认为已经创建出一个好的设计方案为止。到那个时候,你只需把这些卡片保留下来,留待日后引用。索引卡片非常便宜,不吓人,易于携带,并且有助于促进团队合作(Beck 1991)。 7)在适当的细节层创建UML图:一种流行的绘制设计图的方法是由对象管理组织(Object Management Group)定义的统一建模语言(UML)(Fowler 2004)。UML提供了一套丰富的、形式化的表示法,可用于设计实体(entity)及其关系(relationship)。你可以用非正式的UML图来帮助讨论和发现设计思路。从最简单的草图开始,直到你最终选定了一套设计方案,才往其中增加细节。由于UML是标准化的,因此在交流设计观念时大家都能理解它,同时还能加快团队共同讨论各种设计方案的速度 |
相关文章推荐
- 代码大全2笔记-第12章-基本数据类型
- 读《代码大全2》笔记:使用变量的一般事项
- 读《代码大全2》笔记:类的质量
- 代码大全2笔记-第8章-防御式编程
- 读《代码大全2》笔记:防御式编程
- 读《代码大全2》笔记:软件构造中的设计核对表
- 读《代码大全2》笔记:伪代码编程过程
- 读《代码大全2》笔记:软件构建中的设计师
- 代码大全2笔记-第11章-变量名
- 读《代码大全2》笔记:变量的力量
- 表驱动法----代码大全2,第18章学习笔记
- Hibernate框架技术视频课程——笔记(四)
- 笔记之Android Bluetooth Input 连接流程小记
- Linux 学习笔记之 4 Linux文本编辑器
- js学习笔记一-语法结构
- 基础学习笔记之opencv(1):haartraining
- Java课程笔记_4
- JDBC 复习笔记1
- jQuery学习笔记之基础中的基础
- python学习笔记(一)