SRP――一つの共有先の定義は、一つの理由で変わるか
作成: / 公開: / 内容更新:
執筆:tamito0201 / 掲載・運営:プロマリ
丸い共有ボタンの裏側を掘る連載の第4回。SOLID の最初の原則 SRP を、共有先の名札カード1枚からプラグイン全体まで当てて確かめます。責任とは仕事の数ではなく、変更を頼んでくる人の数。Martin の車の修理のたとえから、実際の変更履歴を数える宿題まで、図22点で読み解きます。
依頼主を2人見つけたら、どうするか
4つの問いで採点して、依頼主が2人いるファイルが見つかったとします。すぐに分けるべきでしょうか。SRPは「必ず分けよ」という規則ではありません。分ける線をどこに引くかを決めるための物差しです。判断は、3つの問いを順にたどって行います。
1つ目は、そもそも依頼主が2人以上いるか。2つ目は、2人の依頼が実際にぶつかったか。履歴をたどって、2人の依頼が同じ行や同じ時期に重なった跡があるかを見ます。3つ目は、分けたときの手間より、ぶつからなくなる利点のほうが大きいか。分ければファイルが増え、読む場所も増えます。片方の依頼がめったに来ないなら、分ける手間のほうが大きいこともあります。3つとも「はい」なら分け、1つでも「いいえ」なら、いまは分けずに待ちます。待つときは、気づいたことを記録に残しておくと、次に同じファイルを開いた人が判断を引き継げます。
考えてみる:依頼主が2人いるのに待つのは、SRPに反していない?
反していません。SRP は、変更の依頼がぶつかって困ることを避けるための考え方です。まだ一度もぶつかっておらず、これからもぶつかりそうにないなら、分けても困りごとは減りません。むしろファイルが増えるぶん、読む手間が増えます。Martin の記事が問題にしているのも、頼んでいない人の持ち物を壊すことでした。実際の衝突だけでなく、起こりそうな衝突の大きさも見て分ける時期を決めます。大事なのは、依頼主が2人いることに気づいていて、その判断を記録に残していることです。
分けると決めたら、4つの手順で
分けると決めたら、次の4つの手順で進めます。この作業はリファクタリングとして行います。外から見た動きは変えずに、中の形だけを整えるのです。
まず、履歴をたどって、どの変更が誰の都合で入ったかに印を付けます。次に、ファイルの行ごとに、どの依頼主の持ち物かを決めて色を塗ります。3つ目に、色ごとに新しいファイルへ行を移します。このとき中身は書き換えず、置き場所だけを変えるのが大事です。中身と置き場所を一度に変えると、動きが変わったときに、どちらのせいか分からなくなります。最後に、テストが通ることと、次に来るはずの依頼が1か所で済む形になったかを確かめます。
置き場所を変えても、読者の見える景色は保つ
分割の最後は、フォルダがきれいになったところで止めず、読者の見える結果へ戻って確かめます。次の図は、分ける前と後に同じ設定を渡し、同じ共有欄ができるかを見比べるための模型です。
二枚の画面には、同じ順序のボタンと、同じ表示名があります。裏側の置き場所は変わりましたが、読者が押すものは変わっていません。図でボタンの並びが一致するように、変更前の振る舞いを、変更後の部品の組合せでも保ちます。これは新しい見た目を考える作業ではなく、既存の見た目と操作を守って分ける作業です。
実際には、スクリーンショットが似ているだけでは足りません。共有URL、クリック時に呼ぶ処理、色の上書きが無いときの既定値、設定に知らない共有先が入ったときの扱いなど、外から観測できる結果も確かめます。見た目の確認と、値や操作の確認を重ねると、「配置を動かしただけのつもりで、動作まで変えた」を見つけやすくなります。
分割後には、次に来そうな小さな依頼も一つ当ててみます。たとえば「Xだけを小さい列へ移す」としたら、サイトの設定へ自然にたどり着けるでしょうか。定義と設定の両方へ同じ値を書かなければ動かないなら、境目はまだ途中かもしれません。動作を保ったことと、次の変更が置き場所に合うことを、別々に確認します。
画面を比べる練習では、入力をそろえるところから始めます。同じ記事のURL、同じタイトル、同じサイト設定を渡して、分割前と後を比べます。片方だけ設定を変えた状態では、違いが出ても、分割の影響なのか設定の影響なのかが分かりません。比較のために動かさないものを先に決めます。
次に、一つだけ入力を変えます。色の上書きを外して、既定値へ戻る様子を見る、といった小さな変更です。二枚の画面で同じように戻れば、定義と設定を分けても、その合成の約束を保てていると確かめられます。通常の表示だけでなく、上書きが無い場面を選ぶと、境目のつなぎ方が見えやすくなります。
最後に、今回の分割を知らない人のつもりで、次の修正先を探してみます。サイト固有の色を変えたいとき、最初に設定へ向かえるでしょうか。名前が曖昧で共通定義を開いてしまうなら、ファイルの説明や入口の名前を見直す余地があります。動くことに加え、変更する人が正しい場所へたどり着けることも、分割を仕上げる確認になります。
ここまで確かめたら、変更の説明も短くできます。「並び順の判断をサイト設定へ移した。SNSのURL定義は変えていない。同じ入力で同じ結果になることを確認した」。こう書ける変更は、原則の名前だけを掲げた変更より、読む人が評価しやすくなります。SRPを、ファイルの整理の話から、変更を説明する道具へ戻して終えるわけです。
手を動かして確かめる
今回の練習は、依頼主を実際に数えてみることです。手元のリポジトリで、よく書き換えているファイルを1つ選んでください。git logを使うと、そのファイルを変えたコミットを1行ずつ並べられます。
git log --format="%h %s" -- destinations/x.toml並んだコミットの1行ずつに、「これは誰の都合で入った変更か」と依頼主の印を付けていきます。最後に、印の種類を数えます。1人なら、そのファイルはそのままでかまいません。2人以上なら、前の節の3つの問いに進みます。
練習では、最初からリポジトリ全体を分類しようとしなくて大丈夫です。一つのファイルについて、最近の変更を数件選び、それぞれに「頼んだ立場」「変えたかった結果」「触った行」を書いてみてください。三つの欄を埋めると、同じ名前の人が別の立場で頼んでいたり、別の人が同じ方針を引き継いでいたりすることに気づけます。
答えは「一人だった」「二人だった」で終わらせず、次の変更を一つ予想して、その置き場所まで説明してみます。「共有先のURL変更ならこの定義」「サイトの並び変更ならこの設定」と言えれば、境目が具体的になりました。どこへ置くか決められない依頼が残ったら、それを次のレビューの問いにします。すぐにコードを分割しなくても、調べる対象を絞れれば練習の成果です。
このプラグインでも、実際に数えてみました。
$ git log --format="%h %s" -- destinations/x.toml
7c91af3 refactor(sns-share): 共有先を PHP クラスではなく destinations/<key>.toml のデータで宣言するX の名札カードの履歴は、作ったときの1件だけでした。名札カードの形にしてから、まだ一度も X 側の依頼は来ていません。つまり、依頼主が1人かどうかは、今のところ「設計の上ではそうなっている」という段階です。依頼が来るたびに履歴が伸びていくので、この数え方は、あとから何度でもやり直せます。一方、設定のひな形は11件の変更を受けていて、そのほとんどは設定の書式や版を整えた開発の都合でした。ひな形はプラグインの一部として、開発と一緒に書き換わるファイルだということも、履歴から分かります。
数えた結果は、次のラベルから残せます。宿題:よく書き換えるファイルを1つ選び、変更の履歴から依頼主を数える。依頼主が何人いたか、2人以上だった場合にどこで分けられそうかを書いてもらえると、次の回で紹介するかもしれません。
SRP を「人についての原則」と説明し直した原典は、Robert C. Martin のThe Single Responsibility Principle(2014)です。車の修理のたとえと Employee クラスの例も、この記事にあります。発散的変更と散弾銃手術は、refactoring.guru のDivergent ChangeとShotgun Surgeryで、図つきで読めます。SOLID の5つの原則を「どういうものか・守らないとどうなるか・守るための方法」の順に整理した入門として、NakuRei さんの『SOLID原則完全に理解した!になるための本』も、この記事の整理の参考にしました(単一責任の原則の章)。
SRP によくある4つの誤解
最後に、SRP を読むときに陥りやすい誤解を4つ並べておきます。どれも、1ページ目の「一つの責任は、一つの仕事のことではない」から出てくる誤解です。
| よくある誤解 | この記事での答え |
|---|---|
| 1つのクラスには、1つのメソッドだけを置く | メソッドの数ではなく、依頼主の数を数える。Employee は3つのメソッドを持つことより、3人の依頼主がいることが問題 |
| SRP は、ファイルを小さく分けるための原則 | 分けすぎれば散弾銃手術になる。目盛りは細かさではなく、依頼主の境目に合わせる |
| 依頼主とは、名前のある1人の人のこと | 依頼主は役割のまとまり。同じ人が2つの役割を持てば、依頼主は2人と数える |
| 形が同じコードは、1つにまとめるのが SRP | 形が同じでも、依頼主が違えばまとめない。x.toml と line.toml は同じ7項目だが、1枚にまとめると X と LINE の依頼が同じファイルでぶつかる |
4つ目の誤解は、プログラミングでよく言われる「同じことを2度書かない」という教えと、ぶつかるように見えます。けれど、2度書かないでまとめてよいのは、同じ理由で変わるものだけです。今は同じ形でも、変わる理由が違うものをまとめると、片方の都合で書き換えたときに、もう片方まで変わってしまいます。形が似ていることと、同じものであることは違います。
4つの誤解に共通しているのは、コードの「大きさ」や「数」を見て判断しようとしていることです。SRP が見ているのは、コードの外にいる人です。誰が、どんな都合で、いつ変更を頼んでくるか。その答えから、置き場所の線を引きます。
まとめと、次回
第4回のまとめです。SRP の「一つの責任」は、仕事の数ではなく、変更を頼んでくる依頼主の数でした。Martin が車の修理にたとえたとおり、困るのは頼んでいないところが壊れることで、だから変わる理由の違うものを1か所に置きません。名札カードの依頼主は SNS 各社だけで、並び順や言い回しのようなサイトの判断は、設定ファイルという上の紙に重ねて書きます。コードの中では、同じカードを URL の決まりと見せ方の2つに分けました。データは依頼主で、コードは仕事の種類で分けていますが、どちらも同じ理由で変わるものを集め、違う理由で変わるものを分けるという1つの問いに答えています。
| 問い | 見るもの | 答えが「いいえ」のとき |
|---|---|---|
| 依頼主は1人か | 変更を頼んでくる役割の数 | 依頼主の数だけ置き場所を考える |
| 依頼はここで済むか | 1つの依頼で開くファイルの数 | 散らばった持ち物を1か所へ集める |
| ほかの人が開かないか | 別の依頼で書き換わる行 | その行を持ち主の置き場所へ移す |
| 一緒に変わるか | 変わる時期と理由 | 時期のそろわないものを分けて置く |
分けすぎれば1つの依頼が散らばるので、線は細かさではなく、依頼主の境目に引きます。依頼主が2人いると分かっても、すぐに分ける必要はなく、依頼が実際にぶつかり、分ける利点が手間を上回ったときに、中身を変えずに置き場所だけを動かします。
次回は連載2.2「OCP――共有先を一つ足したときの差分を追う」です。今回は差分を「誰の依頼か」で読み直しましたが、次回は同じ差分を「どこを触らずに済んだか」の目で追います。新しい共有先を足しても、既存の X や LINE の定義を開かずに済むのはなぜか。その約束を、テストでどう守っているかも見ていきます。それでは、次回もお楽しみに!
連載の全体像は本編の連載目次へ。前回の1.3「ADRに残すのは結論より、捨てた案と制約」、1.2「共有先が増えても触らないコードを決める」とあわせて読むと、名札カードという形が、どんな判断と原則の上に立っているかが一続きで見えてきます。
プロマリでは、Webサイトの制作に加えて、共有や計測のような「裏側のしくみ」の設計・導入、それらを運用できる人材の育成に取り組んでいます。設計の分け方をチームでそろえたい方も、お気軽にご相談ください。
記事で数えたファイルを、実際のリポジトリで確かめるための資料です。













この記事全体の感想・質問・設計へのコメント