【SOLID原則】新人エンジニアが教える「オープン・クローズドの原則(OCP)」

設計パターン

こんにちは。新人プログラマーの岩本です。

今回はSOLID原則の1つ「オープン・クローズドの原則(Open-Closed Principle」について、自分なりに調べたことをまとめます。

ソースコードというのは常に変化し続けます。もしコードが変更に弱ければ、バグを生んでしまうことにつながります。

そこでオープン・クローズドの原則が身に付いていれば、変更に強く機能を追加しやすいコードを書くことができます。

ぜひ最後までご覧ください。

この記事は新卒エンジニアが執筆しています。
そのため内容に間違いや不備がある場合があります。
もし間違いを発見しましたら、どんどん指摘していただけると幸いです。

実装環境

  • 言語…Swift 5.8.1
  • OS… macOS Ventura 13.1
  • アプリ… Xcode 14.3.1

オープン・クローズドの原則(OCP)とは

オープン・クローズドの原則(以下、OCP)とは、1988年にBertrand Meyerが提唱した以下のような原則です。

ソフトウェアの構成要素は拡張に対して開いていて、修正に対して閉じていなければならない

『アジャイルソフトウェア開発の奥義 第2版』より引用

簡単にいうと、「既存コードを変更することなく、機能を拡張できるようにすべき👍みたいな考え方です。

コードを変更することなく機能を追加できるので、新機能の実装が容易になります。
逆に新機能を追加するときに既存コードを変更すると、うまく動かなくなる可能性が出てしまいます。

OCPを実現するには

OCPを実現する方法はいくつかありますが、一番簡単なのはインターフェースを使用することです。

例えばViewModelがテスト用のAPIを使って通信する例を考えてみます。

一見問題ないように見えますが、もし本番用のAPIに切り替えたい!となったときに、ViewModelのコードまで変更する必要があります。

これはOCPに反しています。
解決するには間にインターフェースを挟みます。

こうすることによってViewModelのコードを変更することなく、本番用のAPIに切り替えることができるようになります。

ではここからは具体的なコードを用いて、OCPを説明します。

OCPに反したコード

先ほどの図をコードで表現していきます。

まずはOCPに反したコードです。

// テスト用のAPI
class TestAPI {
    func fetchData() {
        print("This is Test API")
    }
}

class ViewModel {
    let api: TestAPI
    
    init(api: TestAPI) {
        self.api = api
    }
    
    func fetchData() {
        api.fetchData()
    }
}

let viewModel = ViewModel(api: TestAPI())

ここで本番用のAPIに切り替えたい!となったとします。

切り替えるためにはViewModelのコードを変更しなければなりません。

// 本番用のAPI
class ProdAPI {
    func fetchData() {
        print("This is Prod API")
    }
}

class ViewModel {
    let api: ProdAPI // ProdAPIに変更する必要がある
    
    init(api: ProdAPI) {
        self.api = api
    }
    
    func fetchData() {
        api.fetchData()
    }
}

let viewModel = ViewModel(api: ProdAPI())

APIを切り替える際にいちいち型を変更するのは面倒ですよね🤔。

OCPに即したコード

ではここからは先ほどのコードを、OCPに適応するように書き直していきます。

まずViewModelとAPIを繋ぐ、インターフェースを定義します。

protocol APIProtocol {
    func fetchData()
}

ViewModelのapiをAPIProtocol型として定義することで、テスト用と本番用を切り替える際に、変更を無くすことができます。

class TestAPI: APIProtocol {
    func fetchData() {
        print("This is Test API")
    }
}

class ProdAPI: APIProtocol {
    func fetchData() {
        print("This is Prod API")
    }
}

class ViewModel {
    let api: APIProtocol // 切り替えの際に変更する必要がない
    
    init(api: APIProtocol) {
        self.api = api
    }
    
    func fetchData() {
        api.fetchData()
    }
}

let viewModel = ViewModel(api: ProdAPI())

これでOCPに即したコードに書き直すことができました。
やってることはとてもシンプルですね😄。

まとめ

今回はSOLID原則の1つ「オープン・クローズドの原則(OCP)」を紹介しました。

OCPとは「既存コードを変更することなく、機能を拡張できるようにすべき」という考え方でした。

やってることはとてもシンプルですが、とても重要な概念です。

ぜひご自身の手で色々と試してみてください。

ここまでのご閲覧ありがとうございました!

参考資料

コメント

タイトルとURLをコピーしました