로버트 C. 마틴의 클린 아키텍처를 읽고 책의 내용을 정리합니다.
프로그래밍은 어렵다
- 데이크스트라는 프로그래밍은 어렵고, 프로그래머는 프로그래밍을 잘하지 못한다는 사실을 인식했다.
- 모든 프로그램은 설령 단순할지라도 인간의 두뇌로 감당하기에는 너무 많은 세부사항을 담고 있었고 아주 작은 세부사항이라도 간과하면 프로그램이 동작하는 것처럼 보이더라도 결국엔 예상 외의 방식으로 실패하곤 했다.
수학적 증명
- 그는 수학적인
증명
이라는 방법으로 이 문제를 해결해 보려고 했다. 즉 프로그램이 올바름을 수학적인 증명으로 해결해 보려 했다.
- 그래서 그는 합리적으로 무언가를 증명하는데 필수적인 기법인
분할 정복 접근법
을 적용하려 했다.
GOTO 문장의 해로움
- 그는 분할 정복 접근법을 적용하는데 goto 문장이 해롭다는 것을 알게 되었다.
- goto 문장은 모듈을 더 작은 단위로 재귀적으로 분해하는 과정에 방해가 되었다.
구조적 프로그래밍
- 반면 그는 goto 문을 좋은 방식으로 (예를 들면 if/then/else 또는 do/while 과 같은) 사용한다면 소프트웨어를 증명 가능한 단위로 재귀적으로 세분화 할 수 있다고 생각했다.
- 그리고 이러한 제어 구조는 순차 실행과 결합했을 때 특별하다는 사실을 깨달았다.
- 이러한 제어 구조는 뵘과 야코피티가 데이크스트라보다 2년 앞서 발견했는데, 이 두명은 모든 프로그램을 순차(sequence), 분기(selection), 반복(iteration) 세 가지 구조만으로 표현할 수 있다는 사실을 증명했다.
- 이 발견은 실로 놀라웠다. 즉, 모듈을 증명 가능하게 하는 바로 그 제어 구조가 모든 프로그램을 만들 수 있는 제어 구조의 최소 집합과 동일하다는 사실이었다. 구조적 프로그래밍은 이렇게 탄생했다.
기능적 분해
- 구조적 프로그래밍을 통해 모듈을 증명 가능한 더 작은 단위로 재귀적으로 분해할 수 있게 되었고, 이는 결국 모듈을 기능적으로 분해할 수 있음을 뜻했다.
- 즉 거대한 문제 기술서를 받더라도 문제를 고수준의 기능들로 분해할 수 있다.
- 그리고 이들 각 기능은 다시 저수준의 함수들로 분해할 수 있고, 이러한 분해 과정을 끝없이 반복할 수 있다.
- 게다가 이렇게 분해한 기능들은 구조적 프로그래밍의 제한된 제어 구조를 이용하여 표현할 수 있다.
- 이들 기법을 사용하면 프로그래머는 대규모 시스템을 모듈과 컴포넌트로 나눌 수 있고, 더 나아가 모듈과 컴포넌트는 입중할 수 있는 아주 작은 기능들로 세분화할 수 있다.
증명의 실패
- 데이크스트라는 그러나 결국 증명을 이루어내지 못했다.
- 다행히도 무언가가 올바른지 입증할 때 사용하는 전략에 엄밀한 수학적 증명만이 있는 것은 아니다.
- 상당히 성공한 또 다른 전략으로는 과학적 방법이 있다.
과학이 구출하다
- 과학은 근본적으로 수학과는 다른데, 과학 이론과 법칙은 그 올바름을 절대 증명할 수 없기 때문이다.
- 과학적 방법은 반증(어떤 사실이나 주장이 옳지 아니함을 그에 반대되는 근거를 들어 증명함)은 가능하지만 증명은 불가능하다.
- 그럼에도 우리는 매일매일 이들 법칙에 모든걸 건다. 자동차를 탈 때마다 F = ma 가 세상이 움직이는 방식을 설명하는 믿을 만한 법칙이라는 데 생사를 건다.
- 결론적으로 수학은 증명 가능한 서술이 참임을 입증하는 원리지만 과학은 증명 가능한 서술이 거짓임을 입증하는 원리라고 할 수 있다.
소프트웨어 테스트
- 데이크라는 "테스트는 버그가 있음을 부여줄 뿐, 버그가 없음을 보여줄 수 었다"고 말한적이 있다.
- 테스트에 충분한 노력을 들였다면 테스트가 보장할 수 있는 것은 프로그램이 목표에 부합할 만큼은 충분히 참이라고 여길 수 있게 해주는 것이 전부다.
- 소프트웨어는 수학적인 구조를 다루는 듯 보이지만, 오히려 과학과 같다. 최선을 다하더라도 올바르지 않음을 증명하는 데 실패함으로써 올바름을 보여주기 때문이다..
- 구조적 프로그래밍은 프로그램을 증명 가능한 세부 기능 집합으로 재귀적으로 분해할 것을 강요한다. 그러고 나서 테스트를 통해 증명 가능한 세부 기능들이 거짓인지를 증명하려고 시도한다. 이처럼 거짓임을 증명하려는 테스트가 실패한다면, 이 기능들은 목표에 부합할 만큼은 충분히 참이라고 여기게 된다.
결론
- 구조적 프로그래밍이 오늘날까지 가치 있는 이유는 프로그래밍에서 반증 가능한 단위를 만들어 낼 수 있는 바로 이 능력 때문이다.
- 아키텍처 관점에서는 기능적 분해를 최고의 실천법 중 하나로 여기는 이유이기도 하다.
- 소프트웨어 아키텍트는 모듈, 컴포넌트, 서비스가 쉽게 반증 가능하도록(테스트하기 쉽도록) 만들기 위해 분주히 노력해야 한다.