Then the debugging cycle starts and we get trap into a fix/deploy/re-fix/re-deploy circle as the user is asking for more and pointing out that what we've developed does not meet his requirements.
At some point, we would need to start from scratch as the code is getting harder and harder to maintain due to the fact that it was a mere proof of concept at the start.
The issue is not your developper skills nor that users are asking the impossible. You were too eager to start coding and did not make sure that you understood everything about the initial request.
The best way to ensure that you know everything that is required for a new feature is to write a functional documentation. I know, it can be boring if you don't like to write, but it will save a lot of time and money in the end.
Upon a new request, the first thing you should do is asked: Why? Take notes, take the time to understand the whole issue from the user's point of view. Try to figure out what the user is trying to achieve by having this new feature. In fact, it may be hiding another issue easier to fix or he may be simply not know how the use the existing softwares properly. It's a matter of figuring if that new request will solve his problem or just add another layer in his work process.
Write everything down in details. Describe each and every steps of the work process. Try to explain with words the main issue, the current work process and finally, the new work process that will be put in place with the new feature.
Make detailed list of data that will need to be handled, each conditions, each constraint. Ensure that you have covered all possibilities and results that should be provided on each one of them.
Once you have completed that documentation, review it with a colleague. Ensure that what you have written does explain the issue and the solution so that anyone will understand the whole process using your documentation.
Finally, review the documentation with the requesting user to ensure that everything has been covered. Often, the user will realize that something is missing or that the described process is not exact and will provide you with valuable informations. Rework your document until the user is satisfied.
At this stage, no code was written, everything has been covered and the user as approved the final result.
Writing a functional document can take a few hours to a few days. Writing code that will need to be fixed over and over again can take months if not years. Better edit a text document than a 100k of lines of code.
If you are having a hard time putting down your solution in spoken words, how can you expect to write down the perfect code?
Listen, explain, validate then code!