【问题标题】:Class data responsibilities类数据职责
【发布时间】:2008-10-04 00:24:32
【问题描述】:

我有一个“采购订单”课程。它包含有关单个采购订单的信息。我有一个用于数据库方法的 DAO 类。

加载和更新采购订单的方法的责任应该在哪里?

PurchaseOrder 类是否应该具有直接使用 DAO 类的“.update”、“insert”、“delete”和“.load”方法,或者 PurchaseOrder 类是否应该不了解 DAO 方法并具有 POController 类管理这些交互?

用户一次只能处理一个 PurchaseOrder。

谢谢!

【问题讨论】:

    标签: design-patterns class-design


    【解决方案1】:

    采购订单应该不知道其持久性的细节。这就是拥有某种数据访问层的意义所在,它处理对象的管理,而对象本身可以专注于只是一个采购订单。

    这也使系统更易于测试,因为您可以创建模拟采购订单并测试系统如何处理它们的逻辑,而不会陷入持久性问题。

    【讨论】:

      【解决方案2】:

      我会通过将 PurchaseOrder 设为接口并将所有 DAO 代码放入实现中来保持简单,然后使用工厂。

      【讨论】:

        【解决方案3】:

        这取决于您认为您的应用程序将存在多长时间。我公司的金属切削应用程序自 1985 年以来一直在不断发展,并通过计算机架构的多次变化进行移植。在我们的例子中,我们几乎总是将事情推到接口(或使用您的术语的控制器类)后面,因为我们不知道 5、10、15 年后的事情状态。

        通过使用控制器类,我们可以更改底层 API,而不会篡改上面的业务逻辑级别和 UI 调整。这些级别代表了多年的工作,因此保持他们的行为很重要。

        请记住,您的项目在生命周期中的大部分时间都处于维护状态。您现在所做的任何让以后更改设计变得更容易的事情都将在以后节省大量时间。

        【讨论】:

          【解决方案4】:

          PurchaseOrder 类应该不知道 DAO。 purchaseOrder 类应该代表数据本身,仅此而已。使用控制器或服务管理器或任何您想要调用它的东西来使用 DAO 持久/加载 PurchaseOrder 记录。这为您的设计提供了最大的灵活性。您有一个数据模型的位置,一个用于存储/检索 PurchaseOrders 的业务逻辑(控制器)的位置,以及一个实际持久化的位置。

          【讨论】:

            【解决方案5】:

            让我告诉你我的推理:

            类方法
            基本原则:持久化是类行为,应该是类方法
            您需要分离关注点,因此您将数据库的细节放在 DAO 类中,并使用该类中的它来实现方法。
            第一个问题:如果您需要支持不同的 DAO 集,您需要通过工厂创建它们。 第二个问题:并非所有持久性行为都与类的实例特别相关。例如 List 和 Search 方法:它们返回类列表,而不是类,并且不依赖于实例。所以它们基本上是静态方法。
            第三个问题:你想支持这个类的继承。因此,持久性细节因父母而异。如果你有静态方法,那将是一个问题。

            所以你继续前进

            控制器
            基本原则:持久化方法不属于单个类,它们比较大,应该分开
            再次需要关注点分离,因此您需要 DAO。这是一个实用程序类,所以方法基本上都是静态
            第一个问题:如果你想支持多个持久化方法,你需要一个工厂来创建 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...
            

            【讨论】:

              【解决方案6】:

              我肯定会将“业务逻辑”(PurchaseOrder)与数据库交互/访问分开。如果您转向不同的供应商等,您可以更轻松地更改访问权限,而不会干扰业务实施,而且您可以更轻松地避免向数据库访问层添加行为。

              【讨论】:

                【解决方案7】:

                就我个人而言,我会创建一个管理交互的对象。我不能为不将此逻辑放在 PurchaseOrder 类本身中提出强有力的理由,但创建此控制器对象会导致更松散耦合的对象。

                【讨论】:

                  【解决方案8】:

                  这里要考虑的关键是您将来可能想做的事情。也许你想用另一个替换你的数据库?这就是为什么您绝对应该将用于与数据库交互的代码与代表 PO 的类分开的原因。这是基本的职责分离,我希望你已经做到了。

                  现在的问题是:您是否想要第三个类(控制器)来管理 PO 和 DAO 类之间的交互?我认为这取决于您可以为 DAO 类创建接口的通用程度。如果 DAO 接口足够通用,您可以使用不同的存储机制编写插件替代它,但不更改接口,那么我会让 PO 类与之交互。如果没有,那么我会编写一个控制器类。

                  要考虑的另一件事是结构的其余部分。保存/加载从哪里开始?如果您要对 PO 进行大量操作(保存、加载、打印、发送给客户),那么拥有一个控制器来完成所有这些操作而不是将功能集成到 PO 类中可能是有意义的.它为您提供了无需修改 PO 类即可添加 PO 操作的优势。

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2021-12-31
                    • 1970-01-01
                    • 1970-01-01
                    • 2016-10-21
                    相关资源
                    最近更新 更多