책 <클린 아키텍처>의 [Part2 벽돌부터 시작하기:프로그래밍 패러다임]을 참조하여 정리한 내용입니다.

서론 - 객체지향을 설명하는 3가지 방식

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


일반적으로 객체지향을 설명하는 방식은 3가지가 있다.

  1. 객체지향은 "데이터와 함수의 조합"이다.
  2. 객체지향은 "실제 세계를 모델링하는 새로운 방법"이다.
  3. 객체지향은 캡슐화, 상속, 다형성이라는 3가지 조건을 충족한 패러다임이다.

위와 같은 설명은 아키텍처의 관점에서 만큼은 충분하지 못하다.


"데이터와 함수의 조합"

객체지향이 "데이터와 함수의 조합"이라는 말은 object.function()과 function(object) 두 방식이 다르다는 것을 내포한다. 그러나 이는 사실상 같다.(저자는 다르다는 주장을 터무니 없다고 표현한다.) 함수에 데이터 구조를 전달하는 방식은 객체지향을 발명하기 이전부터 사용되어져왔다.


"실제 세계를 모델링하는 새로운 방법"

저자는 이러한 설명을 "얼버무리는 수준"의 대답이라고 표현한다. 저자는 "실제 세계를 모델링"한다는 것의 의미가 모호할 뿐더러, 그러한 방향을 추구해야 하는 이유에 대해서 의문을 던진다.

학교 다닐 때 특정 교수님이 이와 유사한 형태로 객체지향을 설명하셨었다. 설득력있다는 생각에 오랫동안 머리 속에 담아 두었던 생각인데.. 너무 쉽게 부정당한 느낌..


캡슐, 상속, 다형성

위 세가지 개념에 기대는 사람들은 이들을 조합하여 객체지향을 설명하거나, 이들을 객체지향의 기본조건으로 내세운다.

위 세가지 개념은 뒤에서 보다 자세히 다룬다.



캡슐화

객체지향언어는 접근 제어자(private, public, protected)와 같은 문법을 이용하여 효과적으로 데이터와 함수를 캡슐화하는 것을 지원한다. 그러나 C언어로도 캡슐화를 구현할 수 있으며, 이는 객체지향 언어보다 강력하다. 이 말인즉슨, 객체지향언어는 캡슐화를 강제하지 않으며 프로그래머가 올바르게 사용할 것이라는 믿음을 기반으로 설계되어졌고, 이러한 측면에서 객체지향언어들은 기존의 C언어보다 캡슐화가 완전하지 못하다.


이러한 이유로 캡슐화가 객체지향을 규정하는 조건이 되기에는 애매한 구석이 있다.



상속

상속 또한 C언어로 구현이 가능하다. 다만 객체지향 언어가 훨씬 편리한 상속 기능을 제공하는 것은 사실이다.


저자는 캡슐화에 대해선 점수를 줄 수 없고 상속에 대해선 0.5점 정도를 부여한다고 말한다ㅋㅋ..
실제 책에선 캡슐화, 상속 모두 C, C++, Java의 예제를 통해서 꽤나 상세하게 다룬다.



다형성

다형성은 함수를 가리키는 함수 포인터를 응용한 기법이며, 함수 포인터는 사실상 40년대 후반 폰노이만 아키텍처 이래로 사용된 방식이다. 물론 함수 포인터를 직접 다루는 것은 까다로운 작업이기 때문에 함수 포인터를 안전하고 편리하게 사용할 수 있게 하는 객체지향의 다형성이 강력한 건 사실이다. 그러나 주목해야 할 것은 다형성이 제어의 흐름(함수 포인터)을 간접적으로 전환한다는 사실이다.

다형성의 진가는 제어의 흐름을 간접적으로 제어한다는 점에 있다. 여기서 의존성의 역전이 일어난다.



의존성의 역전

다형성 이전 소프트웨어에서 제어의 흐름은 일반적으로 고수준 -> 중간 수준 -> 저수준 함수의 순서로 진행되었다. 이 말은 고수준의 함수가 저수준의 함수를 의존한다는 말이며, 저수준 함수에서 변경이 발생할 경우 중간 수준과 고수준에서도 동시에 변경이 일어난다는 말이 된다. 반면에 객체지향 언어의 경우 저수준 함수에 대해서 인터페이스를 통해 규약을 강제할 수 있다. 즉, 고수준 함수가 저수준 함수를 의존하지 않게 된다. 반대로 저수준 함수가 고수준의 인터페이스를 의존하게 된다. 결론적으로 객체지향 언어를 이용할 경우 의존성의 방향을 마음대로 변경할 수 있다.

글로만 설명하기엔 다소 추상적인 개념들이 많다. 책에서는 그림과 코드로 보다 상세하게 설명한다.
저자는 이에 덧붙여 "플러그인 아키텍처", "배포 독립성", "개발 독립성"들을 언급하며 의존성이 역전된 객체지향언어의 장점을 강조한다.



요약(을 해보자면..)

  1. 객체지향을 설명하는 일반적인 세 가지 방식은 불충분하다. ("데이터와 함수의 조합", "실제 세계를 모델링하는 새로운 방법", 캡슐화-상속-다형성)
  2. 왜냐하면 객체지향의 진가는 다형성 그 자체가 아니라 다형성과 같은 기능을 통해서 일어나는 의존성의 역전이기 때문이다.
  3. 의존성의 방향을 제어하면 "플러그인 아키텍처"를 구현할 수 있으며, 이에 따라 "배포 독립성"과 "개발 독립성"이라는 장점을 취할 수 있다.



자의적인 해석이 많이 섞여 있을 수 있으니, 꼭 책을 참고하시길 바랍니다.

책 <클린 아키텍처>의 [Part2 벽돌부터 시작하기:프로그래밍 패러다임]을 참조하여 정리한 내용입니다.


서문

  • 1945년 경 앨런튜링은 바이너리 언어를 사용하여 반복문, 분기문, 할당문, 서브루틴, 스택 등과 같은 구조를 사용하여 프로그램을 만들었다.
  • 1940년대 후반 어셈블리 언어, 1951년 A0컴파일러를 필두로 수 많은 언어들이 탄생하였다.
  • 이처럼 언어적인 차원에서 수 많은 혁신이 일어난 것처럼, 프로그래밍 패러다임에 있어서도 많은 변화가 이루어져왔다.
  • 패러다임은 "프로그래밍을 하는 방법"을 정의하며 언제 어떠한 구조를 사용해야 할 지에 대한 기준이 된다.

구조적 패러다임

데이크스트라는 무부별한 점프(goto)는 프로그램 구조에 해롭다는 사실을 제시했다.

 

C언어에는 goto문이 있다는데, C언어를 안 써본 나는 오히려 goto문이 생소하다.
그렇다.. 구조적 패러다임은 goto문장과 관련이 있다.

 

구조적 패러다임은 무엇인가

구조적 패러다임은 if/then/else(분기문)와 do/while/until(반복문)과 같은 문법으로 프로그래밍을 하는 방식이다. 다시 말하면 goto문을 제약하고 분기와 반복문을 사용하는 기법이다.

 

구조적 패러다임은 현 시대의 프로그래밍 언어를 사용한다면 너무 당연하고 익순한 내용이다. 당연한 걸 당연하다고 말하는 이 패러다임..
'등장'의 이유가 중요하다.

 

구조적 패러다임의 등장 배경

데이크스트라라는 아저씨, 아니, 컴퓨터 과학자가 등장한다.
1950년 대, 데이크스트라가 살던 시절에는 바이너리 언어로 프로그래밍을 하던 시절이였고, 당시에는 간단한 프로그램일지라도 많은 세부사항들을 조작해야만 했다. 그래서 사소한 세부사항을 놓쳐서 프로그램이 실패하는 상황이 자주 벌어졌다.
이러한 상황에서 데이크스트라는 프로그램의 올바름을 입증할 필요성을 느꼈고, 수학의 공리, 정리, 따름정리, 보조정리와 같은 개념을 차용하고자 한다. 즉 작은 단위의 입증된 코드들을 결합하여 전체 코드의 올바름을 입증하고자 하였다.
그런데 무분별한 goto문은 전체 프로그램을 작은 단위로 분해하는데 방해가 된 반면에 특정 방식으로 goto문을 사용하는 것은 오히려 도움이 되었다. 이러한 방식이 바로 분기문(if/then/else)과 반복문(do/while/until)이다.

 

자세한 증명 방식은 생략, 그러나 엄밀한 의미에서 증명은 아니다

 

그러나 증명은 없었다

사실상 프로그램에서 세세한 기능들을 엄밀하게 증명하는 것은 고된 작업이었고, 사실상 그러한 입증을 할 수는 없었다. 그러나 다이크스트라는 과학적 의미에서의 입증은 가능하다고 생각하였다. 즉 어떤 서술(여기선 프로그램)에 대해서 반례가 나오지 않았다면 그것은 목표에 부합할 만큼은 참이라고 여길 수 있다.

이런 관점에서 테스트를 얘기 하자면..

그런 의미에서 테스트는 해당 프로그램이 거짓임을 입증하려는 시도라고 볼 수 있다. 그러므로 테스트 코드가 통과했다면, 해당 프로그램은 목표한 기능에 대해서 만큼은 참이라고 말할 수 있다. 다시 말해 프로그램이 목표한 기능에 대해서 올바르게 동작할 것을 입증하였다고 볼 수 있다.

 

대신에 과학적 증명이 있었다.

 

요약(을 해보자면..)

  1. goto문이 난무하던 옛날(50-60년대)에도 프로그램의 실패가 잦았음.
  2. 다이크스트라라는 컴퓨터 과학자는 프로그램의 정상동작을 보장 할 방법으로 수학적 증명의 방법을 차용하였지만, 결국엔 과학적 증명방식을 창안함.
  3. goto문을 특정 방식으로 제약하면 프로그램의 (과학적)증명이 수월하였음.
  4. 그러한 제약 방식들이 분기문(if/then/else)과 반복문(do/while/until)임.

 

 

참고 문헌

  • 로버트C.마틴, 클린 아키텍처(소프트웨어 구조와 설계의 원칙), 인사이트, 송준이 옮김

+ Recent posts