在设计服务层时,我应该在接口契约中使用我的领域对象吗?例如:
公共无效注册用户(字符串用户名,字符串实名)
VS
公共无效注册用户(用户用户)
域对象应该在客户端代码中还是在服务外观之后构建?
我正在使用 EJB,我的客户端将是本地部署的 Web 应用程序、RMI 客户端,也可能是 Web 服务客户端。
在设计服务层时,我应该在接口契约中使用我的领域对象吗?例如:
公共无效注册用户(字符串用户名,字符串实名)
VS
公共无效注册用户(用户用户)
域对象应该在客户端代码中还是在服务外观之后构建?
我正在使用 EJB,我的客户端将是本地部署的 Web 应用程序、RMI 客户端,也可能是 Web 服务客户端。
从技术上讲,使用一个或另一个没有问题:通过 XSD 的 Web 服务能够支持像字符串这样的原始类型和像用户类这样的复杂对象。
现在,如果你的User
类有 20 个属性,而你只需要username
和realName
注册一个用户怎么办?在这种特殊情况下,最好使用您的第一种方法,因为如果您不强迫您的客户端构建不需要的大型 XML 文档,则需要更少的带宽。
其他情况是您的 User 类根据 JAXB 规则生成复杂且高度嵌套的 XML 文档。这可以为您的客户和复杂的客户实现产生复杂的消息。如果是这种情况,您可以使用域类的更简单版本(可能具有一两个嵌套级别)作为 DTO 来简化消息交换。
在我看来,服务层一般不应该使用域对象。域是处理业务逻辑、规则和工作流的东西,而服务提供了一个接口。
设计服务层时最简单的原则是“服务方法实现单个用例”。(用例是一个输入和输出都定义得很好的场景)。
在您的示例中 - registerUser(String username, String realName)
- 看起来非常好。服务将实例化所有需要的域对象并启动业务操作 - 同时,服务客户端不知道业务逻辑内部(例如,可能有一些特定的用户对象构造等)
在您的所有服务中传递 User 对象似乎没有什么害处。根据 DDD(域驱动设计http://en.wikipedia.org/wiki/Domain-driven_design),这是一个非常好的做法,您的所有域对象都应该在项目的所有层中可用。从长远来看,它将使您的代码更加面向对象,这通常在典型的 Java EE 项目(又名贫血域模型)中被视为缺乏,但唯一的额外建议是您尝试将业务逻辑保留在 User 类中,而不是在您的服务中.
在我看来,从门面层暴露领域对象是不合适的。使用该服务的客户端不应依赖于域对象。最好设计一个数据合约并将它们从外观层公开。它们将仅用于传输数据,即 DTO。考虑到域对象不仅仅是 DTO,它们可以提供一些无功能的东西。此外,外观层中的服务暴露了系统的使用,它可能包括多个领域对象的某些部分的协作,有时可能在外观层中的方法的需求和可用的领域对象之间没有合适的映射。此外,出于网络性能的原因,DTO 及其结构可能需要考虑一些因素。而这些考虑在设计领域对象时通常没有意义。
域对象应该在客户端代码中还是在服务外观之后构建?
域对象应该在服务端创建。客户端仅传递创建对象所需的所有参数。
对象构造的一般算法是:
如果在客户端创建一个对象并传递给服务,那么会出现几个问题: