Hacker News new | ask | show | jobs
by dragonwriter 3095 days ago
> The only argument against globals is testing

No, the newer argument against globals is testing, but that's mostly a side effect of the older issue, that globals limit composability/reusability, which was the main objection to globals before TDD became a popular religion.

1 comments

The "reusability" argument is just as wrong... True reusability (without any changes) is not possible in most cases anyway, and furthermore I don't see a reason why surrounding some static object (which can only exist once in a program, like a sound module, a network module, etc) with braces and a "class" keyword would somehow increase this vague idea of reusability.

It's only a syntactic change. It's not changing what should actually happen. It's just making it less readable. How in the world can that be an improvement on any frontier?

> I don't see a reason why surrounding some static object (which can only exist once in a program, like a sound module, a network module, etc) with braces and a "class" keyword would somehow increase this vague idea of reusability.

Often, because the assumption that it can exist only once is wrong; this is particularly true of instances of some descriptive class of interface to an external hardware resource, which covers all of your examples.

> It's only a syntactic change.

No, it's usually not; while the syntactic change is usually necessary, it usually isn't the whole difference between the desirable modular code and the bad global-using code that should be made, and quite often if you aren't writing it as a global resource in the first place, you never make the other wrong decisions that would need to be changed.

Using globals may occasionally be justified (either as an optimization or, even more rarely, as “correct” from a fundamental design perspective), but most often it's a symptom of sloppy thinking.

> Often, because the assumption that it can exist only once is wrong; this is particularly true of instances of some descriptive class of interface to an external hardware resource, which covers all of your examples.

The key here is how to understand the word "can". It's "only" a design decision! Of course you can do almost anything on a computer. However, most programs don't make sense with two sound modules or network modules or graphics modules. So "can" here means, "it absolutely makes no sense, and I'm never realistically going to instance two or more of this thing". (And if I really want to do that later, 1 in 1000 times, I'll just edit the code).

> it usually isn't the whole difference between the desirable modular code and the bad global-using code that should be made, and quite often if you aren't writing it as a global resource in the first place, you never make the other wrong decisions that would need to be changed.

Give an example: I don't think there are any. I can easily give you some bad things that happen when avoiding globals to represent static resources: Much more input and output arguments to type. Then, the syntactically ugly, useless, meaningless Singleton. I've seen it many times, and it is the best proof that it made no sense to avoid the global in the first place, and it even potentially leads to nondeterministic initialization.

And more importantly, an occasional reader has a much harder time browsing through the code because she never knows where the local variables are pointing at.

Most VR games make sense with 2 displays (Headset + screen), and 2 sound systems (binaural for the headset + stereo for the audience). You'd likely know that from the outset, though.
Yes - and for each of these examples, there would likely be still a single "object instance" managing these devices (e.g. "Display" module). Or two entirely different modules ("Headset" module + "Screen" module), again each having only a single "instance".

The concept of instancing is inappropriate to most situations. The things that we have more than one ("dynamically many") instances from are typically dead data, but then again these are typically managed in a single pool. (That's "tables", again).

> The concept of instancing is inappropriate to most situations.

At the application level, maybe. At the library level, this can easily kill reuse. See Lex/Yacc. They used to assume a program would only have one parser. Then some naive developer tried to parse both JSON and Lua tables in the same program. Oops.

Another example: standard libraries (including home grown ones). They instantiate everywhere: arrays, hash tables, file descriptors…