Listing 5.2 contains the code used to create just the button bar in the previous listing. As a first step in refactoring, we've extracted the code to its own method.
Listing 5.2 The button bar as a separate method def createButtonBar(self):
firstButton = wx.Button(panel, -1, "FIRST") self.Bind(wx.EVT_BUTTON, self.OnFirst, firstButton) prevButton = wx.Button(panel, -1, "<< PREV", pos=(80, 0)) self.Bind(wx.EVT_BUTTON, , self.OnPrev, prevButton) nextButton = wx.Button(panel, -1, "NEXT >>", pos=(16 0, 0)) self.Bind(wx.EVT_BUTTON, self.OnNext, nextButton) lastButton = wx.Button(panel, -1, "LAST", pos=(240, 0)) self.Bind(wx.EVT_BUTTON, self.OnLast, lastButton)
With the code separated out like this, it's easy to see what the commonality is between all the button additions. We can factor that portion out into a generic method, and just call the method repeatedly, as shown in listing 5.3:
Listing 5.3 A generic and improved button-bar method def createButtonBar(self, panel):
self.buildOneButton(panel, "First", self.OnFirst) self.buildOneButton(panel, "<< PREV", self.OnPrev, (80, 0)) self.buildOneButton(panel, "NEXT >>", self.OnNext, (160, 0)) self.buildOneButton(panel, "Last", self.OnLast, (240, 0))
def buildOneButton(self, parent, label, handler, pos=(0,0)): button = wx.Button(parent, -1, label, pos) self.Bind(wx.EVT_BUTTON, handler, button) return button
There are a couple of advantages in following the second example instead of the first. For one thing, the intent of the code is clearer just from reading it—having short methods with meaningful names goes a long way toward signaling intent. The second example also gets rid of all the local variables that are needed just to hold on to IDs (admittedly, you could also get rid of the local variables by hardwiring the IDs, but that can cause duplicate ID problems). This is helpful because it makes the code less complicated, and also because it almost eliminates the common error of cutting and pasting a couple of lines of code and forgetting to change all the variable names. (In a real application, you might need to store the buttons as instance variables to be able to access them later, but for this example, you do not.) In addition, the buildOneButton() method is easily moved to a utility module and could be reused in other frames or other projects. A toolkit of common utilities is a useful thing to have.
Was this article helpful?