ТОДО комментирует со сроками?

51

Фон

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

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

Что я ищу

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

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

Например, если мы переименуем столбец, мы можем создать для него начальную миграцию, а затем два комментария TODO, чтобы убедиться, что оставшиеся две миграции созданы:

// TODO by v55: Create migration to move constraints to new column, remove references to old column in app
// TODO by v56: Create migration to drop old column

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

Дополнительные мысли

Я чувствую, что у меня могут возникнуть проблемы с XY, учитывая, что развертывание и сине-зеленое развертывание считаются наилучшей практикой, и кажется странным, что я не могу найти решение, позволяющее сделать обновления базы данных менее болезненными. Если вы думаете, что я смотрю не совсем правильно, пожалуйста, дайте мне знать в комментарии! Тем не менее, пример базы данных, который я привел, является лишь одним примером, и я думаю, что комментарии TODO с указанием сроков будут полезны и в других ситуациях, поэтому даже если я неправильно подхожу к этой конкретной ситуации, мне бы очень хотелось получить ответы на свои вопросы. актуальный вопрос тоже. Спасибо!

РЕДАКТИРОВАТЬ: я просто подумал о другой ситуации, где это может быть полезно. Если вы используете Feature Toggles для включения частей вашего приложения, когда они будут готовы, вы должны быть осторожны, чтобы очистить их, в противном случае вы можете получить Toggle Debt . Комментарии со сроками могут быть хорошим способом запомнить это.

Джошуа Уолш
источник
19
Проблема TODO - это скорее вопрос дисциплины, чем инструментов.
Брэндон
16
Я думаю, что все люди делают ошибки, и инструменты могут быть хорошим способом смягчить это.
Джошуа Уолш
3
Как насчет того, чтобы делать это программно, как. Я имею в виду написать в классе ваш вариант. Не запускать приложение, если версия равна == 56 с сообщением «класс y», необходимо иметь эту функцию, у вас может быть список таких сообщений. Как вы думаете?
Томер Бен Дэвид
6
Я не согласен с тем, что я обращаюсь к тем, кто говорит «нет»: наша кодовая база опирается на множество других компонентов, над которыми мы не работаем, поэтому мы используем их TODO <Bug#>:для отслеживания обходных путей для проблем с другими компонентами. Когда ошибка устранена в одном из этих компонентов, вы можете легко найти и устранить соответствующие обходные пути. Он не заменяет систему отслеживания проблем, он облегчает обслуживание.
TemporalWolf

Ответы:

53

Этот вопрос действительно два вопроса в одном.

Тодо комментарии

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

Что с этим делать

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

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

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

Изменения базы данных

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

Процесс после развертывания

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

  1. сценарии базы данных preapp
  2. веб-приложения
  3. скрипты базы данных postapp
  4. сценарии базы данных окна обслуживания

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

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

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

Развертывание часто

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

Brandon
источник
18
Комментарии Todo - ужасный способ отслеживать и расставлять приоритеты в работе. Они являются правильным способом объяснить, почему наполовину законченный фрагмент кода развевается на ветру. В идеальном мире ни один код не делает этого. Между тем, в этом ...
candied_orange
6
... иногда хорошо иметь способ отследить технический долг, который не может скрыть никакая деприоритизация от босса. Конечно, вы не получите кредит на его исправление. Иногда вы все равно это исправляете.
candied_orange
3
Итак, стратегия с пост-приложением заключается в том, что эти миграции запускаются после успешного завершения развертывания приложения? Как насчет кода? Допустим, вы переименовываете столбец из фамилии в фамилию. Ваш старый код использует last_name. Вы переносите базу данных, чтобы добавить фамилию и изменить свой код, чтобы использовать фамилию, если она доступна, в противном случае - last_name. После того, как развертывание будет полностью развернуто, вы запустите следующую миграцию, отбросив старый столбец last_name. Но ваш код по-прежнему содержит код для last_name, который теперь не используется и, следовательно, технический долг. Как вы проводите очистку?
Джошуа Уолш
3
Хотя управление элементами действий в комментариях действительно является ужасным способом, наличие комментариев, автоматически создающих проблемы в системе отслеживания, может быть хорошим инструментом, чтобы не забыть сделать это, потому что вы в настоящее время занимаетесь программированием чего-то и не хотите жестко переключаться контекст системы отслеживания проблем.
PlasmaHH
6
ИМХО в этом ответе упущен смысл. ОП попросил найти решение, в котором CI уведомляет команду, когда важная очистка была забыта, не загромождая «систему управления проблемами» (комментарии TODO были только примером, возможно, не идеальным решением для этого). ОП привел несколько веских причин, по которым он не хочет использовать это ранее. Тем не менее, этот ответ предлагает полностью полагаться на отставание, которое в случае ОП является ничем иным, как его «системой управления проблемами». Поэтому ИМХО этот ответ игнорирует суть вопроса и не дает решения.
Док Браун
24

Не используйте TODO. У вас уже есть список TODO в вашем проекте. Это называется трекер проблем.

Я думаю, что настоящая проблема в этом предложении:

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

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

Если ваше управление чрезмерно задерживает последнюю часть задачи, у вас есть два варианта:

  1. поговорите со своим руководством, почему это плохая идея.

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

Йенс Шаудер
источник
Хороший совет, я подумаю над тем, как мы можем заставить систему управления проблемами работать для нас с этой целью. Мне также очень нравится идея «Может быть, даже что-то автоматическое имеет смысл, когда вы логически выполняете одно развертывание», я пытаюсь придумать, как мы можем это сделать. Я не уверен, что это реально возможно, хотя.
Джошуа Уолш
11
Вполне разумно иметь комментарии в форме // TODO(#12345): Frobnicate the sprocket before passing it along, при условии, что ошибка # 12345 является «реальным» номером проблемы, и проблема назначена кому-то. Это облегчает чтение источника, поясняя: «Нет, шаг frobnicate не скрывается ни в одном из вспомогательных методов, он просто не реализован. Посмотрите на ошибку # 12345 для большего контекста». В идеале, вам бы приходилось ежедневно бегать по кодовой базе в поисках закрытых или недействительных номеров выпусков, конечно.
Кевин
9

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

То, о чем вы просите, выполнимо, если вы готовы выполнить работу и выполнить ее.

// TODO v55: создание миграции для перемещения ограничений в новый столбец, удаление ссылок на старый столбец в приложении // TODO v56: создание миграции для удаления старого столбца

grep для того, //TODO by v55когда пришло время развернуть v55. Развертывание сборки запускает скрипт, который выполняет это как интеграционный тест.

Вы можете привязать 55 к вашей версии отслеживания или просто запросить ее.

Будет интересно, если вы захотите проверить // TODO с помощью v54 при выполнении 55. Вместо этого ищите в базе кода 55 раз, просто ищите // TODO по. Затем отфильтруйте этот результат от 1 до 55. Теперь 56 не вызовет сбой.

Вы можете подумать: «О, нам это не понадобится. Мы исправим это каждый раз, пока у нас есть чек». Нет, не будешь.

candied_orange
источник
4
Если это так, мы не делаем рекомендации здесь.
candied_orange
3
Если для такого рода вещей есть общее название, которое можно предоставить, но если вы прочитали страницу, на которой вы разместили
ссылку
6
Чтобы быть ясным, это ваш комментарий, против которого я возражаю, а не весь вопрос.
candied_orange
2
Сайты @YM_Industries SE, как правило, самодостаточны, рекомендации - это, в основном, простые ответы со ссылками на внешние сайты, или они предлагают вам поискать в Google вместо ссылки, но в конечном итоге это тоже самое. Они могут истечь и стать мертвыми. Так что вопрос о рекомендации не по теме, однако кто-то хочет упомянуть инструмент как дополнение к ответу или простому комментарию, он может это сделать.
Вальфрат
2
«Мне было интересно, существует ли существующее решение», - попробуйте спросить нас по адресу softwarerecs.stackexchange.com
Mawg
4

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

Поэтому мы можем с комфортом иметь TODO, не беспокоясь о том, что о них забудут.

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

Инструмент называется Westie, и пример средства проверки проблем Jira приведен на README.md. Смотрите также GitIssueAnalyser.

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

tjheslin1
источник
1
Это классно! Мы также используем JIRA, я мог бы изучить это. На самом деле это не решает мои проблемы с созданием беспорядка в нашей системе управления проблемами, но, по крайней мере, это гарантирует, что их нельзя забыть.
Джошуа Уолш
@YM_Industries Я рад. Я был бы рад принять любой вклад или работать по любым поднятым вопросам.
tjheslin1
4

Не делай. Сделай это сейчас.

TLDR: пишите (и тестируйте) ваши сценарии БД сейчас, а не позже; просто закодируйте их, чтобы их выполнение зависело от версии БД.

пример

Например, давайте представим, что вы хотите изменить имя столбца с SSNна TaxID- обычное требование при переходе на международный уровень.

Чтобы это произошло, может быть , вы будете временно иметь как TaxIDи SSNстолбец. И, поддерживая обе версии, у вас будет триггер для обновления одной из другой. Но вы не хотите хранить этот триггер бесконечно, поэтому позже, когда обратная совместимость больше не нужна, вы захотите, чтобы этот триггер был удален (и SSNстолбец был удален ). Мы собираемся закодировать все это без необходимости в элементах ToDo.

В нашем примере мы будем развертывать сборку 102 (в которой есть новый столбец), сохраняя совместимость со сборкой 101 (в которой этого нет).

Вот шаги.

1. Настройте таблицу версий

  1. Добавьте одну таблицу Configurationс двумя столбцами Nameи Value.

  2. Добавьте строку с параметром Name«TargetVersion» и задайте Valueверсию новой развертываемой сборки.

  3. Добавьте строку с параметром Name«CompatibleWith» и задайте Valueминимальный номер версии, с которым развертывание должно быть совместимым.

Проверяйте и обновляйте эти строки перед каждым развертыванием.

2. Изменить сценарии развертывания

  1. Добавьте сценарий, который создает новый столбец TaxIDрядом SSNи заполняет его из SSNстолбца. Включите этот код в Ifоператор, который проверяет TargetVersion; если целевая версия слишком низкая (т.е. TaxIDпока не нужна), пропустите.

    SELECT @TargetVersion = TargetVersion FROM Configuration
    IF @TargetVersion < '102' THEN RETURN
    ALTER TABLE Customer ADD COLUMN taxID VarChar(12) NOT NULL
    UPDATE Customer SET TaxID = SSN
    
  2. Добавьте скрипт, который создает триггер, который заполняется TaxIDпри вставке или обновлении SSNи наоборот. Включите этот код в Ifоператор, который проверяет целевую версию и совместимую версию; пропустите, если TargetVersion слишком низок ( TaxIDне нужен) или если версия CompatibleWith слишком высока ( SSNполе не требуется).

    SELECT @TargetVersion  = TargetVersion,
           @CompatibleWith = CompatibleWith 
    FROM Configuration
    IF @TargetVersion  < '102' THEN RETURN
    IF @CompatibleWith > '101' THEN RETURN
    CREATE TRIGGER SSNAndTaxIDTrigger ON Customer etc.
    
  3. Добавьте скрипт для удаления SSNстолбца. Включите в Ifоператор, который удаляет столбец, только если версия CompatibleWith достаточно высока ( SSNбольше не нужна).

    SELECT @CompatibleWith = CompatibleWith FROM Configuration
    IF @CompatibleWith <= '101' THEN RETURN
    IF OBJECT_ID('SSNAndTaxIDTrigger') IS NOT NULL DROP TRIGGER SSNAndTaxIDTrigger
    IF EXISTS (SELECT * FROM syscolumns c JOIN sysobject o ON o.id = c.is WHERE o.Name = 'Custeomr' AND c.Name = 'SSN') BEGIN
        ALTER TABLE Customer DROP COLUMN SSN
    END
    

3. Тестирование

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

4. В вашем развертывании playbook

Добавьте шаг для инженера для обновления версии CompatibleWith и строк TargetVersion. Если вы развертываете в Blue, установите TargetVersion в номер версии Blue, а в версии CompatibleWith - номер версии Green; поменяйте их, если вы развертываете Green.

Ловушки

Ваши сценарии развертывания могут ссылаться и ссылаться на номера версий в этой таблице БД. НЕ код выполнения.

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

Итог всего этого

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

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

Джон Ву
источник
Мне очень нравится этот подход, он более элегантен, чем комментарии ToDo. Я подумал об этом вскоре после того, как задал этот вопрос, и думал о том, чтобы написать еще один пост с вопросом о том, как лучше всего это реализовать, но решил, что сначала проведу собственное исследование. Хитрость для нас заключается в том, что мы используем Phinx для миграции наших баз данных, и это на самом деле не поддерживает это. Когда у меня будет время, я найду способ расширить его для поддержки такого рода рабочих процессов. Этот подход не решает вопрос о том, как обеспечить удаление кода обратной совместимости из моего уровня приложений, но он элегантен для проблемы с БД.
Джошуа Уолш
1

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

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

Eternal21
источник
1
Да, я в идеале надеялся считать истекший TODO неудачным тестом. Количество откатов против TODO меня немного удивило, я знаю, что они не являются заменой системы управления проблемами, но, учитывая распространенность TDD / BDD, ясно, что нет реальной проблемы с определением требований в коде и использованием кода для обеспечения выполнения Завершение
Джошуа Уолш
-2

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

mpiazza
источник
1
Репликация базы данных в сине-зеленом развертывании вызывает много головной боли. Когда мой prod env находится где-то между синим и зеленым (например, 50% нагрузки распределены на каждую), мне нужно, чтобы код репликации поддерживал синхронизацию обеих баз данных, даже если их схемы разные. Из проведенного мною исследования кажется, что большинство людей в реальном мире имеют общий экземпляр БД между своим синим и зеленым стеками. Я не считаю это серьезной проблемой, если миграция баз данных происходит достаточно быстро. Сине-зеленые стеки по своей природе должны совместно использовать некоторые ресурсы, по крайней мере балансировщик нагрузки / обратный прокси-сервер.
Джошуа Уолш