🐸
【SOLID原則】オープン・クローズドの原則 - OCP
SOLID原則とは、ソフトウェア設計の5つの原則の頭字語を取ったものです。ソフトウェアをより理解しやすく、より柔軟に、よりメンテナナンス性の高いものにするために考案されました。
- 単一責任の原則(Single Responsibility Principle)
- オープン・クローズドの原則(Open/closed principle)
- リスコフの置換原則(Liskov substitution principle)
- インターフェース分離の原則(Interface segregation principle)
- 依存性逆転の原則(Dependency inversion principle)
今回はSOLID原則のひとつ、オープン・クローズドの原則についてです。
オープン・クローズドの原則
オープン・クローズドの原則について、書籍「アジャイルソフトウェア開発の奥義」では、このように書かれています。
ソフトウェアの構成要素(クラス、モジュール、関数など)は拡張に対しては開いて(オープン:Open)いて、修正に対して閉じて(クローズド:Closed)いなけばならない[1]
つまり、ソフトウェアの振る舞いは既存の成果物を変更せず、新たにコードを追加するだけで対応できるようにするべき、ということです。
次のコードはオープン・クローズドの原則に違反しています。このコードを実行すると動物の鳴き声を出力しますが、猫と犬以外に新たに動物を追加したいとき、AnimalSound関数に対して条件分岐を追加しなければいけません。
そのため既存の成果物(AnimalSound関数)に対して、コードを変更せざるを得ません。
class Animal {
animalName: string
constructor(name: string) {
this.animalName = name
}
}
const AnimalSound = (animal: Animal[]) => {
for (let i = 0; i < animal.length; i++) {
if (animal[i].animalName === 'cat') console.log('meow')
if (animal[i].animalName === 'dog') console.log('bowwow')
}
}
const animals: Animal[] = [new Animal('cat'), new Animal('dog')]
AnimalSound(animals) // meow bowwow
それでは、オープン・クローズドの原則に従うには、どのようにすべきでしょうか。
それは、各動物に対するクラスを作成し、インターフェースを実装します。新しい動物を追加するときは、新しいクラスを作成するだけになり、既存のAnimalSound関数に手を入れなくて良くなります。
interface IAnimal {
makeSound(): string
}
class Cat implements IAnimal {
makeSound = () => 'meow'
}
class Dog implements IAnimal {
makeSound = () => 'bowwow'
}
const AnimalSound = (animals: IAnimal[]) => {
for (let i = 0; i < animals.length; i++) {
console.log(animals[i].makeSound())
}
}
const animals = [new Cat(), new Dog()]
AnimalSound(animals)
これでオープン・クローズドの原則に従うことが出来ました。既存の処理に手を入れないで仕様変更が出来るため、保守性や柔軟性といったメリットを享受出来ました。
-
Robert C. Martin. アジャイルソフトウェア開発の奥義 ↩︎
Discussion