3 ms·
I don't think #1 is necessarily true. Take a common case for a global variable, a metric your app is exposing via prometheus. You have some global variable repr
by Spivak 2y ago
I don't think #1 is necessarily true. Take a common case for a global variable, a metric your app is exposing via prometheus. You have some global variable representing its value. Libraries like to hide the global variable sometimes with cuteness like MetricsRegistey.get_metric("foo") but they're globally readable and writable state. And in your function you do a little metric.observe_event() to increment your counter. I think having this value global helps reasoning because the alternative is going to be a really clunky plumbing of the variable down the stack.
- hansvm 2y agoIt helps with reasoning in some sense, and the net balance might be positive in how much reasoning it enables, but it definitely hurts local reasoning. You need broader context to be able to analyze whether the function is correct (or even what it's supposed to be doing if you don't actively work to prevent entropic decay as the codebase changes). You can't test that function without bringing in that outer context. It (often) doesn't naturally compose well with other functions.
- Joker_vD 2y agoOf course #1 is not necessarily true, it depends on one's coding style, and using globals for application-scoped services like logging/metrics is tentatively fine... although I also think that if we're going to dedicate globals almost exclusively to this use, they probably should have dynamic scoping. On the other hand, I have seen quite a lot of parsing/compilers' code from the seventies and eighties and let me tell you: for some reason, having interfaces between lexer and parser, or lexer and buffered reader, or whatever else to be "call void NextToken(void), it updates global variables TokenKind, TokenNumber, TokenText to store the info about the freshly produced token" was immensely popular. This has gotten slightly less popular but even today e.g. Golang's scanner has method next() that updates scanner's "current token"-related fields and returns nothing. I don't know why: I've written several LL(1) recursive-descent parsers that explicitly pass the current token around the parsing functions and it works perfectly fine.