본문 바로가기

기타/객체지향의 탄생(2013)

객체지향의탄생-객체지향 디자인 원리 SOLID, SRP

수영 한지 5년이 됐다. 나는 글을 쓰는 지금 수영을 책과 글쓰기와 프로그래밍외 유일한 삶의 낙으로 부단히 연습하고 있다. 수영을 배운지 10개월 즈음 되었던 어느날, 수영 연습을 하다가 나는 뭔가 깨달음을 얻고 크게 기뻐했다.

 

수영의 고수로 오르는 중요한 길목인 '물잡기'의 감을 처음 느꼈다. 극심한 몸치로서 3개월동안이나 물에 못 뜨다가 드디어 처음 물에 떴을때의 감동에 이은 모처럼의 큰 깨달음과 감동이었다.

 

물은 액체다. 나는 물은 액체라고 생각하고 손을 뒤로 저었다. 나는 흐물흐물한 액체를 젓고 있으므로, 이때 물을 저으며 몸이 나아가는 느낌은 약하고 불안하다.

 

수영에 대한 강좌 글을 읽어보니 물을 고체라고 생각하고 물을 잡고 뒤로 젓는 물잡기가 진정한 '스트로크' 라고 한다. 물을 고체 잡듯 잡아 뒤로 챈다고 생각하고 열심히 '스트로크' 연습을 했다. 어느날 정말로 물을 고체 잡듯 잡아 뒤로 채는 그 느낌을 알게 된 것이다. 물은 잡기 힘든 액체지만 마치 고체처럼 잡아 뒤로 챌수 있다는 것을 온몸으로 실감한 즐거운 경험이었다. 물잡기 덕분에 몸이 안정적으로 앞으로 전진하는 느낌을 즐길 수 있었다.

 

객체지향을 공부하는 길은, 추상적이고 차원높은 기술 배경 때문에 마치 물과 같은 액체처럼, 지식을 확실히 잡아 머릿속에 채는 일이 약하고 불안하기만 하다. 그러나 부단히 연습하면 언젠가 쉽게 잡을 수 있는 고체처럼 객체지향 지식을 바로 잡아 머릿속에 넣는 일이 가능할 것이다. 수영이든 객체지향이든 노력한 만큼 효과가 있을 것이었다.

 

객체지향이란 물과 같은 액체처럼 선뜻 이해하기 힘든 기술을, 확실히 이해하는데 객체지향 디자인 SOLID 원칙이 크게 도움이 된다. 다만 지금 설명할 SOLID 원칙은 마치 '갑 회사'에게 제출할 정식 산출물처럼 문서화, 매뉴얼화가 되어 있고, 엄격한 느낌을 갖는다.

 

나는 일단 '객체지향 설계를 위한 조언'을 부드럽게 이해한다음, SOLID 법칙을 마치 딱딱한 수학 암기 공식처럼 이해하고 암기할 것이다. SOLID 법칙에는, 이전에 다룬 객체지향을 이롭게 하는 대부분의 법칙과, 앞으로 다룰 디자인패턴의 기본이 되는 대부분의 규칙이 압축되어 있기 때문이다.

 

  1. SRP(Single Responsibility Principle)

클래스는 분업화가 철저한 공장의 노동자와 같다. 이곳의 공장이 잘 돌아가려면 노동자는 오직 하나의 일만해야 한다. 혹시 노동자가 두개의 일을 하게 된다면 공장의 거대한 생산 시스템은 삐걱거리게 된다. 왜냐면 분업화된 공장은 노동자가 자신의 일을 놔둔채 다른 일을 하는 즉시 문제가 생기게끔 생산 시스템 자체가 설계가 되어있기 때문이다. 객체지향 공장 시스템도 공장과 같아서 클래스는 오직 하나의 일만 수행해야 유연하고 확장성 높고 유지보수하기 쉬운 객체지향 시스템의 효과를 얻는다.

 

SRP(Single Responsibility Principle), 단일 책임의 원리라고 한다. 시스템의 모든 객체는 하나의 책임만을 가지며, 객체가 제공하는 모든 기능은 그 하나의 책임을 수행하는데 집중되어 있어야 한다. 객체는 유일하며 다른 객체와 구별이 가능하다. 그들 객체만이 제일 잘 할 수 있는 독립적인 책임을 갖고 있다. 클래스와 메소드는 한가지 종류의 책임만을 다음과 같이 수행한다. 그 책임에 해당하는 일을 모두 한다. 그 일을 다른 클래스나 메소드보다 더 잘한다. 그 일을 자신만이 유일하게 한다. 결론은 객체가 하나의 일만 수행하게 하라.

 

최초에 객체를 설계하는 일은 공장에서 물건 생산하듯 정해진 일이 아니라 최초에 없는 건물을 디자인 하듯 추상적인 과정이어서 객체에 속성과 기능을 결정하는 과정에다가 하나의 일만 수행하게 설계하라고 강요하는 일은 군대에서 흐물흐물한 이불을 각잡고 정리하라는 지시처럼 까다로운 일이다.

 

각 객체가 변화의 요인이 하나뿐이라면, 설계자는 단일 책임의 원리를 정확히 구현한 것이다. 이런 명제를 확인하기위한 좋은 방법이 있다.

 

 

[클래스 분석을 위한 CRC카드]

 

카드 모양만 봐도 무엇을 적고 테스트 하면 되는지 알 수 있다. 제목에 클래스 이름을 적고, 그 아래 내가 계획한 메소드들을 적어본다.

 

위의 설명대로 다음의 클래스가 SRP 규칙을 지키고 있는지 분석해보자.

 

[클래스 CRC 카드 테스트를 위한 예제 클래스]

 

[휴대폰 클래스 CRC카드 분석]

 

나는 휴대폰 클래스의 주요기능을 음성송신, 음성수신, 기기충전, 전화걸기, 전화받기등으로 정해 보았다. 그리고 휴대폰 클래스 CRC카드를 작성했다. 하나하나 따져보기 시작했다.

 

휴대폰이 자신을 '음성송신' 하는가. 이 명제에 대하여, 휴대폰이 자기 내부의 여러 통신 모듈을 이용하여 기지국과 통화를 시도하므로 이 명제는 참이다.

 

휴대폰이 자신을 '음성수신' 하는가. 이 명제에 대하여, 휴대폰이 상대방에게서 들어오는 통신 신호를 자기 내부의 여러 통신 모듈을 이용하여 받아들이고 매끄러운 음성신호로 바꿀 것이므로 이 명제는 참이다.

 

휴대폰이 자신을 '기기충전' 하는가. 이 명제에 대해서는, 휴대폰이 자기 스스로 기기충전을 하지 않고 사람의 행동에 의해 기기충전이 이루어지므로 이 명제는 거짓일 수도 있다. 그러나 휴대폰과 충전기가 연결되었을 경우 기기충전 기능을 작동하는 것은 참이기도 하다. 생각하기에 따라서 참이 될수도 있고 거짓이 될 수 있기 때문에 논란의 여지가 있다. 일단 X로 하고 나중에 클래스를 리팩토링 하기로 했다.

 

휴대폰이 자신을 '전화걸기' 하는가. 이 명제에 대해서는, 휴대폰이 자기 스스로 전화걸기를 하지 않고, 사람이 전화걸기를 시도하므로 거짓이다.

 

휴대폰이 자신을 '전화받기' 하는가. 이 명제에 대해서도, 휴대폰이 자기 스스로 전화받기를 하지 않고, 사람이 전화받기를 시도하므로 거짓이다.

 

내가만든 휴대폰 클래스는 CRC 카드로 분석했다 싶이 하나의 휴대폰 클래스가 모든 일을 하지 못한다. 그럼에도 억지로 하나의 클래스로 밀어넣으면 현실세계의 휴대폰이 아니라 이상한 세계의 클래스와 같다.

 

 

휴대폰은 혼자 작동못하는 수동적인 존재이다. 수동적인 휴대폰을 작동 시키는 존재는 사람이다. 그래서 지금의 휴대폰 클래스를 다음처럼 바꾼다.

 

[클래스 리팩토링 그림]

 

그림에서처럼 충전을 한다. 전화를 건다. 등의 적극적인 행동은 사람 클래스가 맡고 있다. 충전 기능 작동, 전화 송신등의 실제 기능 구현과 누군가 작동사켜야 하는 수동적인 행동은 휴대폰 클래스가 맡고 있다.

 

'클래스는 하나의 일만 잘해야 한다.' SRP 규칙을 지키면 클래스와 클래스 구성도가 깔끔하게 정리됨을 알게 된다.

 

클래스와 클래스 구성도가 깔끔하게 정리되는 것은 객체지향 개발에 있어 마치 깨진 창문 효과를 예방하는 것과 같다.

 

깨진창문 효과는 어느 작업장에 깨진창문처럼 더럽고 지저분한 요소를 방치하면 요소 때문에 주변 환경이 점점 오염되어 결국 작업장을 해치게 된다는 효과이다.

 

초기 클래스 설계시 객체지향다운 설계를 위한 에스알피 규칙을 지키지 않고 마구잡이로 설계를 시작하는 것은 깨진창문과 지저분한 사무실을 갖춰놓고 업무를 시작하는것과 같다.

 

그래서 깨진창문 없는 깔끔한 객체지향 개발을 위해 SRP규칙을 잘 활용할 필요가 있다.

 

덧 ) 이 객체지향의 탄생 원고는 제가 책으로 내려다가 일단 잘 안되었는데요. 이유는 비문이 많다. 단락내 주제가 중복된다. 어떤 상황 설명을 과장한다.등 입니다. 그래도 원고를 일단 블로그에 몽땅 풀어보고 언젠가 제대로 교정해서 다시 도전할 생각입니다. 비문이 많다. 단락내 주제가 중복된다. 어떤 상황 설명을 과장한다. 이점을 감안해서 읽고 객체지향을 이해하는데 도움이 되셨으면 좋겠습니다. 의견도 주셨으면 좋겠습니다. 원고 조금만 교정하면 괜찮을것 같은 출판사 관계자분의 피드백도 환영합니다. 특별한 일 없으면 매주 월수 발행 예정입니다.

'기타 > 객체지향의 탄생(2013)' 카테고리의 다른 글

객체지향의 탄생-LSP  (3) 2015.05.26
객체지향의 탄생-OCP  (1) 2015.05.20
객체지향의 탄생-UML2  (0) 2015.04.22
객체지향의 탄생-UML1  (0) 2015.04.20
객체지향의 탄생-상속과 구성  (0) 2015.04.15