.NET Usage Guidelines

 
Chapter 6 - Programming in the .NET Environment
bySimon Robinsonet al.
Wrox Press 2002
  

In this final section of this .NET Programming chapter we're going to look at the guidelines Microsoft has written for .NET programming.

In any development language there usually arise certain traditional programming styles. The styles are not part of the language itself but are conventions concerning, for example, how variables are named or how certain classes, methods , or functions are used. If most developers using that language follow the same conventions, it makes it easier for different developers to understand each other's code - which in turn generally helps program maintainability. For example, a common (though not universal) convention in Visual Basic 6 was that variables that represents strings have names beginning with lowercase s or lowercase str , as in sResult As String or strMessage As String . Conventions do, however, depend on the language and the environment. For example, C++ developers programming on the Windows platform have traditionally used the prefixes psz or lpsz to indicate strings: char *pszResult; char *lpszMessage;, but on Unix machines it's more common not to use any such prefixes: char *Result; char *Message; .

You'll have gathered from the sample code in this book that the convention in C# is to name variables without prefixes: string Result; string Message; .

Incidentally, the convention by which variable names are prefixed with letters that represent the data type is known as Hungarian notation . It means that other developers reading the code can immediately tell from the variable name what data type the variable represents.

Whereas, with many languages, usage conventions simply evolved as the language was used, with C# and the whole of the .NET Framework Microsoft has written very comprehensive usage guidelines, which are detailed in the .NET/C# MSDN documentation. This should mean that, right from the start, .NET programs will have a high degree of interoperability in terms of developers being able to understand code. The guidelines have also been developed with the benefit of some twenty years hindsight in object-oriented programming, and as a result, have been carefully thought out and appear to have been well received in the developer community to judge by the relevant newsgroups. Hence the guidelines are well worth following.

It should be noted, however, that the guidelines are not the same as language specifications. You should try to follow the guidelines when you can. Nevertheless, if you do have a good reason for not doing so then that's no problem. The general rule is that if you don't follow the usage guidelines you must have a convincing reason. Departing from the guidelines should be a positive decision rather than simply not bothering. Also, as you read the guidelines, you'll notice that in numerous examples in this book, we have chosen not to follow the conventions, usually because the conventions are designed for much larger programs than our samples, and while they are great if you are writing a complete software package, they are not really so suitable for small 20-line standalone programs. In many cases following the conventions would have made our samples harder rather than easier to follow.

The full guidelines for good programming style are quite extensive . Here we will confine ourselves to describing some of the more important guidelines, as well as the ones most likely to catch you out. If you want to make absolutely certain your code follows the usage guidelines completely, then you will need to refer to the MSDN documentation.

Naming Conventions

One important aspect to making your programs understandable is how you choose to name your items - and that includes naming variables, methods, classes, enumerations, and namespaces.

It is intuitively obvious that your names should reflect the purpose of the item, and should be designed not to clash with other names. The general philosophy in the .NET Framework is also that the name of a variable should reflect the purpose of that variable instance and not the data type. For example, Height is a good name for a variable, while IntegerValue isn't. However, you will probably feel that that principle is an ideal that is hard to achieve. Particularly when you are dealing with controls, in most cases, you'll probably feel happier sticking with variable names like ConfirmationDialog and ChooseEmployeeListBox .

Let's look at some of the things you need to think about when choosing names.

Casing of Names

In almost all cases you should use Pascal casing for names. Pascal casing means that the first letter of each word in a name is capitalized: EmployeeSalary , ConfirmationDialog , PlainTextEncoding . You will notice that essentially all of the names of namespaces, classes, and members in the base classes follow Pascal casing. In particular, the convention of joining words using the underscore character is discouraged. So you should try not to write names like employee_salary . It has also been common in other languages to use all-capitals for names of constants. This is not advised in C#, since such names are harder to read - the convention is to use Pascal casing throughout:

   const int MaximumLength;   

The only other casing scheme that you are advised to use is camel casing . Camel casing is similar to Pascal casing, except that the first letter of the first word in the name is not capitalized: employeeSalary , confirmationDialog , plainTextEncoding . There are two situations in which you are advised to use camel casing:

  • Names of all parameters passed to methods should be camel-cased: public void RecordSale(string salesmanName, int quantity);

  • You should also use camel casing in order to distinguish between two items that would otherwise have the same name - a common case is when a property wraps around a field: private string employeeName; public string EmployeeName { get { return employeeName; } }

The above code is regarded by the guidelines as perfectly acceptable. Note, however, that if you are doing this, you should always use camel casing for the private member and Pascal casing for the public or protected member, so that other classes that use your code see only Pascal-cased names (except for parameter names).

You should also be wary about case-sensitivity . C# is case sensitive, so it is quite legal syntactically for names in C# to differ only by the case, as in the above examples. However, you should bear in mind that your assemblies might at some point be called from VB.NET applications - and VB.NET is not case sensitive . Hence, if you do use names that differ only by a case, it is important to do so only in situations in which both names will never be seen outside your assembly. (The above example qualifies as OK because the camel-cased name is attached to a private variable.) Otherwise you may prevent other code written in VB.NET from being able to use your assembly correctly.

Name Styles

You should try to be consistent about your style of names. For example, if one of the methods in a class is called ShowConfirmationDialog() , then you should not give another method a name like ShowDialogWarning() , or WarningDialogShow() . The other method should be called ShowWarningDialog() . Get the idea?

Namespace Names

Namespace names are particularly important to design carefully in order to the avoid risk of ending up with the same name for one of your namespaces as someone else uses. Remember, namespace names are the only way that .NET distinguishes names of objects in shared assemblies. So if you use the same namespace name for your software package as another package, and both packages get installed on the same computer, there are going to be problems. Because of this, it's almost always a good idea to create a top-level namespace with the name of your company, and then nest successive namespaces that narrow down the technology, group , or department you are working in or the name of the package your classes are intended for. Microsoft recommends namespace names that begin < CompanyName > . < TechnologyName >, for example WeaponsOfDestructionCorp.RayGunControllers , or WeaponsOfDestructionCorp.Viruses .

Names and Keywords

It is important the names should not clash with any keywords. In fact, if you attempt to name an item in your code with a word that happens to be a C# keyword, you'll almost certainly get a syntax error because the compiler will assume the name refers to a statement. However, because of the possibility that your classes will be accessed by code written in other languages, it is important that you don't use names that are keywords in other .NET languages. Generally speaking, C++ keywords are similar to C# keywords, so confusion with C++ is unlikely , and those commonly encountered keywords that are unique to Visual C++ tend to start with two underscore characters . Like C#, C++ keywords are spelled in lowercase, so if you hold to the convention of naming your public classes and members with Pascal-style names, then they will always have at least one uppercase letter in their names, and there will be no risk of clashes with C++ keywords. On the other hand, you are more likely to have problems with VB.NET, which has many more keywords than C# does, and being non-case sensitive means you cannot rely on Pascal-style names for your classes and methods.

The following table lists the keywords and standard function calls in VB.NET, which should not be used, in whatever case combination, for your public C# classes.

Abs

Do

Loc

RGB

Add

Double

Local

Right

AddHandler

Each

Lock

RmDir

AddressOf

Else

LOF

Rnd

Alias

ElseIf

Log

RTrim

And

Empty

Long

SaveSettings

Ansi

End

Loop

Second

AppActivate

Enum

LTrim

Seek

Append

EOF

Me

Select

As

Erase

Mid

SetAttr

Asc

Err

Minute

SetException

Assembly

Error

MIRR

Shared

Atan

Event

MkDir

Shell

Auto

Exit

Module

Short

Beep

Exp

Month

Sign

Binary

Explicit

MustInherit

Sin

BitAnd

ExternalSource

MustOverride

Single

BitNot

False

MyBase

SLN

BitOr

FileAttr

MyClass

Space

BitXor

FileCopy

Namespace

Spc

Boolean

FileDateTime

New

Split

ByRef

FileLen

Next

Sqrt

Byte

Filter

Not

Static

ByVal

Finally

Nothing

Step

Call

Fix

NotInheritable

Stop

Case

For

NotOverridable

Str

Catch

Format

Now

StrComp

CBool

FreeFile

NPer

StrConv

CByte

Friend

NPV

Strict

CDate

Function

Null

String

CDbl

FV

Object

Structure

CDec

Get

Oct

Sub

ChDir

GetAllSettings

Off

Switch

ChDrive

GetAttr

On

SYD

Choose

GetException

Open

SyncLock

Chr

GetObject

Option

Tab

CInt

GetSetting

Optional

Tan

Class

GetType

Or

Text

Clear

GoTo

Overloads

Then

CLng

Handles

Overridable

Throw

Close

Hex

Overrides

TimeOfDay

Collection

Hour

ParamArray

Timer

Command

If

Pmt

TimeSerial

Compare

IIf

PPmt

TimeValue

Const

Implements

Preserve

To

Cos

Imports

Print

Today

CreateObject

In

Private

Trim

CShort

Inherits

Property

Try

CSng

Input

Public

TypeName

CStr

InStr

Put

TypeOf

CurDir

Int

PV

UBound

Date

Integer

QBColor

UCase

DateAdd

Interface

Raise

Unicode

DateDiff

IPmt

RaiseEvent

Unlock

DatePart

IRR

Randomize

Until

DateSerial

Is

Rate

Val

DateValue

IsArray

Read

Weekday

Day

IsDate

ReadOnly

While

DDB

IsDbNull

ReDim

Width

Decimal

IsNumeric

Remove

With

Declare

Item

RemoveHandler

WithEvents

Default

Kill

Rename

Write

Delegate

LCase

Replace

WriteOnly

DeleteSetting

Left

Reset

Xor

Dim

Lib

Resume

Year

Dir

Line

Return

 

Use of Properties and Methods

One area that can cause confusion in a class is whether a particular quantity should be represented by a property or a method. The rules here are not hard and fast, but in general, you ought to use a property if something really should look and feel like a variable. This means, among other things, that:

  • Client code should be able to read its value. Write-only properties are not recommended, so for example use a SetPassword( ) method not a write-only Password property.

  • Reading the value should not take too long. The fact that something is a property usually suggests that reading it will be relatively quick.

  • Reading the value should not have any observable and unexpected side effect; for example, setting the value of a property will not have any side effect that is not directly related to the property. Setting the width of a dialog box has the obvious effect of changing the appearance of the dialog box on the screen. That's fine, as that's obviously related to the property in question.

  • It should be possible to set properties in any order. In particular, it is not good practice when setting a property to throw an exception because another related property has not yet been set. For example, if in order to use a class that accesses a database you need to set ConnectionString , UserName , and Password , make sure the class is implemented so the user really can set them in any order.

  • Successive reads of a property should give the same result. If the value of a property is likely to change unpredictably, then you should code it up as a method instead. Speed , in a class that monitors the motion of an automobile, is not a good candidate for a property. Use a GetSpeed() method here; on the other hand, Weight and EngineSize are good candidates for properties as they will not change for a given object.

If the item you are coding up satisfies all of the above criteria, then it is probably a good candidate for a property. Otherwise you should use a method.

Use of Fields

The guidelines are pretty simple here. Fields should almost always be private, except that in some cases it may be acceptable for constant or read-only fields to be public. The reason is that if you make a field public, you may hinder your ability to extend or modify the class in the future.

The above guidelines should give you a rough idea of good practices, and you should also use them in conjunction with good object-oriented programming style.

It's also worth bearing in mind that Microsoft has been fairly careful about being consistent, and has followed its own guidelines when writing the .NET base classes. So a very good way to get an intuitive feel for the conventions to follow when writing .NET code is to simply look at the base classes - see how classes, members, and namespaces are named, and how the class hierarchy works. If you try to write your code in the same style as the base classes, then you shouldn't go far wrong.

  


Professional C#. 2nd Edition
Performance Consulting: A Practical Guide for HR and Learning Professionals
ISBN: 1576754359
EAN: 2147483647
Year: 2002
Pages: 244

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