为了赶上今天近乎疯狂的变化步伐。我们须要尽一切努力编写尽可能宽松灵活的代码。否则,代码很快会变得过时、太脆弱、以至于难以修理,并最终可能会掉队。

26、解耦与得墨忒耳法则

编写羞怯的代码是有益的,羞怯的工作方式有两种:不向别人暴露自己,不与太多人打交道。把代码组织成最小组织单位(模块),并限制它们之间的交互,如果随后出于折中必须替换某个模块,其他模块仍能够正常运行。

使耦合减至最少

当我们要求某个对象完成特定服务时,我们想要它替我们完成该服务,不希望这个对象给我们一个第三方对象、必须加以处理才能获得所需服务。

有许多不必要的依赖关系的系统非常难以维护,往往高度不稳定,为了使依赖关系保持最少,可以使用得墨忒耳法则设计方法和函数。

函数的得墨忒耳法则

函数的得墨忒耳法则试图使模块之间的耦合减至最少,编写尽可能羞怯的代码。

遵守函数的得墨忒耳法则缩小了调用类中的响应集的规模,以这种方式设计的类的错误也往往更少,将使你的代码的适应性更好、更健壮,但也有代价:作为总承包人,你的模块必须之间委托并管理全部子承包人,而不牵涉你的模块的客户。

与任何技术一样,你必须平衡你的特定应用的各种正面因素和负面因素。事实上,通过反转得墨忒耳法则,使若干模块精密耦合,可以获得重大的性能改进。

27、元程序设计

细节会弄乱我们整洁的代码,特别是如果他们经常变化。把细节赶出代码,让我们的代码变得高度可配置和软和,也就是容易适应变化。

动态配置

要配置,不要集成

要用元数据描述应用的配置选项,调谐参数、用户偏好、安装目录等等。

元数据是关于数据的数据。最常见的例子是数据库schema或数据词典,在宽泛意义上,元数据是任何对应用进行描述的数据。在典型情况下,元数据是在运行时,而不是编译时被访问和使用。

元数据驱动的应用

尽可能多的通过元数据配置和驱动应用。

将抽象放进代码,细节放进元数据

这种方法的好处:

  • 迫使你解除你的设计的耦合,从而带来更灵活、可适应性更好的程序
  • 迫使你通过推迟细节处理,创建更健壮、更抽象的设计,完全推迟到程序之外
  • 无需重新编译应用
  • 与通用的变成语言的情况相比,可以通过一种大为接近问题领域的方法表示元数据
  • 用相同的应用引擎,不同的元数据,实现若干不同的项目

商业逻辑

考虑在基于某种规则的系统(即专家系统)中对它们进行编码,并嵌入到你的应用中,这样,你讲通过编写规则、而不是修改代码类配置它。

不要编写渡渡鸟代码

没有元数据,你的代码就不可能获得它应有的适应性与灵活性。

28、时间耦合

时间是软件架构的一个常常被忽视的方面,吸引我们的时间只是进度表上的时间,发布之前我们剩余的时间。但我们这里谈论的是作为软件自身的一种设计要素的时间的角色:并发(事情在同一时间发生)和次序(事情在时间中的相对位置)。

我们需要容许并发,并考虑解除任何时间或次序上的依赖。

工作流

在许多项目中,我们需要把用户的工作流当做需求分析的一部分来进行建模和分析。我们想要找出在同一时间可能发生什么。以及什么必须以严格的次序发生。可以使用动作图,通过找出本来可以、但却没有并行执行的动作,使并行度最大化。

分析工作流,以改善并发性

架构

OTLP架构综览:

输入任务#1  \                -> 应用逻辑#1  ->
输入任务#2  ->  应用程序队列 -|                | -> 数据库队列 -> 数据库handler
输入任务#n  /                -> 应用逻辑#2  ->

在多个消费者进程间进行快速而粗糙的负载平衡的一种途径是饥饿的消费者模型:使用一些独立的消费者任务和一个集中式工作队列取代中央调度器。

为并发进行设计

并发迫使你更仔细地对事情进行思考,这不再是你一个人的舞会。因为事情现在可能会在同一时间发生,你可能会突然看到某些基于时间的依赖关系。

首先,你必须对任何全局或静态变量加以保护,使其免于并发访问;其次不管调用的次序是什么,你都需要确保你给出的是一致的状态信息。

对并发和时序依赖进行思考还能够引导你设计更整洁的接口。

总是为并发进行设计

部署

一旦你设计了具有并发要素的架构,对许多并发服务的处理进行思考就会变得容易。你可以灵活地处理应用的部署方式:单机、客户-服务器、或是n层。通过把你的系统架构成多个独立的服务,你也可以让配置成为动态的。

29、它只是视图

不要把程序写成一个大块,而应该分而治之,把程序划分成模块,每个模块都有其自身的责任。模块的一个好定义就是,它具有单一的、定义良好的责任。

一旦基于责任把程序划分成不同模块,你就有了新的问题。对象怎样互相交谈,你怎样管理他们之间的逻辑依赖?使用事件使得那些对象之间的耦合得以减至最少,事件发送者不需要对接收者有任何明确的了解。

发布/订阅

通过单个例程推送所有事件破坏了对象封装,还增加了耦合,甚至可能还违反DRY原则,正交性原则等。我们可以使用发布/订阅机制实现一种非常重要的设计概念:模型与模型的视图分离。

Model-View-Controller

使视图与模型分离

通过松解模型与视图/控制器之间的耦合,你用低廉的代价为自己换来了许多灵活性,这种技术是最为重要的维护可撤销性的途径之一。

  • 模型

    表示目标对象的抽象数据模型,模型对任何视图和控制器都没有直接的了解

  • 视图

    解释模型的方式,它订阅模型中的变化和来自控制器的逻辑事件

  • 控制器

    控制视图、并向模型提供新数据的途径,它既向模型也向视图发布事件。

30、黑板

黑板系统让我们完全解除了我们的对象之间的耦合,并提供了一个“论坛”,知识消费者和生产者可以在那里匿名、异步地交换数据。如你可能会猜想的那样,它还减少了我们必须编写的代码的数量。

黑板实现

基于计算机的黑板系统最初是为在人工智能中应用而发明的。现代的分布式类黑板系统,以一种键值对模型为基础。

因为我们可以存储对象,可以使用黑板设计基于对象流、而不仅仅是数据的算法。你与黑板有单一、一致的接口。

在构建传统的分布式应用时,你可能会花大量时间,为系统中的每一个分布式事务和交互精心制作独特的API调用,随着接口和交互的组合爆炸,项目可能很快就会变成噩梦。

黑板方式的变成消除了对太多接口的需要,从而带来更优雅、更一致的系统。

用黑板协调工作流

我们可以用黑板协调完全不同的事实和因数,同时又使各参与方保持独立、甚至隔离。

更多有关《程序员修炼之道》的读书笔记,请关注 :
http://tabalt.net/blog/the-pragmatic-programmer-reading-notes/

本文链接:http://tabalt.net/blog/tpp-bend-or-break/,转载请注明。