강의

멘토링

로드맵

Inflearn brand logo image

인프런 커뮤니티 질문&답변

Hika Maeng님의 프로필 이미지
Hika Maeng

작성한 질문수

오브젝트 - 설계 원칙편

1-1. 기능 구현과 설계 원칙

1-1에서 질문있어요.

해결된 질문

작성

·

57

2

1-1에서 미래를 예측할 수 없어 실제로 변경이 발생했을 때 적합한 설계로 개선한다고 했는데 이게 약간 도돌이표 느낌이에요.
왜냐면 설계를 선택할 때 변경될 가정을 기반으로 한다고 했기 때문입니다.

1. 변경 방식에 따라 설계를 선택
2. 변경이 발생하면 설계를 변경
아니 이러면 변경에 대응하기 위한 설계가 아니라 변경 시 마다 설계를 바꾼다는 것인데
애당초 설계를 왜 한 건가 싶은 생각이 맴도는 느낌이네요.
저는 설계를 코드를 변화율에 따라 재배치한다고 생각했는데 변화가 일어날 때마다 설계를 변경할 거면 그건 그냥 설계가 아니라 변경에 따라 코드를 수정한 것 같은..

답변 2

4

조영호님의 프로필 이미지
조영호
지식공유자

Hika Maeng님 안녕하세요. 오랜만에 온라인상에서 이야기 나누네요.

좋은 질문 남겨 주셔서 감사합니다.

1-1에서 설계를 다음과 같이 설명했습니다.

‘설계는 어떤 기능을 구현하는데 적합한 코드의 구조를 결정하는 작업입니다.
다시 말해서 유지보수 가능하게 코드를 배치하는 방법을 의미합니다.’
이 설명에서 유지보수라는 용어는 결국 코드를 이해하고 수정하는 작업이 중심을 이루게 됩니다.

 

여기에서 현재 우리가 알고 있는 변경에 대해 적합한 수준 안에서 코드를 배치를 결정한다는게 중요합니다.
예를 들어서 현재 가격을 계산하는 어떤 기능이 있는데 할인에 대한 요구사항이 존재하지 않는다고 해보겠습니다.
이럴 경우 할인이 추가될 지도 모른다고 가정하고 코드를 짠다면 코드가 이해하기 어려워지고 불필요하게 복잡해질 거에요.
더 큰 문제는 사람들마다 변경될 지도 모른다고 가정하는 사항이 다르다는 점입니다.
어떤 사람은 쿠폰이 추가될 수도 있다고 가정하고, 어떤 사람은 사용자 등급에 따라 가격이 조정될 수도 있다고 가정할 수 있습니다.
이 모든 가정은 앞으로의 요구사항 변경에 해당됩니다. 그리고 이 가정들에 따라 코드의 배치, 즉 설계가 달라집니다.


문제는 저 가정들이 실제로 요구사항에 추가되기까지는 꽤나 오랜 기간이 걸리거나, 아예 추가되지 않을 수도 있다는 점입니다.
따라서 변경에 대비하는 가장 좋은 방법은 현재 우리가 알고 있는 요구사항(여기에서는 가격 계산)을 구현할 수 있는 가장 간단한 코드 배치를 찾는 것입니다.
그리고 실제로 쿠폰이 요구사항으로 추가됐을 때 쿠폰을 추가할 수 있는 설계로 개선하는게 가장 좋겠죠.

 

요구사항 변경이 있을 때마다 설계를 개선하는 것은 큰 관점에서의 리팩터링 목표입니다(작은 관점에서는 가독성을 향상시키는 것이구요).
그리고 단위 테스트가 필요한 중요한 이유 중 하나이구요.
예상만으로 불필요한 기능이나 인프라를 추가하지 않는 YAGNI나 최대한 단순하게 만드는 KISS등도 비슷한 맥락이라고 보시면 될것 같아요.

 

정리하는 차원에서 설계를 왜 하느냐에 대해 답변을 드리면 '현재 우리가 알고 있는 요구사항 변경 안에서 가장 이해하고 수정하기 쉬운 방식으로 단순하게 코드를 배치'하기 위해서입니다.


답변이 되었는지 모르겠네요. :)

1

Hika Maeng님의 프로필 이미지
Hika Maeng
질문자

2단계 차원의 관점이라 느껴져요.

1. 같은 설계 내에서 코드가 변화하는 차원
2. 설계 자체를 변경해야 하는 차원

즉 설계는 1번을 커버하지만 아예 2번도 발생할 수 있다는 느낌이네요.

그리고 회귀테스트와 리팩토링은 엄밀하게는 1번 차원에서 필수인거 같아요. 2번은 결국 테스트 전체도 많이 바꿔야해서 오히려 코드로 된 테스트보다는 테스트해야할 요구사항 정의서로부터 다시 변경된 책임 모델에 의한 테스트를 재 작성해야 할 거 같아요.

조영호님의 프로필 이미지
조영호
지식공유자

말씀하신 부분에서 2번의 경우 테스트는 요구사항 변경때문에 수정된 코드때문에 다른 코드에 부수효과가 발생하지는 않는지 확인하기 위한 회귀 테스트의 용도로 필요합니다.

요구사항이 변경된 코드에 대한 테스트는 변경되겠지만, 그로 인해 다른 부분에 버그가 없는지 확인하기 위한 테스트가 필요합니다.

따라서 기능을 변경하기 위한 리팩터링에서도 부수효과 검증을 위해 테스트가 중요합니다.

 

답변이 되었는지 모르겠네요. 🙂

Hika Maeng님의 프로필 이미지
Hika Maeng
질문자

네.
단지 그냥 저희는 그 테스트 코드들이 코드의 안정성만 확인해주지 도메인 안정성을 그렇게 확보해주지는 않더라구요. 그래서 코드가 아닌 요구스펙 정리서를 규격화된 문서로 작성해서 원본으로 두고 있는 편이긴 합니다.
머랄까 컴파일과 테스트 통과는 잘되는데 그것으로 컨텍스트 오류에 많이 당하다보니..
강의에서 나왔던 설계수준의 변경을 일으키는 것들이 주로 도메인이 크게 변경되는 것이고 그러면 기존 도메인을 파악한 관점에서 작성된 모든 테스트가 오히려 문제를 일으키는 경우도 많더라구요 ^^;

조영호님의 프로필 이미지
조영호
지식공유자

네 말씀하신 것처럼 잘못 작성된 단위 테스트는 리팩터링의 방해요소가 되곤 합니다. 🙂
단위 테스트가 구현과 밀접하게 결합되어 있거나, 비슷한 동작을 검증하는 테스트가 중복되어 있으면 오히려 테스트 실패때문에 리팩터링을 주저하게 되는 경우가 많아요.

 

말씀하신 것처럼 그런 경우에는 단위 테스트를 작성하지 않고, E2E 테스트를 기본으로 두는 경우를 많이 봐왔는데, 당연히 사용자 승인 테스트도 중요한 요소가 됩니다.

 

다만 사용자 승인 테스트는 너무 입도가 크기 때문에 복잡한 도메인 로직을 테스트해야 한다면, 저는 가급적이면 설계를 리팩터링해서 단위 테스트가 효율적으로 사용되도록 만드는 쪽을 선호하고 있어요.

 

좋은 질문 남겨 주셔서 정말 감사합니다. 🙂

Hika Maeng님의 프로필 이미지
Hika Maeng

작성한 질문수

질문하기