同名知乎:少个分号 进入迭代的技术方案可以类比为瀑布模型中的详细设计,其目的是为了让迭代中的具体开发工作顺利进行。 本文,整理了一些日常项目上进入迭代前的技术方案输出物。 迭代技术方案的逻辑迭代技术方案和规划类的技术方案不同,为了让迭代交付更顺利,它有一些更具体的要求。
挑选一些模型承载设计编程的本质是对业务形式化,相比直接使用非形式化的文档,使用形式化的模型承载技术方案可以精确地完成这一转换。 参考以往的团队实践,一般包含如下内容,并找了一些模型承载其实现:
根据这些输出物的特点我们会发现,技术方案主要做一些定义,这样团队成员拿到后可以顺利并行工作,然后再集成。 领域模型 PlantUML我问过很多人一个问题:什么是领域模型?大家的回答模棱两可,甚至有些会非常玄。 根据逻辑指导实践的原则,我对领域模型的定义为:
UML 非常适合表达领域模型,而在众多 UML 工具中, PlantUML 非常适合作为迭代技术方案的设计工具。
在很多时候有必要将 UML 的用途拆分开,在战略设计中,我们不会精细到字段,而是更关注模型和模型的关系。 在迭代技术方案中(战术设计)我们更关注字段、属性等信息,所以这两种模型是不同的。 在迭代技术方案中,我们对领域模型图的产出要求有:
下面是一个 PlantUML 版本领域模型的例子。 代码: @startuml 'https:///class-diagram'
class User <<Aggregate Root>> class UserRole <<Entity>>
enum UserOrigin { 用户来源 -- ADMIN_ADDED 管理员添加 SELF_REGISTERED 自助注册 }
enum Role { 角色 -- ADMIN 管理员 MERCHANT 商户 }
class User { 用户 -- String id 用户ID String name 用户名 UserOrigin origin 用户来源 List<UserRole> roles 用户角色 }
class UserRole { 用户角色 -- String id ID Role role 角色 }
User '1' *-- '*' UserRole
@enduml 渲染图: 数据库模型 SQL如果有了领域模型图来表达实体之间的关系,就不需要数据库库模型来承担这部分职责。 在技术方案中,只体现单表的 DDL 即可。 我们可以通过一些约定让领域模型和数据库模型之间的联系更清晰。
注:以上只是一种约定,根据实际项目取舍和选择。 这样在技术方案中不再需要传统的 E-R 图了,直接输出可以使用 DDL 即可。 DDL 输出要求:
由于没有必要提前进行性能优化考虑,可以在后期补充索引定义。 下面是一份 DDL 例子:
API 模型 OpenAPI设计态的 API 可以使用 Swagger 的 OpenAPI 格式描述,这样可以用来生成 Controller 等样板代码。 OpenAPI 输出要求:PATH 路径、描述和 HTTP Method,请求体、返回体、错误码可能在技术方案阶段很难罗列完所有的字段,可以在实现时参考领域模型的字段风格实现,可以不用做过多的设计。 API 模型在方案设计中主要为了决定服务端提供多少个用例,把用例描述清楚就能把握 API 设计的基线要求。 下面是一份 OpenAPI 例子。 代码: openapi: 3.0.3 info: title: 用户 version: '1' paths: /v1/users: post: summary: 添加用户 get: summary: 查询用户 渲染图: 流程模型 Sequence描述关键流程在技术方案中不是完全必须的,因为有些场景下流程并不难以理解。 流程模型推荐使用时序图,时序图和流程图的差异在于精确性,流程图的缺点是颗粒度难以精确把握。 所以时序图的要求有:
下面是一份时序图的例子。 代码:
渲染图: 文档工具 Markdown 等部分技术方案不能使用上述的模型来描述,或者需要补充一些描述性说明。 我们可以使用标记语言来作为文档工具和输出物。 因为尽量需要放到版本管理中管理设计文档,可以考虑使用 Markdown 等标记语言来写作,可以在维护成本较低的情况下也能获得不错的排版效果。 除了 Markdown 之外还有一些不错的工具:
这两个标记语言带来了更多特性当然也变得更加复杂。 关于代码生成器使用文本格式、形式化模式表达技术方案的好处之一就是可以应用于后续的代码生成器上来。 虽然代码生成器的潮流早已经过去,但是它还是有很多方便之处。
#1 虽然在 AI 编程工具的加持下已经聊胜于无,但是 #2 带来的隐形福利则非常有益。 由于 AI 生成的内容具有不确定性和随机性,通过代码生成器作为脚手架非常适合迭代前期的准备工作,即使它不能很完美的解决所有问题,但是能解决 80% 的重复代码生成。 代码生成器另外一个问题是如何保持更新? 一方面在使用代码生成器之前,我们就不要对生成的代码有自动更新的期待,它只是做好初始化的工作就好了。(尤其是所谓整洁架构+DDD+微服务的项目,一套 CRUD 需要初始化几十个文件,没有代码生成器效率非常低)。 另一方面,也可以在架构上做一些牺牲,将模型代码和逻辑代码分离。
关于完成态的活文档在软件工程中理解设计态和完成态的文档分离的过程,是架构师和自己和解的过程。 我们必须要承认,完美和代码映射的文档是不存在的,即使有也需要巨大的成本去维护。在一线工作过的程序员都应该能理解这个观点,除非是“十指不沾阳春水”的领导。 在迭代前的设计文档是为了表达、评审和传递技术方案、设计意图。 一旦开发完成,迭代前的文档基本上就没有用了。这是 Martin Flower 一派的论调常常反对文档的由来之一,不过这是从一个极端走向另外一个极端。 西里尔·马特雷尔在《活文档:与代码共同演进》一书中提出,要从代码中提取出文档,并称其为“活文档”。 软件工程虽然经常被类比为建筑,但是软件更像是写作工程,软件是由几十上百人一起编写的庞大系列图书。 完成的代码本身就是文档,而我们需要的文档是从这部巨著中提取出来的部分实现模型,用来帮助人们理解整个系统。 所以我们的活文档其实就是讲解如何将代码再次转换为模型,而这些过程都可以自动生成。
对活文档进一步理解是:IT 系统对业务人员透明化。 例如,对于一个财务系统来说,可以将计算公式、业务规则、枚举值、参数表都提取出来,除了 Java 代码无法展示出来之外,其余内容都可以在界面上保留给运维、业务人员帮助他们理解整个系统。 总结迭代方案的本质还是模型,从模型进入迭代,实现代码后又生成模型帮助后续的开发者理解整个系统,如果需要进一步理解系统的细节,代码才是最准确的信息源。 做到这一点就必须对技术方案严肃对待,通过形式化的途径表达设计意图,做到用词精确,才能最大程度通过代码本身解释业务逻辑。 参考资料[1] Plant UML https://www./
[2] Open API 规范 https:///specification/ [3] Markdown https://www./ [4] Online DDL Operations https://dev./doc/refman/8.0/en/innodb-online-ddl-operations.html [5] https:/// [6] https://docutils./rst.html |
|