Enum引发的血案,反思
来源:互联网 发布:方舟生存进化低配优化 编辑:程序博客网 时间:2024/05/20 18:18
前几天公司产品更新版本,更新完后不少用户反应原先保存的report的一些表在新版本打开后设置突然变了,本来选的第六个,现在打开变成第四个了。领导要求赶紧查出原因修改好,发紧急补丁。啊啊。。发紧急补丁可是影响team的performance的,年终奖要打折扣了。。
问题是很容易就查到了,那些设置是用Enum表示的,如下:
1 public enum PeergroupRanks 2 { 3 VSBenchmark, 4 VSBenchmark2, 5 CalBenchmark, 6 PeersBeaten, 7 NumPeergroupBeaten, 8 PeergroupRank, 9 NumPeergrouprank,10 PeergroupPercentile,11 PeergroupDecile,12 PeergroupQuintile,13 PeergroupQuartile,14 15 PeergroupRankOfCount,16 }
一位同事做新feature时加了上面红色的两个,由于存report的时候对于这个Enum只是简单的转成int存起来,大家都知道Enum默认是从0开始,按顺序来,原先存的第6个是PeergroupPercentile,report里存的就是数字5,新加了两个在上面后,数字5就解析成PeergroupRank了。
分析这个问题,觉得这个应该算是代码本身有漏洞,同事不小心踩到了,因为这位同事想法也不能说错,把同一个类型的放到一起,都是Benchmark,代码可读性强。
其实项目里大部分代码对Enum是有所防范的,如:
1 public enum DisplayBenchmark 2 { 3 None, 4 Benchmark1, 5 Benchmark2, 6 CategoryAverage, 7 CalcBenchmarkId, 8 CalcBenchmarkType, 9 CalcBenchmarkCdp,10 }11 12 public static class DisplayBenchmarkCode13 {14 const string BENCHMARK1 = "bm1";15 const string BENCHMARK2 = "bm2";16 const string CATEGORY = "ca";17 18 public static DisplayBenchmark Parse(string code)19 {20 switch (code)21 {22 case BENCHMARK1:23 return DisplayBenchmark.Benchmark1;24 case BENCHMARK2:25 return DisplayBenchmark.Benchmark2;26 case CATEGORY:27 return DisplayBenchmark.CategoryAverage;28 }29 return DisplayBenchmark.Benchmark1;30 }31 32 public static string Convert(this DisplayBenchmark type)33 {34 switch (type)35 {36 case DisplayBenchmark.Benchmark1:37 return BENCHMARK1;38 case DisplayBenchmark.Benchmark2:39 return BENCHMARK2;40 case DisplayBenchmark.CategoryAverage:41 return CATEGORY;42 }43 return BENCHMARK1;44 }45 }
在report里存的是DsiplayBenchmarkType.Convert成的字符串,解析时再Parse,这样更安全,增加Type的同时也要增加相应的Code,一一对应。
当然,在Enum里写上具体值也是可行的,如:
1 public enum PeergroupRanks2 {3 VSBenchmark=0,4 VSBenchmark2=1,5 CalBenchmark=2,6 PeersBeaten=3,7 }
还有人觉得直接用const string就好,个人以为Enum的强类型还是比string好,string的可能性比较多,直接用字符串比较也行,用其他同样string的变量比较也行,没有唯一性,而Enum只能是相同的Type进行比较。
类似的问题的还有hashcode,hashcode会不会变也是依赖于.net framework的算法,谁也不能保证以后算法不会变,所以hashcode也不要做为key存起来,否则后期要改会变得很困难,因为还需要兼容以前存的档案。
另外多语言下的数字也是值得注意的,欧洲那边很多国家的小数点是用逗号表示,分隔符用点号,和我们正好相反,如: 123.456,78 ,这种情况就需要以固定格式存下来,比如ToString时用CultureInfo.InvariantCulture,这样跟区域语言无关,解析时也一样是固定格式解析,double.Parse(value, CultureInfo.InvariantCulture)。显示在界面时就需要用当前的语言格式来显示,总不能给西班牙人看我们常用的小数格式,CultureInfo.CurrentCulture这是当前线程的语言格式,用这个就可以了。
总结起来,要持久化存起来并且需要解析还原的东西是不能变的,保存前是什么状态解析后也要还原这个状态,所以Enum一定要写上值或做转换再存,同样还有hashcode,情愿存长一些的字符串也不要存hashcode(自定义的算法无所谓哈),多语言应用下的小数也需要注意保存和显示的区别。
然后就是上面看到的,同样的项目中绝大部分Enum都做了防范,小部分因为代码规范问题,没能保持一致才出了问题,所以个人觉得这些问题属于基本代码规范问题,在项目设计时就决定好了,每个人不管是老同事还是新进来的同事都需要遵守规范,这样的项目代码更安全,可持续性也更好。
规范的目标是让项目的代码看起来像是一个人写的,团队好的coding风格也会积极影响所有成员。
- Enum引发的血案,反思
- Gitlab:一场“删库”血案引发的反思
- ActiveX引发的“血案”
- size_t引发的血案
- 一个 * 引发的血案
- gets引发的血案
- Print 引发的“血案”
- lease引发的血案
- 一个“-”引发的血案
- MD5引发的血案
- 一个"/"引发的血案
- wrap_content引发的血案
- merge_all引发的血案
- PersistableBundle引发的血案
- 看球引发的血案
- 一个松果引发的血案
- 一个memset引发的血案
- 一条语句引发的血案
- centos7 上mysql的管理
- VoiceOver的使用
- java S2SH项目框架整合搭建实例教程
- fl2440 2.6.35移植触摸屏驱动错误
- web 前端 标签相关
- Enum引发的血案,反思
- localStorage 保存对象Object
- Android 内功心法(番外)——写在设计模式前,面对对象编程基础
- vs中debug和release版本的区别
- 【连载】关系型数据库是如何工作的?(8) - 客户端管理器
- 开发坏境搭建
- 好的SQL习惯
- 用CSS3动画,让页面动起来
- SQLite数据库简介