Language Guidelines
·
Do
not omit access modifiers.
·
Explicitly
declare all identifiers with the appropriate access modifier instead of
allowing the default. Example: // Bad! Void WriteEvent(string message) {…} //
Good! private Void WriteEvent(string message) {…}
·
Do
not use the default (“1.0.*”) versioning scheme.
·
Increment
the AssemblyVersionAttribute value manually.
·
Set
the ComVisibleAttribute to false for all assemblies.
·
Only
selectively enable the ComVisibleAttribute for individual classes when needed.
Example: [assembly: ComVisible(false)] [ComVisible(true)] public MyClass {…}
·
Consider
factoring classes containing unsafe code blocks into a separate assembly.
·
Avoid
mutual references between assemblies.
The following sections describe practices
that the C# team follows to prepare code examples and samples.
String Data Type
·
Use the + operator
to concatenate short strings, as shown in the following code.
C#
string displayName = nameList[n].LastName + ", " + nameList[n].FirstName;
·
To append strings in loops, especially when you are working with
large amounts of text, use a StringBuilder object.
C#
var phrase = "lalalalalalalalalalalalalalalalalalalalalalalalalalalalalala";
var manyPhrases = new StringBuilder();
for (var i = 0; i < 10000; i++)
{
manyPhrases.Append(phrase);
}
//Console.WriteLine("tra" + manyPhrases);
Implicitly Typed Local
Variables
·
Use implicit
typing for local
variables when the type of the variable is obvious from the right side of the
assignment, or when the precise type is not important.
C#
// When the type of a variable is clear from the context, use var
// in the declaration.
var var1 = "This is clearly a string.";
var var2 = 27;
var var3 = Convert.ToInt32(Console.ReadLine());
·
Do not use var when the
type is not apparent from the right side of the assignment.
C#
// When the type of a variable is not clear from the context, use an
// explicit type.
int var4 = ExampleClass.ResultSoFar();
·
Do not rely on the variable name to specify the type of the
variable. It might not be correct.
C#
// Naming the following variable inputInt is misleading.
// It is a string.
var inputInt = Console.ReadLine();
Console.WriteLine(inputInt);
·
Avoid the use of var in place
of dynamic.
The following example uses
implicit typing in a for statement.
C#
var syllable = "ha";
var laugh = "";
for (var i = 0; i < 10; i++)
{
laugh += syllable;
Console.WriteLine(laugh);
}
The following example uses
implicit typing in a foreach statement.
C#
foreach (var ch in laugh)
{
if (ch == 'h')
Console.Write("H");
else
Console.Write(ch);
}
Console.WriteLine();
Unsigned Data Type
·
In general, use int rather
than unsigned types. The use of int is common
throughout C#, and it is easier to interact with other libraries when you use int.
Variables
& Types Guidelines
·
Try
to initialize variables where you declare them.
·
Always
choose the simplest data type, list, or object required.
·
Always
use the built-in C# data type aliases, not the .NET common type system (CTS).
Example: short NOT System.Int16 int NOT System.Int32 long NOT System.Int64
string NOT System.String
·
Only
declare member variables as private. Use properties to provide access to them
with public, protected, or internal access modifiers.
·
Try
to use int for any non-fractional numeric values that will fit the int datatype
- even variables for nonnegative numbers.
·
Only
use long for variables potentially containing values too large for an int.
·
Try
to use double for fractional numbers to ensure decimal precision in
calculations.
·
Only
use float for fractional numbers that will not fit double or decimal.
·
Avoid
using float unless you fully understand the implications upon any calculations.
·
Try
to use decimal when fractional numbers must be rounded to a fixed precision for
calculations. Typically this will involve money.
·
Avoid
using sbyte, short, uint, and ulong unless it is for interop (P/Invoke) with
native libraries
·
Avoid
specifying the type for an enum - use the default of int unless you have an
explicit need for long (very uncommon).
·
Avoid
using inline numeric literals (magic numbers). Instead, use a Constant or Enum.
·
Avoid
declaring string literals inline. Instead use Resources, Constants,
Configuration Files, Registry or other data sources.
·
Declare
readonly or static readonly variables instead of constants for complex types.
·
Only
declare constants for simple types.
·
Avoid
direct casts. Instead, use the “as” operator and check for null.
Example: object
dataObject = LoadData();
DataSet ds =
dataObject as DataSet;
if(ds != null) {…}
·
Always
prefer C# Generic collection types over standard or strong-typed collections.
[C#v2+]
·
Always
explicitly initialize arrays of reference types using a for loop.
·
Avoid
boxing and unboxing value types.
Example: int count =
1;
object refCount =
count;// Implicitly boxed.
int newCount = (int)refCount; // Explicitly
unboxed.
·
Floating
point values should include at least one digit before the decimal place and one
after. Example: totalPercent = 0.05;
·
Try
to use the “@” prefix for string literals instead of escaped strings.
·
Prefer
String.Format() or StringBuilder over string concatenation.
·
Never
concatenate strings inside a loop.
·
Do
not compare strings to String.Empty or “” to check for empty strings. Instead,
compare by using String.Length == 0.
·
Avoid
hidden string allocations within a loop. Use String.Compare() for
case-sensitive
Example: (ToLower()
creates a temp string
// Bad!
int id = -1; string
name = “lance hunt”;
for(int i=0; i <
customerList.Count; i++)
{
if(customerList[i].Name.ToLower() ToLower()
ToLower() == name)
{
id = customerList[i].ID;
}
}
// Good!
int id = -1;
string name = “lance
hunt”;
for(int i=0; i <
customerList.Count; i++)
{
// The “ignoreCase =
true” argument performs a
// case-insensitive
compare without new allocation.
if(String.Compare
String.Compare String.Compare(customerList[i].Name, name, true)== 0) {
id =
customerList[i].ID;
}
}
Arrays
·
Use the concise syntax when you initialize arrays on the
declaration line.
C#
// Preferred syntax. Note that you cannot use var here instead of string[].
string[] vowels1 = { "a", "e", "i", "o", "u" };
// If you use explicit instantiation, you can use var.
var vowels2 = new string[] { "a", "e", "i", "o", "u" };
// If you specify an array size, you must initialize the elements one at a time.
var vowels3 = new string[5];
vowels3[0] = "a";
vowels3[1] = "e";
// And so on.
Delegates
·
Use the concise syntax to create instances of a delegate type.
C#
// First, in class Program, define the delegate type and a method that
// has a matching signature.
// Define the type.
public delegate void Del(string message);
// Define a method that has a matching signature.
public static void DelMethod(string str)
{
Console.WriteLine("DelMethod argument: {0}", str);
}
C#
// In the Main method, create an instance of Del.
// Preferred: Create an instance of Del by using condensed syntax.
Del exampleDel2 = DelMethod;
// The following declaration uses the full syntax.
Del exampleDel1 = new Del(DelMethod);
try-catch and using
Statements in Exception Handling
·
Use a try-catch statement for most exception handling.
C#
static string GetValueFromArray(string[] array, int index)
{
try
{
return array[index];
}
catch (System.IndexOutOfRangeException ex)
{
Console.WriteLine("Index is out of range: {0}", index);
throw;
}
}
·
Simplify your code by using the C# using
statement. If you have a try-finally statement in which the only code in the finally block is a call to the Dispose method, use ausing statement instead.
C#
// This try-finally statement only calls Dispose in the finally block.
Font font1 = new Font("Arial", 10.0f);
try
{
byte charset = font1.GdiCharSet;
}
finally
{
if (font1 != null)
{
((IDisposable)font1).Dispose();
}
}
// You can do the same thing with a using statement.
using (Font font2 = new Font("Arial", 10.0f))
{
byte charset = font2.GdiCharSet;
}
&& and ||
Operators
·
To avoid exceptions and increase performance by skipping
unnecessary comparisons, use && instead of & and || instead of | when you perform comparisons, as shown in the
following example.
C#
Console.Write("Enter a dividend: ");
var dividend = Convert.ToInt32(Console.ReadLine());
Console.Write("Enter a divisor: ");
var divisor = Convert.ToInt32(Console.ReadLine());
// If the divisor is 0, the second clause in the following condition
// causes a run-time error. The && operator short circuits when the
// first expression is false. That is, it does not evaluate the
// second expression. The & operator evaluates both, and causes
// a run-time error when divisor is 0.
if ((divisor != 0) && (dividend / divisor > 0))
{
Console.WriteLine("Quotient: {0}", dividend / divisor);
}
else
{
Console.WriteLine("Attempted division by 0 ends up here.");
}
New Operator
·
Use the concise form of object instantiation, with implicit
typing, as shown in the following declaration.
C#
var instance1 = new ExampleClass();
The previous line is equivalent
to the following declaration.
C#
ExampleClass instance2 = new ExampleClass();
·
Use object initializers to simplify object creation.
C#
// Object initializer.
var instance3 = new ExampleClass { Name = "Desktop", ID = 37414,
Location = "Redmond", Age = 2.3 };
// Default constructor and assignment statements.
var instance4 = new ExampleClass();
instance4.Name = "Desktop";
instance4.ID = 37414;
instance4.Location = "Redmond";
instance4.Age = 2.3;
Event Handling
·
If you are defining an event handler that you do not need to
remove later, use a lambda expression.
C#
public Form2()
{
// You can use a lambda expression to define an event handler.
this.Click += (s, e) =>
{
MessageBox.Show(
((MouseEventArgs)e).Location.ToString());
};
}
C#
// Using a lambda expression shortens the following traditional definition.
public Form1()
{
this.Click += new EventHandler(Form1_Click);
}
void Form1_Click(object sender, EventArgs e)
{
MessageBox.Show(((MouseEventArgs)e).Location.ToString());
}
Events, Delegates, & Threading GuideLines
1. Always check Event & Delegate instances for null before invoking.
2. Use the default EventHandler and EventArgs for most simple events.
3. Always derive a custom EventArgs class to provide additional data.
4. Use the existing CancelEventArgs class to allow the event subscriber to control events.
5. Always use the “lock” keyword instead of the Monitor type.
6. Only lock on a private or private static object.
Example: lock(myVariable);.
7. Avoid locking on a Type.
Example: lock(typeof(MyClass));
8. Avoid locking on the current object instance.
Example: lock(this);
Static Members
·
Call static members by using the class name: ClassName.StaticMember. This
practice makes code more readable by making static access clear. Do not qualify
a static member defined in a base class with the name of a derived class. While
that code compiles, the code readability is misleading, and the code may break
in the future if you add a static member with the same name to the derived
class.
LINQ Queries
·
Use meaningful names for query variables. The following example
uses seattleCustomers for customers who are located in Seattle.
C#
var seattleCustomers = from cust in customers
where cust.City == "Seattle"
select cust.Name;
·
Use aliases to make sure that property names of anonymous types
are correctly capitalized, using Pascal casing.
C#
var localDistributors =
from customer in customers
join distributor in distributors on customer.City equals distributor.City
select new { Customer = customer, Distributor = distributor };
·
Rename properties when the property names in the result would be
ambiguous. For example, if your query returns a customer name and a distributor
ID, instead of leaving them as Name and ID in the result, rename them to clarify that Name is the name of a customer, and ID is the ID of a distributor.
C#
var localDistributors2 =
from cust in customers
join dist in distributors on cust.City equals dist.City
select new { CustomerName = cust.Name, DistributorID = dist.ID };
·
Use implicit typing in the declaration of query variables and
range variables.
C#
var seattleCustomers = from cust in customers
where cust.City == "Seattle"
select cust.Name;
·
Align query clauses under the from clause,
as shown in the previous examples.
·
Use where clauses before other query clauses to ensure
that later query clauses operate on the reduced, filtered set of data.
C#
var seattleCustomers2 = from cust in customers
where cust.City == "Seattle"
orderby cust.Name
select cust;
·
Use multiple from clauses
instead of a join clause to access inner collections. For
example, a collection of Student objects
might each contain a collection of test scores. When the following query is
executed, it returns each score that is over 90, along with the last name of
the student who received the score.
C#
// Use a compound from to access the inner sequence within each element.
var scoreQuery = from student in students
from score in student.Scores
where score > 90
select new { Last = student.LastName, score };
Flow
Control
·
Avoid
invoking methods within a conditional expression.
·
Avoid
creating recursive methods. Use loops or nested loops instead.
·
Avoid
using foreach to iterate over immutable value-type collections. E.g. String
arrays.
·
Do
not modify enumerated items within a foreach statement.
·
Use
the ternary conditional operator only for trivial conditions. Avoid complex or
compound ternary operations. Example: int result = isValid ? 9 : 4;
·
Avoid
evaluating Boolean conditions against true or false. Example: // Bad! if
(isValid == true) {…} // Good! if (isValid) {…}
·
Avoid
assignment within conditional statements. Example: if((i=2)==2) {…}
·
Avoid
compound conditional expressions – use Boolean variables to split parts into
multiple manageable expressions.
Example: // Bad!
if (((value >
_highScore) && (value != _highScore)) && (value <
_maxScore)) {…}
// Good!
isHighScore = (value
>= _highScore);
isTiedHigh = (value ==
_highScore); isValid = (value < _maxValue);
if ((isHighScore
&& ! isTiedHigh) && isValid) {…}
·
Avoid
explicit Boolean tests in conditionals.
Example: // Bad!
if(IsValid == true)
{…};
// Good! if(IsValid)
{…}
·
Only
use switch/case statements for simple operations with parallel conditional
logic.
·
Prefer
nested if/else over switch/case for short conditional sequences and complex
conditions.
·
Prefer
polymorphism over switch/case to encapsulate and delegate complex operations.
Keep Class Size Small: I have seen and written some gigantic classes. But
unfortunately those were never turns out well. Later I found the reason that
is, those large classes try to do too many things. That violates the Single
Responsibility Principle. S
in SOLID (Object Oriented Design).
“The single responsibility principle states that every object
should have a single responsibility, and that responsibility should be entirely
encapsulated by the class. All its services should be narrowly aligned with
that responsibility.”
Or
According to Martin’s
definition :"THERE
SHOULD NEVER BE MORE THAN ONE REASON FOR A CLASS TO CHANGE."
·
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.
·
Method
name should tell what it does. Do not use mis-leading 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 SaveDetails (
string phoneNumber )
{
// Save the phone
number.
}
·
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.
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.
// ...
}
·
Use
the c# or VB.NET specific types (aliases), rather than the types defined in
System namespace.
int age; (not Int16)
string name; (not String)
object contactInfo; (not Object)
·
Some developers prefer to use types in Common Type System
than language specific aliases.
|
·
Always
watch for unexpected values. For example, if you are using a parameter with 2
possible values, never assume that if one is not matching then the only
possibility is the other value.
Good:
If ( memberType ==
eMemberTypes.Registered )
{
// Registered user… do
something…
}
else if ( memberType
== eMemberTypes.Guest )
{
// Guest user... do
something…
}
else
{
// Un expected user type. Throw an exception
throw new Exception (“Un expected value “ +
memberType.ToString() + “’.”)
// If we introduce a new user type in future, we
can easily find
// the problem here.
}
Not Good:
If ( memberType ==
eMemberTypes.Registered )
{
// Registered user… do
something…
}
else
{
// Guest user... do
something…
// If we introduce
another user type in future, this code will
// fail and will not
be noticed.
}
·
Do
not hardcode numbers. Use constants instead. Declare constant in the top of the
file and use it in your code.
·
However,
using constants are also not recommended. You should use the constants in the
config file or database so that you can change it later. Declare them as
constants only if you are sure this value will never need to be changed.
·
Do
not hardcode strings. Use resource files.
·
Convert
strings to lowercase or upper case before comparing. This will ensure the
string will match even if the string being compared has a different case.
if ( name.ToLower() ==
“john” )
{
//…
}
Use String.Empty
instead of “”
Good:
If ( name ==
String.Empty )
{
// do something
}
Not Good:
If ( name == “” )
{
// do something
}
·
Avoid
using member variables. Declare local variables wherever necessary and pass it
to other 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.
·
Use
enum wherever required. Do
not use numbers or strings to indicate discrete values.
Good:
enum MailType
{
Html,
PlainText,
Attachment
}
void SendMail (string
message, MailType mailType)
{
switch ( mailType )
{
case MailType.Html:
// Do something
break;
case
MailType.PlainText:
// Do something
break;
case
MailType.Attachment:
// Do something
break;
default:
// Do something
break;
}
}
Not Good:
void SendMail (string
message, string mailType)
{
switch ( mailType )
{
case "Html":
// Do something
break;
case
"PlainText":
// Do something
break;
case
"Attachment":
// Do something
break;
default:
// Do something
break;
}
}
·
Do
not make the member variables public or protected. Keep them private and expose
public/protected Properties.
·
The
event handler should not contain the code to perform the required action.
Rather call another method from the event handler.
·
Do
not programmatically click a button to execute the same action you have written
in the button click event. Rather, call the same method which is called by the
button click event handler.
·
Never
hardcode a path or drive name in code. Get the application path
programmatically and use relative path.
·
Never
assume that your code will run from drive "C:". You may never know,
some users may run it from network or from a "Z:".
·
In
the application start up, do some kind of "self check" and ensure all
required files and dependancies 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.
·
If
the required configuration file is not found, application should be able to
create one with default values.
·
If
a wrong value found in the configuration file, application should throw an
error or give a message and also should tell the user what are the correct
values.
·
Error
messages should help the user to solve the problem. Never give error messages
like "Error in Application", "There is an error" etc.
Instead give specific messages like "Failed to update database. Please
make sure the login id and password are correct."
·
When
displaying error messages, in addition to telling what is wrong, the message
should also tell what the user should do to solve the problem. Instead of
message like "Failed to update database.", suggest what should the
user do: "Failed to update database. Please make sure the login id and
password are correct."
·
Show
short and friendly message to the user. But log the actual error with all
possible information. This will help a lot in diagnosing problems.
·
Do
not have more than one class in a single file.
·
Have
your own templates for each of the file types in Visual Studio. You can include
your company name, copy right information etc in the template. You can view or
edit the Visual Studio file templates in the folder C:\Program
Files\Microsoft Visual Studio 8\Common7\IDE\ItemTemplatesCache\CSharp\1033. (This folder has the
templates for C#, but you can easily find the corresponding folders or any
other language)
·
Avoid
having very large files. If a single file has more than 1000 lines of code, it
is a good candidate for refactoring. Split them logically into two or more
classes.
·
Avoid
public methods and properties, unless they really need to be accessed from
outside the class. Use “internal” if they are accessed only within the same
assembly.
·
Avoid
passing too many parameters to a method. If you have more than 4~5 parameters,
it is a good candidate to define a class or structure.
·
If
you have a method returning a collection, return an empty collection instead of
null, if you have no data to return. For example, if you have a method
returning an ArrayList, always return a valid ArrayList. If you have no items
to return, then return a valid ArrayList with 0 items. This will make it easy
for the calling application to just check for the “count” rather than doing an
additional check for “null”.
·
Use
the AssemblyInfo file to fill information like version number, description,
company name, copyright notice etc.
·
Logically
organize all your files within appropriate folders. Use 2 level folder
hierarchies. You can have up to 10 folders in the root folder and each folder
can have up to 5 sub folders. If you have too many folders than cannot be accommodated
with the above mentioned 2 level hierarchy, you may need re factoring into
multiple assemblies.
·
Make
sure you have a good logging class which can be configured to log errors,
warning or traces. If you configure to log errors, it should only log errors.
But if you configure to log traces, it should record all (errors, warnings and
trace). Your log class should be written such a way that in future you can
change it easily to log to Windows Event Log, SQL Server, or Email to
administrator or to a File etc without any change in any other part of the
application. Use the log class extensively throughout the code to record
errors, warning and even trace messages that can help you trouble shoot a
problem.
·
If
you are opening database connections, sockets, file stream etc, always close
them in the finally block. This will ensure that even if an exception occurs
after opening the connection, it will be safely closed in the finally block.
·
Declare
variables as close as possible to where it is first used. Use one variable
declaration per line.
·
Use
StringBuilder class instead of String when you have to manipulate string
objects in a loop. The String object works in weird way in .NET. Each time you
append a string, it is actually discarding the old string object and recreating
a new object, which is a relatively expensive operations.
Consider the following
example:
public string
ComposeMessage (string[] lines)
{
string message =
String.Empty;
for (int i = 0; i <
lines.Length; i++)
{
message += lines [i];
}
return message;
}
·
In
the above example, it may look like we are just appending to the string object
‘message’. But what is happening in reality is, the string object is discarded
in each iteration and recreated and appending the line to it.
·
If
your loop has several iterations, then it is a good idea to use StringBuilder
class instead of String object.
See the example where
the String object is replaced with StringBuilder.
public string
ComposeMessage (string[] lines)
{
StringBuilder message
= new StringBuilder();
for (int i = 0; i <
lines.Length; i++)
{
message.Append(
lines[i] );
}
return
message.ToString();
}
·
No
'magic' Numbers Don’t use magic numbers, i.e. place constant numerical values
directly into the source code. Replacing these later on in case of changes
(say, your application can now handle 3540 users instead of the 427 hardcoded
into your code in 50 lines scattered troughout your 25000 LOC) is error-prone
and unproductive. Instead declare a const variable which contains the number :
public class MyMath
{
public const double PI
= 3.14159...
}
·
Avoid Too Many
Parameters
Declare a class instead of too many parameters. Creating a class
that puts all these parameters together. This is generally a better design and
valuable abstraction.
//avoid
public void Checkout(string shippingName, string shippingCity,
string shippingSate, string shippingZip, string billingName,
string billingCity, string billingSate, string billingZip)
{
}
//DO
public void Checkout(ShippingAddress
shippingAddress,BillingAddress billingAddress)
{
}
We should introduce class instead of all parameters.
·
Avoid
Complex Expressions
if(product.Price>500 && !product.IsDeleted &&
!product.IsFeatured &&
product.IsExported)
{
// do something
}
Complex expression have some meaning behind them it is just
hidden by those multiple expressions. We can encapsulate the complex expression
into that object by using a property. That code will be easier to read.
·
Consider Warnings as
Errors
If you notice the code you will find a variable that was
declared but never used. Normally if we build the project we will get a warning
and we can run our project without any error. But we should remove warning as
much as possible. So setup your build to treat warning as Errors like the
following steps:
·
Minimize the Number of
Returns
Minimize the number of returns in each routine. It's harder
to understand a routine if, reading it at the bottom, you're unaware of the
possibility that it returned somewhere above.
Use a return when it enhances readability. In certain
routines, once you know the answer, you want to return it to the calling
routine immediately. If the routine is defined in such a way that it doesn't
require any cleanup, not returning immediately means that you have to write
more code.
//avoid
if(product.Price>15)
{
return false;
}
else if(product.IsDeleted)
{
return false;
}
else if(!product.IsFeatured)
{
return false;
}
else if()
{
//.....
}
return true;
Hide Copy Code
//DO
var
isValid = true;
if(product.Price>15)
{
isValid= false;
}
else if(product.IsDeleted)
{
isValid= false;
}
else if(!product.IsFeatured)
{
isValid= false;
}
return isValid;
You can imagine 4 exit points scattered around 20- 30 lines
of code. That makes you harder to understand and see what is happening inside
the method and what will execute and when will execute.
I got too many responses, some agreeing but mostly
disagreeing that it was a good "standard" to enforce. To find
out the potentiality I did some unit testing and found that for complex method
that have multiple exit points usually have a set of tests for each of those
paths.
if(
BADFunction() == true)
{
// expression
if( anotherFunction() == true )
{
// expression
return true;
}
else
{
//error
}
}
else
{
//error
}
return false;
if(
!GoodFunction())
{
// error.
return false
}
// expression
if(
!GoodFunction2())
{
//error.
return false;
}
// more expression
return true;
·
Checking Loop
Endpoints
A
single loop usually has three cases of interest: the first case, an arbitrarily
selected middle case, and the last case. If you have any special cases that are
different from the first or last case, check those too. If the loop contains
complex computations, get out your calculator and manually check the
calculations.
Conclusion
It
is obvious to implement standards in any software company according to
organizational behavior, project nature, and domain. So I would like to repeat
"Find a convention and stick with it".
If
you think I missed any prominent guideline, please leave that in the comments
section. I’ll try to include that in the main post. Coding For Fun.