我环顾四周,看到了一些很棒的代码片段,用于定义规则、验证、业务对象(实体)等,但我不得不承认,我从未见过完整的优秀且编写良好的业务层。
我只知道我不喜欢什么,但不知道什么是伟大的。
谁能指出一些好的 OO 业务层(或出色的业务对象),或者让我知道他们如何判断业务层以及是什么让一个业务层变得出色?
谢谢
我环顾四周,看到了一些很棒的代码片段,用于定义规则、验证、业务对象(实体)等,但我不得不承认,我从未见过完整的优秀且编写良好的业务层。
我只知道我不喜欢什么,但不知道什么是伟大的。
谁能指出一些好的 OO 业务层(或出色的业务对象),或者让我知道他们如何判断业务层以及是什么让一个业务层变得出色?
谢谢
我从未遇到过编写良好的业务层。
[...] 如果您考虑一下,软件应用程序中的几乎每一行代码都是业务逻辑:
- 客户数据库表及其 CustomerNumber (CHAR-13)、ApprovedDate (DATETIME) 和 SalesRepName (VARCHAR-35) 列:业务逻辑。如果不是,它只是 Table032 与 Column01、Column02 和 Column03。
- 将 10% 折扣扩展到新客户的子程序:绝对是业务逻辑。希望不是软编码。
- 以及以红色突出显示逾期发票的代码:这也是业务逻辑。Internet Explorer 肯定不会寻找字符串“unpaid”和“30+ days”,然后去,嘿,如果有 #990000 背景,那肯定会很好看!
那么如何将所有这些业务逻辑封装在单层代码中呢?当然是糟糕的架构和糟糕的代码!
[...] 通过暗示系统架构应该包括一个专门用于业务逻辑的层,许多开发人员采用了各种非常聪明的技术来实现该目标。它总是以灾难告终。
我想这是因为一般来说,业务逻辑是任意且令人讨厌的。垃圾进垃圾出。
此外,大多数真正优秀的业务层很可能是专有的。;-)
良好的业务层是经过彻底的领域分析设计的。如果您可以捕获业务的语义并将其与任何类型的实现隔离,无论是在数据存储中还是在任何特定应用程序(包括表示)中,那么逻辑应该在不同的上下文中进行良好的分解和可重用。
就像一个好的数据库模式设计应该捕获业务语义并将自己与任何应用程序隔离一样,业务层也应该这样做,即使数据库模式和业务层描述相同的实体和概念,两者也应该可以在不同的上下文中使用--即使业务逻辑发生变化,数据库架构也不必更改,除非架构不反映当前业务。业务层应该与任何存储模式一起工作,只要它是通过中间层抽象出来的。例如,ADO.NET 实体框架允许您设计一个映射到业务层的概念架构,并具有到存储架构的单独映射,无需重新编译业务对象层或概念层即可更改该映射。
如果业务方面的人可以查看用业务层编写的代码并大致了解正在发生的事情,那么这可能很好地表明对象设计正确——你已经成功地传达了一个解决方案问题域而不用来自解决方案域的工件来混淆它。
我总是被困在一块石头和一个坚硬的地方之间。理想情况下,您的业务逻辑根本不关心数据库或 UI 相关问题。
键引起问题 尽管如此,我发现诸如主键和外键之类的东西会引起问题。即使是像 Entity Framework 这样的工具也不能完全消除这种蠕变。将作为 POST 数据传递的 ID 转换为它们各自的对象,仅将其传递给业务层,然后再将它们传递给数据层以再次被剥离,这是非常低效的。
甚至 NoSQL 数据库也存在问题。它们倾向于返回完整的对象模型,但它们通常返回的比您需要的多,并且可能导致问题,因为您假设对象模型不会改变。在 NoSQL 数据库中仍然可以找到密钥。
重用与开销 还有代码重用的问题。数据层返回完全填充的对象是很常见的,包括该特定表中的每一列。但是,业务逻辑通常只关心此信息的有限子集。它适用于仅携带相关数据的专用数据传输对象。当然,您需要在表示之间进行转换,因此您创建了一个映射器类。然后,当您保存时,您需要以某种方式将这些较小的对象转换回完整的数据库表示或执行部分更新(意味着另一个 SQL 命令)。
所以,我看到很多业务层类接受直接映射到数据库表(数据传输对象)的对象。我还看到很多业务层也接受原始 UI 值(表示对象)。业务层在计算过程中调用数据库以检索所需数据的情况也很常见。尝试预先获取它可能效率低下(想想 if 语句如何影响检索到的数据),并且延迟加载的值会导致对数据库的大量魔术或意外调用。
先写逻辑 最近,我一直在尝试先写“核心”代码。这是执行实际业务逻辑的代码。我不了解你,但很多时候在查看别人的代码时,我会问这样一个问题,“但是,它在哪里做 [业务规则]?” 通常,业务逻辑充满了对抓取数据、转换数据等问题的关注,以至于我什至看不到它(大海捞针)。所以,现在我首先实现逻辑,当我弄清楚我需要什么数据时,我将其添加为参数或将其添加到参数对象。让其余代码适应这个新接口通常落在某种中介类上。
不过,就像我说的那样,在编写业务层时,你必须牢记很多,包括性能。上面的方法最近很有用,因为我还没有版本控制或数据库模式的权限。我在一个黑暗的房间里工作,到目前为止我只了解需求。
编写时考虑到测试 利用依赖注入对于预先设计好的架构很有用。尝试考虑如何在不访问数据库或其他服务的情况下测试代码。这也适用于可以在多个上下文中运行的小型、可重用的类。
结论 我的结论是,确实不存在完美的业务层。即使在同一个应用程序中,有时一种方法也只能在 90% 的时间内起作用。我们能做的最好的事情就是尝试编写最简单的东西。在很长一段时间内,我都避免使用 DTO 并使用对象包装 ADO.NET DataRows,因此更新会立即记录在底层 DataTable 中。这是一个巨大的错误,因为我无法复制对象,并且约束导致在奇怪的时间抛出异常。我这样做只是为了避免显式设置参数值。
Martin Fowler 已经在博客中广泛介绍了 DSL。我建议从那里开始。
学习和使用CSLA.Net对我很有帮助(如果你是一名 MS 专家)。我从未实现过“纯”CSLA 应用程序,但使用了架构中提出的许多想法。
您最好的选择是继续寻找难以捉摸的灵丹妙药,并使用最适合您正在解决的问题的想法。把事情简单化。
我发现的一个问题是,即使您有一个设计良好的业务层,也很难阻止业务逻辑泄漏,而开发工具往往会鼓励这种情况。例如,一旦您将验证器控件添加到 ASP.NET WebForm,您就会让业务逻辑泄漏到视图中。验证应该发生在业务层中,并且只有它的结果显示在视图中。一旦您向数据库添加约束,您的数据库中也会有业务逻辑。不过,DBA 类型往往强烈反对最后一点。
我也没有。我们不会在应用程序中创建业务层。相反,我们使用MVC-ARS。业务逻辑嵌入在 (S) 状态机和 (A) 动作中。
可能是因为在现实中我们永远无法将业务逻辑与“流程”、输入、输出、接口完全解耦,最终人们发现很难处理抽象,更不用说将其与现实联系起来了。