この記事は、以前に公開された記事の続きであり、 ここにあります 。
この記事では、後方互換性ポリシーによって課された制限にもかかわらず、コードとして妥協しない方法に、より注意を払います。 また、互換性のない変更が元に戻されるまでリファクタリングを遅らせるのではなく、コードの変更中に継続的なリファクタリングを実行します。 コードが変更されるたびに実行される継続的なリファクタリングのみが、コード設計とアプリケーションアーキテクチャの継続的な改善につながり、コード全体の拡張性とサポートの改善につながります。
後のリファクタリングを遅らせると、技術的負債が増加し、製品所有者にとってビジネス価値のないリファクタリングのユーザーストーリーが作成されます。したがって、そのようなタスクは製品バックログのトップにはなりません。
禁止されているコードの変更とそれらの回避方法
クラス/インターフェースの削除
クラスまたはインターフェイスを削除する代わりに、このエンティティに
@deprecated
注釈を付けます。 また、このエンティティのすべてのメソッドを
@deprecated
として
@deprecated
し、すべてのIDEがすべての非推奨メソッドを正しく強調表示するようにします。
エンティティが
@deprecated
なった理由は、注釈の後に示す必要があります。
@see
アノテーションを使用して、推奨されていないAPIの代わりに使用する新しいAPIを推奨する必要があります。
/** * @deprecated because new api was introduced * @see \New\Api */
@deprecated
コードが削除される製品のバージョンを事前に知ることはできません。計画が変更される可能性があるため(アジャイル)、コードが関連しなくなったバージョンのみを知ることができます。
したがって、パブリックコードを変更する計画についてサードパーティの開発者に通知するために、
@deprecated
アノテーションとともにトークンを追加します
例のように:
/** * @deprecated since 2.1.0 * @see \Magento\Framework\Model\ResourceModel\Db\AbstractDb::save() */ public function save() { // ... }
また、このマーカーは、コードを作成するプログラマーが手動で設定するべきではありません。コードがどのリリースまたはパッチに入るかわからない可能性があるためです。 また、プレリリースビルドを実行する自動スクリプト。 したがって、現在のリリースで提供される新しいコードのために、ビルドツールが添付されます。
パブリックメソッドまたは保護されたメソッドの削除
パブリックコントラクトまたは継承コントラクトとして機能するメソッドを削除する代わりに、メソッドを
@deprecated
として解析する必要があります。 この場合、メソッドコントラクトを保存する必要があります。
クラスまたはインターフェースに新しいメソッドを追加する
Magentoは、インターフェイスがAPIまたは拡張ポイント(SPI)としてどのように使用されるかを知らないため(詳細については、 パート1を参照)、新しいメソッドをコントラクトに追加することも、インターフェイスが使用される場合、後方互換性のない変更(以下BiCと呼びます)ですSPIのように、すなわち サードパーティの開発者(以降3PDと呼びます)は、その実装を提供し、DI構成を介してすぐに実装を置き換えます。 エンティティコントラクトに新しいメソッドを導入することにより、新しいコントラクトの実装を持たない3PDクラスに問題をもたらします。
クラスの場合-誰かがこのクラスを継承し、そのコントラクトを拡張すると、常に名前の衝突が発生する可能性があります。
この場合、次のものが必要です。
- 新しいメソッドで新しいインターフェイスを作成します
- 新しいインターフェイスには、適切な場合、元のクラスに含まれていた他のメソッドが含まれている可能性があり、 凝集度の増加につながります
- この場合、元のクラスの対応するメソッドは、
@deprecated
アノテーションを追加して@deprecated
としてマークする必要があります。これは、新しく作成されたインターフェースのコントラクトを示します。 - 古いメソッドは、ロジックを複製するのではなく、作成されたインターフェイスのメソッドへの呼び出しをプロキシする必要があります。また、プラグインとイベントを操作するときのデータの一貫性を確保する必要があります
- PATCHリリースの一部として変更が行われた場合、新しいインターフェイスを
@api
としてマークすることはできません
静的関数の削除
オプションのパラメータを含むパラメータをパブリックメソッドに追加する
3PDは引き続き継承ベースのAPIを使用し、コントラクトを拡張することでMagentoクラスを継承できるという事実に基づいて、メソッドにパラメーターを追加すると、後継クラスを壊し、元のコントラクトにオプションのパラメーターを追加することになる可能性があります。
古いメソッドのコードを変更する代わりに、変更されたビジネス要件を満たす新しいメソッドシグネチャを示す新しいインターフェイスを導入する必要があります。
さらに、「新しいメソッドをクラスまたはインターフェイスに追加する」の段落で説明されている手順を参照してください。
保護されたメソッドにパラメーターを追加する
メソッドをそのまま保存します。 新しい署名を使用して新しいメソッドを作成し、古いメソッドを
@deprecated
としてマークします。 可能であれば、プライベートとして新しいメソッドを作成します。
メソッドが受け入れる引数のタイプを変更する
- 古いメソッドを
@deprecated
としてマークする - 引数の型が目的の型に変更される新しいメソッドを備えた新しいインターフェイスを導入します
- 古いメソッドの
@see
アノテーションで、新しいメソッドを参照します - 古いメソッドの実装を変更して、受信した古いパラメーターを新しい形式に変換する必要があります。その後、呼び出しは新しく作成されたインターフェイスにプロキシされます
メソッドの戻り値の型を変更する
この問題は、コントラクトに存在するメソッドから継承者のクラスまたはインターフェイスのタイプを返すことで解決できます。 しかし、Magentoは新しいコードに継承ベースのAPIを使用することを推奨していないため、この方法は使用しません。
スローされた例外のタイプを変更する
*新しいタイプの例外が古いコントラクトのサブタイプではない場合のみ。
コンストラクターの変更
新しいパラメーターをコンストラクターに追加するには、パラメーターをオプションにし、受け入れられる引数のリストの最後に追加する必要があります。
コンストラクターの本体は、新しい依存関係が渡されるかどうかを確認する必要があり、新しい依存関係が渡されていない場合(渡された引数の値がnull)、静的メソッド
Magento\Framework\App\ObjectionManager::getInstance()
を使用して依存関係を抽出します。
例:
class ExistingClass { /** * @var \New\Dependency\Interface $newDependency */ private $newDependency; public function __construct( \Old\Dependency\Intreface $oldDependency, $oldRequiredConstructorParameter, $oldOptinalConstructorParameter = null, \New\Dependency\Interface $newDependency = null ) { ... $this>newDependency = $newDependency ?: \Magento\Framework\App\ObjectManager::getInstance() ->get(\New\Dependency\Interface::class); ... } public function existingFunction() { // Existing functionality ... // Use $this->newDependency wherever the new dependency is needed ... } }
BCの修正は、KDPVのクレーンのように常にalwaysいように見えますか?
また、コンストラクターに渡された古い依存関係を削除することが不可能な場合にリファクタリングする方法はありますが、 追加できるのは新しいものだけです。 したがって、SOLID原則に違反する膨大な数の外部依存関係をクラスが受け入れる場合、Dependency Hellを近づけます。
第一に、新しく作成されたコードの過剰な結合を示す静的テストのエラーの抑制を明確に禁止する必要があります。 つまり このようなSuppressWarningは、バグ修正の実行後または新しい機能の実装後に追加しないでください。
オブジェクト間のカップリングのリファクタリングと依存関係の地獄の防止
たとえば、バグを修正するためにクラスに新しい有効な依存関係を導入し、その後、許容される外部依存関係の数のしきい値を超えた場合( 13 )。
私たちは:
- クラスの下位互換性を維持する、つまり そのパブリックおよび保護されたインターフェイス。 ただし、リファクタリングを実行する必要があります。これにより、クラスロジックの一部が個別のエンティティ(小さな特殊なクラス)に取り出されます。
- この場合の既存のクラスは、リファクタリングが実行されたメソッドの既存の使用が正しく動作することを保証するために、ファサードの役割を果たす必要があります。
- 古いpublic / protectedメソッドは、新しいクラスで新しく作成されたメソッドの
@see
アノテーションで@deprecated
としてマークする必要があります。 - 未使用のプライベートクラスプロパティはすべて削除できます。
- 未使用の保護されたクラスプロパティはすべて
@deprecated
としてマークする必要があります - クラスプロパティの未使用の保護変数のPHP DocBlockの型は削除できるため、PHPMDは外部依存関係としてカウントしません。
- コンストラクター内の未使用の依存関係のタイプヒントは削除する必要があるため、PHPMDは外部の依存関係としてカウントしません。
- @SuppressWarnings(PHPMD.UnusedFormalParameter)をコンストラクターに追加して、メソッドに渡される未使用の引数の静的チェックを防止する必要があります。
上記の手順を実行すると、