Express 42
Компания
32,34
рейтинг
3 июля 2013 в 18:55

Разработка → Цена сложности

Мне всегда сложно было объяснить даже самому себе термин «технический долг». Никогда не было понятно, кто, кому, за что и сколько должен. И, если это долг, то как его выплачивать и можно ли выплатить полностью? А можно ли сделать так, чтобы должны были мне?

Совсем недавно прочитал статью Криса Гейла из Yammer, который вводит понятие «цена сложности» (complexity cost), которое мне гораздо ближе и понятнее. Цена сложности описывает ровно тот же аспект разработки сложных систем, что и технический долг, только вносит, с моей точки зрения, большую ясность.

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

Крис пишет в своей статье, что время, которое необходимо потратить на то, чтобы сделать новую функциональность — это самая малая часть затрат на эту функциональность. Он приводит пример, как он сделал что-то для Yammer за 1 час, а в течении следующих 5 лет потратил 40 часов, рассказывая другим инженерам, что это такое и как оно работает. А это значит, что суммарно на эти разговоры ушло не меньше 80 часов, ведь другой инженер тоже тратил на это свое время.

Сложность можно разделить на два вида. Первый вид сложности — это количество функций, которые есть у системы. Второй вид сложности — это оверинжиниринг при реализации какой-то функции. И чем больше функций у продукта, тем дороже его поддержка и изменение. Этот вид сложности можно уменьшить только одним способом — убрать какую-то функцию. Крис пишет, что в Yammer после добавления новой функциональности, они какое-то время наблюдают за ней, и если она не используется и не приносит ценности, то ее убирают. Более того, они меряют, как используются все функции на сайте, для оценки того, во что стоит вкладывать усилия, а от чего можно отказаться.

Второй вид сложности — ненужная сложность, лечится только зрелым инженерным подходом. Вместо того, чтобы сделать что-то «круто» (эта болезнь есть не только у русских молодых инженеров), необходимо думать о том, как сделать что-то максимально просто. Либо упрощать что-то, что уже используется в проекте.

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

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

В нескольких проектах, которые мы консультировали, и на которых использовалась реляционная СУБД, мы избавлялись от MongoDB, значительно упрощая их поддержку.

Когда менеджер спрашивает: «Сколько времени займет сделать вот такую штуку?», — надо сразу подумать о том, что этот вопрос практически лишен смысла, потому что время поддержки и доработки во много раз превышают время создания новой функциональности.

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

А вопросы, которые я поставил в начале статьи, можно превратить всего в один: «Сколько мы переплачиваем за сложность?» Если бы эту цифру можно было посчитать в деньгах, то это и был бы «технический долг».
Автор: @evtuhovich
Express 42
рейтинг 32,34
Компания прекратила активность на сайте

Комментарии (35)

  • +7
    Мне кажется все правильно, всегда радуюсь когда удается удалить какое-то количество кода из проекта.
  • +6
    Цена сложности описывает ровно тот же аспект разработки сложных систем, что и технический долг, только вносит, с моей точки зрения, большую ясность.

    Думаю, это все-таки разные понятия.
    Технический долг это скорее то, что не было сделано вовремя и поэтому повлекло за собой время работы по поддержке, ответам на вопросы, исправления.
    • +6
      Не обязательно повлекло. Просто не было сделано. А вот время на поддержку и т. п. — это уже проценты по этому долгу. Нередко сложные.
  • НЛО прилетело и опубликовало эту надпись здесь
    • 0
      Я тоже не понял фразу про MongoDb — 3 раза перечитывал.
    • +10
      Автор написал, что если в проекте была и реляционная СУБД, и Монго — то от Монго они отказывались и получали минус один сервис, который необходимо поддерживать.
      • +2
        Спасибо за пояснения, я это и имел в виду, но косность речи и отсутствие филологического образования меня подвели.
    • НЛО прилетело и опубликовало эту надпись здесь
    • +2
      Да, я не очень внятно написал. Когда на проекте есть уже СУБД и она активно используется, а MongoDB используется для всякой ерунды, то отказаться от MongoDB вполне оправдано. Но ситуация может быть и противоположной, правильного ответа на все вопросы нет.
      • 0
        Просто в РСУБД рано или поздно прорастает бизнес-логика и так просто уже от нее не избавиться.
    • 0
      По аналогии с экономикой можно сравнить излишнюю сложность с вложением в непрофильный убыточный актив. Т.е. более точно назвать это техническим пассивом.
  • НЛО прилетело и опубликовало эту надпись здесь
    • 0
      Чей-то статья в вики сильно попахивает булшит бинго. «Events can be more easily tracked as well as resolving documented process control and granular reporting issues» во вступлении — эээ щито?
      • +1
        Тема свежая, и в википедии освещена так себе.
      • НЛО прилетело и опубликовало эту надпись здесь
  • +1
    Технический долг это не совсем «цена сложности». Технический долг постояно накапливается в развивающемся проекте. Это незакрытые TODO, сделанные наспех костыли и т.д. Единственный способ уменьшить долг — тратить некоторое время на упрощение и чистку кода. Но тут, как и везде нужна мера :)
    • 0
      А разве проект, который держится только за счёт лесов из костылей — не сложный проект? Я бы сказал, хаотически сложный.
      • 0
        Тут уже тонкое различие в терминологии, я подразумевал «нормальный проект», в котором кол-во костылей все таки не зашкаливает. Цена сложности — это скорее цена не текущих мелких костылей, а все таки необоснованных проектных решений. Например притащить библиотеку с собственным менеджментом памяти ради функции подсчета факториала.
  • +1
    > Хотя в чистом виде «сложность» мы измерить не можем,

    Можем. Почитайте ru.wikipedia.org/wiki/Колмогоровская_сложность
    Если вообще банальным языком выражаться — сложность программы пропорциональна размеру кода в байтах
    (update: ну ладно… пусть не «измерить», но «оценить» можем! часто этого уже достаточно)
    • 0
      сложность программы пропорциональна размеру кода в байтах


      Не согласен. Сложность программы во многом зависит от связанности компонентов. В случае слабосвязанной архитектуры — это сумма сложностей всех компонентов, сложенное со сложностями интеграции этих компонентов (конфиги, адаптеры и т.п.) В случае с сильносвязанной архитектурой (чаще всего это просто отсутствие архитектуры) я бы сказал, что сложность — это произведение сложности всех компонентов, помноженное на их интеграцию.

      Это по личному опыту поддержки/расширения и тех, и других систем.
      • 0
        Мне кажется, в этой формуле ещё не хватает чего-то вроде сценариев использования. То есть, к примеру, вы указали, в качестве сложности интеграции, конфиги. Конфиг, как таковой — может иметь два назначения: подстройка под окружение и подстройка под задачу. И если ПО имеет множество сценариев использования, это как правило отражено в конфиге, что повышает его сложность многократно. Даже если конкретный используемый в текущий момент конфиг прост и мал, документация по нему может содержать сотни параметров с огромным числом вариантов значений, что порождает сложность, оторванную от таких показателей, как количество байт или связанности с другими компонентами. Кроме того, если речь идёт не о развертывании, а о разработке, там происходит примерно тоже самое. Любое изменение в код приходится делать с учётом имеющихся сценариев использования, что требует многократно больше времени для анализа при внесении даже самых простых с виду изменений. При этом, самого по себе кода может быть сравнительно мало, вопрос в том, каким именно он должен быть, чтобы помимо внесения новой функциональности или оптимизации он не нарушал имеющийся ход событий.
  • +3
    Технический долг это совсем не «цена сложности».
    Сейчас поясню.
    В любом проекте, в любой задаче есть три входящих параметра — сроки, цена и качество, причем заказчик может выбрать любые полтора.
    Например, стоит задача «покрасить стену».
    Качественное исполнение предполагает отдирание старой краски, шпатлевку трещин, грунтовку и нанесение трёх слоёв нормального покрытия с необходимыми интервалами на подсыхание.
    Но если заказчик поставил задачу «срок — два часа, денег минимум возможного», то он получит один слой из смеси серо-буро-малиновых остатков, который отвалится после ближайшего дождя и сильно затруднит последующий нормальный ремонт. Плюс в нагрузку — заляпанные краской окна и прилегающую территорию. Вот такие действия и есть «технический долг».
    Если команда работает в условиях авралов и дедлайнов — половина проекта будет из таких вот «долгов». Хотя, если изначально работать на качество, никакой дополнительной сложности не будет — будет просто качественно покрашенная стена.
    • 0
      Добавлю — такая «покраска» может быть оправданой в каких-то случаях. Но. Грамотный менджер должен не порадоваться, что все так ловко вышло, а вздохнуть, и записать себе в черную тетрадочку — такого-то числа создан технический долг в размере ХХ человеко-дней из-за некачественной работы ради укладывания в сроки.
    • 0
      Кстати, по поводу
      сроки, цена и качество
      Я не так давно обнаружил, что качество — это две абсолютно разные вещи в одной. В менджементе под качеством понимают соответствие требованиям, т.е. набор фич грубо говоря, возможности продукта. Но есть еще качество примененных решений, и менеджемент всегда почему-то подразумевает что это качество не обсуждается и всегда запредельно. Тем не менее любой разработчик знает, что требование заказчика можно сделать как следует, а можно закостылить. Для менеджера качество соблюдено, но накоплен технический долг.
      Соответственно мы имеем не треугольник а квадрат: срок-возможности-качество-стоимость.

      PS: Если копать дальше и проанализировать стоимость и срок окажется что нельзя просто так выбирать что-то из этого. Срок увеличивает стоимость. Увеличение стоимости (расширение команды) практически не уменьшает срок, а часто даже увеличивает
  • 0
    > Крис пишет, что в Yammer после добавления новой функциональности, они какое-то время наблюдают за ней, и если она не используется и не приносит ценности, то ее убирают.

    Инетересно как относится Крис к трате времени на это наблюдение? Или наблюдения — работа не инженерная, поэтому в общий зачет не идет? )
    Серьезно, я согласен с автором во многом, кроме подсчета времени на объяснение кода другим разработчикам в сумме времени потраченном на создание кода. Можно с таким же успехом подставлять в уравнение время на кофе.
  • 0
    Автор, при том кто Вы и какие методологии продвигаете — не развернуть тему до конца просто стыдно. Алгоритмические метрики сложности ПО существуют годы, десятки лет. Анализаторы сложности (JDepend, PHP Depend, etc) используются в Continuos Integration в каждом мало-мальски серьёзном проекте.

    Abstraction instability chart, average hierarchy heigh, cyclomatic complexity, ещё десяток основных метрик. Все цифры есть как на ладони. Ваши филосовствования нафиг никому не нужны. Берите инструменты и применяйте их на практике.
    • 0
      Безусловно, я знаю о существовании такого класса инструментов.

      К несчатью, помимо того, что они, по моему мнению, малоинформативны, они никак не учитывают сложность инфраструктуры, не отвечают на вопрос, можно ли сделать какую-то часть проще, а какую-то функциональность выкинуть.

      И, по моему мнению, какие-то концепции, чтобы размышлять и обсуждать неизмеримые и неформализуемые вещи, необходимы, и «цена сложности» — вполне удобная и понятная концепция, которую предложил Крис Гейл.
  • +1
    Никогда не было понятно, кто, кому, за что и сколько должен. И, если это долг, то как его выплачивать и можно ли выплатить полностью?

    Вы. Должны сами себе из прошлого. Работу по поддержке проекта. Сейчас вы быстро сделали костыль вместо длительной разработки и взяли время в долг у себя. В будущем вам придётся это время вернуть с процентами на поддержку костыля.
    • 0
      Долги взятые в одном месте могут оказаться почти бесплатными, а могут очень быстро обрасти процентами, если к костылю продолжают приставлять подпорки.
  • +3
    >термин «технический долг». Никогда не было понятно, кто, кому, за что и сколько должен
    Есть много таких непонятных долгов, например супружеский…
  • 0
    Не помню кто сказал, но очень «в яблочко» на тему усложнения и простоты:

    «Простота — это самое сложное в мире. Это крайний предел опытности и последнее усилие гения.»
    • 0
      lex parsimoniae, Бритва Оккама, 12-13 век
      «Не следует привлекать новые сущности без крайней на то необходимости»
  • 0
    Когда я вижу обсуждения на тему «простота=надёжность», сразу вспоминаю старую статью Михаила Ваннаха из Компьютерры:

    Трехдюймовая пушка образца 1902 года была очень проста. Но перевозить ее на сплошных колесах можно было лишь лошадьми. И недалеко! В то же время гораздо более сложную (но и невероятно технологичную!) ЗиС-3 образца 1942 года можно было волочь за «студером» тысячи верст по не ставшим лучше российским дорогам. Введение шин и рессор повысило надежность!
  • 0
    Когда начинают считать «40 часов за 5 лет» на рассказ про какую-то сложную фичу, надо, наверное, прикинуть, сколько экономится времени этой самой фичей. Но 40 часов за 5 лет — это очень немного, чуть больше, чем потратит разработчик за те же 5 лет на открывание двери офиса с тугой пружиной. Или на проход через турнике с электронным пропуском. Или в туалете на сушку рук ветродуем, в сравнении с вытиранием рук бумажным полотенцем. С тем же успехом можно составить исследование зависимости потерть времени от формы чайного пакетика )

    Время — важно. Но куда важнее понимать, что за что платим. Обычно новинки все же стоят затрат на них, как времени, так и сил, особенно, если в компании есть привычка знания передавать коллегам.

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

Самое читаемое Разработка