侵入的なカスタマイズ

この記事では、侵入的なカスタマイズの特性を定義します。 侵入的なカスタマイズは、継続的なアップグレードの費用をゼロに維持する主要な障害です。 面倒なカスタマイズには、ツールによってなくすことができる種類もありますが、それ以外の種類は引き続き作成者が拡張する必要があります。 X++ コンパイラと Microsoft Visual Studio デザイナーでは、いくつかの種類の侵入的なカスタマイズが禁止されます。 ただし、侵入的なカスタマイズのサブセットはツールよって検出できませんが、継続的なアップグレードを実行しない場合があります。 最終的には、開発者は不注意なカスタマイズを避ける責任があります。

次のいずれかの原則に違反しているカスタマイズは侵入的です。

メモ

他のソリューションを拡張するとき、責任を持つことが求められます。 これには、次のものが含まれます。

  • 拡張の責任を受け入れる。 新しい動作を導入しようとしているため、変更についてのすべての責任を負います。
  • 他の拡張の共存を許可する。 拡張ポイントの唯一のユーザーではないことを認識します。 たとえば、必要なときのみ応答します。
  • 拡張ポイントと一貫性のある拡張のみ追加する。 ソリューションの有効期限は、変更への弾力性によって定義されます。 その拡張ポイントが将来のバージョンで実行されるシナリオが増えることもあれば減ることもあることを認識します。 たとえば、validate() メソッドにのみ関連する検証ロジックを追加します。
  • 実装の詳細への依存関係を回避する。 実装の詳細は、将来のバージョンで変更される可能性が高くなります。 ローカル変数、呼び出しスタック、呼び出し順序への依存を回避し、リフレクションの使用を回避することによって、ソリューションの復元力を高めます。

タイプの定義を変更しないでください。

タイプはその定義によって参照されます。 タイプの定義の変更は大きな変更であり、すべての参照を更新する必要があります。 (たとえば、タイプをホストするモデルで) 今後の参照が正しく実装されるよう確認することが重要です。 これにはいくつかの意味があります。

  • メソッド シグネチャを変更しないでください。 メソッド シグネチャには、戻り値の型、名前 (大文字と小文字の区別を含む)、およびパラメーター (オプションのパラメーターを含む) が含まれます。
  • インターフェイスおよびテーブル マップの実装者の要件を変更しないでください。 たとえば、新しいメソッドをインターフェイスに、または新しいフィールドをテーブル マップに追加しないでください。
  • 抽象クラスから派生したクラスの要件を変更しないでください。 たとえば、クラスに新しい抽象メソッドを追加しないでください。
  • タイプまたはメンバーのアクセス修飾子を減らさないでください。 たとえば、クラス、テーブル、またはメソッドをパブリックからプライベートに変更しないでください。
  • テーブルまたはデータ エンティティで定義されている制約を変更しないでください。 制約には、編集、必須の制約、一意性の制約、および参照の制約を許可することが含まれます。

カプセル化を中止しない

モデルの作成者は、カプセル化されたコードとタイプを管理し続けて製品を改良することができる必要があります。 モデルの所有者は、事前に通知せず、拡張機能およびカスタマイズの下位に影響を及ぼすことなく、自由にカプセル化されたコードを変更および削除できる必要があります。 たとえば、プライベート メソッドを削除された場合、カプセル化は中断されます。 次に、いくつか関連事項を示します。

  • タイプまたはメンバーのアクセス修飾子を増やさないでください。 たとえば、クラス、テーブル、またはメソッドをプライベートからパブリックに変更しないでください。
  • 変更のために何かを閉じる必要がある場合は、カスタマイズ動作のためににそれを開けることはできません。 拡張子の機能は、拡張性に向けオープンであるように設計されなければならないが、変更のためクローズする必要があります。

本質的に付加

拡張機能の一部として追加された機能を通じて新しい動作が有効になります。 拡張子の機能は、拡張子機能で設計および拡張子用にオープンされていなければならず、同じインストールで並行して存在する複数の拡張子をサポートする必要があります。 これにはいくつかの意味があります。

  • オーバーレイしないでください。 オーバーレイヤーは、既定の実装を置き換え、複数のソリューションが同じ要素を変更できないようにします。
  • 標準的な機能の特性を大幅に変更しないでください。 これらの特性には、ユーザー エクスペリエンスとパフォーマンスが含まれます。 たとえば、拡張子がインストールされているが使用されていない場合、パフォーマンスが低下することはありません。
  • EventHandlerResult クラスで結果を無条件に設定しないでください。XppPrePostArgs クラスで戻り値を無条件に設定しないでください。
  • 置換ロジックがリスコフの置換原則に準拠していない限り、既定では、既存の動作を置き換えないでください。

メモ

拡張機能の作成者は、これらの原則に違反しないようにする責任があります。