A: Preface
No rules, inadequate surrounding area. This is especially true in the world of code. As programmers, we don't want our code to be laughed at later: Look, even a change of line is so unprofessional. As a development manager, we don't want our team members to write code that has all kinds of styles, colorful and extremely ugly. Write the code of the specification, first of all need training, second, there are certain means or tools to assist. In this section, we are going to start with these two aspects and talk about how to standardize our code. Of course, because the coding knowledge we're learning is limited, and most often, this section will only design the most basic, most commonly used coding specifications, but even so, it will make our code look a lot more professional after we finish this section.
Note: I do not like to finish all the knowledge at once, for example, the specification, we may only involve 80% of the part today. I like this "28 principle", that is, we only spend 20% of the time to complete 80% of the things, but if we want to complete the remaining 20% of the things, in turn will have to pay an extra 80% of the time, which is a bit more cost-effective. This "28 principle" is important for training or learning knowledge. Our training, if we want to explain 100% of the knowledge point, first will be very boring (because some knowledge needs us to have a dead-point spirit to be enlightened), and secondly will be very time-consuming (we do not want to spend the least time to learn the most knowledge?) Finally, become a real expert, never be trained, so our training, will teach you this 80% part, the rest, then hope that the 80% has been cultivated to your habits, to dig yourself. OK, there's a lot of crap today, but even though we haven't written many lines of code with our course, I'm sure you'll feel it's time to get to the code. So far, we've done a few refactoring and refactoring, and it's actually about the code stepping up to a more prescriptive process. Of course, some of the norms may be completed in this section of the course we will grasp, and more in-depth specifications, we need to learn in the future slowly mastered, and the interesting point is: The specification itself may also exist conflict of ... Well, no matter what, the taste, we slowly realize it, now, go ...
II: Naming conventions
1: Consider using complex numbers in namespaces
If you have a group of similar types that are grouped under the same namespace, you might consider using complex numbers for namespaces.
The most typical example is that in the FCL, we need to centralize all non-generic collection classes together, so we have the System.Collections namespace. The advantage of such a naming convention is that even though we have never used a collection class, we see a namespace like this, and we know that underneath it are some types that are related to collections (that is, collection). Do not appear system.allcollections, system.thecollection such a name, this seems to be either too cumbersome, or ambiguous.
As a practical example, if there is a series of processor types in our project, we can use the namespace processors.
2: Naming types with nouns and noun groups
What is the type? The object-oriented pioneers will tell us that the type corresponds to the actual object in the real world. An object in linguistics means that it is a noun. Therefore, the type should also be named by nouns or noun groups.
A type defines properties and behaviors. It contains the behavior, but not the behavior itself. So, some of the following names are good names for types:
Orderprocessor;
Scoremanager;
Courserepository;
UserControl;
DomainService;
Accordingly, the type name below is considered a bad example:
Orderprocess
Scoremanage
Coursesave
Controlinit
Domainprovide
The name of a verb class is more like a behavior within a type than the type itself.
3: Name the interface with the adjective group
The interface specification is "can do", which means that it regulates what types can behave. Therefore, the name of the interface should be an adjective group, such as:
IDisposable, which indicates that the type can be released;
IEnumerable, which indicates that the type contains items and can be iterated.
It is because the interface represents the behavior of a type, so semantically we can let the type inherit multiple interfaces, such as:
Class sampleclass:idisposable, Ienumerable<sampleclass>
{
//Omit
& nbsp; #region Implementation IDisposable
public void Dispose ()
{
& nbsp; throw new NotImplementedException ();
}
#endregion
#region Implement IEnumerable
public ienumerator<sampleclass> GetEnumerator ()
{
throw new NotImplementedException ();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator ()
{
throw new NotImplementedException ();
#endregion
}
The above code is written in a language that is both grammatical and semantically consistent. If we name the interface Idisposal, the misunderstanding is that the type is a class, not an interface, although we prefix I in front, but still feel that it is semantically consistent.
However, there are some exceptions to this rule in the FCL, such as the IEnumerator interface. However, this situation is relatively small, in most cases we need to always consider using adjectives to name the interface.
4: Name enum type in plural, name enumeration element in singular
An enumeration type should have a plural form, which expresses the semantics of combining a set of related elements. Like what:
Enum Week
{
Monday,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday,
Sunday
}
Here, week has a plural meaning for the day of the week. If we change week to day here, then the code in the call will change to the following:
Day.monday
It's not as straightforward as the following code:
Week.moday
5: Naming public elements with pascalcasing
The properties, fields, and methods that are open to the caller should be named PascalCasing, such as:
Class Person
{
public string FirstName;
public string LastName;
public string Name
{
Get
{
return string. Format ("{0} {1}", FirstName, LastName);
}
}
public string GetName ()
{
return Name;
}
}
In this way, the caller's code in the caller looks like this:
Person. Name
If we don't pay attention to such a naming convention, let the caller's code look like this:
Person.name
We'll start by wondering what the name is and, secondly, its accessibility.
6: Name private fields and local variables with camelcasing
Private fields and local variables are only responsible for this type, and they also adopt and open different methods of properties and fields in the naming scheme. Camelcasing is well suited for this type of naming.
The difference between camelcasing and pascalcasing is that its initials are lowercase. Two different naming conventions are used to make it easier for developers to differentiate them quickly.
In recommendation 123 We give a naming example for the public element, and the following example is an example of a private field and a local variable:
Class Person
{
private string FirstName;
private string LastName;
public string Name
{
Get
{
return string. Format ("{0} {1}", FirstName, LastName);
}
}
private int dosomething (int a, int b)
{
int iTemp = 10;
Return a + B + iTemp;
}
}
In this example, we can see that all private fields, including the method's parameters and local variables, all follow the camelcasing rules of the first letter lowercase. Once we get out of this rule, it's easy to confuse ourselves in the coding process. What is FirstName, is it not a private field, but an open attribute? It's too confusing and scary, because as a developer we have to go back to the name of the variable to know the scope of its access.
7: Consider using affirmative phrases to name Boolean properties
The Boolean value is nothing more than true and false, so it should be represented by a positive phrase, such as: The IS, Can, and has as the prefix.
An example of correctly naming a Boolean property is as follows:
Class SampleClass
{
public bool IsEnabled {get; set;}
public bool Istabstop {get; set;}
public bool AllowDrop {get; set;}
public bool IsActive {get;}
public bool? IsChecked {get; set;}
}
All of these names come from. NET the most recent subset of WPF, where AllowDrop, although not prefixed with a positive phrase, expresses a meaning of whether or not as an action, so it is also a recommended name for a Boolean attribute.
The following are the negative names of Boolean attributes:
Class SampleClass
{
public bool Checked {get; set;}
public bool Loaded {get; set;}
}
Affirmative adjectives or phrases express a definite meaning, but these words or phrases are now used to name events or delegate variables, so they should not be used for Boolean properties.
Three: Code Neat
1: Always provide meaningful naming
Never give your code a meaningless name unless it's malicious.
Afraid of needing too long a name to provide enough meaning? Do not be afraid, in fact, we would prefer to read the code when there is a itemp.
The naming method of int I should only appear in loops (such as for loops), except that we cannot find any reason to make such a meaningless name elsewhere in the code.
2: Method abstraction level should be at the same level
The abstraction level of a method should be at the same level, let's look at the following code:
Class SampleClass
{
public void Init ()
{
Local initialization Code 1
Local Initialization Code 2
Remoteinit ();
}
void Remoteinit ()
{
Remote Initialization Code 1
Remote Initialization Code 2
}
}
The Init method is intended to complete the initialization action, and initialization includes both local initialization and remote initialization. In this code, the internal code of the Init method is organized by the local initialization code that runs directly inside the method, while the remote initialization code is encapsulated as a method to be called here. This is obviously not appropriate, because local initialization and remote initialization are quite the place. As a method, if the remote initialization code exists as a method, the local initialization code should also exist as a method.
Therefore, the above code should be refactored to:
Class SampleClass
{
public void Init ()
{
LocalInit ();
Remoteinit ();
}
void LocalInit ()
{
Local initialization Code 1
Local Initialization Code 2
}
void Remoteinit ()
{
Remote Initialization Code 1
Remote Initialization Code 2
}
}
The reconstructed code looks clear and the abstraction level of all the methods is at one level, and as a reader we look at what the Init method has done.
3: A way to do one thing
The single Responsibility principle (SRP) requires that each type is responsible for only one thing. We extend this concept to a method, and it becomes: one way to do it.
What kind of code is called "doing the same thing"? Referring to the code in the previous recommendation, where the Localinit method and the Remoteinit method are two things, but at the same level of abstraction, it is possible for the type to be merged into the "Initialize" thing. Therefore, the "same thing" depends on the position of abstraction.
The following method has done too many things, so let's look at the actual code:
private UINT status;
private UINT Developerid;
private UINT Flags;
public string Checkdogandgetkey ()
{
Flags = Sentinelkey.sp_standalone_mode;
Status = Osentinelkey.sfntgetlicense (Developerid, Osentinelkeyslicense.software_key, Sentinelkeyslicense.licenseid , flags);
if (Status! = sentinelkey.sp_success)
{
throw new FileNotFoundException ("No legal dongle checked, or driver not properly installed");
}
Status = Osentinelkey.sfntreadstring (Sentinelkeyslicense.sp_1st_string, Readstringvalue, MAX_STRING_LENGTH);
if (Status! = sentinelkey.sp_success)
{
throw new FileNotFoundException ("failed to read the dongle data");
}
Return System.Text.Encoding.ASCII.GetString (Readstringvalue). Substring (0, 7);
}
In method Checkdogandgetkey, the method is responsible for detecting whether the dongle is properly installed and is responsible for reading the relevant information from the dongle. Obviously, this makes checkdogandgetkey, too much responsibility. We can consider refactoring the method to the following two methods:
void Checkdog ()
{
flags = Sentinelkey.sp_standalone_mode;
status = Osentinelkey.sfntgetlicense (Developerid, Osentinelkeyslicense.software_key, Sentinelkeyslicense.licenseid, flags);
if (status! = sentinelkey.sp_success)
{
throw new FileNotFoundException ("No legal dongle checked, or driver not installed properly");
}
}
String Getkeyformdog ()
{
status = Osentinelkey.sfntreadstring ( Sentinelkeyslicense.sp_1st_string, Readstringvalue, max_string_length);
if (status! = sentinelkey.sp_success)
{
throw new FileNotFoundException ("failed to read dongle data");
}
return System.Text.Encoding.ASCII.GetString (Readstringvalue). Substring (0, 7);
}
After refactoring, each method is responsible for just one thing. And, judging from the name, Checkdog is responsible for detecting the dongle, while Getkeyformdog is responsible for obtaining information.
4: Avoid too long methods and too long classes
If you do not follow the "one way only" and the type of "single responsibility Principle", you tend to produce too long methods and too long classes.
If the method is too long, it means that several smaller methods can be reconstructed at a higher level. So, are there any specific indicators to suggest that the method is too long? Yes, it is the number of rows to do the indicator, it is suggested that a method not more than 10 lines, it is recommended not more than 30 lines. Of course, there is no single standard, and it seems to me that if a method needs a scrolling screen in Visual Studio to read it, it must be a bit too long to reconstruct it.
For types, the type code should not exceed 300 lines unless there is a very special reason. If the number of rows is too many, consider the possibility of refactoring.
5: Only the necessary operations are announced
The methods and attributes that are not necessary to be disclosed are private. If you need to expose more than 9 methods and properties, the default settings for Visual Studio require a scrolling screen to be displayed in IntelliSense, to view the graph:
In the We can see that IntelliSense in the visible scope of the method for us also includes the 3 methods inherited from the object, the actual real in this example can show us the valuable information only 6. The entire code for the sample type is as follows:
Class SampleClass
{
int field1;
int field2;
int field3;
public int MyProperty1 {get; set;}
public int MyProperty2 {get; set;}
public int MyProperty3 {get; set;}
public int MyProperty4 {get; set;}
public int MyProperty5 {get; set;}
public int MyProperty6 {get; set;}
public void Mehtod1 ()
{
}
public void Mehtod2 ()
{
}
public void Mehtod3 ()
{
}
}
If we add more public properties or methods to SampleClass, it means that we increase the lookup cost when using IntelliSense.
If we are going to public or internal a method, please consider this necessity carefully. Remember, Visual studio defaults to the access modifiers for the type members we generate are private, and in my opinion, this is what Microsoft is suggesting to us: close access unless necessary.
In addition to the class members, the types are the same, and the types that should not be exposed to other projects should be set to internal. Think of the type default access limiter is internal, which means that type should be open only to the project if we don't intentionally. So, by following this rule, this will make our API look a lot fresher.
Four: Code specification static Check tool
In addition to our own customary norms, there are, of course, static inspection tools in the world to help us analyze whether our code conforms to certain specifications. For now, our habitual practice is to use STYLECOP to help us perform static checks of code specifications.
What is STYLECOP?
StyleCop's early years were Microsoft's own internal static code and mandatory formatting tools. Although some of Microsoft's open-source projects are running out of STYLECOP, we still notice a lot of warnings (and of course, we can also understand that the MS projects themselves define some of their own specifications). Its official address is:
Http://archive.msdn.microsoft.com/sourceanalysis
At this point in this section, the current version is: StyleCop-4.7.44.0, let's take a look at how to use StyleCop for code checking.
Note: The specification settings file used in the video is: Http://back.zuikc.com/Settings.zip
V: Video
Non-public section, please contact the best course (www.zuikc.com)
C # 0 Basic Primer 08: Code specification