Upgrade to Pro — share decks privately, control downloads, hide ads and more …

モデルのリファクタリングが難しいと思ったら、そもそも複雑だったのはビジネス仕様だった ? / ...

Avatar for hatsu hatsu
September 17, 2026

モデルのリファクタリングが難しいと思ったら、そもそも複雑だったのはビジネス仕様だった ? / is-the-business-domain-the-real-complexity

Avatar for hatsu

hatsu

September 17, 2026

More Decks by hatsu

Other Decks in Programming

Transcript

  1. 02 · SELF INTRODUCTION ⾃⼰紹介 2019.4~ フリーランス 2024.6 SHE.inc 2024.09

    Kaigi on Rails で CIの話をした 2026.09 RailsTokyo#6 で話します @hatsu_38 RailsTokyo #6 ‧ モデルのリファクタリングが難しいと思ったら、そもそも複雑だったのはビジネス仕様だった(?) 02 / 32
  2. 03 · AGENDA 話すこと 1. 複雑さの紹介 と 課題内在性負荷‧課題外在性負荷 2. 弊社の「会員システム」の簡単な紹介

    3. 「休会」の設計はイケてなかったのか? 4. モデルの⽬的と安定依存の原則(SDP) ※ リファクタリング というより “リ”アーキテクト や “リ”モデリング って表現が正しい RailsTokyo #6 ‧ モデルのリファクタリングが難しいと思ったら、そもそも複雑だったのはビジネス仕様だった(?) 03 / 32
  3. 04 · DOUBLE BILLING コトの発端 - ⼆重課⾦ • • •

    不要な注⽂申し込み(=⼆重課⾦)が いくつかの状態の組み合わせで発 ⽣してしまっていた 管理画⾯から注⽂を⾏い、休会中 に退会申請を出し、その後休会復 帰予定より前に休会復帰した場合 に発⽣する 要は「退会」や「休会」で、サブ スクで次に注⽂するべき⽇と商品 の判定が難しくなっていた →リアーキテクトしよう! RailsTokyo #6 ‧ モデルのリファクタリングが難しいと思ったら、そもそも複雑だったのはビジネス仕様だった(?) 04 / 32
  4. 06 · PAUSE ELIGIBILITY 休会可能条件 - 簡略化図 in FAQ •

    • FAQ では、休会の資格要件だけ 抜き出したフローチャートを載 せている 通常休会 のご利⽤はできません https://docs.channel.io/shelikes/ja/articles/休会はできる-95144692 RailsTokyo #6 ‧ モデルのリファクタリングが難しいと思ったら、そもそも複雑だったのはビジネス仕様だった(?) 06 / 32
  5. 07 · SPECIAL PAUSE 休会可能条件 - 簡略化図 in FAQ •

    • FAQ では、休会の資格要件だけ 抜き出したフローチャートを載 せている 通常休会 のご利⽤はできません https://docs.channel.io/shelikes/ja/articles/休会はできる-95144692 • 通常休会ができなくても、 特別休会 できる可能性もある https://docs.channel.io/shelikes/ja/articles/妊娠/出産、家族の介護、⼊院 で受講の継続が難しい場合は休会できる?-95144692 RailsTokyo #6 ‧ モデルのリファクタリングが難しいと思ったら、そもそも複雑だったのはビジネス仕様だった(?) 07 / 32
  6. 10 · COGNITIVE LOAD 複雑さは仕⽅ないのか? - 認知的負荷の種類 課題内在性負荷 課題外在性負荷 その問題⾃体がどのくらい複雑か

    その問題の妨げとなる外部要因 8² + 6² = ?² a² + b² = c² ? 8 ? a a=b+2 b=3*2 6 b この問題は、他に解き⽅がなく、これらの⼿ 順を簡略することができないため、この問題 を解く際の負荷は問題に内在しているのです 問題を解く⽅法そのものは難しくなっていな い。しかし aとbを関連付け、bと6を関連付ける 課題外在性の作業に脳を働かせる必要がある 参考: プログラマー脳 優れたプログラマーになるための認知科学に基づくアプローチ RailsTokyo #6 ‧ モデルのリファクタリングが難しいと思ったら、そもそも複雑だったのはビジネス仕様だった(?) 10 / 32
  7. 11 · COGNITIVE LOAD 複雑さは仕⽅ないのか? - 認知的負荷の種類 課題内在性負荷 その問題⾃体がどのくらい複雑か この問題は、他に解き⽅がなく、これらの⼿順

    を簡略することができないため、この問題を解 く際の負荷は問題に内在しているのです 課題外在性負荷 その問題の妨げとなる外部要因 問題を解く⽅法そのものは難しくなっていな い。が、activeの意味はバラバラなので、ワー キングメモリに⼊れておかないけない 11 / 32 RailsTokyo #6 ‧ モデルのリファクタリングが難しいと思ったら、そもそも複雑だったのはビジネス仕様だった(?)
  8. 13 · AGENDA 話すこと 1. 複雑さの紹介 と 課題内在性負荷‧課題外在性負荷 2. 弊社の「会員システム」の簡単な紹介

    3. 「休会」の複雑さと、なぜ複雑になったのか 4. モデルの⽬的と安定依存の原則(SDP) ※ リファクタリング というより “リ”アーキテクト や “リ”モデリング って表現が正しい RailsTokyo #6 ‧ モデルのリファクタリングが難しいと思ったら、そもそも複雑だったのはビジネス仕様だった(?) 13 / 32
  9. 14 · MEMBERSHIP SYSTEM 会員証の仕組み 太郎さん SHElikes 会員証 在籍 2023

    年 4 ⽉から サブスク Nヶ⽉ごとにスタンプを N個買い続ける仕組み(N=1,6,12) 次回 9⽉ XX プラン購⼊予定 4月 5月 6月 7月 8月 9月 10月 11月 12月 スタンプ スタンプが押された⽉は利⽤可能⽉ 退会 月毎にスタンプ購入 = 1ヶ月単位 のサブスク 太郎さん サブスクによる購⼊予定 カードを返す SHElikes 会員証 在籍 2023 年 4 ⽉から 次回 9⽉ XX プラン購⼊予定 4月 5月 6月 7月 8月 9月 6ヶ月まとめてスタンプ購入 = 6ヶ月単位 のサブスク 10月 11月 12月 14 / 32
  10. 15 · PAUSE REQUIREMENTS 休会機能を作りたい!(当時の会話) PdM サブスクによる注⽂を⼀定期間⽌める機能作りたいの。 その期間は⼊会中だけど休会中ってことにしたい! Eng サブスクを⽌めるんですね!6

    か⽉契約の⼈が途中で休会したい場合はないですか? PdM それはルールに違反しているのでないです! Eng サブスクを⽌める期間(=休会)を設定できるようにして、その間注⽂を⽌めるようにしますね! 15 / 32 RailsTokyo #6 ‧ モデルのリファクタリングが難しいと思ったら、そもそも複雑だったのはビジネス仕様だった(?)
  11. 16 · PAUSE TIMING 休会はスタンプが終わるタイミングから開始可能 太郎さん 5月 6月 Nヶ⽉ごとにスタンプを N個買い続ける仕組み(N=1,6,12)

    3ヶ月休会 = サブスク停止期間 次回 9⽉ XX プラン購⼊予定 4月 サブスク SHElikes 会員証 在籍 2023 年 4 ⽉から 7月 × 8月 × 9月 11月 10月 12月 スタンプ スタンプが押された⽉は利⽤可能⽉ × 退会 カードを返す 1ヶ月単位 のサブスク サブスクによる購⼊予定 休会 サブスクを⽌める。スタンプの満期で休会可能 太郎さん 在籍 2023 年 4 ⽉から 次回 9⽉ XX プラン購⼊予定 4月 5月 6月 6ヶ月単位 のサブスク 途中に休会はしない 🙅 3ヶ月休会 = サブスク停止期間 7月 10月 11月 × × × 8月 9月 12月 SHElikes 会員証 1月 2月 3月 16 / 32
  12. 17 · SUBSCRIPTION PAUSE サブスクを停⽌するテーブル作成 Newテーブル サブスク停⽌期間を持つ RailsTokyo #6 ‧

    モデルのリファクタリングが難しいと思ったら、そもそも複雑だったのはビジネス仕様だった(?) 17 / 32
  13. 18 · SPECIAL PAUSE 休会機能、やっぱりスタンプの途中でも休会したい! しばらくして... PdM 6 か⽉の契約期間中だけど、体調が悪くて休会したいって⼈が現れていて。特別ルールで 許可してあげて!

    Eng サブスクを⽌める期間の設定はできるけど、途中の休会は想定してなかったよ... 既存の「休会」は、サブスクを⽌めるを前提に実装したので、サブス クが関係ない休会は実現できなかった。 そして実装時間を省いた昔の我々は...オペレーションでカバー! → 「特別休会」というオペレーション誕⽣💥 18 / 32
  14. 19 · PAUSE LIMITATIONS サブスク停⽌はできるけど、スタンプの途中の休会はできない... 太郎さん SHElikes 会員証 在籍 2023

    年 4 ⽉から サブスク Nヶ⽉ごとにスタンプを N個買い続ける仕組み(N=1,6,12) 次回 9⽉ XX プラン購⼊予定 4月 5月 6月 3ヶ月休会 7月 × 8月 × 9月 10月 11月 12月 スタンプ スタンプが押された⽉は利⽤可能⽉ × 退会 カードを返す 月毎にスタンプ購入 = 1ヶ月単位 のサブスク サブスクによる購⼊予定 休会 サブスクを⽌める。スタンプの満期で休会可能 太郎さん 次回 9⽉ XX プラン購⼊予定 4月 SHElikes 会員証 在籍 2023 年 4 ⽉から 5月 6月 途中に休会したい、、、 7月 8月 9月 6ヶ月まとめてスタンプ購入 = 6ヶ月単位 のサブスク 3ヶ月特別休会 = 無料でスタンプを付与 10月 1月 月 1月 2月 3月 19 / 32
  15. 20 · AGENDA 話すこと 1. 複雑さの紹介 と 課題内在性負荷‧課題外在性負荷 2. 弊社の「会員システム」の簡単な紹介

    3. 「休会」の設計はイケてなかったのか? 4. モデルの⽬的と安定依存の原則(SDP) ※ リファクタリング というより “リ”アーキテクト や “リ”モデリング って表現が正しい RailsTokyo #6 ‧ モデルのリファクタリングが難しいと思ったら、そもそも複雑だったのはビジネス仕様だった(?) 20 / 32
  16. 22 · PURPOSE AND MEANS 考察 - 「休会」の設計はイケてなかったのか? • •

    • • • • サブスクを⽌める仕組みを作っていたので、サブスクが関係ない期間の対 応はできなかった 特別休会って要件が出たタイミングでモデリングを⾒直すべきだったのは ⼤前提そう🙇 「サブスクを⽌める期間を作り、その期間を休会と呼ぶ」が間違いだった 「休会の期間を作り、その期間はサブスクが⽌まる」が正しかったんじゃ ないか 例えば「給与の振り込みを⽌める期間を作り、その期間を休職と呼ぶ」は 明らかにおかしい ⽬的に則したモデルが存在せず、⼿段に則したモデルのみ設計をしていた のではないか RailsTokyo #6 ‧ モデルのリファクタリングが難しいと思ったら、そもそも複雑だったのはビジネス仕様だった(?) 22 / 32
  17. 24 · AGENDA 話すこと 1. 複雑さの紹介 と 課題内在性負荷‧課題外在性負荷 2. 弊社の「会員システム」の簡単な紹介

    3. 「休会」の設計はイケてなかったのか? 4. モデルの⽬的と安定依存の原則(SDP) ※ リファクタリング というより “リ”アーキテクト や “リ”モデリング って表現が正しい RailsTokyo #6 ‧ モデルのリファクタリングが難しいと思ったら、そもそも複雑だったのはビジネス仕様だった(?) 24 / 32
  18. 25 · DOMAIN DISCOVERY 意図がドメインモデルの発⾒を促す • • • • •

    • メールアドレス または 電話番号を 必須にしたい → or 条件でバリデーション🙅 「メールアドレス または 電話番号 を必須にしたい」のはなぜか? 「最低1つは運営からのメッセージ が送信できる連絡先が欲しいから」 → 連絡先モデルを必須にする🙆 ドメインの発⾒! 参考: スケールする要求を⽀える仕様の「意図」と「直交性」 RailsTokyo #6 ‧ モデルのリファクタリングが難しいと思ったら、そもそも複雑だったのはビジネス仕様だった(?) 25 / 32
  19. 26 · PURPOSE AND MEANS ⽬的を発⾒して、ドメインモデルを発⾒する ⽬的 「なぜ?」と聞く なぜ⽌める? →

    休職しているから 休職している 期間を持つ状態 ⼿段 給与の振込を⽌める なぜ休職? → 給与を⽌めたいから、とは⾔わない 操作 なぜ⽌める? → 休会しているから 休会している 在籍したまま、 スタンプの無い期間 定期課⾦を⽌める なぜ休会? → 課⾦を⽌めたいから、とは⾔わない RailsTokyo #6 ‧ モデルのリファクタリングが難しいと思ったら、そもそも複雑だったのはビジネス仕様だった(?) ⽉額プランでの操作 26 / 32
  20. 29 · DEPENDENCY DIRECTION ⽬的を発⾒していたが、⼿段をモデリングしていた 目的 手段 • • 商品を届ける

    宅配便で送 る 店舗で受け 渡す 休会する 自ら運ぶ 定期課金を 停止 有効な期間 を延長する 目的は、手段を選べるが、手段は、上位の目的を知らなくても、自分の責務を果た せばよい 手段は目的に比べて変化、増減がしやすい RailsTokyo #6 ‧ モデルのリファクタリングが難しいと思ったら、そもそも複雑だったのはビジネス仕様だった(?) 29 / 32
  21. 29 · DEPENDENCY DIRECTION ⽬的(安定)が⼿段(変化しやすい)に依存してはいけない • • • • 「休会(=目的)」が「定期課金(手段)」に依存するのが良くなかった

    目的を知れば正しいドメインを発見できる 手段よりも安定したドメインに依存できるので、拡張しやすい 新しい機能にも対応しやすくなる RailsTokyo #6 ‧ モデルのリファクタリングが難しいと思ったら、そもそも複雑だったのはビジネス仕様だった(?) 29 / 32
  22. 31 · TAKEAWAYS まとめ 課題内在性負荷と言う前に要件と意図を聞いてちゃんとモデリングしよう! 1 課題内在性負荷 と思っている仕様も疑う⽬を持とう 2 要求の意図を⾒つけてモデルを発⾒しよう

    3 ⼿段は⽬的より変わりやすい だから、⽬的を⼿段の都合に依存させないようにしよう RailsTokyo #6 ‧ モデルのリファクタリングが難しいと思ったら、そもそも複雑だったのはビジネス仕様だった(?) 31 / 32