좋은 코드, 나쁜 코드 [1장]
코드 품질
- 고품질 코드
- 신뢰할 수 있는 코드
- 유지보스가 용이
- 버그가 적은 소프트웨어를 생산
- 요구사항에 유연하게 대처
- **저품질 코드**
- 요구사항 에 대규모의 코드 변경 및 리팩터링이 필요
- 시스템이 미리 정의되지 않은 상태에 놓이고 손상될 가능성이 있음
- 코드는 어떻게 소프트웨어가 되는가
- 코드는 일반적으로 엔지니어가 작성하자마자 실제로 실행되는 소프트웨어가 되지 않는다.
- 코드가 의도한 대로 작동하고 기존의 기능이 여전히 잘 동작하기 위해서 다양한 과정과 점검이 이루어진다.
- 이러한 과정을 소프트웨어 개발 및 배포 프로세스라고 한다.
- 코드베이스 : 소프트웨어를 빌드할 수 있는 코드가 저장된 저장소
- git, subversion, perfore와 같은 형상 관리 시스템으로 관리됨
- 코드 제출 : 코드 커밋, 풀 요청 병합이며 일반적으로 코드베이스를 자신의 로컬 컴퓨터에 복사하고, 여기서 코드를 변경하며 코드를 메인 코드베이스에 제출한다.
- 코드 검토 : 코드 리뷰 과정이며 다른 엔지니어가 변경된 내용을 검토하도록 한다. 코드 작성자가 놓친 문제를 점검할 수 있다.
- 제출 전 검사 : 병합 전 혹(pre-merge hook), 병합 전 점검(pre-merge check), 커밋 전 점검(pre-commit check)라고 하며, 테스트가 실패하거나 코드가 컴파일되지 않을 경우 변경 사항이 코드베이스에 병합되지 않도록 차단한다.
- 배포(release) : 소프트웨어는 코드베이스의 스냅숏을 기반으로 빌드된다. 다양한 품질 보증 검사 후 실제 실행 환경에 배포되며, 특정 버전을 가져와서 배포하는 프로세스를 배포 브랜치 만들기(cutting release)라는 문구를 자주 사용한다.
- 프로덕션 : 소프트웨어가 서버나 시스템에 배포될 때, 테스트 환경과 같이 내부적으로 사용하는 것이 아닌 실제 서비스되는 환경을 가리킨다. 소프트웨어가 비즈니스 관련 작업을 수행하면 프로덕션 환경에서 실행된다고 할 수 있다.
- 코드는 작동 되어야 한다.
- 코드는 변경된 요구 사항에 적응할 수 있어야 한다.
- [요구사항이 변하는 과정]
- 비즈니스 환경이 변한다.
- 사용자 선호가 변한다.
- 가정이 더 이상 유효하지 않다.
- 새로운 기능이 계속 추가된다.
- [요구사항이 변하는 과정]
- 코드는 이미 존재하는 기능을 중복 구현해서는 안 된다.
- [파일을 다시 저장하는 경우 아래와 같은 환경이 발생]
- 파일에서 바이트 데이터를 로드
- 바이트 데이터를 분석해서 이미지 형식으로 변환
- 이미지를 흑백으로 변환
- 이미지를 다시 바이트로 변환
- 바이트 데이터를 파일로 저장
- 이는 대부분 프로그래밍 언어에서 지원하거나, 라이브러리가 존재한다.
- 이를 재사용하여 아래와 같은 이점을 얻을 수 있다.
- 시간과 노력을 절약
- 버그 가능성 감소
- 기존 전문지식 활용
- 코드 이해가 쉬워짐
- [파일을 다시 저장하는 경우 아래와 같은 환경이 발생]
- **코드 품질의 핵심 요소**
- 코드는 읽기 쉬워야 한다.
- 요구사항 변경이나 디버깅이 필요할 때, 누군가가 내 코드를 이해하려 할 것이다.
- 올바른 추상화 계층을 정의하는 것이 코드의 가독성에 도움이 된다.
- 코드는 예측 가능해야 한다.
- 코드가 무슨 일을 하는지, 입력값으로 무엇을 예상하는지, 무엇을 반환하는지에 대한 정신 모델을 구축해야 한다.
- 아무리 좋은 의도를 가진 코드라도 예측할 수 없는 일을 한다면, 그 상황에 대처할 생각을 하지 못할 것이다.
- 코드를 오용하기 어렵게 해야 한다.
- 코드를 모듈화 해야한다.
- 모듈화는 개체나 시스템의 구성 요소가 독립적으로 교환되거나 교체될 수 있음을 의미한다.
- 모듈화 된 시스템의 주요 특징 중 하나는 인터페이스가 잘 정의되어 서로 다른 구성 요소 간 상호작용하는 지점이 최소화된다는 점이다.
- 이는 변화하는 요구사항에 더 쉽게 적응할 수 있는 코드를 작성하는 데 도움이 된다.
- 코드를 재사용 가능하고 일반화할 수 있게 작성해야 한다.
- 재사용성과 일반화성은 다른 개념을 가지고 있다.
- 재사용성 : 어떤 문제를 해결하기 위한 무언가가 여러 가지 다른 상황에서도 사용될 수 있음을 의미
- 일반화성 : 개념은 유사하나 서로 미묘하게 다른 문제들을 해결할 수 있음을 의미
- 드릴의 경우 구멍을 뚫는 다는 기능이 있어서 여러 곳에 적용할 수 있다. (재사용성)
- 드릴이 앞에 파츠만 교체한다면 나사도 박을 때 사용 가능하다 (일반화성)
- 재사용성과 일반화성은 다른 개념을 가지고 있다.
- 테스트가 용이한 코드를 작성하고, 제대로 테스트 해야한다.
- 단위 테스트 : 개별 함수나 클래스와 같은 작은 단위의 코드를 테스트한다.
- 통합 테스트 : 시스템이 여러 구성 요소, 모듈, 하위 시스템으로 구성될 때, 구성 요소와 하위 시스템을 함께 연결하는 과정
- 종단간 테스트 : 처음부터 끝까지 전체 소프트웨어 시스템에서 작동되는 흐름을 테스트한다.
- **테스트 용이성** : 테스트 대상이 되는 실제 코드를 가리키며 해당 코드가 얼마나 테스트하기 적합한지를 나타낸다.
- 코드를 다 작성하고 테스트하는 것은 용이하지 않다.
- 어떻게 테스트할 것인가를 계속 자문하는 것이 좋다.
- 코드는 읽기 쉬워야 한다.
- 고품질 코드 작성은 일정을 지연시키는가?
- 적절한 방법과 임시변통인 방법에 대해 생각해야 한다.
- 장기적인 방법이 더 번거로움을 줄여줄 가능성이 크다.
- 코드 품질을 고려하지 않고 먼저 떠오르는 대로 코딩하는 것을 피해야 한다.
- 좋은 소프트웨어를 만들려면 고품질 코드를 작성해야 한다.
- 실제 서비스 환경에서 실행되려면 일반적으로 여러 단계의 검사와 테스트를 통과해야 한다.