일급 콜렉션

  • 콜렉션을 포함한 클래스는 반드시 다른 멤버 변수가 없어야 한다.
  • 각 콜렉션은 그 자체로 포장되어 있으므로 이제 콜렉션과 관련된 동작은 근거지가 마련된셈이다.
  • 필터가 일급 콜렉션의 일부가 됨을 알 수 있다. 필터는 또한 스스로 함수 객체가 될 수 있다.
  • 일급 콜렉션은 두 그룹을 같이 묶는다든가 그룹의 각 원소에 규칙을 적용하는 등의 동작을 처리할 수 있다.

예제를 들어 일급 콜렉션을 설명하자면 다음과 같다.

// 일반 콜렉션 사용
Map<String, String> map = new HashMap<>();
map.put("1", "A");
map.put("2", "B");
map.put("3", "C");
// 일급 콜렉션 사용
public class GameRanking {
   private Map<String, String> ranks;
   
   public GameRanking(Map<String, String> ranks) {
      this.rank = rank;
   }
}

이와 같이 Collection을 Wrapping하면서 그 외에 다른 멤버 변수가 없는 상태를 일급 컬렉션이라고 한다.

장점

  1. 비지니스에 종속적인 자료구조
  2. Collection의 불변성을 보장
    • final을 사용해서 일급 콜렉션 내의 콜렉션의 재할당을 금지시킬 수 있다. => 즉 , 각각의 객체들이 절대 값이 바뀔일이 없다는게 보장된다.
  3. 상태와 행위를 한 곳에서 관리
    • 값과 로직이 함께 존재한다.
    • 똑같은 기능을 하는 메소드의 중복 생성을 막을 수 있다.
  4. 이름이 있는 컬렉션

결합도 (coupling)

결합도는 한 모듈과 다른 모듈 간의 상호 의존도 또는 연관 관계이다. 각각의 모듈의 독립적인 관계를 결합도라고 하는데 모듈간의 낮은 결합도는 체계가 잘 분할되어 서로 관계없는 모듈은 분리되어 존재한다는 의미이다. 낮은 결합도를 가진 프로그램 코드는 한 모듈 내의 에러가 다른 모듈에 영향을 미치는 파급효과의 최소화가 가능하며, 한 모듈의 변경이 다른 모듈에 큰 영향을 미치지 않고 모듈의 유지 보수 및 변경이 가능하다. 또한 특정 모듈의 내부 사항을 알지 못해도 그와 관련된 다른 모듈의 효과적인 취급이 가능해진다.

결합도의 종류(순서대로 결합도는 증가한다.)

  1. Data coupling : 단일 파일 또는 동종 테이블을 매개 변수로 통신하는 결합성
  2. Stamp coupling : 두 모듈이 동일한 자료 구조를 조회하는 경우의 결합성
  3. Control coupling : 어떤 모듈이 다른 모듈의 내부 논리 조직을 제어하기 위한 목적으로 제어 신호를 이용하여 통신하는 결합성
  4. Common coupling : 두 모듈이 동일한 총체적 자료 영역을 공동으로 조회하는 경우의 결합성
  5. Content coupling : 한 모듈의 다른 모듈의 내부 기능 및 그 내부 자료를 조회하는 경우이며 내용 결합성이 발생하는 경우

개발자는 낮은 결합도를 유지하게끔 Product를 만들어야 한다.


응집도 (Cohension)

응집도는 한 모듈 내부의 처리 요소들 간의 기능적 연관도를 나타내며 모듈 내부 요소는 명령어, 명령어의 모임, 호출문 특정 작업 수행 코드 등 체계를 모듈 단위로 얼마나 잘 분할하는지를 지침이 되어 모듈간의 결합도를 최소함으로써 체계내의 모든 모듈의 양호한 응집도를 성취해야 합니다.

응집도의 종류 (순서대로 응집도는 감소한다)

  1. 기능성 응집성(functional cohesion) : 잘 정의된 하나의 기능이 하나의 모듈을 이룬 경우, “판매 세금 계산”처럼 동사, 목적어 한 쌍으로 구성
  2. 순차적 응집성(sequential cohesion) : 모듈 내 한 작업의 출력이 다른 작업의 입력이 되는 경우. “다음 거래를 읽고, 그 결과를 마스터 파일에 반영”
  3. 교환적 응집성(communication cohesion) : 동일한 입력과 출력을 사용하는 여러 작업들이 모인 경우. “인사 기록 파일에 근무 성적을 기재하고 급여를 갱신함”
  4. 절차적 응집성(procedural cohesion) : 공유하는 것은 없으나 큰 테두리 안에서 같은 작업에 속하는 경우. “총계를 출력하고 화면을 지우고, 메뉴를 뿌리고, 메뉴를 선택”
  5. 시간적 응집성(temporal cohesion) : 특정 시간에만 수행되는 기능을 묶어놓은 모듈
  6. 논리적 응집성(local cohesion) : 유사 성격을 갖거나 특정 형태로 분류되는 처리 요소들은 하나의 모듈로 형성. “ 사칙 연산에서 주어진 매개변수에 따른 계산”
  7. 우연적 응집성(coincidental cohesion) : 아무 관계 없는 처리 요소들로 모듈이 형성된 경우. 모듈 개념이 상실되어 이해 및 유지보수가 힘든 단점이 있음

개발자는 높은 응집도를 유지하게끔 Product를 만들어야 한다.


생성자에 많은 로직이 포함되면 안되는 이유

생성자는 말 그대로 객체 생성을 위해서 설계되었습니다. 생성자 안에서 사용하는 로직이 지금의 요구사항에서는 문제가 없어보이지만, 해당 객체를 다른 요구사항에서도 사용하게 된다면, 그 로직 때문에 원하는 객체 생성이 어려워집니다. 이미 상용에 배포된 코드면 수십억이 왔다갔다 하는 환경에서 그걸 변경하기란 매우 힘들어서, 똑같지만 생성자 내용만 다른 클래스를 만들어서 사용하게 되겠죠. 정말 어디서나 공통적으로 쓰이겠다 싶은 간단한 비즈니스 룰 정도는 생성자에 포함하겠지만, 그런 것도 웬만하면 지양해야하는 안티패턴입니다. 예외처리 또한 마찬가지 입니다!!!


Mock

Mock이란?

실제 객체를 만들어 사용하기에 시간, 비용 등의 Cost가 높거나 혹은 객체 서로간의 의존성이 강해 구현하기 힘들 경우 대역 객체(Test Double)를 만들어 사용하는 방법이다.

Mock 객체는 언제 필요한가?

  • 테스트 작성을 위한 환경 구축이 어려운 경우
  • 테스트가 특정 경우나 순간에 의존적인 경우
  • 테스트 시간이 오래 걸리는 경우
  • 개인 PC의 성능이나 서버의 성능문제로 오래 걸릴 수 있는 경우 시간을 단축하기 위해 사용한다.

Mock에 대한 기본적인 분류 개념, 테스트 더블

  1. 테스트 더블
    • 테스트를 진행하기 어려운 경우 이를 대신해 테스트를 진행 할 수 있도록 만들어주는 객체를 말한다.
    • Mock 객체와 유사한 의미를 가지며 테스트 더블이 좀 더 상위 의미로 사용된다.
  2. 더미 객체(Dummy Object)
    • 단순히 인스턴스화될 수 있는 수준으로만 객체를 구현한다.
    • 인스턴스화된 객체가 필요할 뿐 해당 객체의 긴으까지 필요하지 않는 경우에 사용한다.
  3. 테스트 스텁(Test Stub)
    • 더미 객체보다 좀 더 구현된 객체로 더미 객체가 마치 실제로 동작하는 것처럼 보이게 만들어 놓은 객체이다.
    • 객체의 특정 상태를 가정해서 만들어 특정 값을 리턴해 주거나 특정 메시지를 출력해 주는 작업을 한다.
    • 특정 상태를 가정해서 하드코딩된 형태이기 때문에 로직에 따른 값의 변경은 테스트 할 수 없다.
    • 즉, 어떤 행위가 호출됬을 때 특정 값으로 리턴시켜주는 형태가 Stub이다.
  4. 페이크 객체(Fake Object)
    • 여러 상태를 대표할 수 있도록 구현된 객체로 실제 로직이 구현된 것처럼 보이게 한다.
    • 실제로 DB에 접속해서 비교할 때와 동일한 모양이 보이도록 객체 내부에 구현할 수 있다.
      • 테스트케이스 작성을위해서 다른 객체들과의 의존성을 제거하기 위해 사용한다.
      • 페이크 객체를 만들 때 복잡도로 인해서 놀겨이 많이 들어 갈 경우 적절한 수준에서 구현하거나, Mock 프레임 워크를 사용한다.
      • 페이크 객체를 생성하기 위한 노력이 많이 필요한 경우 실제 객체를 가져와 테스트 한다.
  5. 테스트 스파이(Test Spy)
    • 테스트에 사용되는 객체, 메소드의 사용 여부 및 정상 호출 여부를 기록하고 요청시 알려준다.
    • 테스트 더블로 구현된 객체에 자기 자신이 호출 되엇을 때 확인이 필요한 부분을 기록하도록 구현한다.
    • 특정 테스트 메서드가 몇번 호출 되었는지 필요한 경우 전역 변수로 카운트를 설정하고 특정 테스트 메서드에 카운트를 올리는 부분을 추가한 후 이 카운트를 가져오는 메서드를 추가한다.
    • 특정 메소드가 호출 되었을 때 또 다른 메서드가 실행이 되어야 한다와 같은 행위 기반 테스트가 필요한 경우 사용한다.
  6. Mock 객체(Mock Object)
    • 행위를 검증하기 위해 사용되는 객체를 지칭하여 수동으로 만들 수도 있고 프레임워크를 통해 만들 수 있다.
    • 행위 기반 테스트는 복잡도나 정확성등 작성하기 어려운 부분이 많기 때문에 상태 기반 테스트가 가능하다면 만들지 않는다.
    • Mock 객체는 테스트 더블 하위객체로 써의 좁은 의미와 테스트 더블을 포함한 넓은 의미 2가지로 사용될 수 있다.

이때 Mock Object는 행위 검증(Behavior Verification)에 사용하고, Stub는 상태 검증(State Verification)에 사용하는 것이다.