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

Концепция очень проста: по сути, это просто условие «если» вокруг рассматриваемого кода. Это обеспечивает два пути кода: один для нового реорганизованного кода и один для предыдущего кода.

#in settings.py
NEW_CODE_FEATURE_FLAG = True
#somewhere else in the code:
if NEW_CODE_FEATURE_FLAG:
    # do this experimental code
else:
    # revert to the previous code

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

Но можем ли мы сделать это аккуратнее? Смешение бизнес-логики и кода рефакторинга не является идеальным. Рассмотрим этот пример с использованием менеджера контекста:

# in a settings.py file:
THIS_CODE_FLAG = LEGACY_CODE
---
print 'Legacy code block start'
with Feature_Flag(mode=THIS_CODE_FLAG, this_code=LEGACY_CODE):
    print 'executing legacy code block'
    r = do_complicated_function()
print 'Legacy code block end'
print 'Refactored code block start'
with Feature_Flag(mode=THIS_CODE_FLAG, this_code=NEW_CODE):
    print('executing refactored code block')
    r = do_refactored_complicated_function()
print('Refactored code block end')

Флаг кода здесь установлен для запуска блока «устаревшего кода», а не блока «нового кода»; следовательно, вывод:

Legacy code block start
executing legacy code block
Legacy code block end
Refactored code block start
Refactored code block end

Выполнить оба блока и подтвердить, что результаты одинаковы

Это здорово: бизнес-логика довольно хорошо отделена от тестирования — но что произойдет, если мы захотим запустить оба блока и убедиться, что результаты одинаковы?
Да, у нас могут быть временные переменные; и поместите assert(a==b) в конце двух блоков. Но не было бы неплохо использовать для этого менеджер контекста? Это позволило бы сохранить хорошее отделение кода рефакторинга от бизнес-логики.

Этот суть делает именно это: оба блока выполняются и сравниваются — просто установите флаг в ASSERT_CODE_BLOCK_RESULTS_SAME и сохраните результат блока обратно в менеджер контекста — если они отличаются, возникнет исключение.

# in a settings.py file:
THIS_CODE_FLAG = ASSERT_CODE_BLOCK_RESULTS_SAME
----
with Feature_Flag(mode=THIS_CODE_FLAG, this_code=LEGACY_CODE) as f:
    r = do_complicated_function()
    f.block_result(r)
with Feature_Flag(mode=THIS_CODE_FLAG, this_code=NEW_CODE) as f
    r = do_refactored_complicated_function()
    f.block_result(r)

Благодаря этому вдохновению stackoverflow.
код: https://gist.github.com/julzhk/7d5f637190e9a3ca9d67cb801392162c
Это всего лишь пример проверки концепции (есть проблема изменяемых ключей и этой уродливой глобальной переменной…) для python 2.7 (о ужас!); содержимое может осесть в пути; Используйте на свой риск.