객체 설계에 필요한 5가지 원칙으로써 유지보수가 쉽고, 유연하고, 확장이 쉬운 소프트웨어를 만들기 위한 수단
- S (Single Responsibility Principle) : 단일 책임 원칙
- O (Open/Close Principle) : 개방/폐쇄 원칙
- L (Liscov Substitution Principle) : 리스코브 치환 원칙
- I (Interface Segregation Principle) : 인터페이스 분리 원칙
- D (Dependency Inversion Principle) : 의존성 역전 원칙
- 이 다섯가지 원칙을 적용한다면
- 쉽게 변경이 가능한 유연한 코드를 가지게 된다. 이것은 재사용과 유지 보수가 쉬워지게 해준다.
- 그렇게 개발된 소프트웨어는 안정되고, 탄탄하며 확장성이 뛰어날 것. (쉽게 새로운 기능을 추가할 수 있다.)
- 디자인 패턴의 사용과 함께, 응집력이 높고 결합도가 낮은 소프트웨어를 만들 수 있다.
- 클래스는 단 하나의 이유로만 변경 가능해야한다.
- 클래스는 한가지의 책임만 가지고 있어야한다.
- 책임이란?
- 객체에 의해 정의되는 응집도 있는 행위의 집합
- 객체가 '무엇을 알고 있는가'와 '무엇을 할 수 있는가'
- 하는 것
- 인스턴스를 생성하거나 계산을 수행하는 등 스스로 하는 것
- 다른 인스턴스의 행동을 유발하는 것
- 다른 인스턴스의 활동을 제어하고 조절하는 것
- 아는 것
- 사적인 정보에 관해 아는 것
- 자신이 유도하거나 계산할 수 있는 것에 관해 아는 것
- 메서드의 들여쓰기는 1번만
- 메서드 15줄, 타입 100줄 이내로 작성
- 확장에는 열려있으나, 변경에는 닫혀 있어야 한다. ( 기능 케이스를 추가할 때 기존 코드를 변경하지 않고 확장해야 한다. )
- 객체가 변경될 때는 해당 객체만 바꿔도 동작이 잘되면 OCP를 잘 지킨 것이고, 바꿔야할 것이 많으면 OCP를 못지킨것.
- 모듈이 주변환경에 지나치게 의존해서는 안된다.
- if/switch문 최대한 사용하지 않으려고 노력하기
- 서브타입은 기본 타입으로 대체 가능해야 한다.
- 자식 클래스는 부모 클래스 동작을 바꾸지 않는다.
- 상속을 사용했을 때 서브클래스는 자신의 슈퍼클래스 대신 사용되도 같은 동작을 해야한다.
- 클래스 내에서 사용하지 않는 인터페이스는 구현하지 말아야 한다.
- 클라이언트 객체는 사용하지 않는 메소드에 의존하면 안된다.
- 인터페이스가 거대해지는 경우 SRP를 어기는 경우가 생길 수 있고, 해당 인터페이스를 채택해서 사용하는 경우 쓰지 않는 메소드가 있어도 넣어야 하는 경우가 발생할 수 있어 최대한 인터페이스를 분리하는 것을 권장함.
- 일반적인 인터페이스를 가지는 것보다 구체적인 각각의 다른 인터페이스를 가지는 것이 나음
- 상위레벨 모듈은 하위레벨 모듈에 의존하면 안된다.
- 두 모듈은 추상화된 인터페이스(프로토콜)에 의존해야한다.
- 추상타입은 구체타입에 의존하지 않게 된다. 구체타입이 추상타입에 의존하게 된다.
- 하위레벨 모듈이 상위레벨 모듈을 참조하는 것은 되지만, 상위레벨 모듈이 하위레벨 모듈을 참조하는 것은 안하는게 좋다. 그런 경우는 제네릭이나 Associate를 사용
- 모듈간의 의존성을 낮추고 클래스간의 결합도를 낮추도록 한다.
- 벌써부터 완전히 이해하려고 하지말자.
- 개념만 파악하고, 계속해서 의식하면서 개발하자.
- 각 원칙을 지키기 위한 안전장치를 계속해서 생각하자.
- 개발자 노수진님의 말에 따르면, SOLID 원칙을 모두 잘 지키려고 하는것은 불가능하다.
- 적절한 트레이드 오프를 할 수 있는 능력 또한 키우자.
- 모든 패턴의 시작인 SRP 원칙 하나만이라도 잘 지키려고 노력해보자.
예제 코드: OOP-Principles-In-Swift