06 октября 2025 г.
Функциональные и нефункциональные требования
Привет. Меня зовут Евгений Ширанков, и я возглавляю команду платформенных сервисов Яндекс 360.
Путешествие в мир архитектуры распределённых систем следует начать с основы основ любого проекта — сбора требований. Мы поговорим о том, зачем собирать функциональные требования. Как хорошо собранные требования влияют на бизнес и помогают разработчикам принимать более зрелые и взвешенные решения.
Давайте для начала проговорим очевидную мысль: не зная требования, нельзя сделать хорошее решение. Давайте приведу пример. Что будет, если вам дать задачу собрать машинку из конструктора, но при этом не дать инструкцию? Конечно, какую-то машину вы соберете, например, гоночную. Но очень может оказаться, что на самом деле нужна была машина для перевозки грузов. И придется или все переделывать заново, или возить грузы на спорткаре. Ни тот, ни другой вариант обычно никому не нравится. И, конечно, было бы проще, если бы инструкцию по сборке нам дали сразу. Но давайте задумаемся: даже если инструкции у нас есть, уверены ли мы, что грузовая машина то, что нам правда нужно? Зачем нам вообще потребовалось возить грузы?
Каждый проект или задача, которую мы делаем, возникла не просто так. У нее есть какая-то первопричина, проблема, которую она решает. И часто, когда заказчики к нам приходят с проектом, они приносят конкретные решения проблемы, которые, кажется, им единственно возможны. Однако, как правило, у любой проблемы всегда бывает более одного способа решения. И наша задача, как инженеров, не просто делать то, что принес заказчик, а выяснить, почему этот проект вообще надо делать, какую проблему он решает. Опытные инженеры хорошо понимают устройство системы и могут предложить более простые в разработке и в то же время более дешевые в поддержке решения, которые решают изначальную проблему и устраивают продукт.
Давайте вернемся к примеру про конструктор машинки. В случае сборки грузовой машины может оказаться, что изначальная проблема была в том, что на игрушечной стройке у кранов кончились батарейки и грузовая машина нам нужна, чтобы их возить по мере необходимости. Эта проблема более сложная, нежели просто постройка грузовика. Для перевозки батареек нужны погрузщики, манипуляторы для их установки. Их постройку также стоило заложить в проект. Возможно, лучшим решением будет переходить батареек на аккумуляторы, это поможет сэкономить ресурсы на дистанции. А еще и решить проблемы с электропитанием можно совершенно по-другому, подключив строительные экраны к розетке.
Зная изначальную проблему, которую мы решаем, можно не только сэкономить ресурсы или построить более стройное решение, но и значительно влиять на сам продукт, на его качество, на то, как он работает и то, каким его видят наши пользователи. Умение решать проблемы, а не просто делать задачи, это именно то, что характеризует опытного инженера, который правда умеет строить сервисы.
Для того, чтобы решать проблемы, нужно погрузиться в контекст продукта. Без понимания происходящего и истинных вызовов, с которыми сталкивается наш продукт, без понимания долгосрочной стратегии его развития, нельзя придумать по-настоящему оптимальное архитектурное решение. А чем более оптимальное решение принимает инженер, тем больше пользы он приносит бизнеса и тем выше его ценность.
Давайте рассмотрим пример. Представим себе, что поступила задача дать возможность администраторам организации Яндекс 360 отличать анимированные фоны в продуктах для своих сотрудников. Чтобы понять, как это спроектировать, надо обратиться к менеджеру и выяснить, какой должен быть пользовательские сценарии, какие ограничения есть и как функциональность должна выглядеть. После этого можно отправляться продумывать архитектуру. Но подождите. В самом ли деле мы узнали всё необходимое нам? Давайте подумаем ещё раз.
В реальности надо копнуть глубже в первопричины проекта. Возможно, кажется так, что проект появился из-за большого числа жалоб на потребление трафика от администраторов какого-то одного клиента. У этого клиента много разбросанных по стране филиалов, где каналы связи стоят дорого. А анимированные фоны довольно требовательно к трафику. В итоге вместо реализации не слишком востребованной фичи можно помочь одному конкретному клиенту, просто разово выключив анимированные фоны в организации, и сэкономить несколько месяцев работы целой команды разработки.
Давайте рассмотрим еще один пример на этот раз из реальной жизни. На определенном этапе развития нашего билинга нам потребовалось сделать скидки на тарифы. Например, на новый год, на черную пятницу. И главное — это надо было сделать быстро, так как на носу был очередной праздник. Давайте подумаем. Праздники — события предсказуемые. Все они есть в календаре, и мы можем заранее к ним подготовить скидки. К тому же их не так уж много, пять-десять в год. Кажется, что мы можем создавать такие акции силами разработки.
Но давайте попытаемся копнуть глубже и обратимся к маркетинговой стратегии Яндекс 360 всех лет. Окажется, что маркетинг Яндекс 360 планирует через полгода начать массово проводить акции не только по календарным праздникам, но по произвольным событиям и инфоповодам, раздавая промокоды со скидками на тарифы. Предсказать число инфоповодов сложно, но их будет точно на порядок больше, чем количество праздников, на которые мы изначально рассчитывали. Поэтому мы, как опытные инженеры, осознав весь контекст решаемой задачи и вектор развития требований, приняли решение вложиться немного больше в разработку скидочной механики. Сделали так, чтобы скидки могли заводить сами маркетологи без участия разработки так быстро, как и может хотеться, не ограничивая рост желания бизнеса техническими ограничениями.
Опытный инженер не только знает истинную проблему конкретного проекта, но понимает стратегию развития продукта и может принимать решения сегодня, которые помогают сэкономить время или ресурсы в будущем. Таким образом, чтобы правильно собрать функциональные требования, недостаточно просто узнать про функционал, который надо делать. Нужно также определить причины возникновения проекта и его контекст, узнать проблему, которую мы решаем. Это поможет нам в свою очередь принять лучшее архитектурное решение. И надо определить планы на развитие функционала. Это поможет заложить расширяемую архитектуру, которая прослужит вам десятилетия.

Для принятия оптимальных архитектурных решений необходимо:

1
  • Погрузиться в контекст продукта
  • 2
  • Понять истинную проблему пользователя
  • 3
  • Понимать направление долгосрочного развития продукта
  • Но на архитектуру влияет не только функциональные, но и нефункциональные требования. Нефункциональные требования помогают понять, насколько быстро, надежно и безопасно должна работать наша система. Какие нагрузки она должна выдерживать, какие пределы масштабирования обеспечивать и какую гибкость предоставлять. Правильный расчет этих параметров позволит построить архитектуру, которая выдержит запуск новых фич, целых продуктов, выход в новые регионы и страны. В Яндекс 360 мы довольно часто запускаем новые фичи и даже продукты. Только в 2025 году мы запустили Документы и Доски. Новые фичи видят десятки миллионов пользователей. И если заранее правильно не оценить нагрузку и объем данных, которые они создадут, то запуск может обернуться катастрофой.
    Давайте рассмотрим стандартный подход, который мы стараемся придерживаться при оценке нефункциональных требований в наших проектах. Для расчета нагрузки нам сначала потребуется оценка аудитории, которая будет использовать наш продукт или фичу. Эти цифры не всегда есть у заказчика, но опытный инженер может рассчитать их самостоятельно. Их можно получить исходя из аудитории похожих продуктов нашей компании или по открытым данным на рынке. Затем надо понять, где наши пользователи находятся. Если мы строим геораспределенный сервис, то надо понять, в каких странах находятся наши пользователи, как они распределены по часовым поясам. Далее нам надо понять, как люди будут использовать наш продукт. Надо определить основные действующие лица и пользовательские сценарии. Эту информацию обычно можно узнать у заказчика. Далее надо прикинуть, как часто эти сценарии будут вызываться, и рассчитать для каждого из них вызовы API, которые нам потребуется сделать. Получив количество вызовов IP по всем сценариям, можно их сложить с учетом распределенности аудитории и получить суммарный RPS. А если прикинуть сколько данных будет загружено и скачано, можно определить необходимый размер хранилища для них и рассчитать нагрузку на сеть. Зная размер нагрузки и объема данных, можно оценить и еще один важный параметр — количество необходимого железа для работы нашей системы. Важно его оценивать не только на старте продукта, но и при запуске каждой большой фичи.

    Прикинуть будущую нагрузку можно, если:

    1
  • Оценить объём активной аудитории
  • 2
  • Изучить географию потенциальных пользователей
  • 3
  • Определить основные сценарии и модель использования сервиса
  • Однажды у нас был проект, на котором мы этого не сделали. При запуске трансляции в Телемосте мы предположили, что фича будет не самой популярной и много ресурсов не потребует. В день запуск стал понятно, что мы зря не уделили должного внимания расчету объемов железа. Требуемых для работы фичи ресурсов оказалось больше, чем у нас было на тот момент. И нам пришлось в спешном порядке занимать железо у коллег.
    К счастью для компании, в Яндексе множество сервисов и всегда есть определенные запасы на непредвиденные случаи. Зачастую необходимые нам объемы железо попросту невозможно купить на рынке и необходимо их заказывать заранее и ждать производства и доставки оборудования в наши даты-центры. Поэтому у нас теперь есть чек-лист для подготовки к архитектурному ревью, который сильно упрощает работу и помогает избежать подобных плачевных ситуаций.
    Но нагрузка на сервис не всегда бывает расчетной. И если вы строите большой сервис, то стоит заранее думать, что произойдет, если нагрузка вдруг внезапно вырастет. Это тоже входит в нефункциональные требования. Мы всегда закладываем буфер на нештатные ситуации. Все наши сервисы работают на нескольких дата-центрах. И ресурсы закладываются так, чтобы при отказе одного из них остальные дата-центры были загружены максимум на определенный процент в пиковые часы. Такой буфер хорошо работает, однако бывает и так, что его не хватает. Бывают неожиданные сплески нагрузки, например, из-за виральности или из-за нештатной работы смежных сервисов. В таких случаях хороший инженер подумает заранее, как поведет себе сервис, чтобы сохранить максимум пользы для своих пользователей. Мы постоянно продумываем сценарии деградации наших сервисов в таких исключительных ситуациях. Например, сервис авторизации будет стараться любыми способами сохранить читающую нагрузку, даже жертвуя пишущей.
    Подводя итоги, сбор функциональных и нефункциональных требований — первый и самый важный шаг построения систем. Должным образом собранные требования позволяют не только построить надежные и расширяемые решения, которые позволяют компаниям расти, но и являются ключом к профессиональному росту инженеров. Чем больше мы погружены в контекст происходящего, тем более взвешено наше решение. Чем больше мы думаем про то, как наша система будет вести себя в продакшене, тем большей ценностью обладают решения, которые мы принимаем. Функциональные и нефункциональные требования связывают технические решения с потребностями пользователей и ограничениями реального мира. Они лежат в основе создания любой системы и определяют её архитектуру.
    В следующих частях нашего путешествия мы познакомимся с конкретными подходами к проектированию систем, которых мы придерживаемся в Яндекс 360. Будет интересно. Я обещаю.