web-dev-qa-db-ja.com

MVCパターンでのモデルとビュー間のデータ同期

MVCパターンについて、コントローラー部分について質問があります。

私がたまたま書いたプログラムのほとんどは基本的にスプレッドシートのようなものです。それらはC/GTK +とPython3/Qt5/Tkinterで書かれていますが、共通の設計を共有しています。MVCパターンのように見えるロジック(データ構造体と重い方法)からGUIを分離しています。

質問 GUIデータを編集して何かを計算するたびに、ビューからモデルにデータを渡す必要がありますか?次に、新しいデータをモデルからビューに渡しますか?それはどのように行われるべきですか?これは、モデルで大量の計算を行う小さなGUIでは問題ないことを理解しています。しかし、大きなテーブルやスプレッドシートのような大きなGUIはどうでしょうか。

Answer @dcorkingとのディスカッションから取った要素は次のとおりです。自分でデータを更新する必要があります。 1つのショートカットは、ケースごとに更新することです。更新が必要なものだけを更新し、残りは変更しないでください。明らかに、1回の変更後にコレクションを並べ替える場合は、いずれにしてもGUI全体を再更新する必要がある場合があります。上記のように自動化された方法のように聞こえる「オブザーバー」が言及されています。

疑似/ Pythonコード

基本的なcollectionitems(ショッピングリスト、ブックライブラリなど)を考えてみましょう。私のメインクラスCollectionには、Itemのリスト(数十または数百)と、リストに適用されるメソッドが含まれています。

#The model package

class Collection():
    def __init__(self, name=""):
        self.name = name
        self.items = []
        self.itmesToUpdate = []

    def sort(self):
        self.items.sort(key=lambda x:float(x.price))
        self.itemsToUpdate = []
        self.itemsToUpdate = listItemsThatWereMovedAround()

class Item():
    def __init__(self, name="", price=0.):
        self.name = name
        self.price = price

今、Guiの部分:

class Gui():
    #The View part.
    def __init__(self):
        self.collection = model.Collection()
        ...then fill the View with widgets (Menus, EditTexts, Buttons, ...)

    #The Controller part starts here
    def setViewFromModel(self):
        for i in self.collection.itemsToUpdate:
            self.editTextName[i].setText(self.container.items[i].name)
            self.editTextPrice[i].setText(self.container.items[i].price)
        self.collection.itemsToUpdate = []# reset the list

    def setModelFromView(self):
        for i in self.collection.itemsToUpdate:
            self.container.items[i].name = self.editTextName[i].getText()
            self.container.items[i].price = self.editTextPrice[i].getText()

    #CALLBACKS
    def onItemModified(self, index):
        self.collection.itemsToUpdate.append(index)

    def onClickSort(self):
        self.setModelFromView()#Read the GUI data
        self.collection.sort()#Compute in Model
        self.setViewFromModel()#Update the View with new data

このデザインは大丈夫ですか?スプレッドシートのようなアプリですか?ありがとうございました。

2
funkygoby

MVCはモデルをどのくらい小さくするかを教えてくれません。

スプレッドシートの場合、ビューとモデル間のデータ構造全体の受け渡しが遅すぎる、またはコードが複雑すぎる場合は、MVCトライアドで単一のセルと同じくらい小さいものを表すことができます。

セルのモデル部分は、適切な方法で、シート全体を表すより大きなビジネスオブジェクトに接続できます。

同様に、セルビューは、シートまたはシート上のウィンドウを表す別のビューに埋め込まれます。

更新

MVCの主な目的は、パフォーマンスを改善することではなく、コードをより理解しやすくすることであり、それにより保守が容易になります。

個別のセルごとにMVCトライアドを作成すると、トライアドが列全体またはシート全体を表す場合よりも、理解と変更が容易になります。ただし、多くの小さなオブジェクトが互いにメッセージを送信することになるため、シート全体に影響する変更のパフォーマンスは低下する可能性があります。

ビューとモデル間でのデータの受け渡しを避けたい場合にも検討する必要があるMVCの代替手段の1つは、直接操作です。直接操作では、ユーザーが操作するオブジェクトは、ビジネスデータ(セル値)とビジネスルール(セル値がどのように変化するか)を格納するオブジェクトです。

2
dcorking