반응형
Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- 알고리즘
- 안드로이드
- 스레드
- Compose
- Coroutine
- 병렬프로그래밍
- 테스트
- 코틀린
- kotlin강좌
- k8s
- 회고
- viewmodel
- g 단위테스트
- 글또
- theming
- 병럴프로그래밍
- 알게되는
- Kotlin
- 안드로이드스튜디오
- 커스텀상태
- 코루틴
- ReactiveProgramming
- 디자인패턴
- Gradle
- 책
- Rxjava
- mockito
- 안드로이드강좌
- android
- 자바
Archives
- Today
- Total
선생님, 개발을 잘하고 싶어요.
[오브젝트] 챕터 8 - 의존성 관리하기 본문
OOP는 객체간에 메시지로 협력하며 기능을 구현하는 것은 좋습니다.
하지만 이걸론 부족합니다. 협력을 위해서 서로를 참조하며 코드가 커지다 보면 참조의 참조의 참조 문제가 발생하게 됩니다.
하나를 수정하면 그 파급효과가 저 멀리까지 퍼진다는 거죠.
그런 문제가 일어나는 이유는 잘못된 의존성 설계 때문에 그렇습니다.
이번 챕터에서는 의존성이 그 자체로 잘못된 것이 아님을 밝히고 어떻게하면 현명하게 사용할 수 있는지 알려줍니다.
의존성의 바람을 바람직 하게 만들라고 조언합니다. 그 방법에 대해서 정확하게 알려주진 않는 듯 합니다.
어떤 의존성이 바람직한가? 를 알려면 아키텍쳐에 대한 학습이 병형되어야 한다고 생각합니다. 클린 아키텍쳐에서 봤던 경계를 기준으로 단방향 의존성을 가진 시스템을 설계하는 게 괜찮을 것 같네요.
부주의한 생성자 활용이 코드 결합도를 높히므로 클라이언트 쪽으로 생성의 책임을 분리하라는 말이 나오는데 DI Framework가 생각났습니다. 제가 지금까지 활용한 DI는 뭔가 Configuration 관점에서 생각하진 않은 것 같네요. 좀더 생성과 기능의 분류를 추출 격리하기 위한 용도로 사용하는 용례를 고민해봐야겠습니다.
- 객체지향 애플리케이션 → 작고 응집도 높은 객체들로 구성
- 책임의 초점이 명확하고 한 가지 일만 잘하는 객체
- 단독으로 수행할 수 있는 작업은 거의 없다.
- 다른 객체의 도움이 필요하다. → 이 과정에서 메시지를 보내게 되고 협력을 낳는다.
- 협력은 객체가 다른 객체에 대해 알 것을 강요한다.
- 그런 객체가 존재한다는 사실을 알아야한다.
- 수신할 수 있는 메시지에 대해 알아야한다.
- 이러한 지식이 객체 사이의 의존성을 만든다.
- 의존성은 수정을 어렵게 만든다.
- 협력을 위해 필요한 의존성 유지하며 변경 방해하는 의존성은 제거해야한다.
<aside> 💡 충분히 협력적이고 유연한 객체를 만들기 위해 의존성을 관리하는 방법을 알아본다.
</aside>
- 의존성 이해하기
- 변경과 의존성
- 실행 시점: 실행 시 의존 대상 객체가 반드시 존재해야 한다.
- 구현 시점: 의존 대상 객체 변경시 의존하는 객체도 함께 변경된다.
- 의존성은 변경에 의한 영향의 전파 가능성을 암시한다.
- 클래스 의존 이외에 다양한 의존이 있을 수 있다. (인자로 받기, 필드로 가지기, 구현하기 등)
- 의존성 전이
- 의존하고 있는 객체가 의존하는 객체에 간접적으로 의존하게 되는 것
- 항상 전이되는 건 아니고, 변경의 방향과 캡슐화의 정도에 따라서 달라진다.
- 런타임 의존성과 컴파일타임 의존성
- 런타임 → 실행 시점, 컴파일타임 → 작성한 코드 구조
- 런타임의 주인공은 객체
- 객체 사이의 의존성이 주요 아젠다
- 컴파일타임의 주인공은 클래스
- 클래스 사이의 의존성이 주요 아젠다
- 실제로 협력할 객체가 어떤 것인지는 런타임에 해결해야 한다.
- 컴파일타임 구조와 런타임 구조 사이의 거리가 멀면 멀수록 설계가 유연해지고 재사용 가능해진다.
- 하지만... 이해하기 어려워지지
- 컨텍스트 독립성
- 구체적인 클래스를 알면 알수록 그 클래스를 활용하는 문맥에 강하게 결합된다.
- 컴파일 에러 <<< 런타임 에러 <<< Context 에러 순으로 해결하기 어렵다.
- 특정 문맥에 강하게 결합될 경우 부주의한 Context 에러가 발생할수 있다.
- 컨텍스트 독립적이다?
- 각 객체가 해당 객체를 실행하는 시스템 문맥을 알지 못해야한다.
- 구체적인 클래스를 알면 알수록 그 클래스를 활용하는 문맥에 강하게 결합된다.
- 의존성 해결하기
- 의존성 해결: 컴파일타임 의존성을 적절한 런타임 의존성으로 교체하는 것
- 생성자
- setter
- 메서드 파라미터
- 각 방법을 혼합하여 사용할 수 있다.
- 의존성 해결: 컴파일타임 의존성을 적절한 런타임 의존성으로 교체하는 것
- 변경과 의존성
- 유연한 설계</aside>
- 의존성과 결합도
- 객체간 상호작용은 필수 즉 의존성은 필수
- 의존성의 정도가 문제
- 의존성을 바람직하게 만들자.
- 협력 대상이 정확한 인스턴스일 필요 없이 “이런 메시지를 수신할 수 있는” 타입이된다.
- 바람직한 의존성은 재사용성과 긴밀한 관계
- 결합도: 의존성의 정도
- 어떤 의존성이 재사용을 방해한다면 결합도가 강하다고 표현할 수 있다.
- 추상화에 의존하라
- 추상화:
- 문제를 해결하는 데 불필요한정보를 감춤
- 결합도를 느슨하게 유지 가능
- 결합도가 강한 순 추상화
- 구체 클래스 의존
- 추상 클래스 의존
- 인터페이스 의존 → 어떤 메시지를 수신할 수 있는지에 대한 지식만 남음
- 추상화:
- 명시적 의존성
- 의존성을 명시적으로 퍼블릭 인터페이스에 노출하는 것
- 의존성을 명시적으로 드러내면 코드를 직접 수정하는 위험을 피할 수 있다.
- </aside>
- new는 해롭다.
- 생성자 호출은 결합도를 높힌다.
- 생성 로직과 사용로직을 분리하라.
- 썰계를 유연하게 하려면
- 사용과 생성 책임 분리
- 의존성을 명시적으로 드러내기
- 추상클래스에 의존하기
- 객체를 생성하는 책임은 클라이언트로 옮기자.
- 가끔은 생성해도 무방하다.
- 설계는 트레이드 오프
- 구체 클래스에 의존하더라도 클래스 사용성을 높힐 수 있다면 해도 괜찮을지도
- 표준 클래스에 대한 의존은 해롭지 않다.
- String에 대한 의존이 해롭겠냐?
- 컨텍스트 확장하기
- 구체 클래스를 직접 다루는 책임을 Client로 옮기면 OCP 달성가능
- 조합 가능한 행동</aside></aside>
- <aside> 💡 객체의 조합을 선언적으로 표현하여 객체들이 무엇을 하는지 표현하는 설계가 좋은 설계
- <aside> 💡 선언적으로 객체의 해동을 정의할 수 있다.
- 의존성과 결합도
- <aside> 💡 의존성 관리를 위한 유용한 원칙 & 기법 소개
'일상 > 책 리뷰' 카테고리의 다른 글
[오브젝트] 챕터 10 - 상속과 코드 재사용 (0) | 2022.03.19 |
---|---|
[오브젝트] 챕터 9 - 유연한 설계 (0) | 2022.03.18 |
[오브젝트] 챕터 7 - 객체 분해 (0) | 2022.03.05 |
[오브젝트] 챕터 6 - 메시지와 인터페이스 (0) | 2022.03.05 |
[오브젝트] 챕터 5 - 책임 할당하기 (0) | 2022.03.02 |
Comments