일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- cli 만들기
- Test
- https 실습
- 자바
- 객체지향
- InnoDB
- 직접 코드로 구현
- MySQL
- ruby
- IntelliJ
- 코틀린
- Pitest
- standard input
- Mutation testing
- 대칭 키 알고리즘
- resizer 구현
- kotlin
- go https 구현
- 오블완
- JPA
- HTTPS
- 돌연변이 테스팅
- standard output
- resize image with go
- https 서버 구현
- Java
- image resizer with go
- AES-GCM
- https implement
- https go
- Today
- Total
Rlog
응집도와 결합도 본문
응집도와 결합도는 소프트웨어 품질을 결정 짓는 요소이다.
대다수의 사람들은 코드를 작성할때 "응집도" 와 "결합도" 를 생각하지 않은채
관성적으로 코드를 적고는 한다.
응집도와 결합도는 무슨 뜻일까?
일단, 이 개념을 이해하기 위해서 알고 있어야 할 선행지식이 있다.
불안정한 부분과 안전한 부분의 분리
바로 "불안정한 부분" 과 "더 안전한 부분" 을 분리해 내는 능력이 필요하다.
예를 들어 아래와 같은 객체가 존재한다고 해보자.
Address 는 모든 변수가 public 하게 열려있다.
우리는 앞으로 Public 하다는건 자신의 내부 속사정을 공개한 객체 취급을 할 것이다.
외부에서 이를 어떻게 사용할까?
위와 같이 사용할 수 있을 것이다.
위와 같이 사용했을때 어떤 문제가 발생할 수 있을까?
아니 "불안정한 부분" 과 "안정한 부분" 은 어디일까?
일반적으로 구현된 부분은 바뀔 가능성이 높다.
예를 들어 아래와 같은 요구사항이 추가됬다고 해보자.
"주소를 추가할때 유저의 주소가 맞는지 한번 검증해주세요"
그럼 저 코드에서 어떻게 하겠는가?
아마도 대부분은 Order 에서 해당 작업을 수행할 것이다.
아래와 같은 코드가 탄생할 것이다.
이제 다른 팀원이 "유저 상세페이지" 작업을 통해 주소를 추가하는 기능을 만든다고 해보자.
그럼 그 팀원은 아래와 같은 코드를 추가할 것 이다.
뭔가 악취가 나지 않는가?
벌써 중복된 부분들이 보이기 시작했다.
이때 또 아래와 같이 요구사항이 변경됬다고 해보자.
아 Validate 할때 오류 메세지가 이상해요; 이거 좀 다 바꿔주세요.
사실 오류 메세지를 상수 변수로 관리해도 된다.
하지만 위에서 내려온 내용이니, 일단 문구를 바꿔보도록 하자.
일단 여기서 하나 짚고 넘어가야 할점은
이제는 "불안정한 부분" 과 "더 안전한 부분" 을 대략적으로 느낄 수 있을 것이다.
"setAddress" 라는 인터페이스는 상대적으로 안정하다.
하지만 그 밑의 구현 내용은 불안정하다.
즉, 따라서 우리는 구현을 해야 할 일이 있으므로 항상 불안정한 부분에 부딪힌다.
방금 요구사항이 변경됬을때, 우리가 수정해야 할 클래스는 무엇일까?
Order 와 User 의 setAddress 라는 메소드안의 불안정한 부분을 모두 수정해야 했다.
아래 도식으로 한번 보자.
위의 그림의 빨간 부분이 변해야 될 부분 이다.
이렇게 되면 누군가 요구사항을 실수로 반영하지 못하는 일이 일어날 수 있게 된다.
이런 상황을 어떻게 대처해야 할까?
바로, 응집도는 높이도 결합도를 낮추는 것이 중요하다.
이제, 본론으로 들어가서 응집도와 결합도를 알아보자.
응집도(Cohesion)
응집도는 말그대로 모듈에 내부의 요소들이 밀접한 연관관계를 지니고 있는지를 나타낸다.
위의 Address Class 를 한번 살펴보자.
Address Class 만 봐서는 응집도가 높다고 생각할 수 있다.
그렇담 Order 를 한번 확인해보자.
Order 의 응집도는 어때 보이는가?
Order 에 Address를 추가하는 부분이 있다.
Order 가 Address를 추가하는 불안정한 부분인 구현해야 할까?
User 또한 똑같다.
User 에 Address를 추가하는 부분이 있다.
User 가 Address를 추가하는 불안정한 부분인 구현해야 할까?
우리가 해야할 것은 "주소 추가 시 주소 정보를 통해 검증과정을 거치는 것이다"
즉, 애초에 이 일은 Address 가 진행해야 할 일이였던 것이다.
이제 User 와 Order 에서 주소 추가 부분을 Address 의 setAddress 인터페이스로 교체해보자.
책임이 잘 분배된거 같지 않은가?
확실히 느끼기 위해서 아까의 요구사항을 다시 들고 오겠다.
아 Validate 할때 오류 메세지가 이상해요; 이거 좀 다 바꿔주세요.
이제 어느 부분만 바꾸면 될까?
바로 Address 의 setAddress 만 바꾸면 될 것이다.
따라서 요구사항에 따른 변경해야할 부분이 아래와 같이 바뀌었다.
이제 대략적으로 응집도에 관한 내용이 감이 올 것이다.
이는 사실 책임 설계 자체의 문제로도 충분히 발생할 수 있는 일이란걸 깨달았다면 잘 이해한 것이다.
그럼 결합도는 무엇일까?
결합도를 한번 알아보자.
결합도(Coupling)
결합도는 다른 모듈에 대한 정보를 어느정도까지 알고 있는지를 나타낸다.
우리는 위와 같은 구조로 변경하여 좋은 구조로 변경한 것 처럼 보인다.
왜 잘 바꿨는데 좋은 구조로 변경한 것 처럼? 이라고 말하는 거지 라고 물어본다면
코드에 아직 결합도가 높아질 여지가 있기 때문이다.
예를 들어, 이제 배달기사의 상세페이지를 제작한다고 해보자.
근데 배달 기사 상세 페이지를 신입이 진행하고 있는데
아래와 같이 배달 기사님의 주소 추가 부분을 작성했다고 해보자.
이런일이 왜 발생했을까?
바로 DeliveryMan 이 Address 에 대한 정보를 알고 있기 때문이다.
즉 DeliverMan 은 다른 모듈인(Address) 에 대한 정보를 알고 있다.
따라서 결합도는 Address 를 모를때 보다 더 높다.
아까 위에서 일어났던 일들을 경험했던 선임 개발자들은
이렇게 작성하는 방법이 "변경에 취약한 코드" 임을 알고 있다.
그래서 setAddress 를 이용하도록 급하게 변경하지만, 이는 근본적인 해결책이 아님을 깨닫는다.
근본적인 해결책은 뭘까?
바로 가시성(visibility) 을 이용하는 것이다.
DeliveryMan 이 Address 의 내부를 못보게 하면 된다.
선임개발자들은 Address 내부 정보의 접근 제한자를 public 이 아닌 private 으로 변경한다.
이제 외부에서는 직접 접근 하는 방식으로 주소를 추가할 수 없다.
이제 DeliveryMan 은 Address 내부 정보를 모른다.
따라서 결합도가 이전보다 낮아졌음을 알 수 있다.
하나 더 결합도가 높을시 파급효과를 도식으로 그려보자.
만약 Public 으로 다 열려있을 시 변경점을 생각해보자.
DeliverMan, User, Order 클래스에서 모두 정보를 알고 있다고 가정하면 아래와 같은 모습이다.
만약 지금 상황에서 Address 내부 속성인 zipCode 를 다른 변수명으로 바꿨다고 해보자.
그렇다면 DeliveryMan, User, Order 의 내부에서 zipcode 를 쓰고 있다면 모두 변경해야 한다.
즉, 다른 모듈의 구현내용 자체를 변경하게 되는 포인트가 될수 있다는 것이다.
따라서 아래와 같은 변경 도식을 가지게 될것이다.
따라서 모듈간의 결합도가 높으면 위와 같은 상황이 발생한다.
앞으로 코드를 작성할때 결합도와 응집도를 잘 생각하자.
아니 이전에 가시성과 책임을 잘 분배하여 객체를 설계하자.
이 글을 정리하기 위해 참고했던 책 혹은 문서
http://www.yes24.com/Product/Goods/74219491
https://ko.wikipedia.org/wiki/%EA%B2%B0%ED%95%A9%EB%8F%84
'Architecture' 카테고리의 다른 글
Web 계층에 Port 를 통해 더 자유로운 코드 짜기 (0) | 2022.01.20 |
---|---|
클린 아키텍쳐와 Domain Layer (2) | 2021.12.08 |
협력과 메세지 (0) | 2021.12.02 |
컴포넌트 (0) | 2021.11.17 |
SOLID (0) | 2021.11.08 |