几点关于优雅代码风格的描述:
代码简单:不隐藏设计者的意图,抽象干净利落,控制语句直截了当。
接口清晰:类型接口表现力直白,字面表达含义,API 相互呼应以增强可测试性。
依赖项少:依赖关系越少越好,依赖少证明内聚程度高,低耦合利于自动测试,便于重构。
没有重复:重复代码意味着某些概念或想法没有在代码中良好的体现,及时重构消除重复。
战术分层:代码分层清晰,隔离明确,减少间接依赖,划清名空间,理清目录。
性能最优:局部代码性能调至最优,减少后期因性能问题修改代码的机会。
自动测试:测试与产品代码同等重要,自动测试覆盖 80% 的代码,剩余 20% 选择性测试。
如果非要添加的话,建议使用 "_" 单下划线前缀,促进大脑更快速的忽略。
1 public class Job
2 {
3 private DateTime _startTime; // use _ as prefix
4 private DateTime endTime; // no prefix
5
6 public DateTime StartTime
7 {
8 get { return _startTime; }
9 set { _startTime = value; }
10 }
11
12 public DateTime EndTime
13 {
14 get { return endTime; }
15 set { endTime = value; }
16 }
17
18 public long ScheduleId { get; private set; } // or no field needed
19 }
使用缩写,这里的 "sch" 其实是想代表 "schedule",但在没有上下文的条件下谁能想的出来呢?我个人是绝对不推荐使用缩写的,除非是普世的理解性存在,例如 "obj", "ctx", "pwd", "ex", "args" 这样非常常见的缩写。
在局部变量的使用中,我认为有一种使用方式是值得推荐的,那就是 "解释性变量"。当今的编程风格中流行使用 Fluent API,这样会产生类似于下面这样的代码。
简单的说就是让逻辑清晰 先声明在去用
1 if(DateTimeOffset.UtcNow >=
2 period
3 .RecurrenceRange.StartDate.ConvertTime(period.TimeZone)
4 .Add(schedule.Period.StartTime.ConvertTime(period.TimeZone).TimeOfDay))
5 {
6 // do something
7 }
这一串 "." 看着好帅气,但我是理解不了这是要比较什么。可以简单重构为解释性变量。
1 var firstOccurrenceStartTime =
2 period
3 .RecurrenceRange.StartDate.ConvertTime(period.TimeZone)
4 .Add(schedule.Period.StartTime.ConvertTime(period.TimeZone).TimeOfDay);
5
6 if(DateTimeOffset.UtcNow >= firstOccurrenceStartTime)
7 {
8 // do something
9 }
注意参数的顺序
public class Command
2 {
3 public Command(int argsA, int argsB)
4 {
5 }
6
7 public Command(int argsA, int argsB, int argsC)
8 {
9 }
10 }
函数
我们或许都知道,函数命名要动词开头,如需要可与名词结合。而函数设计的要求是尽量只做一件事,这件事有时简单有时困难。
简单的可以像下面这种一句话代码:
1 internal bool CheckDateTimeWeekendDay(DateTimeOffset dateTime)
2 {
3 return dateTime.DayOfWeek == DayOfWeek.Saturday
4 || dateTime.DayOfWeek == DayOfWeek.Sunday;
5 }
复杂的见到几百行的函数也不新奇。拆解长函数的方法有很多,这么不做赘述。这里推荐一种使用 C# 语法糖衍生出的函数设计方法。
上面的小函数其实是非常过程化的代码,其是为类 DateTimeOffset 服务,我们可以使用 C# 中的扩展方法来优化这个小函数。
1 internal static class DateTimeOffsetExtensions
2 {
3 internal static bool IsWeekendDay(this DateTimeOffset dateTime)
4 {
5 return dateTime.DayOfWeek == DayOfWeek.Saturday
6 || dateTime.DayOfWeek == DayOfWeek.Sunday;
7 }
8 }
这样,我们就可以像下面这样使用了,感觉会不会好一些?
1 if(DateTimeOffset.Now.IsWeekendDay())
2 {
3 // do something
4 }