ソフトウェア設計の言語化スキルを磨くこと

たとえば設計について議論するときや、コードレビューで指摘をするときに、「なぜその設計が良いと思うのか?」について言語化するのが上手だと、確実に良いことがあります。

言語化が上手にできるかが一つの壁なのではないか、と感じることもあります。後輩を育てたりチームをリードするような立場になると、特に必要性を感じるのではないかなと。

自分も、うまく言語化できたことですんなり議論を進められていると感じることは多いですし、逆に直感的な良さを言語化できなかったことで直感に反する方向に進んでしまい、結果よくなかったというような苦い経験もあります。

前提: ソフトウェア設計の良さは静的には決まらない

良い設計・良いコードとは何なのか。という質問に一言で答えるなら、「保守性が高い」ことだと思います。つまり、今後の変更・拡張を、高速にバグが少なく行えるような状態が良い設計・良いコードです。(一般的にはこれで70%くらいはカバーしていると思います。正確にいうとそれだけじゃないのですが。)

逆に言うと、今後一切変更されないコードであれば良いも悪いもないわけです。例えば、設計力の高いシニアなエンジニアがスタートアップ最初期に入っても活躍できるとは限らないのはこれによります。スタートアップ最初期のコードの多くは、その後頻繁に変更されずに捨てられる運命なので。

プログラミング初級者が陥りがちな罠の一つとして、「良いコード」「美しいコード」が今すぐ存在すると考え、すぐに追い求めてしまうというものがあります。実際には、その設計やコードが良いかどうかは、周りの環境に大きく依存します。今後、コードのどの部分が変更されるのかはコードそのものではなく、ビジネスやチーム等に依存するのは当然です。

もっというと、未来を完全に予測することは不可能なので、現在ある情報をすべてそろえたとしても良いコードかどうかは決まらないことになります。ここを今後変えるって言ってたから変更しやすいようにようにしたのにちっとも使わないじゃねぇかよぉ〜みたいな話は何度も経験してます。

どうせすべてを見通すことはできないので、基本の方針は以下のようになります:
・未来を見通す努力をする。(例: 企画者とよく話す)
・テストを書く。あとから変更しやすいように。
・頻繁に変更されるかわからない部分は YAGNI ("You ain't gonna need it", 必要になってからやる) でいく。
・非常に小さい努力でできることはする。あるいは、小さい努力である程度の確率で良い設計ができるよう、プログラマーとしての基本の所作を身につける。

マジックナンバーは避けて定数にしましょう、みたいなのは、基本動作の類です。しかし、これすらも微妙です。例えば、HTTPのステータスコードについて、 `BAD_REQUEST = 400` みたいな定数を定義して使っているコードは、間違いなく残念なコードです。なぜこんなコードは書かないのか。その理由の一つは、Bad Requestを表すステータスコードの値が400であることが、今後変わることはほぼ絶対にありえない、ということです。(もうひとつは、ステータスコードという概念と値が十分に知られていることです)

設計の言語化スキルが重要である、2つの理由

あなたが設計について勉強し、周りよりも良い設計ができるようになってきたとします。単一責任原則・凝集度/疎結合など、良い設計をはかるための指標もいくつか手にしています。

正しい議論をするための補助になる

あらゆるところに `42` という数値が散らばって書かれているコードのPRを見ます。嫌な感じがします。あなたはPRのコメントにこう書きます:「マジックナンバーはやめて、定数にしましょう」しかしPRの主qsonaはマジックナンバー大好き人間なのでただでは引き下がりません。「定数のが文字数が多いし、定数を定義する場所を決めるのも面倒です。」

もっともらしい返信を前にして、しかしこのコードに最終責任を持たないといけないあなたは引き下がるわけにはいきません。理由を考え、コメントを書きます。「DRY原則に反しているからよくないです。」

しかし、この返信は(場合によっては)よくありませんでした。ソフトウェアの原則は往々にしてコンフリクトしたり、コンテキストによって捉え方が変わったりします。なので、ある方面から見て原則に則っていないだけでは必ずしも悪いコードの理由にはなりません。基本的に、いきなり原則を理由にするのではなく、現実の問題に即して理由を説明し、参考として原則を挙げるのが良い姿です。

DRY原則を破るとなぜいけないのだっけ...そう、値に変更があったときに全箇所を変えなければいけないのが問題なのです。あなたはそう説明しようとして、ふと立ち止まります - この42という値は実は法律で定められていて、そうそう変更されることはありえないのでした。であれば、「値に変更があったときに...」というのは悪いコードの理由にはなっていないはずです。

もう少し考えて、あなたはもう一つの理由に行き着きます。マジックナンバーのもう一つの問題 - 42という値が何を表しているのかパッと分からないので、読み手が混乱する可能性がある。したがって、変数という形でラベル付けをして読みやすくしてほしい - 実はこちらが最初に感じた違和感の正体だったのです。

...という、スケールの小さい話をやたらと詳細に書いてみました。実際はもっと大きな設計の議論にて、このようなことが起きがちです。前提にも書いた通り、設計の良さは静的に決まらないので、お互いの情報を出し合って何が良いのかを考えていく作業が必要なのです。単に原則を持ち出すのではなく、その原則の意味を理解し、起こりうる問題などを具体的に説明することで、議論を深める補助とすることができます。

周囲や自分のレベルアップへの貢献

上のような動作を常にしていると、周囲に対して自分の思考を公開しているような状態になります。周囲の人々は、ひとつの事柄に使える考え方ではなく、いろいろな事柄に適用できる考え方を学ぶことができるので、設計に関して学ぶ効率が良くなります。

周囲の人たちの設計レベルが上がるのは、とても良いことです。あなたは良い設計・良いコードにしたいので、良い設計ができる人が増えればそれだけ全体の設計の質は上がるし、設計議論の前提が揃ってきて質も高くなります。信頼してもらいやすくなる、というような副次的な効果もあります。

ついでに、自分のレベルも確実にあがります。必然的に設計の良し悪しにかかわる物事を分解して考えられるようになり、より難しい設計判断をするための支えになります。

どうやって設計の言語化スキルを磨くのか

とにかく実践する

個人的な意見ですが、とにかく実際の事例にぶつかってやっていくしかないと思います。

PRのレビューや設計の議論のときに、「ここまで書けば相手が理解するだろう」というラインをなるべく下げ、抽象的な言葉ではなく具体的に書くように訓練するとよいです。

今までがりがりコードを書くことで価値を発揮していたとすると、そこに時間をかけることに抵抗があるかもしれないですが、言語化も価値や成長に繋がると意識して、意識して時間をとったほうがいいかもしれません。

分からなければ分からないと言ってくれる人をまわりにつける

あなたがチームリーダーであるなら、最終的にはリーダーが決めたらメンバーはそれに従うことになるはずです。大事なのは、納得できないなら納得できるまで聞いてくれるように要請したり、そういう空気を作ることだと思います。

こいつめんどくさいから反論しないほうがいいな、とか、聞いてもあんまり納得できる答えが返ってこないな、とか思われると、わざわざ聞き返してこなくなります。

知識のインプットの際に抽象化を意識する

新しいデザインパターンや、ブログ記事を読んだりするときに、過去の経験や、他に知っているパターン や、より高次の設計原則に結びつけて考えられるようになると、理論と実践が統合されてより強固な設計スキルになっていくように感じています。

自分が知っている人の中では @shinpei0213 さんはこれがとても上手くて、彼の発信はいつも勉強になります。実際に振り返ってみると、自分がこれに気付かされたのは、以下の「Vue.jsで実現するMVVMパターン Fluxアーキテクチャとの距離」という記事を読んだときかな、と思います。


まとめ

いかがでしたか(以下略

noteの通貨流通量を増やしていきたい!!