• Dependency-Structure-Matrix & DDD & Layered-Architecture
    DEV 2024. 1. 8. 20:58

    project 내부 Dependency를 파악해 높은 응집력, 낮은 결합도를 가진 코드를 유지하는 방법과 도구를 DDD 관점에서 알아보자.

    • 일반적으로 코드를 이해하는 데 개발 시간의 60%를 사용
      - https://ieeexplore.ieee.org/document/7997917
    • 코드 규모가 커지면 복잡도도 올라가기 때문에 코드 시각화, 코드 출력, 스크래치 리팩터링 등의 도움을 받을 수 있다.

    코드 시각화

    Dependency structure matrix(DSM)

    •  프로젝트 내 dependency 파악하는 방법 중 하나

    DSM & Directed graph

    • 열을 기준으로 dependency 파악
    • 다이어그램에서 dependency는 화살표가 들어오는 것으로 파악
    • task1 task3 dependency(의존성)을 가진다.
      - task3 task1을 사용한다.
    • task2 task1 dependency(의존성)을 가진다.
    • task4 task2, task5 dependency(의존성)을 가진다.
    • 테스트 코드를 작성 시 테스트코드가 해당 모듈을 사용하는 모듈(해당모듈이 의존을 가지고 있는 모듈)이라고 생각하고 작성하면 편하다.
      - task4에 대한 테스트코드를 작성한다면 화살표를 거꾸로 찾아가 task2, task5에서 실행할 만한 case를 테스트하면 된다.

    Circular Dependency(순환참조)

    config of relationships
    circular dependency

    • 메트릭스를 통해 순환참조를 쉽게 찾아낼 수 있다.
    • A C에 의존, C A에 의존 = 순환참조
    • 파란 선을 기준으로 포개었을 때 겹치는 부분이 있다면 Circular Dependency

    순환참조의 문제점

    • 변경에 의해 영향받는 범위를 파악하기 어렵다.
      - 순환참조가 발생되면 컴포넌트 간의 명확한 경계가 사라지고 연쇄적으로 변경에 의한 영향 발생 가능성
    • 메모리 누수, 가비지컬랙션 오버헤드, 예측 불가능한 동작, 코드 복잡도

    DSM in Intellij

    dependency matrix menu

    • 메뉴에 없다면 Plugins: Dependencies Structure Matrix 설정을 on으로 변경
    • Ultimate license만 지원 🫤

    DSM tool window

    • 메트릭스는 많이 사용되는 구성요소를 아래로 정렬
      = 메트릭스 상단 구성요소가 아래 구성요소에 종속된다는 의미
    • 종속성 = 파란색
    • 순환참조 = 빨간색
    • 초록색 → 사용  선택모듈  사용  노랑색

    모듈의 영향 범위

    • 선택한 모듈을 수정했을 때 영향을 받는 모듈의 범위를 확인 가능

    Domain-Driven Design(DDD)

    • DDD에 대해 처음부터 설명할 수 없지만, DDD의 핵심목표는
      - High cohesion, Loosly coupling(높은 응집력, 낮은 결합도)
    • 도메인은 서로 철저히 분리, 변경과 확장에 용이한 설계

    Layered Architecture

    • DDD의 구체적 설계 (Tactical Design) 목적별 계층으로 나누어 설계

    layered architecture
    layered architecture 2

    • Presentation Layer: UI Layer
    • Service Layer: Domain Layer Data Layer classclass들 간의 제어(Control) 또는 연결(Interface)
      - 비지니스 로직은 구현 x
    • Domain Layer: Domain Object별로 Business Logic처리
    • Data Layer: Database와의 CRUD처리
    • spring boot 어노테이션
      - Presentation Layer => @Controller, @RestController
      - Service Layer, Domain Layer => @Service
      - Data Layer => @Repository
    • Layered Architecture를 올바르게 구현하기 위한 두 가지 중요한 규칙
      - 위의 계층에서 아래 계층에는 접근이 가능하지만 아래에서 위로는 불가능한 것을 기본으로 한다.
      - 한 계층의 관심사와 관련된 어떤 것도 다른 계층에 배치되어서는 안 된다.

    Layered Architecture in DSM

    good layered architecture

    • 비교적 layer 구조가 잘 지켜진 시스템
    • 위 계층이 아래 계층으로만 접근, 아래애서 위로 접근하지 않는다.

    strict layered architectrue

    • 보다 엄격하게 한다면 하나의 레이어는 바로 아래 레이어에서만 접근
    • model application만의 의존을 갖는다.
    • util에서 수정이 일어날 경우 영향을 받는 범위는 framework에 국한된다.
    • 좋은 구조이지만 실제로 하기는 쉽지 않다.
    • util의 기능을 applicaton에서 사용하려 할 경우, framework, domain, model을 거쳐서 해당 기능을 제공해야 하기 때문에 오히려 비효율적일 수도

    순환 참조

    • 하위 레이어에서 상위 레이어를 호출
    • util에서 application, model을 사용/참조
      = 순환 참조 발생 가능성
    • 해결방법
      - 직접적인 순환 참조인 경우 새로운 패키지 생성
      - 간접적인 참조의 경우 Interface로 연결

    순환 끊기

    순환 참조

    • Entities에 새로 추가된 클래스 하나가 Authorizer를 사용하게 되어 순환참조가 일어난다면
    • Database 컴포넌트에서 수정이 일어났을 때 Entities, Authorizer, Interactors와 호환 확인
    • 순환참조가 일어나면서 Entities, Authorizer, Interactors가 거대한 컴포넌트가 되는 이슈

    1. 의존성 역전 원칙 (DIP)  적용

    DIP 적용

    2. 새로운 패키지 생성

    • Entities와 Authorizer가 모두 의존하는 새로운 패키지를 만들고 두 컴포넌트가 모두 의존하는 클래스들을 이동

    새 패키지 생성

    결론은

    • High cohesion, Loosly coupling(높은 응집력, 낮은 결합도)
    • 변경과 확장에 용이한 설계를 위한 모든 일들..

    Ref.

     

     
    728x90
go.