这是从原书中第12章到后面的读书笔记,对于前面的读书笔记及思考参见 UML和模式应用读书笔记二(做正确的事)
0x2B | ~0x2B
–Hamlet
上面的答案是0xFF
包
logical architecture是软件类的宏观组织结构,他将软件类组织为包,子系统和层等.
层
layer是对类,包或子系统的粗粒度分组,
OO系统的层一般包括用户界面,应用逻辑和逻辑对象,技术服务(数据库和日志)三层
在严格的分层架构中,层只能调用与其相邻的下层服务.这种设计在网络协议栈中比较常见,而在信息系统中不太常见.在信息系统中通常使用宽松的分层架构,其中较高层可以调用其下任何层的服务.
有的时候我们的确需要反向传递信息(例如通知GUI窗口对象改变颜色,这个时候就通过观察者模式,由GUI监听来实现)
从UI层发送到领域层的消息是将SSD中所描述的消息,例如enterItem
在开发过程的早期,我们会画出UML包图的草图,然后根据这些草图来组织代码.随着时间的流逝,代码库不断增长,同时我们在编程上花费的时间更多,并减少了建模或绘制UML图的时间.此时,可以利用UML CASE工具对源代码进行逆向工程,从而自动生成包图
内部嵌套包的表示
分包demo
//—UI层
com.mycompany.nextgen.ui.swing
com.mycompany.nextgen.ui.web
//—领域层
com.mycompany.nextgen.domain.sales
com.mycompany.nextgen.domain.payments
//—技术服务层
com.mycompany.service.persistence
//—第三方
org.apache.log4j
org.apache.soap.rpc
//—基础层
com.mycompany.util
注意上面有些包名带了nextgen,有些没有
分包原则
relational cohesion=内部关系的数量/类型的数量
分解为稳定和不稳定的两个子集
在早期迭代阶段确定良好的包结构是非常困难的,通常,包结构会随着细化迭代的深入不断进行演化,这也应该是细化阶段的目标(因为包结构具有重要架构意义),当细化阶段结束时大部分包结构将会稳定化
包之间循环依赖的方案
- 将循环分解出来作为较小的包
- 使用接口
增强包稳定的方法
-仅包含或主要包含接口和抽象类
- 不依赖其他包
- 稳定代码,经过充分测试
- 强制规定具有缓慢变化周期
有一个族接口组成的包
将一组功能相关的接口放入单独的包,与其实现类分离.接口的实现放在单独的包总
我个人不是很赞同这种方案
层
最底层
文中建议不要将一些外部资源或服务放到逻辑中低于基础层的地方,因为他们不属于任何逻辑层,层大致上只有上面那几种
层之间的耦合
- 所有较高层都依赖于技术服务层和基础层
- 领域层依赖于基础设置层
- UI层调用应用层,应用层调用领域层.除非没有应用层,UI层不直接调用领域层
- 对于单进程的"桌面"应用,领域层的软件对象对于UI层,应用层可见,或者在上述各层之间传递
- 在分布式系统中,通常将领域对象序列化副本(value object)传递给ui层.在此情形下,领域层部署在服务器,客户节点得到副本
应用层
在某些应用中,并不需要应用层.当下属情形发生时,应用层具有效用
- 系统使用多个用户接口.(例如web页面和swing gui),应用层对象可以充当负责收集和合并不同用户接口数据的适配器,同时充当隐藏对领域层访问的外观
- 在分布式系统,领域层和ui层在不同节点
- 领域层不能活不应该维护会话状态
- 通过限定窗口或web页面的顺序定义了工作流,并且必须表示这一工作流
总的看来,应用层就是Controller?
层的禁忌
- 会导致性能问题
- 可以使用pipes和filter代替,特别是变换顺序可以改变时