匈牙利命名法为何被淘汰 匈牙利命名规则标识符


匈牙利命名法为何被淘汰 匈牙利命名规则标识符

文章插图
背景之前在做一个老项目重构的时候 。由于数据库不能改动 。所以还是继续沿用之前的老数据库 。保护安全险公司嘛 。哪怕加了个互联网保护安全险的 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 的命名处理的 。但想了一下觉得没必要 。毕竟是咱们命名不标准 。何必去改这个命名处理机制呢 。划不来 。

推荐阅读