반응형
반응형

SOLID 원칙

#객체지향프로그래밍

객체지향 5대 원칙(SOLID)

  1. SRP(단일 책임 원칙)
  2. OCP(개방-폐쇄 원칙)
  3. LSP(리스코프 치환 원칙)
  4. DIP(의존 역전 원칙)
  5. 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는 다음과 같은 내용을 담고 있다.
    1. 상위 모듈은 하위 모듈에 의존해서는 안된다. 상위 모듈과 하위 모듈 모두 추상화에 의존해야 한다.
    2. 추상화는 세부 사항에 의존해서는 안된다. 세부사항이 추상화에 의존해야 한다.
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()

기존에 만들었던 스타벅스와 투썸을 의존성 주입을 통하여 타입만 변경해줌으로써 다른 코드들은 유지한 채 가게를 수정 할 수 있게 된다.

반응형

+ Recent posts