Over the past couple years at MathWorks we have been transitioning from a legacy procedural testing framework to what is now MATLAB's native unit test framework. It has been great to see the internal adoption rate of this framework increase steadily as more teams begin to see and utilize its various benefits.
However one of the biggest challenges we have seen in migrating to the new MATLAB unit testing paradigm is the existence of team specific helpers, tools, and ecosystems that are incompatible with the new framework.
Why are they incompatible?
Well, because a central feature of the legacy framework is globally available and Global Variables Destroy Design Information. Read that post first it isn't too long. Near the end of these comments I started jumping out of my chair with my fist in the air yelling Yes! YES! YESSS!!!
Go ahead read it. I'll wait...
Ready? Great stuff eh? Any of that sound familiar? How about:
"Many people say that the wouldn't want to [design without globals] because they imagine that they'd end up passing extra parameters all over the place in their code."
"When a thing is global it is accessible everywhere, and people tend to use it without discipline."
And therein lies the true cost of using global state. There are many, many reasons why global state is a bad thing, but this is perhaps the most pervasive and sinister: global state turns the entire design of the entire ecosystem into one big coupled garbled hard-to-change mess. Global state acts as an implicit parameter to every single function and method call in your ecosystem . When we allow global state we are saying, "Feel free to use this as you like, oh and by the way, since you need it so often we will just go ahead and waive your requirement to tell me you need to use it." That's a little bit like a bank saying, "You seem to withdraw money from your account so often that we will just go ahead and waive the requirement for you to use a bank card and pin. No need to identify yourself with that context, we'll assume that whenever money is pulled from your account it is approved by you. Look how easy we've made it for you. You don't even have to carry around a wallet!"
What could go wrong?
The fallacy is that the global state makes things seem easier at first because it does not require design discipline. It's only down the road that we realize the problems it creates, but by that time the design damage has been done. It is nigh impossible to back out designs that rely on it. The poor design choice of introducing global state negatively effects the design of the entire set of tools that operate in its ecosystem.
Well, in the MATLAB unit test framework we have not relied on global state and have instead required those who operate in the framework to have the appropriate context to do things like verifications and assertions. In tests that do not require using the same ecosystem as legacy tests this has not lead to any significant problems. When the ecosystem is clean there are many in model approaches and patterns to writing tests and related test tools.
However, on the flipside when a test utilizes the full ecosystem and tools built around global accessibility of its parameters it is a much harder problem.
This is not just a testing problem, this is a very general software engineering principle. Introducing global state to the software system causes problems with concurrency (e.g. parallelism using Parallel Computing Toolbox), significantly complicates reentrancy, and is almost always marked by spooky action at a distance.
What is global state in MATLAB? The obvious answer is usage of global variables. However here is a short list of other constructs which can easily be used to introduce global state in MATLAB:
- persistent variables
- objects with Constant properties containing mutable handle objects
- default property values in MATLAB classes containing handle objects
- appdata on a global object, such as the root object
- the Singleton design pattern if it gives access to any mutable state
- Variables defined in the globally accessible (and mutable) base workspace
I have found that very rarely (almost never) does the solution to a given problem truly require using such global state. Think twice (twenty times!) about your design if you are tempted. If it is used in the end, always make sure that the exposure of this state is limited to as few clients as possible.
To leave a comment, please click here to sign in to your MathWorks Account or create a new one.