いアヒルの子から白鳥、または湾曲したコードを修正する方法

画像



これは何ですか?



多くの人が、1つの小さなタスクで動作するプロジェクトを書き始めますが、このストーリーがマルチユーザー管理システム、たとえばコンテンツ、またはところではプロダクションにつながることを意味するわけではありません。 そして、すべてがクールでクールなように見えます。書かれているコードが完全に松葉杖とハードコードで構成されていることを理解し始めるまで、すべてが機能します。 緊急の問題があります。新しい機能を追加するときは、「そこに何が書かれていたのか」を覚えて、非常に長い間このコードをいじる必要があります。 特に、この記事は、最初の段階でリファクタリングの明らかな必要性を持たない初心者開発者を対象としており、現在は不快な状況にあります。



タイプセット、クエリ、松葉杖、時には読めないハードコードが入り口にあるとします。



どのように役立ちますか



リファクタリングの結果、システムは何を獲得しますか?

-構造化されたモジュラーコード。

-UIとロジックの分離。

-UNITテストを作成する機能。

-APIで許可されたアプリケーションに対してのみAPIを作成する機能。

-別のデータベースに転送するためのより簡単なアプローチ。



ケースの特定の例は、「それを行う方法とどこから始めるか」です。 このような修正を順番に処理することを提案します。同時に、2番目の段階を完了することなく、3番目の段階を開始しないでください。 作業中のシステムのコードを修正します。すべてが正常に機能することを理解するために、事前に機能テストを作成することをお勧めします。



ステージ



1. アルゴリズム的アプローチ

テストできない(そしておそらく他の場所でも繰り返される)恐ろしいレイアウトコードを見てみましょう。 シンプルで簡単ですが、そのようなコードのシーケンス-既知のトラブルの束を作成します。



index.php

<h1></h1> <? $DB = new DBConnector; $DB->query('SELECT * FROM users LIMIT 10'); if($DB->get_num_rows()){ while($user = $DB->fetch_row()){ echo '<p>'.$user['name'].'</p>'; } } ?>
      
      







2. 手続き的アプローチ

このシステムの他の場所で関数を作成して呼び出してみませんか? 手続き型プログラミングへの移行はコードの削減に役立ちますが、1回の呼び出しの例を使用すると悪化します。



functions.php

 $DB = new DBConnector function GetUsers(){ global $DB; $DB->query('SELECT * FROM users LIMIT 10'); if($DB->get_num_rows()){ while($user[] = $DB->fetch_row()); return $users; } else { return array(); } } ?>
      
      







index.php

 <h1></h1> <? include 'functions.php'; $users = GetUsers(); foreach($users as $u) { echo '<p>'.$u.'</p>'; } ?>
      
      







コメント: すでに改善されています。 すべてのリクエストをこのフォームに変換すると、モジュールで動作する特定のfunctions.phpのリストを確実に取得できます。 したがって、モデルはすでにUIから分離されており、各関数、およびそのような関数の呼び出しのシーケンスをテストできます。



3. オブジェクト指向アプローチ

必要な機能セットのみで機能するのに十分な場合、システム内のすべての機能を接続する必要があるのはなぜですか? たとえば、単純なユーザーのリストがあるページでは、タスクやプロジェクトなどの機能のリスト全体を接続する必要はありません。 モジュールで作業クラスを作成して、このモジュールのみで作業オブジェクトを作成するのはなぜですか? Get(追加/編集)メソッドの同じパラメーターの関数の継承が、モジュールを操作するためのクラスを生成するスーパークラスから単純に継承されるように、アーキテクチャを構築できます。 また、機能のためにデータベースにアクセスする必要が常にあるとは限らない可能性があるため、データベースに接続することさえできます。



データベースに接続し、いくつかのレコードのリストを取得するメソッドを持つ基本的な抽象スーパークラスを作成します。 ユーザーを操作するためのクラスを継承し、オブジェクトを作成してレコードを取得します。



Baseclass.php

 abstract class BaseClass{ protected $dataBase; protected $moduleName; function __construct(){ $this->dataBase = new DBConnector; } //        function Get($limit=10){ $DB->query('SELECT * FROM '.$this->moduleName.' LIMIT '.$limit); if($DB->get_num_rows()){ while($user[] = $DB->fetch_row()); return $users; } else { return array(); } } }
      
      







UserClass.php

 include 'BaseClass.php' class UserClass extend BaseClass{ function __construct (){ parent::construct('users'); } }
      
      







index.php

 <h1></h1> <? include 'UserClass.php'; $users = new UserClass; $users = $users->get(); //  foreach($users as $u) { echo '<p>'.$u.'</p>'; } ?>
      
      







コメント: たくさんのコードがありますが、より良いですか? 実際、これらの2つのクラスはAPIを作成する最初のステップです。 なぜそう 実際には、RESTFull APIを介したリクエストはアドレスで行われ、多くの場合モジュール名があります。 アドレスに応じて、クラスを接続(またはClassLoaderを接続)し、このユーザーに許可されている一連の関数を呼び出します(権限またはロールハンドラーを挿入できますが、これは別の話です)。





この記事の本質は、リファクタリングがほとんど常に可能であり 、最も絶望的な状況でもしばしば必要であるということです。 誰もが美しいコードを愛していますが、多くの場合、それを書く時間がないので、間違いなくこれは悪い習慣です。



この場合、3つの段階が与えられ、その結果、システムはアプリケーションロジックからUIの分離を受け取ります。 これにより、ユニットテストの作成、RESTfull APIの作成、および完了した作業に対する自己満足の可能性のために、曲がったコードでオーバーロードされたシステムが準備されます。 多くの人にとって、これはもちろん明らかなことかもしれませんが、サードパーティのアプリケーションを作成するか、APIを提供するように求められると、ときどき赤面する必要があります。



PS:私はどんなコメントにも、そしておそらく、同様の性質の問題に対する他の方法と解決策へのリンクに喜んでいます。



All Articles