The best possible way to avoid this problem is to use the Observer pattern built into Magento whenever possible. It's not in nearly enough places, but when you have the option, using it will let you play nicely even with other poorly behaved extensions.
Nextly, try to override the minimum number of classes. It sounds obvious, but there have been times when I've thought it was necessary to override every one of the shipping calculator classes (the code was easy, but needed to be repeated). With some more work, I was instead able to override a single class and save myself some maintenance headache to boot.
When you do this, you may still run into conflicfts with other extensions overriding the same classes you are. This is unfortunately not a solved problem in Magento, and there isn't a great way to resolve it other than contacting the person in question and hashing out a solution.
Finally, to the problem of upgradeability, a common problem I see in people's code is that they, without thinking, override an entire function when it isn't necessary. So you get this:
function doSomethingUseful() {
// ...100 lines of parent code...
unset($result['badKey']);
// ...100 lines of parent code...
return $result;
}
When you go to upgrade a site, that's 200 more lines of code likely to cause a bug. Bad times! Instead, something like this often works (and is an easy improvement):
function doSomethingUseful() {
$result = parent::doSomethingUseful();
unset($result['badKey']);
return $result;
}
It's faster, it's more readable, it's less error prone, everyone wins!
Hope that helps!
Thanks,
Joe