Skip to content
isdnetworks
Go back

이름은 옛 용도를 가리키고 있었다

기간 할인을 손보려고 grep -rn 으로 관련 코드를 찾았다. LimitedDiscount 라는 모델이 있었다. 열어 보니 기간 할인만 다루는 것이 아니었다.

Table of contents

Open Table of contents

여러 용도가 한 모델에 들어 있었다

컬럼을 봤다.

CREATE TABLE limited_discount (
  discount_no  INT NOT NULL AUTO_INCREMENT,
  product_no   INT NOT NULL,
  rate         INT NOT NULL,
  start_date   DATETIME NULL,
  end_date     DATETIME NULL,
  coupon_code  VARCHAR(30) NULL,
  member_grade INT NULL,
  event_no     INT NULL,
  ...
);

기간을 담는 start_dateend_date 말고도 쿠폰과 회원 등급과 이벤트가 붙어 있다. 처음에는 기간 할인용이었는데 나중에 다른 할인이 생길 때마다 coupon_codemember_gradeevent_no 가 붙은 것이다.

이름이 판단을 흐렸다

이름이 LimitedDiscount 니까 기간 할인만 여기 있다고 생각했다. 쿠폰 할인을 찾으려고 다른 데를 뒤졌는데 없었다. coupon_code 컬럼과 함께 여기 있었다.

이름이 옛 용도를 가리키면 찾는 사람이 다른 데를 본다. 이름이 정확하면 grep 한 번에 끝날 탐색이 이름이 어긋나 있으면 한참 걸린다.

무엇이 들어 있는지 세어 봤다

SELECT
  SUM(coupon_code IS NOT NULL) AS coupon,
  SUM(member_grade IS NOT NULL) AS grade,
  SUM(event_no IS NOT NULL) AS event,
  SUM(coupon_code IS NULL AND member_grade IS NULL AND event_no IS NULL) AS period_only,
  COUNT(*) AS total
FROM limited_discount;
coupon  grade  event  period_only  total
  1204    891    340         2118   4553

period_only 가 2118로 절반이 안 된다. 이름이 가리키는 것이 소수인 상태였다. 코드를 읽는 것만으로는 이 비율을 알 수 없고 COUNT(*) 를 돌려 봐야 나온다.

판단 기준 — 나눌지 합칠지

세 가지를 봤다. 그대로 두고 이름만 Discount 로 바꿀 수 있다. 그러면 클래스와 테이블 이름을 쓰는 곳을 다 고쳐야 한다. 유형별로 PeriodDiscountCouponDiscount 로 나눌 수도 있다. 깔끔하지만 공통 로직이 흩어진다. 하나로 두되 유형 컬럼으로 가르는 방법도 있다.

세 번째로 했다. 할인 금액을 계산하는 방식은 거의 같았고 WHERE 조건만 달라서 PeriodDiscount 쪽으로 나누면 중복이 생긴다.

ALTER TABLE limited_discount
  ADD COLUMN discount_type VARCHAR(20) NOT NULL DEFAULT 'period' AFTER product_no;

기존 행에 유형을 채웠다.

UPDATE limited_discount SET discount_type = 'coupon' WHERE coupon_code IS NOT NULL;
UPDATE limited_discount SET discount_type = 'grade'  WHERE member_grade IS NOT NULL;
UPDATE limited_discount SET discount_type = 'event'  WHERE event_no IS NOT NULL;

순서가 중요해서 여러 조건이 겹치는 행이 있는지 먼저 봤다.

SELECT COUNT(*) FROM limited_discount
WHERE (coupon_code IS NOT NULL) + (member_grade IS NOT NULL) + (event_no IS NOT NULL) > 1;
-- 0

0이라 UPDATE 순서와 무관했다. 겹치는 것이 있었으면 어느 유형인지 정해야 했다. discount_type 한 컬럼으로는 못 담는 경우도 나왔을 것이다.

이름 교체와 주석

테이블 이름을 바로 안 바꿨다. 쓰는 곳이 60군데였다.

class Discount_model extends CI_Model {
    protected $table = 'limited_discount';   // 옛 테이블 이름
    ...
}

// 옛 이름 유지 (당분간)
class Limited_discount_model extends Discount_model {}

새로 짜는 코드는 Discount_model 을 쓰고 옛 코드는 Limited_discount_model 로 그대로 돈다. 한 달 뒤에 옛 이름을 쓰는 곳이 남았는지 봤다.

$ grep -rln "Limited_discount_model" --include=*.php application/

grep -rln 에 12곳이 남아서 하나씩 바꿨고 전부 없어진 뒤에 별칭 클래스를 지웠다.

이름과 실제가 달라진 경위를 주석에 쓸까 했는데 안 썼다. 원래 기간할인용이었으나 어느 해에 쿠폰이 추가됐다는 식의 주석은 계속 낡는다. 이력은 커밋 메시지가 담을 일이다.

/**
 * 할인 모델. discount_type 으로 유형을 구분한다.
 *   period  기간 할인 (start_date ~ end_date)
 *   coupon  쿠폰 할인 (coupon_code)
 *   grade   등급 할인 (member_grade)
 *   event   이벤트 할인 (event_no)
 */

지금 무엇인지만 적었다.

이름과 실제가 어긋난 것이 더 있는지도 봤다. 테이블 이름에 특정 개념이 든 것을 골라 그 개념 밖의 컬럼이 있는지 보는 방식이다.

member_point       → 포인트 말고 쿠폰, 등급 정보도 있음
order_delivery     → 배송 말고 반품 정보도 있음
product_review     → 후기 말고 문의도 있음

세 개가 더 나왔고 product_review 가 특히 심했다. 후기와 문의가 한 테이블에 있고 유형 컬럼도 없어서 목록으로 적어 두고 손댈 일이 있을 때 같이 정리하기로 했다.

정리


Share this post on:

Previous Post
선물함이 별도 테이블이었다
Next Post
유저 테이블에 성격이 다른 컬럼이 섞여 있었다