web-dev-qa-db-ja.com

別の「アブストラクト/インターフェースを使用する理由」の質問。しかし、私はソロの開発者です。なぜそれを使うのですか?

私はそれの目的とすべてを知っています。私は自分自身をもう2年間はソロ開発者だと思っています。

私はそれが契約であるという答えを常に見ます。はい、わかりました。

しかし、ここに私の心にあるものがあります:

クラスがインターフェイスが要求するものを提供しなかった場合、エラーがスローされます。

まあ、クラスが本当にそのメソッドを必要とする場合、それを呼び出す何かがあり、それが正しくない場合でも、エラーをスローしますか?

違いは何ですか?

私は実際にそれを実装して「規範」に沿って進むことができますが、「なぜ」という疑問にぶつかります。理解せずに盲目的にフォローするのは好きではありません。

編集:

私は以前にこの質問についての回答を何度も検索してみましたが、いつも見つけているのは「だから誰か他の人がいるとき...」のようなものです。以前に他の人と一緒に作業しようとしたことがなく、それが本当にインターフェースを使用する理由であるかどうかはわかりません。

つまり、私は自分ですべてを行うので、コード内の何が適切かを知っていますか?また、メソッドの実装を忘れても、メソッドが定義されていないというエラーが表示されます。

編集2:

依存性注入は非常に良い答えです。これらにインターフェイスを実装すると、依存関係の実装を交換する必要がある場合に役立ちます。あなたは何とかしてあなたが必要とするものが提供されると確信しています。

これは、コンポーネント間の契約(おそらく開発者間の契約でもある)であることは、もう少しはっきりしています。

7
jen

私はそれが契約であるという答えを常に見ます。はい、わかりました。

私は実際にそれを実装して「規範」に沿って進むことができますが、「なぜ」という疑問にぶつかります。

理由を尋ねるなら、あなたは本当にそれを理解しないかもしれません。

インターフェイスの使用は、分離技術です。これにより、コードの一部が、コードの別の部分の実装の詳細を知らなくてもかまいません。これにより、変更コードの他の部分が影響を受けないという知識で安全な実装の詳細を実現できます。

これにより、変更を加える際の認知負荷が軽減されます。これにより、変更後に物事が適切に機能することを確認するために必要なテスト作業が軽減されます。また、複数の実装を同時に共存させる必要がある場合に、これらの機能を使用すると作業が非常に簡単になります。

ただし、これらのメリットが不要な場合があるため、インターフェースはオーバーヘッドになります。この種の影響を実際に学習する最良の方法は、コードを記述することです。インターフェースでいくつか書いてください。なしで書いてください。それぞれのデザインがどのように変化するかをご覧ください。プログラムへの変更が、設計に応じてどのように異なる影響を与えるかを確認してください。

13
Telastyn

インターフェースが必要だと思わなければ、おそらく必要ありません。クラスを直接使用するだけです。単純にする。インターフェイスが1つのクラスのみで実装されている場合、それはおそらく役に立たないインターフェイスです。

インターフェースは、以下のような特定の状況で役立ちます。

  • 一部のサービスの互換性のある複数の実装を許可する
  • テスト目的でコンポーネントを模擬できるようにする
  • サブシステム間の契約の定義

ただし、これらの要件がない場合は、インターフェースは必要ありません。

契約(インターフェースを取る場合)は開発者の間の契約ではなく、コンポーネントの間の契約です。開発者の数は関係ありません。問題は、そのような分離が価値を提供するほどシステムが複雑かどうかです。

6
JacquesB

単体テストを作成するときに、クラスに基づいてモックを作成したモックフレームワークを使用する場合、非常に明確に定義されたクラスのインターフェイスは必要ないと思います。

抽象化はリファクタリングから来るべきです

  • 2つのクラスに共通の実装の詳細がある場合、 [〜#〜] dry [〜#〜] の原則に従って、これらのビットを抽象クラスに移動することができます。
  • 2つのクラスが異なる実装で同じ動作をする場合、インターフェースを使用して動作を定義し、必要に応じて各実装を注入します

結論として、時期尚早の最適化と抽象化は過剰なエンジニアリング( [〜#〜] yagni [〜#〜] 原則)につながるということには同意します。

'solo'の議論については、2年後には別の人物になり、コードベースを保守可能にしておけば、your-current-selfに感謝します。または、いくつかの決定を下してすみません。

2
Andrei Epure

私に関する限り、学校はそのようなことを教える非常に貧しい仕事をしています。問題は、システムが大きくなると、意味のあるものになるだけです。

実世界のケースを取り上げて、抽象の価値を示しましょう。

私は、いくつかの「紙」(ディスクに印刷される)レポートを要約して画面上のチェックオフリストに変換するプログラムをここに持っています。 現在(上司のことを知っているので、リストがどこかの時点で大きくならない場合、私は非常に驚くでしょう)考えられるさまざまなレポート構造の半ダースの異なるパーサーとそれらの構造のいくつかは実際には複数を持つことができますレポート。

レポートタイプごとに個別のチェックオフルーチンを作成する必要がありますか?もちろん違います!しかし、標準の「レポート」はありません。すべてのレポートタイプに共通する唯一のフィールドは数量です。

したがって、レポートを表す抽象型があり、すべてのレポートに共通の一連の動作を実装します。次に、レポートを解析し、目的のフィールドの名前を含む文字列に応答して値を生成する方法を知っているレポートタイプごとにクラスを用意します。

同様に、同じ名前の文字列を取り、アイテムに貼り付けるラベルを出力するラベルプリンターがあります。

画面チェックオフとラベルプリンターの両方が抽象レポートタイプで完全に機能します(もちろん、構成ファイルから読み取られた情報に応じて子孫タイプとして初期化されました)。新しいレポートがシステムに追加されたときに更新する必要はほとんどありません。 。

私の現在の主要言語であるC#では、インターフェースは、それを使用するクラスとは別の動作を定義する必要がある場合に使用します。私はまだそれを書く理由を見つけていませんが、標準的なシステムの1つであるIDisposableを検討しています。基本的に、限られたリソースを制御するクラスは、適切なクリーンアップを保証するためにこれを実装する必要があります。

0
Loren Pechtel

この特定のポイントに答える:

つまり、私は自分ですべてを行うので、コード内の何が適切かを知っていますか?

何かを書いたからといって、何が必要なのかを常に覚えているとは限りません。特に、大規模なコードベースでの数年後のことです。

あなたはそれを書いていない人よりもナビゲートする方が簡単だと思うかもしれませんが、それはあなたがそれのすべての面を覚えているという意味でもありません。

0
user232573

インターフェイスは契約であり、その90%は他の人/テクノロジーとの契約です。しかし、彼らはまた自分自身との契約になることができます:あなたの未来の自分。

アプリケーションを新しいプラットフォームに移植し、データを取得する場所を変更する必要があるが、古いプラットフォームは引き続きサポートするとします。おっと、今度は2つの異なるバージョンのデータ取得コードと、それを使用するすべてのコードを記述する必要があります。または、インターフェイスを使用して別のクラスをロードし、別のソースからデータを取得することもできます。

これは実際に私に起こった実際のシナリオです。ローカルデータベースを使用し、現場の技術者向けにタブレット(データ接続なし)で実行する既存のWPFアプリがありました。それをUWP/iOS/Androidに移植して、電話や接続されたタブレットで実行できるようにする必要がありました。しかし、私は古いバージョンを放棄して、何百もの新しい電話/タブレットを一度に購入することを会社に要求することはできませんでした。インターフェイスを介してデータアクセス層を抽象化したので、ローカルデータベースではなくサービスにアクセスする新しいデータアクセスクラスを作成し、DIを使用して環境に適したクラスをロードしました。

0
HiredMind