Search code examples
c++architecturesolid-principles

How to extend a class stored in the database without big consequences for the whole system?


I'm writing my simple database which reads the Person class fields from a csv file and writes them to a vector. But if in the future I want to add new fields to the Person class, I will have to redo the class constructor, in the function of reading and writing the csv file, I will also have to change the constructor. Is it possible to somehow add fields to the Person class with minimal code changes?

Person class:

person::person(unsigned int _id, std::string &_fullname, std::string &_occupation)
    : id(_id), fullname(_fullname), occupation(_occupation) {

}

unsigned int person::getId() const {
    return id;
}

const std::string &person::getFullname() const {
    return fullname;
}

const std::string &person::getOccupation() const {
    return occupation;
}

void person::setOccupation(std::string &_occupation) {
    person::occupation = _occupation;
}

person_csv_converter class:

person_csv_converter::person_csv_converter(const std::string &_csvFilename) {
    in.open(_csvFilename);

    if (in.is_open()) {
        std::cout << "CSV file was found!";
    } else {
        throw file_not_found_exception("File was not found or file type is incorrect!");
    }
}

person_csv_converter::~person_csv_converter() {
    in.close();
}

std::vector<std::string> person_csv_converter::readLines() {
    std::string line;
    std::vector<std::string> lines;

    while (std::getline(in, line)) {
        lines.push_back(line);
    }

    return lines;
}

std::vector<person> person_csv_converter::convert(const std::vector<std::string> &_csvLines) {
    std::vector<person> persons;

    //pseudo code:
    /*
     * for i in range(_csvLines.size()) {
     *     vector.append(new person(_csvLines.split(",")))
     * }
     */
}

As a solution, I can suggest using a map instead of fields, which will contain <field, value> pairs, and at the time of reading the csv file, instead of the constructor, call the setter. Maybe there is something else?


Solution

  • Your idea of using std::map<Key, Value> makes perfect sense. The downside is that you can't enforce that an ID is an unsigned integer, or other similar semantic constrains. This makes sense. The CSV file can contain a column "ID" with a value "-1", or even "". Reading the CSV gives you string values.

    This isn't a problem that's particular to C++. It's common in software maintenance. What if someone has two occupations? Maintaining any large, real-world data set and its associated code base will be a job. There are no silver bullets.