Making your Force.com package “managed released” allows your users to safely upgrade to newer versions of your package in the future. Unfortunately this is accomplished by forcing your future data model to be a superset of your entire current data model – there is no way to limit what is exposed so forget about encapsulation.
In the real world all data models change over time.
One way to work-around the problem of needing to change a field is to just add another field and stop using the original field. Your customer’s code will continue to compile and run though it is unlikely that the expected functionality will result as their code is relying on the original now unused field rather than the replacement field. And unless they have good quality unit tests written it may take a while for them to discover the problem.
I hit a road-block case for which the work-around does not work. I had a master-detail relationship and wanted to replace the master object with a different object. During the refactoring I created a trigger to always populate a reference to a dummy master object in the detail object – not nice but it kept the unit tests working. But when I then looked at the user interface layouts I discovered that the reference to the master object cannot be removed from the layout and its required check-box cannot be unchecked. So the user is forced to enter a value (an irrelevant reference to an irrelevant object) before the trigger can do its work – hardly acceptable usability.
All that can be done to “solve” the problem is to put the code in a new “managed released” package using a different namespace. This means that new instances will work fine. But it also means that there is no upgrade path at all for the existing old “managed released” instances. Also creating a new package is an error-prone process as the packaging meta-data has to be manually re-created.
Please vote for Make managed packages less restrictive / more intelligent – the present mechanisms are just too basic to meet real-world needs.