「レガシーをぶっつぶせ。現場でDDD!2nd」の 第2部 C に参加した
『レガシーをぶっつぶせ。現場でDDD!2nd 「インプット<アウトプット!」』 第2部 かとじゅんさんの「C:モデリングワークショップ 〜割り勘ドメイン編〜」に参加してきたのでその参加記です。
よくDDDは「実際にやってみるとわかる」というのはよく聞いていたのですが、 それを同じようなモチベーションでやってみようという人が集まってやってみる場というのはとても貴重でした。
今回はその中の1パートで行われた、割り勘ドメインのモデリングワークショップでやったことと、その感想を書いていきたいと思います。
グループワークでの割り勘ドメイン設計
タイトルにもある通りいくつかの要件を満たした上で割り勘システムを作ろうという課題でした。 以下実際の資料から引用いたします。
幹事が 飲み会 を開催する(システムの外) 幹事が、システム上に、開催した 飲み会 の 名前, 開催日時 などを設定する 幹事が、システム上の、開催した 飲み会 の 参加者 を追加/削除する 幹事が、システム上の、開催した 飲み会 の 支払区分 (多め,普通,少なめ)ごとに 支払割合 を設定する 幹事が、システム上の、開催した 飲み会 の 請求金額 を設定する 幹事が、システムを利用して 飲み会 の 参加者ごとの支払金額 を計算する 割り勘の具体的な計算方法は決まっていません。チームで相談してください。ただし以下は考慮してください 割り勘の方針には、 支払金額 が多め・普通・少なめを考慮すること(上司は多め、遅く来た人は少なめに金額設定するため) 飲み会 の 請求金額 と割り勘した 合計支払金額 に 差額 が生じる場合は、システム化対象外してよいです(余裕があるチームは幹事が負担する仕様で検討してください) たとえば、20,000円で3人で均等の割り勘の場合、1人6,666円とすると2円の不足が生じます。不足分は幹事が負担するときれいですが仕様外にしてもよいです。あまり細かいところに時間を掛けすぎないようにしましょう。
30分でモデルやプロパティ、メソッドまでを実装、45分で改善をしていこうという物です。
実際自分のチームがどういう風なプロセスを経て実装して行ったかを時系列順で箇条書きに書き起こしてみます。
- まずは要件の中に出てくる名詞を列挙して、それぞれの関係を考えていく方針に
- 1番大きいものは「飲み会」、「飲み会」には、お店からの「請求金額」と「参加者達(参加者のリスト)」がいる
- 「参加者」にはそれぞれ「請求区分」(多い、普通、少ない)が当てはまっている
- 「請求区分」ごとに「請求割合」が決まっている
- ここまでで、「飲み会」クラスと、「参加者」クラス、「請求区分」クラスは絶対にいるということで作成
- 次に具体的な計算ロジックについて
- 割合を使って比重を変えるやり方をする
- ある人Xの支払い金額 = 「請求金額」に、Xの支払い割合 / 全員の支払い割合の和
- 参加者が誰かを指定すると、その人の請求金額がわかる
- 例えば全員が「多い」にした場合に、全員の支払い金額が、全員が「普通」にした場合と同じになるのは許容する
- ある人Xの支払い金額 = 「請求金額」に、Xの支払い割合 / 全員の支払い割合の和
- しかしこのやり方だと、「全員の支払い金額」が「請求金額」が等しくならない場合がある、それは「差額」として別に考える
- この計算は飲み会があると発生するので、計算メソッドは飲み会に持たせる
- 割合を使って比重を変えるやり方をする
- ここまでして「参加者達」を参加者のリストにすると上記の「全員の支払い割合の和」を求めるのが大変なのもあり、「参加者達」をクラスに分離
- 「参加者」のリスト
- メソッドとして、「全員の支払い割合の和」が出せるようにする
- お金と人の発生タイミングについて、実際のユースケースと認識を合わせる
- 1.このシステムを使うタイミングは、飲み会発生後、人とお金は必ず存在する
- 2.人が集まってから、飲み会が発生、その後お金が発生する。なので「請求金額」がないこともある
- この辺は特に指定がなかったこと、自分たちのこれまでのロジックが1よりであったことから、1ということで改めて認識を揃えました
出来上がった実際の関係図はこんな感じでした。
実装を完了した時には当初の予定であった30分をオーバーしていたのですが、 実際時間は正確に切られているわけではなく、実装と改善の時間はチームごとに自由にしていいということだったので、作業はとてもしやすかったです。
改善パートでは、主に支払い人数の増減の対応、参加者が0人にならないように「参加者等」クラスの拡張などをしていました。
ここらへんは特に引っかかることなく、時々声かけていいただけたヒント部分もしっかり実装できていたと感じています。 振り返ると実装パートの部分で、この「金額」とは何か?などをしっかり議論して、拙いながらも区別できる名前をつけ認識を揃えていたのが効いていたのかなと思いました。
一通り要件を満たし、全体を全員で見回したうえであがった反省としては、あまりに飲み会クラスが大きくなってしまったことと、 ある参加者が飲み会によって立場が変わるのに、上のようにしたため、その度に実際は同一人物の参加者が増えてしまうことです(「ある飲み会Aのxさん」と「ある飲み会Bのxさん」)。 後者は使い切りということで許容できるとしても、前者はどうするといいんだろうね…と考えたところで、実装パートを終えました。
共有パートで気になった2チームの話
共有パートで自分視点で気になった話や状況をピックアップします
- モデルの持ち方はチームごとに意外とバラバラ
- 計算ロジックは5チーム中、4チームは自分たちと同じ比重で計算する方法、1チームは素直に人数で割ってベース金額を求めた後、「少ない」人は割合に応じて減らす、その後不足分を「多い」人に分配する方法だった
- どのチームもモデルをどこかのタイミングで作り直していいたり、編集を加えていたりしている
- どんなやり方であろうと、チーム間での合意をもって作業をしていた
そんな中自分が気になった2チームがありました。 1チームは、上のピックアップでも出した「ベース金額から分配する計算方法」のチームと、「計算ロジックを飲み会の外に切り出す」チームでした。
「ベース金額から分配する計算方法」のチームの方にモデルの写真を撮らせていただいたので、載せさせていただきます。ありがとうございました。 確かに支払い金額を人数で割った「普通」の人が払うベース金額、「少ない」人がベース金額に割引率をかけて払う金額、「多い」人はその不足分を割って払う、という図があります。
「ベース金額から分配する計算方法」のグループの方に、なぜこのやり方になったのかという話をしたところ、 チーム内では全員がこのやり方を支持していて、かつ、実際の割り勘でよくある動きをシステムに落としたという話を聞くことができました。
確かに彼らの考えたやり方は今回の要件である、請求割合のやり方から考えると少し変わった計算方式のように感じましたが、 実際の割り勘では、「少ない人は1000円、残った分を他の人で割る」や、「上司が1万円置いて行って、残りを割る」といったケースは多く、実際のシステムの方向性としてとてもありな計算方だなと感心しました。
確かにその計算方法を作ったグループの方は、「自分の支払い金額もそうだけど誰かがいくら払うかがしっかりわかること」をどこかのチームかに質問していたような気がしていて、とにかく実際のユーズケースを考えて考えていたんだなととても納得しました。
その上で、「計算ロジックを飲み会の外に切り出す」チームを見てみると、 今回の生産システムの中で1番変わりやすい部分をしっかり外に出した設計というのはとても正しいものなのかもしれないと感じました。
どういう経緯でチーム全体がその設計にたどり着いたか聞きたかったのですが、グループの人がどなたかわからず話を聞くことはできませんでした…。
こういう風になぜその実装にしたのかを直接聞くことができる場というのはとても楽しく、 その上で自分のチームのモデリングを見るとまだまだ直したいところ、こうすべきかもという考えが湧いてきて、 「モデリングをする」ということへの理解がとても深まる時間になりました。
全体の感想
- チーム内でモデリングをする際はチーム内で考えていることをしっかり揃え、きっちり言葉にしていくことが大切だということを感じた
- 実際にコードにしていくことで、自分たちが考え切れていなかった部分がわかってくることもある
- モデリングされたものだけではわからないこともある、その背景を聞くことでモデルの良さがよりわかることもある
- その上で今回のワークショップはそれらを痛感する機会になりました
- 一方2時間はあっという間でもっとやりたい!という気持ちが強かったです
- それこそ、「割合の他に、特定の支払区分の人の支払額を定数で指定できる様にする」を追加したらどうなっていたでしょう………
最後になりますが、とてもあっという間で自分の中でモヤっとしていた、実際どうやるんだろう?、が参加前より明確になるような時間を過ごせました。 運営の方、一緒にグループワークした方、同じワークショップに参加した方、ありがとうございました。