关于业务对象本质的思考(1)

关于业务对象本质的思考

[摘要]:本文基于前人在OO、DDD等领域的研究成果,结合个人工作经验及感悟,对业务对象(Business Object)的本质进行了提炼和总结,并就BO三要素以及BO的获取和验证等问题进行了阐述,旨在加深OOA/D人员对BO的正确认识,分析并设计出更优质的软件产品。

1 引言

对于采用OO思想,并具有N层架构的计算机程序而言,业务对象(Business Object)一般位于业务逻辑层(也叫领域层[1]),作为领域模型元素的一部分,描述了来自于业务域中的一个人、事、物或概念[2],主要用来解决商业逻辑(即业务操作)问题,是为实现当前软件(或系统)的某一(或某些)特定功能而服务的。因此,它仅仅是从当前业务域的角度,对现实世界的一次抽象。

业务对象、业务实体、实体、领域对象在某种程度上是可以互换的术语[此处仅仅说是“某种程度上”,目的在于分析BO三要素的实质,针对于不同的理论,这几个名词确实存在差别,但本文不做赘述]。

2 对象三要素

依据Wikipedia对object的定义[2],对象具有以下三个要素:

■ 标识(identity),是唯一区别其他对象的标志;

■ 状态(state),描述对象所蕴含的信息;

■ 行为(behavior),对象所持有的、描述对象如何被使用的方法。

BO are state and behavior together.下文仅对状态和行为进行阐述,BO的标识不做赘述。

2.1 状态

相对于字段、变量、属性等词,用“状态”一词来描述对象的“性格特点”最为合适。字段、变量、属性等,无非是描述对象状态的不同表现手法。就目前个人对BO状态的理解而言,BO的状态信息有两类:固有信息和动态信息。其中,固有信息是对象从诞生时与生俱来的信息(就像一个新生命的诞生一样,出生年月日、肤色、性别等信息是生来就有的);动态信息,即随着BO的成长,它会走入某一个人生场景中,扮演了某一个角色,从而在这个场景中被赋予了一些额外的信息,如:小明是个学生(从入学时,学生的基本信息被赋予),某天他去市图书馆借阅图书,此时他在借书这个场景中扮演了借书者这个角色,从而具有了借阅证、借阅信息等动态信息。

2.1.1   固有信息

个人认为业务对象在被构建(初始化)后,应达到一个相对比较稳定,且具有一定业务含义的状态,即业务对象的属性应已进行了相应的初始化设置,这样的构建才算合理、完整。与人类世界类似,人在出生时,就已经构造好了婴儿的鼻子、眼睛、手等内容,虽然此时他还没有衣服、母语、身份证等信息,但他在出生时,是一个相对较稳定且有意义的个体,就可以完成婴儿的核心操作,如:哭、呼吸、挥手等。试想,一个对象在构建之后,还需要通过频繁的setter()方法后才可以完成核心业务操作,这是良好封装的表现么?对调用者而言,核心目标是使用BO所公布的方法,用之前还要先setter这个,再setter那个,显然是一种很烦人的,至少setter()这个和那个,不是调用者的本意,更不是调用者的职责

提前构造好该构造好的信息(注意:不是所有的信息都要一股脑的全构造好)是保证BO不被滥用的第一步。此处容易产生疑问,若一个BO在构造时涉及大量的初始信息,也统统的从构造函数里面作为参数注入么?关于这方面的顾虑,我的解答:首先,构造其本质就是初始化BO实例,无关痛痒的new 一个空的或不完整的BO实例一样是没啥意义(甚至是扰乱视听);其次,参数多,说明对象将被构造得彻底,带来更多稳定性,可试图对参数进行分类封装,以减少这方面的纠结(但个人认为,没必要);最后,建议结合spring的依赖注入、Bean的配置等内容进行理解。

2.1.2   动态信息

进入某一场景,扮演某一角色(我更喜欢用“戴上帽子”这个说法),将拥有额外的动态属性。同“固有属性”的构建,某一业务对象走入特定的场景,扮演了另一角色时,也应该将这些动态属性予以设置。一句话,对象应尽量在构建自身的过程中完成自身状态的设置。

Student  trace = new Student(“trace”,1900.10.10,man….);

trace.drink();

IBorrower  borrower = trace.ActAs<IBorrower>();

borrower.borrowBooks();

2.1.3   属性封装

在OO的世界里,封装的概念是最简单的,但却是最关键且最难以把握的。对内部信息的封装是作为合格OOA/D人员必须遵循的最基本原则。

【问】:不封装属性,将业务对象的信息暴露出来,程序正常实现了,好像也没出什么大问题?!

【答】:恭喜你,你通过对那么多唾手可得的信息,实现了业务功能(暂且不说程序代码结构如何,是否内聚/低耦),看上去没有问题。但若需求变化,甚至是高层策略都变化的话,如何应付?

信息的不封装(或封装不完整),已经让太多的程序员吃尽苦头,而且往往都是自己亲手埋下的苦果,并总伴随着“如果重新再来,我肯定不会这么设计”的后悔和无奈。信息不封装(或封装不完整)带来的副作用:

1、内聚,难。业务对象的信息过多的暴露出去,容易滋生强盗逻辑,想捏回去形成一团,难!信息全部都暴露给外界,调用者还需要你BO干嘛?原因很简单:我能够伸手拿到你的任何信息,想实现什么就实现什么,可以为所欲为。如果你还有胆量暴露一些更改BO属性的权限,那我岂不是想怎么改就怎么改。你(业务对象)能控制得了?你还想内聚?做梦!

2、解耦,难。一个成语叫“覆水难收”,放出去的信息将被调用者肆意使用,而且呈现出快速蔓延的趋势,一张复杂的耦合网必然产生。等回头开始重构解耦时,发现堆积如山的代码、耦合似网的结构,已经让你无从下手。动一下,就引起全身阵痛。常见的做法:(1)刨一小块,改改变量名、方法名,移一些代码,用接口再包装一下(隔离嘛),循环的修改,最终发现进展依然是非常缓慢,几乎还没触及到业务核心;(2)先用方法(1)试试,一阵子后,MD,烦死了,直接推倒重新搞。这些做法还需要考虑一个问题:放出去的接口和信息已被调用者大量使用,怎么办?

 

针对上述的苦痛,推荐下面的做法:

1、在对象构建时,把能设置的状态信息尽可能的予以赋值,提前封装;

2、尽可能的不要公布内部信息。能够private的,尽可能的私有。除非迫不得已,尽量不要将setter() 放出,仅使其read only。[个人感受]:以前写代码,从来不顾及private/protect/public,统统public,导致的恶果已经让我吃了好几壶。

2.2 行为

业务行为才是软件真正所关注的问题,对象的行为方式是对象价值的重要体现,也是区别于其他对象的重要标志。因此,我们说“BO因职责而存在!”。

2.2.1   贫血VS充血

关于贫血模型和充血模型的争论从未休止过,但本文仅从BO的角度论述二者的差异(仅为个人之见)。

■ 贫血对象

由不具有任何行为的业务对象形成的领域模型,称为“贫血模型”[2]。对只有属性的getter/setter方法,不具有业务行为的BO,可认为是“贫血对象”。丧失业务逻辑行为的贫血对象,和Value Oject类似,扮演了Data Container的角色,而在业务域中的逻辑操作方面将失去能力(或被遗弃、边缘化)。

■ 充血对象——按大师的说法,与BO直接相关的行为职责将划归到BO中,使其在领域模型中扮演重要的角色。

但是二者不能绝对的说谁好、谁不好,应该一分为二的去看,它们各自具有其特点,应用在不同的场景中。特别地,对于那些需求难以完全吃透、明确,或许用贫血模型较充血模型要更好把控局势。“用户需求——业务——领域”是一个对知识掌握程度递增的过程,领域模型的建立应基于对客观业务域的透彻掌握,不能偏左,也不可以偏右(不就是博弈么?没有最优秀的东西,只存在考虑诸多因素下的较为合适的东西)。

2.2.2   职责单一

在谈“职责单一”前,先说说business core。BizCore是系统核心价值(业务骨架、灵魂)的体现。本人对BizCore的理解:它应该是最精炼、纯粹、简单、直接、轻量级的业务核心。因此,不属于核心业务逻辑范畴的职责和行为(如:持久化操作),尽量抛出去交给该处理它们的对象去处理。[在写下这段文字时,很想再加入DDD的某些概念,但是用一个新概念解释一个原本不太晦涩的概念,实在是不妥]

有了这个边界(或者说原则),再谈谈SRP(职责单一原则)。经常会看到God class(上帝类,你可以认为它就是一个充血充得快爆掉的对象),它几乎可以干所有涉及到它的工作,从而形成代码有几百行乃至上千行的牛X类(本人见过的最牛X类,接近5k行代码)。请问:有了这么一个牛X类,其他类不就成了浮云和鸡肋了么?这样可能引发很多问题:

1、理解难。几千行的代码,没有几个人有耐心阅读,几乎没人能够完全理解其表达的业务含义。我敢保证:这样的类,会对方法名的表意性带来巨大的冲击,如:getFlowDataFromTaliformAfterSave….(),哇靠!这个方法名算好的,更匪夷所思的方法名将让执着的程序员头都要爆掉。

2、修改难。没有很好的理解,如何修改?如何重构?

3、扩展难。丢了它玩不转,不丢它又引来一堆麻烦,对于一个几千行的实现类来说(除非大多都是public static 的方法),吃资源不说,接口隔离、应对扩展方面也是比较吃力的。

2.2.3   谁拥有数据,谁持有行为

BO行为的本质是对BO自身状态的改变,以实现业务目标,并且这种状态的更改可能还需要其他协作者的参与(关联关系)。因此,我们可以说“谁拥有数据,谁就持有更改这些数据(状态)的行为”。

现实中,跟BO有关系的行为可能较多,全部纳入到BO中,会造成BO的臃肿和污染,违背SRP。所以,行为的归属需要遵循一些原则:

■ 可重用度高或是对象固有、与BO状态密切关联的方法放在BO中。

■ 可重用度低或者不是对象所固有(而依赖于特定场景)、与BO状态没有密切联系的方法放在BO管理者或服务层。

上面的原则,和DDD中关于领域模型(domain model)的行为归属类同。甚至我觉得领域模型中的对象,即为最纯粹的BO。

2.2.4   方法属于客户

BO就是一个黑盒子,其中包含了逻辑和数据,而对象的使用者不知道里面有什么数据,也不知道实际的运行逻辑。使用者所能做的就是与对象进行交互,以完成当前的业务目标。因此,对象的行为是为客户而定。

正如前面我们所说,行为(方法、职责)是BO存在的根本,而行为就是为了交互,为供调用者所使用。调用者会根据自己的需要,向它认为应该由谁提供行为的BO发出操作申请,一切都是以“客户(调用者)”为中心而服务的。

2.2.5   行为封装

关于对象行为的封装,有两个层面:

1、千万不要以为自己拥有这么多数据,就可以肆意的发布任何方法,真正被调用者使用的方法其实也很少。跟现实中的人一样,过多的对外暴露行为,别人会把你的信息四处传播,到时候你想改变一下自己的形象,难!因此,仅对外暴露稳定的、合理的、刚刚满足客户需求的API就足够。

2、行为在不同级别的范围内应该封装,仅自己内部使用的话,private就OK了,如果需要让子类持有,protect一下就OK了。总之,在定义BO的行为时,握紧手中的那把尺子,尽量谨慎行事,不要过早的给自己挖坑、负债。

————————以下内容在下一篇文章中涉及————————

3 对象的获取

1、原始资料中的名词获取;

2、抽象角度

3、抽象层次

4、业务域vs领域vs技术域

4 良好BO的验证

5 总结与展望

1、基于数据库表的分析与设计;

2、封装变化

3、OO需要一分为二

4、关于“业务架构师”

6 参考文献

[1] Eric Evans. 领域驱动设计[M] 清华大学出版社

[2]大象:Thinking in UML

[3] http://en.wikipedia.org/wiki/Business_object

[4] http://stackoverflow.com

[5] Martin C Robert. 敏捷软件开发 原则、模式与实践(C#版)[M] 人民邮电出版社 p107

[6]Steve Freeman, Nat Pryce. Growing Object-Oriented Software, Guided by Tests.

转载于:https://www.cnblogs.com/trace/archive/2011/12/13/2286847.html

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
数据分析与可视化 什么是数据分析? 数据分析是基于商业目的,有目的的进行收集、整理、加工和分析数据,提炼有价信息 的一个过程.其过程概括起来主要包括:明确分析目的与框架、数据收集、数据处理、数 据分析、数据展现和撰写报告等6个阶段。 明确分析目的与框架 一个分析项目,你的数据对象是谁?商业目的是什么?要解决什么业务问题?数据分 析师对这些都要了然于心。基于商业的理解,整理分析框架和分析思路。例如,减少新 客户的流失、优化活动效果、提高客户响应率等等。不同的项目对数据的要求,使用的 分析手段也是不一样的. 2、数据收集 数据收集是按照确定的数据分析和框架内容,有目的的收集、整合相关数据的一个过 程,它是数据分析的一个基础。 数据处理 数据处理是指对收集到的数据进行加工、整理,以便开展数据分析,它是数据分析前 必不可少的阶段。这个过程是数据分析整个过程中最占据时间的,也在一定程度上取决 于数据仓库的搭建和数据质量的保证. 数据处理主要包括数据清洗、数据转化等处理方法。 4、数据分析 数据分析是指通过分析手段、方法和技巧对准备好的数据进行探索、分析,从中发现 因果关系、内部联系业务规律,为商业目提供决策参考. 到了这个阶段,要能驾驭数据、开展数据分析,就要涉及到工具和方法的使用。其一 要熟悉常规数据分析方法,最基本的要了解例如方差、回归、因子、聚类、分类、时间 序列等多元和数据分析方法的原理、使用范围、优缺点和结果的解释;其二是熟悉1+1种 数据分析工具,Excel是最常见,一般的数据分析我们可以通过Excel完成,后而要熟悉一个 专业的分析软件,如数据分析工具SPSS/SAS/R/Matlab等,便于进行一些专业的统计分析 、数据建模等. 5、数据展现 一般情况下,数据分析的结果都是通过图、表的方式来呈现,俗话说:字不如表,表不 如图。借助数据展现手段,能更直观的让数据分析师表述想要呈现的信息、观点和建议。 常用的图表包括饼图、折线图、柱形图/条形图、散点图、雷达图等、金字塔图、矩 阵图、漏斗图、帕雷托图等。 6、撰写报告 最后阶段,就是撰写数据分析报告,这是对整个数据分析成果的一个呈现.通过分析报告 ,把数据分析的目的、过程、结果及方案完整呈现出来,以供商业目的提供参考。 一份好的数据分析报告,首先需要有一个好的分析框架,并且图文并茂,层次明晰, 能够让阅读者一目了然.结构清晰、主次分明可以使阅读者正确理解报告内容;图文并茂 ,可以令数据更加生动活泼,提高视觉冲击力,有助于阅读者更形象、直观地看清楚问题 和结论,从而产生思考. 另外,数据分析报告需要有明确的结论、建议和解决方案,不仅仅是找出问题,后者 是更重要的,否则称不上好的分析,同时也失去了报告的意义,数据的初衷就是为解决 一个商业目的才进行的分析,不能舍本求末. 数据分析常用的方法有哪些?他们多用来分析哪些类型的数据?通过分析可以得到怎样的 结果和结论?怎样得到保证其信度和效度? 常用数据分析方法:聚类分析、因子分析、相关分析、对应分析、回归分析、方差分析 ; 数据分析常用的图表方法:柏拉图(排列图)、直方图(Histogram)、散点图(scatter diagram)、鱼骨图(Ishikawa)、FMEA、点图、柱状图、雷达图、趋势图。 数据分析统计工具:SPSS、minitab、JMP. 常用数据分析方法: 1、聚类分析(Cluster Analysis) 聚类分析指将物理或抽象对象的集合分组成为由类似的对象组成的多个类的分析过程。 聚类是将数据分类到不同的类或者簇这样的一个过程,所以同一个簇中的对象有很大的 相似性,而不同簇间的对象有很大的相异性。聚类分析是一种探索性的分析,在分类的 过程中,人们不必事先给出一个分类的标准,聚类分析能够从样本数据出发,自动进行分 类。聚类分析所使用方法的不同,常常会得到不同的结论。不同研究者对于同一组数据 进行聚类分析,所得到的聚类数未必一致. 2、因子分析(Factor Analysis) 因子分析是指研究从变量群中提取共性因子的统计技术。因子分析就是从大量的数据中 寻找内在的联系,减少决策的困难。 因子分析的方法约有10多种,如重心法、影像分析法,最大似然解、最小平方法、阿尔 发抽因法、拉奥典型抽因法等等。这些方法本质上大都属近似方法,是以相关系数矩阵 为基础的,所不同的是相关系数矩阵对角线上的值,采用不同的共同性 2估值。在社会 学研究中,因子分析常采用以主成分分析为基础的反覆法。 3、相关分析(Correlation Analysis) 相关分析(correlation analysis),相关分析是研究现象之间是否存在某种依存关系,并对具体有依存关系的现 象探讨其相关方向以及相关程度.相关关系是一种非确定性的关系,例如

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值