In my application, I have a few classes. Many of these classes share common state like a reference to the logger for example. For example, both A and B require some common state to get their job done.
class A { Logger &logger; CommonThing &thing; public: void performTaskA(); }; class B { Logger &logger; CommonThing &thing; std::vector<OtherThing> stuff; public: void performTaskB(); }; Another example of a pattern from my application: C holds an instance of A because C needs to performTaskA in order to performTaskC.
class C { Logger &logger; CommonThing &thing; A a; public: void performTaskC() { a.performTaskA(); } }; C is basically storing Logger and CommonThing twice. A doesn't actually have any state of its own so C could very well construct A in-place every time it needs to access it's interface.
I'm a fan of dependency injection. If an object is required to perform an operation, I pass it in. However, this has resulted in functions and constructors taking many parameters. I frequently have to wrap parameter lists down multiple lines because they're so damn long.
The operations being performed require a lot of state. That is the nature of the operations. If I could, functions would just have less dependencies but that is not really an option. I have an idea for solving some of the mentioned problems.
I stumbled apon a code snippet from a C++ compiler. I don't remember the details but I saw a number of functions, each taking a pointer to a context object as a parameter. I could put all of the common state into a single struct and then pass around a reference to the struct.
struct Context { Logger logger; CommonThing thing; }; void performTaskA(Context &); void performTaskC(Context &); Neither A nor C need to be classes anymore. They can just be groups of functions that take a context. The reason they were classes before is because if they were functions, they would have very long parameter lists.
The use of a context struct seems to solve most of the problems but it brings along its own set of problems. What I'm essentially making is a "god class" except that the member functions are grouped together into multiple files. It's nolonger obvious what a function accesses because it could access anything. Although, if a function suddenly needs to access something, I nolonger need to update the parameter lists of a bunch of functions.
Is the context struct better than what I have now?
I really hope this isn't off-topic. I've tried to keep it generic so that answers could help more than one person. I wanted to ask here before I make a major change to the codebase and rewrite a whole lot of stuff.