Archive for the ‘apprenticeship’ Category

A Craftsman’s Legacy

Tuesday, April 13th, 2010

I’ve been thinking a lot recently about legacies, the things that we leave behind, things that out live us. The very nature of our business doesn’t leave much room for lasting legacies, sure you have legacy code, but that in itself often carry’s negative connotations. Rarely do we celebrate our old code, the fact that those cringe worthy snippets are actually serving as a reminder of how far we have come. Ok, so you previously wrote huge controllers, large complicated methods, overused design patterns and violated every best practice going. But now you know better, you’re well versed in the ‘Fat Models, Skinny Controller’ mantra, you refactor to design patterns when necessary and you abstract those large methods. Legacy code is great. But thats not the point of this post.

I want to explore our lasting legacy beyond code. Unfortunately every line of code we write will be refactored, replaced and removed at some point. The great software we write today will become obsolete tomorrow, replaced by some better, faster, feature-rich app. Or it loses it’s relevance in a sector that changes so rapidly. For me this is worrying, what will I leave behind? Is my code destined to live on only in the archives of the internet, left on a few old hard-drives, eventually no longer able to run or compile. The answer is probably yes. I don’t believe my lasting legacy as a software developer (craftsman) lies in code, but in the people I will meet, my future apprentices. Our only tangible lasting legacy is what we impart into other people. They will watch us, question us, learn from us. Some of our habits will become their habits, our tools will become there tools. If we mentor them right, they will go on to impart into other people and so our legacy continues.

I have only recently embarked on my apprenticeship and already learning a huge amount. The time spent pair programming, chatting and socialising with Chris is already shaping the craftsman I will become. James and I will no doubt mentor others in the future, the things we have learnt from Chris as well as our own experiences being passed on to our apprentices. Our legacies living on…

Introducing Testy

Sunday, March 21st, 2010

Both Richard and I have been set a rather daunting new task by our mentor Chris: to implement, in Ruby, a web server compliant with RFC 2616 (sans caching and the Accept header). To successfully complete the task, we must be able to serve static HTML pages to a modern browser, but we get bonus points for other content types and, in Chris’ words, “super bonus points” for interfacing with Rack. One catch: we’re only allowed to use the standard Ruby libraries to complete this, no gems allowed.

As my implementation must be test-driven and I can’t use Test::Unit, the first part of the challenge is to build a simple test framework. Luckily, I already have one just lying around! Aimee and Spencer both had to build test frameworks for their first apprenticeship task and it sounded like an interesting challenge, so in a spare hour or two I created testy.

I tried to keep testy simple: it only has an assert method, which checks whether the given expression evaluates to true. I may add more later as I need them. Failed assertions raise an exception that is caught by the TestSuiteRunner. This is an easy way of stopping execution of the test and providing debug information.

The TestRunner takes a directory on initialisation and loads every file in the directory. I wanted to avoid forcing the same file name and class name for my test suites mainly to allow more than one TestSuite per file. This makes it possible to use multiple TestSuites in the way one can use “describe” blocks in RSpec files. To accomplish this, each time TestSuite is subclassed, the suite is registered at the TestSuite class level using the Ruby self.inherited hook. This may come back to bite me later as it’s not very flexible, but at least it’ll get me started.

And just because I was playing around I added some features that, while not strictly necessary, should make development a bit easier:

  • Any exceptions are caught and processed as a failure to stop the whole suite from bombing out.
  • Added a setup method to the TestSuite so that shared setup of tests can be extracted.
  • Pending methods, just because it was easy after writing the assert method.

The next step is to finish reading RFC 2616 and then decide on how to begin. I imagine I’ll be playing around with Ruby sockets for a while, but more importantly I’ll need to be thinking about what and how I’m going to test this application. As I’ll be outside of my comfort zone of RSpec and Cucumber, it may be time to reevaluate how I test my code.

Attending Corey Haines’ excellent Code Retreat at Bletchley Park got me thinking about how I approach TDD. I naturally tend to write more complex code than is required for the functionality I’m building, so I find it quite hard to slow down and really think about what I’m trying to achieve: am I breaking my tests down into small enough units of behaviour? Am I really doing the simplest possible thing to make my tests pass?

I also need to give some thought to how granular my tests will be. Cucumber advocates an outside-in approach to development, but what if integration tests really are a scam as J.B. Rainsberger asserts? How much value does automated testing of larger parts of an application really provide?

And then there’s Rack. Is it simpler to ignore Rack because YAGNI, or will I be shooting myself in the foot if my design just doesn’t fit the Rack paradigm easily? I’ve yet to be really convinced that architectural changes can be driven out from small refactors as new requirements are added: are there some things that just need to be considered up front?

Lots of questions, but no easy answers. I’ll be blogging about some of them as I start to flesh out the answers myself. In the meantime, any feedback or thoughts about testy or any of the questions raised here will be gratefully received.

Presentation of my apprenticeship task

Sunday, February 21st, 2010

Here is a presentation i made to some of my colleagues on friday explaining my first apprenticeship task, my wiki, how i went about it, the problems i encountered and what i learnt from the whole experience.

See my Apprenticeship task presentation on youtube.

BBC Talk on A Philosophy of Software

Sunday, February 21st, 2010

Video of a talk I gave recently at the BBC about the nature of software development. We discuss craftsmanship, apprenticeship and the limitations of university education, amongst other topics.

Watch the video here:

Licky wiki news

Thursday, February 4th, 2010

Just a quick update on licky, my little wiki apprenticeship task i’m doing. I realise that time has gone on and i haven’t talked about it as much as i might, plus i actually have some quite encouraging news to report now!

Last time i wrote, i was just starting to work on Pages and a PageFactory to find them or create them as necessary. Since then i’ve added a persistence strategy which saves wiki pages to the filesystem. I pass the desired directory to the strategy so that test pages can be kept separate from real pages. This was necessary as i wanted to clear out the test directory every time after use and i didn’t want to accidentally delete real pages.

After that little burst of progress i stalled for a long time as i knew i needed to start writing the web interface and i didn’t know where to begin. James gave me a good idea which was to set up a simple Webserver class that would wrap around the web server of my choice. I have chosen WEBrick for the time being, but it shouldn’t be too difficult to swap in another one later, probably with another strategy pattern. James suggested i start by visiting a page and looking for the text ‘Hello world’. I thought this was a good idea and so i started finding out about WEBrick servlets.

With that start i was suddenly able to leap ahead, testing and implementing everything i need so that my wiki is now able to create, show and edit pages through the web interface. I feel as if i am very close now. Possibly the only thing left to do is add a way to link between pages and then i can truly call it a wiki.

Test driving the development of this whole project has been extremely educational. I know i started off getting too involved in writing a test framework, so Enrique pulled me back and made me think of the simplest thing that could possibly work. I began with one method: assert_equal. That was enough in the beginning. As time went on i added two more methods: assert_true and assert_contains. When necessary i added useful debugging information to report failures. At the appropriate time i refactored the testing framework into a module that could be included into multiple test classes.

I know i also started thinking about the web server too early. I started off trying to work with ERB and templates, as i am familiar with Rails, and in the end all i needed was a few servlets. As Enrique made me realise, the most important part of a wiki is not that it runs on a web server. The most important thing is content. Pages, with content, saved to a file system. Having focussed on that and got a real solid, well tested mechanism for saving and retrieving pages, i knew that the WEBrick servlets could rely on the underlying framework, and when the time came, it did not let me down.

Driving out feature ambiguity

Friday, January 15th, 2010

Cucumber features are very useful. The ability to spec out what the customer wants in detail in a format they can read and understand really helps to communicatate what needs to be done. This combined with the ability to execute the feature to ensure that it is completed correctly catches many bugs and incorrect assumptions.

However there is one area of bugs that features don’t catch so well, and even cause to some extent. These bugs are built right into the text in the form of ambiguity, sometimes through the constraint of features being executable.

This came up recently in a conversation with James and Enrique at Eden Development about James’ apprentice task, the Snakes and Ladders Kata. It turns out that the text of one of the features runs against the commonly understood way that Snakes and Ladders works:

Scenario: Win the game
    Given player 1 is on position 97
    And player 1 rolls 3
    Then player 1 has won the game

Question: is that a valid scenario? Given the commonly understand rules of Snakes and Ladders, you cannot just start on position 97. Implementing it as written complicates the domain model.

How do you implement the first step? Do you go for a simple:

Given /^player (.*?) is on position (.*?)$/ do |player, position|
  @game.set_player_position(player, position)
end

The potential issue with this is that you are exposing a method that in real life won’t get called, just to set up a test. It’s also tying your model down to a particular structure, by implying that the game stores an arbitraty position variable for a player. This might not be the best way to model the problem.

The other option is to change the scenario such that the “Win the game” is tested in a similar way to the following:

Scenario: Win the game
    Given a game is started with two players
    And the following dice are rolled:
      |3|
      |4|
      |5|
      |5|
      (etc.)
    Then player 1 has won the game

That satisfies our understand of Snakes and Ladders, and gives us more freedom in our domain model. In this case, we simply modify the agreed scenario in the code and sidestep the problem.

Right? Wrong.

The important thing to remember is that the customer is always right about how the software should behave, even when it violates our commonly understood assumptions about the world. The software they want you to build might require a different implementation of Snakes and Ladders. They might have a 3 year-old daughter they’re planning to play the game with, who always wants to be given a headstart. In this case, we’ve not delivered what they want, simply because it makes life easier for us. We’ve let our assumptions and our concerns for good design drive out the features, rather than letting the features drive our design.

There’s another possibility: when the customer wrote this scenario, they simply used “starts on position X” as a shortcut and don’t really care if it’s possible to do this in real life. In this case, we can work with them to write the scenario so as not to cheapen our design for the sake of easier feature writing.

The key insight: there’s no way that we can know which it is from reading the scenario. We have to ask the customer and drive out the ambiguity in the feature.

We mustn’t let the necessary constraints of executable features build ambiguity into your conversations about what the customer really wants. And we must be constantly talking to the customer all the way through the iteration, especially if they’re not on site.

You might think “It’s only Snakes and Ladders, what does it matter?” It matters a great deal: situations like this come up regularly in real life projects. Practising how to deal with these issues and the conversations that result is one of the many powerful things you gain by doing katas.

What’s your take on the above problem? Have you come across it in real life?

Last one of 2009

Thursday, December 24th, 2009

Today is my last working day of 2009, this last year has flown by! I did briefly contemplate writing a blog about the things that I have learned this year, but soon realised that would be crazy, there has been so much. This time last year I had been a Ruby developer for 3 months, on top of that I was learning Rails, TDD/BDD, Agile etc. I also distinctly remember what the last week (of 2008) in the office was like, I got to see first hand what happens when the technology that should be working for you, starts to work against you. The technology we were using to store our data was falling over frequently, the delivery date for the iteration was looming and important decisions had to be made. Stick with it and try and make it work? or migrate over to something a little more tried and tested? We went with the latter, because of good design decisions and practices.

That week I learned the value of abstraction, had we had tied our data model code too closely with a certain technology we would have been in trouble. Despite being a bit of an inconvenience the move over to the other technology was relatively easy. The other lesson I learned was to take the last week of the year off :) So that’s what I’m doing.

Bringing everything back up to the present, this week has been good all-in-all. Monday afternoon was the time that I ran through my first apprenticeship task with disappointing results. We were asked to do a Binary Search code kata in Ruby and RSpec. The kata was successful in that the tests I wrote lead me to a solution, the way in which I approached the tests was wrong… very wrong. I approached the problem how I would with any new model I was creating, I started to spec how I wanted the code to behave. This challenge differed slightly from your day-to-day client project, in that you are trying to drive the development of an already-designed algorithm. All I really needed to do was to drive an initial set of assertions and then develop a suite of tests to cover the other edge cases. There was no real need to test every line of code. By doing so you only tie yourself down to your implementation. What if you were asked to implement the algorithm using a different approach, you would have to throw away all your code and most of your tests. Waste. If I had written a suite of tests that covered exactly what the outcome should be, I would only have to re-write my code, using the same tests to confirm when it was complete (all passing). Very important lesson learned, thanks James and Chris.

So i’m going to spend some time running through my kata again until I get it nailed. It has also inspired me to spend some time learning how other people do TDD. I have realised over the last year how different everybody approaches TDD, it is very rare to find two people who completely agree on how best to write tests. Everybody has their own styles and practices, and thats a good thing, as long as the code is tested well. Over time i’m sure i’ll develop my own style and practices, but always remaining open to change.

Have a great Christmas and New Year! See you in 2010!

A Model for Life

Thursday, December 17th, 2009

17 December 2009

Its nearly two weeks since Todd gave me my first apprenticeship task:

Assignment: To logically model an individual’s life from the perspective of a parent instructing their child guidelines on how to make decisions to maximize happiness.

Requirements: Your model of a “Life” can be as extensive or granular as you wish to take it. There is generally no wrong answer, other that it must reflect reality. You will be expected to defend your model and the business rules you create.

Your model must take into to account (at minimum):

  • Desires
  • Needs
  • Relationships
  • Finances
  • A State of well-being (happiness)
  • An unforeseen disaster

My son will be 2 on Monday. Its been amazing to watch him grow up and see him develop into a real character. When I think back to those first few weeks, I can say exactly what he needed and what made him happy then.

So long as he was warm, dry and fed and he had his mum he was happy - he was also mostly asleep.

Now its a different story. He still needs to be warm, dry and fed, but its no longer enough. He has to be entertained or challenged. He needs to see all the significant people in his life (coming home from work to excited shrieks of “Daddy, daddy” never gets old). He loves to visit his favourite places, play with favourite toys and watch his favourite DVDs. His life has become much more complex, and what makes him happy has followed suit.

This is how I’m going to approach this problem. I’m going to try to model a life from the point of view of a baby initially and see how it will evolves with time. I’ll continue to record my progress here.

Craftsmanship vs. Apprenticeship

Tuesday, December 15th, 2009

There’s been a lengthy discussion on the software craftsmanship mailing list over the last couple of days regarding the dangers of the Apprentice - Journeyman - Master metaphor, and how this potentially threatens to put people off the idea of software craftmanship. The responses were thoughtful and well reasoned, which showed off the general level of maturity and professionalism on the list excellently.

We’ve recently started our own apprenticeship system at Eden, and I shared a few lessons learned so far on the thread. I’ve repeated a few below, and expanded to reflect my own current thinking:

Craftsmanship is not the same as Apprenticeship. To use a computer science term, they are orthogonal: you can have one without the other. Craftsmanship is difficult to argue against and is rapidly becoming a consensus amongst a large section of our industry. Apprenticeship is a little more nascent and untested, and potentially carries more dangers. You don’t need formal apprenticeship to embrace craftsmanship.

Everyone gets to be a craftsman. Following on from this, all who want to can be craftsmen/crafters/codesmiths/whatever the most apt term is: there should be no pecking order. Indeed, the more senior among us should be taking the lower place of serving those who would learn from us. Being a craftsman is more a state of mind than a level of ability or experience.

Use verbs, not nouns. We are wherever possible using the terms as verbs not nouns in everyday use: “Richard is apprenticing to Chris”, “Chris is mentoring James”, for example. This prevent anyone “being” anything: it’s rather what you do than who you are. Those who might have a job title of “apprentice” (or not) also “mentor” others (including seniors) in specific areas they are particularly strong in.

We don’t need masters, we need mentors. We’re not taking the metaphor as far as the “master” at Eden: I just don’t think that’s helpful to anyone at the moment. All of us know people who are more experienced than us, who can “mentor” us. I say let’s just leave it at that. Rather than seeking actively seeking “apprentices” (which indirectly sets ourselves up on a pedestal), let’s be actively seeking “mentors” and passively open to “apprenticing” others who ask us. That way we’ll be helpful and inclusive, taking the lowest place at the table.

Hopefully that gives some insight in to how this language might in a professional environment. Waving loaded language around is like a waving a loaded weapon: it has powerful influence, but people can get hurt :)

We’ve purposely treaded very carefully at Eden to try and bring in the best of the “apprenticeship” metaphor without all the trappings.

What are your thoughts on the debate? Is apprenticeship useful, or are there better metaphors?

Update on my wiki

Tuesday, December 15th, 2009

Since i last wrote, i have gone in a few directions trying to get started with my apprenticeship wiki task, got a bit stuck, talked to Enrique a lot, thought a lot, and i think i’m on track now.

My first mistake was to focus on the test framework. I was pretty pleased with my given/when/expect framework, and it actually sort of worked, but it wasn’t really necessary for what i needed. In the spirit of “the simplest thing that could possibly work”, this is the bare minimum you need for a testing framework:

def assert_equal(actual, expected)
  puts actual == expected
end

My second mistake was to get carried away with making a web interface. I learnt a bit about WEBrick and how to embed ERB into a web page. That will become useful later, but it was the wrong place to start. After i had done all that experimenting, i still didn’t have anything remotely like a wiki framework!

Enrique asked me, “what is the most important part of the wiki?” – the answer is: content. If i have no content i have no wiki. So i am making it as basic as possible: creating a Page object and assigning it some content. Then i am moving on to a PageFactory that has the responsibility of finding pages. The pages may be stored in a database, filesystem, or even just in memory. It doesn’t matter for the moment. Whatever i decide to use, the PageFactory will deal with it.

My progress is now on github so you can follow along with my progress if you wish. The repository is sermoa/licky – licky meaning ‘little wiki’! :)