Разделите чтение и запись на IFileReader и IFileWriter, чтобы клиент зависел только от нужной операции. Открытие и закрытие лучше связать с жизненным циклом файлового объекта через RAII.
Разделение контракта файловой системы для повышения расширяемости
Разделите чтение и запись на IFileReader и IFileWriter, чтобы клиент зависел только от нужной операции. Открытие и закрытие лучше связать с жизненным циклом файлового объекта через RAII.
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
Условие
Необходимо проанализировать существующий контракт IFileHandler. Как можно разбить его на более узкоспециализированные интерфейсы, чтобы улучшить масштабируемость и удовлетворить принцип единственной ответственности (SRP)?
class IFileHandler {
public:
virtual void open(std::string path) = 0;
virtual void close() = 0;
virtual std::vector<std::string> readLines() = 0;
virtual void writeLines(const std::vector<std::string>& data) = 0;
virtual ~IFileHandler() {}
};
class MyFile : public IFileHandler {
void open(std::string path) override;
void close() override;
std::vector<std::string> readLines() override;
void writeLines(const std::vector<std::string>& data) override;
};
Ответ
Разделите чтение и запись на IFileReader и IFileWriter, чтобы клиент зависел только от нужной операции. Открытие и закрытие лучше связать с жизненным циклом файлового объекта через RAII.
#include <string>
#include <vector>
struct IFileReader {
virtual std::vector<std::string> readLines() = 0;
virtual ~IFileReader() = default;
};
struct IFileWriter {
virtual void writeLines(const std::vector<std::string>& data) = 0;
virtual ~IFileWriter() = default;
};
MyFile может реализовать оба интерфейса. Парсер получает IFileReader&, экспортёр — IFileWriter&. Дескриптор открывается при создании конкретного объекта и освобождается в деструкторе; явный close с сообщением об ошибке при необходимости остаётся отдельной операцией. Это прежде всего принцип разделения интерфейсов (ISP); один лишь распил методов ещё не гарантирует SRP.