2 ms·
The 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 m
by acbart 7y ago
The 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.
- acbart 7y agoIndeed, we do talk more about good contracts with the Turtle alphabet than we do about global state. But it's a small part of the conversation. The `World` (which is based on the concept from Racket's Universe library) does indeed get broken down into smaller objects. We talk about how to do that too. The idea is to lead this naturally into more OO stuff next semester, but we talk for a while about how we can use dictionaries to structure data at least.