PImpl Idiom



Если вы никогда не пользовались этой идиомой и только мельком читали про нее, то, скорее всего, вы вообще не понимаете, что это и для чего оно нужно. Вашей вины в этом нет, для работы вам она не нужна, а объясняют ее максимально уныло. В других телеграм каналах вы могли видеть что-то типа: "pimpl - это когда все в другой класс, а в этом классе только указатель остается. Нужно для уменьшения времени компиляции, сокрытия данных и увеличения производительности".



Последнее вообще в корне неверно. Если у вас есть указатель на тип, то объект этого типа вы должны создать через new, например. А это вызов аллокатора, который довольно много ресурсов сжирает. Плюс компилятор может не суметь заинлайнить некоторые операции из-за добавления еще одного уровня индирекции. Никто ж не поясняет за свои слова. Можно говорить все, что угодно. И так схавают.



В общем, попытаюсь объяснить. В одном посте все не уместится. Так как деталей ОЧ МНОГО. Давайте для начала разберемся со сферой применения исходя из преимуществ.



Сокращение времени компиляции. "Сомнительно, но ... окэй". Для большинства разработчиков - это вообще минус. Пока проектик собирается, можно и в ютубчик глянуть или кофеек попить. В общем, пожить за деньги работодателя. Никто не собирается проектировать приложение так, чтобы у него поменьше время компиляции было. Если оно превышает что-то типа 10-20 минут, то тогда можно заморочиться и порефакторить код. Но обычно, все не доходит до таких масштабов.



Сокрытие данных. Вот тут начинаются интересности. За каким макаром вам скрывать данные в своем проекте? У вас есть база, с ней надо как-то работать, вы пишете классы для работы с базой. Не очень понятно, зачем тут что-то скрывать. В проекте все видят реализацию и никаких секретов быть не должно. Но вот другая сторона вопроса. Вы пишете фреймворк по работе с базой. Типа libpqxx. Теперь есть смысл скрывать данные. Потому что пользователи - другие программисты и вы, например, не хотите им показывать, какой у вас там говнокод во фреймворке. Ну или по-взрослому, вы не хотите передавать свою библиотеку с исходниками, чтобы не раскрывать детали реализации или секреты интеллектуальной собственности. Вот это, я понимаю, причина.



На этом, обычно, преимущества заканчиваются. Но, на мой взгляд, тут упущено главное преимущество. ABI обратная совместимость. ABI - Application Binary Interface. Этот термин из той же бочки, что и API. Библиотека - бинарно совместима, если программа, динамически связанная с предыдущей версией библиотеки, продолжает работать с более новыми версиями библиотеки без необходимости перекомпиляции. Если программа нуждается в перекомпиляции, но не нуждается в модификации исходников, то библиотека - совместима по исходному коду. Первое утверждение относится к ABI, второе к API. Видим, что ABI накладывает более жесткие требования к интерфейсу библиотеки. Действительно, я не хочу заново компилировать свой суперхорошо работающий проект только для того, чтобы мочь использовать новую версию библиотеки. А если я использую 10 библиотек? А если 100? Мне нужно за каждой следить и при установке новой версии пересобирать бинарь? Это уже слишком. Сохранение ABI экономит кучу времени, сил и ограждает от проблем. Это делает распространение ПО намного более легким занятием.



И вот тут важный момент. Главным преимуществом Pimpl выделяют уменьшение времени компиляции. Изменение в impl классе никак не будут влиять на код, который использует публичный класс. Поэтому такой код перекомпилировать ненужно, нужна только новая версия объектного файла класса impl. И это сокращает время компиляции. Но это же всего лишь следствие сохранения бинарной совместимости вашего класса с пользовательским кодом. Вдумайтесь: главным преимуществом выделяют следствие другого преимущества, которое даже не выделяют. Это конечно смех. Если вы поняли это, просто читая информацию только из ру сегмента - вы герой.



Из этого всего я делаю вывод, что реально пользуется всеми преимуществами pimpl только разработка библиотек/фреймворков. Для обсуждения - милости простим в комментарии.



Stay aware. Stay cool.