몬스터 체력을 계산으로 정하다가 특정 몬스터만 손으로 정하기로 했다. MySQL 의 monster 테이블 같은 칸에 넣었다.
Table of contents
Open Table of contents
어느 쪽인지 알 수 없었다
hp 칸에는 숫자만 있어서 어느 것이 계산으로 나온 값이고 어느 것이 손으로 넣은 값인지 구분이 안 됐다.
계산식을 바꿨을 때 문제가 됐다. 식을 바꾸고 UPDATE 로 전부 다시 넣으니 손으로 넣은 값도 같이 덮였다. 덮이고 나면 원래 무엇이었는지 알 방법도 없다.
자리를 나눠 담았다
계산값과 손으로 넣은 값을 다른 칸에 두고 읽을 때 고르게 했다.
int hp = (m.hpOverride > 0) ? m.hpOverride : m.hpCalc;
처음에는 이렇게 0 을 「없음」으로 썼다. 그런데 0 도 넣고 싶은 값일 수 있어서 나중에 다시 걸린다. hp_override 를 NULL 허용으로 두고 SQL 쪽에서 COALESCE(hp_override, hp_calc) 로 고르게 바꿨다. NULL 은 값이 아니라 없음이라 헷갈릴 자리가 없다.
계산식을 바꿔도 손으로 넣은 칸은 안 건드린다. 왜 손으로 넣었는지도 같이 적었다. 이유가 없으면 나중에 계산식을 고칠 때 이걸 그대로 둬야 하는지 판단할 수 없다. 실제로 이유가 없는 값이 몇 개 있었고 아무도 몰라서 계산값으로 되돌렸다.
예외를 세어 봤다
WHERE hp_override IS NOT NULL 로 세니 180 마리 중 41 마리였다. 4 분의 1 이 예외다.
이 정도면 계산식이 안 맞는다는 뜻이었다. 식을 다시 만들어 보니 41개 중 33개가 새 식으로 설명됐다.
int hp = level * 20 + 100 + (isBoss ? level * 50 : 0);
보스 여부가 식에서 빠져 있었다. 예외를 세어 보니 규칙에 빠진 것이 드러난 것이다. 예외가 많으면 그 예외를 관리할 것이 아니라 규칙을 다시 봐야 한다.
덮어쓰기 전과 화면 표시
새 식으로 전부 다시 넣기 전에 무엇이 바뀌는지 먼저 뽑았다.
SELECT monster_id, hp_calc AS old_hp, (level*20+100+IF(is_boss,level*50,0)) AS new_hp
FROM monster
WHERE hp_calc <> (level*20+100+IF(is_boss,level*50,0));
147 건이 나왔고 눈으로 훑고 나서 넣었다. 넣기 전에 무엇이 바뀌는지 보는 것과 넣고 나서 이상한 것을 찾는 것은 다르다.
바꾸기 전 값도 남겨 뒀다.
CREATE TABLE monster_bak_20120324 AS SELECT * FROM monster;
앞에서 손으로 넣은 값을 잃은 것이 이걸 안 해서였다.
기획 쪽이 보는 JSP 화면에도 어느 쪽인지 드러나게 했다. 표시가 있으면 왜 이 몬스터만 다른지를 묻지 않는다. 직접 입력이 얼마나 많은지도 보인다.
정리
- 계산으로 나온 값과 손으로 넣은 값을 같은 자리에 두면 구분이 안 된다
- 덮이고 나면 원래 무엇이었는지도 알 수 없다
- 자리를 나누고 읽을 때 고른다. 없음은
0이 아니라NULL로 둔다 COALESCE로 고르면0도 정상 값으로 다룰 수 있다- 왜 손으로 넣었는지 같이 적는다. 없으면 지워도 되는지 모른다
- 예외가 몇 개인지 센다. 예외가 많으면 규칙에 빠진 것이 있다
- 덮어쓰기 전에 무엇이 바뀌는지 뽑아 본다
- 바꾸기 전 값을 남긴다.
CREATE TABLE ... AS SELECT한 줄이면 된다 - 화면에서도 구분해 보인다