Coding Practices


  1. Avoid putting multiple classes in a single file.

  2. A single file should contribute types to only a single namespace. Avoid having multiple namespaces in the same file.

  3. Avoid files with more than 500 lines (excluding machine-generated code).

  4. Avoid methods with more than 25 lines.

  5. Avoid methods with more than five arguments. Use structures for passing multiple arguments.

  6. Lines should not exceed 80 characters.

  7. Do not manually edit any machine-generated code.

    1. If modifying machine-generated code, modify the format and style to match this coding standard.

    2. Use partial classes whenever possible to factor out the maintained portions.

  8. Avoid comments that explain the obvious. Code should be self-explanatory. Good code with readable variable and method names should not require comments.

  9. Document only operational assumptions, algorithm insights, and so on.

  10. Avoid method-level documentation.

    1. Use extensive external documentation for API documentation.

    2. Use method-level comments only as tool tips for other developers.

  11. With the exception of zero and one, never hardcode a numeric value; always declare a constant instead.

  12. Use the const directive only on natural constants, such as the number of days of the week.

  13. Avoid using const on read-only variables. For that, use the readonly directive:

     public class MyClass {    public const int DaysInWeek = 7;    public readonlyint Number;    public MyClass(int someValue)    {       Number = someValue;    } } 

  14. Assert every assumption. On average, every fifth line is an assertion:

     using System.Diagnostics; object GetObject( ) {...} object someObject = GetObject( ); Debug.Assert(someObject != null); 

  15. Every line of code should be walked through in a "white box" testing manner.

  16. Catch only exceptions for which you have explicit handling.

  17. In a catch statement that throws an exception, always throw the original exception (or another exception constructed from the original exception) to maintain the stack location of the original error:

     catch(Exception exception) {      MessageBox.Show(exception.Message);    throw;  //Same as throw exception; } 

  18. Avoid error code as method return values.

  19. Avoid defining custom exception classes.

  20. When defining custom exceptions:

    1. Derive the custom exception from Exception.

    2. Provide custom serialization.

  21. Avoid multiple Main( ) methods in a single assembly.

  22. Make only the most necessary types public; mark others as internal.

  23. Avoid friend assemblies, as they increase interassembly coupling.

  24. Avoid code that relies on an assembly running from a particular location.

  25. Minimize code in application assemblies (i.e., EXE client assemblies). Use class libraries instead to contain business logic.

  26. Avoid providing explicit values for enums:

     //Correct public enum Color {    Red,Green,Blue } //Avoid public enum Color {    Red = 1,Green = 2,Blue = 3 } 

  27. Avoid specifying a type for an enum:

     //Avoid public enum Color : long {    Red,Green,Blue } 

  28. Always use a curly brace scope in an if statement, even if it contains a single statement.

  29. Avoid using the trinary conditional operator.

  30. Avoid function calls in Boolean conditional statements. Assign into local variables and check on them:

     bool IsEverythingOK( ) {...} //Avoid: if(IsEverythingOK( )) {...} //Correct: bool ok = IsEverythingOK( ); if(ok) {...} 

  31. Always use zero-based arrays.

  32. Always explicitly initialize an array of reference types:

     public class MyClass {} const int ArrraySize = 100; MyClass[] array = new MyClass[ArrraySize]; for(int index = 0; index < array.Length; index++) {    array[index] = new MyClass( ); } 

  33. Do not provide public or protected member variables. Use properties instead.

  34. Avoid using the new inheritance qualifier. Use override instead.

  35. Always mark public and protected methods as virtual in a non-sealed class.

  36. Never use unsafe code, except when using interop.

  37. Avoid explicit casting. Use the as operator to defensively cast to a type:

     Dog dog = new GermanShepherd( ); GermanShepherd shepherd = dog asGermanShepherd; if(shepherd != null) {...} 

  38. Always check a delegate for null before invoking it.

  39. Do not provide public event member variables. Use event accessors instead.

  40. Avoid defining event-handling delegates. Use GenericEventHandler instead.

  41. Avoid raising events explicitly. Use EventsHelper to publish events defensively.

  42. Always use interfaces.

  43. Classes and interfaces should have at least a 2:1 ratio of methods to properties.

  44. Avoid interfaces with one member.

  45. Strive to have three to five members per interface.

  46. Do not have more than 20 members per interface. The practical limit is probably 12.

  47. Avoid events as interface members.

  48. When using abstract classes, offer an interface as well.

  49. Expose interfaces on class hierarchies.

  50. Prefer using explicit interface implementation.

  51. Never assume a type supports an interface. Defensively query for that interface:

     SomeType obj1; IMyInterface obj2; /* Some code to initialize obj1, then: */ obj2 = obj1 as IMyInterface; if(obj2 != null) {    obj2.Method1( ); } else {    //Handle error in expected interface }  

  52. Never hardcode strings that will be presented to end users. Use resources instead.

  53. Never hardcode strings that might change based on deployment, such as connection strings.

  54. Use String.Empty instead of "":

     //Avoid string name = ""; //Correct string name = String.Empty; 

  55. When building a long string, use StringBuilder, not string.

  56. Avoid providing methods on structures.

    1. Parameterized constructors are encouraged.

    2. You can overload operators.

  57. Always provide a static constructor when providing static member variables.

  58. Do not use late-binding invocation when early binding is possible.

  59. Use application logging and tracing.

  60. Never use goto, except in a switch statement fall-through.

  61. Always have a default case in a switch statement that asserts:

     int number = SomeMethod( ); switch(number) {    case 1:   Trace.WriteLine("Case 1:");   break;    case 2:   Trace.WriteLine("Case 2:");   break;    default:    Debug.Assert(false);   break; } 

  62. Do not use the this reference unless invoking another constructor from within a constructor:

     //Example of proper use of 'this' public class MyClass {    public MyClass(string message)    {}    public MyClass( ) : this("Hello")    {} } 

  63. Do not use the base word to access base class members unless you wish to resolve a conflict with a subclass member of the same name or when invoking a base class constructor:

     //Example of proper use of 'base' public class Dog {    public Dog(string name)    {}    virtual public void Bark(int howLong)    {} } public class GermanShepherd : Dog {    public GermanShepherd(string name) : base(name)    {}    override public void Bark(int howLong)    {       base.Bark(howLong);     } } 

  64. Do not use GC.AddMemoryPressure( ).

  65. Do not rely on HandleCollector.

  66. Implement Dispose( ) and Finalize( ) methods based on the template in Chapter 4.

  67. Always run code unchecked by default (for the sake of performance), but explicitly in checked mode for overflow- or underflow-prone operations:

     int CalcPower(int number,int power) {    int result = 1;    for(int count = 1;count <= power;count++)    {      checked      {         result *= number;      }    }    return result; } 

  68. Avoid explicit code exclusion of method calls (#if...#endif). Use conditional methods instead:

     public class MyClass {    [Conditional("MySpecialCondition")]    public void MyMethod( )    {} } 

  69. Avoid casting to and from System.Object in code that uses generics. Use constraints or the as operator instead:

     class SomeClass {} //Avoid: class MyClass<T> {    void SomeMethod(T t)    {      object temp = t;      SomeClass obj = (SomeClass)temp;    } } //Correct: class MyClass<T> where T : SomeClass {      void SomeMethod(T t)      {       SomeClass obj = t;      } } 

  70. Do not define constraints in generic interfaces. Interface-level constraints can often be replaced by strong typing:

     public class Customer {...} //Avoid: public interface IList<T> where T : Customer {...} //Correct: public interface ICustomerList : IList<Customer> {...} 

  71. Do not define method-specific constraints in interfaces.

  72. If a class or a method offers both generic and non-generic flavors, always prefer using the generics flavor.

  73. When implementing a generic interface that derived from an equivalent non-generic interface (such as IEnumerable<T>), use explicit interface implementation on all methods, and implement the non-generic methods by delegating to the generic ones:

         class MyCollection<T> : IEnumerable<T>     {        IEnumerator<T> IEnumerable<T>.GetEnumerator()        {...}        IEnumerator IEnumerable.GetEnumerator()        {           IEnumerable<T> enumerable = this;           return enumerable.GetEnumerator();        }     } 



Programming. NET Components
Programming .NET Components, 2nd Edition
ISBN: 0596102070
EAN: 2147483647
Year: 2003
Pages: 145
Authors: Juval Lowy

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net