SmartHR Tech Blog

SmartHR 開発者ブログ

チームで良いコードの基準がバラバラ? 『オブジェクト指向設計実践ガイド』の読書会を通して共通認識を作りました

こんにちは、冬本番ですね。皆さんはいかがお過ごしでしょうか? 新規事業開発チームでプロダクトエンジニアをしているmuranoです。

昨年の9月から11月にかけて、チームで『オブジェクト指向設計実践ガイド~Rubyでわかる 進化しつづける柔軟なアプリケーションの育て方』の読書会を実施しました。今回は、その読書会で学んだことをご紹介したいと思います。

Railsで開発をしている中で、「チームで良いコードの基準が共有できていない」「オブジェクト指向なプログラミングがなかなかできない」「すぐにif文が増えてどんどん複雑になってしまう」といったお悩みをお持ちの方に、少しでも参考になれば嬉しいです。

この記事で分かること

  • 読書会を通じて「良いコード」の共通認識を作る方法
  • 『オブジェクト指向設計実践ガイド』から得られる実践的な学び
  • 学びをCursorルールや設計ドキュメントに活かす具体的な方法

なぜ読書会を行ったの?

読書会を始めた背景には、チームで開発する中で「良いコード」や「良い設計」の基準がメンバーごとにばらついていると感じていたことがあります。Railsで開発を進めていくうちに、if文が増えて変更が難しくなるコードや、後から仕様変更が入ったときにどこをどう直せばよいか判断しづらい場面が増えてきました。長期的に保守しやすい設計を意識的に身につける必要性を強く感じていました。

そこで、単に本の内容をなぞるのではなく、「後からでも設計を変更できるようにする」という本の思想を起点に、チーム全体の設計力・実装力を底上げすることを狙って読書会を企画しました。さらに、「オブジェクト指向における良い設計とは何か」を共通言語として整理し、Cursor ルールなどに設計方針を言語化して残すことで、メンバー全員(AI も含む)が再現性を持って良い設計・実装ができる状態を目指しました。

なぜ『オブジェクト指向設計実践ガイド~Rubyでわかる 進化しつづける柔軟なアプリケーションの育て方』を選んだの?

この書籍を選んだのは、私たちのチームが抱えていた課題に最も直接的にアプローチできる内容だったためです。チームでは、読書会で扱う書籍の候補として、『CODE COMPLETE 第2版』や『Tidy First?』、『研鑽Rubyプログラミング』など複数の技術書を検討しました。

その中で『オブジェクト指向設計実践ガイド』を選んだ決め手は、以下の3点でした。

  • Rubyでの実装例が豊富
    • 開発に使っているRubyでの具体例があり、学んだ内容を即座に実務に活かしやすい
  • 設計原則の実践方法が明確
    • 単一責任の原則やデメテルの法則といった設計原則を、実際のコードでどう実現するかが具体的に示されている
  • 変更しやすさに焦点を当てている
    • 「完璧な設計」ではなく「後から変更できる設計」という現実的な目標設定が、保守フェーズにあるプロダクトを扱う私たちの状況に合致していた

この書籍は、チームで「良いコード」の基準を共有し、変更に強い設計を実践するための土台として最適だと判断しました。

読書会の進め方

読書会は、週に1度1時間ほどのペースで集まり、事前に参加者が『オブジェクト指向設計実践ガイド』の該当章を読んで、要点や気になったトピックを持ち寄って議論する形式で進めました。最初の回では第1章「オブジェクト指向設計」を読みながら、「そもそもなぜこの本を読むのか」「どのくらいのペースで進めるのか」といった目的や進め方をチームで言語化し、期待値をそろえるところから始めました。

本書は濃密な内容だったため、一度さらっと読むだけでは腹落ちしにくい章も多くありました。基本的には1回の開催で1章を目安に読み進めつつ、必要に応じてペースを落としてじっくり読む方針としました。全9章をおよそ2ヶ月強で読み切るスケジュールを持ちながら、単に読み終えることをゴールにするのではなく、「その回で得た学びをプロダクトの設計・実装にどう活かすか」を毎回のテーマとして設定し、最後にチームで具体的なアクションを整理するようにしていました。

具体的には Figjam を読書会の記録場所として、章ごとに以下の流れで意見出し・議論を行いました。

---
title: 章ごとの進め方
---
flowchart TD
    A[学び・感想]
    subgraph B[開発に活かせそうなこと]
      B1[実施決定]
      B2[要検討]
      B3[やらない]
    end

    A --> B

読書会を Figjam で行った様子

このスタイルでの読書会は、チームでは3回目だったため定番のスタイルとして定着しています。感想から日々の開発へのフィードバックという流れがスムーズにできるため、とてもオススメです。

『オブジェクト指向設計実践ガイド』から得た学び

ここからは、読書会で得た学びをご紹介します。

「複雑だから仕方ない」は言い訳だった

「仕様が複雑だからコードも複雑になるのは仕方ない」──私たちのチームには、どこかそんな諦めがありました。本書はその前提を覆してくれました。

設計の目的は「あとからでも設計を変更できるようにすること」。この一文を読んだとき、ハッとしました。変更コストの高さは仕様の複雑さではなく、依存関係の管理不足が原因だったのではないかと。変更を前提にした設計を心がけることで、あの「つらいコード」も改善できる可能性が見えてきました。

「このクラス、何してるの?」に答えられるか

単一責任の原則は知識としては知っていても、いざ実践するとなると判断が難しいものです。本書が示してくれた問いかけは、シンプルながら強力でした。

クラスの責任を説明する際に、「または」や「それと」が含まれていないか?

それらの言葉があるクラスは2つ以上の責任を負っています。レビューや既存コードの見直しで、この問いを使うようになってから、責任の境界線がぐっと見えやすくなりました。

「どのクラスを作るか」ではなく「どんなメッセージが必要か」

クラス設計では、「このデータを扱うクラスを作って…」とオブジェクトから発想しがちです。本書は「オブジェクトそのものではなく、やり取りされるメッセージに注目せよ」と教えてくれました。

「どんなメッセージが飛び交うべきか?」を起点にすると、設計の発想が変わるんです。イベント型モデルやFinderオブジェクトなど、これまで何となく使っていたパターンも「なぜそう設計するのか」を意図的に説明できるようになりました。

テストは設計を映す鏡

「変更しやすいコードこそが良い設計であり、その状態をテストが支えてくれる」という言葉が、テストに対する見方を変えてくれました。

テストが書きにくいと感じたら、それは設計に問題があるサインなんです。テストコードは単なる動作確認ではなく、設計の良し悪しを映し出す鏡なのだと捉え直すことで、「テストのためのリファクタリング」という発想が自然に生まれるようになりました。

学びをチームにどう活かしたか

読書会で得た学びを「読んで終わり」にしないため、毎回の議論の最後に「開発に活かせそうなこと」を整理し、具体的なアクションに落とし込みました。ここでは、実際にチームで取り組んだことを紹介します。

Cursor ルールへの設計原則の言語化

私たちは、読書会で繰り返し話題に上がった「デメテルの法則」や「クラスで分岐する case 文の回避」といった原則を、Cursor ルールに追加しました。これにより、AI によるコード生成やセルフレビューの際に、設計原則に沿ったフィードバックが自動的に得られるようになりました。

たとえば、以下のような原則をルール化しています。

  • デメテルの法則に違反するメソッドチェーン(object.a.b.c のような呼び出し)を検出し、委譲メソッドの作成を促す
  • クラスの型で分岐する case 文や kind_of? / is_a? の使用を検出し、ポリモーフィズムへの置き換えを検討させる

チームメンバーの暗黙知だった設計判断を明文化することで、経験の浅いメンバーやAIも含めて、一定の品質を保った設計ができる土台が整いました。

設計ドキュメントテンプレートへのシーケンス図の追加

第4章「柔軟なインターフェースをつくる」の議論を通じて、「オブジェクト間でどんなメッセージがやり取りされるか」を可視化する重要性を再認識しました。そこで、設計ドキュメントのテンプレートにシーケンス図のセクションを追加しました。

複雑な処理フローを設計する際に、事前にシーケンス図を描くことで、オブジェクト間の依存関係や責任分担を俯瞰できるようになりました。「どのオブジェクトがどのメッセージを受け取るべきか」を図示することで、レビュー時の議論も具体的になり、設計の手戻りが減りました。

設計パターンの積極的な適用

読書会を通じて、これまで何となく使っていたパターンに名前と意図が付いたことが、大きな変化でした。その結果、以下のようなリファクタリングや設計判断がチーム内でスムーズに行われるようになりました。

  • イベント型モデルの活用
    • フォームオブジェクトとして実装していた処理を、責任を明確にしたイベント型モデルに置き換える判断が増えた
  • Finder オブジェクトの導入
    • コントローラーで複雑な検索ロジックを抱えていた箇所を、Finder オブジェクトに切り出すことで、テストしやすく再利用可能な設計に改善された
  • 依存方向の意識
    • 「自身より変更されないものに依存する」という原則を意識し、ドメインモデル間の依存関係を見直した

読書会を通じて変わったこと・良かったこと

ここからは、読書会を経てチームや開発にどんな変化や良い影響が生まれたのか、実体験を交えてお伝えします。

設計の共通言語ができた

チーム内では、読書会を通じて設計を語るための共通言語が生まれたことが、大きな変化でした。「このクラス、単一責任になってる?」「デメテルの法則に違反してない?」といった会話が自然に交わされるようになり、レビューなどの場面で設計に関する議論がスムーズに進むようになりました。

また、以前は「なんとなく複雑だよね」で終わっていた会話が、「責任が2つ以上あるから分割しよう」「依存の向きを逆にすると変更しやすくなる」といった具体的な改善提案に変わりました。

リファクタリングへの心理的ハードルが下がった

チームでは、「今の実装でも問題ないしリファクタリングのメリットが少ないから触らない方がいい」という消極的な姿勢から、「今リファクタリングしておけば将来の変更コストが下がる」という前向きな判断ができるようになりました。読書会で「何もしないことの将来的なコスト」について繰り返し議論したことで、適切なタイミングでリファクタリングする判断力が身につきました。

実際に、この半年で実装した機能に対して、複雑になっていた箇所を段階的にリファクタリングする動きが出てきました。「完璧な設計を目指すのではなく、漸進的に改善していく」という考え方が浸透したことで、開発のリズムも良くなっています。

開発の生産性が向上した

設計の質が上がったことで、仕様変更への対応が格段に楽になりました。以前であれば「全部を変更するより一から書き直した方が早い」と感じたような変更でも、「ここを直せば影響範囲はここまで」と明確に判断できるようになり、自信を持って変更できるようになりました。

テストの書きやすさも向上しています。以前はRequest specを結合テストとして、なるべく全ての処理をテストする方針でしたが、責任が明確になったクラス設計によって、Request specのテスト範囲とクラスごとのテスト範囲が明確になり、必要最小限のテストコードに収まるようになりました。

AI 時代における設計力の重要性を再認識

私たちは、AI(Cursor など)がコードを書いてくれる時代だからこそ、「何を作るべきか」「どう設計すべきか」を人間が判断する重要性が高まっていると再認識しました。読書会を通じて設計原則を Cursor ルールに言語化したことで、AI が生成するコードの品質も向上しました。

AI が書いたコードをレビューする際も、設計原則を基準に「このクラスは責任が多すぎる」「依存の向きが逆」といった指摘ができるようになり、開発の効率と品質の両立が実現できています。

まとめ

『オブジェクト指向設計実践ガイド』の読書会を通じて、チームで「良いコード」「良い設計」の共通認識を作ることができました。「単一責任の原則」「デメテルの法則」といった設計原則を共通言語として、具体的で建設的な議論ができるようになりました。

特に印象的だったのは、「設計の目的は、あとからでも設計を変更できるようにすること」という本の核心的なメッセージです。この考え方は、単にきれいなコードを書くことではなく、ビジネスの変化に柔軟に対応できるコードを書くことの重要性を教えてくれました。変更しやすい設計を心がけることで、開発の生産性が向上し、新機能の追加や仕様変更への対応が以前よりもスムーズになりました。

また、学びを「読んで終わり」にせず、Cursor ルールへの設計原則の追加や、設計書のテンプレートの改善など、具体的なアクションに落とし込んだことも良かったです。読書会という形式を取ることで、チーム全体で同じ目線を持ち、日々の開発で実践する文化が醸成されました。

もしあなたのチームで「良いコードの基準が共有できていない」「変更のたびにコードが複雑になっていく」といった課題を感じているなら、ぜひチームでの読書会を試してください。本記事で紹介した学びや後で紹介するチェックリストが、その第一歩として役立てば幸いです。

付録:設計改善チェックリスト

この記事では、読書会で得た学びからピックアップして紹介しましたが、他にも多くの学びがありました。せっかくですので、チェックリストにして他の方も使えるようにしました。ぜひご活用いただけたら嬉しいです。

オブジェクト指向設計改善チェックリスト.md

以下はオススメの使い方です。

  • 新規実装時
    • 実装前にこのチェックリストを確認し、適切な設計を検討する
  • コードレビュー時
    • レビュイーとレビュワーの両方がチェックリストを参照する
  • リファクタリング時
    • 改善ポイントを見つけるためにチェックリストを使用する
  • 定期的な見直し
    • 四半期に一度程度、主要なクラスに対してチェックを実施する