web-dev-qa-db-ja.com

SOLID原則は、このコードで壊していますか?

以下の疑似コードで? SOLID原則を破っていますか?

interface i_pet
  string get_name()
  string get_species()
  color get_fur_color()
end interface

interface i_cat implements i_pet
end interface

interface i_fish implements i_pet
   bool get_is_fresh_water()
end interface

class cat implements i_cat
  string name
  string species
  color fur_color

  cat(string name, string species, color fur_color):
    this.name = name
    this.species = species
    this.fur_color = fur color

  string get_species():
    return species

  string get_name():
    return name

  color get_fur_color:
    return fur_color
end class

class fish implements i_fish
  string name
  string species
  bool is_fresh_water

  string get_species():
    return species

  string get_name():
    return name

  color get_fur_color():
    throw exception

  bool get_is_fresh_water():
    return is_fresh_water
end class

class pet_printer
  print_pet_name(i_pet pet):
    print pet.get_name()

  print_fur_color(i_pet pet):
    print pet.get_fur_color()

  print_pet_species(i_pet pet):
    print pet.get_species()

  print_pet_type(i_pet pet):
    switch type of pet:
      case i_fish:
        print "Fish";
      case i_cat:
        print "Cat";
      default:
        print "Unkown";
    end switch
end class

私はInterface segregation principleを壊していると思います。i_petにはget_fur_colorがありますが、他の問題を特定できませんか?

2
NoName

ISPが壊れているかどうかは、クライアントが必要とするインターフェースの部分に依存します

例のようにクライアントが1つだけで、すべてのインターフェイスメソッドが必要な場合、これはISP違反ではありません。

さらに、色が「不明確」であることは完全に意味があります。これは、魚などのペットの戻り値となる可能性があります。これは、物事をシンプルに保つための有効な設計決定であり、SOLID原則に違反しません。

1
Doc Brown
  • クラスcatspeciesのインスタンスフィールドがあるのはなぜですか?定義上、すべての猫は同じ種です。

  • あなたが言うように、すべてのペットが毛皮を持っているわけではないので、fur_colori_petに場所がありません。しかし、それはISPの問題ではありません、それはさらに悪いことです-メソッドは、ほとんどのクライアントが必要とする以上のものではありません、それは積極的ですwrongこれは、サブクラスなどに適している場合とそうでない場合があるためです。

2
Kilian Foth

はい、そうです。i_Petを実装するbirdの別のインターフェイスを作成するようなものですが、「color get_fur_color()」を使用します。

interface i_pet
  string get_name()
  string get_species()
end interface

interface i_bird implements i_pet
  color get_fur_color()
end interface

それ以外の場合、あなたがあなたの確固たる原則を破るなら、私は考えません。猫には「脊椎動物」の種があり、ペットには「XYZ」という名前があるので、すべてのペットには名前と種があります。

編集:catの余分なインターフェースを空として削除します。また、これらの関数をプロパティに変更します(無力ではありませんが、良い習慣です)。 関数とプロパティの違いはこちらをご覧ください の違いについての詳細:

1
Swati

ここでは、SOLIDとは関係のないかなりの数の原則が違反されています。 SOLIDはすべての有用な原理の包括的なリストではありません。ボブおじさん自身もSOLIDを超えて検討する価値のある原理を発表しています。

SOLID違反のみに焦点を当てたいが、その狭い視野がISPについて混乱を引き起こしていると述べた。

具体的には、唯一のクライアントでfur_colorを要求するのは理にかなっていますか:pet_printer

ここでの原理は抽象化です。 pet_printerクライアントには、印刷しているペットを正確に知らない権利がありますか?ここでペットタイプが重い仕事をすることを要求できますか?

抽象化はSOLID原則ではありませんが、それでも良い原則です。それをフォローしているのであれば、飼っているペットのタイプやpet_printerを知る必要はありません。はfur_colorを要求し、結果として「該当なし」になることがあります。この値は、質問を変更せずにすべてのペットが毛皮を持っているという仮定を拒否します。 このような値 は長い伝統がありますコンピュータサイエンスと数学の分野です。それが ゼロやネガティブのような数値 がある理由です。

そうすれば、すべてのペットのサブタイプが毛皮の色の質問に答えることができます。したがって、ファーカラーについて質問するクライアントは、サブタイプを知る必要はありません。

それでも満足できない場合は、クライアントが何をしているかを深く掘り下げる必要があります。ペットを印刷しようとしています。サブタイプについて質問しないとわからないサブタイプ固有の詳細を処理しようとしているため、混乱しています。

これを行うクライアントは、OOPの原則に違反しています。古いコードを変更せずに新しいタイプを簡単に追加できるはずです。これにより、SOLID原則がOpen Closedと呼ばれます原則(OCP)これは、古く、テスト済みで、実証済みのコードを変更して新しいものを追加しなければならないのはうんざりする、空想的な方法です。

pet_printerを変更せずにparrotsを追加できる設計が望ましいです。

これの最悪の違反はprint_pet_typeメソッドです。スイッチが悪だと言っているわけではありませんが、なぜ型階層を構築してからそれを使用しないのですか?各ペットにtypeメソッドを指定すると、スイッチが失敗する可能性があります。これでpet_printerparrotsが存在するかどうかを知る必要がなくなりました。

私は、ペットプリンターにペットについてほとんど知らせず、印刷方法に集中できるように、コンソール、ログ、紙、画面などの設計に努めます。

そうすれば、pet_printerは毛皮が何であるかを知らないため、ISPの原則の問題は解決されます。サブタイプは、どの詳細を印刷する必要があるか尋ねられたときに、毛皮について何か言うかどうかを決定します。

SOLIDを真空でフォローしないでください。SOLID原則は古い原則の裏にあります。それらがなければSOLIDちょっぴり響く単語を綴ることが起こる多くの無意味な混乱です。

1
candied_orange

ISPに違反していますが、アウトオブプレース方式のため、それほどではありません。

ISPの背後にある考え方は、インターフェイスを小さく保つことです。つまり、実際には、1つの動作上の側面のみを定義する必要があります。これは、ICatとIFishの両方が最適ではなく、ISPの観点からは無意味であることを意味します。

ICatの代わりに、IScratcher、IJumper、IMeatEaterなどのインターフェースを用意し、それらをCatに実装する必要があります。

IFishの代わりに、ISwimmerとIUnderwaterBreatherが必要です。

1
Martin Maat

書かれているように、あなたは Liskov置換原理インターフェース分離原理 を破っています。 i_petを実装するものは、何も壊すことなく置換できる必要があります。 fishクラスが原因で、get_fur_color()が実装されていないために失敗します。さらに、pet_printerは オープンクローズの原則を破っています ここでの問題は、fishまたはcatの印刷名が変更された場合、この無関係なクラスも変更される必要があることです。犬が追加された場合は、再度変更する必要があります。 i_catの空のインターフェースは、 [〜#〜] yagni [〜#〜] 原則の違反の例であり、これはさらに問題を引き起こす可能性がありますインターフェースが単純に実装または変更されている場合。

最初の問題の修正は、メソッド名をgetColor()に変更するのと同じくらい簡単かもしれません。これはより一般的で、あらゆるペットで機能します。カラークラスは、その部分が関連する場合のプライマリおよびセカンダリカラーの処理方法を担当します。ペットプリンタークラスの問題を解決するために、タイプは、getType()メソッドによって簡単に返されるi_petインターフェースの一部である読み取り専用の文字列になることができます。これは、オープンクローズの原則の問題を解決するのに役立つだけでなく、各オブジェクトが外部オブジェクトに問い合わせてその情報に基づいて動作するのではなく、独自の型を伝えるようになるので、tell do n't askに従います。

1
Ryathal