본문 바로가기
C.W.K.
Stream
Lesson 05 of 05 · published

두 번째 추출

~12 min · extraction, census, shared-kit, drift-guard, standing-practice

Level 0차가운 용기
0 XP0/37 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete

두 번째 추출

첫 추출은 규칙을 증명하고, 두 번째 추출은 시스템을 증명해. workshop 둘이 중립 queue kernel 를 벌어들인 뒤에도 더 어려운 질문이 남아 있었어. kernel 을 실제 제품 하나로 만들어 주는 접착 코드, 그러니까 engine 몸통이나 CLI 동사, attachment 저장소 같은 것들이 어디로 가야 하는가 하는 문제야. 얼핏 제품 색깔이 진해서 첫 추출에서는 빠져나갔거든.

답은 편집이 아니라 census 로 왔어. 뭔가 옮기기 전에 프로그램은 먼저 셌어. attachment 저장소는 두 workshop 사이에서 바이트까지 똑같았어. engine 과 CLI 도 각자 앱 이름만 지우면 같았는데, 아무도 정당화 못 하는 drift 딱 세 개가 남아 있었지. slug 를 어느 층이 만들어 내는지, one-open 경합을 어느 쪽이 막는지, 착지가 어느 repo 를 수렴시키는지. 추출은 그 seam 을 가져가면서 drift 들을 그 자리에서 조정했어. 같은 텍스트는 단서일 뿐이고, 조정된 차이가 craft 야. 웹 UI 를 engine 포트에서 서빙하는 정책 하나는 스물여섯 개 engine 에서 세 가지 모양으로 손수 짜여 있었는데 — census 는 second-use 창을 진작 놓쳤다는 사실을 발견하는 방법이기도 해. 사본이 스물여섯 개면 두 번째 사본은 아주 옛날에 지나갔거든. 브라우저 origin 규칙 하나는 똑같은 복사본 열 개에, 두 검사 순서가 조용히 뒤집힌 사본 하나가 숨어 있었지. “이거 반복되는 것 같은데”가 여기서 측정값이 돼. 사본 몇 개, 모양 몇 가지, 어느 하나가 drift 했는지까지.

운반 수단은 workshop 자기 사다리였어. promotion 트랙이 가르치는 그 명시적 경로로 만들어진 named pipeline 하나가 추출 자체를 domain 으로 삼았지. plumbing 모양 하나를 공유 kit 으로 옮기고 사본 전부를 수렴시키는 일. 그 파이프라인으로 하루 오후에 일곱 건의 승격이 뛰었고, 전부 같은 기록 시스템의 평범한 row 로 큐잉·게이트·착지됐어. doctrine 은 자기 workshop 을 만나서도 살아남은 게 아니라, 자기 반복을 위한 도구까지 만들어낸 거야.

추출 뒤에 경계가 어디 사는지 봐. 각 consumer 는 “여기 편집하지 마”라고 찍힌 생성 사본을 vendor 하고, 손편집이 들어오면 drift test 가 test suite 를 떨궈. 수정은 upstream 에서 한 번만 일어나고 resync 로 퍼져. 주석 몇 줄짜리 경고는 마감 앞에서 지는데 빨간 테스트는 안 지거든. 구조로 지키는 경계가 문장으로 지키는 경계보다 오래 살아.

프로젝트가 아니라 상시 관행이야

몇 주 뒤 kit-ification 을 묶던 우산 태스크는 닫혔어. 추출이 끝나서가 아니라 영원히 안 끝나서야. sibling 들이 자라면서 새 seam 이 계속 나타나고, 각각은 같은 루프로 들어와. census, 승격, resync. 그 뒤 git 로그를 채우는 resync 커밋들은 노이즈가 아니야. seam 이 upstream 변경을 한 번에 하나씩 받아들이는 모습이고, 건강한 수렴이란 바로 그 모양이야. 그 스트림을 읽는 법을 익혀둬. 새 동작을 싣는 커밋이 시그널이고, 사본을 수렴시키는 커밋은 관리야. 둘을 헷갈리면 살아있는 시스템이 시끄러워 보여.

재고, 한 번만 추출하고, 구조로 지켜. census 가 반복을 측정값으로 바꾸고, kit 이 seam 을 사본 하나로 바꾸고, drift test 가 경계를 스스로 집행하게 만들어. 주석으로 끝난 추출은 그 순간부터 drift 하고 있어.

Code

추출 전에 사본을 모양별로 census·python
import hashlib

def census(copies: dict[str, tuple[str, str]]) -> dict[str, list[str]]:
    """Group vendored copies by shape after app-name normalization."""
    shapes: dict[str, list[str]] = {}
    for app, (text, own_name) in copies.items():
        neutral = text.replace(own_name, "<app>")
        digest = hashlib.sha256(neutral.encode()).hexdigest()
        shapes.setdefault(digest, []).append(app)
    return shapes

copies = {
    "crucible":   ("rows = PipelineRows('crucible')",   "crucible"),
    "touchstone": ("rows = PipelineRows('touchstone')", "touchstone"),
    "anvil":      ("rows = load_json('anvil.json')",    "anvil"),
}
shapes = census(copies)
assert sorted(len(v) for v in shapes.values()) == [1, 2]
widest = max(shapes.values(), key=len)
assert set(widest) == {"crucible", "touchstone"}  # extract this seam first
print(f"{len(shapes)} shapes; extract the {len(widest)}-copy seam first")

External links

Exercise

네 프로젝트 세 군데 이상에 사는 helper 하나를 골라. 각 사본을 정규화하고(이름, 경로), 모양을 지문으로 찍고, 추출 순서랑 그 결정을 뒤집을 증거 딱 하나를 적어봐.
Hint
정규화 후 바이트까지 같으면 제일 강한 신호야. drift 한 사본은 추출이 거절해야 할 seam 의 이름을 알려줘.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.