방어적 프로그래밍을 다시 생각하기

모든 코드에 null 체크와 예외 처리를 겹겹이 넣는다고 해서 항상 더 안전한 코드는 아니다. 오히려 핵심 흐름이 흐려지고, 팀원이나 테스트를 신뢰하지 못한다는 신호처럼 보일 때도 있다.

물론 외부 입력이나 신뢰할 수 없는 경계에서는 방어가 필요하다. 다만 내부 로직까지 불안감으로 감싸기보다는, 계약을 분명히 하고 단위 테스트로 기대 동작을 고정하는 편이 낫다. 한 번 손으로 확인한 내용을 테스트로 남기면 다음 수정 때 다시 눈으로 확인하지 않아도 된다.

중요한 내용은 위에 둔다

코드는 보통 위에서 아래로 읽힌다. 그래서 public 메서드처럼 사용자가 먼저 이해해야 할 흐름은 위에 두고, private 메서드처럼 세부 구현은 아래에 두는 편이 자연스럽다. 독자는 큰 그림을 먼저 보고, 필요할 때만 아래로 내려가면 된다.

이 구조는 단순한 정렬 규칙이 아니라 글의 구성과 비슷하다. 중요한 주장과 흐름을 앞에 배치하고, 세부 근거를 뒤에 둔다. 코드도 마찬가지로 읽는 사람의 집중력이 가장 높을 때 핵심을 보여주는 것이 좋다.

객체지향의 장점은 의존성 관리다

객체지향의 큰 장점 중 하나는 의존성을 다루는 능력이다. 런타임에서 실제로 협력하는 관계는 유지하되, 소스 코드의 의존 방향은 인터페이스를 통해 바꿀 수 있다. 구체 구현에 직접 의존하지 않고 추상화에 의존하면 변경의 영향 범위를 줄일 수 있다.

예를 들어 모듈 A가 모듈 B의 구체 클래스에 직접 의존하면 B의 변화가 A로 쉽게 번진다. 그 사이에 인터페이스를 두면 A는 인터페이스에 의존하고, B는 그 인터페이스를 구현하는 쪽으로 분리된다. 이렇게 하면 실행 시 협력은 그대로 두면서 코드 수준의 결합을 낮출 수 있다.

소스 코드의 의존성 레이어

애플리케이션 코드와 시작 지점의 코드는 분리해서 바라보는 것이 좋다. 애플리케이션 파티션에는 대부분의 비즈니스 규칙과 핵심 로직이 있고, 메인 파티션에는 설정, 팩토리, 실행 진입점 같은 낮은 수준의 조립 코드가 놓인다.

중요한 기준은 두 영역 사이에 선을 그을 수 있느냐이다. 애플리케이션의 핵심 로직이 실행 환경이나 설정 방식에 끌려다니지 않아야 테스트와 변경이 쉬워진다. 의존성의 방향을 의식적으로 관리하면 구조가 더 오래 버틴다.