Подтвердить что ты не робот

Когда переписать базу кода с нуля

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

Вы можете прочитать статью здесь: Вещи, которые вы не должны делать

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

Код построен как веб-сайт, не имеет разделения проблем, нет модульного тестирования и дублирования кода во всем мире. Нет уровня данных, нет реальной бизнес-логики, если вы не подсчитаете кучу классов в App_Code.

Я сделал рекомендацию держателям акций, что, хотя мы должны хранить существующий код и выпускать исправления ошибок, а также некоторые незначительные выпуски функций, мы должны немедленно переписать его с помощью Test Driven Development и с четким разделение проблем. Я думаю о том, чтобы перейти по пути ASP.NET MVC.

Моя единственная забота - это, конечно, время, которое может потребоваться, чтобы переписать с нуля. Это не совсем сложно, довольно запущен веб-приложение мельницы с членством и т.д.

Есть ли у кого-нибудь из вас подобная проблема? Какие конкретные шаги вы предприняли?

UPDATE:

Итак... Что я в итоге решил сделать? Я принял подход Мэтта и решил реорганизовать многие области.

  • Так как App_Code получал довольно большой и, таким образом, замедляет сборку время, я удалил многие из классов и превратили их в класс Библиотека.
  • Я создал очень простой доступ к данным Слой, содержащий все ADO вызовы и создал объект SqlHelper для выполнения этих вызовов.

  • Я реализовал более чистое протоколирование
    решение, которое гораздо более кратким.

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

4b9b3361

Ответ 1

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

Проблема с дублированием кода? Вытащите его в библиотеку классов или утилит в центральном месте в следующий раз, когда вам придется исправить ошибку в дублированном коде.

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

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

Ответ 2

В книге Факты и ошибки в разработке программного обеспечения говорится об этом: "Модификация повторно используемого кода особенно подвержена ошибкам. Если более 20-25 процентов компонента должны быть пересмотрены, более эффективно и эффективно переписывать его с нуля". Цифры исходят из некоторых статистических исследований, выполненных по этому вопросу. Я думаю, что цифры могут отличаться в зависимости от качества базы кода, поэтому в вашем случае представляется более эффективным и эффективным переписывать его с нуля, принимая во внимание это утверждение.

Ответ 3

В статье Джоэля все сказано.

В принципе никогда.

Как указывает Джоэл: вы просто потеряете слишком много, делая это с нуля. Вероятно, это займет больше времени, чем вы думаете, и каков конечный результат? Что-то, что в принципе делает то же самое. Так что бизнес-пример для этого?

Это важный момент: стоит денег писать что-то с нуля. Как вы окупите эти деньги? Многие программисты игнорируют эту точку просто потому, что им не нравится код - иногда с обоснованием, иногда нет.

Ответ 4

У меня было такое приложение, и переписать было очень полезно. Однако вы должны попытаться использовать "улучшающую" ловушку.

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

Убедитесь, что вы решите, что именно будет изменено и что будет только переписано - заранее.

Ответ 5

Я был частью небольшой команды, которая переписала код с нуля, включая бизнес-правила обратного проектирования более раннего кода. Исходным приложением был веб-сервис, написанный на С++ (с регулярными сбоями и серьезными утечками памяти) и веб-приложение ASP.Net 1.0, а замена была веб-службой на основе asmx на С# 2.0 и веб-приложением ASP.Net 2.0 с Ajax. Это сказало некоторые вещи, которые команда сделала и объяснила руководству

  • Мы поддерживали существующую базу кода в производстве до тех пор, пока новый код не был готов.
  • Руководство согласилось с тем, что переписать (первый выпуск) не будет вводить никаких новых функций, а просто внедрять существующие функции. Мы добавили только 1-2 новых функций в конце.
  • Небольшая команда состояла из очень опытных разработчиков с отличной способностью понимать и сотрудничать.
  • Труднее было получить талант С++ в организации, а С# рассматривалась как лучшая альтернатива для будущего обслуживания.
  • Мы согласились на агрессивный таймфрейм, но в то же время были уверены и очень мотивированы для работы на С# 2.0, ASP.Net 2.0 и т.д.
  • У нас был лидер команды, который защищал нас от высшего руководства, и мы следовали за этим процессом.

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

Ответ 6

На ум приходит только одна квази-законная причина: политика.

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

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

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

Политика может быть огромной болью.

Ответ 7

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

  • Windows NT (сломался от старой кодовой базы DOS. На этом фундаменте были созданы Win2k, WinXP и предстоящий Win7. Да, Vista тоже. Последняя версия Windows на старой базе была печально известной WinME)
  • Mac OS X (перестроил свой флагманский продукт на FreeBSD)
  • Многие случаи, когда конкурент вытесняет де-факто стандарт. (например, Excel и Lotus 123).

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

Ответ 8

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

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

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

Ответ 9

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

Но если вы исправите существующий код за один раз, вы тот, кто знает, как работает денежная машина.

Ответ 10

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

По крайней мере, сразу начните писать тесты.

Ответ 11

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

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

Ответ 12

Я бы скорее делал вещи по частям, например, создавал back-end для базы данных с моделью данных, когда вы работаете в этих областях (то есть, сначала пользовательский логин, затем управление пользователями и т.д.), и настраивайте существующий интерфейс для использования нового back-end (интерфейс управляется, поэтому вы можете также добавить тесты). Это позволит сохранить существующий код с возможными недокументированными настройками и поведениями, которые вы бы не реплицировали, развиваясь снова с нуля, одновременно добавляя некоторое разделение проблем.

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

Ответ 13

Отвечаю: переписывайте с нуля как можно чаще.

Я потратил большую часть своей карьеры, наследуя дымящиеся кучи навоза, которые вежливо называли "программами", написанными молодыми, неопытными программистами, которых менеджеры считали "рок-звездами". Эти вещи, как правило, не могут быть исправлены, и вы в конечном итоге тратите в 10 раз больше усилий, чтобы они хромали, так как вы потратили бы просто переписывание их с нуля.

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

Говоря об этом, не все перезаписи - хорошая идея. Windows Vista, например.

Ответ 14

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

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

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

Ответ 15

Я думаю, это зависит от двух вещей:

1) Недопустимый базовый дизайн устаревшей кодовой базы,

2) Время, необходимое для перезаписи.

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

2) Несмотря на много кода и очень запутанные процессы запуска. Наш двигатель не так много делал. Так что переписать было не так долго. Иногда менеджеры не понимают, что функциональность сотен тысяч строк кода может быть перестроена за очень короткое время.

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

Теперь, если построение базовой функциональности займет у нас шесть месяцев, у нас не будет много аргументов.

Ответ 16

В экономике существует противоречивое утверждение, в котором говорится:

Никогда не учитывайте потоотделенные затраты

Потоки стоят, согласно Википедии (https://en.wikipedia.org/wiki/Sunk_cost):

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

Когда поточные затраты связаны с политическим давлением или личным эго (какой менеджер хочет быть тем, кто признает, что они приняли плохое решение или не контролировали результаты должным образом, даже если это было неизбежно или не поддавалось прямому контролю?), это приводит к ситуации, названной эскалацией обязательств (https://en.wikipedia.org/wiki/Escalation_of_commitment), которая определяется как:

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

Как это относится к коду?

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

Тогда существует целая концепция технического долга, которая, как и финансовый долг, МОЖЕТ и БУДЕТ накапливаться до такой степени, что кодовая база становится технически несостоятельной. Все больше и больше времени и ресурсов вкладывается в устранение ошибок, тушение пожаров и чрезмерно сложные улучшения, в результате чего прогресс вперед становится дорогостоящим, сложным и опасным. Проекты занимают больше времени и дольше из-за дефектов и отрываются от работы по проекту для устранения производственных проблем. Через несколько часов "инциденты" начинают становиться ожидаемой операцией, а не какой-то редкой вспышкой. Вместо того чтобы отступать и начинать делать все правильно, чтобы увеличить нашу будущую производительность (и качество жизни), мы оказываемся в положении, когда мы вынуждены добавлять все больше и больше технических долгов для соблюдения сроков - технического эквивалента денежные авансы на кредитной карте, чтобы внести минимальный платеж на другую карту.

Что все сказано, это не означает, что мы должны переписываться, когда это возможно, и не следует избегать переписывания рабочего кода любой ценой. Обе крайности являются потенциально расточительными, а последние, как правило, приводят к увеличению обязательств (потому что любой ценой означает полное пренебрежение к расходам, даже если эти издержки полностью опережают выгоды). То, что должно произойти, - объективная оценка затрат и преимуществ переписывания кода в сравнении с постепенными улучшениями. Задача состоит в том, чтобы найти кого-то, обладающего опытом и объективностью, для правильного принятия этого решения. Для нас, разработчиков, мы, как правило, склонны к переписыванию, потому что он имеет тенденцию быть намного интереснее и интереснее, чем работать с какой-то дрянной устаревшей кодовой базой. Бизнес-менеджеры, как правило, предвзято относятся к другому направлению, потому что переписывание накладывает некоторые неизвестные с небольшой ощутимой непосредственной выгодой. Результатом, как правило, является отсутствие реального решения, которое затем по умолчанию продолжает сбрасывать часы в существующий код, пока какое-то обстоятельство не потребует направленного сдвига (или разработчик скрытно переписывает код и обычно получает порку для него).

Я работал над кодовыми базами, которые были несколько спасенными, хотя и уродливыми. Они не придерживались установленных практик или стандартов, не использовали шаблоны, были некрасивы, но они выполняли свои намеченные функции достаточно хорошо и были достаточно гибкими, чтобы их можно было модифицировать для удовлетворения ожидаемых будущих потребностей в ожидаемом сроке действия приложения, Хотя это не гламурно, было вполне приемлемо сохранить этот код в живых, делая дополнительные улучшения, когда появилась возможность. Выполнение в противном случае принесло бы небольшую выгоду, чем выглядело бы красиво. Я бы сказал, что большинство кода, о котором я должен переписать это? вопрос возникает под этой категорией, и я нахожу себя объясняющим младшим разработчикам в команде, что, хотя было бы здорово переписать YetAnotherLineOfBusinessApp в {вставить здесь структуру whizzbang}, это не обязательно или желательно, и вот некоторые способы мы можем улучшить его...

Я также работал над кодовыми базами, которые были безнадежными. Это были приложения, которые едва запускались в первую очередь, как правило, отстают от графика и состояния с пониженной функциональностью. Они были написаны так, что никто, кроме оригинального разработчика, не сможет понять, что в конечном итоге делает код. Я называю это кодом только для чтения. После того, как оно написано, любые попытки изменения потенциально приводят к системной неразборчивой ошибке неизвестного происхождения, что приводит к панике в оптовых переписях массивных монолитных кодовых конструкций, которые не имеют никакой цели, кроме как обучить нынешнего разработчика тому, что на самом деле происходит с переменной, искусно названной obj_85 к времени выполнения достигает строки 1,209 вложенных 7 уровней в глубину if... else..., switch и foreach... с инструкциями где-то в методе DoEverythingAndMakeCoffee(...). Попытки реорганизовать этот код приводят к сбою. Каждый пройденный вами путь ведет к другой проблеме, а также к другим путям, а затем к путям этой ветки, а затем обращается назад к предыдущему пути, и после двух недель реферирования одного класса по-разному вы понимаете, что, хотя, возможно, лучше инкапсулироваться, новый код почти столь же пьяный и запутанный, как старый код, вероятно, содержит еще больше ошибок, потому что первоначальное намерение того, что вы реорганизовали, было совершенно неясно, и, не зная, какие именно деловые случаи привели к первоначальной катастрофе, в первую очередь, вы не может быть уверен, что вы полностью воспроизвели функциональность. Прогресс почти не существует, потому что перевод кодовой базы почти невозможно, и что-то настолько невиновное переименовывает переменную или использует правильный тип, выдает экспоненциальное количество непредвиденных побочных эффектов.

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

Итак, как вы решаете?

  • Насколько хорошо работает существующий код? Является ли он надежным и относительно свободным от дефектов?
  • Могут ли люди моей команды понять, что этот код делает с разумной степенью усилий? Если я привожу опытного разработчика, сможет ли он/она иметь достаточное представление об этом, чтобы стать продуктивным в разумные сроки?
  • Делать то, что должно быть - простыми дефектами, выполнять геологические измерения времени, чтобы исправить; настолько, что мы не можем сделать реальные улучшения или выполнить сроки выполнения проекта?
  • Является ли такая кодовая база настолько хрупкой и ожидаемой продолжительностью жизни, что способность приложения адаптироваться к будущим ожидаемым бизнес-потребностям весьма сомнительна?
  • Соответствует ли существующий код исходным функциональным требованиям?
  • Является ли ваша организация даже восприимчивой к инвестированию в приложение, или кто-то (особенно кто-то на более высоком уровне на диаграмме org), будет передан для решения проблемы?
  • Можете ли вы предоставить финансовое обоснование или обоснование риска, подкрепленное жесткими фактами, чтобы сделать бизнес-пример для перезаписи?
  • Если после полного учета времени и затрат на переписывание (включая разработку надлежащих спецификаций, тестирование качества, стабилизацию после подготовки и обучение, имеет ли смысл начинать переписывать код (мы, разработчики, склонны только думать в терминах времени кодирования)?
  • Есть ли у вас выбор? Возможно ли, что существующий код соответствует требованиям (потому что, если нет, переписывание огромных рядов будет частью проекта и считается "улучшением" вместо перезаписи)?

Ответ 17

Там есть старая поговорка, в которой говорится:

Нет такой вещи, как плохой код. Там только код, который делает то, что вы хотите и код, который этого не делает.

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

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