敏捷软件开发原则模式与实践读书笔记3_第1页
敏捷软件开发原则模式与实践读书笔记3_第2页
敏捷软件开发原则模式与实践读书笔记3_第3页
敏捷软件开发原则模式与实践读书笔记3_第4页
敏捷软件开发原则模式与实践读书笔记3_第5页
已阅读5页,还剩5页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、精品文档敏捷软件开发原则、模式与实践读 书笔记3敏捷软件开发:原则、模式与实践读书笔记 32010年04月01日星期四17: 20第18章薪水支付案例研究:第一次迭代开始第18章薪水支付案例研究:第一次迭代开始-18.1介绍本章使用的用户素材都 是很简单的,这是初期迭代的特征,仅提供用户所需商业价值中最小的部分。本章 进行快速的分析和会话设计,这通常发生在一次迭代开始时。下一章进行实际的设 计工作,完成但愿测试和实现。 第18章薪水支付案例研究:第一次迭代开始- 18.1.1规格说明描述在和客户交谈时关于第一次迭代中的素材的记录。根据用户 素材,可以首先生成数据库模式(database sch

2、ema),不过在使用这种方法产生的 应用程序中,数据库成为了关注的中心。数据库是实现细节,应该尽可能推迟考虑 数据库。有太多的应用程序,之所以和数据库绑定在一起而无法分开,就是因为一 开始设计时就把数据库考虑在内。请记住,抽象的定义,本质部分的放大,无关紧 要部分的祛除。在项目的当前阶段,数据库是无关紧要的;它只不过是用来存储和 访问数据的技术而已。第18章薪水支付案例研究:第一次迭代开始-18.2基于 用例的分析先来考虑一下系统行为,而不是系统的数据。一种捕获、分析系统行为的方法是创建用例(user case)。按照最初Jacobson的描述,用例和XP中的用 户素材的概念非常相似。用例就是

3、更详细一点的用户素材。一旦在迭代中要实现当 前该用户素材,这种详细是合适的。在进行用例分析时,我们关注用户素材和验收 测试,以找出系统的用户会执行的操作种类。接着我们会努力弄清楚系统怎样去响 应这些操作。列举了 7个本地迭代选取的用户素材。下面把用户素材转化为详细的 用例。只要有助于考虑出每个素材的代码设计即可,不要陷入过多的细节。第18章薪水支付案例研究:第一次迭代开始-18.2.1增加雇员根据增加雇员用 例分析操作方面:利用 COMMANDS,创建 AddEmployeeTransaction基类,三个 派生类 AddHourlyEmployeeTransaction、AddSalarie

4、dEmployeeTransaction 、 AddCommissionedEmployeeTransaction。把每项工作戈U分至U自己的类中,遵循 SRP 原则。也可以把所有代码放到一个模块中,这样就减少了类的数量,系统也更简 单,但使所有的操作代码集中于一个模块造成庞大切可能出错的模块。对象模型: 抵制住记录规划或字段结构等数据库倾向的诱惑,从对象模型的角度思考:图18.2: Employee基类,3 个派生类 HourlyEmployee、CommissionedEmployee SalariedEmployee。第18章薪水支付案例研究:第一次迭代开始-18.2.2删除 雇员描述删

5、除雇员用例。第18章薪水支付案例研究:第一次迭代开始-18.2.3 登记时间卡描述等级时间卡用例。用例表示,一些操作只能应用于某类雇员。这加 强了不同类的雇员应该使用不同的类表的观点。第18章薪水支付案例研究:第一次迭代开始-18.2.4登记销售凭条用例4:登记销售凭条。与用例3类似,暗示 一些操作只能应用于某类雇员。第18章薪水支付案例研究:第一次迭代开始-18.2.5登记协会服务费用例5:登记协会服务费协会会员有自己的成员标识。第18章薪水支付案例研究:第一次迭代开始-18.2.6更改雇员明细用例6:更改雇员 明细该用例具有启迪性。由于可以把雇员从钟点工,修改为带薪雇员。显然图 18.2并

6、不合适。在薪水计算中,使用 STRATEGY式也许更恰当。图18.6: Employee类持有一个名为Paymentclassification的对象,这个对象具有HourlyClassification 、SalariedClassification 、 CommissionedClassification 。HourlyClassification 含有 Timecard 对象歹U表。 CommissionedClassification 含有 SalesReceipt 。者B是采用了组合(composition) 方式使用STRATEGY现支付方式的改变。对于协会成员使用了NULL OB

7、JECT式。这些模式的使用使得系统很好的符合了OCP Employee对于支付方式、支付类别、协会从属关系的变化都是封闭的。这样,可以在不影响Employee的情况下,向系统增加新的支付方式,支付类别以及协会从属关系。图 18.6成为了我们的核 心模型,(core model)或者架构(architecture)。是薪水支付系统所有事情的核 心。在薪水支付案例中的其他类和设计,相对于这个基础结构而言都是次要的。当 然,这个结构也会和其他部分仪一起演化。 第18章薪水支付案例研究:第一次迭代开始-18.2.7发薪日用例7现在运行薪 水支付应用程序将薪水计算的任务交付给PaymentClassif

8、ication 。 第18章薪水支付案例研究:第一次迭代开始-18.3反思:我们学到了什么用简单的用力分析 可以提供丰富以及系统设计的洞察力。图18.6-18.10就是通过思考这些用例得到的,更确切地说,是思考行为得到的。 第18章薪水支付案例研究:第一次迭代 开始-18.4找出潜在的抽象为了有效的OCP必须搜寻出隐藏于应用背后的对象。 应用需求,甚至用例,不会表达,这些抽象。需求和用例太关注细节以至于不能潜 在抽象的一般性。SLS:提炼公用组件也是这个道理。 第18章薪水支付案例研 究:第一次迭代开始-18.4.1支付薪水时间表抽象支付时间是非常多边的。过度依 过工具和过程低估智力和经验都是

9、灾难的源泉。结果是:增加PaymentSchedule,以及其3个子类对应已知的三种方式。Employee包含了 PaymentSchedule。第 18章薪水支付案例研究:第一次迭代开始-18.4.2支付方式支付方式的抽象已经从 18.6图中表现出来了,他就是 PayMethod 第18章薪水支付案例研究:第一次 迭代开始-18.4.3从属关系某一雇员可能属于某一协会,但实际是一个雇员可能属 于多个协会。结果是Employe持有Affiliation的列表,如果不属于任何协会Affiliation列表,置空即可,不必使用 NULL OBJECT式了。第18章薪水支付案例研究:第一次迭代开始-

10、18.5结论在一次迭代开始,开发团队通常会聚集在 一个白板前,一起思考需要实现的用户素材。这类快速设计会话持续时间会小于1小时。也许会产生UML但最终这些UML会留在白板上。会话的目的就是发起思 考活动,并为开发人员提供一个公共的,可依据其展开工作的智力模型,而不是为 了确定设计。本章就是一个快速设计会话的原原本本的例子。 第19章薪水支付案例研究:实现本章以微笑增量的方式来创建代码。UMLS用于展现我们的想法,为交流提供媒介。图 19.1 ,使用名为Transaction的抽象基 类代表操作。采用COMMANDS具有execute方法。第19章薪水支付案例研究:实现-19.1增加雇员图19.

11、2,描述AddEmployeeTransaction的上下结构。像 往常一样,使用测试优先的方法编写代码:程序 19.1. 第19章薪水支付案例研 究:实现-19.1.1薪水支付系统数据库 AddEmployeeTransaction类使用了 PayrollDatabase 的类,PayrollDatabase 中保存了一 empID为键值的 Dictionary 。 PayrollDatabase 是 FACADE(式的列子。程序 19.3 , 19.4 该实现是 为了帮助通过最初的测试用例。一般而言,我们认为数据库实现是细节。应该尽可 能推迟细节的设计决策。不管这个特定的数据库,是RDBM

12、S平面文件(flatfile)、或者OODBM现。现在仅对API感兴趣,随后会发现有关数据库的合适实 现。推进有关数据库的细节,是一项不常见的、但却很值得的实践。直到对需求有 了更多的了解,才进行有关的数据库的决策。通过等待,避免把过多的基础结构放 入数据库中。我们仅仅实现刚好实现满足应用程序功能的数据库。第19章薪水支付案例研究:实现-19.1.2使用TEMPLATE METHOD来增加雇员图19.4,展示 了增加雇员的动态模型。图中, AddEmployeeTransaction向自己发送了一条消息 (SLS:调用),其子类实现了这条消息(SLS:方法)。这是一个TEMPLATE METH

13、OD 式的应用。程序19.5、19.6是AddEmployeeTransaction的头文件和cpp文件。程 序19.7、19.8是AddSalariedTransaction 的头文件和cpp文件。第19章薪水 支付案例研究:实现-19.2删除雇员图19.5、19.6中展现了删除雇员操作的静 态,动态实现。主要类为 DeleteEmployeeTransaction 。 第19章薪水支付案例 研究:实现-19.2.1全局变量对于全局变量 GpayrollDatabase ,数十年来,教科书 和教师一直有好的理由不鼓励使用全局变量。在本例中,使用SINGLETONEMINISTATE真式具有不

14、必要复杂性的臭味。但并不认为全局变量本身是邪恶的,本 例中就很适合使用。 第19章薪水支付案例研究:实现-19.3时间卡、销售凭条以及服务费用图19.7、19.8展示了时间卡操作的静态和动态结构。主要思路:从 PayrollDatabase 得至ij Employee-PaymentClassification ,将 TimeCard放入其中。将 TimeCard放 入 PaymentClassification 中时,需要使用,dynamic_cast 操作符。程序 19.12 为测试用例。程序19.13为TimeCard的实现,目前就店一个数据类。程序 19.13 为TimeCardTra

15、nsaction类的实现。其中使用了字符串异常。这不是一个好的长期 实践,在抛出异常时很容易出现泄漏内存或资源的代码,要注意。图 19.9、19.10 展示了向应支付薪水的雇员中登记销售凭条的设计。图19.11、19.12展示了向协会成员等级服务费用的设计。程序19.16为测试用例,第19章薪水支付案例研 究:实现-19.3.1代码与UMLB UMM没有验证它的代码是很危险的。代码可以告 诉你UML能告诉你的设计内容。在 UML中放入不需要的内容,也许总有一天会用 上,但在用上之前必须要不断的维护。所以关于员工的会员,我们从对象列表改会 NULL OBJECT式。程序 19.17、19.18

16、展示了使用 NULL OBJEC模式的 ServiceChangeTransaction 类的实现。第19章薪水支付案例研究:实现-19.4 更改雇员属性图19.3、19.4展示了修改雇员属性的动态结构,SLS:我觉得作者的设计,一直是按照一个操作一个类的方式设计的,如果这样的设计放到很多系统 中,肯定会有类爆炸的问题。又t道作者没有发现这个问题?图19.15、19.16、19.17 展示了改动的动态模型。使用 TEMPLATE METHOD,从 PayrollDatabase取Employee对象的操作在基类中,然后调用自己的 change函数,在子类中实现 change函数。程序19.19

17、展示了 ChangeNameTransaction的测试用例。程序 19.20、19.21展示了抽象基类 ChangeEmployeeTransaction的实现。一个明显的 TEMPLATE METHOD。程序 19.22、19.23 展示了 ChangeNameTransaction类的 实现。TEMPLATE METHOD的另一半。第19章薪水支付案例研究:实现- 19.4.1 更改雇员类别图 19.18-19.21 展示了 ChangeClassificationTransaction 的动态行为。又一个 TEMPLATE METHOD;。程序19.24展示了 ChangeHourly

18、Transaction 的测试用例。程序 19.24、19.25 展示了 ChangeClassificationTransaction 的实现。TEMPLATE METHOD。程序 19.26、19.27 展示了 ChangeHourlyTransaction 的实现。TEMPLATE METHOD;。 图 19.22-19.28 展示了 ChangeMethodTransaction、 ChangeAffilicationTransaction 以及子类的 UMLH。与 ChangeClassificationTransaction 的实现是一脉相承的。 第19章薪水支付案 例研究:实现-

19、19.4.2我当时抽了什么烟了 PayrollDatabase应该记录Bill的协 会成员关系,但在UML中并没有显示这一点。SLS:也就是说,雇员与协会这件 的关系,没有被持久化到数据库中。通过为 ChangeAffiliation 增加 RecordMemership(Employee*)来解决这个问题。SLS:以前白程序 19.23 ChangeNameTransaction.cpp ,也没有把改动持久化啊?有点迷糊。 ChangeUnaffiliationTransaction是一件让人不快的事,在 Affiliation 放入RecordMemberShip和 EraseMember

20、Ship,会解决这个问题,但会让 Affiliation 知 道PayrollDatabase也让人不快。最终保持这个轻微违反 OCP勺设计。SLS:这 块感觉有点学究气。第19章薪水支付案例研究:实现-19.5支付雇员薪水图19.29-19.33展示了支 付薪水的动态行为和静态结构。CalculatePay算法依赖于Employee依赖的 PaymentClassification ,是否支付日期依赖于 Empoyeefl勺 PaymentSchelue,支付 信息依赖于Employee的PaymentMethod这种高度的抽象,使得,这些算法对于 新类型的支付类别、支付薪水的时间、从属关系

21、,以及支付方式,都可以做到封 闭。其中引入了登记的概念,也就是计算正确的支付金额,并发送给Employee后,会等级支付信息。这样 Calculate的计算方法为从最近的支付日期到指定日期 的薪水。第19章薪水支付案例研究:实现-19.5.1我们希望开发人员做商务决 策吗登记这个概念,在用户素材中并没有提到,只是我用这个概念解决遇到的问题 -担心同一时间,同一日期多次调用 Payday方法,所以要确保不会出现多次支付 薪水的情况。我并没有咨询客户。实际我做了一个商务决策,我断定,多次运行薪 水支付程序,会有不同的结果。其实我应该咨询客户和项目管理人员。在和客户的 协商中,我发现等级违反了客户意

22、图。他们希望再次运行以便检查错误。客户说根 本不必考虑支付时间以外的时间卡或者销售条。登记方案被抛弃。SLS:作者写这段的意思是,开发人员不应该做商务觉得,要多与客户沟通。第19章薪水支付案例研究:实现-19.5.2支付带薪雇员薪水程序19.36为支付带薪雇员的测试用 例。程序 19.37 为 PaydayTransaction : Execute :取得所有 Employee,并循环调 用IsPayDate方法。程序19.38为Monthshedule.cpp的部分实现。程序19.39为Employee: PayDay()的实现。SLS:注意:PayCheckM是一个数据类。 第 19 章薪

23、水支付案例研究:实现-19.5.3支付钟点雇员薪水支付钟点雇员薪水的实现, 是用来说明测优先设计增量型的很好示例。我们会从最简单的测试用例开始,直到 更加复杂的测试用例。程序19.40-19.46都为逐步增加复杂度的测试用例,以及 HourlyClassification.cpp 、WeeklySchedule.cpp 的代码片段。第 19 章薪水支 付案例研究:实现-19.5.4支付期:一个设计问题本节实现计算会费和服务费的功 能。程序19.47为带薪雇员转变为协会会员后,支付其薪水。问题:用户素材说会 费每周提交一次,带薪雇员的薪水是每月支付,一个月包含几周?询问客户得知会费每周五累加一次

24、。将IsInPayPeriod 函数放到HourlyClassification ,是错误 的。用于确定支付期的函数应该属于 PaymentSchedule类。UMLJEI并没有帮我们捕 捉这个问题,再次说明代码反馈对于设计是多么重要。程序 19.48,PaydayTransaction : Execute 程序 19.49 , PaymentClassification : IsInPayPeriod 以上两个程序演示了,将 IsInPayPeriod A HourlyClassification 转移出来的代码。程序 19.50 , UnionAffiliation : Calculate

25、Deductions(),展 示如何计算雇员的会费。程序19.51 ,为按小时支付雇员的会费扣除的测试用例。 程序19.52,验证当前支付之间外的会费没有被扣除。将判断日期是否在某个时间 段内的IsInPayPeriod 的函数放到了 Date中,改名IsBetween。程序19.53程序 19.54、19.55 展示了 Employee.h 和Employee.cpp 第19章薪水支付案例研究: 实现-19.6主程序图19.34、19.35描绘了主程序的静态和动态结构。PayrollApplication处在一个循环之中,交替从 TransactionSource获取操作,然后执行。Tran

26、sactionSource是一个抽象类,可以有各种实现,图中为TextTransactionSource 。TransactionSource 中接口和实现的分离使操作的来源 可以成为抽象的。例如: GUITransactionSource、RemoteTransactionSource 第 19章薪水支付案例研究:实现-19.7数据库在完成了本次的迭代中的分析、设计、 实现工作后,可以考虑数据库了。可以使用OODBMS实现PayrollDatabase ,对应用程序的对象模型没有影响。可以使用平面文件来,实现 PayrollDatabase,但 对于大量数据或并发访问的应用来讲,则无法满足需

27、求。可以使用RDBMS实现PayrollDatabase 。关键在于,数据库只是管理存储的机制。通常不应该作为设计 和实现的主要因素。流到最后,作为细节处理。这样实现持久化功能时,我们就会 有很多方案可供选择。也没有和任何数据库或产品绑定,我们可以选择,替换数据 库。设计者应该解除设计和数据库之间的耦合,应用设计不应该依赖于任何特定的 数据库。SLS:我觉得上边的观点,是极端的面向对象观点,或叫极端的设计观 点。实际使用时,这样设计会导致巨大的不必要的复杂性。数据库应用,还是面向 数据库比较好。没想到看着面向对象设计的书,却要不使用面向对象设计。首先我 们的目的,是为了满足客户需求,而不是做面

28、向对象设计,所以,应该有一套面向 数据库的设计方法。我们不应该为了面向对象而去面向对象。就像前边一直有所表 述的“知道何时不运用运行一个设计原则、模式或最佳实践,比知道如何运用它同 样重要”,第二章一开始也说,XP并不是唯一的选择。同样,面向对象也不是唯一 的选择,或者我们可以选择面向数据库设计 ?知道何时不运用面向对象设计也同样 重要。当然,作者是在讲面向对象设计,不可能突然将,面向数据库方面的设计, 但面向数据库的设计也值得研究。第19章薪水支付案例研究:实现-19.8薪水支付系统设计总计由于使用了大量的抽象和多态,使得绝大部分设计对于薪水支 付策略更改做了封闭。在这个过程中,我们很少考虑

29、我们是否在进行分析、设计、 实现(SLS:意思是没有考虑处于哪个阶段),相反,我们全神贯注于清楚和封闭问 题。尽力找出潜在的抽象。最终,我们获得一个薪水支付应用的初始设计,并且拥 有了一组在整体上和问题域密切关联的核心类。SLS:对于18章,图18.6薪水支付的核心模型,是通过分析行为得到的静态结构。我觉得这个结构是简洁的。但 19章,由于使用了 COMMANDS,导致了类爆炸,增加了复杂性。当然,使用 COMMA得了巨大的好处,19.6主程序对这种好处有所阐述。SLS:对于 本例,我觉作者的目的,是要获得一组在整体上和问题域密切关联的核心类,所 以作者没有考虑数据库和界面。而这种去界面,去数

30、据库的“一组核心类”是对问题域的高度抽象,由于其巨大的可扩展性,所以在以后的设计中,非常值得借鉴。至 于”面向数据库设计“那是另一码事。第19章薪水支付案例研究:实现-19.8.1 历史讲述,本例子的历史,是1994年就创建了图示,并在1995年出版的一本书中 使用。但由于当时没有代码反馈,所以犯了一些错误。从而凸显出,代码反馈的重 要性。第19章薪水支付案例研究:实现-19.8.2资源 第IV部分打包薪水支付系统本章部分研究把大的软件系统分割成包的设计原则。第20章包的设计原则优美的包裹-安东尼类对于小的应用程序来说是非常方便 的组织单元,但对于应用程序规模和复杂度比较高的程序,需要在更高的

31、层次对应 用程序进行组织,那就是包。本章讲述6个原则,前三个关注包的内聚性,如何 把类划分到包中,后三个关注包的耦合性(确定包之间的关系),最后两个还描述了 一组依赖性管理度量,据此对设计中的依赖结构进行度量。第20章包的设计原则-20.1如何进行包的设计UM叶包可以是类的容器。把类组织成包,可以在更高 的层次理解设计。根据一些原则对应用程序的类进行划分。跨包的类的依赖关系, 导致了包之间的依赖关系,这就提出了如下几个问题:1.想包中分配类时应该依据什么原则?2.应该使用什么设计原则管理包之间的关系 ?3.包的设计应该先于类(自 顶向下)?还是类的设计先于包(自底向上)?4.如何实际表现出包?

32、C+中,JAVA 中,其他环境5.包创建好后,应该用于何种目的?第20章包的设计原则-20.2粒 度:包的内聚性原则本节讲述包的内聚性的三个原则,帮助开发者把类划分到包 中。这些原则依赖于:至少存在一些类,并且他们之间的关系已经确定。这些原则 是依据自底向上的观点划分的。第20章包的设计原则-20.2.1重用发布等价 原则RE的重用发布等价原则当重用一个类库时,对这个类库的作者的期望当然 是:好的文档、可工作的代码、规格清晰的接口。但除了这些还有:首先,希望代 码作者这保证维护代码。其次,希望代码作者计划修改接口和功能等改动时,通知 你。但仅仅是通知是不够的,要允许你具有不使用新版本的权利。当

33、不使用新版本 时,必须对旧版本继续提供支持。这是一个行政问题。REP旨出,一个包的重用粒度可以和发布粒度一样大。重用的东西必须被同时发布和跟踪。简单的声称重用是 不够的,要建立一个跟踪系统,为潜在的使用者提供需要的变更通知,安全性,支 持后,重用才有可能。REP合我们关于如何把设计划分到包中的第一个提示,由于 重用性必须是基于包的,所以可重用的包,必须基于可重用的类,因此该包必须有 可重用的类组成。我们必须从重用者的角度考虑包的内容,如果包中的软件是为了可重用的,那么他就不能包含不是为重用目的而设计的软件。一个包中的软件要么 都是可重用的,要么都不是可重用的。SLS:为包的使用者提供一个干净的

34、纯粹的用于重用的包。但这好像和共同重用原则一样。对于这个原则,我理解为,重用 和发布一样重要。要重用就要配合发布,跟踪等。但这和包的划分有什么关系 呢? SLS:网络资料的辅助理解:OOS计模式和设计原则一个可重用的元件(组 件、一个类、一组类等),只有在它们被某种发布(Release)系统管理以后,才能被 重用。将什么类放在一个包中的判断标准之一就是重用,并且因为包是发布的最小 单元,它们同样也是重用的最小单元。体系结构师应该将可重用的类都放在包中。 SLS: REPfc要讲述重用和发布的关系,同时指出将重用的类都放在包中。CR比指那些放入包中的可重用的类,都要为了一个目的而重用。第20章包

35、的设计原则-20.2.2共同重用原则CRPr一个包中的所有类都应该是共同重用的。如果重用 了包中的一个类,那么就要重用包中的所有类。这一原则,决定哪些类放入同一个 包中。规定趋向共同重用的类应该属于同一个包。简称 CRP止匕外,包经常以共享 库、DLL jar等物理表示的形式出现。当我依赖于一个包,我将依赖于包中的每 一个类。防止包中与我无关的修改导致重新验证和发行。第20章包的设计原则-20.2.3共同封闭原则CCPr包中的所有类,对于同一类性质的变化应该是共同封闭 的。一个变化若对一个包产生影响,将对包中的所有类产生影响,而对于其他的包 中的类不产生任何影响。简称 CCP这是单一职责对于包

36、的重新规定。这一原则规 定,对于包,不应该包含多个引起其变化的原因。在大多数应用程序中,可维护性 的重要性要大于可重用性。如果一个应用中的代码必须修改,那么我们更改都集中 在一个包中。CC限励由于同样原因而更改的所有类聚集在同一个地方。以减少软 件的发布、重新验证、重新发行的工作量。这个原则和开放封闭原则密切相关。但 正如我们学的的,100%寸闭是不可能做到的,应该有策略的进行封闭。我们设计的 系统应该对于我们最常见的变化做到封闭。第20章包的设计原则-20.2.4包的内聚性过去,我们队内聚性的认识,远比上面 3个原则所蕴含的简单。我们习惯于 认为内聚性,不过是一个模块执行一项并且仅能执行一项

37、功能。在选择共同组织到 包中的类时,必须考虑重用性和可开发性之间的相反作用力。这不是一个简单的工 作。并且这个作用力是动态的。今天关注可开发行,明天可能关注可重用性。 SLS:我理解可开发行为,是一个相对于重用性的概念。就是只关注当前功能的 实现。而不是重用。就叫可开发性。可能实际开发效率。如果关注可重用性,从重 用多角度增加功能点。SLS:软件行业呼唤可开发性设计,DFD(Design for Developability ,可开发性设计)简单说来,可开发性设计就是我们在开发一个软 件(相关)产品时,软件的设计应当考虑方便开发人员(大部分情况下就是我们自己) 进行开发,或者说在设计时应考虑如

38、何提高开发效率。DFMM1 Design forManufacturability( 可制造性设计)的简称,主要研究产品本身的物理设计与制造 系统各部分之间的相互关系,并把它用于产品设计中以便将整个制造系统融合在一 起进行总体优化。DFMP以降低产品的开发周期和成本,使之能更顺利地投入生产 第20章包的设计原则-20.3稳定性:包的耦合性原则我们会再次看到,可开发 性和逻辑设计之间的冲突,来自技术和行政方面的作用力会影响包的组织结构,这 种作用力,还是易变的。 第20章包的设计原则-20.3.1无环依赖原则AD的在包 的依赖关系图中,不允许存在环。“晨后综合症:造成来后,因为其他同事昨晚对 代

39、码的修改,导致自己的程序出现问题。在几个开发人员的小项目中,这不是大问 题。但当开发团队的规模增长时,就会带来噩梦。在缺乏纪律的团队中,几周都无 法构建出一个稳定的项目版本是很常见的。每个人都在忙于修改代码以适应别人的 代码。对于这种问题的解决方法有:每周构建, ADP 第20章包的设计原则- 20.3.2每周构建每周构建尝尝应用在中等规模的项目中:每周前四天各自工作, 互不打扰。周五集成。糟糕的是,随着项目的增长,集成工作量越来越大。从而导 致效率下降,导致危机。第20章包的设计原则-20.3.3消除依赖环通过把开发 环境划分为可发布的包可以解决上述问题。这些包可以作为工作单元拆分出来。每

40、个工作单元都收版本控制,都有发布。其他团队会可以决定是否采用其他团队的新 版本。这是一个非常简单合理的过程,并被广泛使用。要使这个方法起效。包的依 赖关系中不能存在环。SLS:上述方法,对每个单元都建立版本,会增加版本控 制的工作量,对于超大的项目也许合适。我认为由架构师,从总体的角度划分包, 划分包之间的结构,是解决这个这个问题的更好的方法。也许是敏捷开发不允许架 构师的存在,所以作者没有提到这个问题。图 20.1包结构是有向无环图。这类表 明包之间依赖关系的图,非常好。第20章包的设计原则-20.3.4包的依赖关系 图中环造成的影响依赖环,会导致这些有依赖关系的包,编程一个大包。从而影响

41、发布,造成相互影响。单元测试和发布非常困难,容易出错。难于确定构建关系。第20章包的设计原则-20.3.5解除依赖环将依赖关系图恢复为 DAG勺方法:1. 使用依赖导致。从客户角度(函数调用者),而不是服务者(函数提供者)的角度命名 接口。是接口属于客户规则的又一应用。2.将组成环的包,合并为一个包。 第 20章包的设计原则-20.3.6抖动第二个方案意味着,在需求改变面前,包的结构是 不稳定的。第20章包的设计原则-20.4自顶向下设计现在可以得出结论:不能 自顶向下的设计包的结构。这意味着包的结构,不是设计系统首先考虑的事情之 一,事实上,包的结构,应该是随着系统的增长、变化而逐步演化的。

42、也许这违反 直觉,我们已经认为包这样的大粒度分解,也是高层功能分解。事实上,包的依赖 关系图,几乎和描述应用程序功能之间,没有关系。项目开始无软件可构件,就没 有关系图。随着项目规模的增长,不断使用 SRP CCP ADP等同类放到一个包中, 关注重用,去掉依赖环。包的依赖关系,是和系统逻辑设计一同增长和演化的。第20章包的设计原则-20.5稳定依赖原则SDPr朝着稳定的方向进行依赖设计不 能是固定的,设计的可维护和某种程度的易变性是必要的。通过共同封闭原则,我 们创建变化敏感型的包,这些包期待变化。对于任何包而言,如果其时可变的,就 不能让难于改变的包依赖它。这会导致一边包的难以改变。通过

43、SDP要确保易于 更改的包不会被难于更改的包所依赖。第20章包的设计原则-20.5.1稳定性硬币竖在桌子上,我们认为它是不稳定的。虽然没有人碰他,他不会倒。可见稳定性 与变化的频率(不碰硬币他不会动)没有直接关系。韦伯斯特认为:”不容易被移 动,被认为是稳定稳定性和更改所需要的工作量有关。对于软件来说,被依赖的 包越多,那么这个包就应该越稳定。因为依赖关系导致改动的工作量变大。第20章包的设计原则-20.5.2稳定性度量度量一个包的稳定性:计算该包进出依赖关 系的数目。不稳定性I二输出耦合度(处于该包内部并依赖该包外类的数目)/输入耦 合度(处于该包外部并依赖该包类的数目)+输出耦合度。箭头所

44、指是被依赖者。1=0最大稳定性。C+”,通过计算#include语句表示。java中计算import 。 SPD 定,一个包的I的度量值应该大于它所依赖的包的I度量值。也即是说I应该顺着 依赖的方向减小。第20章包的设计原则-20.5.3并非所有的包都应该是稳定的 如果一个系统中所有的包都是最大程度的问题,那么这个系统是不可变的。这并不 是希望的事情。我们希望系统中,一些包是稳定的,一些是不稳定的。可变色位于 顶部,依赖于底部稳定的包。这样向上的箭头意味着违反SDP 第20章包的设计原则-20.5.4在那里放置高层设计系统中,某些软件并不经常改变,改软件代表 系统的高层架构和设计决策。我们希望

45、这些架构觉得是稳定的。然而,如果把高层 设计放入稳定的包中,那么体现高层设计的源代码会很难改变,这样又不具有灵活 性。怎样具有最高稳定性,又具有灵活性 ?OC就是答案,抽象类符合OCP 第 20章包的设计原则-20.6稳定抽象原则SA的包的抽象,应该和其稳定程度一致。 该原则将稳定性和抽象性联系起来。该规则规定:稳定的包应该是抽象的,这样他 的稳定性就不会使其无法扩展。不稳定的包应该是具体的,因为不稳定性使其内部 代码易于更改。SD济口 SAP在一起,形成了针对包的DIP原则。结论是,依赖应该 朝抽象的方向进行。DIP是一个处理类的原则,类没有灰度的概念。类要么是抽 象,要么是具体的。第20章

46、包的设计原则-20.6.1抽象性度量抽象性A才由象类 的数目/包中类的总数第20章包的设计原则-20.6.2主序列现在我们定义不稳定 性I和抽象性A的关系,创建一个以A为纵轴,I为横轴的坐标图,在坐标图中两 种好的包的类型。最稳定最抽象的包位于左上角,最不稳定最具体的包位于右下 角。位于(0,0)附近的被称为痛苦地带。高度稳定且具体的。应该注意,数据库模 式就是这样的一个例子。数据库模式的异变众所周之 (SLS:就算使用数据类,也依 然是异变的)并且他是非常具体,高度被依赖的。这就是为什么面向对象应用程序 和数据库之间的接口难以定义,以及数据库模式更新通常都很痛苦的原因。还有工 具库也位于(0,0)位于(1,1)附近的被称为无用地带,抽象,但不被依赖。主序列: (1,0)至(0,1)的线。(命名来自作者对天文学和HR图(赫罗图横行真实亮度与表面 问的的关系)第20章包的设计原则-20.6.3到主序列的距离度量包到主序列的 距离。距离D=|A+L-1/根号二规范化距离D=|A+L-1|使用这个度量,可以全面分析 一个设计和主序

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论