Как писать высококлассный код. Часть пятая. StyleCop
После небольшой паузы, связанной с подготовкой и выступлением на .NET Saturday, я продолжаю цикл статей под общим названием «Как писать высококлассный код». Сегодняшняя статья будет посвящена инструменту под названием StyleCop.
StyleCop – младшая сестра или брат (кому как удобней) инструмента FxCop, о котором я писал в предыдущей части. Но, в отличии от FxCop, StyleCop обладает большим количеством дополнительных правил, связанных с оформлением кода.
Скачать инструмент можно по адресу http://stylecop.codeplex.com/, работает только для C# кода. На момент написания статьи последней стабильной версией инструмента является версия 4.4.0.
После установки StyleCop в Visual Studio появляется дополнительный функционал:
Все правила делятся на несколько групп:
- Documentation
- Layout
- Maintainability
- Naming
- Ordering
- Readability
- Spacing
Включить или выключить правила можно в окне свойств:
Рассмотрим основные правила, с которыми сталкиваются разработчики.
Documentation rules
*MustBeDocumented – все элементы (методы, переменные и т.д. должны быть задокументированы, включая приватные члены).
SA1625: ElementDocumentationMustNotBeCopiedAndPasted – описание переменных не должно совпадать:
/// <summary> /// Joins a first name and a last name together into a single string. /// </summary> /// <param name="firstName">Part of the name.</param> /// <param name="lastName">Part of the name.</param> /// <returns>The joined names.</returns> public string JoinNames(string firstName, string lastName) { return firstName + " " + lastName; }
SA1633: FileMustHaveHeader – все файлы должны содержать шапку:
//----------------------------------------------------------------------- // <copyright file="Widget.cs" company="Sprocket Enterprises"> // Copyright (c) Sprocket Enterprises. All rights reserved. // </copyright> // <author>John Doe</author> //-----------------------------------------------------------------------
Причем название файла должно совпадать со значением в file (SA1638: FileHeaderFileNameDocumentationMustMatchFileName).
SA1642: ConstructorSummaryDocumentationMustBeginWithStandardText – описание конструктора должно соответствовать шаблону "Initializes a new instance of the {class name} class.":
/// <summary> /// Initializes a new instance of the <see cref="Customer"/> class. /// </summary> public Customer() { }
То же самое для деструкторов (SA1643: DestructorSummaryDocumentationMustBeginWithStandardText).
Layout rules
SA1500: CurlyBracketsForMultiLineStatementsMustNotShareLine – скобки должны располагаться на отдельных линиях, т.е. вместо
public object Method() { lock (this) { return this.value; } }
должно быть
public object Method() { lock (this) { return this.value; } }
Между методом и комментариями не должно быть пустых линий (SA1506: ElementDocumentationHeadersMustNotBeFollowedByBlankLine), как здесь:
/// <summary> /// Gets a value indicating whether the control is enabled. /// </summary> public bool Enabled { get { return this.enabled; } }
То же самое для кода внутри методов (SA1507: CodeMustNotContainMultipleBlankLinesInARow).
Остальные правила также касаются, в основном, необходимости удаления пустых линий.
Maintainability rules
SA1119: StatementMustNotUseUnnecessaryParenthesis – код не должен содержать лишние скобки:
int x = (5 + b); string y = (this.Method()).ToString(); return (x.Value);
правильно:
int x = 5 + b; string y = this.Method().ToString(); return x.Value;
Все методы и свойства должны иметь явно указанный идентификатор доступа (SA1400: AccessModifierMustBeDeclared).
Один файл может содержать только один одноименный класс (SA1402: FileMayOnlyContainASingleClass).
Для математических выражений необходимо четко указывать порядок выполнения с помощью дополнительных скобок (SA1407: ArithmeticExpressionsMustDeclarePrecedence). Т.е. такой код:
int x = 5 + y * b / 6 % z - 2;
нужно переписать таким образом:
int x = 5 + (y * ((b / 6) % z)) - 2;
Код не должен содержать не используемый код (SA1409: RemoveUnnecessaryCode):
Naming rules
Если коротко, то названия методов, классов должны начинаться с заглавной буквы (SA1300: ElementMustBeginWithUpperCaseLetter), а интерфейсы – с буквы “I” (SA1302: InterfaceNamesMustBeginWithI). Нельзя использовать префиксы m_ или s_ в именах переменных (SA1308: VariableNamesMustNotBePrefixed), а также нельзя использовать символ подчеркивания (SA1309: FieldNamesMustNotBeginWithUnderscore, SA1310: FieldNamesMustNotContainUnderscore).
Ordering rules
Одно из самых обсуждаемых правил – все usings должны размещаться внутри namespaces.
Неправильно:
using System; using Guid = System.Guid; namespace Microsoft.Sample { public class Program { } }
Правильно:
namespace Microsoft.Sample { using System; using Guid = System.Guid; public class Program { } }
Если говорить о причине такого правила, то она связана с возможными трудностями при работе с алиасами.
Например, такой код успешно скомпилируется:
using Guid = System.Guid; namespace Microsoft.Sample { public class Guid { public Guid(string s) { } } public class Program { public static void Main(string[] args) { Guid g = new Guid("hello"); } } }
Но здесь непонятно, какой из Guid будет использоваться.
Такой код вызовет предупреждение CS0576: Namespace 'Microsoft.Sample' contains a definition conflicting with alias 'Guid':
namespace Microsoft.Sample { using Guid = System.Guid; public class Guid { public Guid(string s) { } } public class Program { public static void Main(string[] args) { Guid g = new Guid("hello"); } } }
Но поможет избежать путаницы в наименованиях.
Все элементы должны располагаться в нужном порядке внутри исходного файла (SA1201: ElementsMustAppearInTheCorrectOrder):
- Extern Alias Directives
- Using Directives
- Namespaces
- Delegates
- Enums
- Interfaces
- Structs
- Classes
В классе, структуре, интерфейсе порядок должен быть такой:
- Fields
- Constructors
- Finalizers (Destructors)
- Delegates
- Events
- Enums
- Interfaces
- Properties
- Indexers
- Methods
- Structs
- Classes
Элементы должны быть отсортированы о уровню доступа (SA1202: ElementsMustBeOrderedByAccess):
- public
- internal
- protected internal
- protected
- private
Все usings должны быть отсортированы, а неиспользуемые – удалены (SA1210: UsingDirectivesMustBeOrderedAlphabeticallyByNamespace).
Readability rules
Необходимо использовать префикс this для доступа к членам классов (SA1101: PrefixLocalCallsWithThis). Остальные правила такого типа связаны с позиционированием параметров, регионов, выражений и т.д.
Необходимо использовать string.Empty вместо пустой строки (SA1122: UseStringEmptyForEmptyStrings).
Необходимо использовать встроенные алиасы (int, string вместо Int32, String и т.д.) (SA1121: UseBuiltInTypeAlias).
Spacing rules
В этой группе много правил, связанных с табуляцией и пробелами. Если кратко, то код не должен содержать лишние пробелы, а использование табуляции запрещено (SA1027: TabsMustNotBeUsed).
Отключение правил в коде
Для того, чтобы не проверять некий код на определенное правило, можно воспользоваться специальным атрибутом:
[SuppressMessage("Rule Category, "Rule Id", "Justification")]
где:
- Rule Category – пространство имен StyleCop, в котором объявлено. Например, Microsoft.StyleCop.CSharp.DocumentationRules;
- Rule Id –идентификатор правила в формате shortname:longname. Например, SA1600:ElementsMustBeDocumented;
- Justification – текст, который будет использован для объяснения причины, почему то или иное правило было пропущено.
Пример:
[SuppressMessage("Microsoft.StyleCop.CSharp.DocumentationRules", "SA1600:ElementsMustBeDocumented")] public class MyUndocumentedClass { public void MyUndocumentedMethod { } }
Если вы хотите запретить все правила в заданном пространстве имен, то это можно сделать таким образом:
public class OuterClass { [SuppressMessage("Microsoft.StyleCop.CSharp.DocumentationRules", "*")] public class InnerClass { public void MyUndocumentedMethod { } } }
StyleCop for Resharper
Кроме, собственно, StyleCop, есть еще один продукт под названием StyleCop for Resharper. Как нетрудно догадаться из названия, этот инструмент служит для интеграции правил с Resharper.
Сайт: http://stylecopforresharper.codeplex.com/
В целом, использование StyleCop делает ваш код красивым и простым с точки зрения читабельности и оформления, что очень важно для последовательной поддержки.
Литература:
Компании из статьи
Microsoft Украина | Украинское подразделение компании Microsoft. |