Your SlideShare is downloading. ×
Back-2-Basics: .NET Coding Standards For The Real World<br />
Check Out Your Local User Groups!<br />San Diego Cloud Computing User Group<br />www.azureusergroup.com/group/sandiegoazur...
Win Free Software!<br />Rules<br />Provide your business card (or email and name)*<br />Indicate on the back what software...
Agenda<br />5<br />
Overview<br />
Why Do You Need Standards?<br />First, you might not agree witheverything I say… that’s okay!<br />Pick a standard for you...
After Selecting a Standard<br />Make sure it’s easily available to each programmer<br />Print or electronically<br />Enfor...
Real World Analysis Example<br />Scenario: In production Client Server Application with millions in sales<br />Nine projec...
Code.It Right Stats<br />All<br />Important<br />
Assembly Layout<br />
General Assembly Tips<br />Never hardcode strings that might change based on deployment such as connection strings<br />Be...
General Assembly Tips<br />Sign (strong name) your assemblies, including the client applications. <br />Also, sign interop...
Mark as CLS Compliant<br />Forces your assembly to be compliant with the Common Language Specification (CLS). <br />Assemb...
Element Order<br />
Elements of the Same Type<br />Should appear in this order:<br />public elements<br />protected elements<br />internal ele...
Namespaces<br />The general rule for naming namespaces is to use the company name followed by the technology name and opti...
Enums<br />Use abbreviations sparingly for Enums and their values<br />Do not use an Enum suffix on Enum type names<br />U...
Enums<br />Always add the FlagsAttribute to a bit field Enum type<br />Avoid providing explicit values for Enums (unless n...
Interfaces<br />Prefix interface names with the letter “I”<br />Do not use the underscore character. Use abbreviations spa...
Classes<br />Use a noun or noun phrase to name a class.<br />Avoid putting multiple classes in a single file.<br />A file ...
Events<br />Use Pascal case<br />Use an EventHandler suffix on event handler names. <br />Name an event argument class wit...
Member Variables (Fields)<br />Use camel case as a rule, or uppercase for very small words<br />Prefix private variables w...
Properties<br />Use Pascal case<br />Use a noun or noun phrase to name properties<br />Properties that return arrays or co...
Properties<br />Properties should not have dependencies on each other<br />Setting one property should not affect other pr...
Constructors<br />Do not call code from a constructor!<br />Can cause Exceptions.<br />Capture parameters only.<br />Provi...
Destructors<br />Avoid using destructors!<br />It is not possible to predict when garbage collection will occur.<br />The ...
Methods<br />Use Pascal case<br />Use verbs, verb phrases or verb-object pair to name methods<br />Always mark public and ...
Method Overloading<br />Use method overloading to provide different methods that do semantically the same thing. <br />Use...
Do Not Expose Generic List<br />List is a generic collection designed for performance not inheritance and<br />Applies to ...
Stop Exceptions BEFORE They Happen!<br />Defensive Programming<br />
Prevent Exceptions<br />Practice Defensive Programming!<br />Any code that might cause an exception (accessing files, usin...
Parameters<br />Always check for valid parameter arguments<br />Perform argument validation for every public or protected ...
Enums<br />Never assume that Enum arguments will be in the defined range.<br />Enums are just an Int32, so any valid numbe...
TryParse<br />Use the .TryParse method on value types when assigning from a string.<br />WILL NOT cause an exception!<br /...
Exceptions<br />When doing any operation that could cause an exception, wrap in Try - Catch block<br />Use System.Environm...
Code Style<br />
Variables<br />Avoid single character variable names<br />i, t etc.<br />Do not abbreviate variable words (such as num, in...
Accessing Class Member Variables<br />Preface all calls to class members with this./Me., and place base./MyBase. before ca...
Strings<br />When building a long string, always (almost) use StringBuilder, not string!<br />C#<br />StringBuilder builde...
Upcoming SlideShare
Loading in...5
×

Back-2-Basics: .NET Coding Standards For The Real World

1,300

Published on

This session will guide any level of programmer to greater productivity by providing the information needed to write consistent, maintainable code. Learn about project setup, assembly layout, code style, defensive programming and much, much more. We will even go over some real in production code and see what the programmer did wrong in "What's Wrong With this Code?". Code tips are included to help you write better, error free applications. Lots of code examples in C# and VB.NET.

Published in: Technology
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
1,300
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
0
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide
  • C# Use Style Cope to enforce.
  • DEMO: DefensiveProgramming.vb - SafeIntegerSet
  • The original exception object should not be re-throwed explicitly. Violation of this rule will complicate debugging and ruin the exception&apos;s stack trace.
  • ToStringGetHashCodeEquals
  • Or use an automatic property!
  • Transcript of "Back-2-Basics: .NET Coding Standards For The Real World"

    1. 1. Back-2-Basics: .NET Coding Standards For The Real World<br />
    2. 2.
    3. 3. Check Out Your Local User Groups!<br />San Diego Cloud Computing User Group<br />www.azureusergroup.com/group/sandiegoazureusergroup<br />San Diego .NET Developers Group<br />www.sddotnetdg.org<br />San Diego .NET User Group<br />www.sandiegodotnet.com<br />San Diego SQL Server User Group<br />www.sdsqlug.org<br />
    4. 4. Win Free Software!<br />Rules<br />Provide your business card (or email and name)*<br />Indicate on the back what software you are interested in<br />Otherwise I will pick <br />Winners will be picked next week<br />*Yes, most likely I’m going to send you and email about my user group (sddotnetdg.org) and or web site (dotNetTips.com)<br />Prizes<br />CodeRush and Refactor Pro from DevExpress (4)<br />SecondCopy (automatic backup software) (5) *<br />CodeIt.Right Standard from SubMain (4)<br />*Requires mailing address and phone number<br />
    5. 5. Agenda<br />5<br />
    6. 6. Overview<br />
    7. 7. Why Do You Need Standards?<br />First, you might not agree witheverything I say… that’s okay!<br />Pick a standard for your company<br />Every programmer on the same page<br />Easier to read and understand code<br />Easier to maintain code<br />Produces more stable, reliable code<br />Stick to the standard!!!<br />
    8. 8. After Selecting a Standard<br />Make sure it’s easily available to each programmer<br />Print or electronically<br />Enforce via code reviews<br />Provide programs to make it easier for programmers to maintain:<br />StyleCop – Free for C# programmers.<br />CodeIt.Right – Enterprise edition shares profiles. Can create custom profiles for your company.<br />
    9. 9. Real World Analysis Example<br />Scenario: In production Client Server Application with millions in sales<br />Nine projects of 183,177 lines of .NET code written by multiple programmers (junior to principal)<br />StyleCop<br />Analyze<br />Code.It Right<br />7,076<br />< 1,100<br />6,216<br />< 2,527<br />5,091<br />< 1,837<br />This is why you need to follow good coding practices throughout the lifecycle of the project!<br />
    10. 10. Code.It Right Stats<br />All<br />Important<br />
    11. 11. Assembly Layout<br />
    12. 12. General Assembly Tips<br />Never hardcode strings that might change based on deployment such as connection strings<br />Best place to put them are in user or application level Settings in your application.<br />Remember to save on exit and load on start!<br />Automatic in VB.NET <br />Other locations can include: Registration Database, Databases and more… <br />DEMO<br />
    13. 13. General Assembly Tips<br />Sign (strong name) your assemblies, including the client applications. <br />Also, sign interop assemblies with the project’s .snk file<br />Name assemblies in the following format:<br /><Company>.<Component>.dll<br />Project names should be named the same.<br />Microsoft.VisualBasic.dll<br />dotNetTips.Utility.dll<br />Acme.Services.References.dll<br />
    14. 14. Mark as CLS Compliant<br />Forces your assembly to be compliant with the Common Language Specification (CLS). <br />Assemblies, modules, and types can be CLS-compliant even if some parts of the assembly, module, or type are not CLS-compliant, as long as these two conditions are met: <br />If the element is marked as CLS-compliant, the parts that are not CLS-compliant must be marked using CLSCompliantAttribute with its argument set to false. <br />A comparable CLS-compliant alternative member must be supplied for each member that is not CLS-compliant.<br />DEMO<br />
    15. 15. Element Order<br />
    16. 16. Elements of the Same Type<br />Should appear in this order:<br />public elements<br />protected elements<br />internal elements<br />private elements<br />Use #region/ #endregion to group namespace-level and class-level elements<br />Use separate regions to organize the private, protected, and internal members.<br />
    17. 17. Namespaces<br />The general rule for naming namespaces is to use the company name followed by the technology name and optionally the feature and design<br />CompanyName.TechnologyName[.Feature][.Design]<br />
    18. 18. Enums<br />Use abbreviations sparingly for Enums and their values<br />Do not use an Enum suffix on Enum type names<br />Use a singular name for most Enum types, but use a plural name for Enum types that are bit fields<br />
    19. 19. Enums<br />Always add the FlagsAttribute to a bit field Enum type<br />Avoid providing explicit values for Enums (unless necessary)<br />Avoid specifying a type for an Enum<br />Public Enum WebServiceAction<br /> GetCurrentMode<br /> PauseService<br /> ResumeService<br /> StartService<br /> StopService<br />End Enum<br />
    20. 20. Interfaces<br />Prefix interface names with the letter “I”<br />Do not use the underscore character. Use abbreviations sparingly.<br />Challenging to version over releases<br />The smaller, more focused the interface the better<br />public interface IDisposable<br />{<br /> // Methods void Dispose();<br />}<br />
    21. 21. Classes<br />Use a noun or noun phrase to name a class.<br />Avoid putting multiple classes in a single file.<br />A file name should reflect the class it contains. <br />Provide a default private constructor if there are only static methods and properties on a class. <br />Use Static Class in C# or a Module in VB.NET<br />
    22. 22. Events<br />Use Pascal case<br />Use an EventHandler suffix on event handler names. <br />Name an event argument class with the EventArgs suffix.<br />Use EventHandler<> to declare handlers.<br />Be careful with non-UI threads calling back to the UI!<br />Use the BackgroundWorker Control in Windows Forms<br />DEMO<br />
    23. 23. Member Variables (Fields)<br />Use camel case as a rule, or uppercase for very small words<br />Prefix private variables with a "_”<br />Member variables should not be declared public<br />Use a Property instead<br />Const member variables may be declared public<br />
    24. 24. Properties<br />Use Pascal case<br />Use a noun or noun phrase to name properties<br />Properties that return arrays or collections should be methods. <br />Do not use write-only properties <br />Consider providing events that are raised when certain properties are changed. <br />Name them <Property>Changed<br />
    25. 25. Properties<br />Properties should not have dependencies on each other<br />Setting one property should not affect other properties<br />Properties should be settable in any order.<br />DEMO<br />
    26. 26. Constructors<br />Do not call code from a constructor!<br />Can cause Exceptions.<br />Capture parameters only.<br />Provide a constructor for every class. <br />Do not use the this./ Me. reference unless invoking another constructor from within a constructor.<br />Provide a protected constructor that can be used by types in a derived class.<br />
    27. 27. Destructors<br />Avoid using destructors!<br />It is not possible to predict when garbage collection will occur.<br />The garbage collector has no knowledge of unmanaged resources such as window handles, or open files and streams. <br />Implement IDisposible if you do!<br />Use the try/finally (or Using) to make sure that unmanaged resources are disposed of even if an exception interrupts your application. <br />DEMO<br />
    28. 28. Methods<br />Use Pascal case<br />Use verbs, verb phrases or verb-object pair to name methods<br />Always mark public and protected methods as virtual/Overridable in a non-sealed class. <br />Methods with return values should have a name describing the value returned<br />DEMO<br />
    29. 29. Method Overloading<br />Use method overloading to provide different methods that do semantically the same thing. <br />Use method overloading instead of allowing default arguments. <br />Overloaded methods should call the most complete method<br />If you provide the ability to override a method, make only the most complete overload virtual and define the other operations in terms of it<br />DEMO<br />
    30. 30. Do Not Expose Generic List<br />List is a generic collection designed for performance not inheritance and<br />Applies to public API’s<br />Does not contain any virtual members<br />Can not tell when updated<br />Use Instead:<br />System.Collections.ObjectModel.Collection<br />System.Collections.ObjectModel.ReadOnlyCollection<br />System.Collections.ObjectModel.KeyedCollection<br />Use Interfaces:<br />IDictionary<br />DEMO<br />
    31. 31. Stop Exceptions BEFORE They Happen!<br />Defensive Programming<br />
    32. 32. Prevent Exceptions<br />Practice Defensive Programming!<br />Any code that might cause an exception (accessing files, using objects like DataSets etc.) should check the object (depending on the type) so an Exception is not thrown<br />For example, call File.Exists to avoid a FileNotFoundException<br />Check and object for null<br />Check a DataSet for rows<br />Check an Array for bounds<br />Check String for null or empty<br />DEMO<br />
    33. 33. Parameters<br />Always check for valid parameter arguments<br />Perform argument validation for every public or protected method<br />Throw meaningful exceptions to the developer for invalid parameter arguments<br />Use the System.ArgumentException class<br />Or your own class derived from System.ArgumentException <br />DEMO<br />
    34. 34. Enums<br />Never assume that Enum arguments will be in the defined range.<br />Enums are just an Int32, so any valid number in that range could be sent in!<br />Always use Enum.IsDefined to verify value before using!<br />DEMO<br />
    35. 35. TryParse<br />Use the .TryParse method on value types when assigning from a string.<br />WILL NOT cause an exception!<br />Returns result of True/False<br />DEMO<br />
    36. 36. Exceptions<br />When doing any operation that could cause an exception, wrap in Try - Catch block<br />Use System.Environment.FailFast instead if unsafe for further execution<br />Do not catch non-specific exceptions (for common API’s)<br />Use Finally for cleanup code<br />When throwing Exceptions try using from System instead of creating custom Exceptions<br />Use MyApplication_UnhandledException event in VB.NET WinForm apps<br />Use Application_Error event in ASP.NET apps<br />
    37. 37. Code Style<br />
    38. 38. Variables<br />Avoid single character variable names<br />i, t etc.<br />Do not abbreviate variable words (such as num, instead of number)<br />Unless they are well known like Xml, Html or IO<br />If deriving from a core type, add the suffix of the identify type. <br />ArgumentException or FileStream<br />Use camel case for local variables<br />firstName<br />
    39. 39. Accessing Class Member Variables<br />Preface all calls to class members with this./Me., and place base./MyBase. before calls to all members of a base class<br />Class BaseClass<br /> Public Sub ProcessData()<br /> End Sub<br />End Class<br />Class MainClass<br /> Inherits BaseClass<br /> Public Sub AnalyzeData()<br /> End Sub<br /> 'Correct usage of this. and base.<br /> Public Sub Good()<br /> Me.AnalyzeData()<br /> MyBase.ProcessData()<br /> End Sub<br /> 'Incorrect usage.<br /> Public Sub Bad()<br /> AnalyzeData()<br /> ProcessData()<br /> End Sub<br />End Class<br />
    40. 40. Strings<br />When building a long string, always (almost) use StringBuilder, not string!<br />C#<br />StringBuilder builder = new StringBuilder("The error ");<br />builder.Append(errorMessage); // errorMessage is defined elsewhere<br />builder.Append("occurred at ");<br />builder.Append(DateTime.Now);<br />Console.WriteLine(builder.ToString());<br />VB<br />Dim builder As New StringBuilder("The error ")<br />builder.Append(errorMessage) 'errorMessage is defined elsewhere<br />builder.Append("occurred at ")<br />builder.Append(DateTime.Now)<br />Console.WriteLine(builder.ToString())<br />DEMO<br />
    41. 41. Parameters<br />Use descriptive parameter names<br />Parameter names should be descriptive enough such that the name of the parameter and its value can be used to determine its meaning in most scenarios<br />Do not prefix parameter names with Hungarian type notation<br />Public Function ManageIIs(ByVal server As String, ByVal userName As String, ByVal password As System.Security.SecureString, ByVal domain As String, ByVal instance As String, <br /> ByVal action As IIsWebServiceAction) As Int32<br />End Function<br />
    42. 42. Generic Type Parameters<br />If possible use descriptive type parameters for generic parameters<br />Prefix with T<br />Use only T, K etc if is self-explanatory<br />C#<br />public static string ConvertArrayToString<TArray>(TArray[] array) where TArray : IEnumerable <br />{ <br />}<br />VB<br />Public Shared Function ConvertArrayToString(Of TArray As {IEnumerable})(ByVal array As TArray()) As String<br />End Function<br />DEMO<br />
    43. 43. Commenting<br />Comment your code!<br />While coding or before<br />Keep it short and understandable<br />Mark changes with explanation, who changed it and the date (if that is your company standard)<br />NEVER WAIT UNTIL AFTER YOU ARE DONE CODING!<br />
    44. 44. Xml Commenting<br />Now supported by VB.NET and C#!<br />Comment all public classes and methods!<br />XML can be turned into help docs, help html with applications like Sandcastle<br />http://sandcastle.notlong.com<br />Very useful for teams and documentation for users.<br />Make this easy by using GhostDoc<br />http://ghostdoc.notlong.com<br />DEMO<br />
    45. 45. Let’s See What We Have Learned/ Know<br />What’s Wrong With This Code?<br />
    46. 46. Constructor<br />public class FileCache<br />{<br /> public FileCache(string tempPath)<br />  {<br />   var appData = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),Global.UserDataFolder);<br /> var cacheDir = Path.Combine(appData, tempPath); <br />   if (Directory.Exists(cacheDir) == false)<br /> { <br />     Directory.CreateDirectory(cacheDir);<br />  }<br />   }<br />}<br />public class FileCache<br />{<br /> public FileCache(string tempPath)<br />  {<br />   this.TempPath = tempPath;<br />  }<br />}<br />46<br />
    47. 47. Method <br />public static string SQLValue(string parameter, string value)<br />{<br />  if (String.IsNullOrEmpty(parameter))<br />  {<br />  throw new ArgumentNullException("parameter");<br />  }<br /> <br />  if (string.IsNullOrEmpty(value))<br />    return (parameter + " = NULL");<br />  else<br />    return (parameter + " = '" + value.Trim() + "'");<br />}<br />public static string SQLValue(string parameter, string value)<br />{<br /> if (String.IsNullOrEmpty(parameter))<br />   {<br />     throw new ArgumentNullException("parameter");<br />    }<br /> <br />  if (string.IsNullOrEmpty(value))<br />   return (String.Format("{0} = NULL", parameter)); <br />  else<br />    return (String.Format("{0} = '{1}'", parameter, value.Trim()));<br />}<br />public static string CreateSQLParameter(string name, string value)<br />{<br /> if (String.IsNullOrEmpty(name))<br />  {<br />   throw new ArgumentNullException(”name");<br />  }<br /> <br />  return string.IsNullOrEmpty(value) ? (String.Format("{0} = NULL", name)) : (String.Format("{0} = '{1}'", name, value.Trim()));<br />}<br />public static string SQLValue(string name, string value)<br />{<br /> if (string.IsNullOrEmpty(value))<br />   return (name + " = NULL");<br />  else<br />   return (name + " = '" + value.Trim() + "'");<br />}<br />
    48. 48. Exception<br />private void UpdateVendor()<br />{<br /> try<br /> {<br /> //Code that causes and exception <br /> }<br /> catch (ValidationException ex)<br /> {<br /> //Clean up code<br /> throw ex;<br /> }<br /> catch (Exception ex)<br /> {<br /> LogWriter.WriteException(ex, <br /> System.Diagnostics.TraceEventType.Error, this.Name);<br /> }<br />}<br />
    49. 49. Structure<br /> Public Structure UserInfo<br /> Private _contactName As String<br /> Public Property ContactName() As String<br /> Get<br /> Return _contactName<br /> End Get<br /> Set(ByVal value As String)<br /> _contactName = value<br /> End Set<br /> End Property<br /> Private _email As String<br /> Public Property Email() As String<br /> Get<br /> Return _email<br /> End Get<br /> Set(ByVal value As String)<br /> _email = value<br /> End Set<br /> End Property<br /> Public Overrides Function ToString() As String<br /> Return Me.ContactName<br /> End Function<br /> Public Overloads Overrides Function GetHashCode() As Integer<br /> Return Me.ContactName.GetHashCode Or Me.Email.GetHashCode<br /> End Function<br /> Public Overloads Overrides Function Equals(ByVal obj As [Object]) As Boolean<br /> Dim testObject As UserInfo = CType(obj, UserInfo)<br /> If Me.ContactName = testObject.ContactName AndAlso Me.Email = testObject.Email<br /> Return True<br /> Else<br /> Return False<br /> End If<br /> End Function<br /> End Structure<br /> Public Structure UserInfo<br /> Private _contactName As String<br /> Public Property ContactName() As String<br /> Get<br /> Return _contactName<br /> End Get<br /> Set(ByVal value As String)<br /> _contactName = value<br /> End Set<br /> End Property<br /> Private _email As String<br /> Public Property Email() As String<br /> Get<br /> Return _email<br /> End Get<br /> Set(ByVal value As String)<br /> _email = value<br /> End Set<br /> End Property<br /> Public Overrides Function ToString() As String<br /> Return Me.ContactName<br /> End Function<br />Public Overloads Overrides Function GetHashCode() As Integer<br /> Return Me.ContactName.GetHashCode Or Me.Email.GetHashCode<br /> End Function<br /> End Structure<br /> Public Structure UserInfo<br /> Private _contactName As String<br /> Public Property ContactName() As String<br /> Get<br /> Return _contactName<br /> End Get<br /> Set(ByVal value As String)<br /> _contactName = value<br /> End Set<br /> End Property<br /> Private _email As String<br /> Public Property Email() As String<br /> Get<br /> Return _email<br /> End Get<br /> Set(ByVal value As String)<br /> _email = value<br /> End Set<br /> End Property<br />Public Overrides Function ToString() As String<br /> Return Me.ContactName<br /> End Function<br />End Structure<br /> Public Structure UserInfo<br /> Private _contactName As String<br /> Public Property ContactName() As String<br /> Get<br /> Return _contactName<br /> End Get<br /> Set(ByVal value As String)<br /> _contactName = value<br /> End Set<br /> End Property<br /> Private _email As String<br /> Public Property Email() As String<br /> Get<br /> Return _email<br /> End Get<br /> Set(ByVal value As String)<br /> _email = value<br /> End Set<br /> End Property<br />End Structure<br />
    50. 50. Enum<br />public enum MergeTypes<br />{<br /> InsCo = 1,<br /> Agents = 2,<br /> Vendors = 3<br />}<br />public enum MergeType<br />{<br />InsuranceCompanies,<br /> Agents,<br /> Vendors<br />}<br />public enum MergeType<br />{<br />None,<br />InsuranceCompanies,<br /> Agents,<br /> Vendors<br />}<br />
    51. 51. Fields<br />public class Contact<br />{<br /> protected string mNamePrefix = "";<br /> protected string mFirstName = "";<br /> protected string mLastName = "";<br /> protected string mPhone1 = "";<br /> protected string mExtension1 = "";<br /> protected string mEmailAddress = "";<br /> //Code<br />}<br />public class Contact<br />{<br />private string _namePrefix = string.Empty;<br />protected string NamePrefix<br /> {<br /> get { return _namePrefix; }<br /> set { _namePrefix = value; }<br /> }<br /> //Code<br />}<br />
    52. 52. Events<br />public delegate void ReportListEventHandler(object sender, ReportListEventArgs e);<br />public event ReportListEventHandler ReportSelected;<br />public event EventHandler<ReportListEventArgs> ReportSelected;<br />
    53. 53. Summary<br />
    54. 54. Products To Help Out<br />StyleCop<br />http://stylecop.notlong.com<br />CodeIt.Right<br />http://codeitright.notlong.com<br />FXCop<br />http://fxcop.notlong.com<br />Or Use Analyze in VS Team Systems<br />Refactor Pro! For Visual Studio<br />http://refactorpro.notlong.com <br />I Use All 4!<br />54<br />
    55. 55. Resourses (Besides My Book)<br />Design Guidelines for Class Library Developers<br />http://DGForClassLibrary.notlong.com<br />.NET Framework General Reference Naming Guidelines<br />http://namingguide.notlong.com<br />

    ×