Нет смысла говорить, что "надо писать код без ошибок". Ошибки были, есть и будут. Все хорошо понимают, что ошибки следует исправлять. Люди забывают, что ошибка должна быть исправлена с минимальными временными и денежными затратами!
Нет смысла говорить, что "надо писать код без ошибок". Ошибки были, есть и будут. Все хорошо понимают, что ошибки следует исправлять. Люди забывают, что ошибка должна быть исправлена с минимальными временными и денежными затратами!
Статический анализ кода: борьба с удорожанием ошибок
1.
Статический анализ кода:
борьба с удорожанием
ошибок
Команда PVS-Studio
www.viva64.com
2.
Ошибки были, есть и будут
• Нет смысла говорить, что "надо писать код без ошибок"
• Ошибки были, есть и будут
• Все хорошо понимают, что ошибки следует исправлять
• Люди забывают, что ошибка должна быть исправлена с
минимальными временными и денежными затратами!
3.
Когда много героев - это плохой симптом
• Интересно рассказывать, как героически искали ошибку в течение
недели
• Однако для команды ничего нет хорошего в необходимости
совершать такие подвиги
Этому городу коду нужен герой!
4.
Чем раньше исправить ошибку, тем лучше
• В зависимости от типа бага, его исправление на этапе
кодирования обойдётся в 10-100 раз дешевле, чем на этапе
эксплуатации
• Есть разные методы:
• обзор кода
• юнит-тесты (или TDD)
• тестирование новой функциональности самим разработчиком
• динамический анализ кода (разновидность тестов)
• статический анализ, о котором мы будем говорить подробнее
5.
Что такое обзор кода
• Код смотрят несколько программистов
• В идеале - без компьютера
• Высказывают замечания и
рекомендации
6.
Преимущества обзора кода людьми
• Можно найти сложные ошибки
• Можно найти ошибки высокого уровня (например, выбран
медленный алгоритм)
7.
Недостатки обзора кода людьми
• Бывают ошибки, о существовании которых все собравшиеся даже
не догадываются
• Дорого
• Люди быстро устают
8.
Компромисс - статический анализ
• Преимущества анализаторов:
• проверяют весь код
• не устают
• знакомы с хитрыми паттернами ошибок
• Недостатки
• это просто программы, а не искусственный интеллект
• Однозначная польза, так как ошибки обнаруживаются сразу
• Аналогия: проверка орфографии в Microsoft Word.
9.
Инструменты статического анализа кода
• Будем рассказывать на примере PVS-Studio
• А вообще, найдётся инструмент на любой вкус:
• FxCop
• Klocwork
• Parasoft
• SonarQube
• Veracode
• Ещё: https://en.Wikipedia.org/wiki/List_of_tools_for_static_code_analysis
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.
Несколько примеров: поспешили
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.
Несколько примеров: сортировка
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.
Несколько примеров: нюанс
• Анализатор может распознавать паттерны ошибок, о
существовании которых команда даже не догадывается.
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
15.
Основная ошибка использования
анализатора кода
• Разовые проверки неэффективны
• Аналогия с предупреждениями компилятора
• Всё мешающее уже поправлено, осталась мелочь или
плавающие ошибки
16.
Ложные срабатывания
• Неизбежное зло, но инструменты предоставляют различные
механизмы борьбы с ними
• Работа с ложными срабатываниями на примере PVS-Studio
• точечное подавление
• отключение анализа отдельных папок/файлов
• отключение диагностик
• самое важное - база разметки, про неё подробнее
17.
PVS-Studio. Идеология базы разметки
• Позволяет начать использовать анализатор сразу для нового или
изменённого кода
• Старые ошибки, скорее всего, не критичны для
работоспособности, и их можно смотреть не спеша
18.
Как начать работать с базой разметки
1. Проверяем проект
2. Указываем, что все выданные предупреждения нам пока не
интересны
3. Закладываем файл с базой в систему контроля версий
4. PROFIT
19.
Дополнение
• Можно настроить запуск PVS-Studio на сервере
• И, используя утилиту BlameNotifier, рассылать письма тем, кто
заложил подозрительный код
20.
Почему так много говорится о
регулярности использования?
• Из отзыва пользователя PVS-Studio: "Пример использования
статического анализатора" - https://www.viva64.com/en/b/0221/
Резюме: ошибка, на обнаружение которой было безуспешно
потрачено около 50 часов, при помощи однократного запуска
анализатора была обнаружена и исправлена менее, чем за час!
Александр Лотохов
21.
SonarQube: визуализация данных
• Платформа с открытым исходным кодом для непрерывного
анализа и измерения качества кода
• Содержит ряд анализаторов, в том числе Sonar C#
• Красивая визуализация
23.
SonarQube: интеграция со сторонними
анализаторами. Зачем?
• Сильная сторона Sonar C# - оценка качества кода (поиск "запахов
кода")
• Слабая сторона Sonar C# - мало диагностик для поиска ошибок,
приводящих к неправильной работе приложений
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/
26.
Ещё одна важная ошибка
• Миф: это инструменты для новичков!
• Миф: мы профессионалы и не допускаем опечаток!
• Все мы допускаем ошибки. Причем, есть ситуации, где так и тянет
ошибиться.
• Например, Андрей Карпов написал статью:
The Evil within the Comparison Functions
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.
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.
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.
The Evil within the Comparison Functions
• Ссылка на статью:
https://www.viva64.com/en/b/0509/
31.
Итоги:
• Статический анализ - способ сразу найти часть ошибок, пока они
не подорожали
• Статический анализ должен использоваться регулярно
• Можно начать использовать анализ сразу, отложив правку старых
ошибок на потом
• C# программистам есть смысл обратить внимание на SonarQube
(Sonar С#) и PVS-Studio
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/
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.
Если осталось время, ещё примеры
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.
Если осталось время, ещё примеры
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.
Если осталось время, ещё примеры
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.
Если осталось время, ещё примеры
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.
Если осталось время, ещё примеры
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.
Если осталось время, ещё примеры
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.
Если осталось время, ещё примеры
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.
Если осталось время, ещё примеры
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.
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.
Если осталось время, ещё примеры
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.
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.
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.
Ещё больше примеров:
https://www.viva64.com/en/examples/
Il semblerait que vous ayez déjà ajouté cette diapositive à .
Créer un clipboard
Vous avez clippé votre première diapositive !
En clippant ainsi les diapos qui vous intéressent, vous pourrez les revoir plus tard. Personnalisez le nom d’un clipboard pour mettre de côté vos diapositives.
Créer un clipboard
Partager ce SlideShare
Vous avez les pubs en horreur?
Obtenez SlideShare sans publicité
Bénéficiez d'un accès à des millions de présentations, documents, e-books, de livres audio, de magazines et bien plus encore, sans la moindre publicité.
Offre spéciale pour les lecteurs de SlideShare
Juste pour vous: Essai GRATUIT de 60 jours dans la plus grande bibliothèque numérique du monde.
La famille SlideShare vient de s'agrandir. Profitez de l'accès à des millions de livres numériques, livres audio, magazines et bien plus encore sur Scribd.
Apparemment, vous utilisez un bloqueur de publicités qui est en cours d'exécution. En ajoutant SlideShare à la liste blanche de votre bloqueur de publicités, vous soutenez notre communauté de créateurs de contenu.
Vous détestez les publicités?
Nous avons mis à jour notre politique de confidentialité.
Nous avons mis à jour notre politique de confidentialité pour nous conformer à l'évolution des réglementations mondiales en matière de confidentialité et pour vous informer de la manière dont nous utilisons vos données de façon limitée.
Vous pouvez consulter les détails ci-dessous. En cliquant sur Accepter, vous acceptez la politique de confidentialité mise à jour.