DanLevy.net

シングルパーパスな人々に気をつけろ

純粋すぎて痛い

Single Responsibility Principle(単一責任の原則)は、あまりにも理にかなっているため、判断力をすり抜けてしまうような考え方のひとつだ。

ひとつのことだけをしろ。うまくやれ。モジュールは焦点を絞れ。変更の理由をコードに与えろ。良いアドバイスだ。

ところが、誰かがそのアドバイスをメジャーに変えてしまい、「5行を超える関数はコードの匂いがする」と宣言し始める。

問題なのはSRPではない。「小さい」ことを「凝集している」ことの代用品とみなすことだ。

その瞬間、あなたは「シングルパーパスな人々」に出くわしたことになる。モジュール化について完全に間違っているわけではないが、有用な境界線と最大限の断片化を混同している開発者たちだ。

ソフトウェアアーキテクチャにおける暴力
コンポーネント、コンポーネント、どこまでもコンポーネント

I. その下にある有用なアイデア

フォームにチェックボックスを1つ追加するだけで、 ideally 1つのファイルにしか影響を与えないはずだ。5つのディレクトリにまたがる8つのファイルに影響を与えるなんて…お前らのことだ、React/Redux。

SRPが判断力を持って適用されれば、確かに役に立つ。単一の概念的タスクに焦点を当てたコード単位は、理解しやすい。テストは適切な境界で動作を対象にできる。明確なモジュールは、アプリケーションの残りの部分を引きずり込まなくても、システムの一部を変更しやすくする。

古典的なUnixの例でさえ、スローガンが示唆するほどには純粋ではない。ls はファイルをリストするが、opendirreaddirclosedirstat などの呼び出しも調整している。有用な単位は最小限の操作ではない。タスクを解決する最小限の凝集したものだ。

オリジナルのUnix哲学は、すべてを単一の関数やファイルに縮小することではなく、合成単純さについてだった。

この違いは重要だ。「ひとつの責任」は「1行の振る舞い」と同じではない。

II. 過剰な抽象化:単純さがカオスに変わるとき

「5行を超える関数はすべて『コードの匂い』だ」と建築家が insisting する。私たちのコードベースは今、 clueless な絶望の匂いをかすかに放っている。

この失敗モードは、すでにあなたの週を悪化させた後なら簡単に見分けがつく。

コードベースにはファイルが増えているが、形は失われている。すべてのヘルパーがヘルパーを持っている。すべての概念が、製品の意味ではなく技術的な役割で名付けられたフォルダに分割されている。チェックボックスを追加するには、コンポーネント、フック、セレクター、アクション、リデューサー、定数、テストフィクスチャ、そしてインポートパスが罪悪感を持たないように存在するだけのバレルエクスポートに触れる必要がある。

この無限の仕事パターンからの脱出はない
コンポーネント、コンポーネント、どこまでもコンポーネント

その純粋さは何を買ったのか?

私は、単純な100行の機能が15以上のファイルに切り刻まれ、それぞれが1つか2つの関数しか含まない「純粋な」小さな天使であるコードベースの深淵を覗き込んだことがある。その混乱を頭の中に保持しようとする認知的爆発半径は、分離からの理論的な利点を完全に打ち消した。それは単純ではなかった。ただ散らばっていただけだ。

III. 完璧さの代償:開発者への影響

機能を実際に出荷するよりも、ファイル構造と命名規則について議論する時間の方が長い。これがアジャイルなのか?

芸術の域に達するほどの messy さ
芸術の域に達するほどの messy さ

この病理的な断片化は美的な問題だけではない。開発者がどのように注意を払うかを変える:

生産性の低下: 技術的負債を忘れろ。これは強迫神経症的なディレクトリのネストを通じて蓄積された組織的負債だ。すべての小さな修正が、抽象化の層を通じた考古学的な発掘調査になる。時間は cd ..grep のブラックホールに消えていく。

テストの税金: テストスイートは自信を与える代わりに、摩擦の源になる。軽微なリファクタで壊れたテストを修正するために時間が溶けていく。それらのテストは、検証すべき微視的な詳細にあまりにも密結合していた。

認知的負荷: 人間の脳が同時に扱える断片化された情報には限界がある。開発者に12の散らばったファイルからプログラムの流れを組み立てさせることは、理解を積極的に妨げ、自信を持った変更をより難しくする。

IV. 実用主義の採用:実践的な代替案

「関連する2つの関数を同じファイルに置くことを提案したら、ステージングを削除する提案をしたかのような反応をされた」 — 回復中の純粋主義者の読者より

出口はSRPを放棄することではない。答えはそれを意味の正しいレベルで適用することだ。

実践ではこれがどのような姿になるか:

目標は博士号論文に値する理論的な完璧さではなく、同僚(そして未来のあなた)がビルに火をつけたいと思わずにナビゲート、理解、修正できるコードを作成することだ。

時には、ファイルが50行ではなく200行になることもある。時には、関数がデータの取得わずかな変換の両方を処理することもある。時には、クラスに2つの責任があり、それらが密結合しているため一緒にあるべきこともある。それがシステム全体を作業しやすくするなら、おそらく正しい選択だ。

実用的な質問に relentessly に焦点を当てろ:

V. 結論:凝集性と保守性のあるコードの育成

単一責任の原則は有用なツールだ。コードベースを原子の粉塵に粉砕するための命令ではない。どんなツールと同様に、その価値は使う人の判断に依存する。

だから、3行を超える関数に戦争を仕掛ける準備ができているシングルパーパスな人々に出くわしたら、深呼吸しろ。12ファイルのチェックボックスを思い出せ。

私たちの仕事は、理論的に完璧な雪の結晶のような関数を構築することではない。私たちの仕事は、動作し、問題を解決し、次に触れる人を罰しないソフトウェアを構築することだ。

実用的であれ。結果に焦点を当てろ。完璧な純粋さの追求が保守可能なコードの敵になるな。あなたの正気、そしてあなたのチームの速度は、それに依存している。

¹ 皮肉なことに、最低レベルで実際の単一責任を達成するには、表面のすぐ下に隠された immense な複雑さが必要だということ。

² ここでの純粋性について話しているのは、関数が論理的に「1つのこと」だけを行うべきだという考えだ。副作用のない関数型プログラミングの「純粋関数」の概念と混同するな。それは別の、時には関連するが異なるアイデアだ。