Подтвердить что ты не робот

Как делиться концепциями бизнеса на разных языках программирования?

Мы разрабатываем распределенную систему, созданную из компонентов, реализованных на разных языках программирования (С++, С# и Python), и обмениваемся друг с другом по сети. Все компоненты системы работают с одними и теми же бизнес-концепциями и обмениваются друг с другом также с точки зрения этих понятий.

В результате мы сильно боремся со следующими двумя проблемами:

  • Сохранение представления наших бизнес-концепций на этих трех языках в синхронизации
  • Сериализация/десериализация наших бизнес-концепций на этих языках

Наивное решение этой проблемы было бы просто трижды определить те же структуры данных (и код сериализации) (для С++, С# и Python).

К сожалению, это решение имеет серьезные недостатки:

  • Он создает много "дублирования кода"
  • Требуется огромное количество тестов интеграции на разных языках, чтобы синхронизировать все.

Другое решение, которое мы рассмотрели, основано на таких платформах, как ProtoBufs или Thrift. Эти структуры имеют внутренний язык, в котором определены бизнес-концепции, а затем представление этих понятий в С++, С# и Python (вместе с логикой сериализации) автоматически генерируется этими фреймами.

Хотя это решение не имеет вышеуказанных проблем, у него есть еще один недостаток: код, созданный этими фреймами, объединяет структуры данных, представляющие основные бизнес-концепции, и код, необходимый для сериализации/десериализации этих структур данных.

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

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

Может ли кто-нибудь порекомендовать решение, которое обойдет описанные проблемы?

4b9b3361

Ответ 1

Лев, вы можете посмотреть ICE. Он предоставляет объектно-ориентированный IDL с отображением на все языки, которые вы используете (С++, Python,.NET(все языки .NET, а не только С#, насколько я понимаю)). Хотя ICE - это среда среднего уровня, вам не нужно следовать всем ее политикам.

В частности, в вашей ситуации вы можете определить интерфейсы своих компонентов в ICE IDL и поддерживать их как часть кода. Затем вы можете генерировать код как часть вашей строковой процедуры и работать оттуда. Или вы можете использовать больше возможностей, которые дает вам ICE.

ICE поддерживает структуры данных С++ STL и поддерживает наследование, следовательно, это должно дать вам достаточно мощный формализм для постепенного создания вашей системы с течением времени с хорошей степенью ремонтопригодности.

Ответ 2

Ну, когда-то MS пыталась решить это с помощью IDL. Ну, на самом деле он пытался решить немного больше, чем определять структуры данных, но, во всяком случае, это все в прошлом, потому что никто в здравом уме не пошел по COM-маршруту в эти дни.

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

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

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

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

Ответ 3

Я согласен с Tristan Reid (обертывание бизнес-логики). На самом деле, несколько месяцев назад я столкнулся с той же проблемой, а затем случайно обнаружил книгу "Искусство программирования Unix" (свободно доступный онлайн). Что привлекло мое внимание, было философией ветки политики от механизма (т.е. Интерфейсов от двигателей). Современные среды программирования, такие как платформа NET, пытаются интегрировать все под одним доменом. В те дни меня попросили разработать WEB-приложение, которое должно было удовлетворять следующим требованиям:

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

  • Он должен был быть доступен с помощью разных интерфейсов: веб, командной строки и графического интерфейса рабочего стола.

  • Он должен был запускаться в Windows и Linux.

Я уверен, что полностью разработал механизм (движки) на C/С++ и использовал собственные библиотеки ОС (POSIX или WinAPI) и хорошие библиотеки с открытым исходным кодом (postgresql, xml и т.д.). Я разработал модули двигателей в качестве программ командной строки, и в итоге я реализовал два интерфейса: web (с инфраструктурой PHP + JQuery) и рабочий стол (NET framework). Оба интерфейса не имели ничего общего с механизмами: они просто запускали исполняемые модули основных модулей, вызывая такие функции, как CreateProcess() в Windows или fork() в UNIX, и использовали каналы для мониторинга своих процессов.

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

Ответ 4

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

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

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

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

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

Генерация кода может быть правильным выбором здесь, если причина 2 - ваша проблема. Если существующие генераторы кода не пострадают от ваших потребностей, почему бы вам просто не написать свой собственный? Определите интерфейсы, например, как классы в С#, внесите некоторые мета-атрибуты и используйте отражение в генераторе кода, чтобы извлечь информацию снова при создании соответствующих С++, Python, а также "реального использования" кода С#. Если вам нужны разные варианты с сериализацией или без нее, сгенерируйте их тоже. Рабочий генератор не должен быть больше усилий, чем несколько дней (YMMV в зависимости от ваших требований).

Ответ 5

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

Ответ 6

Вы можете смоделировать эти структуры данных с помощью таких инструментов, как UML-модельер (Enterprise Architect приходит на ум, поскольку он может генерировать код для всех 3.), а затем генерировать код для каждого языка непосредственно из модели.

Хотя я бы внимательно посмотрел на предыдущий комментарий об использовании XSD.

Ответ 7

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