How to avoid excessive parameter passing?

后端 未结 6 853
予麋鹿
予麋鹿 2021-02-11 00:22

I am developing a medium size program in python spread across 5 modules. The program accepts command line arguments using OptionParser in the main module e.g. main.py. These opt

相关标签:
6条回答
  • 2021-02-11 00:45

    If "a" is a real object and not just a set of independent helper methods, you can create an "p" member variable in "a" and set it when you instantiate an "a" object. Then your main class will not need to pass "p" into meth1 and meth2 once "a" has been instantiated.

    0 讨论(0)
  • 2021-02-11 00:50

    With objects, parameter lists should normally be very small, since most appropriate information is a property of the object itself. The standard way to handle this is to configure the object properties and then call the appropriate methods of that object. In this case set p as an attribute of a. Your meth2 should also complain if p is not set.

    0 讨论(0)
  • 2021-02-11 00:51

    [Caution: my answer isn't specific to python.]

    I remember that Code Complete called this kind of parameter a "tramp parameter". Googling for "tramp parameter" doesn't return many results, however.

    Some alternatives to tramp parameters might include:

    • Put the data in a global variable
    • Put the data in a static variable of a class (similar to global data)
    • Put the data in an instance variable of a class
    • Pseudo-global variable: hidden behind a singleton, or some dependency injection mechanism

    Personally, I don't mind a tramp parameter as long as there's no more than one; i.e. your example is OK for me, but I wouldn't like ...

    import a
    p1 = some_command_line_argument_value
    p2 = another_command_line_argument_value
    p3 = a_further_command_line_argument_value
    a.meth1(p1, p2, p3)
    

    ... instead I'd prefer ...

    import a
    p = several_command_line_argument_values
    a.meth1(p)
    

    ... because if meth2 decides that it wants more data than before, I'd prefer if it could extract this extra data from the original parameter which it's already being passed, so that I don't need to edit meth1.

    0 讨论(0)
  • 2021-02-11 00:52

    Maybe you should organize your code more into classes and objects? As I was writing this, Jimmy showed a class-instance based answer, so here is a pure class-based answer. This would be most useful if you only ever wanted a single behavior; if there is any chance at all you might want different defaults some of the time, you should use ordinary object-oriented programming in Python, i.e. pass around class instances with the property p set in the instance, not the class.

    class Aclass(object):
        p = None
        @classmethod
        def init_p(cls, value):
            p = value
        @classmethod
        def meth1(cls):
            # some code
            res = cls.meth2()
            # some more code w/ res
        @classmethod
        def meth2(cls):
            # do something with p
            pass
    
    from a import Aclass as ac
    
    ac.init_p(some_command_line_argument_value)
    
    ac.meth1()
    ac.meth2()
    
    0 讨论(0)
  • 2021-02-11 00:57

    Your example is reminiscent of the code smell Message Chains. You may find the corresponding refactoring, Hide Delegate, informative.

    0 讨论(0)
  • 2021-02-11 01:02

    Create objects of types relevant to your program, and store the command line options relevant to each in them. Example:

    import WidgetFrobnosticator
    f = WidgetFrobnosticator()
    f.allow_oncave_widgets = option_allow_concave_widgets
    f.respect_weasel_pins = option_respect_weasel_pins
    
    # Now the methods of WidgetFrobnosticator have access to your command-line parameters,
    # in a way that's not dependent on the input format.
    
    import PlatypusFactory
    p = PlatypusFactory()
    p.allow_parthenogenesis = option_allow_parthenogenesis
    p.max_population = option_max_population
    
    # The platypus factory knows about its own options, but not those of the WidgetFrobnosticator
    # or vice versa.  This makes each class easier to read and implement.
    
    0 讨论(0)
提交回复
热议问题