Trust is the highest form of motivation. It brings out the very best in people.
– Stephen R. Covey, The 7 Habits of Highly Effective People
It’s basically a sacred project management mantra by now: divide your work into tasks that are as small as possible. Estimate them with your team. Then drop them into the all-knowing product backlog. But no one seems to be looking very critically at how this practice has affected the software engineering profession. Back in the 90’s, when I started programming, this was not how it worked. It was, dare I say, a little more professional.
Back then, your boss had a dozen or more things they were responsible for and when you got hired they breathed a deep sigh of relief.
“Finally, now that Vincent is here, I can make him do A and B; and with Ted doing C, D, and E and Jan doing F, G, and H, I can finally get to I, J, K, L, and M.”
Most importantly, A and B were big things, like whole products or large system libraries. Building and maintaining them consumed all of your time. They were your delegated responsibilities, not mere tasks. It wasn’t that hard to manage people this way either. If you weren’t doing a good job, the boss would let you know.
“Hey, Vincent, A isn’t turning out quite like I was imagining. Can you do a little more of this — and definitely more cowbell.”
Then you went back to your private office (I sure miss private offices, but that is a topic for another day) and fixed a few things. Later, in a weekly status meeting you would tell people how it went — yep, that’s right, no daily stand-ups where you look mournfully at your shoes and admit that you didn’t make any notable progress yet.
No backlog grooming meetings or burn-down charts either. Your manager simply looked at how your products were coming along. A little trust, some accountability, and a healthy portion of “give me some space to do my work.”
The way we work now is different. Sadly, it’s less motivating, less efficient, and profoundly less respectful of individual abilities.
As I see it, little tasks are born of a fundamentally different management attitude. Small tasks are a not-so-subtle way of saying that all the product vision lies with management. Keep away. Don’t touch.
While larger tasks send a completely different message. Here, management is giving you bigger pieces to chew on, inviting you to mix some of your own creativity with the end product. You get to do some design work, think about what the customer needs, and take pride in what comes out the other end. Sure, the organization has an overarching strategy, but they still want people to take on responsibilities, not just errands. They trust you to align with the overall vision and because you feel like you are part of the “club”, you actually want to.
Small tasks have also taken hold because they fit nicely with the age-old assembly-line mentality. Sadly, there are armies of managers that still live by that dogma. For them, it is all about picking metrics and optimizing them — management by chart and graph.
Unfortunately, little tasks in Jira (or any of the dozens of other issue tracking systems out there) bring the promise of a whole host of tasty new charts and graphs: burn-down, burn-up, velocity, lead-time, cycle time, task age, throughput, failed deployment, flow and control. It’s as irresistible as candy to a baby.
But, assigning responsibilities instead of tasks takes away an assembly-line manager’s favorite tools. Because they are larger, responsibilities can’t be so easily measured and tracked. And so, metrics-managers will fight tooth and nail to keep your processes laser focused on dividing and cataloging your work into tiny, little traceable instructions.
Sadly, as developers, we do it to ourselves as well. Once someone gives us a better title, we are right on board with the program. When a regular developer might have had a chance to do some research or design, we immediately snatch it away for ourselves.
As technical management, we standardize our frameworks, languages, deployment operating systems, and cloud service providers. We write wrappers around networking, logging, and monitoring libraries and demand they always be used. Then, after we have taken the task of designing and researching the CI/CD tools and pipeline, we write coding standards for our coding standards.
Worse yet, we design every product’s architecture, and expect any deviation to be approved by us first. All that is left are tiny morsels. Grunt work for the foot soldiers once the fun has been stripped away.
Poor front-line programmers are left wide-eyed with empty bowls, asking “please sir, can I have some more? I just wanted to design one little service. I know I am not worthy, but can I please just write my own sql queries without using that awful ORM? PLEASE?”
Sadly, when those poor programmers finally seek promotion, hoping for their first real shot at higher level engagement, they are rebuffed: “You don’t really have any design experience I am afraid. We are looking for someone who has designed large systems.”
To their managers they could rightfully reply, “that was your doing, not mine!”
There is a grave misconception circulating that if you just sit down, in a comfy conference room chair, and split a project into tiny tasks, small enough to be individually estimated accurately, then when you add them up, Viola! You’ll have a highly accurate estimate for the whole project! Easy peasy.
There are two problems with this ill-fated plan. First, no task, even a small one, is easy to estimate. I have seen many “tiny”, one-day tasks blow up into week long campaigns. All because of hidden complexity that comes popping out like a Pandora’s box once you start coding on it.
Second, when you divide work into little tasks, before actually working on any of them, you are making untested assumptions. Many of them. The more tasks you define, the more facets of a hypothetical design you must assume (implicitly of course, since no one ever writes design assumptions in task descriptions). Soon, you’ve created a long chain of design choices, all depending on previous ones, sitting on sticky notes on the wall.
The problem is, as soon as you start working on one of them, you will undoubtedly realize that some of the implicit design decisions it depends on are totally wrong. Now, not only will you spend MUCH more time than was previously estimated for this task, but all other tasks that depend on its faulty design are now invalid. The whole house of cards comes tumbling down. Time for another all-day backlog grooming session? What a waste!
Back in the day, before everyone realized that software companies were positioned to make lots of money, we had some elbow room. We had a lot of responsibility and the ability to make a lot of decisions. But now, a lot more people have piled onto the island. Unfortunately, some of them have slowly chipped away at the domain of the software engineer. One by one, descending from their vessels they planted their flags:
“I am Amerigo, the product guy. Heretofore, no developer will make product decisions, for they are mine.”
“And I am Ferdinand, process guy. Heretofore, no developer will make process decisions, for they are mine.”
“I Bartolomeu will enforce compliance.”
“I Vasco used to be pretty good at Microsoft Access, I guess I’ll be the database guy.”
One by one, until every responsibility that wasn’t actual open-up-emacs-and-start-typing-stuff programming was taken away, forbidden even. And then, the remaining, purely technical tasks were carved up by architecture/standard hoarding engineers, hungry for something of substance. Only dry, broken carcasses were left scattered on the ground.
Of course, there is a solution to this predicament — delegate responsibilities to everyone, all the way down to the bottom of the hierarchy. Or better yet, flattening or abolishing the hierarchy all together. But until that happens, you’ll just have to content yourself with measly for-loops and if-statements — following the coding standard of course.