“Even bad code can function. But if the code isn’t clean, it can bring a development organization to its knees.” — Robert C. Martin (Uncle Bob)
The SOLID Principles are as follows:
S – Single Responsibility principle
O – Open-Closed principle
L – Liskov Substitution principle
I – Interface Segregation principle
D – Dependency Inversion principle
- 클래스는 단 한 개의 책임을 가져야 한다.
- 클래스가 변경되는 이유는 단 한 개여야 한다
일할 때도 분업화가 중요하듯이, 책임 소재가 불분명하면 작은 오류에도 시스템 전체에 큰 영향을 줄 수 있기 때문에, 하나의 클래스의 단일 책임 원칙을 지키도록 해야한다.
위의 코드는 SRP 원칙을 위반하고 있다.
1. calculatePay()
는 회계팀이 해야하는 일이다.
2. reportHours()
는 인사 관리팀이 해야하는 일이다.
3. save()
는 데이터베이스 관리자들이 해야하는 일이다.
그래서 이 문제를 해결하기 위해서는 주체가 다른 서로 다른 코드를 나누어주면 된다.
사용자가 .js 소스 코드 파일을 열어 수동으로 조작하지 않고도 모듈의 기능을 확장하도록 허용해야한다.
위를 해석하자면 이렇다. 즉, 소프트웨어 개체는 확장성을 위해 개방적이어야하지만, 수정에 관해서는 폐쇄적이어야한다는 뜻이다. 이 개방/폐쇄 원칙은 버전이 업데이트가 될때마다 새로운 기능을 추가하기 위해서 코드를 고치는 것이 아니라 코드를 추가할 수 있어야한다는 것을 뜻한다.
자주 변경되는 내용은 수정하기 쉽게 설계 하고, 변경되지 않아야 하는 것은 수정되는 내용에 영향을 받지 않게 하는 것이 포인트다.
예를 들어 모든 피고용인이 역할을 하나씩 가지고 있고 그에 따른 특권 혹은 이점을 가지고 있다고 하자.
기존의 코드를 바꾸지 않고 우리는 어떻게 새로운 역할을 추가할 수 있을까?
위의 코드를 보면, 우리는 checkPrivilege
라는 메소드는 하나도 건드리지 않고 새로운 역할을 추가하는 메소드 addRoles
를 만들어 OCP 원칙을 지킬 수 있었음을 알 수 있다.
부모 클래스와 자식 클래스 사이의 행위에는 일관성이 있어야 한다는 원칙이며, 이는 객체 지향 프로그래밍에서 부모 클래스의 인스턴스 대신 자식 클래스의 인스터스를 사용해도 문제가 없어야 한다는 것을 의미한다.
예를 들어, 이전 글에서 class에 대한 clean code 원칙을 다룰때 상속은 반드시 is-a 관계일때 쓰는 것이 좋다고 하였다.
'클라이언트는 사용하지 않는 인터페이스에 의존하도록 강요받으면 안된다'.
클라이언트가 방대한 양의 옵션을 설정하지 않도록 하는 것이 좋다. 그리고 설정을 선택적으로 하여 무거운 인터페이스를 만드는 것을 방지할 수 있어야한다.
예를 들어, 한 클래스에 여러명의 클라이언트가 있다면, 클라이언트들이 필요한 모든 메소드를 클래스에 다 포함시키는 것이 아니라, 한명 한명의 클라이언트를 위한 특정한 인터페이스를 만들고 그것을 클래스에 선택적으로 포함시킬 수 있도록 하는 것이 좋다.
'자신보다 변하기 쉬운 것에 의존하지마라'
이 말은 즉 두가지 중요한 요소를 뜻한다
1. 상위 모듈은 하위 모듈에 종속되어서는 안된다. 둘다 추상화에 의존하여야한다.
2. 추상화는 세부사항에 의존하지 않아야한다. 세부사항은 추상화에 의해 달라져야한다.