実装の前にインターフェイスAPIを作成する必要がありますか?


14

私は最近、より「組織化された」プログラミングを掘り下げてきましたが、実装ではなくインターフェイスにプログラミングする必要があることを学んでいます。それを念頭に置いて、可能であれば実装を記述する前に、インターフェイスでプロジェクトを「スケッチ」する方が良いでしょうか?

サードパーティのライブラリ(Lidgrenなど)を使用する場合は、これらをインターフェイスでラップし、IOCコンテナを介して解決する必要がありますか、それともインターフェイスに公開してもかまいませんか?


私の個人的な経験では、最初にアーキテクチャを設計するのは良いことです。各クラスの責任です。書き留める必要はありません。考えたり、紙にスケッチしたりするだけです。それから個人的な好みについてですが、実装を開始するすべてのメソッドについて最初にドキュメントコメントを書くことをお勧めします。ドキュメントを書くと、コードを書き始める前に機能について考えることができます。
スルタン

はい。実装する前に、インターフェイス(または、そのための抽象クラス)をプログラムします。実装が行き詰まる(そして投資される)前に、クライアントからサーバーへ、またはその逆の「正しい」メッセージフローを得るのに役立ちます。問題の非常に良好なスライドショー:グッドAPIを設計する方法&なぜそれが事項
マージャンVenema氏

回答:


8

残念ながら、これはしばしば個人的な好みに帰着することがわかります。

ただし、これまで説明してきたことは良いようです。実際、必要な場合(お勧めします)、次のアプローチを使用できます。

  1. アプリケーションスケルトンをインターフェイス、抽象クラス(スタブ)、およびクラス(スタブ)として記述します
  2. これらのインターフェースとスタブに対するテストを作成します(今のところ失敗します)
  3. 実装を記述します(実装が完了すると、テストが合格し始めます)

あなたはもっと「組織化された」コードを書くことに集中しています。TDDに従うことでこれを支援できます。

いくつかの追加ポイント:

  • IoCコンテナーは便利です。できる限りそれらとDIを使用します。
  • くださいサードパーティのライブラリをラップします。これにより、コード(ユーザーが制御するコード)とサードパーティコード(ユーザーが制御しないコード)の間の結合が緩和されます。

1
これは私が当初考えていたものでしたが、YAGNIの原則に違反すると言われました。私の多くのプロジェクトで見つかった問題は、私が書いたブロブコードの量で維持できなくなってしまうことです。これは、適切に整理したり攻撃計画を立てたりしないためです。
ダンパントリー

どの部分がYAGNIに違反しますか?
メタファイト

サードパーティのライブラリをラップします。
ダンパントリー

2
要約すると、サードパーティのライブラリが変化する可能性は何ですか?この可能性が0%の場合は、YAGNIを確認してください。しかし、それはめったにありません。また、サードパーティのライブラリをラップすると、他のコードの単体テストが簡単になる場合があります(たとえば、サードパーティのライブラリをモックアウトできなかった場合)
MetaFight

1
@DanPantry:サードパーティライブラリのラップはYAGNI違反ではありませんが、「独自のコードのサードパーティライブラリの侵入」に対する非常に必要な保護です。ライブラリをスワップアウトできるというだけではありませんが、MetaFightは、ライブラリの新しいバージョンでの変更に対する防御も述べているため、そうしないと独自のコード全体の変更が必要になります。ライブラリ(および特にその特定の型:クラス、列挙、構造体など)をラップすることにより、独自のコードを分離し、ライブラリが変更されたときに(何らかの理由で)変更する単一のポイントを持ちます。
マルジャンヴェネマ

13

はい、既知の実装ではなくインターフェイスに対してコーディングする必要があります。また、インターフェイスを独自のコードから出現させるのではなく、最初に構築する必要があります。

両方の推奨事項の理由はほぼ同じです。コンピュータープログラミングは主に人的要因に関するものです。多くの人はこれを驚くべきことに気付きますが、考慮してください。同じコンピューティング問題を解決するためのほぼ無限の数の異なる方法があり、同等にうまく機能します。それらのほとんどすべては、それらを書いていない人(または実際には少し後に著者に)にとって意味をなすことは完全に不可能です。

したがって、優れたソフトウェアエンジニアリングは、ソースコードを後で使用できるようにする方法で、主に目的の効果(合理的な効率で正しい計算)を達成する方法に関するものです。インターフェイスとAPIは、この分野の重要な部分です。これらを使用すると、一度に1つの説明レベルで問題について考えることができます。これは、ビジネスの一貫性ルールリンクリストの実装を同時に考えるよりもはるかに簡単です。したがって、このような懸念の分離を強制的に課すことは、クライアントプログラマーが好きなようにコードを使用できるようにするより優れています。

これは多くのカウボーイプログラマーにとって信じがたいことです。彼らは自分が書いたものをすべて理解し、平均的な思想家よりもはるかに優れており、「より少ない」プログラマーのトラブルを引き起こす複雑さをすべて処理できると確信しています。自分の認知制限に気付かないことは非常に一般的な現象です。これが、コード編成のベストプラクティスが非常に重要である(そしてしばしば無視される)理由です。

繰り返しますが、インターフェースとAPIの障壁は、あなたが自分自身だけに協力している場合でも、大部分は良好です。外部ライブラリについては、よく考え抜かれたAPIが提供されていれば、そのライブラリを別のライブラリと交換する必要がないと予想される限り、問題なく使用できます。それ以外の場合は、ラッパーまたは腐敗防止レイヤーが非常に良いアイデアです。


SEの主な目的は、ソースコードを後で使用できるようにすることで、望ましい効果を達成することです。私はいつもきれいなコードを求めて戦っていた最後の仕事でそれをうまく表現できたらよかったのに!
メタファイト

APIの命名規則はありますか。それは、私があらゆる場所で使用することになります。たとえば、コマンドパターンを実行している場合、「コマンド可能」と呼びますか?
スヌープ

@StevieV例えば、様々ありますIBlahによって実装Blah、またはBlahによって実装BlahImpl。私は両方嫌い、および使用する傾向Blahによって実装OralBlahWrittenBlahまたはASLBlah。しかし、いつものように、一般的な標準よりも既存のコードベースと期待に準拠することが重要です。
キリアンフォス

4

単にインターフェイスにプログラミングするのではなく、テスト駆動開発/設計(TDD)を検討してください。

多くの人はTDDをテスト方法と考えていますが、実際にはテストを使用してコードの使用方法をテストに公開する設計アプローチです(最初は単体テストを使用しますが、統合テストを使用することもできます)。

インターフェイスへのプログラミングはツールセットの重要な武器ですが、ほとんどの場合と同様に、常に必要とは限らないため、常に適切なソリューション/手法/プラクティスではありません。必要なインターフェイスにプログラムする必要があります。

TDDを使用すると、そのようなインターフェイスが重要であり、率直に言って重要ではない場所を探索する必要があります。そして最後に、コードベース全体でかなり良いユニットテストのセットが必要です。

サードパーティのライブラリの使用に関しては、必要に応じて独自の抽象化でそれらをラップすることを強くお勧めします。APIのクライアントにそれらを「知らせ」ないでください。

幸運を!

[編集:メガフライトの答えを見た-完全に同意する]


2
TDDは暗黙的に、実装ではなくインターフェイスの観点から考えていますが、正式な「インターフェイス」宣言ではない場合があります。
ダグ

1
これは素晴らしい答えです。TDDを提案するための+1。これは、OPの新しいプロジェクトで作業する際にどこから始めるべきかという本当の問題の解決策であると思います。重要であり、率直に言って、重要ではありません。」
ベンジャミンホジソン

2

やり過ぎだと思います。APIのユーザーが特定の方法で何かを実装/使用することを強制される必要がない場合は、除外します。インターフェイスはコントラクトです。必要ないのであれば、なぜそれを提供するのですか?

人々はインターフェースを使いすぎると思います。ほとんどの場合は不要な複雑さのレイヤーを追加しています。


インターフェース使用している人はいると思います。再利用可能なピースを作成する場合、インターフェースは「素敵な」追加だけでなく、大事なことでもあります。もちろん実際の実装に加えて。
JensG

1

契約に対するプログラミングは、ほとんどの場合、良いアイデアです。そのコントラクトはインターフェイスである必要はなく、代わりにクラスによって実現できます。私の意見では、ユニットテストの問題とフレームワークのモックのために、インターフェイスはDIとともに多少使い古されています。

個人的には、複数の契約を実装できる可能性がある場合、または実装する可能性が高い場合にのみ、インターフェイスを導入することを好みます。インターフェイスは、データアクセスを抽象化したいリポジトリには最適ですが、比較的柔軟性が低いと思われる標準的なビジネスロジックにはそれほど適していません。

現在、インターフェイスがないと、特に純粋主義者にとって、ユニットテストで問題が発生する可能性があります。しかし、内部の依存関係ではなく、プログラムの外部の依存関係を模倣することに興味があります。コード構造をエコーするのではなく、テストでコードの検証を実行する必要があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.