Если Ваш предпочтительный язык сценариев не имеет чего-то как строгий режим Perl, как Вы находите опечатки? Вы - поблочное тестирование все? Каждый конструктор, каждый метод? Действительно ли это - единственный способ пойти об этом?
Действительно тщательные модульные тесты - самая важная техника (да, я всегда стремлюсь к 100% покрытию), поскольку они также отлавливают множество других опечаток (например, когда я пишу +
, а подразумеваю -
), проблемы "не по правилам" и т.д. Интеграционные и нагрузочные тесты, выполняющие каждую функцию, являются второй линией обороны против всех видов ошибок (в основном, правда, более глубоких и сложных;-)).
Далее идут такие инструменты, как pylint и pychecker и раскрашивающие редакторы (я не использую настоящие IDE, но они тоже могли бы помочь, подобно тому, как это делает мой надежный редактор gvim;-).
Такие техники, как обязательные обзоры кода (например, например, видео с моим интервью на эту тему здесь), хотя и крайне важны, должны фокусироваться на других вопросах - вопросах, которые автоматизированные инструменты просто не поймают, таких как полнота и правильность комментариев/документов, выбор хороших/быстрых алгоритмов и тому подобное (см. здесь краткое изложение доклада, который я сделал на эту тему на той же конференции, на которой я получил это интервью, и ссылку на PDF слайдов).
Некоторые редакторы (например, NetBeans) анализируют ваш код и подчеркивают «подозрительные» части, например неиспользуемые переменные, что может быть признаком опечатки. NB также выделяет идентификатор над курсором в другом месте экрана, что также помогает.
Конечно, никакая хитрая уловка с IDE не заменит надлежащего тестирования.
В Ruby неправильное написание локальной переменной привело бы к ужасной смерти программы, и это нормально.
Ошибка в написании переменной экземпляра не приводит к ужасной смерти программы, а это плохо. Чтобы обнаружить такие случаи, используйте предупреждения . К сожалению, вы не можете легко указать Ruby, чтобы обрабатывал предупреждения как ошибки .
TDD -- сначала пишите тесты, затем простейший код для прохождения теста. Так вы можете быть более уверены, что у вас нет нетестируемого кода. Это поможет убедиться, что в вашем коде меньше опечаток и других ошибок.
Парное программирование/обзоры кода - две пары глаз лучше, чем одна пара.
IDE с intellisense - не панацея, но очень помогает избежать опечаток. Если вы используете intellisense, вы обычно получаете ошибки подстановки, а не опечатки. Их несложно найти с помощью тестов.
Многие инструменты модульного тестирования могут показать процент строк, которые они протестировали. Чем ближе этот процент к 100%, тем меньше вероятность опечатки в имени переменной.
Я пишу весь свой код Python в eclipse IDE. Как предположил Младен Ябланович, затмение подчеркивает подозрительные части.
Следующим шагом будет запуск кода. Я могу столкнуться с двумя типами ошибок.
Ошибки, которые интерпретатор улавливает и дает мне номер строки: Обычно их довольно легко отладить, особенно если вы напечатаете все переменные в этой строке непосредственно перед этой строкой, чтобы убедиться, что они содержат значения, которые вы ' буду ожидать.
Неожиданное поведение: ваш код в порядке, интерпретатор не жалуется, но ваш код ведет себя не так, как вы этого хотите. Когда это происходит (редко, потому что я обычно достаточно хорошо проектирую свои модули - процесс, который занимает около 7 минут - прежде чем я начну кодировать), я начинаю смотреть на модули / функции в том порядке, в котором они вызываются, и пытаюсь выполнить программу в моя голова, как это увидел бы переводчик.Если это не сработает, я перейду к исследованию отладчика. Обычно это не сводится к этому, но если это так, это довольно большая ошибка, и на ее исправление уйдет довольно много времени. Модульные тесты помогают, но, честно говоря, я думаю, что как ученый-компьютерщик, я должен иметь возможность отлаживать его с точки зрения анализа алгоритмов, что обычно быстрее, чем модульное тестирование (по крайней мере, для меня). Кроме того, выбор анализа алгоритмов вместо модульного тестирования тренирует мой мозг, чтобы я не делал таких ошибок в будущем, в отличие от модульного тестирования, которое помогает мне решить проблему сейчас, но мало что помогает я избегаю повторения той же / подобной ошибки в будущем.
Надеюсь, это поможет
Есть ошибки, кроме "опечаток". Если вы что-то не тестируете, знание того, что в именах переменных были обнаружены ошибки, в любом случае вас мало что ждет.
Я полагаю, что под "опечаткой" вы подразумеваете опечатку в именах переменных / функций / классов. Это меньшая проблема в Python, чем в Perl, поскольку Perl (и я верю, что Ruby) по умолчанию автоматически создает переменную и инициализирует ее нулем или "" при первом использовании. Python не делает этого, поскольку использование переменной, которая не была явно создана, является ошибкой, поэтому в этом смысле она уже находится в «строгом» режиме.
Я использую Vim с плагином pyflakes , который подчеркивает большинство типов опечаток, как только вы их вводите. Я также часто использую pylint и pychecker, поскольку они могут отлавливать множество других ошибок.
Еще одна вещь, которую я делаю, - это интенсивно использую автозаполнение Vim - я набираю имя полностью один раз, а затем при последующих использовании имени набираю первые несколько букв и использую
или
для циклического перебора совпадений.
Я также использую разработку через тестирование, чтобы обеспечить 100% покрытие модульным тестированием.
Я считаю, что сочетание всех этих практик означает, что проблем, вызванных опечатками, практически не существует.
В моем случае я широко использую модульное тестирование (разработка на Python). Поскольку существует множество облегченных фреймворков тестирования, хорошо интегрированных в язык (или IDE, если хотите), их использование почти не причиняет вам боли;)
Посмотрите на этот пример:
def unpack_args(func):
def deco_func(*args):
if isinstance(args, tuple):
args = args[0]
return func(*args)
return deco_func
def func1(*args):
"""
>>> func1(1,2,3)
(1, 2, 3)
>>> func1(*func2(1,2,3))
(1, 2, 3)
>>> func1(func2(1,2,3))
((1, 2, 3),)
"""
return args
def func2(*args):
"""
>>> func2(1,2,3)
(1, 2, 3)
"""
return args
@unpack_args
def func3(*args):
return args
def test():
"""
>>> func3(func2(1,2,3))
(1, 2, 3)
"""
import doctest
doctest.testmod(verbose=True)
test()
-----------------------------
Results:
Trying:
func1(1,2,3)
Expecting:
(1, 2, 3)
ok
Trying:
func1(*func2(1,2,3))
Expecting:
(1, 2, 3)
ok
Trying:
func1(func2(1,2,3))
Expecting:
((1, 2, 3),)
ok
Trying:
func2(1,2,3)
Expecting:
(1, 2, 3)
ok
Trying:
func3(func2(1,2,3))
Expecting:
(1, 2, 3)
ok
3 items had no tests:
__main__
__main__.func3
__main__.unpack_args
3 items passed all tests:
3 tests in __main__.func1
1 tests in __main__.func2
1 tests in __main__.test
5 tests in 6 items.
5 passed and 0 failed.
Test passed.