【问题标题】:Returning a new Object vs modifying one passed in as a parameter返回一个新对象与修改一个作为参数传入的对象
【发布时间】:2011-03-28 14:50:06
【问题描述】:

我在代码审查期间遇到了以下代码。

我的直觉告诉我,这没有遵循正确的 OOP。

我认为 LoadObject 方法应该返回一个新的 SomeObject 对象,而不是修改传递给它的对象。虽然我真的找不到一个正确的解释为什么这更好。

我的解决方案更好吗?如果是这样,为什么?具体来说,在给定的代码示例(如果有)中违反了哪些 OOP 原则或标准?

   public void someMethod()
    {
        ...
        var someObject = new SomeObject();
        LoadSomeObject(reader,someObject);
    }

    private void LoadSomeObject(SqlDataReader reader, SomeObject someObject)
    {
       someObject.Id = reader.GetGuid(0);
    }

【问题讨论】:

  • 看起来你可能也在变异SqlDataReader

标签: c# java oop design-principles


【解决方案1】:

没有通用的 OO 概念,这与这样的代码冲突。 但是后来你会发现如果你不遵循一些设计原则,你会发现很难收集和理解操纵 SomeObject 实例的方法。 对于初学者来说,最简单的方法可能是分离两种主要的程序:

  • 功能性 - 旨在创建新实例而不是改变其他对象。
  • 有条不紊 - 旨在更改其主机实例的状态。

这里好主意,如果你想分离 SomeObject 操作逻辑是创建 SomeObjectBuilder 类型与

 public void loadFromReader( SqlDataReader reader )

方法和

public SomeObject getValue()

财产

【讨论】:

    【解决方案2】:

    我同意你的直觉,在大多数情况下感觉有点不对劲。我同意返回一些东西会更好,因为它只是更清楚地表明正在修改某些东西。看到正在使用的返回值可以立即清楚发生了什么。

    我觉得这感觉还是好一些,不过(在大多数情况下无论如何):

    public void someMethod()
    {
        ...
        var someObject = new SomeObject();
        someObject.Load(reader);
    }
    

    然后显然在SomeObject 类中,你会有

    public void Load(SqlDataReader reader)
    {
       this.Id = reader.GetGuid(0);
    }
    

    这个想法是支持实例方法而不是静态方法。当您可以让对象对自己的数据进行操作时,为什么还要费心创建对象并传递其数据?

    【讨论】:

      【解决方案3】:

      如果LoadSomeObject 将返回一个新的SomeObject,您可能需要更改方法名称以避免混淆。也许是NewAndLoadSomeObject

      【讨论】:

        【解决方案4】:

        无论哪种方式都是完全可以接受的,但是在决定哪种方式适合您的特定情况时,您希望对返回的对象做什么的考虑会发挥作用。不变性,即在每个操作中创建一个新实例是 .NET 中字符串的处理方式。

        一个复制方法显然需要返回一个副本。例如,在单例对象上工作的方法不适合返回新对象,因为更改可能会丢失。

        【讨论】:

          【解决方案5】:

          我不是 OO 专家,所以对这些持保留态度。

          1. 对象应尽可能自行管理/定义其行为。如果您曾经是松散耦合的负责人,那么这背后的基本原理是显而易见的。将LoadSomeObject 的细节转移到SomeObject 的实现中,我很可能是更好的设计决策,但是对于这样一个一般示例来说,这很难讨论。

          2. 可变状态在任何命令式代码(包括 OO 代码)中都非常适用,它是这些范例的核心“特性”。 OTOH,不可变状态具有无法定义的优势(我想我们在这里有几个关于该主题的问题,否则请询问任何 FP 拥护者),并且拥有一些不可变对象并不是特别非 OO。

          编辑:你也可以将 reader 传递给 SomeObject 的构造函数。

          【讨论】:

          • 有什么特别的原因被 russjudge 的回答接受了 4 倍的赞成票?
          【解决方案6】:

          代码的编写方式没有任何问题,因为您只是在修改 someObject 上的属性。

          但是,在 LoadSomeObject 中创建 someObject 并返回它也是正确的。

          此时,两种选择都一样正确。

          【讨论】:

            猜你喜欢
            • 2013-08-06
            • 1970-01-01
            • 1970-01-01
            • 2016-03-04
            • 2018-04-16
            • 2021-06-30
            • 2011-03-28
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多