Предметно-ориентированное мультимоделирование [1] — это парадигма разработки программного обеспечения, в которой каждое представление явно описывается как отдельный предметно-ориентированный язык (DSL).
Успешная разработка современной корпоративной системы требует конвергенции нескольких взглядов. Бизнес-аналитики, эксперты в предметной области, проектировщики взаимодействия, эксперты по базам данных и разработчики с различными видами опыта — все они принимают участие в процессе создания такой системы. Их различные рабочие продукты должны управляться, согласовываться и интегрироваться для создания работающей системы. У каждого участника процесса разработки есть определенный язык, адаптированный для решения проблем, характерных для его взгляда на систему. Задача интеграции этих различных взглядов и избежания потенциальной какофонии нескольких различных языков — это проблема координации .
Мультимоделирование, ориентированное на домен [1], является многообещающим по сравнению с более традиционными парадигмами разработки, такими как одноязыковое программирование и моделирование общего назначения . Чтобы воспользоваться преимуществами этой новой парадигмы, мы должны решить проблему координации. Эта проблема также известна как проблема фрагментации в контексте глобального управления моделями.
Одним из предложений по решению этой проблемы является метод координации . [1] Это трехэтапный метод преодоления препятствий интеграции различных взглядов и координации нескольких языков. Метод предписывает, как (1) идентифицировать и (2) указывать ссылки через языковые границы, то есть совпадения между разными языками. Наконец, метод предлагает конкретные предложения о том, как (3) применять эти знания в реальной разработке в форме последовательности, навигации и руководства.
Корпоративные системы, основанные на нескольких предметно-ориентированных языках, широко распространены. Языки с метамоделью, определенной в расширяемом языке разметки (XML), пользуются особенно широким распространением. Чтобы проиллюстрировать разработку с использованием нескольких языков, мы приведем пример из тематического исследования: система Apache Open For Business (OFBiz). Вкратце, OFBiz — это система планирования ресурсов предприятия , которая включает стандартные компоненты, такие как инвентаризация, бухгалтерский учет, электронная коммерция и т. д. Эти компоненты реализованы с помощью смеси языков на основе XML и обычного кода Java. В качестве примера давайте сосредоточимся на компоненте управления контентом , в частности на варианте использования, в котором администратор создает онлайн-опрос, как показано на снимке экрана ниже. Мы будем называть этот пример примером создания опроса .
На рисунке показан снимок экрана административного интерфейса приложения управления контентом в работающем экземпляре OFBiz. Чтобы создать опрос, пользователь заполняет поля формы ввода и нажимает кнопку обновления . Это создает новый опрос, который можно редактировать и позже публиковать на веб-сайте интерфейса в OFBiz. За кулисами этот вариант использования включает в себя несколько артефактов, написанных на разных языках. В этом примере давайте сосредоточимся только на трех из этих языков: Entity, Service и Form DSL.
Эти три языка примерно соответствуют структурным, поведенческим и пользовательским интерфейсам в OFBiz. Entity DSL используется для описания базовой модели данных и, следовательно, способа сохранения созданного опроса. Service DSL используется для описания интерфейса сервиса, который вызывается, когда пользователь нажимает кнопку обновления . Наконец, Form DSL используется для описания визуального вида формы. Хотя три языка предназначены для разных целей, их нельзя полностью разделить. Пользовательский интерфейс вызывает определенную прикладную логику, и эта прикладная логика манипулирует данными приложения. Это пример неортогональных проблем . Языки пересекаются, поскольку проблемы, которые они представляют, не могут быть полностью разделены. Давайте рассмотрим эти три языка снизу вверх и укажем на их совпадения.
Entity DSL определяет структуру данных в OFBiz. В приведенном ниже листинге показано определение сущности Survey, которая является бизнес-объектом, представляющим концепцию опроса. Код в листинге не требует пояснений: сущность с именем Survey определяется с 10 полями. Каждое поле имеет имя и тип. Поле surveyId используется в качестве первичного ключа . Это определение загружается центральным компонентом в OFBiz, называемым механизмом сущностей . Механизм сущностей создает экземпляр соответствующего бизнес-объекта . Целью механизма сущностей является управление транзакционными свойствами всех бизнес-объектов и взаимодействие с различными механизмами сохранения, такими как Java Database Connectivity , Enterprise JavaBeans или даже некоторые устаревшие системы .
<entity entity-name= "Опрос" ... title= "Сущность опроса" > <имя поля = "surveyId" тип= "id-ne" /> < имя поля= "surveyName" тип= "name" /> < имя поля= "description" тип= "description" /> < имя поля= "comments" тип= "comment" /> < имя поля= "submitCaption" тип= "short-varchar" /> < имя поля= "responseService" тип= "long-varchar" /> < имя поля= "isAnonymous" тип= "indicator" ... /> < имя поля= "allowMultiple" тип= "indicator" ... /> < имя поля= "allowUpdate" тип= "indicator" ... /> < имя поля= "acroFormContentId" тип= "id-ne" ... /> <prim-key field= "surveyId" /> </entity>
Service DSL определяет интерфейс сервисов в OFBiz. Каждый сервис инкапсулирует часть прикладной логики системы. Цель этого языка — иметь единую абстракцию над различными механизмами реализации. Отдельные сервисы могут быть реализованы на Java, языке сценариев или с использованием механизма правил . В приведенном ниже списке показан интерфейс сервиса createSurvey.
Помимо имени, элемент service указывает местоположение и команду вызова реализации для этого сервиса. Атрибут default-entity-name указывает, что этот сервис ссылается на сущность Survey, которая была определена в предыдущем листинге. Это перекрытие между двумя языками, в частности, так называемая мягкая ссылка . Модель в Service DSL ссылается на модель в Entity DSL. Эта ссылка используется в двух элементах auto-attributes ниже, которые указывают входные и выходные данные сервиса в виде типизированных атрибутов. В качестве входных данных сервис принимает атрибуты, соответствующие всем полям непервичного ключа (nonpk) сущности Survey, и эти атрибуты являются необязательными. В качестве выходных данных сервис возвращает атрибуты, соответствующие полям первичного ключа (pk) Survey, т. е. в данном случае полю surveyId, и эти атрибуты являются обязательными. Цель ссылки между языками в данном случае состоит в том, чтобы уменьшить избыточность. Атрибуты сервиса createSurvey соответствуют полям сущности Survey, и поэтому их необходимо указывать только один раз.
<service name= "createSurvey" default-entity-name= "Survey" ... location= "org/ofbiz/content/survey/SurveyServices.xml" invoke= "createSurvey" > ... <permission-service service-name= "contentManagerPermission" main-action= "CREATE" /> <auto-attributes include= "nonpk" mode= "IN" Optional= "true" /> <auto-attributes include= "pk" mode= "OUT" Optional= "false" /> </service>
Form DSL используется для описания макета и внешнего вида форм ввода в пользовательском интерфейсе. Язык состоит из таких концепций домена, как Form и Field. В приведенном ниже листинге показана реализация формы EditSurvey. На этот раз Form DSL перекрывается с Service DSL. Атрибут target формы и элементы alt-target указывают, что ввод из отправки этой формы должен быть направлен либо в службу updateSurvey, либо в службу createSurvey. Элемент auto-fields-service указывает, что форма должна включать поле, соответствующее каждому из атрибутов службы updateSurvey (которые аналогичны атрибутам службы createSurvey). Это создает аналогичный эффект импорта определений из другой модели, как и в случае элементов auto-attributes в предыдущем листинге. Далее мы видим, что можно настраивать внешний вид этих импортированных полей, таких как isAnonymous. Наконец, добавляется submitButton с локализованным заголовком, чтобы пользователь мог отправлять свои данные в указанную службу.
<form name= "EditSurvey" type= "single" target= "updateSurvey" title= "" default-map-name= "survey" > <alt-target use-when= "survey==null" target= "createSurvey" /> <auto-fields-service service-name= "updateSurvey" /> <field use-when= "survey!=null" name= "surveyId" ... /> ... <field name= "isAnonymous" > <drop-down no-current-selected-key= "N" allow-empty= "false" > <option key= "Y" /><option key= "N" /> </drop-down> </field> ... <field name= "submitButton" title= "${uiLabelMap.CommonUpdate}" widget-style= "smallSubmit" > <submit button-type= "кнопка" /> </поле > </форма>
Пример создания опроса , описанный здесь, реализован с использованием моделей на трех разных языках. Полная реализация на самом деле включает в себя даже больше языков, таких как Screen DSL для указания макета экрана, на котором размещается форма, и Minilang DSL, который является языком манипулирования данными, используемым для реализации сервиса. Однако эти три языка иллюстрируют основную идею конкретизации каждой проблемы. Пример также показывает простой способ уменьшения избыточности, позволяя языкам слегка перекрываться.
Предметно-ориентированные языки , подобные описанным выше, имеют ограниченную выразительность. Часто необходимо добавлять фрагменты кода на языке общего назначения, таком как Java, для реализации специализированной функциональности, которая выходит за рамки языков. Этот метод называется многоуровневой настройкой . [2] Поскольку этот метод очень часто используется в установках с несколькими языками, мы проиллюстрируем его продолжением примера. Назовем это примером сборки PDF .
Предположим, мы хотим создать файл PDF для каждого ответа на опрос в онлайн-опросах, которые создают пользователи. Создание файла PDF выходит за рамки наших языков, поэтому нам нужно написать некоторый код Java, который может вызывать стороннюю библиотеку PDF для выполнения этой специализированной функции. Требуются два артефакта:
Во-первых, дополнительная модель сервиса, как показано ниже, в Service DSL, которая определяет интерфейс конкретного сервиса, чтобы к нему можно было получить доступ на уровне моделирования. Модель сервиса описывает местоположение реализации и то, каковы входные и выходные атрибуты.
< имя службы = "buildPdfFromSurveyResponse" engine = "java" location = "org.ofbiz.content.survey.PdfSurveyServices" invoke = "buildPdfFromSurveyResponse" > < имя атрибута = "surveyResponseId" mode = "IN" Optional = "false" ... /> < имя атрибута = "outByteWrapper" mode = "OUT" Optional = "false" ... /> </service>
Во-вторых, нам нужен фрагмент кода, как показано ниже, который содержит фактическую реализацию этой службы. Служба может иметь несколько входов и выходов, поэтому входные данные для метода Java представляют собой карту, называемую контекстом, из имен аргументов в значения аргументов и возвращают выходные данные в форме другой карты, называемой результатами.
public static Map buildPdfFromSurveyResponse ( DispatchContext dctx , Map context ) { String id = ( String ) context.get ( "surveyResponseId" ); Map results = new HashMap (); try { // ...ответ извлекается из базы данных... // ... из ответа создается PDF-файл... // ... PDF-файл сериализуется как байтовый массив... ByteWrapper outByteWrapper = ... ; results.put ( "outByteWrapper" , outByteWrapper ); } catch ( Exception e ) {} return results ; }
Этот многоуровневый метод настройки использует мягкие ссылки, похожие на пример создания опроса . Главное отличие в том, что ссылка здесь находится между моделью и кодом, а не между моделью и моделью. Преимущество в этом случае в том, что можно использовать стороннюю библиотеку Java для создания PDF-файлов. Другое типичное применение — использование фрагментов кода Java для вызова внешних веб-сервисов и импорта результатов в подходящем формате.
Пример иллюстрирует некоторые преимущества использования нескольких языков в разработке. Однако существуют и трудности, связанные с этим типом разработки. Эти трудности вытекают из наблюдения, что чем больше видов артефактов мы вводим в наш процесс, тем больше требуется координации между усилиями разработчиков. Мы будем называть эти трудности проблемой координации . Проблема координации имеет концептуальный и технический аспекты. Концептуально, основная проблема заключается в понимании различных языков и их взаимодействия. Чтобы правильно проектировать и координировать модели на нескольких языках, разработчики должны иметь достаточное понимание того, как взаимодействуют языки. Технически, основная проблема заключается в обеспечении согласованности. Должны быть предоставлены инструменты для раннего обнаружения несоответствий, т. е. во время моделирования, и помощи разработчикам в разрешении этих несоответствий. Далее мы рассмотрим эти два аспекта более подробно.
Первая проблема, с которой сталкиваются разработчики при начале разработки на нескольких языках, — это языковая какофония . Изучение различных языков и понимание их взаимодействия необходимо для понимания сложной композиции артефактов. Например, фреймворк OFBiz имеет семнадцать различных языков и более 200 000 строк кода предметно-ориентированного языка, поэтому сложность может быть довольно подавляющей! В настоящее время не существует устоявшегося метода описания различных языков, чтобы разработчики могли быстро достичь операционного понимания. Инструменты здесь важны как специальный механизм для обучения и исследования, поскольку разработчики обычно используют инструменты для обучения путем экспериментов. Есть три области, где инструменты для предметно-ориентированных моделей особенно полезны:
Во-первых, понимание языка может быть сложным, и в случае доменных языков на основе XML частое и интуитивно понятное возражение — это возражение о том, что синтаксис имеет значение . Этот аргумент можно сформулировать следующим образом: «Разные языки сложны для понимания и только добавляют путаницы, поскольку их синтаксис на основе XML особенно многословен и непонятен. Использование одного языка общего назначения, такого как Java, было бы лучше, поскольку тогда разработчики могли бы полагаться на синтаксис, который они уже знают». Хотя это возражение, безусловно, важно, оно упускает центральный момент. XML или аналогичный формат представления может не быть тем синтаксисом, с которым на самом деле работают разработчики. Одним из преимуществ использования доменных языков на основе XML является то, что мы можем предоставлять доменные редакторы. На рисунке ниже показано, как может выглядеть гипотетический редактор для Entity DSL. Этот редактор представляет домен простым и визуально привлекательным образом, но вполне может использовать XML-представление (и, возможно, конфигурацию макета) под ним.
Так же, как мы можем жаловаться на то, что XML — плохой выбор, мы также можем возразить, что язык общего назначения, такой как Java, — плохой выбор для некоторых задач. Более того, разработчики могут чувствовать себя менее запуганными редактором в рисунке, чем листингами кода в XML или Java. Если мы признаем, что синтаксис имеет значение , то использование разных языков с адаптированными редакторами становится разумной стратегией. Простота редактора делает язык более простым для понимания и, следовательно, более простым в использовании. Другими словами, возражение о важности синтаксиса может быть той самой причиной, по которой мы исследуем область предметно-ориентированных языков .
Во-вторых, языковые взаимодействия выявляют связи между языками. Разработчики должны иметь возможность переходить между связанными элементами в различных артефактах. Простота навигации между различными программными артефактами является важным критерием для инструментов в традиционных средах разработки. Хотя мы не проводили никаких эмпирических исследований в этой области, мы предполагаем, что надлежащие средства навигации повышают производительность. Это утверждение подтверждается наблюдением, что все основные среды разработки сегодня предлагают довольно сложные средства навигации, такие как браузер иерархии типов или возможность быстрого поиска и перехода к ссылкам на определение метода. Среды разработки могут предоставлять эти средства навигации, поскольку они поддерживают постоянно обновляемую модель исходных файлов в форме абстрактного синтаксического дерева .
В среде разработки с несколькими языками навигация намного сложнее. Существующие среды не приспособлены для анализа и представления моделей DSL в виде абстрактных синтаксических деревьев для произвольных и, возможно, даже специфичных для приложений языков, таких как языки из предыдущего примера. Более того, без этого внутреннего представления существующие среды не могут разрешить ни внутриязыковые, ни межъязыковые ссылки для таких языков и, следовательно, не могут обеспечить полезную навигацию. Это означает, что разработчики должны поддерживать концептуальную модель того, как связаны части их системы. С другой стороны, новые инструменты с возможностями навигации, приспособленными для нескольких языков, были бы очень полезны для понимания отношений между языками. В терминах примера создания опроса такие инструменты должны отображать отношения между тремя языками, используя мягкие ссылки в качестве точек навигации.
В-третьих, чтобы понимать использование языка, мы должны уметь отличать правильные операции редактирования от неправильных в нашей среде разработки. Традиционные среды разработки долгое время предоставляли руководство во время написания программы. Инкрементная компиляция позволяет среде предлагать разработчику подробные предложения, например, как завершить оператор. Существуют также более навязчивые виды руководства, такие как синтаксически-ориентированные редакторы, в которые можно вводить только ввод, соответствующий грамматике. Универсальные текстовые редакторы, которые можно параметризовать с помощью грамматики языка, существуют уже давно. [3]
Существующие редакторы не учитывают межъязыковые отношения согласованности при предоставлении руководства. В предыдущем примере идеальный редактор должен, например, иметь возможность предлагать службу createSurvey в качестве допустимого значения, когда разработчик редактирует целевой атрибут в определении формы. Среда, которая могла бы рассуждать об артефактах из разных языков, также могла бы помочь разработчику определить состояния программы, в которых была локальная, но не глобальная согласованность. Такая ситуация может возникнуть, когда модель хорошо сформирована и, следовательно, локально согласована, но в то же время нарушает межъязыковое ограничение. Руководство или интеллектуальная помощь в форме предложений о том, как завершить модель, были бы полезны для установок с несколькими языками и сложными ограничениями согласованности. Операции редактирования, предлагаемые инструментом, могли бы облегчить разработчику начало процесса изучения того, как использовать языки.
Технический аспект проблемы координации по сути является вопросом обеспечения согласованности. Как мы можем обнаружить несоответствия между моделями из нескольких языков во время моделирования? Чтобы полностью понять сложность требований согласованности системы, основанной на нескольких языках, полезно уточнить нашу концепцию согласованности.
Согласованность может быть как внутри-, так и между-согласованностью. Внутри-согласованность касается согласованности элементов в пределах одной модели. Требования здесь таковы, что модель должна соответствовать своей метамодели, т. е. быть синтаксически правильно сформированной. В терминах примера создания опроса, модель сущности должна, например, соответствовать схеме XSD Entity DSL. Эта схема является метамоделью Entity DSL и определяет, как элементы могут быть составлены и каковы, в некоторой степени, допустимые домены атрибутов.
Взаимная согласованность достигается, когда ссылки через языковые границы могут быть разрешены. Этот вид согласованности может быть далее подразделен на (1) согласованность модели с моделью и (2) согласованность модели с кодом. Согласованность модели с моделью касается ссылочной целостности , а также высокоуровневых ограничений системы. В примере создания опроса атрибут default-entity-name из списка Service ссылается на атрибут name из списка Entity. Если мы изменим одно из этих значений, не обновив другое, мы нарушим ссылку. Существуют также более высокоуровневые ограничения согласованности между различными моделями, как обсуждается далее. Проект может иметь определенные шаблоны или соглашения для наименования и соотнесения элементов модели. Текущие среды разработки должны быть адаптированы к определенным языкам с помощью рукописных плагинов или аналогичных механизмов, чтобы обеспечить согласованность между языками, такими как в предыдущем примере.
Согласованность модели с кодом является существенным требованием в многоуровневой настройке. Когда модели дополняются фрагментами кода, как в примере сборки PDF , необходимо проверить, что модели и код действительно подходят . Это отчасти вопрос обеспечения того, чтобы мягкие ссылки между моделями и кодом не были нарушены, аналогично ссылочной целостности в согласованности модели с моделью. Но это также вопрос обеспечения того, чтобы код не нарушал ожидания, установленные в модели. В примере сборки PDF модель указывает, что outByteWrapper всегда будет частью вывода, т. е. ключ outByteWrapper помещается в карту результатов. Анализ кода показывает, что outByteWrapper будет частью вывода только в том случае, если до строки 10 не будет выброшено никаких исключений. Другими словами, некоторые возможные выполнения кода нарушат спецификацию на уровне моделирования. В более общем плане, мы можем утверждать, что многоуровневая настройка накладывает очень тонкие ограничения на задействованные модели и фрагменты кода.
Проблема координации возникает из-за того, что в одной системе используется несколько языков. Два предыдущих подраздела иллюстрируют, что эта проблема имеет как концептуальную сторону, так и низкоуровневую техническую сторону. Проблемы, которые мы описали, являются реальными, а не гипотетическими. В частности, мы столкнулись с этими проблемами в двух конкретных и репрезентативных тематических исследованиях: система планирования ресурсов предприятия OFBiz и система здравоохранения District Health Information System ( DHIS ). Оба случая представляют собой системы среднего размера, которые находятся в реальном промышленном использовании. Наше решение практических проблем, с которыми мы столкнулись во время работы с этими системами, — это набор руководств и прототипов. Далее мы представим общую концептуальную структуру, которая объединяет руководящие принципы и прототипы в последовательный метод: метод координации .
Целью метода координации [1] является решение проблемы координации и, таким образом, обеспечение лучшей поддержки для разработки с несколькими языками. Чтобы правильно оценить метод, важно понимать, что он не предписывает дизайн отдельных языков. Для этого уже было предложено множество методов и инструментов. [4] [5] Этот метод предполагает наличие настройки с несколькими предметно-ориентированными языками. При наличии такой настройки можно применить метод. Метод состоит из трех шагов, как показано на схеме ниже. Каждый шаг состоит из пары частей, которые показаны на схеме в виде маленьких квадратиков. Квадраты с пунктирными линиями представляют автоматические процессы, а квадраты со сплошными линиями представляют ручные. Далее мы объясним эти шаги немного подробнее.
Целью этапа идентификации является выявление языковых совпадений. Как описано в примере, совпадение — это область, в которой пересекаются интересы двух языков. Мягкие ссылки из Form DSL в Service DSL и из Service DSL в Entity DSL в сценарии использования создания опроса являются примерами таких совпадений. Другим примером является случай, когда для расширения модели используется настраиваемый фрагмент кода. Такие совпадения часто встречаются, когда требуется выразительность языков общего назначения для реализации специализированных требований, выходящих за рамки модели. Этап идентификации может быть как ручным, так и автоматическим процессом в зависимости от сложности совпадений. Когда совпадения выявлены и сделаны явными, эта информация используется в качестве входных данных для второго шага метода: шага спецификации.
Целью этапа спецификации является создание модели координации , которая определяет, как взаимодействуют языки. Ссылки через языковые границы в системе составляют модель координации для этой конкретной системы. Она создается путем сопоставления основных программных артефактов в общее представление. Дополнительная информация, такая как ограничения, специфичные для домена или приложения, также может быть закодирована для обеспечения расширенного представления. Модель координации основана на общей информации, такой как грамматики и ограничения языка, а также на информации, специфичной для приложения, такой как конкретные модели и ограничения, специфичные для приложения. Это означает, что даже если одни и те же языки используются в нескольких продуктах, каждый продукт имеет спецификацию своей собственной уникальной модели координации. Модель координации используется в качестве основы для различных форм рассуждений на последнем этапе метода: этапе приложения.
Целью этапа применения является использование преимуществ координационной модели. Координационная модель позволяет инструментам извлекать три слоя полезной информации. Во-первых, координационная модель может использоваться для обеспечения согласованности на нескольких языках. Координационная модель определяет отношения согласованности, например, как элементы из разных языков могут ссылаться друг на друга. Инструменты могут обеспечивать ссылочную целостность и выполнять статические проверки окончательной системы перед развертыванием. Во-вторых, отношения согласованности используются для навигации, визуализации и отображения сети разных языков в настройке разработки. Эта информация используется для быстрой связи и соотнесения элементов из разных языков и для обеспечения прослеживаемости между разными моделями. В-третьих, на основе отношений согласованности и навигационной информации о том, как связаны элементы, инструменты могут предоставлять руководство, в частности, завершение или помощь. Завершение модели может, например, предоставляться в общем виде через инструменты, специфичные для домена.
Метод координации [1] лучше всего рассматривать как концептуальную структуру, которая предписывает определенный рабочий процесс при работе с несколькими языками. Три последовательных шага, которые составляют этот рабочий процесс, не поддерживаются интегрированным рабочим местом или средой разработки. Основное внимание уделяется расширению существующих сред разработчика для добавления поддержки для (1) идентификации, (2) спецификации и (3) применения. Главным преимуществом этого подхода было то, что разработчики фактически протестировали нашу работу и дали нам обратную связь. Такая оценка метода ценна, поскольку она снижает риск решения чисто гипотетической проблемы. Несколько статей представляют различные шаги метода координации, сообщают об этой оценке и подробно описывают технические аспекты каждого отдельного эксперимента. В целом, результаты были многообещающими: в производственных системах было обнаружено значительное количество ошибок, что привело к конструктивному диалогу с разработчиками о будущих требованиях к инструментам. Процесс разработки, основанный на этих рекомендациях и поддерживаемый инструментами, представляет собой серьезную попытку решить проблему координации и сделать предметно-ориентированное мультимоделирование практическим предложением.