BAEKJH BE Developer

응집도(cohesion)

2021-01-22
BAEKJungHo
OOP

logo

서론

응집도는 소프트웨어 설계에 있어서 복잡성을 알 수 있는 지표가됩니다. 이번 시간에는 응집도에 대해서 배워 보겠습니다.

응집도(cohesion)

응집도(cohesion)는 서로 어떻게 연관되어 있는지를 가리킨다. 정확히 말하자면 응집도는 클래스나 메서드의 책임이 서로 얼마나 강하게 연결되어 있는지를 측정한다.

  • 응집도는 소프트웨어의 복잡성을 유추하는데 도움을 준다.
  • 응집도는 높을 수록 좋다.

클래스 수준의 응집도

실무에서는 일반적으로 다음과 같은 여섯 가지 방법으로 그룹화한다.

  • 기능
  • 정보
  • 유틸리티
  • 논리
  • 순차
  • 시간

기능

기능을 비슷한 메서드끼리 그룹화한다.

같은 기능을 사용하는 메서드를 그룹화 하면 찾기도 쉽고 DRY(Don't repeat yourself) 원칙을 지킬 수 있으며, 재사용성이 증가한다.

단점은, 하나의 메서드만 갖는 클래스가 많아지게 된다면 오히려 코드가 장황해지고 복잡해 질 수 있다.

정보

같은 데이터나 도메인 객체를 처리하는 메서드를 그룹화 한다.

예를 들어 동영상(Video) 객체를 만들고, 읽고, 수정하고, 삭제하는 기능(CRUD)이 필요해 이런 기능만 제공하는 클래스를 만들 수도 있다.

스프링을 이용해 웹 개발을 하다보면 Repository Interface 혹은 DAO class 를 만들고(일반적으로, Repository 와 DAO 는 도메인 객체를 처리하는 메서드(CRUD)를 그룹화한 인터페이스 혹은 클래스이다.) 그에 대한 구현체를 만들어서 사용하는 경우가 많다. 주로 DB 와 상호작용할 때 흔하게 볼 수 있다. 이러한 패턴을 DAO(Date Access Object)라고 하며, DAO 는 영구 저장 데이터베이스나 인메모리 데이터베이스 같은 데이터 소스로의 접근을 추상화하고 캡슐화 한다.

정보 응집의 단점은, 필요한 기능을 가지고 있는 클래스 전체를 DI(Dependency Injection) 해야한다.

유틸리티

관련성이 없는 메서드를 한 클래스로 그룹화 한다.

특히 메서드가 어디에 속해야할지 결정하기 어려울 때에는 유틸리티 클래스(utility class)에 추가하기도 한다.

예를들어 날짜와 관련된 작업을 하는 메서드를 그룹화하게된다면, 이 클래스는 여러 클래스에서 사용할 가능성이 높고, 각 메서드의 파라미터들이 원시타입인 경우가 대다수이다. 따라서 유틸리티 클래스의 특징은 메서드를 static 으로 선언하는게 대다수이다. static 으로 만들어 컴파일 시점에 미리 메모리에 올려놓고, 필요할때 꺼내쓰는 편이 성능상 더 좋기 때문이다. 또한 파라미터가 원시타입이면 스레드로부터 안전하다.

유틸리티 클래스의 단점은 낮은 응집도로 이어진다는 것이다. 그리고 서로 연관없는 메서드들이 모여있을 가능성이 크므로, 가급적 이해하기 쉽도록 만들어야 한다.

논리

같은 논리에 해당하는 메서드를 하나의 클래스로 그룹화 한다.

예를들어 파일을 파싱하는 기능을 모아둔 클래스가 있다고 해보자

public class Parser {
    
    public String parseFromCSV(final String line) {
        // 생략
        throw new UnsupportedOperationException();
    }

    public String parseFromJSON(final String line) {
        // 생략
        throw new UnsupportedOperationException();
    }

    public String parseFromXML(final String line) {
        // 생략
        throw new UnsupportedOperationException();
    }
    
}

위 메서드들은 파싱이라는 논리로 그룹화되었다. 하지만 위 메서드들은 서로 관련이 없다. 그리고 이 방법은 하나의 클래스에서 여러개의 책임을 가지고 있으므로 SRP를 위배하기 때문에 추천하는 방식이 아니다.

순차

여러 동작이 어떻게 함께 수행되는지 쉽게 이해하기 위해 하나의 클래스로 그룹화 한다.

순차 응집은 여러 동작이 어떻게 함께 수행되는지 쉽게 이해할 수 있다. 하지만 이 응집을 적용하면, 클래스가 바뀌어야 할 이유가 여러가지가 되므로 SRP를 위배한다.

시간

시간 응집은 여러 연산 중 시간과 관련된 연산을 그룹화한다.

어떤 처리 작업을 시작하기 전과 뒤에 초기화, 뒷정리 작업(ex. DB 의 연결과 종료)같은 기능을 담당하는 메서드를 포함하는 클래스가 그 예다.

응집도 수준과 장단점

  • 기능(높은 응집도)
    • 장점 : 이해하기 쉬움
    • 단점 : 너무 단순한 클래스 생성
  • 정보(중간 응집도)
    • 장점 : 유지보수하기 쉬움
    • 단점 : 불필요한 의존성
  • 순차(중간 응집도)
    • 장점 : 관련 동작을 찾기 쉬움
    • 단점 : SRP 를 위배할 수 있음
  • 논리(중간 응집도)
    • 장점 : 높은 수준의 카테고리화 제공
    • 단점 : SRP 를 위배할 수 있음
  • 유틸리티(낮은 응집도)
    • 장점 : 간단하게 추가 가능
    • 단점 : 클래스의 책임을 파악하기 어려움
  • 시간(낮은 응집도)
    • 장점 : 판단 불가
    • 단점 : 각 동작을 이해하고 사용하기 어려움

메서드 수준의 응집도

메서드가 자신의 이름과 연관없는 일을 처리하거나, if/else 구문이 많거나 들여쓰기가 2단계 이상인 경우에는 해당 메서드를 더 작게 분리해야 한다.

안티 응집도(anti-cohesion)

갓 인터페이스(한 인터페이스에 모든 기능을 포함시킨 경우를 의미)를 피하기 위해서 극단적으로 인터페이스를 잘게 쪼개는 경우가 있다. (ex. 인터페이스 하나당 메서드 한개) 이런 경우에는 안티 응집도(anti-cohesion)가 발생한다. 즉, 기능이 여러 인터페이스로 분산되므로 자주 사용하는 기능을 찾기 어렵다.

참고

Real-world Software Development


Comments

Index