4

Ok。OOのいくつかの側面とライブラリの設計に関していくつか質問があります。

  1. ライブラリは自給自足である必要がありますか?たとえば、外部の依存性注入フレームワークを使用できますか、それとも、より軽量な方法で独自に実装する必要がありますか?

  2. リスコフの置換原則は、メソッドまたはクラスの動作がわからないポリモーフィズムにどのように適合しますか?あなたはそれが期待通りに機能することを期待していますか?

  3. ソースコードの部分で、悪い習慣は、インターフェースを/interfacesそれらの実装から分離されたフォルダー(例えば)に保持しますか?

  4. where T : typeまた、実装だけでなく、インターフェイスのジェネリック型()を区切るのも悪い習慣ですか?(これは私はそうは思いませんが、それを確認するだけです)。

  5. オブジェクトの関係が「できる」と「ある」の両方であり、メソッドなどのデフォルトの実装が必要ない場合、インターフェースは抽象クラスよりも有利ですか?

それでおしまい。お時間をいただきありがとうございます=)

4

5 に答える 5

3

1.図書館は自給自足である必要がありますか?

ライブラリは、たとえば、依存性注入フレームワークを確実に使用できます。ただし、ライブラリのユーザーにDIフレームワークを強制するかどうかは議論の余地があります。

2.リスコフの置換原則はポリモーフィズムにどのように適合しますか?

Liskovの置換原則は、ある実装を別の実装と交換できるようにすること(置換)であり、動作に関係なく、ユーザーが契約を順守するときにエラーが発生することはありません。たとえば、をaに交換するCanonPrinterと、クラスEpsonPrinterのメソッドのみを使用する場合でも印刷できるはずです。Printer何かを呼び出すPrinterが、その基礎となる特定の実装(Canon、Epson)を持つことは、ポリモーフィズムです。

3.インターフェースを実装とは別のフォルダーに保持するのは悪い習慣ですか?

インターフェースを実装から切り離したいかどうかは個人的な好みです。私はそれをしません。実装ごとのインターフェースすらありません。プロジェクトに付加価値を与える場合にのみ、実装用のインターフェースを用意することは理にかなっていると思います。

4.実装だけでなく、インターフェイスのジェネリック型を制限することも悪い習慣ですか?

ジェネリック型を特定の型に限定する必要があると思われる場合は、それが理にかなっている場所で行う必要があります(したがって、これはインターフェイス上にある可能性があります)。たとえば、オブジェクトにIPrintableDocument<TPrinter>限定TPrinterせずにを設定しても意味がないので、そうします。Printer

5.オブジェクトの関係が「できる」と「ある」の両方である場合、インターフェースは抽象クラスよりも有利ですか?

実際、ほとんどの人は抽象クラスを使用、インターフェースは関係を実行できます。理由:クラスは1つの基本クラスからのみ継承できますが、複数のインターフェースから継承できます。本質的に、これは、クラス1つのもの(aEmployee Person)である可能性がありますICopyDocumentsが、複数のこと(、、、である可能性がIWalkAboutあります)を実行できることを意味しIMakeCoffeeます。インターフェースが両方であるときに何をするかは、好みによって異なります。


質問のほとんどは、クラス(またはインターフェイス)のコントラクトに関係しています。コントラクトは、ユーザー(別のクラス、他の誰かのコード)がクラスとそのメンバーに対して実行できること実行できないことを指定し、ユーザーが何を実行するかを指定します。クラスが実行することと実行しないことを期待する場合があります

例:ユーザー、オブジェクトがパラメータータイプと一致する場合にのみ、オブジェクトを引数としてメソッドに渡すことができます。クラス、戻り型に一致する戻り値としてオブジェクトのみを返します。ユーザーはクラスで定義されたメンバーのみを呼び出すことができ、クラスそれらのメソッドがコントラクトに従って動作することを確認します(つまり、エラーをスローせず、副作用がなく、nullを返さない)。

ジェネリック型の制約も契約の一部です。コントラクトのドキュメント部分も考慮します。メソッド例外をスローしないと記載されている場合、実装は例外をスローしてはなりません。それを強制する構文やコンパイラ規則はありませんが、それは契約の一部です。コントラクトの一部はコンパイラーまたはランタイムによって強制されますが、そうでない部分もあります。

クラスまたはインターフェースに特定のコントラクトがある場合、任意のサブクラスまたは実装をその代わりに使用でき、そのサブクラスまたは実装がコントラクトに準拠している場合でも機能します。それが契約に準拠している場合、それはリスコフの置換原則(LSP)です。そして、それから逸脱するのは簡単であり、多くのプログラマーはそうします。時々あなたは選択の余地がありません。

.NET FrameworkでのLSP違反の明確な例は、ReadOnlyCollection<T>クラスです。インターフェイスを実装しIList<T>ますが、多くのメソッドの実際の実装はありません。したがって、IList<T>aReadOnlyCollection<T>を期待しているユーザーを渡し、そのユーザーがを呼び出そうとするとlist.Add、例外がスローされます。したがって、常に代わりに使用できるとは限らないIList<T>ためReadOnlyCollection<T>、LSPに違反します。

于 2012-08-02T19:29:09.980 に答える
1

私はこれらに順番に答えようとします:

  1. 場合によります。外部の依存関係を利用すると、ライブラリの有用性と範囲が制限される可能性があります。これは、その依存関係が利用可能な状況でのみ使用できるためです。ただし、これは問題ない場合があり、依存関係を回避しようとするよりも優先されます。ライブラリのユーザーが常に特定のDIフレームワークを使用していることがわかっている場合は、機能するために「適応」が必要なものを実装するのではなく、その周りにライブラリを構築します。

  2. 「メソッドやクラスの動作がわからない場合は?」使用しているタイプの契約を知っておく必要があります。LSPは基本的に、どのような具体的なタイプを取得しても、基本クラス/インターフェイスコントラクトは常に有効であると言っています。これは、「タイプを使用」して、それが機能することを期待できることを意味します。

  3. いいえ-しかし、これは非公開の実装の詳細です。通常、名前空間を分離することはお勧めできませんが、ソースコードツリーを名前空間と一致させておくとよい場合がよくあります。

  4. いいえ。インターフェースが実際に特定のタイプでのみ使用されることを意図している場合は、インターフェースに制約があるはずです。

  5. 一般に、単一の契約は、関係の1つの側面のみを提供する必要があります。コントラクトが「is-a」「can-do」を示唆している場合は、おそらく「can-do」インターフェースを実装する抽象クラスの2つのコントラクトに分割する必要があります。

于 2012-08-02T19:26:10.847 に答える
0
  1. "場合によります"。しかし、特にDIやORMのように人口の多い(そして実装が難しい)領域では、独自のホイールを再発明することにはほとんど価値がありません。特に、(a)依存関係をbin展開するか、(b)ライブラリがnugetパッケージの場合は、依存関係をnugetパッケージとして指定できる場合(もちろんそうあるべきです)

  2. LSPはポリモーフィズムとはほとんど関係がありません。クラス(またはメソッド)はコントラクトに従って動作する必要があると記載されています。実際、実装者の動作について知っているのはそれだけです。

  3. フォルダは名前空間に対応している必要があります。インターフェイスを別の名前空間に配置しますか?私はそうしません、そして私は誰もそうすべきではないと思います。そして、私が1つの実装のみとのインターフェースを持っている場合(例えば、単体テストによって引き起こされる)、私はその実装とともに1つのファイルにとどまるのを好みます。

  4. いいえ、ちがいます。なぜそうなのか?

  5. デフォルトの実装が必要ない場合は、インターフェースを入手してください。インターフェイスは、実装の継承を台無しにしないため、モックが簡単で、実装も簡単です。IAuthentication実際、1つのクラスに複数のインターフェースを実装することもできますが、それが何らかの形で意図を強調している場合(たとえば、セキュリティを扱う特定のサービスがある場合、との両方を実装することは珍しくありませんIAuthorization)。最近、私は抽象クラスが明らかに必要な場合にのみ抽象クラスを選択します。

于 2012-08-02T19:40:49.487 に答える
0

5時に刺します。

抽象クラスとインターフェースの唯一の違いは、抽象クラスがクラス変数を持つことができるということです。抽象クラスが仮想メソッドのみで構成されている場合は、インターフェイスを選択します。

于 2012-08-02T19:25:45.637 に答える
0

#1- http://jeviathon.com/2012/03/05/roll-your-own-syndrome/

基本的に、要点は、誰かが同じことを行う堅牢でテスト済みのサポートされているソフトウェアをすでに作成している可能性があるのに、なぜ「独自の」xyzフレームワークを作成するのかということです。

車輪の再発明ではなく、使用する「適切な」外部ライブラリとフレームワークを選択するための調査に時間を費やしてください。

于 2012-08-02T19:40:07.063 に答える