After a few false starts, I've started a redesign of a Kivy project. My goal is to separate as much of the behavior and data models as possible from code using the Kivy framework. This, hopefully, would allow for more robust testing and possible reuse with other UI frameworks.
What I have in mind mirrors Martin Fowler's Presentation Model.
Presentation Model allows you to write logic that is completely independent of the views used for display. You also do not need to rely on the view to store state. The downside is that you need a synchronization mechanism between the presentation model and the view.
Code Example
The design I envision relies on explicit getters and setters in a pure Python model, which would also contain methods the Kivy classes could use as callbacks:
class PresentationModel:
def __init__(self, data1):
self._data1 = data1
def get_data1(self):
return self._data1
def set_data1(self, value)
''' Validate, call the backend, etc '''
self._data1 = value
return True
def callback(*args):
''' Do some stuff here and/or the backend '''
And then all the synchronization code would stay inside a Kivy widget subclass, assigning each PM property as and AliasProperty.
class MyBoxLayout(BoxLayout):
data1 = AliasProperty(get_data1, set_data1, bind=['_data1'], cache=True)
Questions
Has anyone attempted this? Are there any githubs or projects that would show a real-world example?
If I were to use this strategy, Kivy's Docs say all setters need to return True. From what I can tell, Python ignores return values from setters in general. Would there be any performance issue or other drawback to doing that?
Related
I have a lot of different child classes that inherit from one base class. However all the different child classes implement very similar methods. So if I want to change code in the child classes, I have to change it multiple times.
For me this sounds like bad practice and I would like to implement it correcty. But after a lot of googling I still didn't find a coherent way of how this should be done.
Here is an example of what I mean:
from ABC import ABC, abstractmethod
import logging.config
class BaseModel(ABC):
def __init__(self):
# initialize logging
logging.config.fileConfig(os.path.join(os.getcwd(),
'../myconfig.ini'))
self.logger = logging.getLogger(__name__)
#abstractmethod
def prepare_data(self):
"""
Prepares the needed data.
"""
self.logger.info('Data preparation started.\n')
pass
So this is my BaseClass. Now from this class multiple other classes inherit the init and prepare_data method. The prepare_data method is very similar for every class.
class Class_One(BaseModel):
def __init__(self):
super.__init()__
def prepare_data(self):
super().prepare_data()
# Some code that this method does
class Class_Two(BaseModel):
def __init__(self):
super.__init()__
def prepare_data(self):
super().prepare_data()
# Some code that this method does
# Code is almost the same as for Class_One
class Class_Three(BaseModel):
def __init__(self):
super.__init()__
def prepare_data(self):
super().prepare_data()
# Some code that this method does
# Code is almost the same as for Class_One and Class_Two
# etc.
I suppose you could refactor the methods into another file and then call them in each class. I would love to know how to do this correctly. Thanks a lot in advance!
I'm afraid there's no generic one-size-fits-all magic answer - it all really depend on the "almost" part AND on the forces that will drive change in those parts of the code. IOW, one can only really answer on a concrete example...
This being said, there are a couple lessons learned from experience, which are mostly summmarized in the famous (but unfortunately often misunderstood) GOF "Design Patterns" book. If you take time to first read the first part of the book, you understand that most of (if not all) the patterns in the catalog are based on the same principle: separate the variant from the invariant. Once you can tell one from the other in your code (warning: there's a trap here and beginner almost always fall into it), which pattern to apply is usually obvious (sometimes to the point you only realize you used this and that patterns after you refactored your code).
Now as I said, there IS a trap: accidental duplication. Just because two pieces of code look similar doesn't mean they are duplicates - quite often, they are only "accidentally" similar now but the forces that will make one or the other change are mostly unrelated. If you try to immediatly refactor this code, you'll soon find yourself making the "generic" case more and more complicated to support changes that are actually unrelated, and end up with an overcomplicated, undecipherable mess that only make your code unmaintainable. So the trick here is to carefully examine the whole context, ask yourself what would drive change in one or the other "similar" parts, and if in doubt, wait until you know more. If it happens than each time you change A you have to make the exact same change in B for the exact same reasons then you DO have real duplicate.
For a more practical, short-term advise based on what we can guess from your way too abstract example (and from experience), there are at least two patterns that are most often involved in factoring out duplication in a class hierarchy: the template method and the strategy.
NB : I said "unfortunately often misunderstood" because most people seem to jump to the patterns catalog and try to forcefit all of them in their code (whether it makes sense for the problem at hand or not), and usually by copy-pasting the canonical textbook _implementation_ (usually Java or C++ based) instead of understanding the _concept_ and implementing it in a way that's both idiomatic and adapted to the concrete use case (example: when functions are first class object, you don't necessarily need a Strategie class with abstract base and concrete subclasses - most often plain old callback functions JustWork(tm)).
EDIT totally unrelated but this:
def __init__(self):
# initialize logging
logging.config.fileConfig(os.path.join(os.getcwd(),
'../myconfig.ini'))
self.logger = logging.getLogger(__name__)
is NOT how to use logging. Library code can use loggers, but must not configure anything - this is the application's (your main script / function / whatever) responsability, the rational being that the proper logging config depends on the context - which type of application is using the lib (a CLI app, a local GUI app and a backend web app don't have the same needs at all) and in which kind of environment (a local dev env will want much more logs than a production one for example).
Also, with the logger created with __name__ in your base class module, all child classes will send their log to the same logger, which is certainly not what you want (you want them to have their own package / module specific loggers so you can fine tune the config per package / module).
And finally, this:
os.path.join(os.getcwd(), '../myconfig.ini')
certainly doesn't work as you expect - your cwd can be just anything at this point and you have no way of knowing in advance. If you want to reference a path relative to the current file's directory, you want os.path.dirname(os.path.realpath(__file__)). And of course adding system specific path stuff (ie "../") in a os.path.join() call totally defeats the whole point of using os.path.
When inheriting a class and overriding a method you don't always know what's inside the original class. And if I understand correctly, various aspects of how this is handled in Python are intentionally designed to accommodate this. But I have to think that all or most of the Qt code is documented somewhere. I've found the Qt for Python documentation to be refreshing (compared to PyQt) and lists all methods for a class with a fair amount of detail but I've not been able to find the actual code for specific methods and descriptions are not always very complete. For instance, consider if I want to override the mousePressEvent for a combobox.
class mycombo(QtWidgets.QComboBox):
def __init__(self, parent = None):
super(mycombo, self).__init__()
self.setAcceptDrops(True)
self.setFocusPolicy(QtCore.Qt.NoFocus)
def mousePressEvent(self,event):
In the Qt for Python documentation I see that QComboBox inherits from QWidget
which has this to say about mousePressEvent:
https://doc.qt.io/qtforpython/PySide2/QtWidgets/QWidget.html#PySide2.QtWidgets.PySide2.QtWidgets.QWidget.mousePressEvent
There are some useful things written there but, how do I determine what's actually happening in the 'original' mousePressEvent? I don't want to interfere with other parts of the operation that are actually desired. In this case, perhaps the handling of popup widgets like the description mentions, is desired. But I also might not want to super the original method. Is there more documentation for this that I've somehow missed? It seems that some of the widgets are subclassed and modified in Python and others are only in C++?
TL; DR; There is no documentation or need as the source code can change without notifying developers.
Actually you should not know what each method does since that can change in a new version. If your goal is to add functionalities then do not override the implementation of the parent class by calling it to super().foo_method(), so you can add logic before or after the original implementation
class MyCombo(QtWidgets.QComboBox):
def __init__(self, parent = None):
super(MyCombo, self).__init__(parent)
self.setAcceptDrops(True)
self.setFocusPolicy(QtCore.Qt.NoFocus)
def mousePressEvent(self,event):
# stuff
super(MyCombo, self).mousePressEvent(event)
# another stuff
If you still want to know what happens in that function then you should check the source code:
void QComboBox::mousePressEvent(QMouseEvent *e)
{
Q_D(QComboBox);
if (!QGuiApplication::styleHints()->setFocusOnTouchRelease())
d->showPopupFromMouseEvent(e);
}
Qt has 2 types of API since it implements PIMPL/D-Pointer so analyzing the source code of the class will not be enough if you want to understand the logic, the public API rarely changes for what it is, but instead the private API has changes continuously.
In conclusion, if you want to add functionalities then just analyze the documentation as this is respected even when the code changes. Another way of understanding how it works is by modifying and analyzing the changes that occur in the GUI.
What PyQt/Qt For Python does is a wrapper to handle C++ classes, so in general what can be done in C++ can be done in Python except for some minor things that can be done in one and not in another.
I have constructed a main window GUI using qt designer and pyqt. As the program grows more complex, using only one class may result in too many methods and attributes to manage. I figured that I should construct new classes in order to make things more manageable.
My first question is, how do I know when do I add a new class for my application? Is there any rule of thumb as a general guide? Is it a good idea to add a new class for new windows/tabs?
My second question is, if I added new classes for my application, how do my new class gain access to the Ui_MainWindow design file that I designed in Qt designer? Below is the sample code for my main window. Its a simple clock which displays the current time. Lets say if I would like to create a class for the clock display itself, how can I rewrite the code using OOP efficiently?
from PyQt4 import QtGui
from myMainWindowUI import Ui_MainWindow
class MyMainWindow(QtGui.QMainWindow, Ui_MainWindow):
def __init__(self, *args, **kwargs):
super(MyMainWindow, self).__init__(*args, **kwargs)
self.setupUi(self)
self.timer = QtCore.QTimer(self)
self.timer.timeout.connect(self.Time)
self.timer.timeout.connect(self.Date)
self.timer.start(1000)
self.lcdNumber_time.setDigitCount(8)
self.lcdNumber_time.display(strftime("%H"+":"+"%M"+":"+"%S"))
self.label_dynamic_date.setText(strftime("%Y"+" "+"%B"+" "+"%d"+", "+"%A"))
def Time(self):
self.lcdNumber_time.display(strftime("%H"+":"+"%M"+":"+"%S"))
def Date(self):
self.label_dynamic_date.setText(strftime("%Y"+" "+"%B"+" "+"%d"+", "+"%A"))
app = QtGui.QApplication(sys.argv) # A new instance of QApplication
form = MyMainWindow()
form.show()
app.exec_()
In general, this isn't necessarily a Qt-specific problem. It isn't necessarily a python-specific problem either. You could extend this question to any language that supports class-based programming, or even any language with functions.
It makes sense to write a class when you want to encapsulate behavior. A class should usually provide a single purpose, and expose an interface to the outside that allows users of the class to interact with exactly the behavior you have designed. Once you have this single-purpose class, you now have reusable behavior. You could apply part of this reasoning to functions, where you say a given function has a specific purpose and once you design it to do the one bit of behavior, you now have a reusable function.
Applying this to Qt, it would make sense to move code into its own class when its logic is no longer trivial. An example would be where you are first creating and showing a QMessageBox from your main window. But then at some point you need to collect more types of information, and even pass some initial information in when you construct the dialog. While you could construct this on the fly in your main window, as needed, it would be better to move it into its own dialog class, with its own private logic of how to be constructed. Then you just instantiate one as needed, passing it the expected parameters to its constructor. Now your main window no longer has to also be concerned with constructing special dialogs.
Another point (which wasn't exactly clear from your question) is that Qt Designer UI files each represent a single class. It is expected that this UI definition will be applied to a single class in code. It would be bad design to have ClassA(UI_mainWindow) and ClassB, and have ClassB access members of ClassA or know anything about the internal implementation of ClassA. Back to our topic of "separation of concerns", ClassB should have its own purpose and interface, and be used by the ClassA(UI_mainWindow) to achieve that purpose. You don't want ClassB knowing anything about the main window or being able to do more than its designed purpose.
Let's assume your timer example was actually more trivial than you have shown it to be. If you moved it to another class, you should rely on custom signals to communicate intentions back to other classes like the main window. Or you could move each of the lcd and label widgets into their own custom classes with their own timer logic that made them self contained. Either way, signal/slot lets custom widgets connect with each other without needing to know anything about the other widgets.
In summary, you could say that it would be good to create individual classes in Qt when you are constructing any non-trivial UI elements in another class (when it requires many lines of code, or it requires a bunch of SLOT functions and wiring for internal logic). This will keep you from repeating your logic, and allow you to have reusable code. It will also keep your main window smaller and easier to debug, since you can keep a smaller mental model in your brain of what the main window is doing. If you try to keep your UI elements as single-purpose focused and generic as possible, you will end up having a lot of classes that can be reused.
Im programming a library, I want to structure my code in a way that potential users find it easy to use this library. I have looked at this excellent video of great API design. One of the golden rules is to have a good design pattern. I have two in mind. The Facade design patten and the factory design patten. Both these design pattens are used to achieve a great level of abstraction in program code for users to use.
Im finding it ever so difficult on which or if both to apply. Of course, I would like to avoid having anti-pattens.
The language I am using is Python, which is quite different to Java Which is emphasised in the video link provided above.
How my library would work:
Character class
Window class
Many character objects can be created.
Say if I was to use the facade design pattern I would have both this classes initialised in the facade constructor, so that they can be called in the methods:
class Facade():
__init__(self):
self.character = Character()
self.window = Window()
here I would create methods which represent methods created in the character and window class. These could then easily be called by users:
Facade = Facade()
Facade.methodUsedInCharacterClass()
Facade.methodUsedInCharacterClass()
Facade.methodUsedInWindowClass()
But here is where I see the facade having a problem, you can have two different characters, which you would want to have to do different things. You could do this:
Facade = Facade()
badguy= Facade.methodUsedInCharacterClass()
goodguy= Facade.methodUsedInCharacterClass()
Facade.methodUsedInWindowClass()
You cant then use the badguy or goodguy variables to invoke other behaviours, such as
badguy.rotate()
goodguy.jump()
This is not allowed, but is there a way of doing this?
Also, as the constructor is calling the classes, a factory method could be used, which choses at run time which class to execute by my own understanding. I can only visualise, but in this case how would it apply?
Thanks!
You seem to have misunderstood the purpose of factory and facade patterns.
The factory pattern is used to build things. So you will have a CharacterFactory and a WindowFactory. If customers need to have special characters, they need a way to replace your default CharacterFactory with theirs.
The character factory should then be able to produce different types of characters. This way, you can build default good and bad guys for your game. Customers can then override these methods to modify the defaults.
The facade is used to make an object appear as if it was of a different type. So your window might have a child of type View. A CharacterView would then be a facade which maps information from the character into data for the View interface which the window can then use to display information like health without knowing anything about the character or health.
This means you also need a configuration object that contains the default factories. Customers get one of those from the ConfigFactory.
class ConfigFactory:
def createConfig(self):
config = Config()
config.characterFactory = self.createCharacterFactory()
return config
def createCharacterFactory(self):
return CharacterFactory()
Customers will override this to get their own factory:
class CustomConfigFactory(ConfigFactory):
def createCharacterFactory(self):
return CustomCharacterFactory()
I am dealing with a python application that consists of multiple distributed lightweight components that communicate using RabbitMQ & Kombu.
A component listens on two queues and can receive multiple message types on each queue. Subclasses can override how each message type is processed by registering custom handlers.
All this works fine.
I now have the added requirement that each component must have a basic REST/HTML interface. The idea being you point your browser at the running component and get realtime information on what it is currently doing (what messages it is processing, cpu usage, state info, log, etc.)
It needs to be lightweight, so after some research I have settled on Flask (but am open to suggestions). In pseudocode this means taking:
class Component:
Queue A
Queue B
...
def setup(..):
# connect to the broker & other initialization
def start(..):
# start the event loop and wait for work
def handle_msg_on_A(self,msg):
# dispatch a msg to a handler depending on the msg type
def handle_msg_on_B(self,msg):
...
...
and adding a number of view methods:
#app.route('/')
def web_ui(self):
# render to a template
#app.route('/state')
def get_state(self):
# REST method to return some internal state info as JSON
...
However, bolting a web UI onto a class like this breaks SOLID principles and brings problems with inheritance (a subclass may want to display more/less information). Decorators are not inherited so every view method would need to be explicitly overridden and redecorated. Maybe using a mixin + reflection could work somehow but it feels hackish.
Instead, using composition could work: put the web stuff in a separate class that delegates the url routes to a fixed, predefined set of polymorphic methods on the nested component.
This way components remain unaware of Flask at the cost of some loss in flexibility (the set of available methods is fixed).
I have now discovered Flask blueprints and Application Dispatching and it looks like they could bring a better, more extensible solution. However, I have yet to wrap my head around them.
I feel like I am missing a design pattern here and hopefully somebody with more flask-fu or experience with this type of problem can comment.
Something else was quietly introduced in Flask 0.7 that might be of interest to you - Pluggable Views. These are class based rather than function based endpoints - so you can use the dispatch_request method to manage your state transitions (only overriding it when needed).
The benefit of doing it this way, as opposed to using Application Dispatching, is that you get url_for support all across your application (as opposed to having to hard code in URLs that cross application boundaries.) You'll have to decide if this is something that is likely to be an issue for your application.
In pseudo-code:
# File: Components.py
from flask.views import View
class Component(View):
# Define your Component-specific application logic here
dispatch_request(self, *url_args, **url_kwargs):
# Define route-specific logic that all Components should have here.
# Call Component-specific methods as necessary
class Tool_1(Component):
pass
class Tool_2(Component):
# Override methods here
# File: app.py
from flask import Flask
from yourapplication import Tool_1, Tool_2
app = Flask()
# Assuming you want to pass all additional parameters as one argument
app.add_url_rule("/tool_1/<path:options>", "tool1", view_func=Tool_1.as_view())
# Assuming you want to pass additional parameters separately
tool_2_view = Tool_2.as_view()
app.add_url_rule("/tool_2/", "tool2", view_func=tool_2_view )
app.add_url_rule("/tool_2/<option>", "tool2", view_func=tool_2_view)
app.add_url_rule("/tool_2/<option>/<filter>", "tool2", view_func=tool_2_view)
You can add blueprints to the mix if you have a series of components that are all logically connected together and you don't want to have to remember to put /prefix in front of each one's add_url_rule call. But if you just have a series of components that are mostly independent of each other, this is the pattern I'd use*.
*. On the other hand, if they need to be isolated from each other I'd use the Application Dispatch pattern recommended in the docs.