PHPでの配列の使用をやめる

どこでもPHP配列



私は長い間、PHPでの配列の完全な乱用という1つの問題の考えに悩まされてきました。 おそらく、問題の根源はPHPの手続き上の遺産か、PHPが多数の経験の浅い開発者を引き付けるという事実でしょう。 しかし、実際には、非常に多くの人々がオブジェクトを使用すべき場所に配列を使用しています!



私の意見では、配列を乱用するコードの恐ろしい典型的な例を見てみましょう。 たとえば、データベースからデータを抽出し、配列を介して操作するとします。 ここに私が毎日見ているいくつかの例があります:



$ponds = array( array( "name" => "Breakspear", "size" => "large", "pegs" => "23", "amenities" => array( "toilets" => false, "shop" => true, ), "fishBreeds" => array( array( "name" => "Bream", "stocked" => "2013-10-04 12:16:47", "number" => "100", "record" => "5.4lbs", ), array( "name" => "Perch", "stocked" => "2012-02-02 05:23:32", "number" => "50", "record" => "1.2lbs", ), array( "name" => "Common Carp", "stocked" => "2011-01-23 14:42:59", "number" => "10", "record" => "15.4lbs", ), ), ), );
      
      





特定の釣り池に関する情報を格納する巨大な多次元配列があります。 ここには1つの池しか記載されていませんが、100の池がそこに記載されているとしたらどうなるでしょうか。 結果は何ですか? データセットは配列に格納されていますが、動作は関連付けられていません。 このデータを使用する必要がある場合、ネストされたループでいっぱいの複雑なコードを作成する必要があります。 たとえば、池の魚の総数を取得するにはどうすればよいですか? アレイ全体を調べて、魚の総数を合計する必要があります。 経験の浅い開発者にとっては、これは悪いことではないように見えますが、彼はそうしているでしょうが、私はこのアプローチがもっと好きでした。



 $ponds->getNamed("Breakspear")->getTotalStocked();
      
      





同じ結果を得るためのはるかに少ないコード。 もちろん、データの完全な列挙は避けられませんが、機能は美しくカプセル化されています。 実際、この例は主な問題を明らかにしています-OOPの利点を避けないでください。 最初の例のコードは次のようになります。



 $ponds = new PondCollection(); $pond = new Pond("Breakspear"); $pond->addStockData(new StockData("Bream", 100, "2013-10-04 12:16:47")); $pond->addStockData(new StockData("Perch", 50, "2012-02-02 05:23:32")); $pond->addStockData(new StockData("Common Carp", 10, "2011-01-23 14:42:59")); $pond->addAmenity(new ShopAmenity()); $ponds->add($pond);
      
      





過度の複雑さ



巨大な配列を使用すると、関連する動作を追加することが不可能になるだけでなく、データにアクセスするための複雑なメカニズムを作成する必要があります。 多くの場合、これはネストされたループを使用する健全なメソッドを備えた多機能クラスとして実装されます。 そのように

 foreach ($ponds as $pond) { foreach ($pond["fishBreeds"] as $breed) { $stockedFish += $breed["number"]; } }
      
      





特にデータ構造に変更がある場合、このようなコードを記述して維持することは困難です。 さらに、メソッドの実装は、使用するデータとは関係ありません。



カプセル化のためにクラスを使用すると、最終的にはより多くのコードを記述する必要があるように思えるかもしれませんが、私自身の経験から、将来これによりコストが削減されることを保証しています。 ただ、値を繰り返すために毎回新しいサイクルを書く必要はないと考えてください。 コードが少なくなり、よりクリーンになり、各クラスが行うことの明確な境界が表示されます。



あなたは間違っています



開発者がこのようなコードを書き続ける唯一の理由は、手続きの過去における経験不足または損失です。 OOPは、このようなこと、特に動作を状態にリンクするためだけに考案されました。 信じられないかもしれませんが、バスケットや注文などの重要な部品にこのアンチパターンを使用している電子商取引市場で活動している非常に人気のある会社のコードを見ました。 コードには非常に複雑で脆弱であるため、変更は単に不可能であるため、(バグの存在にもかかわらず)開発者が触れることを単に禁止する場所がコードにあります。 クレイジー



データセットを操作する



データセットを操作するために配列を使用する必要があることを頭から出してください。 「データセット」(またはコレクション)は、配列を使用することを意味しません! 経験の浅い開発者は、イテレータについて聞いたことがないため、これを行います。 これらを使用すると、コレクションを操作して特定の動作を実装できます。 一見難しいですが、実際にはすべてが単純です。 イテレータを実装するクラスは次のとおりです



 class PondsCollection implements IteratorAggregate { private $collection = array(); public function getIterator() { return new ArrayIterator($this->collection); } public function add($pond) { $this->collection[] = $pond; } }
      
      





以上です。 動作と組み合わせて反復可能なデータのコレクションを作成するクラスの実装。 その中心には、クラスに配列が含まれていますが、現在はデータを操作するための適切なメソッドで装飾されています。 IteratorAggregateインターフェイスを実装すると、クラスオブジェクトがループでの作業に使用できるようになります。



 $ponds = new PondsCollection(); $ponds->add(...); foreach ($ponds as $pond) { ... }
      
      





これで、関連する動作を実装するためにセットからデータを取得する必要があるすべての場所が不要になり、データのコレクションに関連付けられ、オブジェクトからアクセス可能になり、コード全体に散在しません。



ドキュメントの詳細:





All Articles