I have a relatively large GUI based OOP software (in Python) were I rely heavily on keeping references throughout the program. For example I would define a Main class with some stored options as an attribute (code example below). In a second class, e.g. OptionFrame I would pass the reference to that stored options object and store it again as an attribute. This has the great advantage that if I change the stored options in OptionFrame it will also be changed in Main. However recently I skrewed up the whole program by writting a function that reinitializes the stored options and therefore gives it a new reference, like reset_options_bad in the example below. Therefore the two option objects in OptionFrame and Main were no longer connected and my program did not work anymore.

Was this design decision to rely heavily on passing references around and relying on them a good idea?

Class OptionFrame:
    def __init__(self,options):

    def change_options(self):
        self.options['example']=False # This should also change the options in main

class Main:
    def __init__(self):
        self.stored_options = {'example':True}   
        self.option_frame = OptionFrame(self.stored_options)

    def reset_options_bad(self):
        self.stored_options = {'example':True} # This is a bad idea

    def reset_options_good(self):
  • 2
    Not in python. You are basically stuck with testing for Main.stored_options is Main.options_frame.options everywhere
    – Caleth
    Sep 6 '17 at 16:14
  • @Caleth Thanks that is a good idea at least. But what to do if the test returns false?
    – Jannick
    Sep 7 '17 at 8:43
  • Fail fast. Throw an exception detailing what you operation did that, let the process exit, see a failing test. something like this may be useful
    – Caleth
    Sep 7 '17 at 8:48

What you basically have is a global variable in disguise. And all the problems of global variables apply. It even gets extra fun when you add a new the reference and you effectively add another global variable.

So I would say it is not a good idea.

  • What design pattern would you propose instead?
    – Jannick
    Sep 6 '17 at 15:13
  • Without knowing the specifics of your situation, my first inclination is toward dependency injection. Inject some kind of service which gets config values (the values themselves, not the object that holds everything). Then if something changes, it returns the correct value. Added benefit that the backing storage can change and the dependent code never needs to know or care.
    – Becuzz
    Sep 6 '17 at 15:27
  • 1
    Sounds like you're describing a Context object. Isn't a Context object really just a global variable that's being handed around? Sep 6 '17 at 15:44
  • @RobertHarvey OP basically has the context object already (Only difference to here is Main is creating it, rather than receiving it).
    – Caleth
    Sep 6 '17 at 16:12
  • So you're saying that a "global variable" is OK, so long as you're injecting it. Sep 6 '17 at 16:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.