一般にソフトウェア、特にWebアプリケーションの開発における主な側面の1つは、ソフトウェアが変更可能であること、つまり周囲の世界の変化に適応できることだと考えています。 これは、開発者がコードの環境の将来の変更を予見しなければならないという意味ではありません。つまり、コードは多くのリファクタリングサイクルに耐えながら、可能な限り長く動作する必要があります。 このため、コードに加えられた変更の結果が予見可能または予測可能であることが必要です。 カットの下で、Magento 2(オンラインストアを構築するためのプラットフォーム)との密接でほぼ親密な関係の結果として形成されたコード隠蔽の領域に対する私の理解をまとめました。 前述の説明では、まずPHP言語、2つ目はWebアプリケーション、3つ目はその他すべてについて言及しています。
変化のローカルおよびグローバルな影響
最も単純なケースは、変更がローカルスコープを超えない場合です。 ローカルスコープとは、関数/メソッドの本体を意味します:
function foo(int $in): int { $out = $in * 2; return $out; }
関数内のコードは好きなように変更できます。 変更の効果が表示されます(関数/メソッドの本体によって制限されます)。 ただし、関数の名前を簡単に変更することはできません。一般的に、誰がfoo()関数を使用し、関数の名前をboo()に変更するとどのコードが実行を停止するのかわかりません。 つまり、関数本体の変更はローカル(表示)であり、関数名(署名-入力パラメーターと出力パラメーターを考慮に入れた)の変更はグローバル(予測不能)です。
この出版物の文脈では、コードによって実装された機能ではなく、コードの変更を検討します。 明らかに、関数foo()がデータベースにエントリを追加する必要があり、リファクタリング後にデータベースからエントリを削除する場合、そのような急激な動作の変化は、関数foo()を使用する外部コードのすべてのフラグメントの動作に予測できない結果をもたらします。 ただし、呼び出しの観点( foo()関数と外部コードのペアリング)からは、変更されていません。
クラス
カプセル化(または、非表示)により、機能の一部を、変更の影響のグローバルエリアから、よりグローバルではないものに、クラスレベルに移動できます。
class Foo { private function localChanges() {} public function globalChanges() {} }
プライベート関数(およびプライベート関数自体)に含まれるコードの部分は、世界中で非常に簡単に処理できます。 変更の範囲はクラス本体に限定されます。
残念ながら、保護された関数についても同じことが言えません。それらの変更の範囲は、公開関数と変わりません。 彼女もグローバルです。
クラス階層
良いマナー(および人間の能力)は、同じクラスの数千行のコードであるコードの「シート」を作成することをお勧めしません。 実装のために、数千行のコードを客観的に記述する必要のある機能がありますが、1つのポイント(あるクラスのパブリックメソッド)から呼び出されるとします。 明らかに、変更の範囲は1つのメソッドに対してのみグローバルであり、残りの機能はプライベートメソッドに従って分散できます。
class MegaFoo { private function validateInput($in) {} ... private function prepareOutput($in) {} public function exec($in) {} }
分解の原理により、「シート」を数千行のコードに分割してコンポーネント部分(クラス)にし、プライベートメソッドでの内部実装を隠し、パブリックメソッドを使用して相互に結合する必要があります。
namespace Vendor\Module\MegaFoo; class Boo { public function validateInput($in) { $result = ($in > 0) ? $in : 0; return $result; } }
namespace Vendor\Module\MegaFoo; class Goo { public function prepareOutput($in) { $result = number_format($in, 2); return $result; } }
namespace Vendor\Module; class MegaFoo { private $boo; private $goo; public function __construct( \Vendor\Module\MegaFoo\Boo $boo, \Vendor\Module\MegaFoo\Goo $goo ) { $this->boo = $boo; $this->goo = $goo; } public function exec($in) { $data = $this->boo->processInput($in); $result = $this->goo->prepareOutput($data); return $result; } }
作成されたクラスのプライベートメソッドの変更の範囲は、クラス自体によって制限されます。 そしてここで、クラス\ Vendor \ Module \ MegaFoo \ Booおよび\ Vendor \ Module \ MegaFoo \ GooのpublicメソッドprocessInput($ in)およびprepareOutput($ data)に対する変更の範囲は、クラス階層によって制限されます。
- \ベンダー\モジュール\ MegaFoo
- \ベンダー\モジュール\ MegaFoo \ Boo
- \ベンダー\モジュール\ MegaFoo \ Goo
クラス\ Vendor \ Module \ MegaFoo \ Booおよび\ Vendor \ Module \ MegaFoo \ Gooのコードから、変更の範囲が制限されていると結論付けることは可能ですか? 残念ながら、ありません。 サードパーティの開発者がコードで\ Vendor \ Module \ MegaFoo \ Boo :: processInputメソッドを直接使用することを禁止するものはありません。 このようなアクションを制限するマーカーは、コードのどこにもありません。 つまり、変更の影響を受ける領域は限られていますが、それを説明するツールがないため、これを利用することはできません。 もちろん、個々のプロジェクトのレベルで、開発グループで有効な契約のレベルでそのようなオプションを議論できます。
モジュール
複雑なアプリケーションを作成するために、開発者は互いの結果を使用せざるを得ません。 これらの結果は、ライブラリ、フレームワーク、これらのフレームワークのモジュールの形式で提示されます。 私見、Magento 2はそのような協力の最前線にいます。 実際、このプラットフォームは、サードパーティのライブラリ(Zend、Symfony、Monologなど)を使用して、いくつかのフレームワーク(Magento 2)に基づいて作成された一連のモジュール(magentoモジュール)です。 Magento-moduleは、アプリケーションが作成され、他のmagento-moduleが使用できる機能から完全に独立したユニットです。 モジュール内およびクラス内のコードは、パブリックとプライベートの2つの部分に分けられることは明らかです。 パブリック-これは、最終アプリケーションの他のモジュールによって使用されることになっているコードです(フレームワーク自体によって呼び出されるコードがパブリック部分を参照するかどうかはわかりません)。プライベートは、モジュールの開発者がモジュールの外部で使用するつもりのないコードです Magento 2独自のモジュールの進化の例は、モジュールのルートにある./Api/フォルダーでパブリックインターフェイスのセットがどのように形成されるかを示しています。
このアイデアを開発する場合、モジュールの開発者は、インターフェイスを通じて、モジュールで公開する予定の機能を明示的に示し、残りのすべてのコードはモジュールの閉じた部分を参照し、サードパーティのコードによる使用に関係なく、再設計されました。 したがって、モジュールの閉じた部分に対する変更の効果は、モジュール自体のファイルに限定されます。 -表示されます。
アプリ
アプリケーションレベルへのパブリックモジュールインターフェイスを明示的に宣言するというアイデアの発展は、同じMagneto- Swagger APIの例で見ることができます 。 たとえこのレベルが変化の影響のある分野に既に弱く関連しているとしても、 Webアプリケーション開発者の観点から見ると、アプリケーション全体の変更の範囲はグローバルスコープと同じです。
まとめ
リファクタリングの品質は、隠蔽の原則(プライベート部分とパブリック部分へのコードの分離)がクラスのレベルだけでなく、単一の機能の実装によって接続されるクラスのグループのレベル、およびアプリケーションが構築されるモジュールのレベルでも適用される場合、大幅に改善できます。
要求しない トマトを投げる 記事に記載されていることがあなたの活動分野で適用できない、またはあまり適用できない場合、コメントがあふれます-これは私の個人的な経験の単なる形式化です。 気に入らない-マイナス。 そして、はい、私はこれらすべてが私の前にすでに発明されていることを知っています。 それを読んだ人に感謝します。