Повторное использование существующих функций - PullRequest
3 голосов
/ 25 октября 2011

При добавлении новой функции в существующую систему, если вы сталкиваетесь с существующей функцией, которая почти делает то, что вам нужно, рекомендуется:

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

-или-

  • Отредактируйте существующую функцию, чтобы обрабатывать обе существующиеcase и ваш новый case, рискуя тем, что вы можете вносить новые ошибки в существующие части системы (что заставляет команду QA плакать)
    • Если вы редактируете существующую функцию, где вы рисуете линию, прежде чем просто создатьновая независимая функция (на основе копии) ... 10% функции, 50% функции?

Ответы [ 3 ]

3 голосов
/ 25 октября 2011

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

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

2 голосов
/ 25 октября 2011

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

Например, старый код:

def utf8len(s):
    return len(s.encode('utf8')) # or maybe something more memory-efficient

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

def utf8len(s):
    if s != None:
        return len(s.encode('utf8')) # old code path is untouched
    else:
        return None # new code path introduced

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

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

Конечно, вам нужно всестороннее тестирование, но оно не обязательно у вас есть.Здесь также есть два конкурирующих императива обслуживания: 1 - не дублируйте код, так как если в нем есть ошибки или поведение, которое может потребоваться изменить в будущем, то вы дублируете ошибки / текущее поведение.2 - принцип открытого / закрытого типа, который немного высокофутулирован, но в основном гласит: «пиши вещи, которые работают, а потом не трогай их».1 говорит, что вам следует провести рефакторинг, чтобы разделить код между этими двумя похожими операциями, 2 говорит, что нет, вы отправили старую, либо она пригодна для этой новой вещи, либо нет, а если нет, то оставьте ее в покое..

1 голос
/ 25 октября 2011

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...