의존 주입의 해석은 매우 간단하다

Mpho Mojapelo의 Unsplash 사진

originally published on bostonc.dev
내가 처음으로 개발자를 맡은 이래로, 나와 함께 일하는 사람들은 모두 의존 주입과 그 중요성에 대해 이야기하고 있다.비록 전문적인 프로그래밍 경험이 있다 하더라도 나는 그것이 도대체 무엇인지 이해하기 어렵다.온라인 자원은 더 많은 용어를 사용할 것이다. 이것은 나를 더욱 곤혹스럽게 할 뿐이다.
이 글은 소프트웨어 개발과 체계 구조를 막 접한 사람들에게 의존 주입이 무엇인지, 왜 의존 주입이 필요한지 간단한 설명을 제공할 전망이다.

만약 네가 차를 한 대 가지고 있다면.너에게 있어서, 나는 네가 차 안에서 음악을 틀기를 좋아한다고 상상한다. (만약 네가 나와 같다면, 특히 따라 부르는 것을 좋아한다.)🎤 🎶).
너의 차는 매우 수지가 맞다.그런데 문제가 하나 있는데, 네 차 안의 음향은 매우 특별하다.그것은 스테레오 시스템에 용접된 CD의 음악만 재생할 수 있다.쿠르와 길드 노래에 싫증이 나면 새로운 스테레오를 사서 현재의 스테레오를 바꿔야 한다는 뜻이다.
class Stereo () {
  constructor(cdName, speakers) {
    this.cdName = cdName;
    this.speakers = speakers;
  }

  function play() {
    speakers.playMusic(this.cdName);
  }
}
이것은 대량의 수공 작업이어서 약간의 시간이 필요하다.다행히 스테레오는 이렇게 만들어지지 않았다.반대로 그들은 CD 리더를 가지고 있어서 너는 그 안에 많은 CD를 넣을 수 있다.그것은 스테레오와 CD가 같은 언어를 사용하기만 하면 모든 CD를 읽을 수 있다. (스테레오에 블루레이 CD를 넣을 수 없다.)너는 언제든지 CD를 가지고 바꿀 수 있다.이것은 의존 주입이다.
class Stereo () {
  constructor(speakers) {
    this.speakers = speakers;
  }

  function play(cdName) {
    speakers.playMusic(cdName);
  }
}
이것은 우리가 CD와 스테레오를 사용한 지 오래되었기 때문에 명백한 해결 방법인 것 같다. (비록 모든 것이 흐르는 미디어이지만!)그러나 소프트웨어는 일반적으로 장면에서 기술한 긴밀한 결합에 따라 작성된다.응용 프로그램이 데이터베이스 등 외부 원본에서 데이터를 얻는 것은 정상적인 것이다.그러나 클라이언트가 다른 데이터베이스에 연결하기를 원할 때 어떤 일이 일어날까요?의존 주입을 사용하면 스테레오의 CD처럼 닫기만 하면 된다.
극장에서 재생되는 현재 영화를 사용자에게 보여주는 프로그램을 만들고 있다고 가정하십시오.이것 좀 보세요pseudocode:
// function to display movies to the user
function displayMovies() {
  // get movies
  var movies = getMovies()

  // display movies
  showMovies(movies)
}

// function to get movies from the database
function getMovies() {
  // connect to our DB (currently a SQLDB)
  var db = new SQLDB(url).Connect()

  // query for movies
  var movies = db.ExecuteQuery('SELECT * FROM movies')

  return movies;
}
SQL 데이터베이스에 연결하고 조회를 한 다음에 이를 사용자에게 보여주고 SQL 데이터베이스에서 영화 데이터를 얻는 간단한 함수가 있습니다.
이것은 실행할 수 있지만, 테스트하기는 매우 어렵다!이를 테스트하기 위해서, 우리는 우리가 테스트한 모든 기계에서 SQLDB를 실행하고 아날로그 데이터를 채워야 한다.미래에 만약에 우리가 갑자기 다른 데이터베이스, 예를 들어 NOSQL 데이터베이스에 연결해야 한다면 우리는 아직도 해야 할 일이 많다.
만약 우리가 이 점을 쉽게 테스트하거나 데이터베이스를 바꾸기를 원한다면, 우리는 응용 프로그램과 데이터베이스 간의 긴밀한 결합을 늦춰야 한다.우리는 데이터베이스에 interface를 정의하고 호출할 수 있는 방법 (구어) 을 사용해서 우리가 사용하는 모든 데이터베이스가 이 인터페이스를 충족시킬 수 있도록 할 수 있다.
이를 어떻게 하는지 살펴보겠습니다(다시, psuedocode:
// movie database interface
interface MovieDB {
  GetAllMovies()
  GetMovie(name)
  // .. other methods needed to manipulate movie database
}

// class for MovieDB held on SQLDB
class SQLMovieDB implements MovieDB {

  // variable to hold db object
  var db;

  // constructor for when SQLMovieDB is created
  constructor(url) {
    // connect to DB
    db = new SQLDB(url).Connect()
  }

  // get all movies
  GetAllMovies() {
    var movies = db.ExecuteQuery('SELECT * FROM movies')
    return movies
  }

  // get a specific movie
  GetMovie(name) {
    var movie = db.ExecuteQuery('SELECT * FROM movies where movies.name is ' + name)
    return movie
  }

  // ... other methods to implement interface
}
좋아요!현재, 우리는 영화 데이터베이스를 SQL Movie DB로 추상화할 수 있는 인터페이스로 추상화했다.이제 영화를 표시하려면 다음과 같이 하십시오.

Note: For languages that don't support interfaces, you can pass additional parameters to functions to replicate the same behavior.


// function to display movies to the user
function displayMovies() {
  // get movies
  var movies = getMovies()

  // display movies
  showMovies(movies)
}

// function to get movies from the database
function getMovies() {
  // connect to our DB
  var db = new SQLMovieDB(url)

  // query for movies
  var movies = db.GetAllMovies()

  return movies;
}

그것은 더욱 테스트하기 쉽다!우리는 아날로그 영화 데이터베이스를 만들어서 우리의 테스트에 사용할 수 있다.
class MockMovieDB implements MovieDB {
  constructor(url) {
    // don't need to do anything
  }

  // get all movies
  GetAllMovies() {
    var movies = [{ title: 'SOME SUPER COOL MOVIE', ...otheData }, ...otherMovies]
    return movies
  }

  // get a specific movie
  GetMovie(name) {
    var movie = { title: 'SOME SUPER COOL MOVIE', ...otherData }
    return movie
  }

  // ... other methods to implement interface
}
이제 테스트 시스템에서 실제 데이터베이스 서버를 구축하지 않고도 MockMovieDB를 사용하여 데이터를 쉽게 시뮬레이션할 수 있습니다.
마지막으로 필요한 경우 NOSQL 데이터베이스와 같은 다른 데이터베이스를 사용할 수 있습니다.
// class for MovieDB held on NOSQLDB
class NOSQLMovieDB implements MovieDB {

  var db;

  constructor(url) {
    db = new NOSQLDB(url).Connect()
  }

  // get all movies
  GetAllMovies() {
    var movies = db.collection('movies').find({});
    return movies
  }

  // get a specific movie
  GetMovie(name) {
    var movie = db.collection('movies').find({ title: name });
    return movie
  }

  // ... other methods to implement interface
}
NOSQLMovieDB를 사용하려면 displayMovies 함수 중 한 줄만 변경하면 됩니다.
// function to display movies to the user
function displayMovies() {
  // get movies
  var movies = getMovies()

  // display movies
  showMovies(movies)
}

// function to get movies from the database
function getMovies() {
  // connect to our DB
  var db = new NOSQLMovieDB(url) // <---- WE ONLY HAVE TO CHANGE HERE

  // query for movies
  var movies = db.GetAllMovies()

  return movies;
}

우리가 원한다면 환경 변수로 옮길 수도 있다.우리는 심지어 무비DB를 주입하여 프로그램을 매개 변수로 삼아 리셋 getMovies 함수의 수요를 없앨 수 있다.
일단 내가 의존 주입을 진정으로 이해하게 되면 위대한 소프트웨어 디자인 모델의 세계는 나에게 문을 열어 준다.이러한 패턴을 사용함으로써 나의 코드는 더욱 깨끗하고 안전하게 변했다.
너의 생각을 나에게 알려줘!
특히 Adam Whitehurst 이 글을 준비하는 데 도움을 주셔서 감사합니다.🤘

좋은 웹페이지 즐겨찾기