design-patterns - pattern书 - naming convention中文




命名类-如何避免将所有事情都称为“<WhatEver>管理器”? (9)

很久以前,我阅读了一篇文章(我相信这是一篇博客文章),这篇文章将我置于命名对象的“正确”轨道上:在程序中对命名进行非常谨慎。

例如,如果我的应用程序(作为典型的商业应用程序)处理用户,公司和地址,我将拥有一个User ,一个Company和一个Address域类 - 可能在UserManagerAddressManagerAddressManager某个AddressManager会弹出该句柄那些事。

那么你能说出那些UserManagerAddressManagerAddressManager功能吗? 不,因为经理是一个非常通用的术语,适合任何你可以用你的域对象做的事情。

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

或者UserManager的工作是检查每个用户对象的数据并以密码方式签署数据。 然后我们会有一个UserRecordsClerk

现在,这个想法坚持我,我尝试应用它。 发现这个简单的想法非常困难。

我可以描述这些课程的作用,并且(只要我不陷入快速和肮脏的编码),我写的课程只能做件事。 我想从描述到名称的想法是一种名称目录,这是一个将概念映射到名称的词汇表。

最终,我想在我的脑海里有一个类似于模式目录的东西(通常设计模式很容易提供对象名称,例如工厂

  • 工厂 - 创建其他对象(从设计模式中获取命名)
  • 牧羊人 - 牧羊人处理对象的生命周期,他们的创建和关闭
  • 同步器 - 在两个或多个对象(或对象层次结构)之间复制数据
  • 保姆 - 帮助物体在创建后达到“可用”状态 - 例如通过连线到其他物体

  • 等等

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

PS:我也对链接​​讨论这个问题的文章和博客感兴趣。 作为开始,以下是让我思考的原始文章: 命名Java类没有“经理”

更新:答案摘要

以下是我在此期间从这个问题中学到的一些小结。

  • 尽量不要创造新的隐喻(保姆)
  • 看看其他框架的功能

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

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

  • 协调员
  • 生成器
  • 作家
  • 读者
  • 处理器
  • 容器
  • 协议
  • 目标
  • 变流器
  • 调节器
  • 视图
  • 实体

并且为这条道路提供一个好的提示:

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


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

前20名是:

  • 属性
  • 类型
  • 帮手
  • 采集
  • 变流器
  • 处理器
  • 信息
  • 提供商
  • 例外
  • 服务
  • 元件
  • 经理
  • 节点
  • 选项
  • 上下文
  • 项目
  • 设计师
  • 基础
  • 编辑

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


当我发现自己想要在类名中使用ManagerHelper时,我认为它是一种代码异味,意味着我还没有找到正确的抽象和/或违反单一责任原则 ,因此重构并付出更多努力进入设计往往使得命名更容易。

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

业务模型类可能很难,因为它们对于每个域都不相同。 有一些术语我使用了很多,例如Policy在某个域中的策略类(例如LateRentalPolicy ),但这些LateRentalPolicy通常是从尝试创建一种“ 无处不在的语言 ”开始的,您可以与业务用户共享这些语言 ,设计和命名类,以便他们模拟真实世界的想法,对象,行为和事件。

技术基础设施类比较容易一些,因为它们描述了我们非常熟悉的领域。 我更喜欢将设计模式名称合并到类名称中,例如InsertUserCommand, CustomerRepository,SapAdapter. 我理解关于实现而非意图沟通的担心,但设计模式与类设计的这两个方面结合在一起 - 至少在您处理基础结构时,即使在隐藏细节时实现设计仍然是透明的。


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

例如,UserRecordsClerk可能会更好地解释为扩展了UserRecordsClerk和CompanyRecordsClerk实现并专用的通用RecordsClerk接口,这意味着可以查看接口中的方法以查看其子类通常使用/通常使用的方法。

看到一本书,比如Design Patterns for info,这本书很棒,可以帮助你清理你的代码 - 如果你还没有使用它的话! ; O)

我认为只要你的模式选择得当,并尽可能使用,那么非常不直观的类名就够了!


我认为最重要的一点是:名称是否足够描述? 你可以通过查看这个名字来告诉班级应该做什么? 在你的类名中使用诸如“经理”,“服务”或“处理程序”之类的词可以被认为是过于通用的,但是由于很多程序员使用它们,它也有助于理解类是什么。

我自己一直在使用立面图案(至少,我认为这就是它所称的)。 我可以有一个只描述一个用户的User类和一个跟踪我的“用户集合”的Users类。 我不把这个班级称为UserManager因为我不喜欢现实生活中的管理者,也不想让他们想起他们:)只要使用复数形式,就可以帮助我理解班级的作用。


我都是名副其实的,而且我经常写关于在选择名字时非常谨慎的重要性。 基于同样的原因,我在命名事物时对比喻很谨慎。 在原始问题中,“工厂”和“同步器”看起来像是他们似乎意义的好名字。 然而,“牧羊人”和“保姆”不是,因为它们是基于隐喻的 。 你的代码中的一个类不能成为保姆; 你称它为保姆,因为它看起来非常像现实生活中的保姆照顾婴儿或孩子。 这在非正式的演讲中没有问题,但是在我看来,对于代码中的类名的确定并不确定,而这些代码必须由谁知道谁知道何时知道。

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

无论如何,惯例可以制造或破坏一个隐喻。 “工厂”本身的使用基于一个隐喻,但已经存在了一段时间,目前在编程领域中广为人知,所以我认为它的使用是安全的。 然而,“保姆”和“牧羊人”是不可接受的。



这听起来像是在dailywtf.com上发布的东西的一个滑溜溜,“有人有跑步经理经理”等。

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

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


随着(比方说) GOF书定义的模式,以及命名对象的命名对象使我在命名类,组织它们和传达意图方面有很长的路要走。 大多数人会理解这个术语(或者至少是它的一个主要部分)。







naming