面向对象之数值的悲剧(8月28日会议有感)
枚举的悲剧
枚举基本用法大家应该都很熟悉,在我们去避免硬编码,增强代码可读性,可维护性方面很好用。不过话说枚举底层还是比较复杂的,以前看过一些关于枚举的说明。至少C#里边的枚举是很复杂的,本身是结构类型(值类型)的,而却继承与类System.Enum(引用类型),而引用类型System.Enum派生与值类型System.ValueType。够乱吧,其实话说我也没搞很明白,所以大家千万不要随随便便就说我很了解某个东西之类的话。
好吧,转入正题(写东西喜欢扯,没办法 ╮(╯▽╰)╭)。
先说一下枚举所带来的问题。例如,我们有个类型变量,需要存储到数据库中。当然存储到数据库中的时候,表里边存的肯定还是数值(因为枚举终究还是数值)。
例如定义枚举
public enum Language
{
SimplifiedChinese,,
English,
French,
Japanese
}
然后假定我们有一个用户的名单,这里边有个字段记录这该用户所使用的语言。那么数据库中记录的就可能是 A 0 B 1 C 3 D 0 E 0 F 1 。OK,现在我们需要添加一种语言,我们在枚举中要加一个繁体中文TraditionalChinese,我想很有可能代码会变成成这样子。
public enum Language
{
SimplifiedChinese,
TraditionalChinese,//新添加的繁体中文
English,
French,
Japanese
}
好吧,悲剧就这样诞生了。
数据中所有原来已英语为语言的人都改为繁体中文了!!是不是很崩溃,而且,这个bug的代码错误还隐藏的如此之深,是一个枚举量的顺序所导致的。因为TraditionalChinese 和 1具有了对应关系。
当然这个问题解决起来不是那么复杂,目前,如果不变枚举,有两种方法:
- 直接在添加新的枚举量的时候,补在Japanese后边,不改变原来的顺序
- 硬性指定各个枚举的值
public enum Language
{
SimplifiedChinese=0,
TraditionalChinese=4,
English=1,
French=2,
Japanese=3
}
我不会誓死阻止你使用第一个方法,但是很不建议,因为你无法防范你的朋友不这样做或者忽略这么一条怪异的理由。对于第二个方法,比第一方法来说会好一点(可是看着还是有那么一点不爽),或者,你可以加一个标注“各个已有的值不可修改”╮(╯▽╰)╭
其他解决方案
- 既然是由于数据库中存储数值所导致的,那么我们为什么不直接把枚举.ToString()存进去呢?取出的时候,再做一次强制转换,这样不仅解决了上述问题,而且还是在查看数据库是可读性也增强了不少。
- 换掉枚举
这里说一下换掉枚举,即枚举的替代
我们可以使用静态常量来代替枚举。如下
public static class Language
{
public static readonly string SimplifiedChinese = "SimplifiedChinese";
public static readonly string TraditionalChinese = "TraditionalChinese";
public static readonly string English = "English";
public static readonly string French = "French";
public static readonly string Japanese = "Japanese";
}
调用的时候,也可以像枚举一样,Language.English,可读性和可维护性都是不错的。我们还可以定义一些方法,实现枚举类似的功能。我们也可从.NET的一些设计上看到这些影子 如WebRequestMethods.Http.Put 等为const string(我还没有去想用const string 和 static readonly string 的差异,不过实现思想一样)
。在Android中一些设计上也有类似的思想,例如R类的设计。
那么,在数据库中存储的也就是这些变量对应的字符串,这个地方和上一种方案是相同的,变数值为字符串。
关于枚举就暂时说到这里。
索引的悲剧
问题的起因在于,我们要做一个菜单,菜单都有索引,比如,最初 索引 0 1 2 3 对应的操单操作是 增,删,改,查。在代码中 我们很肯能会依据索引值来判断要执行什么操作(啊,这是多么危险啊)。后来又多一个操作为 清空数据。我们想把它放在菜单项的第一个位置,这样,原有的索引已被打乱,0 1 2 3 所表述的意义已经发生变化了,导致出错。同样的,做一个下拉列表也是同样的问题。解决方案不复杂,通常这里边会提供一个value,我们在创建item 时,会用这个value来唯一标识该item.这样,在添加新数据时,他也有自己唯一的value。当然这个value做的时候,也有一些代码的技巧。比如我们 先定义一些常量,让他们的名字分别标识每个item,然后,将这些item的value赋为这些变量。
像是这样:
private readonly string MenuItemAdd = "0";
private readonly string MenuItemDel = "1";
private readonly string MenuItemUpdate = "2";
private readonly string MenuItemSelect = "1";
private readonly string MenuItemClear = "1";
MenuItem item = new MenuItem("增?加", MenuItemAdd);
MenuItem item = new MenuItem("增?加", MenuItemDel);
当然你可以用一个类去维护这些readonly string(做这个类的时候,千万不要就是一个真正的单独类,这样化,你的项目中必将有很多零散的小类,也会使你崩溃,假如你做的是一个Android 应用程序,或许你可以定义ActivitiesStr类,里边在定义一个 DataMangActivityStr类,这个类里边再写DataMenuItemValueStr类,这样统一维护会好点,至少,我这么认为。)
Ok,这些问题讲完了,大家会说这与面向对象有关系么?还什么面向对象之数值的悲剧,这不是标题党么?
我们来分析一下这些上述问题是怎么出现的,他们的共性是什么
抽象分析
面向对象与数值的悲剧
上述两个问题,很明显,很有 相同之处,基本上为 我们原要以一个数值代表某种含义,然而由于某种改变,这个数值本省代表的含义发生了变化,这样导致出现错误。细想一下,其实我们这种想法还是很普遍的,做标记啊,什么的,传参数是定义1 标识执行A,传2时执行B,或者男为1,女为2,终究都是我们用一个数值(一个不具有实际意义的东西)去代表另外一个具有实际意义的东西。我们又为什么要用 一些不具有实际意义的1 2 3去代表 具有实际意义的物体呢?数字使我们发明出来描述客观世界的没有错,比如说,我们说这里有几个人,有几张桌子,这都没有错。但是,男,女问题,操作类型问题,他们本身根本不具有数值的意义,只不过使我们在为了方便标识二者时候,给他们的代号,在现实世界中,这个对应是根本不存在的。换句话说,这些都是我们人为强加给这些事物的性质,一旦发生改变,我们临时加给这些事物的性质就无法对抗新的变化,导致错误的出现。我们只是在写程序,而不是在描述这个世界,所以,我们的程序永远应对不了这个世界的变化。可我们是如何解决这些问题呢?
想想为枚举量强制赋固定数值的方案,English怎么变,代表的都是英语,然而1 这个数字是无辜的,他要么代表一个人,一张桌子,是一个代表数量东西,与英语没什么关系。所以,一旦后来的人不小心改了以前的某个枚举量的值(因为他不知道这个规则啊,他不可能想像1 与英语的关系,更不能想象把1改成2了英语就变成法语了)。如果我们用一些具有实际意义的string来标识,string 本身就是一个描述性的东西。比如,我描述这是一个desk,那么谁来都知道这是一个desk,(如果我说1,正常的他就不知道是什么意思)。这就是静态常量的解决方案。那个menuitem也是一样的问题,或许更好的是,我们将value也换做是一个字符串?(但至少有一个MenuItemUpdate = "2" 就比原来好点了,只是这个2又让人郁闷了一下 )。这些问题还是很有意思的,不过也常常使人纠结。
我写了这么多,不知道各位看官有没有明白我在说什么。
或许,我们应该去努力描述这个世界,而不是去做程序,去实现某个功能。客观世界是什么,就是什么,我一直这么想。
相关文章:

C++虚函数探索!
C中的虚函数实现了C中的多态。昨天C老师着重讲了讲虚函数。这个很重要,也有点玄机在里面。 下面阐述一下理论: C的类机制中有支持多态的技术来解决抽象编程。使用的是滞后捆绑技术。即预先设定其成员函数虚函数性质,使得任何捆绑该成员函数的…

htc820+android+l,首款高通64位八核 HTC Desire 820评测
9月初的IFA2014展会期间,多款搭载64位处理器的新品智能手机扎堆发布,也算是拉开了64位处理器安卓手机的时代序幕。其中,最引人注目的新品之一莫过于HTC Desire 820,它于北京时间9月4日在德国柏林发布,拔得了全球首款64…

关于正则表达式 g,m 参数的总结,为了回答“正则表达式(/[^0-9]/g,'')中的/g是什么意思?”...
为了解答“正则表达式(/[^0-9]/g,)中的"/g"是什么意思?”这个问题,也为了能够便于大家对正则表达式有一个更为综合和深刻的认识,我将一些关键点和容易犯糊涂的地方再系统总结一下。 总结1:附件参数g的用法 表达式加上参…

那位13岁就当上老板的开发者是如何炼成的?
当我们听到有关年轻有为的企业家的故事时,大多会想到 25 到 30 岁左右的年轻人。毕竟,Google、亚马逊、Facebook、Twitter、LinkedIn、Pinterest、Instagram、Snapchat 以及其它很多公司的创始人都是在他们 20 多岁时创办的这些企业。随着人们与科技的联…

phonegap android,Phonegap 3不适用于Android Studio
对我来说,这似乎很简单,但我根本做不到.我已经成功安装了npm install -g phonegap并安装了phonegap.C:\var\www\sexdiaries.co.uk>phonegap create sexdiaries -n SexDiaries -i co.uk.sexdiaries.app然后,我被告知Here尝试运行andriod但出现以下错误C:\var\www\sexdiaries.…

安装VCenter提示数据库排序规则有问题
安装VCenter提示数据库排序规则有问题 有时候在安装sql server 数据库时你如果修改了排序规则,那么在安装VCenter时它会提示你的数据库排序规则有问题,不让你安装。这个时候你去修改一下数据库规则就可以继续安装了。 解决方法: 1.把安装光盘…

点滴印象中的周其凤校长
原文:[url]http://blog.sina.com.cn/s/blog_4908ded80100bbui.html?tj1[/url]2003年9月,我进入吉林大学读书,第二年周其凤成为吉林大学新任校长。此后的三年,我见过校长两次,这两次,校长的风格给我留下了深…

开源50万行代码,百亿广告分成,百度智能小程序能成吗?
作者 | 非主流出品 | AI科技大本营终于,BAT 在小程序的赛道上展开了激战,而这一场战争得到了百度前所未有的重视。9 月 4 日,百度总裁张亚勤称拉动百度业务的“新四小龙”——智能小程序、信息流、短视频/小视频以及百度云。紧接着࿰…

接近WinHEC 2008
第一次听说windows硬件工程大会还以为微软要讲她出的硬件的一个技术交流大会,后来才了解到是微软公司面向个人电脑终端、服务器、硬件设备以及驱动程序的最具前瞻性的全球硬件技术信息盛会。而不是讲硬件本身,是与硬件相关的软件产品。今年是第17届WinHE…

加深C# 中字符串前加@符号理解以及使用~~
先看代码(以下代码使用在C#,环境ASP.NET): protectedvoidPage_Load(objectsender, EventArgs e) { test1("\a"); test1("\a"); test2("\a"); test2("\a"); test…

鸿蒙系统首批更新机器,鸿蒙系统升级名单
【鸿蒙系统升级名单】华为的鸿蒙系统算是早早放出消息的重量级产品,国产OS的名号也吸引了不少小伙伴的注意。很多朋友都想体验传闻已久的鸿蒙操作系统,但也担心自己的手机无法支持。那么,鸿蒙操作系统的升级名单到底有哪些呢机器呢?下面就让…

公开课报名 | 基于自定义模板的OCR结果的结构化处理技术
随着行业的发展和技术的成熟,文字识别(OCR)目前已经应用到了多个行业中,比如物流行业快递包裹的分拣,金融行业的支票单据识别输入,交通领域中的车牌识别,以及日常生活中的卡证、票据识别等等。O…

产生所有排列---旋转法------2013年1月22日
我觉得这是一个很巧秒的算法。思路非常直接,从代码里可以很容易看出来,再单步调试查看set数组的值就可以很清楚地明白算法的过程。代码如下:1 #include <stdio.h>2 #define MAX 10003 4 int n3; //the number of set element5 int set[MAX]{1,2,3…

VS Code 正在统治代码编辑器领地!
出品:CSDN(ID:CSDNnews)【CSDN编者按】代码编辑器之于程序员的重要性不言而喻。长久以来,Vim、Emacs等老牌编辑器一直占据着举足轻重的地位,但是近年来情况似乎发生了变化。根据软件工程师招聘网站Tripleby…

Linux主辅DNS数据不同步故障排除
Linux主辅dns数据不同步故障排除欢迎使用微信关注“云运维联盟”公众号,第一时间了解本博客动态!在互联网中,我们知道任何一台提供应用服务的主机(例如:HTTP、FTP等)都有它一个便于记忆Domain Name…

c语言贝叶斯分类,基于朴素贝叶斯分类器的文本分类算法(C语言)
基于朴素贝叶斯分类器的文本分类算法(C语言)基于朴素贝叶斯分类器的文本分类算法(C语言).txt两个人吵架,先说对不起的人,并不是认输了,并不是原谅了。他只是比对方更珍惜这份感情。#include #include #include //_getcwd(), _chdir()#include…

开源项目哪家强?Github年终各大排行榜超级盘点(内附开源项目学习资源)
整理 | Jane出品 | AI科技大本营【导语】提到开源项目,2018 年注定是不平凡的一年。据 Octoverse 报告数据,仅在 2018 年,Github 上的新用户就比过去六年的用户总数还要多 ,存储库数量近一亿,这些增长都要归功于开源社…

给现有MVC项目增加Web API支持
在MVC4中自带了Web API不再需要从Nuget中下载。 Step1:增加System.Web.Http,System.Web.Http.WebHost,System.Net.Http三个程序集的引用,都是4.0版本; Step2:增加路由,默认的路由代码如下 route…

word自动消除html标签,清理Word生成HTML的冗余;清理与清除HTML标签
众所周知,当直接将word中的内容复制到网页上时,会产生很多冗余代码;而现在,在线编辑器又很普遍;就包括,现在用的百度空间的这个文本编辑器,如果直接从WORD中写好的文章复制进来,本来…

开头轰轰烈烈,结局冷冷清清
开头轰轰烈烈,结局冷冷清清转载于:https://blog.51cto.com/xiaomage/115649

C# SQLiteHelper类似SqlHelper类实现存取Sqlite数据库
这个类不是我实现的,原文在这里,我修改了原文中分析sql语句参数的方法,将方法名修改为AttachParameters,将其修饰符修改为private,并直接传递command到这个方法,直接绑定参数到comand。修改后的代码如下 SQ…

Skype for Business Server 2015-03-后端服务器-0-准备
1. 规划-拓朴图 2. 规划-服务器 3. 准备-软件 Sql Server 2014: cn_sql_server_2014_enterprise_edition_x64_dvd_3932882.iso Sql Server 2014 CU6: Cumulative update package 6 for SQL Server 2014 https://support.microsoft.com/en-us/kb/3031047 4. 准备-虚拟…

html文档使用,使用提供 HTML 文档的过程
使用提供 HTML 文档的过程通常,编写一个可处理发送给特定服务的请求的过程是最简单的方式。这样的过程将返回一个 Web 页。或者,该过程也可接受作为 URL 的一部分进行传递的参数以对其输出进行自定义。但以下示例要简单很多。它例示了服务可以简单到什么…

这样学算法,包会包懂so easy~
整理 | Jane出品 | AI科技大本营面试前,大家都会开始刷各类网站,希望能在算法之道上有所进益,也期待有幸能在面试中碰上原题,而在那么多的网站中,LeetCode 一定是候选学习的网站之一。但是 LeetCode 网站上的题量和难度…

上映 10 天,票房就突破 10 亿的《海王》真的有那么好看?
出品:CSDN(ID:CSDNnews)写在前面本文将主要通过Python加上一些数据分析,来证明《海王》好看。《海王》一部电影带你重温《驯龙高手》《变形金刚》《星球大战》《星河战队》《铁血战士》《安德的游戏》《异形》可能还借…

利用SMS OSD实现win2008操作系统的部署
我们知道SMS是一个强大的桌面操作系统,利用SMS可以实现对客户端的软件、硬件等数据的统计,还可以管理公司的资产等等。那么利用SMS OSD是否能部署出XP、win2003、win2008等操作系统呢?今天我们就来试试用SMS OSD来部署win2008操作系统&#x…

企业域名更换操作系列1:为什么要进行域名更换及更换需要注意事项
前段时间在公司讨论对现在域结构调整时,有提到希望能重新启一套域,将现在域内信息全部进行迁移,迁移完成后再把域名改为原域名,此问题从愿景上来看是不错的,因为这种方法虽然操作比较复杂,但是对于用户体验上来看,还是有一定的帮助…

html在页面上div绝对定位,html – 中心浮动div在绝对定位div内
我有这套html和CSS.我想要的是必须让小的小工具块向左浮动但是在绝对定位的小工具包装器内部居中.因此,小工具包装器绝对位于页面底部.它包含x个小工具,它们在包装器内部浮动.所有这些小工具应该在包装器中居中 – 这是可能的,如何……?这真是让我伤心….1not setno…

主角用计算机控制身体,国漫段子手:绝技,用计算机控制挖掘机炒菜
身为古神的叶辰从神境世界陨落到了苍蓝世界,这里百州千国林立,豪强争霸,叶辰在这个苍蓝世界呆了数百年,建立了庞大的势力。在百州千国,叶辰的存在一直都是一个传说。但是来自神境世界的力量慢慢地延伸到了苍蓝世界&…

2018热点总结:BERT最热,GANs最活跃,每20分钟就有一篇论文...
作者 | Ross Taylor 译者 | linstancy 整理 | Jane 出品 | AI科技大本营 【导读】本文的作者 Ross Taylor 和 Robert Stojnic 在今年一起启动了一个名为“Paper with Code”的项目,将 AI 领域的一些研究论文和论文开源代码结合展示,方便大家学习与研究…