代码工匠

Walking The Long Road.

关于业务架构的一些思考

最近换了部门,接手了好几个新项目,也进行了一些重构的尝试,总结一些经验。主要针对Web开发领域,算是抛砖引玉了。

1. 经历的几种业务架构的方式

公司是典型的SOA架构,Web层之下就是远程Service。Web层负责调用Service,Service则在内部整合缓存、数据库等内容,实现业务逻辑。

这样的结构没有什么问题,问题就在于Service内部的实现上。即使是Service的一个方法,内部实现也可能很复杂,这就涉及到代码分解的问题。

例如:在一个SNS系统中,我有一个UserService,负责User的CRUD。当然实际逻辑会比较复杂,例如新建User要创建用户,还要初始化积分、等级、收件箱等内容。那么,我该怎么做这件事呢?

1
2
3
4
5
6
7
8
9
10
11
public interface UserService {

    public boolean addUser(UserDTO userDTO);

    public boolean updateUser(UserDTO userDTO);

    public UserDTO getUser(int id);

    public boolean deleteUser(int id);

}

1.1 随意拆分式

我们之前的结构很随意,大部分代码都直接写在Service的实现类中,Service直接访问Dao实现逻辑。如果过于复杂,则会拆分成一些小的内部Service,并把它们聚合起来。这种方式在业务不复杂的时候,其实工作的还挺好的。

架构1

1.2 水平分层式

新接手的项目,老实说业务会更复杂。之前的做法是将业务分为了dal-数据库访问、domain-领域模型抽象、biz-业务逻辑、service-服务集成四层。例如一个查询数据的操作,可能要经历这么多个分层的流转,才能最终提供外部服务。这样分下来,代码的全复杂度确实也低了不少。

但是这个划分让我接手项目的时候困惑了很久,导致我觉得自己是不是理解能力下降了。后来在着手重构的时候,发现其实很多层次边界根本就很模糊了,甚至连参与维护者也不是很清楚。

过多的分层,会增加坏代码的破坏力,如果边界不是足够清晰,那就不如不分。

我理想的水平分层其实Web-Service-Dao已经足够了,因为他们的边界相对清晰,直接把Dao当做模型也工作得挺好,抽象出Domain来,根据已有的经验略微多余。

架构2

1.3 垂直拆分式

今天在做另一个项目的时候,尝试用一个责任链的方式来做这个事情。采用了垂直拆分的方式,将完成一件事,按照不同的模型,进行了细分,分成多个Processor,接口类似下面这样。Service内部只对这些子Processor做链式调用,它甚至也不知道有多少个Processor。结果这种方法出奇的好,大家发现并行开发很方便,测试也好写了,修改也方便了。

1
2
3
4
5
6
7
8
9
public interface Processor {

    public void onAdd(UserDTO userDTO);

    public void onUpdate(UserDTO userDTO);

    public void onDelete(UserDTO userDTO);

}

架构3

2. 结论:几个架构的检验标准

经过多次的折腾,也接手过不少的项目,我得出这么几个结论:

2.1 一段逻辑,要能让别人轻松的定位到代码在哪里

这是我参与了很多项目的感受。好的结构并不需要跟踪很多代码层次,才能发现其中的逻辑到底在哪里。相反坏的架构可能有很多层抽象,单个复杂度不高,但是一段逻辑你根本不知道在哪一层。当然也可能是逻辑本身就揉成一坨,也不容易找到想要的东西。

快速的发现相关逻辑,可以减少很多维护成本。

当然,有些架构有学习成本,但是掌握之后,能够满足这个要求,我觉得也可以算是好的架构。

2.2 Web开发,可扩展性大于可复用性

根据我一些有限的经验看来,在互联网领域,复用的需求,其实并不如产品需求变更来的迫切。水平分层很大的动机是复用,但是往往内部的复用程度比较有限。而面对需求的变化,水平分层基本上从上到下都进行修改。而合理的垂直拆分可以只修改一个地方,这也是所谓的开闭原则了。

Add a comment