•
이 장은 복잡성과 추상화, 프로세스, 가독성과 같이 추상적인 주제를 소개한다.
•
이 주제는 해킹이냐 소프트웨어 개발의 장인 정신이냐를 다양한 관점에서 설명한다.
1. 복잡성
•
엔지니어의 주요 의무는 복잡성을 설명한 수준까지 줄이는 것이다. 모든 단계를 파악하고 적절한 해결책을 내놓을 수 있다면 이상적이겠지만 그런 두뇌는 없다.
•
컴퓨터 과학과 소프트웨어 공학은 그러한 복잡성을 처리하기 위한 여러 기법들을 개발했으며 다음과 같이 정리해볼 수 있다.
◦
한 번에 시스템의 작은 부분에 집중할 수 있도록 하나의 시스템을 아키텍처 수준에서 서브시스템으로 나눈다.
◦
클래스의 내부 작업을 알 필요가 없도록 인터페이스를 적절하게 잘 정의한다.
◦
불필요한 사항을 기억할 필요가 없도록 인터페이스 수준의 추상화를 유지한다.
◦
전역 데이터는 한 번에 살펴보아야할 코드의 범위를 넓히기 때문에 피한다.
◦
깊은 상속 관계는 생각할 것이 많으므로 피한다.
◦
여러 단계로 중첩되는 반복문과 조건문은 더 간단한 제어 구조로 대체할 수 있으니 사용하지 않는다.
◦
서로 다른 오류 처리 기술을 사용하지 않고 일관된 접근 방법을 선택한다.
◦
언어의 자체적인 내장 예외 메커니즘은 이해하기 난해한 구조를 만들어낼 수 있으므로 체계적으로 사용하도록 한다.
◦
클래스가 너무 거대해지지 않도록 주의한다.
◦
메소드를 간략하게 유지한다.
◦
명확하고 설명이 없어도 충분한 변수 이름을 지어서 처음 본 사람이 보더라도 맥락을 쉽게 파악할 수 있도록 한다.
◦
메소드에 전달되는 매개변수의 수를 최소화하고 메소드 시그니처의 추상화를 유지하는 데 필요한 매개변수만 사용하라.
◦
서로 다른 코드의 차이점을 기억하느라 기억력을 낭비하지 말아라.
◦
5장에서 언급한 부수적인 어려움을 해결한다.
•
복잡한 조건문의 내용을 함수로 구현하겨 테스트가 해결하고자 하는 문제를 추상화하면 코드를 좀 덜 복잡하게 작성할 수 있다.
•
명확하게 정의되고 일관성 있는 인터페이스를 만들면 인터페이스를 구현하는 구체 클래스를 신경쓰지 않아도 된다.
•
요컨데 소프트웨어 설계와 구현의 주요 목표는 복잡성을 정복하는 것이다. 많은 프로그래밍 습관의 일관된 목표는 프로그램의 복잡성을 줄이는 것이며 이는 효과적인 개발자가 되기 위한 핵심 요소다.
2. 자신에게 맞는 프로세스 선택
•
이 책에서 두 번째로 중요한 맥락은 소프트웨어를 개발하는 데 사용하는 프로세스가 매우 중요하다는 점이다.
•
작은 프로젝트에서는 개발자 개인의 능력이 품질에 가장 큰 영향을 끼친다. 그러나 한 명 이상의 개발자로 구성된 프로젝트에서는 조직적인 특성이 프로젝트에 참여한 개인의 능력보다 더 큰 영향을 끼친다.
•
프로세스가 중요하다는 것을 보여주는 한 가지 예는 설계와 코드 작성을 시작하기 전, 요구사항을 엄밀히 검토하여 견고하게 만들지 않았을 때의 결과다.
•
완벽한 요구사항을 말하는 것이 아니다. 요구사항이 어느정도로 견고해야 하는지 결정하라는 의미다. 이에 따라서 점진적으로 배포를 해나가며 수정하는 접근 방법을 택하는 등, 프로세스를 선택할 수 있다.
•
이러한 프로세스에 대한 의식적인 관심이라는 같은 원칙을 설계에도 적용해야 한다.
•
항상 올바른 순서대로 작업하고 있는가?, 순서를 바꾸면 결과가 달라질까?와 같은 생각을 가지고 의식적으로 훌륭한 프로세스를 따르도록 한다.
•
구현이나 요구사항에 한해지는 하위 수준 프로세스도 마찬가지다. 하향식 설계, 상향식 설계 등의 기법들을 적용해볼 수 있고 내게 좀더 적합했던 프로세스를 선택하도록 한다.
•
나븐 프로세스는 두뇌를 낭비한다. 좋은 프로세스는 두뇌를 최대한 활용할 수 있도록 한다.
3. 컴퓨터보다 사람을 위한 프로그램을 작성하라.
•
이 책에서 세 번째로 중요한 맥락은 코드의 가독성을 강조하는 것이다. 다른 사람과의 효율적인 의사소통을 위해 이해하기 쉬운 코드를 작성해야 한다.
•
컴퓨터는 가독성을 모른다. 사람들은 다른 사람들이 코드를 읽는데 도움이 되기 위해 가독성 있는 코드를 작성하려 한다. 가독성은 다음와 같은 측면에서 긍정적인 영향을 준다.
◦
이해도
◦
리뷰 용이성
◦
오류 비율
◦
디버깅
◦
수정 용이성
◦
개발 시간 - 상기 과정의 결과
◦
외적 품질 - 상기 과정의 결과
•
프로젝트를 진행하는 사람이 나 혼자라고 가독성을 잠깐 놔도 괜찮은 것은 아니다. 기억력이 좋지 않은 이상 작성한 지 시간이 좀 된 코드는 까먹기 마련이다.
•
코드 작성이 끝나는 순간, 해당 코드는 프로젝트의 코드다. 작성한 사람의 코드가 아니다. 다만 작성자가 따로 있을 뿐이다. 따라서 코드는 읽기 쉽게 작성해야 한다.
•
이 책의 앞부분에서 가독성에 도움을 주는 훌륭한 클래스, 메소드 및 변수 이름, 신중한 형식화, 작은 코드, 불린 함수로의 추출, 복잡한 계산 중간 결괏값으로 단순화하기와 같은 기술들을 살펴 봤다.
4. 언어에 제약을 받지 않고 언어를 활용한 프로그래밍
•
프로그래밍의 모든 행위는 프로그래밍 언어가 기본적으로 제공하는 개념에 의해서 제약을 받지 않아야한다.
•
언어는 도구다.
5. 컨벤션을 활용하여 핵심에 집중
•
컨벤션은 복잡성을 관리하기 위해 사용하는 지적인 도구 중 하나다.
•
컨벤션을 통해 우리는 지적 활동들을 줄이고 핵심에 조금 더 자원을 집중할 수 있게 된다.
•
컨벤션을 이용하면 하위 수준 작업에 대해 예측이 가능하기 때문인데, 메모리 요청 처리와 오류 처리, 인터페이스에 대한 컨벤션이 있다면 그러한 구조들에 신경을 덜 쓰게 되고 핵심만 확인할 수 있다.
•
그렇다고 컨벤션을 과하게 이용하면 구현 과정에서 문제가 생긴다. 구현 과정에서 충분히 의미를 전달하기에 컨벤션을 지키느라 여력이 없을 수 있다.
•
뭐든 적당히 효과를 볼 정도로만 사용하자.
6. 문제 중심의 프로그래밍
•
복잡성을 다루는 또 다른 방법은 가능한 가장 높은 추상화 수준을 선택하여 작업하는 것이다.
•
이를 위한 하나의 방법은 컴퓨터 과학 자체의 해결책보다는 프로그래밍 문제 중심으로 작업하는 것이다.
◦
최상위 수준의 코드가 파일과 스택, 큐, 배열과 같은 문자에 대한 세부 사항으로 채워져서는 안 된다. 해결하려는 문제를 기술해야 한다.
프로그램을 추상화 수준으로 나누기
•
당연히 특정 시점에선 구현 중심의 관점에서 작업해야 하지만 문제 도메인 관점으로 작업하는 부분에서 구현 수준 관점으로 작업하는 부분을 분리할 수 있다.
•
보통 프로그램을 설계한다면 다음과 같은 추상화 수준으로 고려할 수 있다.
◦
고수준 문제 도메인 관점
▪
문제를 다루는 추상적인 능력을 제공하는 수준으로 이 수준에서의 코드는 프로젝트의 이해 관계자가 읽을 수 있어야 한다.
▪
이 수준의 코드는 프로그래밍 언어의 특정한 기능에 의존하지 않으며 밑의 수준에서 직접 작성한 도구에 의존한다.
◦
저수준 문제 도메인 관점
▪
문제 도에민의 관점에서 작업하는데 필요한 기초 정보를 가지게 된다.
▪
이 수준은 아래의 컴퓨터 과학 구조와 위의 문제 도메인 코드 사이의 아교와 같은 역할을 하는 계층이다.
▪
이 수준에서 코드를 작성하려면 도메인 영역에서 사용되는 어휘들을 찾아내 프로그램이 해결하려는 문제를 다루는 데 사용할 수 있는 블록을 생성해야 한다.
◦
저수준 구현 구조
▪
저수준 구현 구조는 언어 자체에 의해서 제공되는 것보다 약간 높은 수준의 구조다.
▪
연산과 데이터 타입인데, 스택, 큐, 링크드 리스트, 트리 등이다.
◦
프로그래밍 언어 구조와 도구
▪
기본 데이터 타입, 제어 구조 등을 의미한다.
◦
운영체제 연산과 기계 명령
▪
고급 언어를 사용하고 있다면 신경쓰지 않아도 되는 영역이다.
문제 도메인에서 작업하기 위한 저수준 기법
•
문제 도메인 관점에서 의미있는 구조를 구현하기 위하여 클래스를 사용한다.
•
데이터 형에 대한 정보와 구현 세부 사항을 감춘다.
•
문자열과 숫자 리터럴의 의미를 기술하기 위하여 이름 상수를 사용한다.
•
중간 계산 결과를 기술하기 위하여 중간 변수를 할당한다.
•
복잡한 불린 테스트를 명료하게 하기 위해 불린 함수를 사용한다.
7. 낙석을 주의하라
•
컴퓨터 프로그래밍에서 좋은 판단을 내리기 위해서는 경고 표시와 프로그램 문제점 가능성을 나타내는 세밀한 표시에 민감해져야 한다.
•
프로그램에 대한 사고의 질이 프로그램의 질을 결정하기 때문에 사고의 질에 대한 경고에 주의를 길우이는 것은 최종 제품에 직접적인 영향을 준다.
8. 반복, 반복, 또 반복
•
반복은 많은 소프트웨어 개발 행위에 적합하다.
◦
시스템 초기, 명세화 과정에는 모든 요구사항에 동의할 때까지 다양한 버전의 요구사항을 놓고 사용자와 작업하는 것도 포함된다. 이것은 반복적인 프로세스다.
◦
최종 제품을 만들기 전, 빠르고 비용이 적게 드는 대안 해결책을 개발하기 위해 프로토타이핑 하는 것도 반복적인 프로세스다.
•
반복은 제품을 만들기 전에 제품에 대해서 알 수 있는 길을 제공한다.
•
소프트웨어 설계는 발견적 프로세스며 모든 발견적 프로세스처럼 반복적으로 개선하고 향상시켜야 한다.
•
공학에 대한 한 가지 정의는 1달러로 할 수 있는 일을 10센트에 하는 것이다.
◦
늦은 단계의 반복은 1달러로 할 수 있는 일을 2달러로 하는 것과 같다.
•
소프트웨어 공학의 기교는 쓰고 버릴 수 있는 부분을 가능한 빨리, 적은 비용으로 만드는 것이다. 이것이 초기 단계의 반복의 요점이다.
9. 소프트웨어와 종교를 떼어 놓아라
•
특정한 설계나 해결 방법에 대한 교리적인 집착이나 확고한 믿음, 뭔가를 반드시 피하려는 모습 등의 형태를 띤다.
소프트웨어 신탁
•
최신 유행에 집착하기보다 여러 방법을 혼합하여 사용하라. 팀의 실정, 현실에 맞는 방법을 적절히 선택하라.
절충주의
•
하나의 방법만 고집하는 것은 해결책을 문제에 끼워맞추는 것이므로 해롭다.
•
독단적인 자세는 소프트웨어 구현에 대한 절충적인 도구 상자 접근 방법과 상충한다.
실험
•
핵심은 소프트웨어 개발의 모든 측면에 대해 열린 마음을 유지해야 한다는 것이다.
•
제품뿐만 아니라 프로세스에 대한 기술적인 정보를 얻어야 한다. 열린 마음으로 하는 실험과 기존에 정의된 접근 방법에 대한 신앙적인 고집은 적절하지 않다.
요점 정리
•
프로그래밍의 한 가지 중요한 목표는 복잡성을 관리하는 것이다.
•
프로그래밍 프로세스는 팀 단위의 특징으로 최종 제품에 큰 영향을 미친다.
•
팀 프로그래밍은 컴퓨터보단 사람들과의 의사소통 작업이다. 개인 프로그래밍은 컴퓨터보단 자신의 생각을 어떻게 풀어낼 것인가 자신과 소통하는 과정이다.
•
프로그래밍 컨벤션을 남용하면 병보다 더 나쁜 약이 될 수 있다. 하지만 신중하게 사용한다면 개발 환경에 가치 있는 구조를 추가하고 복잡성을 관리하여 의사소통에 도움이 되게 도와준다.
•
해결책보다는 문제의 관점에서 프로그래밍하는 것이 복잡성을 관리하는데 도움을 준다.
•
의심으로부터 오는 짜증과 같이 지적인 경고 표시를 주의하여 사고할 수 있는 기회를 얻으라.
•
각 개발 활동을 적절히 반복할수록 제품은 좋아진다.
•
독단적인 방법론과 품질이 뛰어난 소프트웨어는 어울리지 않는다. 지적인 도구 상자를 프로그래밍 대안으로 채우고 일에 맞는 올바른 도구를 선택할 수 있는 기술을 향상시켜라.