The 20081211 article [WayBack] Don’t use global state to manage a local problem – The Old New Thing reminds me of a process I went through with a programming team a few years ago.
A lot of their source base came from the procedural era: global variables and global methods. No classes. No methods on records.
Taking them to the level of reference counted immutable instances that used dependency injection as an architectural design was a long journey.
Early in their journey, they would create a lot of methods on classes and records at the class level.
Then they started introducing instances that were basically singletons.
Finally they made real instances that could have more than one available at run-time. These would still create other instances when they needed, often through a few singletons that were still left (for instance session state, database connection state, etc).
Then they introduced caches and pools to keep things alive longer than as to speed up things. It also highly complicated life-time management.
Finally they backed down, and started hooking up things through dependency injection.
A lot of the above caused global state to be used for solving local problems.
It was a tough, but fun time, to get them on the right path, tickling them with the right puzzles at the right time to steer them through their journey..
–jeroen