수정이 이용자를 망가뜨릴 때

이 Part의 마지막 발견은 네 도구의 어디 안에도 없었다. 그것은 자상이었다:언어가 커맨드라인 인자를 알리는 방식으로의 작고 옳은 수정이, 언어로 쓰인 프로그램을 조용히 망가뜨렸다 —— 게다가 그저 그런 프로그램이 아니라, 언어 자신의 문서를 공개하는 바로 그 site generator를. 문서 사이트 전체가 404가 되었고, 누군가가 페이지를 방문해 알아챌 때까지 망가진 채였다. 이것은 역주하는 dogfood 루프이고, 이 Part의 실의 맺음 교훈이다.

meredogfoodregressioncompatibilitylanguage-design

이 Part의 마지막 발견은 네 도구의 어디 안에도 없었다. 그것은 언어 자신의 안에 있었고, 최악의 발견이 오는 방식으로 왔다 —— 실패하는 테스트로서가 아니라, 사람이 의지하던 무언가가 동작을 멈췄다는, 바깥 세계로부터의 보고로서. 문서 사이트가 자신의 페이지 하나에 404를 반환하고 있었다. 컴파일러의 테스트 스위트에서 빨강이 된 것은 아무것도 없었다;사이트는 단지, 조용히, 몇 릴리스 전부터 페이지를 세우기를 멈췄고, 링크가 따라져 비어서 돌아올 때까지 아무도 보지 않았다.

작고 옳은 수정

원인은, 그 자체의 관점에서는 완전히 옳았던 변경으로 거슬러 갔다. 이 run의 앞쪽에서, 작은 정리의 한 무리 중에, 프로그램이 커맨드라인 인자를 읽는 방식이 일관화되었다:프로그램이 받는 리스트는 사용자가 친 인자를 담아야 하고, 그 외엔 아무것도 담지 않는다. 수정 전엔 그것이 일관성 없이 스크립트 자신의 경로를 첫 요소로 담고 있었고, 그것은 인자를 읽는 모든 프로그램에 어색한 보상의 한 걸음을 지우는 종류의 작은 사마귀다. 그것을 없애는 것은 옳았다 —— 언어를 더 깔끔하게 하고, 모든 미래의 프로그램을 더 단순하게 했다. 수정에 나쁜 데는 아무것도 없었다. 그것이야말로 이 이야기를 말할 가치가 있게 만드는 것이다:손해는 버그에서 온 게 아니다. 실의 프로그램이 이미 그것에 의지해 쓰였던 거동을, 옳게 바꾼 것에서 왔다.

옛 사마귀에 의지하던 프로그램

문제의 프로그램은 site generator —— 그 자신 언어로 쓰였고, 그 자신 앞 Part의 dogfood —— 문서의 소스 파일을 공개된 website로 바꾸는 도구였다. 그것은 두 인자를 읽었다:입력 디렉터리와 출력 디렉터리. 하지만 그것은 인자 리스트가 아직 스크립트 경로로 시작하던 시절에 쓰였으므로, 입력 디렉터리를 읽기 전에 그 첫 요소를 주의 깊게 건너뛰었다. 수정이 스크립트 경로를 없애자, 그 주의 깊은 건너뜀은 대신 실의 인자를 건너뛰기 시작했다:generator는 출력 디렉터리를 입력인 양 읽고, 소스 파일을 하나도 갖지 않은 폴더에 찾으러 갔고, 변환할 페이지를 영 찾았고, 내용 페이지가 없는 사이트를 써 냈다. 크래시하지 않았다. 에러를 인쇄하지 않았다. 사이트를 세웠다고 보고했고, 실제 세웠다 —— 빈 것을. 옛 거동에 대해 옳았던 보상의 한 걸음이 새 그것에 대해 버그가 되었고, 그리고 망가지는 게 아니라 아무것도 찾지 않음 으로써 실패했으므로, 그것을 알리는 것은 아무것도 없었다.

왜 아무것도 잡지 못했나

이것을 멈췄어야 하고 멈추지 못한 모든 층에 대해 정직할 가치가 있다. 컴파일러의 테스트는 모두 통과 했다, 왜냐하면 그것들은 컴파일러를 테스트하고, 그것으로 세워진 프로그램을 테스트하지 않으므로. site generator에는, 그것을 끝에서 끝까지 돌리고 출력이 실제로 페이지를 담는지 확인하는 테스트가 없었다. 배포 파이프라인은 사이트를 재빌드하고 공개했지만, 페이지 수가 영으로 무너진 것을 알아채지 못했다, 왜냐하면 「빌드는 성공했다」와 「빌드는 무언가를 낳았다」는 다른 주장이고, 확인되던 것은 처음 것뿐이었으므로. 이것들의 각각은 Part의 앞 교훈과 같은 형태다:프로그램은 자기 자신의 형태가 닿는 아픔만 surface할 수 있고, 그리고 이것에 닿는 형태 —— 하류의 프로그램을 끝에서 끝까지 돌리고, 그 실의 출력을 주장하는 —— 를 아무도 쓰지 않았다. gap은 이번엔 언어 안에 없었다;그것은 언어와 그것에 의지하는 프로그램 사이의 공간에 있었고, 그것을 보고 있는 것은 아무것도 없었다.

dogfood 루프, 역주하다

이 프로젝트의 방법 전체에는 한 방향이 심어져 있다:실의 프로그램을 세우고, 그것에 아프게 하고, 수정을 언어로 상류에 밀어 올려, 모든 프로그램이 이득을 얻는다. 이 발견은 그 같은 흐름이 거꾸로 흐른 것이었다. 언어의 상류의 변경이, 옛 거동에 대해 쓰인 프로그램으로 하류로 흘러, 그것을 망가뜨렸다 —— 조용히, 왜냐하면 망가짐이 부재의 형태를 취했으므로. 그것은 dogfooding의 보답에 묶여 딸려 오는 리스크다:일단 실의 프로그램이 언어에 의지하면, 언어는 더는 진공 속에서 바뀔 수 없고, 그리고 「단독으로 옳다」는 「이미 쓰인 모든 것에게 안전하다」와 같지 않다. 보답은 리스크에 값한다 —— 언어 전체가 실의 이용자를 가짐으로써 더 강하다, 그 이용자가 자기 자신의 도구라 해도 —— 하지만 리스크는 실이고, 수정이 옳으니 공짜라고 가장하는 것이, 빈 website를 ship하는 방식이다.

즉각의 수리는 작았다:generator에게, 첫 인자는 이제 입력 디렉터리이고 건너뜀은 필요 없다, 고 가르치는 것, 그리고 사이트는 다시 페이지를 세웠고, 모든 문서 페이지가 응했다. 하지만 수리는 요점이 아니다. 요점은 실패의 형태다 —— 옳은 변경, 조용한 망가짐, 아무도 끝에서 끝까지 테스트하지 않던 하류의 프로그램, 죽은 링크를 따라가는 사람에 의해서만 찾아진 —— 그리고 그것은, 언어가 문제없다고 확인하기를 그만두고 어디가 문제인지를 찾으러 가기로 정한 것으로 시작한 Part의, 어울리는 맺음이다. 이 Part의 도구들은 미리 선택된 곳에서 아프도록 세워졌다. 이 마지막 아픔은 선택되지 않았다;그것은 언어의 자라는 표면적이 돌려보낸 첫 청구서였다. 그 청구서는 프로젝트가 도달한 가장 진실한 징표다:그것은, 언어를 바꾸는 것이 귀결을 가질 만큼, 마침내 충분한 것이 언어로 세워졌다, 를 뜻한다 —— 그것은 이 물건이 실이다, 라고 말하는 다른 방식이다.

← Back to Mere: 언어를 만들다