Skip to content
isdnetworks
Go back

채널마다 형식이 달랐다

여러 판매처에서 주문을 받아 오는 기능을 늘리고 있었다. 세 번째 판매처를 붙이는데 코드가 엉키기 시작했다.

Table of contents

Open Table of contents

조건문이 계속 늘었다

받아 온 자료를 처리하는 함수 안에서 판매처를 가르고 있었다.

foreach ($rows as $r) {
    if ($channel === 'A') {
        $orderNo = $r['ORD_NO'];
        $amount  = (int)$r['AMT'];
    } else if ($channel === 'B') {
        $orderNo = $r['order_id'];
        $amount  = (int)str_replace(',', '', $r['total_price']);
    } else if ($channel === 'C') {
        $orderNo = $r['no'];
        $amount  = (int)($r['price'] * $r['qty']);
    }
    // 이하 공통 처리
}

판매처가 하나 늘 때마다 이 함수가 길어지고 공통 처리를 고치면 셋 다 영향을 받는다. 붙이는 비용이 판매처 수에 따라 커지는 구조였다.

무엇이 다른지 목록으로 만들었다

나누기 전에 무엇이 다른지부터 적었다.

항목ABC
주문번호 필드ORD_NOorder_idno
날짜 형식YYYYMMDDISODD/MM/YYYY
금액 표기정수쉼표 포함 문자열단가 × 수량
문자셋EUC-KRUTF-8UTF-8
파일 형식고정폭CSVXML

다섯 가지가 다르고 나머지는 같았다. 다른 것을 목록으로 만들고 나니 어디를 나누고 어디를 공통으로 둘지가 보였다.

읽는 부분만 나눴다

판매처별로 클래스를 만들고 공통 형태로 바꿔 돌려주게 했다.

class OrderReaderA implements OrderReader {
    public function read($filePath) {
        $rows = $this->parseFixedWidth($filePath);
        $out  = [];
        foreach ($rows as $r) {
            $out[] = [
                'order_no' => trim($r['ORD_NO']),
                'order_date' => date('Y-m-d', strtotime($r['ORD_DT'])),
                'amount' => (int)$r['AMT'],
            ];
        }
        return $out;
    }
}

부르는 쪽은 판매처를 모른다. 읽어 온 뒤로는 전부 같은 처리를 지난다. 네 번째 판매처를 붙일 때 클래스 하나만 만들었고 공통 처리는 안 건드렸다.

문자셋 변환도 각 클래스 안에서 하게 했다. EUC-KR 로 오는 것이 하나뿐인데 공통 처리에서 변환하면 이미 UTF-8 인 것까지 변환돼 깨진다. 변환은 그 형식이 들어오는 자리에서 한다.

변환할 때 무엇으로 읽을지도 걸렸다. 처음에는 mb_convert_encoding($s, 'UTF-8', 'EUC-KR') 로 했는데 상품명에 「똠」 같은 글자가 들어오면 그 자리가 비었다. 확장 한글이 EUC-KR 표에 없어서다.

CP949 로 읽으니 그대로 왕복했다. 한글 자료는 EUC-KR 이라고 적혀 와도 실제로는 CP949 인 경우가 많아 그쪽으로 맞췄다.

공통 형태의 정의와 표본

무엇이 공통 형태인지 적어 두지 않으면 각 클래스가 조금씩 다른 것을 돌려준다.

/**
 * read() 반환 형태
 *   order_no    string  판매처 주문번호 (공백 제거)
 *   order_date  string  YYYY-MM-DD
 *   amount      int     원 단위, 부가세 포함
 *   items       array   [{product_code, qty, price}, ...]
 */

실제로 한 번 어긋났다. 한 클래스가 amount 를 원이 아니라 십원 단위로 돌려주고 있었다. 그래서 read() 가 준 배열을 검사하는 코드를 넣어 읽는 클래스가 잘못 만들면 그 자리에서 걸리게 했다.

각 판매처의 실제 파일도 하나씩 남겨 뒀다. 코드를 고친 뒤 셋을 다 돌려 read() 결과가 같은지 본다. 이게 없으면 한 판매처를 고치다 다른 것을 깨뜨려도 모른다.

정리


Share this post on:

Previous Post
쿠폰이 두 번 쓰였다
Next Post
전역 값이 계정마다 저장돼 있었다