CodeBetter.Com
CodeBetter.Com
RSS 2.0 via Feedburner
           Do you Twitter? Follow us @CodeBetter

Jeremy D. Miller -- The Shade Tree Developer

Under the hood and working with .Net, TDD, Software Design, and Agile Stuff

December 2007 - Posts

  • What I want in the new year

    Getting the negativity out of my system before the end of the year comes with the promise of a new day and a fresh start in a new position.  I was going to call this something like a developer's bill of rights but that's pompous and we don't have a "right" to any of this.  I'm not thinking of any one particular project or organization here but an amalgamation of all the ugliness I've seen the last couple years.  All the same, here's for wishing.

     

    ALT.NET

    I want ALT.NET to be something that ultimately leads to a stronger, more capable .Net developer community.  I want a greater awareness of solid software engineering thinking in .Net teams.  I want things like "Separation of Concerns" and Continuous Integration and TDD/BDD to stop being fancy ivory tower things we don't have time for and start being just things that we do.  That's it.  I don't want to change the world or convert MS to our new (stolen from every other developer community) philosophy.  I do want us to be exchanging ideas with other develoment communities instead of having a closed loop conversation with Microsoft only.  I'm sick of the tortured "what is it all about" and "who made you boss" crap on the mailing lists and the not entirely undeserved negative backlash to ALT.NET. 

    The masked man behind ALT.NET Pursefight put it best:

    We see the person best helped by Alt.Net as that young, enterprising developer living in a cave somewhere with a bunch of old geezers, basically left to his/her own devices to find the best tools/practices to help them implement their solution. Ie that one-in-ten developer who is using NHibernate and CI Factory while the rest of the team is stumbling along blindly, still trying to wrap their brains around all these new-fangled, advanced concepts like DataSets and Generics.

    Perfect.  Let's help that guy out and be a support group for folks like that.  Circa 2002 *I* was that guy.

     

    Customers that care

    You're spending oodles of money to develop this software.  How about a little time and concentration during the project to make sure that what's getting built is valuable?  My wife and I are buying a new house in Austin that's breaking ground this month.  You better believe we're going to be over to the construction site on a regular basis -- even though there's already a blueprint.

     

    To Write Software that Matters

    That's right, I'd like to build stuff that somebody else cares about.  I built a new architecture for a Trade Capture application this past spring that I'm still fairly proud of.  The codebase has a very high level of test coverage, little DSLish fluent interfaces for gluing together common behavior, and has so far been very successful in efforts to extend the system.  It's feature rich, but nobody is using it because nobody was asking for it.  I spent over a year and a half in a satellite office where the mothership didn't give a damn that we existed period.  I want to be the main show and feel like the work has some purpose.

     

    Good Requirements

    Requirements that lead to software that matters and given in a form that's easy for both the developers and testers to use.  I'm shooting for Executable Requirements next year for everything possible.  I refuse to let the dream die.  A vague statement of "just make it work like some other system" does not fit the bill.  Neither does a requirement pulled from a PM's fevered imagination without customer involvement.

     

    Testers embedded and collocated on the team

    I counted it up, since the end of a project in about July of 2001 I have had roughly 12 months where I worked with actual testers.  I think it's close to insanely stupid that so few organizations seem to pay attention to the testing.  Testing seems to go so much easier when it happens closer to coding and problems get fixed easier when the testers are collocated.

     

    A Project Manager that I trust

    Actually, next year PM is one of my hats, so I hope I can trust the PM.  I think too many project managers handle the stress of expectations from above poorly and pass that stress on to the rest of the team.  Other PM's try to create a cult of personality around themselves on the project.   The project manager needs to be someone I can trust to take care of roadblocks from outside and manage priorities -- but never someone I need to be afraid of in retrospectives.

     

    A culture of sharpening the saw

    If I hear any variation on the words "we don't have time for [something that would make us faster], we've got stuff to do!" or "we've just got to Git 'R Done!" one more time from anybody I work with, I will be charged with physical assault.  I'm putting the words "Sharpen the Saw!" on a poster somewhere in our new office space.  I like Jim Shore's Fill in the Gopher Holes analogy here.

     

    A Collaborative Workspace

    I just wrapped up 15 months straight of cubesville living and being monitored.  Cubicles might as well be sold as an "Anti-Collaboration and Isolation" device for your employees.  I can't wait to get back into a team room again.  I'm an introvert by nature, but I've gotten used to XP style teams and I miss the interaction with other people.

     

    An enjoyable environment

    Minimal tension, a dash of fun, and a sense of shared purpose.  I want to be anal retentive about anything related to the code and the final product, but loose about everything else.

     

    No More Legacy Code!

    I'm tired of taking over .Net code that's less than 2 years old that's unmistakably legacy code -- i.e. code that you don't want to work with.  Granted, I'm very particular about how I want things, but test coverage, consistent code formatting and naming, and cyclomatic complexity numbers measured in the tens shouldn't be too much to ask for.  I'll accept bad code in 5 year old systems, but not from freshly minted code.

  • My favorite new blog of 2007

    New bloggers come all the time (and old ones stop producing), but my favorite new blog for 2007 was definitely Max Pool of Codesqueeze.

    Here's his self-compiled Best of Codesqueeze 2007

  • Back to Austin (OT)

    Last year my family & I made the move from Austin to the NYC area.  I've had a very pleasant run at Sungard FST (Finetix), and would happily recommend them if you're interested in doing development in the financial arena.  From a personal perspective it's been obvious for some time that we were happier living in Texas.  I'm starting an exciting new opportunity at the beginning of the year that will finally see me land back in Austin in February.  Because my energy is getting spent on the move, OSS work, and helping to get my new team/product/office ramped up (more on this later), I'm going to shut down the blog for awhile rather than walk around feeling guilty because I haven't posted recently.

    Merry Christmas and Happy Holidays to all of you.  I'll come back to blogging sometime early next year with new posts.  To the Austinites out there, I'll see you at AgileATX in a couple months.

     

    In the meantime, here's to...

    • Bluebonnet season
    • Smoked Chicken Enchiladas at Trudy's
    • Billie Joe Shaver at the Nutty Brown Cafe
    • Waterloo Records
    • Austin City Limits
    • The Alamo Drafthouse
    • The Broken Spoke
    • UT Football
    • Bob Schneider at the Saxon Pub
    • and long Friday lunches at Chuy's
  • The Wheel of Time will go on (Off Topic)

    Not development related, but some of you are probably interested:

    Robert Jordan's wife has selected an author to finish the last WoT book:
     

    http://www.tor-forge.com/NewsArticle.aspx?articleId=647 

  • Cool new way to write more expressive testing DSL's in FitnesseDotNet

    Check out Kenneth Kasajian's new PhraseFixture idea for more readable Fit style tests.  Two thumbs up from me Kenneth.

     

  • The Dependency Injection Application Block from Patterns and Practices

    In case you've missed it, Grigori Melnik has announced that the forthcoming version of the EntLib will include a new application block for Dependency Injection.  I know there's been some level of disquiet about this announcement in ALT.NETish circles, but I think it's going to be a good thing.  I wrote a little bit about it before, but the key points for me are this:

    • Used well, Dependency Injection can do a lot of good in creating a modular design (and no, having TypeMock does not entirely replace the need for or value of DI).  Hopefully, more developers will be introduced to the concepts and usage of DI and Inversion of Control by the new DIAB.
    • From Gigori:  "...we plan to refactor individual EntLib blocks and abstract away configuration code (configurators)."  Jeremy's take:  EntLib classes will now be usable without having to muck with the configuration Xml.  I don't use EntLib in some small part due to my perception of it being "coding in Xml."
    • Patterns and Practices is reaching out to the OSS teams that have already built successful, working Inversion of Control containers.  I think that will alleviate some of the griping about ObjectBuilder from certain folks (like me).  Yes, it's another de facto competitor to working OSS tools from Microsoft, but at least they're being much more open and cooperative this time around.
    • You will be able to swap out the new DIAB for an existing IoC container like StructureMap in both the EntLib and the new WPF Composite client guidance/framework.  That's a huge deal in my book.  Just like the new MVC framework, the new WPF Composite client won't force a choice of IoC tool upon you.
    Frankly, I don't see anything to get all that upset about.  All of us StructureMap/Windsor/Spring.Net enthusiasts need to remember that there are unenlightened shops that simply won't use any OSS tools -- and Microsoft choosing to promote any one of the existing IoC tools as the one true path would start a geeky civil war.
  • My pick for altnetconf quote of the day

    From James Gregory:

    "...if we only code to what the lowest-common-denominator can do then we're never going to get anywhere. "

    The context of this quote is doing a rehash of the old DataSet versus anything else argument.  One pro-DataSet argument is simply that that's what our developers know.  It's also another take on the common ORM, IoC, and TDD just can't be cost effective or maintainable because our developers don't know that stuff issue. 

    If you have to have a mission statement for ALT.NET, I like this quote from the NYC ALT.NET summit this past weekend:  "raise the lowest common denominator for the .Net community."  If we really think that ORM, IoC, TDD and whatever else is valuable and more productive, let's get more people familiar with this stuff instead of compromising. 

  • TDD/BDD and Design by Contract: I don't really see any conflict between the two

    I found an interesting link today from Mario Gleichmann called Test Driven Development and Design By Contract - friend or foe?.  I've always been lukewarm toward Design by Contract (DbC).  Occasionally I'll run into claims from DbC enthusiasts that using DbC completely eliminates the need or desire for Test Driven Development and I'll start rolling my eyes.  That attitude stayed perfectly intact until I spent some time with Greg Young at DevTeach talking about spec#

    After learning a bit about spec# I can see plenty of value for DbC, but certainly not as a full replacement or even an alternative to TDD/BDD.  One way or another it's all about specifying the desired behavior and using some sort of automation to check that the specification is being satisfied.  What I envision is using DbC to efficiently knock down a lot of the boring problems like erroneously passing nulls around at compile time.  I would still use TDD/BDD to get to the interesting part -- the actual behavior of classes and methods.  Greg is claiming that having spec# would replace 2/3 of his unit tests with more declarative DbC style specifications inside the code with arguably a faster feedback loop than running NUnit tests.  All I can say is "cool."  Cutting down feedback cycle time is always advantageous.  Eliminating tedious imperative code with declarative specifications is definitely good.

    I'm not a fan of copious amounts of defensive programming being anywhere but externally facing API's.  I don't write a lot of unit tests checking for bad data coming into or out of methods because I don't see that activity as having a positive reward to effort ratio and I can't abide clutter in the code.  I haven't particularly recognized any real pain from not writing these unit tests, but if I did feel that pain, I'd rather just use DbC specifications in the code and get going with the more interesting work.

     

  • Spring loading your IoC Container

    Ayende has a post up this morning called Inverting Inversion of Control where he talks about registering services with an IoC container at runtime.  Ayende is specifically saying that this technique is useful for injecting services that you either can't control the creation of or simply want to construct in another way.  It's funny that he should post this today because I've been using this technique quite a bit the last couple months in my WinForms development.  I'm breaking open the StructureMap code to start a new release today largely to add a bit more support for this scenario.  To add to the discussion, I'll throw out an example of what I'm doing.

     

    Registering pieces of the ApplicationShell

    In StoryTeller and a couple of my applications at work the ApplicationShell (main form) has grown large and complicated.  It's become advantageous to treat various parts of the main form as separate services of the user interface and let all of them be driven by separate Presenters.  For the sake of consistency with the rest of the application and avoiding nasty Law of Demeter violations, I inject these little pieces of the main form into StructureMap so that StructureMap can instantiate other services that depend on these pieces through constructor arguments.  I could create all of these little user controls and TreeNode's via StructureMap and then call methods to attach them into the ApplicationShell later, but that quickly led to bootstrapping spaghetti code left and right.  It turned out to be much cleaner to use the design time support to place the children controls onto the ApplicationShell form, inject these children into StructureMap, and let StructureMap completely setup the Presenters that depend on these child controls through their constructors.

    When I start up StoryTeller the first thing that I do is bootstrap StructureMap's configuration.  The second thing I do is create the main ApplicationShell form.  After the child In the constructor function of ApplicationShell I call the method below to register some of the child controls of ApplicationShell into StructureMap:

            private void loadShellPartsIntoStructureMap()
            {
                ObjectFactory.InjectStub(typeof (IApplicationShell), this);
                ObjectFactory.InjectStub(typeof (IContentPanel), contentPanel);
                ObjectFactory.InjectStub(typeof (IHierarchyNode), hierarchyExplorer.HierarchyNode);
                ObjectFactory.InjectStub(typeof (IFixtureExplorerView), fixtureExplorer);
            }

    The "InjectStub()" method was originally put into StructureMap to allow you to override normal StructureMap behavior to push in stubs instead of the normal service during testing.  It does also function correctly in this scenario (in the forthcoming 2.1 version I'm going to add a new method called Inject<T>(T service) ).   Regardless of any other prior configuration, StructureMap will always return the instance passed into InjectStub(Type, object) whenever an instance of the specified Type is requested.  When any other class requests IContentPanel directly or through a constructor function, the "contentPanel" child of ApplicationShell will always be returned.

    Now, moving on to see how this works.  I generally use an ApplicationController class to govern the activation and deactivation of screens in the user interface.  The ApplicationController in StoryTeller has a dependency on both the IContentPanel (the tabbing container for screens) and the IHiearchyNode (the top most TreeNode in the navigation tree).  Since we've already injected the two little children into StructureMap, we can completely set up ApplicationController through its constructor.

            public ApplicationController(
                ICommandExecutor executor, 
                IContentPanel panel, 
                IProjectRepository repository,
                ITestEventPublisher publisher, 
                IHierarchyNode hierarchyNode)
            {
                _executor = executor;
                _panel = panel;
                _repository = repository;
                _publisher = publisher;
                _hierarchyNode = hierarchyNode;
            }
     

    As long as I create ApplicationController after the StructureMap bootstrapping and the creation of ApplicationShell, I'm ready to go.  Before I switched to the path of injecting the child controls into StructureMap I had a lot more one off bootstrapping code to push around the IContentPanel and IHiearchyNode controls.  By refactoring to the "injected children" mode I cut back on a lot of undesirable coupling and trimmed down some chatty interfaces. 

    One of my little maxims of programming is to strive to put everything a class needs into a constructor so that we know the class is ready to go as soon as it's created.  This little trick of spring loading the UI controls into the IoC container gets us closer to that ideal.

  • Alt.Net.UK has been announced

    Check it out here on Ben Hall's blog.  I won't be able to go, but I'm looking forward to reading the recaps from the other side of the Atlantic.

    The official website is http://www.altnetuk.com/

  • Do you really know where that code has been?

    Last week I did a talk at DevTeach called "Creating a Maintainable Software Ecosystem" (the slide deck is here).  On one of my slides I had the following bullet point:

    NEVER build and deploy from a developer environment

    Even though it showed up on the slide I don't think I got around to explaining why I don't like creating deployment packages on a developer workstation.  Yesterday someone pinged me wanting to understand why I say you shouldn't make official builds on a development workstation.  Why should I make it a standard that we don't do builds on a developer workstation?

    I'll start by telling some horror stories.  5 years ago I built my very last Windows DNA web application and left the company the following spring.  At the time our standard practice was to compile VB6 DLL's on a development workstation and check the build products into source control.  I would then write up instructions for our configuration management group to manually deploy the COM DLL's as part of any upcoming production push.  It worked exactly as well as you'd think.  Almost a year after I left the company and project I got a phone call from a former colleague.  He needed to make some changes to one of the COM DLL's, but when he downloaded the code out of source control a class was missing and the project wouldn't compile.  He was screwed.  It was worse than he knows because I think I made some last minute code changes in the actual production push that never made it into source control.

    On another project I was asked to redesign a problematic system.  I asked for the source code for the existing system.  Nobody knew where it was.  The original developer was a victim of a recent "Reduction in Force" and wasn't around to help.  Fortunately, someone thought to go check the original developer's old cubicle and found an ancient looking notebook computer in an unlocked drawer that had a copy of the code on its hard drive.  We think it was the code anyway.

    Sure, these are horror stories of incompetence, but if we'd had a policy forbidding production pushes originating from developer workstations and some level of repeatable builds directly from source control we could have headed off some serious problems.

     

    First Causes

    Before I even bother to talk about how and where I want the builds made, let's put out the end goals as I see them:

    1. Repeatable builds.  If anything should go wrong, and it will, can I quickly reproduce the build?
    2. I want to know the provenance of a build.  Where did it come from?  What exact version of the code is in there?  Is it free of foreign bodies of code?  When it comes time to troubleshoot production issues, will I know what code to look at?
    3. I don't want to screw up the production deployment.  Building is never as simple as just compiling, even for XCopy applications. 
    4. I want to know that the exact version of the code being deployed is the version of the code signed off by my QA folks

    If you build on the developer workstation, and especially if you build from your normal working directory, I think you run a significant of blowing all four points.  If your building from your source code on your box there's nothing to guarantee that all the code you're compiling against is both in source control and the proper version of the code.  It's just the code you happen to have on your workstation.  I don't care how conscientious you and your team is, you will flub up with source control from time to time. 

     

    Build on the Build Server

    My teams do official builds to testing and production on the build server as part of the CruiseControl.Net build.  One way or another, I like to have the CruiseControl.Net build put together a deployable package on each and every successful build and stash it off to the side somewhere easy to get to.  Ideally, I like to have the test deploys be something that can be manually triggered to deploy a given version in a single step by the testers themselves.  Why is this important?  Let's go back to our original list of first causes:

    1. Repeatable builds.  CruiseControl.Net runs an automated script with no manual intervention.  If the script works, I say we have repeatability.
    2. I want to know the provenance of a build.  CruiseControl.Net is pulling the code directly out of the master source control repository.  If there's anything missing, the build won't complete.  Besides, we want the master source control repository to be the single authoritative source right? 
    3. I don't want to screw up the production deployment.  All build steps should be automated.  Manual builds are time consuming, but more importantly, they can be error prone.  For example, several of my projects will ratchet up the tracing levels or inject stubs in development environments, but I'll use the NAnt build to guarantee that the correct configuration is used in production.  I want that configuration step to be automated.
    4. I want to know that the exact version of the code being deployed is the version of the code signed off by my QA folks.  See the following sections:

     

    Tracking Build Number with CruiseControl.Net and NAnt

    One of the first targets I add to the NAnt script of a new project is versioning support.  In the StoryTeller.build file for my StoryTeller project I have the following target:

      <target name="version" description="mark AssemblyInfo builds with the build number">
        <property name="assembly-version" value="${project.version}.0000" />
     
        <if test="${property::exists('CCNetLabel')}">
          <property name="assembly-version" value="${project.version}.${CCNetLabel}" />
        </if>
     
        <echo message="I'm running"/>
        <echo file="version.xml" message="&lt;version&gt;${assembly-version}&lt;/version&gt;"  />
     
        <echo message="Marking this build as version ${assembly-version}" />
        <asminfo output="src/CommonAssemblyInfo.cs" language="CSharp">
          ...
     
          <attributes>
            <attribute type="AssemblyVersionAttribute" value="${assembly-version}" />
            ...
          </attributes>
     
          ...
        </asminfo>
      </target>

    Pay attention to the bolded parts.  When the NAnt script runs it will create a new file called CommonAssemblyInfo.cs that contains assembly attributes to identify the product name and build version.  This file is linked to each and every binary in my solution.  As long as this target runs before the compilation I can embed the contents of the "assembly-version" property into the version number of each binary.  The "assembly-version" is created at runtime by appending the current "CCNetLabel" property to the project version.  Assuming the build is successful, I get a batch of binaries that can be clearly traced to a known CruiseControl.Net build.  The "CCNetLabel" is supplied to NAnt from CruiseControl.Net itself and wouldn't be available if you simply ran the StoryTeller.build file manually.  In fact, when I run the NAnt build manually all the binaries will be versioned (as of this writing) as "0.8.0.0000."  Seeing the four zeros at the end of the build tells me this is a local developer build.  In a real project that tells me that these assemblies are not to be trusted because I don't know where this build came from.

    Ok, that's nice.  You know what CC.Net build the assemblies came from, but how can you know exactly which version of the code in source control made up the binaries?  Simple, we just have CC.Net tag the source control with the build number after successful builds.  Fortunately, the CC.Net + Subversion combo makes this very simple.  Here's the snippet from the ccnet.config file for StoryTeller to do just this:

     

      <project name="StoryTeller"  queue="StoryTeller">
        <workingDirectory>d:\work\StoryTeller</workingDirectory>
        <modificationDelaySeconds>10</modificationDelaySeconds>
     
        ...
     
        <sourcecontrol type="svn">
          <trunkUrl>http://storyteller.tigris.org/svn/storyteller/trunk</trunkUrl>
          <workingDirectory>d:\work\StoryTeller</workingDirectory>
          <tagBaseUrl>http://storyteller.tigris.org/svn/storyteller/tags</tagBaseUrl>
          <tagOnSuccess>true</tagOnSuccess>
        </sourcecontrol>
     
        ...
        </publishers>
     
      </project>

    After each successful build, CC.Net will issue a command to Subversion to tag the current revision of the repository trunk as the CCNet build number.  At any time I can retrieve the exact version of the code matching the binaries by the tag number.  It's now trivial to retroactively create a support branch from a given CC.Net build.  Any fights over what code made it into the official build are relatively easy to solve by simply going to the repository browser.

     

    Removing Project Friction 

    The previous part talked about the mechanics of the build, but now let's talk over the workflow.  I want to be able to deploy code to testing and even production with minimal friction.  With a team of any size and embedded testers, I could easily be pushing code to the testers 3-5 times or more a day on average.  To do this effectively, I want to shut down the possibility of errors and miscommunication between myself and the testers.  Specifically, I'm concerned about these issues:

    1. We screwed up the push.  I hate getting bug reports that are caused by botched testing pushes.  100% automation of builds with environment tests baby!
    2. The testers tested the bug fix before the bug fix was deployed.  Don't waste the testers time.  When you fix bugs or new stories, you always tell the testers which build number contains the fixes and new features.  On the other side, the testers have to be aware of the current build number.  Make the build number obvious in some way.  Either teach them to check the assembly versions themselves, put the build number in some kind of "About" screen, or put the build number into the title bar.  However you do it, strive to cut down on miscommunication problems betwixt you and the tester.  "I thought you had already pushed that code" or "oops, you don't have the right code yet" comments need to become a thing of the past.
    3. I want to do the push fast and get right back to work.  By wanting to work iteratively in smaller steps I'm going to need to make far more pushes to testing.  I want them to be automated to spare my time.

     

    Closing Thoughts

    I find it more than a little ironic that traditionalists like to label Extreme Programming as irresponsible hacking, but yet I've learned far more about better configuration management practices from my XP experience than I ever did in a traditional software shop that was desperately chasing higher CMM levels. 

    We all want to be safe, know where things are, and generally stay under control.  I also want to go fast and get stuff done.  I don't want laborious configuration management practices holding me back and retarding my progress.  I never want the fear of the configuration management process to stop me from making the right technical decisions.  For all of these reasons and more, I strongly prefer using project automation wherever possible in place of fancy manual work processes.  The case in point for me was a situation last spring where we hacked up some code because it was just too freaking hard to go through the client's database change management process.

    I think this issue is another point in favor of blurring the lines between project roles.  In my old traditional environment we had a separate configuration management team and the developers had nothing to do with this process other than filling out paperwork.  As I discussed in my horror stories, I was able to color within the lines of their official process and still screw up the configuration management royally.  In a small Agile shop us developers were responsible for configuration management.  We implemented Continuous Integration and automated builds ourselves.  We actually had far, far better control over what code was where inside our environment because change management was baked into the day to day development.

     

    The morale of the story.  If you have a request for a blog topic, you're not in a hurry, and I already have the content sitting around, I will happily write up a blog post for you.

  • A Microcosm of Agile Design

    Last week at DevTeach I did a talk entitled "How does Design get done on an Agile Project?"  In the talk I tried to explain and defend the way that we design software on Agile/Lean projects.  Among the issues that I talked about were:

    1. Return on investment.  How to wrest the maximum business value out of the development effort spent in delivery.
    2. Doing design continuously is more responsible than big upfront design.
    3. Delaying technical complexity and decision making until the proper time.
    4. Enabling the future by creating maintainable code rather than trying to anticipate the future
    5. You aren't gonna need it -- YAGNI!  Why YAGNI is important and valid.  How to call YAGNI today without eliminating tomorrow's efforts.
    6. How does continuous design as practiced by Agile teams affect the composition and roles of the development team? 
    7. How the desire for continuous design affects our design choices

    In order to jump straight into these subjects I used the following scenario taken from real life at one of my former employers shortly after I left. 

    A software team is building a new ASP.NET application with substantial business logic and processing. Do you:

    1. Create a web service for the business logic and make the web application call this web service - even if the web service is running in process with the web application.
    2. Build and deploy the business logic in process with the web application as a simple set of library calls.

    The architect (a friend of mine) with oversight responsibilities was adamant that the team chose option #1.  I wasn't there, but I would have vehemently argued for option #2 (partially just to argue with the architect truth be told).  I do have a pretty good idea what that architect was thinking and the rationale behind his decision making.  Let's take a look at his reasoning first, then talk about why I think option #1 is wrong and option #2 is the more responsible choice.

    Why the Web Service?

    The web application was the one and only consumer of the business logic and processing exposed by the web service today, but what if some other project needed that functionality tomorrow?  This enterprise had any number of large scale enterprise projects get effectively derailed by the difficulty of integration with many of their legacy systems.  In particular, the inventory system was notoriously hard for integration.  Because the company was a large manufacturing company, almost every significant business automation flow had to touch the inventory system, so the difficulty with integration was a large drag across the enterprise.

    The problem with the old inventory system was that all the business logic was tightly embedded into the user screens written in a proprietary language.  When we did projects that required automated interaction with the inventory system we had two basic choices: 

    1. Use the screen emulation software from the vendor to drive the UI automatically
    2. Rewrite the functionality of the screens in some other language, in this case PL/SQL stored procedures

    Neither choice is very desirable.  You could say that everybody involved with creating enterprise solutions there had some scar tissue is an understatement.  To prevent this problem from happening with the new ASP.NET application, the architecture team was demanding that the business layer be exposed and called by web services that would be open to the rest of the world.

    Some of the desire for web services was SOA utopia run amok.  The central architecture team was making a very large bet on SOA throughout the enterprise.  Their philosophy was to expose all business functionality and processing via SOAP services until they reached a critical mass where Business Processing Management and Business Activity Management would be possible.  The infamous "build it (services), and they will come" SOA strategy.  The SOA vision was compelling and set the architect's heads a-spinning with visions of grandeur and colored their thinking.  But was it really paying off?  Would the new services really be useful down the road?*

     

    Why I think my old Architect Buddy was wrong

    I understand the rationale behind my old architect buddy's reasoning, but I'll put forth a couple reasons why I think the web service approach was dead wrong.

    It was more expensive.  The simplest way to deliver the ASP.NET system was to develop the business logic as libraries that ran in process with the ASP.NET application.  Think about that for a minute.  If you built a web service you'd have:

    1. An extra set of build scripts for the second web application, and the build scripts would take longer to run.  That's friction.
    2. Additional security infrastructure between the UI and the backend, especially if you want the web service to be publicly open
    3. Automated and manual testing between the UI and the web services would take longer to run than the corresponding in process solution.  Don't discount how much drag that would introduce into development productivity.
    4. Extra code complexity with the web service contract and web service proxies
    5. More complicated deployment scenarios

    In addition, I'd say that the usage of a web service would make continuous design harder.  If I'm developing both layers in process I can handily evolve the interaction between the UI and the backend by using automated refactoring's with ReSharper.  If I have that kind of "reversibility," I can shave off development time by making simpler assumptions now and add complexity if I absolutely have to later.  With the web service I have to spend more time upfront getting the web service contract right because making evolutionary changes to the web service is harder than using ReSharper on the in process model.  If the web services are really going to be publicly exposed for reuse, I have to spend even more time polishing the service contracts because once it's published I can't easily change my mind.  My advice is to err on the side of reversibility as much as possible.  In this particular case that means bypassing web services in favor of an in process model.

    Reversibility is a real issue.  Because a mistake in the web service contract is so much more difficult and costly to change once it's being used, the rightful tendency is to do more rigorous analysis upfront.  That analysis is going to cost us time.  If I know I can back out or modify a design later, I can do the simple thing to deliver value sooner.  In the case of the web service with only once consumer, an Extreme Programmer would "call YAGNI" to permanently table the construction of the web service until it was absolutely necessary.

     

    The Economic Rationale

    All arguments have to be grounded in some sort of economic rationale, and this case is no different.  Going with the in process model is more economically valuable for two reasons:

    1. Opportunity cost.  The extra mechanical cost of building the web service can be applied instead to creating other features that will provide business value now.  Delivering the web service now creates no immediate value.
    2. It potentially gets the business feature into production earlier.  There isn't any return on investment until something is deployed.  By deploying some features earlier we also start the ROI meter earlier.
    3. The extra complexity would slow down feature delivery throughout the project

    One of the ways that an Agile team strives to deliver a good return on the investment is by eliminating waste.  We don't need a web service so we don't build it.  As simple as that.  The way that I think about it is an analogy from manufacturing.  Exercise "pull" design and architecture instead of "push" architecture.  Don't build infrastructure because you think it'll be valuable later.  Build only the infrastructure that you need for the business functionality on the table.  When we try to get clever with upfront frameworks, abstractions, and infrastructure we can often miss.  We're speculating on what's going to be valuable instead of working off of hard facts.  Remember that no matter how good you are in predicting what you'll need, you're requirements can easily get changed underneath you.  Sometimes the speculation will pay off and other times it'll make things worse.  In the formulation of Extreme Programming I think that Kent Beck made an implicit assumption that the percentages are against speculative design paying off most of the time, so you should practice simplicity every time until forced to do more complex things as a way to be more efficient.

     

    Tomorrow comes

    You did things the way that I said to and built the business logic as simple libraries running in process with the ASP.NET application.  Tomorrow is here and it turns out that some new initiative does indeed need access to our business logic and a web service seems to be the logical choice.  The fears of our enterprise architect have been fully realized - or have they?  Is the business logic hopelessly coupled to the ASP.NET application like he feared would happen, or is it perfectly economic to just expose a new web service on top of the existing business logic and use it as is?  It depends on how we built the system.

    Agile design isn't all dessert and no vegetables.  We saved time and effort on the first project by forgoing the web service we didn't need then, but tomorrow always comes.  The key to working iteratively and incrementally is following good design principles all the time.  If we built the ASP.NET with a good separation of concerns so that the business logic is orthogonal to the user interface, we should be able to put a new headless web service right on top of the existing business logic.  In effect, we just need to build a new remote facade for the business logic and expose this to the outside world. 

     

    But it's cheaper to build it now!

    As a consultant in decidedly non-Agile clients I'm constantly fighting off the notion that it'll be cheaper to just "build it now while we're in there."  It's a tempting thought and it's partially caused by people with overwhelming memories of bad code and painful regression testing experiences.  I'm making the argument that the cost of building the web service should remain constant no matter when we choose to build it assuming that we're following good design principles (separation of concerns, orthogonality, Single Responsibility Principle, etc.).

     

    Team Composition

    As I've tried to convey, my old architect buddy was acting quite rationally according to what he knew and thought.  He wouldn't have bought my argument about the web service being inexpensive to add later because he flat out didn't trust the development team to build the ASP.NET application with a good architecture.  He probably had the design chops to get it done himself, but he wasn't on the project himself.  By forcing the business logic into a web service he thought that he could mandate to the development team some semblance of separation of concerns.  The actual development team needed some developers or architects dedicated to the project that had the ability to create a good design.  It's not good enough to have a supervisory architect drop by for a couple hours at the beginning of the project.  Technical design strength should be applied at the point of attack.

     

    It would have been wrong anyway

    There's one last reason not to build the web service upfront.  It would have been wrong anyway.  In the absence of any other concrete use cases for the web service we would have been either tailoring it to the ASP.NET client or making assumptions about how future callers would be using the web service.  In my opinion, the chances of getting it wrong are far too high to make building the web service upfront all that valuable.  The future projects that need to consume this business logic may need an entirely different usage than the original application.  We're better off waiting until the actual needs arise in order to create the exact web service that we need.  Building the web service now is acting far in advance of the Last Responsible Moment.  Assuming a good design, we haven't eliminated the possibility of building the web service later and we'll know much more about the proper shape of the web service at a later date.  There's no justifiable reason to build the web service now.

    So how about we just do more analysis upfront so that we can make some educated guesses on the future usage?  Now we're allowing ourselves to be vulnerable to analysis/paralysis.  That extra analysis is going to delay the delivery of the initial functionality.  And it'll still be wrong.

     

    One other last thought about the Web Service

    Let's say there was some perfectly valid reason for building the business logic into a web service from the very beginning.  We've got a reusable web service!  Cool!  Except it isn't exactly what the next project needs.  Part of the functionality is usable, but other parts need to be different.  If the actual business logic is built granularly with the Single Responsibility Principle we can reuse the pieces that we need and write all new code for the new functionality.  If the business logic was created as one big chunk and tightly coupled to the service contract of the web service, we're screwed.  My only point here is that the design of the innards of the web service needs to follow the same design principles as we would in endeavoring to create a solid application structure.  I think the SOA enthusiasts too often overlook this issue or somehow believe that a design is "loosely coupled" just because there's a well defined service boundary in there somewhere.  To really be Agile in your design and delivery efforts, almost all production code needs to be built with solid design principles.

     

    Anyway, that's my take on the scenario.  What do you think?  What did I miss?  Wanna argue?

     

     

    * Part of the web service craze was caused by the fact that all of us architect types had a provision in our yearly performance plan that we would be responsible for creating at least one new web service each year.

  • Microsoft P&P is building a new IoC/DI tool -- and I'm okay with that

    In case you haven't already seen the announcement or Ayende's denouncement, the Patterns and Practices team is going to build a new Dependency Injection Application Block as part of the next wave of the Enterprise Library.  As the primary builder of one of the Open Source IoC/DI tools you'd expect me to be indignant about this, but I'm not.  I was certainly peeved about ObjectBuilder a couple years ago, but this time is different.  Partially it's because I've always assumed that they'd get around to this at some point, so it's not any great shock.  I'm not particularly upset because of a couple reasons:

    1. The P&P team reached out to me for input on their new DI tooling.  I also know that they're talking to some of the other teams as well.  I still think the P&P guys could have, and should have, done this with ObjectBuilder.
    2. They said the magic words:  we're going to make it pluggable so you can swap out the base implementation for StructureMap, Windsor, or Spring.Net.  That's a huge acknowledgement of the success of these tools from the P&P team.  Exactly what we've been waiting for from these guys for a long time. 
    3. They might build something better or at least innovative.  There's absolutely no doubt in my mind that I could build a better StructureMap from scratch today after 4 years of actually using IoC tools.  They get to start at the end of that experience curve.  Of course, if mainstream developers start to use IronRuby, IoC rapidly loses its relevance, but let's not get side tracked here.
    4. All of us consultants sooner or later get forced to work for a company with a strict no OSS policy.  Since I really don't care to write an IoC tool from scratch (and I really don't care for ObjectBuilder), it's nice to have something usable from MS itself that I can sneak in.  Of course, in reality I'd just download the StructureMap source code and replace "StructureMap" with "NameOfCompany.IoC."
    5. I think Enterprise Library could be a lot more usable if they really embrace Dependency Injection throughout.  There are pieces of EntLib that I think would be useful, but I don't want to bring in all the dependencies or wrestle with the Xml configuration.  Using DI for configuration generally means that your classes are less coupled to some sort of underlying Xml configuration.  I think applying Inversion of Control to configuration (I don't go get my application settings myself, somebody else will do that for me in my constructor) will make the EntLib easier to digest.
    6. The newer P&P framework and factory thingies can be built with IoC/DI from the ground up.  If we're going to restrict ourselves to static typed languages for the time being, I want enterprise systems and frameworks built with IoC.  Even more importantly, I can use the tool of my choice that I'm already familiar with for configuration of my services.  That's a big win.

    CodePlex notwithstanding, Microsoft's poor attitude and relationship to Open Source Software efforts on the .Net platform has had a negative impact on the community at large.  That out of the way, let's give P&P a chance here.  They did come out and ask for involvement from us.  We've been whining that they don't include us or take feedback early on.  Here's our chance.  Instead of throwing rocks at them, let's try to participate in a helpful manner.  Maybe we can set Microsoft and us up to avoid more Entity Framework debacles.

     

     

     

    As for the competition angle between StructureMap/Windsor/Spring.Net and DIAB, think of the branding.  Calling anything the Something Application Block and putting it next to the original OSS tools is a lot like putting the cheap knockoff cereal boxes right next to Lucky Charms in the grocery store.  Doesn't Dependency Injection Application Block sound a lot like a generic cereal to you?

More Posts

This Blog

Syndication

News

All opinions expressed here constitute my (Jeremy D. Miller's) personal opinion, and do not necessarily represent the opinion of any other organization or person, including (but not limited to) my fellow employees, my employer, its clients or their agents.

About Me

"Best Of" Compendium

StructureMap (Dependency Injection for .Net)

StoryTeller (Supercharged Fit)

Build your own Cab

TestDriven

MVP