1DateTime begin = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day - 1, GlobalSetting.BeginTime, 0, 0);
2db.AddInParameter(command, "begintime", DbType.String, begin);
3db.AddInParameter(command, "endtime", DbType.String, begin.AddDays(1));
2db.AddInParameter(command, "begintime", DbType.String, begin);
3db.AddInParameter(command, "endtime", DbType.String, begin.AddDays(1));
这是我们项目里面的一段“垃圾”代码,能够发现这段代码,完全仰仗于我们每个月要做的日志检查。
稍微对代码做一些解释:这段代码的作用就是查找当前日期的某个时间点开始到前一天同一个时间点之间的数据。GlobalSetting.BeginTime是一个从配置文件中读取的时间点。
我们在日志中发现,这个程序每个月的1日都要抛出异常,按图索骥,就找到了这段代码。
见到了红色部分之后,我真的是又好气又好笑。这位程序员真的对.net理解人类语言的能力有些过于期待了,理所当然的认为:今天的前一天,就是今天减1天。而且这段代码顺利的通过了单元测试以及测试人员的测试,因为,我们测试的日期不是1日。直到程序跑在生产环境上报错之后,我们才有机会发现这个Bug。
在我看来,这段代码有以下3个问题:
1.致命错误
天数减1当作参数传递给DateTime,在每个月1日的时候,天数变为0,DateTime的构造函数抛出异常。其实要获得某个DateTime的日期部分,完全可以使用DateTime自带的属性Date,何必这么复杂的取了年份、取了月份、最后取了日期当参数重新new出来一个DateTime呢,还引入这个致命的错误。
所以,请在实现功能的时候仔细翻一翻MSDN,也许.net早已做过你想做的事情了。
2.性能损失
第3行,为了获得结束日期,begin被加上了1天。但是我们明明在第1行的时候为了获得开始日期减去过一天啊。为什么不在第1行的时候直接获得结束日期,然后在第2行的时候把这个结束日期减去1天的值当作开始日期,第3行的时候直接拿结束日期当作参数呢?减少了一次计算也许不算什么,但是在整个程序中,运行效率都是因为这样一个“不算什么”,那样一个“不算什么”才慢慢的降低的。
所以,请在写代码的时候稍微动动脑筋,虽然.net效率不高,但是不要因为自己的原因造成代码的执行效率低下。
3.潜在风险
第1行代码连续3次调用DateTime.Now有可能造成时间差,如果恰好在2007年12月31日23:59:59.999999调用了一次,第二次调用的时候日期就变成了2008年1月1日。
而且每次进行属性调用,消耗的系统资源也是一个可观的数字。
所以,请坚持在某个属性会被无变化的调用两次或者两次以上的时候,使用用这个属性赋值的局部变量。
====================
以上纯属个人经验,欢迎拍砖。