例として挙げることができる最も一般的な状況は、クラスを知らないstr_repeat( 'very-'、20)古いコードであり、現在のフレームワークで移植または部分的に使用される予定ですが、数千行と数十の依存関係を書き換える時間はありません。 これは、顧客が突然10年以上変わらずに機能していたプロジェクトを大幅に近代化または開発することを決定し、あるパートタイムのプログラマーがそれを台無しにして、ときどきいくつかのサービスをリロードしてパスワードを回復したときに起こります。
この記事は、以前の記事へのコメントの 検索から「Garbage Wrapper」の説明によって促されたことに注意する必要があります 。
ですから、コードを見た後、あなたはすでに落ち込んでいて、コーヒーが終わったと想像してください。今、あなたは開始する準備ができて
短いデバッグの後、プロジェクト全体が何百ものインクルージョンのチェーン上に構築されており、サービス/モデルにするために必要なコードを「引き出す」ことは不可能です。
その素晴らしいnoPSR時代の古典的なファイルを例に取ります。
// legacy_lib.php include("settings.inc.php"); require("functions.php"); require_once("database.connection.php"); define('SOME_CONST', 'value'); $var1 = funcName(CONST_2); function get_Var2A($param1, $param2) { return functionFromAnotherInclude($param2, $param1); } class myClass { var $data = ''; function getData() { global $var1; // do somethig return get_Var2A($var1, SOME_CONST); } } include_once("specialCode.php"); function needThis() { $obj = new myClass(); return unknownFunctionFromInclude() + $obj->getData(); } $var2 = needThis(); printr('{"param":' . $var2 . '; "var": ' . $var1 . '}');
実際、そのようなファイルは多くの場合1000行以上に達することがあり、時にはより多くの依存関係があります。
このコードをクラス、サービスなどに広めることができます。 しかし、同じように機能する可能性はゼロに急ぎます。
タスクを開始し、リファクタリングを「スムーザー」にするか、しばらくそれを延期することを完全に
このような状況では非常に主観的であるため、ここでは標準的なデザインパターンを適用しません。 フライウェイトとアダプターの2つのアプローチのみを使用することをお勧めします。
レガシーコードを実行し、擬似カプセル化するためのアダプターと、アダプターへのユニバーサルアクセスが必要です。
私は故意に(用語|テンプレート)sを使用しません:「facade」、「mapper」、「decorator」など。 疑いもなく、レガシーファイルの内容と構造に応じて、これらまたはそれら(用語|パターン)の方が適している場合があります。
私は相対的普遍性の目標を設定したので、サービス/モデルのニーズへの適応の結果を「適応」することを意味します。
次に、それぞれについて詳しく説明します。
私の場合、 適応の仕事は次のとおりです。
- 必要に応じて、インクルードのディレクトリを変更します。
- 必要なファイルを接続します。
- 結果をバッファリングします。
- グローバル変数をカプセル化します。
- 疑似カプセル化グローバル関数。
- 上記すべてへのアクセスを提供する
アダプターのタスク:
- フィットをカスタマイズして作成します。
- 適応を通常のオブジェクトとして使用する機会を与えるため。
- メソッドとプロパティを再定義する機会を与えるため。
- 「ファサード」、「マッパー」、「デコレーター」、およびその他の構造テンプレートのスーパークラスになるため
結果として得られるもの:
class MyLib extends LegacyAbstractAdapter { /** * Configure flyweight */ protected function configure() { $this ->setLegacyFile('legacy_lib.php') ->setLegacyPath('/path/to/includes') ; } } $myLib = new MyLib(); // $var1 = $myLib->var1; $var2 = $myLib->var2; // $myLib->var1 = 'some new value'; // $res1 = $myLib->get_Var2A($param1, $param2); $res2 = $myLib->needThis(); // $content = $myLib->getFlyweight()->getContent();
今では、装飾、作曲などもできます。
class MyLib extends LegacyAbstractAdapter { /** * Configure flyweight */ protected function configure() { $this ->setLegacyFile('legacy_lib.php') ->setLegacyPath('/path/to/includes') ; } // public function needThis() { return 'dummy value'; } // public function get_Var2A($param1, $param2) { return '<font>' . $this->getFlyweight()->call('get_Var2A', [$param1, $param2]); . '</font>'; } // . }
そして、私の意見では、最終クラス「MyLib」-「adapter」の内容に応じてのみ、より適切に呼び出すことができます。
ファイル内で宣言されたクラスへのアクセスの可能性もあります。インスタンスの作成、定数の取得、静的メソッドの呼び出しです。
これは「名前で」彼に連絡することで直接行うことができますが、そのような機会は抽象化の機会です。 そのようなクラスがリファクタリング後に存在しなくなった場合、すべての呼び出しではなく、そのクラスへのアクセスの1つのメソッドを置き換えるだけで十分です。
そして、もちろん、言及する価値のある多くの欠点があります。
- グローバル関数とクラスは引き続きグローバルであり、「直接」アクセス可能です。このアプローチは、さらに依存するコードを「生成」しないように、それらへのアクセスのみを規制します。
- 仕事のスピード。 テストを完了し、機能を1,000万回使用した結果、「ネイティブ」メソッドの2倍の時間で結果が得られました。 ここでは、負荷と正当化を考慮する必要があります。 私の意見では、ほとんどの場合、これは重大な問題ではありません。
- シングルトン。 包含は1回しか実行できないため、2つの適応を同時に作成することはできません。
要約:リファクタリングに数か月はかからないが、生産性にわずかなマージンがある場合-これは便利だと思います: github
ご清聴ありがとうございました。