0

Below I have a dummie code, where instance methods are definied mainly for code organization. The init function sets up a chain of calls to the various instance methods in a specific order, and I am just starting to feel it is bad practice to have code organized in such a way.

If so are there any references on organizing large classes (such as those found in GUI apps) to improve their readability?

Dummie code:

class App:
    def __init__(self):
        def do_things()

    def do_things(self):
        self.do_a_thing()
        self.do_another_thing()

    def do_a_thing(self):
        self.thing1 = 1    

    def do_another_thing(self):
        self.thing2 = self.thing1 + 1

These functions will only execute once when the class is called, so does that suggest they should not be functions (or instance methods)?

A working example where I have chosen this potentially bad method of organization

Below, the fill() method is akin to do_things(), and e.g. init_scroll() and init_lb() are akin to do_a_thing() and do_another_thing(), etc.

import Tkinter as tk
import tkFont

class EditorApp:
    def __init__( self, master) :
        self.root = master
        self.root.title('Editor')
        self.main = tk.Frame( self.root )
        self.main.pack(fill=tk.BOTH, expand=True)

        self.fill()

##################
# ADDING WIDGETS #
##################
    def fill( self): 
        self.canvas = tk.Canvas( self.main )
        self.canvas.pack(fill=tk.BOTH, expand=tk.YES)
        self.init_scroll()
        self.init_lb()
        self.pack_config_scroll()
        self.pack_bind_lb()
        self.fill_listbox()

##############
# SCROLLBARS #
##############
    def init_scroll(self):
        self.scrollbar  = tk.Scrollbar(self.canvas, orient="vertical")
        self.xscrollbar = tk.Scrollbar(self.canvas, orient="horizontal")

    def pack_config_scroll(self):
        self.scrollbar.config(command=self.lb.yview)
        self.xscrollbar.config(command=self.xview)
        self.scrollbar.pack(side="right", fill="y")
        self.xscrollbar.pack(side="bottom", fill="x")

    def onMouseWheel(self, event):
        self.lb.yview("scroll", event.delta,"units")
        return "break"

    def xview(self, *args):
        self.lb.xview(*args)

################
# MAIN LISTBOX #
################
    def init_lb( self):
        self.lb = tk.Listbox(self.canvas, 
                            font=tkFont.Font(self.canvas, 
                                             family="Courier", 
                                             size=14),
                            yscrollcommand=self.scrollbar.set,   
                            xscrollcommand=self.xscrollbar.set, 
                            exportselection=False)

    def pack_bind_lb(self):
        self.lb.pack(fill="both", expand=True)
        self.lb.bind("<MouseWheel>", self.onMouseWheel)

    def fill_listbox(self):
        dummie_lines = [ 'line%d\t'%x+ ''.join(['AllWorkAndNoPlayMakesJackADullBoy']*100) for x in xrange(50) ]
        for line in  dummie_lines:
            self.lb.insert(tk.END, line) 

if __name__ == '__main__':
    root   = tk.Tk()
    editor = EditorApp(root)
    root.mainloop() 

I have attempted to group similar methods together for the sake of debugging (the code I pulled this from is a class which is 300 lines), but I do not know a lot about the accepted style guidelines.

Also, the full application is posted here

Community
  • 1
  • 1
dermen
  • 5,252
  • 4
  • 23
  • 34

1 Answers1

2

Is your concern that developers may call do_thing independent of do_things? While Python doesn't support private methods, you can indicate that do_thing should be treated as private by using the leading underscore convention:

def _do_thing(self):
    ...

This tells developers not to call _do_thing directly.

Generally, it's a very good idea to break large methods or functions into smaller, more manageable ones. This can be especially important when unittesting code.

matthewatabet
  • 1,463
  • 11
  • 26