7 ms·
Don’t, is always the simplest answer. Global state that is non-constant, causes all sorts of testing issues down the line. It should be avoided. Edit: since a
by bluejekyll 6y ago
Don’t, is always the simplest answer. Global state that is non-constant, causes all sorts of testing issues down the line. It should be avoided.
Edit: since a lot of folks are reading this as saying “never” rather than “avoided”. The point here is to keep access to data and state restricted. The entire application does not need to know that some piece of data is global. If you design a central container in a generic manner, it can restrict access to globals in a way that allows for easier refactoring in the future. It also allows one to design users of those globals in a way that doesn’t leak the fact that these things are global.
By doing this, you don’t leak globals through the application, and you keep things isolated in a way that allows for easier testing.
- aphextron 6y agoIt's not a simple yes/no question. For instance, is a database not ultimately a single mutable global state?
- baq 6y agoA database connection perhaps, but different connections to the same database will see different states of the database depending on the isolation level of the current transaction.
- chousuke 6y agoDatabases are also designed for safe concurrent access with enforceable constraints on data. Would you like your application behaviour to depend on a transient "database" someone made up on the fly? :) I think the key is that your database stores data that lives outside your application, making it observable outside any particular application instance and allowing you to perform ad-hoc queries to validate consistency and fix problems. If you have such mutable state inside a process, it can be very difficult to debug problems when a series of interactions sends your process into an inconsistent state that is only detected some hours later when (if) it finally crashes.
- _28jh 6y agoI hate when I ask something about globals on SO and I get the same blanket answer. Why does every programmer feel the need to tell me that "globals make it hard to reason about the state of your program?" Unfortunately most systems are global based. OpenGL has one global state. A database connection is a global. Either you can use globals to model these things properly or you can complicate it by not using globals. The library will be using globals under the hood anyways.
- swsieber 6y agoThe OpenGL is a much better example than the database connection, FWIW.
- logicslave 6y agoIts dogma. Like a religion. A whole generation of people believing in things with no root evidence except that the knowledge is ubiquitous
- bluejekyll 6y agoI have plenty of history with global state, various contexts in large applications, that make testing code unnecessarily complex. So, yes, global state is sometimes necessary, but it absolutely should be avoided, and access to it should be restricted.
- deleted 6y ago[deleted]
- AnIdiotOnTheNet 6y agoBecause that's the academic answer that doesn't have to deal with real world constraints and pressures. I too have a deep hatred of the "you don't want to do that" answer for this reason: I do deal with real world constraints and pressures and I'm asking my question because "the right way" can't be done in my circumstances!
- cesarb 6y ago> OpenGL has one global state. As far as I know, it doesn't, it's actually thread-local state; you can have multiple states, and you use glXMakeCurrent/eglMakeCurrent to choose which one is active for the current thread. And the protocol which can be considered the successor of OpenGL (Vulkan) replaced the thread-local state with an explicit reference to the state. > A database connection is a global. The product I develop at work uses multiple database connections, to several different databases, which can be added and removed at runtime. They most definitely aren't global.
- dleslie 6y agoThe hardware itself is implicit global state, and often with devices that behave like singletons.
- kjeetgill 6y agoThis is very nearly the exact advice I would give a person working on my team. But I also think when the question is asked broadly it can be ... Presumptuous. Even though I've come to the same conclusions from my experience just discarding the premise of the question (without answering it especially) won't sit will.
- Const-me 6y agoThe OP’s question was about OpenGL. GPUs have gigabytes of external mutable state. Specifically, in my PC the figure is “11GB of that state”. You can’t avoid that. If a language doesn’t offer convenient ways to deal with that state, it simply means that language ain’t a good choice for anything GPU-related, be it graphics or GPGPU.
- bluejekyll 6y agoWhat do you by convenient? There is an extremely good response to how to design this in Rust on the SO post. This doesn't change the way that you should design the rest of the code. The convenience that Rust gives you in this context is strong ownership (i.e. can limit access to the Global except in very desirable patterns) and data-race free with compile time checks around mutability. The standard library has all of these options available, additionally there are a bunch of libraries from the ecosystem that make it even easier.
- Const-me 6y ago> can limit access to the Global except in very desirable patterns It’s desirable when you don’t do much I/O, only implementing some algorithms that compute something. It’s not desirable at all when the majority of your complexity is I/O. An extreme example is a videogame, these can update global mutable state (the VRAM, abstracted behind GL or D3D) with the bandwidth measured in gigabytes/second, often concurrently so from multiple threads. Update: and even for computations, when you want performance, rust’s ownership shenanigans often get in the way. See this C++ code for example: https://github.com/Const-me/SimdPrecisionTest/blob/master/rcppsErrorSummary.cpp https://github.com/Const-me/SimdPrecisionTest/blob/master/rc... You gonna have hard time porting that to Rust, because this vector https://github.com/Const-me/SimdPrecisionTest/blob/master/rcppsErrorSummary.cpp#L212 https://github.com/Const-me/SimdPrecisionTest/blob/master/rc... is updated concurrently by multiple threads of the pool, without any locks.
- bluejekyll 6y agoYou're comparing an implicitly unsafe language implementation, C++, with a language that guarantees safety by default, Rust. There are many people working on non-blocking lock-free datastructures in Rust, but this often requires unsafe implementations. Essentially removing the safety restrictions to do things like what you're showing in the C++. Looking at the code you're showing, I might model this with deque from the Crossbeam project: https://docs.rs/crossbeam/0.7.3/crossbeam/deque/index.html https://docs.rs/crossbeam/0.7.3/crossbeam/deque/index.html I believe that's all lock-free, and offers a safe interface for working with it.