We created this style guide to keep the code in Virto Commerce consistent.
The goal is to help library designers ensure API consistency and ease of use by providing a unified programming model that is independent of the programming language used for development.
These guidelines are based on C# and Microsoft conventions.
We recommend that you follow these design guidelines when developing classes and components that extend the .NET Framework. Inconsistent library design adversely affects developer productivity and discourages adoption.
These guidelines are organized as simple recommendations prefixed with the terms
Do is one that should always be followed. Always might be a bit too strong of a word. Guidelines that literally should always be followed are extremely rare. On the other hand, you need a really unusual case for breaking a Do guideline.
Consider guidelines should generally be followed. If you fully understand the meaning behind the guideline and have a good reason to deviate, then do so. Please strive to be consistent.
Avoid indicates something you should almost never do. Code examples to avoid have an unmistakable red header.
Do not Just don't do it.
Why? gives reasons for following the previous recommendations.
Note: A guideline is flexible and can be adjusted and improved.
This is a set of tools and extension that helps you to detect and fix quality issues as you write your code. You must use these tools and fix the errors before commit to repository.
Use PowerCommands For Visual Studio
Install Productivity Power Tools
Go to “Tools > Options > Productivity Power Tools > PowerCommands” and Enable “Format documents on save” and “Remove and Sort Usings on save”.
Use SonarLint and SonarQube
SonarLint is an IDE extension that helps you detect and fix quality issues as you write code. Like a spell checker, SonarLint squiggles flaws so that they can be fixed before committing code.
Use Visual Studio Code Analysis
We recommend to use the Microsoft Rules rule set to focus on the most critical problems in your code, including potential security holes, application crashes, and other important logic and design errors.
Go to "Visual Studio > Analyze > Run Code Analysis > On Solution".
Read Coding Conventions
Read Design Guidelines
These guidelines are excerpted from the book FRAMEWORK DESIGN GUIDELINES: CONVENTIONS, IDIOMS, AND PATTERNS FOR REUSABLE .NET LIBRARIES, 2ND EDITION, by Krzysztof Cwalina and Brad Abrams.
Naming conventions are hugely important for maintainability and readability. This guide recommends naming conventions for the file names and the symbol names.
Names should be clear and meaningful
- Names should be clear and meaningful.
- Good names replace comments in most cases.
- Good names allow to read the code like a book.
Bad
var dataFromDb = db.GetData();
Good
var employees = employeeService.GetEmployees();
Use full words instead of shortened ones
Do Use full words instead of shortened one.
Bad
var empl = ...
var val = ...
var resp = ...
Good
var employees = ...
var value = ...
var response = ...
Names of private fields and constants should start with `_` and lowercase letter
Do Names of private fields and constants should start with _
and lowercase letter.
This is the only case when _
should be used in names.
Bad
private const int Batch_Size;
private char[] delimiters = { ',', ';' };
Good
private const int _batchSize;
private char[] _delimiters = { ',', ';' };
Don't add `Impl` suffix to interface implementations
Don't add Impl
suffix to interface implementations.
Bad
public class CatalogServiceImpl: ICatalogService
Good
public class CatalogService: ICatalogService
Use `result` instead of `retVal`
Do Use result
instead of retVal
.
Bad
var retVal = ...;
Good
var result = ...;
Use C# keywords instead of classes
Do Use C# keywords instead of classes:
Bad
String fullName = ...;
Int32 counter = ...;
Good
string fullName = ...;
int counter = ...;
Simplify single lambda expression parameter name, use full names for multiple parameters
Do For one argument - always use x
, for more than one - give full meaningful names:
Bad
i => …;
item => …;
(x, y) => …;
Good
x => …;
(key, value) => …;
Don't use regions, especially in small files
Don't use regions (#region), especially in small files.
Why? You have to expand each region before reading the code.
Combine class properties in logical groups
Consider Combine class properties in logical groups.
Initialize properties in the same order as they are declared in the class
Do Initialize properties in the same order as they are declared in the class.
Simplify complex conditions and expressions
Do Simplify complex conditions and expressions by creating intermediate variables with clear and meaningful names.
Check simple values in conditions first
Consider Check simple values in conditions first.
Bad
if (GetSomeValue() > 0 && isActive)
Good
if (isActive && GetSomeValue() > 0)
Split complex methods into multiple short methods with clear and meaningful names
Do Split complex methods into multiple short methods with clear and meaningful names.
Place calling method before the one being called
Do If one method calls another, place calling method before the one being called.
Each method should have only one return at the end
Do Each method should have only one return at the end.
Bad
if(!isActive)
return null;
...
return ...;
Good
var result = null;
if(isActive)
{
...
result = ...;
}
return result;
Avoid calling .ToList() or .ToArray() when you really need IEnumerable
Don't Call .ToList()
or .ToArray()
when you really need IEnumerable.
Don't use Single()
Don't use Single()
. Or if you do, handle exceptions
Bad
var employee = _employeeService.GetEmployees().Single();
Good
var employee = _employeeService.GetEmployees().FirstOrDefault();
Don't make API calls in a loop
Don't make API calls in a loop.
Use kebab notation for API URLs
Do Use kebab notation for API URLs.
Bad
fulfillmentCenters
Good
fulfillment-centers
API methods with [ResponseType(typeof(void))] attribute should return HttpStatusCode.NoContent
Do Return StatusCode(HttpStatusCode.NoContent), not Ok()
Your text editor must support .editorconfig
Do Your text editor must support .editorconfig.
Automatically format documents when saving
Do Automatically format documents when saving:
- Install PowerCommandsforVisualStudio
- Go to Tools > Options > Productivity Power Tools > PowerCommands
- Enable Format documents on save and Remove and Sort Usings on save
Place `System` directives first when sorting usings
Do Place System
directives first when sorting usings
Bad
using Nest;
using VirtoCommerce.Domain.Search
using System.Globalization;
Good
using System.Globalization;
using Nest;
using VirtoCommerce.Domain.Search
Whitespaces at the end of the line are not allowed
Don't Whitespaces at the end of the line are not allowed.
Use the following order of members in a class
Consider Use the following order of members in a class:
- constants
- private fields
- constructors
- public properties
- protected properties
- public methods
- protected methods
- private methods
Use two empty lines to separate public, protected and private method blocks from each other
Do Use two empty lines to separate public, protected and private method blocks from each other.
Bodies of if, for, etc. should be enclosed in braces
Do Bodies of if
, for
, etc. should be enclosed in braces.
Multi-line blocks of code should be separated with empty line from other code
Do Multi-line blocks of code should be separated with empty line from other code.
Separate `return` at the end of the method with empty line from other code
Do Separate return at the end of the method with empty line from other code.
Don't put condition and action on one line
Don't put condition and action on one line.
Avoid breaking the line if it does not exceed 170 characters
Avoid breaking the line if it does not exceed 170 characters.
Break complex (hard to read) LINQ expressions into multiple lines
Do Break complex (hard to read) LINQ expressions into multiple lines
Good
var names = repository.Items
.Where(x => x.IsActive && ids.Contains(x.Id)
.Select(x => x.Name)
.ToArray();
Put `where` on a separate line
Do Put where
on a separate line
Good
public void Parse<T>(string input)
where T: new()
Put a call to `base` or `this` constructor on a separate line
Do Put a call to base
or this
constructor on a separate line
Good
public MyClass(string argument)
: base(argument)
{
...
}
Don't nest multiple using (...), put them on the same level:
Don't nest multiple using (...), put them on the same level:
Good
using(var disposable1 = ...)
using(var disposable2 = ...)
{
...
}
Add `,` at the end of the line in object initializers
Do Add ,
at the end of the line in object initializers.
Why? This will reduce the number of modified lines in the next pull request.
Good
var criteria = new SearchCriteria
{
Skip = 0,
Take = 10,
};
Don't add `SubType Designer`. Use VS 2019, where this bug is fixed
Don't add <SubType>Designer</SubType>
. Use VS 2019, where this bug is fixed.
Use Assert.Equal
Do Use Assert.Equal(expected, actual)
instead of Assert.True(actual == expected)
.
Custom modules must use the same versions of NuGet packages as in platform or in VC modules
Do Custom modules must use the same versions of NuGet packages as in platform or in VC modules.
module.manifest should contain the same dependencies as packages.config
Do module.manifest should contain the same dependencies as packages.config.
Web.config and app.config in modules should contain only the assemblyBinding section
Do Web.config and app.config in modules should contain only the assemblyBinding section
`bin` directroy of the module.zip should not contain files that exist in platform or in dependencies
Do bin
directroy of the module.zip should not contain files that exist in platform or in dependencies. Use module.ignore
to exclude them from the ZIP.
All API actions should have [CheckPermission] attribute
Do All API actions should have [CheckPermission]
attribute.
Good
[CheckPermission(Permission = ThumbnailPredefinedPermissions.Create)]
public IHttpActionResult Create(ThumbnailOption option)
{
_thumbnailOptionService.SaveOrUpdate(new[] { option });
return Ok(option);
}
Compare IDs and SKUs with `EqualsInvariant()`
Do Compare IDs and SKUs with EqualsInvariant()
.
Don't call `repository.GetByIds(ids)` if `ids` is empty
Don't call repository.GetByIds(ids)
if ids
is empty.
Short description
Do Long description
Bad
// Bad code example
Good
// Good code example