Прежде чем начать программирование и даже проектирование ПО, желательно заранее договориться (как минимум с самим собой) о принципах, которые будут положены в основу ваших продуктов. И даже уже существующие продукты можно будет впоследствии привести в соответствие с этими принципами.
Единые принципы упрощают работу с продуктом, так как не нужно переучиваться при переходе с продукта на продукт. Уменьшается порог входа новых сотрудников в проект. Также упрощается и настройка инструментов (система сборки дистрибутивов и т.д.).
В моём случае основными предпосылками, послужившими формированию требований к архитектуре, были:
- потребность адаптировать приложения под веб и под мобильные устройства;
- пожелания программистов работать с современными технологиями (Web API, .NET Core);
- необходимость гарантировать эффективность потребляемых приложением ресурсов (должна быть ограничена возможность создавать неэффективный код);
- потребность в удобстве сопровождения приложений.
Самое главное правило при проектировании требований - не нужно излишних усложнений (принцип “бритвы Оккама”). Не нужно проектировать слишком универсальные приложения, решающие все возможные задачи. Нужно оставлять заделы под дальнейшее развитие и использовать их только при возникновении необходимости.
Далее следуют принципы, которые я использовал в работе.
Модульность
Любое приложение должно состоять из слабо связанных между собой частей - модулей. Это позволяет тестировать каждый модуль в отдельности, а также заменить один модуль другим без капитальной переработки всего приложения. Каждый модуль должен иметь чёткую спецификацию своего API, которое можно вызывать, и зависимостей, к которым обращается он сам. Это API следует документировать.
Каждый модуль может состоять также из набора модулей, то есть они образуют иерархию.
Протоколы взаимодействия
Модули внутри приложения взаимодействуют непосредственно, через вызовы API. Приложения же при общении между собой используют JSON API, то есть обращаются друг к другу через стандартный HTTP-протокол. Этот подход позволяет использовать единое API для взаимодействия десктопных, мобильных и веб-приложений.
При необходимости передачи данных в режиме реального времени следует использовать веб-сокеты. Для обеспечения обратной связи от сервера на клиент можно использовать те же веб-сокеты или SSE.
Сервер
Архитектура - MVC.
Платформа - ASP.NET Core + .NET Core
Должен иметься слой доступа к базе данных с поддержкой создания и автоматического обновления базы данных (миграции). Например, можно использовать Entity Framework Core.
Клиент
Архитектура - MVVM. Обеспечивается возможность юнит-тестирования ViewModel.
Платформа - веб (HTML + CSS + JS), MVVM обеспечивается при помощи knockout.js/angular.
Приложение реализуется одностраничным (SPA). Данные запрашиваются с сервера через AJAX, причём AJAX возвращает только данные, без разметки (за исключением особо сложных случаев). Отображением данных занимается сам клиент.
Крайне желательно, чтобы клиент обращался к серверу с минимальным числом запросов, запрашивал только то, что реально нужно для отображения, и кэшировал полученные с сервера результаты.
Логирование
Логирование должно быть исчерпывающим. Это позволит упросить диагностирование ошибок в релизной версии продукта.
Отказоустойчивость
Система должна обеспечивать работоспособность до определённого заранее выбранного уровня нагрузки (например, количества одновременных подключений). Это проверяется при помощи нагрузочного тестирования. Ошибки в системе не должны приводить к её краху.
Масштабирование
Должно быть возможно увеличивать производительность системы за счёт модернизации инфраструктуры без переписывания самой системы.
Производительность
Система должна удовлетворять выбранным критериям производительности (максимальное время отклика и пр.). Данное условие проверяется при помощи нагрузочного тестирования.
Далее