Escolar Documentos
Profissional Documentos
Cultura Documentos
Prepared by
Dinesh Bhat
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
• 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
2.1.5 PARENTHESES
It is generally a good idea to use parentheses liberally in expressions involving mixed operators to avoid operator
precedence problems
• 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:
Page 5 of 42
Good Programming Practices
• 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.
• 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:
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.
For example:
Microsoft.Media
Microsoft.Media.Design
Page 7 of 42
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.
• 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.
• Name interfaces with nouns or noun phrases, or adjectives that describe behaviour.
Example:
IComponent // noun.
ICustomAttributeProvider //noun.
IPersistable //adjective.
Page 8 of 42
Good Programming Practices
• 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.
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.
You should always add the suffix Attribute to custom attribute classes.
Example:
Page 9 of 42
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 a singular name for most Enum types, but use a plural name for Enum types that are bit fields.
Example:
Good:
public enum Color
{
Red, Green, Blue
}
Not Good:
Not Good:
public enum Color : long
{
Red, Green, Blue
}
O It is recommended that you use static properties instead of public static fields whenever possible.
Example:
public static int Global1 = 100;
Page 10 of 42
Good Programming Practices
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 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.
RemoveAll()
GetCharArray()
Invoke()
Page 11 of 42
Good Programming Practices
• Consider creating a property with the same name as its underlying type.
Example:
Good:
Not Good:
public enum Color
{
// Insert code for Enum here.
}
public class Control
{
public int Color
{
get {// Insert code here.}
set {// Insert code here.}
}
}
Page 12 of 42
Good Programming Practices
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.
• 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.
• Copy a delegate to local variable before publishing to avoid concurrency race condition.
Page 13 of 42
Good Programming Practices
• Always specify a data type for variables when they are declared. This provides strong typing of
variables for best performance.
Good:
Early Binding
Not Good:
Late Binding
if(booleanExpression)
{
return true;
}
else
{
return false;
}
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! */
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:
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).
while(condition)
{
statements;
}
while(condition)
{
/* No Body */
}
Page 16 of 42
Good Programming Practices
do
{
statements;
}
while(condition);
switch(condition)
{
case ABC:
statements;
/* falls through */
case DEF:
statements;
break;
case XYZ:
statements;
break;
default:
statements;
break;
}
Page 17 of 42
Good Programming Practices
Good:
using (Resource res = new Resource()) {
res.DoWork();
}
Not Good:
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.
}
Page 18 of 42
Good Programming Practices
Good:
// Save the address.
SaveAddress ( address );
Not Good:
// Save address and send an email to the supervisor to inform that the
address is updated.
SaveAddress ( address, email );
// Job 2.
// Send an email to inform the supervisor that the address is changed.
// ...
}
• 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.
Page 19 of 42
Good Programming Practices
Good:
const int index = 5;
Not Good:
int index = 5;
Example:
For string
Good :
StringBuilder address = new StringBuilder();
Address.Append( “Bangalore”);
Address.Append( “Delhi”);
Not Good:
string address = null;
address = “Bangalore”
address += “Delhi”;
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;
}
}
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”;
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.
• If all variables and method names are meaningful, that would make the code very readable and will
not need many comments.
• 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.
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.
• If you hide an exception, you will never know if the exception happened or not.
Example:
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.
return "";
}
}
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 Always wrap your stored procedures in high level, type safe class. Only that class invokes the
stored procedure.
[ Transaction(TransactionOption.Required)]
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
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.
Example:
currentThread.Name = threadName;
• Do not rely on setting the thread type to background thread for application shutdown.
• Never call Thread.Join() without checking that you are not joining your own
thread.
Page 26 of 42
Good Programming Practices
thread.Join();
}
Always use the lock () statement rather than explicit Monitor manipulation.
• 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.
• Never stack lock statements because that does not provide atomic locking. Use
WaitHandle.WaitAll() instead.
Page 27 of 42
Good Programming Practices
2.1.27 REMOTING
• Always prefer TCP channel and binary format when using remoting.
• Always provide a sponsor for a client activated object. The sponsor should return the
initial lease time.
• 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.
Page 28 of 42
Good Programming Practices
• Always elevate type filtering to full on both client and host to allow callbacks.
Host Config file:
<channels>
<channel ref="tcp" port="8005">
<serverProviders>
</serverProviders>
</channel>
<channel ref="http" port="8006">
<serverProviders>
</serverProviders>
</channel>
</channels>
</serverProviders>
</channel>
</channels>
Page 29 of 42
Good Programming Practices
[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)
[assembly: ApplicationActivation(ActivationOption.Server)]
AccessChecksLevel=AccessChecksLevelOption.ApplicationComponent,
Authentication=AuthenticationOption.Privacy,
ImpersonationLevel=ImpersonationLevelOption.Identify)]
Page 30 of 42
Good Programming Practices
[ComponentAccessControl]
public class MyComponent : ServicedComponent
{...}
• Always add to the Marshaler role the Everyone user
[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
• Role-Based Security
o Imperative (old way)
Page 31 of 42
Good Programming Practices
o Declarative
[PrincipalPermission(SecurityAction.Demand, Role="Managers")]
void DoTransaction()
{
// this time, really
// do the transaction...
}
• 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.
• 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)
• Not all applications or pages require per-user session state. If it is not required, disable it completely.
Page 33 of 42
Good Programming Practices
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.
• To disable viewstate maintenance for a page, use the following Page directive:
• To disable viewstate maintenance for a single control, use the EnableViewState property:
• To disable viewstate maintenance for an entire application, change the setting in web.config:
• Whether there is an initial request for the page or a response to a server control event.
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.
• Clean up functions that mix code and script throughout a function body.
• 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
• Disable Debug mode before you deploy a production application or measure performance
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.
• It is very easy to retrieve this information from any of your ASP.NET application.
string connstring = null;
connstring =
ConfigurationSettings.AppSettings("ConnectionString");
<appSettings>
</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
o You should be prepared to handle unexpected conditions like network failures, database
crashes and the like.
o We can identify business error conditions in code itself rather than relaying on some database
stored error codes.
Page 37 of 42
Good Programming Practices
o Application_Error event that gets fired every time an unhandled exception occurs in the web
application.
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 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.
• The engineer who wrote the code is mostly responsible for QA.
Page 38 of 42
Good Programming Practices
• Good design results from getting something going quickly, followed by lots of quick iteration.
• 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.
• 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 IDEs
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.
• 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.
• Get to be good friends with a programmer, designer, or writer who’s better than you.
Page 40 of 42