Globals are convenient, but lead to problems in maintainability.
Their use can make two formerly unrelated modules dependent on each other
They are difficult to document (little context)
They make testing difficult (dependencies)
The Concept
Divide the globals into structures that are shared with the components that need them. Example (divisions and names will change):
ChainParameters contains the parameters that control the blockchain (taken mostly from config file and command line)
ConsensusParameters may be needed, or may be able to be wrapped into ChainParameters
ChainStatus contain the mutable data about the current chain at present (i.e. current height, mempool)
P2PParameters contains the parameters on how the P2P network should be managed
P2PStatus contains the mutable data about the current P2P network (i.e. connected CNodes)
RPCParameters contains the parameters that control client connections
RPCStatus contains the mutable data about current RPC connections
Why go through all this?
Dividing the globals into these structures provides
Context - You know what area you are talking to, and have narrowed the scope of what you may be affecting by changing a value or method implementation (interfaces become more clearly defined). Example: It is easier to make descriptive variable names when the context is narrowed.
Testability - Starting X nodes and Y wallets becomes possible within 1 executable, whereas starting 2 nodes within 1 gtest is currently impossible.
Reuse - Derivative chains (or future main chains) have a better idea of what must be added/removed/changed to provide the desired functionality
Itterative development - Structures can be implemented with limited functionality that grows over time.
The over-reaching goal is to develop components that have a well-defined interface and push complexity to lower layers (Why are main.cpp and init.cpp so big? Because the complexity is in the wrong place.).
Globals are convenient, but lead to problems in maintainability.
The Concept
Divide the globals into structures that are shared with the components that need them. Example (divisions and names will change):
ChainParameters
contains the parameters that control the blockchain (taken mostly from config file and command line)ConsensusParameters
may be needed, or may be able to be wrapped intoChainParameters
ChainStatus
contain the mutable data about the current chain at present (i.e. current height, mempool)P2PParameters
contains the parameters on how the P2P network should be managedP2PStatus
contains the mutable data about the current P2P network (i.e. connected CNodes)RPCParameters
contains the parameters that control client connectionsRPCStatus
contains the mutable data about current RPC connectionsWhy go through all this?
Dividing the globals into these structures provides
The over-reaching goal is to develop components that have a well-defined interface and push complexity to lower layers (Why are main.cpp and init.cpp so big? Because the complexity is in the wrong place.).