Pull to refresh

Нужно ли разработчикам проектирование?

Level of difficultyMedium
Reading time7 min
Views8.3K

Я работаю в сфере разработки заказного программного обеспечения. Когда мы говорим о проектировании программного обеспечения, как правило перед нами всплывает такая картинка:

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

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

  1. Отправка уведомлений должна осуществляться посредством SMS и e-mail ежеминутно.

  2. Все уведомления должны храниться в БД с указанием времени отправки.

Простой функционал. Поручив такую работу неопытному разработчику, скорее всего, получим следующее незатейливое решение:

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

Но опытный разработчик посмотрит и скажет, что это плохое решение. В системе может быть много модулей: 10, 20, 100. Если каждый модуль будет обращаться к БД раз в минуту, это может вызвать перегрузку БД, и печальные последствия для системы. Нужно ограничить считывание из БД частотой 1 раз в час. Таким образом мы только что сформулировали первое требование, которое нигде не прозвучало явно. Это важное требование, от выполнения которого зависит стабильность нашей информационной системы:

  • Обращаться к БД не чаще чем 1 раз в час.

Закроем это требование добавлением кэша, который будет осуществлять выборку всех сообщений из БД на ближайший час и с которым будет работать модуль отправки уведомлений.

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

  • Использовать REST API для работы с сообщениями.

В схему нашего решения добавляем кэш, модуль для работы с кэшем и REST API для работы с сообщениями.

После изучения схемы возникает вопрос: сколько сообщений будет отправляться? Они будут отправляться по одному? Если сообщений будет тысячи или десятки тысяч, то, отправляя сообщения по одному, может случиться так, что сервис отправки уведомлений может не успеть передать все данные о сообщениях за отведенный час. Соответственно, отправка уведомлений должна быть пакетной. Это критично для производительности системы.

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

  • Отправлять почтовые сообщения и SMS пакетами.

Из схемы также видно, что присутствует два временных интервала: ежеминутная выборка сообщений из кэша и ежечасная выборка из БД в кэш. Мы собираемся эти интервалы прописывать непосредственно в коде? А если пользователь в какой-то момент поменяет решение о ежеминутной отправке сообщений? Значит, интервалы отправки сообщений и актуализации кэша нужно хранить отдельно, где они могут быть изменены пользователем. Формируем новое требование:

  • Хранить интервалы отправки почтовых сообщений, SMS и выборки из БД в сервисе конфигураций.

У опытных разработчиков может возникнуть еще один вопрос: какое время ожидания (таймаут) если внешние сервисы или БД не работают? Следовательно, необходимо хранить информацию о таймаутах в сервисе конфигураций.

Открытым остается вопрос: куда будут отправляться сообщения об ошибках и метрики работы сервиса?

Добавляются еще требования:

  • Хранить в конфигурации системы таймауты доступа к БД и внешним сервисам.

  • Отправлять информацию об ошибках и метриках в сервисы логирования и мониторинга системы.

Далее возникает вопрос, как будут выдерживаться интервалы отправки уведомлений и загрузки данных из БД? Наш сервис будет крутить бесконечный цикл или нужно более техничное решение? Наверное, лучше всего добавить в систему какой-то таймер или использовать системный cron. Появляется еще одно неявное требование:

  • Использовать таймер или cron для работы сервиса.

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

На схеме мы видим, что в системе используются общие компоненты: логирование, мониторинг, сервис конфигураций. Скорее всего, большинство модулей системы (возможно все) будут взаимодействовать с этими компонентами. Мы будем писать везде один и тот же код? Возможно, в будущем придется заменить сервисы логирования и мониторинга на другие. Что если для сервиса конфигураций придется использовать не собственный компонент, а готовый opensource? Необходимо устранить дублирование кода с помощью dependency injection (DI).

Добавляем еще одно требование к нашему списку:

  • Устранить дублирование кода при работе с сервисом конфигураций, логирования и мониторинга.

Внесем изменения в нашу схему.

Можно и дальше продолжать анализировать решение, добавляя новые требования.

Например:

  • Определить максимальный размер пакета уведомлений;

  • Использовать проверку сервиса на работоспособность – HealthCheck.

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

Давайте приведем список явно озвученных и выявленных нами требований.

Функциональные требования:

  1. Отправка уведомлений должна осуществляться посредством SMS и e-mail ежеминутно;

  2. Информация обо всех уведомлениях должна храниться в БД с указанием времени отправки.

Неозвученные технические требования, которые были выявлены в процессе проектирования:

  1. Обращаться к БД не чаще, чем 1 раз в час;

  2. Использовать REST API для работы с уведомлениями;

  3. Отправлять почтовые сообщения и SMS пакетами;

  4. Хранить интервалы отправки почтовых сообщений, SMS и выборки из БД в сервисе конфигураций;

  5. Хранить в конфигурации системы таймауты доступа к БД и внешним сервисам;

  6. Отправлять информацию об ошибках и метриках в сервисы логирования и мониторинга системы;

  7. Использовать таймер или cron для работы сервиса;

  8. Устранить дублирование кода при работе с сервисом конфигураций, логирования и мониторинга;

  9. Определить максимальный размер пакета уведомлений;

  10. Использовать проверку сервиса на работоспособность – HealthCheck.

В итоге получаем следующий интересный расклад:

  • На 2 явно озвученных функциональных требования было сформулировано еще 10 неозвученных;

  • Обнаружили ранее не выявленную потребность в 4 дополнительных функциональных блоках сервиса: cron, кэш, REST API для работы с уведомлениями, HealthCheck;

  • Выявили потребность в 3 компонентах системы: сервис конфигураций, сервис логирования и сервис мониторинга (написанные самостоятельно или готовые решения).

Итог

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

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

Могло бы помочь такого рода проектирование неопытному разработчику в выявлении проблем еще до написания кода? Да. Как минимум, до старта работ схему решения и описание смогли бы оценить более опытные коллеги и внести корректировки, если потребуется. Схема вместе с описанием решения, помогла бы осуществить внешний технический аудит. Имея подобный артефакт на руках, можно попробовать нарезать задачу на микрозадачи, с которыми могла бы работать команда неопытных разработчиков.

Стоит ли тратить время на отрисовку подобных схем? Проработка текущего решения вместе с созданием схемы у автора заняла 30 мин. Для наглядности этой статьи, схемы рисовались в графическом редакторе, однако – это, могли бы быть и UML-диаграммы. А вообще, проектирование — это не про схемы. Прежде, чем начинать писать код хорошо бы подумать, что Вы будете делать. Вместо схемы Вы можете использовать текстовое описание. Главное понятно донести до команды суть вашего решения.

Описание, схема могут быть результатом коллективной работы. Создавая модуль или фичу каждый может внести свой вклад: изменения в БД, изменения в API, изменения связанных компонентов и т.д.

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

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

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

Эпилог

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

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

Насколько необходимо проектирование (иногда его называет design, а процесс в разработке Design Review) и когда – решать вам. Все плюсы я постарался изложить в этой статье, ну а минусы вы найдете самостоятельно.

Tags:
Hubs:
Total votes 11: ↑11 and ↓0+11
Comments21

Articles