web-dev-qa-db-ja.com

今後APIに動作を追加するための最良の設計原則は何ですか?

APIを設計しています。そして、このAPIはクライアントによって使用されます。

現在、クラス定義には2つの動作があります。シナリオを説明するために、サンプル実装は次のようになります。

public class Session {

    // instance field declaration goes here

    void connect() {
        // method definition goes here
    }

    void submitJob() {
        // method definition goes here
    }
}

今後、このクラス定義にさらに多くの動作を追加して、より多くの機能を提供したいと考えています。また、クライアントコードを変更したくありません(つまり、クライアントはこの単一クラスをインスタンス化し続け、必要に応じて動作を呼び出します)。しかし、このクラス定義を変更したくありません。目標を達成するための動作を追加するために従うことができるデザインパターンや原則はありますか?

注:実行時にビヘイビアーを追加するつもりはありません。

説明やガイドに感謝します。

4
Rabin Halder

実際の構造や予想される行動の変化についてあまり知らなければ、おそらく コマンドパターン が役立つかもしれません。

基本的に、Sessionクラスで多くの異なるメソッドを宣言してそのAPIを常に変更する代わりに、Commandインターフェースとすべての実際のコマンド、つまり実際に必要なものを提供します実行するには(そうでなければ別の方法で行われます)、Commandの具体的な実装に入ります。実際、それは少し似ています。あなたのsubmitJobメソッドは、すでにそのようなコマンドを受信する途中です。 Commandパラメータを追加するだけです... :-)

class Session {

    public void submitJob(JobCommand job) {
        job.execute();
    }
}

interface JobCommand {

    public void execute();
}
4
jhr

インターフェースに対するコード

Sessionは、インターフェイスから2つのメソッドを継承していません。簡潔にするためですか?そうでない場合は、常にインターフェースを備えたAPIを宣言する必要があります。

public interface Session {
    void connect();
    void submitJob();
} 

public class HttpSession implements Session {
    @Override
    public void connect(){

    }

    @Override
    public void submitJob() {

    }
}

APIの進化

あなたのメソッドがパラメータを取らないという事実は、将来あなたをブロックするかもしれません。説明:

Session session = SessionFactory.create();
session.connect();

上記のコードは、APIのcurrentの使用例です。将来的には、connectのパラメーターtokenを受け入れる必要が出てくるでしょう。この場合、インターフェースを次のように変更する必要があるため、失敗します。

public interface Session {
    void connect(String token);
    void submitJob();
} 

別のパラメーターを追加する必要がある場合はどうなりますか?そしてあなたのインターフェースを

public interface Session {
    void connect(String token, String username);
    void submitJob();
} 

あなたは何度も何度もねじ込まれているようです...

それを解決するために、APIデザインですでに見た1つのプラクティス(免責事項:それが良いプラクティスかどうかはわかりません)は、メソッドへのオブジェクトパラメータ。

public interface Session {
    void connect(ConnectParameters params);
    void submitJob();
} 

public final class ConnectParameters {
    private final String token;
    private final String username;
    //TODO: add future parameters here

    ...
}

このソリューションを使用すると、署名が進化してAPIを破壊しないことが保証されます。

4
Spotted