Введение
Основным продуктом деятельности разработчика является программный код. Поэтому процесс обучения разработке программного обеспечения, безусловно, всегда включает развитие навыков по его написанию. Часто теоретические основы, получаемые студентом, покрывают проблемы качества кода, но при решении практических задач студент не уделяет им должного внимания, ограничиваясь только тем, что программа производит правильный результат. Такой подход при применении к разработке промышленных систем может привести к серьезным проблемам, начиная от сложности дальнейшего развития и поддержки продукта до уязвимостей в системе, открывающих доступ злоумышленникам. В связи с этим важно учить студентов следить за качеством кода. Бесспорно, наиболее эффективным методом для этого является контроль преподавателем качества написанного студентом кода, но часто это невозможно, так как требует очень много времени, особенно в больших группах. В таком случае контроль качества может быть автоматизирован при помощи инструментов статического и динамического анализа.
Статический анализ - это процесс выявления ошибок и недочетов в исходном коде программ, выполняемый, в отличие от динамического анализа, без реального выполнения исследуемых программ. [1] Статический анализ позволяет выявлять уязвимости, нарушения стандартов оформления и другие проблемные участки кода, а также подсчитывать различные метрики ПО. Практика статического анализа может быть внедрена в учебный процесс как основное, либо как дополнительное к проверке преподавателем средство контроля качества решений студентами практических задач. Кроме того, если в учебном заведении учет и/или проверка решений автоматизированы, средства статического анализа могут быть интегрированы в существующую инфраструктуру минимальными усилиями.
Целью данной ВКР является исследование возможностей инструментов статического анализа применительно к учебному процессу. Возможности будут продемонстрированы на примере добавления функции статического анализа в дистанционный практикум по программированию ВоГУ, кафедры АВТ.
Целью диссертационной работы является исследование возможностей применения инструментов статического анализа в учебном процессе для проверки решений задач по программированию. Для достижения поставленной цели в данной диссертационной работе решаются следующие задачи:
1. Анализ существующих подходов к решению рассматриваемых задач.
2. Исследование предметной области статического анализа: инструменты статического анализа, типы обнаруживаемых ошибок.
3. Применение полученных теоретических результатов для проектирования модуля статического анализа.
4. Разработка модуля статического анализа, интеграция в систему дистанционного практикума.
5. Внедрение полученных результатов в деятельность университета.
В соответствии с вышесказанным объектом исследования являются ошибки дизайна программного кода.
В качестве предмета исследования выступает применение средств статического анализа для выявления ошибок дизайна программного кода.
В качестве методов исследования в работе использовались методы анализа исходного кода программ, анализа алгоритмов. Кроме того, применялись методы разработки программного обеспечения с использованием объектно-ориентированного подхода.
Научная новизна работы заключается в следующем:
Обоснована целесообразность применения инструментов статического анализа программного кода в учебном процессе. Предложен и реализован способ добавления возможности статического анализа программного кода в функционирующую систему дистанционного обучения программированию.
Практическая значимость результатов диссертации заключается в следующем:
Результаты диссертационной работы будут использованы в учебном процессе Вологодского государственного университета при преподавании курсов “Структуры и алгоритмы обработки данных”, “Программирование на языке высокого уровня” с целью повышения автоматизации процесса проверки решений студентов и сокращения ручного труда преподавательского состава.
Апробация работы: на тему диссертационной работы было опубликовано 3 статьи:
Статический анализ исходного кода в обучении и разработке программного обеспечения // Молодой ученый. -- 2018. -- №22. -- С. 38-39. -- URL https://moluch.ru/archive/208/50975/
Типовые ошибки дизайна программного кода // Молодой ученый. -- 2019. -- №2. -- С. 1-2. -- URL https://moluch.ru/archive/240/55453/
Статический и динамический анализ исходного кода // Молодой ученый. -- 2019. -- №2. -- С. 2-4. -- URL https://moluch.ru/archive/240/55456/
Диссертация состоит из введения, четырех глав, заключения, списка литературы.
1. Анализ предметной области
Статический анализ можно рассматривать как автоматизированный процесс обзора кода.
Задачи, решаемые программами статического анализа кода, можно разделить на 3 категории:
Выявление ошибок в программах. Подробнее про это будет рассказано ниже.
Рекомендации по оформлению кода. Некоторые статические анализаторы позволяют проверять, соответствует ли исходный код, принятому в компании стандарту оформления кода. Имеется в виду контроль количества отступов в различных конструкциях, использование пробелов/символов табуляции и так далее.
Подсчет метрик. Метрика программного обеспечения -- это мера, позволяющая получить численное значение некоторого свойства программного обеспечения или его спецификаций. Существует большое количество разнообразных метрик, которые можно подсчитать, используя те ли иные инструменты.
Как и у любой другой методологии выявления ошибок, у статического анализа есть свои сильные и слабые стороны. Важно понимать, что нет идеального метода тестирования программ. Для разных классов программного обеспечения разные методики будут давать разные результаты. Добиться высокого качества программы можно только используя сочетание различных методик.
Главное преимущество статического анализа состоит в возможности существенного снижения стоимости устранения дефектов в программе. Чем раньше ошибка выявлена, тем меньше стоимость ее исправления. Так согласно данным, приведенным в книге Макконнелла "Совершенный Код" [2], исправление ошибки на этапе тестирования обойдется в десять раз дороже, чем на этапе конструирования (написания кода).
Другие преимущества статического анализа кода:
Полное покрытие кода. Статические анализаторы проверяют даже те фрагменты кода, которые получают управление крайне редко. Такие участки кода, как правило, не удается протестировать другими методами. Это позволяет находить дефекты в обработчиках редких ситуаций, в обработчиках ошибок или в системе логирования.
Статический анализ не зависит от используемого компилятора и среды, в которой будет выполняться скомпилированная программа. Это позволяет находить скрытые ошибки, которые могут проявить себя только через несколько лет. Например, это ошибки неопределенного поведения. Такие ошибки могут проявить себя при смене версии компилятора или при использовании других ключей для оптимизации кода.
Можно легко и быстро обнаруживать опечатки и последствия использования Copy-Paste. Как правило, нахождение этих ошибок другими способами является кране неэффективной тратой времени и усилий.
Недостатки статического анализа кода:
Статический анализ, как правило, слаб в диагностике утечек памяти и параллельных ошибок. Чтобы выявлять подобные ошибки, фактически необходимо виртуально выполнить часть программы. Это крайне сложно реализовать. Также подобные алгоритмы требуют очень много памяти и процессорного времени. Как правило, статические анализаторы ограничиваются диагностикой простых случаев. Более эффективным способом выявления утечек памяти и параллельных ошибок является использование инструментов динамического анализа.
Программа статического анализа предупреждает о подозрительных местах. Это значит, что на самом деле код, может быть совершенно корректен. Это называется ложно-позитивными срабатываниями. Понять, указывает анализатор на ошибку или выдал ложное срабатывание, может только программист. Необходимость просматривать ложные срабатывания отнимает рабочее время и ослабляет внимание к тем участкам кода, где в действительности содержатся ошибки.
1.1 Основные типы ошибок в программном коде
В общем случае задачей статического анализа можно назвать обнаружение ошибок дизайна программного кода. Ниже описаны некоторые наиболее распространенные ошибки дизайна [3], обнаружив которые на ранних этапах разработки можно избежать серьезных проблем:
1. Длинные методы
Большая часть времени программиста тратится на чтение, а не на написание кода. Помимо того, что при чтении таких методов приходится держать много сложной логики в голове, обычно это признак того, что у метода слишком много обязанностей. Длинные методы затрудняют поддержку и отладку кода.
2. Отказ от наследства
Если класс наследуется от базового класса, но не использует ни одного из унаследованных полей или методов, необходимо подумать, действительно ли здесь уместно наследование.
3. Группы данных
Если несколько вызовов методов принимают один и тот же набор аргументов, это может быть признаком того, что эти аргументы связаны между собой. Для повышения организации кода группу аргументов можно объединить в одном классе.
4. Дублирование кода
Распространена ситуация, когда исправленная ошибка появляется в другой части системы. Это может быть результатом дублирования кода, когда ошибка была исправлена не во всех продублированных фрагментах кода. Это создает накладные расходы с точки зрения обслуживания. Разработчики при исправлении ошибки в одном из дублей могут не знать о существовании других.
5. Посредник
Когда класс существует только для делегирования вызовов другому классу, разработчик должен задуматься, какова его реальная цель. Иногда к такому результату приводит рефакторинг кода, при котором логика постепенно удаляется из класса, оставляя почти пустую оболочку.
6. Одержимость примитивными типами
Примитивные типы дают мало с точки зрения контекста предметной области. Например, поле ID(идентификатор) может содержать любое значение, в том числе составное. Если у примитивов есть доменное значение, можно обернуть их в небольшой класс. В последствии этот класс может быть расширен дополнительными методами.
7. Комментарии
Там, где комментарии повторяют то, что можно прочитать из кода, они не несут пользы, особенно если они потеряли актуальность и больше не соответствуют коду.
Вместо того, чтобы добавлять комментарий для пояснения фрагмента кода, нужно подумать, как организовать этот код, чтобы он был понятен без комментария. Например,дать конструкциям более выразительные имена.
8. Расходящиеся модификации
Проблема возникает, когда класс имеет множество причин для изменения. В идеале должна быть прямая связь между общими изменениями и классами.
9. Завистливые функции
Это ситуация, когда метод не использует данные или методы из класса, к которому он принадлежит. Вместо этого он часто обращается к другому классу.
10. Ленивый класс
Класс, затраты на существование которого не окупаются выполняемыми им функциями, должен быть ликвидирован.
11. Имя метода, включающее тип
Необходимо избегать размещения типов в именах методов; это не только избыточно, но и заставляет менять имя в случае изменения типа.
12. Невнятное название
Название метода должно лаконично описывать, что делает этот метод. Признаком правильного названия является то, что другому разработчику для понимания цели метода достаточно прочитать его название.
13. Мертвый код
Неиспользуемый код должен быть удален.
1.2 Обзор систем дистанционного обучения
Для анализа выбраны самые популярные платформы для онлайн-обучения в России и за рубежом. Далее приведено их краткое описание и выводы, сделанные из анализа [4].
Codecademy
Интерактивная онлайн-платформа для обучения 12 языкам программирования: Python, PHP, JavaScript, Ruby, Java и др., а также работе с библиотекой jQuery и языкам разметки и оформления веб-страницы HTML и CSS.
Udacity
Видео лекции на английском языке с субтитрами в сочетании со встроенными тестами и последующими домашними работами, основанные на модели «учиться на практике». Каждая лекция включает в себя встроенный тест, чтобы помочь студентам понять предлагаемые концепции и идеи.
Codewars
Это интерактивный сборник задач по программированию. Сейчас сервис поддерживает следующие языки: Clojure, C++, C#, Elixir, F#, Go, Haskell, Java, JavaScript, PHP, Python, Ruby, Rust, Shell, SQL, Swift, TypeScript.
Coursera
Coursera -- образовательная платформа, которая дает возможность пройти онлайн-обучение в ведущих образовательных учреждениях мира. Проект сотрудничает с университетами, которые публикуют и ведут в системе курсы по различным отраслям знаний.
Code Avengers
Code Avengers предоставляет возможность обучаться в интерактивной и игровой форме основам HTML5, CSS3, JavaScript прямо в браузере.