1

即使我认为我理解单一职责原则和高/低内聚原则,以下问题仍然让我有些困惑

1)假设PlanetBird属性在Car类中任意/随机放置(即,没有代码Car需要或对这两个属性返回的两个对象进行操作) - 换句话说,Planet属性Bird不属于 Car 类

一种)

SRP声明对象应该只有一个改变的理由。

public class Car
{
    public void StartEngine()
    { ... }

    private Planet Planet
    {
        get { ... }
    }

    private Bird Bird
    {
        get { ... }
    }
}

班级是否Car违反 SRP?我会说它不会破坏 SRP,因为任何更改PlanetBird实例都不会传播到Car类?

b)

内聚是指一个类中方法和类级别变量的密切程度。在高度内聚的类中,所有方法和类级变量一起使用以完成特定任务。在具有低内聚度的类中,函数被随机插入到一个类中并用于完成各种不同的任务

假设即使Car类包含这两个随机属性,它仍然只完成一个特定任务(或几个密切相关的任务):

我们会说它Car具有 低内聚性,即使它仍然执行特定任务(或几个密切相关的任务)?

2)假设实例的方法使用Planetand属性来完成特定任务,那么即使在概念上这两个属性不属于(因此最好将and实例作为传递)对它们进行操作的 a 方法的参数)BirdCarCarCarPlanetBirdCar

谢谢你

赫尔顿自行车:

1)

当您将 Bi​​rd 和 Planet 封装在 Car 中时(如果它们是私有的则更糟),所以现在 Car 类有三个改变的理由:

我看不出Car 有什么改变的三个原因,因为在我的第一个问题中,Car's方法甚至不对这两个属性进行操作,因此对公共 API 的任何更改Planet'sBird's不会影响Car类?

2)

The problem here has two components:
1.  Bird and Planet are contained (as opposed to aggregated) in Car class;
2.  Bird and Planet are not conceptually related to Car, much less by some containment relationship.

a)这令人困惑:无论是否包含或聚合实例 ,由于实例的Car修改而必须修改的机会(至少在我的第一个问题中)是否完全相同?PlanetBirdPlanetBird

b)在第二个问题中,Cardo 方法对两个属性进行操作以执行单个特定任务,所以它们在概念上至少不是有些相关吗?你会说即使在第二个问题中,类的凝聚力也很低,即使它只执行一个任务(并且正在使用这两个属性来完成任务)?

4

3 回答 3

1

1)我会说Car不能成立Planetand Bird。这样 Car 有两个不同的职责:汽车功能和持有一些奇怪的物体。应该有一些其他对象/类可以保存世界中的对象:例如:类WorldContainer

2)我会说你的两个例子的凝聚力都很低。管理汽车和一些不同的对象应该使用其他一些界面来完成。将它们粘合在一起的界面。

于 2013-01-14T19:16:17.370 回答
1

car 类确实具有低内聚性,因为它指的是与它的职责集完全不同的类。它还具有更高的耦合面,因为由于 Planet 和 Bird 是公共的,您已经向消费者提供了对这些属性的访问权限,这意味着您现在向任何消费者添加了另外两个“更改原因”,无论是否汽车在内部使用这些。

无论如何,SRP 已被违反,仅仅是因为 Car 现在负责“获得行星或鸟类的方法”,而无视任何耦合/内聚论点。

于 2013-01-14T19:19:41.643 回答
1

SRP 意味着一个类应该只有一个改变的理由。

因此,对 Car 类的修改应该意味着 Car 概念模型发生了变化。

但是,当您将 Bi​​rd 和 Planet 封装在 Car 中时(如果它们是私有的则更糟),因此现在 Car 类有三个更改的理由:

  1. 修改汽车概念模型和/或行为;
  2. 修改 Bird 概念模型和/或行为;
  3. 修改 Planet 概念模型和/或行为;

这里的问题有两个组成部分:

  1. Bird 和 Planet 包含(而不是聚合)在 Car 类中;
  2. Bird 和 Planet 在概念上与 Car 无关,更不用说某种包含关系。

或者,坦率地说(我希望你这样做是一种教学练习),所显示的架构根本没有意义。


聚合示例(在 Python 中)。非内聚类在引用它们的 Car 类定义之外定义。汽车依赖于Bird和Planet,但现在Bird和Planet独立存在。

class Bird():
    hasWings = True

class Planet():
    isFlat = False

class Car():
    owner = Bird()
    substrate = Planet()

参数传递示例(仅汽车类,假设其他类与上述类似)。现在 Car 构造函数(__init__python 中的方法)将实例作为参数。这可能会或可能不会被首选。依赖和耦合仍然存在,但现在可能更加具体。

class Car():
    def __init__(bird, planet)
        owner = bird
        substrate = planet

最后,整个内聚和耦合问题与软件本身并没有太大关系,而是与开发人员有关。编译器不会介意您的命名空间、项目文件夹和文件分发是否混乱,只要它“编译”即可。但是像你做的那样做没有任何意义(在 Car 类中放置一个 Bird 和一个 Planet 类)。刚开始,您对每个类的版本控制会非常混乱。

所以,你不应该违背的纯洁,不是为了它而写在书本上的。这种纯度是(或应该是)人类与机器指令斗争的结果。面向对象和一般的软件架构不是为机器设计的,而是为开发人员的(部分)头脑设计的。

于 2013-01-14T19:53:12.717 回答