I’m coding a long-running, multi-threaded server in C++. It receives requests on a socket, does database lookups and returns responses on a socket.
The server reads various run information from a configuration file, including database connectivity parameters. I have to use a database abstraction class from the company’s code library. I don’t want to wait until trying to do the DB search to lazy instantiate the DB connection (due to not shown complexity and the need for error exit at startup if DB connection cannot be made).
My problem is how to get the database connection information down into the search class without doing any number of “ugly” or bad OOP things that would technically work. I want to learn how to do this right way.
Is there a good design pattern for doing this? Should I be using the “Parameterize from Above” pattern? Am I missing some simpler Composition pattern?
// Read config file.
// Open DB connection using config values.
Server::process_request(string request, string response) {
try {
Process process(request);
if (process.do_parse(response)) {
return REQ_OK;
} else {
// handle error
}
} catch (..,) {
// handle exceptions
}
}
class Process : public GenericRequest {
public:
Process(string *input) : generic_process(input) {};
bool do_parse(string &output);
}
bool Process::do_parse(string &output) {
// Parse the input request.
Search search; // database search object
search.init( search parameters from parsing above );
output = format_response(search.get_results());
}
class Search {
// must use the Database library connection handle.
}
How do I get the DB connection from the Server class at top into the Search class instance at the bottom of the pseudo-code above?
It seems that the problem you are trying to solve is one of objects dependency, and is well solved using dependency injection.
Your class
Processrequires an instance ofSearch, which must be configured somehow. Instead of having instances ofProcessallocating their ownSearchinstance, it would be easier to have them receive a ready made one at construction time. TheProcessclass won’t have to know about theSearchconfiguration details, and thus an unecessary dependency is avoided.But then the problem cascades up to whichever object must create a
Process, because now this one has to know that configuration detail! In your situation, it is not really a problem, since theServerclass is the one creatingProcessinstances, and it happens to know the configuration details forSearch.However, a better solution is to implement a specialized class – for instance
DBService, which will encapsulate the DB details acquired from the configuration step, and provide a method to get ready madeSearchinstances. With this setup, no other objects will depend on theSearchclass for its construction and configuration. As an added benefit, you can easily implement and inject aDBServicemockup object which will help you build test cases.The code above somewhat illustrates the solution. Note that the
newSearchmethod is not constrained to build only aSearchinstance, but may build any object specializing that class (as for example the classDBSearchabove). The dependency is there almost removed fromProcess, which now only needs to know about the interface ofSearchit really manipulates.The central element of good OOP design highlighted here is reducing coupling between objects to reduce the amount of work needed when modifying or enhancing parts of the application,
Please look up for dependency injection on SO for more information on that OOP design pattern.