[클린 코드] TIL(Today I Learned) DAY 4~5

soleil_lucy·2024년 1월 29일
0

TIL (2024.01.29~30)

DAY 4~5

  • 오늘 읽은 범위: 3장 함수

Summary

함수를 잘 만드는 방법?!
1. 작게 만들어라
2. 한 가지만 해라
3. 함수당 추상화 수준은 하나로
4. switch 문 사용 지양하라
5. 서술적인 이름을 사용하라
6. 함수 인수(0개가 이상적이다)
7. 부수 효과를 일으키지 마라
8. 명령과 조회를 분리하라
9. 오류 코드보다 예외를 사용하라
10. 반복하지 마라
11. 구조적 프로그래밍

책에서 기억하고 싶은 내용

3장 함수

  • 어떤 프로그램의 가장 기본적인 단위 === 함수
    Q. 의도를 분명히 표현하는 함수를 어떻게 구현할 수 있을까?
    Q. 함수에 어떤 속성을 부여해야 처음 읽는 사람이 프로그램 내부를 직관적으로 파악할 수 있을까?

  • 이번 장에서 배울 것?
    함수를 잘 만드는 법

[1] 작게 만들어라!

  • 각 함수가 너무도 명백하도록 만들어라

  • 각 함수가 이야기 하나를 표현하도록 만들어라

  • 각 함수가 너무도 멋지게 다음 무대를 준비하도록 만들어라

  • 블록과 들여쓰기
    if 문/ else 문/ while 문 등에 들어가는 블록은 한줄이어야 함
    중첩 구조가 생길만큼 함수가 커져서는 안된다
    함수에서 들여쓰기수준은 1단이나 2단을 넘어서는 안 된다

[2] 한 가지만 해라!

  • 함수는 한 가지를 해야 한다. 그 한 가지를 잘 해야 한다. 그 한 가지만을 해야 한다
  • 함수를 만드는 이유?
    • 큰 개념을 다음 추상화 수준에서 여러 단계로 나눠 수행하기 위해서

[3] 함수당 추상화 수준은 하나로!

  • 함수가 확실히 한 가지 작업만 하려면 함수 내 모든 문장의 추상화 수준이 동일해야 한다
  • 위에서 아래로 코드 읽기: 내려가기 규칙
    • 코드는 위에서 아래로 이야기처럼 읽혀야 좋다
  • 핵심은 짧으면서도 한 가지만 하는 함수다

[4] Switch 문

  • switch 문?
    • N가지를 처리함
  • switch 문을 사용하는 경우?
    • 다형적 객체를 생성할 때, 상속 관계로 숨긴 후에는 절대로 다른 코드에 노출하지 않음

[5] 서술적인 이름을 사용하라!

  • 함수가 작고 단순할수록 서술적인 이름을 고르기 쉬워진다
  • 함수 이름을 정할 때는 여러 단어가 쉽게 읽히는 명명법을 사용한 후 여러 단어를 사용해 함수 기능을 잘 표현하는 이름을 선택한다
  • 서술적인 이름을 사용할 때의 이점?
    • 개발자 머릿속에서도 설계가 뚜렷해지므로 코드를 개선하기 쉬워진다
  • 이름을 붙일 때는 일관성이 있어야 한다
    • Example
      includeSetupAndTeardownPages
      includeSetupPages
      includeSuiteSetupPage
      includeSetupPage

[6] 함수 인수

  • 함수에서 이상적인 인수 개수는 0개(무항)
  1. 단항 형식

    • 함수에 인수 1개를 넘기는 이유는?
      • 인수에 질문을 던지는 경우 Ex) boolean fileExists("MyFile")
      • 인수를 뭔가로 변환해 결과를 반환하는 경우 Ex) InputStream fileOpen("MyFile")
  2. 플래그 인수(사용하지 마세요)

    • 플래그 인수를 사용하지 말아야하는 이유?

      • 함수가 한꺼번에 여러 가지를 처리한다고 대놓고 공표하는 셈

        // 안좋은 예
        function createFile(name, isTemp) {
            if(isTemp) {
               fs.create(`./temp/${name}`);
            } else {
                fs.create(name);
            }
        }
        
        // 좋은 예
        function createFile(name) {
            fs.create(name);
        }
        
        function createTempFile(name){
            createFile(`./temp/${name}`);
        }
  3. 이항 함수(불가피한 이유가 아니면 사용을 지양하자)

    • 인수가 2개인 함수는 인수가 1개인 함수보다 이해하기 어렵다
  4. 삼항 함수(불가피한 이유가 아니면 사용을 지양하자)

    • 인수가 3개인 함수는 인수가 2개인 함수보다 훨씬 더 이해하기 어렵다
  5. 인수 객체

    • 인수가 2~3개 필요하다면 일부를 독자적인 클래스 변수로 선언할 가능성을 짚어본다
    new Circle(x, y, radius);
    
    const center = new Point(x, y);
    new Circle(center, radius);
    
    // or
    new Circle({x, y, radius})
  6. 동사와 키워드

    • 단항 함수는 함수와 인수가 동사/명사 쌍을 이뤄야 한다
    // writeField(name) 더 이해하기 쉽다
    write(name);
    
    writeField(name);
    • 함수 이름에 키워드를 추가하는 형식으로 작성한다
    // 후자로 작성하면 인수 순서를 기억할 필요가 없어진다
    assertEquals(expected, actual);
    
    assertExpectedEqualsActual(expected, actual);

[7] 부수 효과를 일으키지 마라!

  • 부수 효과?
    • 함수에서 약속한 한 가지 일 말고도 다른 일을 하는 것
    • 예시?
      • 클래스 변수를 수정하는 경우(JS의 경우 객체의 프로퍼티 값을 수정하는 경우)
      • 함수로 넘어온 인수나 시스템 전역 변수를 수정하는 경우
  • 부수 효과의 영향?
    • 시간적인 결합을 초래함

[8] 명령과 조회를 분리하라!

  • 함수는 뭔가를 수행하거나 뭔가에 답하거나 둘 중 하나만 해야 한다
    • 객체 상태를 변경하기
    • 객체 정보를 반환하기

[9] 오류 코드보다 예외를 사용하라!

  • 명령 함수에서 오류 코드를 반환하는 방식은 명령/조회 분리 규칙을 미묘하게 위반한다
    if(deletePage(page) === E_OK) { ... }
    위 코드처럼 오류 코드를 반환하면 호출자는 오류 코드를 곧바로 처리해야 한다는 문제에 부딪힌다
    try{
        functionThatMightThrow();
    } catch(e) {
        console.log(e);
    }
    정상 동작과 오류 처리 동작을 분리하면 코드를 이해하고 수정하기 쉬워진다
  • 오류 처리도 한 가지 작업이다
    • 오류 처리도 한 가지 작업에 속한다
      -> 오류를 처리하는 함수는 오류만 처리해야 마땅하다

[10] 반복하지 마라!

  • 중복은 소프트웨어에서 모든 악의 근원이다
  • 객체지향 프로그래밍은 부모 클래스로 몰아 중복을 없앤다

[11] 구조적 프로그래밍

  • Dikstra는 모든 함수와 함수 내 모든 블록에 입구와 출구가 하나만 존재해야 한다고 말했다
    함수는 return 문이 하나여야 한다
    -> 함수가 작을 경우 별 이익을 제공하지 못하고 함수가 아주 클 때만 상당한 이익을 제공한다

함수를 어떻게 짜죠?

  1. 코드를 일단 작성한다
  2. 코드를 다듬는다
  3. 함수를 만든다
  4. 이름을 바꾼다
  5. 중복을 제거한다
  6. 메서드를 줄이고 순서를 바꾼다

오늘 읽은 소감

책에 나와 있는 함수를 잘 만드는 법은 내 코드로 직접 리팩토링을 해봐야지 습득할 수 있을 것 같다. 아직은 책만 읽은 상태여서 이해가 100% 되지 않았다. 깨끗한 코드를 짜기 위해서 연습을 많이 해야겠다.

profile
여행과 책을 좋아하는 개발자입니다.

0개의 댓글

관련 채용 정보