代码规范是最容易被忽视的一项技能。对于领导和开发者来说,实现业务需求并且没有Bug才是最终目的。假如没有健全的Code review机制,项目很容易沦为“Shit mountain”。
相信我们大多数人接触编程的第一门语言是C语言。C语言是一门优秀的面向过程语言,我们可以通过使用基础的数据结构与程序流程来学习编程。因此有些同学会养成命令式编程习惯,例如我们通常会看到这样的程序:
If(…)
//do some thing
If(…)
//do some thing
Else
//do some thing
//do some thing
//do some thing
随着时间的推移,这段代码经手的人越来越多,这个方法也越来越长。
写出整洁的代码是一件很简单,但又没有明确标准的一件事,假如你正好接手了一个代码很规范的项目的话,会学习的很快。我只能通过一些原则性的,理论性的要求,以及工作中的所见所感,给出一些建议。
函数式编程原则性要求:
- 避免参数突变,即无论当前方法的入参是值类型或是引用类型,都应该将其视为不可变类型,应将目标结果作为方法的返回值。常见错误有void FillOrderInfo(Order order)等。应该使用order.BuildInfo(…);或 Order GetOrderDetail(…);等方式。
- 编写合适的高阶函数。即接受委托(方法)作为入参,或者以委托(方法)作为返回值的函数。如Linq中的Where,Select等。
- 编写可测试的代码,即纯函数。纯函数指的是结果只由入参决定的函数,假如你函数中使用了DataTime.Now, 因为它会获取外部操作系统时间,因此会导致当前函数依赖外部环境,不是纯函数。应在外部获取当前时间,作为参数传入,类似行为还有数据库查询,网络调用等。
函数式编程提倡一行函数,C#本身新语法也在往函数式编程方向发展,比如C#9.0中的Init,*语句,记录类型以及之前的模式匹配等,无不展示这些程序设计理念。
业务代码:
- 任何一个方法不要超过50行,十行以内最好,养成分层拆分抽象的习惯,特殊算法等除外。
- 用不着的代码统统删掉,即使希望备份,也不要注释之后留在项目里。
- 要正确使用public 和private。
- 一个.cs文件中应只定义一个接口,或者类型。具有关联关系的两种类型应以子文件夹和命名的方式进行逻辑关联。
如:Event/OrderUpdateEvent.cs; Handler/ OrderUpdateHandler.cs。
- 方法签名即方法设计要尽可能缩小参数范围。
错误示范:
DbContext AddDbContext<T>(Configure conf)
{
connString = conf[“ConnString”];
// do some thing;
}
正确写法:
DbContext AddDbContext<T>(string connString)
{
// do some thing;
}
- 网络接口定义与调用应遵守基本的RESTful规范(不要把Post请求体拆成键值对附加在Url中的!)。
- 异步方法应返回Task,Task<T>, 且最好以Async结尾来命名,如 Task<T> QueryOrderAsync(string id)。
- 尽可能的减少分支复杂度,即将多个if-else改为switch,或使用策略模式等。
- 推荐使用if的中断模式,即if(…) return; 而不是if(…) { //do some thing; }
- 编写简洁的属性,对于TotalPrice,IsValid等需要计算或逻辑判断得出的值,可以灵活使用只读属性{get=>…;}
- 注意I/O请求是否写在了循环当中。
- 可以使用扩展方法,尽量避免使用静态类,字段等。
- 任何变量,函数,类型等命名都要认真且简洁。非共识情况,不许使用简写,缩写,无意义字母,汉字(单元测试除外)等。
要对当前的开发技术有一个较全面的了解,并灵活使用:
- 使用IOC容器,依赖注入。
- 使用EventBus来优化代码。
- 使用AutoMapper来做实体映射。
- 能使用ORM就不要使用SQL。
- 使用Polly来做故障处理。
- 当配置项过多时考虑引入或设计一个配置管理平台。
- 学习领域驱动设计。
- ......