🧑‍💼

LSPで権限移譲を明確化

2025/04/15に公開

「この人なら代わりに任せても問題ない」――ビジネスの現場でもよく聞くこのセリフですが、引き継いだ結果、何かしらのトラブルが発生するということはそう珍しいことではありません。

私もかつて、上司から担当企業を引き継いだ際にまさにそんな経験をしました。自ら考えて動くようにと念を押されていたので、相手の状況を見ながら“良かれと思って”判断し、上司から引き継いだ明確な指針を自分なりに調整してしまったのです。例えば、法人営業として様々な企業にシステム導入を提案する中で――

  • 本来1週間ごとに提案の進捗確認すべきところを、「先方が忙しそうだから」と配慮して2週間空けた
  • 顧客の出したnice to haveな要件を断り切れず持ち帰ってきてしまった

このような判断が裏目に出て、時間ばかりかかった割に成果に結びつかず、案件は決まらない状態の中で、上司からは「勝手に基準を変えてはいけない」とフィードバックを受けました。私は、自律的に動けと言われていたものの、その“自律”の範囲を履き違えていたことに気づかされました。

このような経験は、ソフトウェア設計原則の一つである「リスコフの置換原則(LSP)」を学んだ際に強くリンクしました。LSPは、子クラスが親クラスのふるまいや契約を壊さずに代替可能であるべきだとする考え方です。

上司の代わりに部下が動くのであれば、本来は前提条件、事後条件、不変条件を整理し、どこまでを守り、どこを強化できるかを見極める必要がありました。私はそこを曖昧にしたまま判断してしまったのです。

ソフトウェアの世界では、子クラスが親クラスの契約を守りつつふるまいを拡張することで、システム全体が壊れずに成り立ちます。これは人の組織でも同様で、上司から部下に役割が引き継がれるときも、ふるまいの前提・成果・基準が守られていなければ、全体の信頼や成果が崩れてしまいます。

LSPは、ソフトウェア設計にとどまらず、組織内の役割移譲や業務引き継ぎを円滑に進めるための実用的な視点としても役立つ原則です。

LSPとは何か

ご存知の方も多いかと思いますが、LSP(Liskov Substitution Principle)は1987年、Barbara Liskovにより提唱されたオブジェクト指向設計の原則です。

"親クラスのオブジェクトの代わりに子クラスのオブジェクトを使っても、プログラムの意味が変わってはならない"

この原則を守るためには、以下の条件が重要になります。具体例として航空会社のマイレージサービスとともに見てみましょう。

前提条件(Preconditions)

  • 子クラスで同じか、より緩くすること
  • 親クラスで許されていた操作が、子クラスで禁止されてはいけない。

事後条件(Postconditions)

  • 子クラスで同じか、より強くすること
  • 親クラスが保証していた結果以上を返すことはOK、だがそれ以下はNG。

不変条件(Invariants)

  • 親クラスで成り立っていた状態(ルール)は、子クラスでも維持すること
  • 子クラスで強化するのは構わないが、壊してはいけない。

具体的な設計例

ここではマイレージサービスを題材として、LSPの3条件を顧客クラス設計にを当てはめたクラスが下記になります。

class Customer:
    def book_flight(self, seat_class):
        assert seat_class in ["economy", "business"]  # 前提条件
        return f"Flight booked in {seat_class} class"

    def get_mileage(self):
        return 100  # 事後条件:必ず100マイル付与

    def is_active(self):
        return True  # 不変条件:常にアクティブ状態を維持

class RoyalCustomer(Customer):
    def book_flight(self, seat_class):
        # より緩く:ファーストクラスも許容(前提条件の緩和)
        assert seat_class in ["economy", "business", "first"]
        return f"Royal booking in {seat_class} class"

    def get_mileage(self):
        # より強く:マイルが増える(事後条件の強化)
        return 300

    def is_active(self):
        # 不変条件はそのまま維持
        return super().is_active()

このように、RoyalCustomerはCustomerの代わりに使ってもシステムが壊れず、むしろ機能強化されています。これがLSPを守った設計です。

condition

前提条件(Precondition)
Customer: "economy" または "business" のみ予約可能
RoyalCustomer: "first" も選べる → 条件を緩和(OK)

事後条件(Postcondition)
Customer: 100マイル付与
RoyalCustomer: 300マイル付与 → 成果強化(OK)

不変条件(Invariant)
Customer: is_active() は常に True
RoyalCustomer: 同様に is_active() を維持 → 不変条件を維持(OK)

営業現場でのLSP的ふるまい

上司と部下の役割分担も、まさにクラス継承のような関係です。

前提条件(Precondition)
上司:往訪は先方決裁者がいる場合に限る
部下:担当者レベルでも往訪可能
→ 訪問対象を広げている=前提条件の緩和

事後条件(Postcondition)
上司:見積もりを提示して、ネクストアクションを詰める
部下:見積もり提示に加えて、次回往訪時の契約詳細まで詰めてきた
→ ネクストアクションを具現化=成果を高めている

不変条件(Invariant)
上司:契約前でも顧客対応は公平・丁寧に
部下:契約前後に関係なく、問い合わせには必ず翌営業日以内に回答する
→ 対応姿勢を強化しており、不変条件を保ちつつ拡張している

NGな例:

  • 問い合わせがない限り動きません(前提条件を厳しくしている)
  • 見積書提示後は先方からの連絡待ち(事後条件を弱めている)
  • 信頼は状況次第(不変条件を壊している)

なぜLSPは組織にも通用するのか

ソフトウェアもビジネス組織も、次のような共通点を持っています:

  • 階層構造で動く(親→子/上司→部下)
  • 抽象的な契約や責務の委譲がある
  • 代替可能性(substitutability)を前提にして効率的に設計されている

つまり、ソフトウェア設計の知見は、人や組織の動かし方にも応用が効くのです。私は、営業での失敗経験を通して「行動の自由度」と「ふるまいの契約」は両立しなければならないと直観的に理解することができました。しかしLSPという設計原則は、自由度と制約を明確に言語化しており、非常に感銘を受けたのです。この原則はシステムを壊さないためだけでなく、人の判断にも有効なガイドになるでしょう。

参考

Discussion