D:全局变量坏吗?

D:全局变量坏吗?,d,D,有时我需要获取变量,它可以从代码的任何地方访问。但我经常听说全局变量是不好的。对于这种情况,D的最佳实践是什么 现在,我的代码如下所示: string roothtml; static this() { roothtml = buildPath(getcwd, "html"); } void main() { // } 这是好的还是坏的做法 这取决于你所说的“全球”的真正含义。在上面的例子中,我认为这很好。 您似乎正在显示一个main模块,该模块可能不应导入 无论如何。换句话说,它不

有时我需要获取变量,它可以从代码的任何地方访问。但我经常听说全局变量是不好的。对于这种情况,D的最佳实践是什么

现在,我的代码如下所示:

string roothtml;
static this()
{
    roothtml = buildPath(getcwd, "html");
}

void main()
{
//
}

这是好的还是坏的做法

这取决于你所说的“全球”的真正含义。在上面的例子中,我认为这很好。 您似乎正在显示一个
main
模块,该模块可能不应导入 无论如何。换句话说,它不是真正的全球性的,它是本地的主要 模块。这和我的想法没什么不同

class Main {
  private string _roothtml;
  static this() { _roothtml = buildPath(getcwd, "html"); }
  void run() { }
}
即使它不是你的
main
,D 系统提供了对其自身的保护 拥有只需在
roothtml
上粘贴一个
private
,即可将其封装在模块中 (为了清楚起见,在主模块中这样做不会有什么坏处)

这样的模式在git的源代码中被广泛使用。而不是 如果有一个主模块为给定命令调用函数,那么 有许多
main
函数——每个顶级命令一个

例如,看看

看到源文件顶部声明的变量了吗? 如果将代码包装在一个类中,代码会更清晰或更安全吗 典型的OOP风格或以更纯粹的方式显式地传递给每个函数 功能性风格

每个源文件都充当给定命令的封装单元。这种风格并不总是合适的,但是对于一个可以被认为是一组不同命令的程序来说,它可以比其他的更干净

最终,答案将特定于上下文、给定项目和环境 你的个人风格。一般来说,跨模块全局变量是 可能会被怀疑,但模块级变量有时会更干净
由于以下几个原因,全局变量是有问题的

  • 当你阅读时,很难追踪变量的来源。这使得使用全局变量理解函数变得更加困难
  • 更难跟踪变量的使用位置。这使得修改全局变量的使用方式变得更加困难
  • 注入测试数据和测试存根更难
  • 测试状态将溢出到其他测试
  • \uu gshared
    全局文件需要锁定或不可变
  • 线程本地全局变量是线程本地变量,因此不能将写操作传播到所有线程
  • 任何全局文件都要求您考虑是要将其线程本地还是
    \uuu gshared
  • 如果您需要将单租户应用程序转换为多租户应用程序,那么如果您使用全局变量,这将非常痛苦。这比你想象的更普遍
  • 在运行应用程序时,必须小心不要使用
    -unittest
    构建,这样就不会破坏静态构造函数中初始化的全局状态

从好的方面来说,你不必到处通过全局状态,这很方便。您不必经常使用方法到方法的对象重构。你不必引入依赖注入系统。它不咬你的时候很方便。

我认为每种语言都有例外。设置通常存储在“全局”变量中。不过,如果可能的话,最好保持全局变量为只读。通常情况下,它们是不好的,因为您无法正确控制从何时何地访问它们。不过D可以用属性来反击。@Milie,Bauss谢谢,但你能看看我下面评论中的源代码示例吗(在rcorre回答之后)。也许你可以给我一些建议?下一个例子中,你能帮助我吗?我无法解释如何检查用户是否是管理员。在第93行,我正在尝试写用户是否是管理员。但将这个变量设置为280行,并在main中声明(第50行)。在这种情况下,最好的解决方案是什么?
静态此
->
。您的并没有明显的改进,因为它没有为注入状态的测试提供任何钩子,而且该值实际上是不可变的。改变这些,你会得到一个更复杂但更可测试(和更安全的测试)的解决方案。在某些情况下,这种复杂性可能是不合理的。我并不是建议将类作为替代方案,而是试图说明模块实际上提供了自己的类封装。现在我回过头来看我的答案,它确实有点令人困惑。。。