시스템 수준에서도 깨끗함을 유지하는 방법
시스템 제작과 사용을 분리
- 소프트웨어 시스템은 애플리케이션 객체를 제작하고 의존성을 서로 ‘연결’하는 준비 과정과 준비과정 이후에 이어지는 런타임 로직을 분리해야 한다.
func getService() -> Service {
// Lazy Initialization / Lazy Evaluation
if service == nil {
service = MyService(...)
}
return service
}
/*
good:
불필요한 부하 x, nil 반환 x
bad:
getService 메서드가 MyService에 의존적이다.
만약 MyService가 무거운 객체라면 단위테스트에서 getService 호출 전에 적절한 Mock 객체를 service에 할당해야 한다.
런타임 로직에 객체 생성 로직이 섞여 service가 nil인 경우와 아닌 경우를 둘 다 테스트 해야 한다.
*/
⇒ 설정 논리는 일반 실행 논리와 분리해야 모듈성이 높아진다. 주요 의존성을 해소하기 위한 방식(전반적이며 일관적인 방식)이 필요하다.
Main 분리
- main이나 main이 호출하는 모듈: 생성과 관련된 코드
- 나머지 시스템은 모든 객체가 생성되었고 모든 의존성이 연결되었다고 가정. (Application은 객체 생성 과정을 모름)
팩토리
- 객체가 생성되는 시점을 애플리케이션이 결정할 때도 있다.
- Abstract 팩토리 패턴
- 객체가 생성되는 시점은 Application이 결정하지만 생성 코드는 Application이 알지 못함.
- Abstract 팩토리 패턴
의존성 주입
- 진정한 의존성 주입은 한 걸음 더 나아간다. 클래스가 의존성을 해결하려 시도하지 않는다. 대신에 의존성을 주입하는 방법으로 setter나 생성자 인수(혹은 둘 다)를 제공한다.
테스트 주도 시스템 아키텍처 구축
- 최선의 시스템 구조는 각기 다른 객체로 구현되는 모듈화 된 관심사 영역(도메인)으로 구성된다. 이렇게 서로 다른 영역은 해당 영역 코드에 최소한의 영향을 미치는 관점이나 유사한 도구를 사용해 통합한다. 이런 구조 역시 코드와 마찬가지로 테스트 주도 기법을 적용할 수 있다.
반응형