很久以前我读过一篇文章(我相信一篇博客文章),它让我在命名对象的“正确”轨道上:非常非常谨慎地命名程序中的东西 .
例如,如果我的应用程序(作为一个典型的业务应用程序)处理用户,公司和地址我有一个 User
,一个 Company
和一个 Address
域类 - 可能在某个地方 UserManager
,一个 CompanyManager
和一个 AddressManager
会弹出这个句柄那些事 .
所以你能告诉那些 UserManager
, CompanyManager
和 AddressManager
做什么?不,因为Manager是一个非常通用的术语,适用于您可以对域对象执行的任何操作 .
我读过的文章建议使用非常具体的名称 . 如果它是一个C应用程序并且 UserManager
的工作是分配并从堆中释放用户,那么它将无法管理用户,但会保护他们的出生和死亡 . 嗯,也许我们可以称之为 UserShepherd
.
或者可能是 UserManager
's job is to examine each User object'的数据并以加密方式对数据进行签名 . 然后我们有一个 UserRecordsClerk
.
现在这个想法一直困扰着我,我尝试应用它 . 并且非常难以找到这个简单的想法 .
我可以描述这些类的功能和(只要我不进入快速和脏编码)我写的类完全是 one . 我想念从名称到名称的是一种名称目录,一种将概念映射到名称的词汇表 .
最终我想在我的脑海里有类似图案目录的东西(通常设计图案很容易提供对象名称,例如工厂)
-
Factory - 创建其他对象(从设计模式中命名)
-
牧羊人 - 牧羊人处理物体的生命,它们的创建和关闭
-
Synchronizer - 在两个或多个对象(或对象层次结构)之间复制数据
-
Nanny - 帮助对象在创建后达到“可用”状态 - 例如通过连接到其他对象
-
等
那么,你如何处理这个问题呢?你有一个固定的词汇表,你是否动态发明新的名字,或者你认为命名的东西不是那么重要或错误?
P.S . :我也对链接到讨论这个问题的文章和博客感兴趣 . 首先,这是让我思考的原始文章:Naming Java Classes without a 'Manager'
更新:答案摘要
以下是我在此期间从这个问题中学到的内容的一些总结 .
-
尽量不要创造新的比喻(保姆)
-
看看其他框架的作用
关于这个主题的进一步文章/书籍:
-
What names do you find yourself prepending/appending to classes regularly?
-
书籍:Design Patterns: Elements of Reusable Object-Oriented Software (Hardcover)
-
书籍:Patterns of Enterprise Application Architecture (Hardcover)
并且我从答案中收集了(主观上!)的当前名称前缀/后缀列表:
-
协调员
-
Builder
-
作家
-
读者
-
处理程序
-
容器
-
协议
-
目标
-
转换器
-
控制器
-
查看
-
工厂
-
实体
-
水桶
这条道路的一个好建议:
不要命名瘫痪 . 是的,名字非常重要,但它们不足以浪费大量时间 . 如果你不能在10分钟内想出一个好名字,继续前进 .
13 回答
如果我不能为我的 class 提供一个比XyzManager更具体的名称,那么我将重新考虑这是否真的是属于一个类的功能,即建筑“代码味道” .
如果我们正确地模拟现实世界,我们可以没有任何
xxxFactory
,xxxManager
或xxxRepository
类:;-)
我认为最重要的是要记住:名称是否足够描述?你能看到这个名字应该做什么吗?在类名中使用“经理”,“服务”或“处理程序”等词语可以被认为过于通用,但由于很多程序员使用它们,因此也有助于理解类的用途 .
我自己一直在使用外观模式(至少,我认为这就是所谓的) . 我可以有一个仅描述一个用户的
User
类,以及一个跟踪我的"collection of users"的Users
类 . 我不打电话给 classUserManager
因为我不想提醒他们:)简单地使用复数形式可以帮助我理解 class 的作用 .我认为这里的关键是在代码可见性范围内保持一致,即只要每个需要查看/处理代码的人都理解你的命名约定那么即使你决定调用它们也应该没问题 . 'CompanyThingamabob'和'UserDoohickey' . 如果您在公司工作,第一站是查看公司是否有命名约定 . 如果没有或者您不为公司工作,那么使用对您有意义的术语创建您自己的术语,将其传递给几个随意编码的可信赖的同事/朋友,并合并任何有意义的反馈 .
应用别人的约定,即使它被广泛接受,如果它没有从你的页面跳出来,那么我的书中有点错误 . 首先,我需要在不参考其他文档的情况下理解我的代码,但同时它需要是通用的对于同一行业中同一领域的其他人来说,这并不难理解 .
您可以看看source-code-wordle.de,我已经分析了.NET框架和其他一些库的类名最常用的后缀 .
前20名是:
属性
类型
帮手
集合
转换器
处理程序
info
提供者
例外
服务
元素
经理
节点
选项
工厂
上下文
项目
设计师
基地
编辑
特定于C#,我发现"Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries"有很多关于命名逻辑的好信息 .
至于找到那些更具体的单词,我经常使用词库并跳过相关的单词来尝试找到一个好单词 . 我尝试不花太多时间用它,但随着我在开发过程中的进展,我想出了更好的名字,或者有时意识到
SuchAndSuchManager
应该真的被分解成多个类,然后那个被弃用的类的名称变成非问题 .当我发现自己正在考虑在类名中使用
Manager
或Helper
时,我认为这是一种代码味道,这意味着我没有违反single responsibility principle,因此重构并在设计上投入更多精力通常会使命名变得更加容易 .但即使是精心设计的类也不会(总是)自己命名,而您的选择部分取决于您是创建业务模型类还是技术基础结构类 .
业务模型类可能很难,因为它们对于每个域都是不同的 . 我使用了很多术语,例如
Policy
用于域内的策略类(例如,LateRentalPolicy
),但这些术语通常来自于尝试创建“ubiquitous language”,您可以与业务用户共享,设计和命名类以便他们建模现实世界的想法,对象,行动和事件 .技术基础设施类更容易一些,因为它们描述了我们非常熟悉的域 . 我更喜欢将设计模式名称合并到类名中,例如
InsertUserCommand,
CustomerRepository,
或SapAdapter.
我理解关于沟通实现而不是意图的关注,但设计模式与类设计的这两个方面相结合 - 至少在你处理基础设施时,您希望实现设计即使在隐藏细节时也是透明的 .对于会发布在thedailywtf.com,“ManagerOfPeopleWhoHaveMortgages”等上的东西,这听起来像是一个滑坡 .
我认为一个单一的Manager类不是好设计是正确的,但使用'Manager'并不错 . 我们可能会将其分解为UserAccountManager,UserProfileManager,UserSecurityManager等,而不是UserManager .
“经理”是一个好词,因为它清楚地表明一个 class 并不代表现实世界的“事物” . 'AccountsClerk' - 我该如何判断这是一个管理用户数据的类,还是代表某人作为他们工作的会计文员?
与(例如)GOF book定义的模式相比,以及在这些模式之后的命名对象在命名类,组织它们和传达意图方面有很长的路要走 . 大多数人会理解这种命名法(或至少是其中的一个主要部分) .
我只是为了好名字而且我经常写下在选择名字时要特别小心的重要性 . 出于同样的原因,在命名事物时我对隐喻很谨慎 . 在最初的问题中,"factory"和"synchronizer"看起来就像它们似乎意味着的好名字 . 但是,"shepherd"和"nanny"不是,因为它们基于隐喻 . 你的代码中的一个类不能成为一个保姆;你称它为保姆,因为它照顾其他一些东西,非常像现实生活中的保姆照顾婴儿或小孩 . 这在非正式演讲中是可以的,但不是(在我看来)可以在代码中命名类,这些代码必须由谁知道谁知道何时知道 .
为什么?因为隐喻是文化依赖的,并且通常也是个人依赖的 . 对你来说,命名一个 class “保姆”可以非常清楚,但也许对其他人来说并不是那么清楚 . 除非您编写的代码仅供个人使用,否则我们不应该依赖它 .
在任何情况下,惯例都可以成就或破坏隐喻 . “工厂”本身的使用是基于一个比喻,但它已经存在了很长一段时间,并且目前在编程世界中是众所周知的,所以我认为使用它是安全的 . 然而,“保姆”和“牧羊人”是不可接受的 .
由于你对这个领域的文章感兴趣,你可能会对Steve Yegge的观点文章“名词王国的执行”感兴趣:
http://steve-yegge.blogspot.com/2006/03/execution-in-kingdom-of-nouns.html
我会考虑您用于系统的模式,类的命名约定/编目/分组往往由所使用的模式定义 . 就个人而言,我坚持这些命名惯例,因为它们是另一个人能够接受我的最有可能的方式代码并运行它 .
例如,UserRecordsClerk可能更好地解释为扩展UserRecordsClerk和CompanyRecordsClerk实现然后专注的通用RecordsClerk接口,这意味着可以查看接口中的方法以查看其子类通常用于什么 .
如果您还没有使用它,请参阅Design Patterns这样的书来获取信息,它的目标是使用您的代码! ; O)
我认为只要您的模式选择得恰到好处并尽可能使用,那么非常简单的直接类名应该足够了!
我问similar question,但在可能的情况下,我尝试复制.NET框架中已有的名称,并在Java和Android框架中寻找想法 .
似乎
Helper
,Manager
和Util
是您为协调不包含状态的类而附加的不可避免的名词,通常是程序性的和静态的 . 另一种选择是Coordinator
.您可以使用名称获得特别紫色的修辞,并选择
Minder
,Overseer
,Supervisor
,Administrator
和Master
之类的内容,但正如我所说,我更喜欢将其保留为您习惯使用的框架名称 .您在.NET框架中找到的一些其他常见后缀(如果这是正确的术语)是:
Builder
Writer
Reader
Handler
Container