Co to za dużo do przekazywania danych przez wstrzykiwanie zależności?
Temat wstrzykiwania zależności jest już od jakiegoś czasu obecny w kręgach programowania obiektowego. Czasami widzimy to w WordPressie; czasami nie.
Jestem ich fanem, ale szczerze mówiąc, nie zawsze jestem pewien, ile informacji należy wprowadzić do klasy. Powiedzmy, że mamy dwie klasy, a jedna zawiera informacje, których potrzebuje druga.
- Czy nie wstrzykujemy żadnej klasy do innej klasy?
- Czy do drugiej klasy wstrzykujemy tylko fragment informacji (np. ciąg znaków, liczbę całkowitą, strukturę danych lub cokolwiek innego)?
Nie sądzę, że istnieje na to twarda i szybka reguła, ale prawdopodobnie można bezpiecznie powiedzieć, że lepiej jest wstrzykiwać tylko te dane, których potrzebujesz. Ale wtedy pojawia się pytanie, jak przygotować dane do wstrzyknięcia do danej klasy?
- Czy tworzysz metodę w jednej klasie i przekazujesz ją do innej?
- Czy przekazujesz do niego część informacji prywatnych lub chronionych?
Z drugiej strony myślę, że zależy to od tego, czy coś musi się stać z informacją, zanim zostanie ona przekazana do klasy.
W każdym razie, mógłbym kręcić się na ten temat do końca postu i nigdy nie dojść do konkluzji, więc dlaczego nie przepracować jakiegoś kodu źródłowego, dopóki nie pojawi się coś rozsądnego.
Zacznijmy od stwierdzenia, że mamy główny plik klasy wtyczki i ta klasa jest odpowiedzialna za utrzymanie informacji takich jak:
- ścieżka do wtyczki,
- adres URL wtyczki,
- czy wtyczka jest załadowana,
- aktualnie oglądany ekran,
- oraz klas, do których musi nadawać (pomyśl pub/sub) określone informacje.
Być może szkielet lub odgałęzienie klasy może wyglądać tak :
<?php
class Plugin
{
protected $plugin_path;
protected $plugin_url;
private $loaded;
public function __construct($file)
{
$this->loaded = false;
$this->plugin_path = plugin_dir_path($file);
$this->plugin_url = plugin_dir_url($file);
}
public function isLoaded()
{
return $this->loaded;
}
public function load()
{
// ...
}
private function isCurrentAdminStatus()
{
// ...
}
public function getSubscribers()
{
return [
new OtherPluginClass(...)
];
}
}
W takim razie zacznijmy naprawdę szeroko. Powiedzmy, że chcemy wziąć całą klasę i przekazać ją do jednej z klas, do której przekazuje informacje.
Gdyby tak było, mogłoby to wyglądać tak :
<?php
class Plugin
{
protected $plugin_path;
protected $plugin_url;
private $loaded;
public function __construct($file)
{
$this->loaded = false;
$this->plugin_path = plugin_dir_path($file);
$this->plugin_url = plugin_dir_url($file);
}
public function isLoaded()
{
return $this->loaded;
}
public function load()
{
// ...
}
private function isCurrentAdminStatus()
{
// ...
}
public function getSubscribers()
{
return [
new OtherPluginClass($this)
];
}
}
Ale jednym z wyzwań jest to, że przekazuje znacznie więcej informacji niż to konieczne do innej klasy. Ponadto przekazuje informacje zawierające informacje o klasie, do której przekazuje informacje.
Załóżmy więc, że chcemy zrobić krok wstecz i po prostu przekazać jedną z prywatnych informacji. To proste, prawda? Wygląda to mniej więcej tak :
<?php
class Plugin
{
protected $plugin_path;
protected $plugin_url;
private $loaded;
public function __construct($file)
{
$this->loaded = false;
$this->plugin_path = plugin_dir_path($file);
$this->plugin_url = plugin_dir_url($file);
}
public function isLoaded()
{
return $this->loaded;
}
public function load()
{
// ...
}
private function isCurrentAdminStatus()
{
// ...
}
public function getSubscribers()
{
return [
new OtherPluginClass($this->plugin_path)
];
}
}
W niektórych przypadkach może to być w zupełności wystarczające. Ale, jak wspomniano wcześniej, są też chwile, w których chcemy zebrać informacje, przetworzyć je, a następnie przekazać do klasy.
Aby to zrobić, po prostu zdefiniujemy metodę, przetworzymy informacje, a następnie przekażemy zwracaną wartość do klasy, która potrzebuje informacji :
<?php
class Plugin
{
protected $plugin_path;
protected $plugin_url;
private $loaded;
public function __construct($file)
{
$this->loaded = false;
$this->plugin_path = plugin_dir_path($file);
$this->plugin_url = plugin_dir_url($file);
}
public function isLoaded()
{
return $this->loaded;
}
public function load()
{
// ...
}
private function isCurrentAdminStatus()
{
// ...
}
public function getSubscribers()
{
return [
new OtherPluginClass($this->isCurrentAdminStatus())
];
}
}
Pomysł stojący za tą dyskusją pojawił się podczas pracy nad przeglądem kodu dla ostatniego projektu i omawiania różnych opcji przekazywania informacji do klasy.
Zacząłem więc ogólnie (pomimo tego, co jest konieczne, nawet biorąc pod uwagę powyższy proces myślowy), a następnie zawęziłem go do tego, co jest konieczne.