ここに主な問題があります:
// This class requires some predefined globals
それはあなたにとって驚くべきことかもしれませんが、あなたが実際にやりたいことは、その場合、クラスを定義するときにそれをチェックするのではなく、それをインスタンス化するときにチェックすることだと思います。
クラスがインスタンス化されると、そのコンストラクター関数が呼び出されます。これは私にとってそれをチェックするのに最適な場所のようです:
class Product
{
public function __construct() {
// This class requires some predefined globals
$this->needGlobal('gLogger', 'db', 'glob');
}
private function needGlobal() {
foreach (func_get_args() as $global) {
if (!isset($GLOBALS[$global])) {
throw new RuntimeException(sprintf('Global %s needed but not set.', $global));
}
}
}
...
}
インスタンス化するProduct
と、前提条件が満たされているかどうかが自動的にチェックされます。
$blueShoes = new Product();
前提条件が満たされていない場合、これは機能しませんが、の場合は機能します。
しかし、それはあなたの問題を部分的に解決しているだけです。コードの本当の問題は、グローバル変数が機能するProduct
必要があることです。
代わりに、製品が動作するために必要なものだけを使用するようにします。
class Product
{
private $gLogger;
private $db;
private $glob;
public function __construct(LoggerInterface $gLogger, DbInterface $db, GlobInterface $glob) {
$this->gLogger = $gLogger;
$this->db = $db;
$this->glob = $glob;
}
...
}
使用法:
$redShoes = new Product($gLogger, $db, $glob);
そして、あなたはもはや内部のグローバルなものを気にする必要はありませProduct
ん。
コードを徐々に改善したいとコメントしました。あなたはそうすることができます、ここに方法があります。書かれているように、上記の2番目のバリアントが進むべき道ですが、現在、レガシーコードはそれと互換性がありません。いずれにせよ、Product
クラスが新しいコードである場合は、依存性注入を使用して記述する必要があります。これは、レガシーコードを新しいコードから分離するために重要です。新しいコードにレガシーなものを飲み込ませたくはありません。これにより、新しいコードがレガシーコードになるため、徐々に改善することはできません。新しいレガシーコードを追加するだけです。
したがって、依存性注入を使用してクラス定義を取得します。レガシーのニーズについては、これを保護する2番目のクラスを作成します。
class ProductLegacy extends Product
{
public function __construct() {
// This class requires some predefined globals
list($gLogger, $db, $glob) = $this->needGlobal('gLogger', 'db', 'glob');
parent::__construct($gLogger, $db, $glob);
}
private function needGlobal() {
$variables = array();
foreach (func_get_args() as $global) {
if (!isset($GLOBALS[$global])) {
throw new RuntimeException(sprintf('Global %s needed but not set.', $global));
}
$variables[] = $GLOBALS[$global];
}
return $variables;
}
}
ご覧のとおり、この小さなスタブは、新しい方法で物事を行うグローバルな方法をまとめています。新しいコードでクラスを使用できますProduct
。古いコードとインターフェイスする必要がある場合は、ProductLegacy
クラスのインスタンス化にグローバル変数で機能するクラスを使用します。
これを実行するヘルパー関数を作成して、さまざまなクラスで使用することもできます。あなたのニーズに少し依存します。古いコードと新しいコードの間に明確な線を引くことができる境界線を見つけるだけです。