[Cleancode] TDD, OOP 적용하여 프로그래밍하기(부동산 중개수수료 계산) - 1

강준혁·2022년 1월 21일
0

CleanCode

목록 보기
1/1
post-thumbnail

최근 이전에 대충 읽어봤던 클린코드를 다시금 제대로 보고 있다(제대로 보고있는건지는 모르겠지만)

나는 효율충이라 뭘 하든 최소한의 노력으로 최대한의 결과물을 얻는것을 선호하기에 강의를 신청해서 보고있는데,

강사분이 포인트만 잘 짚어서 친절하게 설명해주시고 예시 코드 퀄리티도 좋아서 아주 만족중이다.
** 제로베이스 클린코드(https://zero-base.co.kr/category_dev_camp/cleancode_1book)

이 강의를 보다보면 부동산 중개수수료를 계산하는 자바 + 스프링 기반 코드를 예시로 설명을 해주시는데

이를 TypeScript 기반으로 다시 작성하며 정리해보려 한다.

프로그램의 요구사항은 다음과 같다. (매우 심플하다)

사용자의 거래방식(매매교환 또는 그 외) 및 부동산 가격을 입력받아 그에 맞는 중개수수료를 계산한다.
중개수수료 계산식은 https://land.seoul.go.kr:444/land/broker/brokerageCommission.do 에 따른다.

이를 내가 이해한 TDD 개발방식에 따라 아래와 같은 순서로 개발한다.

  1. 요구사항에 따라 함수의 인터페이스를 설계한다.
  2. 함수에 인터페이스에 따른 테스트 코드를 작성하고, 실행해본다.
  3. 함수의 상세 로직을 작성한다.
  4. 테스트 코드를 실행한다.
  5. 오류가 발생 하는 경우 로직을 수정한다.
  6. 기존 코드를 개선한다(수정/변경이 쉽고 가독성이 좋도록)
  7. 테스트 코드를 실행한다.
  8. 6 - 7의 반복.

일단 함수의 인터페이스를 만들어보자.

export enum BrokerageType {
    PURCHASE,
    RENT,
}
  
const brockerageCalculator = (type: BrokerageType, amount: number): number => {
    return 0;
}

단순하게 거래방식의 타입과 거래금액을 입력받아 리턴하도록 설계하였다.

그런 뒤에 테스트 코드를 작성하고,

import { brockerageCalculator, BrokerageType } from "./brockerageCalculator"

describe('부동산 중개수수료 계산 테스트', () => {
        it('매매 / 거래금액 1억원 인 경우', () => {
            const result = brockerageCalculator(BrokerageType.PURCHASE, 100_000_000);
            expect(result).toBe(500_000);
        })
        it('매매 / 거래금액 5억원인 경우', () => {
            const result = brockerageCalculator(BrokerageType.PURCHASE, 500_000_000);
            expect(result).toBe(2_000_000);
        })
        it('매매 / 거래금액 16억원인 경우', () => {
            const result = brockerageCalculator(BrokerageType.PURCHASE, 1_600_000_000);
            expect(result).toBe(11_200_000);
        })
        it('임대 / 거래금액 1억원 인 경우', () => {
            const result = brockerageCalculator(BrokerageType.RENT, 100_000_000);
            expect(result).toBe(300_000);
        })
        it('임대 / 거래금액 5억원인 경우', () => {
            const result = brockerageCalculator(BrokerageType.RENT, 500_000_000);
            expect(result).toBe(1_500_000);
        })
        it('임대 / 거래금액 16억원인 경우', () => {
            const result = brockerageCalculator(BrokerageType.RENT, 1_600_000_000);
            expect(result).toBe(9_600_000);
        })
    }
);

실행해본다, 당연히 실패한다.
** 여기서는 6가지 케이스에 대한 테스트케이스를 작성하였지만, 실제로는 모든 케이스에 대한 테스트 케이스를 작성해야 한다.

이제 로직을 단순하게 짜보자.

export const brockerageCalculator = (type: BrokerageType, amount: number) => {
  switch (type) {
    case BrokerageType.PURCHASE:
      if (amount < 50_000_000) {
        return Math.min(amount * 0.6 / 100, 250_000);
      } else if (amount < 200_000_000) {
        return Math.min(amount * 0.5 / 100, 800_000);
      } else if (amount < 900_000_000) {
        return Math.min(amount * 0.4 / 100, Infinity);
      } else if (amount < 1_200_000_000) {
        return Math.min(amount * 0.5 / 100, Infinity);
      } else if (amount < 1_500_000_000) {
        return Math.min(amount * 0.6 / 100, Infinity);
      } else {
        return Math.min(amount * 0.7 / 100, Infinity);
      }
    case BrokerageType.RENT:
      if (amount < 50_000_000) {
        return Math.min(amount * 0.5 / 100, 200_000);
      } else if (amount < 100_000_000) {
        return Math.min(amount * 0.4 / 100, 300_000);
      } else if (amount < 600_000_000) {
        return Math.min(amount * 0.3 / 100, Infinity);
      } else if (amount < 1_200_000_000) {
        return Math.min(amount * 0.4 / 100, Infinity);
      } else if (amount < 1_500_000_000) {
        return Math.min(amount * 0.5 / 100, Infinity);
      } else {
        return Math.min(amount * 0.6 / 100, Infinity);
      }
    default:
      throw new Error('Not defined type');
  }
}

테스트 코드를 실행한다.

성공했다.

개인적으로는 평소 개발할 때 이정도만 해도 정말 잘하는 거라고 생각한다.
대부분(나를 포함해서, 일단 내가 본 사람들은) 테스트 코드 없이 기능만 개발하고 다음 기능개발로 넘어가기 마련이라.

이렇게 테스트 코드를 작성하지 않으면, 나중에 기능을 추가하거나 수정할 때 문제가 생기게 된다.

테스트 코드를 작성하지 않고 기능을 개발했다고 가정했을 때의 발생가능한 시나리오를 예상해보면,

  1. 기능 개발한 뒤 발생가능한 케이스(여기서는 12개의 케이스)에 대해 자체적으로 파라메터를 넣어 확인한 뒤 배포를 한다.
  1. 이후 기능 개선 요청이 온다, 2가지 케이스가 추가되었다.
  1. 로직을 추가하여 2가지 케이스에 대해 자체적으로 파라메터를 넣어 테스트를 해본다.
  1. 이 경우 그 전의 12개의 케이스에 대해서는 정상적으로 동작한다고 장담할 수 있을까? No.

계속적으로 기능이 추가되거나 수정되면 프로그램이 동작하는 경우의 수는 많아지지만

개발 시간은 한정되어있어 모든 케이스에 대한 테스트는 제한되므로 신규로 추가된 기능에 대해서만

한정적으로 테스트를 진행하게 되고, 그러다보면 오류 발생 가능성이 계속 높아지게 된다.

profile
백엔드 개발자

0개의 댓글