Services

服务

通常在我们做模型设计的时候,我们会根据实际业务抽象出很 多业务对象,然后再确定业务对象的状态和行为。一般的,在 业务的通用语言中,我们把名词考虑作为业务对象,如”用户” ;把动词考虑作为业务对象的行为,如”修改密码”。但在有些 业务中,有些动词的行为不属于任何一个对象,比如”食谱生 成”。这类动词代表了业务中一个很重要的行为,而且不能简单 把他们合并到某一个业务实体或则值对象当中。 给一个对象增 加这样的行为只会破坏该对象的职责,只是让它开起来拥有某 个功能。通常,这类行为的类会跨越若干个对象,或者是不同 的类。例如,在食谱生成中,食物数据源、营养份数结构和用 户的饮食偏好等作为输入,然后通过一系列逻辑来生成食谱。 这个功能是放在食物对象还是用户对象上呢,好像一个都不合 适。再举一个简单点的例子,银行系统中, 从一个账户向另 外一个账户转钱,这个功能是放在转出的帐户还是转出的帐户 中呢?感觉哪个都不合适。

就这样,当我们发现业务领域中有这样的行为时,我们的最好 的做法就是将他们声明为服务。服务一般没有状态,但有 时可以存放一些在业务执行时候的一些临时状态。服务代表了 业务领域中的一个清晰的特性。比如,食谱生成、食谱替换、 单位替换等每一个服务都代表了食谱业务的每一个特性。如果 把这样的功能放到某个业务实体或者值对象都会导致混乱。因 为这样将使这些对象的职责变得不清楚,对象间将建立密集的 关系网。高度耦合是糟糕设计的信号,这将大大降低代码可读 性,从而增加维护难度。

当然,服务也不应该是对通常属于业务对象的行为的代替。不 因该为每一个需要的行为或操作来抽象成一个服务。但当一个 行为突显为一个业务中的重要概念或特性时,就需要为他创建 一个服务。以下是服务的3个特性:

  1. 服务执行的操作涉及业务中一个重要的概念, 这个概念通常 不属于某一个业务实体或值对象。

  2. 被执行操作涉及业务中其他对象

  3. 操作是无状态的

服务也分领域模型(Domain)服务和基础设施(Infrustracture) 服务。这个区分也很重要。例如, 一个食谱生成服务就是领域 模型服务,因为他涉及到其他业务对象,如”用户”,”食物”。 而一个薄荷网发送确定email有效性的email发送服务就属于一 个基础设施服务,因为他要做的只是发送一段HTML到用户的邮 箱,跟其他业务对象没有关系。

Comments