SRP――一つの共有先の定義は、一つの理由で変わるか
作成: / 公開: / 内容更新:
執筆:tamito0201 / 掲載・運営:プロマリ
丸い共有ボタンの裏側を掘る連載の第4回。SOLID の最初の原則 SRP を、共有先の名札カード1枚からプラグイン全体まで当てて確かめます。責任とは仕事の数ではなく、変更を頼んでくる人の数。Martin の車の修理のたとえから、実際の変更履歴を数える宿題まで、図22点で読み解きます。
名札カードの依頼主は、SNS各社だけ
SRPの問いを、まず名札カードに当ててみましょう。名札カードとは、連載1.2で読んだ、共有先ごとに1枚ずつ置いたTOMLファイルのことです。X の名札カードの中身は、次の7項目です。
# X(旧Twitter)のポスト画面。
key = 'x'
label = 'ポスト'
brand_color = '#000000'
action = 'open'
endpoint = 'https://twitter.com/intent/tweet'
icon = '<svg viewBox="0 0 24 24" …>…</svg>'
[params]
url = 'url'
text = 'text'
hashtags = 'hashtagsCsv'
via = 'via'7つの項目を1行ずつ読み、「この行は、誰の都合で変わるか」を考えてみます。
key は X を指す名前です。endpoint は X が用意した共有画面のURLで、[params] はそこへ渡す引数の名前です。icon と brand_color は X のロゴと色で、label の「ポスト」は X が決めた呼び名です。action の open は、「新しい画面を開いて共有する」という X の共有の仕方を表します。どの行も、変わるきっかけは X の側にあります。7本の線は、全部同じ1人へ集まります。
アイコンと表示名まで X の持ち物として扱うのには、理由があります。SNS 各社は、自社のロゴの使い方や色、呼び名についての決まりを公開しています。X はかつての「ツイート」を「ポスト」と呼ぶようになり、ロゴも鳥から X の字へ変わりました。こうした変更は、共有ボタンを置くサイトの側ではなく、SNS の側から一方的にやって来ます。だから、アイコンと表示名の既定値は X の名札カードに置き、X の決まりが変わったら、この1枚を直せば済むようにしています。
このように、同じ理由で一緒に変わるものだけが集まっている状態を、凝集度が高いと言います。名札カードは、X の決まりが変わったときに一緒に変わる7項目だけを集めた、凝集度の高い1枚です。だから、この7項目を1枚のカードにまとめています。
図の七本の線は、「七項目が毎回必ず同時に変わる」という意味ではありません。URLだけが変わる日も、ロゴだけが変わる日もあります。それでも、Xの共有機能に追従するための定義として、同じまとまりで理解したい項目です。一緒に変わる可能性があること、同じ知識のまとまりを表すこと、その両方から凝集度を考えています。
ここで、表示名だけを別のファイルへ移す案を試しに考えてみます。表示名を取り出すこと自体は簡単でも、共有先を追加する人は、定義と表示名の二か所を探すことになります。その追加の手間を払ってまで独立させたい変更があるか。無ければ、項目数を減らすためだけの分割は見送れます。SRPは「分ける理由」だけでなく、「一緒に置いてよい理由」を説明するためにも使えるのです。
ここで少し引っかかるのが、label と brand_color です。表示名と色は、サイトの見た目の話ではないのでしょうか。この2つは、X の決まりにそろえた既定値として置いています。何も指定しなければ、X の決まりどおりの呼び名と色で表示されます。サイトが変えたいときは、名札カードではなく、次の設定ファイルで変えます。
並び順と言い回しは、サイトが決める
どのボタンを大きく出すか、どの順に並べるか、どんな言葉で出すか。これを決めるのは SNS 各社ではなく、このサイトの運営者です。そうした判断は、サイトの設定ファイル share_config.toml に書きます。名札カードの既定値は、ここで上書きできます。
[share]
destinations = ["facebook", "x", "line"]
[share.labels]
x = "ポスト"
[share.buttons.x]
color = "" # 空なら、名札カードの既定の色を使う
[share.secondary]
hatena = true
linkedin = true
email = true
copy = true
native = truedestinations に並べた3つが大きなボタンになり、[share.secondary] で true にしたものが、その後ろに小さな丸いボタンとして並びます。[share.labels] は言い回し、[share.buttons.x] の color は色の上書きです。空のままなら、名札カードの既定値が使われます。SNS側の決まりは名札カードに、サイトの判断は設定ファイルに。依頼主ごとに、書く場所が分かれています。
既定値と上書きは、2枚の紙の重ね合わせ
名札カードの値と、設定ファイルの値。同じ「表示名」や「色」が2か所に書けるなら、どちらが使われるのでしょうか。決まりは1つだけです。下に名札カードの紙を置き、その上にサイトの設定の紙を重ねると考えてください。
上の紙に値が書いてあれば、上の値が使われます。上の紙が空なら、下の紙の値が透けて見えます。図では、表示名は上の紙の「ポスト」が使われ、色は上の紙が空なので、下の紙の #000000 がそのまま使われています。実際のコードも、この一言どおりに書かれています。
const label = config.labels[key] ?? destination.appearance.label;
const override = (name, fallback) => {
const value = config.buttons[key]?.[name];
return value === undefined || value === '' ? fallback : value;
};
color: override('color', destination.appearance.color),1行目は「設定の表示名があればそれ、無ければ名札カードの表示名」という意味です。override は「設定に値があって空でなければそれ、そうでなければ既定値」を返します。決まりが1つなので、2か所に書けても迷いません。この決まりのおかげで、名札カードは X の決まりのまま手を付けずに済み、サイトの運営者は自分の紙だけを書き換えればよくなります。2人の依頼が、同じファイルで出会わないのです。
重ねた紙の図では、表示される値と、その値を決めた場所を分けて見てください。完成したボタンが黒いという結果だけでは、名札カードの既定値なのか、サイトが黒を指定したのかは分かりません。設定を直すときには、結果の色から判断せず、どちらの紙が値を出したかまで戻ります。そうすると、「今回はサイトだけを変える」という依頼を、SNS共通の定義へ持ち込まずに済みます。
なお、抜き出したコードでは、表示名の??と、色などに使うoverrideは判定が少し違います。前者は値がnullまたはundefinedなら既定値へ戻り、後者は空文字も既定値へ戻します。「空なら全部同じように透ける」とコード全体へ広げず、この図は設定の上書き先を説明する模型として見てください。境目が分かってから、値の扱いの細部をコードで確かめる順です。
考えてみる:サイトが色を変えたいなら、名札カードの brand_color を直接書き換えたほうが早くない?
1つのサイトだけを考えれば、そのほうが早く見えます。けれど、名札カードはこのプラグインを使うすべてのサイトで共有される1枚です。あるサイトの好みで brand_color を書き換えると、ほかのサイトのボタンの色まで変わってしまいます。しかも、次に X がロゴの色を変えたとき、書き換えた値が X の決まりなのか、どこかのサイトの好みなのか、区別がつかなくなります。サイトの好みはサイトの紙に書いておけば、名札カードはいつでも「X の決まり」だけを表す1枚のままでいられます。









このページ(2ページ目)の感想・質問・設計へのコメント