<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Udi Dahan - The Software Simplist &#187; Architecture</title>
	<atom:link href="http://www.udidahan.com/category/architecture/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.udidahan.com</link>
	<description>Enterprise Development Expert &#38; SOA Specialist</description>
	<lastBuildDate>Sun, 08 Jan 2012 12:45:00 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>The Myth Of &#8220;Infinite Scalability&#8221;</title>
		<link>http://www.udidahan.com/2011/12/29/the-myth-of-infinite-scalability/</link>
		<comments>http://www.udidahan.com/2011/12/29/the-myth-of-infinite-scalability/#comments</comments>
		<pubDate>Thu, 29 Dec 2011 09:58:52 +0000</pubDate>
		<dc:creator>udidahan</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Availability]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[Reliability]]></category>
		<category><![CDATA[Scalability]]></category>

		<guid isPermaLink="false">http://www.udidahan.com/?p=1607</guid>
		<description><![CDATA[Scalability is a topic near and dear to my heart.
Many a client seeks me out for the first time for help in this area.
Usually the request is for an amount substantially smaller than infinity.
It&#8217;s usually on the discussion groups and in conference presentations that infinity is brought into it.
The basics
The first issue with scalability is [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.udidahan.com/wp-content/uploads/globe.jpg" alt="globe" title="globe" width="250" height="205" style="float:right; margin-left:10px; margin-bottom:10px;" />Scalability is a topic near and dear to my heart.</p>
<p>Many a client seeks me out for the first time for help in this area.</p>
<p>Usually the request is for an amount substantially smaller than infinity.</p>
<p>It&#8217;s usually on the discussion groups and in conference presentations that infinity is brought into it.</p>
<h3>The basics</h3>
<p>The first issue with scalability is the use of the word as an adjective: scalable.</p>
<p>&#8220;Is the system scalable?&#8221;</p>
<p>Or the similar verb use: &#8220;Does it scale?&#8221;</p>
<p>The problem here is the implication that there is a yes/no answer to the question. </p>
<p>Scalability is not boolean.</p>
<h3>Linear Scalability</h3>
<p><img src="http://www.udidahan.com/wp-content/uploads/scalability.gif" alt="scalability" title="scalability" width="150" height="150" style="float:right; margin-left:10px; margin-bottom:10px;" />When people talk about scalability, or a system being able to scale, they&#8217;re usually referring to a graph that looks something like this:</p>
<p>The red graph indicating a system that does not scale well, the green graph indicating one that does.</p>
<p>What is missing from this diagram are the labels of the axes. </p>
<p>The Y axis is Cost, Expense, or Money.<br />
The X axis is usually the number of users (for internet-type companies).</p>
<p>Ultimately, scalability is a cost-function that will tell us how much it will cost to have the system support a certain number of users. </p>
<p>Linear scalability is when the cost of the next user is the same as the cost of the previous user. This means our system doesn&#8217;t have bottlenecks. This is what people usually mean when they say &#8220;infinite scalability&#8221;.</p>
<h3>But there&#8217;s more</h3>
<p>As many of the internet companies (and their investors) have realized over the years, there&#8217;s a difference between the number of users and the number of <b>active</b> users. It&#8217;s very easy to scale to a billion users when only 1000 of them are active at any given time.</p>
<p>To be more accurate, what we want is additional X-axes for things like total data managed by the system, number of requests per user, resource utilization per request, propagation speed (how quickly information entered by one user needs to be visible to others), and more.</p>
<p>Scalability is a multi-dimensional cost function, where part of an architects job is to figure out which dimensions are significant for the system/business, and what the expectation for growth is across each axis.</p>
<h3>Preparing for &#8220;infinity&#8221;</h3>
<p>Be careful not to optimize for only a single dimension &#8211; reality is a whole lot more complex.</p>
<p>There are so many other things to deal with as a system scales.</p>
<p>For example, do you really think you&#8217;re going to want your configuration entirely centralized? Putting everything in one place means easier management, yes, but it also means a mistake will instantly affect everyone. Is it worth the risk? Maybe instead of centralization, we could do with some automation that will allow a staged rollout of configuration changes with the ability to rollback. </p>
<p>The same goes for rolling out new versions, patches, and upgrades.</p>
<p>But that now means we may have multiple versions of the same system in production at the same time. How will that work? Will they all talk to the same database? How will we version the database then? If not, how will we handle state? Won&#8217;t this mean our code will have to be backwards compatible from one version to another? Isn&#8217;t that hard? Like, insanely hard?</p>
<p>Please, can we park the whole &#8220;infinite scalability&#8221; thing?<br />
It&#8217;s really not the most important concern &#8211; not by a long shot.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.udidahan.com/2011/12/29/the-myth-of-infinite-scalability/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>Recording of joint interview with Eric Evans</title>
		<link>http://www.udidahan.com/2011/11/30/recording-of-joint-interview-with-eric-evans/</link>
		<comments>http://www.udidahan.com/2011/11/30/recording-of-joint-interview-with-eric-evans/#comments</comments>
		<pubDate>Thu, 01 Dec 2011 04:59:14 +0000</pubDate>
		<dc:creator>udidahan</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[CQRS]]></category>
		<category><![CDATA[DDD]]></category>
		<category><![CDATA[Presentations]]></category>

		<guid isPermaLink="false">http://www.udidahan.com/?p=1597</guid>
		<description><![CDATA[Last month both myself and Eric Evans spoke at a conference run by the International Association of Software Architects (IASA) in Madrid. Eric talked about DDD and I talked about CQRS. While the talks were recorded, I don&#8217;t think they&#8217;ve come online yet.
At the end of the conference, we were interviewed by the local .NET [...]]]></description>
			<content:encoded><![CDATA[<p>Last month both myself and Eric Evans spoke at a conference run by the International Association of Software Architects (IASA) in Madrid. Eric talked about DDD and I talked about CQRS. While the talks were recorded, I don&#8217;t think they&#8217;ve come online yet.</p>
<p>At the end of the conference, we were interviewed by the local .NET magazine dNM and that video is now available <a href="http://vimeo.com/32647895">here</a>. We covered the background on things like DDD, CQRS, and the Cloud. I don&#8217;t think that either of us said anything earth-shattering but if you have half an hour, take a look:</p>
<p><iframe src="http://player.vimeo.com/video/32647895?title=0&amp;byline=0&amp;portrait=0" width="400" height="225" frameborder="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe></p>
]]></content:encoded>
			<wfw:commentRss>http://www.udidahan.com/2011/11/30/recording-of-joint-interview-with-eric-evans/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Why you should be using CQRS almost everywhere…</title>
		<link>http://www.udidahan.com/2011/10/02/why-you-should-be-using-cqrs-almost-everywhere%e2%80%a6/</link>
		<comments>http://www.udidahan.com/2011/10/02/why-you-should-be-using-cqrs-almost-everywhere%e2%80%a6/#comments</comments>
		<pubDate>Sun, 02 Oct 2011 20:45:44 +0000</pubDate>
		<dc:creator>udidahan</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Autonomous Services]]></category>
		<category><![CDATA[CQRS]]></category>
		<category><![CDATA[DDD]]></category>
		<category><![CDATA[OO]]></category>
		<category><![CDATA[SOA]]></category>
		<category><![CDATA[Simplicity]]></category>

		<guid isPermaLink="false">http://www.udidahan.com/?p=1551</guid>
		<description><![CDATA[… but differently than the way most people have been using it.
I think I’ve just about drove everybody crazy now with my apparent zigzagging on CQRS.
Some people heard about CQRS first from one of my presentations and got all excited about it. Then I did some blogging which further drove people to CQRS (as did [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.udidahan.com/wp-content/uploads/grass.jpg" alt="grass" title="grass" width="200" height="150" style="float:right; margin-left:10px; margin-bottom:10px;" />… but differently than the way most people have been using it.</p>
<p>I think I’ve just about drove everybody crazy now with my apparent zigzagging on CQRS.</p>
<p>Some people heard about CQRS first from one of my presentations and got all excited about it. Then I did some blogging which further drove people to CQRS (as did Greg Young and some others). As CQRS was just about to hit its stride with the Early Adopters, I started pushing a more balanced view – CQRS not as an answer, but as one of many questions. More recently I’ve pushed more strongly back against CQRS saying that it should be used rarely.</p>
<h3>So what’s the missing piece?</h3>
<p>If you’re in the Domain-Driven Design camp (as many doing CQRS are), then it’s Bounded Contexts.</p>
<p>If you’re in the Event-Driven SOA camp (a much smaller camp to be sure), then it’s Services.</p>
<p>The problem is the naming, because the DDD guys have their kinds of services which do not fit the definition for Service of the Event-Driven SOA approach.</p>
<p>Let me propose the term Autonomous Business Component for the purposes of this blog post to describe that thing which is both a DDD Bounded Context (have the shared BC part of the acronym) and an SOA Autonomous Services. Resulting in the nice short form:  ABC (and everyone knows you need to have a good acronym if you want something to catch on).</p>
<h3>What does this have to do with CQRS?</h3>
<p>Nothing just yet. Well, at least, nothing directly to do with CQRS.</p>
<p>Although some proponents of CQRS have stated that it can and should be used as the top-most architectural pattern, both myself and Greg Young (arguably the first two to talk about it and the two who ultimately collaborated on naming it – and now Google knows we didn’t means “cars”) always recommended it as a pattern to be used one level down. </p>
<p>Although Greg and I have had many long discussions on the topic and do agree very much about what the overall structure should look like, I’ll try to avoid putting words in his mouth from this point on.</p>
<p>Before talking more about ABCs, let’s discuss the principle upon which they rest: The Single Responsibility Principle (SRP).</p>
<h3>What does SRP have to with CQRS?</h3>
<p>Many developers are familiar with SRP and have seen good results from using it. What we’re going to do is take this principle to the next level.</p>
<p>In Object Orientation (OO), data is encapsulated in an object. A good object does not expose its data to other objects to do with as they wish. Rather, it exposes methods that other objects can invoke, and those methods operate on the internal data.</p>
<p>SRP would guide us to not have the same data exist in two objects. For example, if we saw the customer’s first name as an internal data member of two objects, we’d be right to question that kind of duplication and move to refactor it away. However, when we see two systems doing the exact same thing – somehow that gets excused.</p>
<blockquote><p>“Of course we need to be able to see the customer’s first name in the front-end website as well as in the back-end fulfillment system. How could we NOT have the customer’s first name in both those code-bases?”</p></blockquote>
<p>And there’s the catch.</p>
<p>Who said that a system should be a single code-base?</p>
<h3>But what about integration?</h3>
<p>Although many times we do need to integrate existing systems together, sometimes we have the ability to change those systems. More importantly, when going to create a new solution, we can avoid getting ourselves into the problems that integration tries to solve.</p>
<p>Integrating with a system that cannot be changed can be done also by composing multiple ABCs, but that’s a topic for another post.</p>
<p>It is better to think of integration as a necessary evil – kind of like regular expressions and multi-threading; things to be avoided unless absolutely necessary.</p>
<p>“If you have a problem that you decide to use a regular expression to solve, you now have 2 problems.” Or so the saying goes. With multi-threading, you have a non-deterministic number of problems to solve.</p>
<p>If you thought you had duplicate responsibilities with 2 systems operating on the same data, how will introducing a 3rd code base (also known as “integration”) help? Remember that Single Responsibility Principle – our goal is to get it down to one.</p>
<h3>OK, so how do ABCs do that?</h3>
<p>In order for us to get back into alignment with SRP, that would require us to have responsibility for a single piece of data exist in one code base. Note that SRP makes no statements about how many physical places a given code base can be deployed to. Nor does it state that only a single technology can be in play – code that emits HTML can be packaged at design time together with rich-client code in the same solution.</p>
<p>If an ABC is responsible for a piece of data, it is responsible for it everywhere, and forever. No other ABC should see that data. That data should not travel between ABCs via remote procedure call (RPC) or via publish/subscribe. It is the ultimate level of encapsulation – SRP applied at the highest level of granularity.</p>
<p>This results in systems which are the result of deploying the components of multiple ABCs to the same physical place. The ABC which owns the customer name would have the necessary web code to render it in the e-commerce front-end and in the shipping back-end for printing on labels. This would mean that practically every screen in any UI is a composite of widgets owned by their respective ABCs.</p>
<p>This is ultimately what keeps the complexity of each ABC’s code base to a minimum. </p>
<h3>But why not just use CQRS as the top-level pattern? ABCs are weird.</h3>
<p>Imagine trying to create a single denormalized view model for the entire Amazon.com product page – product name, price, inventory, editorial review, customer comments, other products that customers viewed, other products that customers bought, etc. </p>
<p>Pretty complex, right?</p>
<p>How much duplication would you have for the page shown after you add an item to a cart? Once again, you need to show other products that customers bought, their names, images, prices, and inventory. </p>
<p>And then on the home page – items you might be interested in, names, images, prices.</p>
<p>And that’s only in the front-end system.</p>
<p>It’s not just the duplication, but how complex the code is for each one.</p>
<p>Instead of the duplication that top-level CQRS would bring you, consider an ABC responsible for products names and images that has just about the same view model composed on each of the above screens. The same with another ABC responsible for price.</p>
<p>You may be thinking that this would result in more queries to get the data to show on a page, and you’d be right. But it isn’t necessarily a classical N+1 Select problem, as the queries are bounded to the number of ABCs. Secondly, consider the ability to have well-tuned caching at the granularity of an ABC – something that would be much more difficult when dealing with everything as a single monolithic view model. In short, not only will it not be a performance problem, often it will actually improve performance.</p>
<h3>OK – that explains “everywhere”, what about “forever”?</h3>
<p>Forever is where things get interesting – or more accurately, when they get interesting.</p>
<p>Let’s talk about things like invoices.</p>
<p>One of the requirements in this area is that immutability. If the customer’s name was Jane Smith when they made their purchase, it doesn’t matter that they’ve since changed their name to Jane Jones, the invoice should still show Jane Smith.</p>
<p>Often developers push these types of requirements on the data warehouse guys – that’s where history gets handled. The only thing is that if your ABC owns the customer’s name, then no other code base can deal with it. If it’s your data, you have to handle all historical representations of it.</p>
<p>On the one hand, this would seem to kill the data warehouse. On the other hand, it means that the principles of data warehouses are now core to every code-base.</p>
<p>This means you don’t ever delete data (see my <a href="http://www.udidahan.com/2009/09/01/dont-delete-just-dont/">previous blog post</a> on the subject), and you definitely don’t overwrite it with an update – even if you think you’re in a simple CRUD domain. The only case where you can get away with traditional CRUD is if we’re talking about private data – data that is only ever acted on by a single actor.</p>
<h3>This sounds like the collaboration you talk about with CQRS</h3>
<p>It’s similar in principle but different in practice.</p>
<p>In a collaborative domain, an inherent property of the domain is that multiple actors operate in parallel on the same set of data. A reservation system for concerts would be a good example of a collaborative domain – everyone wants the “good seats” (although it might be better call that competitive rather than collaborative, it is effectively the same principle).</p>
<p>A customer’s name would not fall under that category. It isn’t an inherent property of the domain for multiple actors to operate on that data. While there can be multiple readers, one can easily enforce a single writer without any adverse effects. Doing that with a reservation system would cause the online system to behave as if users were lining up in front of a box office – not a desirable outcome.</p>
<p>Private data would be something like a user’s shopping cart. Until they make a purchase, that data doesn’t need to be visible anywhere. Here you could theoretically do simple CRUD – that is, until the business realizes that there’s extremely valuable information to be extracted from the historical record of things people do with their carts.</p>
<h3>I think you’re ready to make your point, so just make it already</h3>
<p>OK – so we now realize that Update and Delete don’t exist in their traditional form. Delete is really just a kind of update, and update is effectively an “upsert” – a combination of update and insert to retain history. This can be done by having ValidFrom and ValidTo columns for our data.</p>
<p>In which case, Create is really just a special case of Upsert, which looks like this:</p>
<blockquote><p>UPDATE Something SET ValidTo = NOW() WHERE Id=@Id AND ValidTo = NULL; INSERT INTO Something SET { regular values }, Id=@Id, ValidTo = NULL;</p></blockquote>
<p>And then we’d have 2 forms of Read – reading the current state (ValidTo = NULL), and reading history (ValidFrom <= Instant AND (ValidTo >= Instant OR ValidTo = NULL))</p>
<p>Here we don’t need fancy N-Tier architectures, data transfer objects, service layers, or domain models. A simple 2-Tier approach could probably suffice. We don’t need a task-based UI, events, denormalized view models, or any of that CQRS stuff. This was at the crux of my previous <a href="http://www.udidahan.com/2011/04/22/when-to-avoid-cqrs/">anti-CQRS post</a>.</p>
<p>The only thing is that this is exactly CQRS.</p>
<h3>Say what?</h3>
<p>Have we not effectively separated the responsibility of commands/upserts and queries/reads?</p>
<p>As Greg Young has said before, “the creation of 2 objects where there previously was one”.</p>
<p>Effectively 2 paths through our ABC.</p>
<p>CQRS.</p>
<p>Let me give you a second to gather your thoughts.</p>
<p>*</p>
<p>You see, CQRS is an approach, a mind-set – not a cookie cutter solution. Frameworks that guide you to applying CQRS exactly the same way everywhere are taking you in the wrong direction. The fact is that you couldn’t possibly know what your Aggregate Roots were before you figured out how to break your system down into ABCs. Attempting to create commands and events for everything will make you overcomplicate your solution.</p>
<h3>So the built-in history of this model is event-sourcing?</h3>
<p>Well, it’s not event-sourcing in the sense that we don’t necessarily have events. It achieves many of the benefits of event-sourcing by giving us the full history of what happened.</p>
<p>On the whole issue of replaying events to fix bugs – that’s a bit problematic, logically, unless we have a closed system. A closed system is one that doesn’t interact with anything else – no other systems, no users, nothing. As such, closed systems aren’t that common.</p>
<p>In an open system, one with users, let’s say there was a bug. This bug could have caused the wrong data to be written and/or shown to users. As such, users could have submitted subsequent commands based on that erroneous data that they would not have submitted otherwise. There’s no way for us to know.</p>
<p>The problem with replaying events when we fix the bug is that we’re in essence rewriting history – making it as if the user didn’t see the wrong data. The only problem is that we can’t know which events not to replay – we can’t automatically come up with the right events that should have come afterwards. We could try to sit together with our users and have them try to revise history manually, but our organization often isn’t in a bubble. Our users interacted with customers and suppliers. It isn’t feasible to try to undo the real-world impacts of this situation.</p>
<h3>Why didn’t you just tell us this from the very beginning?</h3>
<p>I did, you just weren’t listening.</p>
<p>You wanted a cookie cutter, and until you tried CQRS out as cookie cutter (and saw it create a bunch of complexity) you wouldn’t listen to anything else. </p>
<p>As developers, we’re trained to solve problems – the faster the better. Unfortunately, this causes us to be blind to things that don’t immediately present themselves as solutions.</p>
<p>When applying CQRS with ABCs, the solutions you end up with are very simple, but the process of getting there is quite hard and takes practice. Finding the boundaries of ABCs such that data isn’t duplicated between them and that data doesn’t travel between them either via RPC or publish/subscribe – it may feel impossible the first several times you try. Keep at it – it is almost always possible.</p>
<p>We haven’t touched on the whole saga/aggregate-root thing yet, but that isn’t as important until you can successfully apply the principles described here.</p>
<p>Also, this post has already gotten long enough, so it looks like now would be a good time to stop.</p>
<p>Until next time…</p>
]]></content:encoded>
			<wfw:commentRss>http://www.udidahan.com/2011/10/02/why-you-should-be-using-cqrs-almost-everywhere%e2%80%a6/feed/</wfw:commentRss>
		<slash:comments>47</slash:comments>
		</item>
		<item>
		<title>Inconsistent data, poor performance, or SOA &#8211; pick one</title>
		<link>http://www.udidahan.com/2011/09/18/inconsistent-data-poor-performance-or-soa-pick-one/</link>
		<comments>http://www.udidahan.com/2011/09/18/inconsistent-data-poor-performance-or-soa-pick-one/#comments</comments>
		<pubDate>Sun, 18 Sep 2011 16:52:17 +0000</pubDate>
		<dc:creator>udidahan</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Autonomous Services]]></category>
		<category><![CDATA[Business Rules]]></category>
		<category><![CDATA[CQRS]]></category>
		<category><![CDATA[DDD]]></category>
		<category><![CDATA[Data Access]]></category>
		<category><![CDATA[Databases]]></category>
		<category><![CDATA[Reliability]]></category>
		<category><![CDATA[SOA]]></category>

		<guid isPermaLink="false">http://www.udidahan.com/?p=1527</guid>
		<description><![CDATA[One of the things that surprises some developers that I talk to is that you don&#8217;t always get consistency even with end-to-end synchronous communication and a single database. This goes beyond things like isolation levels that some developers are aware of and is particularly significant in multi-user collaborative domains.
The problem
Let&#8217;s start with an image to [...]]]></description>
			<content:encoded><![CDATA[<p>One of the things that surprises some developers that I talk to is that you don&#8217;t always get consistency even with end-to-end synchronous communication and a single database. This goes beyond things like isolation levels that some developers are aware of and is particularly significant in multi-user collaborative domains.</p>
<h3>The problem</h3>
<p>Let&#8217;s start with an image to describe the scenario:</p>
<p><img src="http://www.udidahan.com/wp-content/uploads/Inconsistency1.gif" alt="Inconsistency" title="Inconsistency" width="600" height="285" class="aligncenter size-full wp-image-1533" /><br />
<center>Image 1. 3 transactions working in parallel on 3 entities</center></p>
<p>The main issue we have here is that the values transaction 2 gets for A and B are those from T0 &#8211; before either transaction 1 or 3 completed. The reason this is an issue is that these old values (usually together with some message data) are used to calculate what the new state of C should be. </p>
<p>Traditional optimistic concurrency techniques won&#8217;t detect any problem if we don&#8217;t touch A or B in transaction 2.</p>
<p>In short, systems today are causing inconsistency.</p>
<h3>Some solutions</h3>
<p>1. Don&#8217;t have transactions which operate on multiple entities (which probably isn&#8217;t possible for some of your most important business logic).</p>
<p>2. Turn on <a href="http://en.wikipedia.org/wiki/Multiversion_concurrency_control">multi-version concurrency control</a> &#8211; this is called snapshot isolation in MS Sql Server.</p>
<p>Yes, you need to turn it on. It&#8217;s off by default.</p>
<p>The good news is that this will stop the writing of inconsistent data to your database.<br />
The bad news is that it will probably cause your system many more exceptions when going to persist.</p>
<p>For those of you who are using transaction messaging with automatic retrying, this will end up as &#8220;just&#8221; a performance problem (unless you follow the recommendations below). For those of you who are using regular web/wcf services (over tcp/http), you&#8217;re &#8220;cross cutting&#8221; exception management will likely end up discarding all the data submitted in those requests (but since that&#8217;s what you&#8217;re doing when you run into deadlocks this shouldn&#8217;t be news to you).</p>
<h3>The solution to the performance issues</h3>
<p>Eventual consistency.</p>
<p>Funny isn&#8217;t it &#8211; all those people who were afraid of eventual consistency got <b>inconsistency</b> instead.</p>
<p>Also, it&#8217;s not enough to just have eventual consistency (like between the command and query sides of CQRS). You need to drastically decrease the size of your entities. And the best way of doing that is to partition those entities across multiple business services (also known in DDD lingo as Bounded Contexts) each with its own database.</p>
<p>This is yet another reason why I say that CQRS shouldn&#8217;t be the top level architectural breakdown. Very useful within a given business service, yes &#8211; though sometimes as small as just some sagas.</p>
<h3>Next steps</h3>
<p>It may seem unusual that the title of this post implies that SOA is the solution, yet the content clearly states that traditional HTTP-based web services are a problem. Even REST wouldn&#8217;t change matters as it doesn&#8217;t influence how transactions are managed against a database.</p>
<p>The SOA solution I&#8217;m talking about here is the one I&#8217;ve spent the last several years <a href="http://www.udidahan.com/category/soa/">blogging about</a>. It&#8217;s a different style of SOA which has services stretch up to contain parts of the UI as well as down to contain parts of the database, resulting in a composite UI and multiple databases. This is a drastically different approach than much of the literature on the topic &#8211; especially Thomas Erl&#8217;s books.</p>
<p>Unfortunately there isn&#8217;t a book out there with all of this in it (that I&#8217;ve found), and I&#8217;m afraid that with my schedule (and family) writing a book is pretty much out of the question. Let&#8217;s face it &#8211; I&#8217;m barely finding time to blog.</p>
<p>The one thing I&#8217;m trying to do more of is provide training on these topics. I&#8217;ve just finished a course in London, doing another this week in Aarhus Denmark, and another next month in San Francisco (which is now sold out). The next openings this year will be in Stockholm, London; Sydney Australia and Austin Texas will be coming in January of next year. I&#8217;ll be coming over to the US more next year so if you missed San Francisco, keep an eye out.</p>
<p>I wish there was more I could do, but I&#8217;m only one guy.</p>
<p>Hmm, maybe it&#8217;s time to change that.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.udidahan.com/2011/09/18/inconsistent-data-poor-performance-or-soa-pick-one/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>The Danger of Centralized Workflows</title>
		<link>http://www.udidahan.com/2011/07/13/the-danger-of-centralized-workflows/</link>
		<comments>http://www.udidahan.com/2011/07/13/the-danger-of-centralized-workflows/#comments</comments>
		<pubDate>Wed, 13 Jul 2011 08:05:19 +0000</pubDate>
		<dc:creator>udidahan</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Autonomous Services]]></category>
		<category><![CDATA[BPM]]></category>
		<category><![CDATA[BizTalk]]></category>
		<category><![CDATA[Business Rules]]></category>
		<category><![CDATA[EDA]]></category>
		<category><![CDATA[OO]]></category>
		<category><![CDATA[Pub/Sub]]></category>
		<category><![CDATA[SOA]]></category>
		<category><![CDATA[Testing]]></category>
		<category><![CDATA[Workflow]]></category>

		<guid isPermaLink="false">http://www.udidahan.com/?p=1493</guid>
		<description><![CDATA[It isn&#8217;t uncommon for me to have a client or student at one of my courses ask me about some kind of workflow tool. This could be Microsoft Workflow Foundation, BizTalk, K2, or some kind of BPEL/orchestration engine. The question usually revolves around using this tool for all workflows in the system as opposed to [...]]]></description>
			<content:encoded><![CDATA[<p>It isn&#8217;t uncommon for me to have a client or student at one of my courses ask me about some kind of workflow tool. This could be Microsoft Workflow Foundation, BizTalk, K2, or some kind of BPEL/orchestration engine. The question usually revolves around using this tool for all workflows in the system as opposed to the SOA-EDA-style publish/subscribe approach I espouse.</p>
<h3>The question</h3>
<p>The main touted benefit of these workflow-centric architectures is that we don&#8217;t have to change the code of the system in order to change its behavior resulting in ultimate flexibility!</p>
<p>Some of you may have already gone down this path and are shaking your heads remembering how your particular road to hell was paved with the exact same good intentions.</p>
<p>Let me explain why these things tend to go horribly wrong.</p>
<h3>What&#8217;s behind the curtain</h3>
<p>It starts with the very nature of workflow &#8211; a flow chart, is procedural in nature. First do this, then that, if this, then that, etc. As we&#8217;ve experienced first hand in our industry, procedural programming is fine for smaller problems but isn&#8217;t powerful enough to handle larger problems. That&#8217;s why we&#8217;ve come up with object-oriented programming.</p>
<p>I have yet to see an object-oriented workflow drag-and-drop engine. Yes, it works great for simple demo-ware apps. But if you try to through your most complex and volatile business logic at it, it will become a big tangled ball of spaghetti &#8211; just like if you were using text rather than pictures to code it.</p>
<p>And that&#8217;s one of the fundamental fallacies about these tools &#8211; you are still writing code. The fact that it doesn&#8217;t look like the rest of your code doesn&#8217;t change that fact. Changing the definition of your workflow in the tool IS changing your code. </p>
<h3>On productivity</h3>
<p>Sometimes people mention how much more productive it would be to use these tools than to write the code &#8220;by hand&#8221;. Occasionally I hear about an attempt to have &#8220;the business&#8221; use these tools to change the workflows themselves &#8211; without the involvement of developers (&#8221;imagine how much faster we could go without those pesky developers!&#8221;).</p>
<p>For those of us who have experienced this first-hand, we know that&#8217;s all wrong. </p>
<p>If &#8220;the business&#8221; is changing the workflows without developer involvement, invariably something breaks, and then they don&#8217;t know what to do. They haven&#8217;t been trained to think the way that developers have &#8211; they don&#8217;t really know how to debug. So the developers are brought back in anyway and from that point on, the business is once again giving requirements and the devs are the one implementing it.</p>
<p>Now when it comes to developer productivity, I can tell you that the keyboard is at least 10x more productive than the mouse. I can bang out an if statement in code much faster than draggy-dropping a diamond on the canvas, and two other activities for each side of the clause.</p>
<h3>On maintainability</h3>
<p>Sometimes the visualization of the workflow is presented as being much more maintainable than &#8220;regular code&#8221;. </p>
<p>When these workflows get to be to big/nested/reused, it ends up looking like the wiring diagram of an Intel chip (or worse). Check out the following diagram taken from the DailyWTF on a <a href="http://thedailywtf.com/Articles/The_Customer-Friendly_System.aspx">customer friendly system</a>:</p>
<p><img src="http://www.udidahan.com/wp-content/uploads/stateModel.gif" alt="stateModel" title="stateModel" width="500" height="564" /></p>
<p>The bigger these get, the less maintainable they are.</p>
<p>Now, some would push back on this saying that a method with 10,000 lines of code in it may be just as bad, if not worse. The thing is that these workflow tools guide developers down a path where it is very likely to end up with big, monolithic, procedural, nested code. When working in real code, we know we need to take responsibility for the cleanliness of our code using object-orientation, patterns, etc and refactoring things when they get too messy.</p>
<p>Here is where I&#8217;d bring up the SOA/pub-sub approach as an alternative &#8211; there is no longer this idea of a centralized anything. You have small pieces of code, each encapsulating a single business responsibility, working in concert with each other &#8211; reacting to each others events.</p>
<h3>Productivity take 2: testing and version control</h3>
<p>If you&#8217;re going to take your most complex and volatile business logic and put it into these workflow tools, have you thought about how your going to test it? How do you know that it works correctly? It tends to be VERY difficult to unit-test these kinds of workflows.</p>
<p>When a developer is implementing a change request, how do they know what other workflows might have been broken? Do they have to manually go through each and every scenario in the system to find out? How&#8217;s that for productivity?</p>
<p>Assuming something did break and the developer wants to see a diff &#8211; what&#8217;s different in the new workflow from the old one, what would that look like? When working with a team, the ability to diff and merge code is at the base of the overall team productivity.</p>
<p>What would happen to your team if you couldn&#8217;t diff or merge code anymore?<br />
In this day and age, it should be considered irresponsible to develop without these version control basics.</p>
<h3>In closing</h3>
<p>There are some cases where these tools might make sense, but those tend to be much more rare than you&#8217;d expect (and there are usually better alternatives anyway). Regardless, the architectural analysis should start without the assumption of centralized workflow, database, or centralized anything for that matter.</p>
<p>If someone tries to push one of these tools/architectures on you, don&#8217;t walk away &#8211; run!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.udidahan.com/2011/07/13/the-danger-of-centralized-workflows/feed/</wfw:commentRss>
		<slash:comments>45</slash:comments>
		</item>
		<item>
		<title>Service Boundaries Aren&#8217;t Process Boundaries</title>
		<link>http://www.udidahan.com/2011/07/03/service-boundaries-arent-process-boundaries/</link>
		<comments>http://www.udidahan.com/2011/07/03/service-boundaries-arent-process-boundaries/#comments</comments>
		<pubDate>Sun, 03 Jul 2011 12:23:37 +0000</pubDate>
		<dc:creator>udidahan</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Autonomous Services]]></category>
		<category><![CDATA[ESB]]></category>
		<category><![CDATA[SOA]]></category>
		<category><![CDATA[Web Services]]></category>

		<guid isPermaLink="false">http://www.udidahan.com/?p=1482</guid>
		<description><![CDATA[Richard Veryard blogged about the topic of service boundaries in SOA, specifically asking why aren&#8217;t more people talking about service boundaries &#8211; especially if they&#8217;re such a core principle in SOA.
I can only speak for myself on this one, but I guess it&#8217;s that there&#8217;s just so many times you can repeat yourself.
So, why this [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.udidahan.com/wp-content/uploads/fence1_14.jpg" alt="boundaries" title="boundaries" width="286" height="217" style="float:right; margin-left:10px; margin-bottom:10px;" />Richard Veryard <a href="http://rvsoapbox.blogspot.com/2011/07/service-boundaries-in-soa.html">blogged</a> about the topic of service boundaries in SOA, specifically asking why aren&#8217;t more people talking about service boundaries &#8211; especially if they&#8217;re such a core principle in SOA.</p>
<p>I can only speak for myself on this one, but I guess it&#8217;s that there&#8217;s just so many times you can repeat yourself.</p>
<p>So, why this post?</p>
<p>Well, Richard was able to dig up an old (2004) presentation I gave about SOA in which I said:</p>
<blockquote><p>&#8220;Services run in a separate process from their clients<br />
A boundary must be crossed to get from the client to the service – network, security, …&#8221;</p></blockquote>
<p>And 7 years later I can say, hand on heart, <b>I was wrong</b>.</p>
<p>Luckily, I&#8217;ve spent much of those past 7 years trying to correct that recommendation. One blog post in which I tried to do that (in mid-2007) was <a href="http://www.udidahan.com/2007/05/19/on-intermediation-and-soa/">On Intermediation and SOA</a> in which I described the relationship between systems (i.e process boundaries) and services:</p>
<blockquote><p>&#8220;all of these “systems” might just end up within the same service, or having parts of them being used by multiple services</p></blockquote>
<p>There can also be multiple services (or, more accurately, parts of multiple services) deployed together in the same system/process. </p>
<p>And this is nothing new &#8211; in the <a href="http://en.wikipedia.org/wiki/4%2B1_Architectural_View_Model">4+1 Architectural View Model</a> by Philippe Kruchten (1995) we can see very clearly the differentiation between the Logical View (our services) and the Physical View (a.k.a the Deployment View). </p>
<p>These views are orthogonal to each other &#8211; multiple elements from one view can map to a single element in another view (and vice versa).</p>
<p>This, if anything, makes it that much harder to identify service boundaries &#8211; if they have nothing to do with the existing applications and systems, then what are they? In my blog post on <a href="http://www.udidahan.com/2010/11/15/the-known-unknowns-of-soa/">The Known Unknowns of SOA</a> I point to the fact that <b>Business Capabilities</b> are much more appropriate constructs than, say, web services which (as it says in the referenced post) &#8220;[are] merely a standardized approach to accessing functionality on remote systems&#8221;.</p>
<p>As I bring this post to a close, I&#8217;m feeling more comfortable rehashing material I&#8217;ve published before:</p>
<p><a href="http://www.udidahan.com/2010/11/08/logical-and-physical-architecture/">Logical and Physical Architecture</a></p>
<p>and the rest of the SOA category on my blog <a href="http://www.udidahan.com/category/soa/">here</a>.</p>
<p>Happy boundary hunting.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.udidahan.com/2011/07/03/service-boundaries-arent-process-boundaries/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Enterprise, SaaS, and Platforms</title>
		<link>http://www.udidahan.com/2011/06/19/enterprise-saas-and-platforms/</link>
		<comments>http://www.udidahan.com/2011/06/19/enterprise-saas-and-platforms/#comments</comments>
		<pubDate>Sun, 19 Jun 2011 12:01:01 +0000</pubDate>
		<dc:creator>udidahan</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[Management]]></category>

		<guid isPermaLink="false">http://www.udidahan.com/?p=1472</guid>
		<description><![CDATA[So it&#8217;s been about a year and a half since my promise to follow up on my Non-Functional Architectural Woes post. Just to give you a short summary, in that post I talked about the fact that many of today&#8217;s &#8220;best practices&#8221; for software design (like layering, ORMs, and web services) don&#8217;t actually provide the [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.udidahan.com/wp-content/uploads/mission_impossible.jpg" alt="mission_impossible" title="mission_impossible" width="250" height="189" style="float:right; margin-left:10px; margin-bottom:10px;" />So it&#8217;s been about a year and a half since my promise to follow up on my <a href="http://www.udidahan.com/2010/01/12/non-functional-architectural-woes/">Non-Functional Architectural Woes</a> post. Just to give you a short summary, in that post I talked about the fact that many of today&#8217;s &#8220;best practices&#8221; for software design (like layering, ORMs, and web services) don&#8217;t actually provide the promised flexibility when requirements end up changing.</p>
<p>Since that post I&#8217;ve blogged about many techniques and approaches to identify better boundaries (like with SOA and DDD) and I&#8217;m seeing more and more developers starting to apply them.</p>
<p>This post will be slightly different.</p>
<p>You see, occasionally we technical people will get requirements that can&#8217;t easily be broken down by functional boundaries. Sometimes the business calls this a &#8220;platform&#8221; &#8211; here&#8217;s an example:</p>
<p>&#8220;We want a flexible, customizable workflow-driven platform that allows end-users to add their own columns to any screen able to support massive datasets for large enterprise customers that will also be intuitive and easy to use for our SaaS push to small and medium-sized businesses (SMBs) &#8211; oh, and then it needs to be multi-tenant too. Did I mention that we promised this would be ready for our most important client by the end of the year?&#8221;</p>
<p>There is only one reasonable answer to the above:</p>
<p>&#8220;I know you want it but, I&#8217;m very sorry, you can&#8217;t have that. It isn&#8217;t possible to do that with one system.&#8221;</p>
<p>It&#8217;s really rare for a technical person to say something like that. The simple reason is that in software, we believe that almost everything is fundamentally possible &#8211; given enough time/money/resources. So, when someone in business comes to us with the requirements above, we say &#8220;It&#8217;s *possible*&#8221;, loosely translated to &#8220;We can&#8217;t prove that that&#8217;s impossible&#8221;.</p>
<p>There are many reasons why you can&#8217;t be SaaS and Enterprise at the same time &#8211; not all of them dealing with software. The marketing, sales, and support stories of each of those markets is VERY different. In the enterprise you&#8217;re usually working with professional services people that customize the generic product &#8211; which then becomes a backwards-compatibility requirement for new development. This will hinder the development team&#8217;s ability to roll out the new shiny features needed to remain competitive in the SaaS space.</p>
<p>In the cases where I&#8217;ve been brought in to help clients with these kinds of systems, I try to work my way up to the person in management who is in charge of the project/product &#8211; often the CEO. Then, in the nicest way possible, I explain that really the only way to have your cake and eat it too is to create 2 companies &#8211; each one focused on its own space &#8211; Saas and Enterprise; each one with its own development team, feature set, release schedule, etc.</p>
<p>There&#8217;s a reason that there&#8217;s an SAP *and* a Salesforce &#8211; it&#8217;s because no one can be all things to all people. It&#8217;s hard enough to become a market leader in just one space. Trying to do both is VERY expensive, and increases the chance of the project failing from the average 60-70% in the industry to probably about 99.9%.</p>
<p>Hope that will save you some grief.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.udidahan.com/2011/06/19/enterprise-saas-and-platforms/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>When to avoid CQRS</title>
		<link>http://www.udidahan.com/2011/04/22/when-to-avoid-cqrs/</link>
		<comments>http://www.udidahan.com/2011/04/22/when-to-avoid-cqrs/#comments</comments>
		<pubDate>Fri, 22 Apr 2011 20:32:50 +0000</pubDate>
		<dc:creator>udidahan</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[CQRS]]></category>
		<category><![CDATA[DDD]]></category>
		<category><![CDATA[Databases]]></category>
		<category><![CDATA[Messaging]]></category>
		<category><![CDATA[SOA]]></category>
		<category><![CDATA[Scalability]]></category>
		<category><![CDATA[Simplicity]]></category>
		<category><![CDATA[Testing]]></category>

		<guid isPermaLink="false">http://www.udidahan.com/?p=1441</guid>
		<description><![CDATA[It looks like that CQRS has finally &#8220;made it&#8221; as a full blown &#8220;best practice&#8221;.
Please accept my apologies for my part in the overly-complex software being created because of it.
I&#8217;ve tried to do what I could to provide a balanced view on the topic with posts like Clarified CQRS and Race Conditions Don&#8217;t Exist.
It looks [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.udidahan.com/wp-content/uploads/image20.png" alt="which way?" title="which way?" style="float:right; margin-left:10px; margin-bottom:10px;" />It looks like that CQRS has finally &#8220;made it&#8221; as a full blown &#8220;best practice&#8221;.</p>
<p>Please accept my apologies for my part in the overly-complex software being created because of it.</p>
<p>I&#8217;ve tried to do what I could to provide a balanced view on the topic with posts like <a href="http://www.udidahan.com/2009/12/09/clarified-cqrs/">Clarified CQRS</a> and <a href="http://www.udidahan.com/2010/08/31/race-conditions-dont-exist/">Race Conditions Don&#8217;t Exist</a>.</p>
<p>It looks like that wasn&#8217;t enough, so I&#8217;ll go right out and say it:</p>
<p>Most people using CQRS (and <a href="http://codebetter.com/gregyoung/2010/02/20/why-use-event-sourcing/">Event Sourcing</a> too) shouldn&#8217;t have done so.</p>
<h3>Should we really go back to N-Tier?</h3>
<p>When not using CQRS (which is the majority of the time), you don&#8217;t need N-Tier either.</p>
<p>You see, if you&#8217;re not in a collaborative domain then you don&#8217;t have multiple writers to the same logical set of data as an inherent property of your domain. As such, having a single database where all data lives isn&#8217;t really necessary. </p>
<p>Data is inherently partitioned by who owns it.</p>
<p>Let&#8217;s take the online shopping cart as an example. There aren&#8217;t any use cases where users operate on each others&#8217; carts &#8211; ergo, not collaborative, therefore not a good candidate for CQRS. Same goes for user profiles, and tons of other cases.</p>
<p>So why is it that we need a separate tier to run our business logic?</p>
<p>Originally, the application server tier was introduced for improved scalability, but specifically around managing the connection pool to the database. Increasing numbers of clients (when each had its own user/account for connecting to the database) caused problems. Luckily, most web applications side-step this problem &#8211; that is, until someone got the idea that the web server was only supposed to run the UI layer, and the Business Logic layer would be on a separate application server tier.</p>
<p>Rubbish &#8211; see Fowler&#8217;s First Law of Distribution: Don&#8217;t.</p>
<p>Keep it all on one tier. Same goes for smart clients.<br />
No, Silverlight, you don&#8217;t count &#8211; architecturally speaking, you&#8217;re a glorified browser.</p>
<h3>But what about scalability?</h3>
<p>In a non-collaborative domain, where you can horizontally add more database servers to support more users/requests/data at the same time you&#8217;re adding web servers &#8211; there is no real scalability problem (caveat, until you&#8217;re Amazon/Google/Facebook scale). </p>
<p>Database servers can be cheap &#8211; if using MySQL/SQL Express/others. </p>
<h3>But what about the built-in event-log CQRS/ES gives us?</h3>
<p>Architectural gold-plating / stealing from the business.</p>
<p>Who put you in a position to decide that development time and resources should be diverted from short-term business-value-adding features to support a non-functional requirement that the business didn&#8217;t ask for?</p>
<p>If you sat down with them, explaining the long-term value of having an archive of all actions in the system, and they said OK, build this into the system from the beginning, that would be fine. Most people who ask me about CQRS and/or Event Sourcing skip this step.</p>
<p>Finally, you can usually implement this specific requirement with some simple interception and logging. Don&#8217;t over-engineer the solution. If using messaging, you can get this by turning on journaling, or if you want to centralize this archive, NServiceBus can forward all messages to a specific queue. </p>
<p>Don&#8217;t forget that this storage has a cost &#8211; including administration. Nothing is free.</p>
<h3>What about the &#8220;proof of correctness&#8221; in Event Sourcing</h3>
<p>I&#8217;ve heard statements made that when you use the events that flowed into/through your system <b>AS</b> your system&#8217;s data, rather than transforming those events to some other schema (relational or otherwise) and storing the result &#8211; you can prove that your system behaves correctly.</p>
<p>Let me put it this way:</p>
<p>No programming technique used by humans will prevent those same humans from creating bugs.<br />
No testing technique used by humans will prevent those same humans from not catching those bugs.<br />
* Automated tests &#8211; see programming technique.</p>
<p>While having a full archive of all events can allow us to roll the system back to some state, fix a bug, and roll forwards, that assumes that we&#8217;re in a closed system. We have users which are outside the system. If a user made a decision based on data influenced by the bug, there&#8217;s no automated way for us to know that, or correct for it as we roll forwards.</p>
<p>In short, we&#8217;re interested in the business&#8217; behavior &#8211; as composed of user and system behavior. No proof can exist.</p>
<h3>Umm, so where should we use it</h3>
<p>If you&#8217;ve uncovered a scenario where you&#8217;re wondering &#8220;first-one-wins, or last-one-wins&#8221;, that&#8217;s often a good candidate for a place where CQRS <b>could</b> make sense. Then re-read my <a href="http://www.udidahan.com/2010/08/31/race-conditions-dont-exist/">Race Conditions Don&#8217;t Exist post</a>.</p>
<p>Also, CQRS should not be your top-level architectural pattern &#8211; that would be SOA.<br />
CQRS, if used at all, would be used inside a service boundary only.</p>
<p>Given that SOA guides us away from having a given 3rd normal form entity exist in any one service, it is unlikely that the building blocks of your CQRS design will be those kinds of entities. Most 3rd normal form one-to-many and many-to-many relationships simply do not exist when doing SOA and CQRS properly.</p>
<p>Therefore, I&#8217;m sorry to say that most sample application you&#8217;ll see online that show CQRS are architecturally wrong. I&#8217;d also be extremely wary of frameworks that guide you towards an entity-style aggregate root CQRS model.</p>
<h3>In Summary</h3>
<p>So, when should you avoid CQRS?</p>
<p>The answer is most of the time.</p>
<p>Here&#8217;s the strongest indication I can give you to know that you&#8217;re doing CQRS correctly: Your aggregate roots are sagas.</p>
<p>And the biggest caveat &#8211; the above are generalizations, and can&#8217;t necessarily be true for every specific scenario. If you&#8217;re Greg Young, then you probably can (and will) decide on your own on these matters. For everybody else, please take these warnings to heart. There have been far too many clients that have come to me all mixed up with their use CQRS in areas where it wasn&#8217;t warranted.</p>
<p>If you want to know everything you need to know to apply CQRS appropriately, please come to <a href="http://www.udidahan.com/training/#Advanced_Distributed_System_Design">my course</a> &#8211; there is so much unlearning to do first that just can&#8217;t happen via a series of blog posts.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.udidahan.com/2011/04/22/when-to-avoid-cqrs/feed/</wfw:commentRss>
		<slash:comments>34</slash:comments>
		</item>
		<item>
		<title>Integration: How and Where</title>
		<link>http://www.udidahan.com/2011/04/08/integration-how-and-where/</link>
		<comments>http://www.udidahan.com/2011/04/08/integration-how-and-where/#comments</comments>
		<pubDate>Fri, 08 Apr 2011 09:18:41 +0000</pubDate>
		<dc:creator>udidahan</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[BizTalk]]></category>
		<category><![CDATA[ESB]]></category>
		<category><![CDATA[Messaging]]></category>
		<category><![CDATA[NServiceBus]]></category>
		<category><![CDATA[Pub/Sub]]></category>
		<category><![CDATA[SOA]]></category>

		<guid isPermaLink="false">http://www.udidahan.com/?p=1428</guid>
		<description><![CDATA[One of the topics that comes up a lot in the context of an Enterprise Service Bus (ESB) is that of integration. Unfortunately, many people take their ideas of reuse and design their integration as being done from a single place &#8211; both logical and physical. That unfortunately creates a bottleneck for all integration activities, [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.udidahan.com/wp-content/uploads/integration.jpg" alt="integration" title="integration" width="200" height="150" style="float:right; margin-left:10px; margin-bottom:10px;" />One of the topics that comes up a lot in the context of an Enterprise Service Bus (ESB) is that of integration. Unfortunately, many people take their ideas of reuse and design their integration as being done from a single place &#8211; both logical and physical. That unfortunately creates a bottleneck for all integration activities, where some are likely to be higher priority than others.</p>
<h3>The ugly truth</h3>
<p>You don&#8217;t need an ESB for integration.</p>
<p>There. I&#8217;ve said it. </p>
<p>Most of the ESB products on the market, in focusing on integration, are addressing the wrong problem.</p>
<h3>What integration is about</h3>
<p>There are three primary components to integration &#8211; data format translation, protocol bridging, and logic. Let&#8217;s take the Agile &#8220;simplest solution that could possibly work&#8221; motto and apply it to these elements:</p>
<ol>
<li>Data format translation<br/>
<ul>
<li>Use something like <a href="http://www.altova.com/mapforce.html">MapForce</a> (from Altova, the guys behind XMLSpy).</li>
<li>At under $1200 for a dev license and handling mapping to/from XML, EDI, flat files, and relational databases, you can host the resulting mapping in any endpoint, as XSLT or even Java/C# &#8211; no need to have &#8220;the bus&#8221; do this for you.</li>
</ul>
</li>
<li>Protocol bridging<br/>
<ul>
<li>Use something like <a href="http://www.nsoftware.com/subscriptions/">/n software</a></li>
<li>At about $1500 for a dev license, you get solutions for FTP, HTTP, SMTP, POP, IMAP, LDAP, DNS, RSS, SMS, Jabber, SOAP, WebDav, etc and, again &#8211; you can host the DLLs in any endpoint you want. Don&#8217;t need expensive buses for this</li>
</ul>
</li>
<li>Logic<br/><br />
This is all you &#8211; no technology can do this for you. If anything, the most important thing is to get all the ugly mapping and protocol bridging stuff out of the way and let you focus on your logic. This is Single Responsibility Principle (un)common sense.
</li>
</ol>
<h3>Digging deeper into the logic</h3>
<p>The interesting thing about most of the protocol stuff mentioned above is that they&#8217;re inherently <b>unreliable</b> and also their performance at runtime is unknowable due to the total load on the target server.</p>
<p>We wouldn&#8217;t want any of the above situations to cause our integration to &#8220;get stuck&#8221;. As such, it is best we think of our integration logic as a long-running process that manages other endpoints which do the actual protocol bridging and data transformations.</p>
<p>This is one of the areas where NServiceBus, with its <a href="http://www.nservicebus.com/Sagas.aspx">sagas</a> can actually help a lot. Just like the other pieces of integration mentioned above, these sagas can run on any endpoint.</p>
<p>You could alternatively look at other technologies like BizTalk and Business Process Execution Language (BPEL) engines, though many of those are designed to be physically centralized (just like many of the ESBs out there).</p>
<p>By the way, if you do want to use NServiceBus together with BizTalk, Michael Stephenson has published some great white papers on getting the two to work together. His latest is about integrating NServiceBus into BizTalk&#8217;s RFID processes &#8211; <a href="http://social.technet.microsoft.com/wiki/contents/articles/biztalk-rfid-amp-nservicebus.aspx">check it out</a>.</p>
<h3>Putting it all together</h3>
<p>When we take all of these pieces and look at them in a cohesive architecture, here&#8217;s what it can look like:</p>
<p><img src="http://www.udidahan.com/wp-content/uploads/DistributedIntegration.jpg" alt="Distributed Integration" title="Distributed Integration" width="600" height="385" class="alignnone size-full wp-image-1432" /></p>
<p>As you can see, integration is physically distributed across multiple endpoints.</p>
<p>Not only that, but the integration logic is kept separate from the protocol bridging and data transformation, enabling independent versioning of each. Just as important, it makes it <b>much</b> easier to unit test that the integration logic is correct as we don&#8217;t have to simulate the target technologies.</p>
<h3>Costs</h3>
<p>As you can see, you can get integration capabilities just as powerful as if you went with something like BizTalk, but without creating a single point of failure in your architecture. In terms of costs, it&#8217;s also quite a bit cheaper.</p>
<p>For a high availability BizTalk deployment, you&#8217;ll be paying <a href="http://www.microsoft.com/biztalk/en/us/pricing-licensing.aspx">over $40,000 per CPU</a> for the Enterprise Edition, not including the extra $7000 per CPU for SQL Server Standard Edition (clustered). For a clustered 4-CPU mid-size deployment, you&#8217;d be in the area of $200,000.</p>
<p>For the distributed integration solution above, you&#8217;d be paying around $2700 in dev licenses (for /n software and Altova MapForce), and $500 per core for NServiceBus Standard Edition. The reason there&#8217;s per-core licensing for NServiceBus is that in a virtualized environment, you&#8217;ll be provisioning virtual cores to your virtual machines. No reason to pay for a quad-core CPU when all you&#8217;re using is a single core. You can also use any number of cores running NServiceBus Express Edition at no cost, so a mid-size deployment with say 8 cores running Standard Edition, and another 24 cores running Express Edition would cost (with the volume discount) an additional $3800 &#8211; a total cost of $6,500.</p>
<p>BizTalk: $200,000 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; NServiceBus: $6,500</p>
<p>&#8216;Nuff said.</p>
<h3>In closing</h3>
<p>We&#8217;ve been bitten by centralized architectures before.</p>
<p>By having our integration distributed, we can version, upgrade, and scale each piece independently.</p>
<p>You&#8217;ve seen how we can use simple, lightweight, and inexpensive technologies to create distributed integration solutions just as powerful and robust as the centralized ESB vendor-offerings out there, but at a tiny fraction of the cost.</p>
<p>Next time the topic of integration is brought up, you&#8217;ll know not to be suckered in by re-branded EAI brokers.</p>
<p><a href="http://www.nservicebus.com/">Learn more about NServiceBus</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.udidahan.com/2011/04/08/integration-how-and-where/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Bus and Broker Pub/Sub Differences</title>
		<link>http://www.udidahan.com/2011/03/24/bus-and-broker-pubsub-differences/</link>
		<comments>http://www.udidahan.com/2011/03/24/bus-and-broker-pubsub-differences/#comments</comments>
		<pubDate>Thu, 24 Mar 2011 21:22:13 +0000</pubDate>
		<dc:creator>udidahan</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[BizTalk]]></category>
		<category><![CDATA[EDA]]></category>
		<category><![CDATA[ESB]]></category>
		<category><![CDATA[MSMQ]]></category>
		<category><![CDATA[Messaging]]></category>
		<category><![CDATA[NServiceBus]]></category>
		<category><![CDATA[Pub/Sub]]></category>
		<category><![CDATA[SOA]]></category>

		<guid isPermaLink="false">http://www.udidahan.com/?p=1421</guid>
		<description><![CDATA[One of the things which often confuses people using NServiceBus for the first time is that it only allows an endpoint to subscribe to a given event from a single other publishing endpoint. The rule that there can only be a single publisher for a given event type is one of the things that differentiates [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.udidahan.com/wp-content/uploads/difference_of_opinion.jpg" alt="differences" title="differences" width="250" height="150" style="float:right; margin-left:10px; margin-bottom:10px;" />One of the things which often confuses people using NServiceBus for the first time is that it only allows an endpoint to subscribe to a given event from a single other publishing endpoint. The rule that there can only be a single publisher for a given event type is one of the things that differentiates buses from brokers, though both obviously allow you to have multiple subscribers.</p>
<h3>Brokers</h3>
<p>Message brokers, more broadly known and used on the Java platform, don&#8217;t come with this constraint. For example, when using ActiveMQ, you can have any number of endpoints come to the broker and publish a message under a given topic. </p>
<p>So where&#8217;s the problem?</p>
<p>It&#8217;s all about accountability.</p>
<p>Let&#8217;s say you&#8217;ve subscribed to a given topic, and have received two events &#8211; one telling you that the price of bananas next week will be $1/kg and another telling you that it&#8217;ll be $2/kg. </p>
<p>Which one is right?</p>
<p>Especially given that those events may have been published by any other endpoint via the broker.</p>
<p>Is it first one wins? Last one wins? How about first one sent vs. first one received? Ditto for last. As a subscriber, can you really be held accountable for having the logic to choose the right one? Shouldn&#8217;t this responsibility have fallen to the publishing side?</p>
<p>This is one of the big drawbacks of the broker, hub and spoke architecture. No responsibility. No single source of truth &#8211; unless everybody&#8217;s going to some central database, in which case &#8211; what&#8217;s the point of all this messaging anyway?</p>
<h3>Buses</h3>
<p>The Bus Architectural Style is all about accountability. If you are going to publish an event, you are accountable for the correctness of the data in that event &#8211; there is no central database that a subscriber can go to &#8220;just in case&#8221;. And the only way that you can be held accountable, is if you have full responsibility &#8211; ergo, you&#8217;re the only one who can publish that type of event.</p>
<p>If you say bananas are going to cost $1/kg next week, that&#8217;s that. Subscribers will not hear from anybody else on that topic.</p>
<p>Now, this is not to say that you can&#8217;t have more than one <b>physical</b> publishing endpoint.</p>
<p>You see, buses differentiate between the logical and the physical. Brokers tend to assume that the physical hub-and-spoke topology is also the logical.</p>
<p>In a bus, while there can only be one <b>logical</b> endpoint publishing a given type of event, that endpoint can be physically scaled out across multiple machines. It is the responsibility of the bus to provide infrastructure facilities to allow for that to happen in such a way that to subscribers, it still appears as if there is really only one publishing endpoint.</p>
<p>The same is true about the subscriber &#8211; one logical subscribing endpoint may be scaled out across multiple machines.</p>
<h3>Product Mix-ups</h3>
<p>Unfortunately, there are many broker-style technologies out there that are being marketed under the banner of the Enterprise Service Bus. While some products have the ability to be deployed in both a centralized and distributed fashion (sometimes called &#8220;federated&#8221; or &#8220;embedded&#8221; mode), many do not enforce the &#8220;single publishing endpoint per event-type&#8221; rule.</p>
<p>Without this constraint, it is just too easy to make mistakes.</p>
<h3>NServiceBus</h3>
<p>By enforcing this constraint, we see the same kind of question appear on the discussion group time and time again:</p>
<p>&#8220;I have an Audit event that I&#8217;d like all of my machines to publish, and have one machine subscribe to them all, but NServiceBus won&#8217;t let me. How do I make NServiceBus support this scenario?&#8221;</p>
<p>And the answer is the same every time:</p>
<p>&#8220;You should have all the machines <b>Send</b> the Audit message (configured to go to the single machine handling that message), and not Publish. It is not an event until its been handled by the endpoint responsible for it.&#8221;</p>
<p>The semantics of the message matter a lot.</p>
<p>When looking at Service-Oriented Architecture, these messages are the contract and, as any lawyer will tell you, contracts need to be explicit and the intentions really need to be spelled out &#8211; otherwise the contract is practically worthless.</p>
<h3>In closing</h3>
<p>Friction is sometimes a good thing &#8211; it prevents us from making mistakes. It keeps cars on the road. And because that&#8217;s not enough friction, we introduce curbs as well.</p>
<p>If you&#8217;re looking for a service bus technology for your next project, check that it&#8217;ll give you the friction that you need to keep everybody safe. Really check what it is that the vendors are offering you &#8211; more often than not, it&#8217;s some ESB lipstick on a broker pig.</p>
<p>To learn more about how NServiceBus supports this kind of publish/subscribe, <a href="http://www.nservicebus.com/PubSub.aspx">click here</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.udidahan.com/2011/03/24/bus-and-broker-pubsub-differences/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Careful with Content-Based Routing</title>
		<link>http://www.udidahan.com/2011/03/20/careful-with-content-based-routing/</link>
		<comments>http://www.udidahan.com/2011/03/20/careful-with-content-based-routing/#comments</comments>
		<pubDate>Sun, 20 Mar 2011 15:32:00 +0000</pubDate>
		<dc:creator>udidahan</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[ESB]]></category>
		<category><![CDATA[Messaging]]></category>
		<category><![CDATA[NServiceBus]]></category>
		<category><![CDATA[SOA]]></category>

		<guid isPermaLink="false">http://www.udidahan.com/?p=1416</guid>
		<description><![CDATA[Every once in a while I get clients who ask me why NServiceBus doesn&#8217;t support content-based routing. My answer sometimes surprises them, &#8220;because it is a dangerous pattern that should usually be avoided&#8221;.
Content-Based Routing and ESBs
Since content-based routing often appears on feature lists for various ESBs, many people consider them to be a necessary part [...]]]></description>
			<content:encoded><![CDATA[<p>Every once in a while I get clients who ask me why NServiceBus doesn&#8217;t support content-based routing. My answer sometimes surprises them, &#8220;because it is a dangerous pattern that should usually be avoided&#8221;.</p>
<h2>Content-Based Routing and ESBs</h2>
<p>Since content-based routing often appears on feature lists for various ESBs, many people consider them to be a necessary part of systems built on SOA principles. The pattern also appears in the book Enterprise Integration Patterns, which apparently is also a convincing reason to use it, even though the book <a href="http://www.eaipatterns.com/ContentBasedRouter.html">specifically states</a>:</p>
<blockquote><p>
&#8220;When implementing a Content-Based Router, special caution should be taken to make the routing function easy to maintain as the router can become a point of frequent maintenance.&#8221;
</p></blockquote>
<p>That&#8217;s right &#8211; maintenance nightmare.</p>
<h2>For Example</h2>
<p>Let&#8217;s take a real-world example &#8211; a trading system where users can put orders for stock and for forex (money from other countries). </p>
<p>We&#8217;d start by creating a message that can be sent by a client:</p>
<p><!-- code formatted by http://manoli.net/csharpformat/ --></p>
<pre class="csharpcode">
<span class="kwrd">public</span> <span class="kwrd">class</span> PlaceOrder : IMessage
{
    <span class="kwrd">public</span> OrderTypeEnum OrderType { get; set; }
    <span class="kwrd">public</span> <span class="kwrd">string</span> Code { get; set; }
    <span class="kwrd">public</span> <span class="kwrd">double</span> Amount { get; set; }
}

<span class="kwrd">public</span> <span class="kwrd">enum</span> OrderTypeEnum
{
    Stock,
    Forex
}</pre>
<p>Clients would send messages by using code like the following:</p>
<pre class="csharpcode">
Bus.Send&lt;PlaceOrder&gt;(m =&gt; {
    m.OrderType = OrderTypeEnum.Stock;
    m.Code = <span class="str">"MSFT"</span>;
    m.Amount = 300;
    m.SetHeader("AccountId", myAccountId);
});</pre>
<p>The header is the way that clients identify themselves in the system.</p>
<p>Let&#8217;s say that the logic for handling the different types of orders is different, but also that we&#8217;d like the logic to be deployed to different endpoints. One reason we might want to do this is so that we can independently scale each of these endpoints. This is where it would appear we&#8217;d need some content-based routing &#8211; having some code that looks at the OrderType property and decides where to route based on its value.</p>
<p>Before we get into solutions, let&#8217;s make this more involved.</p>
<p>Not only do we want to route based on OrderType, but we want to use the account ID in the header to check in our database (or via a web service) if the account belongs to one of our VIP customers, and if so, it should be given higher priority. </p>
<h2>Content-Based Routing and Brokers</h2>
<p>We can see that if we were to go with a content-based routing solution, this would drive our architecture to a hub-and-spoke model where the hub becomes quite large and complex, as well as likely becoming a bottleneck in terms of performance.</p>
<p>This logically centralized place through which all communication flows defines the Broker architectural style &#8211; not that of a Bus. In the Bus architectural style, there is no logical (or physical) hub. You can think of it as a kind of peer-to-peer setup. Just like you wouldn&#8217;t want ethernet getting involved in applicative routing decisions, neither should your bus get involved.</p>
<h2>Business-Topology Mapping Solutions</h2>
<p>Instead, when following the Bus architectural style &#8211; we look at mapping stable business characteristics to bus-level topology. At one level, that would mean defining two different message types for our different types of trades:</p>
<p><!-- code formatted by http://manoli.net/csharpformat/ --></p>
<pre class="csharpcode">
<span class="kwrd">public</span> <span class="kwrd">abstract</span> <span class="kwrd">class</span> PlaceOrder
{
    <span class="kwrd">public</span> <span class="kwrd">string</span> Code { get; set; }
    <span class="kwrd">public</span> <span class="kwrd">double</span> Amount { get; set; }
}

<span class="kwrd">public</span> <span class="kwrd">class</span> PlaceStockOrder : PlaceOrder { }

<span class="kwrd">public</span> <span class="kwrd">class</span> PlaceForexOrder : PlaceOrder { }</pre>
<p>Once we have two different message types, then we can configure the client to have those statically sent to different endpoints like this:</p>
<p><!-- code formatted by http://manoli.net/csharpformat/ --></p>
<pre class="csharpcode">
<span class="kwrd">&lt;</span><span class="html">UnicastBusConfig</span><span class="kwrd">&gt;</span>
  <span class="kwrd">&lt;</span><span class="html">MessageEndpointMappings</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">add</span> <span class="attr">Messages</span><span class="kwrd">="Messages.PlaceStockOrder, Messages"</span> <span class="attr">Endpoint</span><span class="kwrd">="Stock"</span> <span class="kwrd">/&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">add</span> <span class="attr">Messages</span><span class="kwrd">="Messages.PlaceForexOrder, Messages"</span> <span class="attr">Endpoint</span><span class="kwrd">="Forex"</span> <span class="kwrd">/&gt;</span>
  <span class="kwrd">&lt;/</span><span class="html">MessageEndpointMappings</span><span class="kwrd">&gt;</span>
<span class="kwrd">&lt;/</span><span class="html">UnicastBusConfig</span><span class="kwrd">&gt;</span></pre>
<p>And when it comes to handling our VIP customers, the recommendation would be to have those customers be served by a different set of web servers &#8211; we wouldn&#8217;t want a sudden flux in regular customers stealing all the HTTP connections from our VIP customers. Then we&#8217;d statically configure our VIP front-end to talk to our VIP back-end like this:</p>
<p><!-- code formatted by http://manoli.net/csharpformat/ --></p>
<pre class="csharpcode">
<span class="kwrd">&lt;</span><span class="html">UnicastBusConfig</span><span class="kwrd">&gt;</span>
  <span class="kwrd">&lt;</span><span class="html">MessageEndpointMappings</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">add</span> <span class="attr">Messages</span><span class="kwrd">="Messages.PlaceStockOrder, Messages"</span> <span class="attr">Endpoint</span><span class="kwrd">="VIP_Stock"</span> <span class="kwrd">/&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">add</span> <span class="attr">Messages</span><span class="kwrd">="Messages.PlaceForexOrder, Messages"</span> <span class="attr">Endpoint</span><span class="kwrd">="VIP_Forex"</span> <span class="kwrd">/&gt;</span>
  <span class="kwrd">&lt;/</span><span class="html">MessageEndpointMappings</span><span class="kwrd">&gt;</span>
<span class="kwrd">&lt;/</span><span class="html">UnicastBusConfig</span><span class="kwrd">&gt;</span></pre>
<p>And the logic to identify VIP customers would be done in the login screen which, from there, would direct the user to the appropriate web server farm.</p>
<h2>Static vs. Dynamic</h2>
<p>It may appear that the above statically configured solution is less flexible then the afore-mentioned hub-and-spoke content-based routing solution. And that&#8217;s probably correct. But the question is, are the business requirements (better called &#8220;objectives&#8221; in this case) likely to change? If we make the technological solution 10x more flexible than the business needs, but at the cost of maintainability (read time to market), we probably haven&#8217;t used the right tool for the job.</p>
<p>Many times we can find stable business objectives and align the topology of our solution with them. Not all that is dynamic and flexible is necessarily better than that which is static.</p>
<p>I&#8217;d go so far to say that if a solution makes heavy use of content-based routing, it is likely a more fragile solution as implementations of stable business objectives and volatile requirements are mixed up together. </p>
<h2>In Closing</h2>
<p>NServiceBus intentionally does not support content-based routing so as not to make it easy for developers to make architectural blunders that could require full-system rewrites a couple of years down the road.</p>
<p>If you want to learn more about these kinds of architectural principles, I suggest coming to my <a href="http://www.udidahan.com/training/">course</a>. I&#8217;m afraid that New York City is already sold out, but I&#8217;ll be coming back to the US again around October. Stockholm, London, Sydney, and Oslo are now all open for registration.</p>
<p>Hope to see you there.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.udidahan.com/2011/03/20/careful-with-content-based-routing/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>Entities, Transactions, and Broken Boundaries</title>
		<link>http://www.udidahan.com/2011/03/05/entities-transactions-and-broken-boundaries/</link>
		<comments>http://www.udidahan.com/2011/03/05/entities-transactions-and-broken-boundaries/#comments</comments>
		<pubDate>Sat, 05 Mar 2011 11:44:46 +0000</pubDate>
		<dc:creator>udidahan</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Business Rules]]></category>
		<category><![CDATA[DDD]]></category>
		<category><![CDATA[Data Access]]></category>
		<category><![CDATA[DataSets]]></category>
		<category><![CDATA[Databases]]></category>
		<category><![CDATA[OO]]></category>

		<guid isPermaLink="false">http://www.udidahan.com/?p=1409</guid>
		<description><![CDATA[One of the things I cover early on in my course is the problem with traditional layered architecture driving people to create a business logic layer made up of a bunch of inter-related entities. I see this happening a lot, even though nowadays people are calling that bunch of inter-related entities a &#8220;domain model&#8221;.
Let me [...]]]></description>
			<content:encoded><![CDATA[<p>One of the things I cover early on in my course is the problem with traditional layered architecture driving people to create a business logic layer made up of a bunch of inter-related entities. I see this happening a lot, even though nowadays people are calling that bunch of inter-related entities a &#8220;domain model&#8221;.</p>
<p>Let me just say this upfront &#8211; most inter-related entity models are NOT a domain model.<br />
Here&#8217;s why: most transactions don&#8217;t respect entity boundaries.</p>
<p>That being said, you don&#8217;t always need a domain model.<br />
The domain model pattern&#8217;s context is &#8220;if you have complicated and everchanging business rules&#8221; &#8211; right there on page 119 of Patterns of Enterprise Application Architecture.</p>
<p>Persisting the customer&#8217;s first name, last name, and middle initial &#8211; and later reading and showing that data does not sound either complicated or that it is really going to change that much.</p>
<p>Then there are things like credit limits, that may be on the customer entity as well. It is likely that there are business requirements that expect that value to be consistent with the total value of unpaid orders &#8211; data that comes from other entities. </p>
<p>The problem that is created is one of throughput.</p>
<p>Since databases lock an entire row/entity at a time, if one transaction is changing the customer&#8217;s first name, the database would block another transaction that tried to change the same customer&#8217;s credit limit.</p>
<p>The bigger your entities, the more transactions will likely need to operate on them in parallel, the slower your system will get as the number of transactions increases. This feeds back in on itself as often those blocked transactions will have operated already on some other entity, leaving those locked for longer periods of times, blocking even more transactions.</p>
<p>And the absurd thing is that the business never demanded that the customer&#8217;s first name be consistent with the credit limit.</p>
<p>What if we didn&#8217;t have a single Customer entity?</p>
<p>What if we had one that contained first name, last name, middle initial and another that contained things like credit limit, status, and risk rating. These entities would be correlated by the same ID, but could be stored in separate tables in the database. That would do away with much of the cascading locking effects drastically improving our throughput as load increases.</p>
<p>And you know what? That division would still respect the 3rd normal form.</p>
<p>Which of these entities do you think would be classified by the business under the &#8220;complicated and everchanging rules&#8221; category? </p>
<p>And for those entities that are just about data persistence &#8211; do you think it&#8217;s justified to use 3 tiers? Do we really need a view model which we transform to data transfer objects which we transform to domain objects which we transform to relational tables and then all the way back? Wouldn&#8217;t some simpler 2-tier programming suffice &#8211; dare I say datasets? Ruby on Rails? </p>
<p>Are we ready to leave behind the assumption that all elements of a given layer must be built the same way?</p>
]]></content:encoded>
			<wfw:commentRss>http://www.udidahan.com/2011/03/05/entities-transactions-and-broken-boundaries/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Polymorphism and Messaging</title>
		<link>http://www.udidahan.com/2011/01/13/polymorphism-and-messaging/</link>
		<comments>http://www.udidahan.com/2011/01/13/polymorphism-and-messaging/#comments</comments>
		<pubDate>Thu, 13 Jan 2011 08:52:48 +0000</pubDate>
		<dc:creator>udidahan</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[BizTalk]]></category>
		<category><![CDATA[EDA]]></category>
		<category><![CDATA[ESB]]></category>
		<category><![CDATA[Messaging]]></category>
		<category><![CDATA[NServiceBus]]></category>
		<category><![CDATA[Pub/Sub]]></category>
		<category><![CDATA[WCF]]></category>
		<category><![CDATA[Web Services]]></category>

		<guid isPermaLink="false">http://www.udidahan.com/?p=1389</guid>
		<description><![CDATA[One of the questions that came up from my NServiceBus &#8211; .NET Service Bus Smackdown post was about the Polymorphic Message Dispatch and Polymorphic Message Routing features. People wanted to know what those are, why they&#8217;re important, and if other technologies (specifically WCF and BizTalk) support them.
Messaging Basics
First of all, when building a system using [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.udidahan.com/wp-content/uploads/polymorphism.jpg" alt="polymorphism" title="polymorphism" width="213" height="131" style="float:right; margin-left:10px; margin-bottom:10px;" />One of the questions that came up from my <a href="http://www.udidahan.com/2010/08/04/nservicebus-net-service-bus-smackdown/">NServiceBus &#8211; .NET Service Bus Smackdown post</a> was about the Polymorphic Message Dispatch and Polymorphic Message Routing features. People wanted to know what those are, why they&#8217;re important, and if other technologies (specifically WCF and BizTalk) support them.</p>
<h2>Messaging Basics</h2>
<p>First of all, when building a system using messaging, you don&#8217;t have methods that are invoked on some remote object (a.k.a &#8220;service&#8221;) to which you pass parameters. Instead, you use some generic piece of infrastructure (in the world of Java, this is most commonly a Message Broker) to send a message where a message can be thought of as a serializable class. Here&#8217;s an example of a message:</p>
<p><!-- code formatted by http://manoli.net/csharpformat/ --></p>
<pre class="csharpcode">
<span class="kwrd">public</span> <span class="kwrd">class</span> UserCreated : IMessage
{
    <span class="kwrd">public</span> Guid UserId { get; set; }
    <span class="kwrd">public</span> <span class="kwrd">string</span> Name { get; set; }
}</pre>
<p>This message would be published using NServiceBus like this:</p>
<p><!-- code formatted by http://manoli.net/csharpformat/ --></p>
<pre class="csharpcode">
bus.Publish&lt;UserCreated&gt;( m =&gt;
{
    m.UserId = Guid.NewGuid();
    m.Name = <span class="str">"John Smith"</span>;
});
</pre>
<p>This can be contrasted with RPC models like WCF where you need to define a &#8220;service&#8221; that has methods on it, where those methods accepts parameters. Sometimes developers try to make this more generic by having a single &#8220;service&#8221; with one method on it named something like &#8220;Process&#8221; where the parameter it accepts is of the type &#8220;object&#8221;, or they introduce generics like this: Process&lt;T&gt;(T message);</p>
<p>This is where Polymorphic Message Dispatch comes in:</p>
<h2>Polymorphic Message Dispatch</h2>
<p>While you can pull of the WCF generics thing, one thing that is more difficult (without writing your own dispatch model) is to have a pipeline of classes which can be invoked based on their relationship to the type passed in. Using NServiceBus, both of the following message handlers will be invoked when UserCreated arrives:</p>
<p><!-- code formatted by http://manoli.net/csharpformat/ --></p>
<pre class="csharpcode">
<span class="kwrd">public</span> <span class="kwrd">class</span> Persistence : IHandleMessages&lt;UserCreated&gt;
{
    <span class="kwrd">public</span> <span class="kwrd">void</span> Handle(UserCreated message) { }
}

<span class="kwrd">public</span> <span class="kwrd">class</span> Audit : IHandleMessages&lt;IMessage&gt;
{
    <span class="kwrd">public</span> <span class="kwrd">void</span> Handle(IMessage message) { }
}</pre>
<p>Now some might say that WCF, BizTalk, and the .NET Service Bus allow you to do auditing in their own internal pipeline, and that&#8217;s true. The place where this becomes more powerful is when you need to build V2 of your system, and the publisher now publishes a slightly different event &#8211; that a user was created as a part of a campaign, requiring the subscriber to register statistics about the campaign. Of course, this event also means that a user was created. Here&#8217;s how you&#8217;d do that with NServiceBus:</p>
<p><!-- code formatted by http://manoli.net/csharpformat/ --></p>
<pre class="csharpcode">
<span class="kwrd">public</span> <span class="kwrd">class</span> UserCreatedFromCampaign : UserCreated
{
    <span class="kwrd">public</span> Guid CampaignId { get; set; }
}

<span class="rem">//publisher code</span>
bus.Publish&lt;UserCreatedFromCampaign&gt;( m =&gt;
{
    m.UserId = Guid.NewGuid();
    m.Name = <span class="str">"John Smith"</span>;
    m.CampaignId = theCampaignId;
}

<span class="rem">//subscriber code</span>
<span class="kwrd">public</span> <span class="kwrd">class</span> Statistics : IHandleMessages&lt;UserCreatedFromCampaign&gt;
{
    <span class="kwrd">public</span> <span class="kwrd">void</span> Handle(UserCreatedFromCampaign message) { }
}</pre>
<p>The important part is what you don&#8217;t see &#8211; since UserCreatedFromCampaign inherits from UserCrated, the Persistence handler we had from V1 will also be invoked, and so will the Audit handler of course. You don&#8217;t have to make your new code call the old code like you would in a method based dispatch model. This makes sure that the coupling in your service layer code remains constant over time as you grow the functionality of your system.</p>
<p>This was one of the main benefits mentioned by Rackspace in their use of NServiceBus (<a href="http://www.nservicebus.com/Customers.aspx">here</a>):</p>
<blockquote><p>&#8220;The main benefit NServiceBus has brought us so far is developer scalability due to lower coupling and higher consistency in our code.&#8221;</p></blockquote>
<p>But, when looking at the above scenario, we can obviously expect that all sorts of things can happen in relation to campaigns &#8211; it is a separate concern, and thus should be handled by a separate subscriber. And this bring us to&#8230;</p>
<h2>Polymorphic Message Routing</h2>
<p>The challenge that we have here is that we no longer have a hierarchy where something clearly belongs on top of something else. We have users created and activities happening related to campaigns &#8211; that may happen in any combination. By having separate subscribers, we could then introduce new handlers/subscribers to our environment without touching or taking down any of the other subscribers. Here&#8217;s what the subscribers would look like:</p>
<p><!-- code formatted by http://manoli.net/csharpformat/ --></p>
<pre class="csharpcode">
<span class="kwrd">public</span> <span class="kwrd">class</span> Persistence : IHandleMessages&lt;UserCreated&gt;
{
    <span class="kwrd">public</span> <span class="kwrd">void</span> Handle(UserCreated message) { }
}

<span class="kwrd">public</span> <span class="kwrd">class</span> Statistics : IHandleMessages&lt;CampaignActivityOccurred&gt;
{
    <span class="kwrd">public</span> <span class="kwrd">void</span> Handle(CampaignActivityOccurred message) { }
}</pre>
<p>But if each of the above messages were a class, how could we define a message which inherited from both?</p>
<p>Before answering that, we need to understand why the publisher wouldn&#8217;t just publish both of the above messages. You see, the publisher can&#8217;t make any assumptions about its subscribers &#8211; it could be that one of them has logic that correlates across both of these messages that could end up counting the occurrence as happening twice rather than once, possibly charging the account associated with the campaign twice. Publishing two messages results in two transactions when there really should have been one.</p>
<p>So, here&#8217;s how to define messages so that we can have multiple inheritance:</p>
<p><!-- code formatted by http://manoli.net/csharpformat/ --></p>
<pre class="csharpcode">
<span class="kwrd">public</span> <span class="kwrd">interface</span> UserCreated : IMessage
{
    Guid UserId { get; set; }
    <span class="kwrd">string</span> Name { get; set; }
}

<span class="kwrd">public</span> <span class="kwrd">interface</span> CampaignActivityOccurred : IMessage
{
    Guid CampaignId { get; set; }
    Guid ActivityId { get; set; }
}

<span class="kwrd">public</span> <span class="kwrd">interface</span> UserCreatedFromCampaign
                 : UserCreated,
                   CampaignActivityOccurred
{
}</pre>
<p>And when the publisher publishes UserCreatedFromCampaign, the event would be routed to both the UserCreated subscriber and the CampaignActivityOccurred subscriber. The power of this approach is felt as we handle new requirements around purchases made related to a campaign. Now we can have another event which inherits from CampaignActivityOccurred and not have to worry since the existing subscriber will be routed those messages automatically.</p>
<p>Since WCF doesn&#8217;t have publish/subscribe capabilities, we might as well move along.</p>
<p>Not to throw a burning match on an ocean of oil, but REST doesn&#8217;t really support this either.</p>
<h2>Not Content-Based Routing</h2>
<p>This may sound like the <a href="http://www.eaipatterns.com/ContentBasedRouter.html">content-based router pattern from EIP</a> (CBR), but it&#8217;s not. The important difference is that there isn&#8217;t some part of the routing that depends on the structure of the messages. The major drawback of CBR is that it creates a central place in your system that needs to be changed any time *syntactic* changes happen to message structure *in addition to* to changes in the subscribers.</p>
<p>Now, this is where the BizTalk guys would say that &#8220;that&#8217;s why we can do message transformations&#8221;, and then the subscribers wouldn&#8217;t need to be changed. However, can we really know when getting a requirement that the change is syntactic and not semantic? I mean, it&#8217;s quite common that changes to message structures happen together with changes to processing logic. </p>
<p>You may be beginning to get the feeling that more and more logic is being sucked out of the subscribers into some monolithic black hole that is likely going to be unmaintainable and quite slow. </p>
<p>This is one of the main differences between using a bus and a broker &#8211; a bus supports the correct distribution of logic keeping the system loosely coupled; brokers are useful integration engines when you absolutely can&#8217;t change the applications being integrated. Enterprise Application Integration (EAI) brokers don&#8217;t usually make good Enterprise Service Bus (ESB) technology.</p>
<h2>In Closing</h2>
<p>NServiceBus has all sorts of features you didn&#8217;t know you needed until you saw what life could be like when you had them. Most of these features don&#8217;t have snazzy drag-and-drop demos that make people ooh-and-aah and TechEds and PDCs, but they&#8217;re really necessary to avoid finding yourself in yet another big-ball-of-mud code base telling your manager/customer (again) that it would be faster to rebuild the system from scratch than to implement that new requirement in the old one.</p>
<p>Take NServiceBus for a spin and <a href="http://www.nservicebus.com/">see for yourself</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.udidahan.com/2011/01/13/polymorphism-and-messaging/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>The Known Unknowns of SOA</title>
		<link>http://www.udidahan.com/2010/11/15/the-known-unknowns-of-soa/</link>
		<comments>http://www.udidahan.com/2010/11/15/the-known-unknowns-of-soa/#comments</comments>
		<pubDate>Mon, 15 Nov 2010 13:44:40 +0000</pubDate>
		<dc:creator>udidahan</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Autonomous Services]]></category>
		<category><![CDATA[EDA]]></category>
		<category><![CDATA[ESB]]></category>
		<category><![CDATA[Pub/Sub]]></category>
		<category><![CDATA[SOA]]></category>
		<category><![CDATA[Web Services]]></category>

		<guid isPermaLink="false">http://www.udidahan.com/?p=1364</guid>
		<description><![CDATA[One of the better known analysts in the enterprise software area, JP Morgenthal, wrote this post about the relationship between SOA, BPM, and EA. In it he defines SOA as follows:
&#8220;SOA is a practice that focuses on modeling the entities, and relationships between entities, that comprise the business as a set of services. This can [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.udidahan.com/wp-content/uploads/rumsfeld120804.jpg" alt="rumsfeld" title="rumsfeld" width="162" height="225" style="float:right; margin-left:10px; margin-bottom:10px;" />One of the better known analysts in the enterprise software area, JP Morgenthal, wrote this post about <a href="http://soa.dzone.com/news/relationship-between-soa-bpm">the relationship between SOA, BPM, and EA</a>. In it he defines SOA as follows:</p>
<blockquote><p>&#8220;SOA is a practice that focuses on modeling the entities, and relationships between entities, that comprise the business as a set of services. This can be done on a small or large scale. Typically, the relationships in this model represent consumer/provider relationships.&#8221;</p></blockquote>
<p>I have some serious concerns about the ramifications of this definition/description.</p>
<p>First of all, when reading &#8220;entities&#8221;, many people will interpret that to mean the entities found in Entity Relationship Diagrams [<a href="http://en.wikipedia.org/wiki/Entity-relationship_model">ERD</a>] or in Object Oriented Analysis &#038; Design [<a href="http://en.wikipedia.org/wiki/Object-oriented_analysis_and_design">OOAD</a>]. In both, these entities are identified as the &#8220;nouns&#8221; of the domain. Examples of these ERD/OOAD-type entities include things like Customer, Order, and Product.</p>
<p>These are almost always the wrong place to start for identifying services in SOA.</p>
<p>Second, on the consumer/provider relationship: on the one had, this fits very well with how web services can consume (or call) other web services. However, the downsides of using web services as services in SOA is becoming well enough known that even in the same post we see this warning:</p>
<blockquote><p>&#8220;Web Services is not SOA, it is merely a standardized approach to accessing functionality on remote systems.&#8221;</p></blockquote>
<p>But the question remains, if a producer/consumer relationship is OK for SOA-type services, why doesn&#8217;t that hold for web services? And the answer is&#8230; it depends on the type of producer/consumer relationship. The typical relationship is one of synchronous calls from consumer to producer, this is not OK for SOA-type services either. </p>
<p>You see, this synchronous producer/consumer implies a model where services are not able to fulfill their objectives without calling other services. In order for us to achieve the IT/Business alignment promised by SOA, we need services which are autonomous, ie. able to fulfill their objectives without that kind of external help.</p>
<p>Instead, we need to look for a more loosely coupled producer/consumer relationship &#8211; like publish/subscribe, where the producer emits events, and the consumer subscribes and handles those events. The reason that this kind of relationship doesn&#8217;t hurt autonomy is that it disconnects services on the dimension of time. In order for a service to be able to make a decision autonomously without synchronously calling any other service, using only information provided by events it received in the past, it must be strongly aligned with the business.</p>
<p>Most projects which bandy about the SOA acronym aren&#8217;t actually made up of services &#8211; they&#8217;re made up of XML over HTTP functions calling other XML over HTTP functions, eventually calling XML over HTTP databases. You can layer as much XML and HTTP as you want on top of it, but at the end of the day, most projects are just functions calling functions calling databases &#8211; in other words, procedural programming in the large, and no amount of SOAP will wash away the stink.</p>
<p>Here&#8217;s a different definition of services for SOA that may communicate a bit better what it&#8217;s all about:</p>
<blockquote><p>A service is the technical authority for a specific business capability.<br />
Any piece of data or rule must be owned by only one service.</p></blockquote>
<p>What this means is that even when services are publishing and subscribing to each other&#8217;s events, we always know what the authoritative source of truth is for every piece of data and rule. </p>
<p>Also, when looking at services from the lense of business capabilities, what we see is that many user interfaces present information belonging to different capabilities &#8211; a product&#8217;s price alongside whether or not it&#8217;s in stock. In order for us to comply with the above definition of services, this leads us to an understanding that such user interfaces are actually a mashup &#8211; with each service having the fragment of the UI dealing with its particular data.</p>
<p>Ultimately, process boundaries like web apps, back-end, batch-processing are very poor indicators of service boundaries. We&#8217;d expect to see multiple business capabilities manifested in each of those processes.</p>
<p>I know that this may be more confusing than the traditional web services approach but, to paraphrase Donald Rumsfeld, it is better to know that you don&#8217;t know, than to not know that you don&#8217;t know <img src='http://www.udidahan.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  </p>
]]></content:encoded>
			<wfw:commentRss>http://www.udidahan.com/2010/11/15/the-known-unknowns-of-soa/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>Logical and Physical Architecture</title>
		<link>http://www.udidahan.com/2010/11/08/logical-and-physical-architecture/</link>
		<comments>http://www.udidahan.com/2010/11/08/logical-and-physical-architecture/#comments</comments>
		<pubDate>Mon, 08 Nov 2010 19:14:04 +0000</pubDate>
		<dc:creator>udidahan</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Autonomous Services]]></category>
		<category><![CDATA[BizTalk]]></category>
		<category><![CDATA[ESB]]></category>
		<category><![CDATA[SOA]]></category>
		<category><![CDATA[WCF]]></category>
		<category><![CDATA[Web Services]]></category>

		<guid isPermaLink="false">http://www.udidahan.com/?p=1355</guid>
		<description><![CDATA[One architectural misunderstanding I see repeatedly in my work with clients is in the relationship between logical and physical architecture. The most common building-block of these misunderstandings is the web service (or it&#8217;s &#8220;upgraded&#8221; .net counterpart &#8211; the WCF service).
Don&#8217;t get me wrong, sometimes there is a place for a web service, just not everywhere.
So, [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.udidahan.com/wp-content/uploads/orthogonal1.jpg" alt="orthogonal" title="orthogonal" width="300" height="237" style="float:right; margin-left:10px; margin-bottom:10px;" />One architectural misunderstanding I see repeatedly in my work with clients is in the relationship between logical and physical architecture. The most common building-block of these misunderstandings is the web service (or it&#8217;s &#8220;upgraded&#8221; .net counterpart &#8211; the WCF service).</p>
<p>Don&#8217;t get me wrong, sometimes there is a place for a web service, just not everywhere.</p>
<p>So, what&#8217;s the problem?</p>
<p>Well, when developers and architects use web services as the building blocks of their designs, they are creating the same architecture for both the logical and physical elements of their system. Back in 1995, Philippe Kruchten documented his <a href="http://en.wikipedia.org/wiki/4%2B1_Architectural_View_Model">4 + 1 Architectural View Model</a> in which he outlined 4 + 1 different views that should be used to describe an architecture.</p>
<p>Even though since 1995 the number and types of recommended views of software architecture has evolved (with things like the <a href="http://en.wikipedia.org/wiki/Zachman_Framework">Zachman Framework</a> for enterprise architecture numbering some 30 views), there is broad agreement that (at the very least) the logical and physical artifacts should likely be designed differently.</p>
<p>Just because two distinct logical components have been identified in the architecture, that doesn&#8217;t necessarily mean they should be hosted separately (for example by making each one a web/wcf service). In fact, there are significant <b>disadvantages</b> to doing so (as described in the <a href="http://en.wikipedia.org/wiki/Fallacies_of_Distributed_Computing">Fallacies of Distributed Computing</a>).</p>
<p>In some cases, this mistake is exacerbated by a mistaking these components with SOA-type services, resulting in an attempt by developers to have each component have its own contract, which can then be independently versioned. This often results in the need for transformation between the structure of these so-called contracts, but not within the components themselves (oh-no, they&#8217;re &#8220;autonomous&#8221;), but rather in between them using some kind of &#8220;ESB&#8221; technology.</p>
<p>This architectural style is known as the Broker, Hub and Spoke, Mediator, and most importantly &#8211; not SOA. If you find a technology that fits this style perfectly (like BizTalk), that technology is not a Bus, not a Service Bus, and definitely not an Enterprise Service Bus.</p>
<p>One of the problems of this approach is that when any &#8220;service&#8221; contract changes, you have to change all the transformations in your broker that involve it. Unfortunately, most brokers have no unit-testing facility so it&#8217;s very much trial and error, and error, and error. The matter is even more serious since most brokers don&#8217;t enable you to have your transformations or orchestrations in source control, so you can&#8217;t diff to see what changed from the previous version.</p>
<p>It&#8217;s really amazing how much pain can be traced back to that one original misunderstanding. </p>
]]></content:encoded>
			<wfw:commentRss>http://www.udidahan.com/2010/11/08/logical-and-physical-architecture/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Race Conditions Don&#8217;t Exist</title>
		<link>http://www.udidahan.com/2010/08/31/race-conditions-dont-exist/</link>
		<comments>http://www.udidahan.com/2010/08/31/race-conditions-dont-exist/#comments</comments>
		<pubDate>Tue, 31 Aug 2010 09:56:46 +0000</pubDate>
		<dc:creator>udidahan</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[BPM]]></category>
		<category><![CDATA[Business Rules]]></category>
		<category><![CDATA[CQRS]]></category>
		<category><![CDATA[NServiceBus]]></category>
		<category><![CDATA[Pub/Sub]]></category>
		<category><![CDATA[Workflow]]></category>

		<guid isPermaLink="false">http://www.udidahan.com/?p=1335</guid>
		<description><![CDATA[Not in the business world anyway.
The problem is that, as software developers, we&#8217;re all too quick to accept them at face value. We don&#8217;t question the requirements &#8211; in all fairness, it was never our job to do so. We were the ones that implemented them, preferably quickly. 
For example
Let&#8217;s say we get the requirement [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.udidahan.com/wp-content/uploads/crossing-the-finish-line1.jpg" alt="crossing-the-finish-line" title="crossing-the-finish-line" width="200" height="159" style="float:right; margin-left:10px; margin-bottom:10px;"  />Not in the business world anyway.</p>
<p>The problem is that, as software developers, we&#8217;re all too quick to accept them at face value. We don&#8217;t question the requirements &#8211; in all fairness, it was never our job to do so. We were the ones that implemented them, preferably quickly. </p>
<h3>For example</h3>
<p>Let&#8217;s say we get the requirement the following requirements:</p>
<p>1. If the order was already shipped, don&#8217;t let the user cancel the order.<br />
2. If the order was already cancelled, don&#8217;t let the user ship the order.</p>
<p>The race condition here is when we have two users who are looking at the same order, which is neither cancelled nor shipped yet, and each submits a command &#8211; one to ship the order, the other to cancel it.</p>
<p>In these cases, the code is simple &#8211; just an if statement before performing the relevant command.</p>
<h3>So what&#8217;s the problem</h3>
<p>A microsecond difference in timing shouldn&#8217;t make a difference to core business behaviors. Which means that we&#8217;ve actually got here is a bug in the requirements. Users are actually dictating solutions here rather than requirements.</p>
<p>Let&#8217;s ask our stakeholders, &#8220;why shouldn&#8217;t we let users cancel a shipped order? I mean, the users don&#8217;t want the products.&#8221;</p>
<p>And the stakeholders would respond with something like, &#8220;well, we don&#8217;t want to refund the user&#8217;s money then. Or, at least, not all their money. Well, maybe if they return the products in their original packaging, *then* we could give a full refund.&#8221;</p>
<p>And as we drilled deeper, &#8220;when do refunds need to be given? Right away, in the same transaction?&#8221;</p>
<p>The stakeholders would explain, &#8220;no, refunds don&#8217;t need to be given right away.&#8221;</p>
<p>It turns out we were missing the concept of a refund, as well as assuming that all things needed to be processed and enforced immediately. Once we dug into the requirements, we found that there is actually plenty of time to allow both transactions to go through. We just need to add some checks during shipping&#8217;s long-running process to see if the order was cancelled, and then to cut the process short.</p>
<h3>So is everything a long-running process then?</h3>
<p>That&#8217;s actually a fair question &#8211; long-running processes are a lot more common than at first appears.</p>
<p>What we&#8217;re seeing is that cancellation is now a command that has no reason to fail &#8211; just like <a href="http://www.udidahan.com/2009/12/09/clarified-cqrs">CQRS</a> tells us. When this command is performed, it publishes the OrderCancelled event, which the billing service subscribes to. </p>
<p>Billing then starts a long-running process (a saga, in <a href="http://www.NServiceBus.com">NServiceBus</a> lingo), also listening to events from the shipping process, ultimately making a decision when a refund should be given, and for how much.</p>
<h3>Deeper business analysis</h3>
<p>As we discuss matters more with our business stakeholders, we hear that most orders are actually cancelled within an hour of being submitted. It is quite rare for orders to be cancelled days later.</p>
<p>In which case, we could look at modeling the acceptance of an order as a long-running process itself.</p>
<p>When a user places an order, we don&#8217;t immediately publish an event indicating the acceptance of an order, instead a saga is kicked off &#8211; which opens up a timeout for an hour later. If a cancellation command arrives during that period of time, the user gets a full refund (seeing as we didn&#8217;t charge anything since billing didn&#8217;t get the accepted event to begin with), and the saga just shuts itself down. If the timeout occurs an hour later, and the saga didn&#8217;t get a cancel command, then the order is actually accepted and the event is published.</p>
<p>Yes, sagas are everywhere, once you learn to see with business eyes, and no race conditions are left.</p>
<h3>In closing</h3>
<p>Any time you see requirements that indicate a race condition, dig deeper.</p>
<p>What you&#8217;re likely to find are some additional business concepts as well as the introduction of time and the creation of long-running business processes. The implementation at that point will pivot from being trivial if-statements to being richer sagas.</p>
<p>Keep an eye out.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.udidahan.com/2010/08/31/race-conditions-dont-exist/feed/</wfw:commentRss>
		<slash:comments>24</slash:comments>
		</item>
		<item>
		<title>Evolving Loosely-Coupled Frameworks &amp; Apps</title>
		<link>http://www.udidahan.com/2010/07/14/evolving-loosely-coupled-frameworks-and-apps/</link>
		<comments>http://www.udidahan.com/2010/07/14/evolving-loosely-coupled-frameworks-and-apps/#comments</comments>
		<pubDate>Wed, 14 Jul 2010 13:10:18 +0000</pubDate>
		<dc:creator>udidahan</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Dependency Injection]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[NServiceBus]]></category>
		<category><![CDATA[OO]]></category>
		<category><![CDATA[Simplicity]]></category>

		<guid isPermaLink="false">http://www.udidahan.com/?p=1312</guid>
		<description><![CDATA[This post will be less of a big-concept type posts I usually do, and more of a tip for people building and maintaining infrastructure and frameworks either open-source or internally for their companies. I&#8217;m going to illustrate this with NServiceBus as it is a large enough code base to have significant complexity and open so [...]]]></description>
			<content:encoded><![CDATA[<p>This post will be less of a big-concept type posts I usually do, and more of a tip for people building and maintaining infrastructure and frameworks either open-source or internally for their companies. I&#8217;m going to illustrate this with NServiceBus as it is a large enough code base to have significant complexity and open so that you can go and take a look yourself. Trying to include some example in here would be just too small to be useful or for the point to come across.</p>
<h3>Some background</h3>
<p>As a cohesive framework, NServiceBus makes it quite easy for developers to pick and choose which settings they want turned on and off. Being built as a loosely-coupled set of components that don&#8217;t know about each other has always kept the internal complexity low. But as the NServiceBus API has been evolving over the years, and the functionality offered has increased, some interesting challenges have popped up as the codebase has been refactored. </p>
<h3>The challenge</h3>
<p>The UnicastBus class has grown too large and it&#8217;s time to refactor something out. Coincidentally, users have been asking for a better &#8220;header&#8221; story for messages &#8211; the ability to specify static headers that will be appended to all messages being sent (useful for things like security tokens), as well as per message headers. So, we want to refactor all the header management out to its own component independent of the UnicastBus class.</p>
<p>So, here&#8217;s the issue. So far, users have specified &#8220;.UnicastBus()&#8221; as a part of the fluent code-configuration, and shouldn&#8217;t have to change that &#8211; they shouldn&#8217;t need to know that header management is now a separate component. But then how can the new component bootstrap itself into the startup, such that it gets all the dependency injection facilities of the rest of the framework? Remember that the component doesn&#8217;t know which container technology is being used (since the user can swap it out) or when the container has been set.</p>
<h3>The solution</h3>
<p>The only part of the framework that knows about when all DI configuration is set is the configuration component, thus it will have to be the one that invokes the new component (without knowing about it). Introduce an interface (say INeedInitialization) and scan all the types loaded looking for classes which implement that type, register them into the container, and invoke them. Have the new component implement that interface, and in its initialization have it hook into the events and/or pipelines of other parts of the system.</p>
<h3>Other uses</h3>
<p>One historically problematic area in NServiceBus has been people forgetting to call &#8220;.LoadMessageHandlers()&#8221;. This can now be wired in automatically by a class in the UnicastBus component via the same mechanism.</p>
<p>A new feature coming in the next version is the &#8220;data bus&#8221;, a component which will allow sending large quantities of data through the bus without going through the messaging pipelines. This will help people get around the 4MB limit of MSMQ and, even more importantly, the much smaller 8KB limit of Azure. We will be able to introduce the functionality transparently with the same mechanism.</p>
<p>As an extension point, developers can now enrich the NServiceBus framework with their own capabilities and make those available via the contrib project to the community at large. This is better than the IWantToRunAtStartup interface that was only available for those using the generic host (which excluded web apps) and gives a consistent extensibility story for all uses.</p>
<h3>Summary</h3>
<p>Extensibility has always been a challenge when writing object-oriented code and dependency injection techniques have helped, but sometimes you need a bit more to take things to the next level while maintaining a backwards-compatible API.</p>
<p>Like I said, not a ground-shaking topic but something quite necessary in creating loosely-coupled frameworks and applications. Once you know it&#8217;s there, it isn&#8217;t really a big deal. If you didn&#8217;t know to do it, you may have been contorting your codebase in all kinds of ways to try to achieve similar things.</p>
<p>If you want to take a look at the code, you can find the SVN repository here: https://nservicebus.svn.sourceforge.net/svnroot/nservicebus/trunk/</p>
]]></content:encoded>
			<wfw:commentRss>http://www.udidahan.com/2010/07/14/evolving-loosely-coupled-frameworks-and-apps/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>High Availability Presentation</title>
		<link>http://www.udidahan.com/2010/06/21/high-availability-presentation/</link>
		<comments>http://www.udidahan.com/2010/06/21/high-availability-presentation/#comments</comments>
		<pubDate>Mon, 21 Jun 2010 06:36:34 +0000</pubDate>
		<dc:creator>udidahan</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Availability]]></category>
		<category><![CDATA[Presentations]]></category>
		<category><![CDATA[Reliability]]></category>
		<category><![CDATA[The Team]]></category>

		<guid isPermaLink="false">http://www.udidahan.com/?p=1308</guid>
		<description><![CDATA[OK &#8211; this is the last one, I promise. Well, for now, anyway.
Earlier this month at TechEd North America I gave a fairly new presentation that was only delivered once before (at the Connected Systems User Group in London) and I&#8217;m happy to say is now online for your viewing pleasure.
High Availability &#8211; A Contrarian [...]]]></description>
			<content:encoded><![CDATA[<p>OK &#8211; this is the last one, I promise. Well, for now, anyway.</p>
<p>Earlier this month at TechEd North America I gave a fairly new presentation that was only delivered once before (at the Connected Systems User Group in London) and I&#8217;m happy to say is now online for your viewing pleasure.</p>
<p><a href="http://www.msteched.com/2010/NorthAmerica/ARC308">High Availability &#8211; A Contrarian View</a></p>
<p>Comments? Thoughts? Let me know.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.udidahan.com/2010/06/21/high-availability-presentation/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Server Naming and Configuration Conflicts</title>
		<link>http://www.udidahan.com/2010/06/05/server-naming-and-configuration-conflicts/</link>
		<comments>http://www.udidahan.com/2010/06/05/server-naming-and-configuration-conflicts/#comments</comments>
		<pubDate>Sat, 05 Jun 2010 12:59:13 +0000</pubDate>
		<dc:creator>udidahan</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Management]]></category>
		<category><![CDATA[Simplicity]]></category>

		<guid isPermaLink="false">http://www.udidahan.com/?p=1289</guid>
		<description><![CDATA[In my work with clients the topic of how to handle the movement of software from one environment to another inevitably comes up. Sometimes this is in the context of NServiceBus but the problem is more generic. The faster that an organization is able to get software out the door, the more agile they can [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.udidahan.com/wp-content/uploads/Configuration_icon_by_obsilion.png" alt="Configuration" title="Configuration" width="225" height="221" style="float:right;" />In my work with clients the topic of how to handle the movement of software from one environment to another inevitably comes up. Sometimes this is in the context of NServiceBus but the problem is more generic. The faster that an organization is able to get software out the door, the more agile they can be. </p>
<p>Unfortunately, there is one tiny little mistake that I see almost everywhere that gets in the way, and that&#8217;s going to be the topic of this post.</p>
<h3>The Problem</h3>
<p>Let&#8217;s say you have a standard web app environment &#8211; some web servers, application servers, and a database server. Your web servers need to send messages to the application servers. So far, so good.</p>
<p>In your test environment, you have an application server called AS_01_Test, and your web servers are configured to send it messages. However, in your staging environment the application server fulfilling that same role is called AS_01_Stage. This creates a configuration problem &#8211; you need to change the config of your web servers as you move the web app from Test to Staging.</p>
<p>I&#8217;ve seen companies doing all sorts of creative things to get around this problem &#8211; some of them involve putting all configuration settings in a database so that they can be centrally managed and visualized. I&#8217;d like to suggest an alternative approach.</p>
<h3>What if&#8230;</h3>
<p>What if server names were the same across all environments?</p>
<p>Well, you wouldn&#8217;t need to change configuration as you moved the system between environments. That&#8217;s a good thing.</p>
<p>But how can that be? Wouldn&#8217;t there be a conflict if there were two machines with the same name?</p>
<p>The answer is that there wouldn&#8217;t be a conflict if the machines were on different networks. Not all machines have to be on the same network. We can set up as many networks / virtual networks as we like. And it is clear that we don&#8217;t need machines in one environment / network to talk to machines in another environment. I mean, under no circumstances would we want web servers in our test environment to talk to application servers in the production environment.</p>
<p>These separate networks provide much needed isolation, beyond solving the server naming problem.</p>
<h3>In closing</h3>
<p>It&#8217;s really a tiny thing when you think about &#8211; multiple networks. But that&#8217;s exactly why software developers overlook it so often &#8211; because it&#8217;s not a &#8220;software solution&#8221; to the configuration problem we perceive as a &#8220;software problem&#8221;.</p>
<p>I wrote about related multi-environment configuration issues in this earlier post: <a href="http://www.udidahan.com/2009/08/15/convention-over-configuration-the-next-generation/">Convention over Configuration &#8211; The Next Generation</a></p>
<p>I&#8217;m happy to say that this functionality is now in NServiceBus called &#8220;profiles&#8221; and you can read more about how they work <a href="http://www.nservicebus.com/Profiles.aspx">here</a>.</p>
<p>How are you handling the flow of moving software through to production? Leave your comments below.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.udidahan.com/2010/06/05/server-naming-and-configuration-conflicts/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>CQRS isn&#8217;t the answer &#8211; it&#8217;s just one of the questions</title>
		<link>http://www.udidahan.com/2010/05/07/cqrs-isnt-the-answer-its-just-one-of-the-questions/</link>
		<comments>http://www.udidahan.com/2010/05/07/cqrs-isnt-the-answer-its-just-one-of-the-questions/#comments</comments>
		<pubDate>Fri, 07 May 2010 09:25:12 +0000</pubDate>
		<dc:creator>udidahan</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[CQRS]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Management]]></category>
		<category><![CDATA[Simplicity]]></category>

		<guid isPermaLink="false">http://www.udidahan.com/?p=1278</guid>
		<description><![CDATA[With the growing interest in Command/Query Responsibility Segregation (CQRS), more people are starting to ask questions about how to apply it to their applications. CQRS is actually in danger of reaching &#8220;best practice&#8221; status at which point in time people will apply it indiscriminately with truly terrible results. 
One of the things that I&#8217;ve been [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.udidahan.com/wp-content/uploads/dont_pan.gif" alt="dont panic" title="dont panic" width="260" height="180" style="float:right;" />With the growing interest in Command/Query Responsibility Segregation (<a href="http://www.udidahan.com/2009/12/09/clarified-cqrs/">CQRS</a>), more people are starting to ask questions about how to apply it to their applications. CQRS is actually in danger of reaching &#8220;best practice&#8221; status at which point in time people will apply it indiscriminately with truly terrible results. </p>
<p>One of the things that I&#8217;ve been trying to do with my presentations around the world on CQRS was to explain the <b>why</b> behind it, just as much as the what. The problem with the format of these presentations is that they&#8217;re designed to communicate a fairly closed message: here&#8217;s the problem, here&#8217;s how that problem manifests itself, here&#8217;s a solution.</p>
<p>In this post, I&#8217;m going to try to go deeper.</p>
<h3>The hitchhiker&#8217;s guide to the galaxy</h3>
<p>In this most excellent book, one of the things that struck me was the theme that made it&#8217;s way through the whole book &#8211; starting with the answer to life, the universe, and everything: 42. By the time you get to the end of the book, you find out that the real <b>question</b> to life, the universe, and everything is &#8220;what do you get when you multiply 6 by 9&#8243;. And that&#8217;s how the book leaves it.</p>
<p>To us engineers, we can&#8217;t just accept the fact that the book would say that 6*9 = 42 when we know it&#8217;s 54. After bashing our heads on the rigid rules of math, we realize that not all math problems are necessarily in base 10, and that if we switch to base 13, the number 42 is 4*13 + 2 = 54. So, the book was right &#8211; but that&#8217;s not the point.</p>
<h3>What&#8217;s the point?</h3>
<p>The hitchhiker&#8217;s guide is an example of a teaching technique which presents an apparent paradox, leaving the student to dig up unspoken and unthought assumptions in order to resolve it. Key to this technique are rigid rules which do not allow any compromise or shortcuts on the student&#8217;s part. </p>
<p>The purpose of this technique is not for the student to learn the answer, but to gain deeper understanding, which in turn changes the way they go about thinking about problems in the future. </p>
<p>So, when given the problem 4*5, we do not just immediately answer 20, instead we clarify in which numeric base the question is being phrased, and only then go to solve the problem. In base 13, the answer would be 17. In hex, the answer would be 14.</p>
<p>The externally visible change is that we know which questions to ask in order to arrive at the right answer &#8211; not that we know the answer ahead of time.</p>
<h3>Making an &#8220;ass&#8221; out of &#8220;u&#8221; and &#8220;me&#8221;</h3>
<p>Let&#8217;s start at the end &#8211; one of the unspoken assumptions that has been causing problems:</p>
<blockquote><p>
All businesses can be treated the same from the perspective of software.
</p></blockquote>
<p>In our previous example, we assumed that all math problems use base 10. It turns out that different bases are useful for different domains (like base 2 for computers). We can say similar things about degrees and radians in geometry. The more we look at the real world, the more we see this repeating itself. There&#8217;s no reason that software should be any different.</p>
<p>Base 10 is not a ubiquitous best practice. We shouldn&#8217;t be surprised that there really aren&#8217;t best practices for software either.</p>
<p>Here&#8217;s another problematic assumption:</p>
<blockquote><p>
&#8220;The business&#8221; can (and do) tell us what they need in a way we can understand.
</p></blockquote>
<p>So many software fads have been built on the quicksand of this assumption. OOAD &#8211; on verbs and nouns. 4GL and other visual tools that &#8220;the business&#8221; will use directly. SOA &#8211; on IT business alignment. I expect we haven&#8217;t seen the end of this.</p>
<p>Some of you may be wondering why this is false, others are sagely nodding their heads in agreement.</p>
<h3>The myth of &#8220;the business&#8221;</h3>
<p>Unless you have a single user, who is also the CEO paying for the development, there is no &#8220;the&#8221;. It&#8217;s an amalgam of people with different backgrounds, skills, and goals &#8211; there is no homogeneity. Even if no software was involved, many business organizations are dysfunctional with conflicting goals, policies, and politics.</p>
<p>To some extent, we technical people have hidden ourselves away in IT to avoid the scary world of business whose rules we don&#8217;t understand. With the rise in importance of information to the world, we&#8217;ve been pulled back &#8211; being forced to talk to people, and not just computers. Luckily, we&#8217;ve been able to create a buffer to insulate ourselves &#8211; we&#8217;ve taken the less successful technical people from our heard and nominated them &#8220;business analysts&#8221;. No, not all companies do it this way, but we do need to take a minute to reflect on how information flows between the business Mars into and out of the IT Venus.</p>
<h3>On human communication</h3>
<p>Even if we made this insulation layer more permeable, allowing and encouraging more technical people and business people to cross its boundary, we still need to deal with the problem of two humans communicating with each other. There are enough books that have been written on this topic, so I won&#8217;t go into that beyond recommending (strongly) to technical people to read (some of) them.</p>
<p>Rather, I&#8217;d like to focus on the environment in which these discussions take place. IT has been around long enough, and users have used computers long enough, that a certain amount of tainting has taken place. If the world was a trial, the evidence would have been thrown out as untrustworthy.</p>
<p>When users tell you what they want, they&#8217;re usually framing that with respect to the current system that they&#8217;re using. &#8220;Like the old system &#8211; but faster, and with better search, and more information on that screen, and&#8230;&#8221; </p>
<p>At this point, business analysts write down and formalize these &#8220;requirements&#8221; into some IT-sanctioned structure (use cases, user stories, whatever), at which point developers are told to build it. Users only know what they <b>didn&#8217;t</b> want when developers deliver exactly what was asked.</p>
<p>How can that be?</p>
<h3>These are not the &#8220;requirements&#8221; you are looking for</h3>
<p>Users ultimately dictate <b>solutions</b> to us, as a delta from the previous set of solutions we&#8217;ve delivered them. That&#8217;s just human psychology &#8211; writer&#8217;s block when looking at a blank page, as compared to the ease with which we provide &#8220;constructive criticism&#8221; on somebody else&#8217;s work.</p>
<p>We need to get the real requirements. We need to probe beyond the veneer:</p>
<ul>
<li>Why do you need this additional screen? </li>
<li>What real-world trigger will cause you to open it? </li>
<li>Is there more than one trigger? </li>
<li>How are they different?</li>
<li>etc, etc, etc&#8230;</li>
</ul>
<p>This is <b>real</b> work &#8211; different work than programming. It requires different skills. And that&#8217;s not even getting into the political navigation between competing organizational forces.</p>
<p>But let&#8217;s say that you don&#8217;t have (enough) people with these skills in your organization. What then?</p>
<h3>Enter CQRS</h3>
<p>CQRS gives us a set of questions to ask, and some rigid rules that our answers must conform to. If our answers don&#8217;t fit, we need to go back to the drawing board and move things around and/or go back to &#8220;the business&#8221; and seek deeper understanding there.</p>
<p>For each screen/task/piece of data:</p>
<blockquote><p>
Will multiple users be collaborating on data related to this task?<br />
Look at every shred of raw data, not just at the entity level.<br />
Are there business consistency requirements around groups of raw data?
</p></blockquote>
<p>If &#8220;the business&#8221; answers no &#8211; ask them if they see that answer changing, and if so, in what time frame, and why. What changing conditions in the business environment would cause that to change &#8211; what other parts of the system would need to be re-examined under those conditions.</p>
<p>After understanding all that and you find a true single-user-only-thing, then you can use standard &#8220;CRUD&#8221; techniques and technologies. There are no inherent time-propagation problems in a single-user environment &#8211; so eventual consistency is beyond pointless, it actually makes matters worse.</p>
<p>On the other hand, if the business-data-space is collaborative, the inherent time-propagation of information between actors means they will be making decisions on data that isn&#8217;t up-to-the-millisecond-accurate anyway. This is physics, gravity &#8211; you can&#8217;t fight it (and win).</p>
<h3>The rule for collaboration</h3>
<blockquote><p>
Actors must be able submit one-way commands that will fail only under exceptional <b>business</b> circumstances.
</p></blockquote>
<p>The challenge we have is how to achieve the real business objectives uncovered in our previous &#8220;requirements excavation&#8221; activities and follow this rule at the same time. This will likely involve a different user-system interaction than those implemented in the past. UI design is part of the solution domain &#8211; it shouldn&#8217;t be dictated by the business (otherwise it&#8217;s like someone asking you to run a marathon, but also dictating how you do so, like by tying your shoelaces together).</p>
<p>Many of the technical patterns I described in my <a href="http://www.udidahan.com/2009/12/09/clarified-cqrs/">previous blog post</a> describe the tools involved. BTW, hackers can be considered &#8220;exceptional actors&#8221; &#8211; the business actually wants their commands to fail.</p>
<h3>In Summary</h3>
<p>The hard and fast rule of CQRS about one-way commands is relevant for collaborative domains only. This domain has inherent eventual consistency &#8211; in the real world. Taking that and baking it into our solution domain is how we align with the business.</p>
<p>The process we go through, until ultimately arriving at one-way-almost-always-successful-commands <b>is business analysis</b>. Rejecting pre-formulated solutions, truly understanding the business drivers, and then representing those as directly as possible in our solution domain &#8211; that&#8217;s our job.</p>
<p>After doing this enough times and/or in more than one business domain, we may gain the insight that there is no cookie-cutter, one-size-fits-all, best-practice solution architecture for everything. Each problem domain is distinct and different &#8211; and we need to understand the details, because they <b>should</b> shape the resulting software structure.</p>
<p>The next time the business tell us to implement 42, we&#8217;ll use CQRS along with other questioning techniques until we can get &#8220;6 x 9&#8243; out of them, learning from the exercise what are the significant and stable parts of the business &#8211; ultimately helping us to &#8220;build the right system, and to build the system right&#8221;.</p>
<p>Don&#8217;t Panic <img src='http://www.udidahan.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.udidahan.com/2010/05/07/cqrs-isnt-the-answer-its-just-one-of-the-questions/feed/</wfw:commentRss>
		<slash:comments>24</slash:comments>
		</item>
		<item>
		<title>On Design for Testability</title>
		<link>http://www.udidahan.com/2010/04/18/on-design-for-testability/</link>
		<comments>http://www.udidahan.com/2010/04/18/on-design-for-testability/#comments</comments>
		<pubDate>Sun, 18 Apr 2010 15:43:57 +0000</pubDate>
		<dc:creator>udidahan</dc:creator>
				<category><![CDATA[Agile]]></category>
		<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Management]]></category>
		<category><![CDATA[Projects]]></category>
		<category><![CDATA[TDD]]></category>
		<category><![CDATA[Testing]]></category>
		<category><![CDATA[The Team]]></category>

		<guid isPermaLink="false">http://www.udidahan.com/?p=1221</guid>
		<description><![CDATA[Almost at every conference, event, training, or consulting engagement someone asks for my opinion on the whole design for testability thing. I&#8217;m not quite sure why I haven&#8217;t blogged on this topic, especially at the time that a lot of the other bloggers were weighing in, but better late than never.
Before getting into that, I [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.udidahan.com/wp-content/uploads/elephant_balance.png" style="float:right; margin-left:10px; margin-bottom:10px; " alt="keeping balance" title="keeping balance" width="204" height="203" />Almost at every conference, event, training, or consulting engagement someone asks for my opinion on the whole design for testability thing. I&#8217;m not quite sure why I haven&#8217;t blogged on this topic, especially at the time that a lot of the other bloggers were weighing in, but better late than never.</p>
<p>Before getting into that, I want to start with a slightly broader scope of discussion.</p>
<p>You see, I get asked about &#8220;best practices&#8221; on all sorts of things. And I try not to be the kind of consultant that responds with &#8220;it depends&#8221;, but the context of the question often makes the answer irrelevant. And the unspoken context of a best-practice question is:</p>
<h2>Given infinite time and budget</h2>
<p>The biggest problem that I see with well-intentioned, best-practices-following developers and architects is that they <b>don&#8217;t</b> ask the question &#8220;is this the right thing for us to be focusing on right now?&#8221; Understandably, that is a difficult question to answer &#8211; but it needs to be asked, since you don&#8217;t have infinite time or budget to do everything according to best practices (assuming those even exist).</p>
<h2>About testing</h2>
<p>The biggest issue I have with the &#8220;design for testability&#8221; topic is the extremely narrow view it takes of the word &#8220;testability&#8221;, usually in the form of more code written by a developer which invokes the production code of the system, also known as &#8220;unit tests&#8221;.</p>
<p>There are many different kinds of testing &#8211; unit, integration, functional, load, performance, exploratory, etc&#8230; where some may be automated and others not. Should we not discuss what &#8220;design for testability&#8221; means for not-just-unit-testing?</p>
<h2>And what&#8217;s the point of testing anyway?</h2>
<p>It&#8217;s not to find bugs.</p>
<p>Research has shown that testing (of all kinds) is not the most effective way of finding bugs. I don&#8217;t have the reference handy but I&#8217;m pretty sure that it&#8217;s from <a href="http://alistair.cockburn.us/">Alistair Cockburn&#8217;s work</a>. Code reviews are (on average) about 60% more effective.</p>
<p>Don&#8217;t get me wrong &#8211; testing can provide indications that the software <b>has</b> bugs in it, but not necessarily where in the code those bugs are.</p>
<p>The purpose of testing is to provide quantitative and qualitative information about the system that can help various stakeholders in their decision-making processes. The relevance of that information indicates the quality of the testing. Here are some examples:</p>
<ul>
<li>The system supports 100 concurrent users, with the expected user-type distribution (X% role A, Y% role B, etc), performing expected use-case distributions, and collaboration scenarios.</li>
<li>Time to proficiency for new users in role A is expected to be 3 days</li>
<li>Alternate #2 of use case #12 fails on step #3</li>
</ul>
<p>As you can see, the relevance of the above information is dependent on what decisions the various stakeholders need to make. The bullet on load can help us decide if more machines are needed or if developers need to tune the performance of the systems. The bullet on time to proficiency can help us decide if larger investment in usability is required. Information like the last bullet can be used in conjunction with the first two to decide on the timing and type of a release.</p>
<p>The timeliness of this relevant information is critical to the success of a project.</p>
<p>Choosing which and how much of the various testing activities to perform when is something that needs to be revisited several times throughout the lifetime of a project, taking into account the current risks (threats and probabilities) and time and resource investment to mitigate them.</p>
<p>Let me reiterate &#8211; we&#8217;re not going to have enough time to do everything.</p>
<h2>On iterations</h2>
<p>If the only part of your organization that is doing iterations are your developers, you&#8217;re not agile.</p>
<p>In order to capitalize on the information that testers are providing, you need them in your iterations.</p>
<p>The same goes for the other roles involved in the project &#8211; business analysts, DBAs, sysadmins, etc.</p>
<p>I know that 99% of organizations aren&#8217;t structured in a way to do this.</p>
<p>I never said doing this would be easy.</p>
<h2>On design</h2>
<p>Figuring out what kind of design and how much to do when is just as important, and just as hard. Design for testability is one part of that, but not the only one, or necessarily the most important one at any point of time.</p>
<p>Within that design for testability topic is the &#8220;design for unit-testing&#8221; sub-topic which seems to be the popular one. Before getting into the design aspects of it, let&#8217;s take a closer look at the unit-testing side of things.</p>
<h2>On unit-testing</h2>
<p>The assumption is that having more unit tests will lead to a code-base with less bugs, thus requiring shorter time to get the system into production, which will pay back the time it took to write those unit tests to begin with.</p>
<p>In practice, what tends to happen is that as development progresses, testing code breaks as the structure of the production code changes. Now one of two things happens &#8211; either the testing code is removed or rewritten. In either case, we didn&#8217;t get the return on investment we expected on the first bit of testing code. Unfortunately, rare is the case where the relevant people in the organization understand <b>why</b>, resulting in the same situation repeating itself over and over again.</p>
<p>Those projects would have been better off without unit testing, though the organization as a whole might have used those experiences to learn and improve. It&#8217;s been my experience that if the organization wasn&#8217;t conscious enough in the context of the project to notice the situation, it is unlikely to do so at higher levels.</p>
<h2>On fragile unit tests</h2>
<p>The reason that a unit test ends up being rewritten (or removed) is that its code was coupled to the production code in such a way that it broke when the production code changed. This tendency to break (fragility) is a critical property of a unit test. A fragile unit test will slow down a developer doing work on some existing code &#8211; it actually makes the system less maintainable.</p>
<p>For a unit test code to be stable (not fragile) it needs to be coupled to stable properties of the production code. The question of whether the production code is designed in such a way that it has stable properties &#8211; is a design question. Is it a <b>unit</b>? If not, you will <b>not</b> be able to write a unit-test against it.</p>
<p>And anyway, who said that every class is a unit, or should be a unit? Domain models (when done right) are good examples of a unit, yet the classes that make them up may not be units. Unit-testing should only be attempted with things which are units. </p>
<p>I think too much weight is put on whether a dependency of a class is a concrete or interface type, and not nearly enough on the nature of the dependency. I wouldn&#8217;t blame the hammer for pounding my thumb, and by the same token I think that blame should not be directed towards tools like those from TypeMock.</p>
<h2>On tools</h2>
<p>There is so much more depth to both design and testability that needs to be more broadly understood. No tool has yet been created to handle either design or testing in such a way that humans can give up responsibility for the outcome. </p>
<p>Over the years I&#8217;ve noticed that tools are most significant when used by skilled practitioners, which makes sense in retrospect. Giving a novice carpenter a laser-guided saw probably won&#8217;t significantly change the outcome of their work. Ultimately, the skilled practitioners are the ones that create tools &#8211; not the novices. And no tool, no matter how advanced, will make a novice perform at levels like the skilled practitioner.</p>
<p>In the case of a project too big for a single skilled practitioner to complete in the time required (or at all), the balance of importance shifts away from tools to the project management topics described above.</p>
<h2>In summary</h2>
<p>I hope that this post has shed some light on the context in which decisions with respect to testing need to be made. Design is one activity that can support certain kinds of testing, but not the only one, or even the most important one for the given type of testing necessary at that time in the project.</p>
<p>Design is hard. Project management is hard. Testing is hard.</p>
<p>Getting the right mix of people that together have enough experience and skills in these activities isn&#8217;t easy.</p>
<p>Don&#8217;t expect that sprinkling some interfaces in your code base will be enough.<br />
That doesn&#8217;t count much in the way of design, just as writing code in a testing namespace doesn&#8217;t count much in the way of testability.</p>
<p>Looking forward to hearing your comments.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.udidahan.com/2010/04/18/on-design-for-testability/feed/</wfw:commentRss>
		<slash:comments>20</slash:comments>
		</item>
		<item>
		<title>On Small Applications</title>
		<link>http://www.udidahan.com/2010/03/07/on-small-applications/</link>
		<comments>http://www.udidahan.com/2010/03/07/on-small-applications/#comments</comments>
		<pubDate>Sun, 07 Mar 2010 11:32:34 +0000</pubDate>
		<dc:creator>udidahan</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Management]]></category>
		<category><![CDATA[The Team]]></category>

		<guid isPermaLink="false">http://www.udidahan.com/?p=1199</guid>
		<description><![CDATA[I hear this too often: &#8220;X sounds like a great pattern, but it&#8217;s overkill for small applications&#8221;. Many patterns have been subjected to this including (but not limited to): SOA, DDD, CQRS, ORM, etc. Often the statement is made by a person without experience in the given pattern (though possibly experienced in other patterns). Let&#8217;s [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.udidahan.com/wp-content/uploads/small_baby.png" style="float:right; margin-left:10px; margin-bottom:10px;" alt="small" title="small" />I hear this too often: &#8220;X sounds like a great pattern, but it&#8217;s overkill for small applications&#8221;. Many patterns have been subjected to this including (but not limited to): SOA, DDD, CQRS, ORM, etc. Often the statement is made by a person without experience in the given pattern (though possibly experienced in other patterns). Let&#8217;s take a look at the second part &#8211; the &#8220;small application&#8221;, and ask:</p>
<h3>What makes an app small?</h3>
<p>Or inversely, what makes an app warrant the &#8220;enterprise&#8221; moniker?</p>
<p>If there&#8217;s one thing that the history of our industry has shown repeatedly, it&#8217;s that developers aren&#8217;t particularly accurate with their estimates. Like, orders-of-magnitude inaccurate. Knowing this, it&#8217;s surprising that the &#8220;small app&#8221; argument seems to win so many arguments. The same goes for justifications in the form of &#8220;we&#8217;ve got to have an X, this is a BIG project&#8221;.</p>
<p>So, what makes an app small? </p>
<p>Is it a small number of lines of code? Well, what if those lines of code are keeping planes in the air?</p>
<p>Is it a small number of developers? Same as above. Actually, history has shown that some of the most valuable bits of code written were done by small numbers of developers. </p>
<p>Is it that it will only be installed on a single machine? </p>
<p>Is it&#8230;</p>
<p>What could it be?</p>
<h3>The real issue</h3>
<p>The small app argument is a diversionary tactic. </p>
<p>Loosely translated, it means &#8220;I&#8217;m comfortable where I am and I don&#8217;t want to change&#8221;.</p>
<p>Moving on&#8230;</p>
<h3>The real story of size</h3>
<p>Once we actually look at the specific context of an app, we tend to see that someone cares a great deal about it, enough to finance its custom development &#8211; rather than buying an off-the-shelf alternative. The expected lifetime of business use is easily 3-5 years, if not 7-10, during which many enhancements will likely be requested. Thus, some non-functional properties of the code matter &#8211; at the very least maintainability.</p>
<p>In which case, if the given pattern or approach does significantly improve the desired non-functional properties of the app, it only makes sense to use it.</p>
<p>There is one class of software that might possibly be treated as &#8220;small&#8221; &#8211; the one-off script that&#8217;s written to automate some IT task. And even then, so many of these scripts end up living longer than the apps themselves that they should be engineered at the same level of quality.</p>
<h3>In closing</h3>
<p>Don&#8217;t counter a &#8220;small app&#8221; argument with psychology.<br />
It will only make matters worse.</p>
<p>Instead, rephrase the issue around the lifetime of business use. </p>
<p>I&#8217;ve found that there are precious few cases where the harsh light of reality doesn&#8217;t help the appropriate decisions be made. If indeed this is a small-lifetime-app, just drag-and-drop until you&#8217;re done. Otherwise, the time it takes to understand and evaluate the applicability of the given patterns will definitely pay itself back many times over the life of the app.</p>
<p>And managers, keep your ears open for it. The technical risks behind that statement are icebergs waiting to sink your project.</p>
<p>* with thanks to <a href="http://devlicious.com/blogs/mike_nichols/archive/2010/03/06/the-biggest-driver-for-domain-modeling-decisions.aspx">Mike Nichols</a> for pushing my buttons.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.udidahan.com/2010/03/07/on-small-applications/feed/</wfw:commentRss>
		<slash:comments>20</slash:comments>
		</item>
		<item>
		<title>CQRS Video Online</title>
		<link>http://www.udidahan.com/2010/02/26/cqrs-video-online/</link>
		<comments>http://www.udidahan.com/2010/02/26/cqrs-video-online/#comments</comments>
		<pubDate>Fri, 26 Feb 2010 09:42:45 +0000</pubDate>
		<dc:creator>udidahan</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[CQRS]]></category>
		<category><![CDATA[Community]]></category>
		<category><![CDATA[Messaging]]></category>
		<category><![CDATA[Presentations]]></category>
		<category><![CDATA[Pub/Sub]]></category>
		<category><![CDATA[Scalability]]></category>
		<category><![CDATA[Validation]]></category>

		<guid isPermaLink="false">http://www.udidahan.com/?p=1184</guid>
		<description><![CDATA[A couple of weeks ago I gave a talk on Command/Query Responsibility Segregation in London. 
The recording of the talk is online here.
There is one important thing that I didn&#8217;t have enough time to cover, but I want you to keep in mind as you&#8217;re watching this. It is that CQRS is applicable only *within* [...]]]></description>
			<content:encoded><![CDATA[<p>A couple of weeks ago I gave a talk on Command/Query Responsibility Segregation in London. </p>
<p>The recording of the talk is online <a href="http://skillsmatter.com/podcast/open-source-dot-net/udi-dahan-command-query-responsibility-segregation/rl-311">here</a>.</p>
<p>There is one important thing that I didn&#8217;t have enough time to cover, but I want you to keep in mind as you&#8217;re watching this. It is that CQRS is applicable only *within* the context of a single service/BC &#8211; NOT across or between them.</p>
<p>Let me know what you think.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.udidahan.com/2010/02/26/cqrs-video-online/feed/</wfw:commentRss>
		<slash:comments>19</slash:comments>
		</item>
		<item>
		<title>Non-functional Architectural Woes</title>
		<link>http://www.udidahan.com/2010/01/12/non-functional-architectural-woes/</link>
		<comments>http://www.udidahan.com/2010/01/12/non-functional-architectural-woes/#comments</comments>
		<pubDate>Wed, 13 Jan 2010 04:29:31 +0000</pubDate>
		<dc:creator>udidahan</dc:creator>
				<category><![CDATA[Architecture]]></category>

		<guid isPermaLink="false">http://www.udidahan.com/?p=1165</guid>
		<description><![CDATA[
As I sit here in the lounge at Bogota airport waiting for my delayed flight, I remembered something interesting that came up in my 2-week training/consulting in Cali. It&#8217;s not a question that came up, or anything like that. It was that I suddenly noticed a pattern in many of my consulting and training clients [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.udidahan.com/wp-content/uploads/non-functional-architecture.png" style="float:right; margin-left:10px; margin-bottom:10px;" alt="Non-functional architecture" title="Non-functional architecture" /><br />
As I sit here in the lounge at Bogota airport waiting for my delayed flight, I remembered something interesting that came up in my 2-week training/consulting in Cali. It&#8217;s not a question that came up, or anything like that. It was that I suddenly noticed a pattern in many of my consulting and training clients over the past years. And as I thought about it, I realized that it was prevalent in our industry as a whole &#8211; in the literature, on the web, everywhere.</p>
<p>It&#8217;s how people think about functional and non-functional requirements.</p>
<h3>The problem with categorization</h3>
<p>There&#8217;s nothing wrong with categorizing requirements as either functional or non-functional.</p>
<p>The problem is that people project that categorization from the problem domain to the solution domain as well.</p>
<p>There is an impression that architecture and technology choices are, to a large extent, based on non-functional requirements, and only on non-functional requirements.</p>
<p>Here are some examples:</p>
<p><b>Extensibility: </b> Workflow/BPM engine , DSL, Plug-in framework, etc<br />
<b>Scalability: </b> Message/Service Bus, Database (NoSQL camp, I&#8217;m looking at you too), etc<br />
<b>High Availability:</b> See scalability</p>
<p>Too many times have I noticed architects so focused on these issues that they all but ignore the functional requirements and the business objectives of the stakeholders.</p>
<p>Not to place an unfair portion of the blame there, the vendors have been perpetuating the above fallacies to sell more and/or new products. Given the enormous influence of the big vendors (conferences, training, etc) it isn&#8217;t any wonder that architects in the field use the vendors&#8217; &#8220;best practices&#8221;.</p>
<p>The problem that arises from this kind of thinking is a shoe-horning of functional requirements into the architecture decided upon entirely in the context of non-functional requirements.</p>
<h3>Functional Earthquakes</h3>
<p>Stable architecture cannot be created based entirely on non-functional requirements. There are functional requirements that can shake the foundation of a technically-oriented architecture.</p>
<p>Let&#8217;s take the canonical layered architecture with its normalized database. Now we get a new requirement in the form of:</p>
<p>&#8220;As a supplier, when I log-in, I want to see on my home page my most recent purchase orders, grouped by highest value retailer (total historical purchase order value), sorted according to requested time of delivery.&#8221;</p>
<p>In order for a developer to implement this according to the architectural guidelines of normalization and layering here&#8217;s what they do: join retailers who have an agreement with the supplier (join between supplier, retailer, and agreement tables), join the purchase orders and their lines, (ignoring tax for now), sum the line value and group by retailer, and use as an input to the purchase order table joining again, filter in last 24 hours, sort by time of delivery.</p>
<p>So, in our normalized database, we have many millions of purchase orders, hundreds of millions of lines, that we&#8217;re joining against each other as well as several other tables.</p>
<p>After this new feature has been implemented, any time a supplier sees their home page, the system stops accepting purchase orders until the home page has been rendered several minutes later.</p>
<p>Can we really say that our architecture is stable if a single functional requirement can undo all of it&#8217;s non-functional properties?</p>
<p>Obviously not &#8211; but the question the architect (and his boss) are asking is, how did this happen? And if it happened once, can it happen again?</p>
<h3>Lessons Learned &#8211; sorta</h3>
<p>So a reporting database is introduced so that all complex queries like those performed above won&#8217;t prevent the system from accepting new purchase orders. A nightly batch moves data from the normalized DB to the reporting DB. Sounds good &#8211; non-functionally.</p>
<p>And then a new requirement comes in for handling rush-orders. </p>
<p>So we do an hourly batch. But now these batches start to cause hiccups to our transactional system, which gets backed up, and when released, allocates many more threads to deal with the pending load, and the increased concurrency in the databases sharply increases the number of deadlocks, further backing up the system, until the system becomes effectively unavailable.</p>
<p>Can this be happening again? A functional requirement undoing all of our technically elegant non-functional architectural decisions?</p>
<h3>Now what?</h3>
<p>The technology is blamed. We should have never counted on SQL Server to handle our kind of *enterprise* requirements. Let&#8217;s move to Oracle &#8211; it&#8217;s *unbreakable*. (Several months and functionalities later) We should have never counted on a database to handle our kind of enterprise requirements. Let&#8217;s introduce an *Enterprise Service Bus*. (Several months and functionalities later) We should have never counted on our internal IT to host this. Let&#8217;s move to *The Cloud*. (Several months and functionalities later, looking at the bill from our cloud provider) We should have never used .NET for our application because it requires the more expensive Windows cloud. Let&#8217;s rewrite on Linux to reduce our cloud costs.</p>
<p>By this time, all the people who originally worked on the project aren&#8217;t there anymore. And the cycle continues with limited memory of where we started and how we got here.</p>
<p>Soon, soon, we&#8217;ll find that non-functional silver bullet that will make all of our problems go away.</p>
<h3>These are not the droids you are looking for</h3>
<p>They really aren&#8217;t.</p>
<p>If we want our architecture to be stable, we need to base it on stable abstractions. The only thing is that there aren&#8217;t any inherently stable abstractions in the solution domain (as we&#8217;ve had the chance to witness). That really only leaves one other place to look for them &#8211; in the problem domain, also known as the functional requirements.</p>
<p>But functional requirements change all the time! Wasn&#8217;t that what got us into this mess to begin with?</p>
<p>Indeed, but in between the functional requirements and behind them is something that is quite stable: the stakeholders business objectives.</p>
<p>The supply chain will continue to strive to optimize itself. To shorten the time for an order to be fulfilled. To decrease the amount of inventory that a retailer holds. To choose the best set of suppliers for our product catalog. To recognize which retailers give me the most business and serve them better. To identify high potential retailers &#8211; big retailers (like Walmart) who aren&#8217;t buying as much from me as other retailers.</p>
<p>This is how the business has been done for decades and will continue to be done for decades more.</p>
<p>If we could find a way to capture those stable elements and represent them as core elements in our architectural structure, and then balance the non-functional requirements within those functional contexts, maybe, just maybe, our architecture will stand the test of time.</p>
<p>More to come&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.udidahan.com/2010/01/12/non-functional-architectural-woes/feed/</wfw:commentRss>
		<slash:comments>24</slash:comments>
		</item>
		<item>
		<title>Scalability Podcast on Herding Code</title>
		<link>http://www.udidahan.com/2010/01/11/scalability-podcast-on-herding-code/</link>
		<comments>http://www.udidahan.com/2010/01/11/scalability-podcast-on-herding-code/#comments</comments>
		<pubDate>Mon, 11 Jan 2010 19:44:49 +0000</pubDate>
		<dc:creator>udidahan</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Community]]></category>
		<category><![CDATA[Podcast]]></category>
		<category><![CDATA[Scalability]]></category>

		<guid isPermaLink="false">http://www.udidahan.com/?p=1168</guid>
		<description><![CDATA[The great folks over at Herding Code were nice enough to interview me back in November as I was over in Paris giving my 5-day SOA course. We talked about quite a lot of topics related to scalability.
Click here for the full list of topics and to download the podcast.
Let me know what you think [...]]]></description>
			<content:encoded><![CDATA[<p>The great folks over at <a href="http://www.herdingcode.com">Herding Code</a> were nice enough to interview me back in November as I was over in Paris giving my <a href="http://www.UdiDahan.com/training">5-day SOA course</a>. We talked about quite a lot of topics related to scalability.</p>
<p><a href="http://herdingcode.com/?p=229">Click here</a> for the full list of topics and to download the podcast.</p>
<p>Let me know what you think or any questions you may have in the comments.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.udidahan.com/2010/01/11/scalability-podcast-on-herding-code/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

