46

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

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

然后是实现类...

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

4

9 回答 9

63

这是我们使用的:

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

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

于 2009-06-16T12:58:40.617 回答
19

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

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

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

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

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

不过有些人更喜欢这个。

于 2009-06-15T11:04:54.193 回答
10

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

于 2009-06-15T12:41:22.837 回答
8

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

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

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

于 2010-11-19T13:50:12.327 回答
3

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

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

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

于 2009-06-15T12:10:05.767 回答
2

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

于 2009-06-15T14:12:20.700 回答
2

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

于 2010-11-30T18:31:08.700 回答
1

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

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

于 2012-10-05T09:39:00.980 回答
1

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

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

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

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

于 2012-10-09T08:38:06.100 回答