ソフトウェアをシンプルに保つということ
突然ですが、ソフトウェアエンジニアの仕事は何かと聞かれたら何と答えますか?
私は、顧客やユーザーに対して価値のあるソフトウェアを提供することがソフトウェアエンジニアの仕事であると思っています。
では、ソフトウェアの価値を高めるために何が必要でしょうか。
答えのない難しい問題であると思いますが、一つ言えることは、継続的にソフトウェアの価値を高めていくためには、ソフトウェアをシンプルに保つことがとても重要ということです。
では、ソフトウェアをシンプルにするとはどういうことでしょうか。
ざっくり言うと、本当に必要な機能だけを必要最低限の実装で実現することです。
機能が多いほど価値は高い?
ソフトウェアに限った話ではありませんが、一般に製品(プロダクト)は機能が多ければ多いほど価値が高いと思われることが多いです(私自身、数年前までそう思っていました)。
しかし、本当にそうでしょうか。
実際のところ、機能の多さとユーザーにとっての価値の高さは比例するとは限りません。
電化製品を例に考えてみます。
例えばテレビ。
最近のテレビはリモコンに非常に多くのボタンがついており、機能が豊富です。しかし、これらの機能を状況に応じて全て使い分けているという人はどれだけいるでしょうか。
テレビは、電源のオンオフができて、チャンネルを変えることができて、音量を調節することさえできれば、最低限テレビとしての機能は満たせます。もちろん、人によっては複数の機能を利用している人もいるかと思いますが、少なくとも、全ての機能を満遍なく使っているという人は稀だと思います。
必要最低限の機能しか使わないユーザーにとって、ボタンの数が非常に多いリモコンは認知負荷が高く、使い勝手が良いとは言えません。
例えば電子レンジ。
値段の高価な電子レンジは、これまたボタンがたくさんついていて、実に色んなことができます。
使いこなすことができれば便利であることは間違いありませんが、これらの機能を満遍なく使いこなしている人はどれだけいるでしょうか。多くの人は、ワット数と時間を指定して温めることができればそれで充分ではないでしょうか。
リモコンと同様に、ボタンの数が多い家電というのは一見便利そうに見えますが、一部の機能しか使わないユーザーにとっては煩わしいものとなってしまいます。
一般に電化製品は値段が高いほど機能が多くなる傾向がありますが、それが必ずしもユーザーにとっての価値と結びついているとは限りません。必要最低限の機能だけが搭載されたシンプルなつくりでも、ユーザーが満足していれば、それは価値の高いプロダクトと言えます。
ソフトウェアにおけるシンプルさ
ここまで電化製品における例を紹介しましたが、ソフトウェアについても見ていきます。
ここでは、検索エンジンとしてのYahooとGoogleを比較してみます。
検索エンジンとしての体験に注目すると、Googleは検索に特化した非常にシンプルなインターフェースになっています。一方、Yahooはニュースやショッピングなど様々な情報が並ぶポータルサイトです。
Yahooはネットニュースや知恵袋、オークションなど、様々なサービスがあり、個々のサービスにおいて多くのユーザーがいることは間違いないですが、検索エンジンとして比較した場合、Googleを使っている人の方が多いのではないでしょうか。検索という目的だけを見ると、Googleのシンプルさは非常に分かりやすく、使いやすい設計になっていることが分かります。
Less is more という言葉をご存知でしょうか。
「少ない方が豊かである」という意味のデザインや建築の哲学ですが、Googleのトップページはこの思想が体現されている例だと感じます。
バグが少ないソフトウェア
ソフトウェアの価値を高めるためには、品質の高さも重要です。
品質の定義にも様々ありますが、一つ言えるのは、バグ(不具合)が少ないソフトウェアほど品質も高いと評価されるケースが多いです。ユーザーにとって魅力的と思える機能が備わっていたとしても、その機能にバグが多く含まれてユーザーを困らせているとしたら、そのソフトウェアは品質が低く、同時に価値も低くなってしまいます。
では、ソフトウェアのバグを減らすにはどうすればよいでしょうか。
よく言われる冗談として、「バグを生まない最も効果的な方法はコードを書かないことだ」というものがあります。
プログラムというのは、人がコードを書いた時点でバグのリスクが生まれます。
バグが1つもないプログラムというのは、極端なことを言うとコードを何も書いていないプログラムです。
とはいえ、コードが何も書かれていないプログラムは何も動作することがないため、プログラムとしての意味はなく、当然ユーザーに対して何の価値も生みません。
だからこそ、品質の高い価値あるソフトウェアを作るためには、必要最低限の実装で本当に必要な機能だけを実装することが大切です。
AIでバグは減らせるか
最近は人間の代わりにAIがコードを書くことも増えてきたため、人間がコードを書くよりもバグが少なくなるのでは?と思う方もいるかもしれません。確かに、AIは知識豊富で多くの場面で人間よりも優秀なため、文法のミスや考慮漏れによるバグは少なくなるかもしれません。しかし、AIが書いたコードにバグが混在しない根拠はありませんし、AIに頼りすぎることで、人間にとってメンテナンスしづらいコードが量産されてしまう可能性も高まります。
AIを適切に活用できれば生産性向上や品質向上の役に立つことは間違いないですが、AIを使っているからと言ってバグがなくなるわけではありません。AIを使っていたとしても、ソフトウェアをシンプルに保つことは重要ですし、むしろAIの時代だからこそ、ソフトウェアをシンプルに保つことの重要性は増したとも感じています。
テストでバグは減らせるか
ソフトウェアの品質を高めるためにはテストが重要です。
様々なテストケースでソフトウェアをテストすれば、多くのバグを検出することができ、結果としてソフトウェアの品質は高められます。また、それらのテストを自動化しておけば、再テストが容易になるため、長期的な運用や機能改修作業が非常に楽になります。
しかし、テストを自動化したとしても、テストコード自体にバグがない保証はありません。
また、テストの量が増えていくと、仕様変更が起きた時に修正しなければいけないテストコードも増えていき、メンテナンスのコストも増えていきます。テストの自動化は、ソフトウェアの品質を高めるための強力な武器になりますが、同時にテストコードが負債になってしまう可能性も大いにあり得ます。
そういう点では、テストがあるからと言ってやみくもに機能を増やすのは危険です。
結局のところ、テストの有無にかかわらず、ソフトウェア全体をシンプルに保つように設計していくことが、ソフトウェアを長く運用していくために重要になってきます。
YAGNI原則
YAGNIの原則をご存知でしょうか。You Ain’t Gonna Need It. の略で、ソフトウェア開発において「実際に必要となるまで追加しない」という原則になります。
ソフトウェア開発をしていると、「将来こういう機能が追加されるだろう」という予測に基づいて、余計な機能を実装してしまう事があります。しかし、実際には「将来使うかもしれない」という予測は、約90%は使われないのだそうです。
YAGNI原則はコードをシンプルに保つための重要な原則の一つです。
KISS原則
YAGNI原則と併用して紹介されることの多い原則にKISS原則があります。これは、Keep It Simple, Stupid. の略で、直訳だと「シンプルにしておけ、愚か者よ」という意味になります。
この記事での主張したいことは、この原則の主張と一致します。KISS原則は、可読性や保守性を向上させるという文脈において使われることの多い原則で、設計やコードをシンプルにしましょう、という原則です。設計やコードをシンプルにすることは、結果としてソフトウェアの価値を高めることにもつながります。
シンプルの種類
ここまで「シンプル」という言葉を多用してきましたが、改めてシンプルという言葉を整理します。
ソフトウェアにおける「シンプルさ」は大きく2種類あります。
1つ目は、表面的なシンプルさです。例えば、UIのシンプルさや、機能の少なさ、操作が簡単であることを表すシンプルさです。先の家電の例やGoogleの検索はこの手のシンプルさがあります。
2つ目は、ソフトウェアの内部的なシンプルさです。コードの読みやすさはもちろん、依存関係や責務分離などの設計的な観点も含めたシンプルさです。YAGNI原則やKISS原則は、この内部的なシンプルさを保つための原則だと言えます。
この「表面的なシンプルさ」と「ソフトウェアの内部的なシンプルさ」は必ずしも一致するわけではありません。
ユーザーから見るとシンプルなソフトウェアでも、内部の実装が複雑になりすぎているケースは少なくありません。
そのため、ユーザー体験と内部設計の両方の観点でシンプルさを意識することが、ソフトウェアの価値を高めるために重要になります。
価値と負債のトレードオフ
ソフトウェア開発の仕事は、一度プロダクトを作った後にも機能の追加や仕様変更が頻繁に起きます。
顧客やユーザーからの要望があった場合に、その要望に応えてソフトウェアを改修していくことはとても大事です。
しかし、その要望がユーザーにとってどれだけの価値になるかを考慮したうえで意思決定している人はどれだけいるでしょうか。
「顧客がそう言っているから」という理由だけで、Yesマンになって何も考えずに機能を追加しているケースは多いのではないかと思っています。ソフトウェアに対して機能を追加したり仕様を変更するという作業は、開発コストがかかる上に、ソフトウェアに対して技術的負債を増やしてしまう可能性があります。
仮に、ユーザーに届く価値が少ないにも関わらず、技術的な負債が大きく増えてしまうような機能追加があった場合、長期的にみるとそれはソフトウェアの価値を下げているのかもしれません。
開発コストが少なく、技術的負債に対する影響も少なく、それでいてユーザーへの価値が大きく高まる機能であれば、それは実装するべき機能だと判断できます。しかし、ユーザーへの価値と技術的負債が釣り合わない実装を続けていると、ソフトウェアが必要以上に複雑になり、徐々にメンテナンスすることが困難な状態になってしまいます。
開発しているソフトウェアが、「必要以上に複雑になりそう」と感じたら、内部構造をできるだけシンプルに保てるよう、マネージャーや顧客を巻き込んで調整していくことが重要です。
業務は複雑
ここまで、ソフトウェアをシンプルに保つことの大事さを主張してきました。
しかし、ソフトウェアで解決しようとしている業務内容のほとんどは複雑です。そう考えると、全てがシンプルなつくりになっているソフトウェアというのはあまりないのかもしれません。そもそも、全てがシンプルなソフトウェアは、解決できる問題も限られている可能性が高いため、あまり価値の高いソフトウェアにはならないでしょう。
複雑な問題を解決してくれるソフトウェアこそ、価値の高いソフトウェアになり得ます。
とはいえ、必要以上にソフトウェアを複雑にして良いわけではありません。
シンプルさと同様、ソフトウェアの複雑性にも2つの分類があります。それは、「本質的複雑性」と「偶発的複雑性」です。
本質的複雑性とは、業務そのものの複雑性です。ソフトウェアを開発するにあたって、この複雑性を避けては通れません。一方、偶発的複雑性は、不必要な機能や過剰な抽象化といった設計の悪さが招く複雑性です。
偶発的複雑性をどのように減らしていくかは、エンジニアの実力が試される部分でもあります。
偶発的複雑性を減らすための考え方として、YAGNI原則やKISS原則といった原則、あるいはドメイン駆動設計やクリーンアーキテクチャといった設計思想があります。
ソフトウェアエンジニアの役割は、本質的な複雑さを受け入れつつ、偶発的な複雑さをできるだけ減らすこととも言えます。
Simple is hard.(シンプルは難しい)
シンプルという言葉を直訳すると、「単純」や「簡単」といった意味が思い浮かびます。しかし、ソフトウェアをシンプルに保つことは決して簡単なことではありません。 むしろ、何も考えずに開発しているとソフトウェアは自然と複雑になっていきます。
シンプルさを保つための努力と工夫を続けることが、エンジニアとしての価値につながっていくのかもしれません。
