失礼します。今登録したばかりなので、
teratailの文化に馴染めていなかったらごめんなさい。
A,B,Cは独立した機能ですので、それぞれに継承関係は無いほうがいいです。
そして、恐らく質問はクラスの継承をどのようにしようかと悩んでいるのではなく、
どのクラスがどのクラスを使ったらよいかで悩んでいるのだと思います。
結論から言うと最後の
の構造が良いかと思います。
理由はわかっての通り「メールアドレスの管理のみを別立てのクラスに分離にすれば、UIでメールアドレス管理しやすい」からです。
「それはちょっと手間だなぁ」と思っているようですが、実行するのはコンピュータです。
コンピュータはそんな文句は言いません。
それよりも、人が手間だと思うことを考えましょう。
人間にとって手間なのは新しいアドレス管理クラスを追加したとき変更が色んな場所に波及することです。
例えばFacebookからメールアドレスを持ってくるようなクラスを追加したとしましょう。
下記のように簡単な修正で済みますし、もともとあったMailAddressクラスを変更しなくて済みます。
FacebookMailAddress address = new FacebookMailAddress();
address.Name = address.Search("宛先名");
SendMail sendmail = new SendMail();
sendmail.Send(address, "メール本文");
このとき、FacebookMailAddressはMailAddressを継承して実装すると良いです。
なぜならこの実装だとsendmail.Send(address, "メール本文");の引数addressの型が
FacebookMailAddressに変わってしまいます。
するとやはりSendMailの中も変更しないといけなくなります。
MailAddressを継承し、メソッドをオーバーライドすることで、この問題を解決できます。
コードはきっと下記のようになるでしょう。
MailAddress address = new FacebookMailAddress();
address.Name = address.Search("宛先名");
SendMail sendmail = new SendMail();
sendmail.Send(address, "メール本文");
しかし、これではMailAddressを変更したとき、FacebookMailAddressの動作が変わってしまうかもしれません。
予期しない箇所で動作が変わることも、人間にとってはとても手間なのです。
とくに私のような人間は忘れっぽいので、変更の影響が別の場所に出ると見逃してしまいます。
そこでMailAddressの実装は最小限のものにして、もともとあったMailAddressの機能は
MailAddressを継承した別のクラスに定義しましょう。
テキトーにOriginalMailAddressという名前にします。
するとクラスの継承関係は下記みたいなカンジになります
MailAddress-OriginalMailAddress
-FacebookMailAddress
このときMailAddressはインターフェースだけの抽象クラスとして定義することが一般的です。
例えばこんな感じ(C#書き慣れてないので間違ってたらすいません)
interface MailAddress{
String Search(String addressName);
}
このように実装することで、沢山のうれしいことがあります。
例えば下記のこんなかんじでそれぞれのMailAddressを使い分けるようにメソッドを定義できたりします
public void sendMailOriginalMailAddress(String addressName){
MailAddress address = new OriginalMailAddress();
sendmail.Send(address.Search(addressName));
}
public void sendMailFromFacebook(String addressName){
MailAddress address = new FacebookMailAddress();
sendmail.Send(address.Search(addressName));
}
public void sendMail(MailAddress address){
SendMail sendmail = new SendMail();
sendmail.Send(address, "メール本文");
}
なんかキレイになったと思いませんか?
流れを追って説明しましたが、これは
「依存性逆転の原則」というものを適用した流れです。
オブジェクト指向におけるクラス設計の原則で他にあと4つあります。
それぞれの頭文字を取って「SOLID原則」と呼ばれています。
ちなみにわたしの一番好きな原則も「依存性逆転の原則」です。
「抽象に依存せよ」っていうかっこいいフレーズがたまらないんです。
では、もう一つ私の好きな原則を紹介します。
「YAGNI原則」といいます。
You ain't gonna need it.
の略だそうです。直訳すると「そんなの必要ねーよっ」って意味だそうです。
wikipediaのわかりやすい説明では「機能は実際に必要となるまでは追加しないのがよい」ってなってます。
そうなんです。ここまで長く説明したんですけど、こういう設計がもたらす便利さが不要なら、
別にそんな設計しなくてもいいんです。
そのほうがコードは短くなるし、短いコードのほうがバグは発生しにくいんです。
だから、突き詰めて考えていったときに最終的にぶち当たるのは、
クラス設計の原則を当てはめるべきかどうか?というところなんです。
クラス設計には原則のようなルールがありますが、それはあくまで道具です。
これが正しいという答えは自分で判断するしか無いんです。
オブジェクト指向とかクラス設計とかそのへんは、いろんな原則があります。
紹介したキーワードで検索すると、いろんな話が出てきます。
例えば少し難しいですが「リファクタリング:オーム社」という本があります。
家庭の医学みたいに、良くないコードの見つけ方や直し方が書いてあります。
ご参考までに
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2017/08/27 23:36