Здравствуйте! В InterSystems Cache есть вполне практичный способ разрабатывать решения без использования интегрированных в неё инструментов. Весь код проекта можно хранить в виде традиционных файлов с исходным кодом, редактировать в любимой среде разработки, индексировать системой контроля версий и одной командой выполнять импорт и компиляцию классов в СУБД Cache. Более того, это предоставляет возможность использовать любые другие внешние инструменты, например, для сборки и препроцессинга кода. В данной статье будет рассмотрен пока что не традиционный для Cache, но достаточно практичный цикл разработки проектов.

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

Описанные ниже способы организации разработки предусматривают следующее:

  1. Весь проект (его исходный код) находится в файловой системе, с произвольной структурой каталогов.
  2. Директория проекта индексируется системой контроля версий Git.
  3. Исходный код классов записан в файлы в “чистом виде”, соблюдается иерархия классов и пакетов.
  4. Работа над проектом ведется целиком в файловой системе, написание кода — в любом внешнем редакторе или IDE.
  5. Есть возможность подключить любые дополнительные инструменты, например, для препроцессинга кода, макроподстановок на этапе сборки, сборки front end и так далее.

В данной статье не будут рассматриваться рутины, CSP и другие файлы. Работу с первыми можно организовать точно так же, как и с классами, потому в случае необходимости, по аналогии с представленным примером в статье, можно реализовать поддержку рутин самостоятельно. CSP-файлы являются просто файлами на диске, и их не нужно импортировать в СУБД Cache, а только перемещать из одной директории в другую по аналогии с приведённым в статье способом.

Описанный в статье способ не требует никаких дополнительных инструментов и платформ, кроме установленной InterSystems Cache версии 2016.2+ (соответственно, Ensemble и других). Дополнительно будет рассмотрена сборка и препроцессинг клиентского кода, выполненная на технологии Node.JS, открытой и свободной для установки на рабочую машину. Данный метод можно выполнить также и с использованием любых других технологий, включая саму СУБД Cache. NodeJS был выбран, потому что для него существует множество уже готовых пакетов для выполнения задач по сборке и препроцессингу проектов.

Мотивация и преимущества


Возникает вопрос, почему бы просто не продолжать разрабатывать в студии, или перейти на “новую студию”, названную Atelier? Какой смысл в том, чтобы не использовать её?

Язык программирования Cache ObjectScript (COS) отличается от других наиболее распространенных языков, таких как C#, Java, JavaScript, Python, Ruby и т.д. тем, что для работы с ним «из коробки» доступны только предлагаемые и поддерживаемые InterSystems инструменты разработки. Есть также и несколько авторских решений, но все они по замыслу не много чем отличаются от программирования в студии. Программы на Cache ObjectScript, как и их исходный код, хранятся непосредственно в самой СУБД Cache. До появления поддержки UDL в InterSystems Cache 2016.2 (или CDL в версии 2013.2 — читайте далее), для того, чтобы извлечь код в исходном виде из БД в файлы нужно было написать немалую программу, и приложить ещё больше усилий, чтобы положить этот код обратно в СУБД Cache. Теперь, когда это возможно всего с помощью одной команды, без труда можно организовать “традиционную” модель разработки решений: редактирование файлов исходного кода — компиляция — получение результата.

До появления ещё не выпущенной в мир Atelier (на момент написания статьи доступна Field Test версия) вести разработку в Linux/MacOS/… было просто невозможно, так как Cache Studio существует только для Windows-платформ. Способ, описанный в статье, совершенно кроссплатформенный.

Проекты редко когда включают исключительно классы Cache. Возникает вопрос о том, как грамотно хранить исходный код всего проекта в одном репозитории системы контроля версий. И по сегодняшний день для проектов на InterSystems Cache применяется своеобразный цикл разработки — фактическая работа над классами в СУБД Cache ведется в студии, а в репозиторий проекта попадает лишь XML представление класса, не предназначенное для каких-либо модификаций. В случае с Atelier цикл разработки, опять же, заточен под работу исключительно в ней самой, без каких-либо взаимодействий с внешними инструментами. Единственное что, в новой IDE появилась явная возможность экспорта/импорта исходного кода в файлы UDL, которые впоследствии могут быть проиндексированы системой контроля версий, но не более того. Нет взаимодействия с внешними инструментами, сборщиками, анализаторами кода, препроцессорами, нет поддержки произвольной структуры проекта, мета-файлов и в целом, будет поддержка только того, что InterSystems сочтет за нужное поддерживать в рамках Atelier и Eclipse.

И наконец самая главная мотивация, принимая во внимание всё вышеперечисленное — это открыть Cache ObjectScript для всего мира. Это может вызвать появление open-source плагинов для поддержки COS самыми популярными IDE, поддерживаемых сообществом, неизбежно грядущую подсветку синтаксиса cls-файлов, в том числе и на GitHub, и множество различных инструментов, например, для анализа или рефакторинга кода.

Введение


В Cache версии 2016.2 появилась поддержка выгрузки исходного кода в UDL (Universal Definition Language) с помощью методов класса $system.OBJ. В данной статье будут рассматриваться работа с методами именно этого класса. В более ранних версиях, начиная с InterSystems Cache 2013.2 выгрузка кода классов в исходном виде также была возможна с использованием методов класса %Compiler.UDL.TextServices. Всё это позволяет загружать и выгружать из Cache физические файлы с исходным кодом классов или рутин в таком виде, в каком их можно просмотреть в студии. Стоит также отметить, что начиная с версии 2016.2 доступно ещё и Atelier REST API для выгрузки определения классов из СУБД Cache.

Так как ранее была возможность экспортировать и импортировать только XML представление классов, что в значительной мере делало исходный код малочитабельным, UDL открывает новые возможности для ведения разработки проектов с продуктами InterSystems (Cache, Ensemble, HealthCare и другие).

Результатом этой статьи будет простейший проект, организованный в файловой системе, и несколько скриптов, которые позволяют одной командой собрать и импортировать его в СУБД Cache.

Подготовка


Предположим, у нас будет, или уже есть проект на InterSystems Cache, который состоит из классов Cache (а также, возможно, рутин и статического front end). Это необходимое и достаточное условие, чтобы начать применять описанный в статье метод разработки к существующему или новому проекту.

Предполагается, что на машине уже есть локально установленная СУБД Cache версии 2016.2+, в которую будет производиться импорт проекта. Для внедрения даного способа разработки в более ранние версии InterSystems Cache (начиная с 2013.2), вам необходимо будет адаптировать предложенные примеры, используя методы %Compiler.UDL.TextServices. Заполнив форму по ссылке, вы можете скачать и установить пробную версию продукта. При установке, укажите кодировку Unicode вместо 8-bit, а все остальные пункты, предложенные мастером установки, оставьте без изменений.

В статье будет применяться система контроля версий Git. Если у вас не установлен Git, его необходимо установить.

Создание проекта


Структура директории проекта-демонстрации имеет следующий вид:

При этом:

  1. Исходный код проекта находится в директории “source”, а в соответствующей поддиректории “cls” находятся дерево пакетов-классов проекта. На скриншоте проекта выше, как пример, находится пакет DevProject, а в нём класс Robot (DevProject.Robot), REST — подпакет с классом внутри (DevProject.REST.Index).
  2. Скрипт import.* импортирует проект в СУБД Cache.

Код проекта, показанного выше, доступен на GitHub. Предлагается клонировать проект на локальную машину, выполнив следующую инструкцию:

git clone https://github.com/ZitRos/cache-dev-project

Проект содержит в себе директорию source/cls, в которой находится привычная иерархия пакетов. Для демонстрации был создан простейший класс, содержащий класс-метод Message, который выводит сообщение “Welcome, Anonymous!”:

Class DevProject.Robot
{

ClassMethod Message(name As %String = "Anonymous")
{
    write "Welcome, ", name, "!"
}

}

Чтобы импортировать этот и другие классы в СУБД Cache, можно воспользоваться одним из следующих способов:

1. Использовать новую среду разработки от InterSystems — Atelier:



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

2. Выполнить в терминале следующую команду:

do $system.OBJ.ImportDir("D:/Path/To/Project/source/cls",,"ck /checkuptodate=all",,1)

Данная команда рекурсивно загружает все файлы из директории D:/Path/To/Project/source/cls в текущее пространство имен, а также компилирует те классы, которые изменились с последнего момента импорта. Таким образом, повторно загруженные классы без изменений не будут занимать время на компиляцию.

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

3. Создать shell-скрипт (batch-скрипт) и вызывать его каждый раз, когда необходимо импортировать классы в InterSystems Cache:

import

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

Скрипт import


Рассмотрим скрипт, который импортирует проект в СУБД Cache. Для того, чтобы это сделать, ему необходимо немного дополнительной информации о вашем экземпляре Cache, а именно место расположения установленной Cache, область, в которую будет производиться загрузка, а также имя пользователя и пароль для входа в систему. Эти данные редактируются напрямую в скрипте. Скрипт рекомендуется хранить в репозитории и делать его локальную копию с актуальными данными при развертывании проекта на локальной машине.

Исходный код скрипта доступен на GitHub для Windows и *nix систем. Всё, что необходимо сделать — единожды отредактировать несколько переменных в скрипте перед началом работы над проектом.

Скрипт запускает исполняемый файл cache.exe, который находится в директории /bin/ установленной СУБД, и передает ему два аргумента — директорию с базой данных и пространство имен. Затем на вход, через терминальный интерфейс InterSystems Cache скрипт отправляет имя пользователя, пароль и несколько простых команд на языке Cache ObjectScript, импортирующих классы и сообщая об успешном импорте или возникшей ошибке.

Таким образом пользователь получает всю необходимую информацию про импорт и компиляцию классов, а также про ошибки, возникшие во время компиляции. Пример вывода при вызове скрипта import.bat:

Importing project...
Node: DESKTOP-ILGFMGK, Instance: ENSEMBLE20162

USER>
Load of directory started on 06/29/2016 22:59:10

Loading file C:\Users\ZitRo\Desktop\cache-dev-project\source\cls\DevProject\Robot.cls as udl
Loading file C:\Users\ZitRo\Desktop\cache-dev-project\source\cls\DevProject\REST\Index.cls as udl

Compilation started on 06/29/2016 22:59:10 with qualifiers 'ck /checkuptodate=all'
Class DevProject.REST.Index is up-to-date.
Compiling class DevProject.Robot
Compiling routine DevProject.Robot.1
Compilation finished successfully in 0.003s.

Load finished successfully.
IMPORT STATUS: OK

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

USER > do ##class(DevProject.Robot).Message()
Welcome, Anonymous!

В случае, если установленная версия СУБД Cache меньше, чем 2016.2, вы получите следующую ошибку:

ОШИБКА #5840: Невозможно импортировать файл '/root/source/cls/Index.cls', т.к. этот тип не поддерживается.

Расширенный пример


Для получения максимальной выгоды от разработки проекта на технологиях InterSystems, попробуем сделать что-то более привлекательное, добавив графический интерфейс и сборку проекта на NodeJS и Gulp. Результатом будет веб-страница, изображение которой показано ниже.



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



Проект состоит из статического клиентского кода (HTML, CSS, JavaScript), класса на сервере, который описывает REST-интерфейс и одного хранимого в базе данных класса.

Клиент с помощью GET-запроса получает список роботов, которые находятся на сервере. Так же, при нажатии на кнопку “Spawn a new robot!” клиент отправляет GET-запрос на сервер, в результате чего создается новый экземпляр класса Robot, и добавляется в отображаемый список.

Техническую реализацию проекта можно посмотреть на GitHub (ветка “extended”). В статье далее внимание будет уделено именно способу разработки подобных проектов.

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

Здесь, в отличие от предыдущего примера, добавлена клиентская часть приложения, которая находится в директории `source/static`, а также организована сборка проекта с помощью Node.JS и Gulp.

Например, помимо прочего кода в проекте присутствуют специальные комментарии. Пример:

<div class="version">v<!-- @echo package.version --></div>

При сборке проекта этот комментарий будет заменён на версию проекта, которая указана в файле package.json. Так же сборщик выполняет минификацию CSS и JavaScript кода, и копирует весь обработанный код в директорию `build`.

В скрипт `import`, в отличии от предыдущего примера, были добавлены следующие изменения:

  1. Перед импортом выполняется сборка проекта.
  2. Файлы для импорта теперь импортируются из директории `build`, так как они проходят через препроцессор.
  3. Осуществляется копирование файлов из директории `build/static` в директорию с CSP-файлами Cache `csp/user`. Таким образом, после импорта приложение сразу становится доступным.

Детальная инструкция по установке и запуску данного проекта находится в описании к репозиторию.

В результате получен проект, который необходимо настроить всего один раз, путем изменения нескольких переменных в файле `import.*`.

Рассмотренный цикл разработки применяется в нескольких проектах — Cache Visual Editor и Cache Web Terminal. В скором времени он может найти применение и в других проектах, включая ваши собственные.

Среда разработки и отладка


Данный метод разработки не предусматривает отладку без InterSystems Cache. Если вы отлаживаете COS-код больше, чем простым логированием в глобалы, вам всё ещё придётся использовать интегрированные в Cache инструменты для отладки.

С описанным методом разработки появляется большое преимущество — возможность использовать любимую среду разработки для написания COS кода, vim или простой блокнот, разрабатывать в Mac OS или *nix на COS так же, как и на любых других языках программирования. Но с другой стороны COS сейчас практически не имеет никакой поддержки за пределами этой СУБД. Это означает, что даже подсветка синтаксиса на данный момент не поддерживается редакторами, не говоря уже об автодополнении. Но всё это в ближайшее время обязано измениться к лучшему, и все вспомогательные средства сегодня уже готовы быть воплощены в жизнь.

А тем временем, пока Cache ObjectScript распространяется, можно воспользоваться элементарной подсветкой синтаксиса по ключевым словам, которую предлагают некоторые IDE, такие как IntelliJ. И она достаточно неплохо справляется со своей задачей:



В случае с IntelliJ можно попробовать это прямо сейчас — вот файл с настройками, который нужно импортировать, используя меню File -> Import Settings. Подсветка авторская, неполная, дополнения приветствуются.

Заключение


Цель данной статьи — привнести в мир разработки на InterSystems Cache что-то новое, представить публике еще один вариант ведения разработки и способствовать распространению Cache ObjectScript как языка программирования в целом. Любые отзывы, идеи и обсуждения приветствуются.

P.S.
Опытный читатель мог заметить, что в случае, если импорт происходит в экземпляр Cache с настройками безопасности minimal, Cache не запрашивает имя пользователя и пароль, и, в результате, если оставить скрипт без изменений, из-за попытки скриптом ввести имя пользователя и пароль не туда, куда ожидалось, дважды возвращается синтаксическая ошибка. Это никак не влияет на работу скрипта, пока имя пользователя или пароль, например, не будет halt.

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

Комментарии (14)


  1. morisson
    10.10.2016 16:59

    Возникает вопрос, почему бы просто не продолжать разрабатывать в студии, или перейти на “новую студию”, названную Atelier? Какой смысл в том, чтобы не использовать её?

    А где собственно можно посмотреть на новую студию Atelier?
    И не нашел ответа, чем принципиально ваш подход лучше и, «почему бы не перейти на студию, названную Atelier».


    1. ZitRo
      10.10.2016 17:10
      +1

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

      Что касается Atelier, доступна Field Test версия. Ссылку добавлю в статью, спасибо.


      1. morisson
        10.10.2016 17:15

        Про то, что работа с файлами — это понятно. В Atelier тоже работа с файлами. Чем подход лучше Atelier?


        1. ZitRo
          10.10.2016 17:35

          Каждый оценивает сам как и где ему удобнее. Данный способ не привязан к конкретной IDE — в статье как пример упомянута работа в Intellij IDEA, описаны преимущества и недостатки такого подхода. Другое дело, подход не привычный для стека технологий InterSystems, потому может и непонятно. Например, я свои проекты (1, 2) уже около полугода разрабатываю этим способом, собираю фронтенд/бекенд одной кнопкой и студию вообще не открываю. После ~2,5 лет разработки в студии я нашёл такой подход для себя гораздо более удобным. Попробуйте — может, найдёте и вы.


          1. morisson
            10.10.2016 17:50

            Спасибо за ответ)

            Другое дело, подход не привычный для стека технологий InterSystems, потому может и непонятно.
            Почему же непривычный. С Ателье как раз все так же, как Intellij IDEA — тоже файлы, тоже одной кнопкой можно все собирать, только плюс отладчик есть. Т.е. для тех, кто любит Eclipse, Atelier будет лучшим вариантом, правильно? Я вот люблю Atom и тоже все разрабатывается в «файлах», для экспорта-импорта используется эта вот штука.


            1. ZitRo
              10.10.2016 18:14
              +1

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


  1. morisson
    10.10.2016 21:45

    Рассмотренный цикл разработки применяется в нескольких проектах — Cache Visual Editor и Cache Web Terminal.

    А вот про Visual Editor можно поподробнее? Пользуетесь вообще? Игрушка или эффективный инструмент получился?


    1. ZitRo
      10.10.2016 22:01

      Инструмент ещё не готов до конца — его разработка была временно приостановлена, но пользоваться уже можно, установка в один импорт. Очень хорошо применяется в образовательных целях или «быстро что-то поправить», почти полноценный веб-редактор, можно код писать. Адаптирован в том числе и под мобильные платформы. В перспективе сделать ещё экраны редактора хранимых данных и конфигурации.


  1. DmitriyMD
    11.10.2016 13:32

    Статья интересная. Но не совсем понятно, как Вы собираетесь привлечь большое количество разработчиков с текущей политикой лицензирования?


    1. intersystems
      11.10.2016 15:23

      А что необычного в политике лицензирования для вендора с проприетарными технологиями?
      Для коммерческого использования можно купить лицензии и платить за поддержку или взять в аренду (поддержка включена).
      Попробовать продукт можно в бесплатной версии.
      Студенты и преподаватели могут получить полнофункциональные версии и лицензии для разработки, обучения здесь, а также бесплатное выездное обучение, гранты и стажировку.
      Есть также программа поддержки стартапов — подать заявку можно здесь. Если стартап нам понравится, мы предоставляем поддержку, лицензии и хостинг с Cache и Ensemble до тех пор, пока проект не выйдет на самоокупаемость.


  1. DmitriyMD
    11.10.2016 15:41

    Есть также программа поддержки стартапов — подать заявку можно здесь. Если стартап нам понравится, мы предоставляем поддержку, лицензии и хостинг с Cache и Ensemble до тех пор, пока проект не выйдет на самоокупаемость.

    Пользуемся медицинской системой на базе Cache.
    При стартапе в прошлом году, когда приобретали её, не знали о программе поддержки…
    Потратили очень значительную сумму на лицензии, проданные нам разработчиком самой медицинской системы.
    При этом ни как не проверить, на сколько цена соответствовала реальности.


  1. AlexeyMaslov
    11.10.2016 17:55
    +3

    Пользуемся медицинской системой на базе Cache.
    При стартапе в прошлом году...
    Обычно стартапами называют новые разработки, а не новые внедрения; поинтересуйтесь у поставщика вашей МИС, когда состоялся их стартап. Скорее всего, в вашем случае действовала обычная схема «поставщик решения<->потребитель решения», в рамках которой вы получили СУБД, а не приобрели её отдельно для собственных разработок (которые, к слову, не каждый поставщик будет приветствовать; наша компания здесь, пожалуй, исключение).

    P.S. Я сотрудник не InterSystems, а как раз-таки компании-поставщика МИС «qMS» СП.АРМ.


  1. morisson
    18.10.2016 13:23

    А если потребуется удалить или переименовать файл — как вы поступаете?
    Какой процесс в этом случае?
    Удаляете этот класс в сервере разработки вручную тоже?


    1. ZitRo
      18.10.2016 14:33

      Хм. Да, в таком случае только вручную удалять, или писать свой код для очистки области от классов, которых нет в исходниках. Лично в моей практике удаление классов ещё не встречалось.

      В каких-то случаях может и имеет смысл написать скрипт, который бы из, например, истории Git'а вытягивал бы список удалённых классов, и удалял их из СУБД, но думаю более элегантным и простым решением будет удаление отсутствующих при сборке проекта классов в пределах определённого пакета или области.