【问题标题】:What naming convention do you use for the service layer in a Spring MVC application? [closed]您对 Spring MVC 应用程序中的服务层使用什么命名约定? [关闭]
【发布时间】:2012-10-18 21:16:01
【问题描述】:

我一直在为 Spring 应用程序中的服务层找出一个好的命名约定。对于服务层中的每个类,我首先编写它应该实现的接口,然后是实际的类。所以例如我有以下界面:

public interface UserAccountManager{
   public void registerUser(UserAccount newUserAccount);
   public void resetPassword(UserAccount userAccount);
...
}

然后是实现类……

让我烦恼的是,UserAccountManager 是实现类的好名字,所以我不得不给它起一个愚蠢的名字,比如 SimpleUserAccountManager 或 UserAccountDbManager。 到目前为止,您使用了哪些约定?将实现类放在不同的包中并赋予它们与接口相同的名称是一个好主意吗? 另外,您对使用以 Manager 结尾的名称而不是以 Service 结尾的名称有何看法?

【问题讨论】:

    标签: java spring naming-conventions spring-mvc


    【解决方案1】:

    这是我们使用的:

    • XxxDAO(数据访问对象) - 负责与 EntityManager 、 JDBC DataSource 、文件系统等直接交互。应该只包含持久化逻辑,例如 SQL 或 JPA-QL,但不包含(或尽可能少)业务逻辑。只能从经理访问。
    • XxxManager - 在业务级别管理实体,通常执行 CRUD 操作,但添加所需的业务逻辑。
    • Xxx服务 - 业务逻辑所在的层。应该尽可能用简单的对象(字符串、整数等)“说话”。
    • XxxController - UI 交互层。只应与服务对话。
    • XxxUtilities/XxxUtils - Helper 无状态方法,不应该依赖于系统中的任何服务。如果您需要这种依赖关系,请将实用程序类转换为服务或将服务结果添加为参数。

    对于实现,我们添加 Impl 后缀 (XxxServiceImpl),以将其与接口区分开来,如果有多个实现或我们想要添加其他信息,我们将其添加为前缀(JdbcXxxDaoImpl、GoogleMapsGeocodingServiceImpl 等)。这样类名会变得有点长,但它们非常具有描述性和自我记录性。

    【讨论】:

    • 能否明确XxxManager和XxxService的职责?谢谢。
    • 我喜欢这个,但我颠倒了Manager和Service层,所以Service调用到Dao中,Manager包含业务逻辑。
    • 我以前从未见过一个单独的层称为 manager,我不明白它的作用。它通常是我的域层所在的位置。
    • XxxModel - 包含 POJO
    • 包含应用业务层的包可以命名为“服务”吗?
    【解决方案2】:

    Spring 本身为接口提供通用名称,然后根据实现的细节为类命名。这是一个想到的例子:

    interface: Controller
    abstract classes: AbstractController, AbstractCommandController, 
                      SimpleFormController, MultiActionController
    

    我不认为 SimpleUserAccountManager 或 UserAccountDbManager 之类的名称很愚蠢,因为它们传达了有关管理器/服务实施的一些信息。

    我觉得愚蠢的是在实现类中添加“Impl”后缀的常见约定:

    my/package/UserAccountManager
    my/package/impl/UserAccountManagerImpl
    

    不过有些人更喜欢这个。

    【讨论】:

    • 那么你会同时调用接口和 impl UserAccountManager 吗?
    • 在运行 jdepend 之类的工具时,将代码分为“接口包”和“实现包”是很舒服的。它可以帮助您了解代码更改的影响。
    • @Dejelu,我相信 kgiannakakis 用示例进行了正确解释。而不是使用 Impl,我们应该使用它的具体实现。例如,在 DataAccessLayer 上,我们可以有接口“User”,实现类可以后缀为 DataBase API,例如 UserDSE(cassandra 特定实现)、UserHBASE(HBase 特定实现)等。
    • @Dejell 如果您同时调用接口和具体实现,那么至少其中一个名称是错误的。接口需要更通用的名称,或者 UserAccountManagerImpl 需要更具体的名称,例如 AwsUserAccountManager。
    【解决方案3】:

    对于您给出的示例,我将使用反映类如何执行操作的实现名称​​,例如 HibernateUserAccountManager、JPAUserAccountManager 或 JDBCUserAccountManager 等,或者可能只是 UserAccountManagerDAO。

    【讨论】:

    • ++ 得到了很好的答复,但是在类名中完全大写缩写的做法...... 颤抖
    【解决方案4】:

    类名以Manager 还是Service 结尾显然并不重要。一般来说,重要的是名称准确地传达了正在建模的内容。这就是问题的症结所在:“服务”或“经理”并不是我们在软件对象中尝试建模的真实世界对象。相反,它们是我们收集一堆方法的地方,这些方法所做的事情根本不符合我们确实需要/想要建模的任何对象的职责。

    我个人更喜欢“服务”,但这只是因为“经理”看起来像是可以实际建模的东西,即我们的“-manager”对象可能代表现实世界的经理。但这完全是学术性的,我立即承认它没有任何实际意义。

    真正重要的事情通常远比这些细节更基本:拥有一个让所有参与开发的人都很好理解的模型。如果我的经验是可以参考的,那很少是这样的。因此,对于那些询问“经理”或“服务”是否是正确比喻的人,我的建议是:掷硬币,确保每个人都知道约定,然后花时间思考和讨论重要的事情!

    【讨论】:

    • 我喜欢第一段,它传达了一个常见问题:不适合模型类的任意逻辑最终聚合在一个类中——这违反了单一责任原则,这会导致代码耦合。为什么不根据其含义将逻辑解耦为具有有意义名称的不同类。我宁愿完全避免使用 Service/Manager 后缀,因为对于许多人来说,将他们拥有的任何东西放在“Service/Manager”类中的诱惑太高了。
    【解决方案5】:

    我觉得 ServiceManager 的命名后缀纯粹是一种偏好。唯一一次让我们感到困惑的是“服务”是在我们的服务层之上还有 Web 服务的时候。在某些项目中,我们将 Web 服务类简单地称为代理,因为它们所做的只是将 Web 服务调用转换或代理为对我们服务层的调用。

    我同意 kgiannakakis 的观点,即使用“Impl”为您的实现添加后缀不是一个好方法。我也遇到过提到不要这样做的编码最佳实践。在抽象之后命名接口是公认的最佳实践。正如 kgiannakakis 所建议的,在接口之后命名实现类并带有其目的或类型的一些指示符,似乎是普遍接受的方法。

    当我们拥有基于 Web 服务的 DAO 和基于 ORM 的 DAO 时,我们使用包和类名来区分实现类与它们的接口以及彼此之间的区别。我认为将实现放在不同的包中取决于您在包中有多少类,它们的实现方式有何不同,以及您希望将它们拆分多少。

    【讨论】:

    • 这就是为什么我认为 Manager 会减少混乱,因为应用程序的前端位于 Flex 中,并且 AMF 服务位于服务层之上。好点子。
    【解决方案6】:

    您还可以将接口命名为 IUserAccountManager(例如,此约定在 Eclipse RCP 中使用),然后使用 UserAccountManager 作为默认实现。

    【讨论】:

      【解决方案7】:

      对我来说,服务类是关于实现一个用例的,所以我根据服务所代表的用户类型来命名它。因此,如果我有一个具有不同角色的应用程序,比如客户、订单履行人员、数据输入人员和管理员,那么我可能会有一个 CustomerService、一个 OrderFulfillmentService、一个 DataEntryService 和一个 AdminService。我认为根据获取或处理的数据类型来命名服务是一种反模式。所以猜测 UserAccount 操作将是管理员的域,我可能会称之为“AdminService”。

      【讨论】:

        【解决方案8】:

        关于managers和services的区别: 我会说尽可能长时间地为业务逻辑(服务层或管理者层)使用一层。

        一旦该层变得复杂(假设您使用了服务),您就可以添加负责委派一个或另一个服务的管理器,但将业务逻辑保留在服务中。

        所以我会保持服务简单,使用管理器来管理服务,并将业务逻辑保留在服务中。

        我也同意在实现中避免使用 Impl 后缀,而在接口中避免使用 I 后缀。例如,将接口命名为“Controller”并将实现命名为“SimpleController”或“UserController”对我来说听起来更好。

        【讨论】:

          【解决方案9】:

          假设这些是针对 REST 服务的,我认为您的 URI 命名约定比底层实现服务的名称更重要,因为后者在很大程度上对客户端是不可见的。当然,您希望内部命名一致,但这并不重要。

          我们使用的一些 REST 指南:http://soaprobe.blogspot.co.uk/2012/10/soa-rest-service-naming-guideline.html(我的博客)

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2014-10-02
            • 1970-01-01
            • 1970-01-01
            • 2022-10-13
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多