code smell リファクタリング[lazy class編]

lazy classとは

怠け者のクラス。 クラスがほとんど振る舞いを持たずに怠けている状態のこと。(存在している意味がわからない)

なぜ悪いのか

必要がない。 冗長になる。

よくあるパターン

よくあるのは、以下のようなとりあえずserviceクラスを作って、そこに処理を投げている構造です。

package study.lazyclass

class PaymentController {
  def payment(amount: Int) = {
    val service = new Service
    service.pay(amount)
  }
}

class PaymentService {
  def pay(amount: Int): Unit = {
    paymentRepository.save(amount)
  }
}

payメソッドだけが、PaymentServiceクラスに定義されています。 Serviceクラスがpayメソッドと言う振る舞いしか持っていません。

ソリューション

ソリューション自体は非常に簡単です。

関数のインライン化 必要な時に作ればいい。 クラスを作るタイミングとしては、二つ以上の箇所から呼び出されたりなど、関数をまとめるクラスが必要になった時に作ればいいだけです。

class PaymentController {
  def payment(amount: Int) = {
    paymentRepository.save(amount)
  }
}

PaymentControllerから直接、paymentRepositoryを呼び出すように変更しています。

これは、よく言われているYAGNIの法則にもそっています。

ja.wikipedia.org

考え方

ここからがこのcode smellの重要な観点です。

lazy classリダファクタリング自体は非常に簡単にできますが、リファクタリングを実際にするのかどうかが開発手法によって変わってきます。

レイヤードアーキテクチャでアプリケーション構成を考えていくなど、最初から適応するアーキテクチャを考えているならば、上記のようなリファクタリングをする必要はないです。

関数が一つしかない場合でも、きちんとレイヤーを分けて、定義する必要があります。

例えば、レイヤードアーキテクチャを採用しているなら、下図のように依存関係は上から下の一方通行になるように設計しないといけないので、 リファクタリングのコードのような、controller(presentation層)からrepository(infrastructure層)を呼ぶことはできない。

f:id:mhtnim1023:20191231174235p:plain

なのである程度のcode smellを許容しながら、開発を進める必要があります。

しかし、アーキテクチャを最初から考えていくと、そのアーキテクチャのルールに乗らないといけないので、コードを書くのが窮屈になると言う理由で、

基本的に開発の序盤からアーキテクチャを考えるべきではないという開発者もいる。

なので、どんな開発手法をとるかはチームで考えて開発ルールを決定すべき。

まとめ

lazy classのリファクタリングを行いました。

最後までありがとうございます。