Design: How to inform controllers about data modification across application
Asked Answered
P

4

14

In a big system mvc-based there are views responsible for editing data and views that display that data.

Example: UserManagementView and UserSelectionView.

Each subsystem should know whether it needs a data update, after another subsystem has made changes to the same data, in order for its controller to know whether a data update is needed.

My thoughts on this is something like the observer pattern (which is kinda integrated in c#) and all controllers would be listeners and eventually would get notified that data-manipulation occurred.

BindingList<> for example provides a ListChanged event. Similarly, an interface can be created for each data-structure and notify the controller about the change. This would add overhead (IMO) and I find this solution difficult to maintain in a big system, also updating data anyways is not a solution.

Which architectural design can help in this kind of scenarios?

Preoccupancy answered 15/6, 2012 at 13:52 Comment(2)
Should the controller be deciding this? Why does it not delegate this task to a business class?Feoffee
Yes. Actually I am more interested in the architecture of such design. You are correct that the controller is responsible. The question remains..Preoccupancy
N
5

This question sounds like you are trying to use MVC without the model part. If I've misunderstood, editing your question to include a practical use case (example) may help us understand the context.

In general though, nothing should really be persisted/stored in your controllers. So there should be nothing in the controller that requires 'updating' or 'notifying' (ie: no data). Rather the data should be in a separate 'model' layer which manages all your data. Then the views read from the model layer to grab any data for that view.

For a quick refresher check out the wikipedia page on MVC which has a nice classic MVC flowchart and simple write-up on component interactions.

Example for Discussion

Let's try to contrive an example for the purpose of understanding this problem.

Let's say I have a list of users in my application. This list might be shown on:

  • A master admin list view
  • An admin edit user view
  • A user's personal profile view
  • Maybe more?

Each of those views will request the data from your model layer and show something on the screen.

Now let's say a change was committed to one user's profile. That would be accomplished via a controller method which does any work necessary to apply some changes to the model.

My understanding is that you want all of those views to update to reflect that change. That means the views need to reload data from the model. It should not be getting this data from the controller itself, even if the controller triggers this reload/refresh - or rather a controller method may facilitate querying from your model layer. The important part is that you aren't maintaining multiple copies of your data in multiple controllers throughout your application. The persistence is centralized in the model layer.

In the case of winforms the model layer may be able to provide something like the mentioned INotifyPropertyChanged interface if your UI components are built to recognize that interface and refresh accordingly. But that is a fairly platform dependent approach.

A more platform/context agnostic approach would be the pub-sub (publish-subscribe) pattern also mentioned already. In this case each controller method that makes a change to the model would also publish a notification of its changes. Any views for that data can be listening and respond to such a notification by refreshing/reloading the view's data from the model layer.

Nelidanelie answered 29/8, 2012 at 6:45 Comment(0)
I
3

I've successful used the Publish–subscribe pattern pattern to solve this kind of problems. Whenever someone modifies something, that someone might be interested in knowing, you raise a "ObjectWasModified" event, or something more specific if you want like "NewUserAdded", etc... And then, every subsystem or other thing needing to know when that happens, it subscribes to the event of that type. You can add a template parameter to the Event ObjectWasModified or additional conditions, so each system only receives the events that it's really interested in.

Ilyssa answered 9/7, 2012 at 3:18 Comment(0)
K
3

I know WPF in combination with MVVM relies heavily upon INotifyPropertyChanged and additionaly INotifyCollectionChanged. Maybe this simple interface might just do the trick for you.

Read about this here. An article from Josh Smith on the basics of MVVM whereby you can understand the use of INotifyPropertyChanged. Although it's in a WPF environment it's usable in WinForms as well.

Kalmar answered 28/8, 2012 at 12:42 Comment(0)
S
3

Why don't you just use the event model built into .NET? Am I not understanding the question correctly? Your question indicates that you think this add a lot of "overhead" (not clear if you mean performance or developmental), but this solution is very lightweight from a performance standpoint.

class YourModel
{
    //---- event class can contain data elements to update listeners
    public class DataChangedEventArgs : EventArgs
    {
        ...
    }

    //---- this is what the client callback need to look like
    public delegate void DataChangedDelegate(object oSender, DataChangedEventArgs args);

    //---- public event that clients subscribe to
    public event DataChangedDelegate evtDataChanged;

    //---- any changes in YourModel invoke this method to notify clients
    protected void OnChanged(DataChangedEventArgs args)
    {
        if (evtDataChanged != null)
            evtDataChanged(this, args);
    }

    //---- method(s) in your Model that change internal data
    public void ImaDataChanger(...) 
    {
        //---- stuff that changes the data

        OnChanged(args);    //-- notify clients
    }
}

class UserSelectionView
{
    //---- the event callback
    public void DataChangedHandler(object oSender, YourModel.DataChangedEventArgs args)
    {
        //---- process update or refresh data
        //---- UI updates will have to be marshalled to the UI thread
    }

    //---- sign up for events
    public void Subscribe(YourModel model)
    {
        model.evtDataChanged += new YourModel.DataChangedDelegate(DataChangedHandler);
    }
}

You have the option of defining additional events or adding data members to DataChangedEventArgs to provide information about the type of data change.

Also, as indicated in the comments below, if you need to put the view on different computers or in different processes on the same computer, you can use .NET Remoting to achieve this with very few changes in code.

Subsume answered 29/8, 2012 at 6:34 Comment(2)
This is an interesting question because it is an abstract question with a specific use case. The .Net event model would not work for a web based MVC app as the views have a short life cycle until they are rendered. You can't force a web page to be refreshed from a .Net event unless you have some pub-sub system setup to do so. However, your suggestion could work for a winforms app on a single computer (which is what the OP was asking, I'm just thinking more academically :-).Nelidanelie
It specifically stated WinForms. I would not have recommended this solution for ASP. Also, your assertion about this only being appropriate for a single computer is wrong. Using .NET Remoting, this solution can quite easily be expanded to multiple processes on a single computer or to a view clients running on separate computers. Just to inform the academic debate...Subsume

© 2022 - 2024 — McMap. All rights reserved.