OCP――共有先を一つ足したときの差分を追う
作成: / 公開: / 内容更新:
執筆:tamito0201 / 掲載・運営:プロマリ
丸い共有ボタンの裏側を掘る連載の第5回。SOLID の2つ目の原則 OCP を、本物の SNS(Bluesky)の追加を通じて確かめます。名札カード1枚で済む変化と、共通処理のコードを変更することになる変化。差分を1行ずつ追いかけ、閉じる向きは変化の来やすさで選ぶことを、図22点で読み解きます。
検証:本物の SNS を1つ足してみる
OCPにかなっているかどうかは、実際に1つ足してみるのがいちばん確かです。1ページ目で見たとおり、このプラグインでは、共有先ごとに名札カードという設定ファイルを1枚書きます。OCP にかなった作りなら、新しい SNS も名札カードを1枚足すだけで済むはずです。連載1.2では架空の共有先で数えましたが、今回は本物の SNS、Bluesky を足してみます。Bluesky には、ほかのサイトから投稿画面を開くための公式の入口があり、共有ボタンの題材にちょうどよいのです。
検証は、次の順で進めました。まず、プラグインのリポジトリをgit worktreeで作業用のコピーに写しました。公開しているプラグインには何も入れていません。次に、何も足していない状態でテストを流し、結果を記録しました。Node のテストが63件、Python のテストが19件で、どちらもすべて通りました。Node のテストは、ブラウザで動く部分(URL の組み立て、ボタンの並び、クリックしたときの動き)を確かめるものです。Python のテストは、名札カードを読む生成器を確かめるものです。そのうえで Bluesky の名札カードを1枚足し、設定に1行足して、もう一度テストを流します。最後に、変わったファイルと行数を数えます。
足す前の結果を先に取っておくのには、理由があります。足したあとにテストが落ちても、それが足したせいなのか、もともと落ちていたのかが分からなければ、差分を正しく数えられないからです。変更前の状態を記録しておくことで、追加の影響を切り分けて確かめられます。
Bluesky の名札カードを書く
Bluesky の公式ドキュメントによると、投稿画面の入口は https://bsky.app/intent/compose で、渡せる値は text の1つだけです。これに合わせて、名札カードを1枚書きました。
同じドキュメントには、共有ボタンを作るうえで知っておきたいことが、ほかにも書いてあります。投稿は300字まで(正確には、人の目に1文字に見えるまとまりで300個まで)であること。ログインしていない人は、まずサインインを求められること。そして、入口を開いても投稿はすぐには行われず、本人が内容を確かめてから投稿することです。共有ボタンは投稿欄を埋めるところまでを受け持ち、投稿するかどうかは、押した人が決めます。これは X や LINE の共有画面と同じ分担です。
# Bluesky の投稿画面(検証用)。
key = 'bluesky'
label = '投稿'
brand_color = '#1185FE'
action = 'open'
endpoint = 'https://bsky.app/intent/compose'
icon = '<svg viewBox="0 0 24 24" …>…</svg>'
[params]
text = 'text'X の名札カードと並べると、違いがよく分かります。違うのは値だけです。key は bluesky、色は Bluesky の青、endpoint は Bluesky の投稿画面、[params] は text = ‘text’ の1行だけです。Bluesky が受け取る名前は text しかないので、そこに共有文を入れる、という意味になります。項目の種類は、X と同じ7つのままです。名札カードの書き方の型そのものは、1文字も変えていません。
説明書どおりの3つの手順
このプラグインの説明書(docs/customization.md)には、共有先を足す手順が書いてあります。やったことは、この手順どおりです。
説明書の手順は、図2.2-1 のとおり3つです。
① 名札カードを書く:destinations フォルダに bluesky.toml を1枚作ります。中身は、上で見た10行です。
② 設定に並べる:サイトの設定ファイルに、bluesky を表示する共有先として書き足します。設定ファイルには、大きなボタンで並べる共有先の一覧(destinations)と、その後ろに小さなアイコンで並べる共有先の一覧(secondary)の2つがあります。今回は secondary に bluesky = true の1行を足しました。
③ 作り直す:生成器の python3 tools/config.py –write を実行します。このコマンドは名札カードと設定ファイルを読み、ブラウザが読み込む JavaScript のファイル(promari-sns-share.min.js)を作り直します。名札カードを足しても、この作り直しをしないとボタンには出ません。
3つの手順で触るのは、名札カード、設定ファイル、自動で作られる JavaScript のファイルだけです。URL を組み立てる共通処理のコードは、開くことすらありません。「共有先を1つ足す」という作業が、共通処理を書き換えずに終わるように作られている。これが、このプラグインが共有先の追加に対して「閉じている」ということです。
1枚足したときの差分
では、実際に差分はどこに出たのでしょうか。図2.3-1 では、変わった場所を、その変更を頼んでくる人(依頼主)ごとに分けて並べています。新しい SNS の情報は destinations、サイトの設定は config、テストは tools/tests、共通処理は web/src というフォルダにあります。
名札カードを足して作り直した時点で、変わったのは2つのファイルだけでした。git diff の結果を、ファイルの場所と位置を示す行だけ短くして載せます。行頭の + が足した行、- が消した行、何も付いていない行は、前後がどこかを示すための変わっていない行です。
--- a/config/share_config.example.toml
+++ b/config/share_config.example.toml
@@ [share.secondary] @@
email = true # Send by email (mailto).
copy = true # Copy the URL to the clipboard; falls back to a link without JavaScript.
+bluesky = true # Bluesky(検証用)。
native = true # Native share sheet (Web Share API); shown only where navigator.share is available.
--- /dev/null
+++ b/destinations/bluesky.toml
@@ 新しいファイル @@
+# Bluesky の投稿画面(検証用)。
+key = 'bluesky'
+label = '投稿'
+brand_color = '#1185FE'
+action = 'open'
+endpoint = 'https://bsky.app/intent/compose'
+icon = '<svg viewBox="0 0 24 24" …>…</svg>'
+
+[params]
+text = 'text'設定ファイルには bluesky = true の1行が足され、新しい名札カード bluesky.toml は10行がまるごと足されました。消した行(-)は1つもありません。共通処理を含むブラウザ側のコード(web/src)には、1行の差分も出ていません。そして Node のテスト63件は、1件も書き換えずにすべて通りました。X や LINE のボタンが正しい URL を作ることも、並び順も、クリックしたときの動きも、変わっていないということです。
落ちたテストは、在庫表
ただし、Python のテストは3件落ちました。テストの出力を見てみます。
$ python3 -m unittest discover -s tools/tests
FAIL: test_catalog_order_follows_file_names
FAIL: test_extracts_all_bundled_destinations
FAIL: test_example_is_valid
AssertionError: Items in the first set but not the second:
'bluesky'FAIL: のあとに並んでいるのが、落ちた3件のテストの名前です。最後の2行は、「比べた2つの一覧のうち、片方にしか無いものがある。それは ‘bluesky’ だ」という意味です。つまり、テストに書いてある共有先の一覧には bluesky が無いのに、実際の共有先には bluesky が増えていた、ということです。
3件とも、共有先の一覧を丸ごと期待値に書いたテストでした。「共有先は copy・email・facebook・hatena・line・linkedin・native・x の8つ」と書いてあるところに、9つ目の bluesky が現れたので、「一覧に無いものがある」と教えてくれたのです。この記事では、この種のテストを在庫表と呼びます。
在庫表に1行足すのは、閉じた共通処理を変更したことにはなりません。お店で新しい商品を仕入れたら、棚卸し表に1行足すのと同じです。むしろ、在庫表が落ちたことは、「共有先が1つ増えた」という事実を機械がきちんと見ていた証拠です。3件の期待値に bluesky を1行ずつ足すと、Python のテスト19件もすべて通りました。
考えてみる:在庫表のテストは、足すたびに直すことになる。OCP に反していない?
反していません。OCP が閉じておきたいのは「すでに動いているコードの振る舞い」です。在庫表は「いま何が並んでいるか」を書いた一覧で、並んでいるものが増えれば一覧も増えるのが正しい動きです。むしろ一覧のテストがあることで、名札カードを足し忘れたり、消してしまったりしたときに気づけます。直すのは一覧の1行だけで、X や LINE の URL を確かめるテストのような、振る舞いの期待値は1つも書き換えていないことが大事なのです。













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