类数据责任
我有一个"采购订单"课程。它包含有关单个采购订单的信息。我有一个用于数据库方法的DAO类。
负责加载和更新采购订单的方法的责任应该在哪里?
PurchaseOrder类是否应具有直接使用DAO类的'.update','insert','delete'和'.load'方法,或者PurchaseOrder类应忽略DAO方法并具有一个POController类来管理这些方法互动?
用户一次只能处理一个采购订单。
谢谢!
解决方案
我肯定会从数据库交互/访问中分离出"业务逻辑"(PurchaseOrder)。如果我们转移到其他供应商等位置,则可以更轻松地对访问进行更改,而不会潜在地干扰业务实现,并且可以更轻松地避免向数据库访问层添加行为。
采购订单应不了解其持久性的详细信息。这就是拥有某种数据访问层的关键所在,它可以处理对象的管理,并且对象本身可以专注于仅作为采购订单。
这也使系统更易于测试,因为我们可以创建模拟的采购订单并测试系统如何处理订单的逻辑,而不会陷入持久性问题。
就个人而言,我将创建一个管理交互的对象。我没有理由不将这种逻辑放在PurchaseOrder类本身中,但是创建此控制器对象将导致对象之间的耦合更加松散。
这取决于我们认为应用程序将保留多长时间。自1985年以来,我公司的金属切割应用程序就得到了不断的发展,并且由于计算机体系结构的多种变化而不断发展。在我们的案例中,我们几乎总是将事物推到一个接口(或者使用术语的控制器类)的后面,因为我们不会一直处于5、10、15年的状态。
通过使用控制器类,我们可以更改基础的API,而不会影响上面的业务逻辑和UI调整级别。这些级别代表了多年的工作,因此保持其行为很重要。
请记住,项目将在整个生命周期中都处于维护阶段。我们现在所做的使以后更容易更改设计的任何事情,都将为我们节省大量的时间。
PurchaseOrder类应忽略DAO。 PurchaseOrder类应该代表数据本身,仅此而已。使用控制器或者服务管理器或者任何我们想调用的名称,以使用DAO持久化/加载PurchaseOrder记录。这为我们提供了最大的设计灵活性。对于数据模型,我们有一个位置,在业务逻辑(控制器)中,如何存储/检索PurchaseOrders有一个地方,在它的实际持久位置中有一个地方。
这里要考虑的关键是我们将来可能想要做的事情。也许我们想将数据库替换为另一个数据库?这就是为什么我们一定要将与数据库交互的代码与代表PO的类分开的原因。这是基本的责任分离,我希望我们已经做到了。
现在的问题是:我们是否需要第三类(控制器)来管理PO和DAO类之间的交互?我认为这取决于我们可以对DAO类进行界面的通用性。如果DAO接口足够通用,那么我们可以使用其他存储机制为其编写插件替代品,而无需更改接口,那么我将让PO类与之交互。如果没有的话,我会写一个控制器类。
要考虑的另一件事是结构的其余部分。从何处开始保存/加载?如果我们要对PO进行很多操作(保存,加载,打印,发送给客户),那么有一个控制器可以执行所有这些操作,而不是将功能集成到PO类中可能很有意义。 。它为我们提供的优点是,我们可以添加PO操作,而无需修改PO类。
通过将PurchaseOrder设置为接口并将所有DAO代码放入实现中,然后使用工厂,可以简化此过程。
让我向我们介绍我的推理:
类方法
基本原理:持久性是一种阶级行为,应该是一种阶级方法
我们需要将关注点分离,因此我们需要将数据库包含在DAO类中,并使用该类中的类来实现方法。
第一个问题:如果需要支持不同的DAO集,则需要通过工厂创建它们。
第二个问题:并非所有持久性行为都与该类的实例特别相关。例如List和Search方法:它们返回Class列表,而不是类,并且不依赖于实例。因此,它们本质上是静态方法。
第三个问题:我们想在此类上支持继承。因此,持久性细节因父母而异。如果我们有静态方法,那将是一个问题。
所以你继续
控制器
基本原理:持久性方法不属于单个类,它们较大,因此应该分开
再次需要分离关注点,因此我们需要DAO。这是一个Utility类,因此方法基本上都是静态的。
第一个问题:如果要支持多个持久性方法,则需要一个Factory来创建DAO。
第二个问题:我们希望支持类的层次结构,因此不能使用静态类。我们需要通过工厂生成控制器。
第三个问题:我们正在向开发人员提供过于复杂的API。
客户代码示例:
PurchaseOrder po; PurchaseOrderController poc; poc = PurchaseOrderControllerFactory.Instance.Create(); po = poc.GetPurchaseOrder(42); // do stuff poc.SavePurchaseOrder(po);
那我将从头开始。
从行为开始
基本原则:持久性不是行为。行为大于持久性。
在系统中,将有一个采购订单子系统。用户将只能在高级别(用例级别)上与之交互。因此,这些方法将实现"采购订单"用例。这些方法将在需要时通过工厂使用DAO,以访问数据库并执行其所需的任何操作。
简而言之,PurchaseOrder本质上是DTO,是一种快速传递数据的方法。它不应该有行为。
客户代码示例:
// It could be a factory if needed. PurchaseOrderSystem pos = new PurchaseOrderSystem(); List<PurchaseOrder> transacted; transacted = pos.TransactPurchaseOrders(john, 23); // Show transacted purchase orders or whatever...