对象的责任与职责

对象和数据的主要差别就是对象有行为,行为可以看成责任职责(responsibilities以下简称职责)的一种,理解职责是实现好的OO设计的关键。“Understanding responsibilities is key to good object-oriented design”—Martin Fowler 。

对象设计:角色、责任和协作"(Object Design: Roles, Responsibilities, and Collaborations)一书对对象的职责进行了完整阐述。

对象过去一直被看成是被操作的数据,这也是失血贫血模式的来由,这还是一种将对象看成数据结构或集合的另外一种表现,对象是有自主行为的,对象是一种类似机器人的概念。

职责的革命影响力
DDD领域驱动设计中,通常很多人会误将现实中实体完全映射到软件中领域实体,这是一种谬误,现实中实体不是一对一反映到软件中,这其中包括一个抽象过程。我们必须明白:软件领域中一个实体对象通常能够扮演多个现实中实体角色。

由于软件领域中对象根据不同场景可以扮演不同角色,对象的方法可以看成这些角色不同职责的表现,打个比喻:你在家是一个父亲,在单位是一个领导,如果我们建立两个实体父亲和领导就不合适了,没有经过抽象分析,其实只有一个领域模型实体,就是“你”,只不过在不同场景,你扮演不同角色,角色不同反映在角色的权利或职责行为不同,父亲的职责责任与领导的职责责任是不一样的。

同一个领域对象通过不同方法扮演不同角色就带来实现上的一个问题,这就衍生出一种DCI架构,我们建模时,不可能将其扮演的所有角色行为都塞入实体对象中,而是应该根据不同运行场景来动态分配职责,所以,传统OO语言如Java .NET等有些难点,当然可以通过AOP的MIXIN方式变相达到,但是不是很优雅,Qi4J所谓面向组合概念实际就是这样,而Jdonframework则从EDA事件驱动方面婉转来通过事件消息来驱动不同职责响应,最新面向函数式语言如Scala这方面就优雅直接了。

职责概念给OO世界带来巨大革命性变化,使得我们分析需求必须从职责驱动重新看待需求了,DDD一书中分析货运这个案例时,也未能从职责来审视,比如它为运输历史专门建立一个记录对象,如果从职责概念看,运输对象应该知道它自己过去的历史,这是它的职责,所以,运输历史获得应该是运输实体对象的一个方法,而不应该为其单独建立对象。

DDD一书很多方面还是存在数据提取的影子,这是它的历史局限造成的,为了摆脱失血模式纯粹数据对象的影子,对象的职责上升到前所未有的高度。

如何发现职责
如果改变传统将对象看成是死静止的实体概念,将实体对象看成是活的,你就很容易发现其行为职责,现实世界的对象可能是做事情或代表一些信息或东西,但是现实对象不做决定。软件中对象是活的,根据分配给他们的职责能做决定,类似智能机器人。

职责来自于你的软件是如何工作。来自于软件的HOW。寻找和分配职责需要灵感,是一个创造性活动,是一个充满探索冒险发现新奇的乐趣活动,从下面几个方面寻找需求中职责:
1.来自用例分析中顺序图消息发送。
2.构造invention、 约束表达、策略、算法、规格Specification和描述Description都可以成为职责。
3.系统要做的事情或要管理的信息
4.将实体对象看成一个演员(拟人化),扮演一个角色应该知道哪些事情knows something、会做那些事情do sth.,能够控制或决定什么事情。

简明扼要,判断职责的主要就是:它是否知道know这些东西,它是否会做这些东西,或做一些判断决定等。

职责分配
将职责分配给对象,使得对象有形有态。
按照高凝聚原则分配。
使用“如果没有这个职责,会怎样”。
如果发现职责太广泛,不能分配到单个对象中,那么就切分职责,由这些小职责组合成更大职责。

所谓凝聚原则:和DDD中的高聚合概念比较类似,关注类内部;一个类是否充分实现其职责目标?类中方法是否都是为实现这个职责服务的?高聚合代表鲁棒性 重用性和可理解性。

总结
一旦领域对象具有丰富的行为,变成富模型,或充血模型,它实际上就是一个Actor,Actor之间可以通过协作消息进行联系,而Scala的不同于多线程机制的Actor模型底层实现又更好地支撑了这样的富模型,这也是为什么Scala开始非常流行的原因之一。

使用职责来分析需求,建立丰富对象,类似文学中的拟人化手法,将设计想象要赋予现实中静止不会说话的客观事物,当然,不能过,合适即可,目前最大问题是不够。

也需要注意面向对象和面向过程的区别,面向过程是数据和职责功能分离,以职责功能为主,职责功能去操作数据。

使用面向对象的语言并不保证面向对象的思想。如何定义的对象以及如何相互作用才是决定是否面向对象。 所以,你尽管使用Java的SSH组合,如果你把功能职责放在服务Service类中,通过Service驱动DAO操作数据库,操作数据库生成的数据对象,这是典型的面向数据库和面向过程狼狈为奸。

面向对象是将功能职责纳入到对象中,和数据封装起来,形成一个有自主判断和基本逻辑的Actor,就类似于DDD中的聚合和聚合根对象,根对象有职责维持聚合边界一致性的职责。


需求分析越详细越好,如果不能面面俱到,也依靠日后反复迭代,但是个人经验是:用例图 需求顺序图或四色图 状态图或交互图是必须的。
从事创建对象时掌握四个步骤和原则,也是每天座右铭:
1.抽象Abstractions 从实际中抽象

2.职责Responsibilities 寻找职责

3.高聚合High-cohesion: 关注特征属性和职责,分配职责,特征属性是否该对象固有特征?职责是否和该对象固有行为?特征属性对应对象的字段;职责对应对象的方法,这样,对象的字段和方法就有了,实体对象就创建出来了。当然这其中可能一些特征属性包装成值对象,形成聚合群,有一个根实体。

4.松耦合Loose-coupling:关注对象间协作,一个大对象划分两个,大对象中职责就变成两个对象的协作。协作讲究约定,如DBC,设定前置条件 后置条件和不变性,这个过程也涉及聚合边界的划分,一些专注做对象内部工作,不需要和外部对象协作的对象职责专门封装起来,比如内部算法,形成单独的算法类,这个算法类也是聚合群中一个类。当然聚合群中,也有类负责专门协作的。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
面向对象软件工程是一种软件开发方法,它使用对象作为软件系统中的基本构建单元。它的优点包括: 1. 可重用性:面向对象设计使得开发人员可以将已有的类和对象重复利用,从而节省时间和减少开发成本。 2. 模块化:面向对象设计使得软件系统可以被分解成小的、独立的模块,使得开发和维护变得更加容易。 3. 易于扩展性:面向对象设计使得软件系统可以随着需求的变化而进行扩展而不会影响到其他部分的功能。 4. 可维护性:面向对象设计使得软件系统的代码更加易于理解和维护,因为每个对象都有自己的功能和责任。 5. 更好的团队合作:面向对象设计使得团队成员可以更容易地分工合作,因为每个对象都有自己的职责和接口。 然而,面向对象软件工程也有一些缺点,包括: 1. 复杂性:面向对象设计需要开发人员掌握更多的概念和技术,使得系统的复杂度增加。 2. 性能问题:面向对象设计通常需要更多的计算和内存资源,因此可能会导致性能问题。 3. 学习成本高:面向对象设计需要开发人员掌握更多的知识和技能,因此学习成本较高。 面向对象软件工程的方法包括: 1. 面向对象分析(OOA):这个阶段主要关注问题域,目的是识别和描述系统中的对象以及它们之间的关系。 2. 面向对象设计(OOD):这个阶段主要关注解决方案,目的是将OOA阶段识别的对象转换成软件对象,并确定它们之间的接口和实现。 3. 面向对象编程(OOP):这个阶段主要关注实现,目的是使用面向对象的语言(如Java、C++等)来实现OOA和OOD阶段定义的对象和接口。 4. 面向对象测试(OOT):这个阶段主要关注验证,目的是确保系统的功能和质量符合要求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值