티스토리 뷰
테스트 가능한 구조로 만들어라
테스트 가능한 구조를 구성하다보면 유연한 구조가 되는 경우가 많다. 따라서 경험이 적은 나 같은 사람들은 테스트 가능한 방식을 계속해서 생각해보는 것이 유연한 구조를 만드는데 도움이 된다.
의존성 주입
의존성 주입은 객체에서 사용될 값을 강한 의존관계에서 벗어나게 한다. 의존객체를 주입시켜주고, 해당 객체는 계약관계에 의해 사용될 시점에 생성되게 해준다. 의존성주입은 객체 내부에서 직접 생성하는 것이 아니라 사용할 내용을 외부로 이동시켜 변경 가능한 구조로 만들어 준다.
1. 생성자를 통해 주입하는 경우,
Cars 내부에서 재사용이 많이 된다면 매번 객체를 넣어주지 않아도 되는 장점이 있다.
2. 메서드에서 인자를 통해 주입하는 경우,
매번 생성하여 인자를 통해 주입해야하지만 사용시 명확하다는 장점이 있다.
생성자 의존성주입의 예시
수업시간에 생성자를 이용한 의존성 주입에 대한 예시를 설명해 주었다. 수업의 예시를 바탕으로 재작성 해보았다. 아래의 예시는 Conditions라는 움직일 수 있는지 여부를 생성자로 주입받는 경우이다.
public class Cars {
private final List<Car> cars;
private final Conditions conditions;
public Cars(List<Car> cars, Conditions conditions) {
this.cars = cars;
this.conditions = conditions;
}
public void move() {
// 초기화 당시 주입받았던 conditions의 movables를 통해 조건이 결정된다!
List<Movable> movables = conditions.movables(cars.size());
for (int i = 0; i < cars.size(); i++) {
cars.get(i).move(movables.get(i));
}
}
public List<Car> cars(){
return cars;
}
}
움직일 수 있는지 여부를 인터페이스로 정의하고 구체하는 RandomNumber를 만든다.
// 움직임 여부를 판단하는 인터페이스
public interface Movable {
boolean movable();
}
// 무작위 숫자를 가지는 클래스
public class RandomNumber implements Movable {
private int randomNo;
public RandomNumber(int randomNo) {
this.randomNo = randomNo;
}
@Override
public boolean movable() {
if (randomNo > 4) {
return false;
}
return true;
}
}
랜덤넘버는 move가 실행되는 시점에 생성된다. 따라서 Movables의 리턴값을 재정의하면 조건을 조작하여 테스트 가능하다.
public class Conditions {
public List<Movable> movables(int carSize){ // ✨타입이 interface인 것이 포인트
List<Movable> moveConditions = new ArrayList<>();
for (int i = 0; i < carSize; i++) {
moveConditions.add(new RandomNumber(getRandomNo()));
}
return moveConditions;
}
private int getRandomNo() {
final Random random = new Random();
return random.nextInt(10);
}
}
메소드 오버라이드를 통해서 movables은 다르게 재정의할 수 있다. 테스트코드에서는 직접 movables를 재정의 하여 원하는 List<Movable>를 생성해 낼 수 있다. 인터페이스 타입으로 설정되었기 때문에 가능하다!✨
public class CarTest{
@Test
public void 이동_조건들() {
// given
Cars cars = new Cars(Arrays.asList(
new Car("pobi", 2),
new Car("better", 2),
new Car("gold", 3)),
new Conditions() {
// movables의 리턴값을 조정해주었다.
@Override
public List<Movable> movables(int carSize) {
return Arrays.asList(
// ✨interface Movable의 movable()을 람다표현식으로!
() -> false,
() -> true,
() -> true);
}
});
// when
cars.move();
// then
assertThat(cars.cars()).containsExactly(
new Car("pobi", 2),
new Car("better", 3), //이동
new Car("gold", 4)); //이동
}
}
수업때 보여주었던 코드를 기반으로 예시코드를 새로 만들면서 클래스 이름을 변경하였다. Number, RandomNumber, RandomNumbers라는 이름이 내가 구조를 이해하기에는 조금 어렵다고 느껴졌기 때문이다. 하지만, 위와 같이 변경하니 서로간의 의존관계나 연결성이 잘 안보이는 단점이 생기는 듯 하다.
✨클린코드 팁
1. 불변 객체
함수형 프로그래밍의 장점은 side effect가 없다는 것이다. 객체지향에서는 불변객체를 통해 side effect를 줄이고자 한다. 가능한 객체는 불변으로 만든다. 리스트 객체는 불변의 다른 느낌으로 엘레강트 오브젝트에서는 다루고 있다고 한다. 리스트객체까지 불변으로 다룰 필요성은 크지 않은 것 같다.
2. 패키지를 분리해라
같은 속성끼리 패키지를 분리하다보면 인터페이스가 보인다. 의존관계가 생기게 되는 것들이 보이는데 이런 경우 인터페이스를 사용해서 유연하게 만들어 주는 것이 좋다. 분리하다 보면 클래스에 default나 final 키워드로 변경 가능한 것들이 보일 것이다.
3. 데이터에 대한 중복은 최악!!
코드 중복보다 데이터 중복은 최악이다. 한 객체로 알아낼 수 있는 정보는 해당 객체로 알아내는 것이 좋다. 데이터의 싱크를 맞추기 위함이다.
4. 클래스의 필드가 많아지는 것을 경계하라
필드가 많아진다면 필드를 묶어서 새로운 객체를 만들 수 있는지 고민해보라.
'우아한테크코스 > 레벨1' 카테고리의 다른 글
우아한테크코스 한 달 생활기 (0) | 2021.03.28 |
---|---|
Lambda and Stream (람다와 스트림) (0) | 2021.03.24 |
[수업] 상태패턴(State Pattern), 파사드 패턴(Facade Pattern) (0) | 2021.03.21 |
[수업] 객체지향 - 포비의 엘레강트 오브젝트 (0) | 2021.03.21 |
객체지향 SOLID 원칙 (0) | 2021.03.09 |
- Total
- Today
- Yesterday
- 알고리즘
- 우테코수업
- python
- 월간회고
- 객체지향
- Spring
- 글쓰기미션
- 카카오
- 마스터즈코스
- Transaction
- 모의면접준비
- DB
- JS
- React
- 우아한테크코스
- 내부코드
- TCP/IP
- 네트워크
- javascript
- CS
- OS
- 인증
- 학습로그
- 개발공부일지
- 코드스쿼드
- 회고
- JPA
- TIL
- java
- 운영체제
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |