028. (Clean Architecture) 4. 구조적 프로그래밍

4. 구조적 프로그래밍

4.1. 증명

에츠허르 다익스트라(Edsger Wybe Dijkstra)가 초기에 인식한 문제는 프로그래밍이 어렵고, 프로그래머는 프로그래밍을 잘하지 못한다는 사실이었다.

모든 프로그램은 단순할지라도 인간이 감당하기엔 너무 많은 세부사항을 가지고 있었고,

아주 작은 세부사항이라도 누락하면 동작하는 것처럼 보이나 결국엔 예상하지 못한 방식으로 실패를 거듭했다.

이에 다익스트라는 증명이라는 수학적 원리를 이용하여 이를 해결하고자 하였다.

이는 프로그래머가 입증된 구조를 이용하고, 이들 구조를 코드와 결합시키며, 그래서 코드가 올바르다라는 사실을 증명하는 방식이었다.

다익스트라는 이 연구를 진행하면서 goto 문장이 모듈을 더 작은 단위로 재귀적으로 분해하는 과정을 방해한다는 사실을 발견하였다.

만약 모듈을 분해할 수 없는 경우 분할 정복 접근법을 통한 증명을 사용할 수 없게 되기 때문에 goto는 해롭다는 사실을 알아챈 것이다.

좀 더 정확히는 if, then, else에 해당하는 분기와 do, while에 해당하는 반복이라는 단순한 제어구조에서만 이롭다는 것을 발견한 것이다.

모듈이 이러한 종류의 제어 구조만을 사용한다면 증명 가능한 단위로 모듈을 재귀적 세분화하는 것이 가능하다고 생각했다.

결과적으로 다익스트라는 단순한 열거법을 이용해 순차 구문이 올바름을 입증할 수 있다는 사실을 증명하였으며,

모든 프로그램을 순차, 분기, 반복이라는 세 가지 제어 구조만으로 표현할 수 있다는 기존 증명과 결합하여 구조적 프로그래밍의 탄생으로 이어졌다.

참고 위의 기존 증명은 뵘과 야코피니의 Flow diagrams, turing machines and languages with only two formation rules 라는 논문이다.
논문을 읽고 싶다면 이 링크 를 참고하면 된다.

참고 위에서 발표한 논문은 GOTO 문의 해로움(Go To Statement Considered Harmful) 이 라는 논문이다.
논문을 읽고 싶다면 이 링크 를 참고하면 된다.

4.2. 기능적 분해

구조적 프로그래밍을 통해 모듈을 증명 가능한 더 작은 단위로 재귀적으로 분해할 수 있었고, 이는 결국 모듈을 기능적으로 분해할 수 있음을 뜻했다.

따라서 거대한 요구사항도 고수준의 기능들로 분해하고, 고수준의 기능도 저수준의 함수로 분해하는 과정을 반복하여 해결할 수 있었다.

이 기법은 대규모 시스템을 모듈과 컴포넌트로 나누고, 각 모듈과 컴포넌트는 입증 가능한 작은 기능들로 세분화하는 역할을 했다.

4.3. 테스트

다익스트라는 “테스트는 버그가 있음을 보여줄 뿐, 버그가 없음을 보여줄 수는 없다.” 라고 발언한 적이 있다.

다시 말해 프로그램이 잘못되었음을 증명할수는 있지만 맞다고 증명할수는 없던 것이다.

이는 프로그램이 아무리 수학적인 구조를 다루더라도 수학적인 시도가 아님을 반증하며, 입증이 불가능한 프로그램은 아무리 많은 테스트를 하더라도 올바름을 증명할 수 없음을 시사한다.

결국 구조적 프로그래밍은 프로그램을 증명 가능한 세부 기능 집합으로 계속해서 분해할 것을 개발자에게 강요하며, 분해한 결과에 한정해서만 테스트를 통한 증명을 시도할 뿐이다.