web-dev-qa-db-ja.com

REST APIのラッパーを作成するときに静的クラスを使用しても問題ありませんか?

REST APIを使用してC#でWebサービスを使用しています。そのため、各エンドポイント用のラッパークラスを作成しました。静的を使用してラッパーを実装することは良い考えのようです。これにより、コードが見えるようになります。たとえば、Albumsエンドポイントでメソッドを使用すると、次のようになります。

List<Album> albums = AlbumsEndpoint.GetAllAlbums();
Album myAlbum = AlbumsEndpoint.GetAlbum("myAlbumId");

一方、インスタンスを使用してこのAPIを使用すると、見苦しくなります。

List<Album> albums = new AlbumsEndpoint().GetAllAlbums();
Album myAlbum = new AlbumsEndpoint().GetAlbum("myAlbumId");

それでも、このパターンを使用しているSDKはたくさんあります。 ( ここに 一例。)ここにインスタンスを作成する意味は何ですか?シングルトンではないでしょうか?そのインスタンスを存続させるオーバーヘッドが追加されませんか?
では、全体を通して静力学を使用しても大丈夫ですか?インスタンスクラスを使用しないことで何を見逃すのですか?

5
akshay2000

静的クラスメソッドは基本的にグローバル関数であり、OO設計では悪い考えと見なされます。それらが悪いと見なされる理由は、違いを比較しているだけの単純なコード例ではわかりにくいですインスタンスまたはクラス自体で同じメソッドを呼び出す間。

しかし、少し複雑な設計に入ると、グローバル関数が実際の問題になります。

コードを例にとります

_albums = new AlbumsEndpoint().GetAllAlbums();
_

_albums = AlbumsEndpoint.GetAllAlbums();
_

これらは非常に似ているように見えるかもしれませんが、一番上のオブジェクトにはオブジェクトがあり、2番目のオブジェクトにはグローバル関数があります(AlbumsEndpoint.GetAllAlbums()はグローバル関数です。クラス[GetAllAlbums()は、関係のないクラスでもハングアップする可能性があります)

オブジェクトコードはこのような行で置き換えることができます

_albums = myEndpointInstance.GetAllAlbums();
_

そして、これはまだ機能します。 myEndpointInstanceとは何ですか? GetAllAlbumsメソッドを提供するのは、連絡先を満たす任意のオブジェクトです。このオブジェクトは、他の場所から取得することもできます。コード内のここでインスタンス化する必要はありません(依存性注入を参照)。これは、コードがどのタイプのオブジェクトmyEndpointInstanceが期待されるインターフェースを提供する限り、どのタイプでもかまわないため、柔軟性を提供します。

明日、完全に異なる動作をする完全に新しいEndpointオブジェクトを記述して、このオブジェクトをこのコードで渡す場合があります。上記のコードは、エンドポイントオブジェクトの動作howを気にしないため、気になりません。動作するかどうかのみを気にします。そして、別の古いオブジェクトを使用していた他の場所には触れません。これで問題なく動作します。

オブジェクトを使用する代わりにグローバル関数を使用するとどうなるかを見てみましょう。このコードをグローバル関数AlbumsEndpoint.GetAllAlbums()に関連付けました。明日、ここでコードの動作を変更したいが、他の場所では動作を変更したくない。したがって、新しいグローバル関数を作成する必要があります。次に、新しいグローバル関数を使用するようにメソッドのコードを変更する必要があります。

ほとんど変更されない小さなコードベースではそれほど悪くありません。維持する必要がある大きなコードの頭痛。

オブジェクトを使用すると、オブジェクトが提供する柔軟性があり、オブジェクトが理解するすべてのメッセージに対してアクションを実行できます。オブジェクトを呼び出すコードは、オブジェクトが正確に何であるかを知る必要はありません。代わりにグローバル関数を使用する場合、関数の呼び出しをその関数の非常に具体的な実装に結び付け、事実の後でそれを変更することは難しく、バグを引き起こす可能性があります。結局のところ、これはそもそもオブジェクト指向デザインの主な利点の1つです。

10
Cormac Mulhall

フレームワーク/ SDKは、依存関係の注入を可能にするため、おそらくインスタンス化メソッドを使用しますが、これは実際には静的メソッドには当てはまりません。ただし、DIを使用しない場合は、静的メソッドが最も簡単な方法です。接吻。

4
JacquesB

使用する重要な静的メソッドを作成するときはいつでも、テストするのがいかに難しいかを考えると、常にそれを後悔することになります。特に、コードベース全体で使用する場合。

完全に微細な静的メソッドの例:

public static Boolean valueOf(boolean b) {
    return b ? Boolean.TRUE : Boolean.FALSE;
}

また、必要な依存関係もありません。

しかし、次のような場合:

public static User getCurrentUser() {
    var auth = SecurityContextHolder.getContext().getAuthentication();
    if (!auth.isAuthenticated()) {
        throw new UserNotLoggedInException();
    }

    return ((User) auth.getPrincipal());
}

それは悪夢になるだけです。私はこの静的メソッドをあまりにも自由に使用しました。コードを「よりクリーン」に見せることはできましたが、テストははるかに困難になりました。できれば、可能な限りDIを使用することをお勧めします。

免責事項:私はSWEの経験がほとんどないので、この答えを1粒の塩でとってください。ちょうど私の2セントを共有します。

1
abrandell