2

Web 框架似乎总是偏离良好的 OO 代码(您将代码和数据组合在一个对象中,考虑向该对象发送消息等)

主要问题似乎是bean模式的存在。您使用 bean 模式(现在通常称为 POJO,因为人们似乎不了解其中的区别)与数据库、Web 服务和大多数其他事物进行交互。

所以,不,你会被这个没有代码的 setter 和 getter 所困——所以你倾向于添加一堆——本质上是静态函数来操作这些东西。OO 代码的几乎所有优点都消失了。

我看到了我正在考虑的三个解决方案,但想知道其中任何一个是否有任何严重的缺点。

1) 使用 POJO 模式而不是 bean 模式。这意味着从您的 POJO 中消除 setter 和 getter(这样您就可以拥有封装/数据安全),而是添加业务逻辑方法。这似乎是最有意义的——事实上,我认为这就是为什么像 hibernate 这样的库从需要 Bean 转为允许 POJO 的原因,但似乎每个人仍然使用 bean 模式。

2) 使用业务逻辑类扩展您的 Bean,该业务逻辑类使用 bean 的字段作为存储。这似乎很不稳定且有问题,但是很容易将其放入现有的代码库中作为迁移的一种方式...

3) 用业务逻辑对象包装 Bean 模式对象。大多数情况下,如果#1确实有问题,我认为这可能是必要的。

我最想知道的是为什么我从未见过#1 被使用过。我真的很想听听任何使用 Pojo 模式(有业务逻辑,没有 setter 和 getter)来处理休眠对象并且遇到问题(或者让它工作得很好)的人......

4

6 回答 6

3

我会将我的评论更改为答案。我基本上不同意你的开场白

Web 框架似乎总是偏离良好的 OO 代码。

Java EE 或 Spring/JPA 模型中没有任何东西“远离良好的 OO 代码”。像 hibernate 这样的 JPA 提供程序允许 POJO 的事实并不意味着您不能使用在 bean 中定义业务逻辑的富域模型。对于 Java Web 应用程序,我已经看到它以两种方式完成——丰富的域模型,或者在服务层中具有业务逻辑的贫乏域模型,这不是非 OO 或糟糕的设计。

我想你的意思可能是很多应用程序没有用正确的设计和/或正确的 OO 编写。 会同意的。但这与框架无关......

因此,您提出的解决方案基本上都说“使用良好的 OO 原则正确设计您的应用程序”。选项 1 是最简单的。

于 2012-10-10T20:15:34.887 回答
1

我对您在这里争论的确切内容感到困惑,正如您所说的那样,人们都倾向于将 bean 称为“POJO”,然后您建议不要使用 bean,而是使用“POJO”。但要回应这一点:

所以,不,你会被这个没有代码的 setter 和 getter 所困——所以你倾向于添加一堆——本质上是静态函数来操作这些东西。OO 代码的几乎所有优点都消失了。

我不同意这一点——如果你正在编写静态函数来操作你的对象,那么你的设计就有问题。

通常,常见/“最佳”实践是您将业务逻辑包装在类的“服务层”中,该类知道如何操作数据(在您的 bean、POJO、域对象中表示,无论您想调用它们什么)作为响应到应用程序的规则。

没有人阻止你让你的“服务层”是面向对象设计的,有子类和继承等等。

通常,您不会看到有人构建了一个应用程序,其中Employee保存数据的类还包含对 执行操作的方法和逻辑Employee,因为人们倾向于将数据(由Employee类表示)与逻辑分开。而且实际上,一旦你开始拥有对Employee类中的员工实例进行操作的方法,那么你需要让Employee类能够调用存储层本身,现在你使用 Hibernate 来表示结果的类查询(Employee类)也引用了 Hibernate 代码来加载自己,它变得一团糟。

我认为您看到的“问题”只是您对这些类型的应用程序常见的设计理念的分歧。大多数人希望将数据的表示方式与封装应用程序逻辑的代码分开。

于 2012-10-10T20:25:33.367 回答
1

将(大部分)业务逻辑保留在数据对象之外是有充分理由的,但最佳设计将包括其中的某些部分。要做到这一点并不容易,尤其是在蓝领团队环境中,我猜这是所有 Java 开发团队的 95%。

我喜欢将一些简单的、独立的、可广泛重用的逻辑片段放入我的数据对象中;本质上与该数据耦合的代码,而不考虑任何特定的业务请求。例如一些转换、验证等。

至于 getter 和 setter,我不惜一切代价避免使用它们。您可以使用公共最终字段,或者只是普通的公共字段。getter+setter 组合为您提供与公共字段一样多的封装:零。

至于 ORM 解决方案,我严格使用 Hibernate 作为 SQL 的便利,而不是作为持久状态管理器。映射类只是作为 XML 映射的替代品。它们甚至从未在读取操作中实例化。对于插入,我单独保存每个对象,它与单个数据库行一对一映射,没有传递持久性。这基本上意味着我的 Hibernate 模型对象只是一种查看数据库行的 Java 方式(加上方便的连接列规范——没有那些冗余连接条件的 HQL 看起来要好得多)。

于 2012-10-10T21:16:04.913 回答
0

根据最佳实践,业务逻辑应该与表示逻辑分开。大多数 Web 框架都围绕数据的呈现提供了很好的功能。任何涉及数据检索/操作的业务逻辑都应该写在和Business Layer之间,这是一个额外的层。对象充当 和 之间的数据载体。确实是很好的候选者,因为它们是非常轻的对象,具有作为访问器方法的属性。presentation layerdata layerPOJOBusiness LayerPresentation LayerPOJO

休息由你决定。如果您想使用其中包含业务逻辑的复杂 bean 对象,我认为任何 Web 框架都不会阻止您这样做。

希望这可以帮助。

于 2012-10-10T20:18:09.643 回答
0

“我最想知道的是为什么我从未见过 #1 被使用过。” 关注点分离、单一职责原则(可能是最重要的)、可测试性等。“一切都耦合到一切”的模型很方便,但客观上很糟糕。(这并不是说方便的 API 界面不好,但它们应该构建在经过良好分解的、可测试的代码之上,而不是代替它。)

例如,当您在业务逻辑层上添加一个“哑” DTO 层时,其中每个视图都映射到包含创建视图所需的所有内容的 bean,您摆脱了诸如必须保持会话打开以获取关联的问题属性,或者让 ORM 急切地获取它们。(前者还意味着有 N+1 个选择问题,这会增加数据库往返次数。)

如果每个请求都由专用服务层上的单个方法调用提供服务,它还可以更轻松地跟踪事务范围。然后,此调用是对数据的单个逻辑操作,这使得设置事务处理变得微不足道。

最后但并非最不重要的一点是,这种方法导致更容易理解和自行更改的小类。例如,如果您需要更改计算平均绩点的算法,则从那里开始GradePointAverageCalculator并从那里导航,而不是您需要查看的代码范围是“ Student.java,第 1340 到 1486 行,然后是 1502 到 1689,……”

于 2012-10-10T20:22:51.520 回答
0

也许您可以查看其他 Knockout(一个 javascript 框架)使用的模型-视图-视图模型设计模式。在这里,视图模型作为模型和视图之间的层被引入,提供了将视图与模型分离的可能性。

在这里阅读更多信息:http: //knockoutjs.com/documentation/observables.html ..和这里http://en.wikipedia.org/wiki/Model_View_ViewModel

于 2012-10-10T21:01:05.487 回答