Saturday, March 31, 2007

Code Retrospectives

I bet that most of the people who read this blog have been through a code review at some point - a session where a bunch of people get together, look at a piece of code, identify all the things they consider problems and document them. Then the developer goes away and fixes all the problems.
Usually these reviews are relatively infrequent, time consuming, and exhausting. The focus is on finding errors and correcting them, and I know that when I was having my code reviewed this way I found the process quite stressful as well.

I think this model of reviews is pretty much broken. These days I want to get "code reviews" done at least a few times each hour, whether there's anyone else around or not, and the only way to get that is to use automation. In the Java world, tools like Checkstyle, Simian and Complexian provide a wealth of checks - far more than a human team could check in any reasonable amount of time. And despite the names these checks aren't just "style" checks - they help you enforce metrics thresholds as well (which is a separate discussion). Plus there's much less emotion associated with feedback from an automated tool, and the tool has infinite patience.

Once significant chunks of what's covered by traditional code reviews have been handed off to automated tools, the humans are free to use code reviews in a different way. Instead of looking for mistakes, the team can look for opportunities to learn. Accept that the code is the way it is, that everyone was doing the best they could at the time, and review the process that created the code rather than the code itself, all the way back to the root cause. Certainly you'll find some things in the code that must be fixed before you move forwards, but lots of things will be tolerable if you can fix the process so that they don't recur.

In this context, "process" is a broad term - it includes the way you hire people, the training you give them, the tools, the incentives, the requirements; anything that might impact the final code. The Toyota "Five Whys" can be a good way to get to the root cause. (make some note in here)

At this point we've transcended code reviews - what we're doing is far more like a retrospective, focussed tightly on our code. Although retrospectives are usually associated with ends of iterations and releases, we can use code retrospectives much more often.

So instead of treating your code reviews as opportunities to find the mistakes that your colleagues have made, switch to code retrospectives and improve the process that created the code.

Thursday, March 29, 2007

Design Improvement to Design Patterns

Marty ran the Design Improvement workshop last weekend - another full house and another good day. There are some pics on the wiki, and also some blog posts from attendees.

The next workshop is Design Patterns on May 19, and we're really lucky to have secured Andy Bulka as the workshop leader. We've already got four people bidding, so if you're interested you might want to get in now.

Saturday, March 24, 2007

Commenting on ideas

I had this email exchange with a friend, and since it's related to change I thought I'd share it (plus it means I don't have to write a separate blog entry!).



Steve,


We have discussed giving feedback before and that when you start to
give it your automatically
at odds with the person receiving it.


For example, they present a shape that is a triangle and you
believe a square is better, so
suggesting a different shape automatically suggests that they are
incorrect and those that
also have supported the triangle or have not suggested another
shape are also somehow
incorrect. At least this is how I remember you explaining it to me.


Given that your at odds with the person receiving the feedback, is
there any way to give it
in such a way as to lessen the possibility of it being taken
negatively?


I could try the feedback sandwich approach but do you have any
others that you use with
success ?


If you think the feedback will not make a difference do you suggest
keeping quiet, even if
you think your expected to speak up ?




My reply:


Feedback is incredibly difficult, and success or failure can depend
as much on tone and body language as the words used.


First, you need to accept that they may be right and you may be
wrong. I guarantee that whether you accept this or not will come
across somehow. I've used to ask leading questions, until someone
pulled me up on it, and I now I try to make sure that words and
thoughts are a bit better aligned - questions when I'm in doubt,
statements when I'm not.


Maybe the first thing you need to do is better understand why they
used a triangle - "I thought of something different - can you tell
me why you used a triangle?". When you can echo back to the other
person why they used a triangle, and they nod or agree throughout,
then you're on a good track. Then rather than just say "a square is
better", maybe you can say "ok, I understand why you used a triangle,
but I'm concerned about these things as well, and I think that a
square addresses those concerns".


It's quite possible that neither the square or the triangle address
all the concerns - that you've each uncovered some overlapping issues
and some unique issues. Or you've uncovered the same issues, but have
given them different priorities. There may not be right and wrong
solutions, or even outright better or worse.


Although I don't always speak up myself, I don't think it's healthy
to stay quiet when you're asked for feedback, if you have feedback
related to the matter on hand, not general feedback like "I think
you're an idiot"! The times I stay quiet are when I don't think I can
present the feedback appropriately, perhaps because I don't have the
verbal skills, or perhaps because I'm agitated by something at the
time. I certainly need to get better at this myself (this is a case
of do as I say, not do as I do). Try not to offend people, but the
decision about whether the feedback will make a difference doesn't
really belong to you.

Thursday, March 22, 2007

Drawing the reader in

I read a lot of material - some short, some long. A lot of it is mandatory work-related reading, so I can get quite selective about the remaining pieces - if you want me to read something, you need to convince me. I'm willing to give you some of my time upfront, but that may be less than 5 seconds (I kid you not). If what I read in that period seems interesting then I'll give you some more of my time, but even then my commitment isn't open ended; you need to continually convince me to keep going (at least until I can see the end in sight). So how do you do this?

You should be able to see the solution in a typical newspaper article. The article probably has this structure:

  • the impact of the story is captured in the headline;

  • the first paragraph gives a summary of the whole story;

  • the next few paragraphs expand on the first paragraph, but still omit details;

  • the details are contained in the main body of the article


Each reader should be able to read until they've got the level of detail they need - they shouldn't be forced to read from beginning to end just to get an overview.

We have the same problems whenever we write a document presenting something complex (especially when we need someone to make a decision based on the material), and particularly when we write a resume. Make sure that the first few paragraphs contain some sort of summary, something that will convince the reader that it's worth continuing. If a resume starts with the details of the candidates current job, it better be a very interesting job, and if I'm your reader you've got less than 5 seconds to convince me. Bullet points are easy for me to scan in that time; dense text isn't. As you increase my interest and commitment, you can be more demanding of me and I'll be more tolerant.

When you're working on the web you have other structure you can work with as well. Maybe you can build something with Javascript so that the details are available only when the reader asks for them; in that case you don't need to adopt the linear, gradual descent style of the newspaper, you can make the details available wherever they're needed. You can also present sidebars, summaries and pictures that might not have a place in a text only, paper based document.

You may or may not need to give the reader a sense of closure. If you need a decision or an action, you need to make that clear early on, but you should also restate it at the end of the work. You might also benefit from a summary of the main points, related back to the original introduction. But for something like a resume you can probably get away with "here are the rest of the details" - it's expected, and the reader knows they'll only be interested in some of it, but you still should make it easy to pick one point from another.

Be conscious of this approach - see if you can spot in what you read, and bear it in mind when you're writing. Eventually you'll refine it until the transitions are seamless, and your reader will never know why they find your work so interesting!

Thursday, March 15, 2007

Building a store

I just finished watching the video of Building the Store from ClickableBliss, which explains why Mike Zornek build his own web store, and what he learned.

My notes from the presentation:

  • ELC Technologies RoR::PayPal - not a complete interface, doesn't provide express checkout, which is essential

  • vPayPal gem : never got it to work, seemed to have deficiencies, used as a reference

  • Tobias Lutke's PayPal gem - not specific to websites payment pro, related to instant payments

  • ActiveMerchant : couldn't get certain things related to PayPal to work, code submitted by contributor, not maintained. But it's now 1.0 and may work better.

  • SOAP : not used SOAP before, but was the eventual solution

  • These experiences were from about August 2006.

  • If you're going to accept confidential information in a Rails application, make sure you don't log it:

    class ApplicationController < ActionController::Base
    filter_parameter_logging "password"
    filter_parameter_logging "credit_card"
    end



Sorry if I'm cryptic - the video is worth watching :-)

Quicksilver

My Quicksilver education continues. I watched the Merlin Show on using menu items from within Quicksilver (episode 8), and thought it was a great idea (especially for Textmate, which I'm also trying to learn). But when I tried out the example in my QS, it didn't work; at least not at first. So here are the prerequisites for getting menu items to work:

  1. Activate "Enable Advanced Features" in Preferences -> Application

  2. Activate the "User Interface Access (+)" plugin

  3. Make sure that "Enable access for assistive devices" is selected in OS X System Preferences -> Universal Access. I don't have this enabled by default because I use iKey during training courses and it only works if access for assistive devices is turned off.


Hopefully that's it! But if not, Howard Melman has written an excellent Quicksilver User's Guide.

Monday, March 12, 2007

Design Improvement bids close this Friday

A reminder for anyone considering the Design Improvement workshop that bids close this Friday. We've got 12 distinct bidders at the moment, so if you're interested you should probably make a bid near your final limit rather than trying to be tactical about it.

Also a little advance warning - we're looking at running an EAT Design Patterns workshop in May, so watch out for that or let me know if you're interested in getting mail when it's announced.

Thursday, March 8, 2007

Upgrading to Webgen 0.4

I use Webgen to build my website, and I've just finished upgrading to the latest Webgen release, 0.4.2, from version 0.3.8, which was over a year old. It was a bit of a pain, and the Webgen documentation is a little lacking, so I thought I'd share my experiences.

First, I could see that I needed to change the format of my block declarations in my content pages from


blocks:
- {name: content, format: textile}
- {name: sidebar_heading, format: textile}
- {name: sidebar, format: textile}


to

blocks: [[content, textile], [sidebar_heading, textile], [sidebar, textile]]


Not a big deal, though I needed to do it in every file (I need to find a way to get rid of this duplication). I thought that would be enough to get me running, but to my surprise every page generated the message "Invalid structure of meta information".

The problem was that my files (originally created in Windows and now living on my Mac) had lines ending in \r\n and Webgen didn't like this. Things worked better when I changed each file to have lines ending simply in \n.

Next I had to replace references to block content in templates from from
{block_name:}

to
{block: block_name}

After that I was 90% of the way there, with all the standard stuff covered. The next step was to handle two places where I'd used included content.

Webgen 0.4 changes the order of the steps in the evaluation of page files. The new order is:

  1. convert to HTML;

  2. then ERB;

  3. then webgen tags.


In earlier versions I believe the steps were performed in the reverse order. This change in ordering broke some of my "custom" code, where I was including common Textile content into a number of pages by reading it from a file via ERB. Since ERB is now run after the conversion to HTML from Textile I was getting the included Textile content rendered as HTML without translation.

One thing I was using this for was to include a common sidebar. However Webgen now supports nested templates, and that's a better way to solve the common sidebar problem. I now have a template that looks like this:


---
template: ../default.template
--- content
{block: content}
--- sidebar_heading, textile
Services
--- sidebar, textile
<div class="training">
* <a href="{relocatable: eat.page}">Easy Access Training</a>
* <a href="{relocatable: index.page}#softwareDevelopment">Software Development</a>
* <a href="{relocatable: index.page}#coachingAndMentoring">Coaching and Mentoring</a>
* <a href="{relocatable: index.page}#training">In-house Training</a>
</div>
For enquiries regarding any of our services, please <a href="mailto:info@cogentconsulting.com.au">email us</a>.


Pages that want the common sidebar use this template and only need to provide the body content.

The other thing I was using an ERB include for was to provide a common set of textile link aliases (things like [three_rivers_essay]http://www.threeriversinstitute.org/steve%20hayes%20essay.htm). These need to be in the same file as the textile source at the time it's converted to HTML which is before either ERB or tags are handled, so it looked like I was out of luck. My solution was to write my own tag, called "site", which provides the same sort of functionality. A reference to the tag looks like {site: three_rivers_essay} or {site: {name: three_rivers_essay, text: "a different piece of text"}} - I'll include the plugin code at the end of the post.

It's good to see Webgen in active development, I like nested templates, and it's quite easy to write plugins. It would be good to see better documentation (hopefully that will come from the new activity as well) but Thomas Leitner provides excellent support via the forums.





class SiteTag ["Suncorp-Metway", "http://www.suncorp.com.au"],
"three_rivers_essay" => ["software tyranny", 'http://www.threeriversinstitute.org/steve%20hayes%20essay.htm']
# and so on
}
infos( :name => 'Custom/Site',
:summary => 'Return standard sites and labels')
register_tag 'site'
param('name', nil, 'The name of the site that will be linked to')
set_mandatory('name', true)
param('text', nil, 'The text that will be displayed for the link')
def process_tag(tag, chain)
return self.link
end
def link
name = param('name')
definition = @@definitions[name]
raise('Could not find site named ' + name + ' in ' + @@definitions.to_s) unless definition
url = definition[1]
text = param('text') || definition[0]
return "<a href='#{url}'>#{text}</a>"
end
end

Wednesday, March 7, 2007

Maven doesn't work for me

I sometimes joke that I don't know anything at all, I just know people who do know things and ask them what to do. The joke is that this is partly true - in software development it's impossible to know everything, so it's important to rely on people you trust. Which brings me to Maven 2.

I've had a number of people that I respect recommend that I start using Maven 2, so I thought that I would try it on a project that's just starting out. On the other hand, I heard from people on related projects that they'd tried it without success. No problem, I thought, I've got access to some people who have used it, who have a fairly good idea of what I'm after in a build, and I'll be able to get some guidance from them. Given that I had conflicting advice and I was the one advocating Maven, I decided I should do the implementation myself rather than delegating the potential pain to someone else, and that's what I did.

I've spent a day and a half on this and got something that's working ok, but when I get to work today I'm going to back it all out and go back to the Ant-based approach that other teams are using. Why? Because although Maven 2 may work, I can't make it work the way I want it to (the "I" in that sentence is quite important).

First, I love the Maven 2 dependency mechanism. It's great, and even though Maven doesn't rock my world the experience has encouraged me to go and look at Ivy (though that's in the future). My problem is that Maven 2 wants me to conform to its view of the world, and that doesn't match what I want to do. That would be fine if there were plenty of hooks to let me do it my way, even if that was expensive, but either these hooks are missing or the documentation on how to use them is nonexistent or inaccessible (and it's probably a mix of all of these).

So what do I want my build to do that's "non Maven"?

  1. I want to run separate unit and integration tests in one project, and have reports (test results and coverage) for both of them, and I only want to run the tests once to get it. There is a note in the documentation that says that Cobertura will force the tests to run twice and that this will be fixed in future, but every configuration I tried ended up running the tests even more than this.

  2. I want to be able to package the code with instrumentation, run integration tests using this code in a WAR, and measure the coverage.

  3. I want Checkstyle (and Simian and Complexian) to run over all my code, including the tests


I tried separating the integration tests into a separate module and deploying a jar from the "core" module to the integration module, but that didn't give me coverage of the integration tests because the code in the jar wasn't instrumented. The alternative seems to be to compile the code again so I can run the integration tests over it - this seems like a great big hack, and seems to predict more great big hacks down the way.

The idea behind Maven 2 is great, and if you're happy with the outcomes that's great, but the current implementation and documentation doesn't provide the level of customisation I'm looking for.

If anyone has a POM that handles the three points that I would like in my build, than I would be more than pleased to receive it and blog about my experiences using it. I want Maven 2 to work for me, and it's disappointing that it doesn't.

Tuesday, March 6, 2007

Tasmania Trip

Not long ago I had a week's vacation in Tasmania. If you're interested you can read a little more on my personal blog.

Monday, March 5, 2007

Carbon offsets follow up

Following the post on carbon offsets I received an email from Climate Friendly. I'm impressed that they're watching the blogosphere (my wife hates that word), and that they're willing to participate in even small discussions like ours.





I've read the discussion and wanted to mention that the approach that Climate Friendly takes to the issues you're discussing is to communicate a complete message covering efficiency, renewables and offsets plus advocating very strong government policy. For example a number of our customers have a Prius, run their home on Green Power and offset their car emissions, while others do whichever of these they can afford today. Our interest in promoting efficiency is evidenced by the fact that we have many of Australias leading energy efficiency companies, engineers and architects as customers. Picture sof the buildings they have designed are in the URL below. One of these cut emissions 60% by efficiency measures and then used our GreenPower plus carbon offsets to achieve Climate Neutral status. We are very active promoting the achievement of Climate Neutrality through a combination of efficiency, GreenPower and offsets.

My contribution to the more general question of how offsets can be meaningful in an overall context is summarised in an article sent to New Internationalist regarding their article last year about carbon offsets.
URL is
http://www.climatefriendly.com/pdfs/climate%20friendly%20-%20%20Reduce%20Renew%20and%20Offset%20strategy.pdf

This covers voluntary action but we need regulatory action too, urgently.

An article advocating strong government policy is available at http://www.climatefriendly.com/newsletter/goodpolicy.php

Kind regards
Joel Fleming | Managing Director | Climate Friendly

By the way for our emission calcs we are very careful to use the correct emission factors for the baseline case that our projectrs avoid.
For the NZ wind project the carbon credits are based on an "Avoided" gas power plant ..which creates a very low quantity of credits. This means that if you buy carbon creidt from us its not overclaiming by using "brown coal" baseline.


Friday, March 2, 2007

Presentation at Melbourne Patterns Group

I'll be doing a presentation on the Visitor pattern at the Melbourne Patterns Group on Wednesday. I've attached the announcement below (cutting out the bit that said what I was talking about - oops!).





The next patterns group meeting will happen on March 7th at the usual time and location: 6:30 pm at ThoughtWorks Office, Level 11, 155 Queen Street, Melbourne 3001. Parking should be
available near the building.

Please let me know if your coming for the meeting so that I can arrange for the pizza. You can rsvp by forwarding this email to sreeni@gmail.com. Since the building entrance is locked from 5:30 pm, myself or a fellow ThoughtWorker will be patrolling the entrance between 6:30 and 6:45 to let people in. Please call me at 04 3396 3725 if you are left waiting.