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 my codebase and rewirte a whole lot of stuff.
Aucun commentaire:
Enregistrer un commentaire