Thursday, May 13, 2010

Extreme musings pt. 2

This is part 2 of my reflections after 2 months of XP development. (Part 1 can be found over yonder.)

A culture of productivity

One thing that XP really fosters is a culture of getting things done. The entire process is focused around delivering tangible business value to your customer. TDD, and even more-so BDD, are setup so you only write the code you need to get an actual task done. Gone are the days of engineering an entire framework only to later realize it won't work with future requirements or that it wasn't needed at all.

One thing I do miss with this style of development is that it can be fun to architect the frameworks. There is definitely a perceived elegance to throwing some headphones on, getting in the zone, and cranking out huge swaths of code.

However, even though I think I've had success with writing those kinds of frameworks, I can't argue that XP delivers more business value faster. There is still room for those frameworks in XP, but you don't end up writing them until there is a real need for them.

I've heard a saying before that goes something like "The first time you write something, do a one-off, the second time do a one-off, and the third time figure out if there's an abstraction." This what XP guides you to do.

Another thing that's really refreshing is that everyone I now work with is simply focused on being productive. It's not even a burden to them mandated from some whip-cracking exec as much as it is just who they are. An XP shop, at least the one I'm at, seems to automatically weed out anyone who would rather spend half a day surfing the web than be working. The fact that your pair can probably tell the difference between reddit and an IDE probably helps ;)

Less stress

As a whole, the developers I work with who are doing XP are less stressed than any other group I've ever seen. A lot less actually.

A common myth seems to be that if you're not stressed, you're not working hard enough. It's as if there is this secret potential that can only be unleashed if you're stressed. I think it's just the opposite, at least with people who naturally want to be productive. (And do you really want to work with anyone who's not?)

XP (and Agile) is all about getting the most value out of the time you have. You have 4 developers and 2 weeks - lets get the most value we can out of it. Everyone is considered on the same team and everyone has the same goal.

As long as everyone on the project agrees to stick to that approach it results in really happy developers who are excited to crank out quality features faster than I've ever seen. I've been lucky and haven't had to deal with external pressures such as a conference or presentation that might squeeze the timeline yet, but I would say there is less total stress among the ~50 developers I currently work with than the amount in the 12 developers I was with previously.

Also, in true XP fashion, overtime is pretty much disallowed. There are rare cases where this rule is broken, but it's far from the norm. Having a team of fully rested, alert developers seems be often under-appreciated elsewhere, and I'm glad that, as an anti-cement-cutting-board company should, a good life/work balance is highly valued.

Happy customer

All these factors seem to result in happy customers, which is a huge win. Having an honest and engaging relationship with your customer might seem scary at first, but when it works it's a beautiful thing.

Most of our projects have the product owner on-site where they can see exactly what is going on every single day. There's really no way to hide anything, and in the end you realize you don't need to.

For example, my current customer has been quite satisfied with the results we've been able to deliver, and I think it's largely the XP process we can thank for that. We've been honest with him, and he's appreciated that. When thing are good we let him know, and when things aren't going as planned we tell him honestly. The transparency has built a level of trust within the team that is really refreshing. Ultimately, it's better to have your customer decide to abandon a non-essential time sink of a task than to pretend everything is ok and end up delivering sub-par quality.

If XP is wrong, I don't wanna be right

At the end of the day, XP isn't a perfect glowing mecca of butterflies and sunshine, but it's as close as I've seen so far. I often feel like I'm at some sort of oasis where developers have gathered after being worn out at other jobs.

It's really great to be a part of a dedicated team of people solving real problems and providing real value every single day. When you couple that with an environment of honesty and an intentional lack of overtime, you don't have to twist my arm to convince me it's where I want to be right now.

People ask me how we can survive in the economy when we bill in pairs and pay employees well. I tell them I don't know all the details, but we constantly have so much work we're turning down jobs - so something must be going right. At this point, as long as I can have a job where I get to work like this I'll let someone else worry about the rest :)

Monday, May 10, 2010

Extreme musings pt. 1

The main reason I started this blog was to chronicle my thoughts as I transitioned not only to a new job but to an entirely new development style. Since I'm approaching the 2 month mark, I figured now was a good time to check in.

To recap, I'm now doing fairly strict XP - pair programming full time, test driving everything, and an engaged customer whose job it is to manage our backlog. Previously I was doing some sort of half-assed scrum/agile where our biggest victories were having CI, sprint planning meetings, and short (2 week) releases.

Pairing

One of the biggest changes and something I've written about before is pair programming. I had done some pair programming before both in school and professionally, but only when tackling an especially hard problem. Doing it for a full 8 hours every single day is a different beast entirely.

It probably goes without saying that the most critical piece of the pair programming equation is who you are pairing with. I've had the opportunity to pair with 6 people in the past 2 months and each person has been radically different than the last. I could probably write an entire post about different pair personalities, but to keep this at a high level, I think there are 2 main points I've discovered: There are people I really enjoy pairing with and it's been equally helpful to pair with everyone on the team. (To be fair, I haven't paired with anyone I've disliked, but inevitably you'll work better with some than others.)

Obviously it sounds like it would be great to pair with the people you really click with, and it is. But I think that pairing with the other people is equally important. There are always things to learn from pairing with someone new, and I've found it's very important when working on a team to understand the position of all team members on the project. Most of the time when developing, you're spending your brain cycles figuring out how pieces of the application should go together, and the more people you've paired with, the better your understanding of the pieces will be.

Tests f-ing rock

Having a full test suite on your application is awesome. I really can't say that enough. Having a full test suite on your application is awesome. There, I said it again.

I've been writing unit tests for a few years and before doing full time BDD I always felt like I was missing an important piece of why tests are useful. I get it now. When you truly have complete test coverage of your application you are in a position of great power and flexibility. Refactoring, even scary refactoring, is suddenly conquerable. Bugs are more often "oops, we forgot about..." instead of "dude, did you even run this before you committed?!"

The thing about tests is that if you don't have full coverage, you're only getting a fraction of the benefit. It's not until you can reliably count on your tests catching any bugs that you can reach the full potential of a test suite. I do think that some tests are better than no tests, but once you hit the magical full coverage mark, it's an exponential growth in what you get out of them.

(By "full coverage" I don't necessarily mean every single line is directly tested, but that the intent of each method and class is covered. Think BDD instead of TDD, although I'm sure more "pure" TDD can have the same benefits as well.)

...

This post started to get a bit longer than I originally expected so I'm going to break it up into more parts... installment 2 coming soon :)

Friday, May 7, 2010

Good enough

When doing XP development, I've found that the notion of "good enough" comes up a lot. It's a pretty common thing to have to think about when programming, but when you're pairing full time it's something that actually gets discussed directly instead of just going by your gut or by how ambitious/lazy you're feeling on any given day.

When writing code, as with most things in life, there isn't really a black and white concept of "done". Think about mowing your lawn - the point is to get all the blades of grass to a short, uniform length. How uniform your grass must be is really a matter of opinion. Do you let the lawn mower get it relatively close? Probably. Do you go around cutting every single blade by hand with a ruler? I hope not. Do you spend double the time to trim all the edges? Probably. Do you spent another 50% more time to trim that hard to reach part behind the planter that you can only see from that one specific angle? Maybe.

This same pattern applies almost directly to software. Do you make the code meet the requirements? Yes. Do you fine tune every single line of code for the utmost clarity? Probably not. Do you make the new API's you write as easy to use as you can? Maybe.

So how good is good enough? It's always a tradeoff between time and quality. When doing TDD/BDD the test suite can help you with this balance by giving you a safety net of tests to rely on. You can code with confidence that what you're doing will work and that it should play nicely with the rest of the code base. I think this lets people make the "good enough" call earlier than they might otherwise. If your test run green and your requirements are fulfilled you're done, right?

Usually this is great - the sooner you can confidently say "good enough", the sooner you can start working on the next feature. The time/quality scale has been shifted in your favor.

However, I think this safety net can lead people into other traps as well. If you always throw the "good enough" flag as soon as you can, you've become a high risk for technical debt. If you ignore the grass that grows behind the planter for too long, it can start to take over other parts of your yard, and now you have a big problem on your hands.

This problem definitely isn't specific to test driven projects - I've seen many a code base with the programmers gasping for breath in an ocean of debt. The difference I've seen in the TDD projects is that you can actually survive in these oceans. When you have your life jacket of tests strapped to you, the waves don't seem so scary. But again, I'm not sure that is really the best thing either.

One of the major reasons for doing TDD/BDD is that you increase your velocity. You can plow forward without having to worry about the past. However, like on any project, if you don't take time to keep things clean, the technical debt you'll accrue will quickly start to work against whatever velocity gains you made in the first place. Having a suite a of tests certainly helps, but it doesn't make you immune to these kinds of things.

So I issue this plea to all developers, those doing TDD and those not: Remember to take time to keep things clean and sensical in your code and I will do the same, as someday I may be in your code base and you in mine.

Tuesday, May 4, 2010

Leave my constructors alone!

That's right, leave my constructors alone! Yes, they are mine. Why, you might ask? Because someday I might want to use them, and if they are doing anything fancy I might not be too happy about it!

Consider the following:

function Foo(bar) {
  this.bar = bar || {};

  this.refresh();
}

This is a pretty common pattern - you set fields and do whatever initialization is needed. In this case, the constructor is using a refresh method, presumably so new objects and refreshed objects all get setup with the same code.

This might look fairly innocent, but what does that call to the refresh method really do? I don't know, and that's just the point. Maybe it sets some default values. Maybe it makes a database call. Maybe it makes an AJAX request for more data. This is an important thing to know when using an object written this way, as well as when you need them for testing.

What if, for example, refresh makes an AJAX request for more data and updates this.bar when it gets a response. (This could be a likely pattern when your views are data-bound, you would initially show default or cached values and then the view would update itself when new data came in.)

Now, think of testing with Foo objects. Every time you need one you have to worry about an AJAX call being fired by the constructor. Even if you have fake responses in place this can add a lot of complexity. And what about your code? If your tests are hard to maintain, will the actual code be that much better?

Another example - what if for the purposes of a test, we needed to mock the refresh method before it is called. In the JavaScript example above that would be possible if you are using prototypal class patterns (Foo.prototype.refresh = ...).

But, what if we needed to mock the refresh method for just one instance of Foo that you're particularly interested in? Now you're in trouble. True, there are some hackstechniques you might be able to use such as changing Foo.prototype's refresh method before constructing the instance you're interested in, and then changing it back, but that might not always work.

What if your class is written like this:

function Foo(bar) {
  var self = new Base();

  refresh();

  return self;

  function refresh() {
    // Do AJAX-y things
  }
}

Now you're really screwed. How do you control the refresh method in this case? There's no way to prevent it from being called with the actual implementation. Even making refresh public by putting it directly on self wouldn't help, you still couldn't change its behavior until after the object is constructed.

I've found that when object construction is as simple and fast as possible the world is a much happier place. Use the constructors to save off some fields (this.bar = bar) and set some default values if needed.

That's it.

Nice and simple.

If you're concerned that some necessary behavior (such as calling refresh) might be forgotten, create a factory method that will wrap that up for you:

function createAndRefreshFoo(bar) {
  var foo = new Foo(bar);
  foo.refresh();
  return foo;
}

It's not foolproof since your objects could still be constructed without this function, but I think it's a worthy compromise to make.

The overarching theme here is to avoid design patterns that limit you down the road. Having any sort of complex behavior in your constructors is definitely one of those patterns and I would argue it should be avoided unless absolutely necessary.

Keep things simple. Help your fellow developers. Help yourself. And leave my constructors alone!