User:Stuart/Scratchpad/Coding Standards: Difference between revisions

From The Dreaming
Jump to navigation Jump to search
My coding standards from the work wiki
 
Saved my work so far... still ongoing
Line 1: Line 1:
{{nav/stuart}}
{{stub}}
= Coding Standards =
= Coding Standards Take 2 =
 
'''Note to self'''
'''Note to self'''
Things I want to cover in this:
Things I want to cover in this:
Line 9: Line 10:
* SQL code conventions? .NET/SQL conventions?
* SQL code conventions? .NET/SQL conventions?
* Suggestions from me.
* Suggestions from me.
* Git commit standards


== Overview ==
== Overview ==
Line 32: Line 34:
We can then argue about them at wholly unnecessary length and hopefully we'll have something that we can all agree with (or at least compromise on) at the end of it.
We can then argue about them at wholly unnecessary length and hopefully we'll have something that we can all agree with (or at least compromise on) at the end of it.


== Standards ==
I was effectively copying all standards that I found into this page, but that ended up seeming pointless (plus there was quite a bit of stuff which was just not relevant to us), so I'm going to list some standards
Since we have mostly Visual Basic code, I'll tackle that first.
 
== General ==
 
=== File and path names ===
* Generally, folder and file names should not contain characters other alphanumeric ([A-Za-z0-9]), hyphen, dot.
** An exception to this might be user-orientated documentation - eg. a user guide maintained by us - which might contain space characters
 
'''Note: ''' I'd like to go through our code at the end of a release and remove all the spaces from our folder names. They're really painful.
 
=== Tabs vs Spaces ===
There's no 'correct' answer - people have preferences, but consistency is important. Microsoft's [https://msdn.microsoft.com/en-us/library/h63fsef3.aspx Visual Basic Coding Conventions] suggests:
{{q|Insert tabs as spaces, and use smart indenting with four-space indents.}}
 
Spaces seem to be the more widely accepted choice in style guides I've found online, but it seems that most of our code leans towards tabs. Whichever we choose, we should apply it accorss the board for all languages and all dev output (eg. HTML, XML, JSON, C#, VB, C++, Python, CSS, Javascript, anything else).
 
Incidentally, I quite like the [http://nickgravgaard.com/elastic-tabstops/ Elastic Tabstops] idea, but that has somewhat limited implementation.
 
=== Code organisation ===
Where do I start?
 
Our code organisation is all over the place - especially the Automate project. We should try and agree how it ''should'' be organised and then figure out how we can get it there. Some ideas:
* Directories should follow namespaces - eg. {{c|BluePrism.Core.Expressions}} should be in the {{c|Expressions/}} directory inside the root {{c|BluePrism.Core}} directory.
* Some of our directories are in subdirectories beneath the automate root, some are directly in that root; each project should have its folder directly in the automate root - ie. ''not'' in Automate-3.0, ApplicationManager.
** ...or... should we have a subfolder inside automate for the product code ("Product"? "Main"?) - separating each project from each other is unhelpful, but separating our core product from Login Agent, BPJabInstaller, Release, etc. seems sensible.
 
== .Net Code ==
There's a general set of guidelines at [https://msdn.microsoft.com/en-us/library/ms229042.aspx Microsoft's Framework Design Guidelines]. I did start to transcribe them here, but it might be better if we just go through them and collect the ones that we want to adopt.
 
=== Commenting ===
* Non-private members should be XML-documented
* XML-documentation is not necessary for private member variables
* Though I think properties, methods, inner classes et al should still be XML-documented.
 
=== Naming ===
Micrsoft has a huge naming section in its design guidelines - see the [https://msdn.microsoft.com/en-us/library/ms229002.aspx Naming Guidelines]. I'll be referring to this from time to time below.
 
Note: I've used Microsoft's convention of 'camel case', starting with a lowercase letter and 'Pascal case' starting with an uppercase letter, eg.
* PascalCase
* camelCase
 
== Namespaces ==
* Pascal Case
* Should start with "BluePrism" (from the naming guidelines: ''DO prefix namespace names with a company name to prevent namespaces from different companies from having the same name'')
* Should not be the same name as a type inside that namespace
* Filenames should follow the directory structure from the root namespace - eg. {{c|BluePrism.Core.Expressions}} should be in the {{c|Expressions/}} directory inside the {{c|BluePrism.Core}} directory.
** Not unlike the 'removing spaces' above, I would like to re-organise our code, ''especially'' the Automate project, such that it follows this standard. But that's not a small task and it needs separate planning / discussion.
* The general aim (from the naming guidelines) is:
<Company>.(<Product>|<Technology>)[.<Feature>][.<Subnamespace>]
 
== Namespace level elements (class, struct, interface, enum, module) ==
* Pascal Case
* No 'type' prefixes (a personal bugbear of mine with our code) except for interfaces (Nnnngh! See below)
* If appropriate, ''suffix'' with a type - ''eg.'' {{c|UserDetails'''Form'''}}, {{c|Image'''Button'''}}, {{c|NameChanged'''EventArgs'''}}
 
== Interfaces ==
* Begin with a capital I. Ick. Holdover from COM, but that is the .NET standard, so we do the least surprising thing and follow it.
 
== Type Members (methods, properties, inner classes, events) ==
* Pascal Case
 
=== Methods ===
* Typically should be verbs or verb phrases (eg. {{c|CompareTo}}, {{c|Split}}, {{c|GetHashCode}}
* Shouldn't have properties which match the name of 'Get' or 'Set' methods in the type, eg.
** {{c|public string TextWriter { get; } }}
** {{c|public string GetTextWriter() {...} }}
 
=== Properties ===
* Start with a noun -
 
==== Capitalization ====
 
 
====  Member variables: ====
* Start with an underscore followed by camel case - {{c|_xxXxxXxx}}
* Start with "m_" followed by camel case - {{c|m_xxxXxxx}}
* Start with "m" followed by Pascal case - {{c|mXxxxXxxx}}
* Simple camel case name - {{c|xxxXxx}} - distinguish when ambiguous using a {{c|this.xxxXxx}} or {{c|Me.xxxXxxx}}
* Different for VB / C#?
* No convention, just do what you want.
Discuss.
 
==== Classes, Structures, Enums ====
Starting with prefix indicating broad 'type' of element:
* Control - {{c|ctlXxxXxx}}
* Form - {{c|frmXxxXxx}}
* Module - {{c|modXxxXxx}}
* "Class" - {{c|clsXxxXxx}}
 
Yeah, this is a relic of VB6 which I would like to burn - I've never liked it. "Control" and "Form" are classes, what about Enums? Structures? I prefer, from the [https://msdn.microsoft.com/en-us/library/ms229045.aspx Microsoft naming guide]:
{{quote|
* DO choose easily readable identifier names.
For example, a property named {{c|HorizontalAlignment}} is more English-readable than {{c|AlignmentHorizontal}}.
* DO favor readability over brevity.
The property name {{c|CanScrollHorizontally}} is better than {{c|ScrollableX}} (an obscure reference to the X-axis).
}}
 
So, for me - ''suffix'' with the broad type of element where appropriate, so that it's easily readable as English(ish) eg:
* {{c|HelpButtonForm}}
* {{c|HighlighterWindow}}
* {{c|RowBasedDataGridView}}
* {{c|EventFiringDictionary}}
* {{c|BackgroundThreadScheduler}}
* {{c|OperationCompletedEventArgs}}
* {{c|NoSuchQueueException}}
 
 
----
=== Style ===
Taken mostly
* Code to 86 characters. Which seems arbitrary because, as far as I can tell, it is.
 
==== Regions ====
Regions are a neat way of structuring a large source file, so that it's clear which section of the code that something is in.
We have multiple 'region strategies' employed in our code
; No regions at all
: For small classes (<4 pages), regions may just add noise without appreciable gain.
; Region '''all''' the things
: Every element has a region - each method, then a group of methods into some grouping. Thankfully not used too much.
; Add regions by functional area
: "Security Methods", "Xml Handling", "Display Functionality", etc. This works, up to a point, but then you have something which fits in 2 or more of the arbitrary groupings and you have to guess which one the original developer settled on, or whether they weren't sure so they dropped it in the inevitable "General" region - and, suddenly, regions inhibit readability rather than enhance it.
; Add regions by type
: My preference - group together "things of the same type", ie.
:* "Class-scope Declarations" - ie. inner classes, enums, constants, static declarations
:* "Member Variables" - instance members
:* "Auto-properties" - Automatic Properties - ie. properties with implicit get/set definitions
:* "Constructors" - um....
:* "Properties" - Any properties with explicit get/set definitions
:* "Methods"
: I sometimes split the methods into "Event Handling Methods" and "Other Methods"
: But there's no ambiguity about where something should go - an element fits into exactly one region, and it means that all code within a class ends up in a region, for neatness.
 
On a not-unrelated note,
 
 
----
 
 
=== Design Principles ===
 
==== Exceptions ====
* Create reasonably specific exceptions for specific purposes, or use one of the medium-level exceptions available in the core libraries, eg. {{c|NoSuchElementException}} or {{c|PermissionException}}.
* Specifically, don't use the vague {{c|ApplicationException}}; from the [https://msdn.microsoft.com/en-us/library/system.applicationexception%28v=vs.100%29.aspx MSDN ApplicationException page]:
{{q|
If you are designing an application that needs to create its own exceptions, you are advised to derive custom exceptions from the Exception class. It was originally thought that custom exceptions should derive from the ApplicationException class; however in practice this has not been found to add significant value. For more information, see [https://msdn.microsoft.com/en-us/library/seyhszts(v{{=}}vs.100).aspx Best Practices for Handling Exceptions].
}}
 
==== Properties ====
Although properties are technically very similar to methods, they are quite different in terms of their usage scenarios. They should be seen as smart fields. They have the calling syntax of fields, and the flexibility of methods.
 
✓ DO create get-only properties if the caller should not be able to change the value of the property.


=== Visual Basic ===
Keep in mind that if the type of the property is a mutable reference type, the property value can be changed even if the property is get-only.
This is largely cribbed from [https://msdn.microsoft.com/en-us/library/h63fsef3.aspx Visual Basic Coding Conventions]


Microsoft develops samples and documentation that follow the guidelines in this topic. If you follow the same coding conventions, you may gain the following benefits:
X DO NOT provide set-only properties or properties with the setter having broader accessibility than the getter.
* Your code will have a consistent look, so that readers can better focus on content, not layout.
* Readers understand your code more quickly because they can make assumptions based on previous experience.
* You can copy, change, and maintain the code more easily.
* You help ensure that your code demonstrates "best practices" for Visual Basic.


==== Naming Conventions ====
For example, do not use properties with a public setter and a protected getter.
* For information about naming guidelines, see [https://msdn.microsoft.com/en-us/library/ms229002.aspx Naming Guidelines] topic.
* Do not use "My" or "my" as part of a variable name. This practice creates confusion with the My objects.
* You do not have to change the names of objects in auto-generated code to make them fit the guidelines.


==== Layout Conventions ====
If the property getter cannot be provided, implement the functionality as a method instead. Consider starting the method name with Set and follow with what you would have named the property. For example, AppDomain has a method called SetCachePath instead of having a set-only property called CachePath.
* Insert tabs as spaces, and use smart indenting with four-space indents.
*  Pretty listing (reformatting) of code to reformat your code in the code editor. For more information, see Options, Text Editor, Basic (Visual Basic).
* Use only one statement per line. Don't use the Visual Basic line separator character (:).
* Avoid using the explicit line continuation character "_" in favor of implicit line continuation wherever the language allows it.
* Use only one declaration per line.
* If Pretty listing (reformatting) of code doesn't format continuation lines automatically, manually indent continuation lines one tab stop. However, always left-align items in a list.
a As Integer,
b As Integer
* Add at least one blank line between method and property definitions.


==== Commenting Conventions ====
✓ DO provide sensible default values for all properties, ensuring that the defaults do not result in a security hole or terribly inefficient code.
* Put comments on a separate line instead of at the end of a line of code.
* Start comment text with an uppercase letter, and end comment text with a period.
* Insert one space between the comment delimiter (') and the comment text.
' Here is a comment.
* Do not surround comments with formatted blocks of asterisks.


==== Program Structure ====
✓ DO allow properties to be set in any order even if this results in a temporary invalid state of the object.
* When you use the Main method, use the default construct for new console applications, and use My for command-line arguments.
Sub Main()
  For Each argument As String In My.Application.CommandLineArgs
    ' Add code here to use the string variable.
  Next
End Sub


==== Language Guidelines ====
It is common for two or more properties to be interrelated to a point where some values of one property might be invalid given the values of other properties on the same object. In such cases, exceptions resulting from the invalid state should be postponed until the interrelated properties are actually used together by the object.
===== String Data Type =====
* To concatenate strings, use an ampersand (&).
MsgBox("hello" & vbCrLf & "goodbye")
* To append strings in loops, use the StringBuilder object.
Dim longString As New System.Text.StringBuilder
For count As Integer = 1 To 1000
  longString.Append(count)
Next


===== Relaxed Delegates in Event Handlers =====
✓ DO preserve the previous value if a property setter throws an exception.
Do not explicitly qualify the arguments (Object and EventArgs) to event handlers. If you are not using the event arguments that are passed to an event (for example, sender as Object, e as EventArgs), use relaxed delegates, and leave out the event arguments in your code:
Public Sub Form1_Load() Handles Form1.Load
End Sub


===== Unsigned Data Type =====
X AVOID throwing exceptions from property getters.
* Use Integer rather than unsigned types, except where they are necessary. (?!)


===== Arrays =====
Property getters should be simple operations and should not have any preconditions. If a getter can throw an exception, it should probably be redesigned to be a method. Notice that this rule does not apply to indexers, where we do expect exceptions as a result of validating the arguments.
* Use the short syntax when you initialize arrays on the declaration line. For example, use the following syntax.
Dim letters1 As String() = {"a", "b", "c"}
:Do not use the following syntax.
Dim letters2() As String = New String() {"a", "b", "c"}
* Put the array designator on the type, not on the variable. For example, use the following syntax:
Dim letters4 As String() = {"a", "b", "c"}
:Do not use the following syntax:
Dim letters3() As String = {"a", "b", "c"}
* Use the { } syntax when you declare and initialize arrays of basic data types. For example, use the following syntax:
Dim letters5() As String = {"a", "b", "c"}
:Do not use the following syntax:
Dim letters6(2) As String
letters6(0) = "a"
letters6(1) = "b"
letters6(2) = "c"


===== Use the With Keyword =====
* When you make a series of calls to one object, consider using the With keyword:
With orderLog
  .Log = "Application"
  .Source = "Application Name"
  .MachineName = "Computer Name"
End With


===== Use the Try...Catch and Using Statements when you use Exception Handling =====
* Do not use {{c|On Error Goto}}.


===== Use the IsNot Keyword =====
* Use the IsNot keyword instead of Not...Is Nothing.


===== New Keyword =====
* Use short instantiation. For example, use the following syntax:
Dim employees As New List(Of String)
: The preceding line is equivalent to this:
Dim employees2 As List(Of String) = New List(Of String)
* Use object initializers for new objects instead of the parameterless constructor:
Dim orderLog As New EventLog With {
    .Log = "Application",
    .Source = "Application Name",
    .MachineName = "Computer Name"}


===== Event Handling =====
* Use Handles rather than AddHandler:
Private Sub ToolStripMenuItem1_Click() Handles ToolStripMenuItem1.Click
End Sub
* Use AddressOf, and do not instantiate the delegate explicitly:
Dim closeItem As New ToolStripMenuItem(
    "Close", Nothing, AddressOf ToolStripMenuItem1_Click)
Me.MainMenuStrip.Items.Add(closeItem)
* When you define an event, use the short syntax, and let the compiler define the delegate:
Public Event SampleEvent As EventHandler(Of SampleEventArgs)
' or
Public Event SampleEvent(ByVal source As Object,
                          ByVal e As SampleEventArgs)
* Do not verify whether an event is Nothing (null) before you call the RaiseEvent method. RaiseEvent checks for Nothing before it raises the event.


===== Using Shared Members =====
* Call Shared members by using the class name, not from an instance variable.


===== Use XML Literals =====
XML literals simplify the most common tasks that you encounter when you work with XML (for example, load, query, and transform). When you develop with XML, follow these guidelines:
* Use XML literals to create XML documents and fragments instead of calling XML APIs directly.
* Import XML namespaces at the file or project level to take advantage of the performance optimizations for XML literals.
* Use the XML axis properties to access elements and attributes in an XML document.
* Use embedded expressions to include values and to create XML from existing values instead of using API calls such as the {{c|Add}} method:
Private Function GetHtmlDocument(
  ByVal items As IEnumerable(Of XElement)) As String
  Dim htmlDoc = <html>
                  <body>
                    &lt;table border="0" cellspacing="2">
                      <%=
                        From item In items
                        Select <tr>
                                  <td style="width:480">
                                    <%= item.<title>.Value %>
                                  </td>
                                  <td><%= item.<pubDate>.Value %></td>
                                </tr>
                      %>
                    &lt;/table>
                  </body>
                </html>
  Return htmlDoc.ToString()
End Function


===== LINQ Queries =====
== Python ==
* Use meaningful names for query variables:
Code should conform to [http://www.python.org/dev/peps/pep-0008/ PEP8], apparently. (Taken from [[Coding Standards#Python]].)
Dim seattleCustomers = From cust In customers
                        Where cust.City = "Seattle"
* Provide names for elements in a query to make sure that property names of anonymous types are correctly capitalized using Pascal casing:
Dim customerOrders = From customer In customers
                      Join order In orders
                        On customer.CustomerID Equals order.CustomerID
                      Select Customer = customer, Order = order
* Rename properties when the property names in the result would be ambiguous. For example, if your query returns a customer name and an order ID, rename them instead of leaving them as Name and ID in the result:
Dim customerOrders2 = From cust In customers
                      Join ord In orders
                        On cust.CustomerID Equals ord.CustomerID
                      Select CustomerName = cust.Name,
                              OrderID = ord.ID
* Use type inference in the declaration of query variables and range variables:
Dim customerList = From cust In customers
* Align query clauses under the From statement:
Dim newyorkCustomers = From cust In customers
                        Where cust.City = "New York"
                        Select cust.LastName, cust.CompanyName
* Use Where clauses before other query clauses so that later query clauses operate on the filtered set of data:
Dim newyorkCustomers2 = From cust In customers
                        Where cust.City = "New York"
                        Order By cust.LastName
* Use the Join clause to explicitly define a join operation instead of using the Where clause to implicitly define a join operation:
Dim customerList2 = From cust In customers
                    Join order In orders
                      On cust.CustomerID Equals order.CustomerID
                    Select cust, order

Revision as of 14:13, 8 September 2016

Work In Progress

Coding Standards Take 2

Note to self Things I want to cover in this:

  • VB standards (global)
  • C# standards (global)
  • General standards (ours)
  • SQL naming standards
  • SQL code conventions? .NET/SQL conventions?
  • Suggestions from me.
  • Git commit standards

Overview

It has become apparent that there is some disagreement over whether we follow any sort of coding standard at all. I submit that we do, but it is at a very high level, not a prescriptive set of 'commandments' that all code should follow - and I would like to keep it like that, with only functionally dangerous conventions being forbidden rather than stuff that one or two developers don't like the look of.

In general, coding standards exist so that it's one less barrier for a programmer skilled in the language to have to deal with when approaching a new project, so I think we should try and use the general standards and good practices that are largely agreed on within the larger programming community.

As such, I think the best place to start is the Microsoft coding conventions - they are quite liberal, and are detailed in the pages:

I haven't really gone into it in detail, but it might also be worth looking at:

We also have some coding standards, written mostly before my time (2009), which are some more restrictive and, possibly as a result, are largely not followed. These are on the wiki, currently at [Coding Standards]; it may be moved to another page as our current set of standards is promoted - if so, I'll update this reference.

I'm going to try and pull together a few different references here, namely:

  • Microsoft's conventions
  • Our conventions
  • My own preferences

We can then argue about them at wholly unnecessary length and hopefully we'll have something that we can all agree with (or at least compromise on) at the end of it.

I was effectively copying all standards that I found into this page, but that ended up seeming pointless (plus there was quite a bit of stuff which was just not relevant to us), so I'm going to list some standards

General

File and path names

  • Generally, folder and file names should not contain characters other alphanumeric ([A-Za-z0-9]), hyphen, dot.
    • An exception to this might be user-orientated documentation - eg. a user guide maintained by us - which might contain space characters

Note: I'd like to go through our code at the end of a release and remove all the spaces from our folder names. They're really painful.

Tabs vs Spaces

There's no 'correct' answer - people have preferences, but consistency is important. Microsoft's Visual Basic Coding Conventions suggests:

Insert tabs as spaces, and use smart indenting with four-space indents.

Spaces seem to be the more widely accepted choice in style guides I've found online, but it seems that most of our code leans towards tabs. Whichever we choose, we should apply it accorss the board for all languages and all dev output (eg. HTML, XML, JSON, C#, VB, C++, Python, CSS, Javascript, anything else).

Incidentally, I quite like the Elastic Tabstops idea, but that has somewhat limited implementation.

Code organisation

Where do I start?

Our code organisation is all over the place - especially the Automate project. We should try and agree how it should be organised and then figure out how we can get it there. Some ideas:

  • Directories should follow namespaces - eg. BluePrism.Core.Expressions should be in the Expressions/ directory inside the root BluePrism.Core directory.
  • Some of our directories are in subdirectories beneath the automate root, some are directly in that root; each project should have its folder directly in the automate root - ie. not in Automate-3.0, ApplicationManager.
    • ...or... should we have a subfolder inside automate for the product code ("Product"? "Main"?) - separating each project from each other is unhelpful, but separating our core product from Login Agent, BPJabInstaller, Release, etc. seems sensible.

.Net Code

There's a general set of guidelines at Microsoft's Framework Design Guidelines. I did start to transcribe them here, but it might be better if we just go through them and collect the ones that we want to adopt.

Commenting

  • Non-private members should be XML-documented
  • XML-documentation is not necessary for private member variables
  • Though I think properties, methods, inner classes et al should still be XML-documented.

Naming

Micrsoft has a huge naming section in its design guidelines - see the Naming Guidelines. I'll be referring to this from time to time below.

Note: I've used Microsoft's convention of 'camel case', starting with a lowercase letter and 'Pascal case' starting with an uppercase letter, eg.

  • PascalCase
  • camelCase

Namespaces

  • Pascal Case
  • Should start with "BluePrism" (from the naming guidelines: DO prefix namespace names with a company name to prevent namespaces from different companies from having the same name)
  • Should not be the same name as a type inside that namespace
  • Filenames should follow the directory structure from the root namespace - eg. BluePrism.Core.Expressions should be in the Expressions/ directory inside the BluePrism.Core directory.
    • Not unlike the 'removing spaces' above, I would like to re-organise our code, especially the Automate project, such that it follows this standard. But that's not a small task and it needs separate planning / discussion.
  • The general aim (from the naming guidelines) is:
<Company>.(<Product>|<Technology>)[.<Feature>][.<Subnamespace>]

Namespace level elements (class, struct, interface, enum, module)

  • Pascal Case
  • No 'type' prefixes (a personal bugbear of mine with our code) except for interfaces (Nnnngh! See below)
  • If appropriate, suffix with a type - eg. UserDetailsForm, ImageButton, NameChangedEventArgs

Interfaces

  • Begin with a capital I. Ick. Holdover from COM, but that is the .NET standard, so we do the least surprising thing and follow it.

Type Members (methods, properties, inner classes, events)

  • Pascal Case

Methods

  • Typically should be verbs or verb phrases (eg. CompareTo, Split, GetHashCode
  • Shouldn't have properties which match the name of 'Get' or 'Set' methods in the type, eg.
    • public string TextWriter { get; }
    • public string GetTextWriter() {...}

Properties

  • Start with a noun -

Capitalization

Member variables:

  • Start with an underscore followed by camel case - _xxXxxXxx
  • Start with "m_" followed by camel case - m_xxxXxxx
  • Start with "m" followed by Pascal case - mXxxxXxxx
  • Simple camel case name - xxxXxx - distinguish when ambiguous using a this.xxxXxx or Me.xxxXxxx
  • Different for VB / C#?
  • No convention, just do what you want.

Discuss.

Classes, Structures, Enums

Starting with prefix indicating broad 'type' of element:

  • Control - ctlXxxXxx
  • Form - frmXxxXxx
  • Module - modXxxXxx
  • "Class" - clsXxxXxx

Yeah, this is a relic of VB6 which I would like to burn - I've never liked it. "Control" and "Form" are classes, what about Enums? Structures? I prefer, from the Microsoft naming guide:

  • DO choose easily readable identifier names.

For example, a property named HorizontalAlignment is more English-readable than AlignmentHorizontal.

  • DO favor readability over brevity.

The property name CanScrollHorizontally is better than ScrollableX (an obscure reference to the X-axis).

So, for me - suffix with the broad type of element where appropriate, so that it's easily readable as English(ish) eg:

  • HelpButtonForm
  • HighlighterWindow
  • RowBasedDataGridView
  • EventFiringDictionary
  • BackgroundThreadScheduler
  • OperationCompletedEventArgs
  • NoSuchQueueException



Style

Taken mostly

  • Code to 86 characters. Which seems arbitrary because, as far as I can tell, it is.

Regions

Regions are a neat way of structuring a large source file, so that it's clear which section of the code that something is in. We have multiple 'region strategies' employed in our code

No regions at all
For small classes (<4 pages), regions may just add noise without appreciable gain.
Region all the things
Every element has a region - each method, then a group of methods into some grouping. Thankfully not used too much.
Add regions by functional area
"Security Methods", "Xml Handling", "Display Functionality", etc. This works, up to a point, but then you have something which fits in 2 or more of the arbitrary groupings and you have to guess which one the original developer settled on, or whether they weren't sure so they dropped it in the inevitable "General" region - and, suddenly, regions inhibit readability rather than enhance it.
Add regions by type
My preference - group together "things of the same type", ie.
  • "Class-scope Declarations" - ie. inner classes, enums, constants, static declarations
  • "Member Variables" - instance members
  • "Auto-properties" - Automatic Properties - ie. properties with implicit get/set definitions
  • "Constructors" - um....
  • "Properties" - Any properties with explicit get/set definitions
  • "Methods"
I sometimes split the methods into "Event Handling Methods" and "Other Methods"
But there's no ambiguity about where something should go - an element fits into exactly one region, and it means that all code within a class ends up in a region, for neatness.

On a not-unrelated note,




Design Principles

Exceptions

  • Create reasonably specific exceptions for specific purposes, or use one of the medium-level exceptions available in the core libraries, eg. NoSuchElementException or PermissionException.
  • Specifically, don't use the vague ApplicationException; from the MSDN ApplicationException page:

If you are designing an application that needs to create its own exceptions, you are advised to derive custom exceptions from the Exception class. It was originally thought that custom exceptions should derive from the ApplicationException class; however in practice this has not been found to add significant value. For more information, see Best Practices for Handling Exceptions.

Properties

Although properties are technically very similar to methods, they are quite different in terms of their usage scenarios. They should be seen as smart fields. They have the calling syntax of fields, and the flexibility of methods.

✓ DO create get-only properties if the caller should not be able to change the value of the property.

Keep in mind that if the type of the property is a mutable reference type, the property value can be changed even if the property is get-only.

X DO NOT provide set-only properties or properties with the setter having broader accessibility than the getter.

For example, do not use properties with a public setter and a protected getter.

If the property getter cannot be provided, implement the functionality as a method instead. Consider starting the method name with Set and follow with what you would have named the property. For example, AppDomain has a method called SetCachePath instead of having a set-only property called CachePath.

✓ DO provide sensible default values for all properties, ensuring that the defaults do not result in a security hole or terribly inefficient code.

✓ DO allow properties to be set in any order even if this results in a temporary invalid state of the object.

It is common for two or more properties to be interrelated to a point where some values of one property might be invalid given the values of other properties on the same object. In such cases, exceptions resulting from the invalid state should be postponed until the interrelated properties are actually used together by the object.

✓ DO preserve the previous value if a property setter throws an exception.

X AVOID throwing exceptions from property getters.

Property getters should be simple operations and should not have any preconditions. If a getter can throw an exception, it should probably be redesigned to be a method. Notice that this rule does not apply to indexers, where we do expect exceptions as a result of validating the arguments.





Python

Code should conform to PEP8, apparently. (Taken from Coding Standards#Python.)