////
Search
Duplicate
🎸

34. 소프트웨어 장인정신에 대한 주제

이 장은 복잡성과 추상화, 프로세스, 가독성과 같이 추상적인 주제를 소개한다.
이 주제는 해킹이냐 소프트웨어 개발의 장인 정신이냐를 다양한 관점에서 설명한다.

1. 복잡성

엔지니어의 주요 의무는 복잡성을 설명한 수준까지 줄이는 것이다. 모든 단계를 파악하고 적절한 해결책을 내놓을 수 있다면 이상적이겠지만 그런 두뇌는 없다.
컴퓨터 과학과 소프트웨어 공학은 그러한 복잡성을 처리하기 위한 여러 기법들을 개발했으며 다음과 같이 정리해볼 수 있다.
한 번에 시스템의 작은 부분에 집중할 수 있도록 하나의 시스템을 아키텍처 수준에서 서브시스템으로 나눈다.
클래스의 내부 작업을 알 필요가 없도록 인터페이스를 적절하게 잘 정의한다.
불필요한 사항을 기억할 필요가 없도록 인터페이스 수준의 추상화를 유지한다.
전역 데이터는 한 번에 살펴보아야할 코드의 범위를 넓히기 때문에 피한다.
깊은 상속 관계는 생각할 것이 많으므로 피한다.
여러 단계로 중첩되는 반복문과 조건문은 더 간단한 제어 구조로 대체할 수 있으니 사용하지 않는다.
서로 다른 오류 처리 기술을 사용하지 않고 일관된 접근 방법을 선택한다.
언어의 자체적인 내장 예외 메커니즘은 이해하기 난해한 구조를 만들어낼 수 있으므로 체계적으로 사용하도록 한다.
클래스가 너무 거대해지지 않도록 주의한다.
메소드를 간략하게 유지한다.
명확하고 설명이 없어도 충분한 변수 이름을 지어서 처음 본 사람이 보더라도 맥락을 쉽게 파악할 수 있도록 한다.
메소드에 전달되는 매개변수의 수를 최소화하고 메소드 시그니처의 추상화를 유지하는 데 필요한 매개변수만 사용하라.
서로 다른 코드의 차이점을 기억하느라 기억력을 낭비하지 말아라.
5장에서 언급한 부수적인 어려움을 해결한다.
복잡한 조건문의 내용을 함수로 구현하겨 테스트가 해결하고자 하는 문제를 추상화하면 코드를 좀 덜 복잡하게 작성할 수 있다.
명확하게 정의되고 일관성 있는 인터페이스를 만들면 인터페이스를 구현하는 구체 클래스를 신경쓰지 않아도 된다.
요컨데 소프트웨어 설계와 구현의 주요 목표는 복잡성을 정복하는 것이다. 많은 프로그래밍 습관의 일관된 목표는 프로그램의 복잡성을 줄이는 것이며 이는 효과적인 개발자가 되기 위한 핵심 요소다.

2. 자신에게 맞는 프로세스 선택

이 책에서 두 번째로 중요한 맥락은 소프트웨어를 개발하는 데 사용하는 프로세스가 매우 중요하다는 점이다.
작은 프로젝트에서는 개발자 개인의 능력이 품질에 가장 큰 영향을 끼친다. 그러나 한 명 이상의 개발자로 구성된 프로젝트에서는 조직적인 특성이 프로젝트에 참여한 개인의 능력보다 더 큰 영향을 끼친다.
프로세스가 중요하다는 것을 보여주는 한 가지 예는 설계와 코드 작성을 시작하기 전, 요구사항을 엄밀히 검토하여 견고하게 만들지 않았을 때의 결과다.
완벽한 요구사항을 말하는 것이 아니다. 요구사항이 어느정도로 견고해야 하는지 결정하라는 의미다. 이에 따라서 점진적으로 배포를 해나가며 수정하는 접근 방법을 택하는 등, 프로세스를 선택할 수 있다.
이러한 프로세스에 대한 의식적인 관심이라는 같은 원칙을 설계에도 적용해야 한다.
항상 올바른 순서대로 작업하고 있는가?, 순서를 바꾸면 결과가 달라질까?와 같은 생각을 가지고 의식적으로 훌륭한 프로세스를 따르도록 한다.
구현이나 요구사항에 한해지는 하위 수준 프로세스도 마찬가지다. 하향식 설계, 상향식 설계 등의 기법들을 적용해볼 수 있고 내게 좀더 적합했던 프로세스를 선택하도록 한다.
나븐 프로세스는 두뇌를 낭비한다. 좋은 프로세스는 두뇌를 최대한 활용할 수 있도록 한다.

3. 컴퓨터보다 사람을 위한 프로그램을 작성하라.

이 책에서 세 번째로 중요한 맥락은 코드의 가독성을 강조하는 것이다. 다른 사람과의 효율적인 의사소통을 위해 이해하기 쉬운 코드를 작성해야 한다.
컴퓨터는 가독성을 모른다. 사람들은 다른 사람들이 코드를 읽는데 도움이 되기 위해 가독성 있는 코드를 작성하려 한다. 가독성은 다음와 같은 측면에서 긍정적인 영향을 준다.
이해도
리뷰 용이성
오류 비율
디버깅
수정 용이성
개발 시간 - 상기 과정의 결과
외적 품질 - 상기 과정의 결과
프로젝트를 진행하는 사람이 나 혼자라고 가독성을 잠깐 놔도 괜찮은 것은 아니다. 기억력이 좋지 않은 이상 작성한 지 시간이 좀 된 코드는 까먹기 마련이다.
코드 작성이 끝나는 순간, 해당 코드는 프로젝트의 코드다. 작성한 사람의 코드가 아니다. 다만 작성자가 따로 있을 뿐이다. 따라서 코드는 읽기 쉽게 작성해야 한다.
이 책의 앞부분에서 가독성에 도움을 주는 훌륭한 클래스, 메소드 및 변수 이름, 신중한 형식화, 작은 코드, 불린 함수로의 추출, 복잡한 계산 중간 결괏값으로 단순화하기와 같은 기술들을 살펴 봤다.

4. 언어에 제약을 받지 않고 언어를 활용한 프로그래밍

프로그래밍의 모든 행위는 프로그래밍 언어가 기본적으로 제공하는 개념에 의해서 제약을 받지 않아야한다.
언어는 도구다.

5. 컨벤션을 활용하여 핵심에 집중

컨벤션은 복잡성을 관리하기 위해 사용하는 지적인 도구 중 하나다.
컨벤션을 통해 우리는 지적 활동들을 줄이고 핵심에 조금 더 자원을 집중할 수 있게 된다.
컨벤션을 이용하면 하위 수준 작업에 대해 예측이 가능하기 때문인데, 메모리 요청 처리와 오류 처리, 인터페이스에 대한 컨벤션이 있다면 그러한 구조들에 신경을 덜 쓰게 되고 핵심만 확인할 수 있다.
그렇다고 컨벤션을 과하게 이용하면 구현 과정에서 문제가 생긴다. 구현 과정에서 충분히 의미를 전달하기에 컨벤션을 지키느라 여력이 없을 수 있다.
뭐든 적당히 효과를 볼 정도로만 사용하자.

6. 문제 중심의 프로그래밍

복잡성을 다루는 또 다른 방법은 가능한 가장 높은 추상화 수준을 선택하여 작업하는 것이다.
이를 위한 하나의 방법은 컴퓨터 과학 자체의 해결책보다는 프로그래밍 문제 중심으로 작업하는 것이다.
최상위 수준의 코드가 파일과 스택, 큐, 배열과 같은 문자에 대한 세부 사항으로 채워져서는 안 된다. 해결하려는 문제를 기술해야 한다.

프로그램을 추상화 수준으로 나누기

당연히 특정 시점에선 구현 중심의 관점에서 작업해야 하지만 문제 도메인 관점으로 작업하는 부분에서 구현 수준 관점으로 작업하는 부분을 분리할 수 있다.
보통 프로그램을 설계한다면 다음과 같은 추상화 수준으로 고려할 수 있다.
고수준 문제 도메인 관점
문제를 다루는 추상적인 능력을 제공하는 수준으로 이 수준에서의 코드는 프로젝트의 이해 관계자가 읽을 수 있어야 한다.
이 수준의 코드는 프로그래밍 언어의 특정한 기능에 의존하지 않으며 밑의 수준에서 직접 작성한 도구에 의존한다.
저수준 문제 도메인 관점
문제 도에민의 관점에서 작업하는데 필요한 기초 정보를 가지게 된다.
이 수준은 아래의 컴퓨터 과학 구조와 위의 문제 도메인 코드 사이의 아교와 같은 역할을 하는 계층이다.
이 수준에서 코드를 작성하려면 도메인 영역에서 사용되는 어휘들을 찾아내 프로그램이 해결하려는 문제를 다루는 데 사용할 수 있는 블록을 생성해야 한다.
저수준 구현 구조
저수준 구현 구조는 언어 자체에 의해서 제공되는 것보다 약간 높은 수준의 구조다.
연산과 데이터 타입인데, 스택, 큐, 링크드 리스트, 트리 등이다.
프로그래밍 언어 구조와 도구
기본 데이터 타입, 제어 구조 등을 의미한다.
운영체제 연산과 기계 명령
고급 언어를 사용하고 있다면 신경쓰지 않아도 되는 영역이다.

문제 도메인에서 작업하기 위한 저수준 기법

문제 도메인 관점에서 의미있는 구조를 구현하기 위하여 클래스를 사용한다.
데이터 형에 대한 정보와 구현 세부 사항을 감춘다.
문자열과 숫자 리터럴의 의미를 기술하기 위하여 이름 상수를 사용한다.
중간 계산 결과를 기술하기 위하여 중간 변수를 할당한다.
복잡한 불린 테스트를 명료하게 하기 위해 불린 함수를 사용한다.

7. 낙석을 주의하라

컴퓨터 프로그래밍에서 좋은 판단을 내리기 위해서는 경고 표시와 프로그램 문제점 가능성을 나타내는 세밀한 표시에 민감해져야 한다.
프로그램에 대한 사고의 질이 프로그램의 질을 결정하기 때문에 사고의 질에 대한 경고에 주의를 길우이는 것은 최종 제품에 직접적인 영향을 준다.

8. 반복, 반복, 또 반복

반복은 많은 소프트웨어 개발 행위에 적합하다.
시스템 초기, 명세화 과정에는 모든 요구사항에 동의할 때까지 다양한 버전의 요구사항을 놓고 사용자와 작업하는 것도 포함된다. 이것은 반복적인 프로세스다.
최종 제품을 만들기 전, 빠르고 비용이 적게 드는 대안 해결책을 개발하기 위해 프로토타이핑 하는 것도 반복적인 프로세스다.
반복은 제품을 만들기 전에 제품에 대해서 알 수 있는 길을 제공한다.
소프트웨어 설계는 발견적 프로세스며 모든 발견적 프로세스처럼 반복적으로 개선하고 향상시켜야 한다.
공학에 대한 한 가지 정의는 1달러로 할 수 있는 일을 10센트에 하는 것이다.
늦은 단계의 반복은 1달러로 할 수 있는 일을 2달러로 하는 것과 같다.
소프트웨어 공학의 기교는 쓰고 버릴 수 있는 부분을 가능한 빨리, 적은 비용으로 만드는 것이다. 이것이 초기 단계의 반복의 요점이다.

9. 소프트웨어와 종교를 떼어 놓아라

특정한 설계나 해결 방법에 대한 교리적인 집착이나 확고한 믿음, 뭔가를 반드시 피하려는 모습 등의 형태를 띤다.

소프트웨어 신탁

최신 유행에 집착하기보다 여러 방법을 혼합하여 사용하라. 팀의 실정, 현실에 맞는 방법을 적절히 선택하라.

절충주의

하나의 방법만 고집하는 것은 해결책을 문제에 끼워맞추는 것이므로 해롭다.
독단적인 자세는 소프트웨어 구현에 대한 절충적인 도구 상자 접근 방법과 상충한다.

실험

핵심은 소프트웨어 개발의 모든 측면에 대해 열린 마음을 유지해야 한다는 것이다.
제품뿐만 아니라 프로세스에 대한 기술적인 정보를 얻어야 한다. 열린 마음으로 하는 실험과 기존에 정의된 접근 방법에 대한 신앙적인 고집은 적절하지 않다.

요점 정리

프로그래밍의 한 가지 중요한 목표는 복잡성을 관리하는 것이다.
프로그래밍 프로세스는 팀 단위의 특징으로 최종 제품에 큰 영향을 미친다.
팀 프로그래밍은 컴퓨터보단 사람들과의 의사소통 작업이다. 개인 프로그래밍은 컴퓨터보단 자신의 생각을 어떻게 풀어낼 것인가 자신과 소통하는 과정이다.
프로그래밍 컨벤션을 남용하면 병보다 더 나쁜 약이 될 수 있다. 하지만 신중하게 사용한다면 개발 환경에 가치 있는 구조를 추가하고 복잡성을 관리하여 의사소통에 도움이 되게 도와준다.
해결책보다는 문제의 관점에서 프로그래밍하는 것이 복잡성을 관리하는데 도움을 준다.
의심으로부터 오는 짜증과 같이 지적인 경고 표시를 주의하여 사고할 수 있는 기회를 얻으라.
각 개발 활동을 적절히 반복할수록 제품은 좋아진다.
독단적인 방법론과 품질이 뛰어난 소프트웨어는 어울리지 않는다. 지적인 도구 상자를 프로그래밍 대안으로 채우고 일에 맞는 올바른 도구를 선택할 수 있는 기술을 향상시켜라.