二、注重实效的途径
1. 重复的危害
DRY原则
系统中的每一项知识都必须具有单一、无歧义、权威的表示。
DRY –Don’t Repeat Yourself
不要重复你自己。
与此不同的做法是在两个或更多地方表达同一事物。如果你改变其中一处,你必须记得改变其他各处。
重复是怎样发生的:
1) 强加的重复
解决办法:信息的多种表示
代码中的文档,糟糕的代码才需要许多注释,不可信任的注释比完全没有注释更糟糕。
文档与代码,一致更新。
语言问题,应该用头文件记载接口问题,用实现文件记载代码的使用者无须了解的实际细节。
2) 无意的重复
在可能的情况下,应该总是用访问器函数读写对象的属性,这将使未来增加功能变得更容易.
访问器函数的使用与Uniform Access原则紧密相关,该原则规定:模块提供的所有服务都应能通过统一的表示法使用,该表示法不能泄漏它们是通过存储,还是通过计算实现的.
3) 无耐性的重复
“欲速则不达”
4) 开发者之间的重复
鼓励开发者相互进行主动的交流,设置论坛,用以讨论常见问题,让某个团队成员担任项目资料管理员,其工作是促进知识的交流.
提示12 Make it Easy to Reuse 让复用变得容易
你所要做的是营造一种环境,在其中要找到并复用已有的东西,比自己编写更容易.
2. 正交行
在计算技术中,该术语用于表示某种不相依赖性或是解耦性,如果两个或更多事物中的一个发生变化,不会影响其他事物,这些事物就是正交的,在设计良好的系统中,数据库代码与用户界面是正交的.
非正交系统:非正交系统的改变和控制更复杂.
提示13 消除无关事物之间的影响.
正交的好处:
提高生产率,改动得以局部化,所以开发时间和测试时间得以降低,还可以促进复用,对正交的组件进行组合,生产率会提高;
降低风险,将问题局限在该区域中;
工作中应用正交原则的几种方式:
项目团队,正交性团队效率更高;
设计,设计正交的系统,系统应该由一组相互协作的模块组成,每个模块都实现不依赖于其他模块的功能,有时,这些组件被组织为多个层次,每层提供一级抽象。问自己“如果我显著地改变某个特定功能背后的需求,有杜少模块会受影响?”,在正交系统中,答案应为一个。“不要依赖你无法控制的事物属性”.
工具箱与库,在引入第三方工具箱和库时,要注意保持系统的正交性。
编码:
让你的代码保持解耦(编写羞怯的代码)
避免使用全局数据
避免编写相似的函数,重复的代码是结构问题的一种症状(参考Strategy策略模式)
批判自己的代码,并重构(refactoring)
测试 p42,正交地设计和实现的系统也更易于测试
文档
认同正交性,正交性与DRY原则紧密相关,运用DRY原则,你是在寻求使系统中的重复降至最小;运用正交性原则,你可降低系统的各组件间的相互依赖
挑战:
考虑Windows上见到的面向GUI的大型工具盒在shell提示下使用的短小,淡却可以组合的命令行实用工具,哪一种更为正交?
多重继承或多重接口对正交性的影响?
3. 可撤销性
There Are No Final Decisions 不存在最终决策
灵活的架构:CORBA
挑战
“薛定谔的猫”量子力学
4. 曳光弹
曳光弹比费力计算更可取,反馈是即时的,而且因为他们工作在与真正的弹药相同的环境中,外部影响得以降至最低。
在黑暗中发光的代码
提示15 用曳光弹找到目标
曳光代码并非用过就扔的代码:你编写它,是为了保留它,它含有任何一段产品代码都拥有的完整的错误检查、结构、文档以及自查,只不过功能不全而已。
曳光开发与项目永不会结束的理念是一致的:总有改动需要完成,总有功能需要增加,这是一个渐进的过程。
优点:
l 用户能够及早看到能工作的东西
l 开发者构建了一个他们能在其中工作的结构
l 你有了一个集成平台
l 你有了可用于演示的东西
l 你将更能够感觉到工作进展
曳光弹并非总能击中目标
你要调整准星,知道完全击中目标为止,这正是要点所在。
曳光代码 VS 原型制作
原型制作生成用过就扔的代码,曳光代码虽然简约,但却是完整的,并且构成了最终系统的股价的一部分,你可以把原型制作视为在第一发曳光弹发射之前的侦察和情报搜集工作。
5. 原型与便笺
原型的设计目的就是回答一些问题,可以忽略不重要的细节
应制作原型的事物:
任何带有风险的事物,以前没有试过的事物,或是对于最终系统极端关键的额事物,任何未被证明的,实现性的,或有疑问的事物,任何让你绝得不舒服的事物,可以为下列事物制作原型:
l 架构
l 已有系统的新功能
l 外部数据的结构或内容
l 第三方工具或组件
l 性能问题
l 用户界面设计
原型制作是一种学习经验,其价值并不在于所产生的代码,而在于所学到的经验教训,那才是原型制作的要点所在
提示16 Prototype to Learn 为了学习而制作原型
怎样使用原型:
l 在构建原型时,可以忽略那些细节?
l 正确性,使用虚设的数据
l 完整性
l 健壮性,错误检查可能不完整
l 风格
制作架构原型:
n 主要组建的额责任是否得了良好定义?是否适当?
n 主要组件间的协作是否得到了良好定义?
n 耦合是否得以最小化?
n 你能否确定重复的潜在来源?
n 借口定义和各项约束是否可接受?
n 每个模块在执行过程中是否能访问到其所需的数据?是否能在需要时进行访问?
怎样“不”使用原型
如果所在环境或文化中,原型代码的目的有可能被误解,也许最好还是采用曳光弹方法,你最后将得到一个坚实的框架,为将来的开发奠定基础。
6. 领域语言
提示17 靠近问题领域编程
更靠近问题领域,通过在更高的抽象层面上编码,或得专心解决领域问题的自由,并且可以忽略琐碎的实现细节。
7. 估算
估算,以避免发生意外
你解答问题的语境是什么?所有的估算都以问题的模型为基础。
估算来自哪里
估算诀窍:去问已经做过这件事情的人,仔细在周围找找也曾处在类似情况下的人。
理解提问内容
建立系统的模型,建立粗略、就绪的苏伟模型骨架
把模型分解为组件
给每个参数指定值
计算答案,保留奇怪结果的答案,助于对问题或模型的理解
追踪你的估算能力,分析与结果差距的原因
估算项目进度
l 检查需求
l 分析风险
l 设计、实现、继承
l 向用户确认
提示19 通过代码对进度表进行迭代
“我等会儿回答你”