Что позволяет делать лицензия разработчика enterprise позволяет делать кроссплатформенные приложения
Перейти к содержимому

Что позволяет делать лицензия разработчика enterprise позволяет делать кроссплатформенные приложения

  • автор:

Enterprise проекты: что нужно знать разработчику?

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

Приветствую! Меня зовут Андрей Степанов, я CTO во fuse8. Мне интересно знакомиться с опытом коллег по цеху и делиться своим. В сфере я уже больше 20 лет. В этой статье – наблюдения и рекомендации для интересующихся и тех, кто еще не трогал enterprise, но очень хотел бы.

Предположим, вы изучили язык, фреймворк, инструменты, получили опыт разработки и теперь стоите на распутье:

Путь 1 enterprise разработка: микросервисная архитектура, СУБД, очереди, gRPC и проч.

Путь 2 геймдев: Unity.

Путь 3 CMS (content management system) и DXP (digital experience platform): Kentico, Sitecore, Optimizely.

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

Что такое enterprise

Приходит бизнес-заказчик и говорит: «Сделайте мне продукт!». Заказчику нужно изобрести «собственный велосипед» для выполнения конкретной бизнес-задачи. Такой «велосипед» – это цельная система, и у нее есть особенности при разработке:

Вот такой велосипед!

  • Написание кода, который будет поддерживаться многие годы (ООП, SOLID, GOF-паттерны, Unit-тесты и т.д.);
  • Сложная бизнес-логика, которая часто меняется;
  • Использование проверенных фреймворков/библиотек;
  • Написание тестов;
  • Код, доступный для рефакторинга, и создания документации по продукту на его основе;
  • Регулярность code review.

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

Enterprise проект — это всегда вопрос про деньги. Мы не можем использовать непроверенные решения.

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

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

Из чего состоит типичное энтерпрайз приложение

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

Логирование. Недостаточно просто настроить его, нужно подобрать сервис, который будет сохранять логи. Без логирования зачастую невозможно разобраться в проблемах на проде, невозможно восстановить какие-то артефакты.

Метрики и хелсчеки. Мы не можем, запустив проект, отправить уже созданную его часть в свободное плавание, пока сидим и разрабатываем следующую. Сервис может и упасть, а мы этого не узнаем. Падения – это всегда финансовые потери для бизнеса, а их быть не должно. Чтобы их избежать, нужно превентивно, на основании бизнес-метрик, понять, что идет не так, и исправить ситуацию.

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

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

Внутри enterprise приложения должно быть настроено эффективное общение между сервисами: задачи должны выполняться своевременно, нагрузка – распределяться равномерно. В этом помогут очередь, шина, или планировщик задач.

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

На проекте могут быть DevOps-специалисты, но это не значит, что ответственность за процесс деплоя будет лежать только на них.

Если у нас монолит, мы можем кэшировать данные в памяти. Если микросервисы и для каждого отдельного сервиса могут подниматься несколько инстансов – кэшировать в памяти каждого не выйдет. Не понятно как это потом синхронно обновлять. В таких случаях на помощь приходит распределенный кэш: отдельно поднимается сервис, который хранит определенные данные и предоставляет быстрый доступ к ним. Как правило, это key-value хранилище.

Отдельные файловые хранилища. Зачем? За тем, что хранить файлы просто на диске – не удобно. Хранить файлы в базе данных – проблемно. Поэтому зачастую в enterprise проектах используются отдельные файловые хранилища. Это еще один инфраструктурный сервис.

Для задач, связанных с отображением данных, нужно подключить визуалайзер. Так удобнее следить за метриками, смотреть логи, отслеживать хелс-чеки. Мы, например, используем Grafana, чтобы выводить данные и присылать нотификации. Grafana позволяет все собранные данные отобразить так, чтобы было удобно их совокупно анализировать.

Отдельный блок – code style и анализаторы. Когда команда уже большая или среднего размера, каждый может писать код по-своему. Это порой вызывает споры на код-ревью. Поэтому зачастую на enterprise проектах используются анализаторы, которые помогают автоматически находить проблемы, потенциальные ошибки и проверять единый code style.

Какие навыки нужны для успешного решения задач энтерпрайз-проекта

Базы данных:

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

Более продвинутый уровень:

  • План запроса;
  • статистика;
  • нормальные формы;
  • deadlock;
  • триггеры;
  • внутреннее устройство фильтрации и соединения.

Понятное дело, что нам нужно уметь самим создавать таблички, продумывать их архитектуру, понимать все типы связи, ограничений и так далее. Это must-have.

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

Транзакции. Многие запросы нужно делать в рамках транзакций, чтобы не получились неконсистентные данные в БД.

Что нужно, чтобы продумать архитектуру enterprise приложения

  • DDD;
  • SOLID;
  • GOF-паттерны;
  • REST;
  • чистая архитектура (гексагональная архитектура);
  • CI/CD;
  • паттерны, используемые в микросервисной архитектуре.

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

Принципы SOLID с точки зрения архитектуры сильно помогают при разработке.

GOF-паттерны нужны, чтобы писать более расширяемое приложение, более универсальное. Его легко можно будет дорабатывать, что нам очень важно.

REST. Придется делать много интеграций со сторонними сервисами, общение между которыми зачастую реализуется через REST. Еще может понадобиться реализация REST API для приложения, чтобы с ним могли общаться другие сервисы, например spa.

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

Области знаний C# и .Net Framework для enterprise

Инфраструктура enterprise приложения

  • Базы данных (MS SQL, PostgreSQL, MongoDB)
  • Логирование (ELK stack, Grafana Loki)
  • Отслеживание ошибок (Sentry)
  • Сбор метрик и хелсчеков (Prometheus)
  • CI/CD (Docker, Kubernetes, TeamCity, GitLab CI/CD)
  • Очереди, шина данных, планировщик задач (RabbitMQ, Kafka, Hangfire)
  • Файловое хранилище (Minio)
  • Распределённый кэш (Redis)
  • Отображение метрик, логов (Grafana)

Дополнительно к этому всему неплохо бы знать, как работают разные инструменты для поиска проблем в приложении. Например, анализатор памяти (DotMemory), анализатор перфоманса (DotTrace), анализатор запросов в БД (MS SQL Server Profiler).

Микросервисы – модно, молодёжно?

Это кот нашего разработчика Феди

Может показаться, что микросервисы – это классно и круто, что надо каждое новое приложение писать на микросервисах. На самом деле и здесь есть нюансы.

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

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

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

Сбор логов усложняется. Опять же, у нас нет одного лога у одного предложения, как в монолите. Нужно собирать логи с разных сервисов. Возможно, их придется стандартизировать для удобства отображения и просмотра.

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

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

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

За что любят enterprise разработку

  • Возможность использовать самый последний стек технологий.
  • Возможность совершенствовать свой код на протяжении долгого времени.
  • Полное погружение в доменную область бизнеса.
  • Работа с разными библиотеками и инфраструктурными сервисами.
  • Самостоятельное проектирование БД и архитектуры приложения.
  • Хорошая документация по проекту.
  • Налаженный процесс полного цикла реализации задач.

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

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

Просто обновившись, можно оптимизировать использование памяти или увеличить перфоманс. Это удобно.

Вы вольны решать, что будете использовать в проекте: какие именно библиотеки, инфраструктурные сервисы и прочее. Иногда можно их поменять, если совсем не подошло изначально выбранное решение. Получается, что разработчик будет владеть разноплановыми технологиями. Многим как раз нравятся такие проекты за то, что на них можно расширить свой кругозор.

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

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

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

Но не без трудностей

Когда весь день правили баги.

  • Горящие баги на проде, жtсткие сроки реализации фич.
  • Нужно обладать хорошими знаниями по C#, .Net, базам данных.
  • Сложный выбор подходящей под задачу библиотеки или инфраструктурного сервиса.
  • Без своевременного рефакторинга приложение превратится в большой ком грязи.
  • Сложный онбординг нового сотрудника.
  • Свои «велосипеды».

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

По-хорошему, чтобы попасть в энтерпрайс команду, нужно обладать хорошими знаниями по базам данных, фреймворку .Net, языку C#, чтобы не совершать элементарных ошибок. Если допускать ошибки в каких-то базовых вещах – неправильно использовать коллекции, асинхронный код – будут блокеры в разработке и расход бюджета впустую.

Необходимость подбора библиотеки или инфраструктурного сервиса – это и плюс, и минус одновременно. С одной стороны, у вас развязаны руки: вы можете попробовать то, что сами хотите. С другой – если вы выберете что-то не то, потом это будет сложно заменить. Нужно уметь думать превентивно.

Вся ответственность за неправильно выбранный сервис или библиотеку лежит на вас. Это и минус.

Рефакторинг. Нельзя написать проект и потом его только дописывать, не возвращаясь к уже реализованным частям. Постоянно придется рефакторить отдельные участки кода или переписывать их по разным причинам. Требования к продукту по мере его развития могут меняться. Поэтому если не будет своевременного рефакторинга, через несколько лет придется просто выбросить это приложение и написать его с нуля. А это очень сложная задача, когда у тебя есть текущее работающее приложение на проде.

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

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

Что почитать по теме

CLR via C#. Программирование на платформе Microsoft .NET Framework 4.5

Паттерны объектно-ориентированного проектирования

Э. Гамма, Р. Хелм, Р. Джонсон, Дж. Влиссиденес

Чистая архитектура. Искусство разработки программного обеспечения

Принципы юнит-тестирования

Микросервисы. Паттерны разработки и рефакторинга

Реализация методов предметно-ориентированного проектирования

За содействие в подготовке материала отдельная благодарность ведущему.NET разработчику Федору Киселеву.

  • enterprise
  • .net core
  • enterprise architecture
  • энтерпрайз
  • разработка программного обеспечения
  • разработка приложений
  • чистый код

Что позволяет сделать лицензия разработчика Enterprise?

Что позволяет сделать лицензия разработчика Enterprise?

Проверенный ответ:

Лицензия разработчика Enterprise предоставляет ряд преимуществ и возможностей для разработчиков программного обеспечения. Рассмотрим основные функциональные возможности этой лицензии:

1. Расширенные функции разработки: Лицензия Enterprise позволяет работать с различными инструментами и технологиями разработки, такими как Visual Studio, Visual Studio Code и Xamarin. Эти инструменты позволяют создавать разнообразные приложения для различных платформ (Windows, iOS, Android), веб-приложения, игры, а также проводить разработку непрерывного процесса интеграции и развертывания (CI/CD).

2. Доступ ко всему спектру возможностей платформы: С лицензией Enterprise вы получаете доступ ко всем расширенным возможностям и библиотекам платформы разработки Microsoft. Это включает в себя доступ к более широкому набору инструментов, библиотек управления данными (Entity Framework), а также интегрированная разработка с облачными платформами Azure.

3. Написание кросс-платформенных приложений: Лицензия Enterprise позволяет использовать инструменты и технологии для создания кросс-платформенных приложений. Например, платформа Xamarin позволяет разработчикам создавать мобильные приложения, которые могут работать на различных операционных системах, таких как iOS и Android, используя общий код на языке программирования C#.

4. Инструменты для улучшения процесса разработки: Лицензия Enterprise предоставляет доступ к инструментам, которые помогают улучшить процесс разработки и управление проектами. Например, инструменты тестирования и отладки помогают выявить и исправить ошибки в коде, а инструменты анализа производительности позволяют оптимизировать работу приложений.

5. Поддержка и обновления: С лицензией Enterprise вы получаете поддержку от разработчиков Microsoft и доступ к обновлениям и исправлениям ошибок. Это позволяет быть в курсе последних технологических трендов и обеспечивает безопасность и стабильность вашего проекта.

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

C++ Enterprise Edition

c++ee

Удивительно, но за все время моей работы в IT, я ни разу не слышал, чтобы кто-то говорил «enterprise edition» относительно языка программирования, кроме как для Java. Но ведь приложения для корпоративного сегмента люди пишут на многих языках программирования, и сущности, которыми оперируют программисты, если не идентичны, то схожи. И для c++ в частности, я бы хотел заполнить пробел enterpr’айзности, хотя бы рассказав об этом.

Применительно к C++, «enterprise edition» — это подмножество языка и библиотек, позволяющее «быстро» разрабатывать [кроссплатформенные] приложения для слабосвязных модульных систем с распределенной и/или кластерной архитектурой и с прикладной бизнес-логикой и, как правило, высокой нагрузкой.

Чтобы продолжить наш разговор, в первую очередь, необходимо ввести понятия приложения, модуля и плагина

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

Все приложения, выполняя свою уникальную работу, как правило нуждаются в общесистемных механизмах, таких как, доступ к данным (СУБД), обмен информацией через общую шину (JMS), исполнение распределенных и локальных сценариев с сохранением консистентности (Транзакции), обработка запросов, приходящих, например, по протоколу http(s) (fastcgi) или через websocket’ы и т.д… Каждое приложение должно иметь возможность оркестровки своих модулей (OSGI), а в распределенной системе должна быть возможность оркестровки приложений.

Пример схемы распределенной слабосвязной системы

system

Приложение

Пример схемы «корпоративного» серверного приложения.

application

Общее определение приложению, я уже дал, так что разберемся, что же сейчас есть в мире C++ для имплементации этого понятия. Первыми показали реализацию приложения графические фреймворки, такие как Qt и GTK, но их версии приложения изначально предполагали, что приложение — это графическое «окно» со своим контекстом и только спустя время появилось общее видение приложения, в том числе и как системной службы, например, qtservice. Но тащить условно графический фреймворк для сервисной задачи не очень хочется, так что посмотрим в сторону неграфических библиотек. И первым на ум приходит boost… Но к сожалению в списке официальных библиотек нет Boost.Application и ей подобных. Есть отдельный проект Boost.Application. Проект весьма интересный, но, на мой взгляд, многословный, хотя идеология boost соблюдена. Вот пример приложения от Boost.Application

#define BOOST_ALL_DYN_LINK #define BOOST_LIB_DIAGNOSTIC #define BOOST_APPLICATION_FEATURE_NS_SELECT_BOOST #include #include #include using namespace boost; // my application code class myapp < public: myapp(application::context& context) : context_(context) <>void worker() < // . while (st->state() != application::status::stopped) < boost::this_thread::sleep(boost::posix_time::seconds(1)); if (st->state() == application::status::paused) my_log_file_ > // param int operator()() < // launch a work thread boost::thread thread(&myapp::worker, this); context_.find()->wait(); return 0; > bool stop() < my_log_file_ private: std::ofstream my_log_file_; application::context& context_; >; int main(int argc, char* argv[]) < application::context app_context; // auto_handler will automatically add termination, pause and resume (windows) // handlers application::auto_handlerapp(app_context); // to handle args app_context.insert( boost::make_shared(argc, argv)); // my server instantiation boost::system::error_code ec; int result = application::launch(app, app_context, ec); if (ec) < std::cout " return result; >

В приведенном примере определяется приложение myapp со своим основным рабочим потоком worker и механизм запуска этого приложения.
В качестве дополнения приведу аналогичный пример из фреймворка pocoproject

#include #include #include "Poco/AutoPtr.h" #include "Poco/Util/AbstractConfiguration.h" #include "Poco/Util/Application.h" #include "Poco/Util/HelpFormatter.h" #include "Poco/Util/Option.h" #include "Poco/Util/OptionSet.h" using Poco::AutoPtr; using Poco::Util::AbstractConfiguration; using Poco::Util::Application; using Poco::Util::HelpFormatter; using Poco::Util::Option; using Poco::Util::OptionCallback; using Poco::Util::OptionSet; class SampleApp : public Application < public: SampleApp() : _helpRequested(false) <>protected: void initialize(Application &self) < loadConfiguration(); Application::initialize(self); >void uninitialize() < Application::uninitialize(); >void reinitialize(Application &self) < Application::reinitialize(self); >void defineOptions(OptionSet &options) < Application::defineOptions(options); options.addOption( Option("help", "h", "display help information on command line arguments") .required(false) .repeatable(false) .callback(OptionCallback(this, &SampleApp::handleHelp))); > void handleHelp(const std::string &name, const std::string &value) < _helpRequested = true; displayHelp(); stopOptionsProcessing(); >void displayHelp() < HelpFormatter helpFormatter(options()); helpFormatter.setCommand(commandName()); helpFormatter.setUsage("OPTIONS"); helpFormatter.setHeader( "A sample application that demonstrates some of the features of the " "Poco::Util::Application class."); helpFormatter.format(std::cout); >int main(const ArgVec &args) < if (!_helpRequested) < logger().information("Command line:"); std::ostringstream ostr; logger().information(ostr.str()); logger().information("Arguments to main():"); for (const auto &it : args) < logger().information(it); >> return Application::EXIT_OK; > private: bool _helpRequested; >; POCO_APP_MAIN(SampleApp)

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

Слабосвязность, модули и плагины.

Слабосвязность в «корпоративной» системе — это возможность быстрой и безболезненной подмены тех или иных механизмов. Это касается как модулей внутри приложения, так и самих приложений, как реализаций, например, микросервисов. Что же у нас есть, с точки зрения C++. С модулями все плохо, хоть они и реализуют интерфейсы, но живут внутри «скомпилённого» приложения, так что быстрой подмены не будет, но на помощь приходят плагины! С помощью динамических библиотек можно не только организовать быструю подмену, но и одновременную работу двух разных версий. Есть еще целый мир «удаленного вызова процедур» он же RPC. Механизмы поиска реализаций интерфейсов в купе с RPC, породили нечто похожее на OSGI из мира Java. Здорово иметь поддержку этого в экосистеме C++ и она есть, вот пара примеров:

Пример модуля для «сервера приложения» POCO OSP

#include "Poco/OSP/BundleActivator.h" #include "Poco/OSP/BundleContext.h" #include "Poco/ClassLibrary.h" namespace HelloBundle < class BundleActivator: public Poco::OSP::BundleActivator < public: void start(Poco::OSP::BundleContext::Ptr pContext) < pContext->logger().information("Hello, world!"); > void stop(Poco::OSP::BundleContext::Ptr pContext) < pContext->logger().information("Goodbye!"); > >; > // namespace HelloBundle POCO_BEGIN_MANIFEST(Poco::OSP::BundleActivator) POCO_EXPORT_CLASS(HelloBundle::BundleActivator) POCO_END_MANIFEST

Пример модуля для «серврера приложения» Apache Celix

#include "Bar.h" #include "BarActivator.h" using namespace celix::dm; DmActivator* DmActivator::create(DependencyManager& mng) < return new BarActivator(mng); >void BarActivator::init() < std::shared_ptrbar = std::shared_ptr>; Properties props; props["meta.info.key"] = "meta.info.value"; Properties cProps; cProps["also.meta.info.key"] = "also.meta.info.value"; this->cExample.handle = bar.get(); this->cExample.method = [](void *handle, int arg1, double arg2, double *out) < Bar* bar = static_cast(handle); return bar->cMethod(arg1, arg2, out); >; mng.createComponent(bar) //using a pointer a instance. Also supported is lazy initialization (default constructor needed) or a rvalue reference (move) .addInterface(IANOTHER_EXAMPLE_VERSION, props) .addCInterface(&this->cExample, EXAMPLE_NAME, EXAMPLE_VERSION, cProps) .setCallbacks(&Bar::init, &Bar::start, &Bar::stop, &Bar::deinit); >

Хочется отметить, что в распределенных слабосвязных системах необходимо иметь механизмы обеспечивающие транзакционность операций, но на текущий момент для C++ ничего подобного нет. Т.е. как нет возможности внутри одного приложения выполнить запрос к базе данных, файлу и esb в рамках одной транзакции, так и нет такой возможности для распределенных операций. Безусловно все можно написать, но чего-то обобщённого нет. Кто-то скажет, что есть software transactional memory , да, конечно, но это лишь облегчит написание транзакционных механизмов собственными силами.

Инструментарий

Из всего множество вспомогательных инструментов хочу выделить сериализацию и DSL, т.к. их наличие позволяет реализовать многие другие компоненты и сценарии.

Сериализация

Сериализация — процесс перевода какой-либо структуры данных в последовательность битов. Обратной к операции сериализации является операция десериализации (структуризации) — восстановление начального состояния структуры данных из битовой последовательности wikipedia. В контексте C++ важно понимать, что на сегодняшний день нет возможности сериализации объектов и передачи их в другую программу, которая об этом объекте ранее ничего не знала. Под объектом в этом случае я понимаю реализацию некоего класса с полями и методами. Поэтому выделю два основных подхода, применяемые в мире C++ :

  • сериализация в бинарный формат
  • сериализация в формализованный формат

В литературе и интернете часто встречается разделение на бинарный и текстовый формат, но я считаю такое разделение не совсем правильным, например, MsgPack не сохраняет информацию о типе объекта, соответственно, отдается контроль за правильным отображением программисту и формат MsgPack — бинарный. Protobuf, напротив, сохраняет всю метаинформацию в промежуточное представление, что позволяет использовать его между разными языками программирования, при этом, Protobuf тоже бинарный.
Итак процесс сериализации, зачем он нам нужен. Для раскрытия всех нюансов, нужна еще одна статья, я постараюсь объяснить на примерах. Сериализация позволяет, оставаясь в терминах языка программирования, «упаковывать» программные сущности (классы, структуры) для передачи их по сети, для персистентного хранения, например, в файлах и других сценариев, которые, без сериализации, заставляют нас придумывать собственные протоколы, учитывать аппаратную и программную платформу, кодировку текста и.т.д.
Приведу пару примеров библиотек для сериализации:

DSL

Domain Specific Language — язык программирования для вашей предметной области. Действительно, когда мы занимаемся автоматизацией какого-то предприятия, то мы сталкиваемся с предметной областью заказчика и все бизнес-процессы описываем в терминах предметной области, но как только дело доходит до программирования, то программисты вместе с аналитиками занимаются отображением понятий бизнес-процессов в понятия фреймворка и языка программирования. И если бизнес-процессов не определенное количество, а предметная область определена достаточно строго, то имеет смысл создать свой DSL, для имплементации большей части существующих сценариев и добавления новых. В мире с++ не так много возможностей «быстрой» реализации своего DSL. Есть, конечно, механизмы встраивания lua, javascript и других языков программирования в C++-программу, но кому нужны уязвимости и потенциально неконтролируемый движок исполнения «всего» ?! Так что разберем те инструменты, что позволяют делать DSL самому.

Библиотека Boost.Proto как раз создана для создания собственных DSL, это её прямое предназаначение, вот пример

#include #include #include using namespace boost; proto::terminal< std::ostream & >::type cout_ = < std::cout >; template < typename Expr >void evaluate( Expr const & expr ) < proto::default_context ctx; proto::eval(expr, ctx); >int main()

Flex и Bison используются для генерации лексеров и парсеров придуманных Вами грамматик. Синтаксис не простой, но задачу решает эффективно.
Пример кода для генерации лексера

/* scanner for a toy Pascal-like language */ % < /* need this for the call to atof() below */ #include %> DIGIT [0-9] ID [a-z][a-z0-9]* %% + < printf( "An integer: %s (%d)\n", yytext, atoi( yytext ) ); >+"."* < printf( "A float: %s (%g)\n", yytext, atof( yytext ) ); >if|then|begin|end|procedure|function < printf( "A keyword: %s\n", yytext ); > printf( "An identifier: %s\n", yytext ); "+"|"-"|"*"|"/" printf( "An operator: %s\n", yytext ); "<"[^>\n]*">" /* eat up one-line comments */ [ \t\n]+ /* eat up whitespace */ . printf( "Unrecognized character: %s\n", yytext ); %% main( argc, argv ) int argc; char **argv; < ++argv, --argc; /* skip over program name */ if ( argc >0 ) yyin = fopen( argv[0], "r" ); else yyin = stdin; yylex(); >

А еще, существует спецификация SCXML — State Chart XML: State Machine Notation for Control Abstraction, описание конечного автомата в XML-подобной разметке. Это не совсем DSL, но тоже удобный механизм автоматизации процессов без программирования. Отличная имплементация есть у Qt SCXML. Есть и другие рализации, но они не такие гибкие.
Это пример FTP клиента в SCXML нотации, пример взят с сайта Qt Documentation

А так это выглядит в визуализаторе SCXML

Ftp-client-scxml

Доступ к данным и Интеграция

Это, пожалуй, одна из самых «наболевших» тем в мире с++. Мир данных для с++ разработчика всегда связан с необходимостью уметь отображать их на сущности языка программирования. Строку в таблице — в объект или структуру, json — в класс и так далее. В отсутствие рефлексии — это огромная проблема, но мы, с++-ники, не отчаиваемся и находим различные выходы из ситуации. Начнем с СУБД.

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

Все они хороши, но заставляют помнить о нюансах отображения данных из БД в объекты и структуры с++, плюс эффективность SQL-запросов сразу ложиться на ваши плечи.
Следующими примерами будут ORM на C++. Да такие есть! И кстаи, SOCI, поддерживает механизмы ORM, через специализацию soci::type_conversion, но её я намеренно не включил, так как это не прямое её предназначение.

  • LiteSQL C++ — ORM, позволяющий взаимодействовать с СУБД SQLite3, PostgreSQL, MySQL. Эта библиотека требует от программиста предварительного оформить xml-файлы с описанием объектов и отношений, чтобы, с помощью litesql-gen сгенерировать дополнительные исходники.
  • ODB от Code Synthesis — очень интересная ORM, позволяет оставаться в рамках C++, не использую промежуточные файлы описания, вот небольшой пример :
#pragma db object class person < // . private: friend class odb::access; person () <>#pragma db id string email_; string name_; unsigned short age_; >; // . odb::sqlite::database db ("people.db"); person john ("john@doe.org", "John Doe", 31); odb::transaction t (db.begin ()); db.persist (john); typedef odb::query person_query; for (person& p: db.query (person_query::age < 30)); cerr  
  • Wt++ — большой фреймворк, о нем можно вообще отдельную статью написать, тоже содержит ORM, умеющий взаимодействовать с СУБД Sqlite3, Firebird, MariaDB/MySQL, MSSQL Server, PostgreSQL и Oracle.
  • Отдельно хочется упомянуть ORM над sqlite sqlite_orm и hiberlite. Так как sqlite встраиваемая СУБД, а ORM для него проверяет запросы, да и вообще все взаимодействие с БД, в compile-time, то инструмент становится очень удобным для быстрого развертывания и прототипирования.
  • QHibernate — ORM для Qt5 с поддержкой Postgresql. Пропитан идеями hibernate от java.

Хоть и интеграцию через СУБД считают "интеграцией", я предпочту оставить это за скобками и перейти к интеграции через протоколы и API.

  • RPC — remote porocess call, всем известная техника взаимодействия "клиента" с "сервером". Как и в случае c ORM, главная трудность — это написание/генерация различных вспомогательных файлов для связывания протокола с реальными функциями в коде. Я намеренно не буду упоминать различные RPC, реализованные непосредственно в операционной системе, а сосредоточусь на кроссплатформенных решениях.
    • grpc — фреймворк от Google для удалённого вызова процедур, весьма популярный и эффективный фреймворк от google. В основе своей использует google protobuf, его я упоминал в разделе сериализация, поддерживает множество языков программирования, но в корпрративной среде пока новичок.
    • json-rpc — RPC, где в качестве протокола используется JSON, хороший пример реализации — это библиотека libjson-rpc-cpp, вот пример файла описания :
    [ < "name": "sayHello", "params": < "name": "Peter" >, "returns" : "Hello Peter" >, < "name" : "notifyServer" >]

    На основе этого описания генерятся клиентский и серврерный код, который можно использовать в своем приложении. Вообще есть спецификация для JSON-RPC 1.0 и 2.0. Так что вызвать функцию из web-приложения, а обработать в C++ труда не составит.

    • XML-RPC и SOAP — тут явный лидер — это gSOAP, очень мощная библиотека, не думаю, что есть достойные альтернативы. Также как и в предыдущем примере, содаем промежуточный файлик с xml-rpc или soap содержимым, натравливаем на него генератор, получаем код и пользуемся. Типичные примеры запроса и ответа в нотации xml-rpc:
      examples.getState  41      State-Ready   
    • Poco::RemotingNG — очень интересный проект от pocoproject. Позволяет определеять какие классы, функции и т.п. могут быть вызваны удаленно с помощью аннотаций в комментариях. Вот пример,
    typedef unsigned long GroupID; typedef std::string GroupName; //@ serialize struct Group < Group(GroupID _id_, const GroupName &_name_) : id(_id_), name(_name_) <>Group() <> //@ mandatory=false GroupID id; //@ mandatory=false GroupName name; >; // . //@ remote class EXTERNAL_API GInfo < public: typedef Poco::SharedPtrPtr; GInfo(); virtual Group getGroup() const = 0; virtual ~GInfo(); >;

    Для генерации вспомогательного кода используется собственный "компилятор". Долгое время эта функциональность была только в платной версии POCO Framework, но с появлением проекта macchina.io, Вы можете пользоваться этим бесплатно.

    • ActiveMQ-CPP — клиентская библиотека к брокеру Apache AcriveMQ, который написан на java.
    • Apache Kafka C++ client — cppkafka
    • RabbitMQ C++ libs — наверное самый популярный брокер сообщений, имеет несколько библиотек на C/C++.
    • IBM WebSphere MQ C++ classes — проприетарщина, но с очень развитым функционалом.
    • Oracle Message Broker C++ API — тоже, он от Oracle
    • MSMQ — версия от Microsoft

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

    Сетевое взаимодействие

    Я умышлено оставил все что связано непосредственно с сетевым взаимодействием на последок, т.к. на этом поприще у C++ разработчиков меньше всего проблем, на мой взгляд. Остается лишь выбрать паттерн, который ближе всего к Вашему решению, и фреймворк, его реализующий. Прежде чем перечислить самые популярные библиотеки, хочу отметить важную деталь разработки собственных сетевых приложений. Если Вы решили придумать собственный протокол поверх TCP или UDP, будьте готовы, что всякие "умные" средства защиты будут блокировать Ваш трафик, так что озаботьтесь упаковкаой своего протокола, например, в https или могут быть проблемы. Итак, библиотеки :

    • Boost.Asio и Boost.Beast — одино из самых популярных реализаций для асинхронного сетевого взаимодействия, есть поддержка HTTP и WebSockets
    • Poco::Net — тоже очень популярное решение, причем, помимо "сырого" взаимодействия можно использовать готовые классы TCP Server Framework, Reactor Framework, а также клиентские и серверные классы для HTTP, FTP и E-Mail. Так же есть поддержка WebSockets
    • ACE — никогда не пользовался этой библиотекой, но коллеги говорят, что тоже стоящая внимания библиотека, с комплексным подходом для реализации сетевых приложений и не только.
    • Qt Network — в Qt неплохо реализована сетевая часть. Единственный спорный момент — сигналы и слоты для серврерных решений, хотя сервер на Qt !?

    Итого

    Итак, что я хотел сказать обзором этих библиотек. Если у меня получилось, то у Вас осталось впечатление, что "enterprise edition", как бы, есть, а решения для его имплементации и использования — нет, только зоопарк библиотек. Так оно и есть на самом деле. Есть более-менее целостные библиотеки для разработки приложений корпоративного сегмента, но стандартного решения нет. От себя могу лишь рекомендовать pocoproject и maccina.io как отправную точку в исследованиях решений для бэкенда и boost для любых случаев, ну и конечно же ищу единомышленников для продвижения понятия "C++ Enterprise Edition" !

    Кроссплатформенная разработка мобильных приложений в 2020 году

    Я – Сергей Якимов, CTO Omega-R, международной компании по разработке и интеграции IT-решений. На базе многолетнего опыта в сфере информационных технологий и экспертизы компании хочу поделиться своим видением настоящего и ближайшего будущего кроссплатформенной разработки мобильных приложений.

    image

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

    Согласно исследованию Digital 2020 Reports, подготовленному компаниями We Are Social Inc. и Hootsuite Inc., число пользователей интернета по всему миру увеличивается на 9 человек в секунду. Это означает, что каждый день к мировому онлайн-сообществу присоединяется более 800 тысяч человек, которые пользуются настольными или мобильными устройствами. Интересно, что последний вариант становится все более популярным с каждым месяцем.

    Проникновение смартфонов в повседневную жизнь растет во всем мире. Ожидается, что к 2024 году три из четырех используемых телефонов будут смартфонами. Согласно статистике StatCounter, доля пользователей настольных устройств снизилась до 45,66%.

    image

    Самым простым объяснением такого состояния событий является изменение нашего образа жизни. Мы проводим в интернете больше времени, чем когда-либо прежде. Почти каждый имеет доступ к смартфону или планшету. Учитывая то, что среднестатистический пользователь в среднем проводит в сети почти 7 часов в день, неудивительно, что более половины этого трафика поступает с мобильных устройств.

    Это, в свою очередь, подталкивает к росту рынок мобильных приложений. Результатом предпочтения мобильных приложений являются довольно внушительные цифры. Согласно отчету Statista за прошлый год, мировые доходы от мобильных приложений в 2019 году составили 461 млрд долл., а к 2023 году платные загрузки и реклама в приложениях, как предполагается, принесут более 935 млрд долл. дохода.

    Выбор пути мобильной разработки

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

    Одним из первых шагов на пути к цифровому успеху является решение о мобильной операционной системе – это, кстати, было не так просто десять лет назад, когда Android, iOS, Microsoft, RIM и Symbian были вполне жизнеспособными вариантами.

    Сегодня выбор гораздо проще, поскольку единственными крупными игроками остаются Android и iOS, которые вместе составляют около 99% от общей доли рынка мобильных операционных систем. Согласно различным статистическим данным, Android выигрывает по количеству пользователей, но нет недостатка и в сторонниках iOS, доля которого на рынке составляет 25,75%. В то время как Google Play Store может похвастаться большим количеством приложений (2,5 млн), Apple App Store содержит более 1.8 млн приложений. Одного этого факта достаточно, чтобы показать, что ни одну из двух платформ не следует упускать из виду.

    image

    Поскольку выбор мобильной операционной системы является вопросом личных предпочтений пользователей, а не вопросом производительности или доступности, будет целесообразно в конечном итоге создать мобильное приложение как для Android, так и для iOS – и есть три способа сделать это.

    Отдельные нативные приложения для Android и iOS

    Нативное решение, как следует из названия, предполагает разработку приложения на родном для данной платформы языке программирования: Java или Kotlin для Android, Objective-C или Swift для iOS. Будучи глубоко ориентированной на операционную систему, разработка нативных приложений имеет свои достоинства и недостатки. С одной стороны, нативное решение обеспечивает доступ ко всем функциям данной ОС, позволяет неограниченно настраивать интерфейс и предотвращает любые проблемы с производительностью. С другой стороны, если вы хотите охватить оба типа пользователей, вам придется создать два отдельных приложения, которые требуют больше времени, денег и усилий.

    Прогрессивное веб-приложение

    Прогрессивное веб-приложение – технология в веб-разработке, которая добавляет сайтам возможности приложений для мобильных устройств и трансформирует сайт в приложение. На выходе получаем гибрид сайта и приложения для мобильных устройств. Однако, как любой другой вариант, прогрессивные веб-приложения небезупречны, так как они потребляют больше энергии батареи и не могут получить доступ ко всем функциям данного устройства, например, к календарю, камере, контактам и так далее. Кроме этого, теряется возможность перекрестного входа в веб-приложение с помощью приложения Facebook, Инстаграм, Вконтакте или т.д. Несмотря на то что веб-приложение не требует установки из Google Play Store или Apple App Store, последние выполняют функцию крайне удобных библиотек для пользователей.

    Одно кроссплатформенное приложение для двух систем

    Кроссплатформенность – это способность ПО (в нашем случае мобильных приложений) работать на нескольких платформах.

    Кроссплатформенная мобильная разработка позволяет охватить две операционные системы, iOS и Android, одним кодом. Она не предполагает написания кода на родном языке программирования, однако обеспечивает почти нативный опыт благодаря интерфейсу визуализации с использованием собственных элементов управления.

    На текущий момент многие компании используют кроссплатформенные решения, кто-то уже всерьез подумывает перейти на них в ближайшем будущем. Это не только вендоры самих решений, как, например, Facebook со своим React Native, на котором работают приложения Facebook и Instagram, но и другие крупные игроки рынка, у которых имеются продукты, например, на Flutter – Alibaba, Philips Hue, Hamilton, Tencent, Grab, Groupon и другие.

    Существует множество статей, где подробно анализируются все преимущества кроссплатформенных приложений. Однако плюсы и минусы стоит рассматривать на платформе, которая имеет все шансы стать в 2020 году самой популярной среди разработчиков – Flutter.

    Flutter

    Flutter – SDK от компании Google с открытым исходным кодом для создания кроссплатформенных мобильных приложений, который предоставляет пользователям как Android, так и iOS по-настоящему нативный дизайн и опыт. Данная платформа разработки уже на старте показала внушительный рост по сравнению с React Native. Анонсированный на конференции Google I/O 2017 и выпущенный в 2018 году, Flutter остается все еще новичком на рынке платформ для создания кроссплатформенных приложений. С более чем 87 700 звездами в GitHub, что выше результата React Native, и подавляющим большинством разработчиков, называющих его одним из трех самых любимых фреймворков в обзоре Stack Overflow’s annual Developer Survey 2019, Flutter, несомненно, является силой, с которой следует считаться.

    image

    Рассмотрим плюсы и минусы Flutter как платформы для разработки продукта:

    Плюсы

    • короткий time-to-market;
    • производительность приложений наравне с нативными решениями;
    • общая стоимость разработки ниже аналогичного решения с нативными приложениями;
    • поддержка единой кодовой базы;
    • снижение затрат на исправление багов и добавление новой функциональности.

    Минусы

    • некоторую функциональность необходимо разрабатывать независимо на обеих платформах, если нет кроссплатформенных библиотек;
    • один язык разработки – Dart, который необходимо выучить, если компания разрабатывает приложение, не имея необходимой экспертизы. В нашей компании есть разработчики на Flutter, что нейтрализует данный минус и позволяет получить специалистов быстрее поиска на рынке (согласно исследованиям, на найм специалиста тратится не менее двух недель).

    Кроссплатформенные приложения на Flutter разрабатываются аналогично нативным в общепринятых IDE – Android Studio и XCode. Как дополнение, разработчикам доступен hot-reload кода, что ускоряет запуск приложения во время разработки. Кроме этого, процесс публикации ничем не отличается от нативных – собранные дистрибутивы подписываются и загружаются в магазины приложений.

    Польза для бизнеса

    В бизнесе решающую роль зачастую играет метрика TTM (time-to-market). Быть впереди и внедрять новые функции в свой продукт быстрее конкурентов сразу на обеих платформах – об этом с самого начала задумывается любая компания-лидер. Кроссплатформенные фреймворки позволяют это достигать и, как очевидный бонус, получать снижение затрат на разработку на каждом этапе. По нашим подсчетам – разработка на Flutter позволяет снижать общую стоимость разработки продукта на 25-30%.

    Прогноз, перспективы на ближайшие 5 лет

    Все, кому важен быстрый выход на рынок со своим продуктом одновременно на обеих платформах мобильной разработки, уже активно разрабатывают с использованием кроссплатформенных решений. В 2020 году тренд не изменится, и все больше компаний будут использовать кроссплатформенные мобильные приложения на Flutter.

    Google разрабатывает новую ОС Fuchsia, в том числе для мобильных устройств. Flutter заявлен как UI toolkit в этой ОС. В ближайшем будущем Fuchsia может заменить ОС Android, и, несмотря на то что в Fuchsia в данный момент все же добавляется возможность запускать нативные приложения под Android, стоит учитывать эту тенденцию при планировании разработки и выхода на рынок со своими мобильными приложениями.

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

    • Разработка под iOS
    • Разработка мобильных приложений
    • Разработка под Android
    • Dart
    • Flutter

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *