Skip to main content

1장 깨끗한 코드

1. 📌 핵심 개념 정리

✅ 요약하기

프로그래밍은 기계가 실행할 정도로 상세하게 요구사항을 명시하는 작업이며, 코드 없이는 요구사항을 충분히 표현하기 어렵다.
따라서 우리는 좋은 코드와 나쁜 코드를 구분하고, 나쁜 코드를 좋은 코드로 바꾸는 실력을 길러야 한다.

  1. 나쁜 코드

    • 대충 짠 코드의 문제점
      • 일정에 쫒겨서, “나중에 리팩토링하자”는 핑계로 대충 작성한 코드는 처음엔 생산성이 높아 보이지만, 시간이 지날수록 수정 시 엉뚱한 부작용을 일으키며 생산성이 0에 수렴한다.
      • 개발자가 기한을 맞추기 위해 나쁜 코드를 양산하면, 그 책임은 전적으로 프로그래머에게 돌아오며, 고객이나 관리자의 요구를 무조건 따르는 행동은 전문가답지 못하다.
    • 팀과 시스템에 미치는 영향
      • 나쁜 코드가 쌓이면 팀 전체의 생산성이 급격히 저하된다.
      • 새 인력이 추가되어도 시스템 설계에 대한 이해 부족으로 인해 오히려 나쁜 코드를 더 생산하게 된다.
    • 코드의 불멸성
      • "앞으로 코드가 사라질 가망은 없다"는 점에서, 한 번 작성된 코드는 시간이 지나도 계속 영향을 미치므로 처음부터 올바른 설계가 필수적이다.
  2. 깨끗한 코드 (좋은 코드)

    • 기본 특성
      • 간단하고 읽기 쉬운 코드: 코드는 단순하며, 다른 사람이 읽고 고치기 쉬워야 한다.
      • 중복 제거와 명확한 역할 분담: 각 함수, 클래스, 모듈은 한 가지 역할만 수행해야 하며, 표현력 있는 이름을 사용해 중복을 줄인다.
      • 초반부터 간단한 추상화 고려: 인터페이스나 추상 클래스를 먼저 정의하여, 나중에 세부 구현이 변경되어도 외부 코드에 영향을 최소화한다.
      • 주의 깊게 작성: 자신이 저자이자 독자라고 생각하며, 오류 처리 등 세세한 부분까지 꼼꼼하게 신경쓴다.
    • 유명 프로그래머들의 견해
      • 비야네 스트롭스트룹: 깨끗한 코드는 세세한 부분까지 꼼꼼하게 처리하며 한 가지에 집중해야 한다.
      • 그래디 부치: 코드에는 반드시 필요한 내용만 담아, 읽는 이에게 코드의 의도를 명확하게 전달해야 한다.
      • 데이브 토마스: 읽기 쉽고 고치기 쉬운 코드가 바로 깨끗한 코드이다.
      • 마이클 페더스: 깨끗한 코드는 누군가 주의 깊게 짰다는 인상을 주어야 한다.
      • 론 제프리스: 중복을 피하고 한 기능만 수행하며 작게 추상화하여 의도를 명확히 해야 한다.
      • 워드 커닝햄: 코드를 읽으면서 짐작했던 기능을 그대로 수행한다면 그 코드는 깨끗하다고 볼 수 있다.
    • 좋은 코드 작성 실천 방안
      • 보이스카우트 규칙:
        "캠프장은 처음 왔을 때보다 더 깨끗하게 해놓고 떠나라."
        코드를 수정할 때마다 작게라도 개선하며, 변수 이름 개선, 긴 함수 분할, 중복 제거, 복잡한 조건문 정리 등으로 지속적으로 깨끗함을 유지한다.
      • 자신이 저자라 생각하고 작성: 독자들을 고려하여 우아하고 효율적인 코드를 작성한다.
      • 인터페이스 기반 개발 & 프로토타이핑 후 점진적 개선
        • 코드의 유연성 유지: 특정 기능이 완벽히 구현되지 않아도, 인터페이스나 추상 클래스를 통해 외부 코드가 사용할 수 있도록 한다.
        • 일관된 설계 방향 유지: 추상화된 메서드를 먼저 정의하면 팀원들이 기능의 목표와 사용 방식을 쉽게 이해할 수 있다.
        • TDD와의 연계: 인터페이스/추상 클래스를 먼저 작성하고 목(Mock) 객체를 활용해 테스트 가능한 구조를 만든다.

2. 🤔 이해가 어려운 부분

🔍 질문하기

  1. 한가지를 잘 아는 코드

    • 어려웠던 부분
      • 함수, 클래스, 모듈이 주변 상황에 현혹되지 않고 한 가지 역할에 집중하는 코드의 의미.
    • 궁금한 점
      • 의존성을 최대한 줄여 한 기능만 수행하게 한다면, 클래스와 메서드가 무수히 많아지지 않을까? 그 중간 선은 무엇인가?
  2. 명쾌한 추상화

    • 어려웠던 부분
      • 모순적인 단어들을 합쳐서 깨끗한 코드의 특징을 나타낸 점과, 코드가 추측이 아닌 사실에 기반해야 한다는 의미.
    • 궁금한 점
      • 명쾌한 추상화가 구체적으로 어떻게 구현되는지 예시가 필요하다.
  3. 작게 추상화하라!

    • 어려웠던 부분
      • 함수를 더 작은 단위로 분리하고, 각 요소가 명확한 역할을 가지도록 설계하는 방법.
    • 이해한 점
      • 짧고 명확한 함수는 읽기 쉽고 유지보수하기 좋으며, 재사용 가능성과 변경에 유연한 코드를 만든다.
  4. 프리퀄과 원칙 (SOLID 원칙 관련)

    • 어려웠던 부분
      • SRP, OCP, DIP 등 다양한 설계 원칙에 대한 이해 부족.
    • 궁금한 점
      • “ppp의 프리퀄”이란 정확히 무엇을 의미하는가?
  5. 마이클 페더스가 말한 깨끗한 코드

    • 어려웠던 부분
      • "누군가 주의 깊게 짰다는 인상"이 구체적으로 어떤 코드를 의미하는지 파악하기 어렵다.
    • 궁금한 점
      • 주의 깊게 짰다는 인상을 주는 코드의 구체적인 특징은 무엇인가?
  6. 보이스카우트 규칙의 실제 적용

    • 궁금한 점
      • 코드를 수정할 때마다 작게라도 개선하라는 보이스카우트 규칙은, 사람마다 깨끗한 코드 기준이 달라 현실적으로 적용하기 어려운데, 이를 보완할 수 있는 대안은 무엇인가?
  7. 론 제프리스의 클린 코드와 초반 간단한 추상화

    • 어려웠던 부분
      • 초반부터 간단한 추상화를 고려하는 방식이 과도한 추상화로 이어져 코드가 불필요하게 많아지지 않을까 하는 우려.
    • 궁금한 점
      • 해당 방식의 구체적인 장점과 실제 적용 사례는 무엇인가?

3. 📚 참고 사항

📢 논의하기

  1. 관련 자료 공유

  2. SOLID 원칙

    • SRP (단일 책임 원칙): 각 클래스가 하나의 역할만 담당하여 유지보수가 용이해진다.
    • OCP (개방-폐쇄 원칙): 확장에는 열려 있고, 수정에는 닫혀 있어야 한다.
    • LSP (리스코프 치환 원칙): 자식 클래스는 부모 클래스로 대체할 수 있어야 한다.
    • DIP (의존 역전 원칙): 상위 모듈은 하위 모듈에 의존하면 안 되며, 인터페이스나 추상 클래스에 의존해야 한다.
    • ISP (인터페이스 분리 원칙): 클래스가 자신이 사용하지 않는 메서드에 의존하지 않도록, 인터페이스를 세분화하여 특정 클라이언트가 불필요한 기능을 강제로 구현하지 않게 해야 한다.