두 번째 소비자가 측정 계기야
첫 구현에는 확정된 요구와 추측이 섞여 있어. 그때 framework 를 뽑으면 소비자 하나가 아직 증명 안 된 abstraction 비용을 내고, 첫 제품의 우연한 모양이 API 로 굳어. 약간의 중복은 두 번째 사례가 올 때까지 정보를 사는 비용일 수 있어.
두 번째 real consumer 가 나타나면 줄 닮음보다 behavior 를 비교해. 입력이 언제 valid 한지, failure 가 어디 남는지, caller 가 어떤 order 를 기대하는지, 같은 requirement 가 두 제품을 함께 바꾸는지 봐. text 가 같아도 계약이 다를 수 있고 text 가 달라도 invariant 는 같을 수 있어.
첫 구현은 baseline, 둘째는 comparison, extraction 은 세 번째 동작이야. 소비자 둘의 test 를 유지한 채 common contract 를 뽑아야 상상이 아니라 관찰로 interface 를 만들 수 있어. 한쪽 adapter 만 바뀌는 future change 는 seam 이 건강하다는 증거일 수도 있고.
추출 뒤 원래 제품은 버려진 file 이 아니라 thin adapter 로 남아. kernel test 는 shared behavior 를, product test 는 각 언어와 policy 를 계속 검증해. kernel 만 green 이라고 product 가 안 깨졌다는 뜻은 아니니까.
변경 이유를 나란히 둬
최근 change 몇 개를 펼쳐 같은 요구가 양쪽을 함께 움직였는지 봐. 한쪽만 domain 이유로 바뀌었다면 지금 code 가 닮아도 그 policy 는 root 밖에 둬. change pressure 가 copy similarity 보다 강한 증거야.
두 구현을 비교할 때 보는 것
함수 이름과 줄 수부터 맞추면 제일 중요한 차이를 놓쳐. 입력이 언제 유효해지는지, 실패가 어디 기록되는지, 호출자가 어떤 순서를 기대하는지부터 표로 만들어. 두 제품이 같은 실패를 같은 시점에 막고 같은 형태의 증거를 남길 때 공유 행동이야. 하나는 예외를 던지고 다른 하나는 조용히 건너뛴다면 텍스트가 닮아도 계약은 달라. 추출 전 비교표가 나중 커널 API 의 첫 시험 명세가 돼야 해.
그리고 추출 뒤에도 제품 둘의 같은 시험을 그대로 남겨. 커널 시험만 통과한다고 adapter 가 올바른 건 아니야. 소비자 시험이 공통 계약을 각 제품 말로 다시 확인할 때, 재사용이 기능 삭제가 아니라는 걸 증명할 수 있어.