匈牙利命名法为何被淘汰(C++中匈牙利命名法是否该淘汰)
首发

匈牙利命名法为何被淘汰(C++中匈牙利命名法是否该淘汰)

优质
请用语音读文章

背景之前在做一个老项目重构的时候。由于数据库不能改动。所以还是继续沿用之前的老数据库。保护安全险公司嘛。哪怕加了个互联网保护安全险的 title。业务和系统还是偏经典的。数据模型不会轻易地更新;所以这个系统年代比较久远。而且它的数据库表命名方式选用的还是匈牙利命名法。导致在重构时因为这个命名方式让人作呕了我好久……

匈牙利命名法匈牙利命名法(Hungarian notation)。由1972年至1981年在施乐帕洛阿尔托研究中心工作的-程序员 查尔斯·西蒙尼发明。这位前辈后面成了微软的总设计师。

这个命名法的特点是。在命名前面增加类型的前缀。就像这样:

c_name – 姓名。字符串(Char)类型n_age – 年龄。数字(Number)类型t_birthday – 生日。日期/期间(Time)类型可不要小看这个命名法。当年可是很流行的。而且直到今天还是有一些系统仍然在沿用这个命名标准。比如微软的 Win32 API:

况且这个命名法。也不是没有一处擅长的技术。还是有一定的优点的。至少我一眼就可以看出这个字段的类型。

只不过在今天看起来有点怪怪的。不太符合当今的设计风格。如果放到人名上就更有意思了:

男赵四女谢大脚男刘能当匈牙利命名法接触 java咱们这次的重构目标。是要保持老系统表不动的情况下。完全重写。可是新系统是 Java 语言来研究。Java 可是驼峰命名标准的。当这个匈牙利命名法的表迁移到驼峰命名法的 Java 语言会怎么样?

比如 c_name 这个命名。到 Java 里之后。是改为 CName 呢。还是 cName 呢?好像怎么都有点奇怪。不过最后咱们还是选择了 CName 。将类型的前缀完全大写。至少看着稍微正常一点。没那么反人类

c_name -> CNamen_age -> NAget_birthday -> TBirthday当匈牙利命名法接触 JAVA咱们这次的重构目标。是要保持老系统表不动的情况下。完全重写。可是新系统是 Java 语言来研究。Java 可是驼峰命名标准的。当这个匈牙利命名法的表迁移到驼峰命名法的 Java 语言会怎么样?

比如 c_name 这个命名。到 Java 里之后。是改为 CName 呢。还是 cName 呢?好像怎么都有点奇怪。不过最后咱们还是选择了 CName 。将类型的前缀完全大写。至少看着稍微正常一点。没那么反人类

c_name -> CNamen_age -> NAget_birthday -> TBirthday序列化的问题刚确定了命名方式。还没开心多久。我就碰到了一个非常难受的问题……

由于是 Spring 全家桶。Web 层使用的也是 Spring MVC。Spring MVC 的默认 jsON 处理库是 Jackson。在 Web 层返回 JSON 后。数据就成了这个样子:

{ "nid":1, "ctitle":"Effective JAVA"}可我这个 POJO 类是将匈牙利命名法的字段转了大写。它长这样啊:

public class Book { private Integer NId; private String CTitle; public Integer getNId() { return NId; } public void setNId(Integer NId) { this.NId = NId; } public String getCTitle() { return CTitle; } public void setCTitle(String CTitle) { this.CTitle = CTitle; }}大写字段名。在转 JSON 之后变成了小写……要是把这个小写的字段给了前端。前端命名肯定会用小写。那前端在发送到后端时候一定也是小写。

那由于咱们出入参序列化都是 Jackson 。对于 Jackson 来探讨。怎么出就怎么进。还是能解析出来的。看似也没啥问题。只是让人作呕了一点。前后端一个大写一个小写。

不过……事情并没有那么简单。后端不会将所有的报文都作为 POJO 的字段。会存在一些动态的字段。用 Map 存放。可 Map 存放的这些字段。Jackson 在输出时不会转为小写。还是保留原有的大写形式。这样就会导致给前端的字段。虽然都是匈牙利风格。但有那么一些大写有那么一些小写……虽然前端不知道打不打人。但我可不敢这么玩

不同序列化库的处理机制不同Jackson 的匈牙利命名法处理其实 Jackson 序列化之后转小写的原因也很好解释。Java 的设计规范。就是 Bean 中的属性用 private 修饰。然后提供 getter/setter 来提供读取/写入。那么在序列化时。Jackson 通过字段的 Getter 来访问属性值。甚至用 Getter 方法来解析属性名。

Java 的 getter 方法命名标准是。将小写驼峰转大写驼峰。Jackson 在通过 getter 方法名解析字段名时。将 getNID 解析为 nid 了。所以导致最终输出的字段名为小写的 nid。

FastJson 的匈牙利命名法处理本来是想定做化一下 Jackson 的命名处理的。但想了一下觉得没必要。毕竟是咱们命名不标准。何必去改这个命名处理机制呢。划不来。

所以我又尝试着换一种 JSON 库去处理这个命名问题。先试一试阿里的 FastJSON。看看这个国产库的处理怎么样:

{ "cTitle":"Effective JAVA", "nId":1}看到这个序列化结果时。我差点把我键盘按钮上面的 Backspace 按断了……一样是通过 getter 方法解析属性名。两个库的解析规则还能不一样……

在 FastJson 里。c 是小写了。可 Title 里的 T 还是大写。@#¥%……&此处省略100字……

冷静一下之后。心里默念了几遍:“不怪别人。是咱们自己的命名问题。不符合标准人家怎么解析都不关你事……”

不过 JAVA 的生态这么好。JSON 库也不止这两个。再换一个就是。Google 的 Gson 也很不错嘛!

Gson 的匈牙利命名法于是我又换成了 Gson。配置完 Spring MVC Gson Converter 之后。输出结果:

{ "NId":1, "CTitle":"Effective JAVA"}终于换到一个能正常显示原始字段名的 JSON 库了。不过它既然能保持原有字段名。而不是 getter 里解析的属性名。那么它肯定不是解析 getter 方法名的

于是我又去翻了下 Gson 的源码。发现它是直接 getDeclaredFields()。然后makeAccessible。最后直接通过 Field.getValue的方式直接获取属性值的。

相比 Jackson 和 FastJson 里通过 getter 获取属性列表。然后通过调用 getter 方法来获取属性值的方法来探讨。强烈访问私有属性这种做法还是太暴力了。不过我喜欢。至少它能轻松解决了我的问题

其他的序列化问题除了 JSON 这种文本形式的序列化之外。一些二进制的序列化也会有这个尴尬的问题。获取属性列表/属性值。到底是用解析 getter 方法的方式。还是直接 makeAccessible 暴力访问私有属性呢?

这个我测试了一下。比如在 Dubbo 的默认序列化方式(Dubbo 简化的Hession2)中。仍然是 getDeclaredFields。然后访问私有属性

在 JDK 的内置序列化 ObjectOutputStream 中。也是 getDeclaredFields。然后访问私有属性。

不过这种 getDeclaredFields 。然后访问私有属性值的方式。也会有一些劣势。比如在接触代码混淆时。私有属性的值会被全部打乱。而 public 的方法却不会。所以在接触混淆的代码时。这种方式就会乱套了。而通过 getter 方法解析的方式就不会有问题。

所以吧。这个获取属性的方式并没有对错。怎么都可以。不过我认为还是应该通过 getter/setter 的方式来操作。符合 JAVA 的规范。

总结Java 里访问私有属性值。标准的方式是通过 getter 方法。但还是提供了一个 makeAccessible 操作。可以让咱们直接访问私有属性或者私有方法。

一直不太明白 JDK 为什么要这么设计。既然已经指定了规范。为什么还要开个后门呢?如果限制死了这个功能。那么所有序列化的库不就可以统一了。再也没有这种让人作呕的不一致问题!

但对比以上三个序列化库。我觉得都没错。Jackson/FastJson 遵从规范的方式来。老老实实地通过 getter 方法来获取。而 Gson 就有点暴力。直接访问私有属性。各有优势。

介绍浏览:Google一面挂。疯刷1000道JAVA面试题。上岸华为

以上就是由优质生活领域创作者 生活常识网 整理编辑的,如果觉得有帮助欢迎收藏转发~

分享到 :
相关推荐

搞笑的闪亮登场的霸气句子(很酷很洒脱的经典句子)

请用语音读文章1、黑夜给了我一双黑色的眼睛。可我却用它来翻白眼。2、你匍匐在地上[&...

河南景点排行榜前十名是什么地方(湖南景点排行榜前十名是什么地方)

请用语音读文章河南。是我们国家中部的一个省份。这里也是我们国家人扣多的一个省份。这[...

水浒传文章及赏析(深度解析水浒传)

请用语音读文章《水浒传》楔子《张天师祈禳瘟疫洪太尉误走妖魔》中描述五代残唐之后。[&...

个人户口信息网上查询系统(公安部户口查询系统)

请用语音读文章一、网上怎么查户籍由于户籍信息是共享的。所以在网络上可以查询到个人[&...

发表评论

您的电子邮箱地址不会被公开。