Feel Good.

23 ноября 2011

Adapter pattern. Понимание важности.

Перед большинством проектов рано или поздно встает главный вопрос: "Использовать стороннюю компоненту или реализовать свою?", и как это часто бывает, по причине того что использовать уже существующее гораздо проще, чем создавать это заново мы выбираем уже готовое решение.

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

Итак, пришло время вспомнить о существовании такого шаблона проектирования как "Адаптер" (Adapter pattern). Я не буду здесь рассказывать про этот шаблон проектирования, а просто постараюсь выделить главную идею:

Всегда оборачивайте стороннюю компоненту своим интерфейсом и адаптируйте ее под себя.

Первая причина, почему это стоит делать очевидна - это устранение жестких зависимостей на стороннюю компоненту, а учитывая, что у зависимостей есть один неприятный момент: с ростом проекта они тоже разрастаются и чем дальше тем сложнее от них избавиться, и в конце концов можно стать "заложником" сторонней компоненты. Казалось бы простое правило, но на практике периодически сталкиваешься с обратным, да и сам порой забываешь обернуть, например, какой-нибудь logger, serializer(json, xml, yaml) или DI/IoC-контейнер, в надежде, что этот инструмент ты не сменишь никогда в проекте.

Вторая причина - это адаптация компоненты "под себя". Адаптируете компоненту таким образом, чтобы Вам было удобно ее использовать.

Один из примеров из личного опыта.
Не так давно, я занимался проектированием и реализацией сервиса получения финансовой информации в режиме реального времени с фондовых бирж (РТС и ММВБ). В качестве протокола взаимодействия с серверами бирж использовался стандартный (Financial Information eXchange или FIX/FAST).

Изучив спецификацию протокола FIX (и его оптимизацию FAST), было принято решение не писать свой парсер сообщений, а использовать уже готовую библиотеку, реализующую FIX/FAST в полной мере. На рынке (да и в opensource) тогда было несколько предложений", но вот времени чтобы изучить и выбрать подходящую библиотеку (быстродействие/поддержка/удобство использования) у меня тогда не было (выпуск первого рабочего прототипа поджимал все сроки). Тогда я выбрал одну из библиотек; выделил общие требования к библиотеке в виде нескольких интерфейсов: IFixMessage, IFixGroup, IFixSession, IFixEngine, IFixMessageReader, IFixMessageWriter, IFixMessageBuilder; реализовал адаптер. Важно отметить тот факт, что на практике в 80% случаев Вам потребуется лишь 20% функционала, который предлагает сама библиотека, и в этом случае Ваши интерфейсы получаются легкими (ничего "лишнего").

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

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

1 комментарий:

  1. > Всегда оборачивайте стороннюю компоненту своим интерфейсом и адаптируйте ее под себя.

    Сюда же относится работа с ORM, IoC контейнерами и т.п. инфраструктурными штуками. По мере развития проекта, который идет год и более их приходится менять на более новые и подходящие.

    Автору спасибо, что обратил внимание)

    ОтветитьУдалить