가치와 원칙
가치는 원칙보다 높은 수준의 개념
원칙은 가치를 지키기위해서 존재해야한다.
가치를 최우선적으로 생각하며 원칙을 지켜보자
유연성 vs 단순성
소프트웨어 세상에서 비용이란
Time == 비용
위에 언급한 가치를 지키면서 소요되는 비용 시간을 최소화할 수 있다.
모든 문제를 해결하는 절대적인 최고의 선택은 존재하지 않는다.
단지 현재 상황에서 최선의 선택을 하기위해서 우리는 기준을 세우고 코드를 작성해야 한다.
단일 책임 원칙
예: View 컨트롤러는 View를 컨트롤하는 책임을 가지고 있다. 이 외의 책임을 지게 된다면 SRP원칙을 거스르게 된다.
책임은 변경의 이유다.
높은 응집도(낮은 결합도) vs 낮은 응집도(높은 결합도)
여러 객체를 책임질 때 문제:
여러 게임의 스코어를 계산하는 구기 종목 스코어 계산기:
야구게임의 스코어 변경이 농구게임에 영향을 줄 수 있다.
어떠한 객체가 책임을 많이 갖는다고 할 수 있는가?
아래 예를 보자.
여러 직업들이 job클래스에게 많이 의지하고 있고 job 클래스는 결과적으로 과도한 책임감을 갖게 된다.
이를 해소하기 위해 아래 사진과 같이 책임을 분리 시킬 수 있다.
Interface라는 통로를 통해 각각 다른 직업은 job class와 소통을 하게 수정하였고 이 과정을 통해 job class의 책임감은 줄어들게 되었다.
이렇게 기능이 어떻게 작동하는지 테스트해야 하는 것들을 각각의 로직에 맞게 쪼게서 다른 객체에게 넘겨주면 하나의 객체가 너무 많은 책임을 지는 것을 피할 수 있다.
개방-폐쇄 원칙
예 Enum과 Protocol의 수정:
열거형은 타입을 추가하면 다른 변경사항이 많아지는데 Protocol은 타입을 추가할 때 변경사항이 비교적 적다.
반대로 열거형에 메서드 또는 행동을 추가할 경우 열거형에서 수정할 사항이 비교적 적다.
따라서 우리는 객체를 생성할 때 목적성을 가지고 생성해야한다.
리스코프 치환 원칙
자식클래스는 부모 클래스로써의 역할을 완벽히 할 수 있어야 한다.
잘못된 상속은 엄청 큰 문제를 이르킬 수 있기에 조심히 사용해야 한다.
현실과 개발에서의 추상화 방법
오리너구리 예시:
의존성 역전 원칙
예 UITextField는 CustomViewController에 의존해서는 안된다.
하지만 CustomViewController는 UItextField와 통신해야 한다 하는 것이 많다.
따라서 존재하는 UItext delegate라는 통로를 사용하여 위에 언급한 두 객체가 의존성 역전 원칙을 지키면서 통신할 수 있게 된다.
다른예시: 컴퓨터가 여러가지 마우스에 의존하게 되면 안된다. 마우스는 언제나 변할 수 있기 때문이다. 그래서 우리는 USB 포트라는 표준이 있다. 컴퓨터는 직접적으로 마우스와 같은 구체적인 것에 의존하지 않고 USB포트를 통해서 유연하게 여러 마우스와 연결 분리가 가능해진다. 마우스에 의존하지 않는다.
인터페이스 분리 법칙
클라이언트가 불필요한 자신이 사용하지 않는 인터페이스에 의존하지 말아야 한다.
왜냐하면...
상속받은 메서드를 퇴화시켜야 하는 경우가 발생할 수 있다.
불필요한 인터페이스에 의존하면 불필요한 빌드가 유발될 수 있다.
큰 인터페이스를 작은 인터페이스들로 분리하고, 필요한 부분만 클라이언트가 취사선택하여 사용할 수 있게 해야 한다.
*클라이언트: 사용하는 유저
달팽이 클래스가 움직일 수 있는이라는 프로토콜을 채택했는데 프로토콜의 메서드 중 하나가 점프하기이면...나중에 앱에 들어가면 달팽이에게 점프하는 버튼은 있지만 점프하는 기능을 하지 못한다. 이는 불필요한 인터페이스가 제공된 예시이다.
솔리드에 집착하다보면 목적성을 잃을 수 있다. 지켜야 하긴 하지만 너무 매몰되면 안된다.
프로젝트를 진행하는 동안 이 원칙을 모두 다 지키는 것은 매우 힘들다. 경우에 따라 무시해야 할 때도 있다. 그렇기에 이를 무조건적으로 지켜야 한다는 생각은 버리면 좋겠다.