PROMARI JOURNAL

SRP――一つの共有先の定義は、一つの理由で変わるか

作成: / 公開: / 内容更新:

執筆:tamito0201 / 掲載・運営:プロマリ

丸い共有ボタンの裏側を掘る連載の第4回。SOLID の最初の原則 SRP を、共有先の名札カード1枚からプラグイン全体まで当てて確かめます。責任とは仕事の数ではなく、変更を頼んでくる人の数。Martin の車の修理のたとえから、実際の変更履歴を数える宿題まで、図22点で読み解きます。

PASS IT ON

ひとつの発見を、次の会話へ。

依頼主を2人見つけたら、どうするか

4つの問いで採点して、依頼主が2人いるファイルが見つかったとします。すぐに分けるべきでしょうか。SRPは「必ず分けよ」という規則ではありません。分ける線をどこに引くかを決めるための物差しです。判断は、3つの問いを順にたどって行います。

図6-1 2人見つけたら、すぐ分けるべきか
図6-1 2人見つけたら、すぐ分けるべきか。判断の目安(提案)。分けるのは、依頼が実際にぶつかり、分ける利点が手間を上回ったときです。図6-1 2人見つけたら、すぐ分けるべきか。判断の目安(提案)。分けるのは、依頼が実際にぶつかり、分ける利点が手間を上回ったときです。

1つ目は、そもそも依頼主が2人以上いるか。2つ目は、2人の依頼が実際にぶつかったか。履歴をたどって、2人の依頼が同じ行や同じ時期に重なった跡があるかを見ます。3つ目は、分けたときの手間より、ぶつからなくなる利点のほうが大きいか。分ければファイルが増え、読む場所も増えます。片方の依頼がめったに来ないなら、分ける手間のほうが大きいこともあります。3つとも「はい」なら分け、1つでも「いいえ」なら、いまは分けずに待ちます。待つときは、気づいたことを記録に残しておくと、次に同じファイルを開いた人が判断を引き継げます。

考えてみる:依頼主が2人いるのに待つのは、SRPに反していない?

反していません。SRP は、変更の依頼がぶつかって困ることを避けるための考え方です。まだ一度もぶつかっておらず、これからもぶつかりそうにないなら、分けても困りごとは減りません。むしろファイルが増えるぶん、読む手間が増えます。Martin の記事が問題にしているのも、頼んでいない人の持ち物を壊すことでした。実際の衝突だけでなく、起こりそうな衝突の大きさも見て分ける時期を決めます。大事なのは、依頼主が2人いることに気づいていて、その判断を記録に残していることです。

分けると決めたら、4つの手順で

分けると決めたら、次の4つの手順で進めます。この作業はリファクタリングとして行います。外から見た動きは変えずに、中の形だけを整えるのです。

図6.1-1 分けるときの4つの手順
図6.1-1 分けるときの4つの手順。手順の提案。中身を変えずに置き場所だけを動かし、最後に「次の依頼が1か所で済むか」で確かめます。図6.1-1 分けるときの4つの手順。手順の提案。中身を変えずに置き場所だけを動かし、最後に「次の依頼が1か所で済むか」で確かめます。

まず、履歴をたどって、どの変更が誰の都合で入ったかに印を付けます。次に、ファイルの行ごとに、どの依頼主の持ち物かを決めて色を塗ります。3つ目に、色ごとに新しいファイルへ行を移します。このとき中身は書き換えず、置き場所だけを変えるのが大事です。中身と置き場所を一度に変えると、動きが変わったときに、どちらのせいか分からなくなります。最後に、テストが通ることと、次に来るはずの依頼が1か所で済む形になったかを確かめます。

置き場所を変えても、読者の見える景色は保つ

分割の最後は、フォルダがきれいになったところで止めず、読者の見える結果へ戻って確かめます。次の図は、分ける前と後に同じ設定を渡し、同じ共有欄ができるかを見比べるための模型です。

図6.2-1 分ける前後で、同じ景色になるか
図6.2-1 分ける前後で、同じ景色になるか。説明例(分割後の確かめ方)。読者の見える結果を保ったうえで、次の依頼が自然な置き場所へ届くかを確かめます。図6.2-1 分ける前後で、同じ景色になるか。説明例(分割後の確かめ方)。読者の見える結果を保ったうえで、次の依頼が自然な置き場所へ届くかを確かめます。

二枚の画面には、同じ順序のボタンと、同じ表示名があります。裏側の置き場所は変わりましたが、読者が押すものは変わっていません。図でボタンの並びが一致するように、変更前の振る舞いを、変更後の部品の組合せでも保ちます。これは新しい見た目を考える作業ではなく、既存の見た目と操作を守って分ける作業です。

実際には、スクリーンショットが似ているだけでは足りません。共有URL、クリック時に呼ぶ処理、色の上書きが無いときの既定値、設定に知らない共有先が入ったときの扱いなど、外から観測できる結果も確かめます。見た目の確認と、値や操作の確認を重ねると、「配置を動かしただけのつもりで、動作まで変えた」を見つけやすくなります。

分割後には、次に来そうな小さな依頼も一つ当ててみます。たとえば「Xだけを小さい列へ移す」としたら、サイトの設定へ自然にたどり着けるでしょうか。定義と設定の両方へ同じ値を書かなければ動かないなら、境目はまだ途中かもしれません。動作を保ったことと、次の変更が置き場所に合うことを、別々に確認します。

画面を比べる練習では、入力をそろえるところから始めます。同じ記事のURL、同じタイトル、同じサイト設定を渡して、分割前と後を比べます。片方だけ設定を変えた状態では、違いが出ても、分割の影響なのか設定の影響なのかが分かりません。比較のために動かさないものを先に決めます。

次に、一つだけ入力を変えます。色の上書きを外して、既定値へ戻る様子を見る、といった小さな変更です。二枚の画面で同じように戻れば、定義と設定を分けても、その合成の約束を保てていると確かめられます。通常の表示だけでなく、上書きが無い場面を選ぶと、境目のつなぎ方が見えやすくなります。

最後に、今回の分割を知らない人のつもりで、次の修正先を探してみます。サイト固有の色を変えたいとき、最初に設定へ向かえるでしょうか。名前が曖昧で共通定義を開いてしまうなら、ファイルの説明や入口の名前を見直す余地があります。動くことに加え、変更する人が正しい場所へたどり着けることも、分割を仕上げる確認になります。

ここまで確かめたら、変更の説明も短くできます。「並び順の判断をサイト設定へ移した。SNSのURL定義は変えていない。同じ入力で同じ結果になることを確認した」。こう書ける変更は、原則の名前だけを掲げた変更より、読む人が評価しやすくなります。SRPを、ファイルの整理の話から、変更を説明する道具へ戻して終えるわけです。

手を動かして確かめる

今回の練習は、依頼主を実際に数えてみることです。手元のリポジトリで、よく書き換えているファイルを1つ選んでください。git logを使うと、そのファイルを変えたコミットを1行ずつ並べられます。

Shell変更の履歴を1行ずつ並べる(ファイル名は手元のものに置き換える)
git log --format="%h %s" -- destinations/x.toml
図7-1 この回の宿題:変更履歴から依頼主を数える
図7-1 この回の宿題:変更履歴から依頼主を数える。確かめ方の提案。依頼主が2人以上いたら、分ける線を引く候補です。1人なら、そのままでかまいません。図7-1 この回の宿題:変更履歴から依頼主を数える。確かめ方の提案。依頼主が2人以上いたら、分ける線を引く候補です。1人なら、そのままでかまいません。

並んだコミットの1行ずつに、「これは誰の都合で入った変更か」と依頼主の印を付けていきます。最後に、印の種類を数えます。1人なら、そのファイルはそのままでかまいません。2人以上なら、前の節の3つの問いに進みます。

練習では、最初からリポジトリ全体を分類しようとしなくて大丈夫です。一つのファイルについて、最近の変更を数件選び、それぞれに「頼んだ立場」「変えたかった結果」「触った行」を書いてみてください。三つの欄を埋めると、同じ名前の人が別の立場で頼んでいたり、別の人が同じ方針を引き継いでいたりすることに気づけます。

答えは「一人だった」「二人だった」で終わらせず、次の変更を一つ予想して、その置き場所まで説明してみます。「共有先のURL変更ならこの定義」「サイトの並び変更ならこの設定」と言えれば、境目が具体的になりました。どこへ置くか決められない依頼が残ったら、それを次のレビューの問いにします。すぐにコードを分割しなくても、調べる対象を絞れれば練習の成果です。

このプラグインでも、実際に数えてみました。

Shellpromari-toolkit で x.toml の履歴を並べた結果
$ git log --format="%h %s" -- destinations/x.toml
7c91af3 refactor(sns-share): 共有先を PHP クラスではなく destinations/<key>.toml のデータで宣言する
図7-2 実際の履歴で数えてみる
図7-2 実際の履歴で数えてみる。実測(promari-toolkit の履歴)。数えると、名札カードはまだ一度も依頼を受けていません。ひな形の変更の多くは、設定の書式を整えた開発者の都合でした。図7-2 実際の履歴で数えてみる。実測(promari-toolkit の履歴)。数えると、名札カードはまだ一度も依頼を受けていません。ひな形の変更の多くは、設定の書式を整えた開発者の都合でした。

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ページ目の「一つの責任は、一つの仕事のことではない」から出てくる誤解です。

SRP によくある誤解と、この記事での答え
よくある誤解この記事での答え
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サイトの制作に加えて、共有や計測のような「裏側のしくみ」の設計・導入、それらを運用できる人材の育成に取り組んでいます。設計の分け方をチームでそろえたい方も、お気軽にご相談ください。

Web制作・計測・人材育成のご相談はこちら

COMMENTS
コメント…

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

PASS IT ON

この気づきを、誰かにも。

この記事を書いた人

Takaomi Murasaki

Promari SNS Shareの開発を通して、Webの仕組みや設計の選び方を紹介しています。動く実装と、その判断に至るまでを記事に残しています。

公開記事 11 件

プロフィールを見る
THANK YOU FOR READING.すべての記事へ ↗

FROM INSIGHT TO IMPACT

「できたらいいな」を、
動く仕組みに。

記事で見つけたヒントを、あなたの事業へ。
新しいサービスも、手間のかかる業務も。
いまの課題から、つくるべきものを一緒に考えます。

開発・AI・研修の実績を見る

まだ、仕様書はいりません。

「何から始める?」から、ご一緒に。

課題がまとまっていなくても大丈夫。テーマを選ぶと相談文をご用意します。
連絡先の必須入力は、お名前とメールアドレスだけ。

まずは課題の整理から相談する

ご相談後の流れ

  1. 01 内容を確認
  2. 02 メールでご連絡
  3. 03 課題・進め方をご相談
送信だけで契約やお申込みが確定することはありません。