java - 收集命令对象的名称

标签 java oop naming-conventions

我正在开发命令处理程序,其中每个命令可以无限地包含子命令。所有命令都由“ CommandManager”在根级别进行管理,该命令管理器采用用户输入解析选项,然后找到正确的命令并将输入传递给它。由于CommandManager和Command都具有类似的获取和存储指定命令的方式,并且由于这两个类都非常混乱,因此我想将查找和存储命令的逻辑分解为一个通用的超类,但是,我想不起来描述性名称的名称。

我之所以尝试使CommandMagager和Command都扩展另一个类的原因是,命令管理器在根级别上的行为类似于命令。命令实际上不包含任何处理命令的逻辑,它们只是提供一种注册和检索具有特定名称的命令的方法。

是否有任何常规约定可以帮助我找到名称,或者这是解决问题的错误方法?

最佳答案

是的,对此有一些规则,没有一成不变的做法,只是一种经验和模仿使它们成为公认的最佳实践。

总览


明确责任。
使用骆驼套。
命名对象,而不是类。
使用名词。
避免使用InfoProcessorManager之类的词。
如果有对象,请使用单数形式。
对实用程序类使用复数形式。
Abstract前面加上抽象基类。
Impl后缀隐藏的实现类。
不要在interface名称前加上I前缀。
正确使用设计模式名称。
前缀名称及其专业名称。
正确使用数据结构名称


细节

明确责任

重要的是,名称应能很好地反映出责任。名称应传达其意图。

名称对象,而不是类

使用单个对象时看起来不错的名称。命名对象,而不是类。

使用骆驼盒

UseCamelCaseForNamesOfTypesInJava。

使用名词

为对象使用名词。如果对象表示动作,则将动词转换为名词。如果对象表示属性,则将形容词变成名词。例如,如果动作是compile(),则如果它是主动动作,则使用Compiler;如果它是被动技能,则使用Compilable。如果该动作是run(),则是Runner,如果它是主动动作,则使用Runnable,如果它是被动技能。

避免使用InfoProcessorManager之类的词

在大多数情况下,它们只是“我不知道该怎么称呼”(Robert C. Martin)的同义词。这本身就是“我不知道这件事在做什么”或“这件事在做一件以上的事情”的症状。这就是为什么当我们看到这样的名字时,我们经常正确地感到有重构的渴望。

如果有对象,请使用单数形式

类名通常是单数,特别是如果您可以获得单个类的多个对象。我们喜欢为此类对象的集合的变量名称保留复数形式。

好的例子

JButton button;
List<JButton> buttons;


不好的例子

Properties是不好的类名,因为尽管有对象,但它是复数。我们喜欢称List<JButton> jButtons。那么,您如何称呼List<Properties>-propertiesspropertiesespropertiessies ???

对实用程序类使用复数

如果一个类仅包含仅出于为另一种类型提供实用程序方法而存在的静态方法,则该类为实用程序类。

好例子

CollectionsSpilteratorsArraysExecutorsFileSystemsFilesPaths

Abstract前缀抽象基类

接口Foo的抽象基础实现通常称为AbstractFoo

示例:AbstractActionAbstractListAbstractMapAbstractQueue等。

确保此名称是用户几乎看不到的名称,AbstractSomething是实现者/扩展者的好名字,而不是用户的好名字。并且仅在没有更好的名称的情况下选择此名称。

后缀带有Impl的隐藏实现类

提供接口或抽象类Foo的默认实现的类有时仅称为FooImpl

确保用户永远不会看到此名称。永远不能。这仅对实现者有益,没有其他人。诸如XyzImpl之类的名称对用户不得可见。并且仅在没有更好的名称的情况下选择此名称。

不要在interface名称前加上I

OO语言中类型的目的通常是封装和隐藏事物。类型是classinterfaceenum还是@interface注释都是该类型的详细信息。在两种情况下,您需要了解有关类型的这些详细信息:要扩展类型时以及要创建该类型的对象时。这些用例是类型的用例的少数。通过为接口名称加上I前缀,可以大声地声明实际上应该隐藏的实现细节,从而违反了该原理。

I放在interface的名称之前就像使用匈牙利表示法。仅当您在必须跟踪类型的这些物理方面的环境中工作时,匈牙利符号才有意义。 (因此,这几天在C语言中甚至都没有必要!)

此外,当你不想看起来像个白痴


您决定更改接口中的类,反之亦然,并且不重命名类型,最后得到的接口是不带I前缀的类或带I前缀的类。
您决定更改界面中的类,反之亦然,然后重命名该类型,最终会惹恼用户。
Oracle消除了Java未来版本中classinterface之间的差异(不太可能,现在看看接口如何具有静态和默认方法)。
您将API移植到另一种无法区分classinterface的语言,现在具有带I前缀的类或具有不同名称的类。


正确使用设计模式名称

如果使用设计模式,则可以使用它的名称(如果合适)。但是,如果您不使用设计模式,请避免使用设计模式的名称。

在使用设计模式时,可以选择使用设计模式名称-如果有助于或通常使用设计模式的名称,请使用它,例如抽象工厂的Factory后缀。

但是,当您实际上不使用设计模式名称时,几乎必须避免使用它。如果您命名为Command但未实现命令模式,可能会造成混淆,如果您命名为Strategy但未实现策略模式,如果您命名为Factory但未实现策略模式实施Factory模式。

这并不总是令人困惑,可能需要做出一些判断。例如,您可能有一个框架来编写带有接口的命令行程序以及这些命令行程序的抽象基类。尽管实际上这不是Command设计模式,但至少从语言本身的角度来看,您可能还是要称它们为CommandAbstractCommand

使用名称的示例


KeyFactory工厂设计模式
DocumentBuilder生成器设计模式
Action命令设计模式(又名Action,Transaction)


不使用名称的示例


RunnableCallable-命令设计模式,但名称不同,但更为专业。
Collections.synchronizedList()-装饰器的工厂方法


前缀名称及其专业化

当我们在继承树中向下移动时,类名通常会增长,方法是在基类的名称前加上有关专业化的信息。

例子


ListAbstractListArrayListAbstractSequentialListLinkedList
SetAbstractSetHashSetLinkedHashSet


正确使用数据结构名称

如果实现数据结构,请使用适当的名称。

具有键/值对而不管其如何维护的概念称为字典,因此描述该键/值对的接口应命名为字典。 (Java之所以将其命名为Map的原因是Java 1.0中的原始集合是纯设计的,并且已经使用了抽象类Dictionary,因此interface需要一个新名称。)

你的情况

在您的情况下,我可以想象以下设计:


interface Command { void execute(); }可以执行的所有内容。
interface CommandQueue { void submit(Command); }可以向其提交命令的内容。
interface CommandRunner extends CommandQueue { void start(); void stop(); }


如果您提供更多详细信息,我可以更新此部分。对于排队和处理命令的内容,您可能还需要考虑并行化并查看java.util.concurrent

关于java - 收集命令对象的名称,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27580974/

相关文章:

ruby-on-rails - 如何让我的 rails 应用程序显示 url 作为用户名?

Java 11 : Execution default-compile of goal org. apache.maven.plugins :maven-compiler-plugin:3. 8.0 :compile failed.:NullPointerException

Java 正则表达式过于贪婪地捕获组

java - 获取 GAE 上当前部署的所有版本的列表

java - 从动态模型生成 View

promise 的 JavaScript 命名约定?

java - Java中的继承

oop - OOD - 杯子的内容是 Mug 类的属性?

javascript - 使用从一种方法到另一种方法的变量

Python bool 方法命名约定