Part 1 프로그래머를 위한 원칙

엔지니어의 자세

  • 자신감과 올바른 문제 해결 방법
    • “나는 이 문제를 올바른 방법으로 해결할 수 있다”는 믿음을 가져야 합니다.
    • 올바른 방법으로 구현하지 못하는 이유는 자원 부족 뿐이며, 이는 ‘상상할 수 없는 미지의 상황’도 포함됩니다.
    • 지속적인 학습과 기본 법칙에 대한 이해를 통해 올바른 방법을 찾아낼 수 있습니다.
  • 전문가의 도움 활용
    • 신뢰할 수 있는 시니어 엔지니어를 통해 기존 논의를 검토하고 관련 정보를 수집합니다.
    • 표준적이고 타당한 엔지니어링 절차를 따라 올바른 방법을 결정합니다.
  • 휴식의 중요성
    • 문제 해결이 어려울 때는 잠시 휴식을 취하고 마음의 여유를 확보합니다.
    • **“이 프로젝트는 올바르게 진행해야 해. 그러려면 일단 쉬자.”**라는 마음가짐이 필요합니다.

능력자 프로그래머의 한 가지 비밀

  • 자신이 하는 일을 제대로 이해하라
    • 뛰어난 프로그래머가 되기 위해서는 자신의 작업에 대한 깊은 이해가 필수적입니다.
    • 이는 문제 해결 능력을 향상시키고 더 효율적인 코드를 작성하는 데 도움이 됩니다.

Part 2  소프트웨어의 복잡성과 원인

복잡성의 단서

  • 코드가 정상 작동하려면 ‘꼼수’가 필요하다.

  • 다른 개발자들이 코드 사용에 어려움을 느껴 버그가 자주 발생한다.

  • 코드를 수정하는 일이 두렵게 느껴진다.

  • 구현 방식을 두고 팀 내에서 논쟁이 잦다.

위와 같은 단서는 코드의 복잡성이 높아져 유지보수와 확장성에 한계를 드러낸다는 신호입니다.

복잡성을 줄이는 방법: API 분리

• API 설계의 신중함

• 사용자 입장에서 API 사용 방식을 사전에 구체적으로 파악하고 반영해야 한다.

• 구현 전, 실제 사용 방법을 테스트하여 문제점을 발견한다.

• API 출시 전, 팀 내에서 작동 방식에 대한 합의를 이룬다.

• 하위 호환성에 대한 판단

• “이 기능이 향후 몇 년간 충분한 가치를 제공할까?“와 같은 질문으로 필요성을 평가한다.

• 새 기능 추가에 하위 호환성이 방해가 된다면 유지하지 않는 방안도 고려한다.

복잡성은 감옥이다

  • 복잡한 코드는 개발자를 그 업무에 묶어 두는 ‘감옥’이 될 수 있다.
  • 양심 없이 복잡한 코드를 후임에게 넘기는 일은 바람직하지 않다.
  • 개인의 성장과 삶의 균형을 위해 이해 가능성과 유지보수성을 높여야 한다.
  • **“가끔은 휴가도 가고 노래도 만들고 싶었다!”**는 개발자의 삶의 균형을 강조한다.

Part 3 단순성과 소프트웨어 설계

  • 설계는 프로젝트 초반에 하라

    • 처음부터 이해하기 쉽고 유지보수 가능한 단순한 구조를 목표로 설계해야 한다.
  • 미래 예측의 정확성

    • 복잡한 시스템일수록 미래 예측은 어려워지며, 이는 확률적인 문제이다.
    • 목표는 추상적 표현보다 ‘쉽게 이해하고 수정할 수 있는’ 것처럼 구체적이어야 한다.
  • 단순성과 엄격성

    • 단순함을 유지하는 과정에서 사용성이 저하될 수 있는 트레이드오프가 발생할 수 있다.
    • 입력이 두 가지 의미를 가질 수 있다면 사용자에게 선택권을 제공하거나 에러로 처리해야 한다.
  • 둘은 너무 많다

    • 반복되는 패턴이 보이면 즉시 포괄적 솔루션을 만들고, 복사-붙여넣기 대신 일관성을 지켜라.
    • 업데이트 시 ‘기억’에 의존하는 설계가 아닌, 자연스럽게 동작하는 시스템을 목표로 해야 한다.
    • 동일한 상수나 함수가 여러 개 존재하지 않도록 중복을 방지하라.
  • 리팩토링

    • 중복된 로직이 눈에 띄면 통합하라. 한 번에 통합할 수 없다면 두 개씩 병합하는 방식으로 진행하여 점진적 리팩토링을 수행한다.
  • 분별 있는 소프트웨어 설계

    • 변화는 작은 범위로 관리하고 각 단계마다 테스트를 거치며, 각 요소를 작고 간결하게 유지하여 전체 시스템의 단순함을 유지한다.

Part 4 디버깅

  • 버그? 버그의 원인?
    • 버그에는 프로그래머의 의도에 맞게 동작하지 않는 것, 프로그래머의 의도가 사용자의 평범하고 합리적인 기대를 충족시키지 않는 것도 포함된다.
    • 무슨 용도인지 적혀 있지 않은 버튼이 수백만 개 붙어있는 상자는 바르게 사용할 방법이 없다. 설사 사용 설명서를 꼼꼼히 읽은 뒤라 하더라도
    • 무슨 작업을 해야할 지, 그 코드를 어떻게 써야할지 아주 분명하고 정확하게 알 수 없다면 누군가는 실수할 것이다.
    • 내 코드를 보는 다른 사람의 관점을 이해하고 싶다면
      • 사용해본 적 없는 라이브러리에 대한 설명, 새로운 코드를 찾아서 읽어보라 그리고 프로그램 전체가 어떤 역할을 하는지 수정해야한다면 어떻게 할지 생각해보라.
    • 미래에 자신이 보는 코드를 볼 다른 프로그래머가 쉽게 알아볼 수 있는 코드를 쓰겠다는 책임감
  • 재발을 방지하라
    • 문제가 제대로 해결될 때까지 손보지 않아서, 코드베이스가 관리할 수 없는 지경에 이른다.
    • 아주 엉망인 코드베이스도 얼마든지 고칠 수 있다.
    • 해결의 기준은 ‘아무도 그 문제에 다시는 주의를 기울일 필요가 없을 정도가 되어야한다.‘
    • 테스트의 유지보수도 중요
      • 테스트의 유지 보수가 어려우면 개발자가 코드를 변경할 때 테스트도 너무 많이 달라져서 테스트 코드 자체가 수수께끼처럼 복잡해진다.

추가 정보 및 관련 내용

  • 코드의 단순성과 유지보수성
    • 코드의 복잡성은 오류를 증가시키고 팀의 생산성을 저하시킵니다.
    • 클린 코드 원칙을 따라 코드를 작성하면 유지보수가 쉬워집니다.
    • 함수와 모듈을 작은 단위로 분리하고, 명확한 네이밍과 주석을 통해 가독성을 높입니다.
  • 지속적인 학습과 협업
    • 기술은 빠르게 발전하므로 지속적인 학습이 중요합니다.
    • 팀 내에서 지식 공유와 코드 리뷰를 통해 협업을 강화합니다.
  • 하위 호환성과 기술 부채
    • 하위 호환성을 무조건 유지하려다 보면 기술 부채가 쌓일 수 있습니다.
    • 전략적인 판단을 통해 오래된 기능을 제거하거나 개선하는 것이 필요합니다.
  • 개발자 삶의 균형
    • 업무 외적인 삶의 균형을 유지하는 것은 장기적인 생산성과 창의성에 긍정적인 영향을 줍니다.
    • 번아웃을 예방하기 위해 적절한 휴식과 취미 활동이 중요합니다