为什么全局变量不好?

来源:互联网 发布:数据恢复精灵无法勾选 编辑:程序博客网 时间:2024/04/28 03:21

最近有考虑这个问题,百度了下,感觉不是很满意,看到有点赞多的答案,就搬运过来。原文链接:https://softwareengineering.stackexchange.com/questions/148108/why-is-global-state-so-evil。 既然是译文,我就尽量保持原文的信息,但是,翻译水平有限,如果有错误,还望不吝赐教。


Q:为什么全局变量是魔鬼?

在讨论这个问题之前,我先说清楚,我对概念—抽象、依赖注入很了解。我不需要这方面的科普。

我们经常说“不要使用全局变量”“单例(singletons)是魔鬼,因为他们使用全局变量”,却没有真正的理解,全局变量真的有这么不吉利吗?

我们经常需要给应用设置全局配置,比如系统文件夹路径、或者面向所有应用的(application-wide)数据库的证书。

这种情况下,除了把这些设置放在一个所有应用都能访问的全局空间,我想不到更好的方法了。

我知道,滥用全局变量是不好的,但是,全局变量真的有那么邪恶吗?如果真是这样,有什么好的替代方案吗?


A: 总结成一句话,全局变量让程序的状态变得不可预测。
(译者注:状态指,局部变量。全局状态,指全局变量。)
具体的说,想象一下,你有使用同一个全局变量的两个对象。假设你在两个模块中都没有修改全局变量(这里有点难翻译,详细见原文)。那么,任意指定方法(指成员函数)的输出是可以预测的(也是可以测试的),如果你知道在执行这个方法之前系统的状态。

但是,如果有一个对象的一个方法,改变了全局变量的状态,它便触发了全局变量的副作用。这种情况下,你就不知道,另一个对象执行一个方法时的初始状态。当你执行方法,你不再能够预测你能得到的输出,因此,也无法测试。

在学术层面似乎没有那么严重,但是,能够单元测试代码是证明代码正确性(或者,至少满足目标)过程中的重要一步。

在现实中,这种情况可能产生非常严重的后果。假设,你有一个类产生一个全局变量结构,另一个类消费在这个结构中的数据,在程序中改变它的状态或者销毁它。
如果消费类在生产类还没有生产的时候消费,结果是,消费类可能处理不完整的数据,生产类的数据结构可能毁坏或销毁。在这种情况下,程序的行为变得完全不可预测,可能会造成很大的损失。

而且,全局变量有损代码的可读性。如果你的代码有一个外部依赖,它没有显式的引入代码中。那么,无论谁来维护你的代码,都必须要查找,找到它的出处。

至于,是否有替代品存在。是不可能完全没有全局变量。但是,实践中,把所有全局变量包装成一个对象,是有可能。并且,这个变量不能被,你使用的语言的作用域规则引用。如果一个指定的对象需要一个指定的状态,它就应该通过给构造函数传入参数或者通过setter函数,显式的请求这个状态。这就是 依赖注入(Dependency Injection)。

你明明可以通过你使用的语言的作用域规则直接访问,却要通过参数传入状态,看起来是有点傻的,但是,优点是巨大的。如果,有人直接看这个代码片,状态和它的出处是很清楚的。从代码模块的灵活性、它可能被用于其他上下文的角度来说,好处也是巨大的。如果状态是传入的、只在局部代码块中改变它的状态,那么,你可以传入任意的值(只要它的数据类型是正确的)。然后,让你的代码处理。用这种方法写的代码,看起来,组件之间的耦合度很低,修改起来会比较简单。模块中的代码不许要关心,这个状态只从哪里来,只需要关心如何处理它。如果你将状态(state)传入一个代码块,这个代码块便可以独立,不再和依赖全局状态(global state)一样。

有很多其他的原因,为什么传入状态比依赖全局状态好得多。这个答案并不想穷举所有原因。你可能可以写出整整一本书,为什么全局变量是坏的。


其他说法:因为大家都可以改变,所以,你不能依赖它。


A2 :看到深入理解操作系统里有另一个不用全局变量的理由。函数名和已初始化的全局变量称为强符号(strong symbol),未初始化的全局变量称为弱符号(weak symbol)。如果有多个同名弱符号,链接器会任意(是的,任意,random)选择一个,即使这些弱符号的类型可能不一样。这样操作全局变量,会导致内存访问问题(详细请参考:深入理解操作系统第三版)。

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 顾客恶意差评怎么办 淘宝不能看视频怎么办 天猫精灵打不开怎么办 手机淘宝卡死了怎么办 为什么电视盒子打不开怎么办 天猫买了降价了怎么办 试用报告未提交怎么办 试用中心拉黑怎么办 淘宝赠品破了怎么办 淘宝卖家不给赠品怎么办 淘宝赠品有瑕疵怎么办 淘宝赠品不发货怎么办 移动电视没信号怎么办 网络电视死机了怎么办 电视接收网络信号不好怎么办 tcl电视待机打不开怎么办 宽带电视看不了怎么办 电视总是闪退怎么办 电视出现系统更新怎么办 电视一直在更新怎么办 电视更新死机了怎么办 法院打电话不接怎么办 内向不敢辞职怎么办呀 生气后睡不着觉怎么办 被气得睡不着怎么办 一生气就睡不着怎么办 手机接电话声音小怎么办 发微信老公不回怎么办 欠钱没有欠条怎么办 朋友欠钱不还怎么办没欠条 个人欠销售货款怎么办 货款一直不还怎么办 欠钱不接电话找不到人怎么办 欠钱人电话不接怎么办 客户欠款不给怎么办 客户货款打一半怎么办 欠款人不到庭怎么办 别人打电话不接怎么办 百合注册被禁用怎么办? 监控显示未登录怎么办 发票认证了两次怎么办