Использование сторонних библиотек - всегда использовать обертку?


78

Большинство проектов, в которых я участвую, используют несколько компонентов с открытым исходным кодом. Как общий принцип, всегда ли полезно избегать привязки всех компонентов кода к сторонним библиотекам и вместо этого проходить через инкапсулирующую оболочку, чтобы избежать проблем с изменениями?

В качестве примера, большинство наших проектов PHP напрямую используют log4php в качестве каркаса ведения журнала, то есть они создают с помощью \ Logger :: getLogger (), они используют методы -> info () или -> warn () и т. Д. В будущем однако может появиться гипотетическая структура ведения журнала, которая в некотором смысле лучше. В настоящее время все проекты, которые тесно связаны с сигнатурами метода log4php, должны были бы измениться в десятках мест, чтобы соответствовать новым сигнатурам. Это, очевидно, будет иметь большое влияние на кодовую базу, и любое изменение является потенциальной проблемой.

Для того, чтобы создавать перспективные новые кодовые базы из этого сценария, я часто рассматриваю (и иногда реализую) класс-оболочку для инкапсуляции функций ведения журналов и облегчения, хотя и не надежного, изменения способа ведения журналов в будущем с минимальными изменениями. ; код вызывает обертку, обертка передает вызов в структуру ведения журнала du jour .

Принимая во внимание, что есть более сложные примеры с другими библиотеками, я слишком перегружен или это мудрая мера предосторожности в большинстве случаев?

РЕДАКТИРОВАТЬ: Больше соображений - использование внедрения зависимостей и удвоения теста практически требует, чтобы мы в любом случае абстрагировали большинство API («Я хочу проверить, выполняет ли мой код и обновляет ли его состояние, но не писать комментарии в журнале / обращаться к реальной базе данных»). Разве это не решающий фактор?


3
log4XYZ является такой сильной торговой маркой. Его API изменится не раньше, чем изменится API для связанного списка. Обе проблемы давно решены.
Работа

1
Точная копия этого SO вопроса: stackoverflow.com/questions/1916030/…
Майкл Боргвардт

1
Если вы просто используете его для внутреннего использования, независимо от того, переносите вы или нет, это просто компромисс между известной работой сейчас и возможной работой позже. Судебный вызов. Но кое-что, о чем другие респонденты, похоже, забыли говорить, это зависимость от API или зависимость от реализации . Другими словами, вы пропускаете классы из этого стороннего API через собственный публичный API и открываете его пользователям? В этом случае переход к другой библиотеке уже не является простым делом, проблема в том, что теперь это невозможно без нарушения вашего собственного API. Это очень плохо!
Элиас Василенко

1
Для дальнейшего использования: этот шаблон называется onion-архитектурой, где внешняя инфраструктура (вы называете ее внешней библиотекой) скрыта за интерфейсом
k3b

Ответы:


42

Если вы используете только небольшое подмножество стороннего API, имеет смысл написать обертку - это помогает с инкапсуляцией и сокрытием информации, гарантируя, что вы не предоставите потенциально огромный API для своего собственного кода. Это также может помочь убедиться, что все функции, которые вы не хотите использовать, «скрыты».

Еще одна веская причина для обертки, если вы ожидаете изменить стороннюю библиотеку. Если это часть инфраструктуры, которую, как вы знаете, вы не измените, не пишите обертку для нее.


Хорошие моменты, но нас учат, что тесно связанный код плох по многим понятным причинам (сложнее тестировать, труднее реорганизовать и т. Д.). Альтернативная формулировка вопроса: «Если связь плохая, почему нормально соединяться с API?».
lotsoffreetime

7
@lotsoffreetime Вы не можете избежать некоторой связи с API. Поэтому лучше подключиться к вашему собственному API. Таким образом, вы можете изменить библиотеку и, как правило, не нужно менять API, предоставляемый оболочкой.
Джордж Мариан

@ george-marian Если я не могу избежать использования данного API, я, безусловно, могу минимизировать точки касания. Вопрос в том, должен ли я пытаться делать это все время или это перебор?
lotsoffreetime

2
@lotsoffreetime На этот вопрос сложно ответить. Я расширил свой ответ с этой целью. (В основном, это до многих случаев.)
Джордж Мариан

2
@lotsoffreetime: если у вас много свободного времени, то вы можете сделать либо. Но я бы не рекомендовал писать обертку API, за исключением следующих условий: 1) исходный API очень низкого уровня, поэтому вы пишете API более высокого уровня, чтобы лучше соответствовать конкретному проекту, или 2) у вас есть план в В ближайшем будущем, чтобы переключить библиотеки, вы используете текущую библиотеку только в качестве основы для поиска лучшей.
Ложь Райан

28

Не зная, какие супер-великолепные новые функции будет у этого предполагаемого будущего улучшенного регистратора, как бы вы написали обертку? Наиболее логичный выбор - чтобы ваша оболочка создавала какой-то класс logger и имела такие методы, как ->info()или ->warn(). Другими словами, по сути идентичный вашему нынешнему API.

Вместо того, чтобы писать код на будущее, который мне, возможно, никогда не понадобится изменить, или который в любом случае может потребовать неизбежного переписывания, я предпочитаю «код на будущее». То есть, в тех редких случаях , когда я существенно изменить компонент, это когда я пишу обертку , чтобы сделать его совместимым с прошлым кодом. Тем не менее, любой новый код использует новый API, и я реорганизую старый код, чтобы использовать его всякий раз, когда я вносю изменения в тот же файл в любом случае, или как позволяет расписание. Через несколько месяцев я могу снять обертку, и изменение было постепенным и надежным.

Иными словами, обертки действительно имеют смысл только тогда, когда вы уже знаете все API, которые вам нужно обернуть. Хорошие примеры: если ваше приложение должно поддерживать множество различных драйверов баз данных, операционных систем или версий PHP.


«... обертки действительно имеют смысл только тогда, когда вы уже знаете все API, которые вам нужно обернуть». Это было бы верно, если бы я соответствовал API в оболочке; возможно, мне следует использовать термин «инкапсуляция» более сильно, чем обертка. Я бы абстрагировал эти вызовы API, чтобы «как-то записать этот текст», а не «вызывать foo :: log () с этим параметром».
lotsoffreetime

«Не зная, какие супер-великолепные новые функции появится у этого предполагаемого будущего улучшенного регистратора, как бы вы написали обертку?» @ kevin-cline ниже упоминает о будущем регистраторе с лучшей производительностью, а не о новой функции. В этом случае нет нового API для переноса, просто другой метод фабрики.
lotsoffreetime

27

Оборачивая стороннюю библиотеку, вы добавляете дополнительный слой абстракции поверх нее. Это имеет несколько преимуществ:

  • Ваша кодовая база становится более гибкой к изменениям

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

  • Вы можете определить API оболочки независимо от API библиотеки

    Разные библиотеки могут иметь совершенно разные API, и в то же время ни одна из них не может быть именно тем, что вам нужно. Что если какой-то библиотеке нужен токен, который будет передаваться при каждом вызове? Вы можете передавать токен в своем приложении везде, где вам нужно использовать библиотеку, или вы можете хранить его где-то более централизованно, но в любом случае вам нужен токен. Ваш класс-оболочка снова делает все это простым - потому что вы можете просто хранить токен внутри своего класса-оболочки, никогда не подвергая его воздействию какого-либо компонента в вашем приложении, и полностью абстрагировать его от необходимости. Огромное преимущество, если вы когда-либо использовали библиотеку, которая не подчеркивает хороший дизайн API.

  • Модульное тестирование намного проще

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

  • Вы создаете слабосвязанную систему

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


Практический пример

Будем честны. Люди могут спорить о преимуществах и недостатках чего-то подобного часами - вот почему я просто хочу показать вам пример.

Допустим, у вас есть какое-то приложение для Android, и вам нужно загрузить изображения. Существует множество библиотек, которые делают загрузку и кэширование изображений быстрым, например, Picasso или Universal Image Loader .

Теперь мы можем определить интерфейс, который мы собираемся использовать, чтобы обернуть любую используемую нами библиотеку:

public interface ImageService {
    Bitmap load(String url);
}

Это интерфейс, который мы теперь можем использовать во всем приложении, когда нам нужно загрузить изображение. Мы можем создать реализацию этого интерфейса и использовать внедрение зависимостей, чтобы внедрить экземпляр этой реализации везде, где мы используем ImageService.

Допустим, мы изначально решили использовать Пикассо. Теперь мы можем написать реализацию, для ImageServiceкоторой внутри используется Пикассо:

public class PicassoImageService implements ImageService {

    private final Context mContext;

    public PicassoImageService(Context context) {
        mContext = context;
    }

    @Override
    public Bitmap load(String url) {
        return Picasso.with(mContext).load(url).get();
    }
}

Довольно прямо, если вы спросите меня. Обертывание вокруг библиотек не должно быть сложным, чтобы быть полезным. Интерфейс и реализация содержат менее 25 комбинированных строк кода, поэтому создать его было практически невозможно, но мы уже кое-что добились благодаря этому. Видите Contextполе в реализации? Платформа для внедрения зависимостей по вашему выбору уже позаботится о внедрении этой зависимости, прежде чем мы когда-либо будем использовать наше ImageService, теперь вашему приложению не нужно заботиться о том, как загружаются изображения и какие зависимости у этой библиотеки могут быть. Все, что видит ваше приложение, - это ImageServiceкогда ему нужно изображение, к которому он обращается load()с помощью URL - просто и понятно.

Однако реальная выгода приходит, когда мы начинаем что-то менять. Представьте, что теперь нам нужно заменить Picasso на Universal Image Loader, потому что Picasso не поддерживает некоторые функции, которые нам сейчас абсолютно необходимы. Должны ли мы теперь прочесывать нашу кодовую базу и утомительно заменять все вызовы Picasso, а затем иметь дело с десятками ошибок компиляции, потому что мы забыли несколько вызовов Picasso? Нет. Все, что нам нужно сделать, - это создать новую реализацию ImageServiceи сообщить нашей инфраструктуре внедрения зависимостей, чтобы с этого момента использовать эту реализацию:

public class UniversalImageLoaderImageService implements ImageService {

    private final ImageLoader mImageLoader;

    public UniversalImageLoaderImageService(Context context) {

        DisplayImageOptions defaultOptions = new DisplayImageOptions.Builder()
                .cacheInMemory(true)
                .cacheOnDisk(true)
                .build();

        ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(context)
                .defaultDisplayImageOptions(defaultOptions)
                .build();

        mImageLoader = ImageLoader.getInstance();
        mImageLoader.init(config);
    }

    @Override
    public Bitmap load(String url) {
        return mImageLoader.loadImageSync(url);
    }
}

Как видите, реализация может сильно отличаться, но это не имеет значения. Нам не нужно было менять ни одной строки кода где-либо еще в нашем приложении. Мы используем совершенно другую библиотеку, которая может иметь совершенно разные функции или может использоваться совсем по-другому, но нашему приложению все равно. Как и прежде, остальная часть нашего приложения просто видит ImageServiceинтерфейс с его load()методом, и, тем не менее, этот метод реализован, уже не имеет значения.

По крайней мере, для меня все это уже звучит довольно мило, но подождите! Там еще больше. Представьте, что вы пишете модульные тесты для класса, над которым вы работаете, и этот класс использует ImageService. Конечно, вы не можете позволить своим модульным тестам выполнять сетевые вызовы на некотором ресурсе, расположенном на каком-либо другом сервере, но, поскольку вы сейчас используете, ImageServiceвы можете легко позволить load()вернуть статическое значение, Bitmapиспользуемое для модульных тестов, реализовав mocked ImageService:

public class MockImageService implements ImageService {

    private final Bitmap mMockBitmap;

    public MockImageService(Bitmap mockBitmap) {
        mMockBitmap = mockBitmap;
    }

    @Override
    public Bitmap load(String url) {
        return mMockBitmap;
    }
}

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


1
Это также относится и к нестабильному API. Наш код не меняется в 1000 местах только потому, что изменилась базовая библиотека. Очень хороший ответ.
RubberDuck

Очень лаконичный и понятный ответ. Я занимаюсь интерфейсной работой в Интернете. Количество изменений в этом ландшафте безумно. Тот факт, что люди «думают», что они будут без изменений, не означает, что никаких изменений не будет. Я видел упоминания о Ягни. Я хотел бы добавить новую аббревиатуру YDKYAGNI, вы не знаете, что вам это не понадобится. Особенно с веб-связанными реализациями. Как правило, я всегда оборачиваю библиотеки, которые предоставляют только маленький API (например, select2). Большие библиотеки влияют на вашу архитектуру, и их перенос означает, что вы ожидаете, что ваша архитектура изменится, что может, но с меньшей вероятностью это произойдет.
До свидания

Ваш ответ был очень полезным, и представление концепции на примере сделало концепцию еще более ясной.
Анил Горти

24

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

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

Во втором случае вы создаете оболочку, адаптирующую старый интерфейс для управления новой библиотекой. Немного больше работы, но без проблем, и не больше работы, чем вы бы сделали, если бы написали обертку ранее.


4
Я не думаю, что YAGNI обязательно применяется в этой ситуации. Речь идет не о создании функциональности на случай, если она понадобится вам в будущем. Речь идет о создании гибкости в архитектуре. Если такая гибкость не нужна, тогда да, применяется YAGNI. Однако такое определение может быть принято когда-то в будущем, когда внесение изменений, вероятно, будет болезненным.
Джордж Мариан

7
@ Джордж Мариан: проблема в 95% случаев, вам никогда не понадобится гибкость, чтобы измениться. Если вам нужно переключиться на будущую новую библиотеку с превосходной производительностью, тогда будет достаточно просто искать / заменять вызовы или писать оболочку, когда вам это нужно. С другой стороны, если ваша новая библиотека поставляется с другими функциями, обертка теперь становится помехой, поскольку теперь у вас есть две проблемы: портирование старого кода для использования новых функций и поддержка обертки.
Ли Райан

3
@lotsoffreetime: цель «хорошего дизайна» - минимизировать общую стоимость приложения в течение срока его службы. Добавление слоев косвенности для предполагаемых будущих изменений - очень дорогая страховка. Я никогда не видел, чтобы кто-то осознавал какую-либо экономию от такого подхода. Это просто создает тривиальную работу для программистов, чье время было бы намного лучше потрачено на специфические требования заказчика. В большинстве случаев, если вы пишете код, не относящийся к вашему клиенту, вы тратите время и деньги.
Кевин Клайн

1
@ Джордж: если эти изменения болезненные, я думаю, что это процесс запах. В Java я создал бы новые классы с теми же именами, что и у старых классов, но в другом пакете, изменил бы все вхождения старого имени пакета и перезапустил автоматизированные тесты.
Кевин Клайн

1
@kevin Это больше работы и, следовательно, несет больший риск, чем просто обновление оболочки и запуск тестов.
Джордж Мариан,

9

Основная причина написания оболочки вокруг сторонней библиотеки состоит в том, что вы можете обмениваться этой сторонней библиотекой, не изменяя код, который ее использует. Вы не можете избежать связывания с чем-то, поэтому аргумент гласит, что лучше соединиться с API, который вы написали.

Стоит ли это усилий - другая история. Эта дискуссия, вероятно, продолжится еще долго.

Для небольших проектов, где вероятность того, что такое изменение будет необходимо, мала, это, вероятно, ненужные усилия. Для более крупных проектов такая гибкость вполне может перевесить дополнительные усилия по переносу библиотеки. Однако трудно заранее знать, так ли это на самом деле.

Другой способ взглянуть на это - основной принцип абстрагирования того, что может измениться. Таким образом, если сторонняя библиотека хорошо создана и вряд ли будет изменена, то, возможно, не стоит ее оборачивать. Однако, если сторонняя библиотека является относительно новой, существует большая вероятность, что ее потребуется заменить. Тем не менее, развитие существующих библиотек было прекращено много раз. Таким образом, это не простой вопрос.


В случае модульного тестирования, когда возможность внедрения макета API служит для минимизации тестируемого модуля, «потенциал изменения» не является фактором. Сказав это, это все еще мой любимый ответ, так как он наиболее близок к тому, как я думаю. Что бы сказал дядя Боб? :)
lotsoffreetime

Кроме того, небольшие проекты (без команды, базовых спецификаций и т. Д.) Имеют свои собственные правила, в которых вы можете нарушать передовую практику, подобную этой, и в какой-то степени сойти с рук. Но это другой вопрос ...
lotsoffreetime

1

В дополнение к тому, что уже сказал @Oded , я просто хотел бы добавить этот ответ для специальной цели регистрации.


У меня всегда есть интерфейс для регистрации, но мне еще не приходилось заменять log4fooфреймворк.

На создание интерфейса и написание оболочки требуется всего полчаса, поэтому, я полагаю, вы не тратите слишком много времени, если это окажется ненужным.

Это особый случай ЯГНИ. Хотя мне это не нужно, это не займет много времени, и я чувствую себя в большей безопасности. Если день обмена логгером действительно наступит, я буду рад, что потратил полчаса, потому что это сэкономит мне больше, чем день на обмен звонками в реальном проекте. И я никогда не писал и не видел модульный тест для регистрации (кроме тестов для самой реализации регистратора), так что ожидайте дефектов без оболочки.


Я не собираюсь менять log4foo, но он широко известен и служит примером. Интересно также, что два ответа до сих пор дополняют друг друга - «не всегда переносить»; "обернуть на всякий случай".
lotsoffreetime

@Falcon: ты все оборачиваешь? ORM, интерфейс журнала, базовые языковые классы? В конце концов, никто не может сказать, когда может понадобиться лучшая HashMap.
Кевин Клайн

1

Я имею дело именно с этим вопросом в проекте, над которым я сейчас работаю. Но в моем случае библиотека предназначена для графики, и поэтому я могу ограничить ее использование небольшим количеством классов, которые работают с графикой, вместо того, чтобы разбрасывать ее по всему проекту. Таким образом, довольно легко переключать API позже, если мне нужно; в случае с регистратором все становится намного сложнее.

Таким образом, я бы сказал, что решение во многом связано с тем, что именно делает сторонняя библиотека, и сколько боли будет связано с ее изменением. Если изменить все вызовы API будет легко независимо от этого, то, вероятно, это не стоит делать. Если, однако, позднее изменить библиотеку будет очень сложно, то, вероятно, я бы обернул ее сейчас.


Кроме того, другие ответы очень хорошо охватили основной вопрос, поэтому я просто хочу сосредоточиться на этом последнем добавлении, на внедрении зависимостей и макете объектов. Конечно, это зависит от того, как именно работает ваша структура журналирования, но в большинстве случаев нет, что для этого не требуется оболочка (хотя она, вероятно, выиграет от одной). Просто сделайте API для вашего фиктивного объекта точно таким же, как и в сторонней библиотеке, и тогда вы легко сможете заменить фиктивный объект для тестирования.

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


1

Я нахожусь в лагере оберток и не могу заменить стороннюю библиотеку самым большим приоритетом (хотя это и бонус). Мое главное объяснение, которое одобряет упаковку, простое

Сторонние библиотеки не предназначены для наших конкретных потребностей.

И это проявляется, как правило, в форме большого количества дублирования кода, например, разработчики пишут 8 строк кода просто для того, чтобы создать QButtonи стилизовать его так, как должно выглядеть приложение, только для дизайнера, который хочет не только внешний вид но также и функциональность кнопок для полного изменения для всего программного обеспечения, которое в конечном итоге требует возврата и переписывания тысяч строк кода, или обнаруживает, что модернизация конвейера рендеринга требует эпического переписывания, потому что кодовая база разбрызгивала низкоуровневые специальные фиксированные Разрабатывать код OpenGL повсеместно, вместо того, чтобы централизовать проект рендеринга в реальном времени и оставить использование OGL строго для его реализации.

Эти проекты не приспособлены к нашим конкретным потребностям. Они, как правило, предлагают огромный набор того, что действительно необходимо (и то, что не является частью дизайна, так же важно, если не больше, чем то, что есть), и их интерфейсы не предназначены для специального обслуживания наших потребностей на высоком уровне. Мысль = один запрос », который лишает нас всех центральных элементов управления проектами, если мы используем их напрямую. Если разработчики заканчивают тем, что пишут гораздо более низкоуровневый код, чем это требуется для выражения того, что им нужно, они могут иногда сами заключить его в обертку, что делает вас так, что вы получите в итоге десятки наскоро написанных и грубо Разработанные и документированные обертки вместо одной хорошо разработанной, хорошо документированной.

Конечно, я бы применил строгие исключения к библиотекам, в которых обертки представляют собой почти один к одному перевод того, что могут предложить сторонние API. В этом случае может не потребоваться поиск проекта более высокого уровня, который более непосредственно выражал бы требования бизнеса и дизайна (это могло бы иметь место для чего-то, напоминающего скорее «служебную» библиотеку). Но если есть гораздо более приспособленный дизайн, который намного более прямо отражает наши потребности, то я решительно в лагере обёрток, так же как я категорически за использование функции более высокого уровня и ее повторное использование вместо встраивания кода сборки повсюду.

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

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


0

Моя идея о сторонних библиотеках:

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

Следует ли нам избегать использования сторонних библиотек пользовательского интерфейса?

Причины рассмотрения сторонних библиотек:

Кажется, есть две основные причины, по которым разработчики рассматривают использование сторонней библиотеки:

  1. Недостаток навыков или знаний. Допустим, вы работаете над приложением для обмена фотографиями. Вы не начинаете с раскручивания своего собственного крипто.
  2. Нехватка времени или интереса, чтобы что-то построить. Если у вас нет неограниченного количества времени (которого еще нет у человека), вы должны расставить приоритеты.

Большинство библиотек пользовательского интерфейса ( не все! ) Обычно попадают во вторую категорию. Это не ракетостроение, но нужно время, чтобы его правильно построить.

Если это основная бизнес-функция - делай это сам, независимо от того, что это такое.

Существует почти два типа элементов управления / представлений:

  1. Универсальный, позволяющий использовать их в самых разных контекстах, о которых даже не думали их создатели, например, UICollectionViewиз UIKit.
  2. Конкретный, предназначен для одного варианта использования, например UIPickerView. Большинство сторонних библиотек, как правило, попадают во вторую категорию. Более того, они часто извлекаются из существующей кодовой базы, для которой они были оптимизированы.

Неизвестные ранние предположения

Многие из разработчиков делают обзоры кода своего внутреннего кода, но могут воспринимать качество стороннего исходного кода как должное. Стоит потратить немного времени на просмотр кода библиотеки. Вы можете быть удивлены, увидев некоторые красные флаги, например, метание, когда оно не нужно.

Часто изучение идеи более выгодно, чем получение самого кода.

Вы не можете это скрыть

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

Стоимость будущего времени

UIKit меняется с каждым выпуском iOS. Вещи сломаются. Ваша сторонняя зависимость не будет такой необслуживаемой, как вы можете ожидать.

Заключение :

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

Мы используем готовый код для быстрой доставки нашей текущей версии. Однако рано или поздно мы достигаем пределов библиотеки и предстаем перед трудным решением: что делать дальше?


0

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

Я думаю, что эти вопросы могут быть важнее, чем возможность удаленного использования совершенно другой библиотеки позже. Единственный случай, когда я использовал бы обертку, - это когда переход на другую реализацию определенно запланирован или обернутый API недостаточно заморожен и постоянно меняется.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.