Должны ли внешние библиотеки быть обернуты? - PullRequest
4 голосов
/ 01 сентября 2011

Я использовал две библиотеки, SFML и Box2D, и в то же время прилагал большие усилия, чтобы ни одна из их функций или классов не была представлена ​​в основной части моего кода, скрывая их за классами, которые служат чуть больше, чем выступать в качестве посредника между моим кодом и самой библиотекой. Мои посредники принимают следующую форму:

    class MyWindow{
    public:
        // could be 10 or so functions like below
        int doSomething(int arg){
           return library_window->doSomething(arg);
        };
    private:
        library::window * library_window;
    };

Преимущество этого, по крайней мере того, что мне сказали, заключается в том, что мое основное тело кода не зависит от библиотеки таким образом, что, если оно изменится или я выберу другое, скажем, SDL или OpenGL вместо SFML или чего-то еще, я могу переключиться, просто изменив классы-посредники. Но боль от необходимости кодировать точку доступа в каждую функцию, которую я хочу использовать, болезненна и повторяется ...

Действительно ли профессиональные программисты должны обращаться с внешними библиотеками? И стоит ли это того?

Я вообще так делаю?

Ответы [ 6 ]

4 голосов
/ 01 сентября 2011

Не стоит. Просто используйте библиотеки. Если вы в конечном итоге захотите перейти на другую стороннюю библиотеку, вам все равно придется в любом случае изменить код своего приложения ... в противном случае, какой смысл изначально менять, если в обеих версиях все работает одинаково в любом случае.

Друзья не допускают чрезмерного инжиниринга друзей. Просто скажи нет.

3 голосов
/ 01 сентября 2011

Проблема с техникой оболочки, которую вы описываете, состоит в том, что ваша оболочка прозрачна (в истинном смысле этого слова) - каждый метод в библиотеке все еще виден вам через оболочку, с той же семантикой, той жепредварительные условия и т. д. Вы можете "видеть сквозь" свою оболочку.

Такая прозрачная оболочка полезна вам только в том случае, если вы когда-нибудь переключите базовую библиотеку на что-то с идентичной семантикой или, по крайней мере, почти идентичнойсемантика.Рассмотрим этот пример.Скажем, библиотека была std :: fstream, и вашему приложению нужно было читать и записывать файлы, и предположим, что вы старательно написали обертку:

class MyFile {
    std::fstream* fst;
public:
    void writeData(void* data, size_t count) {
        fst->write((const char*) data, count);
    }
    void readData(void* buffer, size_t count) {
        fst->read((char*) data, count);
    }
    // etc, etc.
};

Теперь, допустим, вы хотите (или должны)переключиться на асинхронный ввод / вывод с неблокирующим чтением и записью.Просто нет никакой возможности, чтобы ваша прозрачная оболочка помогла вам сделать этот переход.Асинхронное чтение требует двух методов: один для запуска операции чтения и один для подтверждения того, что чтение завершено.Это также требует от приложения принятия обязательства, что буфер не будет использоваться между этими двумя вызовами методов.

Когда все сказано и сделано, оболочка интерфейса библиотеки полезна, только если очень тщательно разработана, чтобы не быть прозрачной (хорошие интерфейсы непрозрачны).Кроме того, чтобы быть полезным, библиотека, которую вы упаковываете, должна быть чем-то, с чем вы хорошо знакомы.Таким образом, boost :: filesystem может «обернуть» имена путей как для DOS, так и для Unix, потому что авторы хорошо знают пути POSIX, UNIX и DOS и разрабатывают «оболочку» для эффективной инкапсуляции этих реализаций.

Из того, что вы описали, мне кажется, что ваши усилия в конечном итоге будут напрасными.Простое лучше, чем сложное, и если оболочка действительно не инкапсулирует что-то (то есть скрывает основную библиотеку), прямое лучше, чем косвенное.

Это не лицензия для написания спагетти - вашему приложению все еще нужна структура иизоляция основных компонентов (например, изолировать пользовательский интерфейс от фактических расчетов / моделирования / документа, которые предоставляет ваше приложение).Если вы все сделаете правильно, замена библиотеки однажды станет управляемой задачей без какого-либо кода-обертки.

2 голосов
/ 01 сентября 2011

Вы должны обернуть что-либо при двух обстоятельствах:

  1. У вас есть основания полагать, что вы можете изменить это.И я не имею в виду "хорошо, однажды, может быть, вроде".Я имею в виду, что у вас есть реальное убеждение, что вы можете переключать библиотекиВ качестве альтернативы, если вам нужно поддерживать более одной библиотеки.Возможно, вы разрешите выбор между использованием SDL и SFML.Или что угодно.

  2. Вы предоставляете абстракцию этой функциональности.То есть вы не просто делаете тонкую обертку;вы улучшаете этой функциональности.Упрощение интерфейса, добавление функций и т. Д.

1 голос
/ 01 сентября 2011

Неплохая идея, если вы хотите предоставить более простой интерфейс ( Соглашение по конфигурации ).Но если вы просто собираетесь переводить все утилиты из библиотеки 1: 1, то это того не стоит.

1 голос
/ 01 сентября 2011

Да, это правильно, вы должны кодировать основные функции, которые нужны вашей программе, и написать оболочку, которая оборачивает (избыточные ...) библиотеки, чтобы делать то, что вам нужно. Просто добавляя новую библиотеку, вы просто пишете новую оболочку и можете просто поменять базовые оболочки из-под вашей программы, не заботясь об этом. Если вы разделяете ваши заботы, тогда гораздо проще добавить функциональность позже, потому что вам не нужно искать, где вы используете функции или использовать сложные операторы #ifdef для переключения библиотек, вы просто использовали бы простой #ifdef, чтобы определить что-то вроде

#ifdef LIB_A
typedef MyGfxClassA MyGfxClass;
#endif

и т.д ...

1 голос
/ 01 сентября 2011

Это зависит.

Если вы используете очень зрелую библиотеку и, вероятно, не будете переходить на другие реализации, класс-посредник не нужен.Например, вы когда-нибудь инкапсулировали библиотеку stl или boost?

С другой стороны, если используемая вами библиотека является новой или существует множество альтернатив, тогда абстракция может быть полезной.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...