リファクタリングする時間がない場合のレガシーインクルードの疑似カプセル化

今日は、遠い過去から現代のフレームワークへのコードの移行を検討したいと思います。



例として挙げることができる最も一般的な状況はクラスを知らない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」など。 疑いもなく、レガシーファイルの内容と構造に応じて、これらまたはそれら(用語|パターン)の方が適している場合があります。



私は相対的普遍性の目標を設定したので、サービス/モデルのニーズへの適応の結果を「適応」することを意味します。



次に、それぞれについて詳しく説明します。



私の場合、 適応の仕事は次のとおりです。



  1. 必要に応じて、インクルードのディレクトリを変更します。
  2. 必要なファイルを接続します。
  3. 結果をバッファリングします。
  4. グローバル変数をカプセル化します。
  5. 疑似カプセル化グローバル関数。
  6. 上記すべてへのアクセスを提供する


アダプターのタスク:



  1. フィットをカスタマイズして作成します。
  2. 適応を通常のオブジェクトとして使用する機会を与えるため。
  3. メソッドとプロパティを再定義する機会を与えるため。
  4. 「ファサード」、「マッパー」、「デコレーター」、およびその他の構造テンプレートのスーパークラスになるため


結果として得られるもの:



 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つのメソッドを置き換えるだけで十分です。



そして、もちろん、言及する価値のある多くの欠点があります。





要約:リファクタリングに数か月はかからないが、生産性にわずかなマージンがある場合-これは便利だと思います: github



ご清聴ありがとうございました。



All Articles