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

February 2006 - Posts

  • On Rapid Application Development and Creating Maintainable Code

    [EDIT] Before I start, let me make this very clear.  RAD is not evil, it doesn't kill, and for a very common class of applications it is both appropriate and efficient.

     

    Some of my CodeBetter neighbors have been posting and arguing about the relative merits of Rapid Application Development.  There was also quite a bit of internal discussion, part of which was to stop being so opinionated in the blog posting and get back to technical posts.  Let me get this one out of the way, then I'm back to coding.

    What is this "RAD" you speak of?

    Part of the problem is a mismatch in meaning and attention.  There's a bit of a false dichotomy out there that you're a "drag'n dropping" Mort or some sort of aberrant Einstein writing everything in Assembler code.  By no means would I ever recommend that you dump the visual designer for WinForms to create the view code, but I'd strongly recommend against using data aware widgets if there's any business logic involved.

    My definition of Rapid Application Development (there is a full blown process called Rapid Application Development out there that sounds a lot like Agile without the enabling practices like TDD and CI) is the reliance on visual designers and coding wizards to create software with minimal coding, often with data aware screen widgets.  It's a perfectly good way to create little bitty applications that merely provide a thin wrapper around relational database data, and there's a tremendous value out there in being able to slap together these kinds of applications in a hurry.  I got my start in programming doing just this very thing for little applications that my engineering team used.  You could even make the claim that RAD enables business users to build their own applications (that's a horror story for a different day). 

    However as soon as any kind of nontrivial business logic is called for, RAD quickly shows its limitations.  Creating an application by dragging and dropping data aware UI widgets onto the visual designer with business logic embedded in event handlers in the screens every which way is a maintenance nightmare.  Event driven code is one of the nastiest things in the world to debug and understand.  Neal Ford of "No Fluff, Just Stuff" fame already has a good post on the limitations of RAD:  Technology Snake Oil, Part 2: RAD.  I'll sum it up for you with one quote:  "RAD development doesn't scale well".

    Software without Coding, or More Productive Coding

    Let's back up to first causes and look back at the ever present perceptions of software development that brought about Rapid Application Development in the first place. 

    • Software development is too hard and fraught with risk and failure

    I feel like there has been two diametrically opposed approaches to improving software development efficiency.  In one camp is the people trying to create ways of doing software development without coding.  Thus drag n'drop UI wizards ala VB6 and PowerBuilder, the CASE tools fiasco of the 80's, and the current Model Driven Architecture approach.  I'm extremely dubious about MDA (but if it succeeds I'll jump on board) and downright disdainful of Executable UML, but time will tell.  At this point I think we can safely say that pure drag'n drop RAD approaches are only effective for simple applications and move on to approaches that lead to sustainable development.

    The other school of thought is to try to make coding easier and more reliable. Languages like the .Net languages and Java are "softer," they accept changes much more readily than C++ or other older languages.  Dynamic languages like Smalltalk, Python, and Ruby may end up being much better on this score.  Test Driven Development does more than anything I've ever used to create code that is easy to change, both because of the comprehensive unit test coverage and the loose code coupling that TDD requires.  Automated refactoring tools make coding simpler by reducing the mechanical cost of improving and changing code.  Design patterns provide design shortcuts.  Code smells and anti-patterns help us steer away from possible maintenance issues later.

    Looking forward, I'm interested in seeing how Domain Specific Languages, Language Oriented Programming, and Intentional Programming impact software development.  I'm also reading a lot lately from folks looking way back to functional languages like Lisp to create a more productive coding experience by working at a higher level of abstraction.

     

  • Pragmatic viewpoints on SOA

    From DonXML,

    Intro to Web Services - It's All About the Message - NYC Code Camp

    Writing WSDL by hand seems about as efficient as writing IDL by hand back in the COM days.  Every time I'm involved with web service creation we concentrate on creating Data Transfer Object classes to represent the message and let the .Net framework worry about WSDL.  It makes evolutionary design of web services and TDD with mocks a lot easier too. 

    Regardless of your style, you should never, ever couple your internal business classes to the messaging schema and vice versa.  Unless you don't care about maintainability anyway.

     

    From Udi Dahan, Common SOA Pitfalls as well.  What he describes seems pretty dumb to me, but I've seen the exact same thing proposed a couple years ago at a former employer. 

  • Getting off of VSS and onto Subversion

    Steve Barron asked for a pointer to a VSS alternative.  My team uses the open source Subversion system for source control and we're very happy with it.  The best thing to say about it is that it almost never gets into the way like VSS can.  Continuous Integration is certainly much smoother with Subversion.

    For a Subversion client we use a mix of the TortoiseSVN client that integrates into Windows Explorer as a shell extension and the Ankh plugin for Visual Studio.Net integration.  I like Ankh, but I could honestly live without any IDE integration.  Subversion uses an optimistic locking scheme so multiple users can simultaneously edit the same file.  It sounds a little scary at first, but the merging isn't really that big of deal and the convenience factor outweighs the negative results.  Just think what a pain in the neck it was with VSS constantly fighting over who had the project files.  The Subversion clients are smart enough to recursively find new files all at one time, so the client is a lot easier to use from outside the IDE than the VSS client is.  Plus I've found Subversion to be much faster than VSS.

    There is a conversion script to migrate a VSS repository to SVN at http://vss2svn.tigris.org/.  We didn't have much luck with it because of some VSS corruption issues, but a friend of mine was able to use it successfully.

    I'm not fond of CVS because of some bad experiences in the past, but it's also a viable choice.

  • Mapping Enumerations with NHibernate - and hooray for open source unit tests

    This is just to make a permanent note to myself.

    We were using NHibernate this morning to map a class that had an enumeration type property.  By default NHibernate will store the enumeration integer value in the database.  Since this particular table will be viewed directly by support we wanted to persist the enumeration string name.  Here's how you do it (example is taken from NHibernate itself):

    Create your class that has an enumeration property:

    	public class EnumStringClass
    	{
    		private int _id;
    		private SampleEnum _enumValue;
    
    		public EnumStringClass()
    		{
    		}
    
    		public int Id
    		{
    			get { return _id; }
    			set { _id = value; }
    		}
    
    		public SampleEnum EnumValue
    		{
    			get { return _enumValue; }
    			set { _enumValue = value; }
    		}
    	}
    
    	public enum SampleEnum 
    	{
    		On,
    		Off,
    		Dimmed
    	}
    

    Next, you need to create a subclass of the NHibernate NHibernate.Type.EnumStringType class for your custom enumeration type.

    	public class SampleEnumType : NHibernate.Type.EnumStringType
    	{
    		public SampleEnumType() 
    			: base( typeof( SampleEnum ), 10 )
    		{
    			
    		}
    	}
    

    In the NHibernate mapping you need to override the type mapping to use your new derived EnumStringType subclass. The subclass will handle the coercion from strings to enumeration.

    		<property type="NHibernate.Test.TypesTest.SampleEnumType, NHibernate.Test" name="EnumValue" column="enumc"></property>
    

    Unit Tests are Documentation

    There is an important underlying point here.  The NHibernate documentation isn't all that you'd hope for and Google didn't really help much either.  It didn't matter because as soon as I fired up the NHibernate code I quickly found the relevant unit test that demonstrated exactly what to do.  Intention revealing unit tests are one of the best forms of technical documentation, and by definition, they can't get out of synch with the code.  One of the best things you can do to enable the people that follow you in the code is to make your unit tests as clear as possible in the specification and usage of the code.

  • Be Careful Mocking Concrete or Abstract Classes

    I had a question today about whether you could just mark methods as virtual on a concrete class so they could be mocked, or if you should just extract an interface and mock that.  In a statically typed language like C# the safest answer in my book is to extract an interface.  Here's a bit of a reprint from an earlier post on this subject with some additional highlighting:

    I would urge a certain level of caution in mocking an abstract class or a concrete class.  For best results my advice is to only mock interfaces to avoid unwanted side effects.  It is certainly possible to mock an abstract class, doing that leads to some side effects that effectively negate all of the advantages of a mock object.  Dynamic mock object tools like NMock or Rhino Mocks can only override virtual methods.  This might not be so much a problem in other languages, but with the .Net languages all methods are non-virtual by default.  This means that some of the behavior that you were trying to remove from the test with a mock is still there.  The dynamic mock libraries work by using Reflection.Emit to create a dynamic proxy on the fly for the requested interface or abstract class.  In the case of an abstract class the dynamic mock can only intercept virtual members and even worse, the constructor function of the superclass will probably be exercised. 

    http://codebetter.com/blogs/jeremy.miller/archive/2006/01/10/136407.aspx

     

     

  • Amen to that, Brother Haack

    Phil Haack has a great post that's near and dear to my heart, Better Developers Through Diversity.

    He makes a hugely important point that we should never look at Microsoft as the ultimate source of software development knowledge.  I work in a .Net shop, but if you look at how we approach development and the tools we use, you'll spot much more influence from the Agile Java community than Redmond or the VB6/ASP community.  Something that Haack mentions in passing is the number of open source tools that often provide a better or more appropriate alternative to Microsoft's solutions (though my team is about *this* close to ditching log4net because of the versioning problems).  Frequently an open source tool simply plugs a gap in Microsoft's tooling.  For example, Microsoft still does not have any true equivalent to CruiseControl.Net for continuous integration.  If you want to do CI you're still better off using an open source tool, but you'll never know that if you only read and follow MSDN.

    I'm going to channel Scott Bellware here and say that a lot of the advice Microsoft has given out through the years has been harmful.  The closed loop conversations between Mort and the parental oversight at Microsoft has certainly resulted in reams of unsupportable code.  Other development communities have multiple web framework choices that encourage a good separation of concerns in their web applications.  We have drag n' drop tools to create one tier web applications.  Microsoft has a great story for doing RAD development, but not for creating larger, maintainable code bases.

    Microsoft's .Net, VS, and Team System teams aren't conspiring against us to turn us into RAD zombies.  They're giving us what they think we want and need.  It's our responsibility in the community to reflect the need and desire for sustainable development tools and techniques.  Even though I'm bypassing Team System and VS2005 (not touching it until ReSharper 2 is released) for now, they're definitely a step in the right direction, the unfortunate TDD misinformation aside.

    I think this might be changing a little bit in our favor, but overall the intellectual center of software development is rarely in Microsoft development circles.  It might just reflect my development interests, but I can't think of a single canonical book on software development that contains anything more than cursory attention to the .Net platform.  Most of the example code I see in books is written in Java, with C++ a distant second, and C# trailing even farther behind.  The meaty software design books written for  a .Net audience are usually derivative works of the original Java-centric works.  My point here isn't to say the Java, Ruby, or Python communities are superior to ours (because I seriously doubt it is), but rather to second Haack's plea to pay attention to other development communities.

     

    One last thing, in the year 2006 it's almost irresponsible to be using Visual Source UnSafe.

  • More Thoughts on Model View Presenter

    This is a follow up to my post on the Model View Presenter pattern with ASP.Net to address or clarify some of comments from the earlier post.  I apologize for being so slow in answering the comments.

    The Presenter is a GoF Mediator

    Carlton commented that the Presenter class looks a lot like the Gang of Four "Mediator" pattern.  He's absolutely right.  Something to keep in mind when learning to apply design patterns is that a class or group of classes can easily be an instance of more than one pattern.  In this case "Presenter" or "Controller" is just a more specific name for a class within a larger structural pattern.

    Unit Tests Aren't Enough

    MVP certainly makes unit testing easier, but don't forget to create white box integration tests as well.  The unit tests should remove most of the problems, but only integration tests will reveal all of the defects in the code.  Conventional wisdom says to write automated tests just under the skin of the user interface.  Our experience with writing integrated FitNesse tests against the Presenter classes with live services but a stubbed view has been positive.  You could also write integrated tests that use the real view and the Presenter but mock or stub the backend to fully test the presentation.  Sooner or later you'll have to do a full end-to-end test, but I think it's vastly easier to diagnose and fix defects with smaller white box tests first.

    Exposing the Model

    Harris Boyce's colleague didn't like the view class having a reference to the actual Model (WorkItem) object in the following:

    	// Abstracted interface of the WorkItem View screen
    	public interface IWorkItemView
    	{
    		// Packs the user input into a new WorkItem class
    		WorkItem WorkItem{get;}
    
    		// Sets the values in the dropdown list for the WorkItem assigned to user
    		string[] AssignmentList {set;}
    
    		// Sets the values in the dropdown list for the WorkItem categories
    		string[] CategoryList {set;}
    	}
    

    It's a valid objection, but let me try to clarify what I was worried about here.  One of the ways to bog down with the MVP pattern is to make the view interface way too chatty with far too many getters and setters like this:

    	public interface IWorkItemView
    	{
    		string AssignedTo {get; set;}
    		string Category {get; set;}
    		string Description {get; set;}
    		string Priority {get; set;}
    		string Comments {get; set;}
    		
    		/* More properties */
    	}
    

    In this case the Presenter starts to become way too busy with pushing data back and forth between the view getter/setters and the Model objects. One of the strengths of .Net user interface development is the strong support for databinding.  I know it's far from perfect, but it still saves some grunt work and frees the Presenter up to concentrate on flow logic.  I can understand some apprehension about exposing a Domain Model object to a presentation class, so here's some alternatives to consider:

    • The "Model" doesn't have to be a Domain Model class.  You can create a custom Data Transfer Object (very appropriate if there is a web service in the mix) or even a lowly DataSet to be the dedicated "Model" and keep your business logic fully encapsulated from the presentation layer.  We actually create DataSet's from our domain classes for this very purpose.
    • I'm not entirely sold on it, but take a look at Martin Fowler's Presentation Model pattern as an alternative to MVP.  I've used it successfully for complex TreeView operations and the typical "sort/filter/page" operations in every grid reporting page.  I'll post more on that soon.
    • You can happily use more than one Presenter per View.  One Presenter might handle the low level mapping from the Model to the View and input validation while a second Presenter deals with the flow logic and the backend services.

    Constructing Deep Object Graphs

    Michael asked how we handle the creation and assembly of deep dependency chains (but he answered his own question).  The presenter needs a reference to the view and the backend services, which probably have dependencies of their own.  Here's a representative case.  A Presenter class has a dependency on IView, IUserInformationStore, and IServiceFacade.  The concrete class ServiceFacade that implements IServiceFacade has its own dependency on IDomainRepository

    	public class Presenter
    	{
    		private readonly IView _view;
    		private readonly IUserInformationStore _userInformationStore;
    		private readonly IServiceFacade _service;
    
    		public Presenter(IView view, IUserInformationStore userInformationStore, IServiceFacade service)
    		{
    			_view = view;
    			_userInformationStore = userInformationStore;
    			_service = service;
    		}
    	}
    	
    	public class UserInformationStore : IUserInformationStore
    	{
    		public UserInformationStore(string domainControllerName){}
    	}
    
    	public class ServiceFacade : IServiceFacade
    	{
    		private readonly IDomainRepository _repository;
    
    		public ServiceFacade(IDomainRepository repository)
    		{
    			_repository = repository;
    		}
    	}
    
    	
    	public class DomainRepository : IDomainRepository
    	{
    		private readonly IDataSession _session;
    
    		public DomainRepository(IDataSession session)
    		{
    			_session = session;
    		}
    	}
    
    	public class DataSession : IDataSession
    	{
    		public DataSession(string connectionString)
    		{
    			
    		}
    	}
    

    I'm a huge fan of using Inversion of Control/Dependency Injection to promote looser coupling and better testability, but the responsibility of attaching dependencies has to go somewhere.  We obviously don't want the ASPX page that creates the Presenter class be responsible for creating the entire object graph of dependencies like the sample below.

    	public class View : Page, IView
    	{
    		private Presenter _presenter;
    
    		public View()
    		{
    			// Absurd example
    			_presenter = new Presenter(this, 
    				new UserInformationStore("TheNameOfTheDomainController"), 
    				new ServiceFacade(
    					new DomainRepository(
    						new DataSession("a connection string"))));
    		}
    	}
    

    I would suggest one of two solutions.  The simpler, but less powerful solution is to use "greedy" testing constructors to attach mock objects in tests, but use a default no argument constructor when a class is created in production code.

    	public class Presenter
    	{
    		private readonly IView _view;
    		private readonly IUserInformationStore _userInformationStore;
    		private readonly IServiceFacade _service;
    
    		// "Greedy" unit testing constructor only!
    		public Presenter(IView view, IUserInformationStore userInformationStore, IServiceFacade service)
    		{
    			_view = view;
    			_userInformationStore = userInformationStore;
    			_service = service;
    		}
    
    		// Default constructor
    		public Presenter(IView view) : this(view, new UserInformationStore(), new ServiceFacade())
    		{
    		}
    	}
    

    The second and more powerful solution is to use a Dependency Injection tool like StructureMap to create the object graphs and attach all of the dependencies. My colleagues frequently snicker that my answer to most design challenges is to use StructureMap, but this case is exactly what I built it for. 

    	public class View : Page, IView
    	{
    		private Presenter _presenter;
    
    		public View()
    		{
    			_presenter = new Presenter(this);
    		}
    	}
    
    	public class Presenter
    	{
    		private readonly IView _view;
    		private readonly IUserInformationStore _userInformationStore;
    		private readonly IServiceFacade _service;
    
    		// "Greedy" unit testing constructor only!
    		public Presenter(IView view, IUserInformationStore userInformationStore, IServiceFacade service)
    		{
    			_view = view;
    			_userInformationStore = userInformationStore;
    			_service = service;
    		}
    
    		// Default constructor
    		public Presenter(IView view)
    		{
    			_view = view;
    
    			// Use StructureMap to create the object graphs for UserInformationStore and ServiceFacade
    			// with all of the necessary connection string and domain controller configuration
    			_userInformationStore = (IUserInformationStore) ObjectFactory.GetInstance(typeof(IUserInformationStore));
    			_service = (IServiceFacade) ObjectFactory.GetInstance(typeof(IServiceFacade));
    		}
    	}
    
    

    Using StructureMap to wire up the dependencies allows for far more flexibility to mix and match the application configuration.  For example, by my team uses StructureMap to switch our web application from using certificates for authentication to a stubbed security mode on our developer boxes by a simple change in the StructureMap configuration.  We also use StructureMap to turn encryption off for easier debugging, stubbing the database, and switching from an installation where the application runs on two physical tiers in production mode to a testing mode where the entire application runs inside a single AppDomain for easier debugging and faster tests.  Here's a more detailed example of using StructureMap. I've mostly used StructureMap for creating pluggable MVP architectures with WinForms applications, but I don't see why it wouldn't be applicable for web applications as well.

  • Once and for all, email is not a good medium for communication

    http://www.wired.com/news/technology/0,70179-0.html?tw=rss.technology

    And try Alistair Cockburn's classic article on the effectiveness of various forms of communication:  http://alistair.cockburn.us/crystal/articles/cpanfocisd/characterizingpeopleasnonlinear.html

    We're a little satellite office and we suffer from some occasional communication gaffe's related to email misunderstandings.  Body language doesn't come across over email and it's very easy to offend somebody in an email.  Nothing beats face-to-face communication, but I think you're better off picking up a phone to discuss anything that could be contentious rather than relying on email. 

    We struggled a little bit when our one and only tester was at a different office.  Email is a bad enough, but depending on a bug tracking tool for developer-tester communication is borderline insane.  The clincher for me was the time I stumbled over some hidden tab in the bug tracking website and found a really whiny, passive-agressive comment about the developers not giving the tester enough information.  No phone call with questions or even an IM, just a pissy note hidden away in the bug tool.  Grrrr.

    One of my former employer's had the bright idea to outsource a lot of coding overseas, but keep all of the testing and analysis in Austin.  Let's see, developers and testers spread out over about 12 hours time zone difference on two continents and only talking through documents and email.  That sounds like a great recipe for total failure.  When I piped up and said "this isn't going to work" the manager in charge of the offshoring just looked at me funny. 

     

  • Being careful with project codenames

    I have a silly superstition that any project with a cool, cutesy, or grand-sounding codename is doomed to failure.  We're breaking my own rule by calling a new infrastucture subsystem "Firefly" (we're all Firefly/Serenity fans) and talking about a new consolidated dashboard for supporting our messaging workflow called "Highlander."  We actually caused our senior management some consternation when they started to see "Firefly" in our story names on our iteration plans.  The codename doesn't even remotely correlate to the business driver behind our project, and the manager's alarm is perfectly understandable.  They were afraid we were off on some silly techie tangent, instead of what they cared about (business solution).  Hopefully we've managed to alleviate their concerns by communicating that Firefly is a prerequisite infrastructure requirement for the larger project.

    We're keeping the Firefly name internally, but I think we're going to be a little more careful about using the term.  I suggested making the official name the "[Company Name] Communication Foundation," but that went over like a lead balloon.

     

    And I'm still mad about Wash.

  • Apoplexy

    Like many historically Microsoft development shops we struggle with grossly inappropriate usage of stored procedures (every single MS development shop I've worked in or consulted for had this issue to some degree or another).  Part of our "rules engine" varies by configuring the name of a stored procedure per customer for a certain data validation.  The sproc's are edited and deployed outside of any kind of disciplined, consistent process.  We *really* want to get rid of these things, but in the meantime, it's spawning some great internal quotes. 

    "If we can't get rid of the stored procedures, can you build us a 'Stored Procedure Writer' tool?" - Yes, we'll call it Query Analyzer

    "They're just stored procedures, they can't do any harm" - My jaw hit the floor.  It's a running joke in the office now.

    "It's easier for my guys to write stored procedures than have to edit code somewhere" - that one might have been true in the past, but it was a sign in bright pink neon letters that the code *really* needed some serious love.

     

     

    Now listening to and torturing my colleagues with:  What's new Pussycat? by Tom Jones

  • OO, TDD, and Agile processes are all good, but better get the basic things right too

    I mostly blog about more or less abstract topics like Agile development processes, design patterns, and TDD strategies because it's what I'm mostly interested in at the moment.  I definitely think these topics are important, but it's often doing the basic things poorly that make a system unreliable and hard to modify and support.  There are some underlying activities that we have to do to make a system function well, and some of these things aren't really described very well by the Agile canon. 

    Case in point from a conversation I had with a colleague at lunch today, the legacy systems that my team centers around share a database that lacks some logical referential integrity checks and uniqueness constraints.  We were groaning that the database schema allows a motley collection of orphan records and duplicate data that is making our lives harder.  That's the kind of activity that I would consider so intrinsic to building software that I wouldn't even think to talk about it, but the effect of the missing database constraints has caused us some difficulties.  I wouldn't say that all of us need to be experts, but I think every single enterprise developer needs to have some level of comfort with referential database theory.

    Here are some other basic things that I think fall through the cracks a bit if you're not paying attention:

    1. Database indexes.  Too much, too little, or just the wrong indexing will drag your code down
    2. The ACID rules and transactional boundaries.  I think the mass majority of systems I've seen do a bad job of governing their transactional boundaries.  I'm not talking about "look those jokers didn't use the perfect transaction isolation level there," I mean zero transactions at all.  When things blow up and go wrong, will your code and database end up in an invalid state?  Will you lose data?  Drop messages?  It's not just important for database development either, you also need to consider the interaction with any kind of external system or messaging infrastructure as well.
    3. Database archiving.  Databases can get awfully slow when table sizes get bigger.  I watched a batch processing system implemented by a very large and prominent consulting company (here comes the script kiddies!) become almost useless in its 6th week of production due to severe performance problems.  The culprit?  A very poor database design from the software vendor was compounded by the lack of a database archiving strategy.  I got to lead a team that built a replacement a couple months later.  Our system archived records the second that the workflow was completed.  Our throughput was 2 orders of magnitude higher.
    4. File system archiving.  Weird, nasty things happen when servers run out of disk space.
    5. One of the things I love about .Net over the "Set objEverything = Nothing" nonsense in VB6 is garbage collection, but it isn't magic.  Gotta make sure that unmanaged resources are cleaned up.
    6. Database connection discipline.  One of the many reasons I think we all need to stop writing so much ADO.Net code by hand is to eliminate the possibility of screwing up database connection usage.  I've been told this isn't as big an issue with the newer Oracle and Sql Server versions as it was 5 years ago, but I wouldn't bet the farm on the database being able to handle a couple thousand orphaned database connections.
    7. This is probably rare, but I had to fight with an XP zealot PM over this one time.  If you're going to use some sort of offline pessimistic lock, you need to have some sort of mechanism to clear out stale locks.  Things will go wrong.
    8. Adequate tracing and auditing - that is easily accessible and useful to the production support folks.  In Agile process speak - remember that the production support organization is an important stakeholder in your project.  In my case we're the support as well, so I think we'll care a bit about this one.  On the other hand I detest code with too much tracing because I think it obfuscates the code and generates too much noise to be useful. 
    9. Coding standard.  Consistency is the hobgoblin of little minds but the hallmark of a smoothly running software team.  This is called out very specifically by XP as a core practice, but I think my company has done a poor job of developing and following a coding standard in the past. 

    I've seen Agile teams screw themselves by taking a too literal approach to the XP ideals by putting on the blinders and only focusing on the functional requirements from the customer.  There are additional technical requirements that could be termed a "cost of doing business" expense for building a system.  You have to fulfil these requirements to make the system viable.  It's our responsibility as developers and architects to communicate these issues to the project manager to insure these purely technical stories are adequately accomodated by the iteration and release plans.  Now, what to do when the PM doesn't listen to you?  Um, run away?

  • Test Driven Development with ASP.Net and the Model View Presenter Pattern

    DISCLAIMER:  This was written all the way back in Feb. 2006 when we MVP with ASP.NET was the only real alternative.  I thank you for the interest, but there have been better articles written since, and I'd strongly recommend looking at MonoRail or Ruby on Rails or the new MVC framework for ASP.NET if you're interested in maintainable, testable web applications. 

     

    A friend of mine was asking me a while back about ways to apply the Model View Presenter (the “Humble Dialog Box”) pattern to ASP.Net development to promote easier unit testing of the user interface layer.  Two weeks and a major case of writer’s block later, I finally finished the post.  I wrote a blog post last spring describing the usage of MVP (“The Humble Dialog Box”) with WinForms clients, but web development in general and ASP.Net in specific comes with a different set of challenges. 

     So what are the problems with ASP.Net that MVP Solves? 

    If you asked me to name the single most important principle in all of software design, regardless of language, platform, or programming paradigm, I’d say “Separation of Concerns” in a heartbeat.  For the sake of maintainability, each piece of code should have one and only one distinct responsibility.  Even in the initial act of coding I only want to work on one problem at a time.  I want to look at the business logic code without seeing database infrastructure code or HTML construction intermingled with everything else (a huge pet peeve of mine). 

     

    The traditional approach for building maintainable user interface code is to separate the typical concerns of a user interface with the Model View Controller (MVC) pattern.  Unfortunately, ASP.Net is optimized for Rapid Application Development, not for creating maintainable code.  A common criticism of the ASP.Net development model (and ASP classic before that) is that it does not enforce or even encourage a clean Model View Controller separation.  Many ASP.Net applications seem to be a jumble of data access code, HTML markup, and business logic, but it doesn’t have to be that way.  By itself, the “code-behind” model in ASP.Net does not do enough to create a good separation of concerns.  Plus it’s difficult to get code-behind code into unit tests. 

     

    My preference is to use the Model View Presenter pattern to structure ASP.Net code to create maintainable and testable solutions.  I think of MVP as just a flavor of MVC, but it’s worth stating the differences.  The central fact of MVP architectures is that the “view” is a very shallow wrapper around the actual screen.  Unlike most traditional MVC implementations, the view classes are entirely passive.  The Presenter classes are the active classes that are responsible for initiating the view processing. 

     

    The big challenge in unit testing ASP.Net code is the tight coupling to the ASP.Net runtime.  The web controls are very tightly bound to the underlying HttpContext and the web event pipeline, making the user interface code difficult to work with inside an xUnit test harness.  I’ve seen people successfully create fake HttpContext objects in memory, but it really amounts to a hack to test existing legacy ASP.Net code.  You can also use tools like NUnitASP or Selenium to test web applications, but those tests are integration tests, not unit tests.  The best thing to do in my experience is to isolate as much of the functionality as possible away from the ASP.Net runtime into classes that can be easily tested inside of NUnit, and that’s exactly what the MVP pattern does.  Putting this another way, I would suggest that any piece of code that isn’t directly manipulating web controls or parts of the web page should be moved out of the code behind classes and into another class.

     

    A lot of .Net literature describes the “Code-Behind” class as the MVC controller.  I think this is dead wrong.  The code-behind is View code, period.  For best results, the presenter should never have any reference to any type in the System.Web namespace. 

     Class Structure of MVP 

    The basic concept is simple.  Like the classic Model View Controller pattern, you divide the responsibilities of the web page into separate classes.  In specific, we want to isolate as much of the functionality as possible away from the ASP.Net runtimes.  The functionality of a screen is divided into three parts:

     
    • View classes:  Displays data and relays user input and events to the Presenter. 
    • Presenter classes:  Coordinates communication between the view and the backend service or business layer and is responsible for user interface logic
    • Model classes:  The data being displayed or worked on in the screen.  This is could be either a business domain object(s), a data transfer object, or a lowly DataSet.  The Model is also the state of the user session. 
     A Simple Example 

    Let’s dive into some code.  You’re creating a new web screen in a custom workflow application for people to enter and assign “WorkItem’s” to other people.  The screen will have dropdown lists for both the WorkItem category and the assigned user.  In no particular order, let’s start with the Model class.

           public class WorkItem      {            private string _category;            private string _assignedTo;             public string Category            {                  get { return _category; }                  set { _category = value; }            }             public string AssignedTo            {                  get { return _assignedTo; }                  set { _assignedTo = value; }            }             /* Other stuff */      } 

    The next step is to create an abstracted interface to represent the View class.  Note that we’re not yet working with any System.Web classes, web pages, or web controls.  The IWorkItemView interface encapsulates all interaction with the ASP.Net runtime.

           // Abstracted interface of the WorkItem View screen      public interface IWorkItemView      {            // Packs the user input into a new WorkItem class            WorkItem WorkItem{get;}             // Sets the values in the dropdown list for the WorkItem assigned to user            string[] AssignmentList {set;}             // Sets the values in the dropdown list for the WorkItem categories            string[] CategoryList {set;}      } 

    The backend business and workflow system is accessed by a Façade class with an interface called IWorkItemService.  The backend might be a call to a web service, a remoted object, or an in-process call.  All we’re concerned with in the user interface code is how the presenter interacts with the interface of the service. 

           public interface IWorkItemService      {            void ProcessWorkItem(WorkItem entry);            string[] GetAssignmentListForCategory(string category);            string[] GetCategoriesForRoles(string[] roles);      }  

    The lynchpin of the MVP pattern is the Presenter class, WorkItemPresenter.  In this particular user story there is a requirement that the categories displayed in the dropdown on the screen are limited by the role membership of the logged in user.  There is another requirement that the values in the dropdown for the assigned to user are dependent upon the selected category.  The logic that determines the topic and category list is completely isolated from the web page machinery for easier unit testing and maintainability.

                 public class WorkItemPresenter      {            private readonly IWorkItemView _view;            private readonly IWorkItemService _service;             // Use "Dependency Injection" to attach the dependencies for the view            // and service.            public WorkItemPresenter(IWorkItemView view, IWorkItemService service)            {                  _view = view;                  _service = service;            }             public void Initialize()            {                  string[] categoryList = this.determineCategoryListFromUserRoles();                  _view.CategoryList = categoryList;            }             public void Submit()            {                  WorkItem item = _view.WorkItem;                  _service.ProcessWorkItem(item);            }             public void ChangeCategory(string categoryName)            {                  string[] assignmentList = _service.GetAssignmentListForCategory(categoryName);                  _view.AssignmentList = assignmentList;            }             public string[] determineCategoryListFromUserRoles()            {                  // Examine the roles on the IPrincipal object and query IWorkItemService for                    // the possible categories                   return new string[0];            }

          }

     

    The key things to note here are that the WorkItemPresenter class only depends on the abstracted interfaces for IWorkItemView and IWorkItemService.  The WorkItemPresenter class can now be unit tested with mock objects inside of the NUnit.  WorkItemPresenter is just a “Plain Old CLR Object” that can run and be tested completely outside of the ASP.Net process.  This is strictly personal preference, but I like to build and unit test the Presenter class(es) before I even start to create the ASPX or ASCX’s. 

            [TestFixture]      public class WorkItemPresenterTester      {            private DynamicMock _serviceMock;            private DynamicMock _viewMock;            private WorkItemPresenter _presenter;              [SetUp]            public void SetUp()            {                  _serviceMock = new DynamicMock(typeof(IWorkItemService));                  _viewMock = new DynamicMock(typeof(IWorkItemView));                   _presenter = new WorkItemPresenter((IWorkItemView)_viewMock.MockInstance, (IWorkItemService)_serviceMock.MockInstance);            }

          }

     

    Lastly, we’ve got to actually create the web page itself.  I’m using a UserControl as an example, but it could easily be a web page instead.  The WorkItemView UserControl implements the IWorkItemView interface.  It has a reference to an instance of the WorkItemPresenter class with which it communicates.

           public class WorkEntryView : UserControl, IWorkItemView      {            private WorkItemPresenter _presenter;            protected DropDownList assignmentDropdown;            protected DropDownList categoryDropdown;             // The UserControl has a reference to the presenter class            public void AttachPresenter(WorkItemPresenter presenter)            {                  _presenter = presenter;            }             private void Page_Load(object sender, EventArgs e)            {                  categoryDropdown.SelectedIndexChanged += new EventHandler(categoryDropdown_SelectedIndexChanged);            }             #region Web Form Designer generated code             public WorkItem WorkItem {…}              /// <summary>            /// Fill the dropdown list for the possible assignments            /// </summary>            public string[] AssignmentList            {                  set                  {                        assignmentDropdown.Items.Clear();                        foreach (string assignment in value)                        {                              assignmentDropdown.Items.Add(assignment);                        }                  }            }             public string[] CategoryList{…}              // The UserControl immediately relays the user selecting a new Category to the             // presenter object.  The presenter will decide what to do next            private void categoryDropdown_SelectedIndexChanged(object sender, EventArgs e)            {                  string category = categoryDropdown.SelectedValue;                  _presenter.ChangeCategory(category);            }

          }

     

    In this case I have an ASPX page that contains a WorkItemView control.  In the Page_Load event of the ASPX page I create a new instance of the WorkItemPresenter, attach it to the user control, and call Initialize() on the presenter class to start the display.

           public class WorkItemPage : System.Web.UI.Page      {            protected WorkEntryView workEntryControl;             private void Page_Load(object sender, System.EventArgs e)            {                  WorkItemPresenter presenter = new WorkItemPresenter(workEntryControl);                  workEntryControl.AttachPresenter(presenter);                   presenter.Initialize();            }

          }

     State Management 

    A big challenge in any complex web application is session state.  Think of a typical online store like Amazon.  On one hand the logic involved in maintaining the session state is important and certainly deserving of isolated unit tests.  If I was coding for Amazon, I would certainly want to be writing unit tests around maintaining the state of the “shopping cart” when users select and remove items.  The state of the shopping cart will affect the way the page is displayed and the navigation logic after the page.  That’s exactly the kind of logic that is hard to test if you don’t loosely couple the logic from the HttpContext. 

     

    On the other hand, a lot of web screens are only reachable from a series of user actions on previous pages.  The checkout screen can only be reached after working through previous screens.  My first TDD project was an ASP.Net project that had some web pages like this.  We were using NUnitASP to write automated tests.  I didn’t know much about mock objects or MVP (or MVC), so the only way to test my pages and all of their logic was to write tests that progressed through multiple screens just to get to the point where I really wanted to test.  Those tests were laborious to write and very brittle.  Smaller tests are always easier to write and read.  What I’ve learned since then is to either create an abstraction around the state management that the presenter classes depend on, or have another class push the state into the presenter.  I touched on this strategy in an earlier post on mock objects.

     

    At some point you do have to test the actual web screens, and it’s a great thing to have automated testing on the user interfaces.  It’s just a theory, but I’d think seriously about creating intermediate integration tests that use stubs for all the backend and state management to isolate the web views.  You can use a dynamic service locator like StructureMap to substitute stubs for the services with configuration, or create separate ASPX pages to host the UserControl’s and presenter classes, but use the stub objects instead.  You could then write much simpler Selenium tests to verify granular parts of the user interface in isolation.  You’ve got to maintain loose coupling between the user interface code and the backend to pull it off though.  As usual, testability and good design practices are very closely aligned.

     User Input Validation 

    I’ve had a couple of conversations over the last year on the proper place for the user input validation.  I still think you have to take advantage of the built in validation controls in the ASP.Net views if you can do it in a declarative way.  Any kind of validation more complicated than “this field is required” or numeric validation should probably be put into some sort of presenter class or the model classes.   By and large, you want any kind of code that spawns bugs under automated unit testing.  Input validation definitely meets that criterion. 

     

    Something I like to do is use what I think of as “Embedded Controllers.”  You need to be cautious in using the MVP pattern to keep the presenter classes from getting too big with too many responsibilities and preventing the bidirectional view-presenter communication from being way too chatty.  I try to alleviate the presenter “blob” anti-pattern by moving validation logic into other controller classes that are used from within the views.  I also like to move functionality like filtering, paging, and sorting to these secondary controller classes.  It’s just a way of keeping the size of the classes down and maintaining class cohesion. 

     Easier NFit/FitNesse Testing 

    We’ve had some success with writing our FitNesse tests directly against the Presenter classes.  We have been making the Fixture class for the screen implement the interface for the view and passing itself into an instance of the Presenter, then letting an ActionFixture drive the screen.  It’s a lot simpler than trying to drive the tests against the screens themselves.  Our sister office is using FitNesse to drive Selenium tests to great effect, but they’re doing it because they don’t have a suitable service layer to test business logic through.  These Fixtures look something like this:

     using System;using fit; namespace WebSample{      public class DataEntryFixture : Fixture, IWorkItemView      {            private string[] _assignments;            private string[] _categories;            private WorkItemPresenter _presenter;             public DataEntryFixture()            {                  _presenter = new WorkItemPresenter(this, new WorkItemService());            }             public WorkItem WorkItem            {                  get { throw new NotImplementedException(); }            }              public string[] AssignmentList            {                  set { _assignments = value; }            }             public string[] CategoryList            {                  set { _categories = value; }            }             public string SelectedCategory            {                  set                  {                        _presenter.ChangeCategory(value);                  }            }      }

    }

       Related Concepts 
More Posts