[클린코드] 3장. 함수

MEUN·2022년 2월 22일
0

< CLEAN-CODE />

목록 보기
5/17
post-thumbnail

1 주차

화, 수 | Assignment #05

  • 📚 3장. 함수
  • ✔️ TIL

3장. 함수


📘 책에서 기억하고 싶은 내용

  • 함수를 작게 만들어라 (p.42)
    • if/else/while 문 등에 들어가는 블록은 가급적 한 줄이어야 함
    • 함수가 작아질 뿐만 아니라, 블록 내 호출되는 함수명을 적절히 짓는다면, 코드를 이해하기도 쉬워짐
  • 한 가지의 역할만 수행해라 (p.44)
    • "함수는 한 가지를 해야 한다. 그 한 가지를 잘 해야 한다. 그 한 가지만을 해야 한다."
    • 아래에 해당될 경우 그 함수는 한 가지 작업만을 수행함
      • 함수 하위에서 추상화 수준이 하나인 단계만 수행
      • 다른 표현이 아닌 의미 있는 이름으로 다른 함수로 더이상 추출 불가능
  • 함수 당 추상화 수준은 하나로 유지 (p.45)
    • 한 함수 내에 추상화 수준이 일관되지 않으면 특정 표현이 근본 개념, 세부사항 중 어디에 해당되는지 구분하기 어려워짐
      • 근본 개념과 세부사항을 섞기 시작하면 사람들이 점차 함수에 세부사항을 추가하게 됨
  • Switch 문 (p.47)
    • 본질적으로 switch 문 은 N가지의 기능을 처리하므로, 아래 문제점이 발생함
      • 함수가 길어짐
      • 한 가지 작업만 수행하지 않음
      • SRP 위반
      • OCP 위반
      • case 가 추가될 때마다 코드의 수정이 필요함
    • 추상 팩토리 패턴 을 사용하여 해결 가능
      • 추상 팩토리 내 switch 문을 사용해 case 에 따라 적절한 도메인 클래스의 파생 클래스의 인스턴스 리턴
  • 서술적인 이름 사용하라 (p.49)
    • 길고 서술적인 이름이 짧고 어려운 이름보다 좋다. (여러 단어가 쉽게 읽히는 명명법 사용)
    • 단, 일관성을 가지고 이름을 정해야 함
      • 모듈 내에서 함수명은 동일한 문구/명사/동사 사용
  • 함수 인수 (p.50)
    • 인수는 적을수록 좋음 (다른 사람들이 코드를 읽을 때 함수 호출을 이해하기 위해 함수별 인수를 모두 이해해야 하기 때문)
    • 인수가 적을수록 테스트 시에도 호출이 간단하여 용이함
    • 플래그 인수는 가급적 지양하는 대신 true/false 일 때를 나눠 함수를 각각 작성
    • 단항 함수의 경우, 인수의 순서 및 함수/인수의 의도를 제대로 표현하려면 함수와 인수가 동사/명사 쌍을 이루는 게 좋음
      • 예시) writeField(name)
  • 부수 효과(Side Effect)를 일으키지 마라 (p.55)
    • 한 함수 내 한 가지 역할만을 하도록 하거나 불가피하게 시간적인 결합이 필요한 경우 함수명에 분명히 명시
      • 시간적인 결합으로 처리 시 물론 함수가 한 가지만 수행해야 한다는 규칙은 위반하게 됨
    • 출력 인수를 지양하고 함수의 반환 값으로 사용
  • 명령과 조회를 분리하라 (p.56)
    • 함수는 객체 상태를 변경하거나 객체 정보를 반환하거나 둘 중 하나만 해야 함 (둘 다 할 경우, 아래와 같이 혼란을 초래함)
      • public boolean set(String attribute, String value); // 선언부
      • if (set("username", "unclebob")) ... // 실제 호출부
    • 명령과 조회를 분리해 혼란을 애초에 뿌리뽑아야 함
  • 오류 코드보다 예외를 사용하라 (p.57)
    • 오류 코드를 반환하는 방식은 명령/조회 분리 규칙을 미묘하게 위반하며, 표현식으로 사용하기 쉬운 탓에 여러 단계로 중첩되는 코드를 야기함, 예외를 사용하여 코드에서 분리가 필요함
      • 또한, 오류 코드 사용 시 의존성 자석이 당연히 생기게 되는데 예외를 사용할 경우 새로운 예외만 재컴파일/재배치 없이 클래스로 추가 가능
    • try/catch 블록의 trycatch 블록을 각각 별도 함수로 추출하는 것이 좋음 (코드 가독성 향상을 위함)
    • 오류 처리 함수는 오류만 처리하도록 해야 함
  • 반복하지 마라 (p.60)
    • 중복은 소프트웨어에서 모든 악의 근원
    • 중복을 없애면 모듈 가독성이 크게 높아지고, 코드 수정 시 변경해야 할 부분이 감소함
  • 구조적 프로그래밍 (p.61)
    • 구조적 프로그래밍은 함수가 아주 클 때만 큰 이익이 제공됨
      • 목표
        • 모든 함수와 함수 내 모든 블록 내 입구와 출구는 각각 하나여야 함
        • 루프 내 break, continue 는 사용하지 말아야 하고, goto 도 안된다.
    • 작은 함수의 경우, 반드시 지킬 필요 없음 (오히려 때로는 단일 입/출구 규칙보다 의도를 표현하기 쉬워짐)
      • 단, goto 문은 큰 함수에서만 의미가 있으므로, 작은 함수에서는 지양해야 함
  • 점진적으로 개선하라 (p.61)
    • 처음부터 이 장에서 설명한 규칙을 따르는 함수를 개발할 수는 없음
    • 원하는대로 읽힐 때까지 코드를 다듬어 완성해야 함

🤔 소감 및 생각

  • 함수를 깨끗하는 12가지의 방법에 대해서 이론적으로는 공감하지만 실제로는 실무에 당장 적용시켜보기 어려운 경우도 있을 것 같다는 생각이 들었다. 물론 그동안 업무를 진행하며 깨끗한 코드를 작성하지 못했다는 죄책감도 들어 반성했고 책에서 제시하는 방법이 새롭고 흥미롭게 느껴졌다. 하지만 예를 들어 기존 시스템에서 swtich 문 을 사용 시 추상 팩토리 패턴 을 사용하지 않았는데 신규 기능 추가 시에만 적용하는 것도 개인적으로 모호할 것 같았다. 따로 리팩토링 대상 항목을 정해 시스템을 개선하는 작업이면 상관없겠지만 일반적인 유지보수 시에는 바로 적용하기 어려운 방안도 있다고 느꼈다.
  • 자주 사용하는 디자인 패턴이 아니면 공부해도 자주 까먹는 것 같다는 생각이 들었다. 추후 제대로 다시 공부해서 책을 읽을 때 모르는 개념을 자주 검색하는 등 많은 방해가 되지 않도록 해야겠다.

🔍 새롭게 알게 된 내용

  • Fitnesse : 오픈 소스 테스트 도구
  • 추상화 수준 : 각 코드가 추상화 정도에 따라 분류되는 수준으로, 높음, 중간, 낮음 으로 분류됨
  • 추상 팩토리 패턴 : 구체적인 클래스에 의존하지 않고 서로 연관되거나 의존적인 객체들의 조합을 만드는 인터페이스를 제공하는 패턴
  • 시간적인 결합 : 시간을 수반하는 프로그램 또는 시스템 구성 요소 사이의 다양한 의존성
  • 순서 종속성 : 어떤 메소드 호출 시 다른 메소드 호출 전/후에 호출이 필요함, 반드시 정해져 있는 호출 순서를 의미
  • 의존성 자석 : 붙이기는 쉽지만 떼어내기는 쉽지 않은, 많은 곳에서 참조하는 어떠한 구조를 의미

0개의 댓글