(译者序)
“每一个模式描述了一个在我们周围不断重复发生的问题,以及该问题的解决方案的核心。这样,你就能一次又一次地使用该方案而不必做重复劳动。” ———— Christopher Alexander
招式套路可以千变万化,扎实深厚的“内功”却是始终如一;
(前言)
关于软件架构的通用性的书籍,我推荐[POSA] —— “面向模式的软件体系结构”;
迭代开发的核心在于只要软件对用户有用,就应当交付,即使这个软件当时并没有完成;
(引言)
大多数重要的企业应用都是按照某种形式的层次分层设计的;
企业应用:
- 企业应用一般都涉及持久化数据;
- 企业应用一般都涉及大量数据;
- 企业应用一般都涉及很多人同时访问数据;
- 企业应用一般都涉及大量操作数据的用户界面屏幕;
- 企业应用很少独立存在,通常需要与散布在企业周围的其他企业应用集成;
企业应用是多种多样的,不同的问题将导致不同的处理方法;
当构建企业应用系统时,关注硬件的可伸缩性往往比关注容量或效率更重要;
总的来说,购买新硬件还是比修改旧软件来得便宜;
模式的关键点是它们源于实践;
使用模式的关键之一是不能盲目使用;
每个模式相对独立,但又不彼此孤立。有时候它们相互影响,如影随形;
模式为设计提供了一套词汇,这也是为什么模式的名字这么重要的原因;
(P12)
在分解复杂的软件系统时,软件设计者用得最多的技术之一就是分层;
当用分层的观点来考虑系统时,可以将各个子系统想象成按照“多层蛋糕”的形式来组织,每一层都依托在其下层之上。在这种组织方式下,上层使用了下层定义的各种服务,而下层对上层一无所知。另外,每一层对自己的上层隐藏其下层的细节;
当然,并非所有的分层架构都这么隔绝,但绝大多数是不透明的,或至少是几乎不透明的;
(P15)
根据不同的问题,选择一种适合的分离方式,但是切记一定要进行某种形式的分离 —— 至少在子程序级别;
(P16)
只要有可能就用 Web 表现方式,只有在必需的情况下才使用胖客户方式;
(P19)
用“领域模型”而不是“事务脚本”正是面向对象的程序员所极力鼓吹的“理论体系转换”的精髓;
(P20)
“领域模型”的价值在于你一旦掌握了它,就可运用许多现成的技术来较好地组织日趋复杂的领域逻辑;
(P21)
一旦习惯了“领域模型”,一般就可以在将来很好地运用它,从而受益终生;
在许多方面,“表模块”是“事务脚本”和“领域模型”的一个中间地带;
(P22)
开发小组的经验越丰富,我越倾向于使用“领域模型”;
(P23)
“事务脚本”、“领域模型”和“表模块”这三种模式并不互相排斥。事实上,使用“事务脚本”来处理一部分领域逻辑,同时使用“表模块”或“领域模型”来处理剩下的部分,这也是很常见的;
处理领域逻辑的常见方法是将领域层再细分成两层。“服务层”独立出来,置于底层的“领域模型”或“表模块”之上。表现逻辑与领域层的交互完全通过服务层,就好像应用程序的 API 一样;
如果设立了服务层,在其中置入行为的多少是一个至关重要的决定:
- 最小化情况下,“服务层”只是一个外观,所有实际的行为都在下层的对象中,“服务层”所做的只是将上层调用传递到更低层。在这种情况下,“服务层”提供一个更易于使用的 API ,因为它的方法通常根据用例来组织。此时,它也提供一个很方便的切入点,用来增加事务封装和安全检查等功能;
- 另一个极端则是将大多数业务逻辑都以“事务脚本”的形式置于“服务层”中。下层的领域对象变得极为简单。如果下层是“领域模型”,则其中的对象与数据库一一对应,因而此时你就可以使用诸如“活动记录”等较简单的数据源层;
(P26)
清晰的 SQL 和领域逻辑分离是相当有益的;
(P27)
如果领域逻辑非常简单并且类和表十分一致,使用“活动记录”就足够了;
如果领域逻辑比较复杂,“数据映射器”才是需要的;
(P38)
尽量使用已预先编译好的静态 SQL ,而不是每次都编译动态 SQL ;
(P62)
本地接口最好是细粒度接口。细粒度接口非常好,因为它符合一般的面向对象原则,即尽量细分对象,使我们可以以不同方式组合和覆盖这些对象以便在将来对设计进行扩展;
(P63)
只有在无法使用系统自己的远程调用机制时,才使用基于 XML 的 Web Service ;
(P77)
“事务脚本”胜在简单,对于只有少量逻辑的应用程序来说,使用这一模式非常自然,无论在性能上还是理解上都不会带来太大的开销;
(P81)
“领域模型”与系统中其它层之间的耦合程度应达到最小;
(P83)
要熟悉“领域模型”需要实践和训练,但是一旦掌握了它,我发现除了解决最简单的问题外,很少会有人再使用“事务脚本”;
(P86)
“策略类”的巨大价值在于提供了一些良好封装的插入点,来进行应用程序扩展;
(P87)
在面向对象技术中,通过从一个对象到另一个对象的连续传递可以把行为传给最有资格处理的对象,它同时也消除了许多条件判断行为;
相似的条件判断语句可以提取到对象结构本身之中;
(P88)
面向对象的关键思想之一是将数据与对该数据操作的行为绑定在一起;
(P94)
“服务层”定义了应用的边界和从接口客户层角度所能看到的可用操作集。它封装了应用的业务逻辑、事务控制及其操作实现中的响应协调;
“服务层”类的接口是粗粒度的,就接口粒度而言,“服务层”类很适合于远程调用;
(P96)
“服务层”的设计思想来自于应用边界模式;
“服务层”的优点在于它定义了一个公共的应用操作集合,这一集合可被各种客户使用,而且服务层在每个操作中都会协调应用的响应;
(P99)
“服务层”这一设计模式为封装应用的业务逻辑、实现和支持不同的客户以一致的方式调用这些逻辑奠定了基础;
(P101)
“表数据入口”接口很简单,一般包括几个从数据库中获取数据的查找方法以及更新、插入和删除方法;
(P102)
“表数据入口”和“领域模型”很少一起使用,因为“数据映射器”更好地分离了“领域模型”和数据库;
“表数据入口”可以同“表模块”一起很好地使用;它产生一个记录集数据结构由“表模块”处理;
(P103)
在 .Net 环境下,当操作大量信息但又不想一次把全部信息都调入内存时,数据阅读器是合适的选择;
(P107)
通常很难说清“行数据入口”和“活动记录”之间的区别,这个问题的关键要看是否存在任何领域逻辑。如果存在,则是“活动记录”。“行数据入口”仅包含数据库逻辑而没有领域逻辑;
(P275)
进程间调用的开销比进程内调用的开销更大 —— 即使两个进程都在同一台机器上;
(P340)
.Net 对值对象有良好的支持机制,在 C# 中通过声明一个对象为结构而不是类就将它标记为值对象;
(P352)
如果依赖于完全不受自己控制的外部资源,通常会使软件项目受挫;