I am my own worst enemy when it comes to achieving my deadline goals. These are tips and reminders I've found useful through work experience.
Most of the tips are general, but some are specifically suited to programmers/engineers in situations with long compile/simulation phases (compiling is the act of building an executable, simulation is the act of running it to completion).
General Office Productivity Tips:
Procrastination. It comes down to inertia and momentum.
- Understand the problem. It is very easy to avoid working on a problem you do not understand well enough to solve.
- Break it down. Break the larger problem into smaller problems that conceptually you understand and can tackle.
- Review milestones. They are closer than you might think, and it can be a good kick in the pants to think "I have to get this feature done by Thursday" instead of "I have to get this all done in three months".
- Prioritization. Do not starve a high priority feature for lack of understanding to feed a low priority feature you know like the back of your hand.
- Just do it. Attack the problem, no matter how feeble the attempt. Even if you throw out the work, it increases your understanding. It is better try fail than to waste time on something unrelated. Like writing a blog post or checking the InterWeb. LIKE YOU ARE DOING RIGHT NOW.
- Go for a walk. Can't focus? Get away from your desk and stimulate the blood flow to your brain. A change of scenery can unplug a mental block.
Interruptions. What is of concern isn't the time lost servicing the interrupt, it is the time spent context switching back to the original problem. Interrupting someone in flow can take 15 minutes for them to get back to the point they were at before the interruption occurred.
- Net connectivity. Close email, web browser and any messenger programs.
- Answering machine. Forward phone to voice mail.
- Office hours. If you are in a partial support role, set up "office hours" during the day where you will answer questions.
- Meetings. Reduce the number of weekly meetings wherever possible.
- Maximize use of time. Know what time of day you are most effective and schedule the interruptions/meetings to the time when you are not.
Environment. The key is to create a work environment that is free of distractions so that when you've achieved flow you can maintain your focus on the problem at hand.
- Noise. Noise cancellation headsets or headphones with music can cut down on the distracting nature of open concept cube farm hell. Be kind to your co-workers and never use a portable radio or your computer speakers unless you are working late alone. If you're going to have an extended discussion with someone move to a break room or an empty conference room.
- Temperature. Have a portable fan to cool down and a portable heater/sweaters to warm up if your cube doesn't have ideal temperature conditions.
- Snacks. Have food around so that hunger can be satisfied without leaving the building. Don't let your belly be a source of distraction. Nothing that will rot should be left out of sight. Some good low-fat choices: apples, cans of tuna, microwave popcorn, turkey sandwiches (if you have access to a fridge).
- Hydration. Have a bottle/cup of water on your desk that you can sip from throughout the day. The short term gains made from drinking coffee isn't worth the long term loses on memory, dehydration, and the productivity lose from caffeine crashes. Non-caffeinated herbal teas such as peppermint can be useful for weaning yourself from coffee.
- Clutter. I am not hypocritically recommending clean desks, but file away any papers that aren't germane to the problem at hand. When it comes time to search the mountain of looseleaf, at least you will be looking at stuff related to what you are working on.
Manage Expectations. The biggest secret to getting more work done is having less work to do.
- Give feedback. Do not tell management what they want to hear, tell them what you think will happen.
- Accurate Estimations. Develop your estimation skills so that when you say 'task X will take Y to do' they believe you.
- Under commit and over deliver. Realistic schedules give room to do a better job instead of fighting to keep your head above water.
Avoid Burnout. This is the most important tip. Meet the deadline in a sane manner. Ever waste half an hour because you were looking at the wrong results? Ever make a minor two-character typo that drastically changed results and was very insidious to find because it 'looked right''? If you were more alert that would not have happened.
- Relax. Find the balance between enough stress to motivate but not so much stress that you lose the ability to see the simplest solutions and recognize time sinks before you fall into them.
- Minimum overtime. An hour of overtime is less than a regular hour of work because you're reducing your overall ability to produce when you don't get proper rest. Find a balance between working hard and working smart.
- Sleep. Don't let thinking about work impact your sleeping. Sleep debt has to be paid off eventually. You don't want to be useless during the eight hours a day you have to be in front of the keyboard.
- Balance. Find a balance between work, health, activity, friends, family, and hobbies. It will increase your overall work performance. You lose the ability to bounce back with age.
- Don't force alertness. Much like a sleep debt, forcing alertness with caffeine or other stimulates will eventually develop a dependency on them to achieve a baseline state.
Programming Specific Tips:
Complexity. Don't create more work for yourself than is needed.
- Only code what is needed. If a feature 'might be useful' then code it later when it is necessary.
- Simplest solution is the best solution. K.I.S.S. Every line coded is a line that potentially has to be debugged. Focus your debugging effort on solving the problem, not on debugging bells and whistles that don't contribute to the deadline. More time is lost in debugging an unnecessarily complex feature then in designing it.
- Notes to yourself. Put comments in your code with standard identifiers such as "TODO" and "FIXME" that you can come back to later to add the improvements you didn't add the first time. Putting the date you added that comment is optional, but can help during a code cleanup (sorry, I mean "refactoring") five years later.
Multiple build/project directories. "Hey, can you check out the latest version of this file to see if my changes work?'' Except it's never just one file, and the changes never work the first time. Checking code out into your working copy is not just an interruption, but can lose an entire afternoon trying to re-achieve the state you were at before updating that "one file". Having multiple directory trees (hard drive space is cheap) can remove this problem.
- Working. What you currently have checked out any are working on. Only checkout code when you've already verified it works using the Stable/Branch directories.
- Stable. The latest valid snapshot/tag of code that is known to work.
- Branch/Current. The absolute latest checked in version of all code.
Decompose. Problems seem more daunting when you can't see the trees for the forest. Breaking it up into smaller tasks not only reduces procrastination, but it also can increase performance time.
- Design assumptions. Create small unit proofs of any design assumption upfront so that you know the design will work before investing time and energy.
- Strawman Integration. When rapidly prototyping a smaller subset of the design you are pushing the integration issues until the end. It is best to do an upfront integration of a strawman of your design to make sure there aren't any major gotchas and then continue with the prototyping.
- Reduce dependencies. Debugging a rapid prototype can be much faster because you don't have as many sources of errors to look at.
- Smallest solution space. Reduce the unit testbench to only what is necessary to run your prototype. The goal is to reduce the time between starting a simulation run and getting results during development. Keep the inherent downtime in your job from interrupting your flow. You shouldn't have time to think about something other than the problem at hand (ie: Checking Slashdot. Checking this blog is okay).
- Symbolic links. Set up the file structure such that you can run your small unit testbench in parallel with the main design, ie: symbolically link to where any files will exist in the real design. It may still be useful down the road when you want to isolate a problem.
- Metrics. It is much easier to grab profiling/coverage metrics from a smaller testbench that you can iterate many, many times more often then the main design. The statistics might not be "real world", but they can still be helpful.
- Design for debug. Litter your code with error assertions when they receive unexpected values or hit unexpected states. If necessary add a debugging define so that these assertions can be turned off in the production code but turned on again when you encounter a problem. Assertions to test inputs and outputs for illegal values and raise a big red flag will save you a lot of time when integrating.
Parallelism. If you have access to multiple CPUs or a server farm then use them!
- Pipeline. If the compile/simulate/debug flow has dead cycles where you are "waiting for results", then you can make use of those cycles by breaking the work down into distinct units that can be pipelined in parallel. This keeps you actively solving the problem instead of getting caught up in procrastination and servicing interrupts.
- Tracking. Keep a piece of paper (or use your engineering lab book) beside your desk to write down reminders of where you left off in the parallel problems.
- Don't fire and forget. When you switch to working on the next task in the pipeline, periodically check the status on the first task to make sure that it is running properly.
- Always run something. The goal is to always have something running in the background while you develop during the cycles where you would instead be waiting for results. It could be as simple as seeing if what you are working on compiles properly while you're working on something else.
- Organize. Use tools to keep the multiple tasks organized such as different workspaces for different tasks, tabbed terminal windows with different title bars, saved session views, etc.