Yan
Developers always like to argue about coding standards, but more importantly, how to comply with coding standards from beginning to end in the project to ensure project code consistency. In addition, everyone in the team needs to clarify the role of coding specifications. In this article, I will introduce some good practices that I learned and summarized during my years of practice.
Example first
Let's first look at a fizzbuzz example. Fizzbuzz requires a program to traverse numbers from 1 to 100. If a number is a multiple of 3, the program outputs "fizz ". If a number is a multiple of 5, "Buzz" is output ". If a number is a multiple of 3 and a multiple of 5, "fizzbuzz" is output ". If the number is neither a multiple of 3 nor a multiple of 5, you only need to output the number itself.
Example 1:
1 public static void Test() 2 { 3 for (int i = 1; i < 101; i++) 4 { 5 if (i % 3 == 0 && i % 5 == 0) 6 { 7 Console.WriteLine("FizzBuzz"); 8 } 9 else if (i % 3 == 0)10 {11 Console.WriteLine("Fizz");12 }13 else if (i % 5 == 0)14 {15 Console.WriteLine("Buzz");16 }17 else18 {19 Console.WriteLine(i);20 }21 }22 }
What do you feel? Does this code need to be improved?
Example 2:
1 public static void Check() 2 { 3 for (int i = 1; i <= 100; i++) 4 { 5 string output = ""; 6 if (i % 3 == 0) { output = "Fizz"; } 7 if (i % 5 == 0) { output = output + "Buzz"; } 8 if (output == "") { output = i.ToString(); } 9 Console.WriteLine(output);10 }11 }
How do you feel? Can it be further improved?
Okay. Let's try to improve it. Code naming is very difficult for all software developers. We spend a lot of time doing this, and there are too many elements to be named, such as attributes, methods, classes, files, projects, and so on. However, we do need to spend some energy on these names to make the names in the Code more meaningful, and thus improve the readability of the Code.
1 public void DoFizzBuzz() 2 { 3 for (int number = 1; number <= 100; number++) 4 { 5 var output = GetFizzBuzzOutput(number); 6 Console.WriteLine(output); 7 } 8 } 9 10 private static string GetFizzBuzzOutput(int number)11 {12 string output = string.Empty;13 if (number % 3 == 0)14 {15 output = "Fizz";16 }17 if (number % 5 == 0)18 {19 output += "Buzz";20 }21 if (string.IsNullOrEmpty(output))22 {23 output = number.ToString();24 }25 return output;26 }
How does it feel this time? Is it better than the previous example? Is it more readable?
What is better code?
First, the code should be compiled by humans, and then the machine. In the long run, it will not take longer to write readable code than to write messy code. If you can easily understand the code you write, it is easier to confirm that it can work normally. This should already be enough reason to write readable code. In many cases, you need to read the code. For example, you will read the code you wrote during the code review. You or others will read the code you wrote when fixing bugs, it is also read when the code needs to be modified. Also, when others attempt to reuse some of your code in similar projects or projects with similar functions, they will first read your code.
"If you only write code for yourself, why make the code more readable ?"
Well, the main reason for writing readable code is that you will work on another project in the next one to two weeks. At this time, if someone else needs to fix a bug in the current project, what will happen? I am sure he will be lost in your own horrible code.
From my point of view, good code should have the following features:
- The code is easy to write and easy to modify and expand.
- The code is clean and accurate.
- Code is valuable and focuses on quality.
Therefore, we must always consider writing code for people before meeting the needs of machines.
How to improve readability?
First, you need to read and learn the Code Compiled by others to understand what is good code and what is bad code. That is, the code that you feel very easy to understand, and the code that looks super complex. Then, practice. Finally, it takes some time, experience, and practice to improve the readability of your code. Generally, it is difficult for any software company to promote code specifications only through training. Such as peer code review and automated code review tools can also help you. Currently, popular tools include:
- Fxcop: Performs static code analysis on. NET code and provides multiple rules for different forms of analysis.
- Stylecop: an open-source project that uses the code style and consistency specifications to analyze the C # code. It can be run in Visual Studio or integrated into msbuild. Stylecop has also been integrated into some third-party development tools.
- Jetbrains resharper: a well-known productivity improvement tool that makes Microsoft Visual Studio ide more powerful. The. NET developers around the world may not be able to imagine how they do not have such powerful functions as resharper code review, Automatic Code refactoring, quick navigation, and coding assistant in their work.
What are specifications?
According to the Wikipedia Description:"Coding conventions are a set of guidelines for a specific programming language that recommend programming style, practices and methods for each aspect of a piece program written in this language. these conventions usually cover file organization, indentation, comments, declarations, statements, white space, naming conventions, programming conditions, programming principles, programming rules of thumb, semantic tural best practices, etc. these are guidelines for software structural quality. software programmers are highly recommended to follow these guidelines to help improve the readability of their source code and make software maintenance easier. coding conventions are only applicable to the human maintainers and peer reviewers of a software project. conventions may be formalized in a specified ented set of rules that an entire team or company follows, or may be as informal as the habitual coding practices of an individual. coding conventions are not enforced by compilers. as a result, not following some or all of the rules has no impact on the executable programs created from the source code.".
You should be able to tell the differences among attributes, local variables, method names, and class names, because they use different case-sensitive conventions, so these conventions are very valuable. Through the Internet, you have learned a lot about the relevant standards and norms. All you need is to find a standard or establish your own norms, and then always follow this standard.
The source code (Class Library Design Guidelines) used below is developed by Microsoft's special interest group team. I just made some extensions.
Case sensitivity
The following are examples of C # coding standards, naming conventions, and best practices, which can be used as needed.
Pascal Casing
The first letter in the identifier. the first letter of each word in the subsequent series is uppercase. If necessary, the first few letters of the identifier can be capitalized.
Camel Casing
The first letter of the identifier is lowercase, and the first letter of each word in the subsequent series is uppercase.
Reference: Case sensitivity rules
Naming Conventions
On the Internet, you can find enough resources. I just recommend a few of my favorite resources:
- C # coding conventions
- C # Coding principles
- C # coding standards and best practices
- C # Coding specifications and naming conventions
Here I show some basic examples, but as I mentioned above, find a specification that suits you and stick to it.
YesUse Pascal casing to name classes and methods.
public class Product { public void GetActiveProducts() { //... } public void CalculateProductAdditinalCost() { //... } }
YesUse camel casing to name the parameters and local variables of the method.
public class ProductCategory { public void Save(ProductCategory productCategory) { // ... } }
NoUse abbreviations.
// Correct ProductCategory productCategory; // Avoid ProductCategory prodCat;
NoUse an underscore in the identifier.
// Correct ProductCategory productCategory; // Avoid ProductCategory product_Category;
YesUse the letter I before the interface name.
public interface IAddress { }
YesDefine all member variables at the top of the class and static variables at the top.
public class Product { public static string BrandName; public string Name { get; set; } public DateTime DateAvailable { get; set; } public Product() { // ... } }
YesUse a singular word to define enumeration, unless it is a bitfield enumeration.
public enum Direction { North, East, South, West }
NoAdd an Enum suffix to the enumerated name.
//Avoid public enum DirectionEnum { North, East, South, West }Why do we need coding standards?
In large projects, developers often rely on coding standards. They have established many norms and standards, so that remembering these norms and standards has become part of their daily work. Computers do not care about the readability of the code you write. Computers are easier to understand binary machine commands than to read advanced program language statements.
The encoding specification provides many obvious benefits. Of course, you may get more. Generally, the planning of the overall scope of these projects will enable you to focus more on the more important part of the code.
- Code specifications can help transfer knowledge across projects.
- Coding specifications can help you quickly understand code in new projects.
- The code specification emphasizes the relationship between associated projects in the Organization.
You need to write highly readable code to help others understand your code. Code naming is very difficult for our software developers. We have spent a lot of time on it and there are too many elements to name, such as attributes, methods, classes, files, and projects. Therefore, we really need to spend some energy on naming rules to make the name more meaningful and improve the readability of the Code.
Also, the coding specification can make you sleep better at night.
The following rules should be followed by developers to always control the class size.
I have seen and written some very large classes. Unfortunately, the results are always bad. Later, I found the real reason, that is, the super-large classes are trying to do too many things, which violates the single responsibility principle (SRP), that is, the S in the object-oriented design principle solid.
"The single responsibility principle states that every object shocould have a single responsibility, and that responsibility shocould be entirely encapsulated by the class. All its services shocould be narrowly aligned with that responsibility ."
Or, according to Martin Fowler's definition:"There shoshould never be more than one reason for a class to change ."
Why do we need to separate the two duties into separate classes? Because every responsibility is the center of change. When the requirement changes, the change will appear in the class responsible for this responsibility. If a class assumes multiple responsibilities, there will be more than one reason for the change. If a class has multiple responsibilities, these responsibilities have been coupled. In addition, changes in a role may weaken or restrict this class's ability to meet other responsibilities. This coupling will lead to a very fragile design, and the design may be unexpectedly damaged when the responsibilities change.
Avoid outdated comments
Let's talk about outdated comments. According to the definition of Robert C. MARTIN:
"A comment that has gotten old, irrelevant, and incorrect is obsolete. comments get old quickly. it is best not to write a comment that will become obsolete. if you find an obsolete comment, it is best to update it or get rid of it as quickly as possible. obsolete comments tend to migrate away from the code they once described. they become floating islands of irrelevance and misdirection in the code."
Developers of different levels may have their own opinions on this topic. My suggestion is to try to avoid comments for separate methods or short classes. Because most of the comments I have seen are trying to describe the purpose or intent of the Code, or some comments may be meaningless. Developers usually write comments to improve the readability and maintainability of the code, but ensure that the comments you write will not be noise in the code. I think a reasonable method name is more effective than a comment. For example, you can give a more meaningful name to a method. Most comments may become meaningless code noise. Let's take a look at the following comments:
//ensure that we are not exporting //deleted products if (product.IsDeleted && !product.IsExported) { ExportProducts = false; } // This is a for loop that prints the 1 million times for (int i = 0; i < 1000000; i++) { Console.WriteLine(i); }
If we do not write comments, but name a method, such as cancelexportfordeletedproducts (), what will happen? Therefore, proper method naming is more effective than annotation. However, in some cases, code annotations can be very helpful. For example, Visual Studio generates API documents from annotations. The annotations here are slightly different. You need to use the "//" identifier to comment, so that other developers can see the smart prompts of the API or class library.
I didn't mean to avoid comments. According to Kent Beck, more annotations can be used to describe how the program works as a whole, rather than commenting on individual methods. If the comment is trying to describe the purpose or intent of the code, it will be wrong. If you see dense comments in the code, you may realize that there are so many comments that the code is poorly written. For more information, read the following books:
- Professional refactoring in C # and ASP. NET by Danijel arsenovski
- Refactoring: improving existing code design by Martin Fowler, Kent Beck, John Brant, William Opdyke, Don Robert TS
Avoid unnecessary Region
Region is a function provided by Visual Studio that allows you to block code. Region exists because it makes large file navigation easier. Region is also often used to hide ugly code, or classes that have expanded greatly need to be segmented. If a class does too many things, it indicates that it violates the single responsibility principle. Therefore, when you want to add a new region, consider whether it is possible to separate the region into a separate class.
Keep the method short
The more lines of code in the method, the harder it is to understand the method. We recommend that each method contain only 20-25 lines of code. But some people say that line 1-10 is more reasonable. This is just some personal preferences and there are no hard rules. The extraction method is one of the most common refactoring methods. If you find that a method is too long or requires a comment to describe its purpose, you can apply the extraction method. People always ask how long a method is suitable, but the length is not the root of the problem. When you are dealing with complex methods, tracking all local variables is the most complex and time-consuming, while extracting a method can save some time. You can use Visual Studio to extract methods. It will help you track local variables and pass them to new methods or receive the return values of methods.
Using resharper
Using Microsoft Visual Studio
For more information, see msdn.
According to the description in refactoring: improving existing code design,
"Extract method is one of the most common refactoring I do. I look at a method that is too long or look at code that needs a comment to understand its purpose. I then turn that fragment of code into its own method. I prefer short, well-named methods for several reasons. first, it increases the chances that other methods can use a method when the method is finely grained. second, it allows the higher-level methods to read more like a series of comments. overriding also is easier when the methods are finely grained. it does take a little getting used to if you are used to seeing larger methods. and small Methods really work only when you have good names, so you need to pay attention to naming. people sometimes ask me what length I look for in a method. to me length is not the issue. the key is the semantic distance between the method name and the method body. if extracting improves clarity, do it, even if the name is longer than the code you have extracted."
Avoid excessive Parameters
Declare a class to replace multiple parameters. Create a class that contains all parameters. Generally speaking, this is a good design and the abstraction is very valuable.
//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 need to introduce classes to replace all parameters.
Avoid complex expressions
if(product.Price>500 && !product.IsDeleted && !product.IsFeatured && product.IsExported) { // do something }
Complex expressions mean that some meanings are hidden behind them. We can encapsulate these expressions by using attributes to make the code easier to read.
Equivalent warnings to errors
If you read the code, you will find that a variable has been declared but never used. Normally, we get a warning after compiling the project, but it can still run the project without any errors. However, we should try to remove these warnings. Follow these steps to set the warning equivalent to an error on the project:
Streamline multiple responses
Reduce the number of returned functions in each program. If you read the code from the bottom, it is hard to realize that it may have been returned somewhere above, and such code will be hard to understand.
Only one return can enhance readability. If the program is written in this way, it may look clean, but if it is not returned immediately, it also means writing 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;
//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 four exit points are scattered in the 20-30 lines of code, which makes it very difficult for you to understand what is done inside the program and what will be executed, when to execute.
I have received a lot of replies on this point. Some people agree with this point of view, while others disagree that this is a good coding standard. To identify potential problems, I did some unit tests and found that if a complex method contains multiple exit points, a group of tests is usually required to overwrite all the 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;
For more information, see Steve McConnell's code book.
Use assertions
In software development, asserted code is often used to check whether program code is executed according to its design. Generally, true indicates that all operations are completed as expected, and false indicates that unexpected errors have been detected. Assertion usually receives two parameters. A Boolean expression is used to describe the hypothesis as true, and a message parameter is used to describe the cause of assertion failure.
Assertions are usually very useful in developing large, complex, and highly reliable systems.
For example, if the system assumes that a maximum of 100,000 user records are supported, the system may contain an asserted to check that the number of user records is less than or equal to 100,000. in this range, assertions do not work. However, if the number of user records exceeds 100,000, the assertion will throw an error to tell you that the number of records has exceeded the range.
Check the cyclic endpoint Value
A loop usually involves three condition values: the first value, a value in the middle, and the last value. However, if you have any other specific conditions, you also need to perform detection. If the loop contains complex calculations, do not use a calculator. manually check the calculation results.
Summary
Code specifications are usually implemented in any software company according to the organizational behavior, project attributes and fields. Here I want to emphasize again "find a suitable code specification for you, and keep following it ".
If you think that I have omitted a particularly useful coding criterion, please describe it in the comment and I will try to add it to the article.
Coding for fun.
Original article address
Note: the author of the original article monjurul Habib is from Bangladesh. I don't know the language spoken by people in Bangladesh, but I feel that the author's English is very stiff and I cannot understand it in some places, readers forgive me.
Write better C # code