命令对象集合的名称

时间:2014-12-20 14:07:39

标签: java oop naming-conventions

我正在开发一个命令处理程序,其中每个命令都可以无限期地拥有子命令。所有命令都由一个" CommandManager"在根级别进行管理。获取用户输入解析选项然后找到正确的命令并将输入传递给它。由于CommandManager和Command都有类似的获取和存储指定命令的方式,并且由于两个类都非常杂乱,我想将找到并存储命令的逻辑分解为一个共同的超类,但是,我可以'想一个描述性名称来称呼它。

我试图让CommandMagager和Command都扩展另一个类的原因是命令管理器就像根级别的命令一样。命令实际上并不包含任何处理命令的逻辑,它们只提供了一种注册和检索具有特定名称的命令的方法。

是否有任何一般惯例可以帮助我找到名称,或者这是错误的方式来查看问题?

2 个答案:

答案 0 :(得分:5)

是的,有一些关于这一点的规则,没有一成不变的,只是通过经验和模仿成为公认的最佳实践的实践。

概述

  • 明确责任。
  • 使用Camel Case。
  • 命名对象,而不是类。
  • 使用名词。
  • 避免使用InfoProcessorManager等字词。
  • 如果有物体,请使用单数。
  • 对实用程序类使用复数。
  • 使用Abstract前缀抽象基类。
  • 使用Impl隐藏实现类。
  • 请勿将interface名称加上I
  • 正确使用设计模式名称。
  • 前缀名称及其专业化。
  • 正确使用数据结构名称

详细

明确责任

重要的是,这个名字很好地反映了责任。名称应传达其意图。

名称对象,而不是类

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

使用Camel Case

UseCamelCaseForNamesOfTypesInJava。

使用名词

使用名词作为对象。如果对象表示动作,则将动词转换为名词。如果对象表示属性,则将形容词转换为名词。例如,如果操作为compile(),则使用Compiler(如果它是主动操作),或Compilable(如果它是被动功能)。如果操作为run(),请使用Runner(如果是有效操作),Runnable(如果是被动操作)。

避免使用InfoProcessorManager

等字词

在大多数情况下,他们只是&#34的同义词;我不知道该怎么称呼这个" (罗伯特C.马丁)。这本身就是一个症状,我不知道这件事在做什么"或者"这件事做的不止一件事"。这就是为什么当我们看到这样的名字时,我们经常理所当然地感受到重构的冲动。

如果有对象,则使用单数

类名通常是单数,特别是如果你可以获得单个类的多个对象。我们希望为这些对象的集合的变量名保留复数。

好例子

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 s的名称前加上interface就像使用匈牙利符号一样。匈牙利符号只有在您需要跟踪类型的这些物理方面的环境中工作时才有意义。 (就此而言,这些日子里在C中甚至没有必要!)

此外,你不想在

时看起来像个白痴
  • 您决定更改接口中的类,反之亦然,不要重命名该类型,最终会得到一个没有I - 前缀的接口或一个带有I - 前缀的类。
  • 您决定更改界面中的课程,反之亦然,并重命名该类型,最终会让您的用户感到烦恼。
  • Oracle在未来的Java版本中删除了classinterface之间的差异(不是那么不可能,现在看看接口如何使用静态和默认方法)。
  • 您将API移植到另一种语言,该语言不区分classinterface,现在具有I前缀的类或具有不同名称的类。

正确使用设计模式名称

如果使用设计模式,如果合适,可以使用其名称。但是如果你不使用设计模式,请避免使用设计模式的名称。

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

但是,当您实际不使用设计模式名称时,几乎必须避免使用它。如果您为Command命名,但它没有实现命令模式,如果您为Strategy命名,但它没有实现策略模式,如果您为Factory命名,但它没有实现工厂模式

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

使用名称的示例

  • KeyFactory 工厂设计模式
  • DocumentBuilder Builder 设计模式
  • Action 命令设计模式(又名操作交易

未使用名称的示例

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

带有专业化的前缀名称

通过在基类的名称前加上有关特化的信息,在继承树中向前推进,类名称的增长是很常见的。

实施例

  • ListAbstractListArrayListAbstractSequentialListLinkedList
  • SetAbstractSetHashSetLinkedHashSet

正确使用数据结构名称

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

具有键/值对而不管它们如何维护的概念称为字典,因此描述该键的接口应命名为 Dictionary 。 (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

答案 1 :(得分:1)

从您描述模型的方式来看,您看起来正在处理非常接近合成模式的事物(CM是根命令,而C代表单独的命令。) 如果是这种情况,那么您要查找的名称是:

Command
    CompositeCommand
    SimpleCommand

换句话说,您所谓的CommandManager将扮演CompositeCommand的角色,您当前的Command班级将是SimpleCommand,最后, (抽象)你正在寻找的超级课程{I} Command在我提出的术语中。 root用户和任何其他嵌套命令都是CompositeCommand的实例。当然,如果root有一些特殊的行为,你也可以将其建模为:

Command
    CompositeCommand
        RootCommand
    SimpleCommand

这样,RootCommand代替你的CommandManager,它本身是复合的,任何其他带子命令的命令都是CompositeCommand类,而&#34;叶&#34;将是SimpleCommand课程。

我知道,有些人不喜欢带有子类的具体类。如果是这种情况,你应该这样做:

Command
    CompositeCommand
        Subcommand
        RootCommand
    SimpleCommand

现在CommandCompositeCommand是抽象的,所有三个具体类都是子类免费的。

您可能仍在想我为什么要使用这么多名字,而不是CommandManager。这是因为,在我的观点中,没有命令 manager 这样的东西。

最后,您可能需要另一个对象(来自不同的层次结构),比如CommandParser,它将以更抽象的方式提供解析服务。 Command层次结构将使用解析器的服务并将语义添加到否则抽象令牌。这种分离很可能会为Command代码带来更多简单性。同时,它会将命令语言的语法与内部表示分离,这会为您的设计增加更多的灵活性,因为您可以提供两种不同的语法,而无需修改Command层次结构。