새 프로젝트를 받았다. CodeIgniter 를 쓰고 있어서 구조가 있을 것으로 봤는데 Controller 를 열어 보니 한 함수가 300줄이었다.
Table of contents
Open Table of contents
증상 — 한 함수에 다 있었다
읽어 보니 이런 것이 다 들어 있었다.
입력값 검사
DB 조회
계산
다른 조회
화면에 넘길 값 만들기
CodeIgniter 에는 Model 이라는 자리가 있는데 거기가 거의 비어 있었다.
왜 이렇게 됐는지는 짐작이 됐다. 한 자리에 다 쓰면 만들 때는 빠르고 흐름도 한눈에 보이는데 자리를 나누면 파일을 여럿 만들어야 하고 그 순간에는 번거롭다.
문제는 고칠 때 드러났다. 300줄에서 고칠 자리를 찾아야 하고 어디를 건드리면 어디가 영향받는지 안 보인다. 처음 편했던 것이 나중에 비용으로 돌아왔다.
같은 조회가 반복됐다
읽다 보니 같은 조회가 여러 함수에 있었다.
$this->db->where('status', 1);
$this->db->where('deleted', 0);
$q = $this->db->get('products');
여러 곳에 복사돼 있었고 그중 하나가 달랐다.
$this->db->where('status', 1);
// deleted 조건이 없음
deleted 조건이 빠져 지운 것도 나온다. 실제로 그 화면에서 지운 상품이 보인다는 문의가 있었다.
복사하면서 한 줄을 빠뜨린 것이었다. 같은 조회가 흩어져 있는 것 자체가 버그의 원인이었다.
나눠 놓은 자리
조회를 Model 로 옮겼다.
class Product_model extends CI_Model {
public function get_active() {
return $this->db->where('status', 1)
->where('deleted', 0)
->get('products')->result();
}
}
get_active 한 곳이 되니 조건이 갈릴 자리가 없어졌다.
$data['products'] = $this->Product_model->get_active();
부르는 쪽은 한 줄이 됐다. 이런 것을 옮기니 300줄이 50줄쯤으로 줄고 남은 것은 받고 넘기는 것이었다.
옮기면서 무엇을 어디로 보낼지 기준이 필요했다.
[컨트롤러] 요청 받기 · 결과 넘기기
[모델] DB 접근
[그 외 계산] 어디?
계산이 애매했다. Model 에 넣으면 DB와 상관없는 것이 섞이고 Controller 에 두면 다시 길어진다.
libraries/PriceCalculator.php
CodeIgniter 에 libraries 자리가 있어서 DB와 무관한 계산을 거기 모았다. 자리가 딱 정해져 있지 않은 것도 규칙을 정해 두면 다음에 헤매지 않는다.
나누니 시험이 됐다
부수 효과가 있었다. 이 계산은 DB 없이 시험할 수 있었다.
$c = new PriceCalculator();
$r = $c->total([...]);
// 결과가 기대와 같은가
PriceCalculator 에 값을 넣고 결과를 보면 되니 화면을 열지 않아도 됐다. 이때 처음으로 시험 코드를 써 봤고 간단한 것부터 했다.
DB나 요청이 얽힌 것은 여전히 시험을 못 썼다. 준비할 것이 많아서인데 나눠 둔 것만 시험이 됐다.
여기서 알게 된 것이 있다. 나누는 이유가 고치기 쉬움 하나였는데 시험할 수 있음이 하나 더 붙었다. 두 번째는 나눠 봐야 보이는 것이었다.
전부 옮기지는 못했다. 자주 고치는 화면부터 옮기고 안 건드리는 화면은 남겼는데 한 번에 다 하려다 못 끝내는 것보다 나아 보였다. 새로 만드는 것은 처음부터 나눠서 만들어 늘어나는 것을 먼저 막았다.
정리
- 프레임워크에
Model자리가 있어도 안 쓰면 한 곳에 몰린다 - 처음엔 한 곳이 빠른데 고칠 때 어렵다
- 같은 조회가 복사되면 한 줄을 빠뜨린다. 그게 버그가 된다
Model로 옮기면 조건이 갈릴 자리가 없어진다- DB와 무관한 계산은
libraries같은 또 다른 자리가 필요했다 - 나눠 두니 DB 없이 시험할 수 있었다
- 나누는 이유가 고치기 쉬움과 시험 가능 둘이 됐다
- 전부 옮기지 않고 자주 고치는 것부터 하되 신규는 처음부터 나눈다