寻找在服务器端使Web框架更加OO的最佳方法

时间:2012-10-10 20:05:15

标签: java hibernate javabeans pojo oop

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

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

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

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

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

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

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

我最想知道的是为什么我从未见过#1。我真的很想听到那些使用Pojo模式(有业务逻辑,没有setter和getter)的人对hibernate对象的看法,并且遇到了问题(或者说它工作得很好)...

5 个答案:

答案 0 :(得分:3)

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

  

Web框架似乎总是偏离优秀的OO代码。

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

我想也许你想说的是很多应用程序没有用适当的设计和/或适当的OO编写。 我同意。但这与框架无关......

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

答案 1 :(得分:1)

我很困惑你在这里争论的是什么,正如你所说人们倾向于称豆“POJO”然后你建议你使用“POJO”而不是使用bean。但要回应这一点:

  

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

我不同意这一点 - 如果你正在编写静态函数来操纵你的对象,你设计的东西就错了。

通常,常见/“最佳”做法是将业务逻辑包装在知道如何操作数据的类的“服务层”中(在bean,POJO,域对象中表示,无论您想要调用它们) )响应申请规则。

没有人阻止您将“服务层”设计为OO,具有子类和继承以及所有这些。

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

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

答案 2 :(得分:1)

有充分的理由将(大部分)业务逻辑保留在数据对象之外,但最佳设计将包括其中的某些部分。这不是很容易做对,特别是在蓝领团队设置中,我猜95%的Java开发团队都在那里。

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

就吸气剂和孵化器而言,我会不惜一切代价避免它们。您可以使用公共最终字段,也可以只使用普通公共字段。 getter + setter组合为您提供与公共字段完全相同的封装:零。

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

答案 3 :(得分:0)

根据最佳实践,业务逻辑应与表示逻辑分开。大多数Web框架都提供了有关数据表示的很好的功能。数据检索/操作中涉及的任何业务逻辑都应该用Business Layer编写,presentation layerdata layerPOJO之间的附加层。 Business Layer对象表现为Presentation LayerPOJO之间的数据载体。 {{1}}非常适合这个,因为它们是非常轻的对象,具有属性作为存取方法。

休息取决于你。如果你想在其中使用带有业务逻辑的复杂bean对象,我认为任何Web框架都不会阻止你这样做。

希望这有帮助。

答案 4 :(得分:0)

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

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

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

最后但并非最不重要的是,这种方法会导致更容易理解和改变的小班。例如。如果您需要更改用于计算成绩点平均值的算法,请从GradePointAverageCalculator开始并从那里导航,而不是代码范围,您需要将其视为“Student.java,第1340行到第1486行,然后1502年至1689年,......“