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

October 2006 - Posts

  • My Programming Manifesto

    As some of you know, I started a new job this month as a consultant helping clients to adopt Agile practices.  It's been an interesting experience so far.  Working with people who have different philosophies and experiences is always a good opportunity to learn.  I'm getting exposed to different techniques and being forced to examine the things that I believe.  In the end, we all want about the same things -- to write quality software in an efficient manner without working too many weekends or late nights.  We all agree on the basic goals, but our philosophy in achieving these goals are different.  I know there's been a few cases where the clients have cocked an eyebrow at some of my opinions, but in every case I've simply had a different set of ideas for how to build software. 

    Mostly unrelated, but in the spirit of the infamous Agile Manifesto, I'm writing down my own manifesto in an effort to explain the method to my madness.  Many of you are going to disagree with me, and that's okay.  It's my set of values after all, and I'm happy to hear your comments.  Or better yet, go write your own manifesto.

     

    Let's get this out of the way, and please read this literally:  while I do believe there is some value in the stuff on the right, I think the stuff on the left is more valuable and important.

     

    Unit Testing and Testability over Defensive Coding, Tracing, Debugging, and Paranoid Scoping

    I think we can all agree that you can't ship code until you remove enough defects from the code.  While you certainly have to apply a mix of techniques and practices to remove a high percentage of defects, I want to talk about the things we do to our code to wring out the defects.  Off the cuff, I can think of these:

    • Use a debugger to walk through the code to try to uncover the errors through observation
    • Use defensive coding to provide more contextual information about erroneous usage of a section of code
    • Tracing statements in the code to provide debugging information at runtime
    • What I can only call Paranoid Scoping.  Ratcheting up the protection on classes and members to prevent developers that use this code from "harming" themselves.
    • A very high degree of granular unit testing, like that afforded by adopting Test Driven Development.  I'm talking near 100% developer test coverage here. 

    An axiom of software development is that problems are cheaper to fix the sooner that the problems are detected.  If you take that axiom at face value, it's easy to see why I put far more weight into comprehensive test-first unit testing because it gives you far more rapid feedback to find problems fast.  Small, isolated unit tests work on very granular pieces of the code, so the number of variables in any single unit test should be small (if it's not, look for a different way to write the code).  You shouldn't even try to run the code as a whole until all the constituent pieces have been validated through unit tests. 

    Debugging is not efficient, period.  It's simply not smart to try to debug a lot of moving code parts together if you don't have a high confidence level in any of the parts.  If anything goes wrong you've potentially got a lot of variables to check out all at once.  Yes, you can help yourself out by providing tracing to see what data is passing through the code or defensive programming to short circuit processing when you hit a bad value or provide a more descriptive error message.  But no matter how hard you try to add tracing and defensive coding, I still think unit testing will get you to working code faster than any possible kind of debugging.

    Last week one of the developers working on our server side component asked us, the GUI team, to make sure that we had plenty of tracing in our codebase so that integration issues could be adequately diagnosed.  I certainly don't think that's a bad idea, but I'm far more keen on sinking energy into a rigorous set of automated unit tests on both the client in isolation and the server side in isolation before we even attempt to integrate the two pieces.  Since I am a believer in interaction style testing, we'll test our code extensively to prove that our code passes the correct information to the backend through mock objects.

    Don't get me wrong here, I do believe in some amount of defensive coding and tracing, I just think that it's not something you rely on as your primary means for removing defects from the code.  My issue with tracing and defensive coding is the often speculative nature of the activity and the negative impact on code readability.  I strongly prefer to use tracing and defensive coding "defensively."  I'll put in specific exception warning for things we hit in testing that are difficult to debug or around external dependencies.  If I had to choose though, I'd rather have a good suite of environment tests to detect configuration or connectivity problems before I even try to execute the code.  In the end I might also say that I just think that you hit a point of diminishing returns with tracing and defensive coding rather quickly.

    Oh, and by the way, every time I've come across code that had copious amounts of tracing?  The code was truly awful, failure prone code.  Excessive tracing is a code smell.

    The paranoid scoping is probably the single biggest area of disagreement I've hit with my client.  They haven't traditionally used TDD or any kind of comprehensive unit testing strategy in the past, so I don't think they understand the negative impact on automated testing caused by this scoping.  Because they depend more on debugging and waterfall testing for removing defects, they're big on using protected scoping on classes to prevent downstream developers from using objects incorrectly.  In several cases already, I've seen that attitude hamper the testability of the code.  Granular unit testing is dependent on an ability to quickly setup the inputs for a little piece of the code and run that code in isolation.  In a specific case, the server side developers have quite purposely protected all of the setters of the entity classes in the system that should only be set by the server side code.  Reasonable right?  Actually, I'd argue that that strategy ends up doing a great deal of harm to us.  In the current architecture, the entity classes can only function with the complete server side connected.  If we can't change that design, it will dramatically slow down the feedback cycle of the user interface development because we can't unit test the presenters and views in isolation.  I'm perfectly happy to make that code more "dangerous" in exchange for being able to write isolated tests more efficiently.  Besides, we are going to prove that we use the server side code correctly by testing the interaction with the backend as well.  In my world view, improving the testability of the code does far more good to remove defects than the reduced protection levels do bad by letting defects in.

    Sharp Tools over Coding with the Kid Gloves On

    Quoting Bruce Tate:

    We need to let our craftsmen work with sharp tools, rather than protect them from themselves.

    Recently, Paul Stovell took issue with a presentation from Scott Hanselman suggesting that you aggressively mark classes as internal or sealed to protect the users of your API or framework.  I'm going to very strenuously agree with Paul on this one.  In the week after reading Scott Hanselman's post I bumped into three different cases where the exact functionality in a framework that I needed to either use or override was sealed or internal.  In one case I resorted to reflection to manipulate a private member.  In another case I forked the open source framework and I really, really hate to do that.  The attitude of "seal everything" is just going to limit the usefulness of your code.  Make your framework or code easy to use by providing a good Facade and a bit of documentation (i.e. tell me which class is the Facade!), but leave the little underlying pieces accessible and available for usage and modification.  Remove all that sealed and internal "protection" and I can certainly break something, but I can do more positive things with your code as well.  I'm perfectly willing to be responsible for my own solution.

    To put "Sharp Tools" in perspective, let's consider some of the languages I've coded in throughout my career.  Assuming you used "Option Explicit" and pretend for a moment that the reference counting strategy wasn't a huge memory leak, VB6 is the ultimate kiddie glove language.  It shelters developers from a wide range of coding issues by limiting the range of coding constructs.  You can't possibly deny that VB6 was very successful, but it is an extremely limited language in capability.  Limited Object Oriented Programming support and no real multi-threading severely constrained the usage of VB6, especially in server applications (though we certainly tried didn't we?). 

    C# and .Net came along with a lot more power and potential to royally screw things up.  I think it's been a great trade.  I routinely build things in C# that weren't possible in VB6 (windows services to name one) and use OOP techniques that weren't supported by VB6 to great advantage.  I'm happy with C#, or was, until I started seeing some of the capabilities of Ruby. 

    Ruby is a dynamically typed language that also supports metaprogramming, i.e. code that writes code on the fly.  Metaprogramming can be scary to debug, and there's a tremendous opportunity to thoroughly confuse developers, but it's soooo powerful.  A lot of the eye popping features of Ruby on Rails (think ActiveRecord) are clever utilizations of metaprogramming.

    When we worked together, Jeffrey Palermo and I had a running Abbot and Costello routine about static languages (C#) versus dynamic languages (Ruby).  In order, it went something like this:

    1. I gush about something cool from Ruby or Ruby on Rails (migrations, the built in testing support, metaprogramming tricks, etc.)
    2. Jeffrey says "just wait until you inherit a really lousy Ruby codebase without any unit tests. How are you going to support that without compiler checks?
    3. I freely admit that I would panic in that situation, but then I remind Jeffrey of the really lousy C# legacy code we've dealt with that doesn't have any unit tests and say that I don't want to support code without unit tests in any language.

    My point being that just like a sharp knife or power tools, "sharp tool" techniques are safe when combined with some proper precautions (TDD).  Of course I've got a little scar on my bicep from shooting myself with a pneumatic nail gun, so what do I know about safety?

    Several years ago, and long before it was AJAX and Web 2.0, I used to do a lot of DHTML scripting in JavaScript that heavily utilized JavaScript's "Expando" typing and a bit with "eval()."  It worked, but as I recall the debugging was nasty and it wasn't really supportable.  This summer I was on big Ruby and Ruby on Rails kick.  As an experiment and a way to work in a familiar problem domain before I dived into Rails, I decided to go back to some of the JavaScript controls I wrote 4+ years ago and recreate them using Rubyesque coding techniques and Test Driven Development throughout.  Using JSUnit and Prototype, I wrote most of a TreeView control and a sortable, pageable grid.  Granted, I've got much more experience this time around, but even so it went much, much faster.  I was able to shrink the code down considerably compared to the previous versions.  Since I was using TDD I really didn't have to use the debugger very often.  With duck-typing and expando members, mocks and stubs are almost trivial.  The very features that make dynamic languages "unsafe," also lead to easier mechanics for TDD, which in my book is more valuable for "safety" anyway.

     

    Writing Maintainable Code over Architecting for Reuse and the Future

    A couple weeks ago one of the architects at my client asked us to make sure a piece of functionality we're building is reusable later.  I started to object on the grounds of violating YAGNI before I realized that I completely agree with him -- on the ends if not the means.  Some of the other developers are worried about making sure that the code meets future needs and maximizes code refuse.  I think there's an underlying, unspoken assumption that the code cannot efficiently be changed later.  It has to be designed "right" upfront.

    I think that the code needs to be able to change to meet future needs, whatever those turn out to be.  I want our code to be reusable as well.  What I don't believe is that the way to meet these goals is to prematurely generalize the solution or speculatively build in unused hooks that "we'll need in the future."*  If we spend a substantial amount of effort building infrastructure for future needs we risk delaying the initial release.  Even worse, what if the specific infrastructure turns out to be unnecessary?  That turns into waste.  Additionally, I've often observed systems where the biggest impediment to extensibility was actually the very extensibility mechanisms put into place early in the project!

    What I believe in is meticulously creating loosely-coupled, highly cohesive code backed up by comprehensive test and build automation that can accept change.  I think reuse is best accomplished by well factored code, not by specific intention.  If I can really create code that can be efficiently changed, and I firmly believe this is possible, I can add infrastructure and functionality to the code at a later date.  I want my code to be able to safely accommodate a broad range of change because you never really know what the future will bring.  We think we know what the future needs are, but one of the sales guys could easily swoop in with something completely off the wall.  Call me naive, but I really do think that you effectively flatten the change curve through an emphasis on very solid, maintainable code.  I want to be able to build the sales guy's wacky ideas that we don't even know about yet, not just the future features that we "know" we'll need.

    I'm very dubious about a lot of the unbridled SOA enthusiasm I've seen practiced on projects.  In particular, I think the idea of exposing pieces of a new system as web services upfront for a single consumer to be borderline idiotic.  If there's only a single consumer, and the team owns both sides, just write the "service" in process.  The extra cost of writing and debugging the out of process integration point is a complete waste of effort if there isn't a second consumer.  You've simply taken on additional technical risk on the chance that that exact service point will be useful to another consumer at a later point. 

    But wait Jeremy, what if I do need web service later?  What do I do now smart guy?  I told you I should have written the web service.  Well, if the code is really maintainable, i.e it can be safely changed, adding the web service wrapper to expose the existing code base remotely should be strictly an exercise in writing additional code, not changing existing code.  I very honestly, and sincerely, believe that high quality, maintainable code goes a long way towards obviating the need for SOA.**

    I've been working up a long-ish post on writing maintainable code that will expound on this point quite a bit.

     

    Explicit Code over Design Time Wizards

    My team has been coding for about three weeks on a WinForms client using copious amounts of Visual Studio.Net's design time support.  I'm already thinking it's time that we, the .Net community, take a hard critical look at the RAD tools in Visual Studio.  What I'm often seeing is that a little bit of explicit, hand-rolled coding leads to less duplication, better understandability, and vastly better testability than leaning too heavily on the wizard magic.  The effort it takes to create code isn't just the writing of the initial code, it's also the effort it takes to test the code and modify that code later.  In specific, I'm starting to become disenchanted with Data Binding.  I'm really not convinced that the design time support for configuring the data binding justifies itself.  I'm really seeing that pushing user interface behavior into Supervising Controllers with explicit code leads to a more maintainable system than depending on design time configuration of that same behavior.

    Again, this circles back to the idea of making code work through testing and therefore seeking to enhance testability.

    Software Engineering over Computer Science

    I through this in here just to get some flames.  It's a huge pet peeve of mine to see teams agonize over incremental improvements in sorting algorithms or caching or optimizing the number of IL instructions while neglecting to use sound Software Engineering practices.  The success of a system and the staying power of a codebase are rooted in solid configuration and build management practices.  Your algorithm might be fast, but you aren't going to reap much reward for it if you can't consistently get your code to install correctly.  Computer Science knowledge comes into play in some projects.  Good software engineering practices are valuable in every single software development project.

    Here's a longer explanation of the coding ecosystem I believe in.

     

    * How's that for loaded language?

    ** Of course, the natural state of code tends towards entropy, so I think SOA's future is perfectly safe. 

  • The Path not taken...

    EDIT:  I'm not suggesting that you ship code with known Technical Debt here and I'm sorry that I gave off that impression.  That was not my intent.

     

     

    Say you're given a choice between two directions:

    Path A:  Build a crude, simple, hard-coded solution to the immediate needs to get the first release out the door.  You know full well that some of this work will have to be modified or maybe even rewritten for future releases.

    Path B:  Write an elegant solution upfront that addresses all of the needs, present and future, that you can forsee.

    Every case is different, but my stock choice is Path A.  Path B might very well lead to a reduced effort in the long run, but it comes with substantially more risk.  But then again, you might be tackling a lot of complexity upfront in a speculative manner that can easily lead to wasted effort.  On the other hand, I really do believe that as long as you write maintainable code with the full gamut of TDD and CI practices in Path A, you can grow the code to handle future needs.

    All that aside, the single biggest risk is what if the initial release fails?  You simply don't get a "future" if the first release bombs;) 

     

    My younger sister told me a story before her high school graduation.  She was talking to the valedictorian of her class and was asking him how his speech was coming.  She made a typically sarcastic remark that she hoped he wasn't using an analogy to Robert Frost's "The Road not Taken" poem because it was a terrible cliche.  Sure enough, his face turned white and he ran off mumbling to himself. 

  • Brief update on StoryTeller

    It's still cooking.  I just passed 150 NUnit tests.  Right now I'm having to veer off into the tools to import and interact somewhat with FitNesse.  My team is getting started with FitNesse and I  think I'll use the project work a little bit as a testbed for StoryTeller.

    I've gotten a couple volunteers to help code and try out StoryTeller.  I'll be sending emails to everybody in the next couple days.  If you want to jump on board, the easiest thing to do might be to go request a role at http://storyteller.tigris.org.

    How's this for irritating?  We're driving automated acceptance testing of our WinForms application with FitNesse calling through NUnitForms (I'll blog about our experiences in a couple weeks).  We're using, or at least trying out, a third party control library for oohs and aahs in the user experience.  Great, except for one little problem.  Apparently you can only load a single instance of a certain control in any one AppDomain.  Since the FitNesse tests work by starting up the main form at the beginning of every test (gotta start clean), only the first test you run will work correctly.  Just to beat this without spending months looking at the controls in Reflector, I'm building equivalents to FitServer.exe and TestServer.exe inside StoryTeller that will construct and teardown a new AppDomain for every single test.  Grrr.  Typical Microsoft world stuff, thousands of man hours spent on Design Time support and very little on testability.

    Of course, one of the reasons I enjoy test automation is that the code is generally more challenging than the day to day CRUD.
     

     

  • On coding standards

    Clearing out old drafts... 

    Yes, a team needs to agree on a coding standard and consistently follow that standard. That being said, I think the coding standard should be kept as simple as possible and only grow as needed. I think elaborate coding standards that are hard to remember or require developers to go out of their way to follow it do more harm than good.  A couple years ago I watched a client organization spend a tremendous amount of energy enforcing an elaborate coding standard in coding reviews and completely neglect the (poor) structure of their design.  There's a point of diminishing returns on coding standards and it comes up fast.  Learn to like the default "{}" placement in VS.Net or a simple configuration of ReSharper and live with it.

    There's tons of coding standards on the web that you can download and use built by acclaimed .Net experts.  I'd bypass all of them.  A team is much more likely to follow a standard that they've built themselves.  Let the coding standard grow organically as you encounter new needs.  There's absolutely no need to spend a week defining a 200+ point standard upfront because nobody will be able to follow it anyway.

    And the silliest coding standard I've ever seen was the initial C# coding standard at a past employer that was made before anybody had written a single line of C# code.  Here's the highlights as I recall:

    • Always use abstract classes instead of interfaces because you can reuse functionality in the abstract classes.  There are reasons why the language includes both constructs.
    • Every method should have a comment block listing the history of changes to that method.  Source control anybody? 

    In the words of Forrest Gump, "that's all I've got to say about that."

  • Programming language humor

    http://undefined.com/ia/2006/10/27/six-word-stories-about-programming-languages/

    I love the Smalltalk & Lisp stories.  It seems right now that *every* single cool advance in programming comes with a couple of old guys screaming that Smalltalk or Lisp did it better umpteen years ago. 

     

  • There are two types of developers in the world

    Those that say "Goo-id" and those that say "Gwid" (rhymes with Squid)
  • The first step to coding faster

    Forget all the Ivory Tower stuff I like to prattle on about, if you want to be a more productive programmer, learn to keep your hands on the keyboard instead of reaching for that mouse.  It'll make the mechanics faster and leave more time for the "thinking work."

  • CodingLaw!

    Because I watched too many "Man Law!" commercials during this weekend's football games:

     "There must be a stub or a test fixture in every codebase that uses the Simpsons as a theme for fake data"

     
    CodingLaw!
     

    P.S. A consistently effective way to break the ice during pairing sessions is to decide on the fake data theme of the day.  A couple years ago I was on a team with some client developers that weren't exactly warming up to us consultants (not the first or the last time).  As silly as this sounds, one of the coders got a bit friendlier after we used a NASCAR theme for a day in our unit tests.  With another coder we started using a Hair Metal band theme.  Star Wars/Star Trek are cliches now, just throwing ideas out at you that I've used:

    • Dukes of Hazzard
    • Zelazny's Amber series (for the two of us who knew what that was)
    • Hitchhiker's Guide to the Galaxy
    • Wheel of Time
  • Announcing "StoryTeller" - A new .Net tool for FIT test management

    I'd like to announce a new open source tool that I've started called "StoryTeller" that is being hosted on Tigris at http://storyteller.tigris.org.  There isn't any content, but the code is up in Subversion.

    From the website:

    StoryTeller is a new tool for efficient creation and management of automated testing of .Net code with the NFit/FitNesse engine. StoryTeller is specifically created to support an Acceptance Test Driven Development strategy. All existing .Net FitNesse and NFit tests will run under StoryTeller. Features will include editing, tagging, and integration with source control, CruiseControl.Net, NAnt and/or MSBuild, and support for application versioning.

    The name "StoryTeller" is meant to convey a sense of telling the story of an application by defining the systems requirements (the user stories) in executable FIT tests.  My basic goal is to enable Acceptance Test Driven Development by simplifying the mechanical work of designing FitNesse fixture classes and tests.  I definitely want something that makes it as easy as possible for testers to use the Fixture classes we create and for us developers to run their tests at will.  StoryTeller will consist of a .Net 2.0 WinForms application and class libraries to edit and run FIT style tests.  It's very early in its development, but I wanted to announce it early to get some feedback about the feature list and gauge the interest level of the community.

    Why move beyond FitNesse?

    • It lacks integration with source control
    • Little bit difficult to integrate with CruiseControl.Net
    • The .Net support has never been up to par with Java
    • There's simply an opportunity to do it better

     

    Proposed Feature List

    • Human editable test files
    • Run tests with the FitNesse/NFit/FitLibrary.Net engine (duh)
    • Organize tests into a hierarchy of Suite's
    • Define "System Under Test's".  The definition of a SystemUnderTest would include:
      • Source control persistence for the test and suite files within StoryTeller (I'm going to steal outrageously from CC.Net on this)
      • Being able to deploy the latest, or versioned, build of the System Under Test with a NAnt or MSBuild script on command
      • "Component Analyzers" that can build a report in the tool listing the deployed components and versions of those components
      • "Local" systems for developers to run the tests on their workstations and "Remote" systems for testers to edit and execute tests against a remote installation
    • Categorize and run tests by tags.   Tagging could be used to categorize tests by "Regression" or "Acceptance", by user story/feature, or by test owner
    • Create "play lists" of tests
    • Setup and Teardown inclusions
    • Sharing test fragments
    • Easy copying of tests
    • Create test templates
    • WinForms tool to edit tests with guided "Intellisense" like forms for BoundFixture's, FlowFixture's, and an adhoc mode
      • Run the tests inside an NUnit GUI-like tool
    • Wizard to design Fixture grammars to enable consistent test writing well in advance of coding
    • Create reports of test runs that include the results, the version of the tests, and the versions of the installed components
    • Integration with NAnt or MSBuild and CruiseControl.Net
    • Run the tests from within Visual Studio.Net
    • In the distant, misty future I'd like to include some integration for web application testing with Selenium and/or driving WinForms testing with NUnitForms

     

    Questions?

    • Does the world need this?  No, not really, but it'd be awfully nice.  I've been wanting something like this for about a year.
    • Why .Net?  I wanted, and started, to do this with a Ruby on Rails backend and AJAX frontend but didn't get very far.  The choice of technology is completely based on the fact that I'm doing WinForms development for the first time in two years and I could use some significant practice;)
    • When?  I'm planning on being able to use the non-UI pieces soon.  The bare bones UI will follow in a couple months.  Part of the goal behind making this announcement is to goad myself into getting it done.
    • Can I help?  Gladly.  Send me an email.

     

    Got suggestions or questions?  I'm all ears.

  • I used my first closure in C# 2.0!

    Okay, it's lame, but still:

       53                 return Array.Find<ISystemUnderTest>(

       54                     _systems,

       55                     delegate(ISystemUnderTest system)

       56                         {

       57                             return system.Name == systemName;

       58                         });

    where _systems is an array of ISystemUnderTest[] and systemName was an argument to the method that contains this code.

    Somebody will have to correct me, but I think the Ruby equivalent (they call them "blocks") would look like this:

    systems.Find (|system| {system.name == name}) 

    Ruby is definitely cleaner, but I'm happy to have some of this stuff in C# now.  I was playing quite a bit with Prototype in Javascript a couple months back and got hooked on the functional idioms like this method below:

    	table.drawPage = function(iterator, columns){
    this.clear();

    columns.each( function(column){
    this.createHeader(column);
    }.bind(this));


    while (subject = iterator.next()){
    this.drawRow(columns, subject);
    }
    }

    The code "columns.each( function(column){ ..." is the closure.  This calls the current class's createHeader() method on each member of the columns array.  Before you run off and try this  in Javascript, it's Prototype that extends the Javascript Array object with a bunch of "Ruby-isms" like this.  You'll need to grab the Prototype library first.

    Check out Martin Fowler's explanation of closures for an explanation.  I'm really looking forward to  the C# 3.0 features now.  I'm skeptical of much of the Microsoft canon, but I'm sincerely in awe of Anders Hejlsberg. 

     

     

     

  • How to feel like a Programming Genius

    I just got done walking my father through some basic Excel manipulation over the phone.  He's  using a computer for the first time in his life after 30+ years of doing everything with pencil and paper.

    I call it fitting revenge.  I can distinctly recall a Saturday morning after a high school football game that he dragged me out of bed at 6am to help shingle a house all day and getting laughed at for being sluggish.

     

  • Week 2: Scheduling and Coordinating the Work

    Continuing the "Getting Started" series.  My team just finished our second week.  Luckily enough we were able to get through release planning quickly and start Iteration #1 on Tuesday.  CruiseControl.Net is up and running.  I kept a list of the topics that came up this past week that I might want to talk about in the blog, and a single theme pops out:  how to schedule and divide the work.

    First, some little things:

    • Check in code often.  Constant check-in's should keep the overhead of merging to a minimum.  Continuous Integration is an attitude, not just a tool.
    • Work in small steps.  That means write a unit test's worth of code at a time.  The TDD red bar should be a short phase and there really shouldn't be many times when the code can't compile for more than a few minutes.  Working in big chunks without verification is what brings out the inefficient, marathon debugger sessions.
    • If you're helping a team learn TDD from scratch, don't let them start early with dynamic mocks.  Let them get a handle on TDD with work that leads to state based testing first.
    • When you're doing TDD, try to break the work into small tasks.  From that task breakdown, think about how each task or step could be tested.  Your low-level design pretty well follows from testing one task at a time and building up to the whole.  Code from the bottom up!
    • Build business functionality first, and let the infrastructure come second to enable the business functionality.  I tried to avoid this, but it happened anyway.  We got a bit caught up in UI infrastructure and didn't get much functionality built.  The danger of focusing on infrastructure solely upfront is the risk of getting tied down in purely speculative coding that doesn't deliver any value in the end.
    • Check in comments!!!

     

    Iteration #1 Work

    I think the real goal of iteration #1 is to create knowledge more so than code.  You will never produce as much functionality in iteration #1 as you should in later iterations.  The first iteration almost has to be concerned with creating a common vision of how you're going to build the software, especially if the team hasn't worked together before.  You could lay your ears back and code away at full speed, but you'll pay for it later with either technical debt or longish design sessions with the rest of the team explaining (and arguing about after the fact) the technical approach.  I sincerely believe that people understand design strategies far better when they have been present for the formulation of that design strategy.

    I say this mostly to try to alleviate the stress from first iterations when the code isn't flying off your fingers into the IDE.  When you're loading up the first iteration you really shouldn't count on doing as much "work" as you will later on.  I think this is in line with Eric Evan's idea of Knowledge Crunching.

    Splitting the Work

    I've seen two real issues this past week:

    • The beginning of the project is much rougher for merge conflicts than it will be later on in a bigger code base.  Strive to find stories that can keep the multiple pairs out of each other's way.  Even so, it still takes a lot of communication around work on shared or foundational classes.  A simple "hey, we're about to rename this class.  Is that okay with you?" goes a long, long way to alleviating the worst of the merging issues.
    • Rotating people through different areas of the work.  Like I said in the previous section, I'm more concerned about creating the shared understanding upfront than cranking out code right now (on the theory that this shared understanding will pay off immediately in the following iterations).  We're just trying to be cognizant about rotating people through different kinds of story work.  It's a bit incumbent upon each developer to speak up when they think they're getting siloed.

    Serialize the Work

    For best results, you should focus your efforts on completely finishing active stories before starting any coding work on new stories.  You should only start coding work on a new user story if you're completely blocked or out of work on the previous stories.  First you really do have to internalize the idea that the development team as a whole can only take credit for production ready code.  Once you do that, which outcome at the end of an iteration below is better?

    1. 5 out of 10 user stories scheduled for the iteration are production ready.  3 of the others have not been started. 
    2. All 10 stories for the iteration are in some sort of intermediate state. 

    Even though both outcomes may reflect the same amount of effort by the developers, only outcome #1 provides any real business value.

    You also need to get something in the hands of the testers or reviewers by at least mid-iteration if you're going to make your iteration.  Besides, the human mind just doesn't handle context switching all that well.

    Ordering Stories

    XP dogma states that you order the user stories in terms of business value.  In practice I've never found that to be enough.  There's always constraints of some sort that have to be accounted for in your schedule:

    • What stories are understood well enough to work on?  You're going to need to look ahead a bit to make sure you always have enough stories ready to go at the start of each iteration.
    • Does one story depend on some infrastructure that's built in a different story?
    • What stories can be worked in parallel?  If having two or more stories involve the same area of code, you may want to serialize these stories to prevent some nasty merges.
    • Eliminating risk.  This might be technical risk of some sort, but it could also be business risk.  Our project is user interface-intensive.  One of our best ways to reduce risk is to get the user interface in front of the client as soon as possible to make sure the UI is acceptable and meets the business needs.
    • External constraints.  You're almost always dependent upon external groups or even external companies.  You simply cannot do work that depends on a different team without coordinating with them first.  We're going to try to get some representation from the server side team in our iteration planning meetings to deal with this coordination.

    Breaking up Stories

    Don't hesitate to break stories into small units.  For example, there isn't any rule that says you have a one to one relationship between a screen (especially a complicated screen) and a user story.  As long as a user story provides some amount of business value and can be tested by itself, it's fine.  Smaller stories are easier to estimate and drive to completion.  Dividing the work into smaller chunks helps to get working code in front of the users and testers earlier in the iteration to make their jobs easier.

    What I don't feel good about are stories like "Capture the information in the screen" paired with "Persist the information to the database."  Capturing the information in the screen is just a task.  It doesn't really provide any value until it really works from end to end.  Dividing the work into "Capture header information" and "Capture details" and maybe even "Validate the user inputs" into separate stories is much more acceptable to me.

    Can You Have Technical Stories?

    I say preferably not, but it's not the end of the world.  As long as the stories are very focused into a specific technical task to enable the following business stories, I'm fine with technical user stories.  I've often found it easier to pull out a shared technical dependency of multiple stories into a technical story for easier tracking.  What's definitely bad are stories like:  "Create the Data Access Layer" or "Create the Model View Controller Framework."  Those stories are black holes.

  • Moving up to VS2005, but not without ReSharper

    This is probably just a bit of preaching to the choir, but... 

    I'm bringing up the rear on .Net 2.0 adoption.  When VS2005 came out my feeling was that VS2003 + ReSharper would still be superior to VS2005 in terms of coding productivity.  After about 2 days of pairing on VS2005 with workstations that didn't have ReSharper I've decided that I was absolutely right.  Minus ReSharper, I still think VS2005 is clunky to use and feature poor.  Yeah, I know they added the Class Designer and tons more wizardy code generation things, but I don't care.  I want stuff that makes coding easier and faster. 

    I've got the rest of the team talked into at least trying out ReSharper.   A friend of mine asked me several months ago why you would want ReSharper on top of VS2005 and I didn't give a strong enough reason.  After a couple days of working with naked Visual Studio, here's a couple of little reasons why you want to use ReSharper that add up to significant time savings:

    • ReSharper shows syntax and compilation problems in real time by highlighting errors.  With VS2005 you have to compile to get those indications.  Am I being forgetful, or didn't VS2003 do that?
    • Adding "using" statements automatically.  Both from typing a class name and from the "CTRL-ALT-SPACE" statement completion.  That's been driving me batty doing that manually.
    • Suggesting variable names
    • The "surround with" shortcuts to surround a section of code with if/then statements or try/catch constructs
    • The refactoring support.  VS2005 has the bare minimum Extract Method and Rename refactorings, but doesn't go far enough.  ReSharper adds better refactorings for changing a methods signature, extracting abstract classes, and moving methods from subclasses to superclasses and vice versa.
    • Finding types by the "CTRL-N" shortcut
    • Code navigation shortcuts
    • The little codegen tools to create getters, setters, and constructors
    • ReSharper generates Equals() and GetHashCode() methods from the fields in a class.  It's a really sweet feature for unit testing
    All in all, taking advantage of ReSharper (or your refactoring tool of choice) cuts down on the mechanical costs of writing code and goes a long, long way towards making evolutionary design techniques cost effective.  The bottom line is less time typing and more time to spend on design and thinking.

    On the positive side, I haven't seen any of the stability problems that seemed to plague the early adopters of VS2005 (other than debugging).  I haven't seen any sluggishness either, but that might be my new dual core machine with 2GB of RAM.

  • Little Bitty Subversion Tips

    The conventional structure of a Subversion repository is this:

    Root

        Branches

        Tags

        Trunk

     


    If you're using CC.Net and you configure tagging, CC.Net creates a Tag in Subversion after every successful build.  If you check out from the Root, you'll potentially see hundreds of "copies" of the code tree for each CC.Net build.  Add in any possible code branches in the Branches folder, and you got a lot of code.  For that reason alone, check out and update from the Trunk folder, not the Root.

     

    Secondly, you will hit merge conflicts more often early in the project, especially with project files.  Messing with the raw csproj file is messy.  I've found that the easiest way to resolve a project file conflict is to:

    1.) "Revert" and use the master copy from Subversion

    2.) Go add the missing files back to the project 

  • Important Tips for Pairing Etiquette

    1.)  If your a backseater, wait until the driver gets off the line of code to yell at him for a typo

    2.)  When you're pairing, change your IM status to "Pairing with Bob" so your wife doesn't IM you with embarassing terms of endearment. 

    3.)  If you want me to pair with you, I really, really want you to have ReSharper & TestDriven.Net.  VS2005 is basically naked without. 

    Luke Melia adds some more points here. 

     

More Posts Next page »

This Blog

Syndication

News

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

About Me

"Best Of" Compendium

StructureMap (Dependency Injection for .Net)

StoryTeller (Supercharged Fit)

Build your own Cab

TestDriven

MVP