Arguably, there is never going to be a way to cover all possible changes that might be made to the specs. You'd just be writing abstractions =) Sure, you can be highly scalable in your design, and by all means I think you'd be better off for adopting any practices that'll help you in that regard, but ultimately, the most important thing to get across is that your code is not the place to tackle these problems. This is not a technical issue at all.
All customers will want to change the specs. Many are not very tech-savy, and that shouldn't be a problem, because that's our job to be. You'll encounter many customers that'll have a very specific requirement, but no idea what that requirement might entail, or look like in real life. There is only ever going to be one way to deal with this issue:
Make proper agreements. Write a spec that clearly specifies what is included, and - perhaps more importantly - what is not included. Make it clear that any changes to the specs will be implemented at an extra cost, and that they may void any agreed deadline. Make it clear to the customer, when a new requirement comes in, that it is a new requirement - you can't argue about that after the implementation.
In this way, whenever the client has troublesome changes in requirements, you can make it the client's problem, and not yours, in a very professional manner.