제일 의존성이 적은 단위에서 테스트할 때, 테스트하기 힘든 구조가 있다면 아래와 같은 방법을 고려해보자
a. 접근지정자를 조절해서 테스트하기 힘든 부분을 재정의하기
// 처음에 테스트를 하기 쉬운 구조로 작성할 때는 `방법 a`를 이용 // 의존되는 관계를 일괄 수정은 어려우니, 레거시를 처음 리펙토링 할 때도 이 방법이 용이하다 Carcar=newCar() { @Override protectedintgetRandomNo() { return1; } }
b. 파라미터로 받기
// 요구사항이 변하지 않는 상태로 처음 설계할 때는 `방법 b`가 유리 Carcar=newCar(); car.move(1);
c. 인터페이스로 받기
Carcar=newCar(); // 요구사항이 계속 변할 때는 `방법 c`처럼 인터페이스로 빼서 여러 전략을 만들 수 있도록 하는것도 좋다 car.move(newrandomStrategy()); car.move(() -> true);
인스턴스 변수들을 클래스로 포장하자
기존에는 그저 int, String과 같은 변수들이지만, 클래스로 포장할 경우 다음과 같은 이점을 얻을 수 있다
특정 객체의 유효범위를 책임질 수 있다
프로그램 전체에서 일관된 객체를 사용할 수 있다
버그를 줄일 수 있다
여러 유효성이 프로그램 곳곳마다 정의된다면 단일 책임의 원칙을 위배할 수 있다
객체 지향 원칙에 따라서 지켜야할 것들
내부 상태를 나타내는 값들을 getter/setter를 통해 주입하지 말고 명령하는 메서드를 만들자
// 나쁜 예 intposition= RANDOM_POSITION; for (Car car : cars) { if (car.getPosition() < position) { car.setPosition(position); } }
// 좋은 예 intposition= RANDOM_POSITION; for (Car car : cars) { car.move(position); }
객체의 특정 상태값을 비교할 때 getter로 꺼내서 비교하지말고 객체자체를 비교하자
버그의 원인이 상태값을 객체 밖에서 수정할 수 있을 때 많이 발생하니, Immutable하게 사용하는걸 고려해보자
가능한 getter를 사용하지 않도록 해보자
참고
위는 도메인 객체 설계에 관한 내용으로, VIEW LAYER <-> DOMAIN LAYER과 같은 DTO는 getter/setter를 허용함
Car와 CarDto를 만들어야 한다면 두 클래스를 구분짓기 위해 생각해 볼 것들
CarDto 클래스에만 position을 가지는 생성자를 만든다 (도메인 객체와 다르다는 것을 표시하기 위한 관점에서)