Skip to content

Commit

Permalink
Merge pull request #160 from bkoelman/rulenames
Browse files Browse the repository at this point in the history
Update rule names and cheat sheet
  • Loading branch information
dennisdoomen authored May 10, 2018
2 parents 86115e4 + c7a22c0 commit 62f4968
Show file tree
Hide file tree
Showing 10 changed files with 207 additions and 194 deletions.
2 changes: 1 addition & 1 deletion _pages/1000_ClassDesignGuidelines.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ With the exception of extension method containers, static classes very often lea

**Note:** If you really need that static class, mark it as static so that the compiler can prevent instance members and instantiating your class. This relieves you of creating an explicit private constructor.

### <a name="av1010"></a> Don't suppress compiler warnings using the new keyword (AV1010) ![](/assets/images/1.png)
### <a name="av1010"></a> Don't suppress compiler warnings using the `new` keyword (AV1010) ![](/assets/images/1.png)

Compiler warning [CS0114](https://docs.microsoft.com/en-us/dotnet/csharp/misc/cs0114) is issued when breaking [Polymorphism](http://en.wikipedia.org/wiki/Polymorphism_in_object-oriented_programming), one of the most essential object-orientation principles.
The warning goes away when you add the `new` keyword, but it keeps sub-classes difficult to understand. Consider the following two classes:
Expand Down
2 changes: 1 addition & 1 deletion _pages/1100_MemberDesignGuidelines.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ Properties should be stateless with respect to other properties, i.e. there shou

**Exception:** Populating an internal cache or implementing [lazy-loading](http://www.martinfowler.com/eaaCatalog/lazyLoad.html) is a good exception.

### <a name="av1110"></a> Don't use mutual exclusive properties (AV1110) ![](/assets/images/1.png)
### <a name="av1110"></a> Don't use mutually exclusive properties (AV1110) ![](/assets/images/1.png)

Having properties that cannot be used at the same time typically signals a type that represents two conflicting concepts. Even though those concepts may share some of their behavior and states, they obviously have different rules that do not cooperate.

Expand Down
10 changes: 5 additions & 5 deletions _pages/1200_MiscellaneousDesignGuidelines.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ The message should explain the cause of the exception, and clearly describe what

For example, if a method receives a `null` argument, it should throw `ArgumentNullException` instead of its base type `ArgumentException`.

### <a name="av1210"></a> Don't swallow errors by catching generic exceptions (AV1210) ![](/assets/images/1.png)
### <a name="av1210"></a> Don't swallow errors by catching generic exceptions (AV1210) ![](/assets/images/1.png)

Avoid swallowing errors by catching non-specific exceptions, such as `Exception`, `SystemException`, and so on, in application code. Only top-level code, such as a last-chance exception handler, should catch a non-specific exception for logging purposes and a graceful shutdown of the application.
Avoid swallowing errors by catching non-specific exceptions, such as `Exception`, `SystemException`, and so on, in application code. Only top-level code, such as a last-chance exception handler, you should catch a non-specific exception for logging purposes and a graceful shutdown of the application.

### <a name="av1215"></a> Properly handle exceptions in asynchronous code (AV1215) ![](/assets/images/2.png)
When throwing or handling exceptions in code that uses `async`/`await` or a `Task` remember the following two rules:
Expand Down Expand Up @@ -50,7 +50,7 @@ Consider providing events that are raised when certain properties are changed. S

**Note:** If your class has many properties that require corresponding events, consider implementing the `INotifyPropertyChanged` interface instead. It is often used in the [Presentation Model](http://martinfowler.com/eaaDev/PresentationModel.html) and [Model-View-ViewModel](http://msdn.microsoft.com/en-us/magazine/dd419663.aspx) patterns.

### <a name="av1235"></a> Don't pass `null` as the `sender` argument when raising an event (AV1235) ![](/assets/images/1.png)
### <a name="av1235"></a> Don't pass `null` as the `sender` argument when raising an event (AV1235) ![](/assets/images/1.png)

Often an event handler is used to handle similar events from multiple senders. The sender argument is then used to get to the source of the event. Always pass a reference to the source (typically `this`) when raising the event. Furthermore don't pass `null` as the event data parameter when raising an event. If there is no event data, pass `EventArgs.Empty` instead of `null`.

Expand Down Expand Up @@ -81,7 +81,7 @@ Instead of casting to and from the object type in generic types or methods, use
}
}

### <a name="av1250"></a> Evaluate the result of a LINQ expression before returning it (AV1250) ![](/assets/images/1.png)
### <a name="av1250"></a> Evaluate the result of a LINQ expression before returning it (AV1250) ![](/assets/images/1.png)

Consider the following code snippet

Expand All @@ -99,6 +99,6 @@ Consider the following code snippet

Since LINQ queries use deferred execution, returning `query` will actually return the expression tree representing the above query. Each time the caller evaluates this result using a `foreach` cycle or similar, the entire query is re-executed resulting in new instances of `GoldMember` every time. Consequently, you cannot use the `==` operator to compare multiple `GoldMember` instances. Instead, always explicitly evaluate the result of a LINQ query using `ToList()`, `ToArray()` or similar methods.

### <a name="av1251"></a> Do not use `this` and `base` prefixes unless it is required (AV1251) ![](/assets/images/1.png)
### <a name="av1251"></a> Do not use `this` and `base` prefixes unless it is required (AV1251) ![](/assets/images/1.png)

In a class hierarchy, it is not necessary to know at which level a member is declared to use it. Refactoring derived classes is harder if that level is fixed in the code.
18 changes: 9 additions & 9 deletions _pages/1500_MaintainabilityGuidelines.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ sidebar:
### <a name="av1500"></a> Methods should not exceed 7 statements (AV1500) ![](/assets/images/1.png)
A method that requires more than 7 statements is simply doing too much or has too many responsibilities. It also requires the human mind to analyze the exact statements to understand what the code is doing. Break it down into multiple small and focused methods with self-explaining names, but make sure the high-level algorithm is still clear.

### <a name="av1501"></a> Make all members private and types internal sealed by default (AV1501) ![](/assets/images/1.png)
### <a name="av1501"></a> Make all members `private` and types `internal sealed` by default (AV1501) ![](/assets/images/1.png)
To make a more conscious decision on which members to make available to other classes, first restrict the scope as much as possible. Then carefully decide what to expose as a public member or type.

### <a name="av1502"></a> Avoid conditions with double negatives (AV1502) ![](/assets/images/2.png)
Expand Down Expand Up @@ -45,7 +45,7 @@ When using partial types and allocating a part per file, name each file after th
public partial class MyClass
{...}

### <a name="av1510"></a> Use using statements instead of fully qualified type names (AV1510) ![](/assets/images/3.png)
### <a name="av1510"></a> Use `using` statements instead of fully qualified type names (AV1510) ![](/assets/images/3.png)
Limit usage of fully qualified type names to prevent name clashing. For example, don't do this:

var list = new System.Collections.Generic.List<string>();
Expand Down Expand Up @@ -85,7 +85,7 @@ If the value of one constant depends on the value of another, attempt to make th

**Note:** An enumeration can often be used for certain types of symbolic constants.

### <a name="av1520"></a> Only use var when the type is very obvious (AV1520) ![](/assets/images/1.png)
### <a name="av1520"></a> Only use `var` when the type is very obvious (AV1520) ![](/assets/images/1.png)
Only use `var` as the result of a LINQ query, or if the type is very obvious from the same statement and using it would improve readability. So don't

var item = 3; // what type? int? uint? float?
Expand Down Expand Up @@ -120,7 +120,7 @@ Don't use confusing constructs like the one below:

(int a, int b) = M();

### <a name="av1523"></a> Favor Object and Collection Initializers over separate statements (AV1523) ![](/assets/images/2.png)
### <a name="av1523"></a> Favor object and collection initializers over separate statements (AV1523) ![](/assets/images/2.png)
Instead of:

var startInfo = new ProcessStartInfo("myapp.exe");
Expand Down Expand Up @@ -160,7 +160,7 @@ It is usually bad style to compare a `bool`-type expression to `true` or `false`
while (((condition == true) == true) == true) // where do you stop?
while (condition) // OK

### <a name="av1530"></a> Don't change a loop variable inside a for loop (AV1530) ![](/assets/images/2.png)
### <a name="av1530"></a> Don't change a loop variable inside a `for` loop (AV1530) ![](/assets/images/2.png)
Updating the loop variable within the loop body is generally considered confusing, even more so if the loop variable is modified in more than one place.

for (int index = 0; index < 10; ++index)
Expand Down Expand Up @@ -219,7 +219,7 @@ Add a descriptive comment if the `default` block is supposed to be empty. Moreov
}
}

### <a name="av1537"></a> Finish every if-else-if statement with an else-part (AV1537) ![](/assets/images/2.png)
### <a name="av1537"></a> Finish every `if`-`else`-`if` statement with an `else` clause (AV1537) ![](/assets/images/2.png)
For example:

void Foo(string answer)
Expand All @@ -239,10 +239,10 @@ For example:
}
}

### <a name="av1540"></a> Be reluctant with multiple return statements (AV1540) ![](/assets/images/2.png)
### <a name="av1540"></a> Be reluctant with multiple `return` statements (AV1540) ![](/assets/images/2.png)
One entry, one exit is a sound principle and keeps control flow readable. However, if the method body is very small and complies with guideline AV1500 then multiple return statements may actually improve readability over some central boolean flag that is updated at various points.

### <a name="av1545"></a> Don't use if-else statements instead of a simple (conditional) assignment (AV1545) ![](/assets/images/2.png)
### <a name="av1545"></a> Don't use an `if`-`else` construct instead of a simple (conditional) assignment (AV1545) ![](/assets/images/2.png)
Express your intentions directly. For example, rather than:

bool isPositive;
Expand Down Expand Up @@ -387,7 +387,7 @@ C# 4.0's named arguments have been introduced to make it easier to call COM comp

object[] myAttributes = type.GetCustomAttributes(typeof(MyAttribute), inherit: false);

### <a name="av1561"></a> Don't declare signatures with more than three parameters (AV1561) ![](/assets/images/1.png)
### <a name="av1561"></a> Don't declare signatures with more than 3 parameters (AV1561) ![](/assets/images/1.png)
To keep constructors, methods, delegates and local functions small and focused, do not use more than three parameters. Do not use tuple parameters. Do not return tuples with more than two elements.

If you want to use more parameters, use a structure or class to pass multiple arguments, as explained in the [Specification design pattern](http://en.wikipedia.org/wiki/Specification_pattern).
Expand Down
Loading

0 comments on commit 62f4968

Please sign in to comment.