코드보다 먼저 쓴 여섯 줄
Sizzle 아키텍처 문서엔 Domain Model이라는 절이 있어. 두뇌스토밍 첫머리에 내가 제안했고, 레포가 태어난 날 아빠가 나머지 설계랑 같이 승인했지. 핵심은 여섯 줄짜리 표야. 줄마다 객체지향 용어 하나를 요리 쪽 대상 하나에 짝지우고, 그 대상이 뭘 담는지 적어. 표가 먼저였고, 엔진은 그 뒤에 만들어졌어. 그래서 지금도 스키마를 보면 표가 그대로 읽혀.
아래가 그 표야. 문서엔 없는 넷째 칸을 붙였어. 각 줄이 backend/store.py의 어디에 내려앉는지 적은 칸이야. 엔진이 켜질 때마다 저널에서 새로 짓는 SQLite 미러가 이 파일에 있어.
| OO 용어 | Sizzle 대상 | 담는 것 | 내려앉는 곳 |
|---|---|---|---|
| 추상 클래스 | 원리 | 기법이 하는 일, 통하는 이유, 필요한 재료 역할, 메서드 뼈대 | kind가 principle인 classes 행의 summary, why, roles, method |
| 구체 클래스 | 요리 | 원리 하나 이상을 구현한 이름 있는 요리, 그리고 이 요리를 이 요리로 만드는 역할 바인딩 | kind가 dish인 행의 bindings, 그리고 원리마다 class_parents 행 하나 |
| 오버라이드한 서브클래스 | 변형 | 다른 요리에서 갈라져 나온 요리, 이름 붙은 오버라이드와 각각의 이유 | kind가 variant인 행의 overrides, 그리고 부모 행 하나 |
| 객체 | 만남 | 진짜 접시 하나. 사진, 언제 어디서, 아빠가 어떻게 만났는지, 메모, 스레드 | encounters 행 하나, 그 photos 행들, 접시에 보이는 클래스로 가는 links 행들 |
| 인터페이스 | 역할 | 원리가 필요로 하는 슬롯과 예시 재료 | 테이블은 따로 없어. 원리 행의 roles JSON 칸이야 |
| private 멤버 | 파라미터 | 정확한 양, 시간, 온도 | 클래스 행의 parameters 텍스트 칸 |
클래스는 셋, 테이블은 하나
원리, 요리, 변형을 테이블 셋으로 나눌 수도 있었어. 근데 하나야. kind 칸이 이 행이 계층의 몇 층인지 말해 주고, 도메인 서비스는 거기 딱 세 값만 받아. backend/domain.py의 CLASS_KINDS야. 다른 층 몫인 칸은 빈 기본값으로 남아. 원리의 bindings도, 요리의 method도 빈 리스트 그대로지.
테이블이 하나라서 얻는 게 둘이야. 접시의 링크든 부모 간선이든 스레드든, 어느 테이블인지 묻지 않고 id 하나로 아무 클래스나 가리켜. 그리고 읽기가 돌려준 이름을 맞춰 보는 것도 검색 한 번이면 돼. find_dish가 요리랑 변형을 같이 뒤지거든.
네 칸은 구조를 JSON 텍스트로 담아. roles, method, bindings, overrides, 묶어서 CLASS_JSON_FIELDS야. 스토어는 클래스를 읽을 때 이걸 다시 리스트로 풀어. 나머지 name, gloss, cuisine, summary, why, parameters, verdict는 그냥 텍스트고. 남은 두 칸은 기록 자체를 설명해. status는 제안이나 채택 중 하나고(5강), origin은 읽기, 추론된 형제, 아빠 중 하나야.
깐깐한 사람이면 역할한테 테이블을 따로 줬을 거야. JSON 텍스트로 괜찮냐고? 여기선 괜찮아. 역할 안을 들여다보는 쿼리가 하나도 없거든. 역할은 통째로 읽고, 통째로 보여주고, 통째로 나한테 넘겨. 팬트리랑 맞춰 보는 건 부엌 대화에서 그 데이터를 받은 내 몫이야. 게다가 미러엔 마이그레이션이 없어. 켤 때마다 지우고 저널을 다시 재생하니까, 나중에 모양을 바꾸는 데 드는 값은 재시작 한 번이야. 그 재구축은 트랙 5에서 봐.
kind가 두 가지야
같은 단어 kind가 테이블 두 곳에 있는데, 답하는 질문이 달라. 클래스에선 층을 말해. principle, dish, variant. 만남에선 아빠가 그 접시를 어디서 만났는지야. out, home, market, other. 지금 확실히 갈라 둬. 4강에서 둘이 만나거든. 클래스의 증거는 거기 이어진 접시들의 kind로 계산하고, 클래스를 cooked로 만드는 건 home 하나뿐이야.
붙잡는 건 객체 하나뿐
문서의 만남 줄은 데이터 모델 전체를 한 문장으로 끝내. Sizzle이 붙잡는 건 만남뿐이고, 나머진 전부 만남에서 읽어 내거나 대화로 키운다는 거야. encounters 테이블을 보면 그게 보여. 접시엔 찍은 시각, 현지 날짜랑 시간대, kind, 아빠 메모, 장소, 그리고 읽기에 관한 칸 셋이 있어. 요리 이름은 어디에도 없어. 요리는 classes에 살고, links 테이블이 둘을 이어 줘. 그때 source는 reading 아니면 dad야. 접시는 객체야. 그게 무엇의 인스턴스인지는 옆에 따로 적어 둔 주장이고.
상속도 행이야. class_parents는 간선마다 (child, parent) 쌍을 하나씩 들고, 그 쌍이 기본 키라서 같은 간선은 두 번 못 들어가. 그 간선을 타고 복사되는 건 아무것도 없어. 그게 왜 중요한지는 3강에서 봐.
같은 어휘, 다른 결로 자르기
OO Quest를 걸어 봤다면 요리를 객체지향으로 보는 건 벌써 만나 봤을 거야. OO Quest 트랙 4, 요리: 맛의 조절판이 Sizzle이 자라 나온 생각이고, 이 퀘스트에서 그걸 다시 가르치진 않아. 다만 구분 하나는 짚고 갈게. 스키마를 정한 게 바로 그거라서.
그 트랙 4는 요리를 맛의 축으로 잘라. 짠맛, 단맛, 기름맛이 루트고, 감칠맛이랑 향이 믹스인이야. 요리를 읽을 땐 축마다 어디서 오는지 물어. Sizzle은 기법으로 잘라. 향을 기름에 먼저 옮기고 그 기름에서 익히는 원리는, 재료 역할을 인터페이스로 가진 메서드야. 향채, 기름, 주재료, 불. 기름은 양쪽에 다 나와. 한쪽에선 축이고, 다른 쪽에선 역할이야. 둘 다 부엌을 정직하게 읽은 객체지향이야. 그중에서 행 하나에 들어가고, 팬트리랑 맞춰 볼 수 있고, 접시 사진 한 장으로 제안할 수 있는 건 기법 쪽이야.