11

我在哪里工作,我们已经多次讨论这个问题,并正在寻求一个完整的检查。下面是问题:Business Objects应该是数据容器(更像是DTO),还是应该包含可以在该对象上执行某些功能的逻辑。Business Objects - 容器还是功能?

示例 - 如果客户对象包含一些常用属性(名称,Id等),并且该客户对象还包含函数(Save,Calc等)?

一条推理说,将对象与功能(单一责任主体)分开,并将功能放入业务逻辑层或对象中。

另一种推理说,不,如果我有一个客户对象,我只想调用Customer.Save并完成它。为什么我需要知道如何保存客户,如果我消费对象?

我们最近的两个项目已经将功能与对象分开了,但是关于新项目的争论再次提出。哪个更有意义?

编辑

这些结果非常相似,我们的辩论。对一方或另一方投一票将彻底改变方向。还有其他人想要加2美分吗?

EDIT

Eventhough答案采样小,似乎大多数相信在业务对象的功能是可接受的,只要它是简单的,但持久性最好放在一个单独的类/层。我们会试试这个。感谢大家的输入......

回答

10

对象一起是状态和行为。如果一个对象有明显的行为(例如,从他们的出生日期计算一个人的年龄,或者为一张发票计算一个总税额),通过所有手段添加它。无非是DTO的业务对象被称为“贫血域模型”。我不认为这是一个设计要求。

持久性是一种特殊的行为。我称之为“明智的”是商业行为。一个业务对象不需要知道它是持久的。我会说,一个DAO可以保持持久性与业务行为分开。我不把“保存”放在“明智”的范畴。

+0

只是澄清......你的想法是计算和其他简单的函数应该驻留在对象中,但持久性(即.db事务)应驻留在别处。我有这个权利吗? – Walter 2009-11-25 13:31:48

+0

是的,这就是我要说的。当然,这不是唯一的方法。有些人喜欢有物体坚持自己。我通常不会。 – duffymo 2009-11-25 20:37:58

+0

我们一直在讨论业务对象或None中的所有功能。这是我们从未想到的一种可能的妥协。 – Walter 2009-11-30 23:04:46

2

我认为让业务对象知道如何“处理”自己更有意义,然后必须将这种负担放在系统的其他地方。在您的示例中,处理如何“保存”客户数据的最合理的地方对于我而言是在Customer对象中。

这可能是因为我认为数据库是“数据容器”,所以我支持“业务对象”是保护数据容器免受直接访问的较高级别,并强制执行标准的“业务规则”关于如何访问/操纵数据。

+5

我会说,而不是客户对象应该知道如何创建一个“可保存”的表示(例如,哪些属性需要保存并稍后恢复); *实际上*坚持该表示(例如在数据库中)的细节应该完全传递给另一个类。 – 2009-11-30 16:23:06

+0

由于BO可以被一系列使用不同语言和数据存储的系统使用,所以我很乐意看到这些工作。 – 2010-07-14 18:59:16

9

业务对象 CAN可以有业务功能

持久性不是业务功能,但是技术实现。

长话短说:

  1. 保存/更新/删除/查找等等 - 在一个持久层保持从业务对象了。
  2. CalculateSalary,ApplyDiscount等是业务相关的方法,可以是:
    1. 业务的方法的对象(所以BO是实体的自包含表示)或;
    2. 单独的服务实现特定功能(所以BO更像DTOs)。

至于点2
我应该提到的是,办法2.1倾向于使BO的过于臃肿和违反SRP。而2.2引入了更多的维护复杂性

我通常余额在让我把2.1和2.2之间的相关数据为业务对象琐碎的事情,并创建服务稍微复杂scenarious(如果有超过4行代码 - 使它服务)。

这将Business Objects的范例转变为更多的数据传输对象。

但是,这一切都使项目更容易开发,测试和维护。

+0

我用所需的东西来分割2.1和2.2。需要业务对象的功能或仅具有相同功能组的相关对象的功能 - 进入对象(CalculateAge on Person)。使用更多不相关对象的过程(CalculateDiscount考虑到居住地,交付等)是一项单独的服务,很可能甚至是单独的模块/组件。非常复杂的逻辑也是一个单独的类(支付计划中的PaymentPlanCalculator),但是使用C#作为扩展方法公开(在类中使用,但技术上不在其上)。 – TomTom 2010-05-14 10:22:59

+0

感谢您让我阅读SRP。这难道不会使课程数量膨胀,让维修变得更加困难吗? 我知道,应该是一个全新的问题。 – 2010-07-14 18:57:40

1

业务对象应该是关于封装由该对象建模的业务实体的数据和关联行为。可以这样想:面向对象编程的主要原则之一是将数据和关联的行为封装在该数据上。

持久性不是建模对象的行为。如果业务对象是持久性的,那么我发现开发更顺利。如果业务对象与底层管道没有明确关联,开发新代码和单元测试新代码发生得更快,更平滑。这是因为我可以嘲笑这些方面,并忘记必须通过hoops来访问数据库等。我的单元测试将更快地执行(如果每次构建都有数千个自动化测试,那么将会更加快速),而且我将减少压力,因为我不会因为数据库连接问题而导致测试失败(如果您经常脱机或远程工作,并且无法始终访问数据库,那么哦,顺便提一下,这些方面(数据库连接等)应该在其他地方进行测试!)。

推理的另一种说法是,不,如果我有一个客户对象,我只想拨打Customer.Save并完成它。为什么我需要知道如何保存客户,如果我消费对象?

知道Customer有一个Save方法已经知道如何保存客户对象。通过在业务对象中嵌入该逻辑,您并未避免这个问题。相反,您已使您的代码库更紧密地耦合,因此难以维护和测试。推卸坚持对象给别人的责任。

+0

似乎这里的大部分答案都采取了非常单方面的做法。只有一种语言,因此您可以将“代码”对象与业务对象混淆。我是否天真地采取更广泛的观点,我的业务对象的方法没有在BO本身的设计中实现,而是在每个寻求使用BO的解决方案中实现? – 2010-07-14 19:02:05

+0

@Stephanie Page:它与语言关系较少,更多与潜在模式有关。当对象行为的焦点从域到环境交叉时,问题就来了。如果对象被保存到数据库中,我们是否需要在每个域/业务对象中包含数据库逻辑,即连接字符串和字段/列映射或SQL语句?除非将DB逻辑分解到其自己的层中,否则这种方法很快变得难以管理。很少有语言可以处理这种情况,并防止它成为臃肿或冗余代码的来源。 – 2010-07-14 19:40:57

+1

我喜欢这样:从域名到环境的交叉......这是一个很好的比喻。 – 2010-07-16 14:52:45

3

无论平台或语言如何,答案都是一样的。这个问题的关键在于一个对象是否应该能够成为自主或者是否更好地将任何给定的行为散布在具有更多重点责任的对象中。

对于每个班级,答案可能不同。我们最终得到一个光谱,我们可以根据密度责任密度来安排课程。

      (Level of responsibility for behavior) 
     Autonomy - - - - - - - - - - - - - - - - - - - Dependence 
     High 
    C  - <<GOD object>>       <<Spaghetti code>> 
    l  - 
    a  - 
    s  -          
    s  -     
     -       
    s  - 
    i  - 
    z  - 
    e  - <<Template>>        <<Framework>> 
     low 

假设你赞成让班级自己执行所有行为,或者尽可能多地执行所有行为。从这张图的左边开始,当你让自己的班级变得更加独立时,班级的规模将会增长,除非你不断重构它以使其更具通用性。这导致模板。如果没有完成重构,那么这个类的变化就会变得更像“god-like”,因为如果它需要一些行为,它就有了一个方法。领域和方法的数量不断增长,很快就变得难以管理和不可避免。由于课程已经做得如此之多,编程人员宁可添加到怪物中,也不愿意将它分开并剪掉Gordian结。

图的右侧有很大程度上依赖于其他类的类。如果依赖关系很高但个人分类很小,那是框架的标志;每个类没有太大的作用,并且需要大量的依赖类来完成某些功能。另一方面,具有大量代码的高度依赖类也是该类充满意大利面条的标志。

这个问题的关键是要确定你在图上感觉更舒适的地方。无论如何,除非采用某种组织原则,个别课程最终将分散在图表上,这就是您如何实现模板框架的结果。

我刚才写到,我会说班级规模和组织程度之间存在关联。罗伯特C.马丁(或“鲍勃叔叔”)在其关于Design Principles and Design Patterns的非常彻底的论文中涵盖了与包依赖关系类似的理由。 JDepend是第26页图表背后思想的一个实现,并补充了static analysis tools,如CheckstylePMD

+1

+1细分。这将增加我们的辩论。谢谢。 – Walter 2009-11-30 23:37:47

+0

图表工作需要多长时间?非常好的答案...在网站上最好的Q/A之一。 – 2010-07-14 19:04:30

+0

@Stephanie:它花了很多反复试验。这个答案是我在Meta中为Markdown提供表格支持的功能请求的原因之一。 http://meta.stackexchange.com/questions/16356/why-cant-table-markup-elements-be-used/29368#29368 – 2010-07-15 13:32:42

0

业务对象,因为它们被命名,显然应该配置自己的业务逻辑,即业务逻辑在服务层中的域之间的动态。另一方面,BO可以作为数据容器(DTO?)的组成和方法吗?意味着BO是纯粹的函数?这可以避免BO和DTO之间的所有转换。

-1

在MVC架构中,

我们可以说模型包含业务对象。

2

我们已经使用了Rocky Lhotka的CSLA框架多年,并且喜欢它的设计方式。在该框架中,所有功能都包含在对象中。虽然我可以看到将逻辑分离出来的价值,但我认为我们不会很快摆脱这种理念。

+0

优秀点。我也在一些项目上使用过CSLA。我从来没有想过把它列入我们的辩论。 – Walter 2010-11-14 13:54:20