i apologise if this is a silly question however i recently have the following use case.
I have a component which I want to reuse, in one instance i want to be able to edit the data and in another instance i only want it to be viewable.
so this means in one use case i want to render say labels 1, 2 and 3 along with an edit button and in the second use case i do not want to render the edit button.
Now I am using the mvp pattern and I am currently of the understanding that logic should not appear in the presenter.
My question is: if i want to render a component based on logic from the presenter how do i do this without introducing logic in the view.
short examples are very welcome :)
Back-end > sends > the model > to > the presenter > which calls display method on > the view
Your model would be a POJO (typically a shared object retrieved from the back-end). The presenter would make and RPC call to retrieve it. Based on the model configuration the presenter will or will not call some "setAsEditable(Boolen editable)" method available on the view when receiving the model.
The view > sends events to > the presenter > which updates > the model > and sends it to > the back-end
When the user make some action on the view the presenter will receive a notice of it (through events or based on an interface) and update the model. Note the model update logic (like the display logic) is also meant to be in the presenter. The model would then be pushed back to the back-end by the presenter (via RPC). Business logic stays in the back-end.
Personal note:
Hardcore MVPers would enforce strict loose coupling between components, but it often involves writing lots of event classes and/or interfaces (some call it boilerplate). Be pragmatic. I sometimes avoid using this architecture when I know my components won't be reused, and wait until the need for reuse comes to me.
But if you can manage to stay pure, you're good !
Related
In section 10 of the OpenUI5 Developer Guide tutorial on routing (see here), it talks about lazy loading. However the tutorial does not show how to lazy-load data.
Scenario: I have an OpenUI5 app that gives a list of employees and on a detail page shows the main employee details and gives access to further info, projects, hobbies, and notes from the selected employee's resume.
Because in 99.99% of the use cases a user will not wish to look at hobbies, I will prefer not to load hobbie data with the main model for the app. I make this choice based on performance concerns. Instead I will detect the user has requested to see hobbies and load the hobbies data for the current user into the model.
How would I do that ?
Edit: I managed to discover the onTabSelect() plumbing [tip to other confused folks, the OpenUI5 tutorials tend to leave stuff out to keep on topic - it is useful to look at the code of their working versions if you get lost]. After this the routing in the tutorial makes a lot more sense.
My question remains relevant but changes slightly to 'User clicks a tab and I am about to load further JSON data into the model. Should I do this in onInit() of the target controller or before navTo() is invoked to load the controller?' I can see an issue because of the async nature of the JSON fetch meaning if I use onInit() I could end up displaying the page controls before the data arrives.
What is the best practice please ? My money is on pre navTo() though that is an ugly pattern as I would have to repeat the JSON fetch elsewhere if I have another route to the lazy-loading view.
To stick with the example. You can attach your HobbiesController in its onInit method to the display event of the target you are displaying:
var router = this.getOwnerComponent().getRouter();
var target = router.getTarget("resumeTabHobbies");
target.attachDisplay(this.onDisplay, this);
Then you define an onDisplay method which will be now called if you select the corresponding tab and populate your model there.
I have a presenter which makes calls to Handler and get the data from server
same data is needed for another widget which is a miniature version of the existing view, but this will present all time in application.
Here what i have common is calls to handler, same handler and action objects.
What is the best way to design.
My possible solution :
1) Writing one Common class which has access to the dispatcher object (Inject through Ginjector), use the methods to get data.
But as per MVP architecture, dispatcher usage is restricted to presenter only, but this is non-presenter class.
AFAIK there is nothing about MVP which says that everything has to be done in the Presenter. It make sense to encapsulate logic which is common to multiple Presenters in one common class.
MVP is rather a pattern than a rule which is written in stone. So when it makes sense you can deviate a little bit from the pattern.
IMHO the common class is a the right approach.
Using a common class for handling the requests to the backend also makes it easy to implement caching and authentication for example.
There are two ways to do the communication between your Presenters and the common class:
Inject a singleton instance of your common class into all the Presenters that need the data. From the presenter you can call the a method on the common class and register a callback.
Inject the global EventBus into the common class and fire an Event (i.e. LoadDataEvent) from the corresponding Presenters and handle this Event in the common class. When the data is received from the backend you can fire another Event (i.e. DataLoadedEvent) from the common class and handle it in the corresponding Presenters.
Solution 1 is probably easier to implement but you have some coupling between the common class and the Presenter (it's not that bad if you use dependency injection).
Solution 2 requires a little bit more code (you have to define the Events) but provides a lot of flexibility and de-coupling. For example if you create a new Presenter that is also interested in the data you just need to register a Handler for the DataLoadedEvent in the Presenter and you are done.
If you are using event bus, your presenter(which makes calls to Handler) can fire events with new data and your miniature widget can register with event bus to receive them. This way only one presenter would call to server and anything on client can be notified using events.
Me and my team are currently rookie developers in Objective-C (less than 3 months in) working on the development of a simple tab based app with network capabilities that contains a navigator controller with a table view and a corresponding detailed view in each tab. The target is iOS 4 sdk.
On the networking side, we have a single class that functions as a Singleton that processes the NSURLConnection for each one of the views in order to retrieve the data we need for each of the table views.
The functionality works fine and we can retrieve the data correctly but only if the user doesn't change views until the petition is over or the button of the same petition (example: Login button) is pressed on again. Otherwise, different mistakes can happen. For example, an error message that should only be displayed on the root view of one of the navigation controllers appears on the detailed view and vice versa.
We suspect that the issue is that we are currently handling only a single delegate on the Singleton for the "active view" and that we should change it to support a behavior based on the native Mail app in which you can change views while the data that was asked for in each one of the views keeps loading and updating correctly separately.
We have looked over stackoverflow and other websites and we haven't found a proper methodology to follow. We were considering using an NSOperationQueue and wrapping the NSURLConnections on an NSOperation, but we are not sure if that's the proper approach.
Does anyone have any suggestions on the proper way to handle multiple asynchronous NSURLConnections to update multiple views, both parent and child, almost simultaneously at the whim of the user's interaction? Ideally, we don't want to block the UI or disable the buttons as we have been recommended.
Thank you for your time!
Edit - forgot to add, one of the project restrictions set by our client is that we can only use the native iOS sdk network framework and not the ASIHTTPRequest framework or similar. At the same time, we also forgot to add that we are not uploading any information, we are only retrieving it from the WS.
One suggestion is to use NSOperations and a NSOperationsQueue. The nice thing about this arrangement is you can quickly cancel any in-process or queued work (if say the user hits the back button.
There is a project on github, NSOperation-WebFetches-MadeEasy that makes this about as painless as it can be. You incorporate one class in your classes - OperationsRunner - which comes with a "how-to-use-me" in OperationsRunner.h, and two skeleton NSOperations classes, one the subclass of another, with the subclass showing how to fetch an image.
I'm sure others will post of other solutions - its almost a problem getting started as there are a huge number of libraries and projects doing this. That said, OperationsRunner is a bit over 100 lines of code, and the operations about the same, so this is really easy to read, understand, use, and modify.
You say that your singleton has a delegate. Delegation is inappropriate when multiple objects are interested in the result. If you wish to continue using a singleton for fetching data, you must switch your pattern to be based on notifications. Your singleton will have responsibility for determining which connection corresponds to which task, and choosing an appropriate notification to be posted.
If you still need help with this, let me know, I'll try to post some sample code.
Lets take this example. I have a AView which is bound to AViewModel. AView should execute an ACommand on AViewModel, and pass it a parameter. The problem is that ViewA doesnt have enough information to pass to command, so another BView needs to be displayed, in order to gather information from the user. After the VIewB is closed, ViewA invokes ACommand on AViewModel, and passes parameter to it.
How to handle this scenario? Should I allow AView to communicate directly to BView, or I am breaking some rule if I do so?
Another way I am thinking is to invoke a ACommand on AViewModel without a parameter, then from VIewModelA send a message that a information is required to complete the task. This information is captured by MainPageViewModel, than sends a request to open BView, which is bound to BViewModel. When BView is closed, a BVIewModel sends a message with additional info, and ViewModelA has subscribed to this type of message, so it receives it, and completes the task. Pretty complicated for just entering values in two text boxes, right? :)
There are 3 golden rules to MVVM: Separation, Separation & Separation :)
Reasons include: Automated testing of components, complete separation of functionality (e.g. for independent modules), independent team development of modules (without tripping over each other) and generally just easier to figure out what does what.
In answer to your interconnecting two Views: you are adding dependencies that should not exist. Separation of concerns is more important than a little complexity (and I would argue that the messaging model is less complex than maintaining a direct interconnection).
The complexity of publishing/listening for an extra message is nothing compared to the harm of interconnecting unrelated components so your last suggestion is "better", but I would actually suggest a cleaner approach to the whole problem:
A few guidelines:
Views should not know where their data comes from, only how to display a certain shape of data. Command execution is via bindings to ICommands on the VM.
ViewModels should hold a certain shape of data and commands. It should have no idea where the data comes from or what is binding to it.
Models hold the actual data, but have no idea where it is consumed.
Controllers (often overlooked in MVVM) register/push events, populate VMs from models, set the code in ICommands, control visibility of views etc. Controllers are the only thing actually required to stay in memory at all times and they are quite slim (mostly code & little data).
Basically I would suggest adding Controllers to your MVVM pattern (MVCVM?). App/modules create and initialize controllers. Controllers subscribe to events and provide the logic of the application.
Try this pattern and see how simple it becomes to work with lots of Views, ViewModels and Models. You do not mention what language or framework you are using, so I can't make specific suggestions for examples.
The ViewModel can notify the View about property change by raising property change event. If the underlying data (for example, a Plain class which do not implement IPropertyChange) changes, how can ViewModel get notified?
If the underlying data (for example, a Plain class which do not implement IPropertyChange) changes, how can ViewModel get notified?
It cannot, there has to be a mechanism in place to do the notification. The most likely cause is a POCO that is used in one region (or module) of the application is also being used in another, i.e. a loosely coupled master-detail situation. If you are "sharing" the same instance of a POCO like this, then it is unlikely that you haven't also implemented change notification in it. If you have implemented change notification, then a change in one module of the application will automatically be visible to the other module (they are both looking at the same object) and anything that watches for that change notification (like a binding subsystem) will do its thing and pick up the changes.
If you have two separate instances of the same data and one gets updated, the other will not know about it. This also happens when your VM requests data via the Model, and the Model retrieves the data from a disconnected data source like a database or a web service. You don't know when the underlying data has been changed, once again you need to implement a change notification system. You can also take another aproach with this - let the user change the data, then do a fresh grab of the data before saving the user's changes, and if the underlying data has changed while the user was working then you can notify the user and take the appropriate action (or let the user choose the appropriate thing to do).
Does this answer your question? Or do you care to elaborate more about what you are wanting to know?