컴포넌트는 배포 단위다. 컴포넌트는 시스템의 구성 요소로 배포할 수 있는 가장 작은 단위다.
런타임에 플러그인 형태로 결합할 수 있는 동적 링크 파일이 여기에서 말하는 소프트웨어 컴포넌트를 뜻한다.
여기에서는 응집도와 관련된 세 가지 원칙을 논의한다.
재사용 단위는 릴리스 단위와 같다.
새로운 릴리스가 나온다는 소식을 접하면 개발자는 새 릴리스의 변경 사항을 살펴보고 기존 버전을 계속 쓸지 여부를 결정하곤 한다. 새릴리르슬 통합할지, 한다면 언제 할지 등등도 포함.
이 원칙을 소프트웨어 설계, 아키텍천 관점에서 보면 단일 컴포넌트는 응집성 높은 클래스와 모듈들로 구성되어야 함을 뜻한다.
하나의 컴포넌트로 묶인 클래스와 모듈은 반드시 함께 릴리스할 수 있어야 한다.
동일한 이유로 동일한 시점에 변경되는 클래스를 같은 컴포넌트로 묶어라. 서로 다른 시점에 다른 이유로 변경되는 클래스는 다른 컴포넌트로 분리하라.
컴포넌트 단위의 SRP라고 보면 된다.
최대한 변경을 줄이고자 하는 취지에서 나온 원칙, 변경이 일어난다면, 단일 컴포넌트에서 발생하는 것이 제일 낫다.
OCP 원칙과도 매우 밀접하게 관련되어 있다.
대다수의 애플리케이션에서 유지보수성은 재사용성보다 훨씬 더 중요하다
컴포넌트 사용자들을 필요하지 않는 것에 의존하게 강요하지 말라
ISP의 포괄적인 느낌. 필요 없는 클래스를 의존하지 말라.
만약, 어떤 컴포넌트를 의존하는데 해당 컴포넌트에 클래스 하나만 의존한다고 해도 의존성은 조금도 약해지지 않는다. 해당 컴포넌트에서 사용되지 않는 부분이 변경되어도, 재컴파일, 재검증, 재배포할 가능성은 여전히 남아 있기 때문이다.
이 원칙은 어떤 클래스를 하나의 컴포넌트로 묶으면 안되는지에 대한 원칙이다.
위 원칙들을 다 지킬 수는 없다. 적절한 균형을 찾아 컴포넌트를 위치해야 하고 이는 그 때의 상황에 맞게 개발자가 판단해야 하는 문제이다. 지금은 이 방법이 맞더라도 내년은 달라질 수 있다는 점도 명심해야한다.
여기서 설명한 예시로는, 프로젝트 초기에는 REP 보다는 CCP가 중요하다고 한다. 개발 가능성이 재사용성보다 중요한 시기이기 때문임
프로젝트가 점점 성장하고 성숙해지면서, 개발가능성 보다는 재사용성으로 중요도가 높아진다고 한다.
컴포넌트 의존성 그래프에 순환이 있어서는 안 된다
하루 종일 일해서 돌아가게 만든 프로젝트가 다음날 작동이 안 되는 경우가 있다. 이는 다른 누군가가 이 프로젝트가 의존하고 있던 무언가를 수정했기 때문이다. 이를 숙취 증후군(the morning after syndrome)이라고 부른다고 하심.
이 문제의 해결책은 개발 환경을 릴리스 가능한 컴포넌트 단위로 분리하는 것이다. 이렇게 한다면, 컴포넌트는 개별 개발자 또는 단일 개발팀이 책임질 수 있는 작업 단위가 된다.
깃헙의 브랜치 기능?과 비슷한 느낌을 받았다. 내가 작업하고 동작이 가능한 부분을 개발 브랜치에 병합시키고 나느 새로 추가 기능을 만드는 브랜치를 다시 파서 작업하는 것. 그러면 다른 팀원들은 개발 브랜치를 땡겨오기만 하면 작업을 진행할 수 있기 때문에 비슷하지 않나 싶다.
순환이 발생한다면 테스트, 배포시에 상당히 많이 문제가 발생한다. 이 부분을 해결하려면 순환을 끊어야 하는데, 끊는 방법으로는 DIP를 적용하거나, 순환이 발생하는 컴포넌트를 분리해서 새로운 컴포넌트를 만드는 방법이 존재한다.
이를 통해 알 수 있는 점은, 컴포넌트 구조는 프로젝트가 성장함에 따라 변경될 수 있다는 점이고, 절대 처음부터 설계가 가능한 영역이 아니라는 점이다.
안정성의 방향으로(더 안정된 쪽에) 의존하라
변경이 쉽지 않은 컴포넌트가 변동성이 높은 컴포넌트를 의존하게 만들어서는 절대로 안 된다. 한번 의존하게 되면 변동성이 큰 컴포넌트도 변경이 어려워진다.
이를 소프트웨어가 가진 괴팍함이라고 설명하심. 모듈을 만들 때는 변경하기 쉽도록 설계했지만, 이 모듈에 의존성을 매달아 버리면 결국 이 모듈도 변경하기 어려워 지는 것.
안정성은 변화하는 빈도와는 관계가 없고, 쉽게 변하냐 어렵게 변하냐로 정도를 나눈다. 동전의 옆면과 탁자를 생각하면 될 듯 하다.
컴포넌트를 변경하기 어렵게 만드는 경우 중 하나는 하나의 컴포넌트를 여러 개의 컴포넌트가 의존하고 있는 경우이다.
만약 세 개의 컴포넌트가 하나의 컴포넌트(x)를 의존한다면, x는 변경하면 안 되는 이유가 3가지나 되는 것이다.
이 경우에 X는 세 컴포넌트를 책임진다(Responsible)이라 말한다. 반대로 X는 의존하지 않고 있으므로, X가 변경되도록 만들 수 있는 외부요인이 전혀 없다. 이 때 X는 독립적(Independent)라고 말한다.
우리가 기대하는 컴포넌트 구조는 전부 다 안정적인 컴포넌트만 존재하는 것은 아니다. 그렇게 된다면 변경되지 않기 때문이다. 요구사항에 따라 언제나 구조는 바뀔 수 있다. 따라서 적절한 구조는 불안정한 컴포넌트와 안정적인 컴포넌트가 같이 존재하는 구조가 바람직한 구조라고 볼 수 있다.
인터페이스만을 포함하고 구현체가 없는 컴포넌트가 익숙하지 않을 수 있지만, 정적 타입 언어에서는 자주 쓰는 컴포넌트이고 반드시 사용해야 한다.
추상 컴포넌트는 상당히 안정적이다. 따라서 덜 안정적인 컴포넌트가 의존할 수 있는 이상적인 컴포넌트라고 할 수 있다.
컴포넌트는 안정된 정도만큼만 추상화되어야 한다
이 원칙은 안정성과 추상화 정도사이의 관계를 정의한다.
안정된 컴포넌트는 추상 컴포넌트여야 하며, 안정성이 컴포넌트를 확장하는 일을 방해해서는 안 된다고 한다.
또 불안정한 컴포넌트는 반드시 구체 컴포넌트여야 한다고 하는데, 불안정하므로 컴포넌트 내부 구체적인 코드를 쉽게 변경할 수 있어야 하기 때문이라고 한다.
그래서 안정적인 컴포넌트는 인터페이스와 추상 크랠스로 구성되어 쉽게 확장이 가능해야 한다.
SAP와 SDP를 결합하면 컴포넌트에 대한 DIP가 된다고 한다. 하지만 DIP는 클래스에 대한 원칙이고, 앞의 두 원칙은 컴포넌트에 대한 원칙이다. 컴포넌트는 어떤 부분은 추상적이며, 다른 부분은 안정적일 수 있음을 명심해야한다.