클린코드(Clean Code) 정리

Yowon Jeong ·2024년 10월 15일
0

클린 코드: 좋은 코드의 조건과 작성법

개발을 하다 보면, "내가 작성하고 있는 코드가 과연 좋은 코드인가?"라는 고민에 빠질 때가 있는데
이 질문에 대한 답을 찾기 위해 많은 개발자들이 '클린 코드 (Clean Code)' 서적을 많이 추천해줘서 나도 읽어보았다!

이 글에서는 클린 코드를 읽으면서 알게된 핵심 개념과 좋은 코드를 작성하기 위한 방법을 정리하고자 합니다.


1. 의도를 분명히 밝히기

코드의 변수, 함수, 클래스 등의 이름은 코드의 의도를 명확하게 표현할 수 있어야 합니다.
이름만으로도 해당 코드가 어떤 일을 수행하는지 쉽게 예측할 수 있다면, 더 나은 코드라고 할 수 있습니다.

  • 나쁜 예:
    boolean flag = true;
  • 좋은 예:
    boolean isUserLoggedIn = true;

의미 없는 약어나 애매한 이름 대신, 명확한 이름을 사용하세요.


2. 조건을 캡슐화하라

복잡한 조건문은 읽기 어렵고 유지보수가 힘듭니다.
조건을 명확하게 드러내는 함수로 감싸면 코드의 가독성이 크게 향상됩니다.

  • 나쁜 예:
    if ((employee.flags & HOURLY_FLAG) && (employee.age > 65)) {
        // 복지 혜택 자격 확인
    }
  • 좋은 예:
    if (employee.isEligibleForFullBenefits()) {
        // 복지 혜택 자격 확인
    }

3. 객체 생성에 유의미한 이름을 사용하라

생성자를 오버로딩하면 인수의 의미가 불분명해질 수 있습니다.
이럴 때 정적 팩토리 메서드를 사용하여 명확한 이름을 부여하는 것이 좋습니다.

  • 나쁜 예:
    Student student = new Student("James", 85);
  • 좋은 예:
    Student student = Student.withGrade("James", 85);

4. 서술적인 이름을 사용하라

서술적인 이름은 코드를 이해하기 쉽게 만들고, 리팩토링도 더 수월하게 만듭니다.

  • 이름 짓기 규칙:

    • 함수가 작고 단순할수록 서술적인 이름을 붙이기 쉽습니다.
    • 긴 이름을 두려워하지 마세요. 의미를 담는 것이 더 중요합니다.
    • 함수와 변수 이름은 모듈 내에서 일관성을 유지하세요.
  • 예시:

    public void includeSetupAndTeardownPages() { ... }
    public void includeSetupPages() { ... }
    public void includeSuiteSetupPage() { ... }
    public void includeSetupPage() { ... }

5. 명령과 조회를 분리하라 (CQS 원칙)

하나의 함수는 명령(수행)과 조회(확인) 중 하나의 역할만 담당해야 합니다.
두 역할을 동시에 수행하면 코드가 혼란스러워집니다.

  • 나쁜 예:

    public boolean set(String attribute, String value);
    if (set("username", "coco")) { ... }
  • 좋은 예:

    public boolean attributeExists(String attribute);
    public boolean set(String attribute, String value);
    
    if (attributeExists("username")) {
        set("username", "coco");
    }

6. 오류 코드보다 예외를 사용하라

오류 코드를 반환하면 중첩된 조건문이 발생해 코드가 복잡해집니다.
예외 처리를 사용하면 더 간결한 코드를 작성할 수 있습니다.

  • 나쁜 예:

    public Status deletePage(Page page) {
        if (deletePage(page) == E_OK) {
            if (registry.deleteReference(page.name) == E_OK) {
                if (configKeys.deleteKey(page.name.makeKey()) == E_OK) {
                    log.info("page deleted");
                    return E_OK;
                } else {
                    log.error("config key not deleted");
                }
            } else {
                log.error("reference not deleted");
            }
        } else {
            log.error("page not deleted");
        }
        return E_ERROR;
    }
  • 좋은 예:

    public void deletePage(Page page) {
        try {
            deletePageAndAllReferences(page);
        } catch (Exception e) {
            log.error(e.getMessage());
        }
    }
    
    public void deletePageAndAllReferences(Page page) throws Exception {
        deletePage(page);
        registry.deleteReference(page.name);
        configKeys.deleteKey(page.name.makeKey());
    }

7. 설계의 품질을 높여주는 4가지 규칙

  1. 모든 테스트를 실행하라
    : 테스트가 쉬운 코드를 작성하면 단일 책임 원칙(SRP)을 준수하고 낮은 결합도를 갖게 됩니다.
  2. 중복을 제거하라
    : 작은 중복도 제거해 깔끔한 코드를 유지하세요.
  3. 개발자의 의도를 표현하라
    : 좋은 이름과 작은 함수, 단위 테스트는 의도를 명확하게 드러냅니다.
  4. 클래스와 메서드를 작게 유지하라
    : 클래스와 메서드를 작게 유지하면 시스템의 복잡도를 줄일 수 있습니다.

8. 디미터 법칙 (Law of Demeter)

디미터 법칙은 한 객체가 다른 객체의 내부 구조를 직접 참조하지 않도록 하는 원칙입니다.
내부 구조를 노출하면 결합도가 높아지며, 유지보수가 어려워집니다.

  • 나쁜 예:

    String outputDir = ctxt.getOptions().getScratchDir().getAbsolutePath();
  • 좋은 예:

    Options opts = ctxt.getOptions();
    File scratchDir = opts.getScratchDir();
    String outputDir = scratchDir.getAbsolutePath();

profile
내가 개발자라니

0개의 댓글