मैंने अतीत में इस विषय के बारे में काफी पढ़ा है और अंकल बॉब की इस तरह की कुछ दिलचस्प बातचीत देखी । फिर भी, मुझे अपने डेस्कटॉप एप्लिकेशनों को ठीक से आर्किटेक्ट करने में हमेशा बहुत मुश्किल लगता है और यह भेद करना चाहिए कि यूआई की तरफ जिम्मेदारियां होनी चाहिए और तर्क पक्ष के लोगों की।
अच्छी प्रथाओं का बहुत संक्षिप्त सारांश कुछ इस तरह है। आपको यूआई से डिकोड किए गए अपने तर्क को डिज़ाइन करना चाहिए, ताकि आप अपने पुस्तकालय का उपयोग कर सकें (सैद्धांतिक रूप से) कोई फर्क नहीं पड़ता कि किस तरह का बैकएंड / यूआई फ्रेमवर्क है। इसका मतलब यह है कि मूल रूप से यूआई जितना संभव हो उतना डमी होना चाहिए और तर्क पर भारी प्रसंस्करण किया जाना चाहिए। अन्यथा, मैं सचमुच एक सांत्वना अनुप्रयोग, एक वेब अनुप्रयोग या एक डेस्कटॉप के साथ अपने अच्छे पुस्तकालय का उपयोग कर सकता है।
इसके अलावा, चाचा बॉब सुझाव देते हैं कि किस तकनीक का उपयोग करने की अलग-अलग चर्चाएं आपको बहुत सारे लाभ (अच्छे इंटरफेस) प्रदान करेंगी, डिफरेंसिंग की यह अवधारणा आपको बहुत अच्छी तरह से परीक्षण की गई संस्थाओं को बहुत कम करने की अनुमति देती है, जो बहुत अच्छा लगता है लेकिन फिर भी मुश्किल है।
इसलिए, मुझे पता है कि यह प्रश्न काफी व्यापक प्रश्न है जिस पर संपूर्ण इंटरनेट पर और कई बार अच्छी पुस्तकों के बारे में भी चर्चा हुई है। तो इससे कुछ अच्छा पाने के लिए मैं pyqt पर MCV का उपयोग करने के लिए एक बहुत ही छोटे डमी उदाहरण पोस्ट करूँगा:
import sys
import os
import random
from PyQt5 import QtWidgets
from PyQt5 import QtGui
from PyQt5 import QtCore
random.seed(1)
class Model(QtCore.QObject):
item_added = QtCore.pyqtSignal(int)
item_removed = QtCore.pyqtSignal(int)
def __init__(self):
super().__init__()
self.items = {}
def add_item(self):
guid = random.randint(0, 10000)
new_item = {
"pos": [random.randint(50, 100), random.randint(50, 100)]
}
self.items[guid] = new_item
self.item_added.emit(guid)
def remove_item(self):
list_keys = list(self.items.keys())
if len(list_keys) == 0:
self.item_removed.emit(-1)
return
guid = random.choice(list_keys)
self.item_removed.emit(guid)
del self.items[guid]
class View1():
def __init__(self, main_window):
self.main_window = main_window
view = QtWidgets.QGraphicsView()
self.scene = QtWidgets.QGraphicsScene(None)
self.scene.addText("Hello, world!")
view.setScene(self.scene)
view.setStyleSheet("background-color: red;")
main_window.setCentralWidget(view)
class View2():
add_item = QtCore.pyqtSignal(int)
remove_item = QtCore.pyqtSignal(int)
def __init__(self, main_window):
self.main_window = main_window
button_add = QtWidgets.QPushButton("Add")
button_remove = QtWidgets.QPushButton("Remove")
vbl = QtWidgets.QVBoxLayout()
vbl.addWidget(button_add)
vbl.addWidget(button_remove)
view = QtWidgets.QWidget()
view.setLayout(vbl)
view_dock = QtWidgets.QDockWidget('View2', main_window)
view_dock.setWidget(view)
main_window.addDockWidget(QtCore.Qt.RightDockWidgetArea, view_dock)
model = main_window.model
button_add.clicked.connect(model.add_item)
button_remove.clicked.connect(model.remove_item)
class Controller():
def __init__(self, main_window):
self.main_window = main_window
def on_item_added(self, guid):
view1 = self.main_window.view1
model = self.main_window.model
print("item guid={0} added".format(guid))
item = model.items[guid]
x, y = item["pos"]
graphics_item = QtWidgets.QGraphicsEllipseItem(x, y, 60, 40)
item["graphics_item"] = graphics_item
view1.scene.addItem(graphics_item)
def on_item_removed(self, guid):
if guid < 0:
print("global cache of items is empty")
else:
view1 = self.main_window.view1
model = self.main_window.model
item = model.items[guid]
x, y = item["pos"]
graphics_item = item["graphics_item"]
view1.scene.removeItem(graphics_item)
print("item guid={0} removed".format(guid))
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
# (M)odel ===> Model/Library containing should be UI agnostic, right now it's not
self.model = Model()
# (V)iew ===> Coupled to UI
self.view1 = View1(self)
self.view2 = View2(self)
# (C)ontroller ==> Coupled to UI
self.controller = Controller(self)
self.attach_views_to_model()
def attach_views_to_model(self):
self.model.item_added.connect(self.controller.on_item_added)
self.model.item_removed.connect(self.controller.on_item_removed)
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
form = MainWindow()
form.setMinimumSize(800, 600)
form.show()
sys.exit(app.exec_())
उपरोक्त स्निपेट में बहुत सारी खामियां हैं, और अधिक स्पष्ट रूप से यह मॉडल UI फ्रेमवर्क (QObject, pytt संकेतों) के लिए युग्मित किया जा रहा है। मुझे पता है कि उदाहरण वास्तव में डमी है और आप इसे एक ही QMainWindow का उपयोग करके कुछ लाइनों पर कोड कर सकते हैं, लेकिन मेरा उद्देश्य यह समझना है कि कैसे एक बड़े pyqt एप्लिकेशन को ठीक से आर्किटेक्ट किया जाए।
सवाल
आप अच्छी तरह से सामान्य प्रथाओं का पालन करते हुए MVC का उपयोग करके एक बड़े PyQt एप्लिकेशन को कैसे ठीक से आर्किटेक्ट करेंगे?
प्रतिक्रिया दें संदर्भ