Another storage option can be suggested. Let's see how the issue is tackled in conventional programs. Data is separated from the code! Moreover, when it comes to complex programs and systems, data is stored in SQL or NoSQL storages.
An ad-hoc smart contract written for the purpose can be used as a storage. Thus, data will always be kept in the storage of this contract regardless of the current token code version. The code of this contract can be moved to a library, but it is not on the agenda now. There will be no need to migrate data from storage to storage; instead, storage access rights are transferred from version to version. Yet, using this type of storage is not without issues. It will require defining an interface available to any version of the token smart contract, e.g. SQL-like or document-oriented. Speaking of an this storage type examples, have a look at EOS tables.
Let's unite structure, field names and data types under the data scheme
umbrella. A storage smart contract code can consist of a static part (the code that doesn't change regardless of the current data scheme) and a dynamic part (the scheme-dependent code). It is the dynamic part that contains a lot of boilerplate code, therefore it makes sense to automatically generate it, as it is implemented in Protocol Buffers or in Apache Thrift. I happened to handle a similar task developing Ethereum columnar data storage prototype
at the ETHBerlin hackathon.
The data item is described by the following structure: