Ce diaporama a bien été signalé.
Le téléchargement de votre SlideShare est en cours. ×

Статический анализ кода: борьба с удорожанием ошибок

Publicité
Publicité
Publicité
Publicité
Publicité
Publicité
Publicité
Publicité
Publicité
Publicité
Publicité
Publicité

Consultez-les par la suite

1 sur 50 Publicité

Статический анализ кода: борьба с удорожанием ошибок

Télécharger pour lire hors ligne

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

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

Publicité
Publicité

Plus De Contenu Connexe

Diaporamas pour vous (20)

Similaire à Статический анализ кода: борьба с удорожанием ошибок (20)

Publicité

Plus par Andrey Karpov (20)

Plus récents (19)

Publicité

Статический анализ кода: борьба с удорожанием ошибок

  1. 1. Статический анализ кода: борьба с удорожанием ошибок Команда PVS-Studio www.viva64.com
  2. 2. Ошибки были, есть и будут • Нет смысла говорить, что "надо писать код без ошибок" • Ошибки были, есть и будут • Все хорошо понимают, что ошибки следует исправлять • Люди забывают, что ошибка должна быть исправлена с минимальными временными и денежными затратами!
  3. 3. Когда много героев - это плохой симптом • Интересно рассказывать, как героически искали ошибку в течение недели • Однако для команды ничего нет хорошего в необходимости совершать такие подвиги Этому городу коду нужен герой!
  4. 4. Чем раньше исправить ошибку, тем лучше • В зависимости от типа бага, его исправление на этапе кодирования обойдётся в 10-100 раз дешевле, чем на этапе эксплуатации • Есть разные методы: • обзор кода • юнит-тесты (или TDD) • тестирование новой функциональности самим разработчиком • динамический анализ кода (разновидность тестов) • статический анализ, о котором мы будем говорить подробнее
  5. 5. Что такое обзор кода • Код смотрят несколько программистов • В идеале - без компьютера • Высказывают замечания и рекомендации
  6. 6. Преимущества обзора кода людьми • Можно найти сложные ошибки • Можно найти ошибки высокого уровня (например, выбран медленный алгоритм)
  7. 7. Недостатки обзора кода людьми • Бывают ошибки, о существовании которых все собравшиеся даже не догадываются • Дорого • Люди быстро устают
  8. 8. Компромисс - статический анализ • Преимущества анализаторов: • проверяют весь код • не устают • знакомы с хитрыми паттернами ошибок • Недостатки • это просто программы, а не искусственный интеллект • Однозначная польза, так как ошибки обнаруживаются сразу • Аналогия: проверка орфографии в Microsoft Word.
  9. 9. Инструменты статического анализа кода • Будем рассказывать на примере PVS-Studio • А вообще, найдётся инструмент на любой вкус: • FxCop • Klocwork • Parasoft • SonarQube • Veracode • Ещё: https://en.Wikipedia.org/wiki/List_of_tools_for_static_code_analysis
  10. 10. Несколько примеров: опечатка static bool AreEqual (VisualStyleElement value1, VisualStyleElement value2) { return value1.ClassName == value1.ClassName && value1.Part == value2.Part && value1.State == value2.State; } PVS-Studio: V3001 There are identical sub-expressions 'value1.ClassName' to the left and to the right of the '==' operator. ThemeVisualStyles.cs 2141 Mono
  11. 11. Несколько примеров: поспешили void IBackgroundTask.Sweep() { .... // Don't flood the database with progress updates; // Limit it to every 5 seconds. if ((_clock.UtcNow - lastUpdateUtc).Seconds >= 5) { .... PVS-Studio: V3118 Seconds component of TimeSpan is used, which does not represent full time interval. Possibly 'TotalSeconds' value was intended instead. AssetUploader.cs 182 Orchard CMS должно быть TotalSeconds
  12. 12. Несколько примеров: сортировка PVS-Studio: V3078 Original sorting order will be lost after repetitive call to 'OrderBy' method. Use 'ThenBy' method to preserve the original sorting. CodeCoverageMethodElement.cs 124 SharpDevelop void Init() { .... this.SequencePoints.OrderBy(item => item.Line) .OrderBy(item => item.Column); }
  13. 13. Несколько примеров: нюанс • Анализатор может распознавать паттерны ошибок, о существовании которых команда даже не догадывается. static class Profiler { [ThreadStatic] private static Stopwatch timer = new Stopwatch(); .... Mono V3089 Initializer of a field marked by [ThreadStatic] attribute will be called once on the first accessing thread. The field will have default value on different threads. System.Data.Linq- net_4_x Profiler.cs 16
  14. 14. Еще примеры в конце доклада
  15. 15. Основная ошибка использования анализатора кода • Разовые проверки неэффективны • Аналогия с предупреждениями компилятора • Всё мешающее уже поправлено, осталась мелочь или плавающие ошибки
  16. 16. Ложные срабатывания • Неизбежное зло, но инструменты предоставляют различные механизмы борьбы с ними • Работа с ложными срабатываниями на примере PVS-Studio • точечное подавление • отключение анализа отдельных папок/файлов • отключение диагностик • самое важное - база разметки, про неё подробнее
  17. 17. PVS-Studio. Идеология базы разметки • Позволяет начать использовать анализатор сразу для нового или изменённого кода • Старые ошибки, скорее всего, не критичны для работоспособности, и их можно смотреть не спеша
  18. 18. Как начать работать с базой разметки 1. Проверяем проект 2. Указываем, что все выданные предупреждения нам пока не интересны 3. Закладываем файл с базой в систему контроля версий 4. PROFIT
  19. 19. Дополнение • Можно настроить запуск PVS-Studio на сервере • И, используя утилиту BlameNotifier, рассылать письма тем, кто заложил подозрительный код
  20. 20. Почему так много говорится о регулярности использования? • Из отзыва пользователя PVS-Studio: "Пример использования статического анализатора" - https://www.viva64.com/en/b/0221/ Резюме: ошибка, на обнаружение которой было безуспешно потрачено около 50 часов, при помощи однократного запуска анализатора была обнаружена и исправлена менее, чем за час! Александр Лотохов
  21. 21. SonarQube: визуализация данных • Платформа с открытым исходным кодом для непрерывного анализа и измерения качества кода • Содержит ряд анализаторов, в том числе Sonar C# • Красивая визуализация
  22. 22. SonarQube: красота
  23. 23. SonarQube: интеграция со сторонними анализаторами. Зачем? • Сильная сторона Sonar C# - оценка качества кода (поиск "запахов кода") • Слабая сторона Sonar C# - мало диагностик для поиска ошибок, приводящих к неправильной работе приложений
  24. 24. SonarQube: интеграция со сторонними анализаторами • Выход: интеграция с другими анализаторами • Например с PVS-Studio • PVS-Studio особенно хорош в поиске реальных багов и опечаток • 137 диагностик для поиска багов в C# коде Пример: Analysis of PascalABC.NET using SonarQube plugins: SonarC# and PVS-Studio - https://www.viva64.com/en/b/0492/
  25. 25. SonarQube + PVS-Studio
  26. 26. Ещё одна важная ошибка • Миф: это инструменты для новичков! • Миф: мы профессионалы и не допускаем опечаток! • Все мы допускаем ошибки. Причем, есть ситуации, где так и тянет ошибиться. • Например, Андрей Карпов написал статью: The Evil within the Comparison Functions
  27. 27. Инопланетяне в этом не виноваты IronPython and IronRuby public static int Compare(SourceLocation left, SourceLocation right) { if (left < right) return -1; if (right > left) return 1; return 0; } PVS-Studio warning (C#): V3021 There are two 'if' statements with identical conditional expressions. The first 'if' statement contains method return. This means that the second 'if' statement is senseless. SourceLocation.cs 156
  28. 28. The Evil within the Comparison Functions SharpDevelop public int Compare(SharpTreeNode x, SharpTreeNode y) { .... if (typeNameComparison == 0) { if (x.Text.ToString().Length < y.Text.ToString().Length) return -1; if (x.Text.ToString().Length < y.Text.ToString().Length) return 1; PVS-Studio warning: V3021 There are two 'if' statements with identical conditional expressions. The first 'if' statement contains method return. This means that the second 'if' statement is senseless NamespaceTreeNode.cs 87
  29. 29. The Evil within the Comparison Functions public int Compare(GlyphRun a, GlyphRun b) { .... if (aPoint.Y > bPoint.Y) { return -1; } else if (aPoint.Y > bPoint.Y) { result = 1; } else if (aPoint.X < bPoint.X) .... WPF samples by Microsoft PVS-Studio warning: V3003 The use of 'if (A) {...} else if (A) {...}' pattern was detected. There is a probability of logical error presence. Check lines: 418, 422. txtserializerwriter.cs 418
  30. 30. The Evil within the Comparison Functions • Ссылка на статью: https://www.viva64.com/en/b/0509/
  31. 31. Итоги: • Статический анализ - способ сразу найти часть ошибок, пока они не подорожали • Статический анализ должен использоваться регулярно • Можно начать использовать анализ сразу, отложив правку старых ошибок на потом • C# программистам есть смысл обратить внимание на SonarQube (Sonar С#) и PVS-Studio
  32. 32. Полезные ссылки • List of tools for static code analysis https://en.wikipedia.org/wiki/List_of_tools_for_static_code_analysis • PVS-Studio https://www.viva64.com/en/pvs-studio/ • SonaqQube https://www.sonarqube.org/
  33. 33. Q&A www.viva64.com support@viva64.com
  34. 34. Если осталось время, ещё примеры Umbraco protected virtual void OnBeforeNodeRender(ref XmlTree sender, ref XmlTreeNode node, EventArgs e) { if (node != null && node != null) { if (BeforeNodeRender != null) BeforeNodeRender(ref sender, ref node, e); } } PVS-Studio: V3001 There are identical sub-expressions 'node != null' to the left and to the right of the '&&' operator.
  35. 35. Если осталось время, ещё примеры CodeContracts if (mTypeConstraint == TypeConstraint.CLASS) { oh.Output("class", false); comma = true; } else if (mTypeConstraint == TypeConstraint.STRUCT) ..... else if (mTypeConstraint == TypeConstraint.CLASS) { oh.Output(mClassConstraint, false); comma = true; } PVS-Studio: V3003 The use of 'if (A) {...} else if (A) {...}' pattern was detected. There is a probability of logical error presence.
  36. 36. Если осталось время, ещё примеры CodeContracts for (int i = 0; i < data.Length; i++) { if (data[i] != null) { for (int j = 0; j < lastElement[i]; i++) { str.AppendFormat("({0},{1})", data[i][j].Index, data[i][j].Value); } } } PVS-Studio: V3014 It is likely that a wrong variable is being incremented inside the 'for' operator. Consider reviewing 'i'.
  37. 37. Если осталось время, ещё примеры Orleans public static string SanitizeTableProperty(string key) { key.Replace('/', '_'); // Forward slash key.Replace('', '_'); // Backslash key.Replace('#', '_'); // Pound sign key.Replace('?', '_'); // Question mark .... return key; } PVS-Studio: V3010 The return value of function 'Replace' is required to be utilized.
  38. 38. Если осталось время, ещё примеры SharpDevelop public WhitespaceNode(string whiteSpaceText, TextLocation startLocation) { this.WhiteSpaceText = WhiteSpaceText; this.startLocation = startLocation; } PVS-Studio: V3005 The 'this.WhiteSpaceText' variable is assigned to itself. www.viva64.com40
  39. 39. Если осталось время, ещё примеры SharpDevelop ContentPropertyNode clickedNode = clickedButton.DataContext as ContentPropertyNode; clickedNode = clickedButton.DataContext as ContentPropertyNode; if (clickedNode == null) Избыточность. PVS-Studio: V3008 The 'clickedNode' variable is assigned values twice successively. Perhaps this is a mistake.
  40. 40. Если осталось время, ещё примеры SharpDevelop public override string ToString() { return String.Format("[Line {0}:{1,2}-{3,4}:{5}]", File, Row, Column, EndRow, EndColumn, Offset); } PVS-Studio: V3025 Incorrect format. A different number of actual arguments is expected while calling 'Format' function. Expected: 4. Present: 6.
  41. 41. Если осталось время, ещё примеры GitExtensions if (string.IsNullOrEmpty(translationCategory.Name)) new InvalidOperationException( "Cannot add translationCategory without name"); PVS-Studio: V3006 The object was created but it is not being used. The 'throw' keyword could be missing: throw new InvalidOperationException(FOO). throw
  42. 42. Если осталось время, ещё примеры Orleans if (numRemoved > 0) if (logger.IsVerbose) logger.Verbose(....); else if (logger.IsVerbose2) logger.Verbose2(....); PVS-Studio: V3033 It is possible that this 'else' branch must apply to the previous 'if' statement. Interner.cs 274
  43. 43. MSBuild (ResolveSDKReference_Tests.cs) installedSDK.SetMetadata("SDKName", "GoodTestSDK, Version=2.0"); t.InstalledSDKs = new ITaskItem[] { installedSDK }; t.TargetedSDKConfiguration = "Debug"; t.TargetedSDKConfiguration = "x86"; t.BuildEngine = engine; PVS-Studio: V3008 The 't.TargetedSDKConfiguration' variable is assigned values twice successively. Perhaps this is a mistake. t.TargetedSDKArchitecture • Хороший пример, что анализатор дополняет юнит-тесты Если осталось время, ещё примеры
  44. 44. Если осталось время, ещё примеры CruiseControl.NET public void ModificationsAreComparedByModifiedDatetime() { Modification alpha = new Modification(); alpha.ModifiedTime = new DateTime(1975, 3, 3); Modification beta = new Modification(); alpha.ModifiedTime = new DateTime(1961, 3, 3); .... } PVS-Studio: V3008 The 'alpha.ModifiedTime' variable is assigned values twice successively. Perhaps this is a mistake.
  45. 45. Xamarin.Forms (C#) internal bool IsDefault { get { return Left == 0 && Top == 0 && Right == 0 && Left == 0; } } V3001 There are identical sub-expressions 'Left == 0' to the left and to the right of the '&&' operator. Thickness.cs 29 Если осталось время, ещё примеры
  46. 46. Space Engineers (C#) void DeserializeV0(XmlReader reader) { .... if (property.Name == "Rotation" || property.Name == "AxisScale" || property.Name == "AxisScale") continue; .... } Если осталось время, ещё примеры V3001 There are identical sub-expressions 'property.Name == "AxisScale"' to the left and to the right of the '||' operator. Sandbox.Graphics MyParticleEmitter.cs 352
  47. 47. Ещё больше примеров: https://www.viva64.com/en/examples/
  48. 48. The end

×