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

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

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

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

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

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

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

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

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

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

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


更新:答案摘要

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

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

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

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

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

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

还有一个很好的建议:

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


当前回答

当我发现自己正在考虑在类名中使用Manager或Helper时,我认为这是一种代码气味,这意味着我还没有找到正确的抽象,和/或我违反了单一责任原则,因此重构和在设计中投入更多的精力通常会使命名更加容易。

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

业务模型类可能很难,因为它们对于每个领域都不同。我经常使用一些术语,如域内策略类的策略(例如,LateLrentalPolicy),但这些术语通常来自于尝试创建一种可以与业务用户共享的“无处不在的语言”,设计和命名类,以便它们模拟真实世界的想法、对象、动作和事件。

技术基础设施类稍微简单一些,因为它们描述了我们非常熟悉的领域。我更喜欢将设计模式名称合并到类名中,如InsertUserCommand、CustomerRepository或SapAdapter。我理解关于传达实现而不是意图的担忧,但设计模式结合了类设计的这两个方面——至少在处理基础设施时,即使在隐藏细节的同时,也希望实现设计透明。

其他回答

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

为什么?因为隐喻依赖于文化,也常常依赖于个人。对你来说,给一个班级取名“保姆”可能很清楚,但对其他人来说可能不那么清楚。我们不应该依赖它,除非您编写的代码仅供个人使用。

在任何情况下,惯例都可以形成或打破隐喻。“工厂”本身的使用是基于一个隐喻,但这个隐喻已经存在了很长时间,目前在编程界相当知名,所以我想说使用它是安全的。然而,“保姆”和“牧羊人”是不可接受的。

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

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

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

我认为最重要的一点是:这个名字足够描述性吗?你能通过看这个名字来判断这个班应该做什么吗?在类名中使用“Manager”、“Service”或“Handler”等词可能被认为过于通用,但由于许多程序员都使用它们,这也有助于理解类的用途。

我自己也一直在使用门面模式(至少,我认为这就是所谓的)。我可以有一个仅描述一个用户的User类,以及一个跟踪我的“用户集合”的Users类。我不把这个类称为UserManager,因为我不喜欢现实生活中的管理者,我不想被提醒:)简单地使用复数形式有助于我理解这个类的作用。

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

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

;-)

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

看起来Helper、Manager和Util是协调类时不可避免的名词,这些类不包含状态,通常是过程性和静态的。另一种选择是协调员。

你可能会得到特别紫色的名字,并喜欢像Minder、Overser、Supervisor、Administrator和Master这样的东西,但正如我所说,我更喜欢保持它像你习惯的框架名称一样。


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

建设者使用某些参数构造特殊类型实例的类型。生成器通常是一次性的。它甚至可能不需要分配变量。如果类型需要重复创建对象,请使用Factory。如果负责创建多个不同类型对象的类型,请使用工厂。作家把一些变量写进一些东西。读者读一些变量。处理程序设计用于处理一种情况或其他事情。容器可以放些东西进去。