OCPという名前は最悪です。
誰もがOpen-Closed Principle (OCP)を曲解しています。アンクル・ボブのSOLID原則の人気者で、ベルトラン・メイヤーの1988年の名著にルーツを持つものです。「ソフトウェアのエンティティは拡張に対して開き、修正に対して閉じていなければならない」と彼は宣言しました。高尚に聞こえます。でも実際に試してみてください。未来のすべての変更を予測する? 初日からフックを仕込む? 純粋な幻想です。私もやりました。リファクタリングのたびに詐欺師のような気分になりました。
メイヤーの原典からの正確な言葉をここに紹介します:
“Software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification.”
紙の上では高尚です。実践では地獄です。プログラマー——私も含めて——それを予知能力の強制にねじ曲げます。明日の機能のための見えないスロットをコードに書くのです。一つでも外せば恥の連鎖。完璧に当てても過剰設計の惨事。不安の燃料です。
そこにジョン・スキートが真実の爆弾を投下します。2013年のブログ記事。10年経った今も効きます。彼は低レベルの設計Tipsを否定しません。いや、名前にメスを入れます。「Open」と「closed」? 言葉の寄せ集めです。クライアント——コードのクライアントでユーザーのことじゃない——が内部の調整で壊れないようにする。それが本質です。
Swift開発者がOCPでつまずく理由は?
SwiftのプロトコルはOCPを叫びます。関連値付きのenum? 変動への完璧な対応です。それでも私たちは失敗します。決済プロセッサを想像してください。シンプルにスタート:CreditCardHandler。動きます。ところがユーザーがPayPalを要求。無理やり追加? switch文が爆発します。クライアント——注文サービス、UI——すべて書き直し。OCP違反です。コードを修正したからじゃない。変更が波及したからです。
悪いSwift:
class PaymentProcessor {
func process(_ type: String) {
switch type {
case "credit":
// credit logic
case "paypal":
// paypal logic
default:
fatalError()
}
}
}
醜い。Venmo追加? クライアントが悲鳴を上げます。修正:プロトコル。安定した契約です。
protocol PaymentHandler {
func process(amount: Double)
}
class CreditCardHandler: PaymentHandler { ... }
class PayPalHandler: PaymentHandler { ... }
class PaymentProcessor {
func process(_ handler: PaymentHandler) {
handler.process(amount: 100.0)
}
}
クライアントはプロトコルに依存。ハンドラーを入れ替えても波及なし。それがOCPです。修正ゼロじゃない。変更を封じ込めることです。
スキートはクレイグ・ラーマンのProtected Variationsが大好きです。「予測される変動点を特定し、その周りに安定したインターフェースを作成せよ」。揺らぎ——決済タイプなど——を見つけ、囲い込みます。アプリの残りは落ち着きます。
でも予測? スキートは率直です:難しい。やりすぎればYAGNI違反。不足すればリファクタリング地獄です。私の見解? 2015年のマイクロサービス狂乱のエコーです。全員がすべてを分割。モノリスは肥大で腐りました。OCPも同じ罠——時期尚早な抽象化で納品遅れです。
変動の予測は単なる過剰設計か?
その通り、しばしば。ドメインは変わります。昨日はSwiftUIの人気者? 明日にはVisionOSです。幽霊のために構築すればサイクル無駄です。本物のOCP:現在の揺らぎを見つけます。ユーザーがフォーマットに文句? 今すぐプロトコル化。ログに決済の変動? 安定化せよ。
レポートを例に。悪い:一枚岩のReportGenerator。PDF、CSV、HTMLを詰め込み。新Excel? 解体です。
良い:
protocol ReportFormatter {
func format(data: [ReportData]) -> Data
}
class PDFFormatter: ReportFormatter { ... }
// etc.
Generatorはformatterを受け取る。クライアントは無知。変動を檻に入れます。
スキートの名言:
The goal is to design the boundary between them so that when the first part changes, the second part does not need to change every time as well.
境界です。編集禁止じゃない。コードは進化します。それを否定? 妄想です。
Swiftはここで輝きます。拡張。プロトコル指向プログラミング。Appleの贈り物、乱用しなければ。にもかかわらずフォーラムは溢れます:「OCP破壊、クラス修正した!」 いいえ、バカ。抽象化をスキップしたのです。
私の大胆予測? 5年後、教科書は「open-closed」を捨てます。Protected Variationsが勝ちます。スキートが予言した通り。Swiftのactor isolationのようなツールがすでに境界を強制します。AIコード生成? これを焼き込まなければゴミを吐きます。
Swift実装:こうせよ、ああするな
本音トーク。ShapeDrawerアプリ。円、四角。素朴に:
class Canvas {
func draw(shape: String) {
if shape == "circle" { /* draw */ }
else if shape == "square" { /* draw */ }
}
}
三角? Canvas書き直し。クライアント(UI層)が連鎖。
OCP修正:
protocol Drawable {
func draw(on: Canvas)
}
class Circle: Drawable { func draw(on canvas: Canvas) { ... } }
class Canvas {
func render(_ drawable: Drawable) {
drawable.draw(on: self)
}
}
三角追加。Canvasはあくび。クライアント無傷。
スケールアップ。依存注入。ファクトリ。Swiftの@MainActor、async/await——すべて境界の味方です。無視? アプリは崩壊寸前です。
企業風? アンクル・ボブのファンが熱狂的に布教。「変更を予測せよ!」 いいえ。反応せよ。変更軸を安定化。不安減。速度向上。
一文妙案:ツールは進化します。人間はしません。
歴史講座:メイヤーの1988年のEiffelがこれを推進。ウェブ以前です。今? Git、CI/CDが修正を朝食にします。OCPは剛性じゃなく回復力です。
予測:OCPを誤用すればSwiftアプリが膨張します。エンタープライズ標準の20%抽象化肥大。理解を正せば脂肪を削れます。
🧬 Related Insights
- Read more: Why React’s map() Turns Arrays into Magic – Ditch For Loops Forever
- Read more: ClassPilot v2.0.3: Liquid Glass Glow-Up and AI Smarts for Stressed Students
Frequently Asked Questions
What is the Open-Closed Principle OCP really?
安定したインターフェースでクライアントを内部変更から守ること。すべての修正を禁じるものじゃない。
How to implement OCP in Swift?
変動点にプロトコルを使い、依存を注入。拡張はextensionで。
Does OCP mean no code changes ever?
いいえ。爆発半径を抑えるだけです。