📝

Tidy First? まとめ&感想

に公開

概要

コードの振る舞いを変更する前段階の整頓を、行う方法、タイミング、メリットをわかりやすく説明してくれている本。

ソフトウェア設計とは

ズバリ、要素を役立つように関連付けること。

具体的に言うと、

要素の作成と削除
関係性の作成と削除
関係性が生み出す利益の増加

また、ふるまいを変更する準備。

結合のデメリット

1-N

ある変更に際して、1つの要素が任意の数の要素と結合する。

カスケーティング

1つの変更により多くの変更を引き起こし、伝播していくこと。

整頓の具体的な方法

ガード節

if (条件)
    if(not ほかの条件)

ネストはどう考えても読みにくい。

if (not 条件) return 
if (他の条件) return

これはどのリファクタ本でも見かける。

新しいインターフェイスの実装

class UsersController < ApplicationController
  def show
    user = User.find(params[:id])
    render json: {
      id: user.id,
      name: user.name,
      email: user.email,
      created_at: user.created_at.strftime("%Y-%m-%d"),
      posts_count: user.posts.count
    }
  end
end

複雑な変数をそのまま返すのではなく、別のクラスなどでラップする

class UserInfometion
  def initialize(user)
    @user = user
  end

  def as_json
    {
      id: @user.id,
      name: @user.name,
      email: @user.email,
      created_at: @user.created_at.strftime("%Y-%m-%d"),
      posts_count: @user.posts.count
    }
  end
end
class UsersController < ApplicationController
  def show
    user = User.find(params[:id])
    render json: UserSerializer.new(user).as_json
  end
end

※userをインスタンス化することで、UserInfometionはuserを内部に保持する。
これが直接渡すと、UserInfometionのメソッドがすべてuserを引数に取らなければいけないから、柔軟性が低い

設計の心構え

1.後ろからコーディング
2.テストファースト
3.ヘルパーを先に実装

凝集

結合しているファイルは、隣接するようにする。
(もっとも、分離するのが一番望ましい)

変数宣言と初期化

変数を一番最初に全部定義すると、読んでる途中で忘れるから、また上まで戻らなくてはいけない。
無駄。
ただ、構造によってはふるまいを変更してしまうこともある。小さいステップで進めていく。
(自分は今まで一番最初に宣言する派だった)

マジックナンバーの使用

いうまでもなく、だめ

明示的なパラメーター

const params = { a: 1, b: 2 };
foo(params);

function foo(params) {
  console.log(params.a);
  console.log(params.b);
}
const a = 1;
const b = 2;
foo(a, b);

function foo(a, b) {
  console.log(a);
  console.log(b);
}

下のように、関数に渡すとき、変数を明記したほうが明示的でいいらしいが、上のほうが個人的には好き。
シンボルで参照することで、paramsの変数が追加されても、関数の振る舞いが限定されずに、再利用しやすいメソッドになるから。

ヘルパーの抽出

時間的な結合も抽出できる。
(foo.a()はfoo.b()の前に呼び出される必要がある。)

foo.a()
foo.b()
ab()
    a()
    b()

細分化の弊害

細かく分けすぎるがゆえに、かえって読みにくくなることがある。
大事なのは、なるべく多くのコードをインライン化してひとかたまりにして、部品を抽出する。

分けて整頓

大体の整頓は、量が多くなりレビュワーを困らせる。ふるまいの変更と構造の変更は分けて出そう。

整頓のメリットやタイミング

整頓と変更がごちゃごちゃになった場合

進行中の作業を破棄し、初めからやり直し、先に整頓する。再実装するほど、新たな発見の可能性は高まり、多くの価値を引き出せる。

整頓の重要性とふるまいの変更より前に行う理由

整頓は、システムの振る舞いに対する将来の変更を簡単にする。
システムの中で、変更する可能性があるなら、そのコードは整頓する価値がある。

利点1

整頓する(ふるまいの変更に結び付けない)ことで、いくつか価値が生まれる。
将来変更するコードの整頓を行うことにより、たとえその場でシステムの改善がなされなくても、無駄にはならない。その後の変更は安くなる。整頓はお得らしい。

利点2

整頓は設計のノウハウを学べる。

整頓を行うタイミング

整頓を今したほうが安く上がるとき。
整頓するコストがふるまいの変更のコストと比例するとき。
整頓箇所が毎週使われており、見返りがあるなら整頓すべき。
振る舞いの変更の準備ができておらず、整頓することで理解が早くなる時。

構造の変更とふるまいの差

可逆性の有無

可逆性のメリット

デメリットが少ない。
間違いを避けるためのコストをかけるべきでない。その点、少ないコストで戻せるのはそれだけで価値。

整頓後の振る舞いを実装しないことによる選択肢

次にどのようなふるまいを実装できるかというのは、それだけで価値がある。
また、その振る舞いが大きければ大きいほど価値がある。
また、次にどのようなふるまいを実装できるかという選択肢を持っている場合、持っているふるまいの価値の大小を気にする必要はない。
加えて、価格予想の不確実性が高いほど、すぐ実装するのと比べて、選択肢を持っている状態の価値が高い。(失敗するよりもそりゃいいよね)

ただ、結合を完全になくすことはできない

なんなら結合を減らせば減らすほど、別の種類の変更に伴う結合が大きくなる。

大事なのは、結合のコストを払うか、分離のコストを払うか、トレードオフを考慮したうえで実装すること。

Discussion