【问题标题】:Do setters and getters really break the SRP?setter 和 getter 真的会破坏 SRP 吗?
【发布时间】:2013-03-05 01:55:51
【问题描述】:

我最近阅读了an article that describes,他们显然可能会破坏 SRP。现在我完全糊涂了,因为我用 setter 和 getter 编写了很长一段时间的单个类。

另外,我有 found this,但它与 SRP

无关

嗯,乍一看,getter 和 setter 都没有违反单一职责原则,因为它们的逻辑只“属于”当前类。他们可以访问/写入“服务”单一目的的类成员。很好。

但等等,让我们先定义基本术语:

数据访问 = setter 和 getter

数据处理 = 数据处理、CRUD 等操作、验证等

如果是这样,那么我们在一个类中有两个不同的职责,从而破坏了 SRP


让我们假设一下,为了不破坏 SRP,我们将在不同的类中定义数据访问和数据操作。

class DA { // <- Data Access
  public string getName() {
      return this.name;
  }

  public string setName(name) {
     this.name = name;
  }
}

class DataHandler {
     public DataHandler(da) { // <- Inject an instance of DA
         this.da = da;
     }

     public bool validate() {
          // validation stuff
     }
}

看起来不错,因为我们没有违反上述 SRP。但是在这里,我在 DA 类中只有一个 setter 和一个 getter。


现在的问题

1) 即使我只有一个 setter 和 getter,我是否应该始终创建另一个 DA 类,以免破坏 SRP?

2) setter 和 getter 真的会破坏 SRP,它们不应该在任何类中使用吗?

3) 如果是这样,依赖注入总是答案!?

【问题讨论】:

  • :/ 你可能应该编辑过。如果你要打破 SRP,你绝对应该选择 DI。组合优于扩展,等等。
  • 如果您查看我之前的评论(以及我的 pastebin 答案),您可能知道我来自哪里。
  • 即使他们没有破坏 SRP 他们仍然不是干净的恕我直言。问题在于命名,如果你有一个名为“name”的getter setter,那么函数名中就不再有动词。您可以使用“getSetName”,但它有两个动词和尖叫“做不止一件事”。我还认为,由于奇怪的命名,它违反了最小惊讶原则。

标签: dependency-injection solid-principles single-responsibility-principle


【解决方案1】:

setter 和 getter 是否会破坏 SRP?

Setter 和 getter 不是重点。 SRP 的要点是一个类应该只有一个职责。

表示域对象是一项重大责任。执行此操作的对象通常称为“数据对象”。由于语言设计或约定,数据对象通常具有 setter 和 getter,但它们本身并不是单独的责任;他们只是管道。

将数据对象进出持久存储是另一项重大责任。执行此操作的对象通常称为“数据访问对象”(DAO)。一个DAO也不是数据对象可能不需要setter和getter来获取它管理的数据对象类型的属性,尽管我可以想象一个非常糟糕的框架需要它们。与 DAO 一样,其他类型的对象使用数据对象(显示它们、序列化和反序列化它们、对它们执行计算等)而不是数据对象本身可能不需要反映数据对象的 setter 和 getter。

因此,拥有 setter 和 getter 表明您的对象是数据对象。如果它是一个数据对象,并且它也是一个 DAO 或有其他重大责任,它可能确实违反了 SRP。

旁注:您提到了验证。在典型的应用程序中,至少对单个数据对象的验证属于数据对象本身,因为表示域对象并强制执行域对象属性之间的单个正确性和关系几乎是相同的责任。

我是否应该总是创建另一个 DA 类,即使我只有一个 setter 和 getter?

一般来说,是的。重点不是属性的数量;关键是表示和访问是两个不同的职责,属于不同的类。

典型的应用程序有许多域对象,因此如果将域对象与其访问完全分开是有意义的,那么对所有域对象(甚至是单属性的对象)一致地这样做是有意义的。

依赖注入总是解决办法吗?

这取决于您的架构和框架。您可能有不可变的数据对象和 DAO,其方法将它们作为参数;那里没有 DI(尽管您可以将 DAO 注入到使用它们的更高级别的组件中)。您可能拥有使用数据对象或引用 DAO 的数据对象实例化的 DAO(我见过但不喜欢这两种模式);你可能需要 DI 那里。无论哪种方式,它都与其余的讨论没有太大关系。

【讨论】:

    猜你喜欢
    • 2017-01-28
    • 1970-01-01
    • 2018-07-25
    • 1970-01-01
    • 2019-11-03
    • 2010-10-05
    • 1970-01-01
    • 2016-11-17
    • 1970-01-01
    相关资源
    最近更新 更多