WHAT ?
SOLID 원칙이란?
컴퓨터 프로그래밍에서 SOLID란 로버트 마틴이 2000년대 초반에 명명한 객체 지향 프로그래밍 및 설계의 다섯 가지 기본 원칙을 마이클 페더스가 두문자어 기억술로 소개한 것이다. 프로그래머가 시간이 지나도 유지 보수와 확장이 쉬운 시스템을 만들고자 할 때 이 원칙들을 함께 적용할 수 있다. SOLID 원칙들은 소프트웨어 작업에서 프로그래머가 소스 코드가 읽기 쉽고 확장하기 쉽게 될 때까지 소프트웨어 소스 코드를 리팩터링하여 코드 냄새를 제거하기 위해 적용할 수 있는 지침이다. 이 원칙들은 애자일 소프트웨어 개발과 적응적 소프트웨어 개발의 전반적 전략의 일부다.
- 위키백과 -
- 3줄이상부터는 코르티솔 분비를 촉진시키기 때문에 간단히 말해,
- 로버트 마틴이 제시한 객체지향 프로그래밍의 설계 5가지 원칙이다.
- SRP(Single Responsibility Principle) - 단일 책임 원칙
- OCP(Open/Closed Principle ) - 개방/폐쇄 원칙
- LSP(Liskov Substitution Principle) - 리스코프 치환 원칙
- ISP(Interface Segregation Principle) - 인터페이스 분리 원칙
- DIP(Dependeny Inversion Principle) - 의존관계 역전 원칙
- 5가지 원칙의 앞 글자를 모아 'SOLID 원칙'이라 명명한다.
- 유지보수와 확장이 쉬운 프로그램을 만들기 위해서는 해당 원칙을 지향하는 것이 좋다.
- 하나씩 살펴보도록 하자.
SRP(Single Responsibility Principle)
단일 책임 원칙
- 모든 클래스는 하나의 책임만을 가지며, 클래스는 그 책임을 완전히 캡슐화해야 한다.
- 각 클래스는 하나의 역할과 책임을 갖는다.
- 쉽게 말해, 되도록 한 가지 일만 하라는 뜻이다.
- 책임이 1개라고, 메서드가 1개인 것은 아니다.
- '하나의 메서드는 하나의 일만 해야한다' 원칙과 혼용하지 말자.
- 한 클래스가 수행할 수 있는 책임이 많아진다면, 이것은 결합에 기인해, 하나의 책임에 변경사항이 생겼을 때, 다른 책임까지 수정이 필요하게 된다.
단일 책임?
- 단일 책임이란 말이 모호할 수 있다. 우리는 책임을 묶어서 생각하는 데 익숙해져 있기 때문이다.
- 단일 책임은 절대적이 아닌, 상대적 개념이기 때문에, 추상화의 수준에 따라 다르다.
- SOLID 원칙의 창시자인 로버트 마틴은 단일 책임 원칙에 대해 '같이 수정해야될 것들은 묶고, 따로 수정해야될 것들은 분리하는 것'으로 기준을 두었다.
- 단일 책임 원칙은 '클래스(모듈)을 변경되는 이유는 단 한가지여야 한다'라는 의미로 수용하자.
더보기
로버트 마틴은 가장 의미가 전달되지 못한 SOLID 원칙으로 단일 책임의 원칙(SRP, Single Responsibility Principle)을 뽑았다. SRP를 '하나의 모듈이 하나의 책임을 가져야 한다'는 애매한 해석이 아닌 '모듈이 변경되는 이유가 한가지여야 함'으로 받아들여야 한다.
OCP(Open/Closed Principle)
개방/폐쇄 원칙
- 확장은 개방하고, 수정은 폐쇄하라.
- 기존 구성요소는 수정이 일어나지 말아야 하며, 쉽게 확장이 가능하여 재사용할 수 있어야 한다.
- TicoCar와 의존관계에 있는 Driver클래스이다.
- 수동기어 조작을 오토기어 조작으로
- 자동차 움직이는 방법
- 창문 여는 조작
- 운전자가 Tico -> Benz로 차를 바꾸기 위해, BenzCar 클래스를 추가하니, Driver 내에 많은 수정사항이 생긴다.
- 이처럼, 추상화 및 상속 등을 이용해 기존코드는 변경 없이(closed), 새롭게 확장 및 수정(open)할 수 있어야 한다.
LSP(Liskov Substitution Principle)
리스코프 치환 원칙
- Class S가 T의 자식클래스라면 S를 쓰는 곳에 T를 넣어도 작동하도록 만들어라. 그 반대도 작동한다.
- 부모클래스인 크리쳐를 받아서 cry시키는 함수에 자식클래스를 넣어도 작동한다.
- 즉, 상속관계가 명확하다면 치환해도 동일하게 작동한다.
- 부모 클래스 자리에 자식 클래스 넣어도 작동은 하지만, 동일한 작동을 하지 않는다.
- 즉, 예측한 값이 나오지 않는다.
- 함수를 변경했지만 이번엔 개방/폐쇄 원칙을 위반한다.
- Square를 수정시 함수 또한 수정해야 한다.
- 결국, 리스코프 치환 원칙을 위반 시, 개방/폐쇄 원칙 또한 위반한다.
- 직사각형 Is-not 정사각형/ 정사각형 is-a 직사각형
- 직사각형과 정사각형의 관계는 has-A 관계이다.
- 상위 클래스 타입으로 객체를 선언하여 하위 클래스의 인스턴스를 받으면, 업캐스팅된 상태에서 부모의 메서드를 사용해도 동작이 의도대로만 흘러가도록 구성하면 되는 것이다.
- 즉, 상속 관계를 is-a 관계로 명확하는 것이 중요하다.
ISP(Interface Segregation Principle)
인터페이스 분리 원칙
- 클라이언트는 자신이 사용하지 않은 메서드에 의존하면 안된다.
- < = > 클라이언트는 자신이 사용하는 메서드에만 의존해야 한다.
- 큰 덩어리의 인터페이스를 구체적이고 명확한 단위로 나누어야한다는 원칙
- 독수리는 Bird가 맞다.
- 그래서 Bird의 기능을 구현하고 있다.
- 두가지 메서드가 모두 필요하며,
Bird(새)이기에 날고 우는 것이 틀린 게 아니지만,
- 그러나 팽귄과 같이 날 수 없는 새도 존재한다.
- 이때는, fly라는 사용하지 않는 메서드를 의존하게 된다.
- 날 수 있는 새를 인터페이스로 분리, 정의하여 팽귄이 사용하지 않는 메서드를 가지지 않게 했다.
- 클래스는 자신이 사용하지 않는 인터페이스는 구현하지 않아야 한다.
- 사용하지 않는 인터페이스가 수정되더라도, 영향을 받지 않도록 만들어야 한다.
- 차라리 인터페이스 여러개가 낫다!
DIP(Dependeny Inversion Principle)
의존 역전의 원칙
- 고수준 모듈은 저수준 모듈의 구현에 의존해서는 안 된다.
- 저수준 모듈이 고수준 모듈에서 정의한 추상 타입에 의존해야 한다.
- 추상화는 세부 사항에 의존해서는 안된다.
- 세부사항이 추상화에 의존해야 한다.
- 고수준 모듈인 Student 객체가 Paper라는 객체를 의존하고 있다.
- 강의자료(lectureData)라는 특성상 Paper, iPad, GalaxyTab 등 모두 가능하기에 변하기 쉽다.
- 의존 관계를 맺을 때, 변화하기 쉬운 것 혹은 자주 변화하는 것보다는 변화하기 어려운 것, 거의 변화가 없는 것에 의존해야 한다.
- 한마디로 구체적인 클래스보단, 인터페이스나 추상 클래스에 의존해야 한다.
단일 책임 원칙(SRP), 인터페이스 분리 원칙(ISP)
- 객체가 하나의 역할을 하고, 불필요한 참조에 의존하지 않음으로 객체가 커지지 않게 한다.
- 객체가 하나의 일을 하고, 서로 다른 인터페이스를 사용함으로써 변경이 다른곳에 영향을 최소화 할 수 있어 기능 변경에 유연하게 만들 수 있다.
리스코프 치환 원칙(LSP), 의존 역전의 원칙(DIP) = > 개방/폐쇄 원칙(OCP) 지원
- 개방/폐쇄 원칙(OCP)은 변화되는 부분을 추상화하고 다형성을 이용하게 함으로 기능 확장에 있어 기존 코드를 수정하지 않도록 해준다.
- 변화되는 부분의 추상화가 의존 역전의 원칙(DIP)이며, 다형성을 이용하게 하는 것이 리스코프 치환 원칙(LSP)이다.
'TIL' 카테고리의 다른 글
[OOP] 객체 지향 생활 체조 원칙 (0) | 2023.02.21 |
---|---|
[우테코] TDD란?(Test-Driven-Development) (0) | 2023.02.15 |