15 Feb, 2011, plamzi wrote in the 1st comment:
Votes: 0
David Haley said:
This is a pretty classic example of why globals are bad. :smile: Glad you found the problem! These things usually have to do with connections being left in invalid states one way or another.


Globals are bad, agreed, but only because our human memory is so damn' imperfect and compilers often fail to give clear clues when you re-use a global illegally.

In my SQL code, I actually have two global row/result pairs–one I use as a "temp" and the other as a "main". It's a bit more robust but still prone to breaking if you forget…
15 Feb, 2011, David Haley wrote in the 2nd comment:
Votes: 0
How exactly is a compiler supposed to know when a global is used "illegally"…? That's a very serious question. I would venture to guess that there is no precise definition even possible for the problem, and even if there were, it would be formally unsolvable.

Having two globals is not really a solution, it's just deferring the problem. It fails when recursion is necessary, for example.
15 Feb, 2011, Runter wrote in the 3rd comment:
Votes: 0
Typically there's no good reason to use a global voluntarily. From just the namespace clobbering perspective it's just nasty. It's not elegant code. Any time you see people using results or "temps" in globals a red flag should go off. That just amounts to saving a little typing in C declaring variables. It's not often the problem, but it's a symptom of bad things to come.
15 Feb, 2011, David Haley wrote in the 4th comment:
Votes: 0
Pretty much the only situation in which a global is appropriate is when you have some kind of context that can only exist once and that must be passed around all the time. Even in this case, passing the context explicitly makes it much easier to make code re-entrant later on (which makes multi-threading much, much easier).

And yes, global temps are just weird… maybe they made sense when memory was extraordinarily tight and it was costly to have variables on the stack, but those days are long gone.
15 Feb, 2011, plamzi wrote in the 5th comment:
Votes: 0
Well, it seems like the C API for MySQL invites the use of globals, and not just for the database struct itself but for query results as well, so I'm not surprised the OP was using them. This is especially true when you're writing over existing code, and saves you from having to repeat long pre-ambles of empty code just to make a query.

Maybe it's just the bad influence of CircleMUD code, teeming with globals, or my lack of formal schooling in this here trade, but I seem to have a much more relaxed view of globals than most other coders I've met…
15 Feb, 2011, David Haley wrote in the 6th comment:
Votes: 0
I wouldn't say that the API encourages globals; laziness encourages globals. :smile:

Perhaps the only global that makes sense here is the connection handle, because it (usually) only makes sense to have one. Result sets should absolutely not be global, and really, we just saw exactly why. It's a fairly classic CS 101 type of problem.

If lists of variable declarations are really that much of an issue, it's always possible to use a preprocessor directive, although personally I would discourage that as well.
15 Feb, 2011, Runter wrote in the 7th comment:
Votes: 0
I haven't seen Elanthis here in like a year, but his mantra still rings true, "Cutting corners to keep your line count down is just sad."
15 Feb, 2011, jurdendurden wrote in the 8th comment:
Votes: 0
What about things like keeping track of how many players have been on that reboot. These variables need to be accessed both when a character logs in (for updating), and for the who_list function. Is this still considered ugly? Is there a better way I can do it?
15 Feb, 2011, David Haley wrote in the 9th comment:
Votes: 0
Those are variables that exist only once, and so are ok globals. As I said above, making them global means that the application is necessarily single-instanced, but I would not consider that a problem for MUDs…

As a matter of tidiness, though, I would not have the individual variables be global; rather, I would have a single global structure that contained such variables. (Or better yet, several structures of organizationally related variables.)
15 Feb, 2011, jurdendurden wrote in the 10th comment:
Votes: 0
Ahh good idea about the structure. Didn't realize what you meant earlier about the single instanced onces but I suppose I do now :) Thanks!
15 Feb, 2011, David Haley wrote in the 11th comment:
Votes: 0
Think about writing a scripting language program. If you use global variables to keep track of global interpreter state (like maybe what line of code you're executing, or whatever) then you cannot have multiple instances, or in the case of a scripting language, threads. If you want multiple threads, you really want all that state information to be in context objects.

In the case of a MUD you (probably) don't need one process to be hosting several full MUD instances. Most people are content with doing that in several processes. But perhaps you need some kind of tight integration across instances, and inter-process communication isn't practical (for some reason). In that case you might consider removing global variables and passing around the state. This is purely hypothetical, though; I don't think that this is a likely scenario.
16 Feb, 2011, plamzi wrote in the 12th comment:
Votes: 0
David Haley said:
I wouldn't say that the API encourages globals; laziness encourages globals. :smile:

Perhaps the only global that makes sense here is the connection handle, because it (usually) only makes sense to have one. Result sets should absolutely not be global, and really, we just saw exactly why. It's a fairly classic CS 101 type of problem.


I'm far too busy supporting my numerous completed projects to respond to veiled accusations of laziness :). Suffice it to say that if it saves me time and gets the job done, I'd still use a global or a dozen globals, and not just for things like the database structure or a structure of environmental vars or a set of global indices, etc., but pretty much for everything where I see a shortcut opportunity. When debugged properly, it's less code that does exactly the same thing, with less memory use. And, knowing your code and keeping global declarations organized makes it fairly easy to debug any issues that might arise. So, I really don't see a reason to sacrifice hundreds of hours to the gods of coding red tape and I don't think anyone else, except the coding gods themselves, should.
16 Feb, 2011, Runter wrote in the 13th comment:
Votes: 0
When DH said it's classic CS 101 he wasn't kidding. Let's not build false dilemmas between writing efficient code that gets the job done and "saves times" vs sacrificing hundreds of hours. Believe it or not there's people who are very productive without angle shooting for short cuts. The real dilemma is best practices (i.e. widely acknowledged) vs familiarity. Let's keep in mind, the "when properly debugged" argument is pretty much used by practitioners of any frowned upon exercise. Like people using way too many C-macros. Weird pointer convention, or people justifying goto statements.
16 Feb, 2011, Tyche wrote in the 14th comment:
Votes: 0
plamzi said:
I'm far too busy supporting my numerous completed projects to respond to veiled accusations of laziness :). Suffice it to say that if it saves me time and gets the job done, I'd still use a global or a dozen globals, and not just for things like the database structure or a structure of environmental vars or a set of global indices, etc., but pretty much for everything where I see a shortcut opportunity. When debugged properly, it's less code that does exactly the same thing, with less memory use. And, knowing your code and keeping global declarations organized makes it fairly easy to debug any issues that might arise. So, I really don't see a reason to sacrifice hundreds of hours to the gods of coding red tape and I don't think anyone else, except the coding gods themselves, should.


Excellent answer. :-)
16 Feb, 2011, Runter wrote in the 15th comment:
Votes: 0
Tyche said:
plamzi said:
I'm far too busy supporting my numerous completed projects to respond to veiled accusations of laziness :). Suffice it to say that if it saves me time and gets the job done, I'd still use a global or a dozen globals, and not just for things like the database structure or a structure of environmental vars or a set of global indices, etc., but pretty much for everything where I see a shortcut opportunity. When debugged properly, it's less code that does exactly the same thing, with less memory use. And, knowing your code and keeping global declarations organized makes it fairly easy to debug any issues that might arise. So, I really don't see a reason to sacrifice hundreds of hours to the gods of coding red tape and I don't think anyone else, except the coding gods themselves, should.


Excellent answer. :-)


I thought of you when he said it. :)
16 Feb, 2011, David Haley wrote in the 16th comment:
Votes: 0
Plamzi… I feel like you are arguing against the fact that I disagreed, and not the content of my disagreement.

At first, you thought globals were bad, and that it is because we are not good at remembering things:
"Globals are bad, agreed, but only because our human memory is so damn' imperfect"
You then say that you are essentially a hobbyist without formal training:
"or my lack of formal schooling in this here trade"
You also declare yourself an anomaly:
"I seem to have a much more relaxed view of globals than most other coders I've met"

But when I hold my position, you turn around and mock it. You say it's not so hard after all to debug things properly. You say that it's not so hard after all to just know your code. You mock the notion of something being 'theoretically correct' and make fun of coding red tape and gods of coding.

You know what? We just saw an example where these nice and clever shortcuts of yours really screw things up. You can laugh at it as some kind of silly thing that coders do because they're being OCD about it, just because I disagreed with your position. Or you can put that aside a little bit and admit that yeah, just maybe, there are reasons why trained or very experienced programmers don't like global variables, oh and hey – we just saw one. It's up to you, really.

Any competent coder (even Tyche, when he's not trolling me) will agree that it's not a good idea to save a little time now at the cost of hours and hours of debugging.

Yes, I'm being harsh, because your position is quite simply dangerous, and to be honest I think you're reacting to a disagreement and not content – what I'm saying is not hugely different than your original statement. What you're saying is potentially a very bad influence for new coders who don't know any better, and that alone is why I am unhappy about it.

And if you're going to make claims about performance, I would suggest you do so carefully. :smile: Your claim about memory usage is on pretty thin ice, for example. What makes you think it would use less memory? Let's think about it. Consider having one global for the result set. It uses some fixed amount of memory. Now consider having a local declaration instead – it still takes up the same amount of memory. When we enter into the stack frame, we allocate space on the stack. When we leave, that space is freed. So, in fact, it arguably uses less memory, except when the relevant stack frame is active – it only takes up memory when necessary. Now let's consider we have, and need, several locals. This uses more memory. But oops – globals wouldn't work here!! So… yeah.

If you're going to make an argument about performance, it would have to be about the time spent managing the stack. But you didn't. So forgive me if I'm skeptical about your argument.
16 Feb, 2011, plamzi wrote in the 17th comment:
Votes: 0
David Haley said:
If you're going to make an argument about performance, it would have to be about the time spent managing the stack.


Thanks for the correction. I meant "time spent managing the stack" but due to my lack of formal training I didn't know the exact terminology.

David Haley said:
Plamzi… I feel like you are arguing against the fact that I disagreed, and not the content of my disagreement.


I feel like my argumentation has been consistent and focused. Here it is, in a nutshell: "Globals are not inherently bad. When used properly and carefully, they can be good."

You yourself have pointed out several cases where globals make more sense than locals, so we may have more common ground than not.

What I've been positioning myself against is such statements as (I'm paraphrasing) "using a global for query results is absolutely a bad idea." I don't think anything is absolute, not in coding, and not in life.
16 Feb, 2011, Runter wrote in the 18th comment:
Votes: 0
I dunno, I kinda think using a global for query results is a bad idea in all cases. It reminds me of using a global variable for a string buffer in all your methods. Then as soon as there are two methods on the call stack that use the buffer you have clobbering. There's a reason local variables exist. And query results would be a perfect example of where not to use global variables, imo.
16 Feb, 2011, David Haley wrote in the 19th comment:
Votes: 0
I do not disagree with your nutshell statement. As you said, I made the same case. Your post #12 was written in a tone such that – by my interpretation – you were mocking the position that I had taken. So it was unclear to me what exactly you were arguing.

While I agree that we cannot easily make absolute statements, I think it's pretty safe to say that it's almost always a bad idea to use globals for transient, potentially concurrently reused variables. Query results are such variables. Yes, of course, you can always be careful. But one wonders what one is gaining at the cost of introducing severe confusion (or bugs) later on.
16 Feb, 2011, plamzi wrote in the 20th comment:
Votes: 0
David Haley said:
I do not disagree with your nutshell statement. As you said, I made the same case. Your post #12 was written in a tone such that – by my interpretation – you were mocking the position that I had taken. So it was unclear to me what exactly you were arguing.

While I agree that we cannot easily make absolute statements, I think it's pretty safe to say that it's almost always a bad idea to use globals for transient, potentially concurrently reused variables. Query results are such variables. Yes, of course, you can always be careful. But one wonders what one is gaining at the cost of introducing severe confusion (or bugs) later on.


Well, so here's a specific example of how I use globals for query results. If it makes sense to people here, we could add it to the exceptions. If not, I might revisit that code and get rid of the globals. This is all related to a pretty modular quest system sitting on top of CircleMUD C:

At boot time, queries for active/published quests, quest-giving mobiles, and quest targets such as rooms, items, etc. are stored into global indexes. The query result structure is itself the index, and I use MySQL API functions such as mysql_fetch_row to find entries as needed.

Also, all quest-related functions at some point need to find a specific Quest ID and look up properties associated with the particular quest. There are 6-7 nested functions being called when, e. g., a mobile target of a quest is killed. Because pretty much all quest-related functions need to evaluate a specific quest at some point, it seemed unnecessary to have to forward the quest record everywhere as an argument or return. So I have the quest search function placing the matching MYSQL ROW into a global. Then, any number of functions that come later on can access the "quest in question" after the initial evaluating function has found it.

I have experienced first-hand that this solution can be brittle. But because I built the code from scratch, I know where to look for problems. I make sure that the search quest function runs first in any processing logic and that's about it. In some cases, I need a secondary ROW to compare two quests, which at the moment is also stored in a global, but which is used less commonly so can easily be localized.

So, to recap, given that pretty much all of the functions in my quest.c needed to search the quest index and evaluate a row, it just made sense to put a global at the top of that file. Am I wrong?
0.0/100