<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:copyright="http://blogs.law.harvard.edu/tech/rss" xmlns:image="http://purl.org/rss/1.0/modules/image/">
    <channel>
        <title>Design</title>
        <link>http://ayende.com/Blog/category/504.aspx</link>
        <description>Design</description>
        <language>en-US</language>
        <copyright>Ayende Rahien</copyright>
        <managingEditor>Ayende@ayende.com</managingEditor>
        <generator>Subtext Version 1.9.3.51</generator>
        <item>
            <title>Patterns vs. Blueprints</title>
            <link>http://ayende.com/Blog/archive/2008/04/12/Patterns-vs.-Blueprints.aspx</link>
            <description>&lt;p&gt;Recently I had several discussions about the usage of patterns, and application thereof. Usually, there are recommended implementation for a pattern, often this is the way it is presented in its pattern catalog.&lt;/p&gt;  &lt;p&gt;The discussion had to do with the amount of fidelity that you had in implementing the pattern. My view on that is that the usage of a pattern doesn't require a one to one match with the common implementation, but leave room for change while keeping the concepts of the pattern in use.&lt;/p&gt;  &lt;p&gt;Patterns are the overall shape of the solution, they are not a blueprint, to be slavishly followed.&lt;/p&gt;&lt;img src="http://ayende.com/Blog/aggbug/10173.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Ayende Rahien</dc:creator>
            <guid>http://ayende.com/Blog/archive/2008/04/12/Patterns-vs.-Blueprints.aspx</guid>
            <pubDate>Sat, 12 Apr 2008 01:30:03 GMT</pubDate>
            <wfw:comment>http://ayende.com/Blog/comments/10173.aspx</wfw:comment>
            <comments>http://ayende.com/Blog/archive/2008/04/12/Patterns-vs.-Blueprints.aspx#feedback</comments>
            <slash:comments>1</slash:comments>
            <wfw:commentRss>http://ayende.com/Blog/comments/commentRss/10173.aspx</wfw:commentRss>
        </item>
        <item>
            <title>Request/Reply vs. Pub/Sub</title>
            <link>http://ayende.com/Blog/archive/2008/04/10/RequestReply-vs.-PubSub.aspx</link>
            <description>&lt;p&gt;I am having an interesting discussion in email with &lt;a href="http://www.lostechies.com/blogs/evan_hoff/"&gt;Evan Hoff&lt;/a&gt;, about the benefits of pub/sub architecture vs. request/reply. I want to state upfront that I see a lot of value in async one way messaging for a lot of the interactions in an application and across services. However, I am still skeptic about the push for pub/sub all the way.&lt;/p&gt;  &lt;p&gt;To me, it seems like the request/reply model is a very natural one in many common scenarios. In most backend processing systems, I would tend to use pub/sub with &lt;a href="http://www.ayende.com/Blog/archive/2008/04/08/A-Messaging-Saga.aspx"&gt;sagas&lt;/a&gt; as both the easiest and most scalable solution. But in almost all cases that end up in the UI, this just doesn't make sense. Even if I want to fire several requests and then wait for all their reply, the model is still more natural than a pub/sub approach.&lt;/p&gt;  &lt;p&gt;Note that the following code sample use imaginary API.&lt;/p&gt;  &lt;p&gt;Let us go back to the displaying the available candidates. Using the request/reply model, I would have:&lt;/p&gt;  &lt;blockquote&gt;   &lt;pre&gt;&lt;span style="color: #0000ff"&gt;public void &lt;/span&gt;AvailableCandidates()&lt;/pre&gt;

  &lt;pre&gt;{
     var specifications = BuildSpecifications();
     var msg = bus.Process(&lt;span style="color: #0000ff"&gt;new&lt;/span&gt; FindAvailableCandidateMessage(specifications));
     DisplayResults(msg.Results);
}&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;All of those are using the request / reply model.&lt;/p&gt;

&lt;p&gt;The pub/sub model will look somewhat like this:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;pre&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; AvailableCandidates()
{
	var specifications = BuildSpecification();
	
	bus.Publish(&lt;span style="color: #0000ff"&gt;new&lt;/span&gt; FindAvailableCandidatesMessage(specifications))
		.WaitForCallback(&lt;span style="color: #0000ff"&gt;delegate&lt;/span&gt;(AvailableCandidatesMessage msg)
		{
			DisplayResults(msg.Results); 
		});
	
}&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;Or probably something like:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;pre&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; AvailableCandidates()
{
	var specifications = BuildSpecification();
	Guid correlationId = Guid.NewGuid();
	ManualResetEvent waitForReply = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; ManualResetEvent(&lt;span style="color: #0000ff"&gt;false&lt;/span&gt;);
	
	bus.SubscribeOnce&amp;lt;AvailableCandidatesMessage&amp;gt;(correlationId, &lt;span style="color: #0000ff"&gt;delegate&lt;/span&gt;(AvailableCandidatesMessage msg)
		{
			DisplayResults(msg.Results); 
			waitForReply.Set();
		});
	bus.Publish(&lt;span style="color: #0000ff"&gt;new&lt;/span&gt; FindAvailableCandidatesMessage(correlationId, specifications));
	waitForReply.WaitOne();
}&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;Notice that I am not saying anything about the way those are handled once they leave the client. In fact, some of the reasons that were mentioned to favor the pub/sub model is the flexibility that you get when adding more functionality. Such as adding auditing, or redirecting messages to different services based on the type of candidate, etc.&lt;/p&gt;

&lt;p&gt;The problem is that I see not inherent need for pub/sub to make this work. In fact, I think that anything that publish a message and than waits for the callback message is a big API issue, because this &lt;strong&gt;is&lt;/strong&gt; request/reply, but with harder to use API. Even if you are doing the wait in async manner, I still think that this is a bad idea.&lt;/p&gt;

&lt;p&gt;In the context of a request/reply interaction, we can handle everything the way we would handle any other message:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://ayende.com/Blog/images/ayende_com/Blog/WindowsLiveWriter/RequestReplyvs.PubSub_14FAE/image_2.png"&gt;&lt;img height="466" alt="image" src="http://ayende.com/Blog/images/ayende_com/Blog/WindowsLiveWriter/RequestReplyvs.PubSub_14FAE/image_thumb.png" width="792" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;In fact, from the perspective of the infrastructure, there is little need to distinguish those. A message going out will go out either via a request/reply channel or a one way output channel, with a reply maybe arrived through a one way input channel. We don't really care about that.&lt;/p&gt;

&lt;p&gt;From my point of view, it makes a lot more sense than to wait for a callback.&lt;/p&gt;

&lt;p&gt;Thoughts?&lt;/p&gt;&lt;img src="http://ayende.com/Blog/aggbug/10171.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Ayende Rahien</dc:creator>
            <guid>http://ayende.com/Blog/archive/2008/04/10/RequestReply-vs.-PubSub.aspx</guid>
            <pubDate>Thu, 10 Apr 2008 20:52:37 GMT</pubDate>
            <wfw:comment>http://ayende.com/Blog/comments/10171.aspx</wfw:comment>
            <comments>http://ayende.com/Blog/archive/2008/04/10/RequestReply-vs.-PubSub.aspx#feedback</comments>
            <slash:comments>27</slash:comments>
            <wfw:commentRss>http://ayende.com/Blog/comments/commentRss/10171.aspx</wfw:commentRss>
        </item>
        <item>
            <title>SOA Data Access</title>
            <link>http://ayende.com/Blog/archive/2008/04/10/SOA-Data-Access.aspx</link>
            <description>&lt;p&gt;Yesterday I posted about &lt;a href="http://www.ayende.com/Blog/archive/2008/04/08/An-exercise-in-designing-SOA-systems.aspx"&gt;designing an SOA system&lt;/a&gt;. I identified the following service:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;Available candidates - given a set of requirements, will attempt to find all verified candidates that match the requirements. Additional responsibilities include logging search history (important for noticing what requirements are common and desirable), and recording which requirements has no matching physicians in the system (should be passed for human inspection, to decide if head hunting should begin, or this should be ignored).&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&lt;a href="http://bill-poole.blogspot.com/"&gt;BIll Poole&lt;/a&gt; has left a comment regarding this post, which included this statement:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;For example, the "Available Candidates" service appears highly data centric, likely exposing search/data retrieval operations. CRUD interfaces are bad.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;This is something that I have often heard, but I still don't understand. I understand why CRUD interfaces are discourage, you get better results by just using a DB. But in this case? &lt;/p&gt;  &lt;p&gt;How &lt;em&gt;do&lt;/em&gt; you get the data out of an SOA system? It seems to me like this is a natural requirement for the problem at hand, but I feel that I am missing something.&lt;/p&gt;&lt;img src="http://ayende.com/Blog/aggbug/10170.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Ayende Rahien</dc:creator>
            <guid>http://ayende.com/Blog/archive/2008/04/10/SOA-Data-Access.aspx</guid>
            <pubDate>Wed, 09 Apr 2008 23:30:30 GMT</pubDate>
            <wfw:comment>http://ayende.com/Blog/comments/10170.aspx</wfw:comment>
            <comments>http://ayende.com/Blog/archive/2008/04/10/SOA-Data-Access.aspx#feedback</comments>
            <slash:comments>29</slash:comments>
            <wfw:commentRss>http://ayende.com/Blog/comments/commentRss/10170.aspx</wfw:commentRss>
        </item>
        <item>
            <title>An exercise in designing SOA systems</title>
            <link>http://ayende.com/Blog/archive/2008/04/08/An-exercise-in-designing-SOA-systems.aspx</link>
            <description>&lt;p&gt;This question came up in the NServiceBus mailing list, and I think it is very interesting question to try to solve. The standard disclaimers are that I haven't build a real system using this approach, although I am leaning toward it more and more.&lt;/p&gt;  &lt;p&gt;I would like to thank Brad for agreeing to post this example here.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;I would like some advice as to how to properly identify the services I need to create. I know that Udi has said that creating services for each department is a good starting point, but I keep feeling like something is missing. &lt;/p&gt;    &lt;p&gt;So, here's some details.  I work for a company that is the parent of two physician job placement companies.  The parent company would like to create a single system that will support both child companies.  The business processes of both companies have been analyzed and documented, and there is about a 95% overlap in the processes.  Should my team create a monolithic job placement application and wrap it in a service or should I break that application into higher-level business services? &lt;/p&gt;    &lt;p&gt;Here's an example of where I get stuck when trying to map the job placement application's functionality to a high-level business service like Sales Service.  The Sales department is broken into two groups: marketers and recruiters.  Marketers call hospitals to find out what positions are available and try to fill these positions.  Recruiters call physicians to find out if the physician is looking for a new job and tries to find available positions.  Before a physician can be placed, his or her credentials must be verified.  The Credentialing department is responsible for doing this.&lt;/p&gt;    &lt;p&gt;Ok.  So I now have two service candidates (Sales and Credentialing). I have no issues with the credentialing service but the sales service feels like it should be a job placement service.  What if the business decides to take on a new line of business?  This new line-of-business may have the sales department selling something entirely unrelated to job placement services.  Is a job placement service a better idea? But wouldn't that mean that all job placement functionality would need to be placed in that service?  This feels like I'm loosing the agility that SOA gives the business because I'm no longer modeling the way the departments interact with each other.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;I once built a system with very similar concepts, although with drastically different focus. What Brad has already outlined is a good start, but I would break the system even further. We have two main sections of the business that were identified, marketing and recruitment. Let us attack the problem from each side in turn, but keep in mind that we are talking about a single system here.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;High level services:&lt;/strong&gt;&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Available candidates - given a set of requirements, will attempt to find all verified candidates that match the requirements. Additional responsibilities include logging search history (important for noticing what requirements are common and desirable), and recording which requirements has no matching physicians in the system (should be passed for human inspection, to decide if head hunting should begin, or this should be ignored).&lt;/li&gt;    &lt;li&gt;Register open position - enter a new position into the system, with all its requirements. As part of the registration, it will query the available physicians and offer them as matches. If there are no matches, it will register the new position in the recruitment service.&lt;/li&gt;    &lt;li&gt;Register new candidate - enter a new candidate to the system in unverified state. Request credentials verifications from the system.&lt;/li&gt;    &lt;li&gt;Verify credentials - given a candidate, perform a verification of the candidate credentials, references, etc. If the verification succeeds, we move the candidate to the available candidate pool. If the verification fails, we request additional intervention.&lt;/li&gt;    &lt;li&gt;Problematic credentials resolver - there are several reasons for getting problematic credentials, fake credentials, honest mistakes and hostile employers are just a few that comes to mind. In most cases, you need complex logic or human intervention here, and it deserves its own section in the map.&lt;/li&gt;    &lt;li&gt;Candidate hunger* - which candidates are we looking for, this is used by the recruitment guys to know which candidates they should aim for.&lt;/li&gt;    &lt;li&gt;Candidate tracker - if we already assigned a candidate for a job, we already have a happy person, let us keep it this way by ensuring that they remember us, so when they leave, they will contact us again for their next job.&lt;/li&gt;    &lt;li&gt;Potential candidates - given a set of requirements, will attempt to find all candidates that match them. Potential candidates are usually candidates that were gotten from external data sources (the physician listing for the country, for instance), so you want to go through them to see if they can become real candidates.&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Those are just the services that I can think of off the top of my head. Notice that each of them has very few responsibilities, and they match pretty closely a specific business scenario. The services communicate between one another, but they do so using one way, async messaging. This is especially important in this type of scenario, where some services can take long time to process a piece of work (verifying credentials requires a human to call and ask for references, for example).&lt;/p&gt;  &lt;p&gt;My next post will deal with the actual code for one of those services, for now I think this is enough.&lt;/p&gt;  &lt;p&gt;* It was originally a typo, but I like the implications.&lt;/p&gt;&lt;img src="http://ayende.com/Blog/aggbug/10163.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Ayende Rahien</dc:creator>
            <guid>http://ayende.com/Blog/archive/2008/04/08/An-exercise-in-designing-SOA-systems.aspx</guid>
            <pubDate>Tue, 08 Apr 2008 05:39:53 GMT</pubDate>
            <wfw:comment>http://ayende.com/Blog/comments/10163.aspx</wfw:comment>
            <comments>http://ayende.com/Blog/archive/2008/04/08/An-exercise-in-designing-SOA-systems.aspx#feedback</comments>
            <slash:comments>2</slash:comments>
            <wfw:commentRss>http://ayende.com/Blog/comments/commentRss/10163.aspx</wfw:commentRss>
        </item>
        <item>
            <title>Code Generation and the Open Close Principal</title>
            <link>http://ayende.com/Blog/archive/2008/03/29/Code-Generation-and-the-Open-Close-Principal.aspx</link>
            <description>&lt;p&gt;&lt;a href="http://vladan.strigo.net"&gt;Vladan Strigo&lt;/a&gt; made a really inspiring comment about code generation in the NH Users list.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;I didn't want to use codesmith for that because it would de-OCP-fy me in my future efforts :)&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;That makes a lot of sense, and manages to touch on what bothers me the most with code gen as an architectural approach. It gives up a very important concept, and that affect a lot of the stuff that is dependant on that.&lt;/p&gt;&lt;img src="http://ayende.com/Blog/aggbug/10133.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Ayende Rahien</dc:creator>
            <guid>http://ayende.com/Blog/archive/2008/03/29/Code-Generation-and-the-Open-Close-Principal.aspx</guid>
            <pubDate>Sat, 29 Mar 2008 01:26:00 GMT</pubDate>
            <wfw:comment>http://ayende.com/Blog/comments/10133.aspx</wfw:comment>
            <comments>http://ayende.com/Blog/archive/2008/03/29/Code-Generation-and-the-Open-Close-Principal.aspx#feedback</comments>
            <slash:comments>4</slash:comments>
            <wfw:commentRss>http://ayende.com/Blog/comments/commentRss/10133.aspx</wfw:commentRss>
        </item>
        <item>
            <title>Non Invasive API, take 2</title>
            <link>http://ayende.com/Blog/archive/2008/03/25/Non-Invasive-API-take-2.aspx</link>
            <description>&lt;p&gt;A few days ago I presented my typical way of handling container driven polymorphism. &lt;/p&gt;  &lt;blockquote&gt;   &lt;pre&gt;&lt;span style="color: #008000"&gt;// only use for selection&lt;/span&gt;
&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;interface&lt;/span&gt; IRegion&amp;lt;T&amp;gt; : IRegion {}

&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; SetRegion(DependencyObject containerElement, &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; regionName)
{
	IRegion region = (IRegion) IoC.TryResolve(&lt;span style="color: #0000ff"&gt;typeof&lt;/span&gt;(IRegion&amp;lt;&amp;gt;).MakeGenericType(containerElement.GetType()));

	&lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (region != &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;)
		_regions.Add(regionName, region);
}&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;I got an email with some good questions, and it is worth a second post to clarify. The questions:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;The only thing I don’t like is that a lookup in the form of TryResolve(typeof(IRegion&amp;lt;&amp;gt;).MakeGenericType(containerElement.GetType())) would infer an explicit wrapper type for ever possible UI container type. On one hand it gives me the fine grain control I need to specify a different wrapper for an inherited UI container. But on the other hand, it means that ListBox, TreeView, ComboBox and TabControl would all need their own custom wrappers even though they all derive from ItemsControl and all handle adding and removing child entities in the same way.&lt;/p&gt;

  &lt;p&gt;&lt;a name="_MailEndCompose"&gt;But if &lt;/a&gt;containerElement == typeof(ListBox), won’t TryResolve(typeof(IRegion&amp;lt;&amp;gt;).MakeGenericType(containerElement.GetType())) fail to resolve? TryResolve expects an explicit match. It would need to find a registration for IRegion&amp;lt;ListBox&amp;gt;, not IRegion&amp;lt;ItemContainer&amp;gt; right? (Assuming Unity here.)&lt;/p&gt;

  &lt;p&gt;Even if that worked, what if I want all elements that inherit from ItemContainer to be handled by IRegion&amp;lt;ItemContainer&amp;gt; &lt;i&gt;except&lt;/i&gt; TreeView? Say I need to handle TreeView differently for some reason. What’s a nice way to handle the 80% rule generically but still allow an override for special cases?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;My response to that is very simple. Take the same approach, but bigger. Here is all we need to make this happen.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;pre&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; SetRegion(DependencyObject containerElement, &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; regionName)
{
	Type current = containerElement.GetType()
	&lt;span style="color: #0000ff"&gt;while&lt;/span&gt;(current != &lt;span style="color: #0000ff"&gt;typeof&lt;/span&gt;(DependencyObject))
	{
		IRegion region = (IRegion) IoC.TryResolve(&lt;span style="color: #0000ff"&gt;typeof&lt;/span&gt;(IRegion&amp;lt;&amp;gt;).MakeGenericType(current));
	
		&lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (region != &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;)
		{
			_regions.Add(regionName, region);
			&lt;span style="color: #0000ff"&gt;return&lt;/span&gt;;
		}
		
		current = current.BaseType;
	}
}&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now, we can register the following:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;IRegion&amp;lt;TreeView&amp;gt;&lt;/li&gt;

  &lt;li&gt;IRegion&amp;lt;MyCustomRegion&amp;gt;&lt;/li&gt;

  &lt;li&gt;IRegion&amp;lt;ItemsControl&amp;gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And no matter what we will send to SetRegion, we can modify the behavior merely by changing the registration of IRegion&amp;lt;T&amp;gt; implementations. Note that this doesn't assumes any capacity on the container (except the basic resolve-generic-service one).&lt;/p&gt;

&lt;p&gt;This is also a very natural model to follow, in nearly all cases (there is an issue here regarding whatever we should consider interfaces as well, but that is beside the point for this demo, and I would generally not do that anyway).&lt;/p&gt;&lt;img src="http://ayende.com/Blog/aggbug/10118.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Ayende Rahien</dc:creator>
            <guid>http://ayende.com/Blog/archive/2008/03/25/Non-Invasive-API-take-2.aspx</guid>
            <pubDate>Mon, 24 Mar 2008 22:58:25 GMT</pubDate>
            <wfw:comment>http://ayende.com/Blog/comments/10118.aspx</wfw:comment>
            <comments>http://ayende.com/Blog/archive/2008/03/25/Non-Invasive-API-take-2.aspx#feedback</comments>
            <slash:comments>4</slash:comments>
            <wfw:commentRss>http://ayende.com/Blog/comments/commentRss/10118.aspx</wfw:commentRss>
        </item>
        <item>
            <title>You should hard code the idea, not the value</title>
            <link>http://ayende.com/Blog/archive/2008/03/23/You-should-hard-code-the-idea-not-the-value.aspx</link>
            <description>&lt;p&gt;I am reading NServiceBus' code at the moment, and I run into this idea:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;[Serializable]     &lt;br /&gt;[Recoverable]      &lt;br /&gt;[TimeToBeReceived(“0:01:00.000")]      &lt;br /&gt;public class ScheduleInterviewMessage : IMessage      &lt;br /&gt;{      &lt;br /&gt;    public Guid InterviewerId;      &lt;br /&gt;    public Guid CandidateId;      &lt;br /&gt;    public DateTime RequestedTime;      &lt;br /&gt;}&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;I don't like hard coding this value in the message. Obviously this is something that is tied very closed to the idea of the message. Time to live is certainly something that I would want to closely tie to the message itself. But hard coding the value goes against a lot of instincts.&lt;/p&gt;  &lt;p&gt;A while ago I faced a &lt;a href="http://www.ayende.com/Blog/archive/2007/10/09/From-demo-to-production-Handling-the-edge-cases-that-arent.aspx"&gt;similar issue&lt;/a&gt;, in that case, it was scheduling tasks. The timing of the task was tied to what it did. The last example that I had on that post is this:&lt;/p&gt;  &lt;blockquote&gt;   &lt;pre&gt;[Occurances(OccureEvery.Day, At = "08:00", RunAtHolidays = false)]
public class SendSmsTwoDaysBeforeEventStart : ScheduledTask&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;Notice the At = "08:00" ? It bothered me for a while, until I came to the conclusion that I was embedding the wrong piece of information in the code.&lt;/p&gt;

&lt;p&gt;I didn't want this to run at 08:00, I want it to run in the morning. 08:00 was just a handy designation for that. That thought was quickly followed by:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;public enum ScheduledTimes
    &lt;br /&gt;{

    &lt;br /&gt;     Midnight,

    &lt;br /&gt;     EarlyMorning,

    &lt;br /&gt;     Morning,

    &lt;br /&gt;     Noon,

    &lt;br /&gt;     Afternoon,

    &lt;br /&gt;     Evening     &lt;br /&gt;}&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And the code turned to:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;[Occurances(OccureEvery.Day, At = ScheduledTimes.Morning, RunAtHolidays = false)] 
    &lt;br /&gt;public class SendSmsTwoDaysBeforeEventStart : ScheduledTask &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The difference here is that I no longer hard code a specific value, I put the idea there. During deployment, I could have modified what morning meant, very easily.&lt;/p&gt;

&lt;p&gt;Using the same approach, I would define something like:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;public enum TimeToLive
    &lt;br /&gt;{

    &lt;br /&gt;    Immediate,

    &lt;br /&gt;    Short,

    &lt;br /&gt;    Medium,

    &lt;br /&gt;    Long,

    &lt;br /&gt;    Forever

    &lt;br /&gt;}&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I would probably allow to configure the time that each of those values map to, as well.&lt;/p&gt;

&lt;p&gt;This allows to do things like update them on the fly (imagine having to survive a burst of traffic that slows the entire system), so you can increase the time to process a message without losing it.&lt;/p&gt;&lt;img src="http://ayende.com/Blog/aggbug/10112.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Ayende Rahien</dc:creator>
            <guid>http://ayende.com/Blog/archive/2008/03/23/You-should-hard-code-the-idea-not-the-value.aspx</guid>
            <pubDate>Sun, 23 Mar 2008 19:51:13 GMT</pubDate>
            <wfw:comment>http://ayende.com/Blog/comments/10112.aspx</wfw:comment>
            <comments>http://ayende.com/Blog/archive/2008/03/23/You-should-hard-code-the-idea-not-the-value.aspx#feedback</comments>
            <slash:comments>6</slash:comments>
            <wfw:commentRss>http://ayende.com/Blog/comments/commentRss/10112.aspx</wfw:commentRss>
        </item>
        <item>
            <title>A maintainable environment - anti corruption as a way of life</title>
            <link>http://ayende.com/Blog/archive/2008/03/22/A-maintainable-environment--anti-corruption-as-a-way-of.aspx</link>
            <description>&lt;p&gt;Recently I had a number of conversations about how to create a maintainable environment, not only for advanced developers, but an environment that enables beginners and intermediate developers to create good, maintainable, scalable solutions.&lt;/p&gt;
&lt;p&gt;This problem is not a simple one, and there aren't really one off solutions. However, there is quite a lot that can be done, and I am very disturbed by the assumption that nothing can be done about it.&lt;/p&gt;
&lt;p&gt;I noticed that a major part of the problem seems to be in the underlying assumption that in order to make it possible for beginners/intermediate developers to work with the application, you have to do one of two things. Embark on a long education period or dumb down the application to a level that beginners can deal with.&lt;/p&gt;
&lt;p&gt;I am using the term "dumb down" on purpose. This approach goes for the easiest solution possible, those solutions tend to be very easy and supportive for trivial scenarios, but they get very complicate for any real world scenario. They also tend to be focused on RAD, with little regard to the overall maintainability of the solution. I am pretty sure that you have encounter such systems before, they are depressingly common.&lt;/p&gt;
&lt;p&gt;The end result of choosing such an approach is an application whose complexity is not handled by the underlying platform, but rather at each individual case. This significantly complicate the applicatIon and working with in over time. As a quick example (which is sure to annoy a lot of people), I consider any application that has "new SqlConnection()" in it outside the infrastructure layer to be such a system.&lt;/p&gt;
&lt;p&gt;The other alternative, however, is a lengthy training cycle, and slower productivity all around until you get to be proficient in the new approach. And, of course, some people will have really hard time adjusting.&lt;/p&gt;
&lt;p&gt;Or so many people believe, at least. I strongly disagree with the previous statement.&lt;/p&gt;
&lt;p&gt;The way I would choose for such a scenario (a team composed of developers of varying skills, being non trivial application) is to accept the fact that you cannot escape from the complexity and embrace that fact. Instead of trying to base the application on an overly simple foundation, I would base it on advance platform.&lt;/p&gt;
&lt;p&gt;This advance platform would be able to scale to handle the complexity of the application, while concentrating that complexity into the infrastructure layer.&lt;/p&gt;
&lt;p&gt;Some of the concepts involved in creating such an architecture are:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Infrastructure Ignorance - If I have to deal with my infrastructure explicitly, then I need to have developers dealing with it on a regular basis. That doesn't mesh well with the idea of moving all the complexity to the infrastructure.&lt;/li&gt;

  &lt;li&gt;Fizz Buzz concepts - the code that a developer should write should be simple and easy to follow.&lt;/li&gt;

  &lt;li&gt;Follow good design principals - the code written should naturally lean toward single responsibility principal, separation of concerns, etc&lt;/li&gt;

  &lt;li&gt;Easy to figure out - It should be simpler than the alternative for any non trivial scenario. Ideally, you can explain how to solve most scenarios using this approach in half an hour or less (ignoring the infrastructure part, which may be very complex).&lt;/li&gt;

  &lt;li&gt;No training wheels - one of the things that drives me crazy is having two ways to do things. One for the &lt;span style="font-style: italic;"&gt;average&lt;/span&gt; developer, the second for the architect. This usually comes out of putting training wheels on the first approach that make it hard to deal with in more advance scenarios. I see this as a sign of contempt for the rest of the members of the team. If you expect the rest of the team to work in a certain way, make damn sure that this is a way that this is a way that you can live with.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I think that I manage to get fairly close to this in my previous project, and it has proven to be a successful one. I talk about it a bit in &lt;a href="http://www.ayende.com/Blog/archive/2007/09/18/Anti-Corruption-Layers-Striving-for-FizzBuzz-level.aspx"&gt;this post.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I based that system on IoC, NHibernate and WCF. None of this concepts was exposed to the other developers. In fact, after setting this up, we were able to focus on the actual business issues far more often than on the technology involved.&lt;/p&gt;
&lt;p&gt;By the way, I would fully expect that during the project, significant attempts would be made to get the other developers to understand. This technique is about getting a project started and the team productive very early, and doing this using a stable foundation.&lt;/p&gt;
&lt;p&gt;Now, what is this anti corruption stuff in the title of this post? This is very simple, actually. It is here as more than the anti corruption than the anti corruption layers that Feathers is talking about in Working Effectively With Legacy Code. In this case, we start with the assumption that the infrastructure that we will use (even if we are the one building it) is suspect and should not be trusted, so we will do everything in our power to isolate our code from the infrastructure.&lt;/p&gt;
&lt;p&gt;An important benefit of this approach is that we get the ability to modify the infrastructure independently of our application. This means that we can make significant changes very easily, because there is little to no dependencies between the two.&lt;/p&gt;
&lt;img src="http://ayende.com/Blog/aggbug/10109.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Ayende Rahien</dc:creator>
            <guid>http://ayende.com/Blog/archive/2008/03/22/A-maintainable-environment--anti-corruption-as-a-way-of.aspx</guid>
            <pubDate>Sat, 22 Mar 2008 16:26:16 GMT</pubDate>
            <wfw:comment>http://ayende.com/Blog/comments/10109.aspx</wfw:comment>
            <comments>http://ayende.com/Blog/archive/2008/03/22/A-maintainable-environment--anti-corruption-as-a-way-of.aspx#feedback</comments>
            <slash:comments>12</slash:comments>
            <wfw:commentRss>http://ayende.com/Blog/comments/commentRss/10109.aspx</wfw:commentRss>
        </item>
        <item>
            <title>Non invasive API - Now with an IoC container</title>
            <link>http://ayende.com/Blog/archive/2008/03/19/Non-invasive-API--Now-with-an-IoC-container.aspx</link>
            <description>&lt;p&gt;I talked about ways to avoid &lt;a href="http://www.ayende.com/Blog/archive/2008/03/19/Avoiding-Invasive-API-design.aspx"&gt;invasive API design&lt;/a&gt;, and a lot of people asked about how to handle this with a container. First, I want to make it clear that the previous example assumed that you can't rely on a container, so it used Poor Man IoC to do that. Now that we can assume that there is a container, this is another matter entirely.&lt;/p&gt; &lt;p&gt;The API design now shifts to allow me to select the proper implementation from the container automatically. This generally ends up being either as a naming convention on top of a fixed interface, or as a generic interface with a given type as a parameter. The decision depends on what you are doing, basically, and the capabilities of your tools.&lt;/p&gt; &lt;p&gt;For myself, I strongly favor the generic interface approach, which would give us the following syntax:&lt;/p&gt; &lt;blockquote&gt;&lt;pre&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;interface&lt;/span&gt; IMessageHandler&amp;lt;TMsg&amp;gt;
	where TMsg : IMessage
{
	&lt;span style="color: #0000ff"&gt;void&lt;/span&gt; Handle(TMsg msg);
}

&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; EndPoint
{
	&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; HandleMsg(IMessage msg)
	{
		&lt;span style="color: #008000"&gt;// this should be cached and turned into a delegate&lt;/span&gt;
		&lt;span style="color: #008000"&gt;// not reflection call&lt;/span&gt;
		GetGenericHandleMsgMethod().MakeGenericMethod(msg.GetType())
			.Invoke(&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;, &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; &lt;span style="color: #0000ff"&gt;object&lt;/span&gt;[]{msg});
	}

	&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; HandleMsg&amp;lt;TMsg&amp;gt;(TMsg msg)
		where TMsg : IMessage
	{
		IoC.Resolve&amp;lt;IMessageHandler&amp;lt;TMsg&amp;gt;().Handle(msg);
	}

}&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;There is some ugliness in invoking the method with the generic parameter, but this allows you to handle a wide variety of cases very easily.&lt;/p&gt;
&lt;p&gt;Let us take another example, this time it is from the Prism.Services.RegionManagerService:&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; SetRegion(DependencyObject containerElement, &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; regionName)
{
	IRegion region = &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;;

	&lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (containerElement &lt;span style="color: #0000ff"&gt;is&lt;/span&gt; Panel)
	{
		region = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; PanelRegion((Panel)containerElement);
	}
	&lt;span style="color: #0000ff"&gt;else&lt;/span&gt; &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (containerElement &lt;span style="color: #0000ff"&gt;is&lt;/span&gt; ItemsControl)
	{
		region = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; ItemsControlRegion((ItemsControl)containerElement);
	}

	&lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (region != &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;)
		_regions.Add(regionName, region);
}&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;I don't really like this code, let us see what happens when we introduce the idea of the container as a deeply rooted concept:&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;&lt;span style="color: #008000"&gt;// only use for selection&lt;/span&gt;
&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;interface&lt;/span&gt; IRegion&amp;lt;T&amp;gt; : IRegion {}

&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; SetRegion(DependencyObject containerElement, &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; regionName)
{
	IRegion region = (IRegion) IoC.TryResolve(&lt;span style="color: #0000ff"&gt;typeof&lt;/span&gt;(IRegion&amp;lt;&amp;gt;).MakeGenericType(containerElement.GetType()));

	&lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (region != &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;)
		_regions.Add(regionName, region);
}&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;Now the code is much clearer, we can extend it from the outside, without modifying anything when we add a new region type. &lt;/p&gt;&lt;img src="http://ayende.com/Blog/aggbug/10104.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Ayende Rahien</dc:creator>
            <guid>http://ayende.com/Blog/archive/2008/03/19/Non-invasive-API--Now-with-an-IoC-container.aspx</guid>
            <pubDate>Wed, 19 Mar 2008 21:37:41 GMT</pubDate>
            <wfw:comment>http://ayende.com/Blog/comments/10104.aspx</wfw:comment>
            <comments>http://ayende.com/Blog/archive/2008/03/19/Non-invasive-API--Now-with-an-IoC-container.aspx#feedback</comments>
            <slash:comments>14</slash:comments>
            <wfw:commentRss>http://ayende.com/Blog/comments/commentRss/10104.aspx</wfw:commentRss>
        </item>
        <item>
            <title>Avoiding Invasive API design</title>
            <link>http://ayende.com/Blog/archive/2008/03/19/Avoiding-Invasive-API-design.aspx</link>
            <description>&lt;p&gt;I have a strong dislike for invasive API and framework. I dislike them because they require a lot of work, avoid existing options, limit my ability to work with them, etc. They also tend to tie you to a platform for very little reason.&lt;/p&gt; &lt;p&gt;Here is a simple (and fictional) example. Let us assume that we want to write a library to expose our domain model in a version way. So we can do something like this:&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;svn://localhost/Customers/15[@revision=3]&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Now, in order to handle this scenario, I have devised the following schema. I can create the end point using the following approach:&lt;/p&gt; &lt;blockquote&gt;&lt;pre&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; Customers : Versioned&amp;lt;Customer&amp;gt; { }
&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;And I can can specify the revision using an attribute:&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; Customer
{
	&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;virtual&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; Id { &lt;span style="color: #0000ff"&gt;get&lt;/span&gt;; &lt;span style="color: #0000ff"&gt;set&lt;/span&gt;; }

	[SvnVersion]
	&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;virtual&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; Version { &lt;span style="color: #0000ff"&gt;get&lt;/span&gt;; &lt;span style="color: #0000ff"&gt;set&lt;/span&gt;; }
}
&lt;/pre&gt;&lt;/blockquote&gt;
&lt;blockquote&gt;&lt;/blockquote&gt;
&lt;p&gt;Very simple, right? And very straightforward. Except that this in incredibly invasive approach to take.&lt;/p&gt;
&lt;p&gt;I really dislike API that work this way. Now, if I want to expose my domain model using SVN, I need to go into the domain model and start messing with that, just because I want to add another accessibility option?&lt;/p&gt;
&lt;p&gt;This is bad. It violates the open close principal, single responsibility principal and in Ayende Annoyance Principal.&lt;/p&gt;
&lt;p&gt;Let us try to make this easier, shall we?&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; Customers : Versioned&amp;lt;Customer, CustomerVersionPropertyProvider&amp;gt;
{
}&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;Now I don't have to modify the Customer entity, I can do this in a way that doesn't modify Customer, I keep things separate and in general I am happy. From the Versioned class perspective, I now define it as:&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; Versioned&amp;lt;TEntity, TVersionProvider&amp;gt;
	&lt;font color="#0000ff"&gt;where&lt;/font&gt; TVersionProvider : IVersionProvider, &lt;span style="color: #0000ff"&gt;new&lt;/span&gt;()
{
}&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;Actually, this is not really good. We probably want to control the creation of the version provider ourselves (it may need external dependencies, we may want to control its lifetime, etc), so we get to this design:&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; Versioned&amp;lt;TEntity, TVersionProviderFactory&amp;gt;&lt;br /&gt; &lt;font color="#0000ff"&gt;where&lt;/font&gt; TVersionProviderFactory: IVersionProviderFactory, &lt;span style="color: #0000ff"&gt;new&lt;/span&gt;() &lt;br /&gt;{&lt;br /&gt;}

&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;interface&lt;/span&gt; IVersionProviderFactory
{
	IVersionProvider Create();
}

&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; Customers : Versioned&amp;lt;Customers, CustomersVerionProviderFactory&amp;gt;
{
}&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;And now we really have non invasive API, which plays well with other tools.&lt;/p&gt;
&lt;p&gt;Except, the simple scenario that we had before turn out to be really complex. Instead of putting a simple attribute in place, we now need to implement two interfaces, do it per class, and in generally add a lot more work into our life.&lt;/p&gt;
&lt;p&gt;That is also bad. But we can resolve that easily, by defaulting to the invasive behavior (which is really easy to explain), yet allowing extensibility. The way to do it is simple:&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; Versioned&amp;lt;TEntity, TVersionProviderFactory&amp;gt;
	where TVersionProviderFactory: IVersionProviderFactory, &lt;span style="color: #0000ff"&gt;new&lt;/span&gt;() 
{
} 

&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; Versioned&amp;lt;TEntity&amp;gt; : Versioned&amp;lt;TEntity, SvnVersionAttributeVersionProviderFactory&amp;gt;
{
} 


&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; Customers : Versioned&amp;lt;Customer&amp;gt;
{
}&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;Now we have the same API for the simple (and invasive) scenario, but with minimal effort, we have made it possible to use non invasive and smart approaches.&lt;/p&gt;&lt;img src="http://ayende.com/Blog/aggbug/10100.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Ayende Rahien</dc:creator>
            <guid>http://ayende.com/Blog/archive/2008/03/19/Avoiding-Invasive-API-design.aspx</guid>
            <pubDate>Wed, 19 Mar 2008 06:45:43 GMT</pubDate>
            <wfw:comment>http://ayende.com/Blog/comments/10100.aspx</wfw:comment>
            <comments>http://ayende.com/Blog/archive/2008/03/19/Avoiding-Invasive-API-design.aspx#feedback</comments>
            <slash:comments>18</slash:comments>
            <wfw:commentRss>http://ayende.com/Blog/comments/commentRss/10100.aspx</wfw:commentRss>
        </item>
    </channel>
</rss>