SOLID 원칙
#객체지향프로그래밍
객체지향 5대 원칙(SOLID)
- SRP(단일 책임 원칙)
- OCP(개방-폐쇄 원칙)
- LSP(리스코프 치환 원칙)
- DIP(의존 역전 원칙)
- ISP(인터페이스 분리 원칙)
앞 자를 따서 SOLID 원칙 이라고 부른다.
Single Responsiblity Principle (단일 책임 원칙)
한 클래스는 하나의 책임만 가져야 한다.
- 새로운 요구사항과 변경에 잘 대응하기 위해서는 응집도는 높고 결합도는 낮게 구현하여야 한다.
- 하나의 클래스에서 많은 기능이 있다면 클래스 내부의 함수끼리 강한 결합을 발생할 가능성이 높아진다.
Open-Closed Principle (개방-패쇄 원칙)
소프트웨어 요소는 확장에는 열려 있으나 변경에는 닫혀 있어야 한다.
- 변경되는 것이 무엇인지*에 초점을 맞춘다.
- 문장만 보기엔 잘 이해가 되지 않으니 아래 코드를 보자.
class Cafe {
func order() {
print(“스타벅스 아메리카노”)
}
}
let cafe = Cafe()
cafe.order()
기본적으로 스타벅스의 아메리카노를 주문한다. 만약 스타벅스의 아메리카노가 아닌 투썸플레이스의 아메리카노를 주문하도록 요구사항이 변경 되었다면 Cafe의 order 메소드를 수정해야 한다. 이러한 소스코드 변경은 OCP 원칙에 위배된다.
protocol Cafe {
func play()
}
class Starbucks: Cafe {
func order() {
print(“스타벅스 아메리카노”)
}
}
class TwoSomePlace: Cafe {
func order() {
print(“투썸플레이스의 아메리카노”)
}
}
위 코드 처럼 해당 클래스가 주문을 한다는 역할이 분명하게 정해져 있다. 이럴 때 추상화를 사용하여 OCP원칙을 지킬 수 있다. 각 클래스들은 고정된 Protocol에 의존하기 때문에 수정에 대하여 닫혀있고 해당 Protocol을 구현하기만 하면 확장에 대해여 열려 있게 된다.
LSP(Liskov substitution principle)
- 프로그램의 겍체는 정확성을 깨뜨리지 않으면서 하위 타입의 인스턴스로 바꿀 수 있어야 한다.
- 상위 클래스 자리에 하위 클래스가 치환되어도 아무 문제 없어야 한다.
가장 대표적인 예로 정사각형과 직사각형이 있다. 정사각형은 직사각형이 될 수 있지만 직사각형은 정사각형이라고 할 수 없다. 만약 직사각형이 상위 클래스라면 LSP를 위반하게 된다.
ISP(Interface Segregation Principle)
- 하나의 큰 인터페이스보다 특정 케이스를 위한 여러개의 인터페이스를 사용해야 한다.
- 큰 덩어리의 인터페이스들을 구체적이고 작은 단위들로 분리시킴으로써 해당 인터페이스를 채택할 때 꼭 필요한 메서드만 이용할 수 있게 해야한다.
- 해당 원칙을 준수하게 되면 내부 의존성이 약해져 리팩토링을 쉽게 할 수 있다.
DIP(Dependency Inversion Principle)
- 소프트웨어 모듈들을 분리하는 특정 형식
- 구체화보다 추상화에 의존해야 한다.
- 의존성 주입은 이 원칙을 따르는 방법 중 하나이다.
- DIP는 다음과 같은 내용을 담고 있다.
- 상위 모듈은 하위 모듈에 의존해서는 안된다. 상위 모듈과 하위 모듈 모두 추상화에 의존해야 한다.
- 추상화는 세부 사항에 의존해서는 안된다. 세부사항이 추상화에 의존해야 한다.
Class CafeStore {
private let cafe: Cafe
init(cafe: Cafe) {
self.cafe = cafe
}
func order() {
cafe.order()
}
}
let starbucksStore = CafeStore(cafe: Starbucks())
let twosomeplaceStore = CafeStore(cafe: TwosomePlace())
starbucsStore.oredr()
twosomeplaceStore.order()
기존에 만들었던 스타벅스와 투썸을 의존성 주입을 통하여 타입만 변경해줌으로써 다른 코드들은 유지한 채 가게를 수정 할 수 있게 된다.
반응형