본문 바로가기
느리게 변하는 지식

객체지향 설계 기법

by oncerun 2022. 3. 15.
반응형

 

객체지향의 사실과 오해를 읽다가 재밌게 읽은 부분을 발췌해 적어보려 한다.

 

읽던 파트는 객체지향 설계 기법이다. 언젠간 나에게도 애플리케이션 설계할 수 있는 기회가 올지 모른다.

 

객체의 역할, 책임, 협력이 얼마나 견고하고 유연한 객체지향 설계를 하기 위한 중요한 토대라는 것을 계속 강조했다. 

 

하나의 협력안에서 객체가 어떤 역할을 가져야 하고 그 역할을 수행하기 위한 책임이 무엇인가? 

이 순서로 객체지향을 설계해달라고 외치는 책이었다. 

 

이제 과거 선배 개발자들은 어떠한 고민 끝에 "기법"이라는 방법을 만들었는지 구경할 차례가 왔다.

 

1. 책임-주도 설계 (Responsibility-Driven Design)

 

협력에 필요한 책임들을 식별하고 적합한 객체에게 책임을 할당하는 방식으로 애플리케이션을 설계한다. 

 

나는 역할을 먼저 생각하는 것이 좋다고 생각했다. 그 이유는 협력이라는 큰 틀이 정해지고 그 안에서 역할이 생겼을 때 그 역할이 해야 되는 책임은 자동적으로 따라온다고 생각했기 때문이다. 

 

조금 더 살펴보자. 

 

책임-주도 설계 방법은 객체지향 패러다임의 전문가들이 애플리케이션을 개발할 때 어떤 방식으로 사고하고 무엇을 기반으로 의사결정을 내리는지 잘 보여준다.

 

객체지향 시스템은 역할과 책임을 수행하는 자율적인 객체들이 공동체다. 객체는 고립된 섬이 아니라 시스템의 더 큰 목표를 달성하기 위해 다른 객체와 협력하는 존재이다. 

 

사용자의 요구를 만족시킬 수 있는 기능을 제공하는 동시에 이해하기 쉽고, 단순하며, 유연한 상호작용을 제공하는 객체들의 공동체를 구축하는 것이다.

 

그렇다. 나는 매일 사용자의 요구를 받는다. 이를 만족시켜주기 위해 되냐, 안되냐에 대해 논의하고 처리한다. 

 

나는 사용자의 요구를 들으면서 이게 어떻게 해야 될지 생각하면서 듣는다. 하지만 구조적으로 불가능할 때 시간이 오래 걸릴 때 머리가 하얗게 질릴 때는 참으로 난감하다.  왜 안될까라는 질의에는 영향을 받는 코드가 너무 많다고 생각하기 때문이다...

 

객체지향 설계는 애플리케이션의 기능을 구현하기 위한 협력 관계를 고안하고, 협력에 필요한 역할과 책임을 식별한 후 이를 수행할 수 있는 적절한 객체를 식별해 나가는 과정이다. 

객체지향 시스템을 창조하는 작업은 지속적인 훈련과 견고한 기술, 안정적인 가이드라인을 필요로 한다.

 

 

책임-주도 설계 방법은 레베카 워프스브록이 고안했다. 이는 말 그대로 객체의 책임을 중심으로 시스템을 구축하는 설계 방법을 말한다. 

 

시스템의 기능은 더 작은 규모의 책임으로 분할되고 각 책임은 책임을 수행할 적절한 객체에게 할당된다.

객체가 책임을 수행하는 도중에 스스로 처리할 수 없는 정보나 기능이 필요한 경우 적절한 객체를 찾아 필요한 작업을 요청한다. 

 

협력 관계의 기반은 객체가 다른 객체에게 작업을 요청하는 메시지이다.  이러한 협력 관계에서 책임을 여러 종류의 객체가 수행할 수 있다면 협력자는 객체가 아니라 추상적인 역할로 대체된다.

(협력 관계가 발생했을 때 책임을 여러 종류의 객체가 수행할지 판단하는 것이 실무적으로 곤란할 것 같기도 하다. 기획, 요구조건을 봤을 때는 명확해 보이지만 막상 시간이 흐르면 추가 요청이 올 수도 안 올 수도 있기 때문이라고 생각한다.)

 

책임-주도 설계에서는 시스템의 책임을 객체의 책임으로 변환하고, 각 객체가 책임을 수행하는 중에 필요한 정보나 서비스를 제공해줄 협력자를 찾아 해당 협력자에게 책임을 할당하는 순차적인 방식으로 협력 공동체를 구축한다.

 

책임 -주도 설계는 개별적인 객체의 상태가 아니라 객체의 책임과 상호작용에 집중한다.

 

시스템은 스스로 자신을 책임질 수 있을 정도로 충분히 자율적인 동시에 다른 객체와 우호적으로 협력할 수 있을 정도로 충분히 협조적인 객체들로 이뤄진 생태계를 구성하게 된다.

(충분히 자율적이라는 말...?)

 

  • 시스템 책임을 파악 ( 사용자의 요구조건)
  • 시스템 책임을 더 작은 책임으로 분할 
  • 분할된 책임을 수행할 수 있는 객체 또는 역할을 찾아 할당
  • 객체가 책임 수행 중에 다른 객체의 도움이 필요한 경우 이를 책임지는 적절한 객체 또는 역할을 찾는다.
  • 협력 관계를 만든다.

 

내 생각에 시스템 책임을 더 작은 책임으로 분할하면서 그 책임을 수행할 수 있는 객체에 할당한 이후 조금씩 조금씩 확장되어 가는 방식으로 보인다.

 

책임-주도 설계는 객체의 역할, 협력, 책임을 고안하기 위한 방법과 절차를 제시한다. 

절차를 따라가다 보면 객체의 역할, 책임을 통해 협력이 발생할 것이다. 즉 생각하는 방법을 제시하는 느낌이다.

 

2. 디자인 패턴 (Design Pattern)

 

전문가들이 반복적으로 사용하는 해결 방법을 정의해 놓은 설계 템플릿 모음이다. 

특정 문제가 반복되어 나오기 때문에 전문가들이 특정 문제를 해결하기 위해 이미 식별해 놓은 역할, 책임, 협력의 모음이다. 

 

패턴은 모범이 되는 설계다. 모범을 모방하여 약간의 수정을 통해 결과물을 만들어내는 과정은 창조이다.

 

디자인 패턴을 공부할 때 조금 tip이 될 수 있을 것 같은데 이 패턴의 구조를 볼 때 이를 협력에 참여하는 역할과 책임이라는 것에 집중해야 한다. 

이들이 클래스와 메서드가 아닌 협력에 참여하는 역할과 책임의 관점으로 보게 되면 좀 더 넓게 생각할 수 있고

역할은 실제 구현 시 다양한 방식으로 역할을 구현할 수 있다는 사실이고 이는 모방에서 창조가 되는 단계이다.

 

쉽지 않은 내용이다. 

 

기억해야 할 것은 디자인 패턴은 공통으로 사용할 수 있는 역할, 책임, 협력의 템플릿이다. 템플릿을 알고 있다면 특정한 상황에 적용이 가능할 것이고 책임-주도 설계의 절차를 순차적으로 따르지 않고도 시스템 안에 구현할 객체들의 역할과 책임, 협력 관계를 빠르고 손쉽게 포착할 수 있을 것이다. 

(이러한 시야를 갖기 위해 파이팅)

 

 

 

3. 테스트-주도 개발 (Test-Driven Development) 

 

1년 전부터 가장 많이 들었던 개발 방식이다. 

테스트를 먼저 작성하고 테스트를 통과하는 구체적인 코드를 추가하면서 애플리케이션을 완성해가는 방식을 따른다. 

 

이는 단지 테스트를 위한 것이 아닌 설계를 위한 기법이라고 한다. 핵심은 테스트 작성이 아닌 구체적인 코드를 작성해나가면서 역할, 책임, 협력을 식별하고 식별된 역할, 책임, 협력이 적합한지 피드백받는 것이다. 

(와 미쳤다.)

 

테스트-주도 개발이 응집도가 높고 결합도가 낮은 클래스로 구성된 시스템을 개발할 수 있게 하는 최상의  프랙티스인 것은 맞지만 객체지향에 대한 경험이 적은 초보자들은 개발을 주도하기 위해 어떤 테스트를 어떤 식으로 작성해야 하는지 큰 어려움을 겪는다.

 

테스트-주도 개발은 객체가 이미 존재한다고? ( 책임, 역할, 협력할 객체 까지?) 가정하고 객체에게 어떤 메시지를 전송할 것인지 먼저 생각하라고 충고한다.

 

테스트-주도 개발은 테스트를 작성하는 것이 아니라 책임을 수행할 객체 또는 클라이언트가 기대하는 객체의 역할이 메시지를 수신할 때 어떤 결과를 반환하고 그 과정에서 어떤 객체와 협력할 것인지에 대한 기대를 코드의 형태로 작성하는 것이다.

 

역할, 책임, 협력의 관점에서 객체를 바라보는 연습이 필요할 것 같다.  역할을 테스트하고 구체적인 구현체를 테스트하고 그 과정에 협력 관계가 발생하고 어떤 메시지를 주고받을지... 생각을 하는 건가?

 

테스트-주도 개발은 책임-주도 설계의 기본 개념을 따른다고 한다. 

 

책임을 분해하고 책임을 할당할 객체 또는 역할을 찾고 협력 관계를 만드는 과정을 훈련해야 한다. 

때로는 요구사항이 특정 패턴이 사용되어야 함을 눈치채고 패턴을 목표로 빠르게 테스트를 작성할 수 있다. 

 

이는 협력 안에서 객체의 역할과 책임이 무엇이고 이것을 프로그래밍 언어 장치로 구현되는 방식에 대한 감각을 갖춰야 효과적인 테스트를 작성할 수 있다. 

 

즉 테스트-주도 개발은 책임-주도 설계를 통해 도달해야 하는 목적지를 테스트라는 안전장치를 통해 좀 더 빠르고 견고한 방법으로 도달할 수 있는 최상의 설계 프랙티스다.

 

다만 이는 객체지향에 대한 깊이 있는 지식을 요구한다. 

테스트를 작성하기 위해 객체의 메서드를 호출하고 반환 값을 검증하는 것은 객체가 수행해야 하는 책임에 관해 생각한 것이다. 

 

테스트에 필요한 간접 입력 값을 제공하기 위해 스텁을 추가하거나 간접 출력 값을 검증하기 위해 목 객체를 사용하는 것은 객체와 협력해야 하는 협력자에 관해 고민한 결과를 코드로 표현한 것이다.

 

테스트-주도 개발은 책임-주도 설계의 기본 개념, 다양한 원칙과 프랙티스, 패턴을 종합적으로 이해하고 좋은 설계에 대한 감각과 경험을 길러야만 적용할 수 있는 설계기법이다. 역할, 책임, 협력에 집중하고 객체지향의 원칙을 적용하려는 깊이 있는 고민과 노력을 통해서만 테스트-주도 개발의 혜택을 누릴 수 있다.

 

 

 

[마무리]

이 책은 내게 매번 새로움을 준다. 또 예시는 얼마나 재밌는지 자기 전 책을 열면 잘 시간을 넘긴다. 

다만 읽으면서 느끼는 점은 읽고 덮는 것이 아닌 객체지향에 관하여 생각하는 시간과 실무에서 적용한다면 어떻게 할 것인지 생각하는 노력이 필요하다는 것이다.  나도 책을 읽다가 몇 분씩 생각에 잠기기도 한다.

다만 내 경험이 너무 부족해 더 넓은 환경의 설계를 떠올리지 못하는 것이 아쉽기도 하다..

반응형

'느리게 변하는 지식' 카테고리의 다른 글

데드락  (0) 2022.08.04
CPU 작동 원리  (0) 2022.04.08
Lean 소프트웨어 개발  (0) 2022.04.05
소프트웨어 개발 방법론  (0) 2022.04.05
인코딩의 이해 with Java  (0) 2021.08.11

댓글