HTML Dropdown

Monday, 3 August 2015

How to achieve higher standards of Coding in C#:Part4

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.
·         Use implicit typing to determine the type of the loop variable in for and foreach loops.
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. 

No comments:

Post a Comment