
Stewart, Robert wrote:
Jeff Flinn wrote:
I fail to see the analogy between global-state-coupling and exceptions. In the former, you've got a function with dependency upon global state, and any function that calls that function is now dependent upon global state. The only way I can tell that dependency is I have to hunt that down by looking at the source code, or trying to link and getting an unresolved ref liner error. How are exceptions similar?
Let me try another way to explain my point.
In the case of return codes, you must litter every function in the call chain with the appropriate return type. Each function in the chain must examine the returned value to determine whether to proceed or return an error. With exceptions, intermediate functions are ignorant of the exceptions thrown or the code that handles them.
I'm aware of the effects of return codes vs exceptions.
With Singletons, code that needs access to global state accesses a Singleton. Without that, all intermediate functions must be littered with argument(s) for the state needed by the inner function. If the inner function needs access to global state it didn't need before, or no longer needs access to global state it once did, all functions in the call stack must be changed to pass or not pass along that state.
Isn't your first sentence exactly defining singleton abuse... using a singleton as glorified global data access? The major tenet that affords functional programming it's power and robustness is that a function depends only upon it's arguments. The Law of Demeter provides the extension for OO that member functions are allowed to depend upon it's object's(this) state and it's arguments. What makes the singleton's functionality so different from any other arguments or object data members that you don't want to make them just as visible? Yes, system's change, that's why there are refactoring tools and IDE's. If you find yourself with such a brittle system, fix the design. If you just want a quick and dirty hack en lieu of proper design, I guess you can use global data access, but don't dress it up as anything but the hack that it is. Open the back door and let chaos to ensue.
I was never discussing determining whether a function is dependent upon global state.
That's how the singleton has been used in this thread AFAICT.
What use cases do you see where global state access is required?
Consider an environment with a single configuration state object. All code requiring access to that configuration state can either access it as global state, which it is, or that object can be passed to all functions that require it. The latter leads to polluting myriad other functions with arguments they need only to satisfy the functions they call.
That's not a very concrete use case. I contend that this "single configuration state object", really isn't an object. It's just an ad hoc collection of data with no encapsulation, no enforceable class invariants, no behavior. The singleton usage pollutes any functions that use it with a myriad of types that aren't relevant to their responsibilities. Are you saying that getting rid of "arguments they need only to satisfy the functions they call" at the expense of increased hidden coupling is a more valid design decision? Jeff