Hacker News new | ask | show | jobs
Ask HN: How to break up and delegate programming tasks
80 points by efbenson 4199 days ago
I can solve development problems in my head and transfer them to code without a problem. I can design the build the whole system and pass on implemention tasks to the other senior people. However I can not seem to break the tasks up ahead of time on paper in a way that a junior or mid level developer can use to execute the tasks. Does anyone have any resources or tips that I can look into to help me be a better senior developer to the not so senior devs?
17 comments

Stop treating your junior developers like monkeys who are only there to implement your brilliant ideas. That's not their job. Every developer should be able to solve problems; the more senior the developer the greater the impact and complexity of the problem they should be solving. Your job as a senior developer is to work out the high-level architecture that will contain the solutions to the smaller problems - eg solving the highest impact problems.

My advice would be to think in terms of black boxes. You should couch tasks in terms of what the developer can expect to receive through an API and what their code should output. What happens in the middle shouldn't be anything you concern yourself with. When the junior developer works out a solution they can run their idea past you, and if it sounds OK then they write the code. And then you can review their code. The minutia of implementation is not your problem any more.

I agree with you fully, in theory.

However, you have to understand that not all places have the luxury of their junior developers being that competent. We've tried, and we've been bitten many times. I've done it a few times myself since I started managing a team. I give them responsibility, lee-way to make their little "component" how they deem (obviously sticking to basic coding standards, at least), and ample time to complete the work. Senior developers are also at their disposal to answer questions that may arise, or even plain design advice.

And even after all of that, we're left with a steaming pile of half-copy-pasted-from-elsewhere code that's been kludged together and barely works. Some of the code is just there because it was in the sample code, others are just leftovers from failed attempts. Almost as if they kept throwing code at the problem until it "worked". They don't even bother to take a cursory look at the framework method/function that they're utilizing to maybe understand what it does, if not how or why it does so.

I don't know, perhaps we're not doing something right as well. Or maybe we're just unlucky that we have quite a string of dud junior developers. Or perhaps I'm just ranting.

Code reviews. I can't stress enough the importance of code reviews to bring developers aboard a team. They are as important to junior developers as they are to senior developers. It's just that you can wean off senior developers quicker (if you wish to).

When people imagine code reviews, they imagine people analyzing code and haggling about coding guidelines. They are much more than that.

Code reviews are more about the meeting point and the excuse to talk about the software than they are about actually reviewing code. For projects less sensitive to bugs, my code reviews are not about trying to spot off-by-ones or buffer overflows. They are about discussing the problem, as perceived by the developer, possible mismatches between the developer's interpretation and the actual problem, the designed solution, how it fits the problem and how it fits the overall architecture, as well as the actual code.

The actual code review style can be as informal as an end-of-day five minute talk with each developer, all the way to the formal end-of-week review of work done. Have them fit your culture.

In the end, all that it matters, is: keep your team talking.

Perhaps I'm missing your meaning: "It's just that you can wean off senior developers quicker"

Code reviews are just as necessary for senior devs, but it's more about helping everyone to understand what just happened and why: Here's the problem, here's what I did to resolve it, here are the pieces of the system it touches.

That way at least one other developer is in the loop. Two heads are always better than one. Someone else might spot something you've missed... and worst case scenario, if I get hit by a bus tomorrow, someone else knows what I did and there's less of a chance that someone will have to spend a week wading through my code trying to reverse engineer what I just did.

The last point is really not a good one.

It would clearly be better to have the chance someone spends a week wading through your code than explaining all the changes you made to avoid that happening. You'll spend more than a week doing that.

I don't disagree with your other points, though. Two heads are better than one, and code reviews are important for a slew of reasons at all levels.

Not really. Trying to explain your code to someone else helps you understand better as much as it helps someone else to understand it. You only explain it at a high level unless there is a complicated part that you might then go through line by line.
What I mean is that if you do not see permanent value in code reviews, at least the onboarding aspect should be considered undisputabe.
We also do design reviews where I work. The good thing about this is it saves time if you fix a bug or bad implementation at design time rather than waiting for all of the code to be written.
Well, junior developers are just that: junior. That definition can range from 'just finished a coding bootcamp' to '4 years of CS with a bunch of practical internships'. Depending where a developer is on that spectrum, they may behave very differently when given a problem and a bunch of time to solve it.

For example, they might not realise that they should be looking into the framework. They may be scared to ask stupid questions because they don't think they deserve the job in the first place. They got a bit of harsh feedback from someone who didn't take their level into account, and mentioned a whole bunch of things they'd never heard of before, and now they're running around in circles panicking. But not saying anything about it.

Obviously a lot of this boils down to "it depends on the person" and none of this may be true. But here are a few thoughts:

Take a step back and think about what the expectations are and whether those are communicated at all. Assign a specific senior developer as an active mentor, and coach them on how to give constructive feedback if they aren't very good at it (it's a growth opportunity for them). Suggest reading lists, talks, and examples of best practices - including stuff that makes working on a team smoother, like source control, etc. Pair program for the first week or two. Code reviews (as small as possible), design reviews, and even giving them less freedom at first so they get confident rather than overwhelmed. Check in frequently so you don't get a steaming pile that could hopefully have been avoided :)

Out of curiosity, how do you handle things like testing, continuous integration, and code review? I have found, as I stated in another comment, that these sorts of things help quite a bit. Developers will more often than not rise to the occasion when told they need to test and be ready for continuous integration. The only thing I have found useful is to draw the line between ample time and too much time. This comes down to tasking appropriately in small chunks. If the cadence of development in the groups is that, on average, you get two things a day integrated, then I have found that engineers will ask more questions and make better decisions.
We have unit-testing for framework-level code, which is more often written by a senior developer. Continuous integration builds happen every half-hour I think, so we quickly pick up if someone pushed something that breaks the compilation or build process. Though, at that level, I should point out that quite a lot of our business code is written in python, so even basic syntax errors go through further than they should. In this department, I'm pushing for getting lint-checking via Sonarqube integrated into our CI process, which is almost production ready, but delayed.

As for code-review, well to be honest, we don't have a formal process at all. It's simply been that way since before I got here. But in my unit we've managed to get buy-in from the high-ups to start off with it in the next project. So I hope that helps us quite a bit. At least, it'll help me out as I'm currently the only one that reviews code. Every once in a while when I've got down time I go through the commits, and add TODO's and comments all over the place. I've found that it makes it quite obvious to the developer if he sees such comments abundant in their code. If it's seriously bad, I speak to them personally and explain things in detail including the "why"s.

I'll definitely see if we can maybe push for unit-testing for our business code. I'd guess that that, and the incoming code-review processes will help a bit. Perhaps they'll not fight it too much when they realize that it'll increase their quality as well as their overall skill.

Are you running into more design issues ie they didn't fully understand how to solve the problem so they are just throwing code at it? Or are you running more into code issues where the code is just sloppy?

For the first problem I would consider that after you give them a problem and they solve it have them white board it for you. Ask questions about how they handle certain edge cases or problems. If they haven't have them go back and figure it out.

For the problem with sloppy code have code reviews every few days. Just keep on asking questions about special cases, and giving advice on how to better structure code.

I agree with most of this, but I don't agree that the lead should only care about inputs/outputs when it comes to a task a given dev is working on. A lead should have defined conventions for how code in the project is written, and I think it's absolutely reasonable for that to be part of handing off a task to a junior. My approach is usually something like: "Ok Paul, I'm going to have you build out feature X, Y, and Z, defined in ticket #s 1,3, and 5, see the README about coding conventions, and let me know if you need more context/detail on any of these. I'll swing by each morning for a few minutes to see how things are going"). Then beyond talking to each team member every day, we have standups to keep everyone on the same page, on whatever interval makes sense given the complexity of the project.

I think a lead should care about how their team is implementing the features they are working on, because as the lead, it's crucial that you know the ins and outs of the system - where I think we agree though is that a lead shouldn't care about how the work is done, as long as it's done within the project guidelines (coding style, consistent structure, testing, etc.).

I agree to a point. As a lead developer, you should care about it all, but it's also your job to be a mentor. Give your junior devs just enough rope to hang themselves, but be close enough by and approachable enough so that they don't. A little pointer like, "think about this approach" or "don't use a dictionary here because..." or "generics will be your friend here, but beware of x, y and z".

You should be holding your junior developers accountable for writing tests for their code, ensuring that the test coverage is there, ensuring they understand what problem they're solving, ensuring they understand the approach they're taking, ensuring they understand the repercussions of the decisions they're making. This is how they advance from junior to intermediate and eventually to senior.

It is your job as the senior/lead developer to groom your junior devs to make the steps forward and eventually do your job. You shouldn't be telling them how to write the code. When picking holes in their code, it should be constructive, don't just to pick holes in it to pick holes in it, making them feel bad. The goal is to help them understand what's not up to par, why it's not up to par and what approach they can take to fix it. You should neither be writing code for them, nor should you be expecting they make every decision in the same way you would.

Senior devs learn a better tolerance for ambiguity, and have better ability to see the big picture in both the problem space as well as the solution space.

I encourage that sort of thinking from devs I'm mentoring.

I do this by giving creating a rapport where they feel comfortable asking questions. I do by having an attitude that part of my role is to help them be more effective. When asked a question, I drop everything to help them.

I then specifically give them problems that force them to ask questions. This in turn gives me the opportunity push the envelope with their thinking by asking them to answer their own questions.

So when I get asked a question on how to do something, I will ask them if they understand the goals and constraints we need to work in. I make sure they understand that first. Then I ask them for different ways of solving their problem, the pros and cons of each and ultimately what their recommendation is considering those goals and constraints. By that time they generally end up with the "right" answer, and sometimes something I wouldn't have thought of. What I am doing with that exercise is guiding them through the process of how to think about solving the problem. Soon when they come to me, they are already giving me options, pros and cons with a recommendation.

Sometimes I'm asked to decide about a difference of opinion between two devs. Making sure both have the same view of the goals and constraints is really important and most of the time aligning these solves the dispute. If not, then I will have one or both create a minimal test/prototype, time-boxed, that explores the problem. Then we evaluate the results together against the goals and constraints.

This has worked very well for me.

As far as breaking up tasks and delegating, it all depends on their tolerance for ambiguity. I usually start more junior devs with smaller, well defined tasks that have specific acceptance criteria. I adjust the level of definition based on their ability to succeed, but always do it in such a way that it forces them to grow.

The most important realization I had this year is that the biggest problem in software development (from the tech perspective) is not about programming, but about getting people to talk and cooperate.

I don't think you can successfully break up programming tasks for junior devs, who can then independently implement them. It has two problems:

1) You either get a lot of code with incompatible ideas, or you do a lot of coaching.

2) The junior devs are not learning as much as they could.

So you should not try to do this on your own, but rather involve the people who will be implementing the project in the process. You can still design the system in your head in advance, but I think the best approach is to then discuss it with the people on the project and come up with the final version together. Maybe somebody will have a better idea, or just tell you something you missed. As you go deeper and deeper, you will keep discovering problems on the lower levels. Some things will remain unknown or require experimentation, but for most you can come up with a solution. I think it's very valuable if everybody on the team understands the big picture. If the application has a few completely separate modules, then you can do the lower level design in different groups, but it's still useful if the task breakdown comes from the people who will be working on the code. Doing it in a meeting, rather than a write up and review process, gives them instant feedback.

Regarding the task breakdown itself, I try to think of how I'd implement all of the code myself. That means thinking about what data comes though the system and where it can be used to set code boundaries, which parts are more important and which can wait, what would be the smallest presentable version and how can I move it further after it's done, do I have some non-code dependencies (business decisions, dealing with external services). I like to draw diagrams (mainly the data flow). Sometimes tasks are simply large and you can't do much about that, but you can at least some milestones for them.

This makes sense to me in a smaller company when building some web application, probably does not make sense in a different situation. (Sorry for a long comment.)

> I think it's very valuable if everybody on the team understands the big picture.

Completely agree. This will allow the person working on this component to make trade-offs as necessary. They may also catch things that you didn't think of when building the system ie: Separate individuals working on subcomponent A and subcomponent B may realize they can share a lot of logic/configuration - no need to duplicate it.

When I'm outsourcing stuff, I like to use the "clean room" approach. I give the junior developer/outsourcer either a simplified version of the codebase, or some raw materials, and ask them to do the task I need. Then they hand me back the code and I integrate it into the full codebase.

This way they don't need to know the full system or even have access to version control; they just need to get their small goal completed, I can take care of the rest.

Over time, they can earn more and greater responsibility/access.

This may be a very unpopular approach, but it has always worked well for me. Look at the tenets of Extreme Programming and I would imagine you will find great success.

First, how to break up tasks. I write very small user stories. I aim for things that can be accomplished in half a day. This forces me to do two things. We now have smaller tasks with tangible end goals that actually produce something for the end user. These are usually easier for everyone, from management to intern to understand and follow through to completion. We also don't overthink a task, bite sized chunks are easier to digest, after all.

Second, as a few others hand pointed out, you have to trust your junior and mid level developers to complete a task on their own. Write the story in a way that they can understand what the end goal and tangible result will be. If you keep it small and discuss these openly, this will get a lot easier in a short period of time. Don't worry about the implementation details so much, that will come more in a second.

Third, (here comes the unpopular parts!) TEST! Preferably, at least in my view, use Test Driven Development. Enforce an cultural change of moving towards testing. This will document the code as much as anything and if a refactor needs to be done after a junior or mid level developer completes a task, the tests will facilitate that. It will increase your level of trust in their work as they complete tangible user story goals.

Fourth, pair program. You don't always have to, but heck after a while you might actually like it. Pairing allows you to riff off of one another. Junior and senior level developers can get a lot out of this, far more than just the junior learning something from the senior. If you are finding that your junior developers aren't "getting your style" pair for a while. You might start to understand them as well.

Finally, all of this leads to trust. Look, code bases will need refactoring. I am quite Senior and I am sure if I sat with your code, or you with my code, we would find areas where things could have been done better. Trust that if the code works and does what it needs to do according to the small tangible goals of a user story, and that when it has accompanying tests, you and others will be able to refactor it and make it even better over time.

What's the first thing? Whats the next thing? Whats the next thing?

That's the process of thinking i usually take. First, i'm gonna need a project. Then I'm going to need to instantiate a database. Then I have to create the controlling class. then I need to create the initialization. etc.

For the juniors, it helps a lot to have things more bullet point. they should be able to fill in the more minute details on their own, but do get fairly verbose. Break the work into a small logical scope, and then bullet point what needs to happen for it to be completed. And always explain why.

For the mid-level, be more general about it and have them define the tasks that will be completed. This is to give them more say in the process, enable checks & balances, and trains them to write tasks for juniors and mid-level developers when they are one day senior devs. And that's really what your goal should be.

Everything you work on is a means to make everyone below you better. If you know how to solve a problem, let someone else take a crack at it. If they get it wrong, or need some help along the way, you've already got an answer.

And of course, code reviews are an important feedback loop. But always let them maintain ownership. Its their baby. don't fix their code for them unless its more or less an emergency. Mistakes they make can often be reflected back as a failure of process, and not of themselves.

None of these are bulletproof, but try a couple of the following.

Try thinking in terms of strategies and tactics. The overall problem can be described in one high-level sentence of "what" to do. That's the strategy. That strategy can be described in one high-level sentence of "how" to do it. That's the tactic. Then that tactic can be broken down into 2-5 slightly lower-level sentences of "what" to do, which are strategies that are sufficient to meet that tactic. You may continue this for a few strategy/tactic levels. Eventually you have some medium-level strategies you can pass on to junior/midlevel people. But trust them to determine the tactic. If you give someone else a strategy and then tell them what their tactic is, you're micro-managing.

This is also roughly what a lot of refactoring and clean code is about. In a method, you don't want to mix levels of abstraction. Instead, a parent method should call inner methods that are named by what they do, while those inner methods in turn have the logic that is how to do what the method is named. And this can also continue on down to lower levels. When developing this way, you might even mock/facade some of these higher level methods/classes/functions/whatever so you can finish implementing and testing the higher level method/function/class/whatever that calls it.

A full-stack developer that hasn't quite made the jump to "architectural" thinking will often immediately and intuitively identify the lowest-level tasks that need to be done for a project, but like you've noticed, focusing on that implementation style doesn't really scale.

It takes experience, experimentation, and what works for one team or individual, may need to be altered to work for another team or individual.

I like to break up tasks into what I hope is achievable in 4 hours. Always assign yourself as much (or more) of these sized tasks than those your assigning others, if you don't want to appear that your only a manager.

Re-evaluate these sizes often. Especially with a new project, new team, or new person. Maybe due to something you did not foresee right out of the gate, this 4 hour task is really a 16 hour task. Or possibly the other developer is working hard, and learning fast, but you just misjudged how quickly they can complete it in. In this scenario, the next time it comes to split up work (or if you really over-shot, you can re-split up what you gave them) remember this metric, and size it a bit smaller.

Depending on distractions, and how well the above process is tuned, I only hope for 1 of these 4 hour issues to be completed per day, while at the same time, looking at it over a week or two average, not daily, as many programmers do not work in a predictable linear fashion.

Over time as engineers progress and grow at their craft, what they may have been able to do in 4 hours, might be 20 minutes. As you work with others you will get a feel for this, and become more tuned into other people's forte's. Not everyone is good at CSS for example, even if you know how it works. So its not just about skill. The longer you work with people, the better you will get at carving out tasks that work for you and for them, and for the team.

So in summary, experiment with it, give yourself as much work, and in the same manner you delegate tasks to others delegate tasks to yourself. Re-evaluate the size of these tasks often, and try to create tasks that others can get done in a reasonable amount of time, so that they get the feeling of completing something.

Not everyone can be given a big gigantic month long task and not get lost in it, and on the other hand, tasks smaller than 4 hours, really start to feel (and take the energy) of micro-managing. The more senior the developer that has proven they meet goals on time and communicate well, these can be relaxed a bit, and you might find someone really prefers 2-3 day sized tasks, but can also be reliable in this manner.

Finally, ask them. You might be surprised.

There is one key point missing in this discussion, though spotman sort of alludes to it: You cannot do this because you haven't, yet. You will be very poor at this until you have done it a few times. Eventually you will be good at it.

Delegation is a skill. Matching problems to the capabilities of team members is a skill. Accurately recognizing the capabilities of team members is a skill.

These are all skills you can acquire, but they are all skills that you will do more or less poorly on unless and until you have sufficient practice.

You will also be very slow at it until you have practiced a while and gotten better. So you must recognize that at first productivity will decline, because it will take you longer to delegate than doing it yourself.

Is your work environment reasonably "safe"? (Yes, I do mean that in the "touchy-feely" emotional sense; this is important (not trying to dismiss the idea, just using glib humour to forestall inevitable negative comments - some people are uncomfortable recognizing we have emotions and are affected by them...)).

If so, take your team out to lunch, off site. Tell them what you want to do: Delegate more. Tell them why: So the team gets more done, so there isn't a single point of failure or just one person on the critical path, so that junior members can grow into senior members, to challenge people's abilities, to make better hackers.

Next, tell them that this means you need to practice chunking, delegating, managing, etc., and it will take time for you to get better at these things.

Now ask for their help. Work as a team to do these things.

Note: You may also need buy-in from your management before you proceed. They may view this as a risky change, if they like how things are. Depends how supportive they are.

This is a great question! I find that the act of explaining the problem itself helps a great deal in figuring out what the pieces are.

It's totally okay to just talk to a developer about the problem and start sketching out your ideas, without necessarily knowing the specific tasks that you're going to assign.

The abstraction level of the tasks that you should assign will also come out of the level of discussion you're able to have with the person. Everyone has different abilities/amounts of domain knowledge/available time/etc., so there is never "One True Task List" for implementing something; it must depend on the developer.

Finally, it is deeply motivating for the person who's going to do the work to be an involved part of the planning discussion. It's important to anyone to have a certain amount of autonomy in their work, and making them be a part of planning is a great way to do that.

I'm a big fan of old fashion modules are flow charting.

Start by flow charting your program, divide the task into a group of single statements tasks that can be described without the words, "and", "or", "but", etc. If you need to use those words, you need to chain tasks or make decisions.

After several revisions (3-4) you should have a nice overview of what the program should do, and how it will do this.

Selected tightly interacting objects, and combine them into modules. This will be very apparently visually if you followed the first step correctly.

Now you have your scrum/agile modules which can be outlined and given to subordinates, and tracked.

:.:.:

If the whole thing is a just a big ball of spaghetti, make a another revision. If its very very small you might be glossing over the technical details.

Do people mostly use sticky notes / white boards for this? In theory UML tools should be great at this, but in practice I've found that they mostly get in the way. Even if the tool itself works well - then disseminating the info locked in the tool becomes awkward.

More recently, I've fallen back to frequent meetings and a wiki as the best way to work through this kind of activity - but it feels like there should be a better way.

Now you have your scrum/agile modules which can be outlined and given to subordinates, and tracked.

"Agile" micromanagement is great if you're looking to bleed talent. Highly recommended if you're looking to reduce costs and don't care who leaves.

Indeed, a collaborative team is much better than top-down micromanagement. It's a pleasure to work with "agile" teams where everyone can define their own tasks.
http://en.wikipedia.org/wiki/Structured_programming

Stepwise refinement: http://en.wikipedia.org/wiki/Top-down_and_bottom-up_design

Both were written about by Niklaus Wirth, (co-)inventor of Pascal, Modula, Oberon, etc.:

http://en.wikipedia.org/wiki/Niklaus_Wirth

From the above page:

http://sunnyday.mit.edu/16.355/wirth-refinement.html

Not a panacea, but useful, and can be used together with other techniques like OOP / OOAD.

We've tried to handle in a couple different ways depending on the Feature. We either slice up a feature into the different layers they impact, so that individual Dev's can work on a layer. This presents issues related to dependencies. But typically, you can have have two Dev's start at the bitter ends, i.e. Presentation and Data then one of them will tie it up in the middle.

For smaller features, we'll have a Dev just implement it full stack. This takes for granted that a lot of the plumbing is there, i.e. Service Layers

It helps to have these conversation during Planning Meetings. This will help the Dev's involved to get a better understanding of the Stories and Tasks needed to implement.

Draw flow charts, identifying the smallest components along the way. Figure out which components depend on each other. Delegate tasks depending on what's already built, your deadline and each team member's specialty/ability.
I wrote something recently on how to create small tasks for estimating (http://keithba.net/estimate-like-a-boss), which includes an example design doc and spreadsheet of the breakdown. You may find that example useful.

Generally speaking, finding a way to communicate this will depend on the engineer. Someone very junior may require much more detail both in the technical design and the feature itself. Someone more senior needs less of that.

1. Have them pair program with seniors half of their time.

2. Review EVERY piece of code their write. Code reviews daily.

personally i like to write the mvc skeleton myself and decide which frameworks will be used and go from there. or a leader for the backend who assigns out small tasks as small as a "function to draw this btn or move this element" or to "find me a library that does X and is..." and then he can merge them in... then once it takes shape you can share the files and the work.

i suppose usually for me one guy (say techsupp or network admin) sets up the svn/webserver/db, one guy decides on frameworks, one guy writes the skeleton, one guy starts on the interface, art guy does art stuff, typically the lead dev is watching over all this and merging stuff and when ready gives orders and access to the repo. if theres at least some structure and one template or working file/interface the juniors will have more success imo.

I think the lead should be setting up source control, the dev/staging environment, deciding on the frameworks used (for the big stuff at least), and defining the architecture and code style for the project, and last but not least, they should break up the project into major features, and individual modules/components/tasks. As far as the last bit goes, the level of detail I shoot for is something like this (given a fabricated web app as the software being developed):

Feature: User can register an account

Tasks:

  - Registration page markup/styles

  - Registration page JavaScript (form validation/submission)

  - Registration API endpoint (validate properties, ensure user doesn't already exist, persist user model, send email confirmation).
Prerequisites:

  - Data access layer implementation

  - User model

  - App layout markup/styles

  - Email service implementation
I agree with the lead setting up the initial project skeleton, but I'd take it one step farther and say the lead should also document the conventions for adding new modules/etc, so that the structure doesn't start to fall apart once the lead stops being the one managing it day to day.