In the last year, I:
- Created and produced 30 full length video courses for Pluralsight
- Wrote 56 blog posts
- Produced 40 episodes of the Get Up and CODE podcast
- Created 50 YouTube videos
- Published a book
- Spoke at 4 events
- Billed over 100 hours of contract work
- Created a full product, that I am about ready to launch
- Ran 5 kilometers 3 times a week, every week
- Lifted weights 3 times a week, every week
I’m not saying this to brag–although I am certainly proud of these accomplishments. I am saying these things to prove that I know what I am talking about when it comes to productivity.
Being super productive
Right now–as I type–I have a timer ticking down. The clock shows approximately 14 minutes before I’ll take my next break. I live and die by this clock.
You may have guessed it, but the clock is a Pomodoro timer. For the last year, I’ve been religiously using the Pomodoro technique to not only stay on task, but to plan out my days and weeks.
If you aren’t familiar with the Pomodoro technique, the concept is remarkably simple. So simple, that I first dismissed it as ridiculous. But, thanks to my good friend Josh Earl’s success with it, I decided to give it another try.
You basically set a timer for 25 minutes. During that time you pick a single task to accomplish and work on that task, uninterrupted. After 25 minutes you take a break for 5 minutes and then begin again. After 4 cycles, you take a longer 15 minute break. (There are some variations on this, but that is the basic idea.)
Like I said, it seems pretty simple and unremarkable, but I can’t even begin to express how powerful this technique is for getting things done.
I’m lazy by nature. I have to constantly fight against the side of me that wants to procrastinate and slough off my work. The Pomodoro technique helps keep me focused by forcing me to work uninterrupted for a period of time. It also gives me a measure to compare myself against and realistic targets to aspire to achieve.
My week beings on Monday. On Monday morning I wake up and go to the gym to lift weights. When I get back, I have a protein shake and get to work.
The first thing I do when I get to my desk on Monday is start my Pomodoro timer and open up my “Weekly Plan” Trello board. I use this board to organize my week. It has nine columns. Seven columns for the days of the week, one column for today, and one column for done.
My first task of the day is to create the rest of the tasks that I think I can get done that week. I start off with a checklist of things that I know I need to do every week:
- Blog post
- Podcast episode
- YouTube video
- Newsletter email
- Buffer social network posts
Then, I add cards for the current projects I am working on for that week.
Once I’ve got all the cards I can think of on the board, I start tagging each card with a color that represents how many Pomodoros I think that task will take. I have three categories:
- Green: 1 Pomodoro
- Yellow: 2 Pomodoros
- Orange: 3 Pomodoros
If something is going to take up more than three Pomodoros worth of time, it needs to be split into multiple tasks.
Next up is planning the week. For each day of the week–unless there is something that will take up most of my time–I figure I can get about 10 Pomodoros done. This may not seem like a lot, but believe me, it is. I drag cards into the columns until I have filled up each weekday with 10 Pomodoros worth of cards. For weekends, I usually just drag in about three or four.
My estimates are always on the high side, but they are pretty accurate, because it is fairly easy to estimate based on half hour intervals–especially when many of your tasks are repeated each week. (For example, a blog post is estimated at three Pomodoros.)
I have a similar ritual every single day. The first thing I do, after exercising each day, is to open up my Trello board again and this time plan the day.
New things come up and other things need to get shifted around, so planning for the week alone is not sufficient. Often, I’ll have different tasks that I had vaguely identified at the beginning of the week which I’ll give more clarity to later on.
I first drag things over from the appropriate day into my “Today” column until that column is filled with about 10 Pomodoros worth of work. After that, I’ll take a look at the today columns and think about anything I might have missed that needs to get done that day. Finally, I’ll sort the “Today” column based on priority–I want to make sure I am always working on the most important things first.
Once I’ve got the day sorted out, I go back to the rest of the days in the week and move around cards until everything is balanced again. If I find that I’ve got some empty slots, I’ll create new cards and start filling those slots until I am back at full capacity again.
Once all the prep-work is done, it’s time to actually start working on tasks. I grab the first task off the list, start a timer and get to work. At about 5:00, I stop for the day and add up my Pomodoros. If I didn’t hit at least 10, I count on working a little bit that evening. If I did hit 10, it’s optional.
Why this works
So, you may be wondering why this works–why it is worth even writing about such a simple workflow. Well, even though this workflow seems really simple, there are a few key things going on here that aren’t immediately obvious.
First of all, I am using quotas to make sure that I accomplish the volume of work that I want to produce each week. I have quotas for how many blog posts, podcasts, YouTube videos, and other content that I need to produce each week. The things that are being measured by a quota get dropped onto my board first.
I’m also using a daily and weekly quota when it comes to Pomodoros. Pomodoros are little measurable units of work for me. I know that I should be able to get 10 done each day and that I should be able to get roughly 50 done in a week without killing myself. I know from experience that hitting 60-70 will cause a measurable dip in performance the next week and that if I am doing less than 50, I am slacking off.
Because I have those quotas in place, I know what is expected of me each and every week. I have the power to hold myself accountable to a real measurable standard. I can’t emphasize enough how important this point is. If you don’t have a way to hold yourself accountable to a standard that you want to achieve, human nature will cause you to fall way below the bar.
Another major component that makes this technique successful is the awareness of my capacity within a given amount of time. It is really easy to over or under estimate what you can get done in week, because you don’t normally have a ruler that you can use to measure task duration versus your actual capacity. When I start the week, I know that my capacity is about 50–I’ve got that much gas in my car. I get to choose where I want to drive that car that week–I can only go so far. I have to make a realistic prediction of what I can actually get done. From that prediction I have to prioritize my tasks so that the most important things get done first.
Without this understanding of my capacity, it is easy to fall into the trap of overestimating my ability to get work done and underestimating the take it will take to get the work done. With this system, I have a real metric to compare to. I know that I am not going to get 80 Pomodoros done in a week. I know that in an 8 hour day, I will not get 8 hours of work done. I am eliminating my biases by replacing them with real statistics.
Finally, the dedicated focus of the Pomodoro technique makes me more efficient at the work I am doing. When I am solely focused on one task at a time–without checking Facebook or Twitter–I work much more efficiently. Several studies have shown that multitasking causes a drop in efficiency. When I stay focused on a single task, I get much more done. I’ve written about this before, when I talked about quitting your job, but you can easily lose hours of time in a day to small distractions. Over the period of a year’s worth of time, all those wasted minutes can end up equaling weeks of lost productivity.
One huge benefit of this technique is that I am able to do most of this work without stress or guilt. Normally, when I am working, I always feel guilty about how much time I am wasting during the day. I also feel stressed about not getting as much done as I should be getting done. This situation of stress and guilt actually ends up being the perfect breeding ground for procrastination and burnout.
When I am using the Pomodoro technique, I don’t feel the guilt of wasting time, because I know that as long as I get done 10 Pomodoros in a day I have reached my productivity goal for the day. If I get more done, great.
I also don’t feel stressed about getting as much done as I should have, because how much I get done is no longer what is being measured–I’ve taken the burden off of my shoulders. My focus has shifted from results to process. I can’t control the results. Work takes as long as work takes. But, I can control the process. If I put in my 10 Pomodoros for the day and I have sufficiently prioritized my work, then I have done the best that I can do–no need for guilt, shame or stress.
Time for a break
If you are interested in getting started with the Pomodoro technique, I’d recommend checking out Pomodoro Technique Illustrated. And if you have any questions about my process and how it works, feel free to ask and I am happy to answer them in the comments below.
Also, if you liked this post and are interested in more of what I have to say about being productive and boosting your career, sign up for my weekly newsletter here. You also might want to check out the course I am putting together called “How To Market Yourself as a Software Developer.”
Far too many Agile development projects fail. It is hard to even accurately measure the number of failures because so many software development projects end up “complete” and shipped, even though:
- They took far too long to build
- The quality of what we built was poor
- What was built was not what the customer wanted
- The cost to develop was more than it should have been
Over the years, I’ve worked on many different Agile teams and have consulted for and trained many teams on Agile development. In this time, I have found 5 common problems, that if not resolved, are very likely to cause a project to be a failure.
1. Not having a product owner
Of all the things that can cause an Agile software project to fail, not having a person that is ultimately the decision maker for the product being developed is the quickest way to ensure its demise.
It doesn’t matter if you are following Scrum, doing your own Kanban style project or something else; if you want your project to succeed, you need someone who can set its direction and make decisions about the product being developed.
Think about remodeling a kitchen. If you hired a bunch of contractors to come in and do the various jobs, like: plumbing; carpentry; flooring; etc, but you don’t have someone deciding what the actual finished kitchen should look like, you are going to get a random mess.
A few skilled contractors will probably be smart enough to find the right person to ask about what should be done, but it takes more than just making arbitrary decisions about where the cabinets should go to design a kitchen. You need someone to actually come up with a real design and vision and be able to modify that vision appropriately as the project progresses and problems inevitably occur.
It seems pretty nuts to spend a huge amount of money remodeling your kitchen, but not want to invest any time or effort in either designing the finished product or hiring someone to do it.
Yet, day in and day out, I see this exact behavior in software projects. I see companies investing huge amounts of cash in Agile development, but not appointing anyone to be the true owner of what is being built and to set the vision for it.
2. Not iterating
One of the key values that Agile development brings to the software development world is iteration.
What is iteration though?
You may think it means breaking your project into 2 week sprints or iterations. While doing this can facilitate iterative development, it doesn’t mean you are actually iterating.
Confused? Let me explain.
The key to iterating is to develop a product a little bit at time. It would be accurate to describe the process of iterating on a product as evolution of a product.
Whether you believe in macroevolution or not, microevolution, or adaptation is a proven concept. The idea behind evolution is that things change gradually over time. Those small changes add up to result in a big change.
Imagine how silly it would be if evolution worked the way most “Agile” software is built.
Imagine, if you will, a fish that swims in the ocean and has some little fish babies that are born with fully functional legs. Then, those legged fish babies grow up and have fish babies that have wings.
Probably the legs and wings wouldn’t do that fish much good, nor would they be designed properly, because instead of adapting and changing over time, they just suddenly appeared.
Features should not be built in a single sprint or iteration. It is as silly as legs showing up on a fish in a single generation.
Instead, features should be evolved and grow over time. A feature shouldn’t be pushed into a single sprint or iteration and then be done. A feature should start out small and develop and evolve over time as feedback is received and customers or the product owner tries it out.
Far too many times, I see Agile development projects mistake having iterations with actually iterating the development of the product.
Don’t try to ship a completed feature at once, let it evolve over time.
3. Not breaking things down small enough
The main reason why this is so important is because it prevents procrastination. Procrastination usually occurs when either we dread some large task that will be difficult or we don’t know what to do next.
If you can break a big project up into small parts, it will seem easier to accomplish and will have clear steps of progression.
I often see software projects where the person creating the backlogs or work items is not considering the work enough before giving it to the team.
I coined a term for these kinds of backlogs: fatlogs. Fatlogs are backlogs that are not broken down small enough and often are very vague in what needs to be accomplished.
Fatlogs are notoriously difficult to estimate and waste time when trying to explain and understand them. It is critical that fatlogs be broken down into smaller actionable backlogs before being given to an Agile development team or a large amount of time will be wasted.
Many times, I have found that the creator of the fatlog could have easily broken down the work it represents into several smaller backlogs that would be easier to explain and understand, even without knowing much about software development.
I often recommend to Agile development teams that they outright reject fatlogs and send them back up the chain.
“If you can’t take enough time to clearly state what you want, it must not be that important.”
This doesn’t excuse development teams either. Development teams should break down any backlogs they get into small tasks as well.
4. Not setting done criteria
What is the first thing a waiter asks you when you order a steak?
That’s right, they ask you how you would like it done.
If the chef doesn’t know what the done criteria is for your steak, the chef will have to decide what he or she thinks the done criteria is.
You may get back a well-done steak, or a rare steak, or something in between, depending on the personal preferences of the person cooking your meat.
This isn’t a good way to cook steaks and it isn’t a good way to cook software either.
In many software projects I often encounter lots of steaks being cooked but no one defining when they are done. The backlogs most often end up being “done” when time runs out.
It is very important to have explicit unambiguous done criteria for any backlogs being worked on by an Agile development team.
This means that the product owner should be defining some level of acceptance testing. It doesn’t matter if the tests are manual tests or fully automated tests (BATs), what matters is that some criteria is defined by which the team can evaluate whether they have achieved their goal or not.
Lacking this criteria is like a parent responding with “enough” when their child asks “how many more peas do I have to eat?”
Not having done criteria is demotivating and results in the finger pointing game of why the correct thing was not built.
I have found that if you tell someone exactly what is expected of them and what criteria they will be judged by, you get much better results than just throwing them in the ring, slapping them on the back, and saying “do a good job.”
5. Not letting the team be a team
Teams are strange organisms, especially Agile teams.
There are many dynamics that affect how teams act and interact. There are many ways to foster a healthy team and many ways to create unhealthy teams.
A healthy motivated team has synergy, a unhealthy gaunt team can be less effective than all of its members are on their own.
The key to having a healthy motivated team, is letting them be mostly autonomous. Regardless of your political persuasion, you would probably agree that when a country invades another country and sets up an unelected government to oversee the people, there are going to be problems.
The same thing happens in Agile development.
I’m not saying teams shouldn’t have accountability. But if you want to run a software project in an Agile way, you have to let teams self organize and self manage to some degree.
When big brother is always watching and interfering, team dynamics become very different. Naturally, teams usually develop their own cadence, leadership and roles (this is called norms.) However, when outside forces directly interfere with how the team does things, and they don’t have the power to decide their own fate, team members begin to realize that they need to look out for themselves.
Additional agile development resources
I’ve found it to be pretty difficult to find good resources on these topics, but here are a few books I’ve found useful that address some of the issues I described above.
- Succeeding with Agile: Software Development Using Scrum - This book is focused on Scrum but it applies to many different kinds of Agile projects as well. Mike Cohn and I usually agree on most Agile subjects.
- Agile Retrospectives - I’ve found this book to be useful for getting good idea for team retrospectives that can really help to break down some barriers and help teams learn to resolve issues themselves.
- Scrumban and Kanban and Scrum - Both of these books have excellent information about combining Scrum and Kanban and have great solutions for dealing with some of the problems I described above.
What do you think? Have I missed any of the major Agile project killers? Any useful tips for dealing with them?
Let me know in the comments below.
I always hear the advice that we should tackle hard problems first.
It seems like pretty legitimate advice, and many of the reasons for saying so make sense, at least at a surface level.
The reasoning usually revolves around the idea that by tackling the hard problems first you can eliminate your biggest risk early and everything will be smooth sailing from there.
When you really think about the reasoning for solving hard problems first though, most of it is not actually reasoning, but based of off one emotion… fear.
We tend to think it is best to solve hard problems first, because we are thinking about eliminating our fear, not because we are thinking about what approach has the highest chance of success or is the most optimal.
I call this FDD, or Fear Driven Development.
And when I think about it that way, I find myself hard pressed to find a real good reason for tackling hard problems first besides being able to abort early. Which, in some cases might be good, but I’d rather focus on success.
Here are 7 reasons why it might be a good idea to tackle the hard problems last instead of first.
1. Solving easy problems first gives you momentum
When a large ball starts rolling down a hill, it picks up speed rapidly and that large ball can bust through many barriers that it couldn’t before, simply because of one thing it has after rolling down a hill that it didn’t have before—momentum.
On the converse, trying to push a heavy ball up a hill is pretty hard. And if there are barriers on the way to the top of the hill, not only do you have to fight gravity, but you have to be able to push extra hard to get through those barriers.
Life is hard enough, why make it harder?
I recently received an email from a developer that was concerned that his team wasn’t gelling and that they didn’t have the expertise in the technology needed to solve the complicated problem ahead of them.
They were going to start the project by trying to integrate this fairly complex technology and he was afraid that it would cause them a large delay before they would be able to get version 1 out.
Start with your simple problems; get working software out there as soon as possible. Not only will the team gel much more easily as they are having success and making real progress, but that momentum will help them when it is time to solve the more difficult problem.
Even if they have to throw the first version away, when they get to the hard problem, the momentum alone will make them much more likely to reach success in the end.
I could give 100 examples of how solving easy problems to gain momentum can benefit you, but you probably already know intrinsically that this is true.
Long story short, get a running start before taking a big leap.
2. Avoid solving the wrong problem
The big problem with solving the hard problems first is that the hard problems usually require a large amount of context in order to fully understand them.
It is very hard to get the right context for a hard problem when we take it out of its natural order of progression and artificially cut it to the front of the line.
You’d probably like to start a college class by taking the final exam first, so you don’t have to worry about it, but the problem with doing so is that you’ll lack the context and information to understand the questions and to know the answers.
When we try to tackle problems out of order to avoid leaving the hard problems to the end, we end up losing all of the learning and context that would help us to solve the hard problems at the end and we are much much more likely to end up solving the wrong problem, which is a complete waste of time.
3. Someone else may solve the problem for you
Sometimes procrastination is a good thing.
Sometimes, when you purposely push off solving a hard problem till the end, you end up finding that someone else already solved your problem.
I spent a few minutes trying to troubleshoot it, but nothing I was trying was working, so I had to make a decision.
I had 3 choices:
- Keep trying to solve this hard problem before moving on.
- Go on and do other videos and send off a support request to see if they could handle it.
- Make a new project and re-edit all the clips.
Choices 1 and 3 involved tackling a hard problem right then and there.
Choice 2 was to tackle easy problems and see if support could solve my hard problem for me, and if not, I would solve it at the end.
I ended up choosing option 2 and it paid off. It turned out Camtasia support was able to solve my problem. By the time I needed the project to complete my course, they had solved my hard problem for me and I didn’t waste any time upfront trying to tackle it myself.
Now it could have worked out differently; I might have had to solve the problem myself at the end, but instead of assuming I would have to and wasting perhaps a day or 2, trying to solve the problem myself, I pushed it off and kept working on easy problems and I gave someone else a chance to solve my hard problem for me.
It doesn’t happen all the time, but many times if we push off the hard problems we face, we find that by the time we get to them, someone else has already solved the problem for us.
4. Your own subconscious mind may solve the problem
When I said someone else might solve the problem for you, that someone else might actually by you—at least your subconscious mind.
Have you ever had the experience of thinking about a problem and not being able to figure it out, but then you wake up the next morning and suddenly have the answer?
It seems that our subconscious mind is more powerful than we are aware of.
In many cases, if we know of the hard problem we need to solve and have thought about it a little bit, our subconscious mind will start working on the solution, even though we are not aware.
Obviously this isn’t going to work all the time, and your subconscious mind isn’t going to write a bunch of code for you, but in many cases there is at least some benefit to throwing the problem off to our internal “worker thread.”
5. You are more committed to solving the hard problem when you risk everything you do so far
One benefit to saving the hard problem for last is that you have some extra motivation in the form of loss aversion.
We can use this knowledge to our advantage by doing the easy work first and letting our loss aversion help motivate us to solve the harder problems, because we don’t want to lose all the work we put into a project so far.
By starting with easy problem, we put some “skin in the game.”
If we try to solve the hard problems first, we have nothing to lose, so we are much more likely to give up.
6. Hard problems are often easy problems bundled together
And it turns out that many hard problems (not all) are decomposable into many small easy problems.
If you strive to never solve hard problems and to always push them off, you may actually find out that you never have to solve hard problems.
Many times we can chip away at hard problems, by taking bits of them off a little at a time and solving those easier problems. Eventually, you may find that you’ve reached the tootsie roll center of your hard problem lollipop and it is filled with chocolate candy!
Now, some problems aren’t very easily decomposable, but a good majority of problems are. Once you develop the skills to chip off bits of hard problems into smaller easy problems, the world looks like a much more conquerable place.
So, saving hard problems for last and breaking off little pieces of them as you go, can be a good strategy to help you to wear down your opponent before you have to face him.
7. Some hard problems are never truly solved
One of the big problems with tackling the hard problems first is that they tend to fill up as much time as you’ll give them.
If I give you an easy problem, like write a function to reverse a string, there isn’t much to think about. You can solve it a number of different ways and there isn’t a huge difference in the efficiency of the different methods of solving it. It is pretty unlikely you’ll spend weeks revamping your solution and thinking that it’s not quite right.
But, if I give you a problem like, create an in-memory database, not only is it a hard problem, but it has a huge number of possible solutions and can be optimized from now until the end of time. You could spend 2 weeks working on that task or 2 years.
The problem is that many hard problems don’t have a good scope to them when they are solved in isolation.
If you design an engine for a car that isn’t built yet, you won’t know when you are done.
But if you design an engine for a car and you know how much it weighs and know what kind of transmission it will use and what kind of fuel efficiency it needs to have, you can have a much clearer understanding of when your engine design is done.
If you save the hard problems for last, the scope of those hard problems will be much more defined, which will keep you from wasting valuable time over solving a problem or, like I mentioned earlier, solving the wrong problem altogether.
Baccarat is an interesting card game that you’ll find at many casinos. The objective of the game is to correctly predict whether the bank or player will win a hand.
In Baccarat the scoring for a hand is very simple, add up all the cards at their face value with face cards being worth 10 and only count the total in the ones column.
6 + 7 + J = 23 = 3
A + 4 = 5
The highest possible hand is 9 and whoever has the highest hand wins. If the player and banker have the same hand, it is a tie.
I won’t go into the details of how the number of cards are drawn is determined, but if you are interested you can find that information on Wikipedia. Basically, you end up having pretty close to a 50 / 50 chance of either the player or banker winning a hand. (Of course the house edge still is about 1.06% in the best case.)
The interesting thing about Baccarat though, is that despite the odds, despite common sense, despite the understanding that the game is completely random, people will still sit there and record every single hand and score trying to use it to look for patterns to predict future results.
These poor deluded souls actually think they are measuring something on these score cards, as if what happened in the last hand will in any way affect what will happen in the next hand.
After many years of trying to find the secret formula for measuring software development activities, I’ve come to the conclusion that trying to measure just about any aspect of software development is like trying to measure the odds of a future Baccarat hands based previous Baccarat hands.
Why we want to measure software development
It’s understandable why we want to measure software development—we want to improve. We want to find out what is wrong and fix it and we want to know when things go wrong.
After all, who hasn’t heard the famous quote:
“What gets measured gets improved.”
Don’t we all want to improve?
Somehow we get stuck with this awful feeling that the opposite is true—that what doesn’t get measured doesn’t get improved.
And of course we feel guilty about it, because we are not doing a good job of measuring our software development practices.
Just like the avid Baccarat gambler, we want to believe there is some quantifiable thing we can track, which will give us information that can give us the edge.
Sometimes the reason for wanting to measure is more
sinister practical, we want to evaluate the individuals on our team to see who is the best and who is the worst.
If we could figure out how to measure different aspects of software development, a whole world of opportunities open for us:
- We can accurately give customers estimates
- We can choose the best programming language and technology
- We can figure out exactly what kind of person to hire
- We can determine what kind of coffee produces the best code
How we try
I’ve been asked by many managers to come up with good metrics to evaluate a software development team.
I’ve tried just about everything you can think of:
- Lines of code written
- Bugs per developer
- Bugs per line of code
- Defect turn around time
- Average velocity
- Unit test code coverage percentage
- Static analysis warnings introduced
- Build break frequency
I’ve built systems and devised all kinds of clever ways to measure all of these things.
I’ve spent countless hours breaking down backlogs to the smallest level of detail so that I could accurately estimate how long it would take to develop.
I’m sure you’ve probably tried to measure certain aspects of software development, or even tried to figure out what is the best thing to measure.
It’s just too hard
No matter what I measure or how I try to measure it, I find that the actual data is just about as meaningless as notebook full of Baccarat hands.
One of the biggest issues with measuring something is that as soon as you start measuring it, it does start improving.
What I mean by this is that if I tell you that I am going to start looking at some metric, you are going to try and improve that metric. You won’t necessarily improve your overall productivity or quality, but you’ll probably find some way—intentional or not—to “game the system.”
Some managers try to get around this issue by just not telling the team what they are being measured on. But, in my opinion, this is not a good idea. Holding someone accountable to some realistically arbitrary standard without telling them what, is just not very nice at all, to put it mildly.
But really the biggest reason why it is too hard to measure aspects of software development, is that there are just way too many variables.
- Each software development project is different
- Each feature in a project is different
- Software developers and other team members are different
- From day to day even the same software developer is different. Did Jack’s wife just tell him she was cheating on him? Did Joe just become obsessed with an online game? Is Mary just sick of writing code this week?
- As you add more unit tests the build time increases
- Different team members go on PTO
- Bob and Jim become better friends and chat more instead of work
The point is everything is changing every day. Just about every aspect of software development is fluid and changing.
There is not one metric or even a set of metrics you can pick out that will accurately tell you anything useful about a software development project. (At least I have never seen one at any software development shop I’ve ever been at on consulted at.)
If you were building widgets in a factory, you could measure many qualities about that widget making process, because much of it would be the same from day to day, but with software development, you are always exploring new territory and a 1000 different variables concerning how you are developing the software changing at the same time.
Measuring without measuring
So am I basically saying that metrics in software development are completely worthless and we shouldn’t bother to track anything?
No, not exactly.
What I am saying is that trying to use metrics int the same way that we measure the average rainfall in a city, or running pace improvement by looking at its average over time, doesn’t really work in software development.
We can track the numbers, but we can’t draw any good conclusions from them.
For example, say you track defects per lines of code and that number goes up one week, what does it mean? Any number of things could have caused that to happen or it could just be a totally random fluke. You can’t really know because there isn’t a knob you can turn and say “ah, I see we turned up the coffee bitterness factor to 3 and it resulted in more bugs.” Instead there are 500 knobs and they all changed in random directions.
So, I am saying don’t look at how the numbers of any particular metric are moving from day to day or week to week and expect that it means anything at all, instead look for huge deviations, especially if they are sustained.
If all of a sudden your average team velocity dropped down to almost nothing from some very high number, you won’t know what caused it, but you’ll know that it is much more likely that there was one single knob that got cranked in some direction and you’ll at least have some idea what to look for.
You really have to treat the software development process more like a relationship than like a factory.
I don’t have a series of metrics I use to evaluate my relationship with my wife or my friends. I don’t secretly count how many times my wife sighs at me in a day and track it on a calendar to determine our relationship quality factor.
Instead what I do is talk to her and ask her how things are going, or I get a more general idea of the health of the relationship by being involved in it more.
Team retrospectives are a great way to gauge the temperature of the team. Ask the team members how things are going. They will have a pretty good idea if things are improving or slowing down and what the effectiveness level is.
Measure not, but continuously improve, yes
So kick back, don’t worry so much. I promise I won’t tell Six Sigma that you aren’t using metrics.
Instead focus on continuously improving by learning and applying what you learn. If you can’t notice enough of a difference without metrics, metrics wouldn’t have helped you anyway, because the difference would just be lost in variance anyway.
I used to be very confident in my abilities as a software developer.
I used to be able to walk up to a group of software developers and tell them exactly what they were doing wrong and exactly what was the “right” way to do things.
I used to be sure of this myself.
It wasn’t even that long ago. Heck, when I look at the blog posts I wrote 3 years ago I have to slap myself upside my head in realization of just how stupid I was.
Not only was my writing bad, but some of my thoughts seem so immature and uneducated that it feels like a completely different person wrote them.
And I wrote those posts back when I knew it all.
The more I learn, the less I know
Lately I’ve been running into situations more and more often where I don’t have a good answer for problems.
I’ve found myself much more often giving 3 pieces of advice attached with pros and cons rather than giving a single absolute—like I would have done perhaps 3 years ago.
I’ve been finding as I have been learning more and more (the past 3 years have been an accelerated pace of growth for me,) that I am becoming less and less sure of what I know and more and more convinced that there is no such thing as a set of best practices.
I’ve even spent some time postulating on whether or not commonly held beliefs of best practices would be thrown completely out the window given a significant enough motivation to succeed.
My point is that the more doors I open, the more aware I become of the multitude of doors that exist.
It is not just the realization of what I don’t know, but also the realization of weakness of the foundation I am already standing on.
Taking it out of the meta-physical
Let’s drop down out of the philosophical discussion for a bit and talk about a real example.
Perhaps the biggest quandary I struggle with is whether or not to unit test or practice TDD and its variants.
The 3 years ago know-it-all version of me would tell you emphatically “yes, it is a best practice and you should definitely do it all the time.”
The more pragmatic version of me today says, in a much more uncertain tone, “perhaps.”
I don’t want to delve into the topic in this post since I am sure I could write volumes on my ponderings in this area, but I’ve come to a conclusion that it makes sense to write unit tests for code that has few or no dependencies and that it does not make sense to do so for other code.
From that I’ve also derived that I should strive to write code that separates algorithms from coordinators.
I still even feel today that my advice is not wholly sound. I am convinced it is a better approach than 100% TDD and units tests, or no TDD and unit tests, but I am not convinced there isn’t a deeper understanding and truth that supersedes my current thoughts on the matter.
As you can imagine this is quite frustrating and unsettling.
Silver bullets and best practices
What I am coming to realize more and more is that there are no silver bullets and more surprisingly there are not even any such things as best practices.
Now I’ve heard the adage of there being no silver bullets so many times that it makes me physically sick when I hear someone say it, because it is so cliché.
But, I’ve had a hard time swallowing the no best practices pill.
I feel like when I abandon this ship then I am sailing on my life raft in the middle of a vast ocean with no sails and no sense of what direction to go.
A corner-stone of my development career has been in the learning, applying and teaching of best practices. If these things don’t exist, have I just been pedaling snake oil and drinking it myself?
Best practices are simply concrete applications of abstract principles in software development that we cannot directly grasp or see clearly enough to absolutely identify.
Breaking this down a bit, what I am saying is that best practices are not the things themselves to seek, but through the pursuit of best practices we can arrive at a better understanding of the principles that actually are unchanging and absolute.
Best practices are optimal strategies for dealing with the problems of software development based on a particular context. That context is primarily defined by:
- Language and technology choice
- Meta-game (what other software developers and perceived best practices are generally in place and how software development is viewed and understood at a given time.)
- Individual skill and growth (what keeps me straight might slow you down; depends on where you are in your journey.)
There is a gentle balance between process and pragmatism.
When you decide to make your cuts without the cutting guide, it can make you go faster, but only if you know exactly what you are doing.
Where I am now
Every time I open my mouth I feel like I am spewing a bunch of bull crap.
I don’t trust half of what I say, because I know so much of it is wrong.
Yet I have perhaps 10 times more knowledge and quite a bit more experience in regards to software development than I did just 3 years ago.
So what gives?
Overall, I think I am giving better advice based on more practical experience and knowledge, it is just that I am far more aware of my own short-comings and how stupid I am even today.
I have the curse and blessing of knowing that only half of what I am saying has any merit and the other half is utter crap.
Much of this stems from the realization that there are no absolute right ways to do things and best answers for many of the problems of software development.
I used to be under the impression that someone out there had the answer to the question of what is the right way to develop software.
I used to think that I was picking up bit of knowledge, clues, that were unraveling the mystery of software development. That someday I would have all the pieces of understanding and tell others exactly how they should be developing software.
What I found instead was that not only does nobody know the “right” way to develop software, but that it is perhaps an unknowable truth.
The best we can do is try to learn from obvious mistakes we have made before, start with a process that has had some level of success, and modify what we do based on our observations.
We can’t even accurately measure anything about software development and to think we can is just foolishness.
From story points, to velocity, to lines of code per defect and so on and so forth, all of those things are not only impossible to accurately measure, but they don’t really tell us if we are doing better or not.
So, what is my point?
My point is simple.
I have learned that not only do I not have all the answers, but I never will.
What I have learned is always subject for debate and is very rarely absolute, so I should have strong convictions, but hold onto them loosely.
And most importantly, don’t be deceived into thinking there is a right way to develop software that can be known. You can improve the way you develop software and your software development skills, but it will never be based on an absolute set of rules that come down from some magical process or technology.
Let me ask you a question.
How would you develop your next software project if I told you that if you “succeeded” you would be given $1 million dollars, but if you failed you would get nothing?
Success of course is a very fuzzy term, but let’s assume that success means:
- You built a working functional product
- Your customers are happy with it, content enough to call it done
- You delivered it on time
- You delivered it within budget
- It can be fairly easily modified and maintained with its current design for the next 5 years.
This is an all or nothing proposition. Everything is on the line. If you were to succeed, you would be rewarded handsomely, but if you fail, your effort would be entirely wasted.
Oh, also, you can’t work more than 8 hours a day 5 days a week—no winning by heroics alone.
Why ask this question?
Simple, because after thinking about “how to build software” for the last 10 or so years, (in my beginning years, I didn’t really ponder this question) I have decided the answer to this question is the way that software should be built.
I don’t mean that developers should be given an all or nothing proposition. What I mean is that we should be building and designing software as if I proposed the above situation.
This might sound a bit crazy, but think about it for a bit.
Most developers today are paid a salary. Some salaries have bonuses attached for performance, but rarely are we put in a situation where making mistakes or not being as efficient as possible results in dire consequences. The worst that can happen in most cases is that we would get paid for the work we did and then be looking for a new job at the end of the project.
Losing all the time we put into the project and losing out on an opportunity to make a million dollars would be some consequence.
We’d think about software development quite differently
It’s really hard for me to answer the question of whether or not practices like TDD are worth it. I mean sure, I tell my manager it is. I emphasize quality over speed. I say we need to do this or that, but honestly I don’t really know.
I’ve never been put to the test.
No one has ever said to me, “succeed or die.”
No one has ever put the consequences of my choices directly in my own hands.
Never have I actually had to weigh the weight of extra time spent refactoring code, writing unit tests or using an ORM instead of writing SQL directly in my source code.
I choose technologies because they seem good to me or it seems like they’ll help me get things done faster, but I am never really staking much on that choice.
Sure, I may be staking my reputation, or I might lose my job, but chances are I’ll just blame some failure on some other reason or worse yet, I won’t even recognize my failure, because it will be disguised by “good enough.”
“Man, John, you are a big fraudulent a-hole! I can’t believe you go around touting to know stuff, leading people down paths that you yourself don’t even know are correct. Burning up other people’s money in your test lab of software development.”
Maybe it’s true. Maybe I am a big ignorant and arrogant jerk, but somehow I feel that I am not alone.
I’m not saying we don’t or shouldn’t have strong convictions.
I’m not saying that we don’t have good reason to believe the development methodologies and practices we suggest and follow are correct.
What I am saying is…
Our beliefs about software development are mostly theoretical
8 years ago I would have told you that you needed to create UML diagrams before you write any code.
5 years ago I would have probably emphasized the importance of always having an XML schema. I would have told you data without schema is meaningless.
I don’t hold either of those views today.
Perhaps you’ve changed your views in the past few years as well?
The point is that even though we may be down in the trenches doing software development and to some degree finding out what works and what doesn’t, we are basing the results on OUR motivations not the motivations of our customers or our employers.
So, we may eventually get good at making things easier for ourselves, but unless your feet are held to the fire, you’ll never really optimize for building the best software as efficiently as possible.
If you think you already are focusing on building the best software as efficiently as possible and I am just full of crap and you don’t operate that way, I would strongly suggest doing a thorough self-check and also please tell me the secret of the most efficient way to build software, because I definitely want to know.
What about startups or open source projects?
You might be tempted to think that working for yourself or not for money at all would change things, but I’m really not sure that is the case.
I’ve worked on plenty of my own software projects where my fate was directly in my hands.
I’ve built applications like PaceMaker where my financial success with the endeavor was directly tied my own efforts and my efforts alone.
But, do I think I built PaceMaker as efficiently as possible?
No, definitely not!
The problem with PaceMaker and other projects where there is a big potential upside, is that the upside potential is not guaranteed.
I can assure you that if someone said to me that I have 6 months to build PaceMaker and if I succeeded (according to the rules I stated above) that I would be given $1 million dollars, but if I failed I would be given nothing, I would have probably gone about the whole process an entirely different way.
I’m not saying I would have built it with perfect efficiency, but my motivations would have entirely matched up with the footprint of building software as perfectly as possible.
What I mean by this is that I would be trying as hard as I could to do what I absolutely believed was mostly likely to benefit me, and by doing so I would be trying as hard as possible to completely optimize the process of building that software.
What can we do about this?
Now I can’t tell you how I would have built PaceMaker had I been given the million dollar challenge.
There is no way that I could objectively put myself into that situation and give you an answer.
Would I have bothered with unit tests? Would I have have created backlogs and written UATs to make sure they pass? Would I have used an IoC container?
The plain and honest answer is, I don’t know. All I know is that I would have done things differently and on any software project you’ve worked on, you probably would also.
There are a few things we can gather from thinking about this hypothetical proposition.
- Don’t think you know the answer, but at the same time have convictions about what you currently believe. Just hold on to those convictions loosely.
- Even though you can’t realistically be completely objective and build software as if someone was going to pay you 1 million dollars (just like you can’t tickle yourself) you can still try to think as much as possible with this mindset. It is a worthwhile exercise to imagine as if the decisions you are making and the convictions you are holding onto are based on idealism or reality. We could also all examine and at least understand our own motivations.
- Recognize others are in the exact same boat you are. Don’t believe everything an expert says or even believe there are experts. Experience and wisdom count for something, but no one has anywhere close to all the answers.
I’d love to see this experiment actually played out. I’d really be curious to see what the outcome was, especially in a team situation.
Perhaps someday, someone will actually conduct this experiment and share the results.
What about you? How do you think being given the million dollar challenge would change the way you develop software?
I like to procrastinate.
I don’t really enjoy procrastinating, but it is one of my weaknesses. I’ll delay doing something that I know is important until the last moment that it needs to be done.
I’ve learned to overcome this weakness of mine by trying to be more productive to compensate for it.
Blah, blah, blah, productivity system… procrastination… blah blah blah!
I know you’ve heard it all before, but here is the strange part—I almost always get things done well before the deadline.
So what is my problem then?
My problem is that when I sit down to actually do the work, I end up doing a million other little things.
Even though I am overcoming the results of my procrastination by self-imposing much earlier deadlines, I am still fighting against the core of my procrastinating nature.
It is like I have put the angry demon of procrastination in a cage where he can’t harm me, but because I have to constantly feed him and deal with his demands, he’s still slowing me down.
I call it micro-procrastination
Perhaps you suffer from it to.
The symptoms are as follows:
- Sit down to do work and first check Facebook, Twitter, emails and every other single site that could have something interesting and updated for you.
- Justify in your head that you need a 10 minute or so transition period to check all this stuff before you sit down to actually do the work you intend.
- Pick something smaller that is not important and work on that instead. (Clean out email inbox, etc.)
Just about every week, my goal for the week is to record 2 modules for whatever my next Pluralsight course is.
I really never miss this goal, but it would often take me a while to get started each night. I would sit down to do the work, but not actually get to working until about 30 minutes to an hour after when I had first sat down at the computer.
Once I got started, I usually found that I didn’t have any problem continuing with the work until it was finished.
I tended to do the same thing with my blog posts as well. I know now I need to get a blog post down each week, but it would always take me a while to get started writing the post itself.
Even when I went to write code or solve a programming problem, I noticed that I would try to do many other work related activities like answering emails or further investigating a problem, rather than just working solely focused on the task at hand.
I started to notice a common occurrence between all of these situations in my life. If I got about 15 minutes into actually doing my Pluralsight course, writing my blog posts, or coding up a feature, I’d almost always end up staying focused on the task.
I found that I would often not want to quit something once I got started. I’d even miss lunch or be late for lunch or bed because of this.
The 15 minute rule is born
Based on this observation, I decided to try a little experiment. The next time I was going to work on something, instead of doing my usual ritual of checking email, checking twitter etc, I did the following steps:
- Pick out the single task I am sitting at the computer getting prepared to work on. (It helps to define this very clearly.)
- Turn of all distractions for 15 minutes or just decide not to let them bother me for that time period.
- Work without pause, without break and without excuse for 15 minutes straight.
- At the end of 15 minutes, if I want to quit, then I can quit or multi-task.
What I found is that after 15 minutes of working steadfast and diligently on a single task, I didn’t want to quit.
I found that something that I had no motivation or desire to actually be working on 15 minutes before was now all I could think about.
I found that just like it takes the first few chapters to get into a book and actually feel compelled to continue reading it, it takes about 15 minutes for me to get drawn into my work and want to see it finished.
I’ve been applying this “15 minute rule” pretty regularly now, and I have been having some pretty fantastic results.
I’ve also slipped up on occasion and reverted back to my old ways and have had quite the opposite of results.
I’ve tried other systems
Now I’ve definitely tried many other systems that attempt to solve the problem of procrastination or productivity or both, but none of them seemed to work all that well for me.
I know these other systems work, and I know plenty of people are successful with them and that my system isn’t really much of a system at all—it’s just what I do.
The problem I have found with other systems though, is that they are either:
- Too complicated to apply regularly unless you are 100% devoted. (Big barrier to entry.)
- Only address productivity, and priority, but not actually doing work.
- Assume you can sit down and actually do what you have set out to do. (Which remember, was the hardest part for me.)
I am a big fan of Getting Things Done and I highly recommend it. At the very least read it, because it just has some great overall advice, but…
I don’t apply it anymore, because I don’t need to organize what I need to get done. My life is currently so packed and scheduled every day that I already know exactly what I need to be doing just about every hour of my day.
I don’t even watch TV or movies… Ever. No really, I mean never ever.
So, with my schedule being so packed, my biggest problem isn’t figuring out what I should be doing—I’ve got that covered. Instead, my biggest problem is doing it efficiently.
The closest technique to what I am doing is probably the Pomodaro technique. I also think this is a great technique and is likely to work for many people.
I’ve just found that my mind tends to defeat the technique by telling me that I don’t have enough time to get a whole Pomodoro done right now, so I should just do part of one.
You could call what I am doing a modified Pomodoro technique, whereby I set the duration to 15 minutes and actually try to avoid taking breaks for as long a possible.
Why the 15 minute rule works
I suspect the main reason why this technique works is because of momentum.
When we start to get momentum going for us (and 15 minutes seems to be just about enough time to do so) it is much harder to change course.
Focus is also a big part of the 15 minute rule. The world today is a fast paced multi-tasking parallel processing rat race in which we are conditioned to switch our attention between multiple things all at once.
If you are reading this post right now, you probably have even switched back and forth between multiple browser tabs or chat windows or something else and aren’t focusing 100% on reading. I don’t have 15 minutes to grab your full attention and draw you in (unless you are a very slow reader, in which case I congratulate you for making this far.)
The point is, we have to purposely focus on a single thing in order to turn off that natural tendency to try to be omnipresent.
Doing the 15 minute rule forces me to focus, and that focus tends to shut off everything else in my mind with has the potential to distract me.
The 15 minute rule also prevents me from overthinking about a problem and standing back to admire the problem instead of working on it.
It frees me from obligation. If I know I have to work for 15 minutes, I am not afraid of not making much progress. My only obligation is to be working on the task at hand, without interruption and with complete focus for 15 minutes.
I also find that after 15 minutes, I’ve developed a commitment to the work. Because of the time I’ve already invested in the task, I feel more compelled to complete it.
Applying the rule
Hopefully you’ll find this technique useful and if not perhaps you have a better suggestion or technique. If you do I’d very much like to hear it, since I am always looking for some practical ways to be more efficient.
Before I let you be on your way, I’ll leave you with some parting advice that I’ve found useful when applying the 15 minute rule.
- Remove all distractions. That may mean closing browser windows or turn your phone off or just deciding to ignore everything else.
- Don’t forget to focus. Removing distractions is not enough, you must also focus intently on what you are doing. Be present in the moment.
- Work, don’t think. I know thinking is working, but the mind wanders too easily and merely thinking about a topic doesn’t seem to create that same mental traction. This might mean you start writing a first draft or first hack, but it is important to be actually “doing.”
- If you feel like you can’t start “doing,” make your “doing” brainstorming, but brainstorm by actually writing a list or making a mind map.
- If at the end of 15 minutes you are still not into the work and want to quit, go ahead. Come back a little later and try again.
- Take breaks when you need to, as long as the initial focused 15 minutes has passed, I’ve found that I can take a break and actually want to get back to my work.
- Put a sticky note on your monitor or somewhere you’ll notice that reminds you that when you sit down to work to start off with the 15 minute technique.
What slows down the development of software?
Think about this question for a bit. Why is it that as most software evolves it gets harder and harder to add features and improve its structure?
Why is it that tasks that would have at one point been simple are now difficult and complex?
Why is it that teams that should be doing better over time seem to get worse?
Don’t feel bad if you don’t have an immediate answer to those questions. Most software practitioners don’t. They are hard questions after all.
If we knew all the answers, we wouldn’t really have these problems to begin with.
Regardless though, you’ll find many managers, business owners, customers and even software developers themselves looking for the answers to these questions, but often looking in the wrong place.
Process is almost always the first to be blamed. It stands to reason that a degradation of process or problems with the software development process are slowing things down.
Often there is some merit to this proposition, but I’ve found that it is often not the root cause. If your team is not sitting idle and the work that is important is being prioritized, chances are your process is not slowing you down.
Now don’t get me wrong here. I am not saying that these are the only two important aspects to judge a software development process, but I am saying that if generally your team is working hard on important stuff most of the time, you can’t magically improve process to the point of increasing productivity to any considerable order of magnitude. (In most cases.)
Often questions are asked like:
- Should we pair program or not pair program?
- Should we be using Scrum instead of Kanban?
- Should we be changing the way we define a backlog?
- Should we use t-shirt sizes or story points or make all backlogs the same size?
- Do we need more developers or more business analysts?
- Do we need to organize the team differently?
Now these are all great questions that every software project should constantly evaluate and ask themselves, but I’ve found over and over again that there is often a bigger problem staring us in the face that often gets ignored.
Let’s do a little experiment.
Forget about process. Forget about Scrum and backlogs and story points and everything else for a moment.
You are a developer. You have a task to implement some feature in the code base. No one else is around, there is no process, you just need to get this work done.
It might help to think about a feature you recently implemented or one that you are working on now. The important thing with this experiment is that I want to take away all the other “stuff” that isn’t related directly to designing and implementing that feature in the code base.
You will likely come to one of these conclusions:
1. The feature is easy to implement, you can do it quickly and know where to go and what to modify.
Good! That means you don’t really have a problem.
2. It is unclear what to do. You aren’t sure exactly what you are supposed to implement and how it fits into the way the system will be used.
In this case, you may actually have somewhat of a process problem. Your work needs to be more clearly defined before you begin on it. It may be that you just need to ask more questions. It may be that half baked ideas are ending up in your pipeline and someone needs to do a bit more thinking and legwork, before asking a developer to work on them.
3. Its hard to change the code. You’ve got to really dig into multiple areas and ask many questions about how things are working or are intended to work before you can make any changes.
This is the most likely case. Actually usually a combination of 2 and 3. And they both share a common problem—the code and system do not have a design or have departed from that design.
I find time and time again with most software systems experiencing a slow down in feature development turnaround that the problem is the code itself and the system has lost touch with its original design.
You only find this problem in successful companies though, because…
Sometimes you need to run with your shoelaces untied
I’ve consulted for several startups that eventually failed. There was one thing in common with those startups and many other startups in general—they had a well maintained and cared for codebase.
I’ve seen the best designs and best code in failed startups.
This seems a bit contradictory, I know, but let me explain.
The problem is that often these startups with pristine and well maintained code don’t make it to market fast enough. They are basically making sure their shoes laces are nicely tied as they stroll down the block carefully judging each step before it is taken.
What happens is they have the best designed and most maintainable product, but it either doesn’t get out there fast enough and the competition comes in with some VB6 app that two caffeine fueled not-really-programmers-but-I-learned-a-bit-of-code developers wrote overnight or they don’t actually build what the customer wants, because they don’t iterate quick enough.
Now am I saying that you need to write crap code with no design and ship it or you will fail?
Am I saying that you can’t start a company with good software development practices and a clean well maintainable codebase and succeed?
No, but what I am saying is that a majority of companies that are successful are the ones that put the focus on customers and getting the product out there first and software second.
In other words if you look at 10 successful companies over 5 years old and look at their codebase, 9 of them might have some pretty crappy or non-existent architecture and a system that departed pretty far from the original design.
Didn’t you say something about pulling up your pants?
Ok, so where am I driving at with all this?
Time for an analogy.
So these companies that are winning and surviving past year 5, they are usually running. They are running fast, but in the process of running their shoelaces come untied.
They might not even notice the shoelaces are untied until the first few times they step on one and trip. Regardless they keep running. And to some degree, this is good, this is what makes them succeed when some of their failed competitors do take the time to tie their shoelaces, but those competitors end up getting far behind in the race.
The problem comes pretty close to after that 5 year mark, when they want to take things to the next level. All this time they have been running with those shoelaces untied and they have learned to do this kind of wobble run where they occasionally trip on a shoe lace, but they try to keep their legs far enough apart to not actually step on a shoelace.
It slows them down a bit, but they are still running. Still adding those features fast and furious.
After some time though, their pants start to fall down. They don’t really have time to stop running and pull up those pants, so as they are running those pants slip further down.
Now they are really running funny. At this point they are putting forth the effort of running, but the shoelaces and pants are just too much, they are moving quite slow. An old woman with ankle weights power walks past them, but they can’t stop now to tie the shoelaces and pull up those pants, because they have to make up for the time they lost earlier when the pants first fell down.
At this point they start looking for ways to fix the problem without slowing down and pulling up the pants. At this point they try running different ways. They try skipping. Someone gets the idea that they need more legs.
I think you get the idea.
What they really need to do at this point though is…
Stop running, tie your shoes and pull up your pants!
Hopefully you’ve figured out that this analogy is what happens to a mature system’s code base and overall architecture.
Over time when you are running so fast, your system ends up getting its shoelaces undone, which slows you down a little. Soon, your system’s pants start to fall down and then you really start to slow down.
It gets worse and worse until you are moving so slow you are actually moving backwards.
Unfortunately, I don’t have a magic answer. If you’ve gotten the artificial speed boost you can gain from neglecting overall system design and architecture, you have to pay the piper and redesign that system and refactor it back into an architecture.
This might be a complete rewrite, it might be a concerted effort to get things back on track. But, regardless it is going to require you to stop running. (Have you ever tried to tie your shoelaces while running?)
Don’t feel bad, you didn’t do anything wrong. You survived where others who were too careful failed. Just don’t ignore the fact that your pants are at your ankles and you are tripping over every step, do something about it!
Deploying software doesn’t have to be that complicated!
I’ve seen and built many software building and deployment solutions over my career, and I have come to find that most software deployment can be boiled down to a simple process.
I’m not trying to give you a solution for your software deployment automation, nor am I trying to perfectly model your exact process.
What I am trying to do in this post, is to help you to simplify your process.
If you can identify the parts of your deployment process that fit into the simple steps I am going to outline below, it should be much easier for you to automate your deployment process.
Even though software build processes, infrastructure and components are unique, I have found that most software deployment processes can be simplified into the following steps.
- Build software without configuration
- Create environment specific configuration.
- Create a set of database changes.
- Bundle software, configuration and database changes.
- Apply new software
- Apply new configuration
- Apply new database changes
- Start it back up
You might read through these steps and think “well duh.”
You might be tempted to say “my process is more complicated than that.”
I’m not going to argue with you. You are right, your process is probably more complicated than that. But, does it need to be?
Can you simplify your process to fit into these steps?
Sure, the implementation of these steps is likely to be fairly complex and vary for each type of software, but if you can distill the process into these steps, you can much more easily automate that process.
Where people go wrong
The big key to my simple version of deployment is
Build software without configuration
You MUST do this! Departing from this step causes all kinds of pain and complexity. Please don’t try to build your software and the configuration for an environment at the same time. These things must be pulled out from the get g or you will have the pain of trying to tease them apart later – or you will have to create separate builds for each environment.
It is also critical that the same bits that were built by your build server are what is deployed to each environment!
I will say that this isn’t the easiest problem to solve. You may need to have a separate build process that builds up the configuration for an environment.
Separating the two will also force you down the path of building a process to apply that configuration to an environment.
But, if you are willing to accept that this is just a must and bite through this pain, you’ll come out on the other side clean (even though you had to crawl through tunnels of crap.)
The whole story
Now that I’ve hopefully convinced you to separate your configuration from the building of your software, let’s go over the big picture of a deployment using the simple process outlined above.
It all starts out when you build your software. Perhaps you have a continuous integration build server setup that is automatically building software on each check-in; perhaps you are manually kicking off a script.
Once you have built your software, you have some bits that you should be able to apply to any environment. Nothing that you built here should be machine or environment specific in any way.
Now, you kick off another process, or perhaps one was kicked off simultaneously by your continuous integration server. This builds up the configuration for the environment you are going to deploy to.
A similar process is kicked off—also could be simultaneous, for generating a list of database changes that need to be applied to the target environment.
Now that you have your bits, configuration and database changes, you are ready to deploy.
If you are smart, you’ve even built these ahead of time and they are just waiting for when you need them.
Next, gather up the artifacts and move them to the deployment target where you actually apply them.
First, unpack your bits and put the new bits into place. (You may or may not need to take your application fully offline to do this.)
Then apply the new configuration on top of your newly installed bits for that environment.
Finally, apply database changes for that environment.
Now you should be completely deployed and can start up your application.
But how do I do it?
Perhaps you agree with me that the actual process should be what I have outlined and described, but now you are at the point of implementing a solution.
How do you actually automate this stuff?
Good question. If you figure out a simple answer, let me know.
This is the point where you might be writing custom tools and scripts to get all this working. The key is to take it one step at a time.
There are at least two tools out there that I know of that help you do this. I can’t speak for either of these tools, since I haven’t used them myself, but I have heard good things about them.
One other thing to consider is how you are going to get the right stuff to the right server. You will want to think about things like:
- Promoting build products
- Preloading promoted products to servers to make deployment faster
- Getting through firewalls by having the software or some other process PULL the upgrade to your target, rather than you PUSHING it there.
- Rollback, or some kind of mitigation strategy if things go wrong. (My recommendation here is not to get fancy. I have NEVER seen a successful rollback, only a database restore followed by a manual code restore. If you mess up bad, just count on restoring the machine and the database.)
Pay attention young programmers, this is the most important piece of programming advice you will ever hear.
Well perhaps not, but it might be the most important piece of programming advice you hear today.
“Switching gears is grinding gears.”
I’ve been doing this programming thing for quite a while now, and I have come to realize that the biggest thing that saps my productivity is switching gears.
What do I mean by switching gears?
Many different contexts
Switching gears can apply to a variety of different contexts, but it is basically whenever you are working on some task or technology and have to stop what you are doing and either do something else or change the type of thing you are doing.
This is really a bit different than multi-tasking. Multi-tasking is really trying to do more than one thing at once. It usually involves a large amount of rapid context switches, but for this post I am more concerned about the general idea of breaking rhythm.
I think it is easier to speak about this subject if we talk about some specific applications of the idea and why they are harmful.
In the Agile world of software development today, we often are required to switch from problem domain to problem domain as many of our iterations contain mixes of different features on different parts of the system and bugs to be fixed.
Have you ever been in the situation where you were just beginning to understand how some area of the code base worked, or how to work with a particular customer on a particular problem space and then had to switch to something else and start all over again?
Even when you switch back to the original context you were working with, if enough time goes by, it becomes new again. You have to relearn much of what you had learned the last time and just when you begin to hit your groove, the cycle begins again.
This form of switching gears is at the very least frustrating, and at the most a complete demotivator and productivity sapper.
Unfortunately for most developers, this problem is out of your immediate control. But, take note product owners and project managers, there is a reason why iterations should have a goal.
If you are in the precarious position of being a developer pinned against the ropes, try to make some noise and let your management and product owners know that your team will be much more efficient when you aren’t switching gears all the time.
In my experience, the results of replacing this constant context switching with the synergy of a common goal and related features in a segment of time has an astounding effect on productivity that is hard for any serious businessperson to ignore. So speak up!
Switching technology is painful!
It really isn’t worth trying to fight this because you are going to be going against the technology grain to do so. Although, I do suppose this may be one of the reasons for the recent popularity of Node.js.
I’m not saying to not learn new things. It is very important to always be learning.
What I am saying, is to try to find some kind of rhythm with the technology stack you are working with and try not to switch that up.
Technology specific training can really help here as well. I for one, need to learn JQuery better. The problem is that when I am working on a web based feature, I am not forced to learn JQuery because I am not in that context long enough.
So what do I do instead?
I waste time Googling for answers. I know that I have a short coming here and I need to just bite the bullet and spend some dedicated time to really thoroughly learn JQuery, because by Googling for little pieces of it at a time, I am not really making much headway and the context switch ends up stealing what I do learn from my memory.
One more aspect of this is the idea of focused teams. Many software development groups do not like to specialize their developers onto one focus area. I agree whole-heartily with the idea of non-specialization.
But! There is huge benefit to be gained by keeping the same group of developers working on a specific set of technology or part of the code base for a set period of time. I’ll talk about this a bit more, towards the end of this post, but the basic idea is that it takes time for people to find their groove.
I think it is optimal to break any large team up into smaller technology area focused teams that regularly rotate every 3 months or so. The idea here is that you give those teams enough time to get good at what they are doing and actually commit what they have learned to memory, but you rotate them often enough that they don’t end up becoming specialists which are unable to see the whole picture.
This one typically isn’t an issue, but it can be depending on the environment that you are working in.
Teams need enough time to go through that forming, storming, and norming set of phases. If you are constantly interrupting this process by switching around team members, you are never going to get the team to act as an entity of its own.
Teams are generally more efficient than individuals, because they benefit from synergy, when 1 + 1 = more than 2.
But just like a big truck taking some time to get up speed, a team takes time to get going. Also like a big truck, a team can gain momentum that individual developers seldom can achieve.
A smaller aspect of this is pair programming. I suppose that many have been successful switching up programming pairs once a day or so, but I suppose that more teams have been successful switching up pairs at longer intervals.
For me, this interval varies. Sometimes, I feel like I need to stay paired with a teammate for longer than 2 weeks, which is our regular interval, sometimes 2 weeks is fine. It depends on what you are working on and how much momentum you have.
They key here is to make sure that you are giving teams enough time to take up their own flag and stake their territory. Teams can take some time to find their common goal. Self-direction can really help with this.
Ever tried to turn a flat head screw with a screwdriver, but it doesn’t quite turn, because you can’t seem to get the head of the screwdriver into the groove of the screw?
You twist that screwdriver around a bit until finally it slips into the groove. Then when you turn the screwdriver the screw turns with it.
As humans, we tend to be like screwdrivers, we have to find our groove. We all have this adjustment period where we are fumbling through things.
It is very important to make sure that we aren’t switching gears so often that we are not actually turning any screws once we are in the groove.
Regardless of what kind of context switching you are doing—whether it is problem domain, technology or teams—it is important to make sure that you are not spending 90% of your time finding the groove and only 10% of your time “in the groove.”
Depending on what you are doing and what the context switch is, the proper amount of time before switching contexts is going to vary, but I think it is very important be aware of this phenomenon and plan around it. If you don’t you are going to end up spinning your wheels, which is unfulfilling to say the least.