《软件方法(下)》8.2.5.2 属性是否直接描述类(202402更新)(2)

本文讨论了在建模过程中避免错误的关键,包括理解抽象能力的重要性,区分信息存储的本质和表面形式,以及正确处理关系数据库对建模的影响。作者强调了不应将非本质属性如单据和编码作为类的属性,而是应关注领域概念。此外,文中还涉及了状态属性、冗余属性的识别与去除,以及合理使用关联和状态机的设计原则。
摘要由CSDN通过智能技术生成

导致出现违反本要点的错误的原因有:

(1)缺少抽象能力

缺少抽象能力的建模人员经常会把手上素材的信息,一一对应地映射为类和属性,导致本来属于多个类的信息被合并在一个类中。

如图8-63,建模人员对照着一张货物运输托运单,直接把它映射成类,照抄上面的每一栏作为属性。

图片

图8-63 错误:直接把素材照搬成类

建模人员有时还觉得挺符合“类的属性”的。“货物运输托运单的货物名称”,没错啊,手边这张货物运输托运单上确实明晃晃地印有“货物名称”四个字嘛。

托运单、出库单、销售单等各种单据,以及身份证、工作证、图书卡、设备卡等各种卡片和证件,在信息时代之前就已经存在了。它们相当于某种“信息化”的存储结构,存储一个或多个概念的信息,只不过保存的载体不是电子载体,而是甲骨、铜器、竹片、木片、帛布、纸张。

现在,既然用信息系统取代了这些单据、卡片和证件,那么要建模的实体类应该是它们所存储的领域概念,而不是单据、卡片和证件本身。

图8-63右侧的类“货物运输托运单”应该变成如图8-64。

图片

图8-64 建模早期信息存储载体所存储的领域概念

开发团队中可能会有人唧唧歪歪,什么“性能”啦,什么“我们之前都是这样做”啦。碰到这种情况,也不用祭出鲁迅先生的“从来如此,便对么?”,你只需要问他,扔给他一张类似图8-63的**单,他有能力干脆利索地得到类似图8-64吗,没能力就让他TM的闭嘴。

★其实,如果一个人知道如何得到一个清晰、无冗余的模型,说明他具备了一定的建模能力,往往也不会在分析的时候担心这些问题,因为他知道,如果碰到性能问题,可以按照某些套路添加冗余,这些套路和目前所思考的领域知识没有关系,没有必要混杂进来。

在有能力得到图8-64的基础上,可以再来考虑需不需要一个如图8-63右侧的“货物运输托运单”类来维护当时的快照。因为随着时间的推移,对象的属性值会变化。

例如图8-64中,随着时间的推移,如果某个单位的名称或地址改掉了,此时从图8-64计算出图8-63左侧的托运单快照,和事件发生的当时按照图8-63左侧填写的信息是不一样的。

如果这样的快照很重要,可以另外加一个如图8-63右侧的快照类来维护这些信息,这个类是孤立的,和图8-64的类不存在关联。

但这样做很容易出现沿着关联线向外延伸,雪球越滚越大的情况。如图8-64,单位的联系人会换人,人员的电话会改变……最终可能需要一个巨大的类,把所有通过关联线连在一起的类的所有属性组合在一起,而背后的数据量也是庞大的。

更合理的做法是记录本质的变更来源。如果单位变更名称和地址是值得关注的事情,应该添加一个类记录单位变更名称和地址的细节,或者说,记录所有值得记录的对象属性值变更的细节。在此基础上,需要类似图8-63的某个时间点来自多个对象的属性值组合快照时,可以通过计算来还原。

在这里,我们要认清楚非常重要的一点:本质是对象之间存在关联,而不是对象属性值之间存在关联。如图8-64,两个单位之间曾经存在的某次托运关系,并不会因为单位后来改名或改地址而变化,相对于如图8-63列出一堆属性值,记住“托运”和“单位”之间的关联是更本质的——当然,并不影响从本质模型还原出各种视图或报表。

正如上文提到的,如图8-63是在信息化时代之前的一种“信息化”的存储结构。当时不要说没有方法学,即使有方法学让你先分解概念为图8-64,也没有计算设施把它们按需要组合成图8-63或更多的视图。

现在,既然有了条件,就没有必要再去模仿条件不足时的拙劣“模型”了。

很可能在这个时候,伪创新又乘机迎合那些没有抽象能力又不愿意学习的无能之辈。伪创新的说法是:图8-63的快照是发生过的事情,是不会变化的,各种所谓的“流水”才是本质!于是,无能之辈非常开心,热烈拥抱伪创新。

我们可以用科学研究类比一下:背后的规律没搞清楚时,要推测某个数据,可能是靠“经验”来推测。“经验”其实就是发生过的“流水”的记忆。当科学家研究巨量已有的“流水”(即实验数据),探索出其中的规律后,这时再推测数据,就没有必要从之前的巨量“流水”来推测了,根据归纳出来的公式推测即可。当然,之前或之后的各种“流水”可以继续保留,但它们不是本质,是现象。

何况,不是所有的系统都需要保存“流水”。电梯每天上上下下,不知发生多少次“召唤”事件,但目前的电梯系统并不会记录“召唤”事件的细节——谁召唤的、什么时候召唤的……系统只需要维护本质的行为规则,如果采用本书的方法学,可以选择用状态机来表达。

当然,也许有一天,电梯系统有了足够的存储资源,会记录所有的“召唤”流水,但这和背后的规律没有关系。系统是否记录某个事件的细节,不影响事件是否发生、事件是否产生效果,以及背后的行为规则。

(2)受关系数据库建模的影响

建模人员有时会犯这样的错误,在一个类中放上另外一个类的属性作为“外键”。比如针对上面的例子,建模人员会想:“人员”里放“组织名称”确实不合适,但是放个“组织编码”作为外键总可以吧?其实也不可以。"组织编码"是“组织”的属性,是封装在“组织”中的秘密,“人员”不应该拥有“组织”的任何属性,它只能通过关联拥有“组织”对象,然后通过访问“组织”对象公开的操作来间接访问“组织”的属性。

图片

图8-65 不需要“编码”作为“外键”

“人员”里放“组织编码”不合适,放一个无意义的标识“组织ID”呢?同样也不可以。因为这个“组织ID”是“组织”的标识,前文已经说了,标识属性此时不需要存在,所以“组织ID”在“组织”里不存在,更不要说放到其他类中作为“外键”了。

图片

图8-66 不需要“ID”作为“外键”

在设计工作流,需要把类图映射到关系数据库时,确实需要把"组织"表的主键(可能是"编码"也可能是生成的代理主键)放在"人员"表中作为外键,但正如上文所说,这同样是另一个领域的知识,而且映射规律和核心域知识无关。

状态属性和类的匹配

状态属性的名称是一个形容词,类型为布尔类型,用来标记对象是否处在某个状态,如图8-67。

图片

图8-67 状态属性

这些状态属性可能是来自素材中的定语,例如,用例规约提到“可享受优惠的顾客”,那么在识别的时候可能会先把“可享受优惠”放在“顾客”类中。

和“类的属性”刚好相反,状态属性和类连在一起说,要能说得通"属性的类"。例如,图8-67中,“可享受优惠的顾客”是说得通的。

8.2.5.3 属性是否可以从其他地方推导

如果一个属性可以从其他地方推导出来,那么这个属性就是冗余的,可以删掉。

如图8-68,人的年龄可以从出生日期计算得到,应该把年龄删掉。

图片

图8-68 年龄可以从出生日期推导

这个“其他地方”也可以是所关联的类的属性。如图8-69,订单的总金额可以由各个订单项的金额合计得到,那么可以考虑把总金额删掉。

图片

图8-69 总金额可以从各订单项金额合计

状态属性的冗余

状态属性是冗余的,背后往往隐藏着更多的逻辑,需要进一步思考,把它变成更合适的模型内容,但这涉及到还没讲到的知识点,此处只简单举例,后文还会详述。

以图8-55中的“订单”为例,如果问一个“订单”对象,你是“待支付的订单”吗?如果“订单”通过自己的资源就能回答这个问题——例如,查询是否有“支付”对象和自己关联,那么“待支付”就可以作为“订单”的状态机中的一个状态。

图片

图8-70 “待支付”变为“订单”的状态

再看图8-55中的“会议室”。如果问一个“会议室”对象,你是“合适的会议室”吗?这时的回答是犹豫的,因为会议室合适不合适,还需要看开哪个会议,会议A也许不合适,但会议B可能就合适。这样含义的“合适”不能成为“会议室”的状态。

这个“合适”的演变可能并不简单,只是在“会议室”和“会议”之间建立一个“合适”的多对多关联,可能并不能满足要求,甚至是冗余的,因为计算哪些会议室对某个会议合适,正是系统的一个责任。如果是这样,就需要进一步建模背后的规则,如图8-71。

图片

图8-71 “合适”背后的规则

但是,如果“合适”的含义是“当前使用会议室的会议是否合适”,有图8-71的加持,再加上一个“当前会议”的关联,“会议室”是可以回答这个问题的。此时,“当前会议合适”就可以作为“会议室”的状态,其他状态可能有“当前会议不合适”、“无当前会议”、“装修中”。

★把状态放在“会议”,来一个“当前会议室合适”可以吗?也可以。放在哪里更好,后文还会再探讨。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值