Versioning and Evolution: The Heat Death Problem
One challenge with serialization is evolution. Your data format today might not be your data format tomorrow. Consider:
(defun save-versioned-state (filename state version)
"Saves state with a version tag.
For when you know the format will change but pretend it won't."
(let ((versioned-state (tuple 'version version 'data state)))
(save-state filename versioned-state)))
(defun load-versioned-state (filename expected-version)
"Loads state and checks version compatibility.
Returns error if versions don't match, because mixing versions
is like mixing matter and antimatter: exciting but destructive."
(case (load-state filename)
((tuple 'ok (tuple 'version version 'data state))
(if (== version expected-version)
(tuple 'ok state)
(tuple 'error (tuple 'version-mismatch version expected-version))))
(error error)))
This pattern helps you evolve your data formats over time without painting yourself into a corner. When you need to upgrade:
(defun migrate-state-v1-to-v2 (v1-state)
"Migrates from v1 to v2 format.
v2 adds 'anxiety-level' field because that's progress."
(let (((tuple 'player name 'inventory items 'location loc 'status status) v1-state))
(tuple 'player name
'inventory items
'location loc
'status status
'anxiety-level 'moderate)))