Надавливая на GOTO темную сторону

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

Теперь я понимаю, что могут быть аргументы в пользу использования "всего лишь одного маленького GOTO" вместо того, чтобы тратить время на рефакторинг на более удобное решение. Проблема в том, что этот изолированный "только один маленький ГОТО" не настолько изолирован. По крайней мере, раз в неделю или около того появляется новый "один маленький GOTO" для добавления. Эта кодовая база уже является ужасом для работы из-за кода, относящегося к или до 1984 года, который пронизан GOTO, который сделал бы много Pastafarians, полагая, что это вдохновленный самим Flying Spaghetti Monster.

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

Кто-нибудь еще испытал эту проблему, когда все согласны с тем, что мы не можем добавлять новые GOTO, чтобы перевести 2000 строк в случайный раздел, но постоянно ли Anaylsts настаивают на том, чтобы делать это только один раз, и одобрение руководства?

TL;DR;

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

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

Credit: XKCD

Разъяснение:

Перейти к here

alsoThere: Нет, я говорю о виде goto, который перескакивает 1000 строк из одной подпрограммы в другую в середине цикла. Перейти к somewhereClose

there: Я даже не говорил о том, какие gotos вы можете разумно прочитать и определить, что делает программа. Перейти к alsoThere

somewhereClose: Это тот код, который делает фрикадельки midpoint: Если первый раз здесь Goto nextpoint detail: (каждый из них почти полностью отличается) Перейти к pointlessReturn

here: В этом вопросе я не говорил о том, что иногда можно использовать goto. Перейти к there

tacoBell:, и он только что вернулся к чертежной доске. Перейти к Jail

elsewhere: Когда требуется неделя аналитиков, чтобы дешифровать то, что программа делает каждый раз, когда она затрагивается, что-то глубоко не соответствует вашей кодовой базе. На самом деле, я на самом деле до моего hell:, если не обновленный goto 4, выдача спецификации goto detail pointlessReturn: goto tacoBell

Jail: Собственно, просто небольшое обновление с небольшой победой. Я потратил 4 часа на рефакторинг части этой конкретной программы на единую метку за раз, сохраняя каждую итерацию в svn по мере того, как я шел. Каждый шаг (около 20 из них) был небольшим, логичным и достаточно легким, чтобы перейти bypass nextpoint: спонтанно выскочить из вашей еды и на экран через какой-то странный вид магнетизма из спагетти-фрикадельки. Перейти к elseWhere  bypass: разумно проверить, что он не должен вводить какие-либо логические изменения. Используя эту новую, более читаемую версию, я сел с аналитиком и выполнил почти все эти изменения сейчас. Перейти к end

4: first *, если первый раз здесь goto hell, не второй, если первый раз здесь goto hell, нет третьего, если первый раз здесь goto hell четвертый теперь обновленный goto hell

end:

Ответ 1

Сколько ошибок было введено из-за неправильно написанных GOTO? Сколько денег они стоили компании? Превратите проблему в нечто конкретное, а не "это плохо". Как только вы сможете распознать ее как проблему со стороны ответственных лиц, превратите ее в политику типа "никаких новых GOTO для чего-либо, кроме упрощения логики выхода для функции", или "никаких новых GOTO для любых функций, которые не имеют 100% unit test охват". Со временем ужесточите политику.

Ответ 2

GOTO не делают хороших кодовых спагетти, есть множество других факторов. Это обсуждение списка рассылки linux может помочь поставить несколько вещей в перспективу (комментарии Линуса Торвальдса о более широкой картине использования gotos).

Пытаясь внедрить политику "без goto" только ради того, чтобы иметь gotos ничего не достигнет в конечном итоге, и не сделает ваш код более удобным. Изменения должны быть более тонкими и сосредоточены на повышении общего качества кода, подумайте о принципах использования лучших практик для платформы/языка, покрытия unit test, статического анализа и т.д.

Ответ 3

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

У вас есть только один пример. Как вы стоите на этом, будет диктовать, как вы будете развиваться в будущем. Я думаю, у вас есть 4 варианта:

  • Примите запрос и примите, что вы всегда будете делать это.

  • Примите запрос и сразу начните искать новое задание.

  • Откажитесь от дел и будьте готовы сражаться, чтобы исправить беспорядок.

  • Отставка.

Какой вариант вы выберете, будет зависеть от того, насколько вы цените свою работу и свою самооценку.

Ответ 4

Возможно, вы можете использовать шаблон boyscout: оставьте место немного более чистым, чем вы его нашли. Поэтому для каждого featurerequest: не вводите новые gotos, но удаляйте один.

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

Утверждают, что рефакторинг в течение 2 часов сэкономит 20 раз 15 минут в будущем и позволит быстрее и глубже улучшать.

Ответ 5

Назад к принципам:

  • Является ли это доступным для чтения?
  • Это работает?
  • Поддерживается ли это?

Ответ 6

Это классический конфликт "управление" и "технари".

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

Для этого есть несколько причин:

  • Вполне возможно, что хорошо написано легко читать правильно структурированные программы с gotos! Спросите любого ассемблерного программиста; условная ветвь и примитивный цикл do - все, с чем им приходится работать. Просто потому, что "стиль" не является текущим и не означает, что он плохо написан.

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

  • Возврат инвестиций - использование оригинального стиля программирования и внесение минимальных изменений потребует минимальных усилий и быстро справится с запросом клиентов. Тратить много времени и усилий на рефакторинг будет дороже и займет больше времени.

  • Риск-перезаписывать и рефакторинг трудно получить правильно, требуется обширное тестирование реорганизованного кода, и все, что похоже на "ошибки", возможно, было "функциями" в отношении клиента. Особая проблема с "улучшением" устаревшего кода заключается в том, что бизнес-пользователи могут иметь хорошо зарекомендовавшие себя решения, зависящие от имеющейся там ошибки, или использовать существующие ошибки для изменения бизнес-процедур без уведомления ИТ-отдела.

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

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

Если он не сломался, не исправьте его!

PS: Даже Джоэл считает, что это плохая идея: вещи, которые вы никогда не должны делать

Обновление -

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

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

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

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

Ответ 7

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

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

Ответ 8

К сожалению, язык, на котором он написан, не имеет готовых инструментов рефакторинга

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

Ответ 9

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

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

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

Во многих случаях гораздо лучше, чем альтернативы:

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

Ответ 10

Если изменение в программе требует "всего лишь одного маленького goto", я бы сказал, что код был очень удобным.

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

Также имейте в виду, что некоторые "современные" языковые функции, такие как java-запрос "throw" или SQL "ON ERROR", действительно "скрываются".