3장에서는 코드를 정리해야 하는 이유를 이론적으로 파악한다.
22. 요소들을 유익하게 관계 맺는 일
소프트웨어 설계는, 요소들을 유익하게 관계맺는 일
요소
- 요소에는 경계가 있어 어디서 시작하고 끝나는지 알 수 있음
- 요소는 하위요소를 포함함 (계층 구조)
관계 맺기
- 요소 사이의 호출, publish, listen, 참조를 통해 관계를 맺을 수 있음
유익하게
- 요소들 사이에는 잘 보이지 않는 관계가 많음
- 이때 요소들 사이에 중간요소(ex. 함수)를 넣으면 간단해짐
- 기계를 위한다기보단 사람을 위한 작업
- 즉, 관계는 요소들 사이에 이점을 만들어냄
23. 구조와 동작
소프트웨어는 두 가지 방식으로 가치를 만듭니다.
- 현재 소프트웨어가 하는 일 (주문 배송 등 시스템 동작)
- 미래에 새로운 일을 시킬 수 있는 가능성 (옵션에 가까움)
시스템을 더 가치 있게 만들기 위해서 굳이 시스템의 동작을 바꿀 필요가 없었습니다.
다음에 무엇을 할 수 있는지에 대해 선택할 수 있는 기회를 만들자마자, 저는 이미 돈을 번 것입니다.
- 1달러를 넣으면 10달러를 주는 기계보단, 10달러->100달러 기계가 더 좋음
- 더 나은 기계에 도달하기 위한 방법은: 선택 가능성
- 특정 방식으로 동작하는 시스템이 있다는 것 만으로도, 그 시스템이 어떻게 동작해야 하는지에 대한 욕구가 달라진다.
- 다음에 무엇을 할 수 있는지에 대한 선택 가능성이 제공되면, 이미 돈을 번 것!
옵션
- 사전적 정의: 회사의 주식을 일정한 기간(행사기간) 내에 미리 정한 가액(행사가액)에 매수할 수 있는 권리
- 소프트웨어에서는? 주로 확장의 기회
- 환경의 변동성이 클수록 옵션의 가치가 커짐 (혼란스러울 때 기회)
시스템 구조
- 구조는 동작에 영향을 미치지 않음
- 하나의 큰 기능이든, 여러개의 작은 기능이든 같은 동작을 할 수 있음
- 구조는 미래의 기회를 만듦 -> 새 기능 추가 시 쉬워지거나 어려워 질 수 있음
- 구조는 동작과 달리 명확히 드러나지 않을 수 있음
결론
- 선택 가능성을 유지하고 확장하기 위해 구조에 투자해야 하지만, 구조에 대한 투자가 코드를 쉽게 변경하게 만들거나 투자가 제대로 이루어졌는지 알기는 어려움
- 구조 변경과 동작 변경 모두 가치를 만들지만 근본적으로 다름 -> 구조는 되돌리기가 어려움, 가역성 낮음
24. 경제 이론: 시간 가치와 선택 가능성
돈의 속성
- 오늘의 1달러는 내일의 1달러보다 더 가치 있으므로, 빨리 벌고, 쓰는 것은 뒤로 미룬다.
- 혼란스러운 상황에서는 어떤 물건에 대한 옵션이 물건 자체보다 낫기 때문에 불확실성에 맞서는 옵션을 만든다.
소프트웨어 설계는 위 두 속성을 잘 조화해야 한다.
25. 오늘의 1달러가 내일의 1달러보다 크다
돈(시스템)의 가치는 "시점"과 "확실성"에 따라 결정된다.
- 오늘 천만달러 지불하고 10년후 2천만 달러 받기 vs 오늘 1200만 달러 받고 10년후 천만 달러 지불하기
위 케이스에서 전자의 경우 10년동안 긴장속에 있어야하나, 후자는 첫날부터 수익이 보장되므로 앞으로 미래가 기대된다.
즉, 이 책에서는 돈의 시간 가치는 코드 정리를 먼저 하기보다는 나중에 하는 것을 권장한다.
(물론 뒤따르는 동작변경 비용이 너무 크면 먼저 정리)
26. 옵션 (?)
옵션으로 만들 수 있는 가치
- 더 많이, 더 일찍, 더 높은 확률로 돈을 벌기
- 더 적게, 더 늦게, 더 낮은 확률로 돈을 지출하기
위의 모델은 쉽지않다...
켄트백의 교휸
- "다음에 어떤 동작을 구현할 수 있을까?" 고민하기.
동작을 구현하기 전에도, 그 자체로 가치가 있다. 우리는 지금까지 한일에 대한 대가를 받는 것이 아니라, 다음에 할 수 있는 일에 대한 대가를 받고 있는 것이다.
- "다음에 어떤 동작을 구현할 수 있을까?"
라는 질문은 동작 후보 목록이 많을 수록 더 가치있다. 자신의 포트폴리오에서 이사람이 할 수 있는 일이 많을 수록 몸값이 비싸지는 것과 동일하다.
- 가치에 대한 예측이 불확실할 수록 구현하는 것보다 옵션이 지닌 가치가 더 커진다.
변화를 포용하면 창출한 가치를 극대화할 수 있다. 이점이 통상적으로 소프트웨어 개발이 가장 성공하는 지점이다.
오늘 우리가 하는 소프트웨어 설계는, 내일의 동작변경을 구매하는 "옵션"에 대한 프리미엄이다.
27. 옵션과 현금흐름 비교
현금 흐름 할인
- 높은 확률로 먼저 돈을 벌고, 낮은 확률로 나중에 돈을 쓰기
- 코드 정리를 나중에 하자
- 어쩌면 나중엔 정리가 필요 없을 수도 있음
옵션
- 나중에 돈벌 방법을 몰라도 지금 돈 쓰기
- 옵션이 생길 일이 명백하다면, 코드정리 먼저하자
- 동작 변경 이후 정리할 내용이 있다면 또 정리
코드 정리 선행? 또는 후행?
- case1:
코드 정리 비용
+ 코드 정리 후 동작 변경 비용
< 정리 없이 바로 동작 변경 비용
- 명백히 코드정리 먼저 하기
- case2:
코드 정리 비용
+ 코드 정리 후 동작 변경 비용
> 정리 없이 바로 동작 변경 비용
- 애매함, 어떤 것을 먼저 할지는 판단하기 나름
- 단기적인 경제성을 고려해서 정리 없이 동작 변경해도 OK
- 코드 정리 후에 동작 변경하는 것이 더 좋다고 생각해도 OK (경제적 인센티브는 없음)
- 코드 정리 후 더 즐거워진다는 이유도 OK (경제적 인센티브는 없음)
28. 되돌릴 수 있는 구조 변경
가역성
- 동작 변경은 비교적 간단히 되돌릴 수 있다.
- 구조 변경(코드 정리)은 되돌리기 쉽지 않다.
되돌릴 수 있는 설계 결정
- 쉽게 되돌릴 수 있음 -> 잘못되면 되돌리면 됨
- 실수를 피하는 것에 지나치게 노력할 필요 없음
- 그냥 정리일 뿐
되돌릴 수 없는 설계 결정
- 면밀 검토, 여러번 확인하는 것이 좋음
- 천천히 신중하게 결정
- 당분간은 되돌릴 수 있도록 만드는 것이 좋음
- 큰 문제는 되돌리기 어렵지만, 단위를 작게하면 일부분 되돌릴 수 있게 된다.
- 프로토타입 구현, 기능 플래그 확인 등 작은 부분에서 가역성 확보
핵심은, 결정을 되돌릴 수 있도록 소프트웨어를 만드는 것이 중요.
29. 결합도
한 요소를 변경하면 다른 요소도 함께 변경해야 하는 경우, 두 요소는 결합되어있다.
def call():
...
def caller():
call()
caller()
call()
결합도 성질
- 일대다: 보통 어떤 변경이 일어나면, 한 요소는 여러 요소와 결합이 일어남
- 도구로 커버 가능
- 연쇄작용: 변경이 일어나면, 연쇄적으로 다른 요소로 변경이 파급됨
- 연쇄적인 변경 비용이 문제
- 소프트웨어 비용을 크게 좌지우지
되도록이면 결합도는 줄이는 것이 좋다. 결합도를 효율적으로 줄일 수 있는 방향을 고민하자.
(단, 변화될 가능성이 없으면 결합도 줄이는 것에 큰 관심 필요 없음)
30. 콘스탄틴의 등가성
소프트웨어의 개발 비용의 70%는 유지보수 비용이다.
콘스탄틴의 등가성: 소프트웨어 비용은 그것을 변경하는데 드는 비용과 비슷하다.
소수의 큰 "이상값"이 다수의 "정상값"보다 영향도가 높다.
- ex) 가장 큰 5개 폭풍이 작은 폭풍 1만개보다 영향 큼
전체 변경 비용 ~= 큰 변경에 대한 비용
큰 변경들이 비싼 이유는, 변경을 "전파"하기 때문 (결합도)
결국 다음 콘스탄틴의 등식을 얻을 수 있다.
비용(소프트웨어) ~= 비용(전체 변경) ~= 비용(큰 변경들) ~= 결합도
- 즉, 소프트웨어 비용은 결합도와 같다고 볼 수 있다.
결국 소프트웨어 비용을 줄이려면 결합도를 줄여야 한다.
31. 결합도와 결합도 제거
결합도는 잘 드러나지 않는다. 보통 동작변경 시 알아차린다.
결합도가 존재하는 이유
- 결합도를 인지하지 못했기 때문
- 문제되지 않았기 때문
- 피할 수 없기 때문
사실 결합도가 왜 있는지는 중요하지 않고, 결합도 제거를 위한 비용을 지불할 것인지가 중요하다.
class Sender{
fun send() {
writeField1()
writeField2()
}
}
class Reciever{
fun receive() {
readField1()
readField2()
}
}
vs
format = [...]
class Sender{
fun send() {
writeFields(format)
}
}
class Reciever{
fun receive() {
readFields(format)
}
}
- 결합도를 낮춰 한 군데에서 변경할 수 있는 구조
- 하지만 결합도가 완전히 사라진 것은 아님
- 여전히 세번째 필드를 추가하고, 이에 대한 구체적인 처리를 위해선 sender와 reciever 모두 변경이 필요할 수 있음
- 또한 결합도 제거에도 비용이 드는 것을 간과해선 안된다.
이 책에서는, 한 코드에서 결합도를 줄이면 다른 코드에서 결합도가 커지므로, 너무 결합도를 줄이려고 애쓸 필요는 없다고 한다.
32. 응집도
결합된 요소들은 둘을 포함하는 같은 요소의 하위 요소여야 한다.
1. 결합된 요소들에 대해 하위 요소로 묶기
- 메소드 추출 등
2. 결합되지 않은 요소를 가져와 다른 곳에 배치
- 배치를 통해 결합도 높은 것들끼리 응집
33. 결론
코드 정리 고려사항
- 비용: 코드 정리를 하면 비용이 줄어드는가? 아니면 나중에 해야 할까? 아니면 줄일 가능성이 있을까?
- 수익: 코드를 정리하면 수익이 더 커질까? 혹은 더 빨리 발생하거나 커질 가능성이 있을까?
- 결합도: 코드를 정리하면 변경에 필요한 요소의 수가 줄어들까?
- 응집도: 코드를 정리하면 변경을 더 작고 좁은 범위로 집중시켜서 더 적은 수의 요소만 다룰 수 있을까?
- 만족감: 코드를 정리하면서 만족감을 느낄 수 있는가?
코드 정리에 너무 집착하지 말자. 중요한 것은 최상의 상태에서 주체적으로 일해서 좋은 결과물 내는것.
누가? | 언제? | 무엇을? | 어떻게? | 왜? |
---|
나 | 몇 분에서 몇 시간 | 코드 정리 | 구조나 동작 변경 | 결합도와 응집도 |