【问题标题】:Defining global behavior of a function? Good practice定义函数的全局行为?好习惯
【发布时间】:2019-05-18 06:56:25
【问题描述】:

这个问题是一般性的。假设您有很多微服务调用某个内部库。这个库有一个核心函数core_function(arg_1,arg_2,..)

在某些情况下,函数的反应会有所不同。 那么什么是好的做法呢?

我的一些想法:

  1. 向函数添加参数。 behavior_param。 缺点:很多微服务需要重构。微服务是类。所以我必须为每个类引入一个新参数 (或至少一个默认参数)并在调用 功能(当然只适用于需要修改行为的微服务)
  2. 在库中添加一些全局变量,例如 behavior_param 可能在 __init__ 文件中。缺点:我会有一个全局参数,但不喜欢那样。

  3. 使用环境变量。这就像第二种解决方案。但不知何故,我更喜欢这个主意

你怎么看?希望问题很清楚。我正在 python 中寻找最好和最自然的方法。

【问题讨论】:

  • lib 中其他函数的行为是否依赖于此参数?

标签: python design-patterns architecture


【解决方案1】:

您的直觉是正确的——避免使用全局变量来动态修改core_function 的行为。一般来说,它们会让你的代码更难被别人理解,更难维护,更脆弱。将它们用作最后​​的选择。

如果您想修改core_function 的行为而不重构已调用core_function 的所有实例,那么您应该向core_function 添加一个可选参数并提供一个默认值。这个可选参数将规定函数应该遵循的“行为模式”。

改变这个:

def core_function(arg_1, arg_2):

到这里:

def core_function(arg_1, arg_2, behavior_param = 'Default'):

这将允许您现有的代码继续使用 core_function 并保持默认行为且无需任何重构。对于以后的代码,您可以提供可选参数并指定您想要的行为。

【讨论】:

  • 是的,我经常看到并使用它。在这种情况下, core_function 调用位于不同类的深处。所以不知何故,我不喜欢将参数传递给调用的想法。我将不得不为一些通用类再引入一个参数(仅在某些特殊情况下才需要)。另一方面,它绝对是一个干净的解决方案。
  • @MichaelRazum 您是否实际上是在尝试避免使用额外参数使那些父类的构造函数膨胀?如果是这种情况,您可以将 behavior_param 定义为这些类的属性,将其从构造函数中完全省略,并添加类似 set_behavior 的辅助方法,以便可以动态更新属性。
  • 是的。听起来像是一个合理的想法。会考虑的。非常感谢:)!!!
【解决方案2】:

改变行为的标志,无论是全局变量还是函数参数,在某种程度上都可以,但如果它们导致函数代码中的分支过多(ifs),我更喜欢有一组函数,每个一个提供所需行为之一,以及一个根据标志值返回正确函数的工厂函数。

这将选择正确的行为与行为的实现分开。

例如,像这样的:

def factory(arg0, arg1 ..., flag):
   func_map = {
        0: func0,
        1: func1,
        2: func2
   }
   return func_map[flag](arg0, arg1)

result = factory(foo, bar, 1)

如果只有两种可能的行为,我不会这样做,但肯定会考虑三种或更多。

【讨论】:

  • 如果你只有两种行为,你会怎么做?我喜欢这种模式!
  • 只有两个我可能会在函数内部使用一个标志变量(全局或参数)和一个if。我的经验法则基本上是我在函数中看到的ifs(或elifs)越多,我认为它就越需要重构,尽管它总是取决于更广泛的上下文。
【解决方案3】:

这是我对上述问题的解决方案。请注意,使用默认参数的解决方案是标准方法。如果有多个函数应对某些默认行为做出反应,此解决方案会很有帮助。

_default_behavior = { "arg_1": value_1, "arg_2": value_2}

def set_default_behavior(value_1, value_2):
   _default_behavior["arg_1"] = value_1
   _default_behavior["arg_2"] = value_2

def core_function():
   if _default_behavior["arg_1"] == True:
      # do some stuff and also arg_2 may be used
      pass 
   else: 
      # here is the default case
      pass 

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-06-16
    • 2013-10-13
    • 2021-03-15
    • 2017-09-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多