「必要な時に必要なものだけ作る」について考えてみる
はじめに
アジャイル開発をしていると「必要な時に必要なものだけ作る」という考え方がたびたび出てきます。
私は新卒から2年間、アジャイル開発のチームでアプリ開発に携わってきましたが、リファンメント等で「このバックログは本当に今必要か?」であったり、開発チーム内のコードレビューで「このコードは今必要ないのではないか?」というやりとりを何度もしました。
しかし、「必要な」という言葉についてしっかりと向き合ったことはありませんでした。
人によって「必要な」の基準が違うと、会話が平行線をたどってしまい議論が長引いたり、場合によっては手戻りが起きてしまいます。
そこで、アジャイル開発で使われる「必要な時に必要なものだけ作る」について考えてみることにしました。
アジャイルの文脈での「必要な」の使われ方について
「必要な」の使われ方にはビジネス視点と、システム目線の2つがあると考えます。
「アジャイル宣言の背後にある原則」の最初に以下の記載があります。
私たちは以下の原則に従う:
顧客満足を最優先し、
価値のあるソフトウェアを早く継続的に提供します。
https://agilemanifesto.org/iso/ja/principles.html
このことから、アジャイル開発は顧客に価値を早く届けることに重きを置いていると考えられます。
価値のない機能の開発に時間を使ってしまうと、その分本当に届けたい機能を届けるのが遅れてしまうため、開発したい機能が顧客にとって必要か?(≒価値があるか?)について議論するのだと思います。
これがビジネス視点の使われ方です。
次に、アジャイルの開発手法の一つであるエクストリームプログラミング(XP)の価値基準の中に「シンプリティ」(≒コードをシンプルにする)がありますが、シンプリティについてXPのサイトでは以下のように触れられています。
Keep the system uncluttered with extra stuff you guess will be used later. Only 10% of that extra stuff will ever get used, so you are wasting 90% of your time.
http://www.extremeprogramming.org/rules/early.html
直訳すると、「コードを予期せぬ変化に対応できるようにしておくことはシンプルな設計をすることだ。後で使うだろうと思われる余計なものを追加するな(実際に使われるのはその10%程度である)」です。
つまり、「後からどうなるかなんて誰も予想できないのだから、将来を見込んで必要のない実装をしても無駄になる」という意味だと考えられます。
これがシステム目線での使われ方です。
YAGNI原則(※)で馴染みのある方が多いと思います。
※You ain't(aren't) gonna need to it. を略語にした言い方
これら2つの視点は、つながっていると考えます。
- アジャイルの根本にある「顧客への価値提供」を行うためには、何を届けるか(どのバックログから着手するか)を継続的に考える必要がある。
- 「顧客の価値」は市場の状況等で継続的に変わるし、継続的に考え抜くことで最初に思い描いていたプランが変わる可能性だってある。
- (だから我々開発者は)コードを予期せぬ変化に耐えうるようにするため、その時点で必要のないものは作らず、コードをシンプルにしておく。
以降はシステム目線での話に焦点を当てて考えていきたいと思います。
「必要ないものを作らない」=「先のことを考えなくて良いか」?
今必要のないものを作らないのであれば、純粋に与えられた要求を満たせばよく、先を見越した設計をすること自体良くないことなのでしょうか?
これについてはNoだと思います。
極端な例ですが、Webページの製作を手掛けていたとして、最初の公開ではWebページ内の文言が決まっているが、公開後に変更する可能性が高いと言われていたとします。
「今、この時点で必要なものだけ作る」という考え方をした場合、最初の公開で表示する文言をHTML等にべた書きすることになりますが、必ずしもそれが最善というわけではなく、今後のことを考えて表示文言を変数として持っておくことも、変更容易性等のメリットがあります。
このように、「今必要なものだけを作る」と「将来を見越した設計」は対立してしまうこともあります。
では、その時点でどこまでの拡張性を持たせるか迷った時、どのように考えれば良いでしょうか?
誰にとっての「必要?」か
Howを考える前に、もう少し言葉の意味を考えてみようと思います。
そもそも「必要な」の言葉には、誰にとって必要、の「誰」が隠れているはずです。
コードを追加するとき、必ずそれに紐づくバックログがあり、バックログを作った人がいるはずです。
バックログの要求元は開発者の可能性もありますし、別の誰かの依頼かもしれません。
しかし、最終的にバックログを管理し、意思決定を下すのはプロダクトオーナー(PO)です。
POの先には顧客がいて、POは開発者よりも顧客と近い存在であり、顧客にとっての価値を一番考えている存在と言えます。
(もちろん、開発者もPOと一緒に顧客の「価値」を考えるべきですが、ここではPO・開発者という役割に焦点を当てていることを補足させてください。)
にも関わらず、開発者がPOの意思より自分たちの意思をコードに反映してしまうとどうでしょうか。
価値を生み出さないものに時間を費やしてしまう可能性が高まります。
これは、先ほど引用したXPのサイトでも you guess will be used laterと述べられているように、「後で使うかもしれない」と憶測で作業を進めることと同じ問題を引き起こします。
次の例は私の経験で、POの意思より開発者の意志を優先した結果失敗したなと思った例になります。
私はチームではコンポーネント指向のJavaScriptフレームワークを使った開発をしていますが、何もかもコンポーネント化した結果、最終的に無駄になってしまったと感じたことがあります。
もちろん、「コンポーネント化が良くない」といっているのではなく、複数個所で使われるものについてはコンポーネント化するメリットがありました。
しかし、「ここは再利用されるだろう」という憶測でコンポーネント化する単位を決めてしまったことで、後から考えると逆にコードを複雑にしてしまい、無駄な時間を使ってしまったかもしれません。
このUIはどういう進化をたどるか?他のところで使われる可能性があるか?等、PO・デザイナーと密に会話していれば良かったと思います。
UIを例に挙げましたが、機能においても同じで、そのバックログでどこまで作るかをPO・開発者間で認識を合わせたり、受け入れ条件を明確に定義することも大事だと思います。
開発者内部で決める場合
開発者の憶測で考えずPOとの会話が大事だと述べましたが、POも将来のことは分かりませんし、考えが変わるかもしれません。
また、ソースコードの実装レベルでPOに決めてもらう訳にはいかないので、実際には開発者間で決める場面が多いです。
当たり前に思われるかもしれませんが、その時に最も大事なのは、事前にコミュニケーションをすることだと思います。
というのも、私の経験では開発者間で事前に話をせず、実装者一人の考えで共通化をしてしまうケースが多いからです。
その人にとっては良いことをしたつもりなのかもしれませんが、後々使われなくなってコードを複雑化させてしまったり、それに時間を費やしていなければもっと早く出荷できたというケースがあります。
プランニングで作業をタスクの粒度に分割するときに話せるのが一番良いですが、コーディングをしながら悩んだ場合はその時にチームに相談するのも効果的だと思います。
チームに相談する場合、必ずしも全員の意見が一致しないこともあるため、相手に説明可能な自身の判断基準を持つことも大事です。
そうすることで、建設的な議論ができ議論が平行線を辿りづらくなります。
ちなみに私は、あるコードをその時点でプロダクトコードに落とし込むべきか迷ったときは「その知識が確定していることか」を判断軸にするようにしています。
ここでいう知識は、"情報" や "仕様を表現する処理"のことです。
「知識」という単語を使った背景としては、「リファクタリングとともに生きるラジオ」というラジオでスピーカーの方が話されていた、「YAGNIを守るとDRY(※)も守られることになるのでは?」という考えに共感したからです。
※Don't repeat yourself.
DRY原則は知識の二重化を避けるというものです。
すべての知識はシステム内において、単一、かつ明確な、そして信頼できる表現になっていなければならない。
「達人プログラマー 第2版」より
YAGNI原則とDRY原則は異なる原則ではありますが、シンプルなコードを書くという観点においては全く関連性がないわけではなく、YAGNI原則も「知識」を基準に考えると整理しやすくなるのではないかと思います。
例えば、「将来Bになるかもしれないけど、現時点ではA」という情報があり、それが知識としてチームで共通認識を持てている場合は、Bへの拡張性は考えず、Aをそのまま反映させた実装にします。
なぜなら、Bへの拡張性を入れてしまうと、その知識がない人(その会話を聞いてない人)がコードを見たときに、「Bになることが決まったんだ」と誤解してしまうかもしれないからです。
最終的にBにならないかもしれないですし、Bになったのならその時に拡張すればよいです。
逆に、ある処理を入れなくても現時点では振る舞いは変わらない場合でも、その処理が現時点の仕様を反映しているのであれば、仕様を共通の知識として共有するためにコードに組み込むべきだと考えています。
ただし、実際の業務では何かで一括りにできずケースバイケースではあるため、いずれにせよ一人で決めずチームで会話することが大切です。
まとめ
これまでの内容をまとめます。
- アジャイル開発で「必要なときに必要なものを作る」と言われるのは、顧客に価値を早く届けるため。
- 不確実性に耐えられるようにするため、コードをシンプルに保つ必要がある。
- 良かれと思って追加したり、憶測で考えたコードは複雑性を高めたり、後々無駄になったりする。
- それを回避するには、その機能やUIが将来どういう進化をたどるか、POと認識を合わせておくと良い。
- 実装者内で決めるべきレイヤについては、実装前に開発者間で会話することが大事。
おわりに
これだけ長文を書いておいて最終的に「会話が大事」という締め方をするのはなんともですが、結局そこに行きつくのかなと思います。最後まで読んでいただきありがとうございました。
Discussion