手记

如何编写更好的C#代码

引言

开发人员总是喜欢就编码规范进行争论,但更重要的是如何能够在项目中自始至终地遵循编码规范,以保证项目代码的一致性。并且团队中的所有人都需要明确编码规范所起到的作用。在这篇文章中,我会介绍一些在我多年的从业过程中所学习和总结的一些较好的实践。

举例为先

我们先来看一个 FizzBuzz 示例。FizzBuzz 要求编写一个程序,遍历从 1 到 100 的数字。其中如果某数字是 3 的倍数,则程序输出 “Fizz”。如果某数字是 5 的倍数,则输出 “Buzz”。如果某数字即是 3 的倍数也是 5 的倍数,则输出 “FizzBuzz”。如果数字既不是 3 的倍数也不是 5 的倍数,则只需输出该数字本身。


示例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         else
18         {
19           Console.WriteLine(i);
20         }
21       }
22     }

什么感觉?这段代码需要改进吗?

示例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     }

现在感觉如何?还能不能进一步改进?

好,让我们来尝试改进下。代码命名对所有软件开发人员来说都是件非常困难的事情。我们花费了大量的时间来做这件事,而且有太多的需要被命名的元素,例如属性、方法、类、文件、项目等。不过我们的确需要花费一些精力在这些命名上,以使代码中的名称更有意义,进而可以提高代码的可读性。

 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     }

这次感觉怎样?是不是比之前的示例要好些?是不是可读性更好些?

什么是更好的代码?

首先就是代码要为人来编写,其次是为机器。从长期来看,编写可读性好的代码不会比编写混乱的代码要花费更长的时间。如果你能够非常容易地读懂你写的代码,那么想确认其可以正常工作就更容易了。这应该已经是编写易读代码足够充分的理由了。在很多情况下都需要阅读代码,例如在代码评审中会阅读你写的代码,在你或者其他人修复Bug时会阅读你写的代码,在代码需要修改时也会读到。还有就是当其他人准备在类似的项目或有类似功能的项目中尝试复用你的部分代码时也会先阅读你的代码。

“如果你只为你自己写代码,为什么要使代码更具可读性?”

好,编写易读的代码最主要的原因是,在未来的一到两周,你将工作在另一个项目上。而此时,有其他人需要修复当前项目的一个Bug,那么将会发生什么?我敢保证他肯定会迷失在你自己编写的恐怖代码中。

从我的个人观点来看,好的代码应该拥有以下几个特征:

  • 代码容易编写,并易于修改和扩展。

  • 代码干净,并表述准确。

  • 代码有价值,并注重质量。

所以,要时刻考虑先为人来编写代码,然后再满足机器的需要。


如何改进可读性?


首先,你需要阅读学习其他人编写的代码,来了解什么是好的代码,什么是不好的代码。也就是那些你感觉非常容易理解的代码,和感觉看起来超级复杂的代码。然后,进行实践。最后花费一些时间、经验和实践来改进你的代码的可读性。一般来讲仅通过培训这种方式,在任何软件公司中推动编码规范都有些困难。而诸如结对代码评审,自动化代码评审工具等也可以帮助你。目前流行的工具有:

  • FxCop:对 .NET 代码进行静态代码分析,提供了多种规则来进行不同形式的分析。

  • StyleCop:开源项目,其使用代码风格和一致性规范来对分析C#代码。可在 Visual Studio 中运行,也可以集成到 MSBuild 中。StyleCop 也已经被集成到了一些第三方开发工具中。

  • JetBrains ReSharper:非常著名的提升生产力的工具,可以使 Microsoft Visual Studio IDE 更加强大。全世界的 .NET 开发人员可能都无法想象,工作中怎么能没有 ReSharper 的代码审查、代码自动重构、快速导航和编码助手等这些强大的功能呢。

规范是什么?


依据维基百科上的描述:"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 practices, programming principles, programming rules of thumb, architectural 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 documented 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."。

你应该能说出属性、局部变量、方法名、类名等的不同,因为它们使用不同的大小写约定,所以这些约定非常有价值。通过互联网,你已经了解了很多相应的准则和规范,你所需要的仅是找到一种规范或者建立你自己的规范,然后始终遵循该规范。

下面使用到的源代码(类库设计准则)是由微软的 Special Interest Group 团队开发的,我只是做了些扩展。

大小写约定

下面是一些关于C#编码标准、命名约定和最佳实践的示例,可以根据你自己的需要来使用。

Pascal Casing

标示符中的首字母,后续串联的每个单词的首字母均为大写。如果需要,标示符的前几个字母均可大写。

Camel Casing

标示符的首字母为小写,后续串联的每个单词的首字母为大写。


一些命名约定示例

在互联网上你可以找到足够多的资源,我只是推荐几个其中我最喜欢的:

  • C# 编码约定

  • C# 编码准则

  • C# 编码标准和最佳实践

  • C# 编码规范和命名约定

这里我展示了一些最基本的示例,但就像我上面已经提到的,找到一个适合你的规范,然后坚持使用。

使用 Pascal Casing 为类和方法命名。



   public class Product
   {
     public void GetActiveProducts()
     {
       //...
     }
     public void CalculateProductAdditinalCost()
     {
       //...
     }
   }

使用 Camel Casing 为方法的参数和局部变量命名。



   public class ProductCategory
   {
     public void Save(ProductCategory productCategory)
     {
       // ...
     }
   }

不要使用缩写语。

   // Correct
    ProductCategory productCategory;

    // Avoid
    ProductCategory prodCat;

不要在标示符中使用下划线。

   // Correct
    ProductCategory productCategory;

    // Avoid
    ProductCategory product_Category;

在接口名称前使用字母 I 。

public interface IAddress    {    }

在类的顶端定义所有成员变量,在最顶端定义静态变量。

 public class Product
 {
   public static string BrandName;

   public string Name { get; set; }
   public DateTime DateAvailable { get; set; }

   public Product()
   {
     // ...
   }
 }

使用单数的词汇定义枚举,除非是BitField枚举。

public enum Direction
 {
   North,
   East,
   South,
   West
 }

不要为枚举名称添加Enum后缀。

  //Avoid
  public enum DirectionEnum
  {
    North,
    East,
    South,
    West
  }
0人推荐
随时随地看视频
慕课网APP