«Синдром сантехника»: правила работы с легаси-кодом в тестировании



    Многие сталкивались с новичком, который приходил в проект и заявлял, что «все необходимо срочно переделать». А некоторые и сами это говорили или думали. Это — «синдром сантехника»: поведение, характеризующееся желанием все сделать по-своему, «правильно», при работе над новым проектом или при переходе на новую работу. А значит, существующий код, технологии или инструменты нужно переписать, желательно «под себя». Тема была бы банальной, если бы не повторялась так часто от проекта к проекту, с каждым новым набором штата.

    Чем дольше «живет» проект, тем больше в нем накапливается «исторического», наследованного кода, и тем выше становятся шансы встретить горящие глаза поражённого «синдромом сантехника». В этом посте хочется рассказать, каких принципов придерживаются в Parallels (сразу спойлер – это принцип «не навреди»), и как мы поступаем, если решено все-таки «все переделать». Хотя в целом мы считаем, что синдром этот надо лечить, и что использование легаси иногда даже полезно, так как позволяет выпустить продукт вовремя и не тратить время на разработку своих технологий.

    Когда работаешь с «программами-долгожителями», достаточно большой процент в них занимает легаси-код. Например, Parallels Desktop разрабатывается уже более 15 лет. С каждым годом команда расширяется, приходят новые люди, смотрят на то, что написано и заявляют: «Все криво, давайте оторвем руки программисту и все перепишем». Знакомая ситуация?

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

    Мудрость, проверенная опытным путем


    I. Лучшее — враг хорошего. Если унаследованный код или система выполняет всю необходимую функциональность с приемлемым качеством, то не надо его улучшать, лучше направить свою кипучую энергию на что-нибудь более полезное.

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

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

    Что делать?


    Шаг 1. Cмотрим, кто сказал
    1. Фрилансер. Чаще всего полностью переделывать код кидаются люди, у которых нет опыта присоединения к большому проекту со стороны. Например, я сам сначала работал на фрилансе, писал проекты с нуля, и у меня, как у многих подобных разработчиков, сформировалась довольно устойчивая привычка – делать именно так, как мне удобно.

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

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

    4. Высококлассный специалист. Единственный тип «заявителей», к которым стоит прислушаться, хотя и кидаться переделывать по его советам все равно не стоит, пока не осуществлен Шаг 2. Не исключено, что нам достался профессионал ультра-класса, и он действительно сможет доказать, что у нас не так, и сможет сделать лучше. Но дело в том, что я ни одного человека уровня Senior с такими заявлениями не встречал. Когда человек дорастает до такого уровня, то уже может представить себе проект в целом и понимает все недостатки «революционного» метода.

    Шаг 2. Заставляем аргументировать
    Первым делом человека нужно останавливать и проводить анализ его аргументов. Инициировать это разбирательство должен тим-лид. С оговоркой, что «синдромом сантехника» не начал страдать человек, сам пришедший тим-лидом. Тогда разбор полета – дело проджект-менеджера, хотя, честно говоря, зрелый тим-лид никогда не инициирует полную переделку без серьезнейшей аргументации.

    Какие аргументы не пройдут:
    «Мы напишем свое, с шахматами и поэтессами»
    Чаще всего, если продукт уже давно существует на рынке, то он уже как-то работает. Он уже показал, что, несмотря на всю ужасность того, что там под капотом, он функционирует. Например, у нас есть Parallels Desktop (решение для запуска Windows и других операционных систем на Mac без перезагрузки), и иногда можно услышать от новичков: «как-то у вас тут все слишком сложно, давайте я напишу свою виртуальную машину». А поскольку такие вещи в принципе невозможно с наскока сделать, то, когда человек это говорит, то он либо не в теме, либо не в себе. Нужно дать ему сначала набраться опыта в проекте и понять, почему именно так он был реализован изначально.

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

    Почему многолетний код большого проекта лучше вообще не трогать


    Можно вообще убить свой проект
    Где гарантия того, что вы вообще заново что-то напишете и оно будет корректно работать? Ведь этого сейчас еще нет. С точки зрения бизнеса жить нужно сегодняшним днем и обеспечивать непрерывность получения доходов.

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

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

    И начинается: давайте мы все эти костыли повыкидываем, так как это непонятно что и портит код. И не думают, к чему это приведет. Например, когда мы делали один из своих патчей для ядра Linux, то в одном месте грохнули такой костыль: очень уж он был некрасивый и при этом довольно плохо описанный. А потом в обсуждении узнали: определенное оборудование без этого кладжа не работает. Да, оно больше не выпускается, но все же есть у пользователей и работает. И потеря поддержки этого оборудования противоречит философии сообщества Linux. Пришлось переписать наш код так, чтобы этот воркэраунд сохранился один-в-один, и после этого все были удовлетворены.

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

    Можно потерять инициатора и проект
    «Синдром сантехника» поражает, в основном, новых сотрудников. Стоит помнить, что такие люди находятся в группе риска, потому что могут уйти из компании на испытательном периоде (недаром говорят, что испытательный срок – не только для человека, но и для компании). Человеку дали карт-бланш, он начал переделывать, а потом заявил, что ему в компании кофе не нравится и ушел. Это очень опасная ситуация. Получится, что нового ничего нет, а старое уже сломали. Дальше кому-то (и отнюдь не энтузиасту) придется приводить это в работающий вид.

    Что делать, когда решение не переделывать очевидно, а человек «горит идеей»?


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

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

    Направить его энергию в другое русло
    У большинства крупных продуктов всегда есть в наличии какие-то узкие места и проблемы, которые регулярно возникают, так как снаружи все меняется. Хотя нового человека, на мой взгляд, все-таки очень опасно пускать к коду, пока он пару месяцев не поработает с дебаггингом мелких багов, не познакомится с существующим кодом и не докажет уровень своей квалификации.
    Можно дать ему задачу из каких-то боковых проектов, чтобы он запилил именно туда свое новое и посмотреть, что получится. Это при условии, что есть такие слоты в ресурсах, так как рисерч-задач тоже ограниченное количество, здесь как с венчурным бизнесом – в 100 компаний вложился, с одной получил отдачу.

    Когда переделывать все-таки надо


    Продукт в существующих условиях умирает
    Аргумент за переделку – если внешняя среда изменилась настолько, что существующий продукт перестал работать. Например, когда выпустили новую операционную систему, на которую массово начали переходить пользователи, но в этой ОС что-то поменяли так, что ваш продукт, который под предыдущими версиями нормально работал, перестал функционировать или пользователю стало совершенно неудобно им пользоваться. Или когда платформа отмирает – в пример из старенького можно привести BeOS, под которым достаточно много работали с мультимедиа-продуктами, например, сочиняли музыку. Система умерла, а поскольку она была довольно самобытной, то коды из нее практически не переносили в другие системы. С самой OS BeOS то же самое случилось: были компьютеры Atom, на которые они ориентировались, а затем производитель перестал выпускать эти процессоры, и люди, которые писали под этот компьютер, фактически остались у разбитого корыта. И были вынуждены достаточно срочно адаптироваться под Intel, что у них получилось плохо — ниша была занята и там царила другая ОС. И чтобы хоть как-то продлить свою жизнь, им пришлось серьезно переделывать в сторону улучшения портируемости и так далее.

    «Синдром сантехника» сработал: этапы переделки


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

    Если заменять компонент, то желательно делать так: если внешний интерфейс не требует изменения, то мы спокойно делаем вторую реализацию. Желательно сразу найти линии раздела: здесь остаётся старое, а вот тут уже можно переделывать, найти точки входа. И так, сохраняя интерфейс, поменять начинку.

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

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

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

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

    Вместо заключения


    Один мальчик родился с гайкой вместо пупка. И он периодически у родителей спрашивал, почему у него там гайка. Родители обещали рассказать ему об этом на 14-летие. Парню исполнилось 14. И вот он опять подошёл к отцу с матерью и спросил, почему у него гайка вместо пупка. Родители пообещали рассказать ему об этом, когда ему будет 18 лет. В 18 лет он спросил снова и тогда ему рассказали, что есть тропический остров на котором растет пальма, а под этой пальмой зарыт сундук. Там ответы на все его вопросы. Парень долго копил денег и всё таки отравился на этот остров. Нашёл пальму, откопал сундук, в котором лежал гаечный ключ. Не долго думая, он открутил гайку найденым ключом и у него задница отвалилась. Мораль: иногда просто не стоит искать приключения на пятую точку.
    Parallels
    109,00
    Мировой лидер на рынке межплатформенных решений
    Поделиться публикацией

    Комментарии 49

      0
      Ну что тут сказать… Все так и есть, в погоне за «правильным» и «красивым» чрезмерно самонадеянными товарищами очень часто (не всегда конечно) получается известная субстанция, которая сама по себе вдруг оказывается и «некрасивой» и вдобавок «неправильной». И не особо рабочей.
      Хотя чего греха таить, 20 лет назад мне тоже много что казалось «неправильным». А сейчас мой код/подход для молодых кажется «неправильным, несовременным, олд-чего-то-там» (хотя если честно, то все равно каждый раз после сдачи проекта, его хочется в куче мест переделать). Но он хотя бы работает, как было задумано, поэтому тут в игру вступает общеизвестное правило «Если работает — ничего не трогай, ничего не меняй».
        0

        То есть вы пишете такой код, который лучше не трогать вообще — даже сразу после его написания?)

          0
          Нет конечно :)
          Просто у людей с описанным «синдромом сантехника» он (да и любой другой, кроме их собственного) вызывает желание «все переделать».

          Например, я часто использую вариации венгерской нотации при работе (во-первых, я к ней еще с прошлого века привык, а во-вторых удобно, когда код приходится писать сразу на нескольких ЯП в рамках одного проекта. С моей точки зрения конечно), а «продвинутой молодежи» это не нравится, мол это несовременно и не нужно, да и вообще, как так можно «hello world» написать как
          echo 'hello world';

          а не как
          
          ...
          class HelloWorld {
          ...
          ...
          ...
          }
          ...
          $SayHello = new HelloWorld();
          ...
          


          Да и вообще, на этом говне никто не пишет, нужно использовать ЯП ХХХ.
          И скобки нужно расставлять вот так
          class foo {
          ...
          }
          

          А мол ты пишешь «криво и неправильно» вот так:
          class Foo 
          {
          ...
          }
          


          И все в таком духе :) Для описанного в статье «дартаньяна» неважно кто и как писал код, ему важно показать, что он — «дартаньян», а остальные — криворукие нубы.
            0

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

              0
              Ну я так и предпочитаю делать. На мой взгляд, читаемость у такого варианта:
              if (a != b)
                 {
                 for (i = 0; i < 10; i ++)
                      {
                      switch (e)
                           {
                           case ...:
                                break;
                            ...
                           default:
                                ....
                           }
                      e += i;
                      }
                 }
              

              лучше, чем у такого:
              if (a != b)  {
                 for (i = 0; i < 10; i ++) {
                      switch (e) {
                           case ...:
                                break;
                            ...
                           default:
                                ....
                           }
                      e+=i;
                      }
                 }
              


              Но сколько я уже слышал в свой адрес комментариев, что вариант 1 «неправильно и вообще делать нужно вариант 2, ибо только он есть тру»…

              Может, конечно, оно у кого-то и тру, но лично мне второй вариант читать тяжелее.
                +4

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


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

                  0
                  Имхо, тут вы неправы.

                  В чем? В том, что мне нравится/привычно/удобно скобки расставлять вот так? :)
                  Когда я работаю один, меня все устраивает в моей стилистике. Я свободно читаю свой код спустя и 10 лет. Переделать конечно хочется, ага. Но читается легко.

                  Если мне случается поработать с командой, то тут правило простое — как в этой команде принято делать, так делаю и я, ибо в чужой монастырь со своим уставом не ходят. Если в команде сделана ставка, скажем, на серверный рендеринг — значит это сделано по каким-то известным им причинам. Если они предпочитают получать от бэка только JSON и делать с ним всякое на фронте — опять же, это их выбор.
                  Мое дело — это написать код под конкретную задачу/научиться чему-то новому/получить деньги, а не вступать в конфронтацию «как расставлять скобки», «нужна ли венгерская нотация в современном мире», или «вы делаете неправильно, серверный рендер — это аццтой (или наоборот)».

                  Если команду для проекта набираю я, то там могут быть претензии к совсем непонятному для меня коду, но обычно я не требую сменить стиль, достаточно более подробного комментирования кода, на тот случай, если в нем придется рыться через хх лет. Исключения составляют лишь очевидные малопонятные костыли.
                    0
                    почему бы не делать по массовым стандартам?
                    Вот я щас пришел в проект, где сперва писали в одном стиле, потом в другом, потом в третьем. И все не по стандартом. Код читать нереально.
                    где-то перенос скобки, где-то нет, а где-то вобще БЕЗ скобок!
                    Ну и вот что, теперь для чтения кода надо тратить в 2 раза больше времени минимум. понимание логики и того дольше.
                      0
                      Хотя бы потому, что когда тянешь весь проект самостоятельно, используя 3-4 разных ЯП, которые предполагают разные стандарты, то это местами сильно тормозит процесс.
                      (например, из недавнего: на Cи делаем демона-прокладку, который опрашивает некоторую аппаратную часть (датчики) и складывает сырые данные, PHP данные сортирует, облагораживает, распределяет по БД, ну а поверх этого работает фронт на JS/HTML/CSS)
                      Поэтому подвести все к единому виду — на мой взгляд нормальная идея.

                      Ну а в команде обычно работаешь с 1 ЯП, там какой стандарт задали, так и делаешь, ведь скачек между стилистикой нет.
                        0
                        Ну да, у каждого своя логично выстроенная правда и своё видение мира в целом.
                        Ну получается а после все хоть огнем гори)

                        Ведь некоторые программисты делают как им удобно, а не как конечному клиенту.

                        Конечно, может быть частный случай, когда вы и есть клиент/директор, который ввел правила удобства ведущему программисту-мастеру на все ЯП. Все равно без него все пойдет прахом :)
                          0
                          Если бы все всегда были одинаковые, не было бы технического прогресса :)
                  +4
                  Если первый вариант выглядит действительно так, как вы задумывали, то могу отметить что я кажется первый раз в жизни вижу скобки сдвинутые на уровень вложенного кода и это выглядит как минимум странно
                    0
                    Это отголоски древних IDE, которые не умели в нормальное автоформатирование.
                    Поэтому процесс выглядел так: TAB в настройках = 4 и понеслась.

                    Претензий к коду, который предлагает автоформатирование современной IDE, типа
                    if (a != b)
                    {
                        ...
                        bla-bla
                        ...
                    }
                    

                    у меня тоже нет. А вот короткую запись я обычно разворачиваю вручную, или настраиваю на полную, если IDE это позволяет. Привычка.
                  0
                  У вас есть ссылки на исследования показывающие это?
                    +2

                    Попытался сейчас найти но безуспешно. Суть была такова:
                    Если мы спрячем весь текст за неизвестными символами и посмотрим на код, то тот пример о котором мы сможем понять больше -> лучше.


                    Под спойлерами примеры. Откройте по очереди и попытайтесь понять что там спрятано.


                    Короткое форматирование
                    ██████ ████ █████████████ █████ █████ ██████ █
                        ████████████████████████
                            ██████████████████████
                            ███████████
                            █████████████
                    
                        █████████
                    
                        ████████████████████████████
                            ██████████████████████
                        ████████
                            ███████████████████████████
                        █
                    
                        ████████████████████████████████████████████████████████████████
                    
                        ███████████████████████████████████████████████████
                            ███████████████████████
                                ██████████████████████████████████
                            █
                        █
                    █

                    Длинное форматирование
                    ██████ ████ █████████████ █████ █████ ██████
                    █
                        ████████████████████████
                            ██████████████████████
                            ███████████
                            █████████████
                    
                        █████████
                    
                        ██████████████████████████
                        █
                            ██████████████████████
                        █
                        ████
                        █
                            ███████████████████████████
                        █
                    
                        ██████████████
                            ███████████
                            ████████
                            ████████████████████████████
                    
                        █████████████████████████████████████████████████
                        █
                            █████████████████████
                            █
                                ██████████████████████████████████
                            █
                        █
                    █

                    Оригинал
                    public void AMethod(TypeA arga, TypeB typeb)
                    {
                        var path = Path.Combine(
                            arga.someInternalProp,
                            typeb.name,
                            "a literal");
                    
                        Result r;
                    
                        if (Path.IsAbsolute(path))
                        {
                            r = DoSomeStuff(path);
                        }
                        else
                        {
                            r = DoSomeOtherStuff(path);
                        }
                    
                        var response =
                            r.Success ?
                            r.Data :
                            new NullResult(arga, typeb);
                    
                        using (var reader = new ResponseReader(response))
                        {
                            while (readre.Read())
                            {
                                Console.WriteLine(reader.Current);
                            }
                        }
                    }

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

                    +4
                    Пишу так, как принято в языке (или как ide по умолчанию форматирует).
                    Для c#
                    {
                    },
                    для js, java {
                    }.
                    Проблем с переключением между двумя вариантами не испытываю, и с «самоваром» из одного языка не лезу в другой. Хорошо, когда за тебя уже решено, как надо делать.
                    0
                    есть PSR, реально код намного сложнее читается, когда инлайн операнды или скобки хрен пойми как понаставлены.
                    Есть стандарт — извольте следовать. Не хотите? Будут лететь камни.

                    Стандарты делаются как раз для того, чтоб другие люди быстрее и лучше вникали в код и все было единообразно
                      0
                      Мне казалось, что большинство таких вопросов покрываются стандартом кодирования и автоматическим форматированием. Энергию стоит тратить на что-то стоящее, чем обсуждать скобочки-пробельчики
                    0
                    А я вот и сейчас готов поработать на выходных или вечерами ради того, чтобы привести новый проект, попавший в мои руки, в приличный вид… Сначала документацию везде развешу, форматирование, потом выделю библиотечные методы, потом чуть сложнее переделки, стандартизацию, потом врапперы/хелперы какие-то для унификации, а дальше уже и «выхлоп» идёт — можно брать задачу, на которую раньше легко день уходил, делать за пару часов, а дальше идти пить пиво или ещё больше менять продукт.
                    0
                    Не согласен, если не закрывать тех-долг и не рефакторить старые решения рано или поздно разработка действительно придет к состоянию «продукт в существующих условиях умирает». При разработке нужно закладывать под это бюджет, с первого раза сложно получить стройную систему (особенно когда требования часто меняются). Кривая архитектура, legacy и высокий технический долг — в лучшем случае потери бизнесом денег каждый раз когда требуется внести в эту систему правки (вместо 10 минут-ной доработки — несколько дней на то чтобы разобраться в паутине костылей и встроить ещё один костыль чтобы ничего не рухнуло), а в худшем — смерть проекта.
                      +1
                      Надо считать выгоду от модификаций и сравнивать ее с «потерями бизнеса».
                      … потери бизнесом денег каждый раз когда требуется внести в эту систему правки (вместо 10 минут-ной доработки — несколько дней на то чтобы разобраться в паутине костылей и встроить ещё один костыль чтобы ничего не рухнуло)

                      Это крайний случай же. Бывают еще варианты «мы потратим неделю на переделки, зато у нас потом вот это вот будет правиться за 10 минут, а не за час». И если «вот это вот» в ближайшие лет 5 не планируется троготь более 30 раз, то модификации нерентабельны и «бизнес потеряет деньги» как раз на этих «улучшениях». И потом, правильный выбор между «много ресурсов сейчас» или «еще больше, но размазанные на несколько лет» — совсем не очевиден.

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

                        0
                        Ну если вот эти «30 раз» гарантировано не могут повлиять на работоспособность проекта это одно. А если эта часть кода связана со сторонними сервисами? Тогда пара недель работы программиста «про запас» может оказаться дешевле временной неработоспособности элемента, из за сложности с внесением правок.
                        P.S. Понятно что это всё тонкости формулировки конкретного вопроса, от чего и зависит ответ.
                          0

                          Oracle как-то справляется.

                            +1
                            Такие корпорации-гиганты могут годами и десятилетиями делать всякую стремную фигню, и все равно по инерции и за счет накопленной репутации и базы клиентов будут держаться на плаву.
                            А для компаний рангом поменьше это уже будет фатально. Тут где-то недавно была статья про проблемы Notepad++ — что мол там ужасная кодовая база, в итоге новые фичи появляются ооочень медленно, что позволило более новым редакторам типа Sublime вырваться вперед.
                          +1
                          Согласен с вами полностью. На моём текущем месте имеем то, что несколько высокооплачиваемых специалистов по несколько дней дебажат нигде не задокументированное легаси.
                          +3
                          Всё правильно, но автор упустил один положительный аспект переделки. Если 10 раз переделать свою операционную систему, то можно, наконец, понять как она работает и нереально прокачаться в кодинге. :)
                            0
                            Этот аспект положителен с точки зрения сотрудника, а статья все-таки скорее описывает ситуацию с точки зрения бизнеса.
                            0
                            из старенького можно привести BIOS, под которым достаточно много работали с мультимедиа-продуктами, например, сочиняли музыку.

                            У меня аж челюсть отвисла — как под BIOS можно написать мультимедиа-приложения? Пока не понял, что имеется ввиду BeOS. Правда на сегодняшний день она не так уж и мертва — вышла бета-версия Haiku — преемницы BeOS.
                              0
                              Я от этого абзаца целиком вздрогнул. Сперва BIOS, потом Atom… Нет, я конечно допускаю что был прям какой-то компьютер Atom, после смерти которого разработчикам пришлось перейти на Intel(компьютер? процессор? WTF!?), но совпадения слишком уж совпадения. Особенно эпично выглядит на контрасте с остальным текстом
                              +2
                              Двоякие ощущения от этой статьи, ибо от нее складывается ощущение, что legacy-код лучше не трогать. Я категорически не понимаю этого, для меня это из разряда старческого консерватизма, который не редко вредит, чем помогает.

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

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

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

                              Статья вредная и однобокая. Переделывать старый код не только можно, но и надо, главное делать это осторожно, планомерно и частями. Ну и соответственно чтобы аргументов было чуть по более, чем у человека с синдромом сантехника.
                                +1
                                А вы точно читали статью? Раздел «Мудрость проверенная опытным путем» говорит то же самое что и вы просто другими словами. А в остальной части напоминают, что не всегда стоит этим заниматься.
                                Синдром сантехника наблюдается у любого разработчика. Это нормально. Ненормально — не уметь его сдерживать
                                +2
                                Вы чуть-чуть путаете «переписать» и «отрефакторить». Рефакторинг кода — это самое важное для программы, кроме её создания. Рефакторинг — единственный метод сделать настоящий code review на высоком уровне (по уровню абстракций). На момент написания ТЗ было неполным, а полным оно стало в момент окончания написания кода. И уже имея на руках полное ТЗ можно начинать писать нормально. После того, как в коде появится стопятьсот новых фич, придётся рефакторить снова.

                                Единственное основание для не-рефакторинга — maintanance only режим, в котором новые фичи не появляются. Если появляются — надо.

                                А вот «всё переписать» — это чаще всего от нежелания читать старый код. Никто не любит читать код. Но надо. Так что не переписывать, а рефакторить.
                                  0
                                  Есть один знакомый, так при установке игры на d: в Games, установщик предлагал c: и Program Files, так он удалял всё полностью и заново прописывал, да, делал ошибки в пути, но принципиально удалял всё строку. Второй же — редактировал Program Files до Games. В первом случае товарищу не нравится ничей код, всё нитак, а второй же — может воспринимать любой код. Так что, эти всё подходы к чтению и переделыванию «создаются» еще в детстве. И их сложно перебороть.
                                    +1
                                    Не в поддержку или упрёк, но просто факт, к чему может привести такое легаси. Достаточно вспомнить недавний перевод тут на хабре о дремучих джунглях оракловской субд. Тоже много легаси, всё покрыто-перепокрыто тестами, всё работает, но есть куча флагов и поведения с какими-то неявными (до внесения изменений) зависимостями.
                                    Рефакторинг, всё же, требуется по мере развития продукта, иначе может получиться кадавр.
                                      0
                                      А в таком контексте даже интереснее… Просто я как прикладной разработчик, считаю Oracle — лучшей sql-субд с которой приходилось работать, поэтому читал про внутренности с несколько смешанными чувствами.
                                        0
                                        О том, насколько громадное количество наслоений и костылей представляет из себя Oracle DB, я понял уже после того, как в первый раз настраивал Toad: больше 10 лет прошло, а я всё ещё помню название файла tnsnames.ora, и какой адок там творится.
                                          0
                                          Ну объективно, первичная настройка подключения к ораклу — то еще удовольствие. Зато почти одноразовое. Но что за проблемы у вас были с tnsnames? У него насколько помню довольно очевидная структура
                                          С другой стороны я прекрасно понимаю откуда там внутри плотное переплетение костылей. СУБД которая должна быстро работать на богатой куче архитектур и осей, причем коммерческая и при этом живущая дольше меня. Идеальные условия для разведения как по мне :)
                                            0
                                            Проблем особо не было, только непонимание, нафига вообще всё вот это извращение нужно, чего не могли сделать нормальный публичный сетевой RPC.
                                      0

                                      Непонятно несколько моментов:


                                      Получится, что нового ничего нет, а старое уже сломали

                                      Как так? Неужели совершенно нет истории изменений и/или всё переписывание ведётся на мастер-ветке? Если так, но не в переписывании проблема, и даже не в увольнении сотрудника.


                                      С точки зрения бизнеса жить нужно сегодняшним днем и обеспечивать непрерывность получения доходов

                                      Действительно ли так много бизнеса, следующего этим постулатам? А как же пресловутый Customer Retention, над которым теперь все так трясутся? Это, само собой, к теме статьи относится только косвенно.

                                        +1
                                        Мудрость, проверенная опытным путем

                                        I. Лучшее — враг хорошего.


                                        Всегда ненавидел эту фразу… Зачем делать посредственно и называть свой посредственный, плохо продуманный и плохо расширяемый код словом «хорошее», если можно сделать по настоящему хорошо и грамотно? Называть желание человек улучшить и оптимизировать код синдромом сантехника — значит просто бояться критики и обсуждений. Если кто-то хочет улучшить код — почему бы не выслушать его аргументы и не привести в ответ свои? Это просто защита серости, которую лучше из суеверия не трогать, лишь бы она не развалилась.
                                          0
                                          В копилочку ненависти:
                                          Лучше, чем надо — не надо.
                                          и
                                          Работает? — не лезь.
                                            0
                                            «don't fix what isn't broken»
                                            «не мешай машине ездить»
                                            0
                                            У вас просто «синдром сантехника». Архитектура? Не бывает хорошей архитектуры, это вы код читать не умеете /s
                                            0
                                            Стоит так-же упомянуть обратную сторону проблемы, когда бизнесс\команда не хочет переписывать legacy, либо делает это «на отстань». Так-же я не могу принять переписывание в виде «делаем новый фронтенд» + «прокси к легаси бекенду». А когда приходит формулировка «эта функция используется в куче мест продукта и если мы её перепишем, то нужно поддерживать обе версии» — хочется всё спалить.
                                              0
                                              На КДПВ микросервисы собственной персоной
                                                0
                                                Ну как можно было болт перепутать с гайкой? Болт там был, а за приключения на собственную задницу награждают орденом серебряной отвёртки.
                                                  0
                                                  Обычно «взять и переписать», идет вместе с нереальными сроками.
                                                  А давайте мы этот legacy код перепишем!
                                                  Тут работы на пару месяцев!
                                                  Хотя да. Его надо переписывать (рефакторить). Но шаг, за шагом.
                                                  Написал тесты на старую логику.
                                                  К этим тестам написал новую реализацию.
                                                  Долго, нудно и не интересно.
                                                  Обычно «сантехники» «сдуваются» на второй-третьей неделе :-)
                                                    0
                                                    Потому и следует начинать с написания тестов. Чтобы если/когда задор ушёл — выхлопом были хотя бы тесты, а не наполовину переписанный код.

                                                    Причём, с моей точки зрения, тесты в этом всём — как раз самое скучное, поэтому когда у меня снова случится обострение — большая часть тестов уже будет написана, и тут уже отвертеться много сложнее. :)

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

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