🤖

facadeパターンでリファクタリングしてみた

2022/11/22に公開約2,300字

はじめに

この記事では、リファクタリングを通して facade パターンについて学んでいこうと思います。

facade パターンとは

THCHSCORE さんの解説を引用します。

プログラムを作っていくと、最初は小さなものでも、だんだん大きくなっていきます。 たくさんのクラスが出来て、相互に関係しあい、複雑になっていきます。 クラスを使う場合には、それらの関係を正しく理解して、 正しい順番にメソッドを呼び出す必要があります。 大きなプログラムを使って処理を行う場合、 関係しあっているたくさんのクラスを適切に制御しなくてはいけません。 その処理を行うための「窓口」を用意しておくと、 個別にたくさんのクラスを制御しなくても、「窓口」に対して、要求するだけですみます。

Facade パターンは、既存のクラスを複数組み合わせて使う手順を、「窓口」となるクラスを作ってシンプルに利用できるようにするパターンです。

パソコンをイメージしてもらえると理解しやすいと思います。
パソコンはマザーボードやプロセッサなどの複数のパーツからできています。これらのパーツを適切に選択してパソコンを組み立てるのは高度な知識が必要ですし、面倒ですよね。でも、普段私たちは完成品のパソコンを選択するだけで購入することができていると思います。
このように、使用する側は中で何が行われているかを気にせずに、使うことができるようにするのがこのパターンの特徴です。

実践

今回は図書館で本を借りる時のシステムを実装しようと思います。
図書館で本を借りるには、まず本の詳細を検索して本のデータを取得し、受付で図書館利用者の証明をしてから、貸出帳にユーザー ID を記載する必要があります。
まず、facade パターンを使用していない状態です。

interface Book {
  [name: string]: {
    id: string,
    body: string
  }
}

class BookDB {
  private bookDetail: Book = {
    "テストブック": {
      id: "123",
      body: "test"
    }
  }

  public getBookInfo(name: string) {
    return this.bookDetail[name]
  }
}

class Reception {
  private userList = ["tempUserId"]

  public isLibraryUser(userId: string) {
    return this.userList.includes(userId)
  }
}

class LendingBook {
  public lendBook(bookId: string) {
    return
  }
}

const bookInfo = new BookDB().getBookInfo("テストブック")
const reception = new Reception()
if (reception.isLibraryUser("tempUserId")) {
  new LendingBook().lendBook(bookInfo.id)
  console.log(bookInfo)
}

このように実装していると、本の貸出を行う箇所が増えるたびにこの複雑な組み合わせのコードを書く必要が出てきます。
複雑なコードが増えるとドメイン知識の不理解によるバグや仕様の変更が高リスクになります。
ここで facade パターンを使用します。

class BookFacade {
  public lendBook(bookName: string, userId: string) {
    const bookInfo = new BookDB().getBookInfo(bookName)
    const reception = new Reception()
    if (reception.isLibraryUser(userId)) {
      new LendingBook().lendBook(bookInfo.id)
      return bookInfo
    } else {
      return "図書館利用者リストに入っていません。"
    }
  }
}

console.log(new BookFacade().lendBook("テストブック", "tempUserId"))

本を借りるための処理を一つのクラスにまとめることで、利用する側はドメインロジックを気にすることなく使用することができます。
こうするうことで、仕様を変更するときも変更箇所を小さく留めることができます。

感想

デザインパターンと聞くとなんか難しそうなイメージがありますが、意外と普段からやっていることに名前をつけただけのようなパターンも多いような気がします。自分の書くコードのバリエーションの一つとして知っておくのは良さそうです。

参考文献

https://www.techscore.com/tech/DesignPattern/Facade

Discussion

ログインするとコメントできます