关于全球变量及其误用的讨论似乎对其有一定的教条色调。我不是在争论“全局性是坏的”概念,因为它对我来说是有道理的。但是我想知道人们是否有一些有趣的代码片段,它们可以准确地演示如何有效地从代码中重构更高范围的变量和对象。在这个问题中,我正在寻找“我需要在这里使用全局变量,因为它很容易”问题的通用但有用的解决方案的示例或模式。
这是一个假设的,也许是人为的例子。我正在使用全局变量来跟踪发送到函数的参数。然后,如果在链的下游发生故障,我可以返回并使用全局变量中的参数再次调用该函数。
public var myGlobalState:Object = new Object();
public function addPerson (name:String, person:Object, personCount:int, retryCount:int):void
{
myGlobalState = null; // Clear out old values
myGlobalState = new Object();
myGlobalState.name = name;
myGlobalState.person = person;
myGlobalState.personCount = personCount;
myGlobalState.retryCount = retryCount;
person.userId = personCount + 1;
person.name = name;
savePerson(person);
}
public function savePerson (person:Object):void
{
// Some code that attempts to save the person object properties to a database...
// The process returns a status code for SUCCESS of FAILURE.
// CODE TO SAVE TO DATABASE ....
// Return status code...
if (status == "fail")
{
// Retry at least once by calling the addPerson function again
if (myGlobalState.retryCount < 3)
{
addPerson (myGlobalState.name, person, myGlobalState.personCount, myGlobalState.retryCount);
}
}
}
答案 0 :(得分:10)
我没有片段,但我有一个真实世界的例子。 线性校准常数(质谱场) 应用程序是全局的,并且有复杂的代码 存储和恢复全局校准常数 不同的光谱。两个值的使用全部展开 在程序上,很难改变或检查 未校准和校准质量之间的转换 在所有情况下,使用这两个常数的值都是正确的。
我通过封装两个校准常数进行重构 在一个负责转换的班级中 未校准和校准的质量值。做的功能 转换也被引入,因此它集中在一个 放在程序中而不是遍布整个程序 程序。这种封装后来很容易引入 一种新的校准(非线性)。
而不是访问类的两个全局变量 代表频谱的代替将使用和 新校准类的实例,每个实例都带有 它自己的一组校准常数。
答案 1 :(得分:4)
快速解决方案是将所有全局变量添加到一个巨大的对象中,可能还有几个子对象来分隔数据组。将所有这些变量放在一个对象中,您只需要一个全局变量来存储该对象。然后,您的所有代码都将引用此对象中的变量而不是全局变量。
下一步将摆脱这个单一的全球对象。这应该比摆脱几百个全局变量更容易。这可以通过将其更改为您传递给任何其他方法的附加参数来完成。
一旦所有全局数据消失,您可以考虑重构代码,尝试通过以下方式优化此共享对象:将其分成多个较小的对象。但是通过将所有内容移动到单个对象中,您可以更轻松地管理它。
答案 2 :(得分:1)
答案通常在于程序的体系结构。您可以通过某种方式设计全局变量是绝对必要的,您可以按照您从不需要的方式进行设计。在后面的场景中,您通常会得到一个更好,更清晰的架构,并且可以避免为依赖于全局变量等的方法创建单元测试的所有常见问题。
This question也会有所帮助。
P.S。在您的特定场景中,根本不需要全局变量 - 您可以轻松地将其作为参数传递给addPerson
方法。