WebエンジニアのLoL日記

LoLをプレイしたりLJLの試合を見たりするのが好きなエンジニア。LoLのイベントやパッチノートなど気になった点を記事にしたり、LJLについの記事をかいたりしています。某社でWeb系のエンジニアとして働いているので、技術系の記事もたまに書きます。コンタクトを取りたい場合はtwitterまで。

【DDDとコーディングの勉強1】twitter的なサービスを想像しながら考えるDDD

f:id:yoshiki_utakata:20181004212834j:plain

なにこれ

DDDなにそれわからん。難しいんでしょ?という人向けのちょうシンプルDDD勉強会です。

DDDって何?

DDDというのは、ドメイン駆動設計(Domain Driven Development)の略です。 なにそれわからん、と思うでしょう。 まずDDDの考え方を簡単に説明します。

ドメイン」という言葉を考えてみましょう。日本語だと「領域」という単語にあたります。 「ドメイン駆動設計」とは、自分の作るサービスという領域の中の事をよく知り、その知識に基づいて設計島用ということです。

twitterというサービスを作る事を考えましょう。 twitterのコードを設計する時には、twitterというサービスの領域(つまり、twitterというサービスそのものについて)よく知る 必要があるということです。

例えば

  • twitterには「ユーザー」と「ツイート」がある
  • 「ユーザー」はどういうものなのか
    • ユーザーネームがある
    • プロフィールがある
    • いくつかの「ツイート」を持っている
    • ...
  • 「ユーザー」は何ができるのか
    • 他のユーザーをフォロー
    • ツイートをする
    • プロフィールを変更する
    • ...
  • 「ツイート」とはどういうものなのか
    • 本文がある
    • 一つの「ツイート」は一人の「ユーザー」に紐付けられる

こういった、自分のサービスの領域についてよく知り、その上でコードを設計するのが大切ということです。例えばここからこういうコードができたとします。(仮に言語はPHPだったとします)

<?php

class User {
  public $userName;
  public $profle;
  public $tweets;
}

class Tweet {
  public $body;
}

class UserActivityController {
  public function follow(User $object, User $subject);
  public function tweet(User $user, Tweet $tweet);
  public function changeProfile(User $user, $newProfile);
}

こういう設計はそもそもtwitterというサービスを知らないとできませんし、この設計が本当に良いかどうかはtwitterというサービスを本当にしらないとわからないということです。

ここまでのまとめ

twitterというサービスを作るには、twitterというサービスについて(twitterというサービスの「ドメイン」について)よく知らないといけない。

しかし

  • twitterというサービスの仕様をそんなに簡単に把握できたら苦労しませんし
  • サービスの仕様を把握できたからといってそれを完璧にコードに落とし込めるかといったら疑問がわきます
  • さらにはサービスに仕様変更が入る可能性もあります

じゃあどうするの

なんか一般的にこうすると仕様変更に強くなきがするよ、という知見が紹介されているのでそれに従います。

層に分ける

アプリケーションを層に分けます。レイヤードアーキテクチャとか言われます。 例えば下の記事なんかがきれいにまとめられていますが、正直これをみても「ナンノコッチャ」という人も多いかもしれません。

qiita.com

とりあえずわからなければこんな感じの層に分けると良いかと思います。

もちろん、もっと理解できるようになってきたら「ここの層を細かく分けたり」とかしてもいいと思いますが、まずはイメージしやすいものから考えていきます。 それぞれの層について簡単に説明します。

UI層

  • 見た目や画面の動きに関するコードの層です
  • ユーザープロフィール画面にユーザーのアイコンと名前とプロフィール本文、最近のツイート20件を乗せる
  • APIのレスポンスをどういう構造で返すか、なんてこともUI層の役割になります。

ドメイン

  • ここが一番重要な層で、
  • 「ユーザーはどういうものなのか」「ツイートとはどういうものなのか」
  • 「ユーザーはどういうことができるのか」
  • なんかを定義している部分です。
  • twitterの例で上げたコードは実は全部ドメイン層のコードだったわけですね

インフラ層

  • twitterというサービスの仕様には直接関係の無い、インフラ構成に関するコードなどを各部分です
  • 「ツイート」のデータベースはMaster-Slave構成なので、参照系はSlave、更新系はMasterに渡すような処理
  • 「ツイート」はツイートのUserIdの下1桁によってDBが別れているので、どのDBを探せば目的のツイートが探せるのか、という処理
  • データベースに接続するユーザー名やパスワードを取得して実際にデータベースに接続する処理

こういった処理は「twitterというサービスの仕様の核となる部分」とは違います。

twitterというサービス(にかかわらず我々が作るサービス)は複雑です。twitterに登録した「ユーザー」はどんなことができますか?すごいいろんなことができます。ユーザーはどういうことができるのか、それはドメイン層に定義します。ドメイン層を見るだけでtwitterがどのようなものなのか、わかるようにします。twitterがどのようなものなのか、それを知るために、DBがMaster-Slaveになっているかどうかは関係ないのです。DBがMaster-Slaveになっている場合、Masterは更新系、Slaveは参照系のクエリが走りますが、それはtwitterというサービス独自のものではありません。ドメイン層を見るだけでtwitterがどのようなものなのか、わかるようにするために、こういった処理は「インフラ層」に閉じ込めるのです。

ここまでのまとめ

サービスは層に分かれる。ドメイン層にはサービスの仕様を書く。

次回

次回は「依存性の逆転」と、もし余裕があったらDI(依存性の注入)について書きます。