|
Team organisation: horizontal vs vertical. Or is it?
How is your team organised ?
In my travels through IT-land I’ve seen basically two ways of people cooperating in a team or teams cooperating: the vertical and the horizontal organisation. In the vertical organisation, one person (or team) is responsible for one functionality, from start to finish. In the horizontal organisation, one person (or team) is responsible for a common layer of several functionalities and you need each one of them to complete a functionality. As a result of Conway’s Law, this organisation is reflected in the architecture of the systems.
Each of these ways of organizing has distinct advantages and drawbacks. Many organisations go through regular flip-flops, switching from vertical to horizontal and back, only to trade one set of drawbacks for another.
Flip: vertical
The advantage of the vertical model (the integrated team) is that they have their eye firmly on the goal: delivering a useful system for the customer.
We have all seen the disadvantages: silo systems. Systems that are not integrated, have trouble exchanging information, have nothing in common, no reuse, enormous amounts of duplication. A too narrow focus on the local goal (the current system), without looking at the global goal (all systems that support the business).
All good news voor EAI consultants and vendors…
Flop: horizontal
The advantage of the horizontal model is that the people in each layer are very knowledgeable in their area and can focus on one specific area. There’s natural reuse as all applications use common layers.
The big disadvantage is that it’s hard to see the goal of the whole system. Each layer starts to define their own local goal. The local goal can be misaligned with the global goal, or even go against the global goal. Sometimes, the means and the goal get confused: framework authors try to increase the amount of framework code that is used in applications, whether the framework helps the application writers or not; methodologists start to measure conformance to process or documents instead of results; DBAs try to increase database stability by denying all change, at the expense of the applications using the database…
Beyond the flipflop
Of course, most (larger) organisations are not organized along such clear lines: there’s a mixture of horizontal and vertical teams. In these cases there’s often a tension between the two types of groups.
Thinking Beyond Lean by Michael Cusumano and Kentaro Nobeoka describes a refined and pragmatic organisation with a combination of specialists vs generalists, reuse vs uniqueness, integrated vs separated in use at Toyota since a few years. See the previous entry for a more extensive description.
If I can choose, I prefer to start with a vertical organisation, because they have a clear idea of the goal. Then factor out commonalities. Get the different teams, one by one, to communicate with each other, to find commonalities and ways to share useful resources.
With a horizontal organisation, it’s important to make the global goal clear again for everybody involved. One effective way to do this is to create a “virtual crossfunctional team” for the duration of the project. Get the layers to communicate with each other, preferably using a “pull” model, where the layers closest to the customer request services from the layers further away.
Been there, done that!
With the exception of one case, I’ve always worked in “vertically” oriented, customer and delivery focused groups. In the one horizontal case, the goals of the group actually ended up working against the global goal.
Tomorrow, I start to work for a “horizontal” team. More stories will surely follow.
Note to self: keep your eye on the goal!
The one without a bug.
I just don’t seem to learn, do I?
Daddy, where do bugs come from?
My project manager wanted to know where all the bugs came from. Well, there’s this stork and… Yeah, the “Bug Stork”…
Well, no. We make mistakes and introduce errors into our programs. We had a lot of errors. We had so many, we needed a database to keep track of them.
Were some modules more error-prone than others? If so, why? That’s what the project manager wanted to know. He had written a script that counted the number of lines in each module and divided this by the number of bugs assigned to this module. He was going to make a graph of bug density. That would tell us where to concentrate our effort, because we couldn’t fix all the bugs.
He asked me to help him debug his script, because something was going wrong. His script always threw a “division by zero” error when calculating #lines/#bugs. We discovered that there was one module with zero bugs! Clearly, a requirements error: nobody expects a zero-defect module!
The perfect module
Which module had no bugs? Who was the super-programmer who had implemented this perfect module?
Turns out that this module was written by M., a programmer in my team. It was the first thing he ever wrote for the company, fresh out of school. His later work was riddled with errors, like everyone else’s. What had happened?
As M. was new and this was his first programming job, I was asked to mentor him and help him find his way around our code, so I had a pretty good idea how this module was written.
The recipe for a perfect module
I divided the project into small pieces. Before starting on each piece, M. and I would discuss how we could implement it. M. would then go off to implement a bit, asking me questions whenever something was unclear.
When M. had written a piece, we’d go over the code. M. would explain the code to me and I asked questions and gave feedback. Often, the fastest way to explain what I meant was to take over the keyboard and change a bit of code or write another bit. And then M. would change something. We would rework each bit of code until we were happy with it and it worked. And then on to the next small piece.
And what have we learned from this?
It took a lot of effort on my part, effort that wasn’t being put into productive work. But the goal was to teach M. how to code independently.
After that first project, M. didn’t need any more handholding. He could now implement modules on his own. I could go back to my real work: writing and (most of all) debugging modules. Now, we could each work on our own modules. That’s a lot more efficient than two people working on one module.
And things were back to normal: neither M. nor I ever wrote a (even remotely) defect-free module ever again… That’s how it’s supposed to be, isn’t it?
Into the heart of darkness. And back again.
I just don’t seem to learn, do I?
Don’t touch anything!
The previous story told how I did one last project before I left this company. This project involved customisation (for one customer) of the way data was acquired and processed by two applications. In the past, when I changed these applications, I would always introduce errors. My project manager’s motto was “If it works, don’t touch it!”. As if this application was a house of cards… Unfortunately most of the code didn’t work. I had to change some critical code to implement this customisation.
There be monsters here!
Why did I get this project? Probably because no one else dared to take on this project. The main part of the coding would be deep in the bowels of the applications, written long ago. It was like a dark, dank, dangerous dungeon nobody dared to enter. There had been some stories about people going in, but they hadn’t been seen again.
Test yourself!
This feature was intended for one customer. The number one requirement was that for all other customers, the results should be totally compatible with the previous versions of the software. Our customers needed to be able to compare new measurements to their historical data. Hmmm, how could I be sure that my changes didn’t introduce any incompatibilities in the resulting data? This piece of code processed megabytes of data as they came in from the data acquisition hardware. I would never be able to verify its correctness by hand.
Who can verify this data fast enough? The application, of course! If it was fast enough to process the data, it was fast enough to verify the data. I restructured the affected code to look like this:
Cleaning the dungeon
At first, “Changed code” was a copy of the original code. As expected, the “Compare” stage indicated that there were no differences between the two streams.
This code was a real mess: it was hard to understand, full of low-level C pointer manipulations, long functions, function names without meaning, 1 or 2-letter variable names… To understand the code, I started to make small changes. After each small change, I would re-run the application with test data to verify that I hadn’t introduced any incompatibilities. If anything was broken, I undid the change.
After a few days of making these small changes, I had transformed the scary dungeon into a light, airy, cosy little room: the code was now simple and easy to understand. It gave the same results as the original disgusting code. No monsters had been seen or harmed during this transformation.
Now I could implement that feature. It was extremely easy and only took me a couple of hours. I used the same technique to verify that my changes were compatible if the feature was not activated.
And what have we learned from this?
This time I had learned something: you should always have tests for your code. On the next major project, we wrote a whole set of tests that exercised the code we were writing. The test called all of our methods with certain test data and print out the results. I looked at the output and see if everything was well. I ran tests every day, so that we discovered errors early. I was the TestRunner.
When I left that project, nobody ran the tests any more. It was too difficult and time-consuming to run the test application and interpret the results. They might run it once in a while if there was a serious bug, but the test was finally forgotten.
And things were back to normal: people were scared to make changes, bugs weren’t caught quickly, more bug reports came in from testers and customers … That’s how it’s supposed to be, isn’t it?
One for the road
I just don’t seem to learn, do I?
I quit!
After working for a few years for this company, I decided to leave. I had to negotiate with my manager and the HR guy how long I would have to stay on.
The manager proposed that I stay on until I finished “Project X”, a customisation of two of our products for one of our biggest customers. At this company we had a habit of starting projects with many, unclear feature requests and then piling on more features as we were developing. We were all too busy with frantically churning out code to notice the whooshing sound of the deadlines as they flew by. We felt like Mr Creosote, being fed one “wafer-thin” feature at a time, until we exploded. If past performance was an indicator, it would be at least a year before that project would be done and I could get out.
We finally agreed that I would stay on another 5 weeks, the legal minimum. I would do as much of Project X as I could in these last few weeks.
An offer he couldn’t refuse
I asked the product manager to select the few most important features that would satisfy the customer AND that I could implement in a few weeks. He was not amused; he wanted “everything”, as usual. My final offer: “either you get some features OR you get none. It’s your choice, I’m off in 5 weeks in any case”. He grumblingly took the first option and complained to everyone who’d listen about “those developers getting uppity”.
We selected a set of features that was both feasible and provided the customer with a coherent implementation of their requirement. The metaphor we used was: “This is like a software patch panel, so that the customer doesn’t have to waste time manipulating the wiring on the hardware patch panel.”
The knights who say ni no!
Everything had gone smoothly: no features had been added during development. Not that the product manager didn’t try, but I could now afford to say no. Everything had been done according to the company’s process, including all the documents and documentation. I had worked at a relaxed, leisurely pace and yet I had accomplished more than on any other project at that company. In the process I had refactored a particularly nasty piece of code (more on that later) and created a reused piece of code.
4 weeks later…
The product manager performed the acceptance tests. He grumbled about all those missing features. He found a few small errors. We found a major oversight in the requirements: the UI didn’t indicate how the “patch panel” was (re)wired, which was very confusing. Oops!
Next day, I fixed the small errors and we performed the acceptance tests again. Passed.
Around the process in one day
Next day, we discussed how the “wiring visualisation” feature should work, I adapted the specification document, adapted the design, modified our MVC framework, used that to update all affected UIs in both applications and we performed the acceptance tests again. Passed. We had just gone through our whole development process in a single day.
Done. That left me two days to say goodbye to everyone and buy the drinks and snacks for the farewell party. This the most fun AND productive project I’d ever done at that company. And it was the only one that finished on time. I should have quit more often!
And all those extra features? They were never implemented.
And what have we learned from this?
I left for bigger and better things. Well, not bigger and not always better, either. I still scheduled based on features. I still believed that the customer needed all the features they asked.
And things were back to normal: deadlines slipped, goalposts moved. Developers got demotivated. Except for the small (1 month or so) projects… That’s how it’s supposed to be, isn’t it?
I’ll take this task. I’ll take that task
I just don’t seem to learn, do I?
Getting a bit of a reputation
We saw here how soldiers signed up for tasks to create our division’s schedule. We expected this method to give us an easier way to create a stable and fair schedule. And it did. After a while something else happened. Our division started to get a reputation for reliability, punctuality and trustworthiness. We’d always show up on time for tasks and perform them as required. No fuss, no complaints. Our schedules were reliable and credible. It was our schedule, our responsibility to implement it well.
Sometimes, this good reputation worked against us. If you’re the duty officer and you need some more soldiers to complete a work team, where would you look for “volunteers”?
The first rule of this team is: no shouting!
We did have to educate the NCOs (non commissioned officer, the guys ranking above soldier, below officer). In NCO school they got taught that the only way to get soldiers to do something is to shout at them. We didn’t like to be shouted at. Each time we had to deal with a new NCO, we would explain these simple rules:
- You don’t shout. We can hear you perfectly.
- You don’t threaten. You can’t scare us, because we know the rules and regulations as well as you do. Or even better. In a routine, rule-based culture he who knows the rules, rules.
- You tell us what needs to be done, not how.
- In return, we’ll perform the task efficiently, without any fuss.
- That way is easiest for both of us. You know it makes sense.
Most of the NCOs learned the lesson quickly. Some never did and found that dealing with us was very time consuming and tiring. So, they started shouting more and, as a result, found us getting even more tiresome. But if they asked us to perform a task, we would self-organize to get it done quickly.
The dishes are clean? Wow, that’s novel!
The quality of the work increased. For example, when you’re cleaning dishes, it doesn’t take a lot more effort to actually make them clean. We all like to eat out of clean dishes don’t we? These were still the same boring, mind-numbing tasks. But if you sign up for a task, you might as well do it right.
This was unusual. Up until then, soldiers would do the least amount of effort they could get away with. If something wasn’t done right, that was someone else’s problem. Someone else has to eat out of the dirty dishes you failed to clean. You had to eat out of the dirty dishes someone else didn’t clean well.
And what have we learned from this?
Back in the real world, tasks were assigned to me and my teammates. When I led teams, I would assign tasks and tell team members how to perform them. Luckily, I was rarely shouted at. They teach you a lot a stupid stuff at PM school, but not something that stupid.
And things were back to normal: people did their jobs, they were committed. But without “hustle“, without that bit extra where you think about what you do and don’t just do it. That’s how it’s supposed to be, isn’t it?
|
|