专注于 JetBrains IDEA 全家桶,永久激活,教程
持续更新 PyCharm,IDEA,WebStorm,PhpStorm,DataGrip,RubyMine,CLion,AppCode 永久激活教程

复杂应用系统设计与建模

特别说明:本篇文章是我们开发小组的一位北京大学计算机博士大哥,分享到我们组内部的,在此感谢大哥!

写在前头

作者所撰系列文章内容主要聚焦在:基础学科与计算机科学的交叉领域,

以及应用系统的设计与建模方法论两方面内容。笔者在撰文方面的驱动力,借鉴

了敏捷开发的方法论。即,只要笔者捕捉到有价值的经验或思想,在我的思想涌

动,灵感稍纵即逝、兔起鹘落的瞬间,我就会迅速操作键盘将其记录在案,并及

时分享给读者朋友。今后,我也会根据读者的反馈及自己新的认识,持续完善我

的文章。最终使之成为体系上较为完整的、逻辑上较为严谨的、内容上较为有参

考价值的系列文章,或是一本书。与此同时,我也能够畅享在知识传递过程中的

兴奋与愉悦。

笔者会尽力将每篇文章的内容控制在 3000 文字以内,使读者可以利用碎片

时间快速浏览全文。

谁可以读该文

笔者将在该文介绍复杂应用系统的设计与建模方法。文中,我会尽量避免使

用专业性过强的技术术语,旨在迎合更多的读者群体。建议预期的读者可以为,

应用软件设计开发人员、产品经理、项目经理、软件测试工程师及业务专家。

我们开始吧

正如马丁福勒所述,用户的业务逻辑是最没有逻辑的逻辑。没错,不像有着

严格定义的数学函数,我们可以借助强大的微积分工具分析其形态及性质。然而,

我们的应用系统中的业务规则往往是离散的,虽基于逻辑学,但远比纯粹的逻辑

学复杂,起码逻辑学有其完备的推理公式,我们却不能以推理的方式证明业务处

理逻辑是正确的,抑或是错误的。当然,在人工智能领域,可以通过大量的数据

统计,形成或逼近某些数学模型,然后即可借助数学工具对模型进行研究,但这

不是本文讨论的范畴。

应用系统的技术复杂度与业务复杂度相互交织,犹如一团乱麻,让我们剪不

断,理还乱。除此之外,业务团队及技术团队的 KPI 考核指标无疑更是雪上加

霜。然而,技术上的复杂度与业务复杂度相比,前者所占甚少。毕竟,在整个软件生命周期中,技术是相对稳定的,我们的大部分时间是与复杂多变的业务逻辑

打交道。

或许,我们可以从《数据结构》这门课程受到启发,定义良好的数据结构,

可以简化其上的运算。同样,恰如其分的应用架构与数据模型可以使应用系统的

各业务模块职责更加分明、规则更加清晰,更方便后期的维护及扩展,使得应用

朝着预期目标持续快速演进。遗憾的是,这种基于数据模型、自底向上的设计开

发模式极其容易导致开发人员过早的陷于技术细节,而忽略业务的本质,用生硬

的技术手段解决复杂多变的业务问题。该设计开发模式还会削弱面向对象语言的

特性,对象之间不能直接建立关联,更不能很好的支持多态。

不可否认,这种自底向上的设计开发模式曾经发挥过重大的作用。甚至,目

前的绝大部分应用系统的设计开发还在沿用该模式。诚然,对于业务逻辑相对简

单的应用系统,我们可以采用自底向上的开发模式,以便减少前期的沟通、学习

及开发成本。然而,所谓的“简单”只不过是我们主观上的定义或判断而已。退

一步讲,即便目前的业务逻辑的确简单,我们也不能确保今后的业务逻辑还会是

一直保持简单。

那么,有没有更好的系统设计与建模方法论呢?答案是,一定有的。此处,

给读者朋友留个悬念,笔者将在后文的系统水平设计阶段介绍该方法论,在此之

前,笔者有意只字不提,虽然它是该文的主旨。抱歉!该文的前奏略长,也许,

“单刀直入”是较佳的表述方式,但我还是选择了前者。

在应用系统的顶层设计阶段,也可以称其为架构设计或战略设计阶段,我们

须有高屋建瓴的意识,要站在 FFC(北京财富金融中心)的至高层鸟瞰“京城

绚丽多姿的夜景”,切忌过早地陷入实现细节。否则,我们将寸步难行。此阶段,

我们一般采用垂直设计理念,即根据业务类型对系统进行垂直划分,将系统划分

为若干模块(或子系统),确定各模块的边界及职责,同时明确各模块之间的协

作方式。如果是单体应用,各业务模块虽然在同一进程空间,但其逻辑上是分离

的,这样可方便后期的维护,也容易将其重构为分布式微服务。在单体应用中,

如果采用 OSGi 热发布技术,那么,各业务模块之间不仅是在逻辑上隔离的,而

且在物理上也是隔离的,需要明确的是,此处的物理隔离级别是类加载器级别的,

各业务模块仍位于同一进程空间。当然,根据实际需要,各业务模块也可以是分布式微服务应用,这样,各业务模块的隔离级别是进程级的。在生产环境,分布

式微服务一般为主机或容器级别的隔离。顶层设计阶段也是一系列属性与决策的

集合。

接下来,我们讨论应用系统的高层设计。在高层阶段,一般会采用水平设计

方法。水平设计是开发人员最熟悉最“擅长”的设计模式,即对各业务模块水平分

层。正如我们日常使用的计算机(硬件层、OS 层、应用层),OSI 网络通信 7

层参考模型,以及既成事实标准的 TCP/IP 协议,均采用了分层设计的思想。分

层是一种分而治之的思想,使得关注点分离,简化了各层的问题空间,底层对上

层屏蔽细节,只允许上层根据契约依次访问下层。常见的业务应用系统一般分为

展现层、控制层、服务层(或业务逻辑层)以及数据访问层。此处,我们姑且不

讨论被丢掉的两个接口适配层,有兴趣的读者可参阅笔者另一篇文章—某中间服

务应用架构重构方案。

请回顾一下,我们在服务层所使用的领域对象封装了什么数据?我们在服务

层做了哪些事情?在笔者常见的应用系统中,所谓的“领域对象”被定义为“数据

盒子”,只封装了对象的属性,而忽略了对象的行为。比如,“人”这个对象,里

面只封装性别、年龄等属性,没有吃饭、睡觉等行为,所具备的“行为”只不过是

get(获取属性)及 set(为属性赋值)。业界称这种对象为“贫血对象”,我们

不必互相指责或推卸责任。法不责众!因为在国内,“健康对象”实属少见。所有

的“贫血对象”堆积在一起,就形成了“贫血领域模型”。我们所丢掉的对象行为—

业务规则,本应该内聚在其依赖性最强的对象里。恰恰相反,这些对象行为却分

散在各业务模块的服务层中。“贫血对象”,会导致在服务层存在大量对象的 get、

set“行为”,对象中的数据结构被暴露在服务层,如果这些“行为”有访问顺序限

制,服务层必须所熟知,否则后果不堪设想。难怪服务层如此的“臃肿”,并且“臃

肿”现象会日趋严重。

理想情况下,服务层应该是很轻、很薄的一层。与对象的数据或属性一样,

对象的行为(业务规则)应封装在对应的对象中,从而使得数据以及基于数据之

上的操作更加内聚,为服务层提供高内聚的 API。退一步,对象行为哪怕是内聚

在支撑领域模型内也要比散落在服务层好很多。我们可能会把责任归咎于 ORM

(对象关系映射)框架,因为“贫血对象”确实深受其害。我想,读者一定与我有共鸣之处,原因不再详述。当然,基于数据结构的自底向上的设计开发模式也难

逃其咎,这一点已在上文表述。

如果说时下火热的中台应用的初衷是拆掉“烟囱”,实现企业级能力复用;

那么,“健康的领域模型”将会使得业务功能更加内聚,最高程度做到应用系统级

的功能复用,是企业核心业务价值的载体。异曲同工之妙啊!这就是上文留给读

者朋友的悬念—领域驱动设计建模方法论,但愿您能猜到。领域驱动设计建模方

法论,是一种自顶向下的设计方法,可以弥补自底向上设计模式的不足,适合复

杂应用系统的设计开发。实施领域驱动设计建模方法,不仅会改变软件设计开发

人员思维方式,还会改变团队成员之间、团队之间的沟通方式,甚至会改变团队

的组织架构及团队文化。

此外,领域驱动设计是面向对象编程范式的进阶,设计开发人员不仅要深入

掌握业务领域知识,还需有扎实深厚的面向对象设计与面向对象编程的功底。领

域驱动设计不适合采用函数式编程范式实现,函数式编程范式提倡对象的数据与

行为分离,从某种程度上讲,与领域驱动设计背道而驰。

至此,该文讨论了复杂应用系统在顶层设计及高层设计阶段常用的设计建模

方法。还讨论了在高层设计阶段,基于数据结构自底向上设计方法论的不足,并

由此引申出领域设计建模方法论。如有时间和精力,我们将在续文中深入探讨领

域设计建模方法论。谢谢!

文章永久链接:https://tech.souyunku.com/27671

未经允许不得转载:搜云库技术团队 » 复杂应用系统设计与建模

JetBrains 全家桶,激活、破解、教程

提供 JetBrains 全家桶激活码、注册码、破解补丁下载及详细激活教程,支持 IntelliJ IDEA、PyCharm、WebStorm 等工具的永久激活。无论是破解教程,还是最新激活码,均可免费获得,帮助开发者解决常见激活问题,确保轻松破解并快速使用 JetBrains 软件。获取免费的破解补丁和激活码,快速解决激活难题,全面覆盖 2024/2025 版本!

联系我们联系我们