﻿<?xml version="1.0" encoding="utf-8"?><rss version="2.0"><channel><title>igloocoder.com</title><link>http://www.igloocoder.com/</link><description>igloocoder.com</description><copyright>igloocoder.com Consulting Inc. (c) 2013</copyright><ttl>60</ttl><item><title>UI Workflow is business logic</title><description>&lt;p&gt;Over my years as a programmer I’ve focussed a lot of attention and energy on business logic.  I’m sure you have too.  Business logic is, after all, a huge part of what our clients/end users want to see as an output from our development efforts.  But what is included in business logic?  Usually we think of all the conditionals, looping, data mangle-ment, reporting and other similar things.  In my past experiences I’ve poured immense effort into ensuring that this business logic was correct (automated and manual testing), documented (ubiquitous language, automated testing and, yes, comments when appropriate) and centralized (DDD).  While I’ve had intense focus on these needs and practices, I’ve usually neglected to recognize the business logic that is buried in the UI workflow within the application.&lt;/p&gt;  &lt;p&gt;On my current project I’ve been presented with an opportunity to explore this area a bit more in depth.  We don’t have the volume of what I have traditionally considered business logic.  Instead the application is very UI intensive.  As a result I’ve been spending a lot more time worrying about things like “What happens when the user clicks XYZ?”  It became obvious to us very early on that this was the heart of our application’s business logic.&lt;/p&gt;  &lt;p&gt;Once I realized this we were able to focus our attention on the correctness, discoverability, centralization and documentation of the UI workflow.  How did we accomplish this then?  I remember reading somewhere (written by Jeremy Miller I think, although I can’t find a link now) the assertion that “Every application will require the command pattern at some point.” I did some research and found a &lt;a href="http://www.lostechies.com/blogs/derickbailey/archive/2009/12/22/understanding-the-application-controller-through-object-messaging-patterns.aspx"&gt;post by Derick Bailey&lt;/a&gt; explaining how he was using an Application Controller to handle both an Event Aggregator and workflow services.  To quote him:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;Workflow services are the 1,000 foot view of how things get done. They are the direct modeling of a flowchart diagram in code.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;I focused on the first part of his assertion and applied it to the flow of user interfaces.  Basically it has amounted to each user workflow (or sequence of UI concepts) being defined, and executed, in one location.  As an example we have a CreateNewCustomerWorkflowCommand that is executed when the user clicks on the File | Create Customer menu.  It might look something like this:&lt;/p&gt;  &lt;p /&gt;  &lt;div style="width: 850px; color: black; overflow: auto"&gt;   &lt;pre style="margin: 0em; background: #f4f4f4"&gt;&lt;span style="text-align: right; width: 30px; display: inline-block; color: black; margin-right: 10px"&gt;1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt;&lt;span style="color: #000000"&gt;  &lt;span style="color: #0000ff"&gt;class&lt;/span&gt;&lt;span style="color: #000000"&gt;  &lt;span style="color: #2b91af"&gt;CreateNewCustomerWorkflowCommand&lt;/span&gt;&lt;span style="color: #000000"&gt;  : &lt;span style="color: #2b91af"&gt;ICommand&lt;/span&gt;&lt;span style="color: #000000"&gt; &amp;lt;&lt;span style="color: #2b91af"&gt;CreateNewCustomerWorkflow&lt;/span&gt;&lt;span style="color: #000000"&gt; &amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre style="margin: 0em"&gt;&lt;span style="text-align: right; width: 30px; display: inline-block; color: black; margin-right: 10px"&gt;2:&lt;/span&gt; &lt;span style="color: #000000"&gt;{&lt;/span&gt;&lt;/pre&gt;

  &lt;pre style="margin: 0em; background: #f4f4f4"&gt;&lt;span style="text-align: right; width: 30px; display: inline-block; color: black; margin-right: 10px"&gt;3:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;private&lt;/span&gt;&lt;span style="color: #000000"&gt;  &lt;span style="color: #0000ff"&gt;readonly&lt;/span&gt;&lt;span style="color: #000000"&gt;  &lt;span style="color: #2b91af"&gt;ISaveChangesPresenter&lt;/span&gt;&lt;span style="color: #000000"&gt;  _saveChangesPresenter;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre style="margin: 0em"&gt;&lt;span style="text-align: right; width: 30px; display: inline-block; color: black; margin-right: 10px"&gt;4:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;private&lt;/span&gt;&lt;span style="color: #000000"&gt;  &lt;span style="color: #0000ff"&gt;readonly&lt;/span&gt;&lt;span style="color: #000000"&gt;  &lt;span style="color: #2b91af"&gt;ICustomerService&lt;/span&gt;&lt;span style="color: #000000"&gt;  _customerService;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre style="margin: 0em; background: #f4f4f4"&gt;&lt;span style="text-align: right; width: 30px; display: inline-block; color: black; margin-right: 10px"&gt;5:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;private&lt;/span&gt;&lt;span style="color: #000000"&gt;  &lt;span style="color: #0000ff"&gt;readonly&lt;/span&gt;&lt;span style="color: #000000"&gt;  &lt;span style="color: #2b91af"&gt;ICreateNewCustomerPresenter&lt;/span&gt;&lt;span style="color: #000000"&gt;  _createNewCustomerPresenter;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre style="margin: 0em"&gt;&lt;span style="text-align: right; width: 30px; display: inline-block; color: black; margin-right: 10px"&gt;6:&lt;/span&gt; &lt;/pre&gt;

  &lt;pre style="margin: 0em; background: #f4f4f4"&gt;&lt;span style="text-align: right; width: 30px; display: inline-block; color: black; margin-right: 10px"&gt;7:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt;&lt;span style="color: #000000"&gt;  CreateNewCustomerWorkflowCommand(&lt;span style="color: #2b91af"&gt;ISaveChangesPresenter&lt;/span&gt;&lt;span style="color: #000000"&gt;  saveChangesPresenter,&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre style="margin: 0em"&gt;&lt;span style="text-align: right; width: 30px; display: inline-block; color: black; margin-right: 10px"&gt;8:&lt;/span&gt;                                             &lt;span style="color: #2b91af"&gt;ICustomerService&lt;/span&gt;&lt;span style="color: #000000"&gt;  customerService,&lt;/span&gt;&lt;/pre&gt;

  &lt;pre style="margin: 0em; background: #f4f4f4"&gt;&lt;span style="text-align: right; width: 30px; display: inline-block; color: black; margin-right: 10px"&gt;9:&lt;/span&gt;                                             &lt;span style="color: #2b91af"&gt;ICreateNewCustomerPresenter&lt;/span&gt;&lt;span style="color: #000000"&gt;  createNewCustomerPresenter)&lt;/span&gt;&lt;/pre&gt;

  &lt;pre style="margin: 0em"&gt;&lt;span style="text-align: right; width: 30px; display: inline-block; color: black; margin-right: 10px"&gt;10:&lt;/span&gt;     &lt;span style="color: #000000"&gt;{&lt;/span&gt;&lt;/pre&gt;

  &lt;pre style="margin: 0em; background: #f4f4f4"&gt;&lt;span style="text-align: right; width: 30px; display: inline-block; color: black; margin-right: 10px"&gt;11:&lt;/span&gt;         _saveChangesPresenter = saveChangesPresenter;&lt;/pre&gt;

  &lt;pre style="margin: 0em"&gt;&lt;span style="text-align: right; width: 30px; display: inline-block; color: black; margin-right: 10px"&gt;12:&lt;/span&gt;         _customerService = customerService;&lt;/pre&gt;

  &lt;pre style="margin: 0em; background: #f4f4f4"&gt;&lt;span style="text-align: right; width: 30px; display: inline-block; color: black; margin-right: 10px"&gt;13:&lt;/span&gt;         _createNewCustomerPresenter = createNewCustomerPresenter;&lt;/pre&gt;

  &lt;pre style="margin: 0em"&gt;&lt;span style="text-align: right; width: 30px; display: inline-block; color: black; margin-right: 10px"&gt;14:&lt;/span&gt;     &lt;span style="color: #000000"&gt;}&lt;/span&gt;&lt;/pre&gt;

  &lt;pre style="margin: 0em; background: #f4f4f4"&gt;&lt;span style="text-align: right; width: 30px; display: inline-block; color: black; margin-right: 10px"&gt;15:&lt;/span&gt; &lt;/pre&gt;

  &lt;pre style="margin: 0em"&gt;&lt;span style="text-align: right; width: 30px; display: inline-block; color: black; margin-right: 10px"&gt;16:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt;&lt;span style="color: #000000"&gt;  &lt;span style="color: #0000ff"&gt;void&lt;/span&gt;&lt;span style="color: #000000"&gt;  Execute(&lt;span style="color: #2b91af"&gt;CreateNewCustomerWorkflow&lt;/span&gt;&lt;span style="color: #000000"&gt;  commandParameter)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre style="margin: 0em; background: #f4f4f4"&gt;&lt;span style="text-align: right; width: 30px; display: inline-block; color: black; margin-right: 10px"&gt;17:&lt;/span&gt;     &lt;span style="color: #000000"&gt;{&lt;/span&gt;&lt;/pre&gt;

  &lt;pre style="margin: 0em"&gt;&lt;span style="text-align: right; width: 30px; display: inline-block; color: black; margin-right: 10px"&gt;18:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;&lt;span style="color: #000000"&gt;  (commandParameter.CurrentScreenIsDirty)&lt;/span&gt;&lt;/pre&gt;

  &lt;pre style="margin: 0em; background: #f4f4f4"&gt;&lt;span style="text-align: right; width: 30px; display: inline-block; color: black; margin-right: 10px"&gt;19:&lt;/span&gt;         &lt;span style="color: #000000"&gt;{&lt;/span&gt;&lt;/pre&gt;

  &lt;pre style="margin: 0em"&gt;&lt;span style="text-align: right; width: 30px; display: inline-block; color: black; margin-right: 10px"&gt;20:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;var&lt;/span&gt;&lt;span style="color: #000000"&gt;  saveChangesResults = _saveChangesPresenter.Run();&lt;/span&gt;&lt;/pre&gt;

  &lt;pre style="margin: 0em; background: #f4f4f4"&gt;&lt;span style="text-align: right; width: 30px; display: inline-block; color: black; margin-right: 10px"&gt;21:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;&lt;span style="color: #000000"&gt;  (saveChangesResults.ResultState == &lt;span style="color: #2b91af"&gt;ResultState&lt;/span&gt;&lt;span style="color: #000000"&gt; .Cancelled) &lt;span style="color: #0000ff"&gt;return&lt;/span&gt;&lt;span style="color: #000000"&gt; ;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre style="margin: 0em"&gt;&lt;span style="text-align: right; width: 30px; display: inline-block; color: black; margin-right: 10px"&gt;22:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;&lt;span style="color: #000000"&gt;  (saveChangesResults.ResultState == &lt;span style="color: #2b91af"&gt;ResultState&lt;/span&gt;&lt;span style="color: #000000"&gt; .Yes)&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre style="margin: 0em; background: #f4f4f4"&gt;&lt;span style="text-align: right; width: 30px; display: inline-block; color: black; margin-right: 10px"&gt;23:&lt;/span&gt;             &lt;span style="color: #000000"&gt;{&lt;/span&gt;&lt;/pre&gt;

  &lt;pre style="margin: 0em"&gt;&lt;span style="text-align: right; width: 30px; display: inline-block; color: black; margin-right: 10px"&gt;24:&lt;/span&gt;                 _customerService.Save(commandParameter.CurrentScreenCustomerSaveDto);&lt;/pre&gt;

  &lt;pre style="margin: 0em; background: #f4f4f4"&gt;&lt;span style="text-align: right; width: 30px; display: inline-block; color: black; margin-right: 10px"&gt;25:&lt;/span&gt;             &lt;span style="color: #000000"&gt;}&lt;/span&gt;&lt;/pre&gt;

  &lt;pre style="margin: 0em"&gt;&lt;span style="text-align: right; width: 30px; display: inline-block; color: black; margin-right: 10px"&gt;26:&lt;/span&gt;         &lt;span style="color: #000000"&gt;}&lt;/span&gt;&lt;/pre&gt;

  &lt;pre style="margin: 0em; background: #f4f4f4"&gt;&lt;span style="text-align: right; width: 30px; display: inline-block; color: black; margin-right: 10px"&gt;27:&lt;/span&gt; &lt;/pre&gt;

  &lt;pre style="margin: 0em"&gt;&lt;span style="text-align: right; width: 30px; display: inline-block; color: black; margin-right: 10px"&gt;28:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;var&lt;/span&gt;&lt;span style="color: #000000"&gt;  newCustomerResults = _createNewCustomerPresenter.Run();&lt;/span&gt;&lt;/pre&gt;

  &lt;pre style="margin: 0em; background: #f4f4f4"&gt;&lt;span style="text-align: right; width: 30px; display: inline-block; color: black; margin-right: 10px"&gt;29:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;&lt;span style="color: #000000"&gt;  (newCustomerResults.ResultState == &lt;span style="color: #2b91af"&gt;ResultState&lt;/span&gt;&lt;span style="color: #000000"&gt; .Cancelled) &lt;span style="color: #0000ff"&gt;return&lt;/span&gt;&lt;span style="color: #000000"&gt; ;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre style="margin: 0em"&gt;&lt;span style="text-align: right; width: 30px; display: inline-block; color: black; margin-right: 10px"&gt;30:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;&lt;span style="color: #000000"&gt;  (newCustomerResults.ResultState == &lt;span style="color: #2b91af"&gt;ResultState&lt;/span&gt;&lt;span style="color: #000000"&gt; .Save)&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre style="margin: 0em; background: #f4f4f4"&gt;&lt;span style="text-align: right; width: 30px; display: inline-block; color: black; margin-right: 10px"&gt;31:&lt;/span&gt;         &lt;span style="color: #000000"&gt;{&lt;/span&gt;&lt;/pre&gt;

  &lt;pre style="margin: 0em"&gt;&lt;span style="text-align: right; width: 30px; display: inline-block; color: black; margin-right: 10px"&gt;32:&lt;/span&gt;             _customerService.Save(newCustomerResults.Data);&lt;/pre&gt;

  &lt;pre style="margin: 0em; background: #f4f4f4"&gt;&lt;span style="text-align: right; width: 30px; display: inline-block; color: black; margin-right: 10px"&gt;33:&lt;/span&gt;         &lt;span style="color: #000000"&gt;}&lt;/span&gt;&lt;/pre&gt;

  &lt;pre style="margin: 0em"&gt;&lt;span style="text-align: right; width: 30px; display: inline-block; color: black; margin-right: 10px"&gt;34:&lt;/span&gt;     &lt;span style="color: #000000"&gt;}&lt;/span&gt;&lt;/pre&gt;

  &lt;pre style="margin: 0em; background: #f4f4f4"&gt;&lt;span style="text-align: right; width: 30px; display: inline-block; color: black; margin-right: 10px"&gt;35:&lt;/span&gt; &lt;span style="color: #000000"&gt;}&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p /&gt;

&lt;p&gt;As you can see the high level design of the user interaction, and service interaction, is clearly defined here.  Make no mistake, this is business logic.  It answers the question of how does the business expect the creation of a new customer to occur.  We’ve clearly defined this situation in one encapsulated piece of code.  By doing this we have now laid out a pattern whereby any developer looking for a business action can look through these workflows.  They clearly document the expected behaviour during the situation.  Since we’re using Dependency Injection in our situation, we can also write clear tests to continuously validate these expected behaviours.  Those tests, when done in specific ways, can also enhance the documentation surrounding the system.  For example, using BDD style naming and a small utility to retrieve and format the TestFixture and Test names we can generate something like the following:&lt;/p&gt;

&lt;p /&gt;

&lt;div style="width: 850px; color: black; overflow: auto"&gt;
  &lt;pre style="margin: 0em; background: #f4f4f4"&gt;&lt;span style="text-align: right; width: 30px; display: inline-block; color: black; margin-right: 10px"&gt;1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt;&lt;span style="color: #000000"&gt;  &lt;span style="color: #0000ff"&gt;class&lt;/span&gt;&lt;span style="color: #000000"&gt;  &lt;span style="color: #2b91af"&gt;When_the_current_screen_has_pending_changes&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre style="margin: 0em"&gt;&lt;span style="text-align: right; width: 30px; display: inline-block; color: black; margin-right: 10px"&gt;2:&lt;/span&gt; &lt;span style="color: #000000"&gt; &lt;span style="color: #000000"&gt;{&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre style="margin: 0em; background: #f4f4f4"&gt;&lt;span style="text-align: right; width: 30px; display: inline-block; color: black; margin-right: 10px"&gt;3:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt;&lt;span style="color: #000000"&gt;  &lt;span style="color: #0000ff"&gt;void&lt;/span&gt;&lt;span style="color: #000000"&gt;  the_user_should_be_prompted_with_the_option_to_save_those_changes()&lt;span style="color: #000000"&gt;{&lt;/span&gt;&lt;span style="color: #000000"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre style="margin: 0em"&gt;&lt;span style="text-align: right; width: 30px; display: inline-block; color: black; margin-right: 10px"&gt;4:&lt;/span&gt; &lt;span style="color: #000000"&gt;}&lt;/span&gt;&lt;/pre&gt;

  &lt;pre style="margin: 0em; background: #f4f4f4"&gt;&lt;span style="text-align: right; width: 30px; display: inline-block; color: black; margin-right: 10px"&gt;5:&lt;/span&gt; &lt;/pre&gt;

  &lt;pre style="margin: 0em"&gt;&lt;span style="text-align: right; width: 30px; display: inline-block; color: black; margin-right: 10px"&gt;6:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt;&lt;span style="color: #000000"&gt;  &lt;span style="color: #0000ff"&gt;class&lt;/span&gt;&lt;span style="color: #000000"&gt;  &lt;span style="color: #2b91af"&gt;When_the_user_chooses_to_cancel_when_asked_to_save_pending_changes&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre style="margin: 0em; background: #f4f4f4"&gt;&lt;span style="text-align: right; width: 30px; display: inline-block; color: black; margin-right: 10px"&gt;7:&lt;/span&gt; &lt;span style="color: #000000"&gt; &lt;span style="color: #000000"&gt;{&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre style="margin: 0em"&gt;&lt;span style="text-align: right; width: 30px; display: inline-block; color: black; margin-right: 10px"&gt;8:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt;&lt;span style="color: #000000"&gt;  &lt;span style="color: #0000ff"&gt;void&lt;/span&gt;&lt;span style="color: #000000"&gt;  the_pending_changes_should_not_be_saved()&lt;span style="color: #000000"&gt;{&lt;/span&gt;&lt;span style="color: #000000"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre style="margin: 0em; background: #f4f4f4"&gt;&lt;span style="text-align: right; width: 30px; display: inline-block; color: black; margin-right: 10px"&gt;9:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt;&lt;span style="color: #000000"&gt;  &lt;span style="color: #0000ff"&gt;void&lt;/span&gt;&lt;span style="color: #000000"&gt;  the_create_new_customer_dialog_should_not_be_displayed()&lt;span style="color: #000000"&gt;{&lt;/span&gt;&lt;span style="color: #000000"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre style="margin: 0em"&gt;&lt;span style="text-align: right; width: 30px; display: inline-block; color: black; margin-right: 10px"&gt;10:&lt;/span&gt; &lt;span style="color: #000000"&gt;}&lt;/span&gt;&lt;/pre&gt;

  &lt;pre style="margin: 0em; background: #f4f4f4"&gt;&lt;span style="text-align: right; width: 30px; display: inline-block; color: black; margin-right: 10px"&gt;11:&lt;/span&gt; &lt;/pre&gt;

  &lt;pre style="margin: 0em"&gt;&lt;span style="text-align: right; width: 30px; display: inline-block; color: black; margin-right: 10px"&gt;12:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt;&lt;span style="color: #000000"&gt;  &lt;span style="color: #0000ff"&gt;class&lt;/span&gt;&lt;span style="color: #000000"&gt;  &lt;span style="color: #2b91af"&gt;When_the_user_chooses_not_to_save_pending_changes&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre style="margin: 0em; background: #f4f4f4"&gt;&lt;span style="text-align: right; width: 30px; display: inline-block; color: black; margin-right: 10px"&gt;13:&lt;/span&gt; &lt;span style="color: #000000"&gt; &lt;span style="color: #000000"&gt;{&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre style="margin: 0em"&gt;&lt;span style="text-align: right; width: 30px; display: inline-block; color: black; margin-right: 10px"&gt;14:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt;&lt;span style="color: #000000"&gt;  &lt;span style="color: #0000ff"&gt;void&lt;/span&gt;&lt;span style="color: #000000"&gt;  the_pending_changes_should_not_be_saved()&lt;span style="color: #000000"&gt;{&lt;/span&gt;&lt;span style="color: #000000"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre style="margin: 0em; background: #f4f4f4"&gt;&lt;span style="text-align: right; width: 30px; display: inline-block; color: black; margin-right: 10px"&gt;15:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt;&lt;span style="color: #000000"&gt;  &lt;span style="color: #0000ff"&gt;void&lt;/span&gt;&lt;span style="color: #000000"&gt;  the_create_new_customer_dialog_should_be_displayed()&lt;span style="color: #000000"&gt;{&lt;/span&gt;&lt;span style="color: #000000"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre style="margin: 0em"&gt;&lt;span style="text-align: right; width: 30px; display: inline-block; color: black; margin-right: 10px"&gt;16:&lt;/span&gt; &lt;span style="color: #000000"&gt;}&lt;/span&gt;&lt;/pre&gt;

  &lt;pre style="margin: 0em; background: #f4f4f4"&gt;&lt;span style="text-align: right; width: 30px; display: inline-block; color: black; margin-right: 10px"&gt;17:&lt;/span&gt; &lt;/pre&gt;

  &lt;pre style="margin: 0em"&gt;&lt;span style="text-align: right; width: 30px; display: inline-block; color: black; margin-right: 10px"&gt;18:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt;&lt;span style="color: #000000"&gt;  &lt;span style="color: #0000ff"&gt;class&lt;/span&gt;&lt;span style="color: #000000"&gt;  &lt;span style="color: #2b91af"&gt;When_the_user_chooses_to_to_save_pending_changes&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre style="margin: 0em; background: #f4f4f4"&gt;&lt;span style="text-align: right; width: 30px; display: inline-block; color: black; margin-right: 10px"&gt;19:&lt;/span&gt; &lt;span style="color: #000000"&gt; &lt;span style="color: #000000"&gt;{&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre style="margin: 0em"&gt;&lt;span style="text-align: right; width: 30px; display: inline-block; color: black; margin-right: 10px"&gt;20:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt;&lt;span style="color: #000000"&gt;  &lt;span style="color: #0000ff"&gt;void&lt;/span&gt;&lt;span style="color: #000000"&gt;  the_pending_changes_should_be_saved()&lt;span style="color: #000000"&gt;{&lt;/span&gt;&lt;span style="color: #000000"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre style="margin: 0em; background: #f4f4f4"&gt;&lt;span style="text-align: right; width: 30px; display: inline-block; color: black; margin-right: 10px"&gt;21:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt;&lt;span style="color: #000000"&gt;  &lt;span style="color: #0000ff"&gt;void&lt;/span&gt;&lt;span style="color: #000000"&gt;  the_create_new_customer_dialog_should_be_displayed()&lt;span style="color: #000000"&gt;{&lt;/span&gt;&lt;span style="color: #000000"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre style="margin: 0em"&gt;&lt;span style="text-align: right; width: 30px; display: inline-block; color: black; margin-right: 10px"&gt;22:&lt;/span&gt; &lt;span style="color: #000000"&gt;}&lt;/span&gt;&lt;/pre&gt;

  &lt;pre style="margin: 0em; background: #f4f4f4"&gt;&lt;span style="text-align: right; width: 30px; display: inline-block; color: black; margin-right: 10px"&gt;23:&lt;/span&gt; &lt;/pre&gt;

  &lt;pre style="margin: 0em"&gt;&lt;span style="text-align: right; width: 30px; display: inline-block; color: black; margin-right: 10px"&gt;24:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt;&lt;span style="color: #000000"&gt;  &lt;span style="color: #0000ff"&gt;class&lt;/span&gt;&lt;span style="color: #000000"&gt;  &lt;span style="color: #2b91af"&gt;When_the_user_chooses_to_cancel_from_creating_a_new_customer&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre style="margin: 0em; background: #f4f4f4"&gt;&lt;span style="text-align: right; width: 30px; display: inline-block; color: black; margin-right: 10px"&gt;25:&lt;/span&gt; &lt;span style="color: #000000"&gt; &lt;span style="color: #000000"&gt;{&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre style="margin: 0em"&gt;&lt;span style="text-align: right; width: 30px; display: inline-block; color: black; margin-right: 10px"&gt;26:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt;&lt;span style="color: #000000"&gt;  &lt;span style="color: #0000ff"&gt;void&lt;/span&gt;&lt;span style="color: #000000"&gt;  the_new_customer_should_not_be_saved()&lt;span style="color: #000000"&gt;{&lt;/span&gt;&lt;span style="color: #000000"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre style="margin: 0em; background: #f4f4f4"&gt;&lt;span style="text-align: right; width: 30px; display: inline-block; color: black; margin-right: 10px"&gt;27:&lt;/span&gt; &lt;span style="color: #000000"&gt;}&lt;/span&gt;&lt;/pre&gt;

  &lt;pre style="margin: 0em"&gt;&lt;span style="text-align: right; width: 30px; display: inline-block; color: black; margin-right: 10px"&gt;28:&lt;/span&gt; &lt;/pre&gt;

  &lt;pre style="margin: 0em; background: #f4f4f4"&gt;&lt;span style="text-align: right; width: 30px; display: inline-block; color: black; margin-right: 10px"&gt;29:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt;&lt;span style="color: #000000"&gt;  &lt;span style="color: #0000ff"&gt;class&lt;/span&gt;&lt;span style="color: #000000"&gt;  &lt;span style="color: #2b91af"&gt;When_the_user_chooses_to_create_a_new_customer&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre style="margin: 0em"&gt;&lt;span style="text-align: right; width: 30px; display: inline-block; color: black; margin-right: 10px"&gt;30:&lt;/span&gt; &lt;span style="color: #000000"&gt; &lt;span style="color: #000000"&gt;{&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre style="margin: 0em; background: #f4f4f4"&gt;&lt;span style="text-align: right; width: 30px; display: inline-block; color: black; margin-right: 10px"&gt;31:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt;&lt;span style="color: #000000"&gt;  &lt;span style="color: #0000ff"&gt;void&lt;/span&gt;&lt;span style="color: #000000"&gt;  the_new_customer_should_be_saved()&lt;span style="color: #000000"&gt;{&lt;/span&gt;&lt;span style="color: #000000"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre style="margin: 0em"&gt;&lt;span style="text-align: right; width: 30px; display: inline-block; color: black; margin-right: 10px"&gt;32:&lt;/span&gt; &lt;span style="color: #000000"&gt;}&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p /&gt;

&lt;p&gt;As you can see, this technique allows us to create a rich set of documentation outlining how the application should interact with the user when they are creating a new customer.&lt;/p&gt;

&lt;p&gt;Now that we’ve finished implementing this pattern a few times, have I seen any drawbacks?  Not really.  If we didn’t use this technique we’d still have to write the code to coordinate the screen sequencing.  That sequencing would be spread all over the codebase, most likely in the event handlers for buttons on forms (or their associated Presenter/Controller code).  Instead we’ve introduced a couple more classes per workflow and have centralized the sequencing in them.  So the trade off was the addition of a couple of classes per workflow for more discoverability, testability and documentation.  A no brainer if you ask me.&lt;/p&gt;

&lt;p&gt;Is this solution the panacea?  Absolutely not.  It works very well for the application that we’re building though.  In the future will I consider using this pattern? Without doubt.  It might morph and change a bit based on the next application’s needs, but I think that the basic idea is strong and has significant benefits.&lt;/p&gt;

&lt;p&gt;A big shout out to Derick Bailey for writing a great post on the &lt;a href="http://www.lostechies.com/blogs/derickbailey/archive/2009/12/22/understanding-the-application-controller-through-object-messaging-patterns.aspx"&gt;Application Controller, Event Aggregator and Workflow Services&lt;/a&gt;.  Derick even has a sample app available for reference.  I found it to be great for getting started, but it is a little bit trivial as it only implements one simple workflow.  Equally big kudos to Jeremy Miller and his &lt;a href="http://codebetter.com/blogs/jeremy.miller/archive/2007/07/25/the-build-your-own-cab-series-table-of-contents.aspx"&gt;Build Your Own CAB&lt;/a&gt; series which touches all around this type of concept.  Reading both of these sources helped to cement that there was a better way.&lt;/p&gt;</description><link>http://www.igloocoder.com/2303/ui-workflow-is-business-logic?key=b50486d2-a516-4f06-b33b-e4f04a8ea5c2</link><guid>http://www.igloocoder.com/2303/ui-workflow-is-business-logic?key=b50486d2-a516-4f06-b33b-e4f04a8ea5c2</guid><pubDate>Sun, 26 Sep 2010 21:42:00 GMT</pubDate></item><item><title>Visual Studio Project files and coupling</title><description>&lt;p&gt;The way that we’re told to use Visual Studio is that we create a solution file and add into it one or more project files.  Each project file then gets filled with different development artefacts.  When you build inside of Visual Studio each project represents a compiled distributable file (exe, dll, etc).  Many people carry this practice over into their build scripts.  You might be one of them.  I’m here to tell you why you’re wrong to be doing this.&lt;/p&gt;  &lt;p&gt;Let’s say you’re starting a project.  You open Visual Studio, select File | New Project and get things rolling.  In a few minutes you have a Solution that contains a few Projects.  Maybe you have one for the UI, one for the business logic and one for the data access layer.  All is good.  A few months later, after adding many artefacts to the different projects, something triggers the need to split the artefacts into one assembly from one DLL into two DLLs.  &lt;/p&gt;  &lt;p&gt;You set off to make this happen.  Obviously you need to add a new Project to your Solution, modify some references, and shift some files from one Project into another.  Say you’re stuck using an exclusive locking source control system (like VSS…shudder).  You *must* have exclusive access to all the files necessary including:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;the sln so you can add the new project&lt;/li&gt;    &lt;li&gt;at least one existing cs/vb/fsproj which you’ll be removing existing code artefacts from&lt;/li&gt;    &lt;li&gt;any cs/vb/fs files that will be moved &lt;/li&gt;    &lt;li&gt;any cs/vb/fs files that reference the ones moving (using statements will need updating when you change the namespacing on the files being moved) &lt;/li&gt;    &lt;li&gt;possibly some resx files that need to be moved&lt;/li&gt;    &lt;li&gt;possibly config files that need to be changed or moved&lt;/li&gt;    &lt;li&gt;any automated tests that make use of the moving cs/vb/fs files &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;It’s a pretty damn big list of files that you will need to exclusively lock during this process.  Chances are you will need to push all of your co-workers out of the development environment so that you can gain access to all of those files.  Essentially you are, at this point, halting the development process so that you can do nothing more than split one DLL into two.  That in quite inefficient in the short term and it’s completely unsustainable in the long term.&lt;/p&gt;  &lt;p&gt;I can hear you now, “Well I use &amp;lt;git/mercurial/svn/etc&amp;gt; so we won’t have those issues”.  Really?  Think it through for a second.  Go ahead, I’ll wait.&lt;/p&gt;  &lt;p&gt;With the volume of changes that I listed above, you’ll likely want to be working in some kind of isolation, whether that is local or central.  So yes, you can protect yourself from blocking the ongoing development of your co-workers by properly using those version control systems.  But remember, you do have to integrate your changes with their work at some point.  How are you going to do that?  You’ve moved and modified a significant number of files.  You will have to merge your changes into a branch (or the trunk) locally or otherwise.  Trust me, this will be a merge conflict nightmare.  And it won’t be a pain just for you.  What about the co-worker that has local changes outstanding when you commit your merged modification?  They’re going to end up with a massive piece of merge work on their plate as well.  So instead of being blocked while you do the work, you’re actually creating a block for them immediately after you have completed your work.  Again, the easiest way to achieve the changes would be to prevent any other developers from working in the code while modifications are occurring.  Doesn’t that sound an awful lot like exclusive locking?&lt;/p&gt;  &lt;p&gt;Now, I know you’re thinking “Pfft..that doesn’t happen often”.  This is where you’re wrong.  When you started that application development cycle (remember File | New Project?) you likely didn’t have all of the information necessary to determine what your deployables requirements were.  Since you didn’t have all of that information, chances were good, right from the outset, that you were going to be doing the wrong thing.  With that being the case, it means that chances were good that you were going to have to make changes like the one described above.  To me that indicates that you are, by deciding to tie your Visual Studio Projects to your deployables, accepting that you will undertake this overhead.&lt;/p&gt;  &lt;p&gt;People, possibly you, accept this overhead on every software project they participate in.  This is where you’re wrong.  There is a way to avoid all of this, but people shrug it off as “not mainstream” and “colouring outside the lines”.  The thing is it works, so ignore it at your own peril.&lt;/p&gt;  &lt;p&gt;There is a lot of talk in some development circles about decoupling code.  It’s generally accepted that tightly coupled code is harder to modify, extend and maintain.  When you say that a Visual Studio Project is the equivalent of a deployable, you have tightly coupled your deployment and development structures.  Like code, and as the example above shows, it makes it hard to modify, extend and maintain your deployment.  So why not decouple the Visual Studio Project structure from the deployables requirements?&lt;/p&gt;  &lt;p&gt;It’s not that hard to do.  You’ll need to write a build script that doesn’t reference the cs/vb/fsproj files at all.  The .NET Framework kindly provides configurable compiler access for us.  The different language command line compilers (vbc.exe/csc.exe/fsc.exe) allow you to pass in code files, references, resources, etc.  By using this capability, you can build any number of assemblies that you want simply by passing a listing of artefacts into the compiler.  To make it even easier, most build scripting tools provide built in capability to do this.  NAnt and MSBuild both provide (for C#) &amp;lt;csc&amp;gt; tasks that can accept wild carded lists of code files.  This means you can end up with something like this coming out of a solution-project structure that has only one project in it:&lt;/p&gt;  &lt;p&gt;&amp;lt;csc output="MyApp.DAL.dll" target="library" debug="${debug}"&amp;gt;    &lt;br /&gt;  &amp;lt;sources&amp;gt;     &lt;br /&gt;    &amp;lt;include name="MyApp.Core/DAL/**/*.cs"/&amp;gt;     &lt;br /&gt;  &amp;lt;/sources&amp;gt;     &lt;br /&gt;  &amp;lt;references&amp;gt;     &lt;br /&gt;    &amp;lt;include name="log4net.dll"/&amp;gt;     &lt;br /&gt;  &amp;lt;/references&amp;gt;     &lt;br /&gt;&amp;lt;/csc&amp;gt; &lt;/p&gt;  &lt;p&gt;&amp;lt;csc output="MyApp.Core.dll" target="library" debug="${debug}"&amp;gt;    &lt;br /&gt;  &amp;lt;sources&amp;gt;     &lt;br /&gt;    &amp;lt;include name="MyApp.Core/Business/**/*.cs"/&amp;gt;     &lt;br /&gt;  &amp;lt;/sources&amp;gt;     &lt;br /&gt;  &amp;lt;references&amp;gt;     &lt;br /&gt;    &amp;lt;include name="log4net.dll"/&amp;gt;     &lt;br /&gt;    &amp;lt;include name="MyApp.DAL.dll"/&amp;gt;     &lt;br /&gt;  &amp;lt;/references&amp;gt;     &lt;br /&gt;&amp;lt;/csc&amp;gt; &lt;/p&gt;  &lt;p&gt;&amp;lt;csc output="MyApp.UI.exe" target="winexe" debug="${debug}"&amp;gt;    &lt;br /&gt;  &amp;lt;sources&amp;gt;     &lt;br /&gt;    &amp;lt;include name="MyApp.Core/**/*.cs"/&amp;gt;     &lt;br /&gt;    &amp;lt;exclude name="MyApp.Core/DAL/*.cs"/&amp;gt;     &lt;br /&gt;    &amp;lt;exclude name="MyApp.Core/Business/*.cs"/&amp;gt;     &lt;br /&gt;  &amp;lt;/sources&amp;gt;     &lt;br /&gt;  &amp;lt;references&amp;gt;     &lt;br /&gt;    &amp;lt;include name="log4net.dll"/&amp;gt;     &lt;br /&gt;    &amp;lt;include name="MyApp.DAL.dll"/&amp;gt;     &lt;br /&gt;    &amp;lt;include name="MyApp.Core.dll"/&amp;gt;     &lt;br /&gt;  &amp;lt;/references&amp;gt;     &lt;br /&gt;&amp;lt;/csc&amp;gt; &lt;/p&gt;  &lt;p&gt;Likewise, we could consolidate code from multiple projects (really file paths is what the build script sees them as) into one deployable.&lt;/p&gt;  &lt;p&gt;&amp;lt;csc output="MyApp.UI.exe" target="winexe" debug="${debug}"&amp;gt;    &lt;br /&gt;  &amp;lt;sources&amp;gt;     &lt;br /&gt;    &amp;lt;include name="MyApp.DAL/**/*.cs"/&amp;gt;     &lt;br /&gt;    &amp;lt;include name="MyApp.Business/**/*.cs"/&amp;gt;     &lt;br /&gt;    &amp;lt;exclude name="MyApp.UI/**/*.cs"/&amp;gt;     &lt;br /&gt;  &amp;lt;/sources&amp;gt;     &lt;br /&gt;  &amp;lt;references&amp;gt;     &lt;br /&gt;    &amp;lt;include name="log4net.dll"/&amp;gt;   &lt;br /&gt;  &amp;lt;/references&amp;gt;     &lt;br /&gt;&amp;lt;/csc&amp;gt; &lt;/p&gt;  &lt;p&gt;Now, when it comes time to change to meet new deployables needs, you just need to modify your build script.  Modify the inputs for the different compiler calls and/or add new compilations simply by editing one file.  While you’re doing this the rest of your co-workers can continue doing what they need to provide value to the business.  When it comes time for you to commit the changes to how things are getting compiled, you only have to worry about merging one file. Because the build script is far less volatile than the code files in your solution-project structure, that merge should be relatively painless.&lt;/p&gt;  &lt;p&gt;Another way to look at this is that we are now able to configure and use Visual Studio and the solution-project structure in a way that is optimal for developers to &lt;em&gt;write and edit &lt;/em&gt;code.  And, in turn, we configure and use the build script in a way that allows developers to be efficient and effective at &lt;em&gt;compiling and deploying&lt;/em&gt; code.  This is the decoupling that we really should have in our process and ecosystem to allow us to react quickly to change, whether it comes from the business or our own design decisions.&lt;/p&gt;</description><link>http://www.igloocoder.com/2299/visual-studio-project-files-and-coupling?key=9028e45b-571c-4867-ac7e-65cdfe080f23</link><guid>http://www.igloocoder.com/2299/visual-studio-project-files-and-coupling?key=9028e45b-571c-4867-ac7e-65cdfe080f23</guid><pubDate>Wed, 09 Jun 2010 13:39:40 GMT</pubDate></item></channel></rss>