> At that point you're not using global state in the library, which was the point.
Yes. But I want to make clear that you are still using global state for all uses within the project itself. The library can be implemented in whatever way. For example, setting the pointer in a global variable on API entry ;-)
> That doesn't solve the problem at all.
WHICH problem? I don't think there is one.
> Indeed, and they're seen as bad practice for the same reason as global state in general.
This is foolish. There is no problem with global state. Global state is a fact of life. Your process has one address space. It has (probably) one server socket for listening to incoming request. It has (probably) one graphics window to show its state. Whenever you have more (e.g. file descriptors, memory mappings, ...), well then you have a set of that thing, but you have ONE set :-). And so on.
You are not writing a thousand pseudo-isolated programs. But ONE. One entity composed of a fixed number of parts (i.e. modules, code files) that work together to do what must be done.
Why add indirection? Why make it hard to iterate over all open file descriptors? Why thread a window handle through 15 layers of function calls when you have only one graphics window? It adds a lot of boilerplate. It even brings some people to invent hard to digest concepts like monads or objects just to make that terrible code manageable. It makes the code unclear. Someone once described it with this analogy, "I don't say ''I'm meeting one of my wives tonight'', unless I have more than one".
> Yes. But I want to make clear that you are still using global state for all uses within the project itself.
But if we believe in using libraries then often our project will itself be a library.
> The library can be implemented in whatever way. For example, setting the pointer in a global variable on API entry ;-)
And then you have the problem I mentioned: if there is a diamond dependency on your library then the thing using it will break.
> WHICH problem? I don't think there is one.
The problem of not being able to break down your project and understand it piecemeal.
> Global state is a fact of life. Your process has one address space. It has (probably) one server socket for listening to incoming request. It has (probably) one graphics window to show its state.
All those global things are a common source of bugs, as different pieces of the program make subtly different assumptions about them. Perhaps a certain amount of global state is unavoidable. That's not an argument against minimizing it.
> You are not writing a thousand pseudo-isolated programs. But ONE. One entity composed of a fixed number of parts (i.e. modules, code files) that work together to do what must be done.
If you write a program that can only be understood in its entirety, you'll be unable to maintain it once it becomes too big to fit in your head. Writing a thousand isolated functions gives you something much easier to understand and scale.
> Do you want to say that my logging routine is more complex because my windowing handle is global data?
If your logging routine touches your windowing handle that certainly makes it more complex. If I'm meant to know that your logging routine doesn't touch your windowing handle, that's precisely the statement that it isn't global data.
You mean start by building something that can be used and tested in isolation, rather than trying to build an enormous system in one go? Isn't that what you've been arguing against?
No I mean solve the problem "we need to build a program that does what it's required to do" (and no more) before trying to build a library that will cure diseases.
Libraries are much harder than applications because they must work for a large number of applications with diverse requirements. They need to be more abstract, and therein lies the danger.
Regarding the size, clearly wrong. It depends a lot on the library. A windowing or font rastering library will be a lot larger than your typical application.
And for libraries that are much smaller than the application itself, why bother depending on them? (Anecdote, I heard the Excel team in the 90s had their own compiler).
Yes. But I want to make clear that you are still using global state for all uses within the project itself. The library can be implemented in whatever way. For example, setting the pointer in a global variable on API entry ;-)
> That doesn't solve the problem at all.
WHICH problem? I don't think there is one.
> Indeed, and they're seen as bad practice for the same reason as global state in general.
This is foolish. There is no problem with global state. Global state is a fact of life. Your process has one address space. It has (probably) one server socket for listening to incoming request. It has (probably) one graphics window to show its state. Whenever you have more (e.g. file descriptors, memory mappings, ...), well then you have a set of that thing, but you have ONE set :-). And so on.
You are not writing a thousand pseudo-isolated programs. But ONE. One entity composed of a fixed number of parts (i.e. modules, code files) that work together to do what must be done.
Why add indirection? Why make it hard to iterate over all open file descriptors? Why thread a window handle through 15 layers of function calls when you have only one graphics window? It adds a lot of boilerplate. It even brings some people to invent hard to digest concepts like monads or objects just to make that terrible code manageable. It makes the code unclear. Someone once described it with this analogy, "I don't say ''I'm meeting one of my wives tonight'', unless I have more than one".