An excerpt from my upcoming book

There are problems that are complex.  These are the ones that have many moving parts, and there is an emergent behavior that seems greater than the sum of its parts.  Complex problems are fun to solve, and when you’ve done it, you have a great sense of accomplishment.  For example, the Mandelbrot Set is based on a relatively simple equation, and is literally infinitely complex.

Complexity is an intrinsic property of a problem.  Looking at the problem itself, what is the minimal solution for the entirety of the problem?  As simple as possible, but no simpler is the mantra.  As long as the problem is fully stated, the complexity is known, and it can be completed.

Complication, on the other hand, is the set of external considerations, the extrinsic properties.  I could add an Apache server to a linux box and throw it on the internet with a 20-line PHP script to serve content (thus satisfying the full complexity of the problem), but there’s a 99% chance the linux box will be pwned within 24 hours.  Security, therefore, is a complication.  Pre-existing code that you don’t understand and have to work with is a complication.  Development process is a complication.

Complications comprise the ‘work’ part of work.  Some of them you’ll know about, like adding enough security so that your web site is hard to hack, or the code review process you need to get your work into master.  Many of them you won’t know about – a new OpenSSL vulnerability is discovered, an edge case in the code you inherited, a sudden change in the specification.

I will state that at best you can know 40% of the complications involved in a task.  That means that at least 60% of your work is unknown at the time you commit your code to master.  You need to anticipate that 60% and allocate resources to handling these complications.