views:

188

answers:

4

OK I've got 2 really big classes > 1k lines each that I currently have split up into multiple ones. They then get recombined using multiple inheritance. Now I'm wondering, if there is any cleaner/better more pythonic way of doing this. Completely factoring them out would result in endless amounts of self.otherself.do_something calls, which I don't think is the way it should be done.

To make things clear here's what it currently looks like:

from gui_events import GUIEvents # event handlers
from gui_helpers import GUIHelpers # helper methods that don't directly modify the GUI

# GUI.py
class GUI(gtk.Window, GUIEvents, GUIHelpers):
    # general stuff here stuff here

One problem that is result of this is Pylint complaining giving me trillions of "init not called" / "undefined attribute" / "attribute accessed before definition" warnings.

EDIT:
You may want to take a look at the code, to make yourself a picture about what the whole thing actually is.
http://github.com/BonsaiDen/Atarashii/tree/next/atarashii/usr/share/pyshared/atarashii/

Please note, I'm really trying anything to keep this thing as DRY as possible, I'm using pylint to detect code duplication, the only thing it complains about are the imports.

+1  A: 

I think this is more of a general OO-design problem than Python problem. Python pretty much gives you all the classic OOP tools, conveniently packaged. You'd have to describe the problem in more detail (e.g. what do the GUIEvents and GUIHelpers classes contain?)

One Python-specific aspect to consider is the following: Python supports multiple programming paradigms, and often the best solution is not OOP. This may be the case here. But again, you'll have to throw in more details to get a meaningful answer.

Eli Bendersky
You can take a look at the classes here: http://github.com/BonsaiDen/Atarashii/tree/next/atarashii/usr/share/pyshared/atarashii/GUIEvents is mostly about handling stuff when the user clicked a button. GUIHelpers sets up some smaller stuff like labels and others, and also provides some utility functions like is_ready. I'm still not completely done with deciding which methods belong to each of the "subclasses".
Ivo Wetzel
A: 

Your code may be substantially improved by implementing a Model-View-Controller design. Depending on how your GUI and tool are setup, you may also benefit from "widgetizing" portions of your GUI, so that rather than having one giant Model-View-Controller, you have a main Model-View-Controller that manages a bunch of smaller Model-View-Controllers, each for distinct portions of your GUI. This would allow you to break up your tool and GUI into many classes, and you may be able to reuse portions of it, reducing the total amount of code you need to maintain.

While python does support multiple programming paradigms, for GUI tools, the best solution will nearly always be an Object-Oriented design.

Brendan Abel
The problem is I currently don't see a way to reduce the whole thing even further, Dialogs/TrayIcon and the HTMLViews are already in their own classes, so this big GUI thing is currently only managing the binds between those and setting stuff like the statusbar. Also I already DRYed the code to the death... the only thing I could imaging is splitting the GUI into one component that actually modifies visible stuff and the other one just handling events and such, but that will result in the self.otherself.foo calls :/
Ivo Wetzel
+2  A: 

Start by finding classes that model real world concepts that your application needs to work with. Those are natural candidates for classes.

Try to avoid multiple inheritance as much as possible; it's rarely useful and always somewhat confusing. Instead, look to use functional composition ("HAS-A" relationships) to give rich attributes to your objects made of other objects.

Remember to make each method do one small, specific thing; this necessarily entails breaking up methods that do too many things into smaller pieces.

Refactor cases where you find many such methods are duplicating each other's functionality; this is another way to find natural collections of functionality that deserve to be in a distinct class.

bignose
+1: "2 really big classes > 1k lines" Ouch. That clearly misses the point of OO design. All Event Handlers in one class is clearly wrong. Event Helpers isn't a class design.
S.Lott
+1  A: 

If you want to use multiple inheritance to combine everything into one big class (it might make sense to do this), then you can refactor each of the parent classes so that every method and property is either private (starts with '__') or has a short 2-3 character prefix unique to that class. For example, all the methods and properties in your GUIEvents class could start with ge_, everything in GUIHelpers could start with gh_. By doing this, you'll get achieve some of the clarity of using separate sub-class instances (self.ge.doSomething() vs self.ge_doSomething()) and you'll avoid conflicting member names, which is the main risk when combining such large classes into one.

too much php
I guess that's the way I'll go here, because 1. it's easy to do with a search/replace, 2. it will reduce the chance of conflicts, also I'll be able to use more generic names like um_get_items, instead of (update_messages).get_messages and 3. as you've already said it will bring clarity into the code and show where the methods have their origin. All in all it's pretty simple, maybe I'm thinking a bit to complicate after spending 5 weeks programming this thing :D
Ivo Wetzel