命名类 - 如何避免将所有内容称为“<whatever> Manager”?</whatever>

时间:2009-12-08 12:55:29

标签: design-patterns oop naming-conventions naming

很久以前我读过一篇文章(我相信一篇博客文章),它让我在命名对象的“正确”轨道上:非常谨慎地命名程序中的东西。

例如,如果我的应用程序(作为一个典型的商业应用程序)处理用户,公司和地址,我会有UserCompanyAddress域类 - 并且可能会出现一个UserManager,一个CompanyManager和一个AddressManager来处理这些事情。

那么你能告诉那些UserManagerCompanyManagerAddressManager做什么吗?不,因为Manager是一个非常通用的术语,适用于您可以对域对象执行的任何操作。

我读过的文章建议使用非常具体的名称。如果它是一个C ++应用程序并且UserManager的工作正在分配并从堆中释放用户,那么它将不会管理用户,而是保护他们的出生和死亡。嗯,也许我们可以称之为UserShepherd

或者UserManager的工作可能是检查每个User对象的数据并以加密方式对数据进行签名。然后我们有一个UserRecordsClerk

现在这个想法一直困扰着我,我尝试应用它。并且非常难以找到这个简单的想法。

我可以描述这些类的功能和(只要我不进入快速和简单的编码)我写的类完全是一个的东西。我想念从名称到名称的是一种名称目录,一种将概念映射到名称的词汇表。

最终,我希望在我的脑海里有类似图案目录的东西(通常设计图案很容易提供对象名称,例如 factory

  • Factory - 创建其他对象(从设计模式中命名)
  • 牧羊人 - 牧羊人处理物体的生命,它们的创建和关闭
  • Synchronizer - 在两个或多个对象(或对象层次结构)之间复制数据
  • Nanny - 帮助对象在创建后达到“可用”状态 - 例如通过连接到其他对象

  • 等等。

那么,你如何处理这个问题呢?你有一个固定的词汇表,你是否动态发明新的名字,或者你认为命名的东西不那么重要或错误?

P.S。:我也对讨论这个问题的文章和博客的链接感兴趣。首先,这是让我思考它的原始文章:Naming Java Classes without a 'Manager'


更新:答案摘要

以下是我在此期间从这个问题中学到的内容的一点摘要。

  • 尽量不要创造新的比喻(保姆)
  • 了解其他框架的作用

关于此主题的更多文章/书籍:

我从答案中收集的(主观上!)当前名称前缀/后缀列表:

  • 协调员
  • 生成器
  • 作家
  • 阅读器
  • 处理程序
  • 容器
  • 协议
  • 目标
  • 转换器
  • 控制器
  • 查看
  • 实体
  • 铲斗

这条道路的好建议:

  

不要命名瘫痪。是的,名字非常重要,但它们不足以浪费大量时间。如果你在10分钟内想不出一个好名字,继续前进。

13 个答案:

答案 0 :(得分:179)

我问了similar question,但在可能的情况下,我尝试复制.NET框架中已有的名称,并在Java和Android框架中寻找想法。

似乎HelperManagerUtil是您为协调不包含状态的类而附加的不可避免的名词,通常是程序性和静态的。另一种选择是Coordinator

您可以使用这些名称获得特别紫色的内容,并选择MinderOverseerSupervisorAdministratorMaster之类的内容,但是我说我更喜欢把它当作你习惯的框架名称。

您在.NET框架中找到的一些其他常见后缀(如果这是正确的术语)是:

  • Builder
  • Writer
  • Reader
  • Handler
  • Container

答案 1 :(得分:108)

您可以查看source-code-wordle.de,我已经分析了.NET框架和其他一些库的类名最常用的后缀。

前20名是:

  • 属性
  • 辅助
  • 集合
  • 转换器
  • 处理程序
  • 信息
  • 提供商
  • 例外
  • 服务
  • 元素
  • 管理器
  • 节点
  • 选项
  • 工厂
  • 上下文
  • 项目
  • 设计者
  • 编辑

答案 2 :(得分:60)

我都是为了好名字,我经常写下在选择名字时要特别小心的重要性。出于同样的原因,在命名事物时我对隐喻持谨慎态度。在最初的问题中,“工厂”和“同步器”看起来就像它们似乎意味着的好名字。然而,“牧羊人”和“保姆”不是,因为它们基于隐喻。代码中的一个类不能字面上一个保姆;你称之为保姆,因为它照顾其他一些非常像现实生活的保姆照顾婴儿或小孩。这在非正式演讲中是可以的,但不是(在我看来)可以在代码中命名类,这些类必须由谁知道谁知道何时维护。

为什么呢?因为隐喻是文化依赖的,并且通常也是个人依赖的。对你来说,命名一个班级“保姆”可以非常清楚,但也许对其他人来说并不是那么清楚。除非您编写的代码仅供个人使用,否则我们不应该依赖它。

在任何情况下,惯例都可以成就或破坏隐喻。 “工厂”本身的使用是基于一个比喻,但它已经存在了很长一段时间,并且目前在编程世界中是众所周知的,所以我认为使用它是安全的。然而,“保姆”和“牧羊人”是不可接受的。

答案 3 :(得分:46)

如果我们正确地模拟现实世界,我们可以不使用任何xxxFactoryxxxManagerxxxRepository类:

Universe.Instance.Galaxies["Milky Way"].SolarSystems["Sol"]
        .Planets["Earth"].Inhabitants.OfType<Human>().WorkingFor["Initech, USA"]
        .OfType<User>().CreateNew("John Doe");

- )

答案 4 :(得分:35)

这听起来像是一个滑动的斜坡,可以发布在thedailywtf.com上,“ManagerOfPeopleWhoHaveMortgages”等等。

我认为一个单一的Manager类不是好设计是正确的,但使用'Manager'并不错。我们可能会将其分解为UserAccountManager,UserProfileManager,UserSecurityManager等,而不是UserManager。

'经理'是一个好词,因为它清楚地表明一个类不代表一个现实世界的“事物”。 'AccountsClerk' - 我该如何判断这是一个管理用户数据的类,还是代表某个职员的工作人员?

答案 5 :(得分:23)

由于您对这方面的文章感兴趣,您可能对Steve Yegge的观点文章“名词王国中的执行”感兴趣:

http://steve-yegge.blogspot.com/2006/03/execution-in-kingdom-of-nouns.html

答案 6 :(得分:19)

当我发现自己在考虑在类名中使用ManagerHelper时,我认为这是一种代码味道,这意味着我还没有找到正确的抽象和/或我违反了single responsibility principle,所以重构和更多的努力设计往往使命名更容易。

但即使是精心设计的类也不会(总是)自己命名,而您的选择部分取决于您是创建业务模型类还是技术基础结构类。

商业模式类可能很难,因为它们对每个域都不同。我使用了很多术语,例如Policy用于域内的策略类(例如LateRentalPolicy),但这些术语通常来自尝试创建“ubiquitous language”,你可以与业务用户共享,设计和命名类,以便他们模拟真实的想法,对象,操作和事件。

技术基础架构类更容易一些,因为它们描述了我们非常熟悉的域。我更喜欢将设计模式名称合并到类名中,例如InsertUserCommand, CustomerRepository,SapAdapter.我理解关于沟通实现而非意图的关注,但设计模式与类设计的这两个方面相结合 - 至少在您处理基础架构时,您希望实现 design 在您隐藏详细信息时保持透明。

答案 7 :(得分:10)

如果我不能为我的班级提供比XyzManager更具体的名称,那么我将重新考虑这是否真的是一个属于一个类的功能,即建筑“代码味道”。

答案 8 :(得分:9)

使用(例如)GOF book定义的模式,并且在这些模式之后的命名对象在命名类,组织它们和传达意图方面有很长的路要走。大多数人都会理解这种命名法(或至少是其中的一个主要部分)。

答案 9 :(得分:7)

我认为最重要的是要记住:名称是否足够描述?你能看一下这个名字应该做什么吗?在类名中使用“经理”,“服务”或“处理程序”等词语可以被认为过于通用,但由于许多程序员使用它们,因此也有助于理解该类的用途。

我自己一直在使用外观模式(至少,我认为这就是所谓的)。我可以有一个只描述一个用户的User类,以及一个跟踪我的“用户集合”的Users类。我没有把班级称为UserManager因为我不喜欢现实生活中的经理而且我不想被提醒他们:)简单地使用复数形式可以帮助我理解班级的作用。

答案 10 :(得分:5)

特定于C#,我发现"Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries"有很多关于命名逻辑的好信息。

就找到那些更具体的单词而言,我经常使用词库并跳过相关单词来尝试找到一个好单词。我尝试不花费太多时间,因为我在开发过程中提出了更好的名称,或者有时意识到SuchAndSuchManager应该被分解为多个类,然后是那个已弃用的类的名称变得没有问题。

答案 11 :(得分:2)

我认为这里的关键是在代码的可见性范围内保持一致,即只要每个需要查看/处理代码的人都理解你的命名约定那么即使你决定也应该没问题。称他们为'CompanyThingamabob'和'UserDoohickey'。如果您在公司工作,第一站是查看公司是否有命名约定。如果没有或者您不为公司工作,那么使用对您有意义的术语创建您自己的术语,将其传递给几个随意编码的可信赖的同事/朋友,并纳入任何有意义的反馈。< / p>

应用别人的约定,即使它被广泛接受,如果它没有从你的页面跳出来,那么我的书中有点错误。首先,我需要在不参考其他文档的情况下理解我的代码,但同时它需要足够通用,以至于同一行业中同一领域的其他人都无法理解。

答案 12 :(得分:2)

我会考虑您用于系统的模式,类的命名约定/编目/分组往往由所使用的模式定义。就个人而言,我坚持这些命名约定,因为它们是最有可能让另一个人能够拿起我的代码并运行它。

例如,UserRecordsClerk可能更好地解释为扩展UserRecordsClerk和CompanyRecordsClerk实现然后专注的通用RecordsClerk接口,这意味着可以查看接口中的方法以查看其子类通常用于什么。< / p>

有关信息,请参阅Design Patterns这样的书,它是一本很好的书,可以帮助您清理您的目标 - 如果您还没有使用它! ; o)

我认为只要您的模式选择得恰到好处并尽可能使用,那么非常简单的直接类名就足够了!