PROMARI JOURNAL

LSP――Copyに「開くURL」を要求すると何が壊れるか

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

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

丸い共有ボタンの裏側を掘る連載の第6回。SOLID の3つ目の原則 LSP を、長方形と正方形の例と、共有ボタンの実物で確かめます。コピーのボタンに「開く URL」を求める書き換えを実際に作ると、型検査は通り、テストが5件落ちました。事前条件・事後条件・不変条件の3つの約束を、図15点で読み解きます。

PASS IT ON

ひとつの発見を、次の会話へ。
自然光の差す木の机で、丸いくぼみに収まった青い丸い駒を、同じ形の青緑の駒へ差し替えようとしている手元。横には同じ形の紫の駒が置かれている写真風のイメージ

こんにちは、プロマリの紫です。連載「丸いボタンの裏側」の第6回、第2章の3回目です。SOLID は、変更に強いコードを書くための5つの原則を、頭文字でまとめた呼び名です。前回は2つ目の原則 OCP を読み、「足すときに、すでに動いているコードを直さずに済むか」を、本物の SNS を1つ足して確かめました。今回は3つ目の原則、LSPです。テーマは共有先を取り替えても、使う側が困らないかということ。コピーのボタンに「開く URL」を求めると何が壊れるのかを、実際に書き換えて確かめます。

点線の付いた用語は、その言葉を押すと詳しい説明が開きます。意味、身近なたとえ、この実装での使い方を順に読めます。キーボードではTabで用語へ移動し、EnterまたはSpaceで開き、Escapeで本文へ戻れます。各ページで最初に出る用語から参照できるようにしました。

この記事は連載「丸いボタンの裏側」の第6回(2.3)です。前回の2.2「OCP――共有先を一つ足したときの差分を追う」で、押したときの動き(開く・コピー・端末の共有)で分かれる場所を数えました。今回はその続きなので、先に読んでおくと話がつながりやすくなります。連載全体の地図は、本編5ページ目の連載の目次からどうぞ。

この回は6ページあります。1ページ目で LSP の意味と「3つの約束」を確かめ、2ページ目で長方形と正方形という有名な例で原則をつかみます。3ページ目で共有ボタンの実物に戻り、4ページ目で「どの共有先も URL を開けば共有できる」と思い込んだコードを実際に書いて、何が壊れるかを確かめます。5ページ目では、テスト用の代わりの部品を作るときの約束を、6ページ目では OCP とのつながりと、やりすぎの見分け方、宿題に進みます。図は15点です。ここで示す件数や出力は、すべて実際に手元で動かして取ったものです。

取り替えても、使う側が困らないか

記事の上に並んでいる丸いボタンを思い出してください。X のボタンも、コピーのボタンも、見た目は同じ丸です。押し方も同じで、どちらもクリックするだけです。けれど、押したあとに起きることは違います。X のボタンは X の投稿画面を開きます。コピーのボタンは、記事の URL をクリップボードに書き込みます。スマートフォンで出る「共有」のボタンは、端末の共有メニューを開きます。

図1-1 同じ丸いボタン、押したあとの仕事は3つ
図1-1 同じ丸いボタン、押したあとの仕事は3つ。現在のしくみ。見た目と押し方は同じでも、押したあとの仕事は3つとも違います。コピーのボタンには、開く画面がありません。図1-1 同じ丸いボタン、押したあとの仕事は3つ。現在のしくみ。見た目と押し方は同じでも、押したあとの仕事は3つとも違います。コピーのボタンには、開く画面がありません。

見た目が同じだと、つい「どのボタンも、押したら何かの画面を開くもの」と考えたくなります。けれど、コピーのボタンには開く画面がありません。もし、ボタンを押したときの処理を「開く画面の URL を受け取って、それを開く」という1つの手順で書いてしまうと、コピーのボタンは正しく動きません。この回の LSP は、こうした取り違えを防ぐための原則です。

ここで大事なのは、どちらのボタンも悪くないことです。X のボタンは開くのが仕事で、コピーのボタンは書き込むのが仕事です。壊れるのは、使う側が「どれも同じはずだ」と思い込んで、中身の違う部品を同じ手順で動かしたときです。取り替えて壊れるかどうかは、使う側が何に頼っているかで決まります。

Liskov の定義:使う側から見て、振る舞いが変わらない

この原則の名前は、計算機科学者の Barbara Liskov(バーバラ・リスコフ)から来ています。Liskov は1987年の講演「Data Abstraction and Hierarchy」で、ある型を別の型の代わりに使えるための条件を、次のように書きました。「T を使って書かれたどんなプログラム P でも、T の値の代わりに S の値を置いたとき P の振る舞いが変わらないなら、S は T の部分型(サブタイプ)である」。原文は What is wanted here is something like the following substitution property で始まる一文です。

1994年には、Jeannette Wing(ジャネット・ウィング)との共著論文で、この考えがもう少し分かりやすく言い直されています。部分型のオブジェクトは、元の型のオブジェクトを使う人やプログラムから見分けがつかないほど、同じように振る舞うべきだ(the objects of the subtype ought to behave the same as those of the supertype as far as anyone or any program using supertype objects can tell)、という言い方です。

図1.1-1 同じ形の充電器に取り替えたら
図1.1-1 同じ形の充電器に取り替えたら。たとえ。差し込めることと、約束どおりに動くことは別です。LSP が見ているのは、形の先にある約束です。図1.1-1 同じ形の充電器に取り替えたら。たとえ。差し込めることと、約束どおりに動くことは別です。LSP が見ているのは、形の先にある約束です。

身近なもので言えば、スマートフォンの充電器です。純正の充電器が壊れたので、同じ形のプラグの充電器を買ってきたとします。差し込めることは大事ですが、それだけでは足りません。スマートフォンが頼っているのは「決まった電圧で電気が来ること」です。形が同じでも、約束と違う電圧を出す充電器なら、スマートフォンは困ります。LSP が見ているのは、この「形が合うこと」の先にある「出てくるものまで約束どおりか」です。

プログラムに当てはめると、差し込み口の形にあたるのがインターフェースです。メソッドの名前や、受け取る値と返す値の型のことです。TypeScript では、形が合わなければコンパイルの時点で止まります。けれど、形が合っていても、中身の振る舞いが約束と違うことはあります。そこは、形を確かめる仕組みでは見つかりません。

約束を3つに分ける:事前条件・事後条件・不変条件

では、「約束どおり」とは何を指すのでしょうか。約束は、3つに分けて考えると確かめやすくなります。

図1.2-1 約束を3つに分ける
図1.2-1 約束を3つに分ける。説明。入口は狭めない、出口の約束は減らさない、いつもの性質は崩さない。3つがそろえば、使う側は取り替えに気づかずに済みます。図1.2-1 約束を3つに分ける。説明。入口は狭めない、出口の約束は減らさない、いつもの性質は崩さない。3つがそろえば、使う側は取り替えに気づかずに済みます。

1つ目は事前条件です。処理を呼ぶ前に満たしておくべき条件で、「受け付ける入力の範囲」と言いかえられます。充電器なら「日本の家庭用コンセントにつなげば動く」です。2つ目は事後条件です。処理が終わったときに守ると約束する結果で、充電器なら「決まった電圧で電気を出す」です。3つ目は不変条件です。いつ見ても成り立っているべき条件で、充電器なら「本体が熱くなりすぎない」です。

取り替えた部品が約束を守るとは、この3つについて、元の部品より約束を悪くしないことです。事前条件なら、受け付ける範囲を狭めない。事後条件なら、約束する結果を減らさない。不変条件なら、崩さない。入口は狭めない、出口の約束は減らさない、いつもの性質は崩さない。この3つがそろっていれば、使う側は、取り替えたことに気づかずに済みます。

考えてみる:同じ名前のメソッドを持っていれば、取り替えられるの?

名前と型がそろっているのは、差し込み口の形が合っているだけです。取り替えられるかどうかは、その先の3つの約束で決まります。たとえば同じ write という名前でも、片方は書き込みが終わってから返り、もう片方は何もせずに返るなら、使う側は違いに気づけず、壊れた結果を受け取ります。名前と型は必要な条件ですが、それだけでは足りません。

COMMENTS
コメント…

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

PASS IT ON

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

この記事を書いた人

Takaomi Murasaki

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

公開記事 10 件

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

FROM INSIGHT TO IMPACT

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

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

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

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

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

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

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

ご相談後の流れ

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