Modern pimpl идиома
#новичкам
В одном из давнишних постов мы уже обсуждали базовую формулировку и реализацию идиомы pimpl. Это сырой указатель на forward-объявленную структуру.
В современных плюсах, естественно, никто уже так не делает. Сырые указатели уходят в прошлое и старые подходы пересматриваются с применением умных указателей.
Допустим, вы используете какой-то нестандартный формат сериализации данных, например apache avro. Конечно вы хотите написать свою библиотеку сериализации, которая позволить конвертировать данные в/из avro формата. Как должна выглядеть эта библиотека?
Ну скорее всего вы хотите использовать только доменные сущности в интерфейсе библиотеки. В этом случае только эта библиотека зависит от стороннего решения и вы в любой момент смогли, например, изменить формат сериализации, если у вас изменились бизнес требования. Также приятно иметь стабильный интерфейс и линковать стороннее решение только с этой библиотекой.
С такими симптомами ваш терапевт прописал вам однократный прием pimpl идиомы. Выглядеть это может так:
Основная идея - все упоминания и детали реализации avro находятся в cpp и не торчат наружу. Это достигается за счет использования forward-declared класса в хэдэре и определение этого класса в сорцах. За счет этого мы имеем стабильный интерфейс, стабильный ABI и сокращенное время линковки. А за счет использования std::unique_ptr у нас тривиальные реализации всех специальных методов.
Примерно так это и выглядит в современных плюсах. Но это еще не конец для pimpl. Есть решение, которое поможем вам избежать динамических аллокаций. Но об этом в другой раз.
Hide details. Stay cool.
#design
#новичкам
В одном из давнишних постов мы уже обсуждали базовую формулировку и реализацию идиомы pimpl. Это сырой указатель на forward-объявленную структуру.
В современных плюсах, естественно, никто уже так не делает. Сырые указатели уходят в прошлое и старые подходы пересматриваются с применением умных указателей.
Допустим, вы используете какой-то нестандартный формат сериализации данных, например apache avro. Конечно вы хотите написать свою библиотеку сериализации, которая позволить конвертировать данные в/из avro формата. Как должна выглядеть эта библиотека?
Ну скорее всего вы хотите использовать только доменные сущности в интерфейсе библиотеки. В этом случае только эта библиотека зависит от стороннего решения и вы в любой момент смогли, например, изменить формат сериализации, если у вас изменились бизнес требования. Также приятно иметь стабильный интерфейс и линковать стороннее решение только с этой библиотекой.
С такими симптомами ваш терапевт прописал вам однократный прием pimpl идиомы. Выглядеть это может так:
// serializer.hpp
class Serializer {
public:
Serializer();
~Serializer();
// only move-semantic
Serializer(const Serializer&) = delete;
Serializer& operator=(const Serializer&) = delete;
Serializer(Serializer&&) noexcept;
Serializer& operator=(Serializer&&) noexcept;
std::vector<uint8_t> serializeOrder(const domain::Order& person);
domain::Order deserializeOrder(const std::vector<uint8_t>& data);
private:
std::unique_ptr<struct Impl> pimpl_; // Smart pointer on forward-declared struct
};
// serializer.cpp
struct Serializer::Impl {
avro::GenericRecord convertToAvro(const domain::Order&);
domain::Order convertFromAvro(const avro::GenericRecord&);
};
Serializer::Serializer()
: pimpl_(std::make_unique<Impl>()) {
}
Serializer::~Serializer() = default;
Serializer::Serializer(Serializer&&) noexcept = default;
Serializer& Serializer::operator=(Serializer&&) noexcept = default;
std::vector<uint8_t> Serializer::serializeOrder(const domain::Person& person) {
auto record = pimpl_->convertToAvro(person);
return {...};
}
// deserializeOrder
Основная идея - все упоминания и детали реализации avro находятся в cpp и не торчат наружу. Это достигается за счет использования forward-declared класса в хэдэре и определение этого класса в сорцах. За счет этого мы имеем стабильный интерфейс, стабильный ABI и сокращенное время линковки. А за счет использования std::unique_ptr у нас тривиальные реализации всех специальных методов.
Примерно так это и выглядит в современных плюсах. Но это еще не конец для pimpl. Есть решение, которое поможем вам избежать динамических аллокаций. Но об этом в другой раз.
Hide details. Stay cool.
#design