代码之家  ›  专栏  ›  技术社区  ›  Karthik Bollisetti

为什么不可变编程优于可变编程?[已关闭]

  •  -2
  • Karthik Bollisetti  · 技术社区  · 8 年前

    我从所有的 available article 关于这个话题,

    不可变对象的主要优点是可以进行并发编程。 因此,如果任何应用程序使用如此多的线程,那么我们可以使用不变性。

    我的问题是: 如果应用程序不需要多个线程,仍然首选不可变编程?因为为每次更改创建对象的新副本可能会非常昂贵。 (如果是,为什么)

    2 回复  |  直到 8 年前
        1
  •  1
  •   Mike Allen    8 年前

    考虑一下:

    class Time(t: Double) {
      private var time = t // Danger: mutable field
      def getTime = time
      def setTime(t: Double): Unit = time = t
    }
    
    val startAt = new Time(5.0)
    val someOtherTime = startAt
    someOtherTime.setTime(10.0)
    
    // What does startAt.getTime return?
    

    在这个简单的例子中,您可能会(也可能不会)惊讶地发现,在 someOtherTime.setTime(10.0) 返回, startAt.getTime 将具有价值 10.0 而不是 5.0 startAt 是一个 val ?

    Time 如果不看它的内部,我猜你会对这种行为感到非常惊讶。可变对象的状态可以在您不知道更改的情况下更改,特别是在多线程环境中,在多线程环境中,访问 Time.time 必须同步-但即使是单线程的情况也会带来意想不到的复杂性。

    保持对象不变使其易于推理。当这些对象表示 值类型 不变性实际上至关重要。(在任何主要编程语言或库中指定一个并非不变的值类型。)

    关于单线程与多线程编码的另一点:如果您编写的是单线程应用程序,您可能会忽略线程安全这一问题。然而,我认为这在一般情况下有点短视。所有新处理器都有多核,有迹象表明,处理器在未来几年将获得越来越多的核。如果您想编写响应迅速的高性能代码,您需要使用线程安全库编写多线程应用程序。

    如果您编写的代码不是线程安全的,并且它包含许多可变对象,则 共享可变状态 ,然后您必须进行大量重构,使其适合在多线程应用程序中使用。另一方面,如果您的对象是不可变的,并且没有共享的可变状态,那么这项工作就会简单得多。

    顺便提一下,在函数、类等中使用可变状态是完全可能的,前提是可变状态不共享(即外部可见)。这样,您就可以获得可变状态的性能优势,而没有缺点。

        2
  •  0
  •   Jesper Nordenberg    8 年前

    我完全同意,即使在单线程程序中,不可变对象也更容易推理。然而,有时处理可变数据更为实用,例如,如果性能至关重要(我们的计算机针对变异操作进行了优化),或者您使用的库本身就是有状态的。