I'm starting out with wxPython and have been working my way through every tutorial and example I can get my hands on. I've run into a slight problem, however, and it has to do with the wx.App versus the wx.Frame and which should contain specific methods. Just about every example I've seen don't go much beyond layouts/sizers and event handling, none really tackle project organization of a wxPython project.
For example, I have a method that gets a list of folders. The way most examples would deal with this would be to stick the method right in the frame class. This method has the potential to be used in several other parts of the application, so it would make more sense to store it at the application class level.
How should I organize and call "universal" methods like these so that I don't clutter up my frame classes.
UPDATE:
To clarify, the "list of folders" was just an example, my actual method does a lot more work. What I'm saying is I have code that isn't Frame-specific. If I had this in the application class, what is the best way to call it from and event method in my frame.
I'm looking for actual project organization techniques, not programming fundamentals.
Your classes that inherit from wxWidgets/wxPython data types should not implement any business logic. wxWidgets is a GUI library, so any subclasses of wxApp or wxFrame should remain focused on GUI, that is on displaying the interface and being responsive to user actions.
The code that does something useful should be separated from wx, as you can decide later to use it in some web or console application and you don't want to create wxApp object in such case. You can also decide later on to move some computations to separate 'worker threads', while your GUI will be the 'main thread' - responsive, and repainted properly during long lasting computations.
Last but not least - the classes that encapsulate your logic might tend to grow during projects lifetime. If they're mixed with your GUI classes they will grow faster, and finally they become so complex that you're almost unable to debug them...
While having them separated leads to clean code when you don't mix bugs in logic with bugs in GUI (refreshing/layout/progress bar etc.). Such approach has another nice feature - ability to split work among GUI-people and logic-people, which can do their work without constant conflicts.
As Mark stated you should make a new class that handles things like this.
The ideal layout of code when using something like wxWidgets is the model view controller where the wxFrame class only has the code needed to display items and all the logic and business rules are handled by other class that interact with the wxFrame. This way you can change logic and business rules with out having to change your interface and change (or swap) your interface with out having to change your logic and business rules.
I probably should have been a lot clearer from the start, but I found what I was looking for:
http://wiki.wxpython.org/ModelViewController/
Burried within the wxpython wiki, I found several simple, concrete examples of MVC projects.
In a proper OOP design, this would be independent or part of a filesystem class - it wouldn't be part of the app or the frame.
Related
suppose I have a class/model building that has a relation to the class/model wall and this again to the class/model window in a form that one building can have many surfaces and a surface can have many windows (one to many).
Now when I want to add windows to that building, maybe also only to certain surfaces, should the functions(also search functions/loops) be written inside the model? Or outside in a separate class/script that is either called from the model or called from outside?
I could imagine, when the functionality is part of the model, that it could cause problems when changes are needed in the long run.
What is the cleaner architecture/standard since both could work?
If possible can you give me a source to read more into this certain problem?
In my case I'm using python with sqlalchemy and postgres, but this question could also be legitimate for other programming languages.
(I hope this question is not too broad/ opinion based)
For starters, I think this question might have been better asked in Softwareengineering. However, I might as well give you my few cents on this.
As so often, it depends ...
Generally, encapsulation is one of the core concepts in object-oriented programming.
Any change to the state of an object should be done by the object itself (although potentially triggered externally) and therefore be guaranteed to comply with the terms and conditions you defined for your object. The behavior of your object should be implemented inside your object not outside of it.
You don't want to expose your Window's attribute wall publicly for all the world to access it directly. You want to hide it behind getters and setters. You want the Window to refuse being placed on a Wall that is passed to its wall setter if said Wall happens to be 'interior'. You don't want a Person object to change the Window's state from 'open' to 'close' and vice versa directly, you want the Person to call the Window's open() resp. close() method, e.g. to ensure internally that a closed window is not closed again.
Also, hiding implementation details can help maintaining your interface and making changes to your class transparent. Say, for example, you decide that, in addition to disallow interior walls, you now also want to prevent "normal" windows from being put into exterior walls in the basement. You can implement that check into your existing wall setter in Window and the only visible change for external code would be another potential reason for refusal ("window=normal and wall=basement" in addition to "wall=interior"). Or you want to add an attribute representing the state of cleanliness of your Window and, to make a proper distinction between the new cleanliness_state and the old 'open'/'close' state, you want to rename the old attribute to open_close_state. With your methods open(), close() (and potentially is_open() and is_closed()) reading from and writing to your 'open'/'close' state attribute, this change just affects your class implementation, not every piece of code that uses it.
However!
You might have classes that just work as some sort of collection, i.e. data classes. These implement little to no functionality and publicly expose their attributes to be read and written by the whole world, thus broadly ignoring the concept of encapsulation. One could argue that classes/models implemented in an object-relational mapping layer, such as SQLAlchemy, are more of a data object/data class than an object in the OOP sense, especially when used mainly to persist and retrieve structured data. It is not unusual to have external code change the state of such an object or implement its functionality, like the views in the Django framework that uses its own ORM layer to implement and persist models.
So?
It boils down to your concrete case. You already mentioned that you consider restricting the placement of windows; probably based on properties of the windows and walls involved.
If you consider your SQLAlchemy models more than just a way of persisting your objects, go ahead and implement the behavior and change logic right away in your model. But keep in mind that a) you might end up creating conflicts with methods/properties of your model's base class and b) the attributes of your models must remain publicly exposed to maintain the functionality of your ORM layer (Although SQLAlchemy might be able to work with properties as long as both, getter and setter are defined; I have never tested that).
If you want the models to be a rather convenient method of persisting and retrieving your structured data, keep them clean and go for some utility functions or classes that implement your object's behavior and ensure its contract when being used in the code; e.g. have a function place_window_on_wall(window: Window, wall: Wall) that takes care of validation and restrictions when you try to reference a Wall object on your Window's wall attribute. But keep in mind that changes to your model must be reflected in these functions / classes as well.
I consider both options valid; just whatever you opt for, be consistent with your decision.
So I'm using tkinter to make a GUI and at the moment I have several different frames. The way I programmed it is by just using one massive class but everywhere I look online (like here - https://pythonprogramming.net/change-show-new-frame-tkinter/), people are using a new class for every single "page". Is what I am doing wrong/not efficient or is it fine?
Unfortunately I cannot show my code as it's for a CA but the below is similar:
class App(tk.Frame):
def __init__(self):
tk.Frame.__init(self)
self.PageOne()
def PageOne(self):
coding stuff
def PageTwo(self):
pass
What you are doing is probably fine. I say "probably" because it depends on many factors which you haven't explained in your question.
The tutorial you referenced came from a stackoverflow answer that was explicitly addressing how to switch between two frames. It's not necessarily a recommended way to code, it's simply one of many ways.
That being said, if you have distinct pages then you might find it easier to manage your code if each page was a self-contained object. Doing so gives each page its own namespace, so you don't have to worry that one page is accidentally modifying the data that belongs to some other page. Plus, for larger projects it allows you to implement each page in a separate file so you don't end up with one huge file full of code.
Since not all GUIs are oriented around the concept of pages, this technique isn't a one-size-fits-all solution. It's OK to make each page a class, it's also OK to create each page via a function. The choice depends on many variables, such as your comfort with working with classes, the size of your project, the type of UI you're creating, and so on.
I'm writing pretty big and complex application, so I want to stick to design patterns to keep code in good quality. I have problem with one instance that needs to be available for almost all other instances.
Lets say I have instance of BusMonitor (class for logging messages) and other instances that use this instance for logging actions, in example Reactor that parses incoming frames from network protocol and depending on frame it logs different messages.
I have one main instance that creates BusMonitor, Reactor and few more instances.
Now I want Reactor to be able to use BusMonitor instance, how can I do that according to design patterns?
Setting it as a variable for Reactor seems ugly for me:
self._reactor.set_busmonitor(self._busmonitor)
I would do that for every instance that needs access to BusMonitor.
Importing this instance seems even worse.
Altough I can make BusMonitor as Singleton, I mean not as Class but as Module and then import this module but I want to keep things in classes to retain consistency.
What approach would be the best?
I want to keep things in classes to retain consistency
Why? Why is consistency important (other than being a hobgoblin of little minds)?
Use classes where they make sense. Use modules where they don't. Classes in Python are really for encapsulating data and retaining state. If you're not doing those things, don't use classes. Otherwise you're fighting against the language.
As you already have a hierarchy, you could use a chain to get it.. it's not the Chain-of-responsibility pattern, but the idea is similar.
Each widget has a getbusmonitor call, which is return self.parent().getbusmonitor() for all widgets except the root one. You could also cache the results..
I found good way I think. I made module with class BusMonitor, and in the same module, after class definition I make instance of this class. Now I can import it from everywhere in project and I retain consistency using classes and encapsulation.
My first "serious" language was Java, so I have comprehended object-oriented programming in sense that elemental brick of program is a class.
Now I write on VBA and Python. There are module languages and I am feeling persistent discomfort: I don't know how should I decompose program in a modules/classes.
I understand that one module corresponds to one knowledge domain, one module should ba able to test separately...
Should I apprehend module as namespace(c++) only?
I don't do VBA but in python, modules are fundamental. As you say, the can be viewed as namespaces but they are also objects in their own right. They are not classes however, so you cannot inherit from them (at least not directly).
I find that it's a good rule to keep a module concerned with one domain area. The rule that I use for deciding if something is a module level function or a class method is to ask myself if it could meaningfully be used on any objects that satisfy the 'interface' that it's arguments take. If so, then I free it from a class hierarchy and make it a module level function. If its usefulness truly is restricted to a particular class hierarchy, then I make it a method.
If you need it work on all instances of a class hierarchy and you make it a module level function, just remember that all the the subclasses still need to implement the given interface with the given semantics. This is one of the tradeoffs of stepping away from methods: you can no longer make a slight modification and call super. On the other hand, if subclasses are likely to redefine the interface and its semantics, then maybe that particular class hierarchy isn't a very good abstraction and should be rethought.
It is matter of taste. If you use modules your 'program' will be more procedural oriented. If you choose classes it will be more or less object oriented. I'm working with Excel for couple of months and personally I choose classes whenever I can because it is more comfortable to me. If you stop thinking about objects and think of them as Components you can use them with elegance. The main reason why I prefer classes is that you can have it more that one. You can't have two instances of module. It allows me use encapsulation and better code reuse.
For example let's assume that you like to have some kind of logger, to log actions that were done by your program during execution. You can write a module for that. It can have for example a global variable indicating on which particular sheet logging will be done. But consider the following hypothetical situation: your client wants you to include some fancy report generation functionality in your program. You are smart so you figure out that you can use your logging code to prepare them. But you can't do log and report simultaneously by one module. And you can with two instances of logging Component without any changes in their code.
Idioms of languages are different and thats the reason a problem solved in different languages take different approaches.
"C" is all about procedural decomposition.
Main idiom in Java is about "class or Object" decomposition. Functions are not absent, but they become a part of exhibited behavior of these classes.
"Python" provides support for both Class based problem decomposition as well as procedural based.
All of these uses files, packages or modules as concept for organizing large code pieces together. There is nothing that restricts you to have one module for one knowledge domain.
These are decomposition and organizing techniques and can be applied based on the problem at hand.
If you are comfortable with OO, you should be able to use it very well in Python.
VBA also allows the use of classes. Unfortunately, those classes don't support all the features of a full-fleged object oriented language. Especially inheritance is not supported.
But you can work with interfaces, at least up to a certain degree.
I only used modules like "one module = one singleton". My modules contain "static" or even stateless methods. So in my opinion a VBa module is not namespace. More often a bunch of classes and modules would form a "namespace". I often create a new project (DLL, DVB or something similar) for such a "namespace".
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.
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.
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.
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.
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.
One possibility is to assign imported functions to class attributes:
In file a_part_1.py:
def add(self, n):
self.n += n
def __init__(self, n):
self.n = n
And in main class file:
import a_part_1
class A:
__init__ = a_part_1.__init__
add = a_part_1.add
Or if you don't want to update main file when new methods are added:
class A: pass
import a_part_1
for k, v in a_part_1.__dict__.items():
if callable(v):
setattr(A,k,v)