Você está na página 1de 42

Good Programming Practices

A guide to your “code”

Prepared by

Dinesh Bhat

This document contrains 41 pages


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.6.1 CAPITALIZATION STYLES ............................................................................................................................4
2.1.6.2 CASE SENSITIVITY...................................................................................................................................... ...6
2.1.6.3 ABBREVIATIONS.......................................................................................................................... ..................7
2.1.6.4 NAMESPACE NAMING GUIDELINES............................................................................................................7
2.1.6.5 CLASS NAMING GUIDELINES.......................................................................................................................7
2.1.6.6 INTERFACE NAMING GUIDELINES...............................................................................................................8
2.1.6.7 ATTRIBUTE NAMING GUIDELINES...............................................................................................................9
2.1.6.8 ENUMERATION TYPE NAMING GUIDELINES............................................................................................10
2.1.6.9 STATIC FIELD NAMING GUIDELINES.........................................................................................................10
2.1.6.10 PARAMETER NAMING GUIDELINES.........................................................................................................11
2.1.6.11 METHOD NAMING GUIDELINES................................................................................................................11
2.1.6.12 PROPERTY NAMING GUIDELINES...........................................................................................................11
2.1.6.13 EVENT NAMING GUIDELINES...................................................................................................................12
2.1.6.14 DELEGATE NAMING GUIDELINES............................................................................................................13
2.1.7 USE EARLY BINDING FOR BETTER PERFORMANCE.....................................................................................14
2.1.8 RETURNING VALUES................................................................................................................................ ..........14
2.1.9 STATEMENTS................................................................................................................................................ .......15
2.1.9.1 SIMPLE STATEMENTS.................................................................................................................................15
2.1.9.2 COMPOUND STATEMENTS.........................................................................................................................15
2.1.9.3 IF, IF-ELSE, IF ELSE-IF ELSE STATEMENTS..............................................................................................15
2.1.9.4 FOR STATEMENTS...................................................................................................................... .................16
2.1.9.5 WHILE STATEMENTS...................................................................................................................................16
2.1.9.6 DO-WHILE STATEMENTS........................................................................................................................... ..17
2.1.9.7 SWITCH STATEMENTS............................................................................................................................... ..17
2.1.9.8 USING STATEMENT............................................................................................................................... .......17
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
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...............................................................................................................37
2.3 GENERAL TIPS................................................................................................................................... ...................38
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.

Page 3 of 42
Good Programming Practices

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


example:

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 */
}
}

2.1.5 PARENTHESES

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

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


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

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:

BackColor

• Camel case

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

backColor

Page 4 of 42
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:

Sysetm.IO

System.Web.UI

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


WebException
Exception class Pascal Note Always ends with
the suffix Exception.
Read-only Static field Pascal RedValue
IDisposable
Interface Pascal Note Always begins with
the prefix I.
Method Pascal ToString
Namespace Pascal System.Drawing
Parameter Camel typeName

Property Pascal BackColor


redValue
Note Rarely used. A
Protected instance field Camel property is preferable to
using a protected instance
field.
RedValue
Note Rarely used. A
Public instance field Pascal property is preferable to
using a public instance
field.

Page 5 of 42
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.

namespace ee.cummings;
namespace Ee.Cummings;

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

void MyFunction(string a, string A)

• 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.

System.Windows.Forms.Point p

System.Windows.Forms.POINT p

• 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.

int Color
{
get, set
}

int COLOR
{
get, set
}

• 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.

void calculate()

void Calculate()

Page 6 of 42
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:

Good:
GetWindow

Not Good:
GetWin

• 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.
CompanyName.TechnologyName[.Feature][.Design]

For example:

Microsoft.Media

Microsoft.Media.Design

2.1.6.5 Class Naming Guidelines


• Use a noun or noun phrase to name a class.

• Use Pascal case.

Page 7 of 42
Good Programming Practices

• Use abbreviations sparingly.

• 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

public class FileStream

public class Button

public class String

• 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.

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

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:

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

• Use Pascal case.

Page 8 of 42
Good Programming Practices

• Use abbreviations sparingly.

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

• 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.

public interface IServiceProvider

public interface IFormatable

The following code example illustrates how to define the interface IComponent and its standard
implementation, the class Component.

public interface IComponent


{
// Implementation goes here.
}

public class Component: IComponent


{
// Implementation code goes here.
}

• 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:

public class ObsoleteAttribute{}

Page 9 of 42
Good Programming Practices

2.1.6.8 Enumeration Type Naming Guidelines

• 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:

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
}

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:
public static int Global1 = 100;

public static int Global1 = 200;

Page 10 of 42
Good Programming Practices

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.

• 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

Type GetType(string typeName)

string Format(string format, object[] args)

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.

RemoveAll()

GetCharArray()

Invoke()

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.

Page 11 of 42
Good Programming Practices

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

Example:

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.

2.1.6.13 Event Naming Guidelines

The naming guidelines for events:


• Use Pascal case.

• Do not use Hungarian notation.

Page 12 of 42
Good Programming Practices

• 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.

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.

public delegate void MouseEventHandler(object sender,


MouseEventArgs e);

Example: Illustrates a correctly named event argument class.

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

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
Good Programming Practices

delegate void SomeDegate();

public void SomeMethod()


{
//Code goes here.
}

SomeDelegate someDelegate = SomeMethod;

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.

Good:
Early Binding

String[] address = null;

Not Good:
Late Binding

Object[] address = null;

2.1.8 RETURNING VALUES


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

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

Page 14 of 42
Good Programming Practices

2.1.9 STATEMENTS
2.1.9.1 Simple Statements

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

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:

if(condition)
{
statements;
}

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

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

Page 15 of 42
Good Programming Practices

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

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


statement;

2.1.9.4 for Statements

A for statement should have the following form:

for(initialization; condition; update)


{
statements;
}

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

for(initialization; condition; update)


{
/* No Body */
}

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:

while(condition)
{
statements;
}

An empty while statement should have the following form:

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

Page 16 of 42
Good Programming Practices

2.1.9.6 do-while Statements


A do-while statement should have the following form:

do
{
statements;
}
while(condition);

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:

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

case DEF:
statements;
break;

case XYZ:
statements;
break;

default:
statements;
break;
}

2.1.9.8 Using Statement


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

Page 17 of 42
Good Programming Practices

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

Not Good:

Resource res = new Resource(...);


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

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.

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

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 Programming Practices

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.
// ...
}

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 Programming Practices

Good:
const int index = 5;

Not Good:
int index = 5;

2.1.14 STRING CONCATENATION


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

Example:

For string

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

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

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.

Good:
enum MailType
{
Html, PlainText
}
void SendMail (string message, MailType mailType)
{
switch ( mailType )
{
case MailType.Html:
// Do something
break;
case MailType.PlainText:
// Do something
break;
default:
// Do something
break;
}
} Page 20 of 42
Good Programming Practices

Not Good:
void SendMail (string message, string mailType)
{
switch ( mailType )
{
case "Html":
// Do something
break;
case "PlainText":
// Do something
break;
default:
// Do something
break;
}
}

2.1.17 DO NOT MAKE THE MEMBER VARIABLES PUBLIC OR PROTECTED.


Keep them private and expose public/protected Properties.

Good:
public string CurrentUserName
{
Get
{}
Set
{}

Not Good:
Public string CurrentUser = null;

2.1.18 NEVER HARDCODE A PATH OR DRIVE NAME IN CODE.


Get the application path programmatically and use relative path.

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

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

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.

Page 21 of 42
Good Programming Practices

2.1.20 ERROR MESSAGES SHOULD HELP THE USER TO SOLVE THE PROBLEM.
Give specific error messages like

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.

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:

public class FileNotFoundException : Exception


{
// Implementation code goes here.
}

Page 22 of 42
Good Programming Practices

• 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.

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 "";
}
}

2.1.23 MEMORY MANAGEMENT


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

public void Dispose()


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

protected override void Finalize()


{
// Clean up unmanaged resources
base.Finalize(); Page 23 of 42
}
Good Programming Practices

2.1.24 DATA ACCESS

• Accessing Relational Data


o 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.

// Fill the DataSet with each DataAdapter

daCustomers.Fill( dataSet, "Customers" );


daInvoices.Fill( dataSet, "Invoices" );

// Show the customer name


Console.WriteLine( dataSet.Customer[0].FirstName );
Console.WriteLine( dataSet.Customer[0].LastName );

o Always use transactions when accessing a database.

 Always use Enterprise Services transactions

 DO NOT use ADO.Net transactions.

[ Transaction(TransactionOption.Required)]

public class Account : ServicedComponent


{
[ AutoComplete]

// Code goes here Page 24 of 42


}
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 Data
o Use the XmlDataDocument for XML/DataSet integration
o DOM è DataSet è DOM
o Don’t use DOM if you don’t need it
o Only necessary for in-memory editing
o 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:

[Serializable]
public class MyClass
{
[field:NonSerialized]
public event EventHandler MyEvent;
}

Page 25 of 42
Good Programming Practices

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:

Thread currentThread = Thread.CurrentThread;

string threadName = “Main UI Thread”;

currentThread.Name = threadName;

• 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.

Page 26 of 42
Good Programming Practices

void WaitForThreadToDie(Thread thread)


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

thread.Join();
}

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

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

public class MyClass


{
public void DoSomething()
{
lock (this)
{...}
}
}

• 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.

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 27 of 42
Good Programming Practices

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.

public class MySingleton : MarshalByRefObject


{
public override object InitializeLifetimeService()
{
return null;
}
}

• 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.

static void Main()


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

Page 28 of 42
Good Programming Practices

• 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:

<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 29 of 42
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.

[Transaction]
public class MyComponent : ServicedComponent
{
[AutoComplete]
public void MyMethod(long objectIdentifier)
{
GetState(objectIdentifier);
DoWork();
SaveState(objectIdentifier);
}
}

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

public class MyComponent : ServicedComponent


{
protected override bool CanBePooled()
{
return true;
}
}

• 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.

[assembly: ApplicationActivation(ActivationOption.Server)]

[assembly: ApplicationAccessControl(true, //Authorization

AccessChecksLevel=AccessChecksLevelOption.ApplicationComponent,

Authentication=AuthenticationOption.Privacy,

ImpersonationLevel=ImpersonationLevelOption.Identify)]

Page 30 of 42
Good Programming Practices

• 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)]

• Apply SecureMethod attribute to all classes requiring authentication.

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

2.1.29 SECURITY
• Code Access Security
o Access to a protected resource
o The ability to perform a protected operation

FileIOPermission permission = new FileIOPermission(PermissionState.None);


permission.AllLocalFiles = FileIOPermissionAccess.Read;

• Role-Based Security
o Imperative (old way)

public void DoTransaction()


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

o Imperative (new way)

Page 31 of 42
Good Programming Practices

public void DoTransaction()


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

o Declarative

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

• Apply encryption and security protection on application configuration files.

• 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.

Page 32 of 42
Good Programming Practices

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.

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

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.

<%@ Page EnableSessionState="false" %>

Page 33 of 42
Good Programming Practices

2.2.2 CHOOSE YOUR SESSION STATE PROVIDER CAREFULLY


• ASP.NET provides three distinct ways to store session data

Option Description
Inproc 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.

• 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” …/>

Control Level disabling the View state:

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

Page Level disabling the View state:

<%@ Page 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.
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();
} Page 34 of 42
}
Good Programming Practices

• 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.

• 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.

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

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

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.

Response.Write("a");

Response.Write(myString);

Response.Write("b");
Page 35 of 42
Response.Write(myObj.ToString());
Good Programming Practices

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.

• 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.
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>

• 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.

Page 36 of 42
Good Programming Practices

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.

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");
}
• 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.

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);
}
Caution: }
Throwing an exception is an expensive task.
}

Page 37 of 42
Good Programming Practices

• 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.

protected void Application_Error(Object sender, EventArgs e)


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

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"

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.

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


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

2.3 GENERAL TIPS

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

Page 38 of 42
Good Programming Practices

• 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.

• 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.

Page 39 of 42
Good Programming Practices

• 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


o scalable, high-performance
o secure

Page 40 of 42

Você também pode gostar