以下の疑似コードで? 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
がありますが、他の問題を特定できませんか?
ISPが壊れているかどうかは、クライアントが必要とするインターフェースの部分に依存します。
例のようにクライアントが1つだけで、すべてのインターフェイスメソッドが必要な場合、これはISP違反ではありません。
さらに、色が「不明確」であることは完全に意味があります。これは、魚などのペットの戻り値となる可能性があります。これは、物事をシンプルに保つための有効な設計決定であり、SOLID原則に違反しません。
クラスcat
にspecies
のインスタンスフィールドがあるのはなぜですか?定義上、すべての猫は同じ種です。
あなたが言うように、すべてのペットが毛皮を持っているわけではないので、fur_color
はi_pet
に場所がありません。しかし、それはISPの問題ではありません、それはさらに悪いことです-メソッドは、ほとんどのクライアントが必要とする以上のものではありません、それは積極的ですwrongこれは、サブクラスなどに適している場合とそうでない場合があるためです。
はい、そうです。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の余分なインターフェースを空として削除します。また、これらの関数をプロパティに変更します(無力ではありませんが、良い習慣です)。 関数とプロパティの違いはこちらをご覧ください の違いについての詳細:
ここでは、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_printer
はparrots
が存在するかどうかを知る必要がなくなりました。
私は、ペットプリンターにペットについてほとんど知らせず、印刷方法に集中できるように、コンソール、ログ、紙、画面などの設計に努めます。
そうすれば、pet_printer
は毛皮が何であるかを知らないため、ISPの原則の問題は解決されます。サブタイプは、どの詳細を印刷する必要があるか尋ねられたときに、毛皮について何か言うかどうかを決定します。
SOLIDを真空でフォローしないでください。SOLID原則は古い原則の裏にあります。それらがなければSOLIDちょっぴり響く単語を綴ることが起こる多くの無意味な混乱です。
ISPに違反していますが、アウトオブプレース方式のため、それほどではありません。
ISPの背後にある考え方は、インターフェイスを小さく保つことです。つまり、実際には、1つの動作上の側面のみを定義する必要があります。これは、ICatとIFishの両方が最適ではなく、ISPの観点からは無意味であることを意味します。
ICatの代わりに、IScratcher、IJumper、IMeatEaterなどのインターフェースを用意し、それらをCatに実装する必要があります。
IFishの代わりに、ISwimmerとIUnderwaterBreatherが必要です。
書かれているように、あなたは Liskov置換原理 と インターフェース分離原理 を破っています。 i_petを実装するものは、何も壊すことなく置換できる必要があります。 fishクラスが原因で、get_fur_color()が実装されていないために失敗します。さらに、pet_printerは オープンクローズの原則を破っています ここでの問題は、fishまたはcatの印刷名が変更された場合、この無関係なクラスも変更される必要があることです。犬が追加された場合は、再度変更する必要があります。 i_catの空のインターフェースは、 [〜#〜] yagni [〜#〜] 原則の違反の例であり、これはさらに問題を引き起こす可能性がありますインターフェースが単純に実装または変更されている場合。
最初の問題の修正は、メソッド名をgetColor()に変更するのと同じくらい簡単かもしれません。これはより一般的で、あらゆるペットで機能します。カラークラスは、その部分が関連する場合のプライマリおよびセカンダリカラーの処理方法を担当します。ペットプリンタークラスの問題を解決するために、タイプは、getType()メソッドによって簡単に返されるi_petインターフェースの一部である読み取り専用の文字列になることができます。これは、オープンクローズの原則の問題を解決するのに役立つだけでなく、各オブジェクトが外部オブジェクトに問い合わせてその情報に基づいて動作するのではなく、独自の型を伝えるようになるので、tell do n't askに従います。