docs(TechLog): 주제 셋을 스킬대로 다시 쓰고 SSOT 를 저장소 실물로 고친다
건너뛴 참조 다섯을 읽고 나서 다시 썼다 — from-ssot-to-records.md 의 「그림과 증거는 배정 대상이다」, code-tables-diagrams.md 의 표·코드 규칙, explaining.md 의 「이름을 댔으면 왜 있는지도 댄다」. **SSOT 를 먼저 고쳤다.** §3.3 의 코드블록이 저장소와 달랐다 — PATH_PREFIX_KINDS 는 Record 표가 아니라 튜플 배열이고, 진짜 경로 표는 EXPLORE_KIND_PATHS 다. 저장소에서 확인해 실물로 바꾸고, javadoc 이 적어 둔 이유를 함께 옮겼다. §16.7 에 BRANCH_FIELDS 와 pathOf 실물을, §4.3 에 ContractRouteCoverageTest 의 javadoc 과 면제 상수 둘을 더했다. 62,643 → 65,737 자. **계약에 ssot-assets·ssot-evidence 를 배정했다.** 그 절차를 건너뛰어서 SSOT 가 이미 가진 그림과 측정이 글감에 배정되지 않은 채였다. TechLog 12 글감, keycloak-session-store 는 그림 21장·증거 19건을 배정하고 붙일 글감이 없는 그림 4장은 이유를 계약에 적었다. 배정하자 검사기가 「배정한 증거를 기록이 쓰지 않는다」 4건을 드러냈다. **주제 셋을 다시 썼다.** hand-listed-kinds 중앙값 1,925 → 3,760 자 declared-but-not-implemented → 2,608 자 values-lost-between-boundaries → 2,602 자 게시된 기록은 keycloak 4,546 · n+1liner 3,190 이다. 표와 코드를 SSOT 에서 옮기고, Reference 에 담을 수 없던 표(§5.5 의 여덟 자리)를 짝이 되는 Case 로 내렸다. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
6feee5ba57
commit
a8ce0dda07
+22
-8
@@ -61,24 +61,38 @@ tech-log-frontend : 31afb4d 이후
|
||||
|
||||
## 상세가 없으면 목록이 전부 실어야 한다
|
||||
|
||||
결정은 자기 화면을 갖지 않는다. 공개 라우트는 `/projects/{slug}/decisions` 하나이고, 개별 결정은 그 목록 위의 앵커로 간다.
|
||||
결정은 자기 화면을 갖지 않는다. 공개 라우트는 프로젝트의 결정 목록 하나이고, 개별 결정은 그 목록 위의 앵커로 간다.
|
||||
|
||||
상세를 부를 곳이 없으므로 화면이 그리는 칸이 전부 목록 항목에 있어야 한다.
|
||||
앞선 종류들과 여기서 갈린다. Case 와 Reference 와 Question 은 상세 화면이 있어서 목록 항목이 가볍고 상세를 부르면 나머지가 온다. 결정에는 상세를 부를 곳이 없으므로 화면이 그리는 칸이 전부 목록 항목에 있어야 한다.
|
||||
|
||||
## 네 증상이 한 원인이었다
|
||||
|
||||
`ProjectDecisionItem` 에 `title` 이 없어서 프론트가 `statement` 를 제목 칸에 썼다. 결정문은 한 문장이 아니라 문단일 수 있으므로 제목 칸에 전문이 들어갔다.
|
||||
목록 항목에 `title`·`summary`·`consequences`·`evidence` 가 빠져 있었고, 화면 쪽이 없는 칸을 각자 메우고 있었다.
|
||||
|
||||
`summary` 가 없어서 요약 줄이 비었다. `consequences` 와 `evidence` 가 없어서 프론트가 그 둘을 빈 배열로 고정해 뒀다.
|
||||
| 화면에서 무엇이 보였나 | 목록 항목에 무엇이 없었나 | 프론트가 무엇으로 메웠나 |
|
||||
|---|---|---|
|
||||
| 제목 자리에 결정문 전문 | `title` | `statement` 를 제목 자리에 씀 |
|
||||
| 요약 줄이 비어 있음 | `summary` | 아무것도 그리지 않음 |
|
||||
| 영향과 근거가 늘 비어 있음 | `consequences` · `evidence` | 빈 배열로 고정 |
|
||||
|
||||
줄바꿈은 다른 이유였다. 마크다운이 아닌 칸의 줄바꿈을 화면이 접고 있었다.
|
||||
결정문은 한 문장이 아니라 문단일 수 있다. 제목 자리에 전문이 들어가면 목록의 한 줄이 문단 높이로 늘어난다.
|
||||
|
||||
## DB 에는 값이 다 있었다
|
||||
줄바꿈은 원인이 달랐다. 마크다운이 아닌 칸의 줄바꿈을 화면이 접고 있었고, 그것은 목록 항목의 문제가 아니라 렌더링의 문제였다.
|
||||
|
||||
DB 를 조회하면 작성자가 쓴 제목과 여러 줄 요약과 영향 4건이 있었다. 어느 것도 화면까지 오지 못했다.
|
||||
## 저장된 값은 그대로 있었다
|
||||
|
||||
데이터베이스를 조회하면 작성자가 쓴 제목과 여러 줄 요약과 영향 4건이 있었다. 어느 것도 화면까지 오지 못했다.
|
||||
|
||||
Studio 편집기에서는 그 값들이 다 보인다. 두 화면이 같은 데이터를 보는데 한쪽만 비었으므로, 다른 것은 그 사이에 놓인 계약이다.
|
||||
|
||||
## 화면 쪽에서 역으로 확인한다
|
||||
|
||||
이 부류는 응답에서 출발하면 보이지 않는다. 응답에 없는 칸을 찾는 일이기 때문이다.
|
||||
|
||||
화면이 그리는 칸을 먼저 적고 그 칸이 응답에 있는지 하나씩 맞춰야 한다. 상세 endpoint 가 없는 종류에서는 그 목록이 곧 문서 전체가 된다.
|
||||
|
||||
## 확인하지 못한 것
|
||||
|
||||
저장된 값은 조회로 확인했다. 그 시점의 화면 캡처는 남기지 않았다.
|
||||
저장된 값이 그대로였다는 것은 조회로 확인했다. 그 시점의 화면 캡처는 남기지 않았다.
|
||||
|
||||
<!-- body:end -->
|
||||
|
||||
+29
-5
@@ -69,21 +69,45 @@ tech-log-backend : a5f93b9 이후
|
||||
const summary = body.purposeSummary as string; // 계약에 그런 칸이 없다
|
||||
```
|
||||
|
||||
`as string` 이 붙어 있으므로 컴파일러는 그 이름이 응답 타입에 있는지 묻지 않는다. 실행하면 `undefined` 가 나오고 화면은 빈 문자열을 그린다.
|
||||
`as` 는 「이 값을 이 타입으로 다루겠다」는 선언이므로, 컴파일러는 그 이름이 응답 타입에 있는지 묻지 않는다. 실행하면 `undefined` 가 나오고 화면은 빈 문자열을 그린다.
|
||||
|
||||
계약이 주는 이름은 `scopeSummary`, `appliesTo`, `excludedScope` 다.
|
||||
| 게이트웨이가 읽던 이름 | 계약이 주는 이름 |
|
||||
|---|---|
|
||||
| `purposeSummary` | `scopeSummary` |
|
||||
| `applyWhenMarkdown` | `appliesTo` |
|
||||
| `exceptionsMarkdown` | `excludedScope` |
|
||||
| `examplesMarkdown` | (해당 칸 없음) |
|
||||
|
||||
## 본문이 다른 테이블에 있었다
|
||||
|
||||
두 번째 원인은 저장 구조였다. Reference 의 본문은 문서 본문 칸이 아니라 `reference_detail` 의 규칙과 예시에 들어 있다. Studio 편집기가 규칙을 제목과 본문으로 나눠 받고 마크다운 본문을 비워 두기 때문이다.
|
||||
첫 번째 원인을 고쳐도 본문은 여전히 비어 있었다. 두 번째 원인이 저장 구조에 있었다.
|
||||
|
||||
공개 조회는 문서 본문만 읽고 `content: ""` 를 내보냈다. 첫 번째 원인을 고쳐도 본문은 여전히 비어 있었다.
|
||||
Reference 의 본문은 문서 본문 칸이 아니라 규칙과 예시를 담는 별도 테이블에 들어 있다. Studio 편집기가 규칙을 제목과 본문으로 나눠 받고 마크다운 본문을 비워 두기 때문이다. 공개 조회는 문서 본문만 읽고 빈 문자열을 내보냈다.
|
||||
|
||||
한 종류의 저장 구조가 다른 종류와 다르면 조회 쪽이 그것을 알아야 한다. 여기서는 몰랐다.
|
||||
|
||||
## 같은 신호가 여덟 번 더 있었다
|
||||
|
||||
계약에 칸이 없어 값이 화면에 오지 못한 것이 이 건 말고도 여덟 번 있었다.
|
||||
|
||||
| 무엇이 비었나 | 원인 |
|
||||
|---|---|
|
||||
| 문서 요약(제목 아래 한 줄) | 공개 응답에 `summary` 자리가 없어 유형별 요약을 대신 씀 |
|
||||
| 프로젝트 「주요 주제」 | `project_topic` 테이블도 조인도 가능했는데 응답에 실을 칸이 없었다 |
|
||||
| 프로젝트 기록 목록의 요약·주제·게시일 | `RelatedEntry` 를 그대로 실어 칸이 없었다 |
|
||||
| 질문 목록의 주제 | 지식 목록은 처음부터 `primaryTopic` 을 실었는데 질문 목록만 빠짐 |
|
||||
| 프로젝트·주제의 논지 | 담을 칸이 없어 `purpose` 를 대신 보여 줌 |
|
||||
| 주제 목록의 논지·축 | 이름과 개수만 실어, 독자가 들어갈지 말지 정할 근거가 없었다 |
|
||||
| 프로젝트 목록 행의 slug | 다른 목록이 프로젝트를 가리킬 때 쓰는 것은 id 가 아니라 slug 인데 행이 싣지 않았다 |
|
||||
| 결정 목록 항목의 slug | 공개 주소가 앵커인데 항목에 slug 가 없어 화면이 앵커를 달 수 없었다 |
|
||||
|
||||
문서 요약은 증상이 조금 다르다. 빈 칸에 유형별 요약을 대신 넣었더니 머리말이 바로 아래와 같은 글을 두 번 말했다 — 비어 보이는 대신 겹쳐 보였다.
|
||||
|
||||
## 값이 아니라 이름을 지킨다
|
||||
|
||||
고친 뒤에 둔 테스트는 값을 비교하지 않는다. 게이트웨이가 읽는 이름이 계약의 타입에 있는지를 `satisfies` 로 묻는다. 계약에서 그 칸이 사라지면 컴파일이 먼저 멈춘다.
|
||||
|
||||
값을 비교하는 테스트로는 이 결함이 잡히지 않았을 것이다. 픽스처를 게이트웨이가 읽는 이름으로 만들면 값이 그대로 나오기 때문이다.
|
||||
값을 비교하는 테스트로는 이 결함이 잡히지 않는다. 픽스처를 게이트웨이가 읽는 이름으로 만들면 값이 그대로 나오기 때문이다 — 테스트 작성자와 게이트웨이 작성자가 이름에 대해 합의한 것을 확인할 뿐이다.
|
||||
|
||||
## 확인하지 못한 것
|
||||
|
||||
|
||||
+17
-5
@@ -63,18 +63,22 @@ tech-log-backend : 92679f5 이후
|
||||
|
||||
## 세 번 버려졌다
|
||||
|
||||
관계 목록의 라벨을 고치고 화면을 봤을 때 요약은 여전히 비어 있었다. 값이 지나는 경계를 하나씩 따라가니 세 곳에서 버려지고 있었다.
|
||||
|
||||
```text
|
||||
계약(요약 있음)
|
||||
└─ flattenRelations 가 담지 않음 ← 1차로 고침
|
||||
└─ 렌더 모델로 바꿀 때 버림 ← 담을 칸 자체가 없었다
|
||||
└─ 렌더 모델로 바꿀 때 버림 ← 담을 자리 자체가 없었다
|
||||
└─ 화면 목록으로 넘길 때 또 버림
|
||||
```
|
||||
|
||||
첫 번째를 고치고 화면을 봤을 때도 요약은 비어 있었다. 두 번째를 고치려고 보니 렌더 모델 계약에 담을 칸이 없었고, `additionalProperties: false` 라 계약을 고치지 않고는 실을 수 없었다.
|
||||
첫 번째는 코드가 그 칸을 안 읽은 것이라 한 줄로 고쳤다. 두 번째에서 막혔다 — 렌더 모델 계약에 담을 칸이 없었고, 그 스키마가 `additionalProperties: false` 라 계약을 고치지 않고는 실을 수도 없었다.
|
||||
|
||||
## 계약에 칸을 더할 때 required 를 따로 판단한다
|
||||
|
||||
`ResolvedRelation` 에 `summary` 를 더하면서 required 에는 넣지 않았다. 이미 나가 있는 응답에는 그 칸이 없어서, required 로 올리면 배포 순서에 따라 검증이 깨진다.
|
||||
렌더 모델에 `summary` 를 더했다. required 에는 넣지 않았다.
|
||||
|
||||
이미 나가 있는 응답에는 그 칸이 없다. required 로 올리면 계약을 반입한 쪽이 배포되기 전까지 그 응답이 검증에 걸린다. 배포 순서에 따라 깨지는 것과 값이 안 오는 것 중에서 뒤쪽을 골랐다.
|
||||
|
||||
## 한 칸에 셋이 뭉쳐 있었다
|
||||
|
||||
@@ -82,11 +86,19 @@ tech-log-backend : 92679f5 이후
|
||||
|
||||
| 무엇 | 뜻 | 경로별로 어떻게 나왔나 |
|
||||
|---|---|---|
|
||||
| 대상의 종류 | 「근거」「관련 기준」 같은 분류 | 렌더 모델 경로: 작성자의 문장이 이 칸에 눌려 나옴 |
|
||||
| 대상의 종류 | 「근거」「관련 기준」 같은 분류 | 렌더 모델 경로: 작성자의 문장이 이 자리에 눌려 나옴 |
|
||||
| 작성자가 쓴 이유 | 「다음에 무엇을 읽을지」의 답 | 공개 조회 경로: **아예 버려짐** |
|
||||
| 대상의 요약 | 대상이 무엇인지 | — |
|
||||
|
||||
셋을 `label` · `note` · `summary` 로 갈랐다. 설명 칸에는 작성자가 쓴 문장이 있으면 그것을, 없으면 대상의 요약을 보인다. 요약은 대상을 설명하고 문장은 왜 지금 이것을 읽어야 하는지를 설명한다.
|
||||
한 칸에 셋이 들어가니 경로마다 다른 것이 나왔다. 렌더 모델을 지나는 화면에서는 작성자가 쓴 문장이 분류 자리에 눌려 나왔고, 공개 조회를 지나는 화면에서는 그 문장이 아예 사라졌다.
|
||||
|
||||
셋을 `label`·`note`·`summary` 로 갈랐다. 설명 자리에는 문장이 있으면 문장을, 없으면 요약을 보인다. 요약은 대상이 무엇인지 말하고 문장은 왜 지금 그것을 읽어야 하는지 말하므로, 문장이 없을 때 요약으로 대신하는 것은 되지만 반대는 되지 않는다.
|
||||
|
||||
## 한 경계를 고치고 판단하면 안 된다
|
||||
|
||||
이 건에서 「고쳤다」고 두 번 판단했고 두 번 다 틀렸다. 값이 지나는 경계가 열한 개인데 그중 하나만 보고 판단했기 때문이다.
|
||||
|
||||
확인은 배포본에서, 그 값이 실제로 그려지는 곳에서 한다. 타입 검사와 단위 테스트와 「코드를 읽어 보니 맞다」는 전부 중간 지점이다.
|
||||
|
||||
## 확인하지 못한 것
|
||||
|
||||
|
||||
+22
-13
@@ -35,6 +35,8 @@ source:
|
||||
|
||||
## 열한 번 모양이 바뀐다
|
||||
|
||||
공개 화면의 한 줄은 게시 시점에 굳어진 투영 테이블에서 출발해 열한 번 모양을 바꾼 뒤에 그려진다.
|
||||
|
||||
```text
|
||||
PostgreSQL 테이블
|
||||
└─ public_resource_projection (게시 시점에 굳어진 투영)
|
||||
@@ -52,30 +54,37 @@ PostgreSQL 테이블
|
||||
:::evidence key="value-boundaries" alt="저장·백엔드 조립·HTTP envelope·프론트엔드 조립·화면 다섯 묶음을 세 저장소 구역으로 나눠 이은 흐름도" caption=" " zoom="true"
|
||||
:::
|
||||
|
||||
저장 쪽에 둘, 백엔드 조립에 넷, 전선에 하나, 프론트엔드 조립에 셋, 화면에 하나다.
|
||||
저장 쪽에 둘, 백엔드 조립에 넷, 전선에 하나, 프론트엔드 조립에 셋, 화면에 하나다. 저장소 경계로 보면 백엔드가 여섯, 전선이 하나, 프론트엔드가 넷이다.
|
||||
|
||||
이 기간에 적은 결함의 절반 이상이 「이 중 한 경계가 값을 버렸다」는 같은 모양이었다.
|
||||
## 경계마다 무엇이 값을 지키는가
|
||||
|
||||
## 어디서 검사가 끊기는가
|
||||
같은 경계라도 무엇이 확인되는지가 다르다.
|
||||
|
||||
경계마다 무엇이 값을 지키는지가 다르다.
|
||||
| 어디 | 무엇이 확인되나 | 무엇이 확인되지 않나 |
|
||||
|---|---|---|
|
||||
| 어댑터 SQL | 실행할 때 컬럼이 있는지 | 컴파일 시점에는 컬럼 이름을 아무도 안 본다 |
|
||||
| 생성된 DTO | 계약의 스키마 모양 | 그 칸에 값이 담겼는지 |
|
||||
| 게이트웨이 매퍼 | 계약이 준 타입의 이름 | `as` 단언을 쓰면 그 확인이 사라진다 |
|
||||
| 포트와 화면 | 두 타입이 맞는지 | 포트와 어댑터가 타입을 따로 들면 한쪽만 늘어난다 |
|
||||
|
||||
JDBC 어댑터의 SQL 은 컬럼 이름을 문자열로 적는다. 컬럼이 없거나 이름이 다르면 실행할 때 알게 된다.
|
||||
어댑터 SQL 은 컬럼 이름을 문자열로 적는다. 이름이 틀리면 실행할 때 알게 되고, 그 SQL 을 실제로 돌리는 검사가 없으면 배포 뒤에 알게 된다.
|
||||
|
||||
계약이 만든 DTO 와 생성된 타입 사이는 생성기가 지킨다. 다만 생성기가 보는 것은 스키마의 모양이고, 그 칸에 값이 담기는지는 보지 않는다.
|
||||
|
||||
게이트웨이의 매퍼는 계약의 타입을 읽는다. `as` 단언을 쓰면 그 확인이 사라진다.
|
||||
|
||||
포트 타입과 화면 컴포넌트 사이는 TypeScript 가 지킨다. 포트와 어댑터가 타입을 따로 들고 있으면 그 확인도 사라진다.
|
||||
|
||||
## 값을 버려도 오류가 나지 않는다
|
||||
|
||||
이 경계들은 값을 담지 않아도 그렇다고 말하지 않고 다음으로 넘긴다.
|
||||
이 경계들은 값을 담지 않았다고 말하지 않는다. 담지 않은 채 다음으로 넘긴다.
|
||||
|
||||
`undefined` 는 화면에서 빈 문자열이 된다. 빈 배열은 「항목이 없습니다」가 된다. 그래서 화면만 보면 값이 없는 것과 값을 잃은 것이 같아 보인다.
|
||||
`undefined` 는 화면에서 빈 문자열이 되고 빈 배열은 「항목이 없습니다」가 된다. 그래서 화면만 보면 값이 없는 것과 값을 잃은 것이 같아 보이고, 작성 도구에서는 작성자가 그것을 자기가 아직 쓰지 않은 것으로 읽는다.
|
||||
|
||||
## 두 화면이 같은 데이터를 볼 때
|
||||
## 계약을 지나는 길이 둘이다
|
||||
|
||||
Studio 와 공개 화면은 같은 DB 를 보지만 계약이 다르다. Studio 는 작성 계약을, 공개 화면은 조회 계약을 지난다. 한쪽에만 값이 보이면 그 사이의 계약에 칸이 없다.
|
||||
Studio 편집기와 공개 화면은 같은 데이터베이스를 보지만 다른 계약을 지난다. 작성 쪽은 작성 계약을, 조회 쪽은 조회 계약을 지난다.
|
||||
|
||||
두 화면이 같은 값을 두고 다르게 보이면 그 사이에 있는 것은 저장소가 아니라 계약이다. 이 저장소에서 그 신호가 여덟 번 같은 원인을 가리켰다.
|
||||
|
||||
## 이 문서의 결함 절반이 여기서 났다
|
||||
|
||||
이 기간에 적은 결함의 절반 이상이 「이 중 한 경계가 값을 버렸다」는 같은 모양이었다. 한 경계를 고치고 확인하면 다음 경계가 같은 값을 다시 버리는 일도 났다.
|
||||
|
||||
<!-- body:end -->
|
||||
|
||||
+17
-6
@@ -28,31 +28,40 @@ Studio 편집기에서는 값이 다 보이는데 공개 화면만 비어 있으
|
||||
|
||||
## 목적
|
||||
|
||||
DB 에 값이 있는데 화면이 비어 있을 때, 어디를 먼저 볼지 정한다. 이 부류는 오류를 내지 않으므로 로그에서 출발하면 아무것도 나오지 않는다.
|
||||
데이터베이스에 값이 있는데 화면이 비어 있을 때 어디를 먼저 볼지 정한다.
|
||||
|
||||
이 부류는 오류를 내지 않으므로 로그에서 출발하면 아무것도 나오지 않는다. `undefined` 는 빈 문자열로 그려지고 빈 배열은 「항목이 없습니다」로 그려진다.
|
||||
|
||||
## 규칙
|
||||
|
||||
**Studio 에서는 보이고 공개 쪽만 비면 그 사이의 계약을 먼저 본다**
|
||||
두 화면이 같은 DB 를 보는데 한쪽만 비면, 다른 것은 그 사이에 놓인 계약이다.
|
||||
두 화면이 같은 데이터베이스를 보는데 한쪽만 비면, 다른 것은 그 사이에 놓인 계약이다. 작성 쪽은 작성 계약을 지나고 조회 쪽은 조회 계약을 지난다. 이 저장소에서 같은 신호가 여덟 번 같은 원인을 가리켰다.
|
||||
|
||||
**화면이 그리는 칸을 먼저 적고 응답에 있는지 하나씩 맞춘다**
|
||||
응답에서 출발하면 없는 칸은 보이지 않는다. 상세 endpoint 가 없는 종류에서 특히 그렇다 — 목록 항목이 문서 전체를 실어야 한다.
|
||||
응답에서 출발하면 없는 칸은 보이지 않는다. 상세 endpoint 가 없는 종류에서 특히 그렇다 — 부를 상세가 없으므로 목록 항목이 문서 전체를 실어야 하고, 그 목록에 없는 칸은 화면이 각자 메운다.
|
||||
|
||||
**한 종류의 저장 구조가 다른 종류와 다르면 조회 쪽이 그것을 알아야 한다**
|
||||
Reference 의 본문은 문서 본문 칸이 아니라 규칙과 예시를 담는 별도 테이블에 있다. 이름이 맞아도 읽는 곳이 틀리면 빈 문자열이 나온다.
|
||||
|
||||
**칸을 더할 때 required 로 올릴지는 따로 판단한다**
|
||||
이미 나가 있는 응답에는 그 칸이 없다. required 로 올리면 배포 순서에 따라 검증이 깨진다.
|
||||
이미 나가 있는 응답에는 그 칸이 없다. required 로 올리면 계약을 반입한 쪽이 배포되기 전까지 그 응답이 검증에 걸린다. 배포 순서에 따라 깨지는 것과 값이 안 오는 것 중에서 고른다.
|
||||
|
||||
**값이 아니라 이름을 지키는 검사를 둔다**
|
||||
게이트웨이가 읽는 이름이 계약의 타입에 있는지를 묻는다. 값을 비교하는 검사는 픽스처를 게이트웨이가 읽는 이름으로 만들면 그대로 통과한다.
|
||||
게이트웨이가 읽는 이름이 계약의 타입에 있는지를 묻는다. 값을 비교하는 검사는 픽스처를 게이트웨이가 읽는 이름으로 만들면 그대로 통과한다 — 테스트 작성자와 게이트웨이 작성자가 이름에 대해 합의한 것을 확인할 뿐이다.
|
||||
|
||||
## 적용 조건
|
||||
|
||||
같은 데이터를 두 표면이 각자의 계약으로 읽고, 한쪽만 비어 보이는 화면. 작성 계약과 조회 계약이 나뉜 구조에서 걸린다.
|
||||
|
||||
계약에 칸을 더하거나 화면에 칸을 더하는 변경에서도 건다. 화면이 먼저 늘면 그 칸이 응답에 있는지 확인할 곳이 없다.
|
||||
|
||||
## 예외
|
||||
|
||||
두 표면이 같은 계약을 쓰면 이 신호는 성립하지 않는다. 그때는 매퍼나 질의를 먼저 본다.
|
||||
|
||||
저장 구조가 종류마다 다르면 계약이 아니라 조회가 원인일 수 있다. Reference 의 본문이 문서 본문 칸이 아니라 별도 테이블에 있던 것이 그 예다.
|
||||
저장 구조가 종류마다 다르면 계약이 아니라 조회가 원인일 수 있다. 이름이 계약과 맞는데도 값이 비면 그쪽을 본다.
|
||||
|
||||
값이 있는데 겹쳐 보이는 경우는 이 신호가 아니다. 빈 칸을 다른 값으로 메우면 같은 글이 두 번 나온다.
|
||||
|
||||
## 예시
|
||||
|
||||
@@ -63,3 +72,5 @@ DB 에 값이 있는데 화면이 비어 있을 때, 어디를 먼저 볼지 정
|
||||
질문 목록만 주제가 빠져 있어서 질문 줄의 맥락이 「· 프로젝트」로 시작했다. 지식 목록은 처음부터 그 칸을 싣고 있었다.
|
||||
|
||||
프로젝트 목록 행에 slug 가 없었다. 다른 목록이 프로젝트를 가리킬 때 쓰는 것은 id 가 아니라 slug 다.
|
||||
|
||||
문서 요약 자리에 유형별 요약을 대신 넣었더니 머리말이 바로 아래와 같은 글을 두 번 말했다.
|
||||
|
||||
+15
-6
@@ -29,31 +29,38 @@ source:
|
||||
|
||||
## 목적
|
||||
|
||||
「고쳤다」는 판단이 틀리는 것을 막는다. 값이 열한 경계를 지나는 구조에서 한 경계만 보고 판단하면, 다음 경계가 같은 값을 다시 버려도 알 수 없다.
|
||||
「고쳤다」는 판단이 틀리는 것을 막는다.
|
||||
|
||||
값이 열한 경계를 지나는 구조에서 한 경계만 보고 판단하면, 다음 경계가 같은 값을 다시 버려도 알 수 없다. 이 저장소에서 그 판단이 세 번 틀렸다.
|
||||
|
||||
## 규칙
|
||||
|
||||
**고친 값이 실제로 그려지는 곳까지 가서 본다**
|
||||
배포본에서 그 화면을 열거나, 실제 요청을 보내 응답을 읽는다.
|
||||
배포본에서 그 화면을 열거나 실제 요청을 보내 응답을 읽는다. 관계 요약은 세 경계에서 연달아 버려졌고, 매번 화면을 보고 나서야 다음 경계가 버리는 것을 알았다.
|
||||
|
||||
**타입 검사 통과를 반영의 증거로 쓰지 않는다**
|
||||
메서드 매개변수의 bivariance, `as` 단언, 검사 대상이 없는 tsconfig 가 각각 통과시킨 사례가 있다.
|
||||
메서드 매개변수의 bivariance, `as` 단언, 검사 대상이 없는 tsconfig 가 각각 통과시킨 사례가 있다. 통과는 「코드가 맞다」가 아니라 「검사가 그 질문을 하지 않았다」를 뜻할 수 있다.
|
||||
|
||||
**게이트웨이를 실제로 불러 어떤 연산이 나가는지 확인한다**
|
||||
등록을 빠뜨린 연산은 옆 분기로 떨어지므로 서버는 정상 응답을 준다. 나가는 경로를 봐야 알 수 있다.
|
||||
|
||||
**여정이 끝나는 곳을 먼저 정하고 시작한다**
|
||||
어디까지 가면 확인이 끝나는지 모르면 중간에서 멈춘다.
|
||||
어디까지 가면 확인이 끝나는지 모르면 중간에서 멈추게 된다. 공개 화면의 한 줄이면 그 줄이 그려지는 화면이 끝이다.
|
||||
|
||||
**검사가 덮는 구간을 적어 둔다**
|
||||
값이 아니라 이름을 지키는 검사를 두면 여정의 한 구간을 그 검사가 대신한다. 그 구간이 어디까지인지 적어 두지 않으면 다음 사람이 검사를 여정 전체로 읽는다.
|
||||
|
||||
## 적용 조건
|
||||
|
||||
값이 계약·매퍼·포트를 여러 번 갈아타는 구조에서 「고쳤다」를 판단할 때. 계약을 소유한 저장소가 따로 있고 생성기를 지나 들어오면 특히 걸린다.
|
||||
|
||||
앞선 커밋이 같은 값을 고치려다 못 고친 이력이 있으면 반드시 건다. 그 커밋이 무엇을 근거로 고쳤다고 판단했는지가 대개 중간 지점이다.
|
||||
|
||||
## 예외
|
||||
|
||||
경계가 하나뿐이거나 고친 그 곳이 여정의 끝이면 중간 확인으로 충분하다.
|
||||
|
||||
값이 아니라 이름을 지키는 검사를 이미 뒀으면 그 검사가 여정의 한 구간을 대신한다. 다만 검사가 덮는 구간이 어디까지인지 적어 둔다.
|
||||
배포본을 열 수 없는 변경 — 아직 배포되지 않은 경로 — 은 여정의 끝까지 갈 수 없다. 그때는 어디까지 확인했는지를 적는다.
|
||||
|
||||
## 예시
|
||||
|
||||
@@ -61,4 +68,6 @@ source:
|
||||
|
||||
개념 삭제가 계속 질문 삭제 경로로 나갔다. 타입 검사가 통과해서 반영된 줄 알았고, 배포된 번들의 서버 로그에서 404 를 보고 알았다.
|
||||
|
||||
CONCEPT 을 `deleteQuestion` 으로 되돌려 가드가 깨지는 것을 확인했다.
|
||||
CONCEPT 을 질문 삭제로 되돌려 가드가 깨지는 것을 확인했다.
|
||||
|
||||
한 경계를 고치고 판단해 세 번 틀렸다. 값이 지나는 경계가 열한 개다.
|
||||
|
||||
Reference in New Issue
Block a user