注意编码工作中的小细节

人们常说“细节决定成败”。

编码工作中,同样需要关注细节。

本文将给出3个小实例来说明编码中关注细节的重要性,同时给出作者对如何注意编码细节的一点见解(说的不对,请指正)。

这个问题如此地显而易见,竟然没有被发现。

[csharp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. List<int> numList = new List<int>();  
  2. numList.Add(3);  
  3. numList.Add(1);  
  4. numList.Add(4);  
  5. numList.Add(2);  
  6. numList.Add(5);  
  7. numList.OrderBy(it => it).ToList();  
  8. foreach (int i in numList)  
  9. {  
  10.        Console.WriteLine(i);  
  11. }  
在阅读项目代码时,发现了一段类似于例1的代码。代码的本意是想对集合numList排序并将排序后的集合元素一一输出,但实际情况是numList调用OrderBy方法进行排序后却没有将排序的结果赋值给任何对象,而是直接遍历源集合numList输出其中元素,这样做显然得到的不是最初想要的,因为输出的仍是排序前的集合中元素。猜想当时编码者写出这样的代码,主要是因为编码者误认为调用OrderBy方法对集合排序后会将排序结果保存在被排序的集合中,而事实却不是这样。这个小错误应该是显而易见的,但是当时竟然没有被人发现,还是后来出现了BUG才发现了这个编码问题,还好,BUG及时修复了没造成太大的问题,不然就等着哭吧。列举此实例是想告诉大家:不注意细节会让我们的代码危机四伏。而犯一些低级错误正是不注意细节的最初级表现。少犯低级错误是关注细节的良好开端。

 

例2 当时要是考虑得再多一点,问题也就不会出现了。

[csharp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5.    
  6. namespace NoticeDetailExp4  
  7. {  
  8.     class Program  
  9.     {  
  10.         static void Main(string[] args)  
  11.         {  
  12.             //这里的left、top、width、height被写死了,实际情形中是通过某种计算产生的  
  13.             double width = 1.5;  
  14.             double height = 1.5;  
  15.             double left = 0;  
  16.             double top = 0;  
  17.             if (width != 0 && height != 0)  
  18.             {  
  19.                 Rectangle r = ExampleMethod(left, top, width, height);  
  20.             }  
  21.         }  
  22.    
  23.         public static Rectangle ExampleMethod(double left, double top, double width, double height)  
  24.         {  
  25.             return new Rectangle(left, top, width, height);  
  26.         }    
  27.     }  
  28.    
  29.     public class Rectangle  
  30.     {  
  31.         private double left;  
  32.         public double top;  
  33.         public double width;  
  34.         public double height;  
  35.         public Rectangle(double left, double top, double width, double height)  
  36.         {  
  37.             if (width <= 0 || height <= 0)  
  38.             {  
  39.                 throw new InvalidOperationException();  
  40.             }  
  41.             this.left = left;  
  42.             this.top = top;  
  43.             this.width = width;  
  44.             this.height = height;  
  45.         }  
  46.     }  
  47. }  

本例中定义了矩形类Rectangle,Rectangle类的构造函数接收四个参数left,top,width,height来生成Rectangle对象,在生成Rectangle对象时会对输入参数width、height进行校验,当二者中有一个小于等于0时便会抛出无效操作的异常(矩形的长度和高度必须大于0)。再看Rectangle类的实例化代码,调用Rectangle类的构造函数进行实例化前,先对width和height的值进行校验,当width与height的值都不等于0时就调用Rectangle类的实例化方法。这样一来,问题就来了,Rectangle构造函数中要求的width与height的值必须大于0,而在类的实例化前,我们判断width、height值是否合法的条件却是width、height值不等于0,这样一来当我们传入负值时便同样会导致无效操作的异常。当时编码者在实例化Rectangle类时可谓是信心满满地认为width、height值是不会小于0 的,但是不幸的事还是发生了,在某种极端条件下这里的width、height的值小于0了,自然而然出现了BUG。这个例子说明:有些时候我们过于相信自己的判断其实也是忽略细节的另一种表现,要想编码工作尽量趋于完美,我们就应该尽量想得远一点,对于某种解决方案只要有更保险的解决办法时,我们还是应该采用更保险的解决方案。

 

例3 找个最好的实现方案,感觉真的很美好

[csharp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4.    
  5. namespace NoticeDetailExp2  
  6. {  
  7.     class Program  
  8.     {  
  9.         static void Main(string[] args)  
  10.         {  
  11.             List<Work> WorkList = new List<Work>();  
  12.             WorkList.Add(new Work() { Name = "Work1", StartDate = new DateTime(2013, 12, 7), EndDate = new DateTime(2013, 12, 9) });  
  13.             WorkList.Add(new Work() { Name = "Work2", StartDate = new DateTime(2013, 12, 4), EndDate = new DateTime(2013, 12, 7) });  
  14.             WorkList.Add(new Work() { Name = "Work3", StartDate = new DateTime(2013, 12, 7), EndDate = new DateTime(2013, 12, 14) });  
  15.             WorkList.Add(new Work() { Name = "Work4", StartDate = new DateTime(2013, 12, 5), EndDate = new DateTime(2013, 12, 14) });  
  16.             WorkList.Add(new Work() { Name = "Work5", StartDate = new DateTime(2013, 12, 4), EndDate = new DateTime(2013, 12, 5) });  
  17.             WorkList.Add(new Work() { Name = "Work6", StartDate = new DateTime(2013, 12, 13), EndDate = new DateTime(2013, 12, 14) });  
  18.             DateTime dt1 = new DateTime(2013, 12, 6);  
  19.             DateTime dt2 = new DateTime(2013, 12, 12);  
  20.             var needList = WorkList.Where(it => !(it.StartDate > dt2 || it.EndDate < dt1));  
  21.             foreach (var work in needList)  
  22.             {  
  23.                 Console.WriteLine(work.Name + "," + work.StartDate + "," + work.EndDate);  
  24.             }  
  25.         }  
  26.    
  27.         public class Work  
  28.         {  
  29.             public string Name { getset; }  
  30.             public DateTime StartDate { getset; }  
  31.             public DateTime EndDate { getset; }  
  32.         }  
  33.     }  
  34. }  

实例3主要是想实现:筛选出WorkList中满足条件的作业。条件是:作业时间与给定的时间区间[dt1,dt2]存在交集(具体见下图所示)。


 

图中的红色线条代表给定的时间区间[dt1,dt2],(1)-(6)代表所有类型的作业(按照时间跨度区分的作业),很显然图中的(1)、(2)、(3)、(4)的作业满足条件应该被筛选出,而剩下的(5)、(6)应该被排除在外。那这个筛选条件用代码该怎样实现呢,至少有两种实现方法。

方案1:

[csharp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. var needList = WorkList.Where(it =>   
  2.     (it.StartDate < dt1 && it.EndDate > dt1)     //(1)  
  3.     || (it.StartDate > dt1 && it.EndDate < dt2)  //(2)  
  4.     || (it.StartDate > dt1 && it.EndDate > dt2)  //(3)  
  5.     || (it.StartDate < dt1 && it.EndDate > dt2));//(4)  

方案2:

[csharp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. var needList = WorkList.Where(it => !(it.StartDate > dt2 || it.EndDate < dt1));  

本例中采用方案2,方案2是先找到(5)、(6)类作业,再将(5)、(6)类作业从集合中排除。而方案1则是直接从集合中找出(1)、(2)、(3)、(4)类作业。采用方案1写出的条件表达式较复杂,稍不注意便会出错,而采用方案2的代码简单而同样不难理解,综合考虑,选择了方案2。例3主要是想告诉大家:其实每个问题往往都有很多种解决方案,选择一个最好的方案,同样是注意细节的一种表现。

 

好了,本文列举了3个实例说明了编码过程中注意细节的重要性,并得出了自己的一点看法:关注细节,首先不要犯一些低级错误,其次就是要尽量考虑远一点(预知风险),最后就是能够选择最优的解决方案。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值