I was thinking about how to get rid of the singleton anti-pattern that is being used throughout the Vassal code. This is a huge hindrance to maintainability, right now it prevents all kinds of proper testing, and the code can not be properly maintained and refactored without first putting it in a test corset.
I would like to know what the other developers think of this, and also what the interested non-developers think about this as it directly concerns the future of “Vassal Java”. And it does need a future as “Vassal 4” or whatever will be the name of it is still at least 5 to 10 years away, given the current availability of development resources.
Applying the old programming wisdom that any problem can be solved by adding another level of indirection, I have come up with the following plan:
-
step 1
– create one god-singleton, e.g. with the name “VassalInstanceFacade”, have it use a classic singleton pattern with “private static final VassalInstanceFacade instance” and “public static VassalInstanceFacade getInstance()”
– give this facade non-static methods for accessing all other singletons like GameModule, DragBuffer, and also the static methods from PlayerRoster and Map
– deprecate the current static accessors of the singletons like GameModule.getGameModule(), DragBuffer.getBuffer() etc, tell the clients to use VassalInstanceFacade.getGameModule(), VassalInstanceFacade.getDragBuffer() instead
– in the Vassal code, replace calls to GameModule.getGameModule() with VassalInstanceFacade.getInstance().getGameModule() -
step 2
– replace calls to VassalInstanceFacade.getInstance() with a reference to an actual instance of VassalInstanceFacade that is passed to the clients from above, via constructor
– start to write unit tests that pass a mocked VassalInstanceFacade to its clients -
step 3
– use an IoC container to inject instances of VassalInstanceFacade into its clients -
step 4
– split up the VassalInstanceFacade into its subcomponents, have the IoC container inject separate GameModule, DragBuffer etc objects into their clients -
step 5
– refactor the shit out of the current spaghetti code, split up all these god classes into a proper GUI-less model, split the rest into views and controllers, do all of this in a proper test corset
Some of these steps will need to have many small sub-steps, some might be done in parallel, this is only a rough outline. As for development resources, I cannot speak for others but I am willing to spend time on executing this plan. I am not a C++ developer and will have zero involvement with this new “Vassal 4 in C++” anyways.
Feedback is very welcome!