how to avoid spaghetti in Python?

CM cmpython at gmail.com
Tue Jan 21 15:38:49 EST 2014


I've been learning and using Python for a number of years now but never really go particularly disciplined about all good coding practices.  I've definitely learned *some*, but I'm hoping this year to take a good step up in terms of refactoring, maintainability, and mostly just "de-spaghettizing" my approach to writing Python programs.  

But I could use some pointers.

Of course, many pointers will be general programming advice that is common to all languages, and I get that, but I also think that it's possible certain bits of advice are particularly relevant to Python coders, and so I ask here.  (Also because I know there are some great community people here who I'd enjoy getting their take on this).  

A few specific questions in this area...

1) One of my main "spaghetti problems" is something I don't know what to ever call.  Basically it is that I sometimes have a "chain" of functions or objects that get called in some order and these functions may live in different modules and the flow of information may jump around quite a bit, sometimes through 4-5 different parts of the code, and along the way variables get modified (and those variables might be child objects of the whole class, or they may just be objects that exist only within functions' namespaces, or both).  This is hard to debug and maintain.  What would people recommend to manage this?  A system of notes?  A way to simplify the flow?  And what is this problem called (if something other than just spaghetti code) so I can Google more about it?

2) A related question:  Often I find there are two ways to update the value of an object, and I don't know what's best in which circumstances... To begin to explain, let's say the code is within a class that represents a Frame object in a GUI, like wxPython.  Now let's say ALL the code is within this wxFrame class object.  So, any object that is named with "self." prepended, like self.panel, or self.current_customer, or self.current_date, will be a child object of that frame class, and therefore is sort of "global" to the whole frame's namespace and can therefore be accessed from within any function in the class. So let's say I have a function called self.GetCurrentCustomer().  To actually get the name of the current customer into RAM, it goes into the database and uses some rule to get the current customer.  NOW, the question is, which of these should I do?  This:

      def GetCurrentCustomer(self):
          self.current_customer = #do some database stuff here....

Or this:

      def GetCurrentCustomer(self):
          current_customer = #do some database stuff here....
          return current_customer

And what difference does it make?  In the first case, I am just updating the "global" object of the current_customer, so that any function can then use it.  In the second case, I am only returning the current_customer to whatever function(s) call this GetCurrentCustomer() function.

My hunch is the first way leads to spaghetti problems.  But I want to understand what the best practices are in this regard. I have found in some cases the first method seemed handy, but I'm not sure what the best way of thinking about this is.

3) Generally, what are other tools or approaches you would use to organize well a good-sized project so to avoid fighting yourself later when you don't understand your own code and the flow of information through it?  By good sized, say about 20,000 lines of Python code, or something like that.  

This is the sort of question that would be rejected on Stack Overflow, so I hope you can excuse my fishing for insight in a somewhat open/vague way.

Thanks.



More information about the Python-list mailing list