如何设计业务逻辑层

5
为了更明确,我并不指望能够解决这个问题。显然,解决问题是找到答案的重要部分。但是,我没有很多处理良好架构的N层应用程序的经验,我不想最终得到一个难以管理的BLL。
目前,我们的业务逻辑基本上是一团混乱的线球。依赖性错综复杂,相同的业务逻辑被复制了多次。我现在的重点是将业务逻辑从我们所称的数据访问层中提取出来,以便我可以定义已知事件供订阅。我认为我想支持事件驱动/反应式编程模型。
我的希望是有特定可实现的目标,告诉我如何以适合业务逻辑的方式设计这些类集合。如果有区分良好BLL和不良BLL的事情,我想更多地了解它们。
作为一名经验丰富但相对谦虚的程序员,我请求社区成员的建议。
编辑1:
因此,验证逻辑置于业务对象中,但这意味着业务对象需要向GUI通信验证错误/逻辑。这让我考虑将业务操作实现为对象,而不是提供大量关于操作必需性的元数据的对象。我不喜欢代码克隆。

在我的答案中,代码是生成的,尽管这并非严格要求。只是因为很多逻辑是重复的,虽然以这种方式组织有一个好处,就是知道代码更改会进入 BS 文件(如果 DL 中有错误,则会进入其他 DL)。 - Neil
验证逻辑在我看来应该无处不在。 - annakata
您可以使用业务层中定义的专用异常类向 UI 传达有关任何验证错误的信息。 - Andres
2
@Andres,异常作为通信手段……我不太确定。它们是用于异常行为的,验证错误并不算异常情况。 - John Leidegren
我希望我能够给那个更多的赞。 - annakata
6个回答

3
这是一个很广泛的问题。使用ORM技术(例如NHibernate)将数据库与业务逻辑(可怕的术语)分离,这让你可以在大部分时间里保持面向对象编程(显然),并且从架构角度上来说,你可以忽略掉数据库方面的大部分内容。
接下来,我发现领域驱动设计(DDD)是将复杂系统分解为可管理块的最成功方法,尽管它没有得到足够的尊重,但我真正发现UML - 特别是操作和类图 - 在理解和交流系统设计方面非常有用。
总体建议:对一切进行接口化设计,从一开始就构建单元测试,并学会识别和分离可重用服务组件,这些组件可以作为子系统存在。顺便说一句,如果有一群人一起工作,我也会同意并积极使用stylecop :)

但是肯定不止这些。我明白“这取决于情况”,但我们追求解耦和分层架构的原因是有道理的,我只是想弄清楚为什么和如何BLL有意义。 - John Leidegren
2
我知道这不是一个具体的答案,但其实并没有正确的答案。就我个人而言,我相信关注点分离和正确性原则,而DDD是实现这一目标的一种方式。你想要解耦和分层的原因是,你越这样做,就越容易在整个系统中更改功能,而不会创建大量的开发和测试负担,因为软件永远不会完成,总是在变化。这一切都与变更控制有关,这是现代开发的重要组成部分。 - annakata
我只希望有某种明确的答案。这样,我就可以让我的老板(非技术人员)停止烦我,全力支持整个项目。然而,我每天都要重复自己,这很重要,你需要考虑这些事情(关注点分离和正确性原则不仅是信仰,还有足够的证据支持这一点)。我理解你的意思。虽然我对领域驱动设计不是很熟悉,但也许有些新知识可以从中汲取。 - John Leidegren
1
欢迎来到这场战争 - 管理层永远不会理解或欣赏你做那些并不直接为他们赚钱的事情,如果你做得足够好,他们很可能会让你变得多余 :) - annakata
哦,看一下,迪尔伯特 http://feedproxy.google.com/~r/DilbertDailyStrip/~3/mjv5lqlbqn8/ - John Leidegren
显示剩余4条评论

2

我发现领域驱动设计的一些实践对于将复杂的业务逻辑分解为更易管理/可测试的块非常有效。

请查看以下链接中的示例代码:

http://dddpds.codeplex.com/

DDD专注于您的领域层或者说BLL,如果你愿意,希望这会有所帮助。


1

我们只是从架构的角度来谈论这个问题,而其核心仍然是“抽象、抽象、抽象”。

您可以使用EBC进行自顶向下的设计,并将接口定义传递给程序员团队。使用这样的方法(或任何其他可视化技术),可视化依赖关系可以防止在项目中重复业务逻辑。


这很有趣,我不知道EBC。绝对值得探索。我不确定多少是直接适用的,但无论如何我都可以从中学习。谢谢。 - John Leidegren

0

0

嗯,我可以告诉你我们在一个相当大的数据库中心应用程序中使用的技术。我们有一个类来管理数据层,就像你建议的那样,它以DL为后缀。我们有一个程序自动生成这个源文件(非常方便),不过这也意味着如果我们想要扩展功能,你需要派生这个类,因为在重新生成源代码时会覆盖它。

我们还有另一个以OBJ结尾的文件,它仅定义了数据层处理的实际数据库行。

最后但并非最不重要的是,通过一个良好构造的基类,有一个以BS结尾的文件(代表业务逻辑)作为唯一一个没有自动生成的文件,定义事件方法如“New”和“Save”,通过调用基类,完成默认操作。因此,任何从规范偏离的变化都可以在该文件中处理(包括必要时完全重写默认功能)。

对于每个表及其子表(或孙子表),您应该创建一个此类文件的单个组。您还需要一个工厂,其中包含所有对象的完整名称,以便可以通过反射创建任何对象。因此,要修补程序,您只需派生出基本功能并更新数据库中的一行,以便工厂创建该对象而不是默认对象。

希望这能有所帮助,不过我会将其作为社区维基响应留下,这样或许您可以获得更多关于这个建议的反馈。

0
关于“编辑1” - 我遇到过这个问题很多次。我完全同意你的观点:同样的验证必须在多个地方进行。
我过去解决这个问题的方式是以某种方式封装验证规则。可以是元数据/XML,也可以是独立的对象,或者其他什么方式。只要确保它是可以从业务对象请求并在其他地方执行的东西。这样,你只需要编写一次验证代码,然后可以由你的业务对象、UI对象甚至第三方使用你的代码的消费者来执行。
但有一个注意事项:有些验证规则很容易封装/传输,比如“姓氏是必填字段”。然而,你的一些验证规则可能太复杂,涉及的对象太多,无法轻松封装或在元数据中描述:“用户只能在不是员工的情况下使用该优惠券,并且订单是在劳动节周末下的,并且购物车中有2到5件特定类型的商品,除非他们还有其他商品在购物车中,但只有当颜色是我们的‘首发促销’颜色之一时,除了……” - 你知道业务‘逻辑’是怎样的!;)
在这些情况下,我通常只接受事实,即仅在业务层进行一些额外的验证,并确保当这些错误发生时有一种方式将其传播回 UI 层(无论如何,您都需要该通信渠道来报告持久性层错误)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接