Заказчик
АО «КМЗ»
Завод предлагает своим клиентам широкий спектр продуктов в области промышленной чистки газов, энергоэффективных дымососов и нагнетателей.
Компания МСТ завершила очередной этап развития расчётной системы для завода КМЗ.
Данный этап, в основном, был связан с изменениями в пользовательском интерфейсе, но и про новый функционал мы также не забыли, однако, обо всём по порядку.
Интерфейс
В большинстве случаев интерфейс не вызывает особых вопросов, поскольку его адаптация к новым элементам проходит без затруднений. Однако в данном случае возникли неожиданные сложности, которые потребовали дополнительного внимания.
В данном релизе мы полностью перевели интерфейс приложения на использование библиотеки MahApps.Metro, то будем рассказывать в основном про него.
Обычно, для таких свойств элементов как Margin или Padding – внесение изменений в стиль не является проблемой. Однако, при необходимости реализовать более сложное поведение, возникает множество проблем в MahApps. Ярким примером, в данном случае, является наведение курсора мыши на элемент, который при этом использует пользовательский цвет.
Разумеется, в данном случае можно было реализовать свою тему для фреймворка, однако ради одного кастомного элемента реализовывать отдельный стиль – это слишком временезатратное действие! В целом, если немного отойти от обычного использования библиотеки, то приходиться каждый раз читать код библиотеки, что не очень продуктивно для общего процесса разработки.
Но в целом, в библиотеке MahApps не всё так плохо. В ней присутствует множество специальных элементов, которых нет в стоковом WPF, а также имеется собственная библиотека с настраиваемыми иконками, а также большое количество различных helper’ов, которые, в свою очередь, очень облегчают процесс изменения поведение элементов интерфейса.
Таким образом, в библиотеке MahApps также присутствует множество положительных моментов.
Система автообновления
По мере эксплуатации программы стало очевидно, что для обновления на новую версию приложения тратится слишком много времени.
Даже самое незначительное обновление приложения должно происходить с минимальными тратами времени, чтобы не тормозить рабочий процесс.
Поэтому в данной версии, нами была добавлена встроенная функция обновления приложения.
Изначально, мы спроектировали систему обновления на базе библиотеки AutoUpdater.NET. Данная библиотека имеет хорошую гибкость в настройках, и даже после внедрения её в проект, она довольно хорошо себя зарекомендовала. Однако, при этом, было несколько проблем, критичных для данного проекта.
Основной функционал, который обычно требуется от системы автообновления — это скачать и установить новую версию приложения. Но заказчику также была необходима ещё одна дополнительная возможность – автозапуск приложения после обновления.
Довольно простой функционал, который, увы, AutoUpdater.NET не в состоянии предоставить. Вскоре также оказалось, что у AutoUpdater.NET есть проблемы с установкой приложения с помощью msiexec.
Поэтому мы решили отказаться от использования AutoUpdater.NET, и реализовать процесс обновления приложения полностью своими силами.
Список минимальных требований для системы обновлений:
- Сервер, где будут храниться архивы с разными версиями.
- Метаданные, о текущей версии, всё на том же сервере.
- Возможность скачать метаданные и архив с приложением.
Первым делом был настроен сервер. Схема реализации довольно проста, мы использовали nginx для раздачи файлов с доступом только по авторизации.
На стороне приложения было реализовано отдельное приложение, которое будет информирует пользователя о текущем этапе установки. Также была добавлена библиотека, которая оборачивает всю логику по работе с сервером и msiexec в удобное API.
Для работы с метаданными реализовали простой и удобный yaml файл с несколькими параметрами:
version: XX.YY.ZZ.0
url: https://example.com/archive/update-XX.YY.ZZ.0
args: /qr
hash: 5891b5b522d5df086d0ff0b110fbd9d21bb4fc7163af34d08286a2e846f6be03
Файл конфигурации немного похож на AutoUpdater.NET, но читается намного лучше, чем xml.
Если скачиванием метаданных с сервера и проверкой версии всё просто, то установка через msiexec имеет свои особенности.
Для реализации автоматизированной установки (параметр /q) стоит использовать установщик собственной разработкик. Это обусловлено тем, что установка ПО в фоновом режиме требует прозрачности для пользователя, чтобы исключить установку нежелательных программ. Поэтому процесс установки и удаления должен подтверждаться пользователем. Этот подход был согласован с заказчиком, так как его устраивает необходимость нескольких подтверждающих нажатий для завершения установки.
Также возникла проблема с установкой новой версии: утилита msiexec не поддерживает обновление путем установки новой версии поверх старой. В связи с этим было принято решение перед началом установки новой версии сначала удалять текущую, используя GUID приложения для выполнения корректного удаления.
Кроме того, для мониторинга процесса установки требуется минимальное приложение, которое позволит пользователю отслеживать ход установки и, при возникновении непредвиденных проблем, передавать лог установки для анализа.
Однако здесь возникает небольшая сложность: данное приложение поставляется в составе основного ПО, которое удаляется перед установкой новой версии. В связи с этим для корректного обновления установщик необходимо временно копировать в %TEMP% и выполнять установку из этой директории.
Управление единицами измерения ПО
На момент написания данного кейса, единицы измерения только начали вводится в использование, и описание их разработки не является конечным. Однако даже сейчас можно выделить несколько интересных моментов.
Основной интерес здесь представляет сама реализация работа с единицами измерения.
Так например, когда в настройках программы пользователь изменяет единицу измерения группы Давление с Паскалей на Бары, то во всей программе значения связанные с давлением должны быть пересчитаны. Это настройка распространяется только на пользователя.
С точки зрения кода это решается введением промежуточного класса, который может менять отображаемое значение и знает к какой единице измерения он относится.
То есть теперь можно с лёгкостью менять одну единицу измерения на другую и быть уверенным что класс эмитирует событие OnChangeProperty и на интерфейсе отобразиться данное изменение.
Помимо данного класса для каждой единицы реализовано преобразование в базовую единицу данной группы, например для группы Давление это Паскаль.
Данные переходы были реализованы через два класса – преобразование через константу и по формуле. Второй класс, на данный момент используется только для перевода из градусов Цельсия в Фаренгейты.
Редактор газовой смеси
Как правило, все самые сложные части разработки происходят в расчётном модуле программы, однако в редакторе газовой смеси мы также столкнулись с одной интересной задачей, которая больше относится к интерфейсу чем к коду.
Этой задачей являлось отображение значений в колонке Соотношение в зависимости от выбранной единицы измерения (процентное или количественное). Сложность была связана с DataGrid и невозможностью переключать отображаемый Binding с одной переменной на другую силами только XAML на лету.
В процессе разработки, были предприняты попытки реализации кастомного CellTemplate, где в зависимости от выбранной единицы будет отображаться одно из необходимых полей, однако, WPF оказался не настолько гибкий, чтобы реализовать данную возможность и не поломав при этом множество стилей.
Как итог, на данном этапе разработке задача была решена при помощи создания второго DataGrid, хотя, надо признать, что это и не самое элегантное решение.
Управление пользователями
В приложении с самого начала была заложена возможность использовать несколько пользователей, но на начальном этапе эта функциональность почти не использовалась.
Сейчас же, мы дошли до этапа, когда разграничение доступа является важной функцией системы, без которой продолжение работы не целесообразно.
Поэтому мы стали перерабатывать модель пользователя для того, чтобы ввести гибкую настройку прав доступа с лёгкой возможностью добавления новых модулей в систему.
Описание основного функционала представляется излишним, так как он представляет собой стандартный CRUD. Однако модуль управления правами заслуживает отдельного внимания.
Основной функционал модуля помимо создания пользователей включает группировку прав по модулям. Для реализации потребовалось спроектировать структуру данных, поддерживающую произвольное количество разделов с любой степенью вложенности.
В итоге права доступа были реализованы с использованием строк с разделителем. Например, чтобы проверить доступ к элементу B в разделе A, достаточно обратиться к строке вида «A.B» и последовательно проверить доступность каждого элемента.
Изначально предполагалось, что реализация данного функционала может потребовать более сложных решений для интерфейса. Однако на практике оказалось достаточным использовать компонент TreeView с кастомизированным шаблоном.
Послесловие
На данном этапе функциональность успешно используется заказчиком, а мы же, в свою очередь, приступили к дальнейшему расширению возможностей приложения. Впереди еще значительный объем работы, и множество интересных задач, которые непременно будут реализованы нашей командой.
АО «КМЗ» предлагает своим клиентам широкий спектр продуктов в области промышленной чистки газов, энергоэффективных дымососов и нагнетателей. Накопленный опыт, высококвалифицированные технические специалисты позволяют максимально точно решить поставленные задачи, с применением современных технологий в области перемещения газовоздушных смесей, модернизации устаревшего оборудования, увеличения срока службы и снижения расходов на обслуживание.
Отзыв заказчика
Для выполнения проекта АО «КМЗ» выбрана компания «МСТ Компани», поскольку штат включает в себя специалистов, способных решать поставленные задачи. Выражаю огромную благодарность «МСТ Компани» за их профессионализм и гибкий подход к решению не стандартных задач!
Отзыв клиента
В июле 2019 года компания ООО «Аэро-Трейд» искала подрядчика для выполнения работ по внедрению системы безналичной оплаты товаров самолетах авиакомпании «AZUR air». После тщательного изучения рынка, мы решили обратиться для реализации данного проекта в компанию ООО «МСТ Компани». Основной задачей было обеспечить каждый борт авиакомпании «AZUR air» терминалом, который сможет принимать платежи не только на земле, но и во время полёта.
В течении всего времени нашего сотрудничества, специалисты ООО «МСТ Компани» продемонстрировали отличные профессиональные навыки при подготовке проекта, и разработке документации. В результате мы получили гибкое и надёжное решение, которое удовлетворяет нашим требованиям.
По итогам работы с компанией ООО «МСТ Компани» хочется отметить соблюдение принципов делового партнерства, а также четкое соблюдение сроков работ и выполнение взятых на себя обязательств. ООО «Аэро-Трейд» выражает благодарность специалистам компании за проделанную работу в рамках внедрения системы безналичной оплаты на самолетах авиакомпании «AZUR air». И рекомендует компанию ООО «МСТ Компани» как надёжного партнёра в области платёжных решений.