【软件架构方法论(9)】领域模型:如何通过领域模型,提高系统的可扩展性?

发布时间:2026/11/3 1:48:16
【软件架构方法论(9)】领域模型:如何通过领域模型,提高系统的可扩展性? 文章目录一、领域模型决定功能扩展的范围案例人事系统的历史记录问题案例电商系统的分类层次问题二、好的领域模型如何支持扩展将关系、角色抽象1、可扩展的任务依赖关系设计关系抽象2、可扩展的角色和分配设计角色抽象三、如何设计可扩展的领域模型1、考虑当前功能和潜在功能2、使用抽象和组合而不是硬编码3、迭代优化而不是一次到位四、总结领域模型是系统扩展性的基础核心观点领域模型就像房子的承重墙它决定了系统能扩展到哪里不能扩展到哪里。好的领域模型让系统容易扩展差的领域模型让系统难以扩展。因此建模时要考虑未来的功能需求而不仅仅是当前的功能需求。很多系统在初期运行良好但随着业务需求的变化扩展起来越来越困难。比如人事系统最初只能记录员工当前职位后来需要查看员工历史履历却发现数据库设计不支持电商系统最初只支持两级分类后来需要支持多级分类却发现模型设计不支持。这些问题的根源往往不在代码实现而在领域模型设计。一、领域模型决定功能扩展的范围领域模型是对业务世界的抽象任何抽象都意味着有意的省略。你抽象了什么系统就能支持什么你没抽象什么系统就很难支持什么。就像拍照和X光片的区别拍照只能看到表面X光片能看到内部结构。领域模型就是系统的X光片它决定了系统功能的骨骼结构。如果骨骼结构不支持某个功能即使表面代码写得再好也很难实现。案例人事系统的历史记录问题最初的人事系统领域模型很简单公司和员工是一对多的关系一个公司有多个员工员工的姓名、性别、地址、职位、部门、薪水直接作为员工的属性。这个模型支持查看员工当前信息这个功能完全没问题。数据库设计也很简单一个Company表一个Employee表Employee表通过外键关联Company表。但后来业务需求变了HR经理想要查看员工的完整履历包括在不同时间段的职位、部门、薪水变化。比如一个员工可能先做软件工程师后来升职为高级软件工程师再后来调岗到项目经理每次变化都要记录时间段。这时候问题就来了原来的模型只记录了当前信息没有记录历史信息。要支持新功能必须修改模型。如果只是修改应用层代码会发现根本改不动。因为数据库表结构不支持Employee表只有当前的职位、部门、薪水字段没有历史记录业务层的接口也不支持Employee类只有getJobTitle()方法没有getJobHistory()方法。必须重新设计领域模型升级后的模型把职位、“部门”、薪水从员工的属性关键点变成雇佣关系的属性而雇佣关系记录了时间段。这样一个员工可以有多条雇佣记录每条记录对应一个时间段开始时间、结束时间就能支持历史履历查询了。数据库设计需要增加一个Employment表记录employee_id、company_id、时间段、职位、部门、薪水。这样查询员工履历时只需要查询Employment表按时间段排序即可。这个案例说明领域模型决定了系统能支持哪些功能不能支持哪些功能。如果模型设计时没有考虑历史记录系统就很难支持历史查询功能。案例电商系统的分类层次问题电商系统最初的需求是支持两级分类大类和小类。比如电脑办公是大类笔记本是小类。领域模型设计成Category大类和Subcategory小类是两个独立的类Category包含多个Subcategory。数据库设计也很简单一个category表一个subcategory表subcategory表通过外键关联category表。这个模型支持两级分类完全没问题。但后来业务需求变了需要支持多级分类。比如美妆 男士专区 男士剃须用品 刀架/刀片这是四级分类。原来的模型就支持不了了因为Subcategory不能再包含子分类。要支持多级分类必须修改模型让Category可以递归包含自身一个Category可以有一个父Categorysuper_category也可以有多个子Category。这样分类层次就可以是1到N层灵活多了。数据库设计也需要修改只需要一个category表增加一个super_category_id字段外键关联category.id通过这个字段实现递归关系更进一步的如果还需要支持一个商品属于多个分类比如一本书既属于红色读物又属于非虚构文学还属于小说模型还需要再次升级Category和Commodity之间从一对多关系变成多对多关系。数据库设计需要增加一个commodity_category中间表记录commodity_id和category_id的对应关系。这个案例说明领域模型的设计要考虑未来可能的功能需求而不仅仅是当前的功能需求。如果只考虑当前需求模型可能会限制未来的扩展。二、好的领域模型如何支持扩展将关系、角色抽象好的领域模型能够在不修改核心结构的情况下支持新功能的添加。这就像房子的承重墙设计得好可以在不拆墙的情况下改变房间的布局。1、可扩展的任务依赖关系设计关系抽象在项目管理系统中最初只需要支持结束-开始关系一个任务必须等另一个任务结束后才能开始。比如洗锅任务结束后炒菜任务才能开始。如果模型设计成Task直接有一个preTask属性前置任务这个设计支持结束-开始关系没问题。接口可能是这样的Task::SetPreTask(Task pre_task)这个操作可以定义在Task类中。但如果未来需要支持其他关系呢比如开始-开始关系清洁地板开始后刷油漆就可以开始两个任务可以同时开始开始-结束关系哨兵上岗开始后哨兵下岗才能结束第二个任务必须等第一个任务开始后才能结束结束-结束关系批准整个设计结束后制定下一步计划才能结束两个任务必须同时结束如果模型只支持前置任务这种简单关系要支持这些复杂关系就必须修改模型Task类需要增加多个属性来记录不同类型的关系修改接口原来的Task::SetPreTask()接口不够用需要改成TaskUtility::SetTaskDependingRelation(Task task_a, Task task_b, TaskDependingRelation dr)而且这个操作不适合定义在Task类中修改数据库数据库Schema需要改变封装数据库Schema的代码如DAO也需要改变但如果模型设计成有一个任务关系类TaskRelationship它连接两个任务task_a和task_b并记录关系类型结束-开始、开始-开始、开始-结束、结束-结束那么要支持新关系只需要添加新的关系类型枚举值不需要修改核心结构。这样接口可以设计成TaskUtility::SetTaskDependingRelation(Task task_a, Task task_b, TaskDependingRelationType type)关系类型可以扩展但接口结构不需要改变。这个设计的关键在于把关系本身抽象成一个概念而不是把关系硬编码在任务中。这样关系类型就可以扩展而任务和关系之间的核心结构不需要改变。2、可扩展的角色和分配设计角色抽象在项目管理系统中不同企业对角色的定义可能不同有些企业角色很细项目经理、过程经理、质量经理等有些企业角色很粗就是项目成员。系统要支持这两种情况就需要角色定义可以扩展。如果模型设计成角色是固定的几个类项目经理、过程经理等要添加新角色就必须修改代码。但如果模型设计成有一个角色基类具体角色可以继承扩展那么要添加新角色只需要定义新的角色类不需要修改核心代码。更进一步如果系统不仅要支持把任务分配给个人还要支持把任务分配给团队或部门模型也需要扩展。如果模型设计成任务只能分配给个人Person要支持团队分配就必须修改模型Task类需要增加teamAssignment属性修改接口原来的Task::AssignTo(Person person)接口不够用需要增加Task::AssignToTeam(Team team)方法修改数据库需要增加team_assignment相关字段但如果模型设计成任务分配给Party当事人而Party可以是个人Individual或团队Team那么要支持团队分配只需要添加团队类Team继承Party任务分配的核心逻辑不需要改变因为都是分配给Party接口可以设计成Task::AssignTo(Party party)无论是个人还是团队都用同一个接口这样分配对象可以扩展但分配逻辑不需要改变。这就是使用抽象和继承的好处。这个设计的关键在于使用抽象和继承让具体类型可以扩展而核心逻辑不需要改变。三、如何设计可扩展的领域模型设计可扩展的领域模型关键在于功能决定如何建模模型决定功能扩展。1、考虑当前功能和潜在功能建模时不仅要考虑当前需要的功能还要考虑未来可能需要的功能。这不是要你预测所有未来需求而是要你识别那些很可能出现的需求。比如在人事系统中查看历史履历是一个很可能出现的需求因为员工会升职、调岗、离职、再入职。在电商系统中多级分类和商品多分类也是很可能出现的需求因为业务会发展。识别这些很可能出现的需求在建模时提前考虑可以让模型更容易扩展。就像盖房子时即使现在只住一层但如果很可能要加层地基就要打深一点。2、使用抽象和组合而不是硬编码好的领域模型使用抽象和组合来组织概念而不是把具体关系硬编码在类中。比如任务依赖关系不要设计成Task有一个preTask属性而要设计成Task和Task通过TaskRelationship连接。这样关系类型可以扩展关系属性比如延迟时间也可以扩展。再比如资源分配不要设计成Task分配给Person而要设计成Task分配给PartyParty可以是Person或Team。这样分配对象可以扩展分配逻辑不需要改变。3、迭代优化而不是一次到位领域模型不是一次设计就能完美的而是随着对业务理解的深入不断迭代优化的。就像项目管理系统的案例最初的理解可能是项目和任务是一对多后来发现多个项目可以共享任务模型就需要调整。最初可能只考虑任务分配给个人后来发现任务可能分配给团队模型就需要扩展。这个过程是正常的也是必要的。关键是每次迭代时要考虑扩展性而不是只考虑当前需求。如果每次迭代都只考虑当前需求模型会越来越难以扩展。四、总结领域模型是系统扩展性的基础领域模型决定了系统能扩展到哪里不能扩展到哪里。就像房子的承重墙决定了能盖多高能改多大一样。因此设计领域模型时要内外兼修既要满足当前功能需求也要考虑未来扩展需求。就像《高效能人士的七个习惯》中说的由内而外的思维好的软件扩展性需要由内而外的领域模型设计。更重要的是领域模型的扩展性不是靠预测所有未来需求来实现的而是靠识别很可能出现的需求和使用抽象和组合来实现的。这样即使未来需求超出预期模型也能相对容易地调整和扩展。最终一个好的领域模型应该让系统在支持新功能时只需要添加代码而不需要修改核心代码。这种扩展性是系统长期维护和演化的基础。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询