<?xml version="1.0"?>
<rss version="2.0">
<channel>
  <title>The Kitchen in the Zoo - architecture tag</title>
  <link>http://blog.maxant.co.uk:80/pebble/tags/architecture/</link>
  <description>&lt;small&gt;A blog where Ant writes about anything he finds interesting! &lt;a href=&#039;http://www.linkedin.com/in/maxant&#039;&gt;&lt;font color=&#039;white&#039;&gt;Who is Ant?&lt;/font&gt;&lt;/a&gt;      &lt;a href=&#039;/pebble/pages/copyright.html&#039;&gt;&lt;font color=&#039;white&#039;&gt;Copyright 2005-2012 Ant Kutschera&lt;/font&gt;&lt;/a&gt;&lt;/small&gt;</description>
  <language>en</language>
  <copyright>Ant Kutschera</copyright>
  <lastBuildDate>Thu, 10 May 2012 20:07:00 GMT</lastBuildDate>
  <generator>Pebble (http://pebble.sourceforge.net)</generator>
  <docs>http://backend.userland.com/rss</docs>
  
  
  <item>
    <title>Playing with Cache Performance</title>
    <link>http://blog.maxant.co.uk:80/pebble/2010/12/30/1293745380000.html</link>
    
      
        <description>
          &lt;p&gt;My current client has a service which connects to an old IBM z/OS application (legacy system).  The data centre charges for each message sent to this legacy system, rather than using a processor or hardware based pricing model.  The output from this legacy system is always the same, since the calculations are idempotent.  The application calculates prices for travelling along a given route of the train network.  Prices are changed only twice a year through an administration tool.  So in order to save money (a hundered thousand dollars a year), the service which connects to this legacy system had an in-memory least-recently-used (LRU) cache built into it, which removes the least recently used entries when it gets full in order to make space for new entries.  The cache is quite large, thus avoiding making costly calls to the legacy system.  To avoid losing the cache content upon server restarts, a background task was later built to periodically persist the latest data inside this cache.  Upon starting a server, the cache content is re-read.  Entries within the cache have a TTL (time to live) so that stale entries are discarded and re-fetched from the legacy system.&lt;br /&gt;
&lt;br /&gt;
This cache was great in the beginning because it saved the customer a lot of money, but in the mean time several similar caches have been added, as well as more general caches for avoiding repeated database reads, causing our nodes to need over 1.5 GB of RAM.  Analysis has showed that the caches are consuming over 500 MB alone.  The platform is WebSphere and IBM only recommends running with 512 MB per node...  So as you can see, we are on the road to having some memory issues.  In order to avoid these issues, and potentially also save money by requireing less hardware for our applications, I have taken time to think about possible architectures which could solve the problems.&lt;br /&gt;
&lt;br /&gt;
One of the problems is that the cache is an internal part of the service, i.e. it is a glorified Map referenced as a singleton.  That means, each node has its own cache instance.  Worse actually, because of the class loaders in application servers, each application has its own instance of the service and hence its own instance of the cache, and because the service is deployed per application, each cache exists multiple times per node in the cluster.  The result is an architecture as follows, where there are for example 8 instances of the same cache:&lt;br /&gt;
&lt;br /&gt;
&lt;img width=&#034;500&#034; alt=&#034;&#034; src=&#034;/pebble/images/cachePerformance1.gif&#034; /&gt;&lt;br /&gt;
&lt;br /&gt;
While these in memory caches are quick, that is not the main reason for having created them.  The main reasons were to avoid hammering either the database or the legacy systems with repeated queries which result in the same outcome.  While the caches theoretically speed up the the applications, the associated increase in garbage collection might actually result in lower overall speed because the garbage collector needs to run more frequently because there is less memory available for use by the application itself, because the caches consume so much.&lt;br /&gt;
&lt;br /&gt;
This got me thinking about creating a centralized cache, of which there is one single instance for use by all applications.  The architecture would then look like this:&lt;br /&gt;
&lt;br /&gt;
&lt;img width=&#034;500&#034; alt=&#034;&#034; src=&#034;/pebble/images/cachePerformance2.gif&#034; /&gt;&lt;br /&gt;
&lt;br /&gt;
The requirements for the cache are:&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;Persistent, so that server restarts do not cause all content to be lost,&lt;/li&gt;
    &lt;li&gt;Single, so that the entire landscape contains just one cache rather than the same data being cached lots of times as it is today,&lt;/li&gt;
    &lt;li&gt;Relatively fast,&lt;/li&gt;
    &lt;li&gt;No impact on existing infrastructure, i.e. if we stick our cache into our database, that influences the reading/writing of other data by making the database perform less well.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So, what are the options for creating such a cache?&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;In Memory, but remote, backed by persistence, similar to what we have today, only with the service deployed as a remote EJB, rather than being called locally,&lt;/li&gt;
    &lt;li&gt;A bigtable style, NoSQL cache, because they are based on key/value pairs and can handle lots of data,&lt;/li&gt;
    &lt;li&gt;LDAP, because LDAP is persistent as well as optimised for read access.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;br /&gt;
A fourth option might be to use a database cache, i.e. a table devoted to key/value pairs cached in the database, which gets read every time you need data, but this would affect overall database performance, so isn&#039;t really an option.  I have however included such a solution in the solutions that I tried below, simply to compare performance.&lt;br /&gt;
&lt;br /&gt;
While the concept of a bigtable style database is aimed at large amounts of data (billions of rows and millions of columns), what is of interest in this case is that it is based on key/value pairs, which is exactly what we need for our cache.  The caches used today are LRU caches, because to store all possible data would require too much memory (there are millions of routes on the train network), which is also the reason why we wouldn&#039;t want to store all possible routes in the database.  However, because a bigtable style database supports large data sets while maintaining performance, we can potentially just let it contain all possible routes.  The strategy for filling such a cache would be to check the cache for the required entry, if it doesn&#039;t exist, to then query the legacy system, and its answer be cached for future use, until it becomes stale.&lt;br /&gt;
&lt;br /&gt;
So first things first, I started up Glassfish for Eclipse and MySQL to do some tests.  I created a set of tables to contain 100,000 train stations, generated randomly.  Then I added 100,000 random routes, each containing between 3 and twenty stations.  It is these routes which the legacy system calculates prices for.  The first solution I implemented was a pure database cache, where a query to the service which encapsulates the legacy system first checked if the database contained a cache entry for the key, made up of the &amp;quot;from&amp;quot; station and the &amp;quot;to&amp;quot; station codes.  If there was no hit on the cache, the legacy system was queried and its result was cached.  I filled the cache with all 100,000 routes and began making measurements.  My first results were rather poor, with requiring several hundred milliseconds to read from the cache, even though the cache key was the primary key, that is indexed!  OK, the test system was my aging IBM T60 Intel Core Duo (2 core CPU) laptop with only 2 GB RAM, running Windows XP, Glassfish, MySQL, and a handful of other (memory intensive) applications and services.&lt;br /&gt;
&lt;br /&gt;
I started reading up about Cassandra, the Apache application based on bigtable, and in the performance tuning section it mentioned about using two disks for seperate files which it writes.  That made me think about what was going on on my laptop and I realised that one reason why my first solution was so slow was that I was running applications using over 2 GB of RAM, so I was well into the region where the OS was using virtual memory and swapping from RAM to disk continuously.  Sure enough, during tests, my hard disk light was going crazy.  I have been wanting to upgrade this laptop for a while, but it belongs to the client, so I cannot really upgrade it.  But I did a little more reading and decided to try out a USB 3.0 external hard disk (500 GB &amp;quot;My Passport&amp;quot; from Western Digital), together with an Expressbus USB 3.0 adapter.  This gave me a very fast external hard drive.  Random read/write tests showed that this external hard drive was actually up to three times faster than the internal one!&lt;br /&gt;
&lt;br /&gt;
So, I got back to testing, and installed my apps (Glassfish and MySQL, etc) on the external hard drive, leaving the internal harddrive for the OS and disk swapping.  In the ideal world, one would do this the other way around and install an SSD for the OS and its swap file, leaving a slower more conventional spinning hard disk for applications and data.  Anyway, instead of a single drive having to try to do swapping and reading of say the database simultaneously, this configuration let the internal drive handle swapping, while the external drive handled reading for the database, basically allowing parallel tasks.&lt;br /&gt;
&lt;br /&gt;
Sure enough, I was able to get random cache read times for this database cache, down to 15 milliseconds.  It still wasn&#039;t that fast, but interestingly, this database was doing nothing else at all, simply servicing cache reads (i.e. reads out of a single table with a cache key as the primary key, and a &lt;code&gt;varchar&lt;/code&gt; for the value (a serialised Java object).  Since this solution influences the existing infrastructure, i.e. the database, it would not fulfil the requirements I created earlier in this post.&lt;br /&gt;
&lt;br /&gt;
I next downloaded &lt;a href=&#034;http://cassandra.apache.org/&#034; target=&#034;_blank&#034;&gt;Cassandra from Apache&lt;/a&gt;, and read a few introductions like the ones &lt;a target=&#034;blank&#034; href=&#034;http://arin.me/blog/wtf-is-a-supercolumn-cassandra-data-model&#034;&gt;here&lt;/a&gt; and &lt;a target=&#034;blank&#034; href=&#034;http://www.sodeso.nl/?p=354&#034;&gt;here&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
What I wanted to do was not complex at all, so I created a structure with a single ColumnFamily (like a table).  I filled it with all 100,000 routes, and started performance testing, and got average read times similar to MySQL.  I read up a little more about performance tuning and I discovered that I could control the number of entries cached in memory inside Cassandra.  I set this to be 99% and sure enough, my results improved to the point that after a few hundred thousand reads (which would happen fast in production), I was getting read times of around 2 milliseconds.  Cassandra was running as a single process on the same laptop on which GlassFish was running, which contained a service which wrapped calls to Cassandra.  The data structures were simple with each cache entry stored within a single key in Cassandra, basically having a single column for the ColumnFamily, containing the serialised route object.&lt;br /&gt;
&lt;br /&gt;
Further reading introduced the idea that Cassandra is optimised for reading many columns within a single &amp;quot;row&amp;quot; (key).  I tried restructuring the data so that the key for each &amp;quot;row&amp;quot; was the &amp;quot;from&amp;quot; station code, and for each destination from that station, a column was added within the row.  So I had many less keys in Cassandra, but many more columns per row.  And because these bigtable solutions do not require each key to have identical columns, allowing sparsely filled tables, it was perfect for this restructuring.&lt;br /&gt;
&lt;br /&gt;
I refilled the cache using this new structure, and sure enough, once Cassandra had loaded a few hundred thousand keys and they were all cached in its memory (set at 256 MB for the process), average random read times sank to just 1 millisecond.  Compared to MySQL things were looking good.&lt;br /&gt;
&lt;br /&gt;
Time for the next proposed solution, which was to make calls to a remote EJB running in its own node (or rather cluster).  I implemented this by creating a simple stateless session EJB which contained a static reference to a &lt;code&gt;Hashtable&lt;/code&gt; (so that it was thread safe).  I didn&#039;t bother implementing the persistent part in the first instance, because I was interested in how long it would take to simply call the remote EJB and do the lookup in the &lt;code&gt;Map&lt;/code&gt;.  I deployed the EJB to Apache OpenEJB running as a simple process on the same laptop and after filling the cache completely, the average time for random reads was around 2 milliseconds, i.e. similar to Cassandra, albeit a tiny bit slower.&lt;br /&gt;
&lt;br /&gt;
The final option was to try out LDAP.  I only considered this because LDAP is optimised for reading, which is what this service is doing.  I used ApacheDS that also as a process on my laptop.  I filled LDAP with my 100,000 routes by basically filling my organisation unit with new sub-organisational units per key, with the Base64 encoded serialised object attached to the sub-OU as an attribute, such that the cache entry had a URL like &lt;code&gt;ldap://localhost:10389/ou=8500101_8500103,ou=verbindungen,ou=system&lt;/code&gt;.  Sadly I am no expert on LDAP and was not too sure how to optimise it, beyond increasing the cache size attribute of the system partition in &lt;code&gt;server.xml&lt;/code&gt; inside ApacheDS.  The results were far from promising with average random read times around 50 milliseconds.&lt;br /&gt;
&lt;br /&gt;
In all cases, I optimised my code so that connections to the remote processes were created post EJB construction, and just once, until the EJB instance was destroyed (using the &lt;code&gt;@PostConstruct&lt;/code&gt; EJB 3 annotation).  In all cases, the average read times were measured per cache entry, based on 1000 random serial cache reads, after reading over 100,000 entries to ensure that the external process had had time to optimised its own in memory key cache.&lt;br /&gt;
&lt;br /&gt;
The results are summarised as follows:&lt;/p&gt;
&lt;table cellspacing=&#034;0&#034; cellpadding=&#034;0&#034; border=&#034;1&#034;&gt;
    &lt;tbody&gt;
        &lt;tr&gt;
            &lt;td&gt;&lt;b&gt;Solution&lt;/b&gt;&lt;/td&gt;
            &lt;td&gt;&lt;b&gt;Average Read Time&lt;/b&gt;&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;MySQL Cache table&lt;/td&gt;
            &lt;td&gt;15 ms&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;Cassandra&lt;/td&gt;
            &lt;td&gt;1 ms&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;Remote EJB&lt;/td&gt;
            &lt;td&gt;2 ms&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;ApacheDS LDAP&lt;/td&gt;
            &lt;td&gt;50 ms&lt;/td&gt;
        &lt;/tr&gt;
    &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;br /&gt;
The nice part about using Cassandra would be that we don&#039;t have to write the code for this cache, nor maintain it.  Additionally, there are other areas within our landscape that could make good use of a bigtable style solution because the amounts of data are getting very slow to handle, so it would be useful to start getting to know the new world.&lt;br /&gt;
&lt;br /&gt;
The not so nice part about Cassandra, is that it is not standard software at this client.  We would need to create a request for architecture and invest time convincing some enterprise architects that we need Cassandra and that our platform people and data centre should invest in order to support it.  This could end up involving software evalutations and eventual licence costs if they chose a commercial solution.  All this effort could easily cost more than we could possibly save by implementing a single cache in order to reduce the amount of hardware required today.  Politics are great, eh :-|  I shall be putting the proposals forward in the new year, let&#039;s see what they bring.&lt;br /&gt;
&lt;br /&gt;
One quick final note: the times measured here are not realistic of the target environment - a laptop doesn&#039;t compare to a cluster!  But they can be used as relative indicators to suggest which solutions might be worth further investigation.  Only final deployment to production can give the real answer, as shown by this &lt;a href=&#034;http://techcrunch.com/2010/09/07/digg-struggles-vp-engineering-door/&#034; target=&#034;_blank&#034;&gt;example&lt;/a&gt;, although just because Digg had problems, doesn&#039;t mean Cassandra is bad.  It does show that you need to think long and hard about your architecture though. &lt;br /&gt;
&lt;br /&gt;
Copyright &amp;copy; 2010 Ant Kutschera&lt;/p&gt;&lt;div class=&#034;tags&#034;&gt;&lt;span&gt;Social Bookmarks : &lt;/span&gt;&amp;nbsp;&lt;a href=&#034;http://slashdot.org/bookmark.pl?url=http://blog.maxant.co.uk:80/pebble/2010/12/30/1293745380000.html&amp;amp;title=Playing+with+Cache+Performance&#034; target=&#034;_blank&#034; title=&#034;Add this post to Slash Dot&#034;&gt;&lt;img src=&#034;common/images/slashdot.png&#034; alt=&#034;Add this post to Slashdot&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://digg.com/submit?url=http://blog.maxant.co.uk:80/pebble/2010/12/30/1293745380000.html&amp;amp;title=Playing+with+Cache+Performance&#034; target=&#034;_blank&#034; title=&#034;Digg this post&#034;&gt;&lt;img src=&#034;common/images/digg.png&#034; alt=&#034;Add this post to Digg&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://reddit.com/submit?url=http://blog.maxant.co.uk:80/pebble/2010/12/30/1293745380000.html&amp;amp;title=Playing+with+Cache+Performance&#034; target=&#034;_blank&#034; title=&#034;Add this post to Reddit&#034;&gt;&lt;img src=&#034;common/images/reddit.png&#034; alt=&#034;Add this post to Reddit&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://del.icio.us/post?url=http://blog.maxant.co.uk:80/pebble/2010/12/30/1293745380000.html&amp;amp;title=Playing+with+Cache+Performance&#034; target=&#034;_blank&#034; title=&#034;Save this post to Del.icio.us&#034;&gt;&lt;img src=&#034;common/images/delicious.png&#034; alt=&#034;Add this post to Delicious&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.stumbleupon.com/submit?url=http://blog.maxant.co.uk:80/pebble/2010/12/30/1293745380000.html&amp;amp;title=Playing+with+Cache+Performance&#034; target=&#034;_blank&#034; title=&#034;Stumble this post&#034;&gt;&lt;img src=&#034;common/images/stumbleupon.png&#034; alt=&#034;Add this post to Stumble it&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.google.com/bookmarks/mark?op=edit&amp;amp;bkmk=http://blog.maxant.co.uk:80/pebble/2010/12/30/1293745380000.html&amp;amp;title=Playing+with+Cache+Performance&#034; target=&#034;_blank&#034; title=&#034;Add this post to Google&#034;&gt;&lt;img src=&#034;common/images/google.png&#034; alt=&#034;Add this post to Google&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://technorati.com/faves?add=http://blog.maxant.co.uk:80/pebble/2010/12/30/1293745380000.html&#034; target=&#034;_blank&#034; title=&#034;Add this post to Technorati&#034;&gt;&lt;img src=&#034;common/images/technorati.png&#034; alt=&#034;Add this post to Technorati&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.bloglines.com/sub/http://blog.maxant.co.uk:80/pebble/2010/12/30/1293745380000.html&#034; target=&#034;_blank&#034; title=&#034;Add this post to Bloglines&#034;&gt;&lt;img src=&#034;common/images/bloglines.png&#034; alt=&#034;Add this post to Bloglines&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.facebook.com/share.php?u=http://blog.maxant.co.uk:80/pebble/2010/12/30/1293745380000.html&#034; target=&#034;_blank&#034; title=&#034;Add this post to Facebook&#034;&gt;&lt;img src=&#034;common/images/facebook.png&#034; alt=&#034;Add this post to Facebook&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.furl.net/storeIt.jsp?u=http://blog.maxant.co.uk:80/pebble/2010/12/30/1293745380000.html&amp;amp;t=Playing+with+Cache+Performance&#034; target=&#034;_blank&#034; title=&#034;Add this post to Furl&#034;&gt;&lt;img src=&#034;common/images/furl.png&#034; alt=&#034;Add this post to Furl&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;https://favorites.live.com/quickadd.aspx?mkt=en-us&amp;amp;url=http://blog.maxant.co.uk:80/pebble/2010/12/30/1293745380000.html&amp;amp;title=Playing+with+Cache+Performance&#034; target=&#034;_blank&#034; title=&#034;Add this post to Windows Live&#034;&gt;&lt;img src=&#034;common/images/windowslive.png&#034; alt=&#034;Add this post to Windows Live&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://bookmarks.yahoo.com/toolbar/savebm?opener=tb&amp;amp;u=http://blog.maxant.co.uk:80/pebble/2010/12/30/1293745380000.html&amp;amp;t=Playing+with+Cache+Performance&#034; target=&#034;_blank&#034; title=&#034;Add this post to Yahoo!&#034;&gt;&lt;img src=&#034;common/images/yahoo.png&#034; alt=&#034;Add this post to Yahoo!&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&lt;/div&gt;
        </description>
      
      
    
    
    
    <comments>http://blog.maxant.co.uk:80/pebble/2010/12/30/1293745380000.html#comments</comments>
    <guid isPermaLink="true">http://blog.maxant.co.uk:80/pebble/2010/12/30/1293745380000.html</guid>
    <pubDate>Thu, 30 Dec 2010 21:43:00 GMT</pubDate>
  </item>
  
  <item>
    <title>DCI and Services (EJB)</title>
    <link>http://blog.maxant.co.uk:80/pebble/2010/11/20/1290288540000.html</link>
    
      
        <description>
          Data, Context and Interaction (DCI) is a way to improve the readability of object oriented code.  But it has nothing specific to say about things like transactions, security, resources, concurrency, scalability, reliability, or other such concerns.&lt;br&gt;
&lt;br&gt;
Services, in terms of stateless EJBs or Spring Services, have a lot to say about such concerns, and indeed allow the cross-cutting concerns like transactions and security to be configured outside of the code using annotations or deployment descriptors (XML configuration), letting programmers concentrate on business code.  The code they write contains very little code related to transactions or security.  The other concerns are handled by the container in which the services live.&lt;br&gt;
&lt;br&gt;
Services however, constrain developers to think in terms of higher order objects which deliver functionality.  Object orientation (OO) and DCI let programmers program in terms of objects; DCI more so than OO.  In those cases where the programmer wants to have objects with behaviour, rather than passing the object to a service, they can use DCI.&lt;br&gt;
&lt;br&gt;
If objects are to provide rich behaviour (ie. behaviour which relies on security, transactions or resources), then they need to somehow be combined with services, which naturally do this and do it with the help of a container, so that the programmer does not need to write low level boiler plate code, for example to start and commit transactions.&lt;br&gt;
&lt;br&gt;
The idea here, is to explore combining a service solution with a DCI solution.  Comparing SOA to DCI, like I did in my &lt;a target=&#039;_blank&#039; href=&#039;http://www.maxant.co.uk/whitepaperDetails.jsp?uid=10&#039;&gt;white paper&lt;/a&gt;, shows that the DCI context is analagous to the code which calls a service in a SOA solution, and that a context does not really explicitly exist in a SOA solution.  However, thinking a little more abstractly, in DCI an encapsulation of behaviour would be the context together with its roles.  In SOA, this encapsulation is the service itself.  So it is possible to realign the ideas in that white paper, to think of a context as being a service.  If the goal is to create a hybrid between services and DCI, so that all of the concerns listed at the start of this article get handled by a hybrid solution, then the roles still exist as they do in DCI, but the context becomes a &#034;service&#034; in the technical sense.&lt;br&gt;
&lt;br&gt;
Time for an example.  Imagine a train company which owns electrified tracks along which trains run.  They have a business partner who provides the electrical energy, who is offering cheaper energy to consumers who can forecast their energy consumption so that the partner can make their production more efficient.  To deliver these forecasts, the train company checks the timetable for regular passenger transport, as well as all its cargo contracts for bespoke cargo trips.  This allows them to simulate all train trips for a given time period and calcuate the energy requirement.  Now, the company is a national one, and has thousands of kilometers of track and hundreds of trains running.  They have created detailed maps of the terrain over which their tracks run, so they know the uphill and downhill segments and their power consumption changes.  They want to build some simulation software to handle the forecasting.  At the same time, there is a non-functional requirement to complete calculations extremely quickly, so rather than making them sequential, a parallel solution is required.  Here is the proposed object model:&lt;br&gt;
&lt;br&gt;
&lt;ul&gt;
	&lt;li&gt;Trip: Consists of a Train and a list of TripSegments.&lt;/li&gt;
	&lt;li&gt;Train: consists of a list of Locomotives, and a list of Wagons.  The assembly of a train comes from the Timetable.&lt;/li&gt;
	&lt;li&gt;Locomotive: Has an efficiency, a weight and rolling friction factor.&lt;/li&gt;
	&lt;li&gt;Wagon: has a weight and rolling friction factor.&lt;/li&gt;
	&lt;li&gt;TripSegment: has a Segment, and the average speed along which the Train will travel on that segment, during its trip.&lt;/li&gt;
	&lt;li&gt;Segment: a stretch of track, which has a length, positive hill climbs and negative hill decents. Has a starting station and an end station, which are not relevant to the energy calculations - it is the distance which counts.&lt;/li&gt;
	&lt;li&gt;Timetable: a service which provides all Trips for a given time period.&lt;/li&gt;
&lt;/ul&gt;&lt;br&gt;
&lt;br&gt;
In order to make each trip be calculated in parallel, I have chosen to use a feature of EJB whereby the container creates a new thread and does the calculation on that thread.  It means with a simple annotation on a method, I have almost no boiler plate code to write!  In order to use that annotation, my context needs to be an EJB, but seeing as the application is running in an enterprise Java application server anyway (so that I can for example have a nice website as a front end), this is no big deal.&lt;br&gt;
&lt;br&gt;
So, the architecture of this solutions is: a web request to run the calculation is received which makes a call to my process layer (aka application layer).  The process layer calls the timetable to get all trips for the requested period, and for each trip it calls the context to do a calculation in parallel.  The process layer waits for all calculations to complete and returns the result to the web layer to present the results to the user.  Here is the context:
&lt;br&gt;
&lt;br&gt;
&lt;hr size=&#034;2&#034; width=&#034;100%&#034; /&gt;
&lt;div style=&#034;border: thin none ; overflow: auto; width: 525px; height: 300px; background-color: rgb(255, 255, 255);&#034;&gt;
&lt;pre&gt;
@Stateless
@Context
public class ForecastingContext implements ForecastingContextLocal {

	/**
	 * an asynchrounous method for determining the energy requirements of the given trip.
	 */
	@Asynchronous
    public Future&lt;Double&gt; forecastEnergyRequired(Trip trip) {

		BehaviourInjector bi = new BehaviourInjector(this);
		
		//the context simply casts objects into roles, and starts the interaction
		EnergyConciousTrip t = bi.assignRole(trip, EnergyConciousTrip.class);
		double energy = t.forecastEnergyRequirements();
		
		return new AsyncResult&lt;Double&gt;(energy);
    }
}
&lt;/pre&gt;
&lt;/div&gt;
&lt;br&gt;
The context does nothing special, apart from contain the &lt;code&gt;@Asynchronous&lt;/code&gt; annotation which tells the container that calls to this method need to occur on a new thread.  Unlike perhaps more standard DCI, this context has no constructor which takes objects which will play roles, rather the interaction method &#034;forecastEnergyRequired&#034; is passed the object which gets cast into a role.  The reason is that I have no control over the instantiation of the context, because it is an EJB, meaning that the container does the instantiation for me!.  I have not sub-classed BehaviourInjector (which is an option in my framework), because stateless EJBs can be called by multiple threads at the same time, and BehaviourInjector is not thread safe.&lt;br&gt;
&lt;br&gt;
Here are the two roles:&lt;br&gt;
&lt;br&gt;
&lt;hr size=&#034;2&#034; width=&#034;100%&#034; /&gt;
&lt;div style=&#034;border: thin none ; overflow: auto; width: 525px; height: 300px; background-color: rgb(255, 255, 255);&#034;&gt;
&lt;pre&gt;
/**
 * this role is played by a trip so that it is able to 
 * give a prediction about how much energy will be 
 * needed to undertake the trip.
 */
@Role(contextClass=ForecastingContext.class, 
		implementationClass=EnergyConciousTrip.EnergyConciousTripImpl.class)
public interface EnergyConciousTrip {

	double forecastEnergyRequirements(); //role
	List&lt;TripSegment&gt; getTripSegments(); //data
	Train getTrain(); //data
	
	static class EnergyConciousTripImpl{ //role implementation
		
		@CurrentContext
		private IContext ctx;
		
		@Self
		private EnergyConciousTrip self;

		/**
		 * energy consists of a longitudinal component (ie along the track due to 
		 * aerodynamic forces and rolling resistance) as well as altidudal component
		 * (ie due to climbing or descending).
		 * 
		 * E = mgh //ie potential energy for climbing / descending
		 * E = Fd  //ie energy required to overcome resistive forces
		 */
		public double forecastEnergyRequirements(){
			
			//give the train some scientific behaviour and determine
			//its total weight and average efficiency
			ScientificTrain train = ctx.assignRole(self.getTrain(), ScientificTrain.class);
			double totalWeight = train.getTotalWeightKg();
			double avgEff = train.getAverageEfficiency();
			
			//add up all energy per segment
			double energy = 0.0;
			for(TripSegment seg : self.getTripSegments()){
				
				double segmentEnergy = train.getResistanceForce(seg.getSpeed()) * seg.getSegment().getLengthMeters();
				
				segmentEnergy += totalWeight * seg.getSegment().getAltitudeChange();
				
				//each locomotive can pull, but has an efficiency which needs to be factored in!
				//it needs more energy than just pulling wagons, because its inefficient
				segmentEnergy /= avgEff;
				
				energy += segmentEnergy;
			}
			
			return energy;
		}
	}
}


/**
 * played by a train, when it needs to provide scientific details about itself.
 */
@Role(contextClass=ForecastingContext.class,
		implementationClass=ScientificTrain.ScientificTrainImpl.class)
public interface ScientificTrain {

	double getResistanceForce(double speed); //role
	int getTotalWeightKg(); //role
	double getAverageEfficiency(); //role
	List&lt;Wagon&gt; getWagons(); //data 
	List&lt;Locomotive&gt; getLocomotives(); //data
	double getDragCoefficient(); //data
	
	static class ScientificTrainImpl { //role impl

		@Self
		private ScientificTrain self;

		/** 
		 * resistance force is the rolling friction as a 
		 * result of weight, as well as aerodyamic drag.
		 */
		public double getResistanceForce(double speed){
			double resistanceForce = 0.0;
			for(Wagon w : self.getWagons()){
				resistanceForce += w.getWeightKg() * w.getRollingFriction();
			}
			for(Locomotive l : self.getLocomotives()){
				resistanceForce += l.getWeightKg() * l.getRollingFriction();
			}
			
			resistanceForce += speed * speed * self.getDragCoefficient();
			
			return resistanceForce;
		}

		/** total weight of wagons and locs. */
		public int getTotalWeightKg(){
			int weight = 0;
			for(Wagon w : self.getWagons()){
				weight += w.getWeightKg();
			}
			for(Locomotive l : self.getLocomotives()){
				weight += l.getWeightKg();
			}
			return weight;
		}

		/** average of all locs in the train */
		public double getAverageEfficiency(){
			double avg = 0.0;
			for(Locomotive l : self.getLocomotives()){
				avg += l.getEfficiency();
			}
			return avg / self.getLocomotives().size();
		}
	}	
}
&lt;/pre&gt;
&lt;/div&gt;
&lt;br&gt;
There is nothing fancy in these roles - simply the engineering calculations to work out the energy requirements.  I have chosen to implement the role implementations inside the role interface, but there is no reason the role implementations could not exist in their own classes.&lt;br&gt;
&lt;br&gt;
Finally, here is the process layer:&lt;br&gt;
&lt;br&gt;
&lt;hr size=&#034;2&#034; width=&#034;100%&#034; /&gt;
&lt;div style=&#034;border: thin none ; overflow: auto; width: 525px; height: 300px; background-color: rgb(255, 255, 255);&#034;&gt;
&lt;pre&gt;
@Stateless
public class EnergyForecastingService implements EnergyForecastingServiceLocal {

	@EJB
	private TimetableLocal timetable;

	@EJB
	private ForecastingContextLocal forecastingContext;
	
	@Override
	public EnergyRequirementResult forecast() throws InterruptedException, ExecutionException {
		
		long start = System.nanoTime();
		List&lt;Future&lt;Double&gt;&gt; results = new ArrayList&lt;Future&lt;Double&gt;&gt;();
		EnergyRequirementResult result = new EnergyRequirementResult();
		result.setTrips(timetable.getTripsForPeriod(null, null));
		for(Trip trip : result.getTrips()){
			//start it in a parallel thread
			//it will be simulated using a DCI context...
			Future&lt;Double&gt; e = forecastingContext.forecastEnergyRequired(trip);
			results.add(e);
		}
		
		//ok, all started, lets wait until all are done...
		result.setEnergyRequirement(waitForResults(results));
		result.setCalculationTimeNs(System.nanoTime() - start);
		
		return result;
	}

	private double waitForResults(List&lt;Future&lt;Double&gt;&gt; results) throws InterruptedException, ExecutionException {
		double energyRequired = 0.0;
		while(!results.isEmpty()){
			List&lt;Future&lt;Double&gt;&gt; assimilated = new ArrayList&lt;Future&lt;Double&gt;&gt;();
			for(Future&lt;Double&gt; result : results){
				if(result.isDone()){
					assimilated.add(result);
					energyRequired += result.get().doubleValue();
				}
			}
			results.removeAll(assimilated);
			
			//lets give CPU time to other threads while we wait...
			Thread.sleep(5L);
		}
		
		return energyRequired;
	}
}
&lt;/pre&gt;
&lt;/div&gt;
&lt;br&gt;
The process layer uses these funny &#034;Future&#034; objects which allow it to not only get the result from a calculation which has run on another thread, but also to query whether that thread has completed or is still running.  The only boiler plate code needed to handle this multi-threaded code is analysis of results while waiting for them all to complete.&lt;br&gt;
&lt;br&gt;
The context and its roles look like this:&lt;br&gt;
&lt;br&gt;
&lt;img src=&#039;/pebble/images/DCITrainCompanyContexts.gif&#039;&gt;&lt;br&gt;
&lt;br&gt;
One interesting side point, is that the EnergyRequirementResult is a class in the context&#039;s package (namespace), because it only makes sense to create it from the context.  It can be used outside of the context as a read only object to read the results, but it is strongly coupled to the context.  It doesn&#039;t really make sense for it to exist without the context, and thinking in terms of components, or code re-use, it makes sense to place it in the same namespace as the context.  The context and its roles, are afterall a component which can calculate energy requirements - they encapsulate the behaviour to do this.&lt;br&gt;
&lt;br&gt;
It might look strange that the behaviour is not simply added to the train and trip objects.  But it&#039;s hard to see the benefits when looking at such a small project.  Imagine a huge project where the object model is much more complex, and there are many many more use cases.  If you look at the object model in this example, the train and timetable can be used in many more applications than just one which does energy predictions.  Typically within an enterprise, we keep rebuilding similar object models with relevant parts of data, and differing behaviours for each OO solution.  DCI lets you build a large single object model, with behaviours constrained to the contexts in which they are relevant.  This allows the data model to become sufficiently complex to make it usable within the entire enterprise, but not so overly complex that making changes to it breaks it.  Of course it is also arguable, that things like drag coefficients and rolling friction coefficients have no place in an object model of an application related to passenger load planning or whatever else the enterprise needs to do.  In terms of making applications flexible to change, it can help if each application has its own object model, even if it results in code duplication within the enterprise.&lt;br&gt;
&lt;br&gt;
In this example I have turned my context into an EJB, because I want to take advantage of boilerplate code which the container can handle for me - in this case concurrent computing.  Similarly, if my context needs resources, transactions, security, etc, I would use an EJB for my context, and pass the resources which the container injects into it, into the roles using my BehaviourInjector framework (see its documentation for details).  I have solved the banking example used in many DCI articles, by making the contexts EJBs, letting the container handle transactions, and getting hold of the EntityManager (for interacting with the database) by letting the container inject it into the context, which the BehaviourInjector can in turn inject into roles.&lt;br&gt;
&lt;br&gt;
If contexts are to be &#034;services&#034; in the technical sense, it also makes sense for an enterprise to build a context repository to sit along side their service repository.  These are places for software people to look, when needing to see if problems they face have already been solved.  Just as we have tools for searching service repositories and we create documents to list all our services, we will need to do the same for contexts, if DCI is to really be adopted by the enterprise world.&lt;br&gt;
&lt;br&gt;
It&#039;s important to remember that you could build this solution with pure services, or pure OO.  DCI is simply another, and valid way of solving the problem, which concentrates on separating the behaviour from the data in order to make the code more reviewable, while at the same time remaining object oriented, so that the model which the users and customers have, stays similar to that which the programmer uses.  Is creating roles and injecting behaviour into the Train and Trip objects better than putting those methods into a service which does the same thing?  I don&#039;t know...  It is certainly less OO, but is that a bad thing?  Perhaps its just down to designers choice and feeling comfortable with the resulting code.  So long as reading the solution compares to the users and customers stories, that is the important thing.  Mappings between the users/customers world, and the programmers world are unnecessary and cause bugs as well as unsatisfactory users, because the programmer concentrates on solving his problems, rather than the business&#039; problems.&lt;br&gt;
&lt;br&gt;
You can download all the source code for this train app from &lt;a href=&#039;/pebble/files/DCITrainCompanyExampleJEE.zip&#039;&gt;here&lt;/a&gt;.&lt;br&gt;
&lt;br&gt;
PS. I have no idea if train companies need to forecast energy requirements, or even if they work with energy partners.  The creativity of this blog article should not hamper the readers understanding of how to create a service/DCI hybrid, in order to benefit from the way a container handles the concerns listed at the start of this article!&lt;br&gt;
&lt;br&gt;
&amp;copy; 2010 Ant Kutschera
&lt;br&gt;&lt;br&gt;&lt;div class=&#034;tags&#034;&gt;&lt;span&gt;Social Bookmarks : &lt;/span&gt;&amp;nbsp;&lt;a href=&#034;http://slashdot.org/bookmark.pl?url=http://blog.maxant.co.uk:80/pebble/2010/11/20/1290288540000.html&amp;amp;title=DCI+and+Services+%28EJB%29&#034; target=&#034;_blank&#034; title=&#034;Add this post to Slash Dot&#034;&gt;&lt;img src=&#034;common/images/slashdot.png&#034; alt=&#034;Add this post to Slashdot&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://digg.com/submit?url=http://blog.maxant.co.uk:80/pebble/2010/11/20/1290288540000.html&amp;amp;title=DCI+and+Services+%28EJB%29&#034; target=&#034;_blank&#034; title=&#034;Digg this post&#034;&gt;&lt;img src=&#034;common/images/digg.png&#034; alt=&#034;Add this post to Digg&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://reddit.com/submit?url=http://blog.maxant.co.uk:80/pebble/2010/11/20/1290288540000.html&amp;amp;title=DCI+and+Services+%28EJB%29&#034; target=&#034;_blank&#034; title=&#034;Add this post to Reddit&#034;&gt;&lt;img src=&#034;common/images/reddit.png&#034; alt=&#034;Add this post to Reddit&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://del.icio.us/post?url=http://blog.maxant.co.uk:80/pebble/2010/11/20/1290288540000.html&amp;amp;title=DCI+and+Services+%28EJB%29&#034; target=&#034;_blank&#034; title=&#034;Save this post to Del.icio.us&#034;&gt;&lt;img src=&#034;common/images/delicious.png&#034; alt=&#034;Add this post to Delicious&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.stumbleupon.com/submit?url=http://blog.maxant.co.uk:80/pebble/2010/11/20/1290288540000.html&amp;amp;title=DCI+and+Services+%28EJB%29&#034; target=&#034;_blank&#034; title=&#034;Stumble this post&#034;&gt;&lt;img src=&#034;common/images/stumbleupon.png&#034; alt=&#034;Add this post to Stumble it&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.google.com/bookmarks/mark?op=edit&amp;amp;bkmk=http://blog.maxant.co.uk:80/pebble/2010/11/20/1290288540000.html&amp;amp;title=DCI+and+Services+%28EJB%29&#034; target=&#034;_blank&#034; title=&#034;Add this post to Google&#034;&gt;&lt;img src=&#034;common/images/google.png&#034; alt=&#034;Add this post to Google&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://technorati.com/faves?add=http://blog.maxant.co.uk:80/pebble/2010/11/20/1290288540000.html&#034; target=&#034;_blank&#034; title=&#034;Add this post to Technorati&#034;&gt;&lt;img src=&#034;common/images/technorati.png&#034; alt=&#034;Add this post to Technorati&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.bloglines.com/sub/http://blog.maxant.co.uk:80/pebble/2010/11/20/1290288540000.html&#034; target=&#034;_blank&#034; title=&#034;Add this post to Bloglines&#034;&gt;&lt;img src=&#034;common/images/bloglines.png&#034; alt=&#034;Add this post to Bloglines&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.facebook.com/share.php?u=http://blog.maxant.co.uk:80/pebble/2010/11/20/1290288540000.html&#034; target=&#034;_blank&#034; title=&#034;Add this post to Facebook&#034;&gt;&lt;img src=&#034;common/images/facebook.png&#034; alt=&#034;Add this post to Facebook&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.furl.net/storeIt.jsp?u=http://blog.maxant.co.uk:80/pebble/2010/11/20/1290288540000.html&amp;amp;t=DCI+and+Services+%28EJB%29&#034; target=&#034;_blank&#034; title=&#034;Add this post to Furl&#034;&gt;&lt;img src=&#034;common/images/furl.png&#034; alt=&#034;Add this post to Furl&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;https://favorites.live.com/quickadd.aspx?mkt=en-us&amp;amp;url=http://blog.maxant.co.uk:80/pebble/2010/11/20/1290288540000.html&amp;amp;title=DCI+and+Services+%28EJB%29&#034; target=&#034;_blank&#034; title=&#034;Add this post to Windows Live&#034;&gt;&lt;img src=&#034;common/images/windowslive.png&#034; alt=&#034;Add this post to Windows Live&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://bookmarks.yahoo.com/toolbar/savebm?opener=tb&amp;amp;u=http://blog.maxant.co.uk:80/pebble/2010/11/20/1290288540000.html&amp;amp;t=DCI+and+Services+%28EJB%29&#034; target=&#034;_blank&#034; title=&#034;Add this post to Yahoo!&#034;&gt;&lt;img src=&#034;common/images/yahoo.png&#034; alt=&#034;Add this post to Yahoo!&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&lt;/div&gt;
        </description>
      
      
    
    
    
    <comments>http://blog.maxant.co.uk:80/pebble/2010/11/20/1290288540000.html#comments</comments>
    <guid isPermaLink="true">http://blog.maxant.co.uk:80/pebble/2010/11/20/1290288540000.html</guid>
    <pubDate>Sat, 20 Nov 2010 21:29:00 GMT</pubDate>
  </item>
  
  <item>
    <title>DCI Plugin for Eclipse</title>
    <link>http://blog.maxant.co.uk:80/pebble/2010/11/16/1289941080000.html</link>
    
      
        <description>
          &lt;p&gt;The Data, Context, and Interaction (DCI) architecture paradigm introduces the idea of thinking in terms of roles and contexts.  See some of &lt;a target=&#034;_blank&#034; href=&#034;http://www.maxant.co.uk/whitepapers.jsp&#034;&gt;my white papers&lt;/a&gt; for a more detailed introduction into DCI, but for this blog article, consider the following example: a human could be modelled in object oriented programming by creating a super huge massive class which encapsulates all a humans attributes, their behaviours, etc.  You would probably end up with something much too complex to be really maintainable.  Think about when a human becomes a clown for a kids party; most of that behaviour has little to do with being a programmer, which is a different role which the human could play.&lt;br /&gt;
&lt;br /&gt;
So, DCI looks at the problem differently than OOP and solves it by letting the data class be good at being a data class, and putting the behaviours specific to certain roles into &amp;quot;roles&amp;quot;, which in my &lt;a target=&#034;_blank&#034; href=&#034;http://www.maxant.co.uk/tools.jsp&#034;&gt;DCI Tools for Java library&lt;/a&gt; are classes.&lt;br /&gt;
&lt;br /&gt;
Certain roles interact with each other within a given context, such as a clown entertaining kids at a birthday party.  The roles which belong to an interaction are part of the context, and in DCI the context is a class which puts data objects into specific roles, and makes them interact.  The context and its roles form the encapsulation of the behaviour.&lt;br /&gt;
&lt;br /&gt;
I have updated my library, so that there are two new Annotations, namely the @Context and @Role annotations.  The @Context annotation is simply a marker to show that a class is a context.  The @Role annotation is more important.  It is placed onto the role interface class and tells the context where to find the role implementation, and additionally requires that the programmer specifically state to which context the role belongs.&lt;br /&gt;
&lt;br /&gt;
The code ends up looking looking as follows.  First a unit test which creates and calls the context:&lt;/p&gt;
&lt;hr size=&#034;2&#034; width=&#034;100%&#034; /&gt;
&lt;div style=&#034;border: thin none; overflow: auto; width: 525px; height: 300px; background-color: rgb(255, 255, 255);&#034;&gt;
&lt;pre&gt;
    @Test
    public void testExecute() {
    	
    	//create an adult (the clown) and some children, 
    	//and let the party start...
        
    	Human adult = new Human();
        List&lt;human&gt; children = new ArrayList&lt;human&gt;();&lt;br /&gt;        Human child = new Human();&lt;br /&gt;        child.setName(&amp;quot;Johnny&amp;quot;);&lt;br /&gt;        children.add(child);&lt;br /&gt;        child = new Human();&lt;br /&gt;        child.setName(&amp;quot;Jane&amp;quot;);&lt;br /&gt;        children.add(child);&lt;br /&gt;&lt;br /&gt;        ClownContext cc = new ClownContext(adult, children.toArray());&lt;br /&gt;        cc.startParty();&lt;br /&gt;&lt;br /&gt;        //check the party went well...&lt;br /&gt;        assertEquals(0, adult.getHappiness());&lt;br /&gt;        for (Human c : children) {&lt;br /&gt;            assertEquals(1, c.getHappiness());&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/human&gt;&lt;/human&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;
There is nothing special about the code above.  It simply creates some data objects and passes them to the context, and then starts the party (the interaction, or use case).  Next, the context class is shown:&lt;/p&gt;
&lt;hr size=&#034;2&#034; width=&#034;100%&#034; /&gt;
&lt;div style=&#034;border: thin none; overflow: auto; width: 525px; height: 300px; background-color: rgb(255, 255, 255);&#034;&gt;
&lt;pre&gt;
/** the context in which a clown entertains some kids. */
@Context
public class ClownContext extends BehaviourInjector {

    /** the object who will play the clown role */
    private Object adult;
    
    /** the objects who will play the kid role */
    private List&lt;object&gt; children;&lt;br /&gt;&lt;br /&gt;    /**&lt;br /&gt;     * Creates a new Context object. takes &amp;quot;objects&amp;quot; rather than specific types to allow it to be reusable.&lt;br /&gt;     */&lt;br /&gt;    public ClownContext(Object adult, Object[] children) {&lt;br /&gt;        this.adult = adult;&lt;br /&gt;&lt;br /&gt;        this.children = new ArrayList&lt;object&gt;();&lt;br /&gt;&lt;br /&gt;        for (Object child : children) {&lt;br /&gt;            this.children.add(child);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    /** start the interaction */&lt;br /&gt;    public void startParty() {&lt;br /&gt;        Clown clown = assignRole(adult, Clown.class);&lt;br /&gt;        &lt;br /&gt;        clown.applyMakeup();&lt;br /&gt;&lt;br /&gt;        IIterable&lt;kid&gt; kids = getIterable(children.iterator(), Kid.class);&lt;br /&gt;&lt;br /&gt;        clown.makeKidsLaugh(kids);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/kid&gt;&lt;/object&gt;&lt;/object&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;
The context has a few noteworthy points.  First of all, it extends the &lt;code&gt;BehaviourInjector&lt;/code&gt;.  By doing this, it has access to the &lt;code&gt;assignRole(Object, Class)&lt;/code&gt; and &lt;code&gt;getIterable(Iterator, Class)&lt;/code&gt; methods.  Note the &lt;code&gt;@Context&lt;/code&gt; annotation at the top - it&#039;s important for not only helping the programmer spot that it&#039;s a context, but also for the Eclipse plugin which I created and which I introduce below.&lt;br /&gt;
&lt;br /&gt;
You might have spotted that the context above is not tightly coupled with the &lt;code&gt;Human&lt;/code&gt; class.  The reason is simply to make the context and its roles usable in the future, with data classes which I currently know nothing about.  It is feasible that a robot might one day do parties by dressing up as a clown!&lt;br /&gt;
&lt;br /&gt;
Assigning the role is where the behaviour is &amp;quot;injected&amp;quot; into the data object.  The iterable which is created is a special role, which can automatically cast the human children into the role of a kid attending a party.&lt;br /&gt;
&lt;br /&gt;
Next, take a look at the role interface.  This class defines the methods which data object must have to play the role, as well as the behaviour which will be added to the object.&lt;/p&gt;
&lt;hr size=&#034;2&#034; width=&#034;100%&#034; /&gt;
&lt;div style=&#034;border: thin none; overflow: auto; width: 525px; height: 300px; background-color: rgb(255, 255, 255);&#034;&gt;
&lt;pre&gt;
@Role(contextClass = ClownContext.class, 
	  implementationClass = ClownImpl.class)
public interface Clown {

	/** put some makeup on (initialise) */
	public void applyMakeup(); // role

	/** makes kids laugh */
	public void makeKidsLaugh(IIterable&lt;kid&gt; kids); // role&lt;br /&gt;	&lt;br /&gt;	public void setHairColour(Color c); // data&lt;br /&gt;	&lt;br /&gt;}&lt;br /&gt;&lt;/kid&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;
The role interface has the &lt;code&gt;@Role&lt;/code&gt; annotation which tells the behaviour injector firstly to which context the role belongs, and secondly where the actual implementation (behaviour) can be found. In the clown role specified above, two behaviours are added (applying make up and making kids laugh).  The application of make up additionally requires that the clown be able to set his hair colour, so that method which the human class must have is also specified here.&lt;br /&gt;
&lt;br /&gt;
Finally, the role implementation class:&lt;/p&gt;
&lt;hr size=&#034;2&#034; width=&#034;100%&#034; /&gt;
&lt;div style=&#034;border: thin none; overflow: auto; width: 525px; height: 300px; background-color: rgb(255, 255, 255);&#034;&gt;
&lt;pre&gt;
public class ClownImpl {

	@Self
	private Clown self;
	
	/** @see Clown#applyMakeup() */
	public void applyMakeup(){
		self.setHairColour(Color.GREEN);
	}

	/** @see Clown#makeKidsLaugh(IIterable) */
	public void makeKidsLaugh(IIterable&lt;kid&gt; kids) {&lt;br /&gt;		for (Kid kid : kids) {&lt;br /&gt;			kid.laugh();&lt;br /&gt;			System.out.println();&lt;br /&gt;		}&lt;br /&gt;	}&lt;br /&gt;}&lt;br /&gt;&lt;/kid&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;
The role implementation does not need to implement the role interface!  It is simply a class which the behaviour injector relies upon to find behaviour which it cannot find in the data object.  The &lt;code&gt;@Self&lt;/code&gt; annotation on the clown field called self is a reference to the object playing the clown role, and is similar to &amp;quot;this&amp;quot;, just that &amp;quot;this&amp;quot; would be a reference to the instance of the role implementation, rather than the object playing the role.  It allows you to access the data methods of the data object.&lt;br /&gt;
&lt;br /&gt;
Now, as well as helping the programmer to mentally associate contexts with roles, these two annotations allow static analysis of the code to be performed.  Using the Eclipse JDT framework, it is possible to obtain individual tokens of source code, even when the class files don&#039;t compile, in order to build up a model of contexts and roles within a Java project.  I created a little DCI Outline view for Eclipse, similar to the class outline, except rather than showing classes, it shows the contexts and their associated roles. Here&#039;s a screen shot:&lt;br /&gt;
&lt;br /&gt;
&lt;img src=&#034;/pebble/images/dciView1.gif&#034; alt=&#034;&#034; /&gt;&lt;br /&gt;
&lt;br /&gt;
The view shows all contexts which it finds in the selected Java project.  For each context, it shows the package, followed by a list of its methods, and then all the roles that belong to it.&lt;br /&gt;
&lt;br /&gt;
For each role interface, the package is listed, followed by a list of methods which the role interface contains.  At the bottom of a role branch, is the role implementation class.&lt;br /&gt;
&lt;br /&gt;
The idea of this plugin is to give the programmer a view of what contexts are available and what roles they contain.  It puts contexts, roles and their methods into the mind of the programmer letting them think in terms of DCI, exactly the same way which a standard class browser lets the programmer think in terms of classes.&lt;br /&gt;
&lt;br /&gt;
Double clicking on a role interface, role implementation or context will open it in the editor.&lt;br /&gt;
&lt;br /&gt;
The plugin has limited validation capabilities and can determine for example, if a context specified in a role annotation cannot be found within the project, and highlights this so that the programmer can see there is a problem.  In such cases, the view looks like this:&lt;br /&gt;
&lt;br /&gt;
&lt;img src=&#034;/pebble/images/dciView2.gif&#034; alt=&#034;&#034; /&gt;&lt;br /&gt;
&lt;br /&gt;
The code from this example can be downloaded &lt;a href=&#034;/pebble/files/DCIClownExample.zip&#034;&gt;here&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
A full instruction manual, together with the the DCI Tools for Java library, and the Eclipse Update site can be found at &lt;a href=&#034;http://www.maxant.co.uk/tools.jsp&#034;&gt;here&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
Attention: No clowns were harmed during the writing of this blog.&lt;br /&gt;
&lt;br /&gt;
&amp;copy; 2010 Ant Kutschera&lt;/p&gt;&lt;div class=&#034;tags&#034;&gt;&lt;span&gt;Social Bookmarks : &lt;/span&gt;&amp;nbsp;&lt;a href=&#034;http://slashdot.org/bookmark.pl?url=http://blog.maxant.co.uk:80/pebble/2010/11/16/1289941080000.html&amp;amp;title=DCI+Plugin+for+Eclipse&#034; target=&#034;_blank&#034; title=&#034;Add this post to Slash Dot&#034;&gt;&lt;img src=&#034;common/images/slashdot.png&#034; alt=&#034;Add this post to Slashdot&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://digg.com/submit?url=http://blog.maxant.co.uk:80/pebble/2010/11/16/1289941080000.html&amp;amp;title=DCI+Plugin+for+Eclipse&#034; target=&#034;_blank&#034; title=&#034;Digg this post&#034;&gt;&lt;img src=&#034;common/images/digg.png&#034; alt=&#034;Add this post to Digg&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://reddit.com/submit?url=http://blog.maxant.co.uk:80/pebble/2010/11/16/1289941080000.html&amp;amp;title=DCI+Plugin+for+Eclipse&#034; target=&#034;_blank&#034; title=&#034;Add this post to Reddit&#034;&gt;&lt;img src=&#034;common/images/reddit.png&#034; alt=&#034;Add this post to Reddit&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://del.icio.us/post?url=http://blog.maxant.co.uk:80/pebble/2010/11/16/1289941080000.html&amp;amp;title=DCI+Plugin+for+Eclipse&#034; target=&#034;_blank&#034; title=&#034;Save this post to Del.icio.us&#034;&gt;&lt;img src=&#034;common/images/delicious.png&#034; alt=&#034;Add this post to Delicious&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.stumbleupon.com/submit?url=http://blog.maxant.co.uk:80/pebble/2010/11/16/1289941080000.html&amp;amp;title=DCI+Plugin+for+Eclipse&#034; target=&#034;_blank&#034; title=&#034;Stumble this post&#034;&gt;&lt;img src=&#034;common/images/stumbleupon.png&#034; alt=&#034;Add this post to Stumble it&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.google.com/bookmarks/mark?op=edit&amp;amp;bkmk=http://blog.maxant.co.uk:80/pebble/2010/11/16/1289941080000.html&amp;amp;title=DCI+Plugin+for+Eclipse&#034; target=&#034;_blank&#034; title=&#034;Add this post to Google&#034;&gt;&lt;img src=&#034;common/images/google.png&#034; alt=&#034;Add this post to Google&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://technorati.com/faves?add=http://blog.maxant.co.uk:80/pebble/2010/11/16/1289941080000.html&#034; target=&#034;_blank&#034; title=&#034;Add this post to Technorati&#034;&gt;&lt;img src=&#034;common/images/technorati.png&#034; alt=&#034;Add this post to Technorati&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.bloglines.com/sub/http://blog.maxant.co.uk:80/pebble/2010/11/16/1289941080000.html&#034; target=&#034;_blank&#034; title=&#034;Add this post to Bloglines&#034;&gt;&lt;img src=&#034;common/images/bloglines.png&#034; alt=&#034;Add this post to Bloglines&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.facebook.com/share.php?u=http://blog.maxant.co.uk:80/pebble/2010/11/16/1289941080000.html&#034; target=&#034;_blank&#034; title=&#034;Add this post to Facebook&#034;&gt;&lt;img src=&#034;common/images/facebook.png&#034; alt=&#034;Add this post to Facebook&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.furl.net/storeIt.jsp?u=http://blog.maxant.co.uk:80/pebble/2010/11/16/1289941080000.html&amp;amp;t=DCI+Plugin+for+Eclipse&#034; target=&#034;_blank&#034; title=&#034;Add this post to Furl&#034;&gt;&lt;img src=&#034;common/images/furl.png&#034; alt=&#034;Add this post to Furl&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;https://favorites.live.com/quickadd.aspx?mkt=en-us&amp;amp;url=http://blog.maxant.co.uk:80/pebble/2010/11/16/1289941080000.html&amp;amp;title=DCI+Plugin+for+Eclipse&#034; target=&#034;_blank&#034; title=&#034;Add this post to Windows Live&#034;&gt;&lt;img src=&#034;common/images/windowslive.png&#034; alt=&#034;Add this post to Windows Live&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://bookmarks.yahoo.com/toolbar/savebm?opener=tb&amp;amp;u=http://blog.maxant.co.uk:80/pebble/2010/11/16/1289941080000.html&amp;amp;t=DCI+Plugin+for+Eclipse&#034; target=&#034;_blank&#034; title=&#034;Add this post to Yahoo!&#034;&gt;&lt;img src=&#034;common/images/yahoo.png&#034; alt=&#034;Add this post to Yahoo!&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&lt;/div&gt;
        </description>
      
      
    
    
    
    <comments>http://blog.maxant.co.uk:80/pebble/2010/11/16/1289941080000.html#comments</comments>
    <guid isPermaLink="true">http://blog.maxant.co.uk:80/pebble/2010/11/16/1289941080000.html</guid>
    <pubDate>Tue, 16 Nov 2010 20:58:00 GMT</pubDate>
  </item>
  
  <item>
    <title>User Mental Models</title>
    <link>http://blog.maxant.co.uk:80/pebble/2010/11/01/1288649040000.html</link>
    
      
        <description>
          &lt;p&gt;I&#039;ve spent the last 6 weeks looking into an interesting paradigm called Data, Context &amp;amp; Interaction (DCI). &lt;br /&gt;
&lt;br /&gt;
I&#039;ve written a few introductory &lt;a target=&#034;_blank&#034; href=&#034;http://www.maxant.co.uk/whitepapers.jsp&#034;&gt;papers&lt;/a&gt;, and some &lt;a target=&#034;_blank&#034; href=&#034;http://www.maxant.co.uk/tools.jsp&#034;&gt;tools&lt;/a&gt; too. &lt;br /&gt;
&lt;br /&gt;
DCI has the following goals:&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;To improve the readability of object-oriented code by giving system behavior first-class status;&lt;/li&gt;
    &lt;li&gt;To cleanly separate code for rapidly changing system behavior (what the system does) from that for slowly changing domain knowledge (what the system is), instead of combining both in one class interface;&lt;/li&gt;
    &lt;li&gt;To help programmers reason about system-level state and behavior instead of only object state and behavior;&lt;/li&gt;
    &lt;li&gt;To support an object style of thinking that is close to peoples&#039; mental models, rather than the class style of thinking that overshadowed object thinking early in the history of object-oriented programming languages.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The problem recognised by this paradigm is that system behaviour gets fragmented in traditional OOP, over a large number of classes and sub-classes.  The code directly related to a use-case gets fragmented and &amp;quot;lost&amp;quot;.  The boundaries for the behaviour end up being class boundaries and pieces of behaviour are stuck with the data on which they operate, so that the code has high cohesion.  If you want to read the code related to a use-case, you will struggle to extract it and understand it.  I agree with these problems, but have not really encountered them personally for a long time, because I do most of my work predominantly in the SOA paradigm.&lt;br /&gt;
&lt;br /&gt;
When I first read these goals and all the articles I could find about DCI, I interpreted them as roughly:&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;Separating system behaviour from data, to give behaviour first class status;&lt;/li&gt;
    &lt;li&gt;Allowing the programmer&#039;s mental model to become the same as the user&#039;s mental model and hence reduce the number of mappings between programmer&#039;s and user&#039;s mental models;&lt;/li&gt;
    &lt;li&gt;Making code use-case centric, rather than class- or data-centric;&lt;/li&gt;
    &lt;li&gt;Making code reviewable and having less reliance on testing, by keeping fragments of use-case code physically close so it&#039;s not fragmented.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I thought about these interpreted goals hard, because I was convinced that in the applications I help to write, we were achieving them.  I questioned the DCI forums at length about why a SOA architecture couldn&#039;t achieve these goals.  When I say SOA, I don&#039;t mean the modern version involving metadata to describe remote interoperable services like Web Services.  I mean services, like what people used to write in the early 2000&#039;s when EJB stateless session beans first came out.  Java classes which were stateless and contained just behaviour.  Let&#039;s call such service &amp;quot;local services&amp;quot; to distinguish them. &lt;br /&gt;
&lt;br /&gt;
Today around 12pm, I finally understood what the people at the DCI boards meant, when they said that my ideas were not DCI and could not fulfil the DCI goals...  The very first DCI goal shown above relates to object oriented code.  It does not mean make it more readable by splitting the behaviour out and having dumb data objects used by behaviour which is implemented elsewhere, such as happens with SOA.  It really means, letting the code stay &lt;i&gt;object oriented&lt;/i&gt;.  I found that really stange, that in 2010, people still want to really program in traditional object oriented styles.  Let me explain.  In a Zoo, you have animals, and they can all &amp;quot;talk&amp;quot; to some extent.  So you create a model which uses a super-class &amp;quot;Animal&amp;quot; which has a talk method which each animal class can override.  Then maybe you introduce some movement and provide a &amp;quot;walk&amp;quot; method (hmm... snails... guess we need a new level in our inheritance tree to differentiate between walkers and sliders... oh dear our inheritance tree is exploding...).&lt;br /&gt;
&lt;br /&gt;
Fair enough for a zoo.  But in software, especially business software, how often do we really model behaviour inside the entity classes?  Consider a bank account, and transferring money between two of them.  Does the account transfer money from itself to another one, or does &amp;quot;something else&amp;quot; do it?  Or think about a complex set of tickets which are related, for example a train ticket, a hotel booking and a ticket to a concert.  You could buy these as a discounted package.  The package might be just clever enough to give you the price based on adding up the price of its parts, but would you expect the package object to work out the package discount, or would it be the system which works out the discount, and sets it as an attribute on the package object? &lt;br /&gt;
&lt;br /&gt;
In cases where it is something else providing functionality, rather than an entity, we use services.  Services meld really well with object oriented data models.  The services contain no data, just functionality, and the data model contains data, but no real functionality. &lt;br /&gt;
&lt;br /&gt;
I am sure there are users, business analysts and requirements engineers out there, who think of these behaviours as belonging to objects, rather than the system, but for me, this thinking is wrong.  DCI aims to make the programmer&#039;s mental model the same as the user&#039;s, so now we have a problem, because these user&#039;s are not thinking &amp;quot;right&amp;quot;.  But if you think about it, we don&#039;t write software for a single user.  We write software for lots and lots of users (I once wrote an app costing nearly a million CHF for 3 users, but that was an exception).  How can we ensure that their mental models are the same?  And there is usually more than one programmer doing the writing, so how can we ensure their models are also the same?  In agile programming, the users, customers, programmers, analysts, architects, business people and all other stake holders get together and talk.  During that discussion, it is fine to encourage user&#039;s with a &amp;quot;strange&amp;quot; way of looking at the world to think a little differently (it might involve beer, donuts, or threats, but it is possible).  To take a users mental model without encouraging them to refine it is dangerous.  Typically, software is created to improve the user&#039;s life.  If you ask a standard computer user with no IT training, to tell you what they want, in my experience it is not usable.  We once asked our user&#039;s to define the colours of new system which would replace a 20 year old green-screen system.  Their input: light green, a bit of dark green.  Black text.  They had no concept of modern software and what it could do for them or how it might make their lives easier.  You are definitely allowed to encourage users to expand on and improve their original mental models. &lt;br /&gt;
&lt;br /&gt;
So what about software which manipulates things on screen, i.e. the UI part?  Imagine a word processor.  You are typing away and have the feeling that you are on a type writer.  You then want to add a picture.  To add a picture, the program needs to respond to your click, open a file dialog and show you the files in a directory.  You choose a file, click OK, and the picture is read and displayed where the cursor was.  You click the &amp;quot;center&amp;quot; button to centre justify the picture.  What goes on, in the user&#039;s head?  What handles each of these inputs?  Is it a document which responds to his wanting to insert a picture, or the system?  Is it the document which puts the image in the document, or the system?  Is it the document which formats the picture to become centred or is it the system?  In my world, it is the system which does this, and as such, I can program these things to be part of my MVC controller which handles complex state updates.  In my world, the controller would not tell the document to centre the image, but would do so itself.  The document object contains the system state and knows where the image is in the document, and that the paragraph has the centred style.  But the document does not have the ability to do anything useful itself. &lt;br /&gt;
&lt;br /&gt;
In Eclipse RCP UI programming, clicking a button to load a file is handled as an action; you don&#039;t even have the choice of letting your &amp;quot;document&amp;quot; react to the event, unless you are backward thinking and have code in the action which fetches the document from the data model and calls the &amp;quot;insert image&amp;quot; method on it. &lt;br /&gt;
&lt;br /&gt;
I just spent ten minutes getting my wife to open the word processor and describe to me what happens when she inserts an image and left justifies it.  My wife is a standard user, who is word processor and browser proficient.  When talking about actions and reactions (e.g. clicking the ok button in the file dialog which inserts the picture into the document), she always referred to either her or the system doing the work.  If I asked her not to refer to herself, rather an element of the word processor, it was always the system which did the work.  If I were programming the word processor, I therefore wouldn&#039;t be allowed to attach the behaviour to the button or document, rather the button causes the system to load the file.  I could create a class called the system, but for me, a controller which relies on using services to do the work is acceptably close to the user&#039;s mental model.&lt;br /&gt;
&lt;br /&gt;
Maybe I am just at an advantage, because I have lived in the service world for so long.  Either way, the thing to take away is that local services empower the programmer to have a mental model close to the user&#039;s mental model, so that code becomes simpler to maintain.  They also let the system behaviour be first class just as data is, and make code more reviewable by allowing it to be use-case-centric, which reduces reliance on testing. &lt;br /&gt;
&lt;br /&gt;
&amp;copy;2010 Ant Kutschera&lt;/p&gt;&lt;div class=&#034;tags&#034;&gt;&lt;span&gt;Social Bookmarks : &lt;/span&gt;&amp;nbsp;&lt;a href=&#034;http://slashdot.org/bookmark.pl?url=http://blog.maxant.co.uk:80/pebble/2010/11/01/1288649040000.html&amp;amp;title=User+Mental+Models&#034; target=&#034;_blank&#034; title=&#034;Add this post to Slash Dot&#034;&gt;&lt;img src=&#034;common/images/slashdot.png&#034; alt=&#034;Add this post to Slashdot&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://digg.com/submit?url=http://blog.maxant.co.uk:80/pebble/2010/11/01/1288649040000.html&amp;amp;title=User+Mental+Models&#034; target=&#034;_blank&#034; title=&#034;Digg this post&#034;&gt;&lt;img src=&#034;common/images/digg.png&#034; alt=&#034;Add this post to Digg&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://reddit.com/submit?url=http://blog.maxant.co.uk:80/pebble/2010/11/01/1288649040000.html&amp;amp;title=User+Mental+Models&#034; target=&#034;_blank&#034; title=&#034;Add this post to Reddit&#034;&gt;&lt;img src=&#034;common/images/reddit.png&#034; alt=&#034;Add this post to Reddit&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://del.icio.us/post?url=http://blog.maxant.co.uk:80/pebble/2010/11/01/1288649040000.html&amp;amp;title=User+Mental+Models&#034; target=&#034;_blank&#034; title=&#034;Save this post to Del.icio.us&#034;&gt;&lt;img src=&#034;common/images/delicious.png&#034; alt=&#034;Add this post to Delicious&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.stumbleupon.com/submit?url=http://blog.maxant.co.uk:80/pebble/2010/11/01/1288649040000.html&amp;amp;title=User+Mental+Models&#034; target=&#034;_blank&#034; title=&#034;Stumble this post&#034;&gt;&lt;img src=&#034;common/images/stumbleupon.png&#034; alt=&#034;Add this post to Stumble it&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.google.com/bookmarks/mark?op=edit&amp;amp;bkmk=http://blog.maxant.co.uk:80/pebble/2010/11/01/1288649040000.html&amp;amp;title=User+Mental+Models&#034; target=&#034;_blank&#034; title=&#034;Add this post to Google&#034;&gt;&lt;img src=&#034;common/images/google.png&#034; alt=&#034;Add this post to Google&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://technorati.com/faves?add=http://blog.maxant.co.uk:80/pebble/2010/11/01/1288649040000.html&#034; target=&#034;_blank&#034; title=&#034;Add this post to Technorati&#034;&gt;&lt;img src=&#034;common/images/technorati.png&#034; alt=&#034;Add this post to Technorati&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.bloglines.com/sub/http://blog.maxant.co.uk:80/pebble/2010/11/01/1288649040000.html&#034; target=&#034;_blank&#034; title=&#034;Add this post to Bloglines&#034;&gt;&lt;img src=&#034;common/images/bloglines.png&#034; alt=&#034;Add this post to Bloglines&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.facebook.com/share.php?u=http://blog.maxant.co.uk:80/pebble/2010/11/01/1288649040000.html&#034; target=&#034;_blank&#034; title=&#034;Add this post to Facebook&#034;&gt;&lt;img src=&#034;common/images/facebook.png&#034; alt=&#034;Add this post to Facebook&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.furl.net/storeIt.jsp?u=http://blog.maxant.co.uk:80/pebble/2010/11/01/1288649040000.html&amp;amp;t=User+Mental+Models&#034; target=&#034;_blank&#034; title=&#034;Add this post to Furl&#034;&gt;&lt;img src=&#034;common/images/furl.png&#034; alt=&#034;Add this post to Furl&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;https://favorites.live.com/quickadd.aspx?mkt=en-us&amp;amp;url=http://blog.maxant.co.uk:80/pebble/2010/11/01/1288649040000.html&amp;amp;title=User+Mental+Models&#034; target=&#034;_blank&#034; title=&#034;Add this post to Windows Live&#034;&gt;&lt;img src=&#034;common/images/windowslive.png&#034; alt=&#034;Add this post to Windows Live&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://bookmarks.yahoo.com/toolbar/savebm?opener=tb&amp;amp;u=http://blog.maxant.co.uk:80/pebble/2010/11/01/1288649040000.html&amp;amp;t=User+Mental+Models&#034; target=&#034;_blank&#034; title=&#034;Add this post to Yahoo!&#034;&gt;&lt;img src=&#034;common/images/yahoo.png&#034; alt=&#034;Add this post to Yahoo!&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&lt;/div&gt;
        </description>
      
      
    
    
    
    <comments>http://blog.maxant.co.uk:80/pebble/2010/11/01/1288649040000.html#comments</comments>
    <guid isPermaLink="true">http://blog.maxant.co.uk:80/pebble/2010/11/01/1288649040000.html</guid>
    <pubDate>Mon, 01 Nov 2010 22:04:00 GMT</pubDate>
  </item>
  
  <item>
    <title>How Brontosaurs kill Raptors</title>
    <link>http://blog.maxant.co.uk:80/pebble/2010/09/01/1283371140000.html</link>
    
      
        <description>
          &lt;p&gt;The board of a large organisation appoints a CIO who delegates technical decisions to his employees.  In the Enterprise Architecture (EA) department, an expert on Business Intelligence (BI) decides that the strategy for this company is to have a single Enterprise Data Warehouse (EDW).  This makes sense, because experience has shown that in the long run, it is cheaper and more efficient to build one Data Warehouse, rather than start by building &amp;quot;islands&amp;quot; and then later try to merge them together.&lt;br /&gt;
&lt;br /&gt;
In the mean time, some business people working for the company have rallied the budget holders, and started a project to build a new online sales application.  They need to generate some reports based on the sales from this application, in order to set themselves targets and measure their performance.  But, they are not experts when it comes to reporting.  The business sector at which their application is aimed is cutting edge and brand new, so they don&#039;t know what to expect, they don&#039;t really know what kind of reports they will need, and they will certainly need to adapt to the market very quickly.&lt;br /&gt;
&lt;br /&gt;
A project team in the IT department then get the assignment to build the application, including the report generation.  Also knowing little about reporting, they start talking to EA, who set up a meeting, between themselves, the development team, some people from the Quality Assurance (QA) department and some experts from the BI team.  Hours of discussion later, they have made the following conclusions:&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;Company IT Strategy states all reporting must be implemented in the BI solution, to ensure there is only one EDW,&lt;/li&gt;
    &lt;li&gt;The BI team are the only experts of the BI system,&lt;/li&gt;
    &lt;li&gt;The BI team cost a lot, because they are using SAP and consultants (how many SAP guys aren&#039;t freelance?),&lt;/li&gt;
    &lt;li&gt;The BI team dictate a six monthly release cycle, no exceptions,&lt;/li&gt;
    &lt;li&gt;The BI system is a black box, its inner workings stay secret within the BI team.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;br /&gt;
So, a simple question arises...  &amp;quot;Our customer doesn&#039;t know exactly what they want, and because of their business requirements, they need us to be agile.  What do we do and can the BI team help?&amp;quot;, the development team ask.  The first answer skirts around the issue and doesn&#039;t actually deserve being called an answer, because it doesn&#039;t &lt;i&gt;answer&lt;/i&gt; the question.  The development team make the point that the question hasn&#039;t been addressed, to which another attempt to avoid the question is made.  Clearly, either these people don&#039;t understand their businesses needs, or they know they can&#039;t help but won&#039;t admit it.  Either way, the debate moves on.&lt;br /&gt;
&lt;br /&gt;
Days later, the business guys are telling some colleagues about their cool new project over an espresso and a latte.  &amp;quot;Hee hee hee, hoo hoo hoo...&amp;quot;, laugh their colleagues.  &amp;quot;We thought our reports would let us track our progress too, but the IT department screwed us over.  They charged us double and delivered nothing useful.  We tried to submit some change requests to get it working and all the IT department wanted was more money and they couldn&#039;t deliver the changes quick enough anyway!&amp;quot;&lt;br /&gt;
&lt;br /&gt;
The cool business dudes ran over to the IT office, informed their development team about the new information and said, &amp;quot;Guys, we don&#039;t want you to use BI.  Well not for the first release anyway.  Maybe in a year or two.  Sure, it&#039;s policy and all, but we don&#039;t know what we want, and need to gain some experience, so just hack those reports out within budget please!&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
So the development team arrange another meeting with the &lt;strike&gt;astronauts&lt;/strike&gt; EAs and QAs to get that unanswered question answered, and they talk about the customers concerns.  Even if it&#039;s an over reaction, the point is, that another department needs to be involved meaning more communication, less visibility and hence greater costs and risks.  &amp;quot;Sure, no problem if the requirements are stable and known, but this project needs agility&amp;quot;, is the point the dev team makes.  &amp;quot;Well, no, not a chance!&amp;quot;, comes the response.&lt;br /&gt;
&lt;br /&gt;
&amp;quot;In fact,&amp;quot; they continue, &amp;quot;you simply need to go back to the business and tell them that their idea is an architecture infringement - it goes against company policies.  You won&#039;t pass QA, you won&#039;t get the go ahead to go into production, and that&#039;s the end of it&amp;quot;, comes the reply.&lt;br /&gt;
&lt;br /&gt;
A solution oriented response indeed...  &amp;quot;Furthermore,&amp;quot; continues an EA, &amp;quot; the business doesn&#039;t have the right to come into our shop and tell us where to implement things and where not to.  We are the experts in the technology domain.  We make these choices.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Well, his argument is that the business hired the CIO, who delegated responsibility to a BI expert, who created a non-agile policy.  So the business have to swallow the argument and accept that the IT department is shit and won&#039;t give them solutions which they need, to compete in new markets...  I&#039;m not sure he realises that this is his argument, but it is, if you look at it pragmatically.&lt;br /&gt;
&lt;br /&gt;
I&#039;m not sure the cool business dudes see it that way either.  I know I don&#039;t see it that way.  And I know of no solution oriented architect or developer who sees it that way.&lt;br /&gt;
&lt;br /&gt;
Of course I understand the reasons we have EA, QA, Processes and Policies.  For large organisations they are the only way to avoid utter chaos, amongst many other reasons.  Most of my working life has been spent with large organisations, even though in many cases I was allowed to implement agile solutions.  But, after a long day in the office, with some frustrating decisions, I need to rant, so here is my cynical view of EA, QA, Processes and Policies, albeit somewhat harsh: these are all things which get bigger, the larger a company is, and all things which let people hide behind their responsibility of providing the business with the solutions they need.  They all cause large corporations to be compared to large dinosaurs.  These departments seem to have forgotten one golden rule: if the business fails, those departments won&#039;t exist.  In competitive markets like we have today, businesses, no matter how large, need to stay competitive, and they can do so by using IT departments which are able to deliver agile solutions.  These departments also often remind me of self-perpetuating &lt;a target=&#034;_blank&#034; href=&#034;http://www.amazon.co.uk/Witch-Doctors-Management-Saying-Matters/dp/074932645X&#034;&gt;witch doctors (The Witch Doctors, ISBN 074932645X)&lt;/a&gt;.  They justify themselves by stating that the business learned the hard way and now that they have been built up they cannot possibly be removed or have power taken away, like we some how never managed to go live before they existed, or that small companies can&#039;t exist because they don&#039;t have them.&lt;br /&gt;
&lt;br /&gt;
Copyright &amp;copy; Ant Kutschera&lt;/p&gt;&lt;div class=&#034;tags&#034;&gt;&lt;span&gt;Social Bookmarks : &lt;/span&gt;&amp;nbsp;&lt;a href=&#034;http://slashdot.org/bookmark.pl?url=http://blog.maxant.co.uk:80/pebble/2010/09/01/1283371140000.html&amp;amp;title=How+Brontosaurs+kill+Raptors&#034; target=&#034;_blank&#034; title=&#034;Add this post to Slash Dot&#034;&gt;&lt;img src=&#034;common/images/slashdot.png&#034; alt=&#034;Add this post to Slashdot&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://digg.com/submit?url=http://blog.maxant.co.uk:80/pebble/2010/09/01/1283371140000.html&amp;amp;title=How+Brontosaurs+kill+Raptors&#034; target=&#034;_blank&#034; title=&#034;Digg this post&#034;&gt;&lt;img src=&#034;common/images/digg.png&#034; alt=&#034;Add this post to Digg&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://reddit.com/submit?url=http://blog.maxant.co.uk:80/pebble/2010/09/01/1283371140000.html&amp;amp;title=How+Brontosaurs+kill+Raptors&#034; target=&#034;_blank&#034; title=&#034;Add this post to Reddit&#034;&gt;&lt;img src=&#034;common/images/reddit.png&#034; alt=&#034;Add this post to Reddit&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://del.icio.us/post?url=http://blog.maxant.co.uk:80/pebble/2010/09/01/1283371140000.html&amp;amp;title=How+Brontosaurs+kill+Raptors&#034; target=&#034;_blank&#034; title=&#034;Save this post to Del.icio.us&#034;&gt;&lt;img src=&#034;common/images/delicious.png&#034; alt=&#034;Add this post to Delicious&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.stumbleupon.com/submit?url=http://blog.maxant.co.uk:80/pebble/2010/09/01/1283371140000.html&amp;amp;title=How+Brontosaurs+kill+Raptors&#034; target=&#034;_blank&#034; title=&#034;Stumble this post&#034;&gt;&lt;img src=&#034;common/images/stumbleupon.png&#034; alt=&#034;Add this post to Stumble it&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.google.com/bookmarks/mark?op=edit&amp;amp;bkmk=http://blog.maxant.co.uk:80/pebble/2010/09/01/1283371140000.html&amp;amp;title=How+Brontosaurs+kill+Raptors&#034; target=&#034;_blank&#034; title=&#034;Add this post to Google&#034;&gt;&lt;img src=&#034;common/images/google.png&#034; alt=&#034;Add this post to Google&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://technorati.com/faves?add=http://blog.maxant.co.uk:80/pebble/2010/09/01/1283371140000.html&#034; target=&#034;_blank&#034; title=&#034;Add this post to Technorati&#034;&gt;&lt;img src=&#034;common/images/technorati.png&#034; alt=&#034;Add this post to Technorati&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.bloglines.com/sub/http://blog.maxant.co.uk:80/pebble/2010/09/01/1283371140000.html&#034; target=&#034;_blank&#034; title=&#034;Add this post to Bloglines&#034;&gt;&lt;img src=&#034;common/images/bloglines.png&#034; alt=&#034;Add this post to Bloglines&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.facebook.com/share.php?u=http://blog.maxant.co.uk:80/pebble/2010/09/01/1283371140000.html&#034; target=&#034;_blank&#034; title=&#034;Add this post to Facebook&#034;&gt;&lt;img src=&#034;common/images/facebook.png&#034; alt=&#034;Add this post to Facebook&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.furl.net/storeIt.jsp?u=http://blog.maxant.co.uk:80/pebble/2010/09/01/1283371140000.html&amp;amp;t=How+Brontosaurs+kill+Raptors&#034; target=&#034;_blank&#034; title=&#034;Add this post to Furl&#034;&gt;&lt;img src=&#034;common/images/furl.png&#034; alt=&#034;Add this post to Furl&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;https://favorites.live.com/quickadd.aspx?mkt=en-us&amp;amp;url=http://blog.maxant.co.uk:80/pebble/2010/09/01/1283371140000.html&amp;amp;title=How+Brontosaurs+kill+Raptors&#034; target=&#034;_blank&#034; title=&#034;Add this post to Windows Live&#034;&gt;&lt;img src=&#034;common/images/windowslive.png&#034; alt=&#034;Add this post to Windows Live&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://bookmarks.yahoo.com/toolbar/savebm?opener=tb&amp;amp;u=http://blog.maxant.co.uk:80/pebble/2010/09/01/1283371140000.html&amp;amp;t=How+Brontosaurs+kill+Raptors&#034; target=&#034;_blank&#034; title=&#034;Add this post to Yahoo!&#034;&gt;&lt;img src=&#034;common/images/yahoo.png&#034; alt=&#034;Add this post to Yahoo!&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&lt;/div&gt;
        </description>
      
      
    
    
    
    <comments>http://blog.maxant.co.uk:80/pebble/2010/09/01/1283371140000.html#comments</comments>
    <guid isPermaLink="true">http://blog.maxant.co.uk:80/pebble/2010/09/01/1283371140000.html</guid>
    <pubDate>Wed, 01 Sep 2010 19:59:00 GMT</pubDate>
  </item>
  
  </channel>
</rss>

