そりゃ、「賢いデータは必要なのか」ってきかれたら必要と答えるしかないわけですが。
まあ早い話ケースバイケースとしか言いようがないわけで。
でも、今までの経験から行くと「データに振る舞いを持たせすぎ」て困ることは合っても「データと振る舞いを分離しすぎ」(いわゆるドメインモデル貧血症)で困ったことってあんまりないんですよね。
たとえば、ひがさんの日記や2chで出てくる44氏の例は明らかに「データに振る舞いを持たせすぎ」だとおもう(もっというとクラスに役割持もたせすぎ)。これはべつにオブジェクト指向か手続き型かとかじゃなくてふつうにオブジェクト指向で設計してもこうはならないよね。
public class Employee {
private PayCaluculator calculator;
...
public BigDecimal caluculatePay() {
return calculator.calculatePay(this);
}
}
だって現実問題、社員は自分の給料計算しないし。
まあ理由はhttp://pc8.2ch.net/test/read.cgi/tech/1102862221/172に書いたとおりなんだけど。
1.社員の情報だけじゃ給与計算なんて出来ん
勤怠情報とか、税金とか、手当てとか、あと成果主義の会社だったら
会社の業績とかが給与計算に必要なわけで、calculatePayを社員にもたすと
社員とその他もろもろのあいだに依存関係が出来る。
2.calculatePayを社員にもたすと給与計算の変更があるたびに社員クラスを変更しなければならない
そのときに社員クラスにバグを作りこまないという保証がない。
3.calculatePayは月給を計算するんだとして、ボーナスはどうするのか、出張旅費清算はどうするのか?
社員クラスにcalculateボーナスメソッドを持たすとして、会社の制度が変更になってボーナスがなくなったらどうすんの?
そしたらYAGNIだっていわれちゃった。でもドメインモデルを使う利点って変更に強いことなんじゃないの?
給与計算なんて超ホットスポットなんだからもうちょっと変更に強く作ってないと困ります。
自分ならこうするかな。
public class Employee {
getterとかsetterとか
}
public interface PayCaluculator{
public BigDecimal caluculatePay(Employee employee) {
}
でここでデータと振る舞いを分離してるけどこれでオブジェクト指向の利点が得られなくなったかというとそんなことはなくて、たとえば会社に従業員、契約社員、管理者がいてそれぞれ給与計算の方法が違うとしたら、
public class Employee {
getterとかsetterとか
public EmployeeType getEmployeeType();
}
public interface PayCaluculator{
public BigDecimal caluculatePay(Employee employee);
}
public class PayCaluculatorImpl implements PayCaluculator{
private Map payCaluculators = new HashMap();
public void addPayCaluculator(EmployeeType employeeType,PayCaluculator payCaluculator) {
payCaluculators.put(employeeType,payCaluculator);
}
public BigDecimal caluculatePay(Employee employee){
PayCaluculator payCaluculator =
(PayCaluculator) payCaluculators.get(employee.getEmployeeType());
return payCaluculator.caluculatePay(employee);
}
}
public class 従業員PayCaluculatorImpl implements PayCaluculator{
.....
}
とかしてDIすればオブジェクト指向の利点を十分利用できるわけです。しかも、たとえば給与計算するのにたとえば部門の情報が必要になってもEmployeeには一切手を加える必要はないですし。ボーナスの計算でも新しいPayCaluculatorの実装をつくるだけです。
あと
http://www.atmarkit.co.jp/fdotnet/bookpreview/codecomp2nd_06/codecomp2nd_06_01.html
の例なんだけど、これって「データに振る舞いを持たせる」って言っていいのか?
ほとんどsetterとgetterのみのJavaBeansのように感じるんですが。
もちろん上で言ったことはケースバイケースなわけで、たとえば誕生日と現在の日時から現在の年齢を計算するgetAge()なんてメソッドはもちろんEmployeeに入れるべきでしょう。
まあ結局何が言いたいかというと「データと振る舞いを分離しすぎ」なことに注意するべきなのと同様に、「データに振る舞いを持たせすぎ」にも注意が必要って事で。だとすると「データに振る舞いを持たせすぎ」なことにドメインモデル貧血症というなまえがついているように「データに振る舞いを持たせすぎ」なことにも名前を付けるべきじゃないでしょうか。ドメインモデル白血病とかかな。ちょっと不謹慎な気がしますが。なんかいい名前ないですかね。