领域驱动设计-软件核心复杂性应对之道(11)_应用分析模式本章的核心观点是:分析模式是前人已证明有效的、可复用的概念集合,它们为特定领域中常见的问题提供了经过验证的建模起点。 应用分析模式可以避免从零开始的探索,大幅减少试错的时间,并能从一开始就提供一个具有表达力和易实现的模型框架。核心梳理1. 分析模式的定义与价值分析模式并非现成的代码或“菜谱”,而是从实践经验中提炼出的概念集合。它们是在特定业务领域(如会计、金融、库存管理)中反复出现的、被证明有用的建模结构。使用分析模式的价值在于:借用前人的经验:避免重复发明轮子和犯同样的错误,减少代价高昂的试错过程。提供良好的起点:可以基于一个已证明有效的概念框架开始工作,而不是从空白画布里臆想。然后与领域专家合作,精化这个框架。揭示潜在问题:分析模式中通常包含了对实现后果的讨论(如性能、维护复杂性),这能帮助你预见并避免问题。2. 分析模式与DDD的关系在这本书的上下文中,分析模式是知识消化过程的有力输入。它应该被融入团队的知识消化和重构过程中,形成更深层的理解,并促进开发。团队不能盲目照搬模式,而应将其作为思考的催化剂,与领域专家一起调整。3. 分析模式的两个示例展示本章通过两个深入示例,展示了如何将Fowler的《分析模式》一书中的模式应用于实际场景,使原本复杂且被隐藏的过程显式化。* 示例1:账户的利息计算* 问题:初始模型将利息计算逻辑隐藏在“利息计算器”中,导致修改复杂、测试困难。* 应用:开发人员借鉴了《分析模式》中的“账户”模型,引入了"Account"、"Entry"、"Transaction"等显式概念,将利息和付款建模为"Entry"的子类("Accrual"和"Payment")。* 结果:模型更清晰地表达了会计概念,"Interest Calculator"现在只负责创建"Entry"对象,计算逻辑变得简单、可测试。整个夜间批处理也变得更清晰。* 示例2:对夜间批处理程序的深入理解* 问题:夜间批处理脚本中隐藏着复杂的过账规则(如是否需要记录收入所得税),这些规则混杂在脚本逻辑中,难以理解和维护。* 应用:开发人员借鉴了“过账规则”模式,引入了"Posting Rule"对象,将过账规则(何时、向哪个分类账过账)显式化。"Asset"对象根据其性质(利息或手续费)与对应的"Posting Rule"关联。* 结果:复杂的过账逻辑从脚本中转移到了领域对象中,脚本变得非常简单,只负责遍历和调用。规则被显式化,修改起来也更容易。4. 应用分析模式的典型过程遇到问题:发现代码中有难以解释、难以修改的复杂逻辑。阅读模式:开发人员阅读相关的分析模式文献,了解已验证的概念框架。提出假设:基于模式,提出一个初步的模型修改方案。与专家讨论:与领域专家一起走查这个新模型,验证其概念是否准确,是否反映了专家思考问题的方式。这是一个双向学习的过程,可能需要反复调整。重构实现:基于讨论后的模型,进行代码重构和测试。反思“让路”:在应用模式时,可能会遇到实现上的障碍(如ORM对多态性的支持限制),需要做出适当的折中,但不要放弃MODEL-DRIVEN DESIGN的大方向。5. 使用分析模式的注意事项模式不是现成方案:它不可以直接照搬。你需要根据具体情况进行调整,变化可能很大。保持概念一致:如果使用了模式中的术语(如"Posting Rule"),就必须保持其基本概念不变,避免在后续演变中改变其定义,否则会破坏通用语言。避免“大而全”:不要试图一次应用整个宏大的分析框架。应聚焦于当前问题最复杂的部分,逐步应用模式。"精炼"(第15章)在此处至关重要。项目使用时的指导原则基于以上核心思想,在项目中“应用分析模式”时,可以遵循以下原则:1. 将其作为“思考催化剂”,而非“复制粘贴”原则:分析模式是一个有价值的工具,用来激发思考,而不是一个可以不经修改就可直接套用的配方。行动:先有疑问:遇到难以处理的复杂性时,先问自己:“这个领域有没有公认的概念模型或模式?”而不是“我该怎么把这几百行代码改得更好?”查阅文献:保持阅读习惯,了解你所在领域的一些知名的分析模式(如会计、金融、物流、库存、医疗等)。头脑风暴加精化:在阅读模式后,带着模式中的概念去与领域专家进行头脑风暴。模式提供了“骨架”,专家和团队的工作是“填充血肉”,使之符合具体的业务场景。2. 将“分析模式”作为“通用语言”的扩展库原则:当团队决定采纳一个分析模式时,该模式中的核心术语(如"Account"、"Entry"、"Posting Rule")应该被正式纳入团队的通用语言中。行动:命名一致:在代码、文档、白板上,统一使用模式中的术语。概念定义:确保每个术语都有清晰、无歧义的定义,并且团队所有成员(包括领域专家)都理解并认同这个定义。避免术语膨胀:只采纳与当前问题最相关的模式概念,不要为了“架构优雅”而引入所有概念。3. 关注模式的“实现后果”和“折中”原则:一个好的模式不仅说明“如何做”,更重要的是说明做了之后的后果和折中选择(如性能问题、维护成本、实现的局限性)。建模者在决定是否使用时,必须评估这些后果。行动:阅读完整描述:不要只看了模式图(如UML)就动手,要阅读模式相关的完整描述,特别是关于“实现后果”和“策略选择”的部分。评估技术环境:在决定采用前,与团队一起评估当前的技术栈(如ORM、数据库、框架)是否能自然地支撑这个模式,或将面临哪些妥协。接受并管理折中:在例2中,为了数据存储的方便,不得不创建多个"Entry"子类("FeeEntry"、"InterestEntry"等)。这就是要接受的折中。关键是要理解为什么要这么做,并在文档中记录下来,以便指导未来的修改。4. 优先在核心域应用模式,避免过早泛化原则:分析模式最主要的价值应体现在处理最复杂、最重要的业务逻辑上,也就是核心域上。不要在非核心的、简单的子域上也套用复杂的模式,这会造成过度工程。行动:识别核心域:使用战略精炼的原则,找到哪个子域对你的业务成功至关重要且最复杂。投入模式:将最优秀的开发人员和最多的建模精力投入到核心域的建模上,如果这里有一个合适的分析模式,那么投入产出比是最高的。支撑子域用简单方案:对于支撑性、通用的子域(如报表、日志、简单的CRUD),并不需要应用分析模式。使用TRANSCRIPTION SCRIPT或简单的LAYERED ARCHITECTURE即可。总结: 在项目中“应用分析模式”的核心是巧借前人的智慧。其指导原则是:将模式作为激发灵感的起点,而非照抄的菜谱;用模式的语言来丰富团队通用语言;关注模式的实现后果和折中,结合技术环境做出决策;并聚焦于最核心、最复杂的领域来最大化模式的价值。