Jul 292013
 

If I have a criticism of the agile movement it is that not enough time is given over to the role of management, and furthermore not enough care is taken over the distinction between project and line management.

In a study by VersionOne that looked to asses the reasons for failed agile adoptions, almost all could be traced back to reluctance or failure to engage on the part of management and little wonder when the role of leadership is left so ambiguous.

Gil Broza recently wrote a book entitled the Human Side of Agile that aims to address the human aspects of agile implementations, in particular offering practical guidance to how an agile team leader might incorporate these ideas into their role.

Prior to publication, Gil asked that I contribute an anecdote and I was only too happy to oblige – the chapter was on the subject of making the most of your immediate environment. I drew anecdote from my old office where space was in short supply.

It may not always be possible to create the perfect working environment, however it is important to make the most of what is available. My team were looking to map their work flow using a white board and sticky notes. Unfortunately we were situated in the middle of an open plan office without access to walls, nor did we have the necessary space for a for a free standing white board. In the end we bought a roll of white board sheeting and applied it to a nearby structural pillar. Work items flowed from top to bottom and space was tight, but it served our purpose and is still in use years later.

Elsewhere in the book Gil also references How to do Nothing.

Great stuff Gil.

Jul 212013
 

Why do sales guys find it so hard to pay an engineer a compliment?

Imagine this exchange

Jeff: Hi John, how was your weekend?

John: Great, I ran the London marathon and finished in 3 hours dead

Jeff: That’s amazing I can’t believe you managed to run all that way!

Jeff is trying to pay a compliment, but because he has such little idea of what John considers to be important he misses the mark and if anything is more likely to have caused offence.

Now take this into a professional environment. Jeff is a superb engineer, he sweats and bleeds over his code, he does this quietly and in the background, he takes pride in his work and just wants to see people benefit from using his systems. No-one outside of the engineering org really notices his impact because, due to him, everything ‘just works’  with almost zero drama.

One day he receives a request from John in sales who needs him to twiddle knob X, it’s a config change and he has it in production later the same afternoon – really nothing special. That said Jeff has really helped John out  and John is very genuinely grateful. He writes him an email thanking him, he even cc’s his boss. “Jeff I really appreciate all the hard work you put into twiddling knob X, it’s guys like you crushing the knob twiddler that make this company awesome’. Now Jeff should pleased, it’s nice of John to take the time, he recognises this, but it’s a terrible compliment since Jeff took no pride in the change and what’s more it’s clear from John’s email that he has no idea what Jeff does all day – if anything the mail is a de-motivator despite John’s best intentions.

So what should John have done, how do you compliment an engineer? The best possible way is to take the time to understand some of the complexities of their work, and thereby uncover some of what drives them and their passion.

This is of course uncomfortable and frustrating, a bit like trying to write with your weaker hand – the benefits are huge though. Let’s forget for a second about expressing thanks being a nice thing to do  – it also a way to influence and build trust across the organisation.

If as an individual, you can build trust and rapport in multiple parts of the org, you much better placed to get things done – especially when you really need a favour to get you out of a jam.

In this example, I’ve used a Sales guys and an Engineer, simply because I see this as the classic case, but it applies equally in reverse. It’s easy (and lazy) for an Engineer to dismiss Sales or Marketing as brainless – when in reality this attitude is simply highlighting ignorance of what it takes to be successful in these fields.

The point of this post? Try and figure out what those folks with the suits and nice hair are actually doing, it will benefit both you and your company. If they are open to it, try and share some of your stuff too.

On the flip side insults work in the same way, you might enjoy Professor Douglas Comer‘s essay  ‘How to Criticise Computer Scientists’

Jul 152013
 

So I want to tell you about a chap called Rob Ashton. I don’t know Rob but he appears to be extremely excellent. Having got a bit narked off with his enterprise consultancy gig, Rob decided to toss it all in. Without a firm plan in plan in mind, Rob decided to make an offer to the world – anyone willing to cover his expenses could have Rob come and work for them for free. Initially I think the plan was to stick to Europe but things seem to have got out of hand and Rob got all over the place. You can read about it here.

Rob was very strict on the whole ‘not receiving payment’ thing, noting:-

I was offered pay for a number of roles while I was doing this, and turned it all down because I felt it would sully what I was trying to do. Also – I felt it would muck up the balance where the people I was working for really wanted me to be happy because it was all they were giving me.

And this me thinking, companies want to hire the best people they can. As a means to achieve this some companies come to the startling conclusion that if you want to hire and retain good people you need to be prepared to pay for them.

But this isn’t enough. Staff can only be as effective as the company allows them to be. If the company culture stifles productivity and those same staff, while more productive that others, are still not able to fully deliver.

What’s worse is that the company doesn’t realise this is happening, no company deliberately aims to clamp down on productivity. Things tick on the way they always have done, the star hires perform well relatively speaking, and staff stick around because taking a pay cut is difficult. So the warning signs are less obvious.

An interesting thought experiment would be to ask yourself

What would happen if you staff worked for free, what would you need to change?

Let’s ignore the practical implications of this statement, all I’m saying is, if you take money off the table what would keep your staff wanting to work at your company? This isn’t about extra perks and a ball pool, I’m including all extrinsic motivators. This is about identifying what it is about your organisation that demotivates, and identifying how the organisation could improve intrinsic motivation.

  • How would your approach to flexible working change?
  • How about performance review and professional development?
  • Most importantly, what would be the implications for your org chart?

The answers will highly dependent on context, but if we make the assumption that in many cases the goals of the staff member and company are aligned, then why wouldn’t a company want to act on the conclusions?

I think we are starting to see the results of this already in the form of a shift towards flatter hierarchies, ad-hoc work groups and acknowledgement that people are more important than process. Some companies lead the way such as Valve and Gore but any company could benefit from asking themselves this question.

Jul 072013
 

Darth Who?The value of Annual Reviews is a contentious subject, just ask Microsoft. In my view, so long as they are kept separate from pay reviews and form just a small part of the overall act of providing continuous feedback, I can see some value in them as a means to discuss long term progression.

A few years ago my company re-wrote our review template – I was concerned that my team might not take a great deal of interest in the new form, and heaven forbid, might not even read it before the reviews came about.

I felt that everyone would get more from the process if they had some idea of what to expect and how to use the template, so I filled in the form detailing the annual review that no doubt occurred between Emperor Palpatine and Darth Vadar in the aftermath of the original Stars Wars.

I share it here simply because I wish there was more HR material in the world based on Darth Vadar and Emperor Palpatine.

For those of you who consider the annual review to be an outdated process, bear in mind that this happened a long time ago in a galaxy far, far away.

Part 1: Overview of Role and Recent Projects

Vadar writes:

During the past six months I have focusing on the construction of the Death Star with a view to using it as a tool to dominate the Galaxy. The project is extremely complex and I worked closely with key stake holders to ensure that the design and subsequent deployment match business goals and directives.

Separately I have been working closely with the Galactic Fleet to isolate the crush what remains of the Rebel Alliance. This has involved detaining and interrogating key figures as well as embarking on an extensive search across the out reaches of the Empire.

Palpatine writes

I concur with Vader’s comments. It’s also worth noting that Vader has been actively recruiting and restructuring the Galatic fleet leadership team.

Part 2: Performance Overview

Objective #1 – Deliver a fully functional Death Star

Vadar writes:

How well did I perform against this objective?

I delivered a fully operational Death Star, which passed all user acceptance tests. It is true that the delivery was delayed and I put this down to the project management techniques employed in the early stages. Towards the end of the project I took a much more hands on role implementing a more iterative and incremental approach to delivery. In doing it was possible to gain rapid feedback and ensure that value to the customer was maximized. Furthermore I made some tough decisions over poor performing members of the management team, introducing them to my ‘claw of death’.

Next Actions

I consider this objective complete, though note that following the destruction of the Death Star, we may need to build a new one.

Palpatine writes:

I agree that a functional Death Star was delivered. I am pleased that I was able to set a vision and direction and that the manifestation of that vision became a reality. I am also very pleased with the aesthetics, it almost looked like a real Moon.

While I was disappointed by the late delivery of the project I am much more concerned how such an obvious vulnerability found its way through the design reviews. I would have expected that this would have been picked up pretty much form the off. I am also deeply concerned by how it became possible for the Rebel Alliance to steal plans for the Death Star such that they were able to exploit the weakness. Furthermore the destruction of the Death Star has damaged our reputation as a Galactic force – how a single manned fighter was able to implode an entire space station is the stuff of science fiction.

Objective #2 – Crush the Rebel Alliance once and for all

Vadar writes

How well did I perform against this objective?

It’s fair to say that the Rebel Alliance cannot be described a ‘crushed’. I am happy with my overall approach, the Empire is very much in control of the Galaxy and the Rebel Alliance have not been able to secure an outpost, meaning that they are forced to move from temporary base to temporary base to evade a the might of the Galactic fleet. I feel strongly that it is only a matter of time before I have them trapped. That said I failed to account for key figures within the alliance, as well over looking a key vulnerability in the Death Star itself.

Next steps

I will embark upon a Galaxy wide search for the relocated rebel base, and continue with the aforementioned crushing

Palpatine writes

I agree that your general approach was thorough and methodical. I would have like to see more outright annihilation of innocent people but overall I am pleased with your execution.

Where I am less pleased is that you failed to adapt your plan to take into account key events, specifically the rebel attack on the Death Star and Luke Sky Walker’s ability to evade attack. It is unclear to me why you were not able to land a direct hit even when pursuing him along a narrow trench and supported by two of the finest pilots in the galactic fleet.

Part 3: Overall Rating

Vadar writes:

3 out of 5 – Effective contributor

Palpatine writes

2 out of 5 – Low Contributor, I feel that your overall performance was not up to the standard that I would expect from a Lord of the Sith.

Part 4: Feedback on Galactic Empire Inc

Vadar writes:

What I enjoy most about working here? I really like the almost unbounded opportunities to inflict misery and despair on pretty much anyone I like.

One thing I would change about Galactic Empires Inc. I think we need to review the weapons issued to our Storm Troopers, they seem faulty and rarely inflict any damage at all.

One thing I would like to see remain at Galactic Empires Inc. I think that our uniforms are pretty much the best in the industry. This is especially true for the Storm Troopers

Part 5: Future Development/Business Goals

Vadar writes

What I do well: Inspire terror in others.

What I want to improve: Despite being a master of the dark side of the force, I am still unable to consistently smite Knights of the Jedi.

How I would like my career to develop over time:Long term I’d like to move into a Supreme Leader of the Universe role

Palpatine responds

I agree with Vader’s comments, in particular I am keen to help him to improve his smiting skills. While I do not see Vader’s wish to move into Supreme Leader of the Universeship as unrealistic, such roles do not come up often.

Part 6 – Objectives

Objective #1: Create a new death star

Next Actions: Review the design docs to remove unlikely failure modes   Time frame for achievement:  This coming October

Objective #2: Crush the rebel alliance

Next Actions:  Discover the location of the rebel base Time frame for achievement: Next April

Palpatine summarises objectives:

Long term, Vader is looking to rule the entire universe, I see building the most devastating weapon ever created and crushing the only viable opposition as key stepping stones towards this goal.

Part 7: Record of discussion arising from the review discussion

Palpatine summarises

During the meeting we discussed my rating of Vader’s performance. While disappointed he understands that the loss of the Death Star played a big part in my overall decision.


Remember kids, appraisals should be:
  • Separate from pay reviews
  • A small part of a wider mechanism to provide staff with continuous
  • A two way street

I thought that 7 Digital had some good things to say on the subject

Jun 302013
 

Welcome to my getting started with Web2py tutorial.

This tutorial assumes very little on the part of the reader, some knowledge of a programming language will certainly help, but if not don’t worry. I’ll take you from installation through to v1 of your application.

If you don’t want to copy from the tutorial, the full source is hosted on github.

Last time we created the Models as well as the Controller and View for the home page. The next page to look at is the Wall. The Wall is specific to a given user and contains their profile details as well as their weet history.

Wall_reduced

As before we start with in the default.py Controller, add the following method to manage the behaviour for the wall.

# show user's wall, showing profile and posts
def wall():
   #Determine which user's wall is to be displayed
   user = db.auth_user(request.args(0) or me)
   #If user is invalid, return to the home page
   if not user:
       redirect(URL('home'))
   weets = db(db.weets.posted_by==user.id).select(orderby=~db.weets.posted_on,limitby=(0,100))
   return locals()

The first thing to do is determine whose wall it is that we need to display. The line responsible is worth a closer look.

user = db.auth_user(request.args(0) or me)

We have already seen db used as a means to access the database but we have not yet come across ‘request’. Request is an object available to all Controller actions and provide details of the http request that instigated the Controller action being called.

In this case we check the first (technically the zeroth) argument of the request. An argument is best described by example

http://127.0.0.1:8000/witter/default/wall/myargument/myotherargument/

In this specific instance the argument denotes the user id and so the line in question checks if a user id has been specified, if not it assumes that the requester are themselves logged in and trying to access their own wall. If neither case is true then the browser is redirected to the home page.

After that we pull out all the weets for the given user and return local variables, which are then made available to the View.

We will need a new View file called default/wall.html. As before you can create it via the application admin page.

Replace the default code with :-

{{extend 'layout.html'}}
<h2>Profile</h2>
{{=crud.read(db.auth_user,user)}}
<h2>Messages</h2>
{{for weet in weets:}}
<div style="background: #f0f0f0; margin-bottom: 5px; padding: 8px;">
<h3>{{=name_of(weet.posted_by)}} on {{=weet.posted_on}}:</h3>
{{=MARKMIN(weet.body)}}
</div>
{{pass}}

We’ve met crud before, it provides a nice high level abstraction to access database information, in this instance we are using it to pull the profile information about the user. The next section loops through all the weets generated in the Controller and presents them in chronological order – this very much the same logic as we saw on the home page. You can a look for yourself at http://127.0.0.1:8000/witter/default/wall or just navigate there from the Witter home page using the navigation bar at the top.

Search

For the grand finale let’s look at search.

The purpose of this page is to allow a user to search for their friends and then follow them. In some senses it is the simplest of the pages, but as we shall see it contains some interesting functionality behind the scenes.

Firstly, let’s take a look at the Controller, add the following to default.py

# a page for searching for other users
@auth.requires_login()
def search():
   form = SQLFORM.factory(Field('name',requires=IS_NOT_EMPTY()))
   if form.accepts(request):
       tokens = form.vars.name.split()
       query = reduce(lambda a,b:a&b,
                      [db.auth_user.first_name.contains(k)|db.auth_user.last_name.contains(k) \
                           for k in tokens])
       people = db(query).select(orderby=db.auth_user.first_name|db.auth_user.last_name,left=db.followers.on(db.followers.followee==db.auth_user.id))
   else:
       people = []
   return locals()

The first thing we do is create the search form, we do this like so

SQLFORM.factory(Field('name',requires=IS_NOT_EMPTY()))

The SQLFORM.factory can be used to generate a from an existing database table, or, as in this case can be used to generate a form from scratch. The form is very simple and takes a single input ‘name’.

The rest of the Controller handles the action once the input has been received  – this is what the follow is checking for:-

if form.accepts(request):

The remaining code searches for the the search terms amongst other users registered in witter and plugs them into ‘people’, it also determines which of those people the user already follows – the View is going to rely on this follower information.

The Search View

So far so good, now let’s take a look at the View, you’ll need to create a file called default/search.html under the Views section. Replace the default code with:-

{{extend 'layout.html'}}
<h2>Search for people to follow</h2>
{{=form}}

{{if people:}}
<h3>Results</h3>

{{for user in people:}}
<div class="row">
<div class="span3 offset1">{{=A(name_of(user.auth_user), _href=URL('wall',args=user.auth_user.id))}}</div>
<div class="span1">
{{if user.followers.followee:}}
<button onclick="ajax('{{=URL('follow',args=('unfollow',user.auth_user.id))}}',[],null);$(this).parent().html('Unfollowed')">Unfollow</button>
{{else:}}
<button onclick="ajax('{{=URL('follow',args=('follow',user.auth_user.id))}}',[],null);$(this).parent().html('Followed')">Follow</button>
{{pass}}
</div>
</div>
{{pass}}
{{pass}}

Much of this will now be familiar – we pull in the standard template, then the form and then iterate over the ‘people’ (if any) returned by the Controller. Where it get’s interesting is the button definitions.

Firstly we check if the searched for user is already being followed by the search, this means the button can offer to follow unfollowed witterers and unfollow the followed. So far so good, but what does this do?

<button onclick="ajax('{{=URL('follow',args=('follow',user.auth_user.id))}}',[],null);$(this).parent().html('Followed')">Follow</button>

Before I can answer that I need to explain about AJAX. AJAX stands for Asynchronous JavaScript and XML, but this name is largely misleading since it needn’t be asynchronous and needn’t use XML. In short AJAX is a technique for creating dynamic web pages, it allows pages to be updated without needing to reload the entire page, and it does this by exchanging small amounts of information with the server behind the scenes.

Strictly speaking I could have passed on using AJAX in this tutorial, but it is a really useful technique a very simple to implement.

In layman’s terms the button definition says, when the button is clicked make a poke to another Controller action called ‘follow’ and send the arguments ‘follow’ and the user id. Once this is done replace the button (which read ‘Follow’) to be some text that read ‘Followed’.

A final note about the search View is the use of the css classes ‘row’ and ‘span’. These are provided by Bootstrap which is a a popular front end frame work. Bootstrap is not part of Web2py but Web2py does support it out of the box. In this tutorial I’ve deliberately avoided focusing on the look and feel of the app, but Bootstrap provides all the tools necessary to create an attractive web application.

AJAX Callback

And that’s it for the , however, what about the follow action in the Controller? We’ve not implemented that yet. Here goes, add the following to the default.py Controller:-

# this is the Ajax callback
@auth.requires_login()
def follow():
   if request.env.request_method!='POST': raise HTTP(400)
   if request.args(0) =='follow' and not db.followers(follower=me,followee=request.args(1)):
       # insert a new friendship request
       db.followers.insert(follower=me,followee=request.args(1))
   elif request.args(0)=='unfollow':
       # delete a previous friendship request
       db(db.followers.follower==me)(db.followers.followee==request.args(1)).delete()

The most interesting line is the first one.

if request.env.request_method!='POST': raise HTTP(400)

When a browser makes a request to read a web page it uses an HTTP method called GET, this is exactly what you do everytime you point your browser at Google. There are however other HTTP methods, POST being one of them, POST is used to transmit that is expected to change the state of the application. The AJAX call that we initiate in the search,html View is a POST request.

Since this Controller action is there solely to support AJAX calls from search.html, it does not expect to handle HTTP GET requests and rejects them. You can try this for yourself by trying to View http://127.0.0.1:8000/witter/default/follow which should result in a blank page and a error message complaining of a ‘bad request’.

Search

Right so there we have it – all pages are complete, in order to try out the search and folllow/unfollow functionality you’ll need to register to extra users and have them follow each other. Be sure to notice that it is not necessary to refresh the search page every time to make a follow/unfollow request.

So in conclusion what have we achieved?

We created a new web2py application called Witter, created three pages (and an AJAX method) supporting a home page, a user wall and a user search and all backed by a database that will persist the data over time.

Are we done?

Well perhaps, I certainly am.

This tutorial has taken you from nothing at all to a functioning web2py application, that can be extended as you please.

If you are searching for ideas, you might want to move the search functionality into the home page and extend it so that search covers all weets (much like Twitter does). The UI could certainly do with a spruce up (and there are plenty of CSS tutorials out there) and as a final task you could put the thing live, gain awesome traction (due to your custom tweaks) and take over the social media world.

Feedback on this tutorial much appreciated, I’ll leave you with some useful links.