개발/개발 공통

[객체지향 SOLID 원칙] 인터페이스 분리 원칙(ISP)의 이해와 예제

growing-dev 2023. 5. 26. 14:31
반응형

네 번째 SOLID 원칙인 인터페이스 분리 원칙에 대해서 예제를 통해 이해해 보도록 하겠습니다.

 

 

인터페이스 분리 원칙(ISP)의 이해와 예제

 

 

 

 인터페이스 분리 원칙이란

 

인터페이스를 사용할 때 가능한 적은 인터페이스를 사용해야 한다는 원칙입니다. 거대한 인터페이스를 사용한다면 해당 인터페이스에서 사용 불가능하거나 의미 없는 인터페이스까지 사용할 수 있고 의존하게 되므로 불안정한 코드가 되거나 가독성에 좋지 않습니다.

따라서 꼭 필요한 전용 인터페이스를 사용하는 것을 선호해야 합니다.

 

2023.01.14 - [개발/개발 공통] - [객체 지향] SOLID 원칙에 대해서 알아보자

 

[객체 지향] SOLID 원칙에 대해서 알아보자

객체 지향을 공부하면서 SOLID 원칙을 빼놓을 수 없다. SOLID 원칙에 대해서 공부해 본다. SOLID란 로버트 마틴이 2000년대 초반에 명명한 객체지향 프로그래밍 및 설계의 다섯 가지 기본 원칙을 마이

growing-dev101.tistory.com

 

 

 

 

 예제

 

예제는 이전 리스코프 치환 원칙에서 활용했었던 새의 경우를 들어보겠습니다.

Bird라는 클래스는 fly, swim, eat 라는 세 가지 메서드를 가진 인터페이스 클래스입니다.

이때 eagle와 penguin이 Bird를 상속받는다면, eagle는 swim을 못하고, penguin은 fly를 못하기 때문에 각 객체마다 예외적인 상황이 존재하게 되어 이해하기 어려운 코드가 될 수 있습니다.

이런 경우가 바로 인터페이스 분리 원칙을 위배했다고 볼 수 있습니다.

 

#include <iostream>
using namespace std;
class Bird
{
	virtual string fly() = 0;
	virtual string swim() = 0;
	virtual string eat() = 0;
};

class eagle : public Bird
{
	string fly() override
	{
		return "can fly";
	}
	string swim() override
	{
		return "can not swim";
	}
	string eat() override
	{
		return "can eat";
	}
};

class penguin : public Bird
{
	string fly() override
	{
		return "can not fly";
	}
	string swim() override
	{
		return "can swim";
	}
	string eat() override
	{
		return "can eat";
	}
};

 

따라서 이런 경우를 개선하기 위해서는 인터페이크 클래스인 Bird를 분리할 필요가 있습니다.

적절할지는 모르겠지만 BirdCanNotSwim 이라는 인터페이스 하나와 BirdCanNotFly라는 인터페이스로 분리합니다.

eagle의 경우 BirdCanNotSwim을 상속받고 penguin의 경우 BirdCanNotFly 라는 인터페이스를 상속받아서 각각 적절한 인터페이스만을 사용하도록 수정합니다.

 

이렇게 되면 eagle->swim() 이나 penguin->fly()와 같은 메서드가 컴파일 타임에 원칙적으로 차단되므로 안전하고 명확한 코드를 작성할 수 있게 됩니다.

 

#include <iostream>
using namespace std;


class BirdCanNotSwim
{
	virtual string fly() = 0;
	virtual string eat() = 0;
	
};

class BirdCanNotFly
{
	virtual string swim() = 0;
	virtual string eat() = 0;
};

class eagle : public BirdCanNotSwim
{
	string fly() override
	{
		return "can fly";
	}

	string eat() override
	{
		return "can eat";
	}
};

class penguin : public BirdCanNotFly
{

	string swim() override
	{
		return "can swim";
	}
	string eat() override
	{
		return "can eat";
	}
};

 

 

 

 결론

 

인터페이스 분리 원칙은 자칫 과하게 남용하면 인터페이스가 너무 세분화되거나 오히려 가독성에 안 좋아질 수 도 있을 것 같습니다. 모든 원칙이 그렇듯 정답이 있는 건 아니고 각각의 원칙을 이해하고 상황에 맞게 적절하게 활용하여 리팩토링 하는 게 중요하다고 할 수 있겠습니다.

반응형