Как уменьшить количество ошибок при кодировании?

30

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

GSto
источник
Хороший метод - сделать больше предварительного дизайна (не слишком много, но достаточно, чтобы сделать ваш код более структурированным и более легким для понимания).
Джорджио

Ответы:

58

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

Используйте доступные библиотеки. Самый простой способ избежать ошибок при написании служебной программы - это не писать ее.

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

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

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

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

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

David Thornley
источник
х2 - что сказал Райан.
Дж. Б. Р. Уилкинсон,
2
также большинство языков может быть более или менее требовательным. Вы хотите, чтобы это было как можно более разборчиво.
1
«Изучите несколько формальных приемов для более сложных вещей.» ... например?
Дэн Розенстарк
1
@ Яр: Я ожидаю чего-то похожего на системы, описанные в этой книге: amazon.com/Verification-Sequential-Concurrent-Programs-Computer/… ; хотя я должен сказать, что конкретная книга чрезвычайно сухая и скучная, так что, вероятно, есть намного лучшие (но это единственная, которую я прочитал).
Джоери Себрехтс
30

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

Райан Хейс
источник
3
«Думая обо всех случаях заранее» приводит к чистым, полностью определенным интерфейсам, которые могут быть только полезными. Модульные тесты сложно написать, только если вы переоборудуете их в код, не предназначенный для тестирования.
Майк Сеймур
1
Если вы можете, вы должны. К сожалению, в большинстве случаев я видел в модульных тестах нечто большее, чем просто «быстрое исправление ошибок». Итак, если вы можете, тогда вам следует писать тесты заранее, но если это не считается «экономически эффективным», то написание их вместе с исправлениями ошибок поможет вам со временем создать их, не тратя слишком много денег на простую написание модульных тестов. ,
Райан Хейс
4
«Тестирование показывает наличие, а не отсутствие ошибок». - Э. Дейкстра. При этом автоматизированные тесты, безусловно, являются очень полезным способом поддержания и повышения качества программного обеспечения.
лимит 30
9

+1 к обоим комментариям модульного теста.

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

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

Алан
источник
+1 за комментарий статического анализа. Это бесценно, чтобы получить всю эту информацию бесплатно :)
Morten Jensen
9

В дополнение к тому, что было упомянуто:

  • Не игнорируйте коды ошибок - например, не думайте, что вы получили правильный результат, файл был успешно создан и т. Д. ... Потому что однажды что-то произойдет.
  • Не думайте, что ваш код никогда не войдет в какое-то условие и, следовательно, «безопасно игнорировать это условие».
  • Протестируйте свой код, затем протестируйте его кем-то другим. Я считаю, что я худший человек, чтобы проверить свой собственный код.
  • Сделайте перерыв, затем перечитайте свой код и посмотрите, «пропустили ли вы очевидное». Часто случается со мной.

Много других вещей, которые я сейчас забываю, но другие наверняка о них подумают. :)

MetalMikester
источник
7
И если вы так уверены, что условие X никогда не произойдет ... используйте assert, чтобы убедиться, что когда условие X произойдет, вы будете знать об этом (через исключение, запись в журнал или что-то еще).
Фрэнк Шиарар
@MetalMikester: Модульные тесты хороши. Но при наличии языков высокого уровня и хороших библиотек большинство серьезных ошибок требуют интеграции и регрессионного тестирования.
вектор
9

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

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

Я также хотел бы сказать своим коллегам, что каждая ветвь (если, на время,? :) является вероятной ошибкой. Я не могу сказать, каким будет проявление ошибки, но чем менее условно поведение вашего кода, тем больше вероятность того, что он будет свободен от ошибок просто из-за того, что покрытие кода во время выполнения будет более последовательным.

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

штрих-кот-бэнг
источник
По моему опыту, это может быстро стать утомительным, чтобы обойти все состояния для каждого вызова, если методы настолько малы, насколько они должны быть. Эту проблему можно решить с помощью множества небольших неизменяемых классов с коротким временем жизни объекта. Таким образом, вы можете сохранить временное состояние в виде полей и удалить объект, когда он вам больше не нужен. :-)
Йорген Фог
Еще одно соображение для случая, когда это становится утомительным, - это то, что, возможно, вы пытаетесь обойти слишком много состояний. :)
dash-tom-bang
Во многих случаях это правда, но часто это не так. В некоторых доменах вам нужен доступ ко многим состояниям, даже если у вас мало изменяемого состояния. В настоящее время я работаю над генератором кода, где мне нужен доступ к нескольким таблицам символов. Я не хочу передавать их каждому методу.
Йорген Фог
8
  • Напишите меньше кода, который делает больше.
  • Подумайте о последствиях низкого уровня и последствиях высокого уровня
  • Созерцайте абстракцию, которую вы создаете в своем коде.
  • Напишите только существенную сложность, если это возможно.
Пол Натан
источник
Я собирался написать большой пост, который будет выглядеть как «пиши меньше, а значит больше» (я знаю и использую доступные вам инструменты). Я просто +1 это вместо этого.
Kaz Dragon
1
Но будьте осторожны, чтобы не получить причудливый код при попытке добиться меньшего количества кода.
Габлин
1
@gablin: во многих отношениях фантазия в глазах смотрящего. Сегодня я могу написать и прочитать код, который был бы ошеломлен 4 года назад. Хаскель сегодня мне нравится. :)
Пол Натан
8

Немного менее технический ответ: не программируйте, когда вы устали (достаточно 9 часов в день), пьяны или «запечены». Когда я устал, у меня не хватает терпения писать чистый код.

Александр
источник
2
Большинству программистов обычно требуется несколько лет, чтобы понять это. Это важный момент.
Джефф Дэвис
7

Написать модульные тесты и интеграционные тесты .

ysolik
источник
5

Некоторые отличные ответы здесь, касающиеся модульного тестирования и инструментов. Единственное, что я могу добавить к ним, это:

Привлекайте своих тестеров как можно раньше

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

  • Узнайте, каков их план тестирования. Просмотрите их контрольные примеры - покрываете ли вы их все своим кодом?
  • Спросите их за понимание требований. Это так же, как у вас?
  • Дайте им ранние рабочие сборки для проведения пробного тестирования - вы будете удивлены тем, какие улучшения они предложат.

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

Paddyslacker
источник
4

Инструменты статического анализа

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

PS: не забывайте всегда исследовать, почему инструмент говорит вам что-то плохое. Никогда не больно учиться (и не все правильно во всех ситуациях).

Райан Хейс
источник
3

Проверка кода или другие формы рецензирования, такие как парное программирование.

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

Peer Reviews in Software от Karl Wiegers - отличная книга на эту тему.

Майкл
источник
2

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

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

greyfade
источник
2

Здесь много хороших ответов, но я хотел бы добавить несколько вещей. Убедитесь, что вы действительно понимаете требование. Я видел много ошибок, когда пользователь думал, что это требование означает X, а программист думал, что это означает Y. Отойдите назад для разъяснения плохих или неоднозначных требований. Я знаю, что мы все любим прыгать и кодировать, но чем больше времени уделяется пониманию, тем меньше будет доработок и исправлений ошибок.

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

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

HLGEM
источник
1

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

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

Греза
источник
1

Я следую практике Test-Code-Test вместо Code-test-code-test. Это помогает мне подумать о сценариях использования и соответствующим образом сформулировать логику

Львов
источник
1

Используйте инструменты проверки кода, такие как ReSharper или IDE, такие как IntelliJ IDEA, которые предупреждают о многих ошибках копирования и вставки и других, например, указывая на переменные, которые «записываются, но никогда не читаются». Сэкономила мне много времени.

DonJoe
источник
1

Удивительно, но следующие три очень важных момента еще не были упомянуты:

  • Используйте утверждения свободно. Вопрос, который вы всегда должны себе задавать, это не «я должен это утверждать?» но "есть что-то, что я забыл утверждать?"

  • Выбираю неизменность. (Используйте final / readonly либерально.) Чем меньше у вас изменчивое состояние, тем меньше проблем может возникнуть.

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

Майк Накис
источник