In a comment on my earlier post A Globals Class pattern for Python, Mike Müller wrote
“No need for globals. Just explicitly pass your container. In my opinion this is much easier to understand.”
Mike’s comment led me to some further thoughts on the subject.
Suppose you have a number of things — x, y, and z — that you want to make available to many functions in a module.
There are four strategies that you could use. You could
1. pass x, y, and z as individual arguments
2. make x, y, and z globals
or you could create a container C of some sort and
3. pass container C as an argument
4. make container C a global
So you have two basic questions to answer. When you make the things — x, y, and z — available:
A. Do you make them available in global variables, or in arguments that you pass around?
B. Do you make them available individually, or do you put them in some kind of container and make the container available?
My original post assumed that in at least some situations you might answer question A with “use global variables” and then went on to propose that in those situations the best answer to B is “put them in a container”.
Since the point of that post was to point out the usefulness of a class as a container, I called the proposed pattern the Globals Class pattern. But in most cases some other kind of container would do as well as a class. I could almost as easily have called the pattern the Globals Container pattern.
So if you look at these two questions — A and B — I think it is interesting where Mike and I differ, and where we agree.
Question A: args or globals
Where we differ, if you could call it that, is in the answer to A.
Mike wrote “No need for globals. Just explicitly pass your container. In my opinion this is much easier to understand.”
In my post I wrote “Sometimes globals are the best practical solution to a particular programming problem.” But that wasn’t really what the post was about. It was about the answer to question B.
So I can’t really say that Mike and I disagree very much. He says “I like apples”. I say “Sometimes I like an orange.” No big deal.
Question B — multiple things or a single container
What is much more interesting is that we both agree on the answer to question B: use a container object.
But since I was talking about globals, I was talking about a container for globals. Since Mike was talking about arguments, he was talking about a container for arguments.
Which means that we have two different patterns. My earlier post was about strategy 4 — a Globals Container pattern. Mike is talking about strategy 3 — what we might call an Arguments Container pattern.
As it happens, I had stumbled onto the Arguments Container pattern myself, not in Python but in Java. The circumstances were very similar to the circumstances that led to the Python Globals Class pattern. I had a lot of variables that I needed to pass around. As the code evolved,the argument lists got longer and harder to manage. Finally I just bundled all of the variables into a single container object and passed the container around. As I needed to add new arguments, I was able to add them to just one place — the container.
At the time, I felt sort of stupid doing this. I hadn’t ever heard of this as a programming technique. It smacked of sneaking global variables in through the back door, and of course everybody knows that globals are always bad. But it worked, and it made my life a lot easier.
So now Mike comes along and proposes doing exactly the same thing. I feel relieved. I’m not the only one doing this. It may even be a Good Thing.
So I’m happy to announce — not the discovery, certainly — the christening of the Arguments Container pattern, which says, basically:
Sometimes when you have a lot of individual variables that you need to pass around to a lot of different functions or methods, the best solution is to put them into a container object and just pass the container object around.
This is not a specifically Python pattern. And in a way it is No Big Deal. But I’m doing a bit of shouting and arm-waving here because I think that somewhere there is probably at least one person for whom this post might be useful.