├── .gitignore ├── Class.Design.Guidelines.md ├── Documentation.Guidelines.md ├── Framework.Guidelines.md ├── LICENSE ├── Layout.Guidelines.md ├── Maintainability.Guidelines.md ├── Member.Design.Guidelines.md ├── Miscellaneous.Design.Guidelines.md ├── Naming.Guidelines.md ├── Performance.Guidelines.md ├── README.md ├── imgs ├── exception.png ├── important.png ├── may.png ├── must.png ├── note.png └── should.png └── localisation └── ko ├── Class.Design.Guidelines.md ├── Documentation.Guidelines.md ├── Framework.Guidelines.md ├── Layout.Guidelines.md ├── Maintainability.Guidelines.md ├── Member.Design.Guidelines.md ├── Miscellaneous.Design.Guidelines.md ├── Naming.Guidelines.md ├── Performance.Guidelines.md ├── README.md └── imgs ├── exception.png ├── important.png ├── may.png ├── must.png ├── note.png └── should.png /.gitignore: -------------------------------------------------------------------------------- 1 | # Build Folders (you can keep bin if you'd like, to store dlls and pdbs) 2 | [Bb]in/ 3 | [Oo]bj/ 4 | 5 | # mstest test results 6 | TestResults 7 | 8 | ## Ignore Visual Studio temporary files, build results, and 9 | ## files generated by popular Visual Studio add-ons. 10 | 11 | # User-specific files 12 | *.suo 13 | *.user 14 | *.sln.docstates 15 | 16 | # Build results 17 | [Dd]ebug/ 18 | [Rr]elease/ 19 | x64/ 20 | *_i.c 21 | *_p.c 22 | *.ilk 23 | *.meta 24 | *.obj 25 | *.pch 26 | *.pdb 27 | *.pgc 28 | *.pgd 29 | *.rsp 30 | *.sbr 31 | *.tlb 32 | *.tli 33 | *.tlh 34 | *.tmp 35 | *.log 36 | *.vspscc 37 | *.vssscc 38 | .builds 39 | 40 | # Visual C++ cache files 41 | ipch/ 42 | *.aps 43 | *.ncb 44 | *.opensdf 45 | *.sdf 46 | 47 | # Visual Studio profiler 48 | *.psess 49 | *.vsp 50 | *.vspx 51 | 52 | # Guidance Automation Toolkit 53 | *.gpState 54 | 55 | # ReSharper is a .NET coding add-in 56 | _ReSharper* 57 | 58 | # NCrunch 59 | *.ncrunch* 60 | .*crunch*.local.xml 61 | 62 | # Installshield output folder 63 | [Ee]xpress 64 | 65 | # DocProject is a documentation generator add-in 66 | DocProject/buildhelp/ 67 | DocProject/Help/*.HxT 68 | DocProject/Help/*.HxC 69 | DocProject/Help/*.hhc 70 | DocProject/Help/*.hhk 71 | DocProject/Help/*.hhp 72 | DocProject/Help/Html2 73 | DocProject/Help/html 74 | 75 | # Click-Once directory 76 | publish 77 | 78 | # Publish Web Output 79 | *.Publish.xml 80 | 81 | # NuGet Packages Directory 82 | packages 83 | 84 | # Windows Azure Build Output 85 | csx 86 | *.build.csdef 87 | 88 | # Windows Store app package directory 89 | AppPackages/ 90 | 91 | # Others 92 | [Bb]in 93 | [Oo]bj 94 | sql 95 | TestResults 96 | [Tt]est[Rr]esult* 97 | *.Cache 98 | ClientBin 99 | [Ss]tyle[Cc]op.* 100 | ~$* 101 | *.dbmdl 102 | Generated_Code #added for RIA/Silverlight projects 103 | 104 | # Backup & report files from converting an old project file to a newer 105 | # Visual Studio version. Backup files are not needed, because we have git ;-) 106 | _UpgradeReport_Files/ 107 | Backup*/ 108 | UpgradeLog*.XML 109 | -------------------------------------------------------------------------------- /Class.Design.Guidelines.md: -------------------------------------------------------------------------------- 1 | # Class Design Guidelines # 2 | 3 | ## A class or interface should have a single purpose ![](imgs/must.png) ## 4 | 5 | A class or interface should have a single purpose within the system it participates in. In general, a class is either representing a primitive type like an email or ISBN number, an abstraction of some business concept, a plain data structure or responsible for orchestrating the interaction between other classes. It is never a combination of those. This rule is widely known as the [Single Responsibility Principle (SRP)][srp], one of the [SOLID principles][solid]. 6 | 7 | Using [Design Patterns](http://en.wikipedia.org/wiki/Design_pattern_(computer_science)) is to communicate the intent of a class. If a single design pattern is assigned to a class, the class is more likely doing more than one thing. 8 | 9 | 10 | ## An interface should be small and focused ![](imgs/should.png) ## 11 | 12 | Interfaces should have a name that clearly explains the purpose or role of that interface within the system. Do not combine many vaguely related members on the same interface just because they were all on the same class. Separate the members based on the responsibility of those members so that callers only need to call or implement the interface related to a particular task. This rule is more commonly known as the [Interface Segregation Principle (ISP)][isp], one of the [SOLID principles][solid]. 13 | 14 | 15 | ## Use an interface rather than a base class to support multiple implementations ![](imgs/may.png) ## 16 | 17 | If you want to expose an extension point from your class, expose it as an interface rather than a base class. You don't want to force users of that extension point to derive their implementations from a base-class that might have undesired behavior. However, for their convenience you may implement an (abstract) default implementation that can serve as a starting point. 18 | 19 | 20 | ## Use an interface to decouple classes from each other ![](imgs/should.png) ## 21 | 22 | Interfaces are a very effective mechanism for decoupling classes from each other because: 23 | 24 | * they can prevent bidirectional associations; 25 | * they simplify the replacement of one implementation with another; 26 | * They allow replacing an expensive external service or resource with a temporary stub for use in a non-production environment; 27 | * they allow replacing the actual implementation with a dummy implementation or a fake object in a unit test; and 28 | * using a dependency injection framework you can centralize the choice which class is going to be used whenever a specific interface is requested. 29 | 30 | 31 | ## Avoid static classes ![](imgs/may.png) ## 32 | 33 | Static classes very often lead to badly designed code, except implementing extension method containers. They are also very difficult to test in isolation unless you're willing to use some very hacky tools. 34 | 35 | ![NOTE](imgs/note.png) If you really need a static class, mark it as `static` so that the compiler can prevent the class and its members from instantiating. This relieves you of creating an explicit private constructor. 36 | 37 | 38 | ## Don't hide inherited members with the `new` keyword ![](imgs/must.png) ## 39 | 40 | Not only does the new keyword break [Polymorphism](http://en.wikipedia.org/wiki/Polymorphism_in_object-oriented_programming), one of the most essential object-orientation principles, it also makes subclasses more difficult to understand. Consider the following two classes: 41 | 42 | ```c# 43 | public class Book 44 | { 45 | public virtual void Print() 46 | { 47 | Console.WriteLine("Printing Book"); 48 | } 49 | } 50 | 51 | public class PocketBook : Book 52 | { 53 | public new void Print() 54 | { 55 | Console.WriteLine("Printing PocketBook"); 56 | } 57 | } 58 | ``` 59 | 60 | This will cause behavior that you would not normally expect from class hierarchies: 61 | 62 | ```c# 63 | var pocketBook = new PocketBook(); 64 | 65 | pocketBook.Print(); // Will output "Printing PocketBook " 66 | ((Book)pocketBook).Print(); // Will output "Printing Book" 67 | ``` 68 | 69 | It ![MUST](imgs/must.png) **NOT** make a difference whether you call Print through a reference to the base class or through the derived class. 70 | 71 | 72 | ## Treat a derived object as if it were a base class object ![](imgs/should.png) ## 73 | 74 | In other words, you ![SHOULD](imgs/should.png) be able to use a reference to an object of a derived class wherever a reference to its base class object is used without knowing the specific derived class. A very notorious example of a violation of this rule is throwing a `NotImplementedException` when overriding some of the base-class methods. A less subtle example is not honoring the behavior expected by the base-class. This rule is also known as the [Liskov Substitution Principle (LSP)][lsp], one of the [SOLID principles][solid]. 75 | 76 | 77 | ## Don't refer to derived classes from the base class ![](imgs/must.png) ## 78 | 79 | Having dependencies from a base class to its sub-classes goes against proper object-oriented design and might prevent other developers from adding new derived classes. 80 | 81 | 82 | ## Avoid exposing the other objects an object depends on ## 83 | 84 | If you find yourself writing code like this then you might be violating the [Law of Demeter (LoD)](http://en.wikipedia.org/wiki/Law_of_Demeter). More detailed explanations of LoD can be found at [here](http://www.blackwasp.co.uk/LawOfDemeter.aspx). 85 | 86 | ```c# 87 | someObject.SomeProperty.GetChild().Foo() 88 | ``` 89 | 90 | An object should not expose any other classes it depends on because callers may misuse that exposed property or method to access the object behind it. By doing so, you allow calling code to become coupled to the class you are using, and thereby limiting the chance you can easily replace it in a future stage. 91 | 92 | ![NOTE](imgs/note.png) Using a class designed with the [Fluent Interface](http://en.wikipedia.org/wiki/Fluent_interface) pattern like LINQ does seem to violate this rule, but it is simply returning itself so that method chaining is allowed. 93 | 94 | ![EXCEPTION](imgs/exception.png) Inversion of Control (or Dependency Injection) frameworks such as [Unity](http://msdn.microsoft.com/unity), [Autofac](http://autofac.org) or [Ninject](http://www.ninject.org) often require you to expose a dependency as a public property. As long as this property is not used for anything else than dependency injection, it wouldn't be considered as a violation. 95 | 96 | 97 | ## Avoid bidirectional dependencies ![](imgs/must.png) ## 98 | 99 | This means that two classes know about each other's public members or rely on each other's internal behavior. Refactoring or replacing one of those two classes requires changes on both parties and may involve a lot of unexpected work. The most obvious way of breaking that dependency is introducing an interface for one of the classes and using dependency injection. 100 | 101 | 102 | ## Classes should have state and behavior ![](imgs/must.png) ## 103 | 104 | Unless your classes are only to transfer data over communication channels called [Data Transfer Objects](http://martinfowler.com/eaaCatalog/dataTransferObject.html), they ![MUST](imgs/must.png) have logics defining their state and behavior. 105 | 106 | 107 | [solid]: http://programmers.stackexchange.com/questions/202571/solid-principles-and-code-structure 108 | [srp]: http://www.objectmentor.com/resources/articles/srp.pdf 109 | [ocp]: http://www.objectmentor.com/resources/articles/ocp.pdf 110 | [lsp]: http://www.objectmentor.com/resources/articles/lsp.pdf 111 | [isp]: http://www.objectmentor.com/resources/articles/isp.pdf 112 | [dip]: http://www.objectmentor.com/resources/articles/dip.pdf 113 | -------------------------------------------------------------------------------- /Documentation.Guidelines.md: -------------------------------------------------------------------------------- 1 | # Documentation Guidelines # 2 | 3 | ## Write comments and documentation in English ![](imgs/must.png) ## 4 | 5 | Documents must be written in English (see [here](Naming.Guidelines.md#use-english-)). 6 | 7 | ![NOTE](imgs/note.png) Doomen's original document clearly stated that *Use US-English*. In this document, the *US* part is deliberately omitted. 8 | 9 | 10 | ## Document all public, protected and internal types and members ![](imgs/should.png) ## 11 | 12 | Documenting your code allows Visual Studio to pop-up the documentation when your class is used somewhere else. Furthermore, by properly documenting your classes, tools can generate professionally looking class documentation. 13 | 14 | 15 | ## Write XML documentation with another developer in mind ![](imgs/should.png) ## 16 | 17 | Write the documentation of your type with another developer in mind. Assume he or she will not have access to the source code and try to explain how to get the most out of the functionality of your type. 18 | 19 | 20 | ## Write MSDN-style documentation ![](imgs/may.png) ## 21 | 22 | Following the MSDN on-line help style and word choice helps the developer to find its way through your documentation more easily. 23 | 24 | ![NOTE](imgs/note.png) Either [GhostDoc](http://submain.com/products/ghostdoc.aspx) or [Sandcastle Help File Builder](https://shfb.codeplex.com) can generate a starting point for documenting code with a shortcut key. 25 | 26 | 27 | ## Avoid inline comments ![](imgs/should.png) ## 28 | 29 | If you feel the need to explain a block of code using a comment, consider replacing that block with a method having a clear name. 30 | 31 | 32 | ## Only write comments to explain complex algorithms or decisions ![](imgs/must.png) ## 33 | 34 | Try to focus comments on the why and what of a code block and not the how. Avoid explaining the statements in words, but instead help the reader understand why you chose a certain solution or algorithm and what you are trying to achieve. If applicable, also mention that you chose an alternative solution because you ran into a problem with the obvious solution. 35 | 36 | 37 | ## Don't use comments for tracking work to be done later ![](imgs/may.png) ## 38 | 39 | Annotating a block of code or some work to be done using a TODO or similar comment may seem a reasonable way of tracking work-to-be-done. But in reality, nobody really searches for comments like that. Use a work item tracking system such as Team Foundation Server to keep track of left overs. 40 | -------------------------------------------------------------------------------- /Framework.Guidelines.md: -------------------------------------------------------------------------------- 1 | # Framework Guidelines # 2 | 3 | ## Use C# type aliases instead of the types from the `System` namespace ![](imgs/must.png) ## 4 | 5 | For instance, use `object` instead of `Object`, `string` instead of `String`, and `int` instead of `Int32`. These aliases have been introduced to make the primitive types a first class citizen of the C# language so use them accordingly. 6 | 7 | ![EXCEPTION](imgs/exception.png) When referring to static members of those types, it is custom to use the full CLS name, eg) `Int32.Parse()` instead of `int.Parse()`. 8 | 9 | 10 | ## Properly name properties, variables or fields referring to localised resources ![](imgs/may.png) ## 11 | 12 | The guidelines in this topic apply to localisable resources such as error messages and menu text. 13 | 14 | * Use Pascal casing in resource keys. 15 | * Provide descriptive rather than short identifiers. Keep them concise where possible, but don't sacrifice readability. 16 | * Use only alphanumeric characters in naming resources. 17 | 18 | 19 | ## Don't hardcode strings that change based on the deployment ![](imgs/may.png) ## 20 | 21 | Examples include connection strings, server addresses, etc. Use `Resources`, the `ConnectionStrings` property of the `ConfigurationManager` class, or the `Settings` class generated by Visual Studio. Maintain the actual values into the `app.config` or `web.config` (and most definitely not in a custom configuration store). 22 | 23 | 24 | ## Build with the highest warning level ![](imgs/must.png) ## 25 | 26 | Configure the development environment to use **Warning Level 4** for the C# compiler, and enable the option **Treat warnings as errors**. This allows the compiler to enforce the highest possible code quality. 27 | 28 | 29 | ## Properly fill the attributes of the `AssemblyInfo.cs` file ![](imgs/may.png) ## 30 | 31 | Ensure that the attributes for the company name, description, copyright statement, version, etc. are filled. One way to ensure that version and other fields that are common to all assemblies have the same values, is to move the corresponding attributes out of the `AssemblyInfo.cs` into a `SolutionInfo.cs` file that is shared by all projects within the solution. 32 | 33 | 34 | ## Avoid LINQ for simple expressions ![](imgs/may.png) ## 35 | 36 | Rather than 37 | 38 | ```c# 39 | var query = from item in items where item.Length > 0; 40 | ``` 41 | 42 | Prefer using the extension methods from the `System.Linq` namespace. 43 | 44 | ```c# 45 | var query = items.Where(i => i.Length > 0); 46 | ``` 47 | 48 | Since LINQ queries should be written out over multiple lines for readability, the second example is a bit more readable. 49 | 50 | 51 | ## Use Lambda expressions instead of delegates ![](imgs/should.png) ## 52 | 53 | Lambda expressions provide a much more elegant alternative for anonymous delegates. So instead of 54 | 55 | ```c# 56 | Customer c = Array.Find(customers, delegate(Customer c) 57 | { 58 | return c.Name == "Tom"; 59 | }); 60 | ``` 61 | 62 | use a Lambda expression: 63 | 64 | ```c# 65 | Customer c = Array.Find(customers, c => c.Name == "Tom"); 66 | ``` 67 | 68 | Or even better 69 | 70 | ```c# 71 | var customer = customers.Where(c => c.Name == "Tom"); 72 | ``` 73 | 74 | 75 | ## Only use the dynamic keyword when talking to a dynamic object ![](imgs/must.png) ## 76 | 77 | The dynamic keyword has been introduced for working with dynamic languages. Using it introduces a serious performance bottleneck because the compiler has to generate some complex Reflection code. 78 | 79 | Use it only for calling methods or members of a dynamically created instance (using the `Activator`) class as an alternative to `Type.GetProperty()` and `Type.GetMethod()`, or for working with COM Interop types. 80 | 81 | 82 | ## Favour `async`/`await` over the Task ## 83 | 84 | Using the new C# 5.0 keywords results in code that can still be read sequentially and also improves maintainability a lot, even if you need to chain multiple asynchronous operations. For example, rather than defining your method like this: 85 | 86 | ```c# 87 | public Task GetDataAsync() 88 | { 89 | return MyWebService.FetchDataAsync() 90 | .ContinueWith(t => new Data (t.Result)); 91 | } 92 | ``` 93 | 94 | Define it like this: 95 | 96 | ```c# 97 | public async Task GetDataAsync() 98 | { 99 | var result = await MyWebService.FetchDataAsync(); 100 | 101 | return new Data (result); 102 | } 103 | ``` 104 | 105 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014, aliencube.org 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | * Neither the name of the aliencube.org nor the names of its 15 | contributors may be used to endorse or promote products derived from 16 | this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /Layout.Guidelines.md: -------------------------------------------------------------------------------- 1 | # Layout Guidelines # 2 | 3 | ## Use a common layout ![](imgs/must.png) ## 4 | 5 | * Keep the length of each line under 130 characters. 6 | * Use an indentation of 4 whitespaces, and don't use tabs 7 | * Keep one whitespace between keywords like `if` and the expression, but don't add whitespaces after `(` and before `)` such as: 8 | 9 | ```c# 10 | if (condition == null) 11 | ``` 12 | 13 | * Add a whitespace around operators, like `+`, `-`, `==`, etc. 14 | * Always succeed the keywords `if`, `else`, `do`, `while`, `for` and `foreach`, with opening and closing parentheses, even though the language does not require it. 15 | * Always put opening and closing parentheses on a new line. 16 | * Indent object Initialisers and initialise each property on a new line, so use a format like this: 17 | 18 | ```c# 19 | var dto = new ConsumerDto() 20 | { 21 | Id = 123, 22 | Name = "Microsoft", 23 | PartnerShip = PartnerShip.Gold, 24 | } 25 | ``` 26 | 27 | * Don't indent lambda statements and use a format like this: 28 | 29 | ```c# 30 | methodThatTakesAnAction.Do(x => 31 | { 32 | // do something like this 33 | } 34 | ``` 35 | 36 | * Put the entire LINQ statement on one line, or start each keyword at the same indentation, like this: 37 | 38 | ```c# 39 | var query = from product in products where product.Price > 10 select product; 40 | ``` 41 | 42 | or 43 | 44 | ```c# 45 | var query = 46 | from product in products 47 | where product.Price > 10 48 | select product; 49 | ``` 50 | 51 | * Start the LINQ statement with all the `from` expressions and don't interweave them with where restrictions. 52 | * Add braces around every comparison condition, but don't add braces around a singular condition. For example 53 | 54 | ```c# 55 | if (!String.IsNullOrEmpty(str) && (str != "new")) 56 | ``` 57 | 58 | * Add an empty line between multi-line statements, between members, after the closing parentheses, between unrelated code blocks, around the `#region` keyword, and between the using statements of different companies. 59 | 60 | 61 | ## Order and group namespaces according the company ![](imgs/may.png) ## 62 | 63 | ```c# 64 | // Microsoft namespaces are first 65 | using System; 66 | using System.Collections; 67 | using System.XML; 68 | 69 | // Then any other namespaces in alphabetic order 70 | using AvivaSolutions.Business; 71 | using AvivaSolutions.Standard; 72 | 73 | using Telerik.WebControls; 74 | using Telerik.Ajax; 75 | ``` 76 | 77 | 78 | ## Place members in a well-defined order ![](imgs/must.png) ## 79 | 80 | Maintaining a common order allows other team members to find their way in your code more easily. In general, a source file should be readable from top to bottom, as if you are reading a book. This prevents readers from having to browse up and down through the code file. 81 | 82 | 1. Private fields and constants (in a region) 83 | 2. Public constants 84 | 3. Public read-only static fields 85 | 4. Factory Methods 86 | 5. Constructors and the Finalizer 87 | 6. Events 88 | 7. Public Properties 89 | 8. Other methods and private properties in calling order 90 | 91 | 92 | ## Be reluctant with `#region`s ![](imgs/must.png) ## 93 | 94 | Regions can be helpful, but can also hide the main purpose of a class. Therefore, use #regions only for: 95 | 96 | * Private fields and constants (preferably in a `Private Definitions` region). 97 | * Nested classes 98 | * Interface implementations (only if the interface is not the main purpose of that class) 99 | 100 | -------------------------------------------------------------------------------- /Maintainability.Guidelines.md: -------------------------------------------------------------------------------- 1 | # Maintainability Guidelines # 2 | 3 | ## Methods does not exceed 7 statements ![](imgs/must.png) ## 4 | 5 | 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 in multiple small and focused methods with self-explaining names, but make sure the high-level algorithm is still clear. 6 | 7 | 8 | ## Make all members `private` and types `internal` by default ![](imgs/must.png) ## 9 | 10 | 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. 11 | 12 | 13 | ## Avoid conditions with double negatives ![](imgs/should.png) ## 14 | 15 | Although a property like `customer.HasNoOrders` make sense, avoid using it in a negative condition like this: 16 | 17 | ```c# 18 | bool hasOrders = !customer.HasNoOrders; 19 | ``` 20 | 21 | Double negatives are more difficult to grasp than simple expressions, and people tend to read over the double negative easily. 22 | 23 | 24 | ## Name assemblies after their contained namespace ![](imgs/may.png) ## 25 | 26 | All DLLs should be named according to the pattern `..dll` where `` refers to your company's name and `` contains one or more dot-separated clauses. For example `Dnb.Web.Controls.dll`. 27 | 28 | As an example, consider a group of classes organized under the namespace `Dnb.Web.Binding` exposed by a certain assembly. According to this guideline, that assembly should be called `Dnb.Web.Binding.dll`. 29 | 30 | ![EXCEPTION](imgs/exception.png) If you decide to combine classes from multiple unrelated namespaces into one assembly, consider suffix to the assembly with `Core`, but do not use that suffix in the namespaces. For instance, `Dnb.Consulting.Core.dll`. 31 | 32 | 33 | ## Name a source file to the type it contains ![](imgs/may.png) ## 34 | 35 | Use Pascal casing for naming the file and don’t use underscores. 36 | 37 | 38 | ## Limit the contents of a source code file to one type ![](imgs/may.png) ## 39 | 40 | Make sure that one source file can be responsible for fully or partially contributing to one class. 41 | 42 | ![EXCEPTION](imgs/exception.png) Nested types can, for obvious reasons, be part of the same file. 43 | 44 | 45 | ## Name a source file to the logical function of the partial type ![](imgs/may.png) ## 46 | 47 | When using partial types and allocating a part per file, name each file after the logical part that part plays. For example: 48 | 49 | ```c# 50 | // In MyClass.cs 51 | public partial class MyClass 52 | { 53 | ... 54 | } 55 | 56 | // In MyClass.Designer.cs 57 | public partial class MyClass 58 | { 59 | ... 60 | } 61 | ``` 62 | 63 | 64 | ## Use using statements instead of fully qualified type names ![](imgs/may.png) ## 65 | 66 | Limit usage of fully qualified type names to prevent name clashing. For example, don't do this. 67 | 68 | ```c# 69 | var list = new System.Collections.Generic.List(); 70 | ``` 71 | 72 | Instead, do this. 73 | 74 | ```c# 75 | using System.Collections.Generic; 76 | 77 | var list = new List(); 78 | ``` 79 | 80 | If you do need to prevent name clashing, use a using directive to assign an alias: 81 | 82 | ```c# 83 | using Label = System.Web.UI.WebControls.Label; 84 | ``` 85 | 86 | 87 | ## Don't use **magic** numbers ![](imgs/must.png) ## 88 | 89 | Don't use literal values, either numeric or strings, in your code other than to define symbolic constants. For example: 90 | 91 | ```c# 92 | public class Whatever 93 | { 94 | public static readonly Color PapayaWhip = new Color(0xFFEFD5); 95 | public const int MaxNumberOfWheels = 18; 96 | } 97 | ``` 98 | 99 | Strings intended for logging or tracing are exempt from this rule. Literals are allowed when their meaning is clear from the context, and not subject to future changes, For example: 100 | 101 | ```c# 102 | mean = (a + b) / 2; // okay 103 | WaitMilliseconds(waitTimeInSeconds * 1000); // clear enough 104 | ``` 105 | 106 | If the value of one constant depends on the value of another, do attempt to make this explicit in the code. 107 | 108 | ```c# 109 | public class SomeSpecialContainer 110 | { 111 | public const int MaxItems = 32; 112 | public const int HighWaterMark = 3 * MaxItems / 4; // at 75% 113 | } 114 | ``` 115 | 116 | ![NOTE](imgs/note.png) An enumeration can often be used for certain types of symbolic constants. 117 | 118 | 119 | ## Only use `var` when the type is very obvious ![](imgs/must.png) ## 120 | 121 | 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 122 | 123 | ```c# 124 | var i = 3; // what type? int? uint? float? 125 | var myfoo = MyFactoryMethod.Create("arg"); // Not obvious what base-class or 126 | // interface to expect. Also difficult 127 | // to refactor if you can't search for 128 | // the class 129 | ``` 130 | 131 | Instead, use `var` like this. 132 | 133 | ```c# 134 | var q = from order in orders where order.Items > 10 and order.TotalValue > 1000; 135 | var repository = new RepositoryFactory.Get(); 136 | var list = new ReadOnlyCollection(); 137 | ``` 138 | 139 | In all of three above examples it is clear what type to expect. For a more detailed rationale about the advantages and disadvantages of using `var`, read Eric Lippert's [Uses and misuses of implicit typing](http://blogs.msdn.com/b/ericlippert/archive/2011/04/20/uses-and-misuses-of-implicit-typing.aspx). 140 | 141 | 142 | ## Declare and initialize variables as late as possible ![](imgs/should.png) ## 143 | 144 | Avoid the C and Visual Basic styles where all variables have to be defined at the beginning of a block, but rather define and initialize each variable at the point where it is needed. 145 | 146 | 147 | ## Assign each variable in a separate statement ![](imgs/must.png) ## 148 | 149 | Don't use confusing constructs like the one below. 150 | 151 | ```c# 152 | var result = someField = GetSomeMethod(); 153 | ``` 154 | 155 | 156 | ## Favour Object and Collection Initialisers over separate statements ![](imgs/should.png) ## 157 | 158 | Avoid 159 | 160 | ```c# 161 | var startInfo = new ProcessStartInfo("myapp.exe"); 162 | startInfo.StandardOutput = Console.Output; 163 | startInfo.UseShellExecute = true; 164 | ``` 165 | 166 | Instead, use [Object Initialisers](http://msdn.microsoft.com/en-us/library/bb384062.aspx). 167 | 168 | ```c# 169 | var startInfo = new ProcessStartInfo("myapp.exe") 170 | { 171 | StandardOutput = Console.Output, 172 | UseShellExecute = true 173 | }; 174 | ``` 175 | 176 | 177 | Similarly, instead of adding items to collection or dictionary individually 178 | 179 | ```c# 180 | var countries = new List(); 181 | countries.Add("Netherlands"); 182 | countries.Add("United States"); 183 | ``` 184 | 185 | Use collection or [dictionary initialisers](http://msdn.microsoft.com/en-us/library/bb531208.aspx). 186 | 187 | ```c# 188 | var countries = new List 189 | { 190 | "Netherlands", 191 | "United States" 192 | }; 193 | ``` 194 | 195 | 196 | ## Don't make explicit comparisons to `true` or `false` ![](imgs/must.png) ## 197 | 198 | It is usually bad style to compare a `bool` type expression to `true` or `false`. For example: 199 | 200 | ```c# 201 | while (condition == false) // wrong; bad style 202 | while (condition != true) // also wrong 203 | while (((condition == true) == true) == true) // where do you stop? 204 | 205 | while (condition) // OK 206 | ``` 207 | 208 | 209 | ## Don't change a loop variable inside a for or `foreach` loop ![](imgs/should.png) ## 210 | 211 | Updating the loop variable within the loop body is generally considered confusing. It is even worse that the loop variables are modified in more than one place in the loop. Consider `break` or `continue` instead, to change the loop variables. 212 | 213 | ```c# 214 | for (int index = 0; index < 10; ++index) 215 | { 216 | if (some condition) 217 | { 218 | index = 11; // Wrong! Use 'break' or 'continue' instead. 219 | } 220 | } 221 | ``` 222 | 223 | 224 | ## Avoid nested loops ![](imgs/should.png) ## 225 | 226 | A method that nests loops is more difficult to understand than one with only a single loop. In fact, in most cases having nested loops can be replaced with a much simpler LINQ query that uses the `from` keyword twice or more to join the data. 227 | 228 | 229 | ## Always add a block after keywords such as `if`, `else`, `while`, `for`, `foreach` and `case` ![](imgs/should.png) ## 230 | 231 | Please note that this also avoids possible confusion in statements of the form: 232 | 233 | ```c# 234 | // The wrong way: 235 | if (b1) if (b2) Foo(); else Bar(); // which 'if' goes with the 'else'? 236 | 237 | // The right way: 238 | if (b1) 239 | { 240 | if (b2) 241 | { 242 | Foo(); 243 | } 244 | else 245 | { 246 | Bar(); 247 | } 248 | } 249 | ``` 250 | 251 | 252 | ## Always add a default block after the last `case` in a `switch` statement ![](imgs/must.png) ## 253 | 254 | Add a descriptive comment if the default block is supposed to be empty. Moreover, if that block is not supposed to be reached, throw an `InvalidOperationException` to detect future changes that may fall through the existing cases. This ensures better code, because all paths the code can travel has been thought about. 255 | 256 | ```c# 257 | void Foo(string answer) 258 | { 259 | switch (answer) 260 | { 261 | case "no": 262 | Console.WriteLine("You answered with No"); 263 | break; 264 | case "yes": 265 | Console.WriteLine("You answered with Yes"); 266 | break; 267 | default: 268 | // Not supposed to end up here. 269 | throw new InvalidOperationException("Unexpected answer " + answer); 270 | } 271 | } 272 | ``` 273 | 274 | 275 | ## Finish every `if`-`else`-`if` statement with an `else` part ![](imgs/should.png) ## 276 | 277 | Similarly to the `default` block in a `switch` statement, consider the following way: 278 | 279 | ```c# 280 | void Foo(string answer) 281 | { 282 | if (answer == "no") 283 | { 284 | Console.WriteLine("You answered with No"); 285 | } 286 | else if (answer == "yes") 287 | { 288 | Console.WriteLine("You answered with Yes"); 289 | } 290 | else 291 | { 292 | // What should happen when this point is reached? Ignored? If not, 293 | // throw an InvalidOperationException. 294 | } 295 | } 296 | ``` 297 | 298 | 299 | ## Be reluctant with multiple return statements ![](imgs/should.png) ## 300 | 301 | One entry, one exit is a sound principle and keeps control flow readable. However, if the method is very small and complies with [this guideline](Maintainability.Guidelines.md#methods-does-not-exceed-7-statements-) then multiple return statements may actually improve readability over some central boolean flag that is updated at various points. 302 | 303 | 304 | ## Don't use `if`-`else` statements instead of a simple (conditional) assignment ![](imgs/should.png) ## 305 | 306 | Express your intentions directly. For example: 307 | 308 | ```c# 309 | // Bad practice 310 | bool pos; 311 | if (val > 0) 312 | { 313 | pos = true; 314 | } 315 | else 316 | { 317 | pos = false; 318 | } 319 | 320 | // Preferred practice 321 | bool pos = (val > 0); // initialisation 322 | ``` 323 | 324 | Or this can be another alternative: 325 | 326 | ```c# 327 | // Avoid 328 | string result; 329 | if (someString != null) 330 | { 331 | result = someString; 332 | } 333 | else 334 | { 335 | result = "Unavailable"; 336 | } 337 | return result; 338 | 339 | // Instead 340 | return someString ?? "Unavailable"; 341 | ``` 342 | 343 | 344 | ## Encapsulate complex expressions in a method or property ![](imgs/must.png) ## 345 | 346 | Consider the following example: 347 | 348 | ```c# 349 | if (member.HidesBaseClassMember && (member.NodeType != NodeType.InstanceInitializer)) 350 | { 351 | // do something 352 | } 353 | ``` 354 | 355 | In order to understand what this expression is about, you need to analyse its exact details and all the possible outcomes. Obviously, you could add an explanatory comment on top of it, but it is much better to replace this complex expression with a clearly named method like: 356 | 357 | ```c# 358 | if (NonConstructorMemberUsesNewKeyword(member)) 359 | { 360 | // do something 361 | } 362 | 363 | private bool NonConstructorMemberUsesNewKeyword(Member member) 364 | { 365 | return member.HidesBaseClassMember && 366 | member.NodeType != NodeType.InstanceInitializer; 367 | } 368 | ``` 369 | 370 | You still need to understand the expression if you are modifying it, but the calling code is now much easier to grasp. 371 | 372 | 373 | ## Call the most overloaded method from other overloads ![](imgs/should.png) ## 374 | 375 | This guideline only applies to overloads that are intended for providing optional arguments. Consider for example: 376 | 377 | ```c# 378 | public class MyString 379 | { 380 | private string someText; 381 | 382 | public MyString(string text) 383 | { 384 | this.someText = text; 385 | } 386 | 387 | public int IndexOf(string phrase) 388 | { 389 | return IndexOf(phrase, 0, someText.Length); 390 | } 391 | 392 | public int IndexOf(string phrase, int startIndex) 393 | { 394 | return IndexOf(phrase, startIndex, someText.Length - startIndex ); 395 | } 396 | 397 | public virtual int IndexOf(string phrase, int startIndex, int count) 398 | { 399 | return someText.IndexOf(phrase, startIndex, count); 400 | } 401 | } 402 | ``` 403 | 404 | The class `MyString` provides three overloads for the `IndexOf` method, but two of them simply call the one with the most parameters. 405 | 406 | ![NOTE](imgs/note.png) The same rule can apply to class constructors; implement the most complete overload and call that one from the other overloads using the `this()` operator. 407 | 408 | ![NOTE](imgs/note.png) The parameters with the same name should appear in the same position in all overloads. 409 | 410 | ![IMPORTANT](imgs/important.png) If you also want to allow derived classes to override these methods, define the most complete overload as a `protected virtual` method that is called by all overloads. 411 | 412 | 413 | ## Only use optional arguments to replace overloads ![](imgs/must.png) ## 414 | 415 | The only valid reason for using C# 4.0's optional arguments is to replace the example from [this guideline](Maintainability.Guidelines.md#call-the-most-overloaded-method-from-other-overloads-) with a single method like: 416 | 417 | ```c# 418 | public virtual int IndexOf(string phrase, int startIndex = 0, int count = 0) 419 | { 420 | return someText.IndexOf(phrase, startIndex, count); 421 | } 422 | ``` 423 | 424 | If the optional parameter is a reference type then it can only have a default value of `null`. But since strings, lists and collections should never be `null` according to [this rule](Miscellaneous.Design.Guidelines.md#dont-pass-null-as-the-sender-argument-when-raising-an-event-), you must use overloaded methods instead. 425 | 426 | ![NOTE](/imgs/note.png) The default values of the optional parameters are stored at the caller side. As such, changing the default value without recompiling the calling code will not apply the new default value properly. 427 | 428 | ![NOTE](/imgs/note.png) When an interface method defines an optional parameter, its default value is not considered during overload resolution unless you call the concrete class through the interface reference. See [this post](http://blogs.msdn.com/b/ericlippert/archive/2011/05/09/optional-argument-corner-cases-part-one.aspx) by Eric Lippert for more details. 429 | 430 | 431 | ## Avoid using named arguments ![](imgs/must.png) ## 432 | 433 | C# 4.0's named arguments have been introduced to make it easier to call COM components that are known for offering tons of optional parameters. If you need named arguments to improve the readability of the call to a method, that method is probably doing too much and should be refactored. 434 | 435 | The only exception where named arguments improve readability is when a constructor that yields a valid object is called like this: 436 | 437 | ```c# 438 | Person person = new Person 439 | ( 440 | firstName: "John", 441 | lastName: "Smith", 442 | dateOfBirth: new DateTime(1970, 1, 1) 443 | ); 444 | ``` 445 | 446 | 447 | ## Don't allow methods and constructors with more than three parameters ![](imgs/must.png) ## 448 | 449 | If you end up with a method with more than three parameters, use a structure or class for passing multiple arguments such as explained in the [Specification](http://en.wikipedia.org/wiki/Specification_pattern) design pattern. In general, the fewer the number of parameters, the easier it is to understand the method. Additionally, unit testing a method with many parameters requires many scenarios to test. 450 | 451 | 452 | ## Don't use `ref` or `out` parameters ![](imgs/must.png) ## 453 | 454 | They make code less understandable and might cause people to introduce bugs. Prefer returning compound objects instead. 455 | 456 | 457 | ## Avoid methods that take a `bool` flag ![](imgs/should.png) ## 458 | 459 | Consider the following method signature: 460 | 461 | ```c# 462 | public Customer CreateCustomer(bool platinumLevel) {} 463 | ``` 464 | 465 | On first sight this signature seems perfectly fine, but when calling this method you will lose this purpose completely: 466 | 467 | ```c# 468 | Customer customer = CreateCustomer(true); 469 | ``` 470 | 471 | Often, a method taking such a flag is doing more than one thing and needs to be refactored into two or more methods. An alternative solution is to replace the flag with an enumeration. 472 | 473 | 474 | ## Don't use parameters as temporary variables ![](imgs/may.png) ## 475 | 476 | Never use a parameter as a convenient variable for storing temporary state. Even though the type of your temporary variable may be the same, the name usually does not reflect the purpose of the temporary variable. 477 | 478 | 479 | ## Always check the result of an as operation ![](imgs/must.png) ## 480 | 481 | If you use as to obtain a certain interface reference from an object, always ensure that this operation does not return `null`. Failure to do so may cause a `NullReferenceException` at a much later stage if the object did not implement that interface. 482 | 483 | 484 | ## Don't comment out code ![](imgs/must.png) ## 485 | 486 | Never check-in code that is commented-out, but instead use a work item tracking system to keep track of some work to be done. Nobody knows what to do when they encounter a block of commented-out code. Was it temporarily disabled for testing purposes? Was it copied as an example? Should I delete it? 487 | 488 | -------------------------------------------------------------------------------- /Member.Design.Guidelines.md: -------------------------------------------------------------------------------- 1 | # Member Design Guidelines # 2 | 3 | ## Allow properties to be set in any order ![](imgs/must.png) ## 4 | 5 | Properties should be stateless with respect to other properties, i.e. there should not be a difference between first setting property `A` and then `B` or vice versa. 6 | 7 | 8 | ## Use a method instead of a property ## 9 | 10 | Using a method is way better than a property, if: 11 | 12 | * The work is more expensive than setting a field value; 13 | * it represents a conversion such as the `Object.ToString()` method; 14 | * it returns a different result each time it is called, even if the arguments didn't change. For example, the `NewGuid()` method returns a different value each time it is called; or 15 | * the operation causes a side effect such as changing some internal state not directly related the property (which violates the [Command Query Separation](http://martinfowler.com/bliki/CommandQuerySeparation.html)). 16 | 17 | ![EXCEPTION](imgs/exception.png) Populating an internal cache or implementing [lazy-loading](http://www.martinfowler.com/eaaCatalog/lazyLoad.html) is a good exception. 18 | 19 | 20 | ## Don't use mutually exclusive properties ![](imgs/must.png) ## 21 | 22 | Having properties that cannot be used at the same time typically signals a type that is representing two conflicting concepts. Even though those concepts may share some of the behavior and state, they obviously have different rules that do not cooperate. 23 | 24 | This violation is often seen in domain models and introduces all kinds of conditional logic related to those conflicting rules, causing a ripple effect that significantly worsens the maintenance burden. 25 | 26 | 27 | ## A method or property does only one thing ![](imgs/must.png) ## 28 | 29 | Based on [SRP][srp], a method ![MUST](imgs/must.png) have a single responsibility. 30 | 31 | 32 | ## Don't expose stateful objects through static members ![](imgs/should.png) ## 33 | 34 | A stateful object is an object that contains many properties and lots of behavior behind that. If you expose such an object through a static property or method of some other object, it will be very difficult to refactor or unit test a class that relies on such a stateful object. In general, introducing a construction like that is a great example of violating many of the guidelines of this document. 35 | 36 | A classic example of this is the `HttpContext.Current` property, part of ASP.NET. Many see the `HttpContext` class as a source for a lot of ugly code. In fact, the testing guideline [Isolate the Ugly Stuff](http://msdn.microsoft.com/en-us/magazine/dd263069.aspx#id0070015) often refers to this class. 37 | 38 | 39 | ## Return an `IEnumerable` or `ICollection` instead of a concrete collection class ![](imgs/should.png) ## 40 | 41 | In general, you don't want callers to be able to change an internal collection, so don't return arrays, lists or other collection classes directly. Instead, return an `IEnumerable`, or, if the caller must be able to determine the count, an `ICollection`. 42 | 43 | ![NOTE](imgs/note.png) In .NET 4.5, you can also use `IReadOnlyCollection`, `IReadOnlyList` or `IReadOnlyDictionary`. 44 | 45 | 46 | ## Properties, methods and arguments representing strings or collections should never be `null` ![](imgs/must.png) ## 47 | 48 | Returning `null` can be unexpected by the caller. Always return an **empty collection** or an **empty string** instead of a `null` reference. This also prevents cluttering your code base with additional checks for `null`, or even worse, `String.IsNotNullOrEmpty()` or `String.IsNullOrWhiteSpace()`. 49 | 50 | 51 | ## Define parameters as specific as possible ![](imgs/should.png) ## 52 | 53 | If your member needs a specific piece of data, define parameters as specific as that and don't take a container object instead. For instance, consider a method that needs a connection string that is exposed through some central `IConfiguration` interface. Rather than taking a dependency on the entire configuration, just define a parameter for the connection string. This not only prevents unnecessary coupling, it also improved maintainability in a long run. 54 | 55 | 56 | ## Consider using domain-specific value types rather than primitives ![](imgs/may.png) ## 57 | 58 | Instead of using strings, integers and decimals for representing domain specific types such as an ISBN number, an email address or amount of money, consider created dedicated value objects that wrap both the data and the validation rules that apply to it. By doing this, you prevent ending up having multiple implementations of the same business rules, which both improves maintainability and prevents bugs. 59 | 60 | 61 | [solid]: http://programmers.stackexchange.com/questions/202571/solid-principles-and-code-structure 62 | [srp]: http://www.objectmentor.com/resources/articles/srp.pdf 63 | [ocp]: http://www.objectmentor.com/resources/articles/ocp.pdf 64 | [lsp]: http://www.objectmentor.com/resources/articles/lsp.pdf 65 | [isp]: http://www.objectmentor.com/resources/articles/isp.pdf 66 | [dip]: http://www.objectmentor.com/resources/articles/dip.pdf 67 | -------------------------------------------------------------------------------- /Miscellaneous.Design.Guidelines.md: -------------------------------------------------------------------------------- 1 | # Miscellaneous Design Guidelines # 2 | 3 | ## Throw exceptions rather than returning some kind of status value ![](imgs/should.png) ## 4 | 5 | A code base that uses return values for reporting the success or failure tends to have nested if-statements sprinkled all over the code. Quite often, a caller forgets to check the return value anyhow. Structured exception handling has been introduced to allow you to throw exceptions and catch or replace exceptions at a higher layer. In most systems it is quite common to throw exceptions whenever an unexpected situations occurs. 6 | 7 | 8 | ## Provide a rich and meaningful exception message text ![](imgs/should.png) ## 9 | 10 | The message should explain the cause of the exception and clearly describe what needs to be done to avoid the exception. 11 | 12 | 13 | ## Throw the most specific exception that is appropriate ![](imgs/may.png) ## 14 | 15 | For example, if a method receives a `null` argument, it should throw `ArgumentNullException` instead of its base type `ArgumentException`. 16 | 17 | 18 | ## Don't swallow errors by catching generic exceptions ![](imgs/must.png) ## 19 | 20 | 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. 21 | 22 | 23 | ## Properly handle exceptions in asynchronous code ![](imgs/should.png) ## 24 | 25 | When throwing or handling exceptions in code that uses `async`/`await` or a `Task` remember the following two rules: 26 | 27 | * Exceptions that occur within an `async`/`await` block and inside a `Task`'s action are propagated to the awaiter. 28 | * Exceptions that occur in the code preceding the asynchronous block are propagated to the caller. 29 | 30 | 31 | ## Always check an event handler delegate for `null` ![](imgs/must.png) ## 32 | 33 | An event that has no subscribers is `null`, so before invoking, always make sure that the delegate list represented by the event variable is not `null`. Furthermore, to prevent conflicting changes from concurrent threads, use a temporary variable to prevent concurrent changes to the delegate. 34 | 35 | ```c# 36 | event EventHandler Notify; 37 | void RaiseNotifyEvent(NotifyEventArgs args) 38 | { 39 | EventHandler handlers = Notify; 40 | if (handlers != null) 41 | { 42 | handlers(this, args); 43 | } 44 | } 45 | ``` 46 | 47 | You can prevent the delegate list from being empty altogether. Simply assign an empty delegate like this: 48 | 49 | ```c# 50 | event EventHandler Notify = delegate {}; 51 | ``` 52 | 53 | 54 | ## Use a protected virtual method to raise each event ![](imgs/should.png) ## 55 | 56 | Complying with this guideline allows derived classes to handle a base class event by overriding the protected method. The name of the protected virtual method should be the same as the event name prefixed with On. For example, the protected virtual method for an event named `TimeChanged` is named `OnTimeChanged`. 57 | 58 | ![NOTE](imgs/note.png) Derived classes that override the protected virtual method are not required to call the base class implementation. The base class must continue to work correctly even if its implementation is not called. 59 | 60 | 61 | ## Consider providing property-changed events ![](imgs/may.png) ## 62 | 63 | Consider providing events that are raised when certain properties are changed. Such an event should be named `PropertyChanged`, where Property should be replaced with the name of the property with which this event is associated. 64 | 65 | ![NOTE](imgs/note.png) 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. 66 | 67 | 68 | ## Don't pass `null` as the sender argument when raising an event ![](imgs/must.png) ## 69 | 70 | 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`. 71 | 72 | ![EXCEPTION](imgs/exception.png) On static events, the sender argument ![SHOULD](imgs/should.png) be `null`. 73 | 74 | 75 | ## Use generic constraints if applicable ![](imgs/should.png) ## 76 | 77 | Instead of casting to and from the `object` type in generic types or methods, use `where` constraints or the `as` operator to specify the exact characteristics of the generic parameter. For example: 78 | 79 | ```c# 80 | class SomeClass 81 | { 82 | ... 83 | } 84 | 85 | // Don't 86 | class MyClass 87 | { 88 | void SomeMethod(T t) 89 | { 90 | object temp = t; 91 | SomeClass obj = (SomeClass) temp; 92 | } 93 | } 94 | 95 | // Do 96 | class MyClass where T : SomeClass 97 | { 98 | void SomeMethod(T t) 99 | { 100 | SomeClass obj = t; 101 | } 102 | } 103 | ``` 104 | 105 | 106 | ## Evaluate the result of a LINQ expression before returning it ![](imgs/must.png) ## 107 | 108 | Consider the following code snippet: 109 | 110 | ```c# 111 | public IEnumerable GetGoldMemberCustomers() 112 | { 113 | const decimal GoldMemberThresholdInEuro = 1000000; 114 | var q = (from customer in db.Customers 115 | where customer.Balance > GoldMemberThresholdInEuro 116 | select new GoldMember(customer.Name, customer.Balance)); 117 | return q; 118 | } 119 | ``` 120 | 121 | Since LINQ queries use deferred execution, returning `q` will actually return the expression tree representing the above query. Each time the caller evaluates this result using a `foreach` or something 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. -------------------------------------------------------------------------------- /Naming.Guidelines.md: -------------------------------------------------------------------------------- 1 | # Naming Guidelines # 2 | 3 | ## Use English ![](imgs/must.png) ## 4 | 5 | All type members, parameters and variables should be named using words from the English language. 6 | 7 | * Choose easily readable, preferably grammatically correct names. For example, `HorizontalAlignment` is more readable than `AlignmentHorizontal`. 8 | * Favour readability over brevity. The property name `CanScrollHorizontally` is better than `ScrollableX` (an obscure reference to the X-axis). 9 | * Avoid using names that conflict with keywords of widely used programming languages. 10 | 11 | ![EXCEPTION](imgs/exception.png) In most projects, you will use words and phrases from your domain and names specific to your company. Visual Studio's **Static Code Analysis** will perform a spelling check on all code, so you may need to add those terms to a [Custom Code Analysis Dictionary](http://blogs.msdn.com/b/codeanalysis/archive/2007/08/20/new-for-visual-studio-2008-custom-dictionaries.aspx). 12 | 13 | ![NOTE](imgs/note.png) Doomen's original document clearly stated that *Use US-English*. In this document, the *US* part is deliberately omitted. 14 | 15 | 16 | ## Use proper casing for language elements ![](imgs/must.png) ## 17 | 18 | Language element | Casing | Example 19 | -----------------|--------|-------- 20 | Class, Struct | Pascal | `AppDomain` 21 | Interface | Pascal | `IBusinessService` 22 | Enumeration type | Pascal | `ErrorLevel` 23 | Enumeration values | Pascal | `FatalError` 24 | Event | Pascal | `Click` 25 | Private field | Camel | `listItem` 26 | Protected field | Pascal | `MainPanel` 27 | Const field | Pascal | `MaximumItems` 28 | Const variable | Camel | `maximumItems` 29 | Read-only static field | Pascal | `RedValue` 30 | Variable | Camel | `listOfValues` 31 | Method | Pascal | `ToString` 32 | Namespace | Pascal | `System.Drawing` 33 | Parameter | Camel | `typeName` 34 | Type Parameter | Pascal | `TView` 35 | Property | Pascal | `BackColor` 36 | 37 | 38 | ## Don't include numbers in variables, parameters and type members ![](imgs/may.png) ## 39 | 40 | In most cases they are a lazy excuse for not defining a clear and intention-revealing name. 41 | 42 | 43 | ## Don't prefix fields ![](imgs/must.png) ## 44 | 45 | For example, don't use `g_` or `s_` to distinguish static versus non-static fields. In general, a method in which it is difficult to distinguish local variables from member fields is too big. Examples of incorrect identifier names are: `_currentUser`, `mUserName`, `m_loginTime`. 46 | 47 | 48 | ## Don't use abbreviations ![](imgs/should.png) ## 49 | 50 | For example, use `OnButtonClick` rather than `OnBtnClick`. Avoid single character variable names, such as `i` or `q`. Use `index` or `query` instead. 51 | 52 | ![EXCEPTION](imgs/exception.png) Use well-known abbreviations that are widely accepted or well-known within the domain you work. For instance, use `UI` instead of `UserInterface`. 53 | 54 | 55 | ## Name a member, parameter or variable according its meaning and not its type ![](imgs/should.png) ## 56 | 57 | * Use functional names. For example, `GetLength` is a better name than `GetInt`. 58 | * Don't use terms like `Enum`, `Class` or `Struct` in a name. 59 | * Identifiers that refer to a collection type should have a **plural** name. 60 | 61 | 62 | ## Name types using nouns, noun phrases or adjective phrases ![](imgs/should.png) ## 63 | 64 | Bad examples include `SearchExamination` (a page for searching for examinations), `Common` (does not end with a noun, and does not explain its purpose) and `SiteSecurity` (although the name is technically okay, it does not say anything about its purpose). Good examples include `BusinessBinder`, `SmartTextBox`, or `EditableSingleCustomer`. 65 | 66 | Don't include terms like `Utility` or `Helper` in classes. Classes with a name like that are usually static classes and are introduced without considering the object-oriented principles (See [Avoid static classes](Class.Design.Guidelines.md#avoid-static-classes-)). 67 | 68 | 69 | ## Name generic type parameters with descriptive names ![](imgs/should.png) ## 70 | 71 | * Always prefix descriptive type parameter names with the letter `T`. 72 | * Always use a descriptive names unless a single-letter name is completely self-explanatory and a longer name would not add value. Use the single letter `T` as the type parameter in that case. 73 | * Consider indicating constraints placed on a type parameter in the name of parameter. For example, a parameter constrained to `ISession` may be called `TSession`. 74 | 75 | 76 | ## Don't repeat the name of a class or enumeration in its members ![](imgs/must.png) ## 77 | 78 | ```c# 79 | class Employee 80 | { 81 | // Wrong! 82 | static GetEmployee() {} 83 | DeleteEmployee() {} 84 | 85 | // Right 86 | static Get() {...} 87 | Delete() {...} 88 | 89 | // Also correct. 90 | AddNewJob() {...} 91 | RegisterForMeeting() {...} 92 | } 93 | ``` 94 | 95 | 96 | ## Name members similarly to members of related .NET Framework classes ![](imgs/may.png) ## 97 | 98 | .NET developers are already accustomed to the naming patterns the framework uses, so following this same pattern helps them find their way in your classes as well. For instance, if you define a class that behaves like a collection, provide members like `Add`, `Remove` and `Count` instead of `AddItem`, `Delete` or `NumberOfItems`. 99 | 100 | 101 | ## Avoid short names or names that can be mistaken with other names ![](imgs/must.png) ## 102 | 103 | Although technically correct, the following statement can be quite confusing. 104 | 105 | ```c# 106 | bool b001 = (lo == l0) ? (I1 == 11) : (lOl != 101); 107 | ``` 108 | 109 | 110 | ## Properly name properties ![](imgs/should.png) ## 111 | 112 | * Do name properties with nouns, noun phrases, or occasionally adjective phrases. 113 | * Do name Boolean properties with an affirmative phrase. eg) `CanSeek` instead of `CantSeek`. 114 | * Consider prefixing Boolean properties with `Is`, `Has`, `Can`, `Allows`, or `Supports`. 115 | * Consider giving a property the same name as its type. When you have a property that is strongly typed to an enumeration, the name of the property can be the same as the name of the enumeration. For example, if you have an enumeration named `CacheLevel`, a property that returns one of its values can also be named `CacheLevel`. 116 | 117 | 118 | ## Name methods using verb-object pair ![](imgs/should.png) ## 119 | 120 | Name methods using a verb-object pair such as `ShowDialog`. A good name should give the member a hint on the *what*, and if possible, the *why*. Also, don't include `And` in the name of the method. It implies that the method is doing more than one thing, which violates the single responsibility principle explained in [here](Member.Design.Guidelines.md#a-method-or-property-does-only-one-thing-). 121 | 122 | 123 | ## Name namespaces using names, layers, verbs and features ![](imgs/may.png) ## 124 | 125 | For instance, the following namespaces are good examples of that guideline. 126 | 127 | * `NHibernate.Extensibility` 128 | * `Microsoft.ServiceModel.WebApi` 129 | * `Microsoft.VisualStudio.Debugging` 130 | * `FluentAssertion.Primitives` 131 | * `CaliburnMicro.Extensions` 132 | 133 | ![NOTE](imgs/note.png) Never allow namespaces to contain the name of a type, but a noun in its plural form, eg) `Collections`, is usually okay. 134 | 135 | 136 | ## Use a verb or verb phrase to name an event ![](imgs/should.png) ## 137 | 138 | Name events with a verb or a verb phrase. For example: `Click`, `Deleted`, `Closing`, `Minimizing`, and `Arriving`. For example, the declaration of the Search event may look like this: 139 | 140 | ```c# 141 | public event EventHandler Search; 142 | ``` 143 | 144 | 145 | ## Use `-ing` and `-ed` to express pre-events and post-events ![](imgs/may.png) ## 146 | 147 | For example, a close event that is raised before a window is closed would be called `Closing` and one that is raised after the window is closed would be called `Closed`. Don't use `Before` or `After` prefixes or suffixes to indicate pre and post events. 148 | 149 | Suppose you want to define events related to the deletion process of an object. Avoid defining the `Deleting` and `Deleted` events as `BeginDelete` and `EndDelete`. Define those events as follows: 150 | 151 | * `Deleting`: Occurs just before the object is getting deleted 152 | * `Delete`: Occurs when the object needs to be deleted by the event handler. 153 | * `Deleted`: Occurs when the object is already deleted. 154 | 155 | 156 | ## Prefix an event handler with On ![](imgs/may.png) ## 157 | 158 | It is good practice to prefix the method that handles an event with `On`. For example, a method that handles the `Closing` event could be named `OnClosing`. 159 | 160 | 161 | ## Use an underscore for irrelevant lambda parameters ![](imgs/may.png) ## 162 | 163 | If you use a lambda statement, for instance, to subscribe to an event, and the actual parameters of the event are irrelevant, use the following convention to make that more explicit. 164 | 165 | ```c# 166 | button.Click += (_, __) => HandleClick(); 167 | ``` 168 | 169 | 170 | ## Group extension methods in a class suffixed with Extensions ![](imgs/may.png) ## 171 | 172 | If the name of an extension method conflicts with another member or extension method, you must prefix the call with the class name. Having them in a dedicated class with the `Extensions` suffix improves readability. 173 | 174 | 175 | ## Postfix asynchronous methods with `Async` of `TaskAsync` ![](imgs/should.png) ## 176 | 177 | The general convention for methods that return `Task` or `Task` is to post-fix them with `Async`, but if such a method already exist, use `TaskAsync` instead. 178 | 179 | -------------------------------------------------------------------------------- /Performance.Guidelines.md: -------------------------------------------------------------------------------- 1 | # Performance Guidelines # 2 | 3 | ## Consider using `Any()` to determine whether an `IEnumerable` is empty ![](imgs/may.png) ## 4 | 5 | When a method or other member returns an `IEnumerable` or other collection class that does not expose a `Count` property, use the `Any()` extension method rather than `Count()` to determine whether the collection contains items. If you do use `Count()`, you risk that iterating over the entire collection might have a significant impact (such as when it really is an `IQueryable` to a persistent store). 6 | 7 | ![NOTE](imgs/note.png) If you return an `IEnumerable` to prevent editing from outside the owner as explained in [here](Member.Design.Guidelines.md#return-an-ienumerablet-or-icollectiont-instead-of-a-concrete-collection-class-) and you're developing in .NET 4.5+, consider the new read-only classes. 8 | 9 | 10 | ## Only use async for low-intensive long-running activities ## 11 | 12 | The usage of `async` won't automatically run something on a worker thread like `Task.Run` does. It just adds the necessary logic to allow releasing the current thread and marshal the result back on that same thread if a long-running asynchronous operation has completed. In other words, use `async` only for I/O bound operations. 13 | 14 | 15 | ## Prefer Task.Run for CPU intensive activities ## 16 | 17 | If you do need to execute a CPU bound operation, use `Task.Run` to offload the work to a thread from the Thread Pool. Just don't forget that you have to marshal the result back to your main thread manually. 18 | 19 | 20 | ## Beware of mixing up `await`/`async` with `Task.Wait` ## 21 | 22 | `await` will not block the current thread but simply instruct to compiler to generate a state-machine. However, `Task.Wait` will block the thread and may even cause dead-locks (See [Beware of async/await deadlocks in single-threaded environments](Performance.Guidelines.md#beware-of-async-await-deadlocks-in-single-threaded-environments)). 23 | 24 | 25 | ## Beware of `async`/`await` deadlocks in single-threaded environments ## 26 | 27 | Consider the following asynchronous method: 28 | 29 | ```c# 30 | private async Task GetDataAsync() 31 | { 32 | var result = await MyWebService.GetDataAsync(); 33 | return result.ToString(); 34 | } 35 | ``` 36 | 37 | Now when an ASP.NET MVC controller action does this: 38 | 39 | ```c# 40 | public ActionResult ActionAsync() 41 | { 42 | var data = GetDataAsync().Result; 43 | 44 | return View(data); 45 | } 46 | ``` 47 | 48 | You'll end up with a deadlock. Why? Because the `Result` property getter will block until the `async` operation has completed, but since an `async` method will automatically marshal the result back to the original thread and ASP.NET uses a single-threaded synchronisation context, they'll be waiting on each other. A similar problem can also happen on WPF, Silverlight or a Windows Store C#/XAML app. Read more about this [here](http://blogs.msdn.com/b/pfxteam/archive/2011/01/13/10115163.aspx). 49 | 50 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # About the Guidelines # 2 | 3 | The guidelines provide a practical way of developing .NET applications using C# 3.0 or later depending on versions that applications are using. The existing coding guidelines that **Aliencube** have been using were originally written in 2003 by [Mike Kruger](http://www.icsharpcode.net/technotes/sharpdevelopcodingstyle03.pdf). Many development environments, however, have a lot been evolved from that point of time. This document is based on [Dennis Doomen](http://www.dennisdoomen.net)'s [C# Coding Guidelines](http://csharpguidelines.codeplex.com) released on [Nov 26th, 2012](http://csharpguidelines.codeplex.com/releases/view/98254). 4 | 5 | 6 | # History # 7 | 8 | Since Doomen's original document was written in MS-Word and released in PDF, which is hard to be maintainable, I made a decision to use plain markdown format for easy maintenance under the same license he originally set up. In addition to that, I got a permission to translate this into Korean, which will be provided soon. 9 | 10 | 11 | # Rationale # 12 | 13 | Coding guidelines are sometimes overlooked since they are considered as putting some unwanted burdens on developers. However, it has already been proved to worth doing because not all developers: 14 | 15 | * are aware that code is generally read 10 times more than it is changed; 16 | * are aware of the potential pitfalls of certain constructions in C#; 17 | * are introduced into certain conventions when using the .NET Framework such as `IDisposable` or the deferred execution nature of LINQ; 18 | * are aware of the impact of using (or neglecting to use) particular solutions on aspects like security, performance, multi-language support, etc; and 19 | * know that not every developer is as capable of understanding an elegant, but abstract, solution as the original developer. 20 | 21 | 22 | # Basic Principles # 23 | 24 | In general, because this document cannot cover everything for each application's purpose, those two documents provided by Microsoft are the main starting points: 25 | 26 | * [C# Coding Conventions (C# Programming Guide)](http://msdn.microsoft.com/en-us/library/ff926074.aspx) 27 | * [Framework Design Guidelines](http://msdn.microsoft.com/en-us/library/ms229042.aspx) 28 | 29 | Those principles have already been applied to Visual Studio. So, using the default settings can check most of our coding conventions. [ReSharper](http://www.jetbrains.com/resharper) that we are using checks our code in a more robust way so following its default settings would be more efficient. 30 | 31 | In addition to them, this document provides guidelines with the following principles: 32 | 33 | * **The Principle of Least Surprise** (or Astonishment) – you should choose a solution that does include any things people might not understand, or put on the wrong track. 34 | * **Keep It Simple Stupid** (KISS) – the simplest solution is more than sufficient. 35 | * **You Ain't Gonna Need It** (YAGNI) – you should create a solution for the current problem rather than the ones you think will happen later on (since when can you predict the future?). 36 | * **Don't Repeat Yourself** (DRY) – you are encouraged to prevent duplication in your code base without forgetting the [Rule of Three](http://lostechies.com/derickbailey/2012/10/31/abstraction-the-rule-of-three) heuristic. 37 | 38 | 39 | # How to Apply # 40 | 41 | Developers are not forced to comply with this guidelines. However, they are encouraged to apply those guidelines. Each guideline is clearly labeled like: 42 | 43 | * ![MUST](imgs/must.png): This guideline must be considered for coding. 44 | * ![SHOULD](imgs/should.png): This guideline is strongly recommended for coding. 45 | * ![MAY](imgs/may.png): This guideline can be applied for coding. 46 | 47 | ![NOTE](imgs/note.png) The terms – `must`, `should` and `may` – are defined in [RFC 2119](http://www.ietf.org/rfc/rfc2119.txt) 48 | 49 | 50 | # Useful Resources # 51 | 52 | In addition to the many links provided throughout this document, the following books, articles and sites for everyone interested in software quality are recommended: 53 | 54 | * [Code Complete: A Practical Handbook of Software Construction](http://www.amazon.com/Code-Complete-Practical-Handbook-Construction/dp/0735619670) (Steve McConnel) 55 | 56 | It deals with all aspects of software development, and even though the book was originally written in 2004, but you'll be surprised when you see how accurate it still is. I wrote a review in 2009 if you want to get a sense of its contents. 57 | 58 | * [The Art of Agile Development](http://www.amazon.com/Art-Agile-Development-James-Shore/dp/0596527675) (James Shore) 59 | 60 | Another great all-encompassing trip through the many practices preached by processes like Scrum and Extreme Programming. If you're looking for a quick introduction with a pragmatic touch, make sure you read James' book. 61 | 62 | * [Applying Domain Driven-Design and Patterns: With Examples in C# and .NET](http://www.amazon.com/Applying-Domain-Driven-Design-Patterns-Examples/dp/0321268202) (Jimmy Nilsson) 63 | 64 | The book that started my interest for both Domain Driven Design and Test Driven Development. It's one of those books that I wished I had read a few years earlier. It would have saved me from many mistakes. 65 | 66 | * [Jeremy D. Miller's Blog](http://codebetter.com/blogs/jeremy.miller) 67 | 68 | Although he is not that active anymore, in the last couple of years he has written some excellent blog posts on Test Driven Development, Design Patterns and design principles. I've learned a lot from his real-life and practical insights. 69 | 70 | * [LINQ Framework Design Guidelines](http://blogs.msdn.com/b/mirceat/archive/2008/03/13/linq-framework-design-guidelines.aspx) 71 | 72 | A set of rules and recommendations that you should adhere to when creating your own implementations of `IQueryable`. 73 | 74 | * [Best Practices for c# `async`/`await`](http://code.jonwagner.com/2012/09/06/best-practices-for-c-asyncawait/) 75 | 76 | The rationale and source of several of the new guidelines in this documented, written by [Jon Wagner](https://twitter.com/jonwagnerdotcom). 77 | 78 | 79 | # Table of Contents # 80 | 81 | * [Class Design Guidelines](Class.Design.Guidelines.md) 82 | * [Member Design Guidelines](Member.Design.Guidelines.md) 83 | * [Miscellaneous Design Guidelines](Miscellaneous.Design.Guidelines.md) 84 | * [Maintainability Guidelines](Maintainability.Guidelines.md) 85 | * [Naming Guidelines](Naming.Guidelines.md) 86 | * [Performance Guidelines](Performance.Guidelines.md) 87 | * [Framework Guidelines](Framework.Guidelines.md) 88 | * [Documentation Guidelines](Documentation.Guidelines.md) 89 | * [Layout Guidelines](Layout.Guidelines.md) 90 | 91 | 92 | # License # 93 | 94 | This is released under **New BSD License** as its original distributor does. 95 | 96 | >Copyright (c) 2014, aliencube.org All rights reserved. 97 | 98 | >Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 99 | 100 | >* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 101 | 102 | >* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 103 | 104 | >* Neither the name of the aliencube.org nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 105 | 106 | >THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 107 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /imgs/exception.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliencube/CSharp-Coding-Guidelines/11e5d2a70de8061ea4adc07db78c332bcb4aa67b/imgs/exception.png -------------------------------------------------------------------------------- /imgs/important.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliencube/CSharp-Coding-Guidelines/11e5d2a70de8061ea4adc07db78c332bcb4aa67b/imgs/important.png -------------------------------------------------------------------------------- /imgs/may.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliencube/CSharp-Coding-Guidelines/11e5d2a70de8061ea4adc07db78c332bcb4aa67b/imgs/may.png -------------------------------------------------------------------------------- /imgs/must.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliencube/CSharp-Coding-Guidelines/11e5d2a70de8061ea4adc07db78c332bcb4aa67b/imgs/must.png -------------------------------------------------------------------------------- /imgs/note.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliencube/CSharp-Coding-Guidelines/11e5d2a70de8061ea4adc07db78c332bcb4aa67b/imgs/note.png -------------------------------------------------------------------------------- /imgs/should.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliencube/CSharp-Coding-Guidelines/11e5d2a70de8061ea4adc07db78c332bcb4aa67b/imgs/should.png -------------------------------------------------------------------------------- /localisation/ko/Class.Design.Guidelines.md: -------------------------------------------------------------------------------- 1 | # 클라스 설계 가이드라인 Class Design Guidelines # 2 | 3 | ## A class or interface should have a single purpose ![](imgs/must.png) ## 4 | 5 | A class or interface should have a single purpose within the system it participates in. In general, a class is either representing a primitive type like an email or ISBN number, an abstraction of some business concept, a plain data structure or responsible for orchestrating the interaction between other classes. It is never a combination of those. This rule is widely known as the [Single Responsibility Principle (SRP)][srp], one of the [SOLID principles][solid]. 6 | 7 | Using [Design Patterns](http://en.wikipedia.org/wiki/Design_pattern_(computer_science)) is to communicate the intent of a class. If a single design pattern is assigned to a class, the class is more likely doing more than one thing. 8 | 9 | 10 | ## An interface should be small and focused ![](imgs/should.png) ## 11 | 12 | Interfaces should have a name that clearly explains the purpose or role of that interface within the system. Do not combine many vaguely related members on the same interface just because they were all on the same class. Separate the members based on the responsibility of those members so that callers only need to call or implement the interface related to a particular task. This rule is more commonly known as the [Interface Segregation Principle (ISP)][isp], one of the [SOLID principles][solid]. 13 | 14 | 15 | ## Use an interface rather than a base class to support multiple implementations ![](imgs/may.png) ## 16 | 17 | If you want to expose an extension point from your class, expose it as an interface rather than a base class. You don't want to force users of that extension point to derive their implementations from a base-class that might have undesired behavior. However, for their convenience you may implement an (abstract) default implementation that can serve as a starting point. 18 | 19 | 20 | ## Use an interface to decouple classes from each other ![](imgs/should.png) ## 21 | 22 | Interfaces are a very effective mechanism for decoupling classes from each other because: 23 | 24 | * they can prevent bidirectional associations; 25 | * they simplify the replacement of one implementation with another; 26 | * They allow replacing an expensive external service or resource with a temporary stub for use in a non-production environment; 27 | * they allow replacing the actual implementation with a dummy implementation or a fake object in a unit test; and 28 | * using a dependency injection framework you can centralize the choice which class is going to be used whenever a specific interface is requested. 29 | 30 | 31 | ## Avoid static classes ![](imgs/may.png) ## 32 | 33 | Static classes very often lead to badly designed code, except implementing extension method containers. They are also very difficult to test in isolation unless you're willing to use some very hacky tools. 34 | 35 | ![NOTE](imgs/note.png) If you really need a static class, mark it as `static` so that the compiler can prevent the class and its members from instantiating. This relieves you of creating an explicit private constructor. 36 | 37 | 38 | ## Don't hide inherited members with the `new` keyword ![](imgs/must.png) ## 39 | 40 | Not only does the new keyword break [Polymorphism](http://en.wikipedia.org/wiki/Polymorphism_in_object-oriented_programming), one of the most essential object-orientation principles, it also makes subclasses more difficult to understand. Consider the following two classes: 41 | 42 | ```c# 43 | public class Book 44 | { 45 | public virtual void Print() 46 | { 47 | Console.WriteLine("Printing Book"); 48 | } 49 | } 50 | 51 | public class PocketBook : Book 52 | { 53 | public new void Print() 54 | { 55 | Console.WriteLine("Printing PocketBook"); 56 | } 57 | } 58 | ``` 59 | 60 | This will cause behavior that you would not normally expect from class hierarchies: 61 | 62 | ```c# 63 | var pocketBook = new PocketBook(); 64 | 65 | pocketBook.Print(); // Will output "Printing PocketBook " 66 | ((Book)pocketBook).Print(); // Will output "Printing Book" 67 | ``` 68 | 69 | It ![MUST](imgs/must.png) **NOT** make a difference whether you call Print through a reference to the base class or through the derived class. 70 | 71 | 72 | ## Treat a derived object as if it were a base class object ![](imgs/should.png) ## 73 | 74 | In other words, you ![SHOULD](imgs/should.png) be able to use a reference to an object of a derived class wherever a reference to its base class object is used without knowing the specific derived class. A very notorious example of a violation of this rule is throwing a `NotImplementedException` when overriding some of the base-class methods. A less subtle example is not honoring the behavior expected by the base-class. This rule is also known as the [Liskov Substitution Principle (LSP)][lsp], one of the [SOLID principles][solid]. 75 | 76 | 77 | ## Don't refer to derived classes from the base class ![](imgs/must.png) ## 78 | 79 | Having dependencies from a base class to its sub-classes goes against proper object-oriented design and might prevent other developers from adding new derived classes. 80 | 81 | 82 | ## Avoid exposing the other objects an object depends on ## 83 | 84 | If you find yourself writing code like this then you might be violating the [Law of Demeter (LoD)](http://en.wikipedia.org/wiki/Law_of_Demeter). More detailed explanations of LoD can be found at [here](http://www.blackwasp.co.uk/LawOfDemeter.aspx). 85 | 86 | ```c# 87 | someObject.SomeProperty.GetChild().Foo() 88 | ``` 89 | 90 | An object should not expose any other classes it depends on because callers may misuse that exposed property or method to access the object behind it. By doing so, you allow calling code to become coupled to the class you are using, and thereby limiting the chance you can easily replace it in a future stage. 91 | 92 | ![NOTE](imgs/note.png) Using a class designed with the [Fluent Interface](http://en.wikipedia.org/wiki/Fluent_interface) pattern like LINQ does seem to violate this rule, but it is simply returning itself so that method chaining is allowed. 93 | 94 | ![EXCEPTION](imgs/exception.png) Inversion of Control (or Dependency Injection) frameworks such as [Unity](http://msdn.microsoft.com/unity), [Autofac](http://autofac.org) or [Ninject](http://www.ninject.org) often require you to expose a dependency as a public property. As long as this property is not used for anything else than dependency injection, it wouldn't be considered as a violation. 95 | 96 | 97 | ## Avoid bidirectional dependencies ![](imgs/must.png) ## 98 | 99 | This means that two classes know about each other's public members or rely on each other's internal behavior. Refactoring or replacing one of those two classes requires changes on both parties and may involve a lot of unexpected work. The most obvious way of breaking that dependency is introducing an interface for one of the classes and using dependency injection. 100 | 101 | 102 | ## Classes should have state and behavior ![](imgs/must.png) ## 103 | 104 | Unless your classes are only to transfer data over communication channels called [Data Transfer Objects](http://martinfowler.com/eaaCatalog/dataTransferObject.html), they ![MUST](imgs/must.png) have logics defining their state and behavior. 105 | 106 | 107 | [solid]: http://programmers.stackexchange.com/questions/202571/solid-principles-and-code-structure 108 | [srp]: http://www.objectmentor.com/resources/articles/srp.pdf 109 | [ocp]: http://www.objectmentor.com/resources/articles/ocp.pdf 110 | [lsp]: http://www.objectmentor.com/resources/articles/lsp.pdf 111 | [isp]: http://www.objectmentor.com/resources/articles/isp.pdf 112 | [dip]: http://www.objectmentor.com/resources/articles/dip.pdf 113 | -------------------------------------------------------------------------------- /localisation/ko/Documentation.Guidelines.md: -------------------------------------------------------------------------------- 1 | # 문서화 가이드라인 Documentation Guidelines # 2 | 3 | ## Write comments and documentation in English ![](imgs/must.png) ## 4 | 5 | Documents must be written in English (see [here](Naming.Guidelines.md#use-english-)). 6 | 7 | ![NOTE](imgs/note.png) Doomen's original document clearly stated that *Use US-English*. In this document, the *US* part is deliberately omitted. 8 | 9 | 10 | ## Document all public, protected and internal types and members ![](imgs/should.png) ## 11 | 12 | Documenting your code allows Visual Studio to pop-up the documentation when your class is used somewhere else. Furthermore, by properly documenting your classes, tools can generate professionally looking class documentation. 13 | 14 | 15 | ## Write XML documentation with another developer in mind ![](imgs/should.png) ## 16 | 17 | Write the documentation of your type with another developer in mind. Assume he or she will not have access to the source code and try to explain how to get the most out of the functionality of your type. 18 | 19 | 20 | ## Write MSDN-style documentation ![](imgs/may.png) ## 21 | 22 | Following the MSDN on-line help style and word choice helps the developer to find its way through your documentation more easily. 23 | 24 | ![NOTE](imgs/note.png) Either [GhostDoc](http://submain.com/products/ghostdoc.aspx) or [Sandcastle Help File Builder](https://shfb.codeplex.com) can generate a starting point for documenting code with a shortcut key. 25 | 26 | 27 | ## Avoid inline comments ![](imgs/should.png) ## 28 | 29 | If you feel the need to explain a block of code using a comment, consider replacing that block with a method having a clear name. 30 | 31 | 32 | ## Only write comments to explain complex algorithms or decisions ![](imgs/must.png) ## 33 | 34 | Try to focus comments on the why and what of a code block and not the how. Avoid explaining the statements in words, but instead help the reader understand why you chose a certain solution or algorithm and what you are trying to achieve. If applicable, also mention that you chose an alternative solution because you ran into a problem with the obvious solution. 35 | 36 | 37 | ## Don't use comments for tracking work to be done later ![](imgs/may.png) ## 38 | 39 | Annotating a block of code or some work to be done using a TODO or similar comment may seem a reasonable way of tracking work-to-be-done. But in reality, nobody really searches for comments like that. Use a work item tracking system such as Team Foundation Server to keep track of left overs. 40 | 41 | -------------------------------------------------------------------------------- /localisation/ko/Framework.Guidelines.md: -------------------------------------------------------------------------------- 1 | # 프레임워크 가이드라인 Framework Guidelines # 2 | 3 | ## `System` 네임스페이스의 타입보다는 C# 타입 앨러어스를 사용 ![](imgs/must.png) ## 4 | 5 | 예를 들어, `Object`보다는 `object`를, `String`보다는 `string`을, `Int32`보다는 `int`를 사용한다. 이런 앨리어스들은 기본 데이터 타입을 C# 언어의 1등급시민으로 만들기 위해 도임되었기에 후자를 쓰는 것이 좋다. 6 | 7 | ![EXCEPTION](imgs/exception.png) 이 타입들의 정적 멤버들을 가리킬 때는, 전체 CLS 이름을 사용하도록 커스텀한다, 예) `int.Parse()`보다는 `Int32.Parse()`. 8 | 9 | 10 | ## 다국어 지원을 위한 적절한 이름의 속성/변수/필드 ![](imgs/may.png) ## 11 | 12 | 에러 메시지들이나 메뉴 텍스트같은 다국어 지원이 필요한 자원에 적용할 가이드라인 13 | 14 | * 자원의 키값은 파스칼 표기법을 사용 15 | * 짧은 인식자보다는 서술형으로 제공한다. 가능하면 명료하게 유지하면 좋지만, 가독성을 희생하지는 마라. 16 | * 자원의 이름으로는 알파벳 글자만 사용한다. 17 | 18 | ## 배포 환경에 대한 스트링은 하드코딩하지마라 ![](imgs/may.png) ## 19 | 20 | 예를 들어 서버 주소같은 것들은 `ConfigurationManager` 클래스의 `ConnectionStrings` 속성같은 `Resources`를 사용하거나 비쥬얼 스튜디오에서 생성해주는 `Settings` 클래스를 사용하라. 실제값은 `app.config`나 `web.config`에서 관리한다. (웬만하면 설정 공간을 만들지마라.) 21 | 22 | ## 워닝 레벨을 제일 높여라 ![](imgs/must.png) ## 23 | 24 | 개발 환경에서는 C# 컴파일러를 **워닝 레벨 4**를 사용하도록 설정하고, **워닝을 에러처럼 다룬다** 옵션을 활성화한다. 코드 퀄리티를 가능한 높여주도록 컴파일러가 도와줄 것이다. 25 | 26 | ## `AssemblyInfo.cs` 파일의 속성들을 적당해 채워라 ![](imgs/may.png) ## 27 | 28 | 회사 이름, 설명, 저작권 명시, 버전 등을 확실히 하기 위해서 채워넣도록 한다. 모든 어셈블리들에서 공통적으로 사용하는 같은 값들이 있다면 `AssemblyInfo.cs` 밖으로 뽑아서 `SolutionInfo.cs`에 넣으면 해당 솔루션 내 모든 프로젝트에서 공유할 수 있다. 29 | 30 | ## 간단한 표현에는 LINQ를 삼간다 ![](imgs/may.png) ## 31 | 32 | 이렇게 보다는 33 | 34 | ```c# 35 | var query = from item in items where item.Length > 0; 36 | ``` 37 | 38 | `System.Linq` 네임스페이스의 확장 메소드를 사용하는 것이 좋다. 39 | 40 | ```c# 41 | var query = items.Where(i => i.Length > 0); 42 | ``` 43 | 44 | 왜냐면 LINQ 쿼리들은 가독성을 위해 여러줄에 걸쳐 쓰일 수는 있지만, 이 예제에서는 두번째가 더 가독성이 좋다. 45 | 46 | 47 | ## 딜리게이트보다는 람다 표현식을 사용한다 ![](imgs/should.png) ## 48 | 49 | 람다 표현식은 익명 딜리게이트보다 훨씬 우아한 대안을 제공한다. 그래서 이렇게보다는 50 | 51 | ```c# 52 | Customer c = Array.Find(customers, delegate(Customer c) 53 | { 54 | return c.Name == "Tom"; 55 | }); 56 | ``` 57 | 58 | 람다 표현식을 사용하라: 59 | 60 | ```c# 61 | Customer c = Array.Find(customers, c => c.Name == "Tom"); 62 | ``` 63 | 64 | 혹은 이게 더 좋다 65 | 66 | ```c# 67 | var customer = customers.Where(c => c.Name == "Tom"); 68 | ``` 69 | 70 | 71 | ## 다이나믹 객체와 통신할 때만 다이나믹 키워드를 쓴다 ![](imgs/must.png) ## 72 | 73 | 다이나믹 키워드는 다이나믹 언어를 다루기 위해 도입되었다. 컴파일러가 좀 복잡한 리플렉션 코드를 생성해야하기 때문에 심각한 병목현상이 온다. 74 | 75 | `Type.GetProperty()`와 `Type.GetMethod()`에 대한 대안으로 동적으로 생성된 (`Activator`를 사용하는)인스턴스의 멤버/메소드를 호출할 때만 사용하거나, COM Interop 타입을 다룰 때만 사용한다. 76 | 77 | ## Task에서는 되도록 `async`/`await` ## 78 | 79 | C# 5.0 키워드를 사용하면 여러 비동기 작업을 연쇄적으로 할 필요가 있을 때도 코드를 순차적으로 실행할 수 있고 관리하기가 매우 편해진다. 예를 들어 이렇게 메소드를 만들기 보다는: 80 | 81 | ```c# 82 | public Task GetDataAsync() 83 | { 84 | return MyWebService.FetchDataAsync() 85 | .ContinueWith(t => new Data (t.Result)); 86 | } 87 | ``` 88 | 89 | 이렇게 만든다: 90 | 91 | ```c# 92 | public async Task GetDataAsync() 93 | { 94 | var result = await MyWebService.FetchDataAsync(); 95 | 96 | return new Data (result); 97 | } 98 | ``` 99 | 100 | -------------------------------------------------------------------------------- /localisation/ko/Layout.Guidelines.md: -------------------------------------------------------------------------------- 1 | # 레이아웃 가이드라인 Layout Guidelines # 2 | 3 | ## Use a common layout ![](imgs/must.png) ## 4 | 5 | * Keep the length of each line under 130 characters. 6 | * Use an indentation of 4 whitespaces, and don't use tabs 7 | * Keep one whitespace between keywords like `if` and the expression, but don't add whitespaces after `(` and before `)` such as: 8 | 9 | ```c# 10 | if (condition == null) 11 | ``` 12 | 13 | * Add a whitespace around operators, like `+`, `-`, `==`, etc. 14 | * Always succeed the keywords `if`, `else`, `do`, `while`, `for` and `foreach`, with opening and closing parentheses, even though the language does not require it. 15 | * Always put opening and closing parentheses on a new line. 16 | * Indent object Initialisers and initialise each property on a new line, so use a format like this: 17 | 18 | ```c# 19 | var dto = new ConsumerDto() 20 | { 21 | Id = 123, 22 | Name = "Microsoft", 23 | PartnerShip = PartnerShip.Gold, 24 | } 25 | ``` 26 | 27 | * Don't indent lambda statements and use a format like this: 28 | 29 | ```c# 30 | methodThatTakesAnAction.Do(x => 31 | { 32 | // do something like this 33 | } 34 | ``` 35 | 36 | * Put the entire LINQ statement on one line, or start each keyword at the same indentation, like this: 37 | 38 | ```c# 39 | var query = from product in products where product.Price > 10 select product; 40 | ``` 41 | 42 | or 43 | 44 | ```c# 45 | var query = 46 | from product in products 47 | where product.Price > 10 48 | select product; 49 | ``` 50 | 51 | * Start the LINQ statement with all the `from` expressions and don't interweave them with where restrictions. 52 | * Add braces around every comparison condition, but don't add braces around a singular condition. For example 53 | 54 | ```c# 55 | if (!String.IsNullOrEmpty(str) && (str != "new")) 56 | ``` 57 | 58 | * Add an empty line between multi-line statements, between members, after the closing parentheses, between unrelated code blocks, around the `#region` keyword, and between the using statements of different companies. 59 | 60 | 61 | ## Order and group namespaces according the company ![](imgs/may.png) ## 62 | 63 | ```c# 64 | // Microsoft namespaces are first 65 | using System; 66 | using System.Collections; 67 | using System.XML; 68 | 69 | // Then any other namespaces in alphabetic order 70 | using AvivaSolutions.Business; 71 | using AvivaSolutions.Standard; 72 | 73 | using Telerik.WebControls; 74 | using Telerik.Ajax; 75 | ``` 76 | 77 | 78 | ## Place members in a well-defined order ![](imgs/must.png) ## 79 | 80 | Maintaining a common order allows other team members to find their way in your code more easily. In general, a source file should be readable from top to bottom, as if you are reading a book. This prevents readers from having to browse up and down through the code file. 81 | 82 | 1. Private fields and constants (in a region) 83 | 2. Public constants 84 | 3. Public read-only static fields 85 | 4. Factory Methods 86 | 5. Constructors and the Finalizer 87 | 6. Events 88 | 7. Public Properties 89 | 8. Other methods and private properties in calling order 90 | 91 | 92 | ## Be reluctant with `#region`s ![](imgs/must.png) ## 93 | 94 | Regions can be helpful, but can also hide the main purpose of a class. Therefore, use #regions only for: 95 | 96 | * Private fields and constants (preferably in a `Private Definitions` region). 97 | * Nested classes 98 | * Interface implementations (only if the interface is not the main purpose of that class) 99 | 100 | -------------------------------------------------------------------------------- /localisation/ko/Maintainability.Guidelines.md: -------------------------------------------------------------------------------- 1 | # 유지보수성 가이드라인 Maintainability Guidelines # 2 | 3 | ## Methods does not exceed 7 statements ![](imgs/must.png) ## 4 | 5 | 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 in multiple small and focused methods with self-explaining names, but make sure the high-level algorithm is still clear. 6 | 7 | 8 | ## Make all members `private` and types `internal` by default ![](imgs/must.png) ## 9 | 10 | 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. 11 | 12 | 13 | ## Avoid conditions with double negatives ![](imgs/should.png) ## 14 | 15 | Although a property like `customer.HasNoOrders` make sense, avoid using it in a negative condition like this: 16 | 17 | ```c# 18 | bool hasOrders = !customer.HasNoOrders; 19 | ``` 20 | 21 | Double negatives are more difficult to grasp than simple expressions, and people tend to read over the double negative easily. 22 | 23 | 24 | ## Name assemblies after their contained namespace ![](imgs/may.png) ## 25 | 26 | All DLLs should be named according to the pattern `..dll` where `` refers to your company's name and `` contains one or more dot-separated clauses. For example `Dnb.Web.Controls.dll`. 27 | 28 | As an example, consider a group of classes organized under the namespace `Dnb.Web.Binding` exposed by a certain assembly. According to this guideline, that assembly should be called `Dnb.Web.Binding.dll`. 29 | 30 | ![EXCEPTION](imgs/exception.png) If you decide to combine classes from multiple unrelated namespaces into one assembly, consider suffix to the assembly with `Core`, but do not use that suffix in the namespaces. For instance, `Dnb.Consulting.Core.dll`. 31 | 32 | 33 | ## Name a source file to the type it contains ![](imgs/may.png) ## 34 | 35 | Use Pascal casing for naming the file and don’t use underscores. 36 | 37 | 38 | ## Limit the contents of a source code file to one type ![](imgs/may.png) ## 39 | 40 | Make sure that one source file can be responsible for fully or partially contributing to one class. 41 | 42 | ![EXCEPTION](imgs/exception.png) Nested types can, for obvious reasons, be part of the same file. 43 | 44 | 45 | ## Name a source file to the logical function of the partial type ![](imgs/may.png) ## 46 | 47 | When using partial types and allocating a part per file, name each file after the logical part that part plays. For example: 48 | 49 | ```c# 50 | // In MyClass.cs 51 | public partial class MyClass 52 | { 53 | ... 54 | } 55 | 56 | // In MyClass.Designer.cs 57 | public partial class MyClass 58 | { 59 | ... 60 | } 61 | ``` 62 | 63 | 64 | ## Use using statements instead of fully qualified type names ![](imgs/may.png) ## 65 | 66 | Limit usage of fully qualified type names to prevent name clashing. For example, don't do this. 67 | 68 | ```c# 69 | var list = new System.Collections.Generic.List(); 70 | ``` 71 | 72 | Instead, do this. 73 | 74 | ```c# 75 | using System.Collections.Generic; 76 | 77 | var list = new List(); 78 | ``` 79 | 80 | If you do need to prevent name clashing, use a using directive to assign an alias: 81 | 82 | ```c# 83 | using Label = System.Web.UI.WebControls.Label; 84 | ``` 85 | 86 | 87 | ## Don't use **magic** numbers ![](imgs/must.png) ## 88 | 89 | Don't use literal values, either numeric or strings, in your code other than to define symbolic constants. For example: 90 | 91 | ```c# 92 | public class Whatever 93 | { 94 | public static readonly Color PapayaWhip = new Color(0xFFEFD5); 95 | public const int MaxNumberOfWheels = 18; 96 | } 97 | ``` 98 | 99 | Strings intended for logging or tracing are exempt from this rule. Literals are allowed when their meaning is clear from the context, and not subject to future changes, For example: 100 | 101 | ```c# 102 | mean = (a + b) / 2; // okay 103 | WaitMilliseconds(waitTimeInSeconds * 1000); // clear enough 104 | ``` 105 | 106 | If the value of one constant depends on the value of another, do attempt to make this explicit in the code. 107 | 108 | ```c# 109 | public class SomeSpecialContainer 110 | { 111 | public const int MaxItems = 32; 112 | public const int HighWaterMark = 3 * MaxItems / 4; // at 75% 113 | } 114 | ``` 115 | 116 | ![NOTE](imgs/note.png) An enumeration can often be used for certain types of symbolic constants. 117 | 118 | 119 | ## Only use `var` when the type is very obvious ![](imgs/must.png) ## 120 | 121 | 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 122 | 123 | ```c# 124 | var i = 3; // what type? int? uint? float? 125 | var myfoo = MyFactoryMethod.Create("arg"); // Not obvious what base-class or 126 | // interface to expect. Also difficult 127 | // to refactor if you can't search for 128 | // the class 129 | ``` 130 | 131 | Instead, use `var` like this. 132 | 133 | ```c# 134 | var q = from order in orders where order.Items > 10 and order.TotalValue > 1000; 135 | var repository = new RepositoryFactory.Get(); 136 | var list = new ReadOnlyCollection(); 137 | ``` 138 | 139 | In all of three above examples it is clear what type to expect. For a more detailed rationale about the advantages and disadvantages of using `var`, read Eric Lippert's [Uses and misuses of implicit typing](http://blogs.msdn.com/b/ericlippert/archive/2011/04/20/uses-and-misuses-of-implicit-typing.aspx). 140 | 141 | 142 | ## Declare and initialize variables as late as possible ![](imgs/should.png) ## 143 | 144 | Avoid the C and Visual Basic styles where all variables have to be defined at the beginning of a block, but rather define and initialize each variable at the point where it is needed. 145 | 146 | 147 | ## Assign each variable in a separate statement ![](imgs/must.png) ## 148 | 149 | Don't use confusing constructs like the one below. 150 | 151 | ```c# 152 | var result = someField = GetSomeMethod(); 153 | ``` 154 | 155 | 156 | ## Favour Object and Collection Initialisers over separate statements ![](imgs/should.png) ## 157 | 158 | Avoid 159 | 160 | ```c# 161 | var startInfo = new ProcessStartInfo("myapp.exe"); 162 | startInfo.StandardOutput = Console.Output; 163 | startInfo.UseShellExecute = true; 164 | ``` 165 | 166 | Instead, use [Object Initialisers](http://msdn.microsoft.com/en-us/library/bb384062.aspx). 167 | 168 | ```c# 169 | var startInfo = new ProcessStartInfo("myapp.exe") 170 | { 171 | StandardOutput = Console.Output, 172 | UseShellExecute = true 173 | }; 174 | ``` 175 | 176 | 177 | Similarly, instead of adding items to collection or dictionary individually 178 | 179 | ```c# 180 | var countries = new List(); 181 | countries.Add("Netherlands"); 182 | countries.Add("United States"); 183 | ``` 184 | 185 | Use collection or [dictionary initialisers](http://msdn.microsoft.com/en-us/library/bb531208.aspx). 186 | 187 | ```c# 188 | var countries = new List 189 | { 190 | "Netherlands", 191 | "United States" 192 | }; 193 | ``` 194 | 195 | 196 | ## Don't make explicit comparisons to `true` or `false` ![](imgs/must.png) ## 197 | 198 | It is usually bad style to compare a `bool` type expression to `true` or `false`. For example: 199 | 200 | ```c# 201 | while (condition == false) // wrong; bad style 202 | while (condition != true) // also wrong 203 | while (((condition == true) == true) == true) // where do you stop? 204 | 205 | while (condition) // OK 206 | ``` 207 | 208 | 209 | ## Don't change a loop variable inside a for or `foreach` loop ![](imgs/should.png) ## 210 | 211 | Updating the loop variable within the loop body is generally considered confusing. It is even worse that the loop variables are modified in more than one place in the loop. Consider `break` or `continue` instead, to change the loop variables. 212 | 213 | ```c# 214 | for (int index = 0; index < 10; ++index) 215 | { 216 | if (some condition) 217 | { 218 | index = 11; // Wrong! Use 'break' or 'continue' instead. 219 | } 220 | } 221 | ``` 222 | 223 | 224 | ## Avoid nested loops ![](imgs/should.png) ## 225 | 226 | A method that nests loops is more difficult to understand than one with only a single loop. In fact, in most cases having nested loops can be replaced with a much simpler LINQ query that uses the `from` keyword twice or more to join the data. 227 | 228 | 229 | ## Always add a block after keywords such as `if`, `else`, `while`, `for`, `foreach` and `case` ![](imgs/should.png) ## 230 | 231 | Please note that this also avoids possible confusion in statements of the form: 232 | 233 | ```c# 234 | // The wrong way: 235 | if (b1) if (b2) Foo(); else Bar(); // which 'if' goes with the 'else'? 236 | 237 | // The right way: 238 | if (b1) 239 | { 240 | if (b2) 241 | { 242 | Foo(); 243 | } 244 | else 245 | { 246 | Bar(); 247 | } 248 | } 249 | ``` 250 | 251 | 252 | ## Always add a default block after the last `case` in a `switch` statement ![](imgs/must.png) ## 253 | 254 | Add a descriptive comment if the default block is supposed to be empty. Moreover, if that block is not supposed to be reached, throw an `InvalidOperationException` to detect future changes that may fall through the existing cases. This ensures better code, because all paths the code can travel has been thought about. 255 | 256 | ```c# 257 | void Foo(string answer) 258 | { 259 | switch (answer) 260 | { 261 | case "no": 262 | Console.WriteLine("You answered with No"); 263 | break; 264 | case "yes": 265 | Console.WriteLine("You answered with Yes"); 266 | break; 267 | default: 268 | // Not supposed to end up here. 269 | throw new InvalidOperationException("Unexpected answer " + answer); 270 | } 271 | } 272 | ``` 273 | 274 | 275 | ## Finish every `if`-`else`-`if` statement with an `else` part ![](imgs/should.png) ## 276 | 277 | Similarly to the `default` block in a `switch` statement, consider the following way: 278 | 279 | ```c# 280 | void Foo(string answer) 281 | { 282 | if (answer == "no") 283 | { 284 | Console.WriteLine("You answered with No"); 285 | } 286 | else if (answer == "yes") 287 | { 288 | Console.WriteLine("You answered with Yes"); 289 | } 290 | else 291 | { 292 | // What should happen when this point is reached? Ignored? If not, 293 | // throw an InvalidOperationException. 294 | } 295 | } 296 | ``` 297 | 298 | 299 | ## Be reluctant with multiple return statements ![](imgs/should.png) ## 300 | 301 | One entry, one exit is a sound principle and keeps control flow readable. However, if the method is very small and complies with [this guideline](Maintainability.Guidelines.md#methods-does-not-exceed-7-statements-) then multiple return statements may actually improve readability over some central boolean flag that is updated at various points. 302 | 303 | 304 | ## Don't use `if`-`else` statements instead of a simple (conditional) assignment ![](imgs/should.png) ## 305 | 306 | Express your intentions directly. For example: 307 | 308 | ```c# 309 | // Bad practice 310 | bool pos; 311 | if (val > 0) 312 | { 313 | pos = true; 314 | } 315 | else 316 | { 317 | pos = false; 318 | } 319 | 320 | // Preferred practice 321 | bool pos = (val > 0); // initialisation 322 | ``` 323 | 324 | Or this can be another alternative: 325 | 326 | ```c# 327 | // Avoid 328 | string result; 329 | if (someString != null) 330 | { 331 | result = someString; 332 | } 333 | else 334 | { 335 | result = "Unavailable"; 336 | } 337 | return result; 338 | 339 | // Instead 340 | return someString ?? "Unavailable"; 341 | ``` 342 | 343 | 344 | ## Encapsulate complex expressions in a method or property ![](imgs/must.png) ## 345 | 346 | Consider the following example: 347 | 348 | ```c# 349 | if (member.HidesBaseClassMember && (member.NodeType != NodeType.InstanceInitializer)) 350 | { 351 | // do something 352 | } 353 | ``` 354 | 355 | In order to understand what this expression is about, you need to analyse its exact details and all the possible outcomes. Obviously, you could add an explanatory comment on top of it, but it is much better to replace this complex expression with a clearly named method like: 356 | 357 | ```c# 358 | if (NonConstructorMemberUsesNewKeyword(member)) 359 | { 360 | // do something 361 | } 362 | 363 | private bool NonConstructorMemberUsesNewKeyword(Member member) 364 | { 365 | return member.HidesBaseClassMember && 366 | member.NodeType != NodeType.InstanceInitializer; 367 | } 368 | ``` 369 | 370 | You still need to understand the expression if you are modifying it, but the calling code is now much easier to grasp. 371 | 372 | 373 | ## Call the most overloaded method from other overloads ![](imgs/should.png) ## 374 | 375 | This guideline only applies to overloads that are intended for providing optional arguments. Consider for example: 376 | 377 | ```c# 378 | public class MyString 379 | { 380 | private string someText; 381 | 382 | public MyString(string text) 383 | { 384 | this.someText = text; 385 | } 386 | 387 | public int IndexOf(string phrase) 388 | { 389 | return IndexOf(phrase, 0, someText.Length); 390 | } 391 | 392 | public int IndexOf(string phrase, int startIndex) 393 | { 394 | return IndexOf(phrase, startIndex, someText.Length - startIndex ); 395 | } 396 | 397 | public virtual int IndexOf(string phrase, int startIndex, int count) 398 | { 399 | return someText.IndexOf(phrase, startIndex, count); 400 | } 401 | } 402 | ``` 403 | 404 | The class `MyString` provides three overloads for the `IndexOf` method, but two of them simply call the one with the most parameters. 405 | 406 | ![NOTE](imgs/note.png) The same rule can apply to class constructors; implement the most complete overload and call that one from the other overloads using the `this()` operator. 407 | 408 | ![NOTE](imgs/note.png) The parameters with the same name should appear in the same position in all overloads. 409 | 410 | ![IMPORTANT](imgs/important.png) If you also want to allow derived classes to override these methods, define the most complete overload as a `protected virtual` method that is called by all overloads. 411 | 412 | 413 | ## Only use optional arguments to replace overloads ![](imgs/must.png) ## 414 | 415 | The only valid reason for using C# 4.0's optional arguments is to replace the example from [this guideline](Maintainability.Guidelines.md#call-the-most-overloaded-method-from-other-overloads-) with a single method like: 416 | 417 | ```c# 418 | public virtual int IndexOf(string phrase, int startIndex = 0, int count = 0) 419 | { 420 | return someText.IndexOf(phrase, startIndex, count); 421 | } 422 | ``` 423 | 424 | If the optional parameter is a reference type then it can only have a default value of `null`. But since strings, lists and collections should never be `null` according to [this rule](Miscellaneous.Design.Guidelines.md#dont-pass-null-as-the-sender-argument-when-raising-an-event-), you must use overloaded methods instead. 425 | 426 | ![NOTE](/imgs/note.png) The default values of the optional parameters are stored at the caller side. As such, changing the default value without recompiling the calling code will not apply the new default value properly. 427 | 428 | ![NOTE](/imgs/note.png) When an interface method defines an optional parameter, its default value is not considered during overload resolution unless you call the concrete class through the interface reference. See [this post](http://blogs.msdn.com/b/ericlippert/archive/2011/05/09/optional-argument-corner-cases-part-one.aspx) by Eric Lippert for more details. 429 | 430 | 431 | ## Avoid using named arguments ![](imgs/must.png) ## 432 | 433 | C# 4.0's named arguments have been introduced to make it easier to call COM components that are known for offering tons of optional parameters. If you need named arguments to improve the readability of the call to a method, that method is probably doing too much and should be refactored. 434 | 435 | The only exception where named arguments improve readability is when a constructor that yields a valid object is called like this: 436 | 437 | ```c# 438 | Person person = new Person 439 | ( 440 | firstName: "John", 441 | lastName: "Smith", 442 | dateOfBirth: new DateTime(1970, 1, 1) 443 | ); 444 | ``` 445 | 446 | 447 | ## Don't allow methods and constructors with more than three parameters ![](imgs/must.png) ## 448 | 449 | If you end up with a method with more than three parameters, use a structure or class for passing multiple arguments such as explained in the [Specification](http://en.wikipedia.org/wiki/Specification_pattern) design pattern. In general, the fewer the number of parameters, the easier it is to understand the method. Additionally, unit testing a method with many parameters requires many scenarios to test. 450 | 451 | 452 | ## Don't use `ref` or `out` parameters ![](imgs/must.png) ## 453 | 454 | They make code less understandable and might cause people to introduce bugs. Prefer returning compound objects instead. 455 | 456 | 457 | ## Avoid methods that take a `bool` flag ![](imgs/should.png) ## 458 | 459 | Consider the following method signature: 460 | 461 | ```c# 462 | public Customer CreateCustomer(bool platinumLevel) {} 463 | ``` 464 | 465 | On first sight this signature seems perfectly fine, but when calling this method you will lose this purpose completely: 466 | 467 | ```c# 468 | Customer customer = CreateCustomer(true); 469 | ``` 470 | 471 | Often, a method taking such a flag is doing more than one thing and needs to be refactored into two or more methods. An alternative solution is to replace the flag with an enumeration. 472 | 473 | 474 | ## Don't use parameters as temporary variables ![](imgs/may.png) ## 475 | 476 | Never use a parameter as a convenient variable for storing temporary state. Even though the type of your temporary variable may be the same, the name usually does not reflect the purpose of the temporary variable. 477 | 478 | 479 | ## Always check the result of an as operation ![](imgs/must.png) ## 480 | 481 | If you use as to obtain a certain interface reference from an object, always ensure that this operation does not return `null`. Failure to do so may cause a `NullReferenceException` at a much later stage if the object did not implement that interface. 482 | 483 | 484 | ## Don't comment out code ![](imgs/must.png) ## 485 | 486 | Never check-in code that is commented-out, but instead use a work item tracking system to keep track of some work to be done. Nobody knows what to do when they encounter a block of commented-out code. Was it temporarily disabled for testing purposes? Was it copied as an example? Should I delete it? 487 | 488 | -------------------------------------------------------------------------------- /localisation/ko/Member.Design.Guidelines.md: -------------------------------------------------------------------------------- 1 | # 멤버 설계 가이드라인 Member Design Guidelines # 2 | 3 | ## Allow properties to be set in any order ![](imgs/must.png) ## 4 | 5 | Properties should be stateless with respect to other properties, i.e. there should not be a difference between first setting property `A` and then `B` or vice versa. 6 | 7 | 8 | ## Use a method instead of a property ## 9 | 10 | Using a method is way better than a property, if: 11 | 12 | * The work is more expensive than setting a field value; 13 | * it represents a conversion such as the `Object.ToString()` method; 14 | * it returns a different result each time it is called, even if the arguments didn't change. For example, the `NewGuid()` method returns a different value each time it is called; or 15 | * the operation causes a side effect such as changing some internal state not directly related the property (which violates the [Command Query Separation](http://martinfowler.com/bliki/CommandQuerySeparation.html)). 16 | 17 | ![EXCEPTION](imgs/exception.png) Populating an internal cache or implementing [lazy-loading](http://www.martinfowler.com/eaaCatalog/lazyLoad.html) is a good exception. 18 | 19 | 20 | ## Don't use mutually exclusive properties ![](imgs/must.png) ## 21 | 22 | Having properties that cannot be used at the same time typically signals a type that is representing two conflicting concepts. Even though those concepts may share some of the behavior and state, they obviously have different rules that do not cooperate. 23 | 24 | This violation is often seen in domain models and introduces all kinds of conditional logic related to those conflicting rules, causing a ripple effect that significantly worsens the maintenance burden. 25 | 26 | 27 | ## A method or property does only one thing ![](imgs/must.png) ## 28 | 29 | Based on [SRP][srp], a method ![MUST](imgs/must.png) have a single responsibility. 30 | 31 | 32 | ## Don't expose stateful objects through static members ![](imgs/should.png) ## 33 | 34 | A stateful object is an object that contains many properties and lots of behavior behind that. If you expose such an object through a static property or method of some other object, it will be very difficult to refactor or unit test a class that relies on such a stateful object. In general, introducing a construction like that is a great example of violating many of the guidelines of this document. 35 | 36 | A classic example of this is the `HttpContext.Current` property, part of ASP.NET. Many see the `HttpContext` class as a source for a lot of ugly code. In fact, the testing guideline [Isolate the Ugly Stuff](http://msdn.microsoft.com/en-us/magazine/dd263069.aspx#id0070015) often refers to this class. 37 | 38 | 39 | ## Return an `IEnumerable` or `ICollection` instead of a concrete collection class ![](imgs/should.png) ## 40 | 41 | In general, you don't want callers to be able to change an internal collection, so don't return arrays, lists or other collection classes directly. Instead, return an `IEnumerable`, or, if the caller must be able to determine the count, an `ICollection`. 42 | 43 | ![NOTE](imgs/note.png) In .NET 4.5, you can also use `IReadOnlyCollection`, `IReadOnlyList` or `IReadOnlyDictionary`. 44 | 45 | 46 | ## Properties, methods and arguments representing strings or collections should never be `null` ![](imgs/must.png) ## 47 | 48 | Returning `null` can be unexpected by the caller. Always return an **empty collection** or an **empty string** instead of a `null` reference. This also prevents cluttering your code base with additional checks for `null`, or even worse, `String.IsNotNullOrEmpty()` or `String.IsNullOrWhiteSpace()`. 49 | 50 | 51 | ## Define parameters as specific as possible ![](imgs/should.png) ## 52 | 53 | If your member needs a specific piece of data, define parameters as specific as that and don't take a container object instead. For instance, consider a method that needs a connection string that is exposed through some central `IConfiguration` interface. Rather than taking a dependency on the entire configuration, just define a parameter for the connection string. This not only prevents unnecessary coupling, it also improved maintainability in a long run. 54 | 55 | 56 | ## Consider using domain-specific value types rather than primitives ![](imgs/may.png) ## 57 | 58 | Instead of using strings, integers and decimals for representing domain specific types such as an ISBN number, an email address or amount of money, consider created dedicated value objects that wrap both the data and the validation rules that apply to it. By doing this, you prevent ending up having multiple implementations of the same business rules, which both improves maintainability and prevents bugs. 59 | 60 | 61 | [solid]: http://programmers.stackexchange.com/questions/202571/solid-principles-and-code-structure 62 | [srp]: http://www.objectmentor.com/resources/articles/srp.pdf 63 | [ocp]: http://www.objectmentor.com/resources/articles/ocp.pdf 64 | [lsp]: http://www.objectmentor.com/resources/articles/lsp.pdf 65 | [isp]: http://www.objectmentor.com/resources/articles/isp.pdf 66 | [dip]: http://www.objectmentor.com/resources/articles/dip.pdf 67 | -------------------------------------------------------------------------------- /localisation/ko/Miscellaneous.Design.Guidelines.md: -------------------------------------------------------------------------------- 1 | # 일반적인 사항 설계 가이드라인 Miscellaneous Design Guidelines # 2 | 3 | ## Throw exceptions rather than returning some kind of status value ![](imgs/should.png) ## 4 | 5 | A code base that uses return values for reporting the success or failure tends to have nested if-statements sprinkled all over the code. Quite often, a caller forgets to check the return value anyhow. Structured exception handling has been introduced to allow you to throw exceptions and catch or replace exceptions at a higher layer. In most systems it is quite common to throw exceptions whenever an unexpected situations occurs. 6 | 7 | 8 | ## Provide a rich and meaningful exception message text ![](imgs/should.png) ## 9 | 10 | The message should explain the cause of the exception and clearly describe what needs to be done to avoid the exception. 11 | 12 | 13 | ## Throw the most specific exception that is appropriate ![](imgs/may.png) ## 14 | 15 | For example, if a method receives a `null` argument, it should throw `ArgumentNullException` instead of its base type `ArgumentException`. 16 | 17 | 18 | ## Don't swallow errors by catching generic exceptions ![](imgs/must.png) ## 19 | 20 | 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. 21 | 22 | 23 | ## Properly handle exceptions in asynchronous code ![](imgs/should.png) ## 24 | 25 | When throwing or handling exceptions in code that uses `async`/`await` or a `Task` remember the following two rules: 26 | 27 | * Exceptions that occur within an `async`/`await` block and inside a `Task`'s action are propagated to the awaiter. 28 | * Exceptions that occur in the code preceding the asynchronous block are propagated to the caller. 29 | 30 | 31 | ## Always check an event handler delegate for `null` ![](imgs/must.png) ## 32 | 33 | An event that has no subscribers is `null`, so before invoking, always make sure that the delegate list represented by the event variable is not `null`. Furthermore, to prevent conflicting changes from concurrent threads, use a temporary variable to prevent concurrent changes to the delegate. 34 | 35 | ```c# 36 | event EventHandler Notify; 37 | void RaiseNotifyEvent(NotifyEventArgs args) 38 | { 39 | EventHandler handlers = Notify; 40 | if (handlers != null) 41 | { 42 | handlers(this, args); 43 | } 44 | } 45 | ``` 46 | 47 | You can prevent the delegate list from being empty altogether. Simply assign an empty delegate like this: 48 | 49 | ```c# 50 | event EventHandler Notify = delegate {}; 51 | ``` 52 | 53 | 54 | ## Use a protected virtual method to raise each event ![](imgs/should.png) ## 55 | 56 | Complying with this guideline allows derived classes to handle a base class event by overriding the protected method. The name of the protected virtual method should be the same as the event name prefixed with On. For example, the protected virtual method for an event named `TimeChanged` is named `OnTimeChanged`. 57 | 58 | ![NOTE](imgs/note.png) Derived classes that override the protected virtual method are not required to call the base class implementation. The base class must continue to work correctly even if its implementation is not called. 59 | 60 | 61 | ## Consider providing property-changed events ![](imgs/may.png) ## 62 | 63 | Consider providing events that are raised when certain properties are changed. Such an event should be named `PropertyChanged`, where Property should be replaced with the name of the property with which this event is associated. 64 | 65 | ![NOTE](imgs/note.png) 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. 66 | 67 | 68 | ## Don't pass `null` as the sender argument when raising an event ![](imgs/must.png) ## 69 | 70 | 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`. 71 | 72 | ![EXCEPTION](imgs/exception.png) On static events, the sender argument ![SHOULD](imgs/should.png) be `null`. 73 | 74 | 75 | ## Use generic constraints if applicable ![](imgs/should.png) ## 76 | 77 | Instead of casting to and from the `object` type in generic types or methods, use `where` constraints or the `as` operator to specify the exact characteristics of the generic parameter. For example: 78 | 79 | ```c# 80 | class SomeClass 81 | { 82 | ... 83 | } 84 | 85 | // Don't 86 | class MyClass 87 | { 88 | void SomeMethod(T t) 89 | { 90 | object temp = t; 91 | SomeClass obj = (SomeClass) temp; 92 | } 93 | } 94 | 95 | // Do 96 | class MyClass where T : SomeClass 97 | { 98 | void SomeMethod(T t) 99 | { 100 | SomeClass obj = t; 101 | } 102 | } 103 | ``` 104 | 105 | 106 | ## Evaluate the result of a LINQ expression before returning it ![](imgs/must.png) ## 107 | 108 | Consider the following code snippet: 109 | 110 | ```c# 111 | public IEnumerable GetGoldMemberCustomers() 112 | { 113 | const decimal GoldMemberThresholdInEuro = 1000000; 114 | var q = (from customer in db.Customers 115 | where customer.Balance > GoldMemberThresholdInEuro 116 | select new GoldMember(customer.Name, customer.Balance)); 117 | return q; 118 | } 119 | ``` 120 | 121 | Since LINQ queries use deferred execution, returning `q` will actually return the expression tree representing the above query. Each time the caller evaluates this result using a `foreach` or something 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. -------------------------------------------------------------------------------- /localisation/ko/Naming.Guidelines.md: -------------------------------------------------------------------------------- 1 | # 네이밍 가이드라인 Naming Guidelines # 2 | 3 | ## Use English ![](imgs/must.png) ## 4 | 5 | All type members, parameters and variables should be named using words from the English language. 6 | 7 | * Choose easily readable, preferably grammatically correct names. For example, `HorizontalAlignment` is more readable than `AlignmentHorizontal`. 8 | * Favour readability over brevity. The property name `CanScrollHorizontally` is better than `ScrollableX` (an obscure reference to the X-axis). 9 | * Avoid using names that conflict with keywords of widely used programming languages. 10 | 11 | ![EXCEPTION](imgs/exception.png) In most projects, you will use words and phrases from your domain and names specific to your company. Visual Studio's **Static Code Analysis** will perform a spelling check on all code, so you may need to add those terms to a [Custom Code Analysis Dictionary](http://blogs.msdn.com/b/codeanalysis/archive/2007/08/20/new-for-visual-studio-2008-custom-dictionaries.aspx). 12 | 13 | ![NOTE](imgs/note.png) Doomen's original document clearly stated that *Use US-English*. In this document, the *US* part is deliberately omitted. 14 | 15 | 16 | ## Use proper casing for language elements ![](imgs/must.png) ## 17 | 18 | Language element | Casing | Example 19 | -----------------|--------|-------- 20 | Class, Struct | Pascal | `AppDomain` 21 | Interface | Pascal | `IBusinessService` 22 | Enumeration type | Pascal | `ErrorLevel` 23 | Enumeration values | Pascal | `FatalError` 24 | Event | Pascal | `Click` 25 | Private field | Camel | `listItem` 26 | Protected field | Pascal | `MainPanel` 27 | Const field | Pascal | `MaximumItems` 28 | Const variable | Camel | `maximumItems` 29 | Read-only static field | Pascal | `RedValue` 30 | Variable | Camel | `listOfValues` 31 | Method | Pascal | `ToString` 32 | Namespace | Pascal | `System.Drawing` 33 | Parameter | Camel | `typeName` 34 | Type Parameter | Pascal | `TView` 35 | Property | Pascal | `BackColor` 36 | 37 | 38 | ## Don't include numbers in variables, parameters and type members ![](imgs/may.png) ## 39 | 40 | In most cases they are a lazy excuse for not defining a clear and intention-revealing name. 41 | 42 | 43 | ## Don't prefix fields ![](imgs/must.png) ## 44 | 45 | For example, don't use `g_` or `s_` to distinguish static versus non-static fields. In general, a method in which it is difficult to distinguish local variables from member fields is too big. Examples of incorrect identifier names are: `_currentUser`, `mUserName`, `m_loginTime`. 46 | 47 | 48 | ## Don't use abbreviations ![](imgs/should.png) ## 49 | 50 | For example, use `OnButtonClick` rather than `OnBtnClick`. Avoid single character variable names, such as `i` or `q`. Use `index` or `query` instead. 51 | 52 | ![EXCEPTION](imgs/exception.png) Use well-known abbreviations that are widely accepted or well-known within the domain you work. For instance, use `UI` instead of `UserInterface`. 53 | 54 | 55 | ## Name a member, parameter or variable according its meaning and not its type ![](imgs/should.png) ## 56 | 57 | * Use functional names. For example, `GetLength` is a better name than `GetInt`. 58 | * Don't use terms like `Enum`, `Class` or `Struct` in a name. 59 | * Identifiers that refer to a collection type should have a **plural** name. 60 | 61 | 62 | ## Name types using nouns, noun phrases or adjective phrases ![](imgs/should.png) ## 63 | 64 | Bad examples include `SearchExamination` (a page for searching for examinations), `Common` (does not end with a noun, and does not explain its purpose) and `SiteSecurity` (although the name is technically okay, it does not say anything about its purpose). Good examples include `BusinessBinder`, `SmartTextBox`, or `EditableSingleCustomer`. 65 | 66 | Don't include terms like `Utility` or `Helper` in classes. Classes with a name like that are usually static classes and are introduced without considering the object-oriented principles (See [Avoid static classes](Class.Design.Guidelines.md#avoid-static-classes-)). 67 | 68 | 69 | ## Name generic type parameters with descriptive names ![](imgs/should.png) ## 70 | 71 | * Always prefix descriptive type parameter names with the letter `T`. 72 | * Always use a descriptive names unless a single-letter name is completely self-explanatory and a longer name would not add value. Use the single letter `T` as the type parameter in that case. 73 | * Consider indicating constraints placed on a type parameter in the name of parameter. For example, a parameter constrained to `ISession` may be called `TSession`. 74 | 75 | 76 | ## Don't repeat the name of a class or enumeration in its members ![](imgs/must.png) ## 77 | 78 | ```c# 79 | class Employee 80 | { 81 | // Wrong! 82 | static GetEmployee() {} 83 | DeleteEmployee() {} 84 | 85 | // Right 86 | static Get() {...} 87 | Delete() {...} 88 | 89 | // Also correct. 90 | AddNewJob() {...} 91 | RegisterForMeeting() {...} 92 | } 93 | ``` 94 | 95 | 96 | ## Name members similarly to members of related .NET Framework classes ![](imgs/may.png) ## 97 | 98 | .NET developers are already accustomed to the naming patterns the framework uses, so following this same pattern helps them find their way in your classes as well. For instance, if you define a class that behaves like a collection, provide members like `Add`, `Remove` and `Count` instead of `AddItem`, `Delete` or `NumberOfItems`. 99 | 100 | 101 | ## Avoid short names or names that can be mistaken with other names ![](imgs/must.png) ## 102 | 103 | Although technically correct, the following statement can be quite confusing. 104 | 105 | ```c# 106 | bool b001 = (lo == l0) ? (I1 == 11) : (lOl != 101); 107 | ``` 108 | 109 | 110 | ## Properly name properties ![](imgs/should.png) ## 111 | 112 | * Do name properties with nouns, noun phrases, or occasionally adjective phrases. 113 | * Do name Boolean properties with an affirmative phrase. eg) `CanSeek` instead of `CantSeek`. 114 | * Consider prefixing Boolean properties with `Is`, `Has`, `Can`, `Allows`, or `Supports`. 115 | * Consider giving a property the same name as its type. When you have a property that is strongly typed to an enumeration, the name of the property can be the same as the name of the enumeration. For example, if you have an enumeration named `CacheLevel`, a property that returns one of its values can also be named `CacheLevel`. 116 | 117 | 118 | ## Name methods using verb-object pair ![](imgs/should.png) ## 119 | 120 | Name methods using a verb-object pair such as `ShowDialog`. A good name should give the member a hint on the *what*, and if possible, the *why*. Also, don't include `And` in the name of the method. It implies that the method is doing more than one thing, which violates the single responsibility principle explained in [here](Member.Design.Guidelines.md#a-method-or-property-does-only-one-thing-). 121 | 122 | 123 | ## Name namespaces using names, layers, verbs and features ![](imgs/may.png) ## 124 | 125 | For instance, the following namespaces are good examples of that guideline. 126 | 127 | * `NHibernate.Extensibility` 128 | * `Microsoft.ServiceModel.WebApi` 129 | * `Microsoft.VisualStudio.Debugging` 130 | * `FluentAssertion.Primitives` 131 | * `CaliburnMicro.Extensions` 132 | 133 | ![NOTE](imgs/note.png) Never allow namespaces to contain the name of a type, but a noun in its plural form, eg) `Collections`, is usually okay. 134 | 135 | 136 | ## Use a verb or verb phrase to name an event ![](imgs/should.png) ## 137 | 138 | Name events with a verb or a verb phrase. For example: `Click`, `Deleted`, `Closing`, `Minimizing`, and `Arriving`. For example, the declaration of the Search event may look like this: 139 | 140 | ```c# 141 | public event EventHandler Search; 142 | ``` 143 | 144 | 145 | ## Use `-ing` and `-ed` to express pre-events and post-events ![](imgs/may.png) ## 146 | 147 | For example, a close event that is raised before a window is closed would be called `Closing` and one that is raised after the window is closed would be called `Closed`. Don't use `Before` or `After` prefixes or suffixes to indicate pre and post events. 148 | 149 | Suppose you want to define events related to the deletion process of an object. Avoid defining the `Deleting` and `Deleted` events as `BeginDelete` and `EndDelete`. Define those events as follows: 150 | 151 | * `Deleting`: Occurs just before the object is getting deleted 152 | * `Delete`: Occurs when the object needs to be deleted by the event handler. 153 | * `Deleted`: Occurs when the object is already deleted. 154 | 155 | 156 | ## Prefix an event handler with On ![](imgs/may.png) ## 157 | 158 | It is good practice to prefix the method that handles an event with `On`. For example, a method that handles the `Closing` event could be named `OnClosing`. 159 | 160 | 161 | ## Use an underscore for irrelevant lambda parameters ![](imgs/may.png) ## 162 | 163 | If you use a lambda statement, for instance, to subscribe to an event, and the actual parameters of the event are irrelevant, use the following convention to make that more explicit. 164 | 165 | ```c# 166 | button.Click += (_, __) => HandleClick(); 167 | ``` 168 | 169 | 170 | ## Group extension methods in a class suffixed with Extensions ![](imgs/may.png) ## 171 | 172 | If the name of an extension method conflicts with another member or extension method, you must prefix the call with the class name. Having them in a dedicated class with the `Extensions` suffix improves readability. 173 | 174 | 175 | ## Postfix asynchronous methods with `Async` of `TaskAsync` ![](imgs/should.png) ## 176 | 177 | The general convention for methods that return `Task` or `Task` is to post-fix them with `Async`, but if such a method already exist, use `TaskAsync` instead. 178 | 179 | -------------------------------------------------------------------------------- /localisation/ko/Performance.Guidelines.md: -------------------------------------------------------------------------------- 1 | # 퍼포먼스 가이드라인 Performance Guidelines # 2 | 3 | ## Consider using `Any()` to determine whether an `IEnumerable` is empty ![](imgs/may.png) ## 4 | 5 | When a method or other member returns an `IEnumerable` or other collection class that does not expose a `Count` property, use the `Any()` extension method rather than `Count()` to determine whether the collection contains items. If you do use `Count()`, you risk that iterating over the entire collection might have a significant impact (such as when it really is an `IQueryable` to a persistent store). 6 | 7 | ![NOTE](imgs/note.png) If you return an `IEnumerable` to prevent editing from outside the owner as explained in [here](Member.Design.Guidelines.md#return-an-ienumerablet-or-icollectiont-instead-of-a-concrete-collection-class-) and you're developing in .NET 4.5+, consider the new read-only classes. 8 | 9 | 10 | ## Only use async for low-intensive long-running activities ## 11 | 12 | The usage of `async` won't automatically run something on a worker thread like `Task.Run` does. It just adds the necessary logic to allow releasing the current thread and marshal the result back on that same thread if a long-running asynchronous operation has completed. In other words, use `async` only for I/O bound operations. 13 | 14 | 15 | ## Prefer Task.Run for CPU intensive activities ## 16 | 17 | If you do need to execute a CPU bound operation, use `Task.Run` to offload the work to a thread from the Thread Pool. Just don't forget that you have to marshal the result back to your main thread manually. 18 | 19 | 20 | ## Beware of mixing up `await`/`async` with `Task.Wait` ## 21 | 22 | `await` will not block the current thread but simply instruct to compiler to generate a state-machine. However, `Task.Wait` will block the thread and may even cause dead-locks (See [Beware of async/await deadlocks in single-threaded environments](Performance.Guidelines.md#beware-of-async-await-deadlocks-in-single-threaded-environments)). 23 | 24 | 25 | ## Beware of `async`/`await` deadlocks in single-threaded environments ## 26 | 27 | Consider the following asynchronous method: 28 | 29 | ```c# 30 | private async Task GetDataAsync() 31 | { 32 | var result = await MyWebService.GetDataAsync(); 33 | return result.ToString(); 34 | } 35 | ``` 36 | 37 | Now when an ASP.NET MVC controller action does this: 38 | 39 | ```c# 40 | public ActionResult ActionAsync() 41 | { 42 | var data = GetDataAsync().Result; 43 | 44 | return View(data); 45 | } 46 | ``` 47 | 48 | You'll end up with a deadlock. Why? Because the `Result` property getter will block until the `async` operation has completed, but since an `async` method will automatically marshal the result back to the original thread and ASP.NET uses a single-threaded synchronisation context, they'll be waiting on each other. A similar problem can also happen on WPF, Silverlight or a Windows Store C#/XAML app. Read more about this [here](http://blogs.msdn.com/b/pfxteam/archive/2011/01/13/10115163.aspx). 49 | 50 | -------------------------------------------------------------------------------- /localisation/ko/README.md: -------------------------------------------------------------------------------- 1 | # 이 가이드라인에 대하여 (About the Guidelines) # 2 | 3 | The guidelines provide a practical way of developing .NET applications using C# 3.0 or later depending on versions that applications are using. The existing coding guidelines that **Aliencube** have been using were originally written in 2003 by [Mike Kruger](http://www.icsharpcode.net/technotes/sharpdevelopcodingstyle03.pdf). Many development environments, however, have a lot been evolved from that point of time. This document is based on [Dennis Doomen](http://www.dennisdoomen.net)'s [C# Coding Guidelines](http://csharpguidelines.codeplex.com) released on [Nov 26th, 2012](http://csharpguidelines.codeplex.com/releases/view/98254). 4 | 5 | 6 | # 약간의 배경지식 (History) # 7 | 8 | Since Doomen's original document was written in MS-Word and released in PDF, which is hard to be maintainable, I made a decision to use plain markdown format for easy maintenance under the same license he originally set up. In addition to that, I got a permission to translate this into Korean, which will be provided soon. 9 | 10 | 11 | # 가이드라인을 만들게 된 계기 (Rationale) # 12 | 13 | Coding guidelines are sometimes overlooked since they are considered as putting some unwanted burdens on developers. However, it has already been proved to worth doing because not all developers: 14 | 15 | * are aware that code is generally read 10 times more than it is changed; 16 | * are aware of the potential pitfalls of certain constructions in C#; 17 | * are introduced into certain conventions when using the .NET Framework such as `IDisposable` or the deferred execution nature of LINQ; 18 | * are aware of the impact of using (or neglecting to use) particular solutions on aspects like security, performance, multi-language support, etc; and 19 | * know that not every developer is as capable of understanding an elegant, but abstract, solution as the original developer. 20 | 21 | 22 | # 가이드라인 기본 원칙 (Basic Principles) # 23 | 24 | In general, because this document cannot cover everything for each application's purpose, those two documents provided by Microsoft are the main starting points: 25 | 26 | * [C# Coding Conventions (C# Programming Guide)](http://msdn.microsoft.com/en-us/library/ff926074.aspx) 27 | * [Framework Design Guidelines](http://msdn.microsoft.com/en-us/library/ms229042.aspx) 28 | 29 | Those principles have already been applied to Visual Studio. So, using the default settings can check most of our coding conventions. [ReSharper](http://www.jetbrains.com/resharper) that we are using checks our code in a more robust way so following its default settings would be more efficient. 30 | 31 | In addition to them, this document provides guidelines with the following principles: 32 | 33 | * **The Principle of Least Surprise** (or Astonishment) – you should choose a solution that does include any things people might not understand, or put on the wrong track. 34 | * **Keep It Simple Stupid** (KISS) – the simplest solution is more than sufficient. 35 | * **You Ain't Gonna Need It** (YAGNI) – you should create a solution for the current problem rather than the ones you think will happen later on (since when can you predict the future?). 36 | * **Don't Repeat Yourself** (DRY) – you are encouraged to prevent duplication in your code base without forgetting the [Rule of Three](http://lostechies.com/derickbailey/2012/10/31/abstraction-the-rule-of-three) heuristic. 37 | 38 | 39 | # 가이드라인 적용 방법 (How to Apply) # 40 | 41 | Developers are not forced to comply with this guidelines. However, they are encouraged to apply those guidelines. Each guideline is clearly labeled like: 42 | 43 | * ![MUST](imgs/must.png): This guideline must be considered for coding. 44 | * ![SHOULD](imgs/should.png): This guideline is strongly recommended for coding. 45 | * ![MAY](imgs/may.png): This guideline can be applied for coding. 46 | 47 | ![NOTE](imgs/note.png) The terms – `must`, `should` and `may` – are defined in [RFC 2119](http://www.ietf.org/rfc/rfc2119.txt) 48 | 49 | 50 | # 유용한 정보들 (Useful Resources) # 51 | 52 | In addition to the many links provided throughout this document, the following books, articles and sites for everyone interested in software quality are recommended: 53 | 54 | * [Code Complete: A Practical Handbook of Software Construction](http://www.amazon.com/Code-Complete-Practical-Handbook-Construction/dp/0735619670) (Steve McConnel) 55 | 56 | It deals with all aspects of software development, and even though the book was originally written in 2004, but you'll be surprised when you see how accurate it still is. I wrote a review in 2009 if you want to get a sense of its contents. 57 | 58 | * [The Art of Agile Development](http://www.amazon.com/Art-Agile-Development-James-Shore/dp/0596527675) (James Shore) 59 | 60 | Another great all-encompassing trip through the many practices preached by processes like Scrum and Extreme Programming. If you're looking for a quick introduction with a pragmatic touch, make sure you read James' book. 61 | 62 | * [Applying Domain Driven-Design and Patterns: With Examples in C# and .NET](http://www.amazon.com/Applying-Domain-Driven-Design-Patterns-Examples/dp/0321268202) (Jimmy Nilsson) 63 | 64 | The book that started my interest for both Domain Driven Design and Test Driven Development. It's one of those books that I wished I had read a few years earlier. It would have saved me from many mistakes. 65 | 66 | * [Jeremy D. Miller's Blog](http://codebetter.com/blogs/jeremy.miller) 67 | 68 | Although he is not that active anymore, in the last couple of years he has written some excellent blog posts on Test Driven Development, Design Patterns and design principles. I've learned a lot from his real-life and practical insights. 69 | 70 | * [LINQ Framework Design Guidelines](http://blogs.msdn.com/b/mirceat/archive/2008/03/13/linq-framework-design-guidelines.aspx) 71 | 72 | A set of rules and recommendations that you should adhere to when creating your own implementations of `IQueryable`. 73 | 74 | * [Best Practices for c# `async`/`await`](http://code.jonwagner.com/2012/09/06/best-practices-for-c-asyncawait/) 75 | 76 | The rationale and source of several of the new guidelines in this documented, written by [Jon Wagner](https://twitter.com/jonwagnerdotcom). 77 | 78 | 79 | # 목차 (Table of Contents) # 80 | 81 | * [Class Design Guidelines](Class.Design.Guidelines.md) 82 | * [Member Design Guidelines](Member.Design.Guidelines.md) 83 | * [Miscellaneous Design Guidelines](Miscellaneous.Design.Guidelines.md) 84 | * [Maintainability Guidelines](Maintainability.Guidelines.md) 85 | * [Naming Guidelines](Naming.Guidelines.md) 86 | * [Performance Guidelines](Performance.Guidelines.md) 87 | * [Framework Guidelines](Framework.Guidelines.md) 88 | * [Documentation Guidelines](Documentation.Guidelines.md) 89 | * [Layout Guidelines](Layout.Guidelines.md) 90 | 91 | 92 | # 라이센스 (License) # 93 | 94 | This is released under **New BSD License** as its original distributor does. 95 | 96 | >Copyright (c) 2014, aliencube.org All rights reserved. 97 | 98 | >Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 99 | 100 | >* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 101 | 102 | >* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 103 | 104 | >* Neither the name of the aliencube.org nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 105 | 106 | >THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 107 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /localisation/ko/imgs/exception.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliencube/CSharp-Coding-Guidelines/11e5d2a70de8061ea4adc07db78c332bcb4aa67b/localisation/ko/imgs/exception.png -------------------------------------------------------------------------------- /localisation/ko/imgs/important.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliencube/CSharp-Coding-Guidelines/11e5d2a70de8061ea4adc07db78c332bcb4aa67b/localisation/ko/imgs/important.png -------------------------------------------------------------------------------- /localisation/ko/imgs/may.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliencube/CSharp-Coding-Guidelines/11e5d2a70de8061ea4adc07db78c332bcb4aa67b/localisation/ko/imgs/may.png -------------------------------------------------------------------------------- /localisation/ko/imgs/must.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliencube/CSharp-Coding-Guidelines/11e5d2a70de8061ea4adc07db78c332bcb4aa67b/localisation/ko/imgs/must.png -------------------------------------------------------------------------------- /localisation/ko/imgs/note.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliencube/CSharp-Coding-Guidelines/11e5d2a70de8061ea4adc07db78c332bcb4aa67b/localisation/ko/imgs/note.png -------------------------------------------------------------------------------- /localisation/ko/imgs/should.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliencube/CSharp-Coding-Guidelines/11e5d2a70de8061ea4adc07db78c332bcb4aa67b/localisation/ko/imgs/should.png --------------------------------------------------------------------------------