RAD kills. . . software – level 200

I figured the title would get someone’s attention.  I’d like to share this piece of art that I created. 

By now, everyone has been educated about the dangers of cigarettes and
tobacco.  Cigarettes can be addictive and even deadly.  While
they may be soothing in the short-term, they ultimately cause
irreparable damage. 

I’d like to compare this to the RAD style of development.  RAD is
quick and satisfies in the short term.  Sometimes it’s amazing how
many features can be created just by some dragging and dropping. 
You could whip out an entire system in a week.  It’s almost too
good to be true.

But what about next month, and the month after that?  The attempts
at enhancing that system are futile.  You desperately try to get
some productivity out of the RAD approach, and you may be able to slap
on a new feature quickly, but when you have to modify or enhance an
older feature, you can’t get the same satisfaction.  It takes
forever to debug through to see what’s really happening.

RAD is quick, but it incurs huge technical debt.  RAD is like
consumer credit.  You can have it now, but will you really have
time to clean it up later?  If you buy that big-screen HDTV now,
will you really have $3000 extra dollars lying around later?  RAD
can be very tempting, but in the end, it leads only to death. . . of
your software.  At some point, the only recourse will be a total
rewrite.  At that point, will you use RAD again for the rewrite or
use another _sustainable_ process?

Orthogonal to RAD is sustainable development:  Creating interfaces
at key areas of your system to ensure flexibility.  Adequately
testing your software to ensure you don’t break old features when you
introduce new ones.  Ensuring your software never becomes legacy
code, etc.

RAD isn’t the answer.  Creating sustainable software takes work
and is not for the faint-hearted.  It takes good software (dare I
say?) engineers – critical thinkers – disciplined craftsman.

I hope you have enjoyed the satire of this post, but satire can’t exist without a grain of truth.

Palermo’s rules for Pairing (pair programming, that is) – level 200

Palermo’s rules for Pairing:
Pair programming is a great way for real-time code review and collaboration.  Chances are that the end goal will be reached more quickly by working with a partner when writing software.  This might sound counter-intuitive at first if you think that 2 people splitting the work would accomplish the goal faster.  What actually happens very often is that, without communication, work is duplicated, or people code is slightly different directions.  I’m won’t pander to the benefits of pair programming too much, but when pairing, here are my rules:

  • Talk while you code.  Explain the thought process that is leading you to type what you are typing.
  • Play the TDD game.  Have one person write a test, then pass the keyboard so that other other person makes the test pass.  The person who gets the test to pass decides if he wants to write a test next or pass the keyboard.
  • If both programmers aren’t on the same page for the task, whiteboard it to form a common understanding.
  • Commit the code to source control after each task is completed.
  • When working in a team of more than 2, rotate pairs so that knowledge flows.
  • If one of the programmers is a clear novice on the task, have him drive first until he’s no longer the novice.
  • Don’t steal the keyboard.  If you know of a better way to accomplish a task, explain your thought process so that your partner understands the better way.
  • Defer driving.  If you are completely comfortable with the code that is about to be written, pass the keyboard to your partner.  Writing the code will benefit him more than you.
  • Communicate.  It’s tought, and there will be disagreements.  No one has overruling authority.  If you haven’t convinced the other of your viewpoint, you haven’t communicated it effectively.  If it’s important, then everyone on the team must understand why.
  • Communicate.
  • Communicate.

A Microsoft provider _is_ a singleton – always – level 200

I’ve done quite a bit with Whidbey and .Net 2.0 since Beta 1 hit in mid-2004.  I was one of the early adopters that submitted bug reports as well, and I’ve tech editted several .Net 2.0 books, and I’m mostly impressed with .Net 2.0, but there are some aspects that I’m dissapointed with (you can read past ones on my blog).

I’ve been wrapping some of my existing code with the built-in providers in ASP.NET.  I’m finished with the MembershipProvider, but all I needed was 4 of the methods, and the abstract class has over 20.  What a waste.  I’m in the process of wrapping my code with the SiteMapProvider, and that one looks more civilized.

Microsoft has touted it’s Provider pattern as a way to configure application behavior.  They’ve touted it as a custom mix of Strategy and Plugin.  It’s true that you can change the configuration file, and you’ll hook up a different provider, and the behavior of the application will change.

What’s not widely known is that _every_ provider is a Singleton.  There is no getting around it.  The biggest implication of this is that where before, only few had to worry about writing thread-safe code, now even the hobbyist has to be aware of threads when creating a provider.  There is not a way to configure them away from being singletons, either. 

Using them with ASP.NET is the biggest concern because every request runs on a different thread.  Handlers are per-thread, but IHttpModule(s) have AppDomain scope just like providers.  What this means is that providers are not pluggable components. . . they are services and must be treated as such.  They are entities that will serve multiple customers.  Each customer doesn’t get his own instance of the provider, but one instance is shared for the life of the application.  I’d prefer to have one instance per use. 

Early on in the Beta cycle, Rob Howard had the same thoughts as me:
“This is a disastor waiting to happen. We you have an API that is
funtionally wrapped up into a package a static methods (I know the Role
Provider class isn’t static, but it’s access is) you have a service. . . ” 4/16/2004

You can verify my facts here by reading this article on MSDN (search for “thread”).

Austin .Net User Group hosting an MSDN Code Camp March 4th – level 000

What: Austin MSDN Code Camp – register at www.adnug.org

When: March 4, 2006 – 8:30 AM – 5PM

Where: St. Edwards professional learning center, Austin, TX

NOTE:  3 Code Camp speakers are from CodeBetter.com

An MSDN Code Camp is a free
local conference for developers and by developers.  We, as a community are the speakers as well
as the attendees.  See the Code Camp
Manifesto for more information:  http://www.bostondotnet.org/codecamp/default.aspx/CodeCamp/CodeCampManifesto.html

Austin Code Camp is looking for ways to make its
first MSDN Code Camp the best it can be. 
The secret is you! This is an Austin
developer community based event that requires both speakers and attendees. The
goal of the Code Camp is to provide an intensive developer to developer
learning experience that is fun and technically stimulating. The primary focus
is on delivering programming information and sample code that can be used
immediately.
The
event is free and all slides, manuals and demo code are provided
free!  Every attendee will receive a free lunch courtesy of
Microsoft, free t-shirt, free programming book from Wrox, free 1-hour
gift certificate to CyberJocks, and other goodies.  CyberJocks
will even have an XBox gaming room set up at lunch.  This event is
open to all, and is going to be great!

This one-day camp is hosted
at the St. Edwards professional learning center. The Code Camp will contain 1 –
1.5 hours sessions on topics the local community values; these session depend
on the speakers and attendees.

Sessions up for voting now:

Jeremy
Miller                                     
Code Smells
Scott
Bellware                                    
Test-Driven Development Techniques
Jeffrey
Palermo                                   
Pragmatic ASP.NET 2.0 (which features do I need?)
Jeremy
Miller                                     
Dependency Injection – What is it, and what is it good for?
Scott
Bellware                                    
Domain-Driven Design Essentials
Cody
Powell                                       
Writing Maintainable, Multi-threaded Code
Scott
Bellware                                    
C# 3.0 and LINQ
Terry
Meyer                                       
Intro to CSS for .Net Developers
J
Sawyer                                          
Introduction to Windows Workflow Foundation
Eric
Pollitt                                      
Error Management in SQL Server 2005
Steve
Donie                                       
CruiseControl.NET – basic to advanced
J
Sawyer                                          
Building Activities for Windows Workflow Foundation
Blake
Caraway                                     
Smart smart-client architecture
Joe
Celko                                         
Trees in SQL
Ray
Houston                                       
Expanding ASP.NET
Chad
Myers                                        
Designing Extensible Applications
Anil
Desai                                        
Automating Development and Testing Through Virtualization
Paul
Jones                                        
Fault Management – Performance Monitoring

Resharper 2.0 build 215 is much better than 214. It may be worth the risk – level 200

I tried out Resharper 2.0 build
214 (alpha), and it wasn’t stable enough for me to work.  There
were the known hanging problems every time you turned around, and I had
to uninstall it.

I’ve just installed build 215, and it appears that a lot of the bugs have been fixed.  I still use Resharper 1.5 with VS 2003, but with my VS 2005 projects, I missed the quick shortcuts for refactoring and code generation, so I’m risking the alpha.

I’m not uninstalling this one.  215 is “good enough” right now to
boost my productivity.  2.0 has NUnit test-running capability
through a UI widget, but I find that I still prefer the crude text
output of TestDriven.Net.

Bottom line:  If you are very used to Resharper 1.5, and you are
working with VS 2005, give build 215 a shot.  It’s working for
me.  P.S.  Remember to turn off VS intellisense.

Using source control can’t prevent conflicting changes – level 200

For those of you who use source control (and it should be everyone), you know the title of this post to be true.  Source control is just a technology, and no technology makes all problems go away.  In my previous post about software builds, I received a comment about locking checkouts and check-in conflicts.  Rob was particularly interested in whether I check in project and solution files.  The answer is YES.  I check in everything.

If you use VSS, you use the check-out/check-in paradigm.  In this paradigm, someone checks out a file, and it is unavailable until they check it in (much like a library book).  VSS does have the option for shared checkouts so that checked out files are locked against change, but most VSS users I know use locking and are afraid of two code files merging.

Subversion, the SCC system I prefer, uses a different paradigm.  To get the latest source, you would check out a repository or a branch of a repository.  The “Check out” step only happens once when setting up the working copy.  You always have the source checked out, but it is never locked.  If you need updated source from a team member’s changes, you issue the “Update” command.  When you are ready to push some of your changes to the SCC server, you issue a “Commit” command.  Every update is a merge from the source of record into your working copy, and it preserves any changes you may have made to a file while retrieving changes to the rest of the file.  Every commit is a merge of your change into the repository.  Every code move is a merge.  No code file is every locked against change, and everyone can work at once.

VSS users may become afraid of making a change to the same lines of code that another is changing.  This is where you have a communication problem.

SCC systems _cannot_ compensate for communication within a software team.  Communication is essential to working as a team, and if someone is doing a major refactoring, he should communicate with the rest of the team that some big changes are coming through the next time they update.  At the end of the day, the team should coordinate commits so that each commit is verified by the automated build before another is allowed.  This keeps you from committing to a broken build.

You may work with a distributed team, and your job is much harder because you don’t have the benefit of others with you in the war room.  You should still be constantly communicating over IM and telephone.  You must overcome that communication barrier.

In software, communication is key.

Break the dependency on HttpContext in order to test web functionality – level 300

HttpContext.Current is very useful, and it’s easy to sprinkle website code with it.  The bad side effect is that code that calls HttpContext.Current cannot be run in a test harness.  This is a big problem.  This post will show how to test code that needs HttpContext.Current.

The key is to break the dependency on HttpContext.Current.  By breaking the dependency, we can run our code in a test harness (like NUnit) and verify that it’s working correct (test harnesses are also great for debugging).  To start breaking the dependency, consider the following code we have:

        public string GetLoggedInUserName()
        {
            return HttpContext.Current.User.Identity.Name;
        }

This code dives right into the ASP.NET API, and code that depends on this method will be impossible to test.  To break this dependency on HttpContext.Current, we have to know what we really need.  We need the user name of the currently logged in user.  We are pulling this from the IPrincipal object.  We’re going to strip out this code and put an interface in it’s place:

    [PluginFamily(“Default”)]
    public interface ICurrentHttpContext
    {
        IPrincipal Principal { get;}
    }  

Next, we need to have a way for the original class to find a class that implements this interface for runtime.  We’ll use StructureMap for the dirt-simple linking through attributes:

    [Pluggable(“Default”)]
    public class CurrentHttpContext : ICurrentHttpContext
    {
        public IPrincipal Principal
        {
            get { return HttpContext.Current.User; }
        }
    }

Now we need to modify the original class with a testing constructor and a default constructor for dependency discovery:

    public class MyThingy
    {
        ICurrentHttpContext _context;
 
        public MyThingy(ICurrentHttpContext context)
        {
            _context = context;
        }
 
        public MyThingy()
        {
            _context = (ICurrentHttpContext) ObjectFactory.GetInstance(typeof(ICurrentHttpContext));
        }
 
        public string GetLoggedInUserName()
        {
            return _context.Principal.Identity.Name;
        }

    }

Notice here that we have a default constructor that asks StructureMap for the right implementation of ICurrentHttpContext, and for a unit test we have the constructor that accepts a mock instance.  This example shows that it is very easy to break a dependency on HttpContext.Current.  We can continue to use the fantastic services of HttpContext.Current while keeping our codebase testable. 

A software “build” is a lot more than just compiling the solution – level 200

Many developers don’t use source control and don’t use any automated tools.  This is extremely inefficient and troublesome.  Those on teams are forced to use source control in an effort to share the latest code with all members of the team.  In the source control environments, there is a tacit agreement not to commit any code to the repository that will break the build.  If the build breaks, it hinders the velocity of the other developers on the team because they cannot move on while the build is broken.

What does “build” mean?
Some folks use the term “build” to mean compile, and that is incorrect.  On the teams that use no automated tools, the compile might be the only step in their build process, but the two are still different.  The “build” is a process of taking the source of a software system and making it ready for deployment.  Some teams will manually compile the source and stop before deploying to a development environment.  These teams are short-changing themselves because the only feedback they’ve obtained about the current bits is that there are no syntax or linking errors.  There is no verification that any part of the software functions as intended.  Next, they may manually perform some steps to get all the bits and configuration in order to deploy the system to a development environment.  Then after some manual testing, they’ve obtained some level of feedback.

Let’s compare the above with an Agile build.
Here are some steps that are often performed in the build process of an Agile team – these steps are always automated so they run fast and are repeatable:

  • update latest code _and dependencies_ from source control.  (automated process will get latest code from the SCC repository)
  • compile solution (standard compile and link)
  • copy application files to test location (output binaries moved to location to prep for automated testing)
  • run automated unit tests. (automated tests produced through TDD or otherwise – give immediate feedback on the state of the system)
  • automated environment setup to prepare for an integrated test of the system
  • run integration tests. (gives even more feedback that the integration points of the system are functioning correctly – might include a database)
  • run regression tests (if you have them – verifies that all past functionality is still working as before – this is a type of integration test)
  • tag source control with build number if successful (only tag successful builds – discard unsuccessful ones)
  • Notify development team members of success or failure

Some teams add more steps depending on their needs, and some teams don’t have integration or regression tests suites yet.  Each build process should be developed by the team and tailored to the system.  The above are some of the more common steps that Agile teams include in a build process.

The point of an automated build process is to transform the current code into a working system and get feedback on the current quality as fast as possible.  If the entire process is fast, you will run it often and obtain feedback often.  If it’s slow, you won’t do it often.  The only requirement for the developer is to start the build.  Many Agile teams even automate that step by having a program kick off a build after every commit to the SCC repository.  That process is called “Continuous Integration”. 

At the end of a build, the team should be confident that if they deployed these bits to an environment, it would work.  There still may be bugs discovered, but they are confident that old bugs haven’t resurfaced and the system works at least as good as it did on the last build.  The extra testing steps in the build process ensure that the state of the software is always moving forward.  Without these steps, developers have no way of knowing if a change broke an existing feature.

Feedback is key in a build process.  The team should decide what steps can be added to the build process to generate as much feedback as possible.  My team recently inherited a system with a build duration of 25 minutes.  This is way to slow for us, and our initial goal is to reduce that duration to 10 minutes.  We’ll be able to do this by emphasizing fast unit tests more and doing away with some of the really slow integration tests (that have delicate, cumbersome data setup scenarios).

Tools my team uses in our build process:

  • Subversion (source control)
  • CruiseControl.net (build runner and tagger – keeper of the builds)
  • CCTray (system tray notification of successful or failed builds)
  • NAnt (Xml scripting format to describe steps to be run during the build)
  • NUnit (automated test harness)
  • .Net SDK (includes compiler and linker)