객체지향 프로그래밍 패러다임에서는 소프트웨어가 높은 응집성과 낮은 결합성을 가져야 한다.

(* 응집성 : 하나의 모듈이 단일의 역할만을 할 경우 높은 응집성을 가진다. → 단일 책임원칙)

(* 결합성 : 모듈이 다른 모듈에 얼마나 의존하는지에 대한 척도)

결합성을 낮추기 위해서는 상위 수준 모듈이 하위 수준 모듈에 의존하지 않아야한다. 이를 의해서는 의존성 주입패턴을 사용하면 된다.

만약, A.js, B.js, C.js가 존재할때 각 파일들이 서로 얽혀있다면 결합성이 강해진다.

export.module = ()=>{
// this is A
	
}
const A = require("A.js")
export.module = () =>{
// this is B
}
const B = require("B.js")
export.module = () =>{
// this is C
}

이렇게 코드를 구성하게 되면 결합성이 강하기 때문에 모듈의 확장성을 제한하고, 단위 테스트 또한 어려워진다.

즉, stateful한 instance(=export한 특정 인스턴스)에 의존하기 때문에 문제가 발생한다. 따라서 stateful한 모듈(팩토리, 생성자, 인터페이스 등등)을 로드하게 되면 결합성을 낮출 수 있다.

의존성 주입 DI

주로 생성자를 이용하거나 메소드를 이용해서 의존성을 주입한다.

class Chef{
	private Recipe recipe
	
	public Chef(Recipe tmp){ // 생성자로 레시피를 받아서 입력한다.
		this.recipe = tmp
	}
	public setRecipe(Recipe tmp){// setter메소드로 레시피를 입력해준다.
		this.recipe = tmp
	}
}
class Restaurant{
	private Chef burgerChef = new Chef(new HamburgerRecipe())
	private Chef spagettiChef = new Chef(new SpageettiRecipe())

	public changeMenu(){
		burgerChef = new Chef(new CheeseBurgerRecipe())
	}
}

이렇게 의존성을 주입하는 경우 어떤 장점이 있는지 알아보자.

  1. 의존성이 줄어든다. ⇒ 주입받는 대상을 바꿀 수 있어서 수정할 일이 줄어든다.
  2. 재사용성이 높은 코드가 된다. ⇒ 클래스가 좀더 독립적이게 되어 다른 클래스에서 사용가능하다.
  3. 테스트하기 좋은 코드가 된다. ⇒ 테스트를 분리하여 진행가능해 진다.
  4. 가독성이 높아진다. ⇒ 기능들을 별도로 분리하게 되어 자연스레 가독성이 높아진다.