Software Develop/개발이론

SOLID원칙 - OCP (Open Closed Principle)

jaywapp 2023. 1. 16. 11:23

OCP(Open Closed Principle)이란? 

객체는 확장에 대해 열려있어야 하고 수정에 대해서는 닫혀 있어야 한다.

 

위의 말처럼 소프트웨어는 기존 코드의 수정없이 새로운 기능이 추가될 수 있도록 설계되어야 한다. 다시 말해서 이미 개발된 클래스를 다른 클래스나 모듈에서 사용하고 있을 때, 기능 추가의 작업이 수행된다면 사용하는 부분에서의 코드 수정은 없어야 한다라는 말이다.

예시

아래의 예시를 살펴보자. MoviePlayer라는 객체가 있다고 하자. MoviePlayer는 "IronMan"이라는 영화를 입력받아서 재생시키는 기능을 구현하고 있다.

public class MoviePlayer
{
	public void Play(IronMan ironMan)
	{
		ironMan.Play();
	}
}

public class IronMan
{
	public void Play()
	{
		Console.write("I'm Iron man.");
	}
}

 

위와 같은 상황에서 "Thro" 새로운 영화가 추가된다고 하자. 먼저 단순하게 추가해보자.

public class MoviePlayer
{
	public void Play(IronMan ironMan)
	{
		ironMan.Play();
	}

	public void Play(Thor thor)
	{
		thor.Play();
	}
}

public class IronMan
{
	public void Play()
	{
		Console.write("I'm Iron man.");
	}
}

public class Thor
{
	public void Play()
	{
		Console.write("I'm Thor.");
	}
}

 

아, 물론 위와 같이 구현하더라도 목표했던 동작이 수행되는 것에는 문제가 없다. 하지만 OCP 원칙을 따르고 있지 않기 때문에 추후에 또 다른 영화가 추가될 때마다 MoviePlayer 객체는 함수를 추가해줘야 한다. OCP 원칙의 수정에 대해선 닫혀있어야 한다에 어긋난다. 그렇다면 어떻게 구현해야 OCP 원칙을 지킬 수 있을까? IronMan이든 Thor든 모두 Play라는 메서드를 가지고 있다. 이를 추상화해보도록 하자. 

public abstract class Movie
{
	public abstract void Play();
}


public class IronMan : Movie
{
	public override void Play()
	{
		Console.write("I'm Iron man.");
	}
}

public class Thor : Movie
{
	public override void Play()
	{
		Console.write("I'm Thor.");
	}
}

 

추상화 작업을 거치면 위처럼 Movie라는 추상클래스를 IronMan, Thor가 상속받아 구현되었다. 그렇다면 MoviePlayer가 Movie 객체를 사용할 수 있도록 변경해보자.

 

public class MoviePlayer
{
	public void Play(Movie movie)
	{
		movie.Play();
	}
}

 

위와 같이 MoviePlayer가 변경이 되었다. 이러한 구조를 구축한 뒤에 "SpiderMan"이라는 영화가 추가된다고 하면 어떤 식의 코드가 추가가 되는지 살펴보자.

public class MoviePlayer
{
	public void Play(Movie movie)
	{
		movie.Play();
	}
}


public abstract class Movie
{
	public abstract void Play();
}


public class IronMan : Movie
{
	public override void Play()
	{
		Console.write("I'm Iron man.");
	}
}

public class Thor : Movie
{
	public override void Play()
	{
		Console.write("I'm Thor.");
	}
}

public class SpiderMan : Movie
{
	public override void Play()
	{
		Console.write("I'm SpiderMan.");
	}
}

 

추상화 작업 이전에는 Thor가 추가됨에 따라 MoviePlayer 객체가 변경 및 추가되었었다. 하지만 추상화 이후에는 SpiderMan이라는 객체가 추가되었음에도 불구하고 MoviePlayer 객체의 변경 작업은 없다. 이렇게 OCP 원칙을 지키며 개발을 진행하면 기능 추가가 단순해지며 기존 기능에 영향을 끼치지 않을 수 있다.

 

소감

OCP는 너무도 당연한 소리처럼 들리지만 개발할 때 신경쓰지 않으면 이 원칙이 잘 지켜지지 않을 수도 있다. 특히 여러 개발자가 함께 작업하는 프로젝트라면 소통이 부족할 때 꼬이고 무너지기 쉽다. 한 번 원칙이 무너지면 프로그램은 점점 더 구조를 잃어갈 것이다. 때로는 너무 당연한 원칙이 프로젝트의 존폐 자체를 결정할 수도 있음을 명심하며 개발해야겠다.