寫了幾個小專案,在幫助同事的時候發現,每個人對MVC這種設計模式的理解各有千秋。
我對於MVC的理解是M即Model,指的是資料庫層面,V即View,指的是檢視層面,至於C即Control,則是程式碼的邏輯部分。
專案背景介紹,使用QT5寫Gui,Mysql作為資料庫。
我採用C繼承V,M繼承C的模式來實現MVC。view層是將QT生成的ui檔案轉化成python程式碼,不直接修改view層的程式碼;model實現對資料庫的CRUD操作,並return。control作為中間層,呼叫model層的方法獲取結果,完成邏輯功能,再傳遞給view層實現資料渲染。
# view.py
class View(QDialog):
pass
def render_view(self, data):
# render view
pass
# control.py
class Control(View):
pass
def do_something(self):
data = self.get_data()
self.render_view(data)
# model.py
class Model(Control):
pass
def get_data(self):
return `something`
由於model層繼承於control層,當我呼叫model層,也就是control的子類的方法時,它是不存在的,所以我得先宣告一個空方法。
#control.py
class Control(View):
pass
def do_something(self):
data = self.get_data()
self.render_view(data)
def get_data(self):
pass
但達到一定量的程式碼量時,發現control層的pass方法(方法體內只有pass)越來越多,覺得這樣不妥呀~,而且當我要測試資料庫互動是否正常時,也就是測試model層的程式碼,總是會彈出它爸爸的爸爸,也就是view層寫的Gui,導致感覺非常難受。
於是乎,選擇重構,前後花了兩週不到的時間,複用了部分邏輯,程式碼從18K+降到了11K左右。
我選擇將model層作為一個部件類,裝配到control層,原先的view和control的關係不變。
# view.py
class View(QDialog):
pass
def render_view(self, data):
# render view
pass
# control.py
class Control(View):
def __init__(self):
super().__init__()
self.model = Model()
pass
def do_something(self):
data = self.model.get_data()
self.render_view(data)
# model.py
class Model(object):
pass
def get_data(self):
return `something`
這樣處理後,我的model層至此和邏輯徹底分離,測試資料庫互動方便多了,直接在model層下寫個main方法就可以了,而且針對control層可以進行復用,也就是在相同Gui下,我可以在control層例項化多個不同的model,根據業務需要呼叫不同的model,提升程式碼的複用率。
哇咔咔~~