单一责任原则与移动方法重构



我似乎夹在两个设计准则之间。

我有一个表示三维体积的类,它是由块组成的。此类提供简单的修改方法,如AddBlockRemoveBlock

我需要用这个类做几件事

首先,我需要了解有关卷的某些聚合属性,方法如GetTotalWeightGetMaximumWidth

其次,我需要对这些卷执行转换操作,如ShrinkTrim,这些操作基本上符合名称的要求(无需详细说明,卷只是根据一些规则通过添加或删除块来更改)。这些操作有很多逻辑。

我的问题是:如果我将这些查询和转换方法添加到Volume类中,这是否违反了单一责任原则?我的课程职责是:

  • 保留卷数据,允许进行简单的修改(添加和删除块)
  • 提供有关卷的聚合信息
  • 为这些卷提供转换功能

如果我认为这是太多的责任,并且Volume类应该只代表卷,我将需要为转换创建Volume TrimmerVolumeShrinker等类,并为查询创建WeightCalculator

最后一个选项似乎巧妙地将不同类别中的关注点分开。但是,如果我查看VolumeTrimmerTrim(Volume v)细节,它所做的只是通过音量调用操作。同时,我的WeightCalculatorCalculateWeight(Volume v)方法似乎主要关注Volume

当我看到这种方法时,我觉得必须使用Move method重构。我看了看代码,然后说"这个方法主要关注另一个类的属性,所以我最好把这个方法移到这个类中"。但这将责任带回了类!

关于我应该如何处理这个问题,有什么想法吗?我对这些指导方针的理解是错误的吗?

像往常一样,这类问题唯一正确的答案是:这取决于情况。

拥有简单的数据容器类通常是有意义的,比如你的volume类,没有收缩、修剪等方法

还有一个选项可以让Trimmer和Shrinker只在Volume类中使用。通过这种方式,您可以将Volume及其操作很好地封装在一个类中,但也可以将复杂的方法分离,这可能有助于测试。

那么,如何决定哪种设计是正确的呢?以下是几个指导性问题:

  1. 对于收缩器等等,你需要在Volume类中公开那些原本是私有的东西吗?如果是这样的话,这暗示了体积的方法

  2. 对于Shrinker&Co,可能用于测试目的或具有不同性能特征?如果是这样的话,这就意味着要使用单独的类。

  3. Volume的客户是否大多数时间都使用add/removeBlock方法AND收缩AND修剪方法?这将再次提示使用单个类。

  4. 收缩剂&每个公司只需要一个子集的API卷?如果是这样的话,这就意味着要使用单独的类。

据我所知,单一责任原则是相当武断的,因为任何来自更高级别语言的代码都只能做一件事。话虽如此,您的VolumeTrimmer和VolumeShrinker似乎只对Volume属性的子集感兴趣。因此,隔离这些类并只给它们感兴趣的属性的子集是有意义的。这使得它们在其他场景中可重复使用,其中另一个类也有这个子集并希望有相同的行为,但不需要了解Volume的任何信息。有道理吗?

我认为这没有问题。这似乎是Composite模式的一个例子。你的卷是由块组成的。

您的卷没有理由不具有卷范围的操作,如Transform,它可以通过委派到块级别的Transform操作来实现。

最新更新