Баги — это непредвиденное поведение системы ПО. Они бывают разной степени тяжести. Одни препятствуют выполнению самых простых действий, другие частично или полностью прекращают работу системы. В большинстве случаев сообщество/база пользователей находят способы обойти ошибки ПО. В интернете предостаточно блогов, обучающих видео материалов и репозиториев GitHub, рассказывающих, как устранить баги и преодолеть ограничения фреймворков.
Однако ошибки в системах напрямую влияют на качество ПО, которое определяет успех проектов. Поэтому программисты всеми силами стараются уменьшить их число, подбирая для этого различные стратегии.
Причины багов самые разные: недочеты в программировании и зависимостях, неисправности в аппаратном обеспечении. Что касается последних, то они могут вызывать ошибки даже при условии устранения погрешностей в исходном коде и работе платформ. Например, далекие космические лучи могут преобразовать переменную во время выполнения программы, изменив биты физической памяти. Так что ошибки ПО неизбежны, но мы в силах их сократить.
В данной статье на практических примерах мы рассмотрим ряд приемов, позволяющих уменьшить число багов. Эти стратегии вам обязательно пригодятся в дальнейшей работе.
Хорошо подумайте перед использованием зависимости
Создавая код, программисты часто применяют библиотеки зависимостей для экономии времени. Например, при необходимости написать CLI-программу на основе Node.js можно выбрать Commander.js и обойтись без парсинга аргументов командной строки своими силами. Такие библиотеки помогают минимизировать логические ошибки и время разработки. Но при этом они могут снизить качество кода и повлечь за собой ограничения и новые ошибки.
Как правило, программисты не изучают и не проверяют исходный код библиотек ПО. Поэтому есть вероятность ввода таких входных данных, которые они не смогут обработать. Имеющиеся у нас библиотеки не отличаются гибкостью и расширяемостью. При наличии ограничений приходится прибегать к обходным решениям, так называемым хакам, которые зачастую оборачиваются еще более серьезными ошибками. Вот почему крупные технологические компании предпочитают разрабатывать новые библиотеки вместо использования уже существующих.
Однако мы обычно задействуем библиотеки ПО, принимая во внимание их общие преимущества. Перед интеграцией конкретной библиотеки в базу кода лучше изучить все свойственные ей ошибки, ограничения, стандарты оформления кода, тесты производительности и поддержку сообщества. Обязательно пишите для нее модульные тесты во избежание сбоев в процессе обновлений.
Перепроверяйте все даже после простого рефакторинга
Вспомним, как программисты начинают работу над проектами ПО. Некоторые команды разработки превращают проекты POC (проверки концепции) в готовое для продакшн ПО. Между тем есть и те, кто перед программированием даже проектирует структуру базы кода. Однако большинство продуктов ПО начинались как POC. Например, взгляните на исходную базу кода фреймворка Flutter и сравните ее с текущей структурой проекта:
Программисты так часто проводят рефакторинг, чтобы превратить эти рабочие этапы POC в системы ПО, готовые для продакшена. Рефакторинг кода все чаще встречается даже в базах кода, уже предназначенных для продакшена. Временами этот процесс создает логические проблемы, которые не под силу распознать даже наборам тестов.
Недавно я провел простой рефакторинг в одном из проектов с открытым ПО: разбил большую функцию на несколько подфункций. Позднее я обнаружил нарушения в работе одного из модулей. Их причиной стал рефакторинг, изменивший поток выполнения предыдущих инструкций. Вот почему следует перепроверять все даже после внесения простых изменений, поскольку они могут повлиять на логический поток системы ПО.
Не оставляйте наскоро выполненные патчи в главной базе кода
Написать идеальный код без ошибок, мелких недочетов в паттернах проектирования, скрытых логических проблем — невозможно. Код, подготовленный к коммиту сегодня, может содержать незаметные ошибки, которые придется исправлять завтра. Их обнаружат три непосредственных участника процесса: вы, тестировщики и пользователи. Когда программисты замечают баг на стороне пользователя, они зачастую стараются решить проблему при помощи патчей, т. е. быстрых исправлений (hotfix).
Такие решения радуют пользователей, но при этом способны снизить качество кода и вызвать еще больше ошибок. В связи с этим рекомендуется вернуться к проблеме и вдумчиво ее устранить.
Написание быстрых патчей для спасения репутации продукта ПО — дело нередкое. В таких случаях сначала вносим незамедлительное исправление, а позднее доводим его до ума. Так мы предотвратим возможные ошибки в будущем, возникающие вследствие предыдущих поспешных мер. Не стоит исправлять ошибки в продакшн в стрессовом состоянии, поскольку это чревато появлением новых недочетов.
Пишите чистый код и используйте качественное руководство по стилю
Старшие инженеры мотивируют младших коллег по проекту писать чистый код для поддержания качества исходного. При таком подходе базы кода становятся менее подверженными ошибкам, более понятными и расширяемыми. Каждая из них обладает уникальным логическим потоком, основанным на входных данных и условных операторах. В соответствии с ним мы можем начертить структуру ориентированного графа.
Вы пишите чистый код и тем самым уменьшаете сложность графа логического потока. А вот грязный и запутанный код его только усложняет. Программистам становится затруднительно мысленно выстраивать логическую структуру для внесения изменений. В результате запланированные функциональности системы ПО могут содержать еще больше ошибок.
Таким образом, лучше всего писать чистый код, следуя общепринятому руководству по стилю. Если у вас его нет, переходите по ссылке и выбирайте из списка высококачественных соглашений и стандартов оформления. Смело меняйте эти руководства, исходя из своих предпочтений.
Продумывайте стратегии обработки ошибок
Все системы ПО выполняют 4 стандартных действия: принимают и обрабатывают входные данные, сохраняют и отображают/возвращают информацию. У каждого действия пользователя есть ожидаемый результат. Например, если вы используете инструмент Angular CLI для создания нового одностраничного приложения, то рассчитываете сделать это с помощью команды ng new
. Но иногда программы не выдают ожидаемые результаты во время выполнения.
В таких случаях программисты пишут код обработки ошибок для получения альтернативного результата вместо запланированного. С этой целью они применяют разные подходы: условные инструкции if-else
, проверка кода с ошибками, перехват исключений посредством блоков try-catch
.
Необработанные ошибки, как и выполнение программы с ошибочными входными данными, могут вызвать сбой системы или повлечь за собой сохранение неверной информации в памяти. Убедитесь, что избранный подход обработки ошибок успешно выдает лучший альтернативный результат. Иначе придется иметь дело с долгосрочными ошибками, которые нелегко будет исправить.
К ошибкам в коде приводит чрезмерное увлечение моделями типа try-catch
. По этой причине руководство Google по стилю C++ не рекомендует задействовать стандартные исключения. А в Gо исключения не представлены в виде функциональности. Сокращение потоков обработки ошибок посредством значений по умолчанию — отличная практика, которая помогает избежать сбоев системы по причине необработанных ошибок.
Благодарим за внимание!
Читайте также:
- Как ваша программа использует память
- О дивный читаемый код
- Собеседование: 8 самых распространенных ошибок программистов
Читайте нас в Telegram, VK и Яндекс.Дзен
Перевод статьи Shalitha Suranga: 5 Tips for Reducing Bugs in Software Development Projects