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对象的看法,并且遇到了问题(或者说它工作得很好)...
答案 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 layer
是data layer
和POJO
之间的附加层。 Business Layer
对象表现为Presentation Layer
和POJO
之间的数据载体。 {{1}}非常适合这个,因为它们是非常轻的对象,具有属性作为存取方法。
休息取决于你。如果你想在其中使用带有业务逻辑的复杂bean对象,我认为任何Web框架都不会阻止你这样做。
希望这有帮助。
答案 4 :(得分:0)
“我最想知道的是为什么我从未见过使用#1。”关注点分离,单一责任原则(可能最重要的是),可测试性等。“一切都与一切相结合”的模型很方便,但客观上很糟糕。 (这并不是说方便的API表面很糟糕,但它们应该构建在经过充分考虑的,可测试的代码上,而不是代替它。)
例如,当您在业务逻辑层上添加“哑”DTO层时,每个视图都映射到包含创建视图所需的所有内容的bean,您可以解决诸如必须保持会话打开的问题获取关联的属性,或者争论ORM以急切地获取它们。 (前者也暗示N + 1选择了增加数据库往返的问题。)
如果每个请求都由专用服务层上的单个方法调用提供,它还可以更轻松地跟踪事务范围。这个调用是对数据的单个逻辑操作,这使得设置事务处理变得微不足道。
最后但并非最不重要的是,这种方法会导致更容易理解和改变的小班。例如。如果您需要更改用于计算成绩点平均值的算法,请从GradePointAverageCalculator
开始并从那里导航,而不是代码范围,您需要将其视为“Student.java
,第1340行到第1486行,然后1502年至1689年,......“