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

в 7:05, , рубрики: дифференциальные уравнения, Исследования и прогнозы в IT, математика, моделирование, управление разработкой

Некоторое время назад между мной и моим хорошим другом состоялся разговор, в котором прозвучали такие фразы:

— Количество программистов будет постоянно расти — ведь количество кода растет, и для его поддержки постоянно требуется все больше разработчиков.
— Но код стареет, часть его уходит из поддержки. Не исключено даже наличие какого-то равновесия.

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

Вопрос первый. Может ли поддержка «съесть» все ресурсы разработки?

Рассмотрим коллектив программистов, в котором число участников постоянно. Доля их рабочего времени $mu(t)$ ($0<mu(t)<1$) приходится на разработку нового кода, а оставшаяся доля времени $1-mu(t)$ уходит на поддержку. В рамках допущений модели предположим, что первый вид деятельности направлен на увеличение объёма кода, а второй — на его изменение (исправление ошибок) и существенного влияния на объём кода не оказывает.

Обозначим $y(t)$ весь объём кода, написанный к моменту времени $t$. Считая скорость написания кода пропорциональной $mu(t)$, получаем:

$frac{dy(t)}{dt}=a_0 mu(t); a_0in mathbb{R}, a_0 > 0.$

Естественно предположить, что трудозатраты на поддержку кода пропорциональны его объёму:

$1-mu(t)=a_1 y(t); a_1in mathbb{R}, a_1 > 0$

или

$mu(t)=1-a_1y(t)$

Откуда

$frac{dy(t)}{dt}=a_0 (1-a_1y(t))).$

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

$y(t)=frac{1}{a_1}(1-e^{-a_0a_1t}).$

При $tto+infty$ функция $y(t)to1/a_1$, а $mu(t)to 0$. И это означает постепенное сокращение с течением времени разработки нового функционала до нуля и переход всех ресурсов на поддержку.

Однако, если за время $h>0$ код устаревает и перестаёт поддерживаться, то объём кода, требующего поддержки, в момент времени $t$ равен уже $y(t) - y(t-h).$ Тогда

$1-mu(t)=a_1 (y(t) - y(t-h)),$

$mu(t)=1-a_1(y(t) - y(t-h)),$

а $y(t)$ является решением дифференциального уравнения с запаздывающим аргументом [1]:

$frac{dy(t)}{dt}=a_0 (1-a_1(y(t) - y(t-h))).$

Решение такого уравнения однозначно определяется заданием значений $y(t)$ «до начала времён», при $tin [-h, 0]$. Так как до начального момента времени кода написано ещё не было, то в нашем случае $y(t)=0$ при $tin[-h, 0]$.

Рассмотрим несколько примеров. Будем измерять время в годах, а объём кода в тысячах строк. Тогда для $a_0$ приемлемыми являются значения порядка десятков, мы возьмём 50 и 100. То есть за год группа разработки напишет пятьдесят и сто тысяч строк кода соответственно. Для $a_1$ приемлемыми могут быть величины: $0.25/a_0$, $0.5/a_0$, $1/a_0$. Это означает, что группа разработчиков способна поддерживать объём кода, который написан ей же за год, при занятости на четверть, на половину или для этого требуется полная занятость. В качестве среднего времени жизни кода зададимся величинами: 1, 2 и 4 года. Решая уравнение численно, получим примеры поведения функции $mu(t)$ для некоторых комбинаций параметров $h, a_0, a_1$.
image
Характер поведения функции $mu(t)$ в условиях старения кода изменился. Функция перестала быть монотонной, но колебания со временем «успокаиваются», наблюдается тенденция стремления $mu(t)$ к некоторому постоянному значению. Графики показывают: чем больше $h$, $a_0$ и $a_1$, то есть чем медленнее стареет код, чем быстрее происходит разработка нового кода и чем ниже качество кода, тем меньше ресурсов будет оставаться для разработки нового функционала. Было желание привести хотя бы один пример, в котором $mu(t)$ «прижалась» близко к нулю. Но это потребовало подбора очень плохих показателей качества разработки и долго не стареющего кода. Даже на левом нижнем графике на новый функционал остается ощутимое количество ресурсов. Поэтому правильный ответ на первый вопрос скорее такой: теоретически — да, это возможно; практически — вряд ли.

Вопросы, на которые не удалось получить ответ:

  1. Верно ли, что $mu(t)$ стремится к некоторому пределу при $tto+infty$ для всех $a_0, a_1 > 0$? Если не для всех, то для каких?
  2. Если предел существует, то как его значение зависит от $a_0, a_1$?

Вопрос второй. Может ли поддержка кода стать причиной неограниченного роста количества программистов?

Обозначим $q(t)$ количество программистов, занятых разработкой нового кода. Как и выше, $y(t)$ — объём кода, написанного к моменту времени $t$. Тогда

$frac{dy(t)}{dt}=a_2 q(t); a_2in mathbb{R}, a_2 > 0.$

Пусть поддержкой кода заняты $p(t)$ программистов. C учётом старения кода,

$p(t)=a_3(y(t)-y(t-h));a_3in mathbb{R}, a_3>0.$

Откуда

$p(t)=a_3int_{t-h}^{t}frac{dy(s)}{ds}ds=a_2a_3int_{t-h}^tq(s)ds.$

Если $q(t)leq C_1$, то

$p(t)leq a_1a_2C_1h.$

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

Заключение

Рассмотренные модели являются «мягкими» математическими моделями [2]. Они очень просты. Тем не менее, зависимость результатов моделирования от значений параметров соответствует ожидаемой для реальных систем, это говорит в пользу адекватности моделей и достаточной точности для получения качественных оценок.

Список литературы

1. Эльсгольц Л.Э., Норкин С.Б. Введение в теорию дифференциальных уравнений с отклоняющимся аргументом. Москва. Издательство «Наука». 1971.
2. Арнольд В.И. «Жесткие» и «мягкие» математические модели. Москва. Издательство МЦНМО. 2004.

Автор: Дмитрий Пашуткин

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js