3장. 함수(1)

고기호·2024년 8월 27일
1

클린 코드

목록 보기
3/3
post-thumbnail

3장. 함수(1)


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

작게 만들어라

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

한 가지만 해라

  • 함수는 한 가지를 해야한다. 그 한 가지를 잘 해야 한다. 그 한 가지만을 해야 한다.

  • 한 가지만 하는 지 판단

    • 해당 함수 아래에서 추상화 수준이 하나인지 판단한다.

      
      1. 페이지가 테스트 페이지인지 판단한다.
      2. 그렇다면 설정 페이지와 해제 페이지를 넣는다.
      3. 페이지를 HTML로 랜더링한다.
      

      → 페이지가 테스트 페이지인지 확인 한 후 테스트 페이지라면 설정 페이지와 해제 페이지를 넣는다. 테스트 페이지든 아니든 페이지를 HTML로 렌더링한다.

    • 의미 있는 이름으로 다른 함수를 추출할 수 있다면 그 함수는 여러 작업을 하는 샘이다.

함수당 추상화 수준은 하나로

  • 함수가 확실히 한 가지의 일만 하려면 함수 내 모든 문장의 추상화 수준이 동일해야한다.
    • 특정 코드가 근본 개념인가? 세부사항인가?

위에서 아래로 코드 읽기: 내려가기 규칙

  • 코드는 위에서 아래로 이야기처럼 읽혀야 좋다.
    • 한 함수 다음에는 추상화 수준이 한 단계 낮은 함수가 온다.
      • 즉, 위에서 아래로 프로그램을 읽으면 함수 추상화 수준이 한 번에 한 단계 낮은 함수가 온다.
        • 이것을 내려가기 규칙이라 부른다.
          설정 페이지와 해제 페이지를 포함하려면, 설정 페이지를 포함하고,
          테스트 페이지 내용을 포함하고, 해제 페이지를 포함한다.
          	
          	설정 페이지를 포함하려면, ~
          	
          	슈트 설정 페이지를 포함하려면, ~
          	
          	부모 계층을 검색하려면, ~

Switch 문

  • Switch 문의 경우 다양한 문제점을 가지는데
    1. 함수가 길다.
    2. 한가지 작업만 수행하지 않는다.
    3. SRP(단일 책임 원칙)를 위반한다.
    4. OCP(개방 폐쇄 원칙)를 위반한다.
  • 해결잭
    • 추상 팩토리 패턴에 꽁꽁 숨긴다

      // TypeHandlers.js
      class TypeHandler {
          getMessage() {
              throw new Error("This method should be overridden");
          }
      }
      
      class TypeAHandler extends TypeHandler {
          getMessage() {
              return "You selected Type A";
          }
      }
      
      class TypeBHandler extends TypeHandler {
          getMessage() {
              return "You selected Type B";
          }
      }
      
      class TypeCHandler extends TypeHandler {
          getMessage() {
              return "You selected Type C";
          }
      }
      
      class DefaultHandler extends TypeHandler {
          getMessage() {
              return "Unknown type";
          }
      }
      
      export class TypeFactory {
          static createHandler(type) {
              switch (type) {
                  case 'A':
                      return new TypeAHandler();
                  case 'B':
                      return new TypeBHandler();
                  case 'C':
                      return new TypeCHandler();
                  default:
                      return new DefaultHandler();
              }
          }
      }
      // App.js
      import React, { useState } from 'react';
      import { TypeFactory } from './TypeHandlers';
      
      function App() {
          const [message, setMessage] = useState('');
      
          const handleClick = (type) => {
              const handler = TypeFactory.createHandler(type);
              setMessage(handler.getMessage());
          };
      
          return (
              <div>
                  <h1>Select a Type</h1>
                  <button onClick={() => handleClick('A')}>Type A</button>
                  <button onClick={() => handleClick('B')}>Type B</button>
                  <button onClick={() => handleClick('C')}>Type C</button>
                  <button onClick={() => handleClick('D')}>Unknown Type</button>
      
                  <p>{message}</p>
              </div>
          );
      }
      
      export default App;

서술적인 이름을 사용해라

  • 이름이 길어도 괜찮다
  • 이름을 붙일 때는 일관성이 있어야한다.
    • 모듈 내에서 함수 이름은 같은 문거, 명사, 동사를 사용한다.
      • ex) includeSetupAndTeardownPages, includeSetupPages, includeSuiteSetupPage, includeSetupPage 등…

reference


클린 코드(로버트 C 마틴)

profile
웹 개발자 고기호입니다.

0개의 댓글