Release retrospective on extreme programming practices – level 300

Tomorrow, my team will make a software release that’s been in the works
since the end of January (2.5 months of work).  We’ve been using exteme programming
practices, and I’ll lay out the good, the bad, and the ugly as I look
back on the release.  First, here is a rundown of some things we
have been doing:

  • Source control with Subversion
    Every developer also receives email notifications of every commit to
    source control.  Each developer is responsible for reviewing
    commits.
  • Continuous integration with CruiseControl.Net.  Every time code is committed to source control, CC.Net runs our automated build that is based on NAnt
    Each developer receives a success or failure notification in his
    CCTray.  Broken builds are not acceptable and must be fixed
    immediately.  Code cannot be checked into source control while the
    build is broken.  Our build runs unit tests, integration tests and
    acceptance tests as well as creating a deployment package that’s used
    for the install.
  • Automation.  We automate everything.  For example, we
    have 8 development databases, and when the database scripts are updated
    in source control, all 8 databases are dropped and recreated from the
    changed scripts.  Builds of components are propogated to
    components that depend on them.  Installation of the latest build
    on the dev and test environment is completely automated allowing our
    tester to pull the latest build with the click of a button. 
  • Test-driven development (TDD)
    – we drive the design of our classes through unit tests.  The
    byproducts are a loosely-coupled design and a large battery of unit
    tests that are run continuously with every build.
  • Pair programming
    All production code is written by a pair of developers.  We have
    single tasks too (like tweaks to the CC.Net build, etc), but all new
    code and code changes are written by two developers.  We use VNC
    for pairing because it allows us more comfort by having our own mouse,
    keyboard and display even though we are working on a single workstation.
  • Collective code ownership
    We don’t have a concept of a single person’s code.  If we need to
    change some code, we change it.  No need to consult someone for
    “permission”.
  • The simplest design that will work
    Not the simplest design that will compile.  “Work” is defined by
    the customer.  We will defer longer-range designs because in
    practice we know that code written for 6 months down the road will
    likely be wasted work because in 6 months, the customer will decide to
    go in a different direction.  If not, it’s just as easy to add the
    same code 6 months from now.
  • Constant improvement.  We are constantly improving the
    system and the way in which it’s tested.  We have an idea wall
    (whiteboard) with a list of items we try to squeeze in that will allow
    us to go faster.
  • Iterations
    We use 2 week iterations.  We define and execute work two weeks at
    a time.  The customer is allowed to reprioritize every two
    weeks.  We know change is a part of software engineering, so we
    don’t try to fight it.

So now, I’ll run down the good, the bad, and the ugly:
The good:

  • We finished a week early.  Our automated testing and
    installs really paid off by allowing us to move very quickly. 
    From the time we changed some code, a new build could be on the test
    environment within 30 minutes (after being confirmed by all automated
    tests passing).
  • Very, very few bugs.  Because of the heavy emphasis on
    automated testing, bugs are squeezed out of existence.  The only
    place where bugs creeped in were places where we missed an opportunity
    for an integration test or a small feature overlooked.  The code
    with tests had absolutely no bugs.
  • Easy deployment.  Because of our emphasis on automation, our
    system installs on development and test servers, and it’s super easy to
    use the same process for deployment to our hosted servers. 
  • No deathmarch at the end of the release cycle.  We used a
    sustainable pace throughout the release, and we avoided a last-minute
    firedrill to make a date.

The bad:

  • It was hard.  To maintain the sustainable pace, we worked
    hard all day every day.  It was mentally tiring because of the
    discipline required to work at this level of efficiency.
  • It makes it hard for the wife to be able to call at any
    time.  Because we all work in the same war room and are pairing on
    all production code, when my wife calls, it’s never a good time to
    talk, and I have to help her understand our way of working and that I
    can’t have a phone conversation at any time.  Family emergencies
    obviously take precendence, but my wife likes to call and chat, and
    that doesn’t work with extreme programming because we are engaged all
    the time.
  • It takes a certain type of programmer to work in this disciplined
    fashion, and not all programmers want to work this way.  It is
    taxing for us because sometimes we don’t want to pair program, but we
    know we must. 

The ugly:

  • The code we inherited.  We are improving a system with
    inadequate test coverage.  The test that are there are integration
    tests and when they fail, it’s a mystery to discover what part of the
    code is actually the problem.  We made vast improvements on the
    testability of the system, and we’ve employed acceptance tests with the
    FitNesse wiki to allow for automated full system tests.
  • Technical debt and politics.  We constantly made
    improvements to the code and the way we worked.  Sometimes this
    wasn’t obvious to management.  We had to make some changes to
    facilitate some needed behavior, but management wanted the behavior
    without paying for the prerequisite work.  In this case, it was
    our responsibility to push back and not allow technical debt to
    accumulate just for political reasons.  We try as much as possible
    to keep technical decisions out of political ones.  It’s our job
    to take customer requirements and translate them into working
    software.  The manner in which we do that is our decision (the
    decision of the technical players on the software team).

Overall, the employment of these extreme programming practices has been
wildly successful.  We’ve improved the system in a very short
period of time while adding functionality, and we’ve paid down
technical debt we inherited without incurring more.  We are
encouraged by these results, and we will continue these practices that
have been working for us.  We’ll look for even more ways to go
faster by improving efficiency.  We’ll increase our level of test
automation to free up our tester for more in-depth exploratory
testing.  Overall, management is pleased because we’ve produced
the business value that matters.  That’s all that matters: 
delivering software that adds business value.

TDD makes refactoring easy – level 300

Here is the main reasoning for this:  TDD states that a unit test
is written before a unit of code.  Each unit of code will have a
unit test.  When a unit of code needs to be refactored (changed
in structure without affecting behavior), the unit test will preserve
the behavior of the code.  The unit can be refactored quickly, and
the unit tests will assert that the code still behaves as originally
intended.

Consider refactoring without unit tests or with only integration
tests.  First, without tests.  You refactor a piece of code
that doesn’t have a test.  Now to ensure that you didn’t break
anything, you have to run your application with some scenarios that are
sure to exercise the changed code.  This is more time-consuming
that merely running the unit tests for the unit in question. 

Suppose you have _some_ tests for the unit, but they aren’t unit
tests.  The tests involve several other pieces of code as
well.  If all is well, the tests will still pass, but it they
fail, you would have to debug into the test to find out what’s really
going on since the test has a larger scope.  A unit test’s scope
is only that of the code unit, and if the test fails, it pinpoints the
area of failure.

TDD reveals poor class design – level 300

If a class is well-designed, it will be easy to unit test.  Good
design speeds up unit testing, and TDD reveals bad design.  In
this way, TDD speeds up unit testing.

For a very simple example, consider a controller class that takes a
domain object and saves it to the database using a data access
class.  When test-driving this code, it will be impossible to
create a unit test for this if it is poorly designed.  Consider
this poor design:  the SaveXX() method instantiates the data
access class and passes the domain object to it for saving.  With
TDD it would be impossible to write a unit test for that because you
can’t fake the data access class, and you must test the controller
class apart from the dependency on the data access layer.

Because of the major roadblock in designing a test for code designed
poorly, it forces the developer to come up with a better design. 
This better design will be a cinch to unit test because it will be
loosely coupled.  Loose coupling is essential for unit testing.

To write a test for this controller class, I’ll have to define an
interface for this portion of the data access layer.  I’ll inject
this interface into the constructor of the controller class and call it
in my SaveXX() method.  With this design pending, I can fake the
interface in my test and assert that it was called with the correct
object.  This will be my test.  Next, I’ll write the code
that makes the test pass. 

Poorly designed code is hard to test, and thinking about testability
will force a more thoughtful design.  I would even go as far to
say that at the class level, a testable class is a well-designed class.

TDD speeds up unit testing – level 300

Before reading this post, I recommend reading a previous post of mine along with the comments and trackbacks to related posts.

First, you may wonder why I’m contending that TDD speeds up unit
testing if TDD itself stresses unit testing so much.  One can unit
test without employing TDD.  I can write some code and write a
unit test for it.  If I use this method, I’m likely to have a hard
time unit testing the code because it may call out to a database or the
file system or a web service or some other object that is difficult to
create in isolation.  If I think about how I’m going to test the
code as I’m writing it, I’ll end up with code that’s easier to test
because I’ll depend on interfaces and employ other techniques to ensure
my code is loosely coupled
Because my goal was a piece of code for which it was easy to write a
unit test, I’ll end up with code designed for that.  At this
point, I’m blurring the lines between just unit testing and TDD. 
I didn’t write my unit test first, but I _thought_ about how I would
write my unit test first.  I imagined the method of testing before
writing the code.  From this point, it’s a snap to then actually
write the test that’s floating around in my head before coding the
production code.

From a pragmatic sense, it probably doesn’t matter which code is
actually typed first if you’ve already decided on the unit test in your
head.  You’ve written the unit test in your head before the
production code.  The typing is then just semantics. 

If you aren’t thinking about unit testing at all (if you don’t
currently do unit testing), then this whole topic is worthless for you,
but if you are attempting to write unit tests after you design your
code, I’m sure you can relate that it’s often difficult because you
have to pull in other classes just to test a single class.  If
this happens, then it’s not a unit test at all.  It’s an
integration test because it tests multiple things.  The difference
in unit testing and integration testing is a topic for another post,
but the difference is very important, and if the difference is not
understood, then arguments for/against TDD don’t make much sense at all.

The above is how TDD speeds up writing unit tests (if you have already been doing unit testing).

If the goal is code with unit tests, then the code will be designed for
easy unit testing.  To design for easy unit testing, a developer
has to think about the test first.  This leads to mental TDD, and
after the code is designed, the unit test can be written quickly. 
The next step would naturally be to just go ahead and type the test
first instead of keeping it in your brain.  If at this point you
prefer to continue to type the test after the production code, go
ahead.  You will have benefited some by focusing more on how to
test the code.

Sam Gentile packed the house at ADNUG and preached the good news of Extreme Programming – level 200

Sam has already posted about it here, but I’ll continue.

Yesterday’s Austin .Net User Group meeting was a big success.  We had 80 people, our largest crowd in a long time.  Miguel Castro was pretty close with 75, but for the past several months we’ve had over 5 first-time guests, so people are spreading the word about the group.  I try to keep the group focused on software concepts that are core to building sustainable software that can add value to the business now and for years to come.  If you believe in “voting with your feet”, then these topics are getting a lot of votes. 

Sam answered a question about what skills were needed in a developer, and he made a great point:  A good software developer is one who can create software that’s easy to change.  Not someone who’s an expert in SQL server, Indigo, ASP.NET, etc because those technologies will be the next legacy systems.  A good developer hops from technology to technology but always keeps the software easy to change – after all, that’s the only constant.

We normally go until 7:30pm, but yesterday we went to 8:05 (Sam could have talked until midnight, but I had to cut him off), and 75% of the folks stayed to the very end (60 out of 80).  It was obvious that everyone was very interested in what was being said.

We went to Rudy’s BBQ afterward and continued the discourse.  12 folks stayed until 10:30pm talking about TDD, iterations, FIT, estimating, how to handle a developer that’s not pulling his weight, etc.  Great talk!

Sam was amazed that it was 80 degrees in the middle of the day and 70 degrees late at night.  He’s used to it being bitterly cold.  For us, that’s just what it’s like in Texas – of course we deal with 100+ in the summer also, and it only snows once a decade.

Sam Gentile on Extreme Programming at the Austin .Net User Group – level 300

Yesterday (Sunday), Sam Gentile came into town on his INETA speaker trip to the Austin .Net User Group.  Since we had some extra time with Sam before the user group meeting, I organized a bbq at my house in Leander, TX. 
We grilled some inch-thick ribeye steaks on the back patio and had a
good time talking about software for hours.  We talked about the
merits of FIT, automation, and other things in play in the extreme
programming world.  Some people you might know in attendance (and
if I didn’t list your name, get a blog) were:  Sam Gentile, Steve Donie, Blake Caraway, Jeremy Miller, and Scott Bellware.

He said something that stands out in my mind, and I may change the way
I view and talk about the way I work on a day-to-day basis.  I’ve
been using the term “Agile” to describe the group of practices that I
and my team uses.  He has convinced me that the term “Extreme
Programming” is a more accurate term.  It really is extreme. 
There is a solid goal in sight, and we have to be very disciplined
about how we do things in order to keep our software
maintainable.  One way to think about it is:  How true is the
statment “grass is green”.  Is that statement somewhat true, or is it
very true?  Truth is extreme.  It is not relative  or
subjective.  Truth is truth, and there is no room for negotiation
before it ceases to be true.  With extreme programming, if you negotiation, it’s no longer extreme: it becomes moderate.  Moderate programming.

How good can it get?  It needs to be extremely good, not moderately good.

Sam is speaking to the user group as I write this post, and he
explains the principles of extreme programming extremely well. 
Great job, Sam!

XP iterations, estimating and executing (an add-on) – level 200

This is a response to Sam Gentile’s post: Iteration
XV and IterationXVI – The One Week Iterations
.

My team does 2 week iterations, and I think that timeframe works well.  It’s just enough time to bite off a measurable amount of work while minimizing the percentage of overhead that iteration planning brings.

Our boss keeps an Excel spreadsheet with our burndown list for the purpose of keeping upper management up-to-date, but the team goes off of the whiteboard.  The whiteboard is the master list and can be updated at any time. 

6 months ago, iteration planning took all day to do because we were unorganized, and we got too much into analysis (off track).  Now, our iteration plannings are much more focused.  If we have unanswered questions, we throw an analysis spike on the storyboard.  This keeps our planning meeting on target.  Now we have it down to about 2 hours. 

We estimate in points first to cap the work for an iteration.  Then we break down the stories into tasks and estimate in ideal hours.  Our minimum for a task is 2 hours, since nothing EVER takes just “5 minutes”. 

Last iteration, we got half-way through and were 3 days behind.  We had grossly underestimated.  It worked out, though because we caught up with some tasks that were grossly overestimated. 🙂  We’re still getting better. 

Rocky gets it all wrong about Test-Driven Development (TDD) – level 200

I’m listening to the latest .Net Rocks show with Rocky Lhotka, and I’m saddened that he gets it so wrong about TDD.  DNR’s last episode ROCKED with Jean Paul Boodhoo,
who talked about TDD and other Agile concepts.  Jean Paul is a
practitioner of TDD, as am I, and he explained the process and its
benefits very well.  Congrats, Jean Paul on a job well done.

Rocky, on the other hand, gets it all wrong.  I respect Rocky and
his contributions to the developer community, but he’s wrong on this
issue.  Let me recap:

At the beginning of the dnr show, he comments on TDD.  He makes
some invalid points.  His points are bulleted, and my responses
are in green:

  • It comes from the premise that you don’t have intellisense in the IDE.
    • I’m really not sure how he came up with this since most other good IDEs have intellisense. 
  • In the Microsoft space, you lose so much by going down the road to TDD.
    • This is a very vague statement, but I’ve
      gained so much by doing TDD.  My rate of development has sped up
      because my debugging time has gone almost down to zero!
  • Rocky misunderstands the process because he states that it involves writing a bunch of tests first before coding.
    • TDD involves writing a single test first and writing code to fulfill it.
  • He states that on large systems, you can’t do it one test method at a time.
    • Can’t?  Any large system is made up
      of smaller parts, down to actual classes and methods as the building
      blocks.  TDD helps define the classes and methods.  TDD
      forces you to start small, but helps build a solid foundation.
  • He says that developers don’t think the way of “test-first”.
    • This is actually a true statement but in
      no way is a weakness of TDD.  Test-first is a learned method just
      like programming as a whole.  Learning to think first is very
      similar to understanding the purpose of the code first.  If you
      can understand the purpose of the code before writing the code, you end
      up with less code churn and a clean class design.
  • Rocky relates that he has always made small test projects or console apps to be test harnesses to test code.
    • I used to do that also, until I graduated to NUnit.
    • These test harnesses are valuable, but as
      you accumulate them, they are hard to manage, and since they are
      valuable, you don’t want to throw them away.  NUnit allows these
      test harnesses to be managed effectively.  Each test method is a
      test harness.

Another false point made in conversation is that once these test
fixtures are created, developers will be hesitant to refactor code
because it would cause them to have to refactor all the tests that use
the code.  Let me say from experience that unit test coverage
makes me want to refactore MORE!  I am so comfortable refactoring
because I have unit test coverage that assures me that I haven’t broken
anything.  In fact, when I am in parts of the code that is older
and doesn’t have good test coverage, I am scared of refactoring because
I have no way of being sure that I didn’t break anything.  Note,
that I also use Resharper, and I would not want to code at all without
it or the DevExpress tools.

I love .Net Rocks, and I’ve listened to it from the very first show (and I’ve been a guest),
and I’m glad all viewpoints are represented, but the above bullet
points are incorrect, and I hope some of you will comment on them as well.

Using enum strings with NHibernate persistence – level 400

One of the things that is not very obvious when using NHibernate is how to using Enumerations.  If you merely map an enum with the hbm.xml, NHibernate will persist that class member as an int, which is the underlying type of an Enum value type.  Even if you have your database table configured with a string field, you’ll get an integer in your string field.

To have NHibernate use the string representation of the enum for storing in the database, you need to use a special type class.  Below is a simple example of using the EnumStringType that NHibernate provides.  Consider the following enum that I want to use in my class (this is a very simplified example):

    public enum DeliveryStatus
    {
        Pending,
        Ready,
        Sent
    }

When mapping this in my class, NHibernate would persist 0, 1, and 2 in my database.  What I actually want are the strings to be stored in my table (no comments about normalization, please).  Here is a wierd thing you have to do to achieve this goal.  Here is my mapping:
<?xml version=”1.0″ encoding=”utf-8″ ?>
<hibernate-mapping xmlns=”urn:nhibernate-mapping-2.0″>
    <class name=”Palermo.Shipping.Shipment, Palermo.Shipping” table=”Shipment”>
        <id name=”TrackingId” column=”TrackingId” type=”String” length=”30″ >
            <generator class=”assigned”/>
        </id>
       
        <property name=”DeliveryState” column=”DeliveryState”
            type=”Palermo.Shipping.DeliveryStatusType, Palermo.Shipping”/>
       
    </class>

</hibernate-mapping>

Notice that I have a new type referenced for DeliveryState:  DeliveryStatusType.  This is what’s new.  This type helps NHibernate map an enum string instead of the int.  For this, I must define this type in my code:

    public class DeliveryStatusType : EnumStringType
    {
        public DeliveryStatusType() : base(typeof (DeliveryStatus), 30)
        {
        }
    }

Note that this is very simple, and the 30 specifies the max length of the enum string.  I’d recommend setting this number the same as the length of your string field in your database.

With these small steps, NHibernate will now map Pending, Ready, and Sent to the database field.  Normal programmatic interaction is the same.  NHibernate will take care of all the data access.  Without the above solution, one might be tempted to use string constants, but I’d highly recommend using enums when the possible values are known. 

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.