결정-0055: 컨텍스트 경계를 ArchUnit으로 강제한다
상태
Accepted
맥락
Java 의 접근 제어자는 패키지 단위이고 하위 패키지는 별개 패키지입니다. 따라서 컨텍스트의 내부를 감출 수단이 언어에 없습니다. contract 만 공개한다는 규칙을 세워도 컴파일러는 다른 패키지를 임포트하는 코드를 그대로 통과시킵니다.
문서에만 적힌 규칙은 지켜지지 않습니다. 특히 마감이 가까울 때 "이번만" 직접 참조하는 코드가 들어오고, 그것이 선례가 되어 다음 참조의 근거가 됩니다. 모듈러 모놀리스는 물리적 격리가 없으므로 이 침식이 아무 저항 없이 진행됩니다.
결정
구조 규칙을 ArchUnit 테스트로 인코딩하고 빌드 게이트에 포함합니다. 위반은 빌드 실패입니다.
| 항목 | 내용 |
|---|---|
| 규칙 위치 | 테스트 소스의 아키텍처 패키지 |
| 실행 시점 | 빌드 경로의 테스트 태스크에서 함께 실행됩니다 |
| 위반 표시 | 위반한 타입과 위치를 지목하여 실패합니다 |
규칙은 컨텍스트를 열거하지 않고 패키지에서 자동 판별합니다. 루트 다음 토큰을 컨텍스트로 추출하므로 컨텍스트가 추가되어도 테스트를 고치지 않습니다.
열거 방식을 쓰지 않는 이유는 명확합니다. 컨텍스트를 추가할 때마다 테스트를 고쳐야 하고, 고치는 것을 잊으면 새 컨텍스트만 검사에서 빠집니다. 검사가 도는데도 통과하므로 빠진 사실이 드러나지 않습니다.
이름으로 판정하는 규칙이 함께 들어갑니다. 명령 서비스가 조회 포트를 의존하지 않는다는 규칙, 컨트롤러가 저장소를 직접 의존하지 않는다는 규칙이 접미사 규약에 기대어 동작합니다. 따라서 접미사 변경은 규칙 변경으로 취급합니다.
검토한 대안
코드 리뷰로 확인한다
| 구분 | 내용 |
|---|---|
| 장점 | 도구를 도입하지 않아도 됩니다. 맥락을 아는 사람이 예외를 판단할 수 있습니다 |
| 단점 | 검토자가 매번 전체 임포트를 확인해야 합니다. 놓치는 것이 정상이며 놓친 것이 선례가 됩니다 |
| 기각 사유 | 규칙의 자동 강제가 품질 목표 1입니다. 수동 확인은 그 목표를 달성하지 못합니다 |
모듈 시스템으로 나눈다
| 구분 | 내용 |
|---|---|
| 장점 | 컴파일러가 경계를 강제합니다. 우회가 원천적으로 불가능합니다 |
| 단점 | 빌드 구성이 복잡해지고 컨텍스트를 나누고 합치는 비용이 크게 오릅니다 |
| 기각 사유 | 초기에는 경계가 자주 바뀝니다. 경계 변경이 비싸지면 잘못 그은 경계를 고치지 않게 되며, 그것이 규칙 위반보다 나쁩니다 |
결과
경계 위반이 빌드에서 차단됩니다. 문서의 규칙과 코드의 상태가 어긋날 수 없습니다.
감수하는 것이 둘입니다.
경계 전체가 도구 하나에 걸립니다. ArchUnit 테스트를 끄거나 완화하면 그 즉시 모든 경계가 사라집니다. 그래서 규칙을 느슨하게 만드는 변경을 리뷰 대상으로 고정하고, 완화가 필요하면 ADR 로 남깁니다.
규칙이 이름 규약에 의존합니다. 접미사를 바꾸면 검사가 조용히 대상을 놓칩니다. 검사가 실패하지 않으므로 바뀐 사실이 드러나지 않습니다.