软件建模16:四色与领域无关组件
租赁 A1 原定在 11 点结束,客户申请延到 13 点,但同一设备 E1 已在 12 点承诺给 A2。若先生成新的租赁文档,再检查设备占用,延期虽然被拒绝,文档却可能显示 13 点。换一台相机也不能只改设备编号:候选设备可能已被占用,或者其实是一台投影仪。 这些变化需要同时考虑参与方、资源、活动和文档。领域无关组件可以提供候选关系,但租赁的冲突条件与更新顺序仍须另外定义。本篇用两个实际候选对照,检查延期和替换失败以后保留了哪些状态。 从原书选择需要的部分 出版社第 5 章包括项目活动、会计及文档管理。活动部分区分请求与活动,文档部分区分模板、具体文档及相关活动。这些分组是知识复用入口,并非可以直接调用的租赁库。出版社原章,§5.1、§5.3,印刷页154–181 本例只选活动和文档的部分关系:参与方提出租赁约定,约定引用具体资源;成功修改约定时,生成新文档修订并保留旧版。没有复制原书全部组件,也没有实现会计管理。代码中的 RentalService、资源冲突算法和模板选择政策都是本系列自己的教学适配。 “领域无关”在这里表示一种关系组织可迁移到多个业务。它不意味着每个领域都能...
软件建模15:四种 archetype
设备 E1 和 E2 都属于 CAM-A 型号,但租出 E1 不能让 E2 一起变成已出租。P1 同时办理租赁和验收,结束经办任职也不能删除这个人的验收职责。如果只按几个相似名词建立类,实物、共享描述、业务角色与一次租赁约定很容易混在一起。 四色建模用四种 archetype 提醒建模者检查这些区别。本篇把它们作为租赁模型的候选分类,用真实对象操作检验身份和历史是否丢失。颜色不参与程序判断,也不替模型选择数据库表、聚合或不可变类型。 四种语义如何进入租赁案例 四种 archetype 通常以粉色 Moment-Interval、黄色 Role、蓝色 Description、绿色 Party-Place-Thing 表示。出版社第 5 章的实例提供了核对入口:项目及活动请求是粉色,承担职责的角色是黄色,请求池是绿色;账户示例还区分粉色汇率事实与蓝色货币对描述。出版社原章,§5.1.1、§5.2.1,印刷页157、167 应用到本系列时,分类需要回答具体问题。Moment-Interval 关注一次值得保留的业务发生或期间;Role 表达对象在某种关系中的职责;Descriptio...
软件建模14:计划、资源与承诺
客户计划在十点至十二点租两台相机。系统能够接受这项请求,可能因为同型号还有两台容量,也可能因为已经选定设备 E1、E2。这两种确认都没有证明相机已经交付;交付时只拿走一台,也不能把原来承诺的两台悄悄改成一台。 账户、分录与费用 区分了费用、收款和记账。本篇继续使用合成租赁案例,把计划租期、资源承诺和实际执行分开,并运行两种资源分配候选。实验仍采用 UTC 半开区间、保留请求回执和取消不恢复旧请求的基线规则。 同一个时间段为什么要出现三次 计划动作记录意图:希望什么类型的设备、多少台、何时使用。资源承诺记录系统已经接受的占用范围。实际动作记录显式登记的执行情况,包括实际数量和实际时段。三个对象可能恰好数值相同,也可能不同;相同值不会使它们成为同一个事实。 如果把计划直接当成占用,客户试填一张表就可能阻挡其他预订;如果确认后直接生成实际动作,未到场的客户会被当成已经领取设备。若只保留最后修改过的数量,则无法区分原来只承诺一台和承诺两台却只交付一台。这个区别决定取消、补交付和对账的后续规则。 本篇的原始模式线索来自 Fowler 站点托管、由 Pierre De Swert 整理的《...
软件建模13:账户、分录与费用
一笔设备租赁费用先被登记为一百二十元,核对后应为一百元。客户支付一百元,随后又获得二十五元折扣,最后收到二十五元退款。如果订单只有一个可修改的 amount 字段,最终的七十五元无法解释这些变化:最初登记了什么、客户付了多少、折扣是否已经退成现金,都要另找记录。 有效时间与记录时间 保留了目录历史;费用记录还需要解释金额变化之间的关系。本篇使用合成租赁事实构造一个教学账本,检查费用、收款、折扣、退款和冲正。所有金额和处理规则都是实验输入,不代表真实支付,也不构成财务合规方案。 一笔费用涉及四种对象 费用事实表示“登记了一项应收一百元的费用”,它带有事实编号、币种、金额和发生时刻。账户提供累计变化的分类视角,分录记录某个账户的一次有符号变化,会计事务把相互对应的分录连接起来。四种对象的身份不同,不能都用订单编号替代。 本文引用 Martin Fowler 于2005年1月22日发布的两篇草稿。Accounting Entry 明确说明:原书把 Account 和 Entry 放在同一个模式中,网页草稿将它们分开讨论。因此这里的分篇术语来自2005年草稿,不把网页组织方式写成原书章...
软件建模12:有效时间与记录时间
二月二十日,一项设备日租服务在目录中显示一百元。三月十五日收到更正:二月十五日起应为八十元。四月五日又收到第二次更正,同一生效日的价格实际应为九十元。查询“二月二十日多少钱”时,一百、八十和九十都能在记录里找到,区别在于查询采用哪个时点掌握的信息。 分类、规格与类型对象 让旧合同固定到签约规格。本篇继续检查目录历史:既要按当前认识查看过去价格,也要重现某次报价时能看到的目录。所有日期、价格和更正均为合成教学材料;目录追溯更正不自动改变已签合同,更没有自动退款的含义。 一次查询需要两个时间参数 有效时间回答某个事实在哪段业务时间适用,记录时间回答系统从什么时候开始按这份记录理解事实。二月十五日是更正价格的有效起点,三月十五日是本系统收到并录入第一次更正的时点。把后者直接写成二月十五日,会丢掉信息迟到一个月这一事实。 Martin Fowler 在2021年4月7日发表的《Bitemporal History》中使用 actual history 与 record history 区分这两个维度,并讨论追溯更新使历史认识发生变化的情况。本篇把它们对应为有效时间与记录时间;实际价格样...
软件建模11:分类、规格与类型对象
租赁目录增加一种防水相机,库存系统是否需要增加一个程序子类?同一型号买了两台,防水能力可以共享描述,但它们不能共享设备编号和归还状态。目录调整租金以后,已经签下的合同是否也跟着涨价?这几个问题都涉及“类型”,实际需要分别检查分类、规格描述和一次具体服务。 时间、数量与身份 已经区分设备身份与记录修订。本篇继续使用设备租赁教学场景,为实物增加型号描述,为一次服务增加规格引用;实验检验运行期增加类型以及规格变更对旧合同的影响。它是独立的 Python 模型,没有把目录、服务或合同功能加入 Java 预留基线。 一台设备与一种型号 E1 和 E2 是两台实物,都属于 CAM-A 型号。设备编号、当前位置和当前使用状态可以不同;型号所描述的公共能力则相同。若在每台设备上复制整份型号说明,修正规格时需要找到全部副本,还要区分哪些字段实际上记录的是单台实物的检验结果。 另一种方案是给每种型号建立一个子类,例如 CamA、CamB。当差别只是名称、功能清单等目录数据时,型号越多,类层次也会不断扩展。目录新增一个值还需要修改程序,业务配置与程序发布之间因此形成了依赖。 Johnson 与 Wo...
软件建模10:Quantity、Measurement 与 Observation
设备 E1 的交接记录收到三个输入:“累计运行 60 分钟”“外观有划痕”“传感器故障,未取得读数”。若都塞进一个 value 字段,调用方必须猜测 60 的单位、划痕属于哪种检查,以及空值能否当成零。即使每行都有时间,数值之间的比较也未必有意义。 分析模式的复用 已用简化记录验证历史查询的用途。本篇将记录内容收紧为量值、现象类型与观测事实,实际拒绝错误单位、错误类别和没有说明的缺测。代码仍是独立教学增量,尚未进入 Java 租赁核心。 数字必须带着单位 Quantity 表示一个数额及其单位。1999 年第三章 UML 补充材料的图 3.2 使用这两个部分,图 3.6 进一步把 Measurement 与被观察对象、现象类型联系起来。这些是本篇概念来源,设备、分钟换算及校验代码是教学改造。第三章补充材料,图 3.2、3.6 实验用 Decimal 保存数额,仅登记小时、分钟、米和厘米四种单位。小时与分钟属于时间维度,米与厘米属于长度维度。60 分钟转成小时得到 1,1.70 米转成厘米得到 170.00;前者不能转换成米。未知单位和非有限数值在构造时被拒绝。 单位转换没有依靠...
软件建模09:Party、Role 与责任
参与方 P1 在 10 点开始代表组织 O1 办理设备租赁,12 点又承担 O1 的验收职责,15 点结束租赁经办任职。查询 14 点时,P1 有两项职责;查询 15 点时,应只剩验收职责。P1 同时为另一组织 O2 办理租赁,这项关系也不能随 O1 的任职终止而消失。 这组新增教学场景沿用设备租赁案例,但不属于现有 RentalDesk 的能力。Java 基线尚未接收操作者身份。这里用独立实验检查个人、组织和带期间的责任关系,检验继承、角色字段与关系记录分别能回答什么。 参与方身份与业务角色 Fowler 的 Accountability 补充材料第 5—6 页把 Party 用于个人与组织的共同抽象,并说明共同部分值得提取时才采用。组织可以是业务组织单位,不能把 Party 自动解释为具有法律资格的法人。材料也提醒,参与方的角色并不意味着必须采用 Role Object。Party 原始说明,第 5—6 页 本篇采用 Party(id, kind),kind 只允许 person 与 organization。P1 与 O1 的区别由种类表达;“租赁经办”和“验收”则依赖某...
软件建模08:分析模式的复用
设备 E1 交付时的累计运行读数是 120 小时,归还时是 126 小时。如果台账只有一个 operatingHours 字段,更新以后只能看到 126。需要计算本次使用量时,交付读数已经丢失。补一张读数记录表可以解决问题,但是否还要增加 Quantity、Measurement、Observation 等对象,需要由接下来的查询决定。 系列前七篇已用租赁场景检查结构、协作、行为和数值边界。分析模式提供的是其他问题中已经整理过的概念关系。本篇从两个候选实现比较开始,检验这些关系能否解释租赁读数,再用一个独立的合成身高观测例子检查可迁移部分。这里的设备读数是新增教学假设,尚未接入 Java 的 RentalDesk。 从丢失的答案确定问题 原有预留基线只处理指定设备、半开租期、重复请求和取消。它不读取运行小时数,也不会因为设备出现划痕而改变预留结果。新增需求是假设租赁交接需要保留读数和外观记录,并能回答“交付时登记了什么”。这个问题不能由当前设备状态完整回答。 先考虑更小的业务:操作员只查看设备最新累计小时数,不追溯、不结算,也没有第二类读数。一个固定字段已经足够。把它改成五张表...
软件建模07:时间、数量与身份
一台设备上午十点至十一点被租用,下一笔从十一点开始,是否冲突?报价里的十元和十美元能否相加?设备改了名称以后,过去的租赁记录应该显示哪个名称?这些问题往往被藏进时间戳、小数和字符串字段里,直到边界数据出现,才发现字段类型没有表达业务需要的区别。 状态、流程和决策 为报价使用了“整数计费天数”这一输入,但没有定义它怎样从租期计算。本篇先检查时间、数值和身份各自的含义,再讨论这些选择对实现的限制。设备租赁仍是教学场景,日租算法、货币转换和历史政策均不能由 Java 类型替业务作出决定。 相邻租期是否争用同一个端点 系列基线 RentalDesk.Period 已经使用 Instant start 和 Instant end,要求开始严格早于结束。租期解释为半开区间 [start,end):包含开始,不包含结束。两个租期重叠,当且仅当各自的开始都早于另一个的结束。 12return start.isBefore(other.end) && other.start.isBefore(end); 因此十点至十一点与十一点至十二点不重叠。这里的十一点属于后一段...










