Top Banner
Good Programming Practices Good Programming Practices A guide to your “code” A guide to your “code” Prepared by Dinesh Bhat
51

DotNet-Good programming practices

Oct 15, 2014

Download

Documents

Techshankar

sql,server,sqlserver,dotnet,asp.net,csharp
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: DotNet-Good programming practices

Good Programming PracticesGood Programming Practices

A guide to your “code”A guide to your “code”

Prepared by

Dinesh Bhat

This document contrains 41 pages

Page 2: DotNet-Good programming practices

TABLE OF CONTENTS

1 INTRODUCTION.............................................................................................................................................................. 3

2 GUIDELINES .................................................................................................................................................................. 3

2.1 BEST PRACTICES FOR GOOD PROGRAMMING.................................................................................................3

2.1.1 AVOID HAVING TOO LARGE FILES.....................................................................................................................3

2.1.2 AVOID WRITING VERY LONG METHODS...........................................................................................................3

2.1.3 WHITE SPACE........................................................................................................................................................ 3

2.1.4 BLANK SPACES....................................................................................................................................................3

2.1.5 PARENTHESES......................................................................................................................................................4

2.1.6 NAMING GUIDELINES...........................................................................................................................................4

2.1.7 USE EARLY BINDING FOR BETTER PERFORMANCE.....................................................................................14

2.1.8 RETURNING VALUES..........................................................................................................................................14

2.1.9 STATEMENTS......................................................................................................................................................15

2.1.10 METHOD NAME SHOULD TELL WHAT IT DOES............................................................................................18

2.1.11 A METHOD SHOULD DO ONLY 'ONE JOB'.....................................................................................................18

2.1.12 PAY ATTENTION TO INITIALIZATION ORDER................................................................................................19

2.1.13 DO NOT HARDCODE NUMBERS......................................................................................................................19

2.1.14 STRING CONCATENATION..............................................................................................................................20

2.1.15 AVOID USING MANY MEMBER VARIABLES..................................................................................................20

2.1.16 USE ENUM WHEREVER REQUIRED................................................................................................................20

2.1.17 DO NOT MAKE THE MEMBER VARIABLES PUBLIC OR PROTECTED........................................................21

2.1.18 NEVER HARDCODE A PATH OR DRIVE NAME IN CODE..............................................................................21

2.1.19 "SELF CHECK" WHEN THE APPLICATION STARTSUP................................................................................21

2.1.20 ERROR MESSAGES SHOULD HELP THE USER TO SOLVE THE PROBLEM..............................................22

2.1.21 AVOID COMMENTING EVERY LINE OF CODE...............................................................................................22

2.1.22 EXCEPTION HANDLING....................................................................................................................................22

2.1.23 MEMORY MANAGEMENT.................................................................................................................................23

2.1.24 DATA ACCESS...................................................................................................................................................24

2.1.25 SERIALIZATION.................................................................................................................................................25

2.1.26 MULTITHREADING............................................................................................................................................26

2.1.27 REMOTING......................................................................................................................................................... 28

2.1.28 ENTERPRISE SERVICES .................................................................................................................................30

2.1.29 SECURITY.......................................................................................................................................................... 31

2.2 ASP.NET................................................................................................................................................................ 33

2.2.1 DISABLE SESSION STATE WHEN NOT IN USE...............................................................................................33

2.2.2 CHOOSE YOUR SESSION STATE PROVIDER CAREFULLY...........................................................................34

2.2.3 USAGE OF VIEWSTATE......................................................................................................................................34

2.2.4 AVOID EXCESSIVE ROUND TRIPS TO THE SERVER......................................................................................34

2.2.5 USE PAGE.ISPOSTBACK TO AVOID EXTRA WORK ON A ROUND TRIP......................................................34

Page 3: DotNet-Good programming practices

2.2.6 REUSE WORK BY CACHING..............................................................................................................................35

2.2.7 REMOVE CODE FROM CONTENT AS MUCH AS POSSIBLE...........................................................................35

2.2.8 NEW PAGE DIRECTIVES....................................................................................................................................35

2.2.9 USE RESPONSE.WRITE FOR STRING CONCATENATION..............................................................................35

2.2.10 DO NOT FORGET TO DISABLE DEBUG MODE..............................................................................................36

2.2.11 USE SERVER CONTROLS ONLY WHEN APPROPRIATE..............................................................................36

2.2.12 USE THE WEB.CONFIG/MACHINE.CONFIG FILE TO STORE APPLICATION WIDE DATA.........................36

2.2.13 EXCEPTION HANDLING IN ASP.NET...............................................................................................................36

2.3 GENERAL TIPS..................................................................................................................................................... 38

Page 4: DotNet-Good programming practices

Good Programming Practices

1 INTRODUCTION

This document provides coding techniques and programming practices for improving the quality of source code. This can be used as a part of the induction manual when new team members/technical members are introduced to the team. This document highlights some of the best practices for coding in c# language and sets some general guidelines for effective coding.

2 GUIDELINES

2.1 BEST PRACTICES FOR GOOD PROGRAMMING

2.1.1 AVOID HAVING TOO LARGE FILES.

If a file has more than 300~400 lines of code, you must consider refactoring code into helper classes.

2.1.2 AVOID WRITING VERY LONG METHODS.

A method should typically have 1~25 lines of code. If a method has more than 25 lines of code, you must consider re factoring into separate methods.

2.1.3 WHITE SPACE

Blank lines improve readability by setting off sections of code that are logically related.

Two blank lines should always be used between sections of a source file. That is, two blank lines should follow:

the opening comment

the package statement

the import statements

the class and interface declaration

One blank line should always be used in the following circumstances:

Between methods

Between the local variables in a method and its first statement

Before a block or single-line comment.

Between logical sections inside a method to improve readability.

Use common sense and don't be afraid to put blank lines!

2.1.4 BLANK SPACES

Blank spaces should be used in the following circumstances:

A blank space should appear after commas in argument lists.

All binary operators except. Should be separated from their operands by spaces. Blank spaces should never separate unary operators such as unary minus, increment ("++"), and decrement ("--") from their operands.

The expressions in a “for” statement should be separated by blank spaces.

Page 3 of 42

Page 5: DotNet-Good programming practices

Good Programming Practices

example:

2.1.5 PARENTHESES

It is generally a good idea to use parentheses liberally in expressions involving mixed operators to avoid operator precedence problems

2.1.6 NAMING GUIDELINES

A consistent naming pattern is one of the most important elements of predictability and discoverability in a managed class library.

2.1.6.1 Capitalization Styles

Describes the Pascal case, camel case, and uppercase capitalization styles to use to name identifiers in class libraries.

Pascal case

The first letter in the identifier and the first letter of each subsequent concatenated word are capitalized. You can use Pascal case for identifiers of three or more characters.

Example:

Camel case

The first letter of an identifier is lowercase and the first letter of each subsequent concatenated word is capitalized.

Example:

Page 4 of 42

BackColor

backColor

public void aMethod(int a, int b, int c, int d){ a += c + d; a = (a + b) / (c * d);

printSize("size is " + foo);

for(expr1; expr2; expr3) { /* No Body */ }}

if(a == b && c == d) // AVOID!if((a == b) && (c == d)) // RIGHT

Page 6: DotNet-Good programming practices

Good Programming Practices

Uppercase

All letters in the identifier are capitalized. Use this convention only for identifiers that consist of two or fewer letters.

Example:

The following table summarizes the capitalization rules and provides examples for the different types of identifiers:

Identifier Case Example

Class Pascal AppDomain

Enum type Pascal ErrorLevel

Enum values Pascal FatalError

Event Pascal ValueChange

Exception class PascalWebException Note   Always ends with the suffix Exception.

Read-only Static field Pascal RedValue

Interface PascalIDisposable Note   Always begins with the prefix I.

Method Pascal ToString

Namespace Pascal System.Drawing

Parameter Camel typeName

Property Pascal BackColor

Protected instance field Camel

redValue Note   Rarely used. A property is preferable to using a protected instance field.

Public instance field Pascal

RedValue Note   Rarely used. A property is preferable to using a public instance field.

Page 5 of 42

Sysetm.IO

System.Web.UI

Page 7: DotNet-Good programming practices

Good Programming Practices

2.1.6.2 Case Sensitivity

Do not use names that require case sensitivity. Components must be fully usable from both case-sensitive and case-insensitive languages.

Case-insensitive languages cannot distinguish between two names within the same context that differ only by case. Therefore, you must avoid this situation in the components or classes that you create.

Do not create two namespaces with names that differ only by case. For example, a case insensitive language cannot distinguish between the following two namespace declarations.

Do not create a function with parameter names that differ only by case. The following example is incorrect.

Do not create a namespace with type names that differ only by case. In the following example, Point p and POINT p are inappropriate type names because they differ only by case.

Do not create a type with property names that differ only by case. In the following example,int Color and int COLOR are inappropriate property names because they differ only by case.

Do not create a type with method names that differ only by case. In the following example, calculate and Calculate are inappropriate method names because they differ only by case.

Page 6 of 42

namespace ee.cummings;namespace Ee.Cummings;

void MyFunction(string a, string A)

System.Windows.Forms.Point p

System.Windows.Forms.POINT p

int Color {

get, set}

int COLOR {

get, set}

void calculate()

void Calculate()

Page 8: DotNet-Good programming practices

Good Programming Practices

2.1.6.3 Abbreviations

To avoid confusion and guarantee cross-language interoperation, follow these rules regarding the use of abbreviations:

Do not use abbreviations or contractions as parts of identifier names.Example:

Do not use acronyms that are not generally accepted in the computing field.

Where appropriate, use well-known acronyms to replace lengthy phrase names. For example, use UI for User Interface and OLAP for On-line Analytical Processing.

When using acronyms, use Pascal case or camel case for acronyms more than two characters long. For example, use HtmlButton or htmlButton. However, you should capitalize acronyms that consist of only two characters, such as System.IO instead of System.Io.

Do not use abbreviations in identifiers or parameter names. If you must use abbreviations, use camel case for abbreviations that consist of more than two characters, even if this contradicts the standard abbreviation of the word.

2.1.6.4 Namespace Naming Guidelines

You should use Pascal case for namespaces

The general rule for naming namespaces is to use the company name followed by the technology name and optionally the feature and design as follows.

2.1.6.5 Class Naming Guidelines

Use a noun or noun phrase to name a class.

Use Pascal case.

Use abbreviations sparingly.

Page 7 of 42

Good:GetWindow

Not Good:GetWin

CompanyName.TechnologyName[.Feature][.Design]

For example:

Microsoft.Media

Microsoft.Media.Design

Page 9: DotNet-Good programming practices

Good Programming Practices

Do not use a type prefix, such as C for class, on a class name. For example, use the class name

FileStream rather than CFileStream.

Do not use the underscore character (_).

Where appropriate, use a compound word to name a derived class. The second part of the derived class's name should be the name of the base class. Example : ApplicationException

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

2.1.6.6 Interface Naming Guidelines

The following rules outline the naming guidelines for interfaces:

Name interfaces with nouns or noun phrases, or adjectives that describe behaviour.Example:

Use Pascal case.

Use abbreviations sparingly.

Prefix interface names with the letter I, to indicate that the type is an interface.

Page 8 of 42

public class FileStream

public class Button

public class String

IComponent // noun. ICustomAttributeProvider //noun. IPersistable //adjective.

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 )}

}

Page 10: DotNet-Good programming practices

Good Programming Practices

Use similar names when you define a class/interface pair where the class is a standard implementation of the interface. The names should differ only by the letter I prefix on the interface name.

Do not use the underscore character (_).

Always user Interfaces.

Example:The following are examples of correctly named interfaces.

The following code example illustrates how to define the interface IComponent and its standard

implementation, the class Component.

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

Avoid interfaces with one method.

No more than 20 members per interface.

Avoid event as interface members.

Avoid abstract methods, user interfaces instead.

2.1.6.7 Attribute Naming Guidelines

You should always add the suffix Attribute to custom attribute classes.Example:

2.1.6.8 Enumeration Type Naming Guidelines

Page 9 of 42

public interface IServiceProvider

public interface IFormatable

public interface IComponent{

// Implementation goes here.}

public class Component: IComponent { // Implementation code goes here.}

public class ObsoleteAttribute{}

Page 11: DotNet-Good programming practices

Good Programming Practices

The enumeration (Enum) value type inherits from the Enum Class.

o Use Pascal case for Enum types and value names. o Use abbreviations sparingly.

o Do not use an Enum suffix on Enum type names.

o Use a singular name for most Enum types, but use a plural name for Enum types that are bit fields.

o Always add the FlagsAttribute to a bit field Enum type.

Example:

2.1.6.9 Static Field Naming Guidelines

Naming guidelines for static fields:

o Use nouns, noun phrases, or abbreviations of nouns to name static fields.

o Use Pascal case.

o Do not use a Hungarian notation prefix on static field names.

o It is recommended that you use static properties instead of public static fields whenever possible.

Example:

2.1.6.10 Parameter Naming Guidelines

It is important to carefully follow these parameter naming guidelines because visual design tools that provide context sensitive help and class browsing functionality display method parameter names to users in the designer.

Page 10 of 42

Good:public enum Color{

Red, Green, Blue}

Not Good:

Public enum Color{

Red = 1, Green = 2, Blue = 3}

Specifying type for an enum

Not Good:public enum Color : long{

Red, Green, Blue}

public static int Global1 = 100;

public static int Global1 = 200;

Page 12: DotNet-Good programming practices

Good Programming Practices

Use camel case for parameter names.

Use descriptive parameter names. Parameter names should be descriptive enough that the name of the parameter and its type can be used to determine its meaning in most scenarios.

Use names that describe a parameter's meaning rather than names that describe a parameter's type. Development tools should provide meaningful information about a parameter's type. Therefore, a parameter's name can be put to better use by describing meaning. Use type-based parameter names sparingly and only where it is appropriate.

Do not use reserved parameters.

Do not prefix parameter names with Hungarian type notation.

Example: correctly named parameters

2.1.6.11 Method Naming Guidelines

The following rules outline the naming guidelines for methods:

Use verbs or verb phrases to name methods.

Use Pascal case

Examples: Correctly named methods.

2.1.6.12 Property Naming Guidelines

The following rules outline the naming guidelines for properties:

Use a noun or noun phrase to name properties.

Use Pascal case.

Do not use Hungarian notation.

Consider creating a property with the same name as its underlying type.

Example:

Page 11 of 42

Type GetType(string typeName)

string Format(string format, object[] args)

RemoveAll()

GetCharArray()

Invoke()

Good:

1) public class smapleClass{

public color BackColor{

//Code for get and set assessors goes here.}

}

2) Providing a property with the same name as a type.

public enum Color {

// Insert code for Enum here.}public class Control {

public Color Color {

get {// Insert code here.} set {// Insert code here.}

}}

Not Good:public enum Color {

// Insert code for Enum here.}public class Control {

public int Color { get {// Insert code here.} set {// Insert code here.} }

}

This is incorrect because the property Color is of type Integer.

Page 13: DotNet-Good programming practices

Good Programming Practices

2.1.6.13 Event Naming Guidelines

The naming guidelines for events: Use Pascal case.

Do not use Hungarian notation.

Use an EventHandler suffix on event handler names.

Specify two parameters named sender and e.

o The sender parameter represents the object that raised the event. The sender parameter is always of type object.

Page 12 of 42

Page 14: DotNet-Good programming practices

Good Programming Practices

o The state associated with the event is encapsulated in an instance of an event class named e. Use

an appropriate and specific event class for the e parameter type.

Name an event argument class with the EventArgs suffix.

Consider naming events with a verb. For example, correctly named event names include Clicked, Painting, and DroppedDown.

Do not use a prefix or suffix on the event declaration on the type. For example, use Close instead of OnClose.

Example: Illustrates an event handler with an appropriate name and parameters.

Example: Illustrates a correctly named event argument class.

2.1.6.14 Delegate Naming Guidelines

The naming guidelines for events:

Use Pascal case.

Do not use Hungarian notation.

Copy a delegate to local variable before publishing to avoid concurrency race condition.

Always check a delegate for null before invoking it.

Use delegate inference instead of explicit delegate instantiation

Page 13 of 42

public delegate void MouseEventHandler(object sender, MouseEventArgs e);

public class MouseEventArgs : EventArgs { int x; int y;

public MouseEventArgs(int x, int y) { this.x = x; this.y = y;

} public int X { get { return x; } } public int Y { get { return y; } } }

delegate void SomeDegate();

public void SomeMethod(){

//Code goes here.}

SomeDelegate someDelegate = SomeMethod;

Page 15: DotNet-Good programming practices

Good Programming Practices

2.1.7 USE EARLY BINDING FOR BETTER PERFORMANCE

Early Binding provides much better performance than late binding.

Always specify a data type for variables when they are declared. This provides strong typing of variables for best performance.

2.1.8 RETURNING VALUES

Try to make the structure of your program match the intent. Example:

2.1.9 STATEMENTS

2.1.9.1 Simple Statements

Page 14 of 42

if(booleanExpression){ return true;}else{ return false;}

should instead be written as return booleanExpression;

Similarly, if(condition){ return x;}return y;

should be written as return ((condition) ? x : y);

argv++; /* Correct */argc--; /* Correct */argv++; argc--; /* AVOID! */

Good:Early Binding

String[] address = null;

Not Good: Late Binding

Object[] address = null;

Page 16: DotNet-Good programming practices

Good Programming Practices

2.1.9.2 Compound Statements

Compound statements are statements that contain lists of statements enclosed in braces "{ statements }".

The enclosed statements should be indented one more level than the enclosing braces.

The opening brace should be at the beginning of the line that precedes the compound statement; the closing brace should begin a line and be indented to the opening brace.

Braces are used around all statements, even single statements, when they are part of a control structure, such as an if-else or for statement. This makes it easier to add statements without accidentally introducing bugs due to forgetting to add braces.

2.1.9.3 if, if-else, if else-if else Statements

The if-else class of statements should have the following form:

Note: if statements always use braces {}. Avoid the following error-prone form:

Page 15 of 42

if(condition){ statements;}

if(condition){ statements;}else{ statements;}

if(condition){ statements;}else if(condition){ statements;}else{ statements;}

if(condition) /* AVOID! THIS OMITS THE BRACES {}! */statement;

Page 17: DotNet-Good programming practices

Good Programming Practices

2.1.9.4 for Statements

A for statement should have the following form:

An empty for statement (one in which all the work is done in the initialization, condition, and update clauses) should have the following form:

When using the comma operator in the initialization or update clause of a “for” statement, avoid the complexity of using more than three variables.

If needed, use separate statements before the “for” loop (for the initialization clause) or at the end of the loop (for the update clause).

2.1.9.5 while Statements

A while statement should have the following form:

2.1.9.6 do-while Statements

A do-while statement should have the following form:

Page 16 of 42

for(initialization; condition; update){ statements;}

for(initialization; condition; update){ /* No Body */}

while(condition){ statements;}

An empty while statement should have the following form:

while(condition){ /* No Body */}

do{ statements;}while(condition);

Page 18: DotNet-Good programming practices

Good Programming Practices

2.1.9.7 switch Statements

Never use goto unless in a switch statement fall through.

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

A switch statement should have the following form:

2.1.9.8 Using Statement

Works with any IDisposable objectData access classes, streams, text readers and writers, network classes, etc.

Page 17 of 42

switch(condition){ case ABC: statements; /* falls through */

case DEF: statements; break;

case XYZ: statements; break;

default: statements; break;}

Good:using (Resource res = new Resource()) { res.DoWork();}

Not Good:

Resource res = new Resource(...);try { res.DoWork();}finally { if (res != null) ((IDisposable)res).Dispose();}

Page 19: DotNet-Good programming practices

Good Programming Practices

2.1.10 METHOD NAME SHOULD TELL WHAT IT DOES.

Do not use misleading names. If the method name is obvious, there is no need of documentation explaining what the method does.

2.1.11 A METHOD SHOULD DO ONLY 'ONE JOB'.

Do not combine more than one job in a single method, even if those jobs are very small.

Page 18 of 42

Good: void SavePhoneNumber ( string phoneNumber ){// Save the phone number.}

Not Good: // This method will save the phone number.void SaveData ( string phoneNumber ){// Save the phone number.}Good: // Save the address.SaveAddress ( address );

// Send an email to the supervisor to inform that the address is updated.SendEmail ( address, email );

void SaveAddress ( string address ){// Save the address.// ...}

void SendEmail ( string address, string email ){// Send an email to inform the supervisor that the address is changed.// ...}

Not Good: // Save address and send an email to the supervisor to inform that the address is updated.SaveAddress ( address, email );

void SaveAddress ( string address, string email ){// Job 1.// Save the address.// ...

// Job 2.// Send an email to inform the supervisor that the address is changed.// ...}

Page 20: DotNet-Good programming practices

Good Programming Practices

2.1.12 PAY ATTENTION TO INITIALIZATION ORDER

The C# language adds the concept of initializes on member variable declarations

These initializes get executed before the body of the constructor gets executed.

Variable initializes get executed before the base class's constructor gets executed.

Do not initialize variable of base class data; the base class has not yet been constructed.

2.1.13 DO NOT HARDCODE NUMBERS.

Use constants instead.

Page 19 of 42

Good: const int index = 5;

Not Good: int index = 5;

Page 21: DotNet-Good programming practices

Good Programming Practices

2.1.14 STRING CONCATENATION

When building a log string, use StringBuilder, not string. Using StringBuilder instead of string will increase the performance.

Example:

2.1.15 AVOID USING MANY MEMBER VARIABLES.

Declare local variables and pass it to methods instead of sharing a member variable between methods. If you share a member variable between methods, it will be difficult to track which method changed the value and when.

2.1.16 USE ENUM WHEREVER REQUIRED.

Do not use numbers or strings to indicate discrete values.

Page 20 of 42

Good: enum MailType{Html, PlainText}void SendMail (string message, MailType mailType){switch ( mailType ){

case MailType.Html:// Do somethingbreak;

case MailType.PlainText:// Do somethingbreak;

default:// Do somethingbreak;

}}

Not Good: void SendMail (string message, string mailType){switch ( mailType ){

case "Html":// Do somethingbreak;

case "PlainText":// Do somethingbreak;

default:// Do somethingbreak;

}}

For string

Good : StringBuilder address = new StringBuilder(); Address.Append( “Bangalore”); Address.Append( “Delhi”);

Not Good: string address = null; address = “Bangalore”

address += “Delhi”;

Page 22: DotNet-Good programming practices

Good Programming Practices

2.1.17 DO NOT MAKE THE MEMBER VARIABLES PUBLIC OR PROTECTED.

Keep them private and expose public/protected Properties.

2.1.18 NEVER HARDCODE A PATH OR DRIVE NAME IN CODE.

Get the application path programmatically and use relative path.

2.1.19 "SELF CHECK" WHEN THE APPLICATION STARTSUP.

"Self check" and ensure all required files and dependencies are available in the expected locations. Check for database connection in start up, if required. Give a friendly message to the user in case of any problems.

2.1.20 ERROR MESSAGES SHOULD HELP THE USER TO SOLVE THE PROBLEM.

Give specific error messages like

Page 21 of 42

Good:public string CurrentUserName{

Get{ }

Set{ }

}

Not Good:Public string CurrentUser = null;

Good:String FilePath = Application.StartupPath + “\test.txt”;

Not Good:String FilePath = “C:\foldername\test.txt”;

Good:"Failed to update database. Please make sure the login id and password

are correct."

Not Good:"Error in Application", "There is an error" etc.

Page 23: DotNet-Good programming practices

Good Programming Practices

2.1.21 AVOID COMMENTING EVERY LINE OF CODE.

Do not write comments for every line of code and every variable declared. Write comments wherever required.

But good readable code will require very less comments.

If all variables and method names are meaningful, that would make the code very readable and will not need many comments.

Less line of comments will make the code more elegant.

But if the code is not clean/readable and there are less comments, that is worse.

Do spells check on comments and also make sure proper grammar and punctuation is used.

If you have to use some complex or wired logic for any reason, document it very well with sufficient comments.

2.1.22 EXCEPTION HANDLING

The following rules outline the guidelines for raising and handling errors: All code paths that result in an exception should provide a method to check for success without throwing an

exception.

Never do a 'catch exception and do nothing'.

If you hide an exception, you will never know if the exception happened or not.

End Exception class names with the Exception suffix.

Example:

Do not use exceptions for normal or expected errors, or for normal flow of control.

In case of exceptions, give a friendly message to the user, but log the actual error with all possible details about the error, including the time it occurred, method and class name etc. Always catch only the specific exception, not generic exception.

Page 22 of 42

Good: void ReadFromFile ( string fileName ){

try{// read from file.

}catch ( FileIOException ex ){// log error.// re-throw exception depending on your case.throw;

}}

Not Good: void ReadFromFile ( string fileName ){

try{// read from file.

}catch (Exception ex){// Catching general exception is bad... we will never know whether it// was a file error or some other error.

// Here you are hiding an exception. // In this case no one will ever know that an exception happened.

return ""; }

}

public class FileNotFoundException : Exception { // Implementation code goes here.}

Page 24: DotNet-Good programming practices

Good Programming Practices

2.1.23 MEMORY MANAGEMENT

Avoid Finalize() Only use Finalize() with Dispose()

Page 23 of 42

public void Dispose(){ // Clean up unmanaged resources GC.SuppressFinalize( this );}

protected override void Finalize(){ // Clean up unmanaged resources base.Finalize();}

Page 25: DotNet-Good programming practices

Good Programming Practices

2.1.24 DATA ACCESS

Accessing Relational Datao Always use the optimal Managed Provider

o Pick DataReader over DataSet when possible

o When the data will be remoted (disconnected) to the client or a remote application or component – for example, when using a Web Service that returns a Dataset.

o When more than one set of rows must be stored (and optionally the relationships between them).

o Used stored procedures when possible

o Always wrap your stored procedures in high level, type safe class. Only that class invokes the stored procedure.

o Avoid putting any logic inside a stored procedure.

o Always use type – safe data sets or data tables.

o Always use transactions when accessing a database.

Always use Enterprise Services transactions

DO NOT use ADO.Net transactions.

Page 24 of 42

// Fill the DataSet with each DataAdapter

daCustomers.Fill( dataSet, "Customers" );daInvoices.Fill( dataSet, "Invoices" );

// Show the customer nameConsole.WriteLine( dataSet.Customer[0].FirstName );Console.WriteLine( dataSet.Customer[0].LastName );

[ Transaction(TransactionOption.Required)]

public class Account : ServicedComponent{

[ AutoComplete]

// Code goes here}

Page 26: DotNet-Good programming practices

Good Programming Practices

o Always use transaction isolation level set to serializable.

o Avoid SQL Server Authentication

Use Windows Authentication instead.

Use SQL (TDS) classes for Data Access

There are two sets of objects for accessing a data source:

o Objects prefixed OleDb (from the System.Data.OleDb namespace) use an OLE-DB provider to access that data store.

o Objects prefixed Sql (from the System.Data.SqlClient namespace) use the Microsoft SQL Server Tabular Data Stream (TDS) interface to access that data store.

o The Sql prefixed objects are much faster and more efficient, and should always be used where you know that the data store will be Microsoft SQL server 7, 2000 or above.

XML Datao Use the XmlDataDocument for XML/DataSet integrationo DOM è DataSet è DOMo Don’t use DOM if you don’t need ito Only necessary for in-memory editingo XmlReader is faster than DOM

2.1.25 SERIALIZATION

Always mark non-sealed classes as serializable.

Always mark un-serializable member variables as non-serializable.

Always mark delegates on a serialized class as non - serializable fields.

Example:

2.1.26 MULTITHREADING

Use synchronization Domains. Avoid manual synchronization because that offen leads to deadlocks and race conditions.

Never call outside your synchronization domains.

Always name your threads. Name is traced in the debugger Threads window, making a debug session more productive.

Example:

Page 25 of 42

[Serializable]public class MyClass{

[field:NonSerialized]public event EventHandler MyEvent;

}

Thread currentThread = Thread.CurrentThread;

string threadName = “Main UI Thread”;

currentThread.Name = threadName;

Page 27: DotNet-Good programming practices

Good Programming Practices

Do not call Suspend() or Resume() on a thread.

Do not call Thread.Sleep().

o Thread.Sleep(0) is acceptable optimization technique to force a context switch.

o Thread.Sleep() is acceptable in testing or simulation code.

Do not call Thread.SpinWait().

Do not call Thread.Abort() to terminate threads.

o Use a synchronization object instead to signal the thread to terminate.

Avoid explicitly setting thread priority to control execution.

Do not read the value of the ThreadState property.

o Use Thread.IsAlive() to determine whether the thread is dead.

Do not rely on setting the thread type to background thread for application shutdown.

o Use a watchdog or other monitoring entity to deterministically kill threads.

Do not uses thread local storage unless thread affinity is guaranteed.

Do not call Thread.MemoryBarrier().

Never call Thread.Join() without checking that you are not joining your own thread.

Always use the lock () statement rather than explicit Monitor manipulation.

Page 26 of 42

void WaitForThreadToDie(Thread thread) {

Debug.Assert(Thread.CurrentThread.GetHashCode() != thread.GetHashCode());

thread.Join(); }

Page 28: DotNet-Good programming practices

Good Programming Practices

Always encapsulate the lock () statement inside the object it protects.

Avoid fragmented locking.

Avoid using a Monitor to wait or pulse objects. Use manual or auto-reset events instead.

Do not use volatile variables. Lock your object or fields instead to guarantee deterministic and thread-safe access.

o Do not use Thread.VolatileRead(), Thread.VolatileWrite() or the volatile modifier.

Never stack lock statements because that does not provide atomic locking. Use WaitHandle.WaitAll() instead.

2.1.27 REMOTING

Prefer administrative configuration to programmatic configuration.

Always implement IDisposable on single call objects.

Always prefer TCP channel and binary format when using remoting.

o Unless a firewall is present.

Always provide a null lease for a singleton object.

Page 27 of 42

public class MyClass { public void DoSomething() {

lock (this) {...} } }

MyClass obj1 = new MyClass(); MyClass obj2 = new MyClass(); MyClass obj3 = new MyClass();

//Do not stack lock statements lock(obj1) lock(obj2) lock(obj3) {

obj1.DoSomething(); obj2.DoSomething(); obj3.DoSomething();

}

Page 29: DotNet-Good programming practices

Good Programming Practices

Always provide a sponsor for a client activated object. The sponsor should return the initial lease time.

Always unregister the sponsor on client application shutdown.

Always put remote objects in class libraries.

Avoid using SoapSuds.

Avoid hosting in IIS.

Avoid using uni-directional channels.

Always load a remoting configuration file in Main() even if the file is empty, and the application does not use remoting.

Allow the option of remoting some types later on, post deployment, and changing the application topology.

Avoid using Activator.GetObject() and Activator.CreateInstance() for remote objects activation. Use new instead.

Always register port 0 on the client side, to allow callbacks.

Always elevate type filtering to full on both client and host to allow callbacks. Host Config file:

Page 28 of 42

public class MySingleton : MarshalByRefObject {

public override object InitializeLifetimeService() {

return null; }

}

static void Main() {

RemotingConfiguration.Configure("MyApp.exe.config"); /* Rest of Main() */

}

<channels> <channel ref="tcp" port="8005">

<serverProviders>

<formatter ref="soap" typeFilterLevel="Full"/> <formatter ref="binary" typeFilterLevel="Full"/>

</serverProviders> </channel> <channel ref="http" port="8006">

<serverProviders>

<formatter ref="soap" typeFilterLevel="Full"/> <formatter ref="binary" typeFilterLevel="Full"/>

</serverProviders> </channel>

</channels>

Client Config file: <channels>

<channel ref="tcp" port="0"> <serverProviders>

<formatter ref="soap" typeFilterLevel="Full"/> <formatter ref="binary" typeFilterLevel="Full"/>

</serverProviders> </channel>

</channels>

Page 30: DotNet-Good programming practices

Good Programming Practices

2.1.28 ENTERPRISE SERVICES

Do not catch exceptions in a transactional method. Use the AutoComplete attribute.

Do not call SetComplete(), SetAbort(), and the like. Use the AutoComplete attribute.

Page 29 of 42

[Transaction] public class MyComponent : ServicedComponent {

[AutoComplete] public void MyMethod(long objectIdentifier) {

GetState(objectIdentifier); DoWork(); SaveState(objectIdentifier);

} }

Page 31: DotNet-Good programming practices

Good Programming Practices

Always override CanBePooled and return true (unless you have a good reason not to return to pool)

Always call Dispose() explicitly on a pooled objects unless the component is configured to use JITA as well.

Never call Dispose() when the component uses JITA.

Always set authorization level to application and component.

Set authentication level to privacy on all applications.

Set impersonation level on client assemblies to Identity. Always set ComponentAccessControl attribute on serviced components to

true o The default is true.

[ComponentAccessControl] public class MyComponent : ServicedComponent {...}

Always add to the Marshaler role the Everyone user

[assembly: SecurityRole("Marshaler",SetEveryoneAccess = true)]

Page 30 of 42

public class MyComponent : ServicedComponent {

protected override bool CanBePooled() {

return true; }

}

[assembly: ApplicationActivation(ActivationOption.Server)]

[assembly: ApplicationAccessControl(true, //Authorization

AccessChecksLevel=AccessChecksLevelOption.ApplicationComponent,

Authentication=AuthenticationOption.Privacy,

ImpersonationLevel=ImpersonationLevelOption.Identify)]

Page 32: DotNet-Good programming practices

Good Programming Practices

Apply SecureMethod attribute to all classes requiring authentication.

[SecureMethod] public class MyComponent: ServicedComponent {...}

2.1.29 SECURITY

Code Access Securityo Access to a protected resource o The ability to perform a protected operation

Role-Based Securityo Imperative (old way)

o Imperative (new way)

o Declarative

Apply encryption and security protection on application configuration files.

Page 31 of 42

public void DoTransaction(){ PrincipalPermission permission = new PrincipalPermission(null, "Managers"); permission.Demand(); // Now do the transaction...}

public void DoTransaction(){ IPrincipal principal = Thread.CurrentPrincipal; if (!principal.IsInRole("Managers")) { throw new SecurityException("Not a " + "manager!"); } // OK, do the transaction...}

FileIOPermission permission = new FileIOPermission(PermissionState.None);permission.AllLocalFiles = FileIOPermissionAccess.Read;

[PrincipalPermission(SecurityAction.Demand, Role="Managers")]void DoTransaction(){ // this time, really // do the transaction...}

Page 33: DotNet-Good programming practices

Good Programming Practices

Do not use the /unsafe switch of TlbImp.exe. Wrap the CCW in managed code so

that you could assert and demand permissions declaratively on the wrapper.

On client machine, deploy a security policy which grants client application only the permissions to call back the server and to potentially display user interface.

Client application identified by strong name.

Always refuse at the assembly level all permissions not required to perform the task at hand.

2.2 ASP.NET

The designers of Microsoft® ASP.NET have done an excellent job in preserving backward compatibility with ASP applications; you need to be aware of a few best practices as follows.

Page 32 of 42

In ASP, you can declare subroutines and global variables in between your code delimiters.

<% Dim X Dim str

Sub MySub() Response.Write "This is a string." End Sub

%>In ASP.Net (Old Way)

<script language = "vb" runat = "server">String str;int x,y;

private int add( int I, int j ){

return ( i + j )}

</script>

In ASP.Net (Best Way) in code behind we have to write like this

private string str;int i, j;

private int add( int i, int j ){

return ( i + j );}

Page 34: DotNet-Good programming practices

Good Programming Practices

2.2.1 DISABLE SESSION STATE WHEN NOT IN USE

Not all applications or pages require per-user session state. If it is not required, disable it completely.

2.2.2 CHOOSE YOUR SESSION STATE PROVIDER CAREFULLY

ASP.NET provides three distinct ways to store session data

Option DescriptionInproc Session state is stored locally on this server (ASP style).StateServer Session state is stored in a state service process located remotely or

potentially locally.SqlServer Session state is stored in a SQL Server database.Off Session state is disabled.

In-proc session state is by far the fastest solution. If you are only storing small amounts of volatile data in session state you should use the in-process provider.

Out-of-process solutions are primarily useful in Web garden and Web farm scenarios or in situations in which data cannot be lost in the event of a server/process restart.

2.2.3 USAGE OF VIEWSTATE

Depending on the size of the viewstate, transmitting it across a network can entail a performance hit.

Page 33 of 42

<%@ Page EnableSessionState="false" %>

Page 35: DotNet-Good programming practices

Good Programming Practices

To disable viewstate maintenance for a page, use the following Page directive:

<%@Page EnableViewState=”false” … %>

To disable viewstate maintenance for a single control, use the EnableViewState property:

<ASP: DataGrid EnableViewState=”false” … runat=”server”/>

To disable viewstate maintenance for an entire application, change the setting in web.config:

<Pages enableviewstate=”false” …/>

2.2.4 AVOID EXCESSIVE ROUND TRIPS TO THE SERVER

Validating form entries can often take place on the client before the user submits data.

2.2.5 USE PAGE.ISPOSTBACK TO AVOID EXTRA WORK ON A ROUND TRIP

Handle server control postbacks.

Whether there is an initial request for the page or a response to a server control event.

2.2.6 REUSE WORK BY CACHING

Dynamic response generated by a request use output cache. Caches portions of a response generated by a request use fragment cache. Caches portions of a response generated by a request use data cache.

CAUTION: When you use the @ OutputCache directive, the Duration and VaryByParam attributes are required. If you do not include them, a parser error occurs when the page is first requested.

2.2.7 REMOVE CODE FROM CONTENT AS MUCH AS POSSIBLE

Separate your code from HTML content.

Page 34 of 42

void Page_Load(Object sender, EventArgs e){ // ...set up a connection and command here... if (!Page.IsPostBack)

{ String query = "select * from Authors where FirstName like '%JUSTIN%'"; myCommand.Fill(ds, "Authors"); myDataGrid.DataBind(); }}

Control Level disabling the View state:

<asp:datagrid EnableViewState="false" datasource="..." runat="server"/>

Page Level disabling the View state:

<%@ Page EnableViewState="false" %>

Page 36: DotNet-Good programming practices

Good Programming Practices

Clean up functions that mix code and script throughout a function body.

2.2.8 NEW PAGE DIRECTIVES

You can have as many lines of directives as you need.

Directives may be located anywhere in your .aspx file.

Standard practice is to place them at the beginning of the file.

2.2.9 USE RESPONSE.WRITE FOR STRING CONCATENATION

Use the HttpResponse.Write method in your pages or user controls for string concatenation.o This method offers buffering and concatenation services that are very efficient.

Using multiple calls to Response.Write, is faster than concatenating a string with a single call.

2.2.10 DO NOT FORGET TO DISABLE DEBUG MODE

Debug mode degrades performance significantly.

Disable Debug mode before you deploy a production application or measure performance

2.2.11 USE SERVER CONTROLS ONLY WHEN APPROPRIATE

When the element is only used to run some client-side script.

Example: A button that opens a new browser window or that interacts with a client-side ActiveX control or java

applet, or that calculates some value for display in the page using DHTML or an alert dialog.

When the element is a hyperlink that opens a different page or URL and there is no need to process the values for the hyperlink on the server.

Page 35 of 42

<%@ Page Language="vb" CodeBehind="test.aspx.vb"%>

<%@QutputCache Duration="60" VaryByParam="none" %>

Response.Write("a");

Response.Write(myString);

Response.Write("b");

Response.Write(myObj.ToString());

Page 37: DotNet-Good programming practices

Good Programming Practices

Any other times when access to the element’s properties, methods or events in server-side code is not

required.

2.2.12 USE THE WEB.CONFIG/MACHINE.CONFIG FILE TO STORE APPLICATION WIDE DATA

While you can use the web.config file to store your database connection string it is more secure to store the database connection string in the File / machine.config file.

It is very easy to retrieve this information from any of your ASP.NET application.

Server that has many different sites all using the same database (i.e. different IP addresses and domain names, not subwebs), the best solution if you want to keep all of the connection information in one place is to use the machine.config file for the server.

2.2.13 EXCEPTION HANDLING IN ASP.NET

The various options available for us for handling errors in asp.net are:

Code in such a way that possibility of error is less.

o Try to avoid error conditions as far as possible

Trapping errors as and when they occur.

o You should be prepared to handle unexpected conditions like network failures, database crashes and the like.

Page 36 of 42

string connstring = null;connstring = ConfigurationSettings.AppSettings("ConnectionString");

To add support for this to your Web.Config, you need to add an AppSettings section, like this one:

<appSettings>

<add key="ConnectionString" value="(your connection string)" />

</appSettings>

public class TextReader{ public string ReadLine() { try { // Read a line from the stream. }

catch ( NullReferenceException NRE ){  Response.Write("Null Reference Exception<BR>");}catch ( Exception DefaultExcep ){   Response.Write("Error Occured, Unknown Orgin");}finally{   Response.Write("Caught Exception");}

}}

Page 38: DotNet-Good programming practices

Good Programming Practices

Throw errors wherever appropriate to assist unified error handling.o Brings the uniformity in the error handling techniques.

o We can identify business error conditions in code itself rather than relaying on some database stored error codes.

o We can provide much detailed and user-friendly information to the users.

Caution: Throwing an exception is an expensive task.

Handle errors via Application_Error event in global.asax.

o Application_Error event that gets fired every time an unhandled exception occurs in the web application.

Note: This event will be fired only for unhandled exceptions

Provide custom error pages for predefined IIS errors.

o This provides much better user experience by the use of custom error pages.

o The Page class has a property called as ErrorPage that can contain url of a HTML/ASPX page that will be displayed if any unhandled exception occurs in your code.

Mywebform.ErrorPage="errpage.aspx"

Page 37 of 42

public class TextReader{ public string ReadLine() { try { // Read a line from the stream. } catch (Exception e) { throw new IOException ("Could not read from stream", e); } }}

protected void Application_Error(Object sender, EventArgs e){

Response.Write("Unexpected error occured ! <br>" & Server.GetLastError().Message);Response.End();

}

Page 39: DotNet-Good programming practices

Good Programming Practices

o In the web.config file, turn on the customErrors mode as shown below:

<customErrors mode="On" />

Provide custom error pages for business errors.

o This you can customize error pages without going to IIS snap-in and also change them easily in future

o Modify <customErrors> section of web.config file.

2.3 GENERAL TIPS

The engineer who wrote the code is mostly responsible for QA.

No code is finished until the unit test is finished.

Good design results from getting something going quickly, followed by lots of quick iteration.

The best architectures evolve for a long time.

Code reviews are a regular part of development.

Difficult parts of code are best done by a team of two people working closely together.

If you see a new bug while doing something else, drop everything and jump on the chance to fix it. It just makes your life easier down the road.

It is possible to eliminate all bugs from many subsystems and you should use techniques that make it possible, like Monte Carlo simulations and exhaustive checking code whenever possible.

Complexity is your enemy – the sooner you learn the smell of too much complexity, the better.

Simplicity is your friend. Don’t fall for a really cool fancy algorithm unless you know you need it.

Don’t build elaborate systems unless you know you need them.

Research existing open source project to make sure the code you need isn’t already available.

Never write a slow program.

Page 38 of 42

<customErrors mode="On" defaultRedirect="errpage.aspx">

<error statusCode="404" redirect="filenotfound.aspx" /> </customErrors>

Page 40: DotNet-Good programming practices

Good Programming Practices

By the time your project is finished your competitor’s project will be way better than you think.

Price is only one feature of software. It’s often not the most important. From the user’s perspective, simple things should be simple and complex things should be possible.

Automate releases.

Use source level debuggers.

Use IDEs

Don’t write makefiles unless you have too.

Measures then optimize.

Always spend at least 10% of your time learning new things. Use multiple languages, programming environments, operating systems and programming

methodologies until you are comfortable with them and learn to appreciate the benefits of different approaches.

Use the best tools, even if they are expensive.

Optimize variable names for maximum clarity, not minimum typing.

It’s OK to make mistakes. The only thing that isn’t OK is to not learn from them.

Don’t leave code commented out unless it’s clearly explained.

Approach each piece of code you write like its final finished code. Don’t leave loose ends to clean up later because you’ll never have time to clean them up.

Never code an algorithm that you know won’t work in the final product either because it won’t scale, run fast enough, or will have a rare failure case.

All successful products have a life longer than you can conceive. Files and processors will grow by factors of 10,000 – make sure your design can accommodate change.

Don’t code the first algorithm that comes to mind. Try to examine all possible approaches and choose the best. Get someone to review your approach before coding.

Don’t put band aids on bad code, rewrite it. At first is seems hard, but after you’ve done it awhile you’ll find successive rewrites go much faster than you thought.

When you work on someone else’s code, don’t leave it in worse shape than it came to you. Ask the original author to review your change.

No bug is impossible to fix.

Get to be good friends with a programmer, designer, or writer who’s better than you.

The Code should be

o consistent and predictable

Page 39 of 42

Page 41: DotNet-Good programming practices

Good Programming Practices

o scalable, high-performance o secure

Page 40 of 42