2

classをMyClass介して API/Datalayer/external-something と通信する Objective-C クラスが与えられた場合、(周囲のアーチに応じて)コンストラクターで のインスタンスを受け取って受け取るか、 のインスタンスを必要とする各メソッド呼び出しに渡す必要があります。繋がり。この方法では、アプリケーション ロジックをカプセル化し、接続の詳細を無視することができます。ConnectionMyClassConnectionConnectionMyClass

MyClassさまざまな外部コンポーネントまたは単体テストでロジックを再利用するには、 class の代わりにMyClassprotocol() を使用するのが適切です。このように、さまざまなクラス (たとえば、ConnectionHttp、ConnnectionAPI2、ConnectionTestingEmulateProxyIssue など)を実装している限り、それらを使用できます。ConnectionProtocolConnectionMyClassConnectionProtocol

ここで、開発者が 、 で繰り返されMyClassMyOtherClassで一連の操作を実行するコード ブロックを持っているとしConnectionProtocolます。これはDRY原則に違反するため、受け入れられません。

  1. MyClassMyOtherClass、および は (NSObject 以外の) 共通の基底クラスを共有しないため、開発者は単純に機能を基底クラスにマージすることはできません。

  2. の各実装で機能を繰り返す必要があるため、DRYConnectionProtocolに再び違反するメソッドを追加します。ConnectionProtocol

  3. メソッドを@optionalメンバーにするConnectionProtocolことはまだ機能しません。

    • メソッドは頻繁に使用され、各実装で実装する必要があります。
    • メソッド ロジックは、 SoCに違反する接続ではなく、アプリケーションに固有のものです。
  4. ConnectionProtocol開発者は、渡されたオブジェクトがプロトコルを実装しているかどうかを確認し、必要な操作を実行するカテゴリを NSObject に追加することを検討しています。これには欠点があります。

    • NSObject のメソッド スペースは、カテゴリが使用されているファイル内のすべてのオブジェクトに対して汚染されています。
    • カテゴリ メソッドが正しく呼び出されないエラーはランタイムにキャッチされ、開発者は何らかの理由で厳密に型指定された言語を選択しました
  5. ConnectionProtocolカテゴリを使用して拡張されます。これは DRY 原則に違反せず、SoC を尊重します。ただし、Objective-C 仕様に違反しています。

    @implementation id< ConnectionProtocol > (AppLogicMethods)
    
    -(void)specialMethod:(NSObject*)myParam
    {
        // Do Stuff  
    }
    
    @end
    

DRYに違反せず、 SoCを尊重し、Objective-C の制限を満たすことなく、この問題を解決するにはどうすればよいでしょうか?

4

2 に答える 2

2

これは DRY 原則に違反するため、受け入れられません。

DRY は、難攻不落の自然の法則ではありません。米国のほとんどの州では重罪でさえありません。これは有用な設計ガイダンスの一部であり、シンプルさや SAAADの回避など、他の有用な設計ガイダンスと比較検討する必要があります。単純なコードを数行繰り返すことを恐れて、多くのプロジェクトが過度に複雑になるのを見てきました。簡潔さよりも明確さが重要です。マジックはWETより悪いです。

とはいえ、DRY は有用なガイダンスであり、ここで適切に組み込むことができると思います。

ここで、開発者が、MyClass、MyOtherClass で繰り返され、ConnectionProtocol で一連の操作を実行するコード ブロックを持っているとします。

これは、実際のトランスポートとは独立した高レベルの操作があることを示唆しています (「繰り返されるコードのブロック…および ConnectionProtocol で一連の操作を実行する」)。これは、間違ったレベルで抽象化していることを示唆しています。低レベルのトランスポート (「HTTP」) があり、そのトランスポートを管理する「接続」と呼ばれる高レベルのものがあります。したがってConnection、 HAS-A<Transport>であり、MyClassHAS -A である具体的なクラスが必要Connectionです。

とはいえ、この<Transport>プロトコルを作成するには時間がかかります。Connectionトランスポート ロジックを含むクラスから始めます。私が解決しなければならない唯一の問題が単体テストである場合、Connection複雑さを注入するのではなく、おそらくそのためにサブクラス化するでしょう。テスト以外の問題が発生した場合は、リファクタリングして余分なレイヤーを追加します。あまりにも多くのレイヤーを早期に追加することは、コードベースを過度に複雑にする一般的な方法であり、複雑さは、同じことを繰り返すよりも堅牢性の悪い敵です。

補足として、クラスメソッドを使用して共通コードをパッケージ化する答えも非常に合理的なアプローチであり、用途によってはより簡単になる場合があります。

于 2013-10-15T23:00:12.507 に答える
0

ConnectionProtocolmyParamが渡される「ユーティリティ クラス」が作成されます。

@implementation ConnectionProtocolAppLogicMethods

+(void)specialMethod:(NSObject*)myParam connection:(id<ConnectionProtocol>)connection
{
    // Do Stuff
}

@end
于 2013-10-15T21:31:33.393 に答える