Dependency Injection гэж юу вэ?

Dependency Injection гэж юу вэ?

Dependency injection бол хамгийн энгийн загварчлалын аргуудын нэг. Мөн тайлбарлахад нилээд төвөгтэй аргачлал. Ихэнх бусад тайлбар дээр Dependency Injection-ны талаар ойлгомжгүй, ядаргаатайгаар тайлбарлацан байдаг. Би PHP –тэй илүү тохиромжтойгоор тайлбарлахыг оролдсон. PHP бол голчилж вэб хөгжүүлэхэд зориулагдсан хэл учираас жишээ болгож вэб-ийн нэг энгийн жишээг авч үзье.

HTTP протокол-д нөхцөл, харъяалал ашиглахын тулд вэб-д хэрэглэгчийн мэдээллийг вэбийн хүсэлтүүдэд хадгалж өгөх хэрэгтэй болдог. Ингэхийн тулд тун энгийнээр cookie эсвэл Php-ын session гэсэн механизмуудыг ашиглах боломжтой байдаг.

$_SESSION[‘language’] = ‘fr’;

Дээрх код нь хэрэглэгчийн хэлийг session-ын language гэсэн хувьсагчид хадгалж байна. Ингэх нь нэг хэрэглэгчийн дараа дараагийн хүсэлтүүдэд language нь глобал $_SESSION array-с хандагдагдах боломжтой болдог.

$user_language = $_SESSION['language'];

Dependency Injection нь зөвхөн Объект-Хандалтад програмчлалд яригддаг болохоор, бид PHP session механизмыг бүхэлд нь хамарсан SessionStorage гэсэн класстай байгаа гэж үзэцгээе.

class SessionStorage
{
  function __construct($cookieName = 'PHP_SESS_ID')
  {
    session_name($cookieName);
    session_start();
  }
 
  function set($key, $value)
  {
    $_SESSION[$key] = $value;
  }

  function get($key)
  {
    return $_SESSION[$key];
  }

  // ...
}

Мөн өндөр түвшний User класс interface-тэй:

class User
{
  protected $storage;

  function __construct()
  {
    $this->storage = new SessionStorage();
  }

  function setLanguage($language)
  {
    $this->storage->set('language', $language);
  }

  function getLanguage()
  {
    return $this->storage->get('language');
  }

  // ...
}

Эдгээр класууд нь маш энгийн бөгөөд User классыг ашиглах нь мөн хялбархан:

$user = new User();
$user->setLanguage('fr');
$user_language = $user->getLanguage();

Бид илүү уян хатан зүйлийг хүсэх хүртэл бүгд маш сайн бөгөөд зүйгээр байна.  Тухайлбал хэрэв чи cookie-ынхээ нэрийг өөрчлөхийг хүсвэл яах вэ? Энд зарим бас боломжууд байнаа.

  • User классын SessionStorage байгуулагчид нэрийг шууд оноож өгнө
  • User классын гадна тогтмол зарлана
  • Session-ны нэрийг User-ын байгуулагчын аргументараар нэмнэ
class User
{
  function __construct()
  {
    $this->storage = new SessionStorage('SESSION_ID');
  }

  // ...
}
class User
{
  function __construct()
  {
    $this->storage = new SessionStorage(STORAGE_SESSION_NAME);
  }

  // ...
}

define('STORAGE_SESSION_NAME', 'SESSION_ID');
class User
{
  function __construct($sessionName)
  {
    $this->storage = new SessionStorage($sessionName);
  }

  // ...
}

$user = new User('SESSION_ID');

Storage класс-д сонголтуудын array-г нэмнэ.

class User
{
  function __construct($storageOptions)
  {
    $this->storage = new SessionStorage($storageOptions['session_name']);
  }

  // ...
}

$user = new User(array('session_name' => 'SESSION_ID'));

Эдгээр бүх оролдлогууд нь ер муу. Session-ны нэрийг User класс-д кодчилж өгөх нь үнэхээр асуудлыг шийдчиж чадахгүй. Учир нь User классыг өөрчлөхгүйгээр дараа нь чи санаагаа хялбархан өөрчлөх боломжгүй. Тогтмол ашиглах нь мөн муу учир нь User класс нь тогтмол тодорхойлогдохоос хамаарах учираас. Session-ны нэрийг аргументаар дамжуулах эсвэл сонголтуудын array-г ашиглах нь хамгийн тохиромжтой боловч, бас ч тиймч сайн санаа биш. Энэ нь User-ын байгуулагчын аргументуудыг объекттой хамааралгүй өөр зүйлүүдтэй хольж замбраагүй болгодог.

Гэтэл дахиад нэг өөр хялбар өөрчлөх боломжгүй нэг асуудал байнаа. SessionStorage  классыг яаж өөрчлөх вэ? Тухайлбал хялбархан тест хийхийн тулд хуурмаг объектоор засварлах. Эсвэл чи session-оо баазын хүснэгтэд эсвэл санах ойдоо хадгалахыг хүсвэл дээрх хэрэгжүүлэлт нь  User класс-г өөрчлөхгүйгээр боломжүй юм.

Dependency Injection-г оруул. User классын дотор SessionStorage-ыг үүсгэхийн оронд User-ын объектыг SessionStorage-ын объектоор тарьцгаая: Энэ яах вэ гэвэл User классын байгуулагч функцын аргументаар SessionStorage –ын объектыг дамжуулна гэсэн үг.

class User
{
  function __construct($storage)
  {
    $this->storage = $storage;
  }

  // ...
}

Энэ бол Dependency Injection.  Өөр юу ч байхгүй. Одоо User классыг ашиглахад таныг эхлээд SessionStorage классын объект үүсгэх хэрэгтэй болох руу аваачдаг:

$storage = new SessionStorage('SESSION_ID');
$user = new User($storage);

Одоо session-ны хадгалах объектыг тохируулах нь тун энгийн бөгөөд session-г хадгалах классыг өөрчлөхөд мөн хялбархан болсон. Одоо User классыг өөрчлөхгүйгээр бүх зүйл боломжтой болсон.

Pico Container website Dependency Injection-г дараах маягаар тайлбарласан.

“Dependency Injection бол хаана компонент өөрсдөөсөө хамааралтайгаар байгуулагч функцуудаар, функцуудаар (method), эсвэл шууд талбар руу өгөгдөх юм.”

Dependency Injection байгуулагч функцын –ын injection(тарилтыг) хориглодоггүй.

  • Байгуулагчын тарилт (Constructor Injection):
    • Setter Injection:
    • Property Injection:
class User
{
  function __construct($storage)
  {
    $this->storage = $storage;
  }

  // ...
}
class User
{
  function setSessionStorage($storage)
  {
    $this->storage = $storage;
  }

  // ...
}
class User
{
  public $sessionStorage;
}

$user->sessionStorage = $storage;

Туршлагаас үзвэл, required dependencies (шаардагдах хараат байдал) –ын хамгийн сайн нь бидний жишээнд гарсан шиг constructor injection (байгуулагчын тарилт) мөн optional dependencies-д setter injection тухайлбал cache объект.

Одоо цагт, ихэнх  PHP framework-ууд үлэмж ихээр Dependency Injection-г тэдгээрийн холбогдох компонентуудыг холбогч болон салгагчаар тавихад ашигладаг:

// symfony: A constructor injection example
$dispatcher = new sfEventDispatcher();
$storage = new sfMySQLSessionStorage(array('database' => 'session', 'db_table' => 'session'));
$user = new sfUser($dispatcher, $storage, array('default_culture' => 'en'));

// Zend Framework: A setter injection example
$transport = new Zend_Mail_Transport_Smtp('smtp.gmail.com', array(
  'auth'     => 'login',
  'username' => 'foo',
  'password' => 'bar',
  'ssl'      => 'ssl',
  'port'     => 465,
));

$mailer = new Zend_Mail();
$mailer->setDefaultTransport($transport);

Хэрэв та Dependency Injection –ны талаар илүү мэдэхийг хүсвэл, Martin Fowler introduction эсвэл Jeff More presentation –аас харах боломжтой.

Өнөөдөртөө ингээд боллоо. Одоо та Dependency Injection-ны талаар илүү ойлголттой болсон байх гэж найдаж байна.

Дараагийн сэдэв Dependency Injection Containers.

эх сурвалж: http://bit.ly/3ggju

Advertisements

One thought on “Dependency Injection гэж юу вэ?

Хариулт үлдээх

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Өөрчлөх )

Twitter picture

You are commenting using your Twitter account. Log Out / Өөрчлөх )

Facebook photo

You are commenting using your Facebook account. Log Out / Өөрчлөх )

Google+ photo

You are commenting using your Google+ account. Log Out / Өөрчлөх )

Connecting to %s