For many years, I have been sending messages around large Max patches using send and receive objects. However, I'm starting to see the benefits of using value objects.
The biggest drawback to value objects, and why I avoided them previously, is that if you update a value, it doesn't spit that new value out of all other named instances of value. So in that sense, it's less "immediate" than just sending messages using send/receive.
However, as patchers start to grow in complexity, keeping track of all the variables becomes more difficult. One solution is to place a copy of all value objects in a single subpatcher, and have that patcher act as both a sort of "header" file for the whole patch (to answer the frequent question "now, what the hell did I name that variable?"), as well as allowing you to see the state of every variable across the entire patch at once. It's also a good central place to write in your comments about each variable.
Here's an example "global_values" subpatcher. Note the use of the [active] object to bang all the value objects in the patch any time the subpatcher window is opened or brought to the front.
As an extension of this idea, I thought of a possible design pattern for creating large patches: all values go into value objects, and send/receives are used for bangs only. The one exception would be for sending messages to display objects – if the destination of a particular message is simply to be shown on screen for the user to read, then you might as well just throw it down a send/receive chute, rather than go through the effort to save it into a value.
Obviously, using variables in programming isn't a ground-breaking idea! But using variables within Max has been counter to my habits for so long, that this seems like an idea worth sharing and exploring.