Цена сложности

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

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

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

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

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

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

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

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

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

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

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

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

    Подробнее
    Реклама
    Комментарии 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 лет на открывание двери офиса с тугой пружиной. Или на проход через турнике с электронным пропуском. Или в туалете на сушку рук ветродуем, в сравнении с вытиранием рук бумажным полотенцем. С тем же успехом можно составить исследование зависимости потерть времени от формы чайного пакетика )

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

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

                                          Самое читаемое