<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://devlicio.us/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Krzysztof Kozmic : c#</title><link>http://devlicio.us/blogs/krzysztof_kozmic/archive/tags/c_2300_/default.aspx</link><description>Tags: c#</description><dc:language>en</dc:language><generator>CommunityServer 2008.5 SP1 (Build: 31106.3070)</generator><item><title>To constructor or to property dependency?</title><link>http://devlicio.us/blogs/krzysztof_kozmic/archive/2012/09/05/to-constructor-or-to-property-dependency.aspx</link><pubDate>Wed, 05 Sep 2012 12:32:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:70305</guid><dc:creator>Krzysztof Koźmic</dc:creator><slash:comments>10</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://devlicio.us/blogs/krzysztof_kozmic/rsscomments.aspx?PostID=70305</wfw:commentRss><comments>http://devlicio.us/blogs/krzysztof_kozmic/archive/2012/09/05/to-constructor-or-to-property-dependency.aspx#comments</comments><description>&lt;p&gt;Us, devel&amp;shy;op&amp;shy;ers, are a bit like that comic strip (&lt;a href="http://xkcd.com/1095/"&gt;from always great xkcd&lt;/a&gt;):&lt;/p&gt;
&lt;p&gt;&lt;img alt="Crazy Straws" src="http://imgs.xkcd.com/comics/crazy_straws.png" title="The new crowd is heavily shaped by this guy named Eric, who&amp;#39;s basically the Paris Hilton of the amateur plastic crazy straw design world." /&gt;&lt;/p&gt;
&lt;p&gt;We can end&amp;shy;lessly debate over tabs ver&amp;shy;sus spaces (don&amp;#39;t even get me started), whether to use optional semi&amp;shy;colon or not, and other seem&amp;shy;ingly irrel&amp;shy;e&amp;shy;vant top&amp;shy;ics. We can have heated, informed debates with a lot of merit, or (much more often) not very con&amp;shy;struc&amp;shy;tive exchanges of opinions.&lt;/p&gt;
&lt;p&gt;I men&amp;shy;tion that to explic&amp;shy;itly point out, while this post might be per&amp;shy;ceived as one of such dis&amp;shy;cus&amp;shy;sions, the goal of it is not to be a flame&amp;shy;war bait, but to share some experience.&lt;/p&gt;
&lt;p&gt;So hav&amp;shy;ing said that, let&amp;#39;s cut to the chase.&lt;/p&gt;
&lt;h3&gt;Depen&amp;shy;den&amp;shy;cies, mechan&amp;shy;ics and semantics&lt;/h3&gt;
&lt;p&gt;Writ&amp;shy;ing soft&amp;shy;ware in an object ori&amp;shy;ented lan&amp;shy;guage, like C#, fol&amp;shy;low&amp;shy;ing estab&amp;shy;lished prac&amp;shy;tices (&lt;span class="caps"&gt;SOLID&lt;/span&gt; etc) we tend to end up with many types, con&amp;shy;cen&amp;shy;trated on doing one thing, and del&amp;shy;e&amp;shy;gat&amp;shy;ing the rest to others.&lt;/p&gt;
&lt;p&gt;Let&amp;#39;s take an arti&amp;shy;fi&amp;shy;cial exam&amp;shy;ple of a class that is sup&amp;shy;posed to han&amp;shy;dle sce&amp;shy;nario where a user moved and we need to update their address.&lt;/p&gt;
&lt;pre class="brush: csharp; title: ; notranslate"&gt;public class UserService: IUserService
{
   // some other members

   public void UserMoved(UserMovedCommand command)
   {
      var user = session.Get&amp;lt;User&amp;gt;(command.UserId);

      logger.Info(&amp;quot;Updating address for user {0} from {1} to {2}&amp;quot;, user.Id, user.Address, command.Address);

      user.UpdateAddress(command.Address);

      bus.Publish(new UserAddressUpdated(user.Id, user.Address));
   }
}
&lt;/pre&gt;
&lt;p&gt;There are four lines of code in this method, and three dif&amp;shy;fer&amp;shy;ent depen&amp;shy;den&amp;shy;cies are in use: ses&amp;shy;sion, log&amp;shy;ger and bus. As an author of this code, you have a few options of sup&amp;shy;ply&amp;shy;ing those depen&amp;shy;den&amp;shy;cies, two of which that we&amp;#39;re going to con&amp;shy;cen&amp;shy;trate on (and by far the most pop&amp;shy;u&amp;shy;lar) are con&amp;shy;struc&amp;shy;tor depen&amp;shy;den&amp;shy;cies and prop&amp;shy;erty dependencies.&lt;/p&gt;
&lt;h3&gt;Tra&amp;shy;di&amp;shy;tional school of thought&lt;/h3&gt;
&lt;p&gt;Tra&amp;shy;di&amp;shy;tional approach to that prob&amp;shy;lem among C# devel&amp;shy;op&amp;shy;ers goes some&amp;shy;thing like this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Use con&amp;shy;struc&amp;shy;tor for required depen&amp;shy;den&amp;shy;cies and prop&amp;shy;er&amp;shy;ties for optional dependencies.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This option is by far the most pop&amp;shy;u&amp;shy;lar and I used to fol&amp;shy;low it myself for a long time. Recently how&amp;shy;ever, at first uncon&amp;shy;sciously, I moved away from it.&lt;/p&gt;
&lt;p&gt;While in the&amp;shy;ory it&amp;#39;s a neat, arbi&amp;shy;trary rule that&amp;#39;s easy to fol&amp;shy;low, in prac&amp;shy;tice I found it is based on a flawed premise. The premise is this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;By look&amp;shy;ing at the class&amp;#39; con&amp;shy;struc&amp;shy;tor and prop&amp;shy;er&amp;shy;ties you will be able to eas&amp;shy;ily see the min&amp;shy;i&amp;shy;mal set of required depen&amp;shy;den&amp;shy;cies (those that go into the con&amp;shy;struc&amp;shy;tor) and optional set that can be sup&amp;shy;plied, but the class doesn&amp;#39;t require them (those are exposed as properties).&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Fol&amp;shy;low&amp;shy;ing the rule we might build our class like that:&lt;/p&gt;
&lt;pre class="brush: csharp; title: ; notranslate"&gt;public class UserService: IUserService
{
   // some other members

   public UserService(ISession session, IBus bus)
   {
      //the obvious
   }

   public ILogger Logger {get; set;}
}
&lt;/pre&gt;
&lt;p&gt;This assumes that ses&amp;shy;sion and bus are required and log&amp;shy;ger is not (usu&amp;shy;ally it would be ini&amp;shy;tialised to some sort of NullLogger).&lt;/p&gt;
&lt;p&gt;In prac&amp;shy;tice I noticed a few things that make use&amp;shy;ful&amp;shy;ness of this rule questionable:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It ignores con&amp;shy;struc&amp;shy;tor over&amp;shy;loads. If I have another con&amp;shy;struc&amp;shy;tor that takes just ses&amp;shy;sion does it mean bus is an optional or manda&amp;shy;tory depen&amp;shy;dency? Even with&amp;shy;out over&amp;shy;load&amp;shy;ing, in C# 4 or later, I can default my con&amp;shy;struc&amp;shy;tor para&amp;shy;me&amp;shy;ters to null. Does it make them required or mandatory?&lt;/li&gt;
&lt;li&gt;It ignores the fact that in real&amp;shy;ity I very rarely, if ever, have really optional depen&amp;shy;den&amp;shy;cies. Notice the first code sam&amp;shy;ple assumes all of its depen&amp;shy;den&amp;shy;cies, includ&amp;shy;ing log&amp;shy;ger, are not null. If it was truly optional, I should prob&amp;shy;a&amp;shy;bly pro&amp;shy;tect myself from Null&amp;shy;Ref&amp;shy;er&amp;shy;ence&amp;shy;Ex&amp;shy;cep&amp;shy;tions, and in the process com&amp;shy;pletely destroy read&amp;shy;abil&amp;shy;ity of the method, allow&amp;shy;ing it to grow in size for no real benefit.&lt;/li&gt;
&lt;li&gt;It ignores the fact that I will almost never con&amp;shy;struct instances of those classes myself, del&amp;shy;e&amp;shy;gat&amp;shy;ing this task to my IoC con&amp;shy;tainer. Most mature IoC con&amp;shy;tain&amp;shy;ers are able to han&amp;shy;dle con&amp;shy;struc&amp;shy;tor over&amp;shy;loads and defaulted con&amp;shy;struc&amp;shy;tor para&amp;shy;me&amp;shy;ters, as well as mak&amp;shy;ing prop&amp;shy;er&amp;shy;ties required, ren&amp;shy;der&amp;shy;ing the argu&amp;shy;ment about required ver&amp;shy;sus optional moot.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Another, more prac&amp;shy;ti&amp;shy;cal rule, is this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Use con&amp;shy;struc&amp;shy;tor for not-changing depen&amp;shy;den&amp;shy;cies and prop&amp;shy;er&amp;shy;ties for ones that can change dur&amp;shy;ing object&amp;#39;s lifetime.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In other words, ses&amp;shy;sion and bus would end up being pri&amp;shy;vate read&amp;shy;only fields &amp;mdash; the C# com&amp;shy;piler would enforce that once we set them (option&amp;shy;ally val&amp;shy;i&amp;shy;dat&amp;shy;ing them first) the fields in the con&amp;shy;struc&amp;shy;tor, we are guar&amp;shy;an&amp;shy;teed to be deal&amp;shy;ing with the same (cor&amp;shy;rect, not null) objects ever after. On the other hand, Log&amp;shy;ger is up in the air, since tech&amp;shy;ni&amp;shy;cally at any point in time some&amp;shy;one can swap it for a dif&amp;shy;fer&amp;shy;ent instance, or set it to null. There&amp;shy;fore, what usu&amp;shy;ally log&amp;shy;i&amp;shy;cally fol&amp;shy;lows from there, is that prop&amp;shy;erty depen&amp;shy;den&amp;shy;cies should be avoided and every&amp;shy;thing should go through the constructor.&lt;/p&gt;
&lt;p&gt;I used to be the fol&amp;shy;lower of this rule until quite recently, but then it does have its flaws as well.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It leads to some nasty code in sub&amp;shy;classes where the base class has depen&amp;shy;den&amp;shy;cies. One exam&amp;shy;ple I saw recently was a &lt;span class="caps"&gt;WPF&lt;/span&gt; view model base class with depen&amp;shy;dency on dis&amp;shy;patcher. Because of that every sin&amp;shy;gle (and there were many) view model inher&amp;shy;it&amp;shy;ing from it, needed to have a con&amp;shy;struc&amp;shy;tor declared that takes dis&amp;shy;patcher and passes it up to the base con&amp;shy;struc&amp;shy;tor. Now imag&amp;shy;ine what hap&amp;shy;pens when you find you need event aggre&amp;shy;ga&amp;shy;tor in every view model. You will need to alter every sin&amp;shy;gle view model class you have to add that, and that&amp;#39;s a refac&amp;shy;tor&amp;shy;ing ReSharper will not aid you with.&lt;/li&gt;
&lt;li&gt;It trusts the com&amp;shy;piler more than devel&amp;shy;op&amp;shy;ers. Just because a set&amp;shy;ter is pub&amp;shy;lic, doesn&amp;#39;t mean the devel&amp;shy;op&amp;shy;ers will write code set&amp;shy;ting it to some ran&amp;shy;dom val&amp;shy;ues all over the place. It is all a mat&amp;shy;ter of con&amp;shy;ven&amp;shy;tions used in your par&amp;shy;tic&amp;shy;u&amp;shy;lar team. On the team I&amp;#39;m cur&amp;shy;rently work&amp;shy;ing with the rule that every&amp;shy;body knows and fol&amp;shy;lows is we do not use prop&amp;shy;er&amp;shy;ties, even set&amp;shy;table ones, to reas&amp;shy;sign depen&amp;shy;den&amp;shy;cies, we&amp;#39;re using meth&amp;shy;ods for that. There&amp;shy;fore, based on the assump&amp;shy;tion that devel&amp;shy;op&amp;shy;ers can be trusted, when read&amp;shy;ing the code and see&amp;shy;ing a prop&amp;shy;erty I know it won&amp;#39;t be used to change state, so read&amp;shy;abil&amp;shy;ity and imme&amp;shy;di&amp;shy;ate under&amp;shy;stand&amp;shy;ing of the code does not suffer.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In real&amp;shy;ity, I don&amp;#39;t actu&amp;shy;ally think the cur&amp;shy;rent one, or few of my last projects had even a require&amp;shy;ment to swap ser&amp;shy;vice depen&amp;shy;den&amp;shy;cies. Gen&amp;shy;er&amp;shy;ally you will direct your depen&amp;shy;dency graphs from more to less volatile objects (that is object will depend on objects with equal or longer lifes&amp;shy;pan). In few cases where that&amp;#39;s not the case the depen&amp;shy;den&amp;shy;cies would be pulled from a fac&amp;shy;tory, and used only within the scope of a sin&amp;shy;gle method, there&amp;shy;fore not being avail&amp;shy;able to the out&amp;shy;side world. The only sce&amp;shy;nario where a long-lived depen&amp;shy;dency would be swapped that I can think of, is some sort of failover or circuit-breaker, but then again, that would be likely dealt with inter&amp;shy;nally, inside the component.&lt;/p&gt;
&lt;p&gt;So, look&amp;shy;ing back at the code I tend to write, all depen&amp;shy;den&amp;shy;cies tend to be manda&amp;shy;tory, and all of them tend to not change after the object has been created.&lt;/p&gt;
&lt;h3&gt;What then?&lt;/h3&gt;
&lt;p&gt;This robs the afore&amp;shy;men&amp;shy;tioned approaches from their adver&amp;shy;tised ben&amp;shy;e&amp;shy;fits. As such I tend to draw the divi&amp;shy;sion along dif&amp;shy;fer&amp;shy;ent lines. It does work for me quite well so far, and in my mind, offers a few ben&amp;shy;e&amp;shy;fits. The rule I fol&amp;shy;low these days can be explained as follows:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Use con&amp;shy;struc&amp;shy;tor for application-level depen&amp;shy;den&amp;shy;cies and prop&amp;shy;er&amp;shy;ties for infra&amp;shy;struc&amp;shy;ture or inte&amp;shy;gra&amp;shy;tion dependencies.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In other words, the depen&amp;shy;den&amp;shy;cies that are part of the essence of what the type is doing go into the con&amp;shy;struc&amp;shy;tor, and depen&amp;shy;den&amp;shy;cies that are part of the &amp;quot;back&amp;shy;ground&amp;quot; go via properties.&lt;/p&gt;
&lt;p&gt;Using our exam&amp;shy;ple from before, with this approach the ses&amp;shy;sion would come via con&amp;shy;struc&amp;shy;tor. It is part of the essence of what the class is doing, being used to obtain the very user whose address infor&amp;shy;ma&amp;shy;tion we want to update. Log&amp;shy;ging and pub&amp;shy;lish&amp;shy;ing the infor&amp;shy;ma&amp;shy;tion onto the bus are some&amp;shy;what less essen&amp;shy;tial to the task, being more of an infra&amp;shy;struc&amp;shy;ture con&amp;shy;cerns, there&amp;shy;fore bus and log&amp;shy;ger would be exposed as properties.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;This approach clearly puts dis&amp;shy;tinc&amp;shy;tion between what&amp;#39;s essen&amp;shy;tial, busi&amp;shy;ness logic, and what is book&amp;shy;keep&amp;shy;ing. Prop&amp;shy;er&amp;shy;ties and fields have dif&amp;shy;fer&amp;shy;ent nam&amp;shy;ing con&amp;shy;ven&amp;shy;tions, and (espe&amp;shy;cially with ReSharper&amp;#39;s &amp;#39;Color iden&amp;shy;ti&amp;shy;fiers&amp;#39; option) with my code colour&amp;shy;ing scheme have sig&amp;shy;nif&amp;shy;i&amp;shy;cantly dif&amp;shy;fer&amp;shy;ent colours. This makes is much eas&amp;shy;ier to find what really is impor&amp;shy;tant in code.&lt;/li&gt;
&lt;li&gt;Given the infra&amp;shy;struc&amp;shy;ture level depen&amp;shy;den&amp;shy;cies tend to be pushed up to base classes (like in the View&amp;shy;Model exam&amp;shy;ple with Dis&amp;shy;patcher and Even&amp;shy;tAg&amp;shy;gre&amp;shy;ga&amp;shy;tor) the inher&amp;shy;i&amp;shy;tors end up being leaner and more readable.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;In clos&amp;shy;ing&lt;/h3&gt;
&lt;p&gt;So there you have it. It may be less pure, but trades purity for read&amp;shy;abil&amp;shy;ity and reduces amount of boil&amp;shy;er&amp;shy;plate code, and that&amp;#39;s a trade&amp;shy;off I am happy to make.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicio.us/aggbug.aspx?PostID=70305" width="1" height="1"&gt;</description><category domain="http://devlicio.us/blogs/krzysztof_kozmic/archive/tags/Design/default.aspx">Design</category><category domain="http://devlicio.us/blogs/krzysztof_kozmic/archive/tags/c_2300_/default.aspx">c#</category></item></channel></rss>