During my life and career as a programmer, I have gradually adopted a pragmatic attitude towards software projects and my role in them. I expect every assignment to end up being something totally different from what was explained in the originally project specification. Also, at any given moment fundamental conditions for the work may radically change in relation to what they were a month or even week ago, and they may do so many times. This is to be expected of any normal software project.
I believe this because I see it happen constantly in projects I work in, but I have also figured out that there may be a logical reason for it. Here's what I think:
There is a good chance that every software project will contain elements, large or small, that no one has ever done before. Also, there will most likely be elements, large or small, in a software project that you partake in, that you have never done before.
The reason for this is one of the things that sets programming apart from other crafts: duplication. It's popular to compare programming with other vocations, such as architecture/house building. Most of these comparisons fall flat - creating a piece of software has little in common with building a house. You might compare it to the work of machine engineers, since a computer program can be seen as a kind of machine. Writing a program can be compared to making the blueprint for a machine (or collection of several machines working on a conveyor belt), making soda bottles or mowing the lawn.
But where machines need to be set up in a physical location, possibly needing adjustments to the blueprint to adapt to the environment it runs in, a software program lives in the memory of a computer, where it has all it needs, no more tangible than the thoughts in my brain as I am writing this text. And where a machine needs time to be physically set up, connecting parts that have been transported to the location where the machine is assembled, a software program, once written and ready for production, may be installed on a computer in minutes. If it is prepared for its platform, in the blink of an eye.
In a software project, the resulting product (putting aside project plans, minutiae, and other side effects deemed crucial to the workings of a successful project) is some source code that may be used to create a working piece of software on some selected platform. You need to make this source code (actual program code plus configuration data used by the program code) because you can't use existing software to do the task you need accomplished.
This may be because the software you need has been written by someone else, but requiring too high a purchase price - you believe you can create the same software yourself at a lower cost. Or maybe the software exists for Linux, but you are restricted to using Windows computers. Or maybe the software doesn't exist at all. I have personally dealt with mostly the last of these three possibilities. I believe the first one is rare, except for hobbyists, who often don't organise their work into projects.
Unless you're too mean to buy existing software (or, as is sometimes the case, have an irrational fear of using free software), there will be elements in your project that no one has done before, be it conditions of a new platform or a whole new software solution that the world has never seen. Certainly no member of the project has done it before. If they had, they would dig out their old source code, copy it, and then look for something else to do. If the software exists as free, open source software on the web, the software developer may well download and use it despite restrictions put by the employer, maybe changing some labels to disguise the true origin of the code.
The never-heard-of challenges of a new piece of software can often go deep into the low level. Sorting a list is a classical problem in computer sience, with many established solutions for different situations, but this project might need to sort a huge matrix with respect to other structures on some ad hoc-basis, without needing an aeon to complete. The developer needs to think up a solution for this with little help from the giants whose shoulders he thought he was standing on.
The current trend of development systems with short intervals between status updates, team programming etc may be well suited for handling this issue concerning the unknown that is inherent in all software development. I still feel that we could be humbler and more accepting towards the fact that we don't always know quite what we are doing, in life as in programming.