5 ms·
OK, so I'm genuinely confused about what your objection to global state is. You mention issues with assignment, and so on - those are issues with Python `global
by nneonneo 7y ago
OK, so I'm genuinely confused about what your objection to global state is. You mention issues with assignment, and so on - those are issues with Python `globals` and variables in the global namespace, not issues with global state per se. A lot of Python programs use global variables in the form of imports, so I don't see anything wrong here. (Pygame Zero's implicit imports could be a point of objection - but it'd be very easy to hack a small wrapper to force students to import the names they need instead).
In terms of global state, I don't see much of a distinction between Pygame Zero's globals and a god-singleton like `World`. Both feature large amounts of implicit state, just off by one layer of indirection. For the vast majority of games, it wouldn't make sense to have more than one `World`. You might want more than one game scene/level/etc. but that's distinct from the overall windowing system, graphics state, etc. which would be stored in `World`.
- chronial 7y ago> However, a major concern I have for this architecture from a pedagogical perspective is it's reliance on the global namespace. Their concerns are not specific to pygame. They are trying to teach their students to not have global state and are afraid that using pygame in its current form would undermine those teachings.
- bvrmn 7y agoThere is no difference between OS level global state and framework level global state. Students and teacher are free to create clean abstractions on top of any global state. Why are we tolerable to OS boundary and not tolerable to in-process API boundary?
- pingyong 7y ago>but that's distinct from the overall windowing system, graphics state, etc. which would be stored in `World`. That'd be pretty odd naming, usually 'World' would own all your game objects and scene, but have no relation to the windowing system or swap chain. Regardless though, I wouldn't make the windowing system or swap chain or d3dcontext global either, I mean all of that is literally designed to be wrapped into some object. (Well, the window requires some trickery, but it's still prettier than a global handle in the end.) There's really no reason for a game to have actually global state, even if most games are only going to need one window.
- acbart 7y agoThe objection is because of testing, debugging, and getting compiler/autograder feedback. Obviously, global data is powerful and allows us to do a lot. I let my students define top-level functions and use them globally throughout their programs, and as you say the import mechanism also gives us useful constants and functions to be used anywhere. We talk about how great global constants are for this reason. The problem is mutation. When you have global mutable state, it becomes difficult to reason about the program. Code written in one part of the program can cause issues hundreds of lines later even though they are seemingly unrelated. You can no longer easily write simple unit tests to confirm that your program works as intended. Global mutable state also frustrates my attempts to use program analysis to give enhanced autograded feedback. As a concrete example early in the course, we use the Turtle library to define a bunch of functions to write letters, and then they use those functions to write out their names. Difficulty ensues when I ask them to swap definitions and reuse the functions. One kind of issue they encounter is the Turtle library's reliance on global state, which makes it difficult to reason about where the cursor should be after you call a function. You are thinking about the World example, but what about when they make a list of Coin objects? With global state, they start encountering very mysterious bugs related to the shared coin instances. When its all contained within the World object being passed around, we can write more coherent unit tests to debug this kind of trouble. In a class of 150, it's helpful to give them mechanisms like that.
- nneonneo 7y ago> Code written in one part of the program can cause issues hundreds of lines later even though they are seemingly unrelated. How does this change when functions accept big singletons like "World"? At some point you'd have to break it down into smaller objects - at which point you may as well introduce proper OO factoring and design. I do see the point though - global state is easy to mutate by accident in a function that should otherwise not need to mutate global state (say, a function like "def apply_gravity(cur_velocity)" should not be able to accidentally change the gravitational constant or the object position). The example with the Turtle library is an interesting one, but I'd argue the problem is that the function contracts are not fully defined, rather than a problem with global state. A function needs to clearly specify what state it expects and what state it will produce - whether that state is in the ether (global) or whether the state is explicitly provided as a big object. For example, a function to draw a letter might logically be expected to place the cursor at the right edge of the current character (facing right, say), so that another function can advance the x-position for the next character. If it's contractually specified then there shouldn't be an issue.