본문 바로가기

객체 설계의 원칙『 설계가 왜 필요할까?』

by Recstasy 2019. 10. 31.

설계의 악취

프로그램 설계가 잘못된 증상을 가리켜 '설계의 악취'라고 하는데, 악취가 지속되면 결국 종양처럼 소프트웨어 전체 구조가 무너져내린다. '설계의 악취'는 프로그래머가 성장하면서 어쩔 수 없이 거쳐야 하는 과정이다. 일종의 '성장통'이라 생각한다. 설계의 악취와 관련된 증상은 다음과 같다.


1 [경직성] 

설계를 변경하기 어렵다. 특정 부분을 변경하기 위해서 시스템의 다른 부분들까지 변경해야 하는 상황이다.

2 [취약성] 

망가지기 쉬운 설계를 의미한다. 특정 부분을 변경했을 때, 해당 부분과 개념적으로 아무런 관련이 없는 부분이 망가진다. 

3 [부동성] 

설계를 재사용하기 어렵다. 시스템을 다른 시스템에서 재사용하 ㄹ수 있는 컴포넌트로 구분하기가 어려운 상태에 놓여 있다.

4 [점착성] 

제대로 동작하기 어렵다. 구현이 특정 케이스에만 한정되어 있는 경우, 상황이 조금만 변하더라도 동작하지 않는다. 이런 경우를 두고 점착성이 높다고 한다.

5 [불필요한 복잡성]  

과도한 설계가 원인이다. 객체지향 5원칙을 너무 과도하게 사용하거나 디자인패턴을 남발하다보면 설계자조차 자신의 코드를 연구해야 할 정도로 추상적이며, 복잡해진다. 이는 원칙을 적용하지 않는 것보다 못한 상태다.

6 [불필요한 반복] 

추상화를 함으로써 충분히 제거할 수 있는 반복이 남용된 상황이다. 특히, 이벤트 설계에 있어, 사용자가 이벤트를 과도하게 사용해야 하는 경우가 발생한다면 이는 문제가 있다.

7 [불투명성] 

'글'로 생각하면, 혼란스러운 표현이라 할 수 있다. 가령, A->B로 이어져야 하는 부분에서 A->C->B로 이어지면, B에 대한 의도를 알 수가 없다. B부분이 장황하게 이어져 있다면 더 큰 문제가 된다. 이를 불투명성이라 한다. 



누구나 프로그래밍을 처음 배울 때는 어떻게든 '아웃풋'을 내야한다는 식으로 접근한다. 이렇게 아웃풋만을 강조하는 방식을 '기능주의적 관점'이라 한다. 

문제는 기능만 중시하다보면 요구사항이 변경되는 순간에 모든 영역이 무너질 수 있다.  


하지만 어떻게든 특정 기능이 작동되는 게 가장 중요한 시절이 있다. 사실 '기능주의 중시적 관점'은 굉장히 중요하다. 어떤 분야건 아마추어 시절에는 '양'이 '질'을 압도해야만 성장의 기회가 주어지기 때문이다. 자전거를 처음 배우면서 사이클 선수의 테크닉을 익힐 수는 없으며,  피카소와 같은 거장도 처음에는 선부터 그었다. 어떤 분야건 절대량에 이르지 않은 상태에서 테크닉은 독이 된다. 이 때문에 처음부터 테크닉을 요구하는 사람들은 일정 수준이상 성장하지 못한다. 


처음 코딩에 입문하여 여러 기능을 구현하다보면 뭔가 아쉬운 부분을 느끼게 된다. 기능을 구현하는 것에만 치중하다보니 변경에 취약해지거나 특정한 상황에서만 사용할 수 밖에 없는 상황(이식 불가)이 발생한다.그리고 프로그래머가 폭발적으로 성장할 때가 있다면 바로 이러한 취약점을 느꼈을 때다. '양'으로 더이상 성장하기 힘든 한계를 느꼈다면 '질'적 성장이 필요하다. 이때 구조의 관점에서 전체를 바라볼 수 있는 '디자인 패턴'이나 유연한 아키텍처 설계를 습득하게 된다면 프로그래머는 비약적으로 성장한다. 


프로그래머의 지적 호기심이 최고조에 이르는 시기, 이때 비로소 필요한 테크닉이 바로 구조와 설계다. 전체 코드를 구조의 관점에서 바라보면 지금껏 세부적 기능에만 치중했던 자신의 좁은 시야를 극복할 수 있고, 다른 차원으로 성장할 수 있다. 이렇게 다른 차원으로 성장하는 경계를 '지적 임계점'이라 한다. 


'지적 임계점'은 전문가라면 겪을 수밖에 없는 공통적인 경험이다. 양이 질적 성장으로 변하는 시기를 거쳐야 한 분야의 전문가가 탄생하는데, 프로그래밍의 세계에서는 아키텍처와 구조적 설계가 '지적 임계점'의 역할을 담당한다.



객체지향 5원칙

아키텍처는 위의 7가지 사항, '코드의 악취(code smell)'를 최대한 효과적으로 대응할 수 있는 최적 설계방법을 제시하고, 유스케이스를 표현하는 기능 집합에 대해 최적의 설계를 구성할 수 있는 5가지 객체지향 원칙들을 지향해야 한다. 


1. SRP(Single Responsibility Principle) : 단일 책임 원칙   

2. OCP(Open-Closed Principle) : 개방 폐쇄 원칙

3. LSP(Liskov Substitution Principle) : 리스코프 치환 원칙

4. DIP(Dependency Inversion Principle) : 의존관계 역전 원칙

5. ISP(Interface Segregation Principle) : 인터페이스 분리 원칙



소프트웨어 공학이 태동한 지 30년이 넘었지만 위의 5가지 원칙은 더욱 굳건해졌다. 다수의 소프트웨어 개발자와 연구자의 고찰과 경험의 집합체가 결합된 형태가 위의 5가지 원칙이다. 이는 일종의 소프트웨어 개발자의 '내공'이라 할 수 있다.


개발자의 내공은 '책임-역할-관계'를 중심으로 하는 효율적인 도메인 설계와 동시에 위의 5가지 원칙을 통한 유연한 설계가 핵심이다. 그중에서도 객체지향 5원칙의 판단이 상당히 중요하다.  코드에서 아무런 악취(7가지 증상)가 없다면 굳이 원칙을 적용할 필요는 없기 때문이다. 원칙이라는 이유만으로 무조건 따르는 것은 오히려 좋지 않다. 하지만 이 정도 판단을 내릴 수 있으려면 기본적으로 내공이 탄탄해야 함은 말할 것도 없다.



UML이란 신기루

대개 소프트웨어 설계를 말할 때, UML을 설계로 오해하는 경우가 있다. UML을 멋있게 만들어서 벽에 붙여놓으면 그것으로 설계가 끝난 것처럼 생각하는 개발팀도 있을 것이다. 그러나 UML은 설계가 아니다. 소프트웨어에서 설계도는 '소스 코드'다. 디자이너는 디자인으로 말하고, 개발자는 소스코드로 말한다. 


설계에서 불변의 법칙은 요구사항은 변한다는 것이다. 어떤 설계도 완벽하지 않다. 시간, 상황, 기술, 심리적 요인, 환경적 변화 등 소프트웨어는 반드시 변하는 요구사항을 받아들이게 될 상황을 맞이한다. 


가령, 그렇게 단순한 자동자판기 역시 지폐, 신용카드 결제, 모바일 결제 등 상황에 따라 설계가 달라졌는데 다른 소프트웨어는 말할 것도 없다. 요구사항은 반드시 변한다는 진리를 받아들일 때, 설계는 점차 진화한다. 따라서 UML은 그냥 신기루일 뿐이다. 유스케이스를 중심으로 메시지를 추출하는 목적 그 이상 그 이하도 아니다. UML을 믿지 말고, 도메인간의 메시지와 협력관계 그리고 테스트로 작성한 소스코드를 믿어라.

 

댓글

최신글 전체

이미지
제목
글쓴이
등록일