I wonder how one would go about adding different data sources to an already existing code. For example, let's say that I have this piece of code:
//DataFromFile.cpp
#include "Data.h"
class DataFromFile
{
public:
DataFromFile() { filename = ""; }
~DataFromFile() { delete data; }
void loadValue(const char *filename) { //getting data from a file }
void printData() { data->printData(); }
private:
string filename;
Data *data;
};
//Source.cpp
#include <iostream>
#include "DataFromParameter.h"
int main(int argc, char **argv)
{
DataFromFile oldData;
oldData.loadValue("example.txt");
oldData.printData();
return 0;
}
and need to create class DataFromDatabase or DataFromParameter but without changing the way DataFromFile works (this code is used throughout various programs and going through their code is out of the question). Creating an interface seemed like a good way to go, so I came up with this solution:
//IData.h
#include "Data.h"
class IData
{
public:
IData() { data = NULL; }
virtual ~IData() = 0 { delete data; }
void printData() { if (data != NULL) data->printData(); }
protected:
Data *data;
}
//DataFromParameter.h
#include "IData.h"
class DataFromParameter : public IData
{
public:
DataFromParameter(const int value) { this->data = new Data(value); }
~DataFromParameter() {}
};
//DataFromFile.h
#include "IData.h"
class DataFromFile : public IData
{
public:
DataFromFile() { filename = ""; }
DataFromFile(const char *filename) { loadValue(filename); }
~DataFromFile() {}
void loadValue(const char *filename) { //getting data from a file }
private:
string filename;
}
As you can see IData and DataFromParameter are the new classes and I also added some methods to DataFromFile. Creating the new objects and calling their methods:
//Source.cpp
#include <iostream>
#include "DataFromParameter.h"
int main(int argc, char **argv)
{
//Source: file (the old way)
DataFromFile oldData;
oldData.loadValue("example.txt");
oldData.printData();
//Source: file (the new way)
IData *newData1 = new DataFromFile("example.txt");
newData1->printData();
delete newData1;
//Source: parameter
IData *newData2 = new DataFromParameter(atoi(argv[1]));
newData2->printData();
delete newData2;
return 0;
}
It works, nevertheless I'm not very happy with it; especially the DataFromFile class code looks messy - I know why it looks that way but am sure someone else would get pretty confused what exactly is going on in there.
My question is: is there a better way to go here? Is the sloppiness necessary (given the circumstances) or am I missing some obvious solution to the problem?