4

我相信 OO,但不至于应该使用不适当的设计/实现来实现“OO 兼容”。

那么,如何应对 Serlvet/EJB/DataContainer 分层架构:

  • Servlet 接收请求并调用“业务层”(例如会话 EJB)
  • 业务层从数据库中定位DataContainers并对其进行操作以实现业务逻辑
  • DataContainers 不包含真正的代码,只是获取/设置对应于数据库。

这种方法很有吸引力;DataContainers 清楚地知道它们的作用,并且很容易知道数据的来源。

除了不是 OO 之外,这还会导致业务层类不清楚,难以命名和组织。

即使我们试图更加“OO”(例如,将其中一些方法放在 DataConatiners 中),其中一些操作对不止一组数据进行操作。

您如何防止业务层变得混乱,但又不会用业务逻辑污染您的 DataContainer?

例子

class UserServlet {
  handleRequest() {
    String id = request.get("id");
    String name = request.get("name");
    if (UserBizLayer.updateUserName(id,name))
      response.setStatus(OK);
    else
      response.setStatus(BAD_REQUEST);
  }
}

class UseBizLayer {
    updateUserName(String id, String name) {
        long key = toLong(id);
        user = userDAO.find(key);
        if user == null
            return false;
        if (!validateUserName(name))
            return false;
        user.setName(name);
        userDAO.update(user);
        return true;
    }

    validateUserName(String name) {
        // do some validations and return
    }
}

class User {
    long key;
    String name;
    String email;

    // imagine getters/setters here
}
  • 我们不想要validateUserName用户,因为它只对名称进行操作;我想它可以进入另一个类,但是我们有另一个程序“uti”类型类
  • 我们不希望在 User 上使用持久化方法,因为将数据结构与其持久化策略解耦是有价值的
  • 我们不希望 Servlet 中包含业务逻辑,因为我们可能需要在其他地方重用该逻辑
  • 我们不希望我们的业务逻辑在我们的用户中,因为这对用户类有太多的吸引力,使得业务逻辑的重用变得困难,并将用户与其持久性策略相耦合

我意识到这个例子并没有那么糟糕,但是想象一下 10 个 DataContainers 和 20 个 BizLayer 对象,每个对象都有几个方法。想象一下,其中一些操作并非“以”特定数据容器为中心。

我们如何防止这成为程序上的混乱?

4

6 回答 6

3

因此,我将在几个要点中解决我对此的想法:

  1. 似乎在 Java EE 系统中,有时您必须处理 Java EE 的管道,管道并不总是受益于 OO 概念,但它肯定可以通过一点创造力和工作来实现。例如,您可以利用 AbstractFactory 等东西来帮助尽可能多地通用此基础架构。
  2. 您正在研究的很多内容都在 Eric Evans 的优秀著作《领域驱动设计》中进行了讨论。我强烈建议您查看它,因为他确实解决了表达领域知识和处理支持它的技术基础设施的问题。
  3. 在阅读并 GROKD 一些 DDD 之后,我会将我的技术基础架构封装在存储库中。存储库都将被编写为使用基于会话 EJB 的持久性策略。您将编写一个知道如何与会话 EJBS 对话的默认实现。要完成这项工作,您需要添加一些约定并在您的界面中指定该约定/约定。存储库完成所有的 CRUD,并且仅在绝对需要时才应该做更多的事情。如果您说“我的 DAOS 是我的存储库”,那么我会同意。
  4. 所以继续这个。您需要一些东西来封装在 UseBizLayer 中表达的工作单元。在这个级别上,我认为它的本质是你被困在编写所有将成为事务脚本的代码。您正在创建责任和状态的分离。这通常是我在 Java EE 系统中看到它作为一种默认架构完成的方式。但它不是面向对象的。我会尝试探索该模型,看看我是否至少可以尝试将写入 BizClasses 的一些行为通用化。
  5. 我之前使用的另一种方法是去掉 BizLayer 类,然后将来自域的调用代理到执行操作的实际存储库/DAO。然而,这可能需要在基础设施建设方面进行一些投资。但是您可以使用像 Spring 这样的框架做很多事情,并使用一些 AOP 概念来使其正常工作并减少所需的自定义基础架构的数量。
于 2008-09-30T15:30:44.327 回答
1

由于您正在实现类和对象,因此无论您如何分层,您的解决方案都将是面向对象的 - 根据您的情况/需求,它的结构可能不是很好!;-)

至于您的具体问题,在某些情况下, validateUserName 属于 User 类是有意义的,因为每个 User 都希望有一个有效的名称。或者,您可以拥有一个验证实用程序类,假设其他事物具有使用相同验证规则的名称。电子邮件也是如此。您可以将它们拆分为 NameValidator 和 EmailValidator 类,如果它们会被大量使用,这将是一个很好的解决方案。您还可以在刚刚调用实用程序类方法的 User 对象上提供一个 validateUserName 函数。所有这些都是有效的解决方案。

OOD/OOP 的一大乐趣在于,当设计正确时,您就知道它是正确的,因为很多事情只是从模型中掉出来,您可以做到以前无法做到的。

在这种情况下,我会创建 NameValidator 和 EmailValidator 类,因为其他实体将来可能会有名称和电子邮件地址,但我会在 User 类上提供 validateName 和 validateEmailAddress 函数,因为这样可以为 biz 提供更方便的界面使用的对象。

其余的“我们不想要”的子弹都是正确的;它们不仅是正确分层所必需的,而且对于干净的 OO 设计也是必需的。

基于层之间的关注点分离,分层和 OO 密切相关。我认为您的想法是正确的,但是需要一些实用程序类来进行常见的验证

于 2008-09-30T15:14:30.980 回答
1

想想如果没有计算机,这些任务将如何完成,并以这种方式为您的系统建模。

简单示例... 客户填写表格请求小部件,将其交给员工,员工验证客户身份,处理表格,获取小部件,将小部件和交易记录提供给客户并保存公司某处的交易记录。

客户是否存储他们的数据?不,员工会。员工在存储客户数据时扮演什么角色?客户记录保管员。

表格是否验证已正确填写?不,员工会。员工在这样做时扮演什么角色?表单处理器。

谁给客户小部件?充当小部件分销商的员工

等等...

要将其推送到 Java EE 实现中...

Servlet 代表客户端执行操作,填写表单(从 HTTP 请求中提取数据并生成适当的 Java 对象)并将其传递给适当的员工(EJB),然后由员工处理表单需要完成的事情. 在处理请求时,EJB 可能需要将其传递给另一个专门处理不同任务的 EJB,其中一部分将包括从/向存储(您的数据层)访问/放入信息。唯一不应该直接映射到类比的应该是关于对象如何相互通信以及数据层如何与存储通信的细节。

于 2008-09-30T15:15:11.573 回答
0

我自己也有同样的想法。

在传统的 MVC 中,最重要的是将 View 与 Model 和 Controller 部分分开。将控制器和模型分开似乎是个好主意,因为您最终可能会得到臃肿的模型对象:


public class UserModel extends DatabaseModel implements XMLable, CRUDdy, Serializable, Fooable, Barloney, Baznatchy, Wibbling, Validating {
  // member fields
  // getters and setters
  // 100 interface methods
}

尽管您可以为上述许多接口使用单独的控制器(或整个模式),是的,它本质上是相当程序化的,但我想这就是现在的工作方式。或者,您可以意识到某些接口正在做同样的事情(CRUDdy - 数据库存储和检索,Serializable - 与二进制格式相同,XMLable,与 XML 相同),因此您应该创建一个单独的系统来处理这个问题,使用每个潜在的后端都是系统处理的单独实现。天哪,写的真烂。

也许有像“co-classes”这样的东西,让你有单独的源文件用于控制器实现,就好像它们是它们所作用的模型类的成员一样。

至于业务规则,它们经常同时处理多个模型,因此它们应该是分开的。

于 2008-09-30T15:17:36.963 回答
0

我认为这是一个关于“关注点分离”的问题。您似乎在分层架构的正确轨道上走了很长一段路,但也许您需要做更多相同的事情 - 即在您的 Java EE 层中创建架构层?

DataContainer 看起来很像数据传输对象 (DTO) 模式。

现代 OO 设计有很多小类,每个小类都与少数“朋友”相关,例如通过组合。这可能会产生比您真正熟悉的更多的类和 Java 样板,但它应该会产生更好的分层设计,并且更容易进行单元测试和维护。

(+1 代表问题,+1 代表您何时知道自己拥有分层权利的答案)

于 2009-10-14T21:43:24.707 回答
-1

粗略地说,“我们不想要”部分必须删除。要么你希望它是正确的,要么你希望它保持原样。当你需要一个类时,创建一个类是没有意义的。“我们有很多”是一个糟糕的借口。

确实,公开所有内部类不好的,但根据我的经验,为每个概念创建一个类(即一个用户、一个 ID、一个数据库概念......)总是有帮助的。

其次,Facade 模式难道不是可以解决大量 BizRules 类的存在,隐藏在一个组织良好且干净的界面后面吗?

于 2008-09-30T14:59:23.343 回答