单一功能类(命名为动词)

Single function classes (named as verbs)

我正在尝试一种新的代码结构,在这种结构中,我将所有庞大的存储库和工厂拆分为较小的 classes 负载,每个负载都有一个职责。除此之外,我对 class 名称使用动词,因为我认为这是准确描述每个 class 的含义的最佳方式。

每个 class 只有一个 public 方法(称为 "Execute"),但通常有私有方法,有时还有带参数的构造函数。

例子:

之前:

class DocumentRepository {
  public List<Document> GetDocuments()
  public void SaveDocument(Document document)
  public Document CopyDocument(int id)
}

之后:

class GetDocuments {
  public List<Document> Execute()
}
class SaveDocument {
  public void Execute(Document document)
}
class CopyDocument {
  public Document Execute(int id)
}

这种结构的一个好处是我更愿意将 public 方法的功能拆分为多个私有方法(更易于阅读和管理)。在此之前会增加存储库中的混乱,但现在私有方法包含在它们单独的 classes.

我一直读到 classes 应该有名词作为名字,但是当 class 只有一个用途时,最好用它的作用来命名它。

问题

这是个坏主意吗(分离和命名)?如果是这样,创建这种分离并避免大 classes 的更好方法是什么?

编辑: 应该指出的是,我是从命令-查询的角度得出这些(奇怪的)想法的。因此,将它与存储库进行比较可能最有意义。

Is this a bad idea (both the separation and the naming)?

我想说命名​​主要是个人喜好问题。然而,您的新设计简直太糟糕了。

您应该以逻辑方式将功能相关的方法组合在一起,通常基于它执行操作的实体。我会说您的 GetSave 等方法属于存储库模式 class 或实体 class 本身。 从不 我会把方法变成 classes,那根本没有意义。

我知道您想减少每个 class 的行数。也许最好使用一个基础 class 来放入公共代码,或者将一些重复的动作拆分成一个单独的 class.

IMO,你的设计很奇怪。

当然,我理解您的目的 - 通过将私有方法移动到其他地方来减少 class 中的噪音,但是将每个方法移动到单独的 class 中似乎太过分了。

以前,您只需要一个对象即可获取、保存和复制文档。现在你需要 3 个并行!我想你可以创建一个包装器来包装这三个 classes,

public class DocumentRepository {
    public readonly GetDocument Get = new GetDocument();
    public readonly SaveDocument Save = new SaveDocument();
    public readonly CopyDocument Copy = new CopyDocument();
}

但还是太复杂了。

如果您想要更少的噪音,请尝试以更好的方式组织您的 class 并使用 #region#endregion(如果您的 IDE 支持它们)。如果我是你,我会这样做:

public SomeClass {
    // private fields
    ...
    // properties
    ...
    // public methods
    ...
    // private methods
    ...
}

另一种方法是:

public SomeClass {
    // private fields
    ...
    // properties
    ...
    // public method 1
    ...
    #region
    // private methods related/called by public method 1
    ...
    #endregion
    // public method 2
    ...
    #region
    // private methods related/called by public method 2
    ...
    #endregion
    // public method 3
    ...
    #region
    // private methods related/called by public method 3
    ...
    #endregion

    #region
    // other private methods that are not related to a particular public method.
    #endregion
}

虽然将每个方法都提取到单独的 class 中似乎过于激进,但其中还是有道理的。对于高负载系统,正在应用命令查询责任分离 (CQRS) 原则。它的主要思想是将查询(幂等方法,不修改系统状态,但仅 returning 数据)与命令(修改系统状态的方法;在 "pure" CQRS 中它们甚至不return数据——虽然我还是很难接受这个)。

这样做会使您的系统更加稳定且易于扩展,因为您可以拥有许多除了读取之外什么都不做的分布式节点,专注于修改数据的单个节点的性能。然而,并非所有系统都真正需要它。

即使您真的需要一个单独的 class 用于单个方法,将其命名为 verb 也不是一个好主意,因为它会使其他开发人员感到困惑(留在一个 class 中很难以确定您在代码中看到的内容 - 其他 class 名称或此 class' 内部方法)。你不需要在这里发明自己的符号,只需使用以下(相对标准):

class GetDocumentsQuery { }

class SaveDocumentCommand { }

class CopyDocumentCommand { }

有关 CQRS 的更多信息:

  1. https://en.wikipedia.org/wiki/Command%E2%80%93query_separation

  2. http://rob.conery.io/2014/03/04/repositories-and-unitofwork-are-not-a-good-idea/