본문 바로가기
SW

클린 아키텍처:소프트웨어 구조와 설계의 원칙(Clean Architecture) - 2부 : 벽돌부터 시작하기: 프로그래밍 패러다임 (5장)

by 라꾸스떼(YR) 2020. 2. 27.
반응형

[5장] 객체 지향 프로그래밍

좋은 아키텍처를 만드는 일은 객체 지향(Object-Oriented,oo) 설계 원칙을 이해하고 응용하는 데서 출발한다.

oo란? 데이터와 함수의 조합, 실제 세계를 모델링하는 새로운 방법

OO의 본질을 설명하기 위해 세 가지 주문에 기대는 부류도 있는데, 캡슐화(encapsulation), 상속(inheritance), 다형성(polymorphism)이 바로 그 주문이다. 이들은 oo가 이 세 가지 개념을 적절하게 조합한 것이거나, 또는 oo 언어는 최소한 세 가지 요소를 반드시 지원해야 한다고 말한다.

 

<캡슐화?>

이를 통해 데이터와 함수가 응집력 있게 구성된 집단을 서로 구분 짓는 선을 그을 수 있다. 구분선 바깥에서 데이터는 은닉되고, 일부 함수만이 외부에 노출된다. 이 개념들이 실제 oo언어에서는 각각 클래스의 private 멤버 데이터와 public 멤버 함수로 표현된다.

c프로그래머는 먼저 데이터 구조와 함수를 헤더 파일에 선언하고, 구현 파일에서 이들을 구현했다. c++컴파일러는 기술적인 이유(컴파일러는 클래스의 인스턴스 크기를 알 수 있어야 한다.)로 클래스의 멤버 변수를 해당 클래스의 헤더 파일에 선언할 것을 요구했다. 물론 멤버 변수에 접근하는 일은 컴파일러가 막겠지만, 사용자는 멤버 변수가 존재한다는 사실 자체를 알게 된다. 언어에 public, private, protected 키워드를 도입함으로써 불완전한 캡슐화를 사실상 어느 정도 보완하기는 했다. 하지만 이는 컴파일러가 헤더 파일에서 멤버 변수를 볼 수 있어야 했기 때문에 조치한 임시방편일 뿐이다.

이 때문에 oo가 강력한 캡슐화에 의존한다는 정의는 받아들이기 힘들다. 실제로 많은 oo언어가 캡슐화를 거의 강제하지않는다.(파이썬) oo프로그래밍은 프로그래머가 충분히 올바르게 행동함으로써 캡슐화된 데이터를 우회해서 사용하지 않을 거라는 믿음을 기반으로 한다.

 

<상속?>

상속이란 단순히 어떤 변수와 함수를 하나의 유효 범위로 묶어서 재정의하는 일에 불과하다.

oo 언어에서는 이러한 업캐스팅(upcasting)이 암묵적으로 이뤄진다. 따라서 oo언어가 완전히 새로운 개념을 만들지는 못했지만, 데이터 구조에 가면을 씌우는 일을 상당히 편리한 방식으로 제공했다고 볼 수는 있다. 간략히 요약하면, 캡슐화에 대해서는 oo에 점수를 줄 수 없고, 상속에 대해서만 0.5점 정도를 부여할 수 있다. 이렇게만 보면 그저 그런 점수다.

 

<다형성?>

getchar() 함수는 STDIN에서 문자를 읽는다. 그러면 STDIN은 어떤 장치인가? putchar() 함수는 STDOUT으로 문자를 쓴다. 그런데 STDOUT은 또 어떤 장치인가? 이러한 함수는 다형적(polymorphic)이다. 즉, 행위가 STDIN과 STDOUT의 타입에 의존한다.

c++에서는 클래스의 모든 가상 함수(virtual function)는 vtable이라는 테이블에 포인터를 가지고 있고, 모든 가상 함수 호출은 이 테이블을 거치게 된다. 파생 클래스의 생성자는 생성하려는 객체의 vtable을 단순히 자신(파생 클래스)의 함수들로 덮어 쓸 뿐이다. 함수를 가리키는 포인터를 응용한 것이 다형성인 것이다.

 

<다형성이 가진 힘>

플러그인 아키텍처(plugin architecture)는 이처럼 입출력 장치 독립성을 지원하기 위해 만들어졌다. oo의 등장으로 언제 어디서든 플러그인 아키텍처를 적용할 수 있게 되었다.

 

<의존성 역전>

전형적인 호출 트리의 경우 main 함수가 고수준 함수를 호출하고, 고수준 함수는 다시 중간 수준 함수를 호출하며, 중간 수준 함수는 다시 저수준 함수를 호출한다.

즉, 제어흐름은 시스템의 행위에 따라 결정되며, 소스 코드 의존성은 제어흐름에 따라 결정된다. 하지만 다형성이 끼어들면 무언가 특별한 일이 일어난다.

의존성 역전(dpendecny inversion)

oo언어가 다형성을 안전하고 편리하게 제공한다는 사실은 소스 코드의 의존성을 어디에서든 역전시킬 수 있다는 뜻이기도 하다.

소스 코드 의존성은 소스 코드 사이에 인터페이스를 추가함으로써 방향을 역전시킬 수 있다.

호출하는 모듈이든 아니면 호출 받는 모듈이든 관계없이 소프트웨어 아키텍트는 소스 코드 의존성을 원하는 방향으로 설정할 수 있다.

즉, ui와 데이터베이스가 업무 규칙의 플러그인이 된다는 뜻이다. 업무 규칙을 ui와 데이터베이스와는 독립적으로 배포할 수 있따.

다시 말해 특정 컴포넌트의 소스 코드가 변경되면, 해당 코드가 포함된 컴포넌트만 다시 배포하면 된다. 이것이 바로 배포 독립성(independent deployability)이다.

시스템의 모듈을 독립적으로 배포할 수 있게 되면, 서로 다른 팀에서 각 모듈을 독립적으로 개발할 수 있다. 그리고 이것이 개발 독립성(independent developability)이다.

 

<결론>

oo란 다형성을 이용하여 전체 시스템의 모든 소스 코드 의존성에 대한 절대적인 제어 권한을 획득할 수 있는 능력이다. oo를 사용하면 아키텍트는 플러그인 아키텍처를 구성할 수 있고, 이를 통해 고수준의 정책을 포함하는 모듈은 저수준의 세부사항을 포함하는 모듈에 대해 독립성을 보장할 수 있다. 저수준의 세부사항은 중요도가 낮은 플러그인 모듈로 만들 수 있고, 고수준의 정책을 포함하는 모듈과는 독립적으로 개발하고 배포할 수 있다.

반응형

댓글