BoostStudy / design-patterns

디자인 패턴의 아름다움 스터디 저장소
6 stars 0 forks source link

CHAPTER 5 리팩터링 기법 #5

Closed lee-ji-hoon closed 5 months ago

lee-ji-hoon commented 5 months ago

1. 코드를 리팩터링할 때 겪을 수 있는 문제는 어떤 것들이 있을까? 코드 리팩터링과 관련하여 어떤 생각을 가지고 있는지 이야기해보자.

2. 이진 검색 알고리즘의 개선된 형태를 설계한다고 가정하자. 증가하는 배열에서 주어진 값보다 크거나 같은 첫 번째 요소를 찾은 다음, 이 알고리즘에 대한 단위 테스트 케이스를 설계해보자.

3-1. 정적함수를 호출하는 코드인 IdGenerator.generateTransactionId()가 포함되어있다. 이 것이 코드의 테스트 용이성에 영향을 미치는지 생각해보자. 그리고 단위 테스트를 작성할 때 정적 함수인 generateTransatcionId()를 모의구현해야 하는지도 생각해보자.

3-2. 의존성 주입은 클래스 내부에서 객체를 생성하는 것이 아니라 외부에서 객체를 생성한 후 클래스에 전달하는 것을 의미하는데, 모든 객체를 클래스 외부에서 생성해야 하는 것이 옳은가? 또한 코드의 테스트 용이성에 영향을 주지 않고 클래스 내에서 생성할 수 있는 유형의 객체는 어떤 것이 있는가?

4. 일반적인 개발에서 디커플링은 어디에서나 볼 수 있다. 예를 들어 Spring의 AOP는 비즈니스 코드와 그렇지 않은 코드의 디커플링을 구현할 수 있게 도와주며, IoC는 객체 생성과 사용의 디커플링을 구현할 수 있는데, 이외에 또 다른 디커플링 방법이 있는지 생각해보자.

5. Logger 클래스의 객체인 logger는 static final로 정의되어 클래스 내부에 생성되는데, 이것이 IdGenerator 클래스의 테스트 용이성에 영향을 미치는지 생각을 해보고, Logger 클래스의 객체 logger를 의존성 주입을 통해 IdGenerator 클래스에 주입해야 하는지 생각해보자.

lee-ji-hoon commented 5 months ago

1. 코드를 리팩터링할 때 겪을 수 있는 문제는 어떤 것들이 있을까? 코드 리팩터링과 관련하여 어떤 생각을 가지고 있는지 이야기해보자.

리팩터링은 기존 코드의 기능을 유지하면서 구조를 개선하는 과정이므로, 기존 기능에 영향을 주지 않아야 하지만 실수로 인한 버그 발생, 리팩터링 과정에서 예상치 못한 의존성 발견, 리팩터링으로 인한 성능 저하 등이 발생할 수도 있어서, 리팩터링을 하기 위해서는 단위 테스트가 매우 중요하다고 생각을하고, 점진적으로 작은 단계씩 하는 것이 중요하다고 생각

2. 이진 검색 알고리즘의 개선된 형태를 설계한다고 가정하자. 증가하는 배열에서 주어진 값보다 크거나 같은 첫 번째 요소를 찾은 다음, 이 알고리즘에 대한 단위 테스트 케이스를 설계해보자.

단위 테스트는 경계 조건(예: 배열의 첫 번째나 마지막 요소 검색), 특수 케이스(예: 빈 배열, 한 요소만 있는 배열), 그리고 정상 동작을 검증하는 케이스 등?

3-1. 정적함수를 호출하는 코드인 IdGenerator.generateTransactionId()가 포함되어이 ㅆ다. 이 것이 코드의 테스트 용이성에 영향을 미치는지 생각해보자. 그리고 단위 테스트를 작성할 때 정적 함수인 generateTransatcionId()를 모의구현해야 하는지도 생각해보자.

정적 함수는 전역 상태를 갖거나 변경할 수 있으므로 단위 테스트를 어렵게 만들 수 있기 때문에 IdGenerator.generateTransactionId() 와 같은 함수는 테스트할 때 예측 가능한 값을 반환하지 않을 수 있으므로, 테스트를 위해 mock이 필요해보인다.

3-2. 의존성 주입은 클래스 내부에서 객체를 생성하는 것이 아니라 외부에서 객체를 생성한 후 클래스에 전달하는 것을 의미하는데, 모든 객체를 클래스 외부에서 생성해야 하는 것이 옳은가? 또한 코드의 테스트 용이성에 영향을 주지 않고 클래스 내에서 생성할 수 있는 유형의 객체는 어떤 것이 있는가?

모든 객체를 외부에서 생성하고 주입하는 것은 굳이 필요 없다고 생각하며 상태가 없고 구성이 변하지 않는 객체나, 특정 클래스에 강하게 연결되어 있는 객체는 내부에서 생성해도 무방하다고 생각

의존성 주입은 테스트 용이성 및 코드의 유연성을 높여주지만 그만큼 학습이 필요하고 코드의 복잡성을 유발할수도 있어서 무조건은 아닌거 같다.

4. 일반적인 개발에서 디커플링은 어디에서나 볼 수 있다. 예를 들어 Spring의 AOP는 비즈니스 코드와 그렇지 않은 코드의 디커플링을 구현할 수 있게 도와주며, IoC는 객체 생성과 사용의 디커플링을 구현할 수 있는데, 이외에 또 다른 디커플링 방법이 있는지 생각해보자.

이벤트 기반 시스템, 메시지 큐 등을 통한 비동기 통신도 컴포넌트 간의 결합도를 낮추는 데 도움이 될 수 있지 않을까?

5. Logger 클래스의 객체인 logger는 static final로 정의되어 클래스 내부에 생성되는데, 이것이 IdGenerator 클래스의 테스트 용이성에 영향을 미치는지 생각을 해보고, Logger 클래스의 객체 logger를 의존성 주입을 통해 IdGenerator 클래스에 주입해야 하는지 생각해보자.

static final로 정의된 Logger 인스턴스는 테스트 중에 다른 설정이나 동작을 모의 테스트하기 어렵게 만들 수 있으며, 테스트 중에 로깅 동작을 제어하고자 한다면, 의존성 주입을 통해 Logger를 IdGenerator 클래스에 주입하는 것이 좋다.

의존성 주입을 사용하면, 테스트 환경에서 Logger의 인스턴스르 교체하거나, 로깅 동작을 모의할 수 있으므로 테스트 용이성이 향상된다.

ldh019 commented 5 months ago

1. 코드를 리팩터링할 때 겪을 수 있는 문제는 어떤 것들이 있을까? 코드 리팩터링과 관련하여 어떤 생각을 가지고 있는지 이야기해보자.

가장 흔한 일은 수정했는데 코드에 영향이 가는 것. 영향이 안 가도록 여러번 수정하는게 리팩터링의 묘미 아닐까요(?) 리팩터링은 해야하는데.. 하고 생각하는 마음의 숙제 같은것. 마치 단위 테스트 같은거랄까나

2. 이진 검색 알고리즘의 개선된 형태를 설계한다고 가정하자. 증가하는 배열에서 주어진 값보다 크거나 같은 첫 번째 요소를 찾은 다음, 이 알고리즘에 대한 단위 테스트 케이스를 설계해보자.

첫번 째 요소가 큰 경우, 같은 경우, 작은 경우 / 배열이 비어있거나 없는(?) 경우 / 배열에 값이 모두 작은 경우

3-1. 정적함수를 호출하는 코드인 IdGenerator.generateTransactionId()가 포함되어있다. 이 것이 코드의 테스트 용이성에 영향을 미치는지 생각해보자. 그리고 단위 테스트를 작성할 때 정적 함수인 generateTransatcionId()를 모의구현해야 하는지도 생각해보자.

무슨 값이 나올지 모름. 모의구현 해야한다고 생각.

3-2. 의존성 주입은 클래스 내부에서 객체를 생성하는 것이 아니라 외부에서 객체를 생성한 후 클래스에 전달하는 것을 의미하는데, 모든 객체를 클래스 외부에서 생성해야 하는 것이 옳은가? 또한 코드의 테스트 용이성에 영향을 주지 않고 클래스 내에서 생성할 수 있는 유형의 객체는 어떤 것이 있는가?

모든 객체를 다 외부에서 생성하는 것은 옳지 않은 경우가 있을 수도 있다..! 의존 관계가 필요한 애들은 내부에서 생성해야 하지 않을까? 클래스 내에서 생성해도 되는 건 그 클래스에서만 쓰는 객체 같은거..?

4. 일반적인 개발에서 디커플링은 어디에서나 볼 수 있다. 예를 들어 Spring의 AOP는 비즈니스 코드와 그렇지 않은 코드의 디커플링을 구현할 수 있게 도와주며, IoC는 객체 생성과 사용의 디커플링을 구현할 수 있는데, 이외에 또 다른 디커플링 방법이 있는지 생각해보자.

잘 몰라요.. 뭐가 있지

5. Logger 클래스의 객체인 logger는 static final로 정의되어 클래스 내부에 생성되는데, 이것이 IdGenerator 클래스의 테스트 용이성에 영향을 미치는지 생각을 해보고, Logger 클래스의 객체 logger를 의존성 주입을 통해 IdGenerator 클래스에 주입해야 하는지 생각해보자.

로그가 잘 찍히는지 확인하는 것도 단위 테스트의 확인 사항이라면 영향을 미칠것이다. 이런 경우 의존성 주입으로 인스턴스를 넣어줘야 문제 없이 잘 테스트할 수 있을것이다.

yangsooplus commented 5 months ago

1. 코드를 리팩터링할 때 겪을 수 있는 문제는 어떤 것들이 있을까? 코드 리팩터링과 관련하여 어떤 생각을 가지고 있는지 이야기해보자.

항상 리팩토링 할때는 새로 짜는게 나을만큼 개판인 코드를 리팩토링 하는 상황이었는데, 저자가 말하길 이 때는 이미 늦었다고 하더라고 (시체) 그래서 코드 품질은 항시 신경써야겟다는 생각이 들엇따~

2. 이진 검색 알고리즘의 개선된 형태를 설계한다고 가정하자. 증가하는 배열에서 주어진 값보다 크거나 같은 첫 번째 요소를 찾은 다음, 이 알고리즘에 대한 단위 테스트 케이스를 설계해보자.

요소의 개수가 짝수/홀수, 모든 요소의 값이 동일할 때, 배열이 비어있을 때, 배열에 요소가 1개 있을 때, 요소가 정렬되어 있지 않을때....도 예방하도록 하면 좋을지도?

3-1. 정적함수를 호출하는 코드인 IdGenerator.generateTransactionId()가 포함되어 있다. 이 것이 코드의 테스트 용이성에 영향을 미치는지 생각해보자. 그리고 단위 테스트를 작성할 때 정적 함수인 generateTransatcionId()를 모의구현해야 하는지도 생각해보자.

언어에서 제공하거나 프레임워크에서 제공하는 변하지 않고 안정된 정적함수가 아니라면 모킹해야할듯

3-2. 의존성 주입은 클래스 내부에서 객체를 생성하는 것이 아니라 외부에서 객체를 생성한 후 클래스에 전달하는 것을 의미하는데, 모든 객체를 클래스 외부에서 생성해야 하는 것이 옳은가? 또한 코드의 테스트 용이성에 영향을 주지 않고 클래스 내에서 생성할 수 있는 유형의 객체는 어떤 것이 있는가?

무지성 의존성 주입은 주입하는 쪽에서 알 필요 없는 객체까지 생성할 위험이 있고, Hilt 같은 의존성 주입 라이브러리를 사용한다면 쓸데없이 코드량만 늘어날 거시다 흠.. 클래스 내에서 계산하고 쓰고 버리는 객체 같은거?

4. 일반적인 개발에서 디커플링은 어디에서나 볼 수 있다. 예를 들어 Spring의 AOP는 비즈니스 코드와 그렇지 않은 코드의 디커플링을 구현할 수 있게 도와주며, IoC는 객체 생성과 사용의 디커플링을 구현할 수 있는데, 이외에 또 다른 디커플링 방법이 있는지 생각해보자.

길 가는 커플 사이로 지나간다.

5. Logger 클래스의 객체인 logger는 static final로 정의되어 클래스 내부에 생성되는데, 이것이 IdGenerator 클래스의 테스트 용이성에 영향을 미치는지 생각을 해보고, Logger 클래스의 객체 logger를 의존성 주입을 통해 IdGenerator 클래스에 주입해야 하는지 생각해보자.

사실 로그 찍는거까지 주입해야하나 싶긴한데....... 갑자기 Timber 같은 로그 라이브러리를 도입하게 된다면 의존성 주입으로 짜놓은 경우에 주입하는 객체를 바꿈으로서 적용할 수 있겠지

audxo112 commented 5 months ago

1. 코드를 리팩터링할 때 겪을 수 있는 문제는 어떤 것들이 있을까? 코드 리팩터링과 관련하여 어떤 생각을 가지고 있는지 이야기해보자.

interface 는 원래 수정되지 않는것을 전제로 코드를 작성하게 되는데 구조 자체가 적합하지 않아 수정하는 경우가 많아서 Interface 부터 다시 구조를 작성하게 되는데 그로인해 개발시간이 비약적으로 증가하게 된다

2. 이진 검색 알고리즘의 개선된 형태를 설계한다고 가정하자. 증가하는 배열에서 주어진 값보다 크거나 같은 첫 번째 요소를 찾은 다음, 이 알고리즘에 대한 단위 테스트 케이스를 설계해보자.

첫번째, 마지막 값을 찾는 경우 존재하지 않는 값을 찾는 경우 원하는 값을 찾는 경우

3-1. 정적함수를 호출하는 코드인 IdGenerator.generateTransactionId()가 포함되어있다. 이 것이 코드의 테스트 용이성에 영향을 미치는지 생각해보자. 그리고 단위 테스트를 작성할 때 정적 함수인 generateTransatcionId()를 모의구현해야 하는지도 생각해보자.

정적함수 이기 때문에 모의 구현하기 힘들다 generateTransactionId 는 랜덤한 값을 결과로 반환하기 때문에 원하는 아이디가 생성되었을때를 테스트 하려면 (동일한 Id 가 생성된 경우 등) generateTransactionId 를 모의 구현해야한다

3-2. 의존성 주입은 클래스 내부에서 객체를 생성하는 것이 아니라 외부에서 객체를 생성한 후 클래스에 전달하는 것을 의미하는데, 모든 객체를 클래스 외부에서 생성해야 하는 것이 옳은가? 또한 코드의 테스트 용이성에 영향을 주지 않고 클래스 내에서 생성할 수 있는 유형의 객체는 어떤 것이 있는가?

Math 같은 너무나 명확한 클래스의 경우 굳이 주입할 필요는 없다

4. 일반적인 개발에서 디커플링은 어디에서나 볼 수 있다. 예를 들어 Spring의 AOP는 비즈니스 코드와 그렇지 않은 코드의 디커플링을 구현할 수 있게 도와주며, IoC는 객체 생성과 사용의 디커플링을 구현할 수 있는데, 이외에 또 다른 디커플링 방법이 있는지 생각해보자.

Domain 과 같은 중간 계층을 이용하여 디커플링 하게 구현할 수 있다

5. Logger 클래스의 객체인 logger는 static final로 정의되어 클래스 내부에 생성되는데, 이것이 IdGenerator 클래스의 테스트 용이성에 영향을 미치는지 생각을 해보고, Logger 클래스의 객체 logger를 의존성 주입을 통해 IdGenerator 클래스에 주입해야 하는지 생각해보자.

Logger 는 결과만 반환하기 때문에 일반적으로는 테스트 하는데 문제가 없지만 만약 아이디 생성을 모의 구현을 통해 고정을 하여 테스트를 하고 싶다면 문제가 생기게 된다