Comments 35
КМК, наглядный пример старого изречения: "можно решить любую проблему добавлением еще одного уровня абстракции, кроме проблемы слишком большого количества абстракций"
На практике я бы все-таки учитывал насколько легаси действительно легаси, и сколько нам его надо.
Я занимался сам изоляцией легаси, и это может быть очень круто — сам видел.
Но заниматься этим при каждом удобном случае… сомневаюсь. А уж особенно сравнивать это со сторонним кодом — очень странно. У легаси есть одно положительное свойство — оно, как правило, не меняется. Так что с точки зрения тестов чуть ли не первый кандидат на мок (хотя проблемы, которые описаны, безусловно имеют место быть)
Сильно зависит от определения легаси. Есть и такое (недословно): «легаси — код, при изменениях которого ты не можешь сказать, будут ли нежелательные сторонние эффекты».
Да, и поэтому это последний кандидат на изменение, если разработчики головой не заскорбели.
Сторонний продукт с которым идет сравнение, вполне может меняться (даже радикально) без малейших угрызений совести
Да, все так есть. И бывают случаи, когда надо править легаси, матюгаясь и скрестив пальцы, чтобы ничего не сломалось. И бывают случаи, когда лучше обернуть легаси и жертвовать чем-то ради того, чтобы не ковыряться в этом гуано динозавров.
Но посыл статьи ведь не в этом, а в сравнении легаси со сторонним кодом с точки зрения TDD. А это неочевидно — если и так необходимо оборачивать легаси, тесты тут уже побоку, а если дело только в тестах, то сравнение со сторонним кодом сомнительно хотя бы по вероятности изменения
А можно отгородиться от него обёрткой, которая с таким подходом через пару лет и для автора станет легаси, и он начнёт писать следующую обёртку. И, вместо того, чтобы исправить 1 проверку где-то в глубине первоначального кода, будет править 100500 обёрток, написанные под разные сценарии.
Ключевое тут — вы можете очень планомерно переводить проект на новую реализацию, покрывать все тестами, рефакторить и т.д.
Если вы боитесь править код — этот код определенно надо либо выкинуть либо переписать. И важно тут не просто героически ринуться переписывать а продумать стратегию тестирования, разобраться в эффектах которые этот код оказывает на систему, и изолировать в обертке все по максимуму.
Разве что функционал за который код отвечает пока не нуждается в изменениях. В этой ситуации если у вас есть свободная минутка можно просто добавить парочку интеграционных тестов (я их не люблю но обычно юниты для такого кода не подойдут).
Но нужно понимать, конечно, что нет абсолютных правил или догм. Главный критерий — увереннность в понимании того, чо старый код делает и на что повлияют потенциальные изменения.
Лучше не надо править старый код пока есть его использование без обёрток.Риски от правки старого кода никак не меняются, написана вокруг него обёртка, или нет.
А так да, придется тесты писать и думать что делаете, магии не бывает.
Кроме того, обёртки позволяют выявлять расхождения между поведением старого и нового кода за счёт вызова обоих и сравнения результатов по методике схожей с А/Б тестированием.
В каждый момент времени можно найти код с разной степенью устаревания, думаю, нельзя выделить конкретный момент, когда уже нужно делать обёртку над ним. Вндрение подобных абстракций, скорее, должно быть архитектруным решением, которое принимается на очередном цикле стратегического планирования.
Большинство пишут код так что уже через пару дней его можно считать легаси.
Одно точно ясно, что этим кодом мы полностью управляем…
Тогда скорее остаются вопросы: на сколько мы его знаем? на сколько он покрыт тестами?
На сколько он поддерживаемый?
Несколько забавных правил рефакторинга… это правило 3, прежде чем прежде чем рефакторить надо понять зону ответственности кода, надо код покрыть тестами…
Просто если мы будем относиться к легаси-коду как к стороннему модулю, то это говорит о том что этот код так и будет валятся неизменный, а также как до меня написали, мы добавим еще один слой абстракций… и тут возникает вопрос, а верно ли это? мы же управляем этим кодом.
То есть по факту можно покрыть код всякими фасадами, декораторами, адаптерами, наследованием и т.д. и т.п., но скорее это надо делать частично, если других вариантов пока нет, и поднимать вопрос об изменении архитектуры.
Я не вижу пока причин полноценно относиться к легаси-коду как внешней зависимости.
первые разработчики сделали код.
вторые сделали уровень абстракции над предыдущим кодом.
третьи сделали уровень абстракции над предыдущим кодом.
четвертые…
Если у вас есть кусок системы которые непонятно что делает, то вам в любом случае придется разобраться с тем, что оно делает. Вот только в случае «перепишу ка я с нуля», велика вероятность что на выходе получится другой непонятный кусок кода который будет непонятен уже третьему разработчику, ведь легаси он на то и легаси что объективно оценить задачу у вас не выйдет. А это значит что в какой-то момент вы пойдете на компромис «сделать задачу хорошо или сделать задачу что бы работало но с не такими жесткими факапами по срокам»
1) ЧТО это? Это мы, что ли, пять лет назад писали? Срочно дайте мне меня-пять-лет-назад!
2) «принцип дома программиста» — если на этот код чихнуть — все развалится. Это нормально. Легаси — это если оно разваливается, но ты не понимаешь даже того, почему.
3) Приоритетное. Взято с реального проекта(обработчик скриптового языка на Lua, аргументы частично удалены для сокращения обьема). Если при беглом пролистывании наметанный глаз видит такое — то это срочно нужно как-то куда-то деть и обращаться бережно, как с хрустальной вазой. В отличие от 2 пункта — касается комментов, а не самого кода.
-- пофикшу позже, юникод неработает. Почему? ХЗ. КОИ-8 навсегда. Armat.
function tmp (...)
...
end
-- я ХЗ на кой тут это надо, но без этой ереси все падает к del . А логи можно и почистить руками. David.
callerr (...)
WTF = GetScriptPosX(ScriptWay, ObrStroka, FlagZalypyByka)
-- Да, без флага никак. То есть совсем. И что он делает мы не знаем, возвращает nil. Но без него nil идет уже в основу. И как эта магия вызова сОтоны работает мы тоже ХЗ. Я не нашел даже где он выставляется - то ли в недрах функции, то ли вообще из двигла выдергивается, там, del, МАГИЯ происходит. David.
...
-- Я без понятия почему, но в двигле этих гомоdel значения XYZ мыши инвертированы. Кроме того, граничные значения опять таки инвертируются, так что далее - такой вот трэш. BK4Ever. И да, del v0.15.2 - ну просто полный del, баг на баге.
WTF4 = WTF4 * -1
if WTF4 == 128 then
WTF4 = 127
elseif WTF4 == -128 then
WTF4 = -127
elseif WTF4 > 128 or WTF4 < -128
callerr(...)
WTF4 = 0
end
SetScriptPos(X, WTF4, dec)
-- Почему везде DEC? Потому, что на дробных в одних местах надо точку, в других - запятую. В падлу, проще округлить. David.
Устаревший код – сторонний код