くらしのマーケット開発ブログ

「くらしのマーケット」を運営する、みんなのマーケット株式会社のテックブログです

DDD開発をしてみての振り返り

バックエンドエンジニアの@akiraです。
今回はチームで採用しているドメイン駆動設計について、実際に開発してみて三ヶ月ほど経ちましたので、その知見等を公開したいと思います。
まず初めに、ドメイン駆動設計の基礎をおさらいしましょう。

f:id:curama-tech:20200324204507j:plain
ひざまずいて話を聞くたんさん

ドメイン駆動設計(Domain-Driven Design)とは

Eric Evans氏が提唱した設計手法です。
ドメインモデルを使って、実装とドメインの概念を一致させることで、ドメインの複雑な問題を解決できます。

ドメインとは対象ビジネスが扱う業務領域のことであり、ソフトウェアによって解決しようとしている問題とも言えます。
ドメインモデルとは、ドメインから必要な概念を抽出したものであり、ユビキタス言語から構築されるものです。
ドメインモデルとユビキタス言語は、定義だけでは理解し辛いかもしれませんので、10円玉を例に説明します。

現実世界における10円玉の属性をいくつかピックアップすると、以下などが挙げられるかと思います。

  1. ほぼ銅で作られている
  2. 約4.5グラム
  3. 所々傷がある
  4. 10円の金銭的価値をもつ
  5. 硬貨

しかし、ソフトウェアの世界において10円玉の概念を実装するならば、上記全ての属性が扱われることはないでしょう。
例えば「10円の金銭的価値を持つ」という属性だけが抽出されてクラスとして定義されます。
このクラスがドメインモデルであり、10円玉から「10円の金銭的価値を持つ」属性だけを抽出することをモデル化と言います。
また、この「10円の金銭的価値を持つ」自体がユビキタス言語です。
ユビキタス言語は、ドメイン駆動設計で開発を行うチーム内で共有する言語のことで、ドメインの概念や仕様を指します。

ところで、券売機の組み込みソフトウェアをドメイン駆動設計で開発する場合、「紙幣」または「硬貨」として定義される「お金」の「種類」というユビキタス言語があるかもしれません。
この場合、上記の10円玉の属性における「硬貨」はユビキタス言語として定義されているため、ドメインから抽出され、モデル化されます。

ドメインはそれ単体では広範囲な領域となるため、通常は複数の小さなドメインに分かれます。
この複数に分けられたドメインサブドメインと言います。
サブドメインで最も価値が大きく重要なものをコアドメインと呼び、他のサブドメインと区別します。

ドメイン駆動設計はStrategic Design(戦略的設計)とTactical Design(戦術的設計)の二つで構成されます。
Strategic Designはドメインの分析とモデリングをどう行うかを示すビジネス的設計であり、Tactical Designはどのようにコードを書くかの技術的設計を指します。

ドメイン駆動設計には主に二種類の登場人物がいます。
デべロッパーとドメインエキスパートです。
デべロッパーは、要するにコードを書く人です。
ドメインエキスパートは、そのドメインに詳しい人を指しますが、必ずしもビジネス側で働く人を指すとは限りません。
デべロッパーがドメインエキスパートを兼ねていることもあります。
ユビキタス言語は、デべロッパーとドメインエキスパートの両方が理解できる言語でなければなりません。

Eric氏はドメイン駆動設計においてレイヤードアーキテクチャーを推奨していますが、関心の分離ができれば他のアーキテクチャーでも実装は可能でしょう。
また、プログラミング言語としては、オブジェクト指向プログラミングが可能な言語を推奨しています。

クリーンアーキテクチャ

私のチームでは、クリーンアーキテクチャーに則ってコードを書いています。
クリーンアーキテクチャーには次の三つの層が存在します。

また上記の三層には次の依存関係があります。各層が矢印の方向に依存しています。

Domain層 <- Application層 <- Infrastructure層

Domain層はどこにも依存せず、Domain層内でドメインロジックの実装が完結します。
Application層はDomain層に依存し、Domain層で定義されたドメインモデルを使って特定のユースケースを実装します。
Infrastructure層はApplication層に依存し、Application層で定義されたServiceやRepositoryなどのインタフェースの実装を行います。

クリーンアーキテクチャーによって依存性を一方向に保ちながら関心を分離することができ、コードが非常に読みやすくなります。

ドメイン駆動設計の採用直後からドメインモデルの作成まで

昨年末からドメイン駆動設計による新規開発がスタートしましたが、当時はドメイン駆動設計に詳しいメンバーが”SAMURAI”こと@karkiしかいませんでした。
私はWeb上の記事を読み漁って基礎知識を吸収しつつ、理解した内容を社内勉強会を開催してチームメンバーに共有しました。
また、Eric Evans著書『Domain-Driven Design: Tackling Complexity in the Heart of Software』(英語版)を福利厚生で購入して読み込み、理解を深めました。

f:id:curama-tech:20200324204512j:plain
勉強会の様子

12月あたりからおおよそドメイン駆動設計を理解できてきたので、@karkiと共に初期のTactical Designを進めていくことにしました。
@karkiは、くらしのマーケットのビジネスに詳しいのはもちろんのこと、システムにも非常に詳しいため、デべロッパーでありながらドメインエキスパートでもありました。
彼からも随時ドメインについての知識を吸収し、理解を深めていきました。

Tactical Designはまず、ホワイトボードでドメインモデルを描くことから始めました。
UMLほど正確には描かずに、本当にラフな感じで描いて修正していきました。
おおよそドメインモデルが描けたら、今度はTypeScriptでざっくり実装していきました。
ドメインモデルのメソッドを追っていき、目的の処理ができることを確認して、初期のTactical Designを完了しました。

Strategic Designで悩む

ドメインの中で、共通のドメインモデルを使う三つのサブドメインが存在していました。
これらのサブドメインを別々に実装するか、一つにまとめて定義するかで苦悶しました。
まとめたサブドメインから別々に切り出して実装することは比較的容易だが、別々に実装したドメインモデルを統合するのは難しいとチームで判断し、結局サブドメインをまとめることにしました。
今振り返ると、この判断で間違いなかったと思います。
サブドメイン単位でISSUEを切って、各々開発に着手し始めました。
まとめたサブドメインは共通のドメインモデルを使うため、設計変更やリファクタリングが発生する度にマージコンフリクトが発生しました。
コンフリクトが発生するとDXも低下するため、リファクタリングは別PRを立てて一回のリファクタリングのスコープを限定することでコンフリクトの量を減らすことができました。

Tactical Designとテーブル設計

サブドメインのDomain層とApplication層のコードが書き終わったあたりで、テーブル設計にも着手し始めました。
インタフェースを実装するクラスが二種類存在するドメインモデルは、それぞれの具象クラス独自の属性が少なく、クラスの種類も二種類と少なかったため、シングルテーブル継承で設計しました。
一方、インタフェースの実装クラスが多数存在するドメインモデルは、具象テーブル継承で設計しました。

ドメイン駆動設計とテーブル設計

実はこの開発が始まる前に、私は既存機能のリプレイスをドメイン駆動設計で行なっておりました。
既存機能のPythonコードをドメイン駆動設計 + TypeScriptで実装し直し、DBのテーブルは既存のテーブルを使う、といった開発でした。
しかし、この開発で大いに苦労しました。
というのも、テーブルは一切変更しないため、ドメインモデルのプロパティがテーブルのカラムに依存したものとなってしまったためです。
なんとか実装したのですが、DBとのやり取りでDBModelとドメインモデルの変換処理が毎回発生し、そのためのコードを大量に書く結果となりました。

ドメイン駆動設計によるリプレイスでは、テーブルを変更しない場合は、ドメインモデルがデータモデルに依存しないように気をつけましょう。

ユビキタス言語とドキュメントについて

ユビキタス言語は、ドメインエキスパートとデべロッパーの両方が理解していなければいけない言語です。
ユビキタス言語をコードとして実装する上で、日本語のユビキタス言語を英語に変換する必要があり、その対応表をチーム専用の辞書として作成しました。
辞書には特定の概念(単語)が英語と日本語で表現されているため、コードを読んでどんなドメインの概念が表現されているかがよく分かるようになりました。
ドメインモデルのプロパティ名やメソッド名もユビキタス言語を使うことで、より一層ドメインの知識を反映したコードが書けました。

ドメイン駆動設計を成功させるためのTips

ドメイン駆動設計を三ヶ月やってみて非常に大切だと感じた点が二つあります。

一つ目は、”とにかく早くプロトタイプを作ること”です。
ドメイン駆動設計は、一度の設計でベストなドメインモデルが手に入ることはなく、数多くのリファクタリングを経てそれに近づいていくとEric氏は指摘しています。
毎回のリファクタリングに時間がかかっていると設計が改善せず、見通しの良い設計となっていくこともないでしょう。
そのため、ドメイン駆動設計の導入段階で、ある程度コードを書ける必要があります。

二つ目は、”コミュニケーション”です。
これは、仕事をする上での一般的なコミュニケーションの重要性とは少し意味が異なります。
ドメイン駆動設計では日々のコミュニケーションでもユビキタス言語が使われるため、そこでユビキタス言語自体が鍛えられ洗練されていくのです。
その結果、認識違いを見つけたり、より良い設計のアイデアが生まれたりと、Eric氏が著書で述べている”ブレークスルー”に繋がります。

f:id:curama-tech:20200324204519j:plain
足のニオイが気になるねこ

おわりに

現在もドメイン駆動設計でコードを書いており、改善点はまだまだたくさんありそうです。
今後も色々なやり方を試してみて、より良い方法を見つけていきたいです。

私たちテックチームでは「くらしのマーケット」を一緒に作る仲間を募集しています。
みんなのマーケットでDDD開発をしたい方は、ぜひコーポレートサイト https://www.minma.jp/ までお気軽にご連絡ください!

第三回LTを開催しました

テクノロジー本部バックエンドエンジニアの福原です。
くらしのマーケットを運営しているみんなのマーケットでは、
社内 LT 会を定期的に開催しています。 LT 会がついに第三回を迎えたので、
会社の雰囲気を伝える&こんな発表をしているよというのを紹介していきたいと思います!

LT 会とは

LT とはLightning Talksの略で、 5 分程度の短いプレゼンをする会です。
LT は、IT 系の勉強会などで開催されていることが多いです。
みんなのマーケットでは、技術枠と自由枠を分けて LT 会をしています。

開催のきっかけ

みんなのマーケットでは、新卒の研修が終わったタイミングで、学んだ内容を発表する会があります。
その発表会に触発されたエンジニア(福原)が、勝手に開催したのがきっかけです。
発表する人を募集したところ、思ったより反応がよく、第三回を開催することができました。

発表内容

今までの発表の内容として、テック系の LT は

  • ぼくは Emacs を使う
  • モダン Web フロントエンド開発環境解説
  • お絵かきチャットに挑戦

といったように、自分で作ってみた系のものから最新技術を取り入れる系まで、様々な分野の発表がありました。 また、自由枠では

  • 坂道グループの Web ページを比較してみた
  • 「わかりやすい文章」の書き方
  • 学ぶ技術

のように自分の趣味を絡めた発表もありました。

開催して良かったこと

開催して良かったこととして、

  • 社内メンバーの興味ある技術がわかった
  • 今までキャッチアップしてなかった分野の技術を知れた
  • LT をきっかけに開発できた(LT 駆動開発)

の 3 つが大きかったです。
また、「次は自分も発表したい」という声が上がったのも良かったと思います。

次回の課題

LT 会の発表終了後には、LT 会に関しての感想や要望を上げてもらっているのですが
その際に、「他部署からも発表者を募ろう」という意見がありました。
第 4 回はテクノロジー本部だけではなく、他部署の発表枠を作ることで
非エンジニアが問題と感じている部分を、技術で解決できないかと試みたいと思います。

最後に

今まで、社内で LT 会を開催してなかったのがもったいないくらい、良い発表がいっぱい聞けました!
特に自分の分野とは違う分野の発表が多々あり、どれも勉強になりました。
今後はこの LT 会から、実際にプロダクトに使われるものが出てきたらな良いな、と主催者として思ってます。

私たちテックチームでは「くらしのマーケット」を一緒に作る仲間を募集しています。
みんなのマーケットで LT をしたい方は、ぜひコーポレートサイト https://www.minma.jp/ までお気軽にご連絡ください!

【宮崎】QAエンジニア 業務体験会@みんなのマーケット宮崎オフィス

f:id:curama-tech:20200117201125j:plain
みんなのマーケット 宮崎オフィス

■イベント説明

今回みんなのマーケットでは、くらしのマーケットの規模が拡大する中で、今後もサイトやアプリを安定して稼働させていくために、QAを増員します。

QAとは「Quality Assurance=品質保証」という職種で、新機能のテストを行い、公開前に不具合を発見することで、出張サービスの良い体験づくりを支えています。

そこで今回は「実際どんな事をやるの?」「QAってなんか難しそう…」そんなお悩みを解消すべく、イベントを開催することになりました!

題して「この「違和感」、どげんかせんといかん!!!」

あなたの「違和感」で勝負しませんか?

■イベント概要

【日時】1月20日(月)19:30 ~ 21:00(受付:19:15~19:30)
【場所】みんなのマーケット 宮崎支社(JR九州 宮崎駅より徒歩約20分)
【住所】宮崎県宮崎市橘通西5-1-24 矢野興業第二ビル6F
【参加費】¥0

■内容

全く未経験の方にもお楽しみいただけるよう「Webページに仕込まれた間違い(バグ)をどれだけ早く見つけられるかを競う」といった大会形式でのイベントとなっております。

優勝者には商品が贈呈されますので、ぜひご参加ください!

■参加方法

・connpassからお申込みください。
https://minma.connpass.com/event/161061/

■こんな人向け

誰でも参加OKです!
・IT業界に興味がある未経験者
・QAまたは、ITに関連する仕事の経験者
・近くにお住まいの方
・転職検討中の方

■持ち物

特にございません。

■服装

私服(社員も全員私服です!)

■注意事項

・駐車場はございませんので、公共交通機関をご利用いただくか、徒歩でお越しください。
・参加された方同士のトラブルは、当事者間での解決をお願い致します。
・社内での怪我や事故に関しましては、一切の責任を負いかねますのでご注意ください。
・イベント中に写真を撮影し、SNSに掲載する場合がございます。撮影NGの場合は気兼ねなくお申し付けください。

ansibleで 「NameError: name 'temp_path' is not defined」 と言われた話

バックエンドエンジニア 兼 SRE のまのめです。

くらしのマーケットでは、デプロイの仕組みとして ansible を採用しており、テスト環境の構築でも同じ仕組みを利用しています。
テスト環境は対応する git のブランチ別に構築することができるようにしています。
この環境を社内では tako 環境 と呼んでおり、テスト環境を構築することを tako を焼く と呼んでいます。

今回は、その tako 環境で遭遇したエラーに関して、備忘録的な意味で書いていこうと思います。
なお、ちょっとした対応の失敗も含んだ内容なので、あしからず。

事の発端

ある日、tako を焼いたメンバーから「tako 焼きに失敗する」と言われました。
エラーを見てみると、

NameError: name 'temp_path' is not defined

と書かれていますが、 temp_path という変数を register している箇所は ansible-playbook の task にありません。
はて…ということで、調査開始です。

調査

まずはググる、ということで該当のエラーで検索したところ、GitHub issue 上で

Out of disk space condition gives error

と言われていました。(リンク)

ということで、ディスクスペースを調べたのですが、

$ df -h
Filesystem      Size  Used Avail Use% Mounted on
devtmpfs         16G   52K   16G   1% /dev
tmpfs            16G  112K   16G   1% /dev/shm
/dev/xxx         99G   46G   53G   7% /

(一部名前など改変しています)
といったように、ディスクスペースには問題がありません。

次に、そもそもコケている ansible-playbook の task の内容を確認したところ、

-   name: install latest version of epel repository
    yum:
        name: epel-release
        state: latest

となっています。

試しにこのコマンドを実行してみようと思い、tako 環境に入って epel-release のインストールを試したら、以下のように出ました。

$ sudo yum install epel-release
Loaded plugins: priorities, update-motd, upgrade-helper
Cannot open logfile /var/log/yum.log
Could not create lock at /var/run/yum.pid: [Errno 30] Read-only file system: '/var/run/yum.pid'

Can't create lock file; exiting

ほう…どうやらなにかしらが原因で yum の pid ファイルが lock されてしまったようです。

lock の解除のため、メンバーに許可を取って EC2 インスタンスを再起動してみたところ、問題が発生し、原因もわかりました。

原因

再起動をかけたところ、インスタンスステータスのチェックが失敗し続け、ssh もできなくなりました。
もはや中身を見ることが叶わなくなったので、EC2 のコンソールから「システムログの取得」をしたところ、こんなエラーが出ていました。

[/sbin/fsck.ext4 (1) -- /] fsck.ext4 -a /dev/xxx
/ contains a file system with errors, check forced.
/: Inodes that were part of a corrupted orphan linked list found.  

/: UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY.
  (i.e., without -a or -p options)
[FAILED]

*** An error occurred during the file system check.
***/dev/fd/9: line 2: plymouth: command not found
Give root password for maintenance

\(^o^)/
どうやら EBS の問題で、 ファイルシステムに不良が出てしまった ようです。
ファイルロックがかかっていたのも関係していそうですね。

対処

EBS の差し替え目的で、インスタンスを立て直しました。
tako 環境用にいろいろ設定するのが手間ですが、仕方ないです。

最後に

tako 環境は無事復旧できました。
パニックになっていたのでインスタンスの再起動という手を取りましたが、それまでは ssh できていたので、普通に fsck をやればもっと早く原因が分かって対処もできたはずですね。
あと、epel-release のインストールにコケた際に、もう少し詳細に調べたほうが良かったです。 そもそも lock ファイルが作れないというエラーなので、もうその時点でおかしいですよね。

私たちテックチームでは「くらしのマーケット」を一緒に作る仲間を募集しています。
今回のようなケースをスマートに解決できる SRE の方も大募集中です。
くらしのマーケットのシステムに興味がある方はコーポレートサイト https://www.minma.jp/ までお気軽にご連絡ください!

第1回 みんなでボードゲーム会@みんなのマーケット不動前オフィス

f:id:curama-tech:20190816130404p:plain

■イベント説明

引越したばかりのみんなのマーケットの綺麗なオフィスで、ボードゲームをする会です。 みんなのマーケットのエンジニア(ボドゲエキスパート)とデザイナー(ボドゲビギナー)が主催するイベントです。 ボードゲームをしたい方なら誰でも参加可能です! 飲み物とお菓子もご用意する予定です!

■イベント概要

【日時】8月24日(土)13:00〜20:00(13:00〜13:30 受付)
※途中参加・退室OK
※終了時刻変更の可能性あり
【場所】みんなのマーケット株式会社(目黒線不動前駅2分)
【住所】東京都品川区西五反田4丁目31−18 目黒テクノビル3F
【参加費】¥0

※途中参加の方へ
当日はビルの入り口が施錠されているため、13:30以降にご参加の場合はあらかじめご連絡いただく必要があります。参加フォームに参加時刻をご入力ください。

■参加方法

下記のフォームより必要事項をご入力ください。
https://forms.gle/eM9hMFhZrXZkf8wa7

※フォーム以外からお申込をご希望の場合
facebookからお申込
https://www.facebook.com/events/1569858529811640/

・connpassからお申込
https://minma.connpass.com/event/141661/

・twiplaからお申込
https://twipla.jp/events/399133

■こんな人向け

誰でも参加OKです!

ボードゲームアナログゲームがお好きな方
ボドゲをやってみたかった方
・みんなのマーケットのオフィスを見たい方
・みんなのマーケットのエンジニアとボドゲでバトルしたい方
・みんなのマーケットのエンジニアとお話したい方
・近くにお住いのかた
・転職をお考え中の方

などなど、お子様・家族連れも大歓迎です!

■タイムテーブル

12:50 受付開始
13:00 ボードゲーム開始
15:00 お知らせ(少しだけ会社のお話をさせてください)
15:20 引き続きゲーム
20:00 終了

■みんなのマーケットにあるボードゲーム

持ち込み大歓迎です!
-スコットランドヤード東京
-インサイダー
-ラブレター
-爆爆バルーン
-ガイスター
-ドンジャラ
-スパイのウインク
-コヨーテ
-犯人は踊る
-ゴモジン
-ゴキブリポーカー
-ナインタイル
-パニックラボ
-ケルベロス
-Kill doctor lucky
-Pralaya
- AVALONレジスタンス:アヴァロン) - タイムボム - ワンナイト新郎 - 知略悪略 - お邪魔者 - お邪魔者2

f:id:curama-tech:20190816130436j:plain
ボードゲーム

■持ち物

・名刺(名刺がない方は受付にて必要事項のご記載のご記載をお願いします)
・持ち込みできるボドゲがある方はぜひご持参下さい!
・飲食の持ち込み可能です(飲み物とお菓子をご用意する予定です)

不動前駅からのアクセス

  1. 目黒線不動前駅を出て左折します。
  2. 商店街を進むと、右手に「BlueNote system」という賃貸管理の会社が見えます。
  3. その左横の小道に入ります。(「いずみ薬局」の前の道)
  4. 小道に入って最初の角を左折します。(左手は「クリーニング竹和」、右手は「ヒロセクリニック」の看板)
  5. 道を進むと大通りにぶつかるので、そこを右折します。
  6. 右手の「銀座よしえクリニック」を過ぎると、目黒テクノビルがあります。(銀座よしえクリニックの隣の建物です)
    会場はこちらの3階です。

■注意事項

・猫がいるので、アレルギー等をお持ちの方は参加をご遠慮ください。
・会場に駐車場、駐輪場はございません。公共交通機関をご利用願います。
・参加された方同士のトラブルは、当事者間での解決をお願い致します。
・社内にはトレーニングルームがあり、たくさんの機器が設置されています。社内での怪我や事故に関しましては、一切の責任を負いかねますのでご注意ください。
・終了時刻が変更になる可能性があります。終了時刻が変更になる場合、みんなのマーケット公式Twitterアカウントにてお知らせいたします。
・イベント中に写真を撮影し、SNSに掲載する予定です。撮影前に撮影可否を確認いたしますので、撮影NGの場合は気兼ねなくお申し出ください。