kimyu0218
  • [Good Code, Bad Code] 1장 코드 품질
    2024년 01월 24일 14시 51분 47초에 업로드 된 글입니다.
    작성자: @kimyu0218

    개발자로 진로를 정한 후에 처음으로 내돈내산 한 코딩 관련 서적이다! (전공 서적, 선물 제외) 정말 유명한 도서들이 많지만 굳이 이 책을 고른 이유는 학습한 내용을 프로젝트에 적용하고 싶기 때문이다. 개발 서적을 구매하더라도 현재 진행중인 프로젝트와 맞지 않는 경우, 배운 내용을 곧바로 써먹기 힘들어 흥미가 떨어지고 학습 내용도 휘발된다. 하지만 코드 품질은 어느 프로젝트에나 적용할 수 있기 때문에 나의 수요와 딱 맞아 떨어졌다.
     

    회사의 운명을 결정 짓는 코드 품질

    이 책을 읽기 전까진 막연하게 유지보수의 용이성 때문이라고 생각했다. 하지만 코드 품질로 인해 한 기업이 망할 수도 있다.

    고품질의 코드를 작성하기 위해서는 많은 노력이 필요하다. 코드 품질을 위해 꼼꼼히 개발하다가 다른 경쟁사의 제품이 먼저 출시되면 큰 낭패다. 그럼에도 불구하고 코드 품질을 고려하여 개발해야 하는 이유는 뭘까?

    고품질의 코드는..
    • 요구사항을 완벽하게 충족한다.
    • 요구사항이 변해도 사소한 추가 작업만으로 빠르게 반영할 수 있다.
    • 오류가 발생해도 시스템이 복구되거나 부분적으로 동작한다.

    이처럼 고품질의 코드는 유지보수의 용이성 뿐만 아니라 신뢰성, 안전성과도 연관이 깊다.
     

    고품질 코드를 작성하기 위한 핵심 전략

    좋은 코드는 안전하고, 실제로 동작하며 변경된 요구사항에 적응할 수 있어야 한다. 이러한 목표를 만족하기 위해서는 다음 요소를 고려해야 한다.

     

    1. 코드는 읽기 쉬워야 한다.
    2. 코드는 예측 가능해야 한다.
    3. 코드는 오용하기 어려워야 한다.
    4. 코드를 모듈화 한다.
    5. 코드를 일반화하여 재사용할 수 있도록 작성한다.
    6. 테스트가 용이한 코드를 작성하고 테스트 한다.

     

    내 코드의 가독성을 평가해보자

    다른 전략들은 다음 장들을 읽고 적용해볼 예정이다. 이번 포스팅에서는 코드 가독성만 평가할 것이다.

    코드는 다른 사람이 읽고 이해하기 쉽도록 작성해야 한다. 개인 프로젝트가 아니라면 다른 개발자의 코드 리뷰를 받아야 하는 상황이 발생하기 때문이다. 상대방이 읽기 쉬운 코드를 작성하면 검토 과정에서 미처 발견하지 못한 오류나 놓친 세부 사항을 발견할 수 있다. (잠재적인 버그 사전에 처리 가능!)

    코드의 가독성을 검토하는 몇 가지 지표
    • 코드가 무슨 일을 하고 있는가
    • 코드가 어떤 것을 필요로 하는가
    • 코드 실행 후 어떤 결과물을 얻을 수 있는가

    위의 지표를 바탕으로 내가 작성한 코드의 가독성을 평가해볼 것이다. 코드를 살펴보기 전에 해당 프로젝트의 목적에 대해 간단히 짚고 넘어가겠다.
     
    swagger를 이용하면 별도의 API 문서를 작성할 필요 없이 코드만으로 API 문서를 만들 수 있다. 하지만 문서화를 꼼꼼히 하다보면 생산성이 떨어지고, 이는 일정이 늦어지는 결과를 초래할 수 있다. 위 문제점을 해결하기 위해 API에 필요한 기본 응답 데코레이터를 자동으로 만들어주는 swagger-decorator-builder를 만들었다.
     
    아래는 `SwaggerDecoratorBuilder`를 호출하는 부분이다. 해당 코드는 `FindAllCats`라는 API에서 사용하지 않는 기본 응답 데코레이터들을 제거하고 있다.
    하지만 `remove` 만으로는 어떤 데코레이터를 제거하는지 파악하기 힘들다. API 문서를 위해 `ApiResponse` 외에도 `ApiOperation`, `ApiParam`, `ApiQuery` 등을 사용할 수 있는데 어떤 데코레이터를 삭제하는 건지 알 수 없다.

    export const FindAllCatsDecorator = (target: string, returnType: any) =>
      new SwaggerDecoratorBuilder(target, 'GET', returnType)
        .remove(401)
        .remove(403)
        .remove(404)
        .build();

    위 코드를 다음과 같이 수정하여 `remove`라는 메서드가 어떤 일을 수행하는지 직관적으로 표현했다. 이제 주석 부분이 없어도 `removeResponse`가 어떤 데코레이터를 삭제하는지 알 수 있다. (물론 빌더 패턴에 대한 이해, 패키지에 대한 이해는 어느 정도 선행이 필요하다)

    export const FindAllCatsDecorator = (target: string, returnType: any) =>
      new SwaggerDecoratorBuilder(target, 'GET', returnType)
        .removeResponse(401)
        .removeResponse(403)
        .removeResponse(404)
        .build();

     아래는 `SwaggerDecoratorBuilder` 클래스다.

    export class SwaggerDecoratorBuilder {
      ...
      addParam(param: ApiParamOptions): this {...}
      addQuery(query: ApiQueryOptions): this {...}
      addResponse(response: number | ApiResponseOptions): this {...}
      removeResponse(status: SwaggerHttpStatus): this {...}
      build(): MethodDecorator {...}
      setBody(body: ApiBodyOptions): this {...}
      setOperation(operation: ApiOperationOptions): this {...}
      ...
    }

    주석이 없어도 `add*`는 `Api*` 데코레이터를 만들어주는 함수, `set*`은 `Api*` 데코레이터 값을 설정하는 함수라는 걸 알 수 있다!

    📋 가독성 체크포인트
    • 코드가 무슨 일을 하고 있는가 ✔️
    • 코드가 어떤 것을 필요로 하는가 ✔️
    • 코드 실행 후 어떤 결과물을 얻을 수 있는가 ✔️

    '학습기록 > 독서' 카테고리의 다른 글

    [Good Code, Bad Code] 2장 추상화 계층  (0) 2024.02.01
    댓글