如此重要但是经常被忽视的代码架构!

软件开发的生命周期,大致都是一样的流程:

  • 需求分析,产出概念模型
  • 概要设计,包括系统边界设计、内部架构设计、设计决策
  • 详细设计,包括代码架构,业务逻辑实现
  • 开发代码
  • 单元测试、连通测试
  • 部署上线
  • 系统运维

这样的流程,开发代码这个步骤,其实是个分界点,它实现了前面的设计,同时开发好的代码会最终的进行测试和运行。

正常情况下,概念模型、边界交互设计、数据流设计、系统内部架构设计、设计决策等等,都会产出成文档,供各方阅读和实施,然而,经常情况下大家却忽视了,如何在代码架构中表达这些设计意图。经常会看到一些系统的设计非常的清晰和高大上,但是去阅读代码的时候,却发现一团乱麻。如果涉及系统的交接、文档过时,就会发现这又变成了一个糟糕的系统。

其实在代码中如果承载了这些意图,岂不是最好的体现。

代码架构在规范化模型架构中的位置

normalize_model_architecture
对应到系统实现过程中,对于需求分析的产出,会得到领域模型,对于边界模型的设计会产出系统上下文交互、接口设计,然而由于内部模型和代码模型因为限于系统的内部,只要它实现了边界模型,就不用关系怎么实现,最后导致了这部分关注不多,导致混乱。

架构明显的编程风格

无论怎么努力,模型设计和代码实现之间,会存在差异,只不过是多和少的差别。

模型的设计产出的是文档,但是文档只能表达主模型的一部分内容或者投影,无法全部表达,文档同时也存在维护代价过高,从而导致容易过时的问题。

采用架构明显的编码风格进行编程就是在源代码中嵌入关于系统架构模型的线索,一种设计意图。也就是说,在程序可以运行这样一个最低要求之上,还遵循了模型嵌入代码原理。

这里目的是为了嵌入模型,目的也是能否在代码中表达领域模型?能否表达设计模型呢?

对于领域模型,表达设计意图的标准方法就是,把对领域中类型和关系的理解,映射到程序中的类结构。

而在代码中表达模块模块试图类型和运行时视图类型,主要是通过在模块的命名中,加入通用的模式命名来实现的,比如:

  • *Manager
  • *Service
  • *Factory
  • *Filter
  • *Builder
  • *Agent
  • *Proxy
  • *Repository
  • *StatusManager
  • *RuleEngine
  • *Facade

可以看到,这些词语来源于设计模式、分析模式、通用包名次,通过这些名次的约定,再和团队成员约定一个通用完善的代码架构,即可通过代码表达设计意图。

一个通用完善的代码架构

大量的书籍资料,都会提供概念模型、系统交互设计等设计,然而对于代码架构,并没有一个很规范通用的标准,这也导致了大家写出来的代码各种各样,包命名和依赖混乱不堪,代码简直无法阅读。

而组织良好的包划分、关系依赖设计,是让代码变得能阅读,并且能表达设计意图的第一步。

a_very_good_package_architectrue

这个模型每个部分的说明,在图中都有注释。

而主要的一个划分的方法,就是技术实现和业务逻辑的区别。

业务逻辑是我们提供的系统的实现目标,但是这也是很容易变化的部分,如果能封装到一个模块,隔离变化,交给对业务理解透彻的同学实现,会有很好的效果。

而对外提供接口、代码粘合、保存数据到DB、调用第三方资源、实现dto/model/entiry的转换,这些代码因为不涉及业务逻辑,谁都能写,因为不包含业务逻辑,那么变化的频率也会降低。

business的输入,是来自manager获取或者整合好的业务对象,business通过各种逻辑处理和转换,给出业务结果,然后由manager对外进行分发。

 

文中引用资源:

  • 架构明显的编码风格,来自书籍《恰如其分的软件架构》
  • 代码架构图的划分,是对infoq的《架构漫谈》作者kevin提供的文章《从架构的角度看如何写好代码》中架构的改进和注释

本文地址:http://www.crazyant.net/1973.html



发表评论

电子邮件地址不会被公开。