Scala - 在特征,类,对象之间拆分代码时的设计选择

时间:2017-11-17 20:18:08

标签: scala

我的代码总是一团糟,我认为我缺乏一些基础知识。当我尝试将功能分解为特征和对象时,我不太确定最佳实践是什么......或者为什么选择一种形式而不是另一种形式。我已经使用了以下三种方法,但我不一定清楚为什么选择其中一种方法。任何人都可以帮我思考构建这些依赖关系的不同方法吗?

选项1 - 最简单的方法,模块化,根据需要调用...老实说,我倾向于总是这条路线保持简单...虽然它经常需要传递大量的参数这个方法比这个简单的例子更复杂,所以它不是很优雅。

object A {
  def run(x: T): Unit = ??? // do stuff with x
}

object Main {
  val x: T = ???
  def main(args: Array[String]): Unit = {
    A.run(x)
  }
}

选项2 - 我在历史上大部分时间都在代码中使用这种方法...如果特征A中的代码是为对象Main设计的,我只是把它拆分成了东西更容易理解......这在逻辑上对我有意义。它还最大限度地减少了传递给函数的参数,感觉更清晰。但是......这使得代码更难以重用。如果从现在起六个月后我需要一个特性而不是对象Main的某个函数,因为我以一种意想不到的方式扩展了一个项目,这很难。

trait A {
  def x: T
  def run: Unit = ??? // do stuff with x
}

object Main extends A {
  val x: T = ???

  def main(args: Array[String]): Unit = {
    run
  }
}

选项3 - 我认为最好将大量依赖项混合在一起?老实说,我不太确定。同样,随着项目在功能上的扩展,这变得非常难以重复使用。可能是由于我选择的设计很差。

trait A {
  this: Main =>
  val runner: Runner
  class Runner(x: T) {
    def run: Unit = ??? // do stuff with x
  }
}


object Main extends A {
  val x: T = ???
  val runner = new Runner(x)

  def main(args: Array[String]): Unit = {
    runner.run
  }
}

有关为何选择其中一个与其他人的任何想法,以帮助我朝着编写更好的代码迈出一步?它是否归结为最简单的可读性和平衡通过较少的论点与使事情变得更清晰和更易读的权衡,或者是否有更聪明的方式来考虑程序设计。

有关学习如何更好地做出这些决定的地方的建议吗?

1 个答案:

答案 0 :(得分:2)

当你想要一个简单的接口来做一些不改变任何状态的东西(纯函数)时,我使用object。在Math类中考虑一下这个例子。另外,如果您想实施singleton dessing模式,也可以使用object

如果你知道一堆不同类的对象将拥有相同的接口,我会使用trait。如果不这样做,定义trait

可能会有点过分

如果你想要一个类的真实对象实例,那么你需要封装私有属性的转换。当我知道我需要abstract data-type时,我通常会这样做,即隐藏实现细节的数据结构或实体。

请注意,正如JörgWMittag所说,这与Java不同,因为在scala中你可以使用类来定义对象。