抨击匈牙利命名法

抨击匈牙利命名法
   匈牙利命名法是一种编程时的命名规范。命名规范是程序书写规范中最重要也是最富争议的地方,自古乃兵家必争之地。命名规范有何用?四个字:名正言顺。用二分法,命名规范分为好的命名规范和坏的命名规范,也就是说名正言顺的命名规范和名不正言不顺的命名规范。好的舞鞋是让舞者感觉不到其存在的舞鞋,坏的舞鞋是让舞者带着镣铐起舞。一个坏的命名规范具有的破坏力比一个好的命名规范具有的创造力要大得多。
 
   本文要证明的是:匈牙利命名法是一个坏的命名规范。本文的作用范围为静态强类型编程语言。本文的分析范本为C语言和C++语言。下文中的匈法为匈牙利命名法的简称。
 
    1.匈牙利命名法的成本
 
   匈法的表现形式为给变量名附加上类型名前缀,例如:nFoo, szFoo, pFoo, cpFoo分别表示整型变量、字符串型变量、指针型变量和常指针型变量。可以看出,匈法将变量的类型信息从单一地点(声明变量处)复制到了多个地点(使用变量处),这是冗余法。冗余法的成本之一是要维护副本的一致性。这个成本在编写和维护代码的过程中需要改变变量的类型时付出。冗余法的成本之二是占用了额外的空间。一个优秀的书写者会自觉地遵从一个法则:代码最小组织单位的长度以30个自然行以下为宜,如果超过50行就应该重新组织。一个变量的书写空间会给这一法则添加不必要的难度。
 
    2.匈牙利命名法的收益
 
   这里要证明匈牙利命名法的收益是含糊的、无法预期的。
 
   范本1: strcpy(pstrFoo, pcstrFoo2) vs. strcpy(foo, foo2)
 
   匈法在这里有什么收益呢?我看不到。没有一个程序员会承认自己不知道strcpy函数的参数类型吧。
 
   范本2: unknown_function(nFoo) vs. unknown_function(foo)
 
   匈法在这里有什么收益呢?我看不到。对于一个不知道确定类型的函数,程序员应该去查看该函数的文档,这是一种成本。使用匈法的唯一好处是看代码的人知道这个函数要求一个整型参数,这又有什么用处呢?函数是一种接口,参数的类型仅仅是接口中的一小部分。诸如函数的功能、出口信息、线程安全性、异常安全性、参数合法性等重要信息还是必须查阅文档。
 
   范本3: nFoo=nBar vs. foo=bar
 
   匈法在这里有什么收益呢?我看不到。使用匈法的唯一好处是看代码的人知道这里发生了一个整型变量的复制动作,听起来没什么问题,可以安心睡大觉了。如果他看到的是nFoo=szBar,可能会从美梦中惊醒。且慢,事情真的会是这样吗?我想首先被惊醒的应该是编译器。另一方面,nFoo=nBar只是在语法上合法而已,看代码的人真正关心的是语义的合法性,匈法对此毫无帮助。另一方面,一个优秀的书写者会自觉地遵从一个法则:代码最小组织单位中的临时变量以一两个为宜,如果超过三个就应该重新组织。结合前述第一个法则,可以得出这样的结论:易于理解的代码本身就应该是易于理解的,这是代码的内建高质量。好的命名规范对内建高质量的助益相当有限,而坏的命名规范对内建高质量的损害比人们想象的要大。
 
    3.匈牙利命名法的实施
 
   这里要证明匈牙利命名法在C语言是难以实施的,在C++语言中是无法实施的。从逻辑上讲,对匈法的收益做出否定的结论以后,再来论证匈法的可行性,是画蛇添足。不过有鉴于小马哥曾让已射杀之敌死灰复燃,我还是再踏上一支脚为妙。
 
   前面讲过,匈法是类型系统的冗余,所以实施匈法的关键是我们是否能够精确地对类型系统进行复制。这取决于类型系统的复杂性。
 
   先来看看C语言:
 
    1.内置类型:int, char, float, double 复制为 n, ch, f, d?好像没有什么问题。不过谁来告诉我void应该怎么表示?
 
    2.组合类型:array, union, enum, struct 复制为 a, u, e, s?好象比较别扭。
 
   这里的难点不是为主类型取名,而是为副类型取名。an表示整型数组?sfoo,sbar表示结构foo,结构barausfoo表示联合结构foo数组?累不累啊。
 
    3.特殊类型:pointerpointer在理论上应该是组合类型,但是在C语言中可以认为是内置类型,因为C语言并没有非常严格地区分不同的指针类型。下面开始表演:pausfoo表示联合结构foo数组指针?ppp表示指针的指针的指针?
 
   噩梦还没有结束,再来看看类型系统更为丰富的C++语言:
 
    1.class:如果说C语言中的struct还可以用stru搪塞过去的话,不要梦想用cls来搪塞C++中的class。严格地讲,class根本就并不是一个类型,而是创造类型的工具,在C++中,语言内置类型的数量和class创造的用户自定义类型的数量相比完全可以忽略不计。 stdvectorFoo表示标准库向量类型变量Foo?疯狂的念头。
 
    2.命名空间:boostfilesystemiteratorFoo,表示boost空间filesystem子空间遍历目录类型变量Foo?程序员要崩溃了。
 
    3.模板:你记得std::map<std::string, std::string>类型的确切名字吗?我是记不得了,好像超过255个字符,还是饶了我吧。
 
    4.模板参数:template <class T, class BinaryPredicate>const T& max (const T& a, const T& b, BinaryPredicate comp) 聪明的你,请用匈法为T命名。上帝在发笑。
 
    5.类型修饰:static, extern, mutable, register, volatile, const, short, long, unsigned 噩梦加上修饰是什么?还是噩梦。
 
   你愿意做镣铐上的舞者吗?
 
 
文章来源:
在Windows系统中,若希望关闭IPv4自动配置并手动设置静态IP及DNS配置,可以通过以下方式实现: 网络适配器的TCP/IP协议配置中支持手动设置IP地址、子网掩码、默认网关以及DNS服务器。进入“控制面板” → “网络和共享中心” → “更改适配器设置”,右键点击当前使用的网络连接,在属性窗口中双击“Internet协议版本4 (TCP/IPv4)”。选择“使用下面的IP地址”并填写所需的IP信息,同时可指定首选DNS服务器[^1]。 此外,也可以通过命令行工具来配置静态IP和恢复动态获取模式。例如,使用`netsh interface ip set address "连接名称" dhcp`可以将特定网络接口的IP地址设置为通过DHCP自动获取;同样地,执行`netsh interface ip set dns "连接名称" dhcp`则可以让DNS设置也恢复到由DHCP分配的状态[^2]。 对于需要频繁切换不同DNS环境的情况,存在一个基于Python脚本的解决方案,该方案允许用户检查当前活动的网络接口,并提供修改这些接口上DNS设置的功能。此脚本首先验证运行它的用户是否具有管理员权限,然后列出所有活跃的网络接口及其相关信息,接着展示所选接口现有的DNS服务器列表,并给出选项让用户进行DNS设置的调整[^4]。 当遇到DNS异常时,比如无法解析域名或者访问互联网受阻,一种常见的修复方法是利用系统自带的网络故障排除工具尝试自动修复问题。如果自动修复无效,则推荐按照上述步骤手动更正DNS配置。另一种做法是直接更换至公共DNS服务如Google DNS(8.8.8.8),这通常能解决由于本地ISP提供的DNS服务器不稳定导致的问题[^3]。 为了确保系统的稳定性与安全性,还可以进一步采取措施禁用不必要的自动配置特性,比如APIPA(Automatic Private IP Addressing)。这项功能会在计算机未能从DHCP服务器获得有效IP地址时启用,从而分配一个私有范围内的链接本地地址。要彻底禁用这一机制,可通过修改注册表项`HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Dhcp`下的`Start`值为`4`以达到目的。需要注意的是,实施此类更改前应充分评估其对网络连通性的影响,并且操作后可能需要重启机器才能生效。 ```bash # 示例:通过注册表编辑器禁用DHCP客户端服务 reg add "HKLM\SYSTEM\CurrentControlSet\Services\Dhcp" /v Start /t REG_DWORD /d 4 /f ``` 最后,请记得任何涉及系统级配置的改动都应当谨慎处理,尤其是在生产环境中。务必保证理解每一步骤的作用后再做相应更改,并保持对原始配置的良好记录以便必要时回滚。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值