我编写的大多数程序都是相对可流程化的过程,具有已定义的开始和希望结束。问题本身可能很复杂,但不容易倾向于集中使用对象和事件驱动编程。通常,我只是通过各种批量的文本数据来生成不同的文本数据。偶尔我只需要创建一个类:例如,为了跟踪警告,错误和调试消息,我创建了一个带有一个实例(myErr)的类(Problems),我相信它是Singleton设计模式的一个例子。作为另一个因素,我的同事比我更老派(程序性),并且不熟悉面向对象的编程,所以我不愿意创造他们无法解开的东西。
然而,我一次又一次地听到,Singleton设计模式是否真的是一种反模式,应该避免,因为全局变量是坏的。
次要函数需要传递给它们的参数很少,并且不需要知道配置(不变)或程序状态(更改) - 我同意。但是,链中间的函数(主要控制程序流)需要大量的配置变量和一些程序状态变量。我相信将十几个参数传递给一个函数是一个“解决方案”,但几乎不具吸引力。当然,我可以将变量填充到单个散列/字典/关联数组中,但这似乎是作弊。
例如,连接到Active Directory以创建一个新帐户,我需要诸如管理用户名,密码,目标OU,一些默认组,域等配置变量。我必须将这些参数传递下来通过各种甚至不会使用它们的功能,只需将它们通过链条拖拽下来,这最终会导致实际需要它们的功能。
我至少会声明配置变量是不变的,以保护它们,但是现在我选择的语言(Python)没有提供简单的方法来做到这一点,尽管配方确实存在作为变通方法。
无数的Stack Overflow问题已经触及了原因?不良和必要的回避,但不要经常提到与这种准宗教限制生活的技巧。你是如何解决全球变量和项目状态的问题,或者至少与之和解?你在哪里做出妥协?你的伎俩是什么,除了围绕功能的争论?
答案 0 :(得分:5)
我认为单身人士模式或类似情况有时间和地点。要记住的关键点是,一次又一次,当涉及使用全局/共享/静态变量以及单例模式的“错误”选择时,许多人都经历了特定的恐怖。
在您的情况下,您正在谈论具体的配置。我认为使用单例样式模式访问这些配置项没有任何害处。每个应用程序都有配置,它应该位于你可以调用的位置,没有必要只是传递它,这比它帮助更复杂。
这里的关键是确保你真正需要信息只存在一次,配置是我发现使用这种模式的最佳原因之一。
答案 1 :(得分:3)
全局数据是不变的或定义明确的过程范围的对象(例如,日志记录),通常可以用作全局数据。配置数据,特别是如果它位于本地文件中,将属于同一类别(整个过程/应用程序只有一个文件,类似于日志记录)。
一般情况下,如果你发现你必须传递额外的参数只是为了将它们传递给另一个函数,你应该将该函数“拉”起来并让另一个函数调解。另一个更实用的方法是说明这是测试驱动的开发,因为它会强制你传递依赖关系。
另一种思考方式是:如果该函数不能轻易知道调用子函数的所有细节,请拉出子函数,并强制使用更高,更知识的层来获取所需信息。我发现这种技术对代码质量具有很强的导向性,因为它可以构建分隔的部分,而不是整体式的野兽。
在关于活动目录的示例中,不是传递ad_connect
的参数,而是传递处理必要逻辑的对象,然后使用一个函数来调解该对象与函数之间的交互。它
def create_user(name, ad_user, ad_pass, ad_ou, ...):
conn = ad_connect(ad_user, ad_pass, ...)
conn.CreateRecord(ad_user)
def create_user_mediator(name, ad_controller):
ad_controller.CreateRecord("cn=%s" % name)
这只是一种做法,当然,它有其优点和缺点。它只是create_user
如何避免必须使用全局变量的一个例子。