很久以前,我读过一篇文章(我相信是一篇博客文章),这篇文章让我在命名对象方面走上了“正确”的道路:对程序中的事物命名要非常谨慎。

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

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

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

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

现在这个想法一直困扰着我,我试着去应用它。我发现这个简单的想法非常难。

我可以描述这些类做什么,(只要我不陷入快速和肮脏的编码)我编写的类只做一件事。我错过了从描述到名称的一种名称目录,一种将概念映射到名称的词汇表。

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

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

那么,你如何处理这个问题?你有固定的词汇表吗?你是临时发明新的名字吗?还是你认为给不那么重要或错误的东西命名?

注:我还对讨论这个问题的文章和博客的链接感兴趣。首先,这是一篇让我思考的原创文章:在没有“管理器”的情况下命名Java类


更新:答案摘要

下面是我从这个问题中学到的一点总结。

尽量不要制造新的隐喻(保姆)看看其他框架做什么

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

你发现自己经常在课前加上什么名字?命名类的最佳方法是什么?书:设计模式:可重用面向对象软件的元素(精装本)书:企业应用程序架构的模式(精装本)书:实现模式(平装)

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

协调员建设者作家读者处理程序容器协议目标转换器控制器看法工厂实体水桶

还有一个很好的建议:

不要陷入命名麻痹。是的,名字很重要,但它们不够重要,不足以浪费大量时间。如果你不能在10分钟内想出一个好名字,那就继续吧。


当前回答

如果我们正确地模拟了真实世界,那么我们就可以不使用任何xxxFactory、xxxManager或xxxRepository类:

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

;-)

其他回答

具体到C#,我发现“框架设计指南:可重用.NET库的惯例、习语和模式”中有很多关于命名逻辑的好信息。

至于寻找那些更具体的单词,我经常使用同义词库,并在相关单词之间跳跃,试图找到一个好单词。不过,我尽量不花太多时间,随着开发的进展,我想出了更好的名称,或者有时意识到SuchAndSuchManager真的应该被分解为多个类,然后那个被弃用的类的名称就不再是问题了。

这听起来像是一个很滑的斜坡,可能会在dailywtf.com上发布,“拥有抵押贷款的人的经理”等。

我认为一个单一的Manager类不是好的设计是正确的,但使用“Manager”也不错。我们可以将其分解为UserAccountManager、UserProfileManager、UserSecurityManager等,而不是UserManager。

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

熟悉GOF书中定义的模式,并以此命名对象,这让我在命名类、组织类和传达意图方面有了很长的路。大多数人都会理解这个术语(或者至少是其中的一个主要部分)。

我会考虑您在系统中使用的模式,类的命名约定/编目/分组往往由所使用的模式定义。就我个人而言,我坚持这些命名约定,因为它们是其他人最有可能获取我的代码并使用它运行的方式。

例如,UserRecordsClerk可能被更好地解释为扩展了一个通用的Recordslerk接口,UserRecordslerk和CompanyRecordslerk都实现了该接口,然后对其进行了专门处理,这意味着可以查看接口中的方法,以了解其子类通常的用途。

请参阅《设计模式》之类的书了解信息,这是一本很棒的书,可能会帮助您明确代码的目标-如果您还没有使用它的话;o)

我认为,只要您的模式选择得当,并且使用得当,那么相当简单的类名就足够了!

我认为这里的关键是要在代码的可见性范围内保持一致,即,只要需要查看/处理代码的每个人都理解您的命名约定,那么这应该很好,即使您决定将其称为“CompanyThingamabob”和“UserDoohickey”。如果你在一家公司工作,第一步是看是否有公司命名的惯例。如果没有,或者你不为公司工作,那么就创建自己的、对你有意义的术语,将其传递给几个值得信任的同事/朋友,他们至少会随意编写代码,并结合任何有意义的反馈。

在我的书中,套用别人的惯例,即使它被广泛接受,如果它不从页面上跳出来攻击你,也是有点错误的。首先,我需要在不参考其他文档的情况下理解我的代码,但同时它需要足够通用,以使同一行业中同一领域的其他人无法理解。