[XP]インクリメンタルな設計の定義と運用事例(2024 Advent Calendar 15日目)

@Panda_Program

この記事は私をシニアエンジニアにしてくれた「真のアジャイル開発」体験記の15日目の記事です。このアドベントカレンダーは「ある機能開発チームでスクラム, XP, DevOps を一度に実践したら真のアジャイル開発ができた」という内容です。執筆者は全てプログラミングをするパンダです。

インクリメンタルな設計

本記事ではXPのインクリメンタルな設計の定義と自分たちのプロジェクトでの運用を紹介します。

インクリメンタルな設計の定義

インクリメンタルな設計とは、必要になった時に必要な分だけ設計をするというアジャイル開発を代表するプラクティスです。

ウォーターフォール型の開発では、事前にすべて設計をしてから開発に取り組みます。ウォーターフォールでは設計フェーズが完了すると実装フェーズに移ります。この場合、実装フェーズで得たフィードバックを設計フェーズに還元できません。一方、XPは設計をして実装してさらに再設計をしたり次の設計をします。部分的な設計と実装を繰り返すことにより、現場でのフィードバックを重視するのです。

システムは日々変化するビジネスニーズに柔軟に応えられなければなりません。この変化に柔軟に対応できる準備をし続けることが重要です。アジャイル開発では間違うことは問題ありません。間違ったことがまま進むことが問題なのです。間違ったまま進んでしまった後に多大な変更コストをかけて修正をするのではなく、毎日少しの労力をかけて設計を綺麗に保ち続けることが重要です。

また、間違っていることを間違っているというためにはチームの人間関係をしっかり築く必要があります。例え建設的な意見であっても間違っていると指摘することは心理的なハードルがあります。改善提案だとしても、他の人からは否定的な意見だと受け取られる恐れがあるからです。発言する側もそれを聞く側も、何かを指摘することで人を責めるのではなくコトの改善を考えているのだという信頼関係を先に構築していなければ、チーム内で自由な意見は出てきません。するとチームが間違ったままの方向で進み続ける可能性が高くなるのです。

XPはコードの設計や自動テストの継続的な改善という技術のプラクティスや、人間関係を円滑にするコミュニケーション重視のプラクティスを備えています。これらを実践することにより、設計や実装の変更コストを低く抑えられるのです。

インクリメンタルな設計を行うタイミングは、コードに手を入れる直前が適しています。すべての箇所を最初から細部にわたって設計するのではなく、仕様変更やメンバー間での認識と実装の乖離が明らかになった際に再設計を行います。それは時にコードをシンプルに保つためのリファクタリングという形で表れることもあります。

インクリメンタルな設計の運用

インクリメンタルな設計は、フィードバックを強く意識し続けなければ実践が難しい手法です。ソフトウェア開発をウォーターフォール型の「設計」「実装」「テスト」といった工程に分け、後ろの工程が前の工程へフィードバックを反映できない場合、インクリメンタルな設計の実践は困難になります。そのため、これはフィードバックを重視するアジャイル開発ならではのプラクティスだと言えます。

ここではインクリメンタルな設計について、アプリケーションコードの設計を中心に解説します。システムアーキテクチャやデータベースのテーブル設計については割愛します。

インクリメンタルな設計の運用: 設計を実施するタイミング

インクリメンタルな設計を行うタイミングは2つあります。それはコードの実装前と実装後に分けられます。

まず実装前に設計をするケースです。これは設計に着手する一般的なタイミングです。いくつか例を挙げます。

  • 大まかな仕様が固まって実装に着手可能になったとき
  • 誰かに設計レビューを依頼しなければならないとき
  • テストファーストでコードを書き始めるとき

このとき、設計の参考にするのは対象領域をよく知る人との会話やドメイン知識、ドメインモデル図、プロダクトオーナーが記述した仕様書、チームメンバーの知識や経験、さらにはプロジェクトの既存のコードです。これらを元にユーザーストーリーを満たす「動くソフトウェア」を作り上げます。

次は実装後に設計を行うケースです。一度設計と実装を終えているため、これは一般的に再設計と呼ばれています。

  • 実装が終わってテストをパスしているものの、コードスメル(コードの不吉な兆候)を感じてより良い方法で書き直したいとき
  • 仕様の追加や変更が発生して、既存の設計では実装が困難になったとき(リファクタリングが必要と判断されたとき)
  • ドメインの専門家やチームメンバーとの議論を通じて新たな発見をして、既存のドメインモデルが変更されたとき

他にも実装内容を整理して図やドキュメントとして記述している間に、より良い設計を思いつくこともあるでしょう。

再設計のタイミングに共通しているのは、設計に対するフィードバックが得られているという点です。設計と実装に対する良し悪しのフィードバックを得られたからこそ、再設計が必要だとわかるからです。一度実装を終えたコード、仕様変更、ドメインモデルの修正、図やドキュメントの作成・整理をきっかけに設計を見直しましょう。

インクリメンタルな設計の運用: 必要なときに必要な分だけ設計をする

優れた設計を目指す努力は重要ですが、最初から完璧な設計を作り上げることは現実的ではありません。ユーザーのニーズが変化し、それに応じてソフトウェアの仕様やソフトウェアに対する要求は変化するからです。このため、すべてに対して完璧な設計をするのではなく、必要十分な設計だけを行って先に進むことが重要です。

間違っていたら再設計すればいいのだと考えると、様々なところから情報を収集してあれやこれやと考えた結果、設計がいつまでも終わらない「分析麻痺(Analysis Paralysis)」や「完璧主義の罠」に陥ることを避けられます。

このように、インクリメンタルな設計とは何も設計をせずに実装に進むということではありません。設計をおざなりにするというのはアジャイル開発に対するよくある勘違いです。インクリメンタルな設計とは、実装直前に必要十分な設計を行うことで、コードの変更コストを小さく保つためのプラクティスなのです。

現在のIDE環境では、命名の変更やメソッドの切り出し、ディレクトリ構造の変更などのコストは大きくありません。ファイルやクラスのより良い分類方法を思いついた場合は、ディレクトリ構造やファイル名の変更を実施するべきです。TDDで実装を進めている場合、テストがすでに存在するため変更によるバグ混入の不安は軽減されています。様々な変更をした後にテストが成功していればリファクタリングは完了です。

ここまでアプリケーションコードでインクリメンタルな設計を紹介してきました。一方で、インフラ構成やテーブル設計、アプリケーションアーキテクチャに関してはインクリメンタルな設計が向かない場合もあります。これらは変更が不可能ではないものの、影響範囲が広く、変更コストが大きいためです。たとえば、アプリケーションをモノリス、モジュラーモノリス、マイクロサービスのどれで構築するかや、AWS上でやりたいことを実現するために何を使うのかなどは、前もって慎重に検討する必要があるでしょう。

クリーンアーキテクチャという書籍でボブおじさんは「変更できないソフトウェアはもはやソフトではなくハードウェアである」と述べています。インクリメンタルな設計を実践して必要な部分を継ぎ足していき、間違ったと分かったら勇気を持って改修したりリファクタリングをし続けましょう。このプラクティスを継続していればコードの変更コストは低く抑えられていることでしょう。

次はストーリーの定義と運用を紹介します。

Happy Coding 🎉

パンダのイラスト
パンダ

記事が面白いと思ったらツイートやはてブをお願いします!皆さんの感想が執筆のモチベーションになります。最後まで読んでくれてありがとう。

  • Share on Hatena
  • Share on Twitter
  • Share on Line
  • Copy to clipboard

advent-calendar」カテゴリの投稿