Thursday, May 31, 2007

From Noam Chomsky

Who always says it better than me...

"If you assume that there is no hope, you guarantee that there will be no hope. If you assume that there is an instinct for freedom, there are opportunities to change things, etc., there's a chance to contribute to the making of a better world. That's your choice."

Friday, May 25, 2007

A New Agile Manifesto?

Brian Marick makes some great points here about things that are important to agile development, but weren't the first order of business when our major concern was getting permission to do it. If the default is that agile is acceptable, Brian points out that it's essential to understand what teams need to execute agile processes successfully.

Brian's pulls are "Skill, Disciple, Ease and Joy". Parts of this resonate with something I've said to plenty of people - too many software developers consider pain to be part of their jobs. I've seen some terrible things done and excused with "it's always hard", or "it has to be that way". For change to occur, we first need to see the potential for something better ("it shouldn't hurt like this"), and then we need to be able to envision that better thing (which requires skill). And the result is frequently things that are easier to use for everyone.

The joy thing is going to be even harder though. Programmers seem to have an habit of finding someone else to blame for their pain, rather than looking closely at themselves. If you don't believe me, go read some Dilbert. Dilbert's problems are caused by Catbert, by PHB, sometimes by Wally, and he's generally the good natured, innocent bystander. Now these characters are intentionally caricatures, and I don't want to stretch the analogy too far, but I think they capture the software development zeitgeist. We'd do better if we stopped seeing ourselves as victims, and involved ourselves in finding solutions to the problems we see, especially the ones that impact us! If you think your boss is making stupid decisions, make it your business to understand their perspective on the decision - maybe you're not even looking at the same problems!

Anyway, Brian says things better than I can right now, so go read his blog.

Wednesday, May 16, 2007

Cogent, Year One

When I started Cogent I had a couple of aims, some of which were poorly articulated at the time. I wanted to create an environment that didn't have the employer/employee tension that I experienced in most workplaces; I wanted to be able to work with the people I wanted to on the jobs I wanted to, and be able to say no to the other stuff; and I wanted to create an environment that was attractive to other developers. I'm pleased to say that at lot of this has been accomplished (I can't say that I've accomplished it since lots of people have helped, particularly Marty Andrews), but I'm now also more aware of the limitations of the approach



It's been just over a year since I started consulting again. After doing some Rails and R&D work at IBS I was really lucky to be able to spend three months in Bangalore working with a Wall St bank. It not only gave me a chance to see the Indian Silicon Valley from the inside, so that it's no longer just an abstract concept, it also gave me a chance to catch up with people I hadn't seen since I left New York in 2001. Then I was able to take six weeks off, which was exactly the flexibility that I was looking for when I started consulting, and now I'm working at Sensis with a bunch of good people, including some people working under the Cogent umbrella.



Over that time Marty has gone from being someone simply billing under the Cogent umbrella to effectively being a partner in the business, which has made things both easier and much more interesting. We've got six people billing effectively full time consulting work through Cogent, and another two people billing part of their work that way. Everyone keeps the vast majority of their own revenue, leaving just a little bit for shared expenses. And I've been learning more about accounting and running a business, which has its good and bad points. That's all the good stuff.



What I've become aware of lately is that while the current business model is 'fair', in the sense that everyone keeps they earn, it has some drawbacks, the main one being that there's no financial incentive for collaboration. There's still room for altruism, and none of us are particularly selfish, but financially there's no reason for me to spend time helping someone else build up their skills, or increase the rate they can charge, especially if means spending less time on something that would help me directly. I can live with that situation, but I don't really feel good about it.



As a result, we've started (just started) thinking about different relationships people might have with Cogent, reflecting different levels of risk and independence. The model we have now is great for people with deep skills who are happy to independently find their own work and bear the associated risks. It's not so good for people who want more predictability, or who would like to work more collaboratively, or have someone who was helping them improve their skills. One possibility is a full employment model, though we'd still have our signature financial transparency and profit sharing of some sort. Cogent takes the risk of finding work and paying salaries, and gets a share of profits in return. The employee gets security and predictability, and gives up some of their revenue in return - it's a pretty traditional model at the core. But we'd expect people to eventually move away from this into a looser arrangement, where they bear more of the risk and get more of the revenue, and eventually into the associate arrangements that we have now. We'd want to have enough flexibility so that no one needed to completely abandon Cogent as their needs and contributions changed.



Early days yet. We'll have to see what happens.




Thursday, May 10, 2007

Just when you least expect it...

I rarely post about personal things on this blog, but I'm going to make an exception. What follows is an email that my wife sent to me yesterday. Jamie is our three year old son - I hope that I can just retain a fragment of the magic that he holds lightly in his hands right now, and that he never understands that you can lose it.


Tonight while walking home, Jamie asked me where the moon was, and I said, "I don't know - maybe it's behind the clouds." He said, "When I get big and go into space, I will get the moon and bring it down for you. Okay, Mummy?"Awwwwwww.

Tuesday, May 8, 2007

RailsBrain

If you need to refer to the Rails API documentation frequently, as I do, then you'll really appreciate RailsBrain.

Monday, May 7, 2007

Design Patterns - last reminder

A final reminder that if we receive enough bids we'll be closing the Design Patterns workshop to attendees midnight this Friday. Post your bids by email.

Template Methods in Java and Ruby

Template method is a pattern commonly used in Java frameworks to allow application specific configuration of a generic framework. Most of the behaviour is contained in a generic Base class (usually abstract), and the consumer provides their specific implementation in a concrete subclass that overrides methods invoked from the superclass template. Some form of dependency injection (often Spring) is used to let the application know what concrete class needs to be instantiated. Testing the concrete extension usually means testing that it invoked the responsibilities of the superclass as expected. Let's look at an example.

class Extension extends Base
{
void extensionMethod()
{
this.abstractBehaviour(someParameter);
}
}

I want to test interactions, so normally I'd use a mock, but I can't mock out the superclass. A brute force approach is to roll my own mocking by creating a new subclass for testing.

class TestExtension extends Extension
{
boolean wasInvoked = false;
void abstractBehaviour(Object parameter)
{
wasInvoked = true; // could be more complicated
}
}

public void testExtension()
{
TestExtension extension = new TestExtension();
extension.invokeFrameworkMethod();
assertTrue(extension.wasInvoked);
}

An alternative is to inject an object that encapsulates the behaviour as a strategy, like this:

class Extension extends Base
{
Extension(Implementation implementation)
{
this.implementation = implementation;
}

void extensionMethod()
{
this.implementation(this);
}
}

Then I can inject a mock or stub implementation and verify that it is invoked, and separately verify that the implementation does what I expect by injecting a mock/stub Base into the implementation. That certainly separates the two concerns, and each concern is neatly unit tested. It's also quite a bit of code. It also points us in a new direction for the framework - injection of strategy objects for the customisable pieces of code instead of using template method and inheritance.

Ruby can handle the problem using both these approaches, but there's a third alternative that isn't available in Java. In Ruby, I can directly change the behavious of the framework class.

class Base
def extensionMethod
abstractBehaviour(parameters)
end
end

All done. No new classes, no injection, and the entire application is aware of the change once the code is loaded. But how do you test it? We go one step further, and override the behaviour of just the Base instance that we are testing, like this:

specify "Should invoke abstract behaviour" do
base = Base.new
class << base
attr_reader :was_invoked
def abstractBehaviour(parameter)
was_invoked = true # could be more complicated
end
end
base.invokeFrameworkMethod
base.was_invoked.should == true
end

Of course, in Ruby you might still benefit from the flexibility of using injected strategy objects rather than a template method, but you might also be able to get away with something that is even easier than either of the Java alternatives.