1장 깨끗한 코드

코드가 존재하리라

코드는 요구사항을 표현하는 언어

나쁜 코드

  • 과거에 인기있던 한 프로그램이 제품 출시 주기가 늘어지고, 버그가 많이 생기고, 프로그램 시동 시간이 길어지고 프로그램이 죽는 횟수도 늘어나 고객들이 많이 떠나가고 결국 망했다. 회사가 망한 원인은 바로 나쁜 코드 탓이었다.

  • 다시 돌아와 나중에 정리하겠다고 다짐했었다.

  • 르블랑의 법칙 : 나중은 결코 오지 않는다.

나쁜 코드로 치르는 대가

  • 나쁜 코드가 쌓일수록 팀 생산성은 떨어진다. 그러다가 마침내 9에 근접한다.

태도

  • 좋은 코드를 사수하는 일은 프로그래머들의 책임이다.

  • 나쁜 코드의 위험을 이해하지 못하는 관리자 말을 그대로 따르는 행동은 전문가답지 못하다.

원초적 난제

  • 기한을 맞추는 유일한 방법(즉, 빨리 가는 유일한 방법)은 언제나 코드를 최대한 깨끗하게 유지하는 습관이다.

깨끗한 코드라는 예술?

  • 깨끗한 코드와 나쁜 코드를 구분할 줄 안다고 깨끗한 코드를 작성할 줄 안다는 뜻은 아니다.

  • 깨끗한 코드를 작성하려면 ‘청결’이라는 힘겹게 습득한 감각을 활용해 자잘한 기법들을 적용하는 절제와 규율이 필요하다. 열쇠는 ‘코드 감각’이다.

  • 코드 감각이 있는 프로그래머는 나쁜 모듈을 보면 좋은 모듈로 개선할 방안을 떠올린다. 코드 감각으로 최고 방안을 선택한 후 여기서 거기까지 이동하는 경로를 계획한다.

깨끗한 코드란?

비야네 스트롭스트룹

  • 보기에 즐거운 코드

  • 효율적인 코드

    속도도 포함되지만, CPU 자원을 낭비하지 않는 코드도 포함된다.

  • 코드를 망치려는 유혹을 주지 않는 코드

    나쁜 코드는 나쁜 코드를 유혹한다. (깨진 창문 이론)

    따라서 유혹하지 않게 애초에 깨끗한 코드를 작성해라

  • 철저한 오류를 처리하는 코드

    세세한 사항까지 꼼꼼하게 신경써라

    • 프로그래머들이 대충 넘어가는 부분 : 오류 처리, 메모리 누수, 경쟁 상태, 일관성 없는 명명법

  • 가지에 집중하는 코드

그래디 부치

  • 가독성이 좋은 코드

    깨끗한 코드는 잘 쓴 문장처럼 읽힌다.

  • 명쾌한 추상화

    코드는 추측이 아니라 사실에 기반해야 한다.

    반드시 필요한 내용만 담아야 한다.

데이브 토마스

  • 깨끗한 코드는 다른 사람이 고치기 쉽고 읽기 쉬운 코드

  • 테스트 케이스(단위 테스트, 인수 테스트)가 있는 코드

    아무리 코드가 우아해도, 아무리 가독성이 높아도, 테스트 케이스가 없으면 깨끗하지 않다.

  • 최소의 코드

    작을수록 좋다.

마이클 페더스

  • 누군가 시간을 들여 깔끔하고 단정하게 정리한 느낌을 주는 코드

론 제프리스

  • 모든 테스트를 통과한다.

  • 중복이 없다.

  • 시스템 내 모든 설계 아이디어를 표현한다.

  • 클래스, 메서드, 함수 등을 최대한 줄인다. → 최소한의 기능만 담으라는 의미인 것 같다.

어떤 집합에서 특정 항목을 찾아낼 필요가 자주 생긴다. 이런 상황이 발생하면 나는 추상 메서드나 추상 클래스를 만들어 실제 구현을 감싼다.

워드 커닝햄

  • 코드를 읽으면서 짐작했던 기능을 각 루틴이 그대로 수행한다면 깨끗한 코드라 불러도 되겠다.

  • 코드가 그 문제를 풀기 위한 언어처럼 보인다면 아름다운 코드라 불러도 되겠다.

보이스카우트 규칙

  • 적극적으로 코드의 퇴보를 막아야한다.

  • 잘 짠 코드가 전부가 아니다. 시간이 지나도 언제나 깨끗하게 유지해야 한다.

코드를 작성하기 이전의 코드보다 좀 더 깨끗한 코드를 작성한다면 코드는 절대 나빠지지 않는다. 한꺼번에 많은 시간과 노력을 투자해 코드를 정리할 필요가 없다. 변수 이름 하나를 개선하고, 조금 긴 함수 하나를 분할하고, 약간의 중복을 제거하고, 복잡한 if 문 하나를 정리하면 충분하다.

설계 원칙 SOLID

  • SRP(The Single Responsibility Principle): 클래스에는 한 가지, 단 한 가지 변경 이유만 존재해야 한다.

  • OCP(The Open Closed Principle): 클래스는 확장에 열려 있어야 하며 변경에 닫혀 있어야 한다.

  • LSP(The Liscov Substitution Principle): 상속받은 클래스는 기초 클래스를 대체할 수 있어야 한다.

  • DIP(The Dependency Injection Principle): 추상화에 의존해야 하며, 구체화에 의존하면 안 된다.

  • ISP(The Interface Segregation Principle): 클라이언트에 밀접하게 작게 쪼개진 인터페이스를 유지한다.

Last updated