3️⃣

[読書メモ]オブジェクト設計スタイルガイド 2章4~6節 with TypeScript

2024/02/03に公開

オブジェクト設計スタイルガイドを読みながら、TypeScriptでやるならどうやるかを考えながら書きました。
要約的に読める内容になっていると思うので、サクッと3分ぐらいで読める記事となっています。
https://www.oreilly.co.jp/books/9784814400331/

2.4 全てのコンストラクタ引数を必須とする

コンストラクタ引数を必須としない場合、無駄なif文が増えてしまう。
デフォルト値を実装の詳細に書き込んでしまうことでさらに複雑になり得る。

type FileOption = {
  path: string;
};

class NG_FileLogger {
  constructor(private fileOption?: FileOption) {}

  log = (msg: string) => {
    // コンストラクタ引数を必須としない場合、無駄なif文が増えてしまう。
    if (this.fileOption) {
        console.log(this.fileOption.path);
    }
    console.log(msg);
  };
}

class NG2_FileLogger {
  constructor(private fileOption?: FileOption) {}

  log = (msg: string) => {
    // デフォルト値を実装の詳細に書き込んでしまうことでさらに複雑になり得る。
    const path = this.fileOption ? this.fileOption.path :'default.txt'
    console.log(path);
    console.log(msg);
  };
}

2.5 コンストラクタ引数による注入のみを使う

他にNGなパターンだと、setterを使うやり方。

ただ、この方法は以下のルールに反している

  • 不完全な状態のアブジェクトを作成できるべきではない
  • サービスはイミュータブルでなければならない
type FileOption = {
  path: string;
};

class NG_FileLogger {
  private fileOption?: FileOption

  constructor() {}

  setOption(opt: FileOption) {
    this.fileOption = opt
  }

  log = (msg: string) => {
    // コンストラクタ引数を必須としない場合、無駄なif文が増えてしまう。
    if (this.fileOption) {
        console.log(this.fileOption.path);
    }
    console.log(msg);
  };
}

2.6 省略可能な依存関係というものは成立しない

NULLオブジェクト(何もしないダミーオブジェクト)を使用するパターンで対応する

class CsvImporter {
  private EventDispatcher: EventDispatcher;
  constructor() {}
}

interface EventDispatcher {
  dispatchEvent(eventName: string): void;
}

class EventDispatcherDummy implements EventDispatcher {
  dispatchEvent(eventName: string): void {
    // do nothing
  }
}

Discussion