Clean Code ch6 Objects and Data Structure

Clean Code勉強メモ

出典: 

Objects and Data Structure

  • 脳死getter/setterはpublicメンバと同じようなものだぞという話

Data Abstraction

  • 二次元座標上の点
public class Point {
  public double x;
  public double y;
}
public interface Point {
  double getX();
  double getY();
  void setCartesian(double x, double y);
  double getR();
  double getTheta();
  void setPolar(double r, double theta);
}
  • 前者は内部表現を暴露している
  • 後者は完全に隠蔽している

    • 実装がデカルト座標系なのか極座標系なのか区別できない

      • どちらでもないかもしれない
  • 後者はアクセスポリシーも表現している

    • getは別々に呼び出せる
    • setは(x,y) または (r,θ) を一度に設定することを強制している

      • cf. 前者はx,y別々にセットできる
  • 実装を隠蔽するとは、抽象化するということである

    • 関数を噛ませればいいというものではない

Data/Obect Anti-Symmetry

  • オブジェクトとデータ構造との違い

    • オブジェクトはデータを抽象化の裏に隠蔽して、それを操作する関数を公開する
    • データ構造はデータを公開し、意味のある関数(操作)は持たない
  • 「全てはオブジェクト」というのは神話

    • OOと手続きは相補的
OO 手続き
データ構造の追加 容易 大変
(すべての関数に変更が跳ねる)
関数の追加 大変
(全てのクラスに変更が跳ねる)
容易
  • 【補】手続き型の特徴はVisitor Patternと同じ感じ

    • 振る舞いの追加は容易だが、クラスの種類の追加が大変になる

The Law of Demeter

  • デメテルの法則
  • ドットがいっぱいあるのは駄目ってやつ

    • 隠蔽されるべき内部表現をほじくってるから

Train Wrecks

final String outputDir = ctxt.getOptions().getScratchDir().getAbsolutePath();
  • この手のコードは「列車事故」と呼ばれる

    • 列車が連なっているようなさまから
  • 分けよう
Options opts = ctxt.getOptions();
File scratchDir = opts.getScratchDir().
final String outputDir = scratchDir.getAbsolutePath();
  • 【補】FowlerのRefactoring的には、inline function化して前者へとリファクタリングするのでは?
  • これはデメテルの法則違反か?
  • オブジェクトであるか、データ構造であるかによる

    • オブジェクトなら内部表現の暴露なのでデメテルの法則違反
    • 後者にはあてはまらない

      • アクセサ関数が混乱の元
final String outputDir = ctxt.options.scratchDir.absolutePath;
  • publicメンバアクセスならデメテルの法則違反が疑われることはあるまい

Hybrids

  • 半オブジェクト半データ構造のハイブリッド
  • 悪いところどりなのでやめよう

    • 関数の追加もデータ構造の追加も困難になる

Hiding Structure

  • オブジェクトから内部表現を引っこ抜いて仕事するのではなく、オブジェクトに仕事させよう

Data Transfer Objects

  • 「データ構造」の典型

    • publicメンバをもち、関数を持たないクラス
    • DB通信、ソケットからのメッセージのパース等で有用
    • 生のデータからオブジェクトを構築する際、変換の最初の段階でよく用いられる

      • 【所感】最低限の型を担保するバリデーションのような感じだろうか

        • ドメインロジック等は「オブジェクト」に任せる
  • getterやsetterで包んでも特にメリットはない

    • 【補】immutableにしたい場合などはあると思う

Active Record

  • DTOの特別なやつ

    • save()とかfind()とか生えてる
    • DBのテーブルや他のデータソースと、データ構造との直接変換
  • このデータ構造にビジネスロジックメソッドを載せて、オブジェクトとして扱おうとする開発者がいる
  • 前述の、半オブジェクト半データ構造のハイブリッドになってしまうので良くない
  • Active Recordはデータ構造として扱い、ビジネスロジックは別のオブジェクトに持たせよう
  • 【所感】それActive RecordじゃなくてRow Data Gatewayだと思います

    • PofEAA的には「ビジネスロジックが載ったRow Data Gateway」がActive Recordなのであって、Active Recordにビジネスロジックを載せるのは定義上正しい

Conclusion

  • 新しい種類のデータを柔軟に追加できるようにしたければ、オブジェクト
  • 新しいふるまいを柔軟に追加できるようにしたければ、データ構造と手続き
  • 偏見を持たず、その時々で適したものを選ぶことが肝要

英語

  • unmistakably

    • 間違いなく
  • sneer

    • あざ笑う
  • warrant

    • 正当化する
  • diametrically opposed

    • 全く正反対で
  • dichotomy

    • 二分法
  • innards

    • 内部、はらわた
  • quintessential

    • 典型的な

      • = typical