Object design rough talksへ行ってきました
金曜の夜、Object design rough talksへ行ってきました。Twitterのハッシュタグは #ObjectDesign でした。
- Object design rough talks on Zusaar http://www.zusaar.com/event/5037004
面白かったトークの抜粋と感想を書きます。
t_hysshさん「オブジェクト指向レッスン」
感想
こういったルールは、チームでコーディング方法を統一することを目的とするなら機能しそうだなぁと思いました。
また、林さんは、実際に仕事でチームに適用したところそこそこ上手くいったとおっしゃっていたので、オブジェクト指向を理解している人が、そうでない人のコードをレビューしながら適用すると、オブジェクト指向を学習する上でも効果があるのかもしれません。
ただ、以前、次のスライドを見て素振りのつもりで取り組んだ結果、悩んでしまったことを思い出しました。
形はルールに沿っているものの、オブジェクト指向で設計されたコードが出来上がったかというと違いました。あの時の理解と技能の不足を補うために必要だったのは、カタを覚えて繰り返す以外のアプローチだと思います。
オブジェクト指向で書かれたコードの特徴的な部分を抜き出してコーディング規約として定型化しても、それをなぞることでオブジェクト指向の設計をリバースすることはできない、というのが自分の考えです。
yaakaitoさんのトーク
この記事を書かれた方でした。
- SNSチームでのドメイン駆動設計の実践 http://labs.gree.jp/blog/2013/12/9330/
内容
仕事の開発でドメイン駆動設計をどんなふうに取り入れて、どんなことになったか、というお話でした。開発対象は、SNSのようなWebサービスのフロントエンドとのことです。
- どうやってドメインモデルを分析したか
- 分析を民主的にやるか、独裁的にやるか
- 民主的にやるとコミュニケーションコストが高い
- 人によって思っていることが違うというのを引き出せた
ここでの"民主的"は、おそらく「皆で話し合って決める」という意味だと思います。
人による認識の相違の例として、(Twitterのような機能で)「ツイートの下にコンテンツ(文章や写真など)がある」という構造にもかかわらず、「ツイートからコンテンツを生成する」という感じの名前の変数があったせいで、関係性を逆転して捉えてしまうケースがあった、というエピソードが挙げられました。既存の処理の命名や実装に引きずられて、ドメインモデルの構造定義を間違えそうになった、という話ですね。
冒頭の記事は帰宅してから読みましたが、あらかじめ読んでおけばよかったと思いました。
感想
ドメイン分析を皆でやるか一人でやるかについては、難しいなーと思いました。最近、既存のパッケージ製品の更改のために1人で分析の真似事をやりましたが(レビューしてくれるアーキテクトはいるけど、ドメインエキスパートは不参加で)、自分の間違いに気づくのに時間がかかりました。意見の違う人と議論する時間を節約できるのは利点ですが。
また、「すでにあるものに分析が引きずられる」という話には頷いてしまいました。自分の場合、一旦完成したシステムが目の前にすでにあったので、DBの構造、各種命名、処理の実装、ユーザマニュアルの章立てなど、あらゆるものが分析のヒントにもなり罠にもなる感じでした。で、実装に引きずられない分析がしたいと思うわけですが、それって意味あるのか?とも思います。
ドメインモデルに加えて、よりフロント側にアプリケーションモデルを定義したという話も、興味深かったです。ドメインモデル≒Modelと、アプリケーションモデル≒ViewModelですよね。
ドメイン分析の結果を直接展開するのは、ドメインモデルと呼んでいるレイヤーだと想像しますが、ドメインモデルの入れ子構造や1対多関係を、アプリケーションモデルにどこまで展開するのかが気になりました。
深い構造のままフロントへ持っていくと、画面を描画するための実装が複雑になります。とはいえ、アプリケーションモデルを画面構築用の入れ物として作ろうとしても、(一覧表示用の要素のように)リストで持ち回りたいデータが出てくると、"ドメインモデルぽいけどドメインモデルじゃないちょっと複雑な1対多構造"を定義したくなたりします。そのあたりのさじ加減が悩みです。
uzzuさんのトーク「オブジェクトで会話できてる?with DDD」
内容
- 「モデル」という言葉を使わないようにしよう
- コンテキストがないと解釈がばらばらになってしまうから
- モデルという言葉を使うときは何のモデルなのかを明確にしよう(例: ドメインモデル)
- オブジェクトの概念的寿命≠ライフサイクル
- コンテキスト境界を超えると、不適切になる語がある
- 例: スコア
- 野球、サッカー、バスケットボール
- 1点ずつしか得点が入らないサッカーで、AddScore(1)のようなメソッドは不適切
- オブジェクトのライフサイクルに関する実装が、ドメインモデルの実装に混ざるのはダメ
- 実際のモデル概念図の説明
- Passive ViewパターンとSpecificationパターン
- ゲーム内の計算結果を得るためのIPolicy
- 分析にはコストがかかる
- 許容できないコストになりそうだったらやめたほうがよい
- 規模が小さいものに適用してもあまり意味がない
質疑
- コストがかかりそうだけどどこまでやるの?
- たとえば、RepositoryクラスはReadとWriteがあるから、厳密には責務を分割できていない。参照系だけならEntityReaderとでもするところ。それをひとつにまとめると、実装はラクになる。
- レイヤーを縦割りで担当するか、横割りで担当するか
- 縦割りで担当した方が、上から下まで見ることになるので教育としてよいという人もいるが、(発表者は)横割り派。横の方が各レイヤーの技術についての習熟度が上がる。インフラ層も業務層も、どちらも難しい。それぞれに担当を配置+アーキテクトという体制がよい。
- レイヤー横割りで開発すると、1つのシナリオを実装するだけでも、全レイヤーの開発者が必要になり、オーバーヘッドが大きいのでは。
- 今回は新規開発だったので、UIをプロトタイプ開発している間に、別のメンバーがドメイン層を作るというようにして、対応した。
- ユーザの言葉で定義しようといいつつ、ユーザもわれわれも日本語話者なのに、図に英語があるが、英語と日本語の同期はどう取るの?
- 覚えましょう。
チームの共通語として通用するなら、定義した言葉が英語として正確でなくても、モデリングにおいては問題ないとする、という意見もありました。
- 人間は論理的でないが、その論理的でないもののためのドメインモデルはどうやるのがよいのか?
- まだ取り組めていない。フロー、意味の一貫性、アニメーションが誘導するメンタルモデルなどをモデリングできればとは考えている。
「デザインに違和感を持ったら、デザイナにフィードバックしよう。それを採用するかしないか考えて決めるのがデザイナ」という意見が出たのは、このくだりですね。
- 「ドメインを決める」というが、ドメインは育てるものでは? ドメイン定義に失敗したときにリカバリするためのプラクティスを知りたい。
- 新規開発で失敗してしまうと、それを直す目的だけで工期を取るのは難しいのではないか。失敗を防ぐには、(範囲が?)小さいうちに失敗するのがよいかもしれない。
これについては、質問された方から「デザイナとエンジニアとドメインエキスパートの三者で、ユーザのメンタルモデルを作るのがよいのではないか」「結局『誰を喜ばせたいのか』から練る方針で」という意見がありました。
プロジェクトで大方針を1つ固めるより、いくつかの方針(選択肢?)を持ち、やるときは部分的に始めるのがいいのでは、という話もありました。
感想
「オブジェクトの概念的寿命≠ライフサイクル」については、TODO あとで調べる です。
スコアの例がよく理解できなくて、サッカーのスコアもバスケットボールのスコアも、「プレイ中に加算されてゆくもの」という概念は一緒じゃないの?と思ってしまっていました。でも、後のrosylillyさんのトークでちょっと分かった気分になりました。そこまで一般化するとやりすぎ、という話なのかなと。
日本語と英語の話については、次のtweetを見てさっそく電子書籍を購入し、今の開発で使っている言葉を確認しました。
この本の存在は知っていましたが、当分読むことはないと思っていました(今の仕事でやっているローカライズでは、別のチームが作ってくれた言語セットを使っていて、自分で一から考える必要がないので)。しかし、クラス、メソッド、変数やドメインモデルの命名の際にも、使える本だったんですね。
質疑で「メンタルモデル」という言葉が何度も出てきて、なんのこっちゃと思っていたのですが(不勉強ですみません)、これも後のrosylillyさんのトークでちょっと分かった気分になりました。
rosylillyさんのトーク「DCI」
- Points of View https://speakerdeck.com/rosylilly/points-of-view
内容
- リンゴの写真と窓の写真を並べて、間に「vs」と書く
この分解の違いが、メンタルモデルの違い。
- 具体的な振る舞いを集めたものに名前がつく
- 最初から名前をつけるのは難しいことも多い
- 例: DBの関連テーブルにあたるものもオブジェクトであるべきだが、名前付けが難しい
- ユーザがコミュニティに参加することで作成される「つながり」オブジェクトは、deleteしたりswapしたりできる
- 怖いボタン
- ユーザは、その操作をキャンセルできるかできないかが分からないボタンを押したくない
- 例: 「Show Accounts」「Transfer Money」「Show Logs」←まんなかのボタンだけこわい。「送金先を選ぶ」とかにして欲しい
- こういうことが起きるのは、開発者とユーザが同じ方向を見ていないから
- 開発者が知識を積むと、ユーザ当事者の気持ちが分からなくなる
- 解決策として、チームの新入りに、チームにすでにあるUIやコードの「分からないこと」を聞こう
- 高血圧なドメインモデル
- ある時だけ必要になる振る舞いをドメインモデルに入れていいの?
- シチュエーションが違うと意味が異なるものを、無理にまとめるのは抽象化しすぎ
- 分類、分割しよう
- 例: 商品は売り手にとっては売り物だが、買い手にとっては購入品
- 分解や誘導によって現れるメンタルモデル
- エンジニアのメンタルモデルは世の中で多数派ではない
- BluePrint
- https://github.com/magnet-inc/blue_print
- コンテキストの下に振る舞いがあるような構造を作れるテンプレートジェネレータ
- 仕事で投入していい感じにいってるとのこと
感想
プレゼンテーションが素晴らしくて聞き入ってしまいました。また、大量の鳩画像を見て、鳩に目覚めそうになりました。
メンタルモデルの説明が分かりやすかったです。他の説明も知りたいので、TODO あとで調べる です。
「DBの関連テーブルにあたるものもオブジェクトであるべきだが、名前付けが難しい」について、自分もいつも悩んでいます。そもそも、実際に分析していると「つながりはオブジェクトにすべきかどうか」の時点で議論になることもあります。つながり自体が管理対象ならば、イベント系エンティティを受け取るドメインモデルとして、もちろんオブジェクトにすべきだと思います。1対多や多対多の関係を整理するためだけの情報ならば、オブジェクトは不要で、DBのテーブルを参照するだけで十分、という局面もあるかもしれません。
自分の場合、「あるシナリオでだけ必要になる振る舞い」は、Viewに関する操作であればアプリケーションモデル、データ操作であればRepositoryに入れる感じでやっています。ドメインモデルからは排除します。これでいいのかは TODO 勉強する ですね。
BluePrintのコンセプトはすごいなあと思いました。ドメイン分析するとコストがかかるとか、分析したいのは分かるけどダルいとか言ってる老害に対する明確な煽り純粋に技術的なアプローチで、痺れました。
全体の感想
当初は内輪の勉強会にするつもりだったそうですが、広く公開してくださり、ありがとうございました。とても面白かったです。最初はtweetしながら聴いてたんですが、途中からトークを聴くのに没頭してしまい、Twitterのことを忘れていました。
ここしばらく1人でずっとエンティティの整理をやっていて、いろいろ悩むことがあり、ヒントを探したいと思って参加しました。ヒントは多々ありました。まずは、ずっと避けていたDDD本を読んでみます。(DDDより先に身につけるべきことがたくさんあるという認識で、後回しにしていました)
お話ししてくださった皆さん、主催の方、会場提供くださったLINEさん、ありがとうございました。