Pull to refresh
55.9

Пишем REST-приложение на Delphi

Level of difficultyEasy
Reading time7 min
Views7K

Привет, Хабр!

Я Ануар, работаю в GlowByte и профессионально играю на нервах (шутка ?).

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

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

Задача

Одним прекрасным вечерком «приплыла» задача реализации распределенного десктопного простенького приложения, работающего с единой базой данных (БД), проще говоря, программа для MS Windows, работающая в офисах в разных городах с едиными данными. Сразу в голове всплыл стандартный шаблон трехуровневой архитектуры (three-tier) программного обеспечения (ПО):

Трехуровневая архитектура ПО
Трехуровневая архитектура ПО

Исходя из первоначальных вводных и пришедших мыслей на скорую руку, отчетливо вырисовывалась следующая картина. Приложение простенькое и десктопное – сразу вспомнилась давно забытая IDE Delphi, в которой за очень короткое время можно реализовать довольно неплохой интерфейс (VCL-приложение Windows). А раз приложение распределенное (возможность работы с данными пользователям с разных мест), то, значит, БД должна быть доступна через Интернет.

Итак: десктопное приложение реализовано на Delphi, БД, размещенная в сети Интернет... Сразу на ум пришли мысли об аренде хостинга и о том, что должна быть обеспечена безопасность данных. Поэтому БД должна принимать только локальные подключения. Но как связать приложение и БД, учитывая вышеописанные вводные?

Конечно же, с помощью REST API, тем более опыт уже имелся при реализации бэкенда внутреннего продукта GlowByte, реализующего RESTfull API. Учитывая, что имеющиеся на рынке стандартные конфигурации хостинга включают в себя PHP и MySQL,  реализация бэкенда по архитектуре REST и взаимодействия с БД только через локальные подключения не представляла особой сложности. При этом помним, что реализация и стоимость владения должны быть низкими.

Архитектура разрабатываемого приложения виделась следующим образом:

Архитектура разрабатываемого ПО
Архитектура разрабатываемого ПО

В качестве протокола обмена информацией был выбран HTTP, данные решено передавать в формате JSON.

Помня, что мы из GlowByte, а в GlowByte работают высококлассные специалисты с высоким уровнем компетенций (уж позвольте мне минутку самопиара ?), вышеописанная задача виделась решаемой за пару дней. И, подчеркну вновь, решение должно было быть реализовано с минимальными вложениями и минимальной стоимостью владения, что накладывало определенные ограничения при реализации.

Бэкенд

Первым этапом была спроектирована база данных разрабатываемого ПО и определены эндпоинты REST API.

На втором этапе разработали бэкенд на PHP без использования фреймворков и каких-то сложных схем, которые бы повлияли на время разработки и стоимость владения. Виделась реализация API в виде единой точки входа. 

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

Помня, что все лучшее уже давно придумано за нас, и держа в голове, что существующие паттерны (шаблоны) позволяют писать более читабельный код, а процесс разработки – делать комфортным, разграничивая работу frontend- и backend-разработчиков, мы начали рыться в своей голове, вспоминая, на что похоже наше решение. Немного поразмыслив, мы поняли, что оно как нельзя лучше вписывалось в архитектурный паттерн API-шлюз (API Gateway). 

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

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

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

В процессе поиска информации в Интернете было принято решение реализовать архитектуру бэкенда самим на основе имеющейся информации (например, статьи) и собственных знаний.

С учетом всего вышеизложенного архитектура бэкенда стала выглядеть следующим образом:

Архитектура бэкенда
Архитектура бэкенда

Коротко поясню, как это работает. Поступающие запросы необходимо обработать на сервере (бэкенде). Запросы на сервере попадают в index.php, где проверяются на соответствие требованиям. Если поступивший запрос соответствует предъявляемым критериям, он передается в apiEngine.php, который его маршрутизирует (переключает) на конкретный сервис либо предоставляет соответствующий ответ.

Таким образом, если нашу архитектуру переложить на паттерн API Gateway, то слой Gateway состоит из index.php и apiEngine.php, слой микросервисов –  из классов, наследованных от apiBaseClass.php. В apiBaseClass.php реализован общий функционал, например, подключение к БД.

С бэкендом разобрались, настала пора приступать к разработке десктопного приложения. Как мы уже сказали, делать его мы хотели на Delphi.

Квест

Это был третий и самый интересный этап – непосредственно разработка программы в IDE Delphi с использованием разработанного нами REST API.

Разработка интерфейса программы не вызвала сложностей, благо в IDE Delphi имеются удобные функции drag-and-drop визуальных компонентов и удобный интерфейс их настройки.

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

Но не тут-то было.  Часовой “гуглеж” показал, что эта тема мало освещена в контексте использования Delphi. Очень много информации по традиционным технологиям, таким как DataSnap или DataAbstract. Но так как вводной установкой у нас была быстрая разработка с использованием стандартного хостинга, то все хорошо описанные технологии нам не подходили по причине того, что серверная часть предполагала реализацию на ОС MS Windows либо была очень специфична и не позволяла реализовать на обычном хостинге. Это противоречило нашим условиям легкости разработки, развертывания и стоимости владения. По сути, на данном этапе мы искали возможность построения простого REST-клиента в IDE Delphi.

В сети много информации о классических реализациях (DataSnap, DataAbstract, kbmMW, RemObjects SDK, Indy, RAD Server, FireDAC и т. д.) с «поднятием» своей специфичной серверной части, но подробной информации, как реализовать и какие компоненты использовать при реализации трехзвенного приложения, использующего REST API на Delphi, нет.

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

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

Так, например, было с Indy idHTTP: большинство компонентов не подходили именно по причине того, что требовали большого объема программирования и не было единой точки подключения.

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

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

REST-клиент

Для построения простого REST-клиента достаточно следующих компонентов: TRESTClient, THTTPBasicAuthenticator, TRESTRequest, TRESTResponse, TRESTResponseDataSetAdapter и TClientDataSet.

Краткое описание:
  • TRESTClient – компонент для создания и управления HTTP-соединением с сервером REST API;

  •   THTTPBasicAuthenticator – компонент, обеспечивающий базовую аутентификацию HTTP, хранящий в заголовке REST-запроса логин и пароль пользователя в формате base64;

  •   TRESTRequest – компонент для формирования REST-запроса к API;

  •   TRESTResponse – компонент ответа, содержащий в себе код ответа HTTP, сообщение об ошибке (если имеется) и возвращенные данные;

  •   TRESTResponseDataSetAdapter – компонент для преобразования и подготовки к отображению полученных данных;

  •   TClientDataSet – компонент хранения в памяти набора данных.

С учетом вышеописанного архитектура нашего VCL-приложения стала выглядеть следующим образом:

Архитектура приложения
Архитектура приложения

Эпилог

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

Чуть позже оставлю ссылку на GitHub с проектом, реализующим операции CRUD, используя GET- и POST-запросы (интерфейс реализован на Delphi в виде десктопного приложения, бэкенд – на PHP без использования каких-либо фреймворков). Оговорюсь, что код требует ревью и не учитывает современные концепции, подходы и шаблоны (паттерны) ООП для PHP, это тоже тема отдельной статьи.

Tags:
Hubs:
Total votes 13: ↑12 and ↓1+12
Comments52

Articles

Information

Website
glowbyteconsulting.com
Registered
Founded
2004
Employees
1,001–5,000 employees
Location
Россия
Representative
Снежана Шибаева