ravelll の日記

よしなに

エリック・エヴァンスのドメイン駆動設計 2章メモ

ユビキタス言語とそれを作る・使う上でのよくある勘違いの章と理解した。

第2章 コミュニケーションと言語の使い方

  • 言語はドメインに関する意思決定と実装を結ぶもの
    • 言語の乖離は実装の乖離に繋がりそう
  • ドメインエキスパートと開発者のそれぞれがドメインを記述する言語を独自に作り出してしまう
    • 翻訳が必要になるが、翻訳はモデルの概念を混乱させることに繋がり、混乱は破壊的なリファクタリングに繋がる
    • 通訳は知識の噛み砕きを鈍化させる
  • ちゃんとモデルに基づいた言語で会話をするように頑張らないと知識の噛み砕きのプロセスが良いモデルを作ることに繋がらなくなっていく
  • 実装に紐づく言語でみんながしゃべると不意に矛盾が見つかることが多くなって便利で、その一方で開発者の言葉をそのまま共通言語として採用するにはドメインエキスパート側の負担が大きいので双方から歩み寄った現実的な解としてのユビキタス言語という概念、という感じ?
  • 何でもかんでもユビキタス言語化するのではなく、あくまでもモデルが対象とする範囲においてユビキタス言語を作る、というのはなるほどという感じ
  • ユビキタス言語は開発者・ドメインエキスパートが理解するものの最大公約数となるような定義ではなく、厳密に限定された定義としなくてはならない
    • 両者が同じものを想像する程度に理解できる名前だからオッケーというものではない
  • UML はそれを書き出して議論に中心に置くことで統一した相互関係・モデル名を全員が持ち議論できるようにする = Unified Modeling Laungage
  • UML はそんなに完璧に詳細を書き出すものではない
  • UML はオブジェクトの属性と関係は容易に書き出せる一方でオブジェクトの振る舞いや制約は書き出しづらいツール
    • その限界をユビキタス言語を用いた会話によって補える
  • "モデルは図ではない"
    • 図は単にモデルについて議論する際にコミュニケーションや理解を円滑にするための表現の1つというだけ
    • 前職で開発の進行をやったときにすべてのモデルを言葉で表現しようとしたけど、もっと図を使ったり、複数の方向からモデル作成を試行してみればよかったな…
      • そもそもコミュニケーションが足りてなさすぎたのも問題だった

書かれた設計ドキュメント

  • ドキュメントが事実と乖離していく問題
    • XP => 極力書かずにコードに語らせる。コメントはこれに含まれないので重視しない
      • 厳密で活きたモデルを保てるが、理解しづらい。また背景を伝えられない
  • "すでにコードがうまくやっていることを、ドキュメントでもやろうとするべきではない"
    • ドキュメントはコードを補足する
  • ドキュメントはそれが必要なら乖離が問題として浮上する
  • 問題にならず乖離しているドキュメントは更新するのも時間の無駄
  • ユビキタス言語でモデルの背景となるビジネス知識などを共有することに成功するとモデルのドキュメンテーションを小さくすることができる
    • ドキュメントでコードと会話を補足する
  • "正しいことをするだけでなく、正しいことを言うコードを書くためには、潔癖でなければならない"
    • 前者だけではモデルとの繋がりが曖昧になる(名前が曖昧とか)
  • コードから何らかモデルを説明するもの(図とかテキストとか)を出力する方法は研究されていないのかな
    • コードを直接ドメインエキスパートが読むのは現実的には難しいけどそれを抽象化したものを使って会話ができると良さそうな気がする

説明のためのモデル

  • 実装、設計、コミュニケーションの根底にあるモデルはチームで1つにしよう
  • モデルのコアとなるものではなく一般知識を説明するためには別のモデルを利用できる
    • そのときにはコアとなるモデルと混同しないように UML は使わないほうが良い

エリック・エヴァンスのドメイン駆動設計 1章メモ

今週から社内で読書会が開かれることになった。基本的には事前に読んでくるスタイルの会ということで第1回の範囲となる1章を読んだので、雑に取ったメモを放流。

1章 知識を噛み砕く

  • ドメイン知識が無い状態でもの(PCB)を作った体験
  • ドメインエキスパート(PCB回路設計者)がソフトウェアが達成すべきものをよく知っているわけではない
  • ドメインエキスパートと話し合う中で語彙を研鑽する
    • 用語の不一致を正す、使うべき言葉をドメインエキスパートが学ぶ
  • 処理の流れ(モデル)を一緒に書いていくやり方が良い?
    • 登場人物の名前を知る
    • 登場人物の関係を知る
    • 処理の名前を知る
    • 処理の概要・目的を知る
  • ドメインエキスパートとの議論においてソフトウェアの詳細に立ち入り過ぎないよう気をつけるべきっぽい
    • "すみません、詳細に立ち入りすぎました"
  • ドメインモデルを注意深く作成することで本質的な処理を見つけやすくなる?
    • "その後ほんの数日のうちに〜実際に計算したことには変わりない"
  • ドメインエキスパートと一緒に図を作ったことで、あるドメインの複雑さの中で今回つくる機能が持たねばならない部分がどこなのか、を開発者単体で考えたときと比べて精度高く知った状態で開発に入ることができるのでは
    • 複雑さを見誤るとどんなに設計が良くても負債になりそう
    • 例えば Web アプリだと DB の設計を含むくらい機能開発をするときにはミスると辛いしそこを境界線として特に注意深くドメインエキスパートとコミュニケーション取りながら作る、みたくすると良いのかもしれない
  • ドメインエキスパートと一緒に図を作ることでソフトウェアの構造をドメインエキスパートより理解できるようになる
    • その結果、ドメインエキスパートがソフトウェア開発に協力的になる、という流れがある
    • ドメインエキスパートとの距離を感じたら大まかな設計を一緒にやってみることから始めると良いのかな
    • ソフトウェア開発者がドメインエキスパートとコミュニケーションを取るフレームワークとなった
      • 完全にいい話
  • ドメインエキスパートと一緒にモデルを作成しソフトウェアを開発することで、ドメイン知識がソフトウェアに組み込まれる
  • 本ではドメインエキスパートがオブジェクト間の相互作用を提示するまでになってるけどそれを望むのはきつそう
  • 顧客が本当に求めているものを協力して探すには、やはりモデルを一緒に作るのが良さそうに感じた
    • "モデルを改良すると、コードも一緒に進化した。数カ月後、PCB 技術者は自分たちの期待を上回る、機能豊富なツールを手にしていた。"

効果的なモデリングの要素

  • 筆者によるこの話についてこれが成功の秘訣だったリスト
    • モデルと実装を結びつけること
    • モデルに基づいて言語を洗練させること
      • 最初辛い(主にドメインエキスパートが)けど相互にモデルを理解できるようにしておくことでモデルの構造と矛盾しない思考で議論することができるようになった
    • 知識豊富なモデルを開発すること
      • モデルは単なるデータスキーマではなく、複雑な問題を解決する振る舞いと守るべきルールがある。クゥ〜ッ
    • モデルを蒸留すること
      • 蒸留 = 本質的でない概念を切り捨てる
    • ブレインストーミングと実験をすること
      • モデルの形を色々と書いてみては議論することで使えるか調べた
      • このときに会話がぎこちない = このモデルはダメそうという判断ができた
  • (ravelll)開発者がドメインエキスパートのとき DDD を利用する利点はあるのか
    • ユーザーを登場人物に含めて間接的にモデルについて議論する、と考えるとモデルを洗練させ実装と一致させる狙いで利用する意味が十分ありそう
    • DDD が良いのは翻訳による情報の欠如や時間的なロス、人間関係の改善とするなら、ユーザーと直接話すことはなく開発者がただ議論するだけなら翻訳のオーバーヘッドも小さそうなので実は効果的ではない?

知識の噛み砕き

  • "噛み砕く" = それの根底にある意味を知るプロセス
  • "ドメインモデルを噛み砕く"ということ
    • 情報の流れを掬ってその重要な意味の大部分を理解できる抽象的なモデルを見つけること
  • 知識の噛み砕きは一人で行うものではなく、開発者とドメインエキスパートで行う
    • 大抵は開発者が率いる
  • 知識噛み砕きプロセスの失敗事例
    • (1.) ウォーターフォールでの流れ
      • ビジネスエキスパートがアナリストに話をする
      • アナリストが情報を噛み砕き抽象化する
      • ソフトウェアエンジニアがそれを実装する
        • この流れにはフィードバックのタイミングがない
        • アナリストが基にするのはビジネスエキスパートの話だけ
    • (2.) イテレーティブにやってるけど抽象化してなくて知識が積み上がらない
      • 何を作るかビジネスエキスパートに聞いて実装し、終わったら提示する
      • "何を作るか" だけに集中するとモデルの蒸留が行われなくてダメそう
      • "そうしたやり方でも(snip)既存機能の必然的な帰結として強力な新機能が現れるという段階には、決して到達することがない。"
        • ゴールド・エクスペリエンス・レクイエム!!
      • 抽象化もドメインエキスパートとの共同作業なしに行うとドメインエキスパートの考えと乖離してしまう
      • "チームメンバ間のやりとりは、メンバ全員がモデルを一緒にかみ砕くことで変化する。" いい話っぽい
      • ドメインモデルを絶えず改良すると開発者はビジネスにおける重要な原理を習得するよう強いられる、というのがちょっとわかってない
        • ドメインモデルを絶えず改良すること = ドメインエキスパートと絶えずコミュニケーションを取ることで、
        • 重要な原理を習得していないことはドメインエキスパートとコミュニケーションを取ってモデルを作ることを妨げるから?
  • うまく知識をチームが噛み砕けるとモデルはビジネスの深い知識を反映したものになる
    • "改善されるにつれて、モデルは、プロジェクトの中を流れ続ける情報を体系化するためのツールとなっていく。"

継続的学習

  • 生産的なチームを知識を意識的に育てる
    • 十分な知識が無いことを認識することはしばしば難しい
    • 知識はメンバーの入れ替えやアウトソーシング等によって流出する
  • "技術的な知識" って例えば gRPC について知る、みたいな話?
  • 知識があると知識の噛み砕きをよりうまくできるようになる
  • 例えば PCB の事例について学んだところ
    • (エキスパートとの対話を通じて)アプリケーションに関連する重要な概念の理解
    • 構築している内容がただしいかどうかのチェックを行うこと
  • 大事なのは共同作業によって作成されたモデルが残ることではなく知識の噛み砕きのプロセスを起こさせること
    • 知識の噛み砕きが行われることで以後の作業がより効果的になる

知識豊富な設計

  • 設計やリファクタリングはモデルの変化を主軸として行われるもの
    • 逆に言えば、開発者はモデルの変化に機敏に対応できる設計にし、実際に追従していかねばならない
  • 存在しているエンティティやコードを超えて、相互作用やビジネスルールに注目する
    • コードは合っているがビジネスルールとして矛盾している、ということに気づける
    • この辺コードレビューしてるとどうやったら気付けるのかな〜とよくなる…
      • 普段から背景となるビジネスルールまでを考えてコードを読み書きすることで一歩抽象度の高いレビューができるようになる?
  • 人間は自身が触れている世界のプロセスを処理する中おきるギャップを思考によって無意識に調整・補完している
    • そんなことはソフトウェアにできないので、知識をちゃんと噛み砕いて具体化させ、実装したり切り捨てたりする
  • 貨物船の例
    • あるモデルが満たすべきルールを相互作用のプロセスに押し込んでいる
      • これではドメインエキスパートがコード(エンティティを指している?)を読んでも検証できない
    • 知らない人が要求定義とコードとを結びつけるのが困難になる
    • この例ではオーバーブッキングポリシーを別クラスとして表現しているけど、これはポリシーは船舶にも荷物にも紐づくものではなくビジネスとして存在する"知識"であるから独立したクラスとして表現されるのが適当、という判断?
      • "知識を確固たるものにして共有するのに使えることを示すために用いた" とある

深いモデル

  • アプリケーション作ってるときにそれを誰がどう使っているのかを勝手に思い込んでいらない機能を作る、というのは超あるあるという感じ

ISUCON9 予選に参加してきました #isucon

チーム泥酔チャンスとして同僚の @manicmaniac, @mpls104 と共に参加してきました。ISUCON 予選に参加するのは ISUCON7 ぶりで、ポジションは当時から変わってインフラ担当。

やったこと(〜前日)

  • リハーサル環境の構築
  • デプロイスクリプトの準備
  • 設定をまとめた nginx.conf, my.cnf の準備
    • メルカリ社が出題担当なら nginx(OpenResty) + MySQL かな、そうに違いない!そうであってくれ頼む〜という心境でした(h2o や PostgreSQL に疎い)
  • puma, nginx, MySQL の設定・インストールの素振り
  • ログ解析の素振り
    • kataribe, mysqldumpslow, pt-query-digest

やったこと(当日)

アプリケーションのコードはほとんど変更せずに終わってしまった。

  • インスタンス作成
  • コードを commit
  • ミドルウェア周り色々
    • 設定のバックアップ、ダンプ、設定変更、ログ解析など
  • /users/transactions.json の改善
    • SQL の複雑さを ruby に押し付ける + INDEX 貼る感じで改善を試みるも失敗、断念
  • /buy の自商品購入時に 403 を返す処理をトランザクション外で行う
    • SELECT FOR UPDATE 回避の意図だったけどよく分からんしとりあえずやる〜?くらいの感じだった

写真は当日のホワイトボードの様子。書き殴られている。

f:id:ravelll:20190908181816j:plain
書き殴り

結果

4010点でした。
このスコアには開始3時間くらいで到達した(ログを見ると12:47:47)のだけど、5時間そこから伸ばせず終わってしまった…

f:id:ravelll:20190908220829p:plain
この時点で5位だった

POST /buy で 403 が増え続け、何が理由なの〜とみんなで数時間唸っていました。ちゃんと復習せねば。

反省

  • とにかく準備に余裕がなかった
    • 8月半ばまでメンバー募集してたり体調悪かったりスケジュールが詰まってたりした。余裕のあるスケジュール大事
  • ドキュメント読みつつアプリケーションをじっくり触る時間を取ればよかった
    • ISUCON7 のときも言った気がする…
  • puma のログをちゃんと出しつつやればよかった
    • 事前に素振りできてなくて、なあなあで出さないまま続けてしまった
  • アプリケーションのコードを一通り眺めて怪しい要素をリストすれば良かった
    • 終わってから "そういや bump って何?" となってダメだった
    • ボトルネックとなっている処理の周辺しか眺めなかった
  • 明確に役割分担をしておくべきだったかも
    • A さんは X についての知見をためておき当日は手を動かしてもらうこと、というのを合意して学習を効率化すべきだったかも
      • 一部調査が被った
    • インフラの設定を複数人がカジュアルにいじって知らないうちに死んでた、ということが何度かあった

今回は事前準備が全然できなくて "みんなで楽しめればそれで優勝" くらいの気持ちだったのだけど、いざ成果を出せずに終わるとやっぱり悔しい。前回はウオオオとなる瞬間が一度はあったのだけど、今回はそういった機会が本当に一度もなくヌル〜ッと終わってしまったのもやや悲しかった…とはいえ歯が立たなかったということはそれだけ学ぶべきことが多かったということなので、後日ちゃんと振り返りして糧にしたいですね。

そして次回があるならばもっと余裕を持って臨めるといいな。次回のメンバーを早速募集します。当方ピアノ兼 Ruby