tag:blogger.com,1999:blog-22587889.post7081930481177872827..comments2024-02-11T13:21:47.930+05:30Comments on Ruminations of a Programmer: Domain Classes or Interfaces ?Anonymoushttp://www.blogger.com/profile/01613713587074301135noreply@blogger.comBlogger11125tag:blogger.com,1999:blog-22587889.post-90745186028041889712007-06-18T20:40:00.000+05:302007-06-18T20:40:00.000+05:30I guess it depends on the way you use rules. When ...I guess it depends on the way you use rules. When we evaluate them we tend to do it for an entire aggregate, so you get 0+ broken rules. In that case if you try to do something that broken rules won't allow we raise a bog standard validation exception and attach the broken rules.<BR/><BR/>An example blog entry on the topic might be interesting :)Colin Jackhttps://www.blogger.com/profile/01403166737046938219noreply@blogger.comtag:blogger.com,1999:blog-22587889.post-1355510524003661232007-06-14T10:23:00.000+05:302007-06-14T10:23:00.000+05:30@Colin:I have to disagree with you on the exceptio...<I>@Colin:</I><BR/>I have to disagree with you on the exception part. My feeling is that exceptions *should* be part of the domain language, along with the rules.<BR/><BR/>And Cedric's blog is here : http://beust.com/weblog.Anonymoushttps://www.blogger.com/profile/01613713587074301135noreply@blogger.comtag:blogger.com,1999:blog-22587889.post-12999272081351596832007-06-13T22:06:00.000+05:302007-06-13T22:06:00.000+05:30Good post, I agree with almost all of it. In my vi...Good post, I agree with almost all of it. <BR/><BR/>In my view people often talk about using interfaces in the domain when there will only actually be one implementation, to me thats a poor design.<BR/><BR/>I also don't see the exceptions are part of the domain language, instead I see the associated rules as being part of the domain language. So for me the rule name should become part of the domain language but the exceptions do not have to be, its the rules that matter to me when discussing things with the domain experts.<BR/><BR/>By the way where can I find Cedrics blog, his blogger profile is not available.Colin Jackhttps://www.blogger.com/profile/01403166737046938219noreply@blogger.comtag:blogger.com,1999:blog-22587889.post-39515108556071779822006-11-01T16:28:00.000+05:302006-11-01T16:28:00.000+05:30Hi Debasish,
nice to see the discussion continuin...Hi Debasish,<br /><br />nice to see the discussion continuing on blogs.<br /><br />I fully agree with Cedric's point:<br /><br /><i>Using concrete classes (even abstract ones) is a worse solution to the problem that the I*2 approach, because it ties you to an implementation, no matter how thin. Before you know it, your clients will be relying on subtle side-effects and undocumented behaviors of your code, and it will make future evolution much harder than if you had used interfaces from the start.</i><br /><br />Other than this, I'd like to say that in any way I don't like the I*2 approach in domain models, because domain model interfaces are not the same as service provider interfaces or alike: domain model interfaces are mostly used/implemented in the context of the same business application, so every change to the published interface can be better supported through refactoring.<br />Obviously, if domain model interfaces were used in unknown contexts, that would be a problem.<br /><br />Just my two cents.<br /><br />Cheers!<br /><br />Sergio B.Sergio Bossahttps://www.blogger.com/profile/09315991044338298083noreply@blogger.comtag:blogger.com,1999:blog-22587889.post-28004131282040205912006-11-01T14:46:00.000+05:302006-11-01T14:46:00.000+05:30I'd stick with interfaces and complement the API w...I'd stick with interfaces and complement the API with a set of tests to verify documented required conditions. You'd still be left at the mercy of the implementors, but that's not easy to get out of!Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-22587889.post-19670732863256699402006-11-01T10:35:00.000+05:302006-11-01T10:35:00.000+05:30[for rjae :]
Hi Rjae -
Intention revealing except...<i>[for rjae :]</i><br />Hi Rjae -<br /><br />Intention revealing exceptions are definitely part of intention revealing interfaces, as Erik Evans has said it. And, they also should be coming from the ubiquitous language. In the example that I have posted, InvalidValueDateException is one such artifact.<br /><br />The strategy that I usually follow is to have the base class InvalidValueDateException in the throws clause of the api and have derived classes like ValueDateLessThanTradeDateException (extending InvalidValueDateException) or ValueDateNotBusinessDateException thrown from within the method for specific cases. All child exceptions that may get thrown are documented with the Javadoc. However, in the example which I posted, my focus was a bit different and hence the exception handling part did not get adequate focus.<br /><br />But, yes, I agree with u that all exceptions should be intention revealing.Anonymoushttps://www.blogger.com/profile/01613713587074301135noreply@blogger.comtag:blogger.com,1999:blog-22587889.post-69543858157519882132006-11-01T09:53:00.000+05:302006-11-01T09:53:00.000+05:30[for cedric :]
Hi Cedric -
My entire post is rela...<i>[for cedric :]</i><br />Hi Cedric -<br /><br />My entire post is related to domain level abstractions and not exactly for api design at large. My point is that domain level abstractions *should be* tied to global domain level constraints as well. And we cannot express this using Java pure interfaces. In the example that I posted, the value-date calculated must honor the post-conditions that have been checked in the abstract class. Hence, instead of every implementer of a pure interface, implementing the same constraints (violation of DRY), why not mandate it in the skeleton implementation.<br /><br />For cases where such constraints are not there, which I find mostly for SPIs and service layer APIs, pure interfaces are great - they allow easy mocking. But for behavior rich domain objects, doesn't it make sense to tie the implementers to the global constraints ?<br /><br />Your thoughts please ..Anonymoushttps://www.blogger.com/profile/01613713587074301135noreply@blogger.comtag:blogger.com,1999:blog-22587889.post-89030454431374921262006-11-01T02:19:00.000+05:302006-11-01T02:19:00.000+05:30Great topic. You have laid out the issues well - i...Great topic. You have laid out the issues well - in a manner that is thought provoking. Thank you.<br /><br />I believe I may extend the discussion on <a href="http://applanet.com/">my blog</a>. My immmediate thought comparing IValueDateCalculator to ValueDateCalculator is why not use intention-revealing-exceptions. Your example is adding nothing more than the following definition would:<br /><br />interface IValueDateCalculator {<br /> Date calculateValueDate(final Date tradeDate)<br /> throws BusinessDateNotBeforeTradeDateException;}<br /><br />My next thought was that tests reveal intentions of this sort. When reviewing a new package I look at the test assertions.<br /><br />These are my immediate thoughts. I am curious what you think.Rjae Eastonhttps://www.blogger.com/profile/14442336821503943018noreply@blogger.comtag:blogger.com,1999:blog-22587889.post-10130883134055196112006-10-31T23:51:00.000+05:302006-10-31T23:51:00.000+05:30Hi Debasish, and thanks for the kind words.
Using...Hi Debasish, and thanks for the kind words.<br /><br />Using concrete classes (even abstract ones) is a worse solution to the problem that the I*2 approach, because it ties you to an implementation, no matter how thin. Before you know it, your clients will be relying on subtle side-effects and undocumented behaviors of your code, and it will make future evolution much harder than if you had used interfaces from the start.<br /><br />I would also argue that instanceof is only evil when polymorphism could be used in its place, which is not the case when you are trying to have two different versions of an API co-exist in a client. instanceof looks perfectly reasonable to me in this case.Cedrichttps://www.blogger.com/profile/13274064962794267826noreply@blogger.comtag:blogger.com,1999:blog-22587889.post-24947537982732337192006-10-31T22:39:00.000+05:302006-10-31T22:39:00.000+05:30Hi Cedric -
Before going into any debate, let me ...Hi Cedric -<br /><br />Before going into any debate, let me acknowledge the fact that I am a regular reader of your blog and I enjoy every bit of it. We have also been using TestNG with great success for the last one year or so. <br /><br />Now to the point that u have made. I have mentioned that I*2 is being used in Eclipse and it does not need a certificate by me to bring home the fact that it has been used successfully. By mentioning that it does not scale, what I meant was that in the face of an evolutionary model, very soon we may reach I*4 or I*5 and the client code getting littered with multiple checks of *instanceof*. In case of Eclipse, I know that api design is being controlled extremely well and with utmost care - it is not so in the run-of-the-mill enterprise projects that get kicked off every now and then. And the alternative ? I think abstract classes provide a better scalability and evolutionability (in the sense that u can plug in a default implementation). This is purely from my personal experience - I am open to suggestions on the contrary as I have mentioned in the post requesting for suggestions from the experts.Anonymoushttps://www.blogger.com/profile/01613713587074301135noreply@blogger.comtag:blogger.com,1999:blog-22587889.post-87443742194086653462006-10-31T19:57:00.000+05:302006-10-31T19:57:00.000+05:30Hi Debashih,
You say that the I2 approach doesn't...Hi Debashih,<br /><br />You say that the I2 approach doesn't scale, but you fail to provide an alternative and you conveniently leave out the fact that this approach has been used successfully in many very popular API's (among which Eclipse, Win32 and even the JDK), some of which allow to run code that was written more than ten years ago.<br /><br />To my knowledge, I2 is the only way to correctly address the immutability of your API's and therefore, to guarantee the longevity of your code.Cedrichttps://www.blogger.com/profile/13274064962794267826noreply@blogger.com