I am changing my application to use the MVC pattern. Currently in the notify() method for the observer I am sending the entire model to the View. Is this correct or should be be creating seperate Events and send them to the clients?
The Observable
public interface Observable<T> {
void notifyObservers(T model);
void addObserver(Observer<T> o);
void removeObserver(Observer<T> o);
void removeAllObservers();
}
The Observer
public interface Observer<T> {
void notify(T o);
}
The model sends notifications to view like this
#Override
public void notifyObservers(ModelViewInterface model) {
for(Observer<ModelViewInterface> o : this.observers)
o.notify(model);
}
And I notify them like this
notifyObservers(this);
In the ModelViewInterface I only have the getter methods (no setter methods) and my model implements this interface.
There are a few ways to do this sort of thing. For example, you could:
Send the model with every update, have the view replace its reference with every update.
This is ok, especially for a proof of concept. You may run into problems if you distribute your app across a network, as the messages become larger.
Send the delta with every update, have the view update itself based on this delta. This would have the benefit of smaller messages. On a distributed system this might work better, but you need to handle the local model maintenance in the view.
Dont send any of the model with updates to the view, but just tell the view that the model has changed and it should figure out what to do. On a distributed system, you could have the remote and local models work on keeping each other in sync, but the communication between the model and the view is very simple.
Related
We are developing a board game in Java for a school project and we're having an argument with our tutors on the correct implementation of the MVC pattern (that we are required to use).
In our current implementation the View is subscribed as an Observer to some classes in the model, for example the spaces where the pawns can be placed. This spaces have mutable fields, as you can see in the short example below:
public class Space extends Observable {
private List<Pawn> pawns;
private Card card;
// public getters and setters for pawns and card
}
It seemed very intuitive for us to give the View direct reference to this class, in this way we can query the Space every frame to retrieve its status (we are using libgdx for the GUI, so we are updating the window every frame).
Now, even though we are not modifying the Model in the View but just calling the getters, our tutor said this approach wasn't acceptable because we could modify the Model from the View since we are giving direct reference to mutable objects, and wants us to add a layer of indirection / modify our POJOs in such a way that the View is not able to modify the model.
Could YAGNI be applied to this request? We managed to give the responsibility of modifying the model entirely to the Controller, so I really don't understand why we should change our API just for the reason of restricting access to the Model even though we are not modifying it from the View anyway.
Also, since we are probably going to implement their request, what would be the best approach to complete the task? Making the View see a copy of the model classes so that every modification is pointless? Or maybe creating an interface that only exposes immutable objects to the View?
Thanks in advance for any clarification, we are a bit disoriented by this request.
Ideally, your View layer would only use immutable objects — not the same thing as unmodifiable interfaces to otherwise mutable objects — with the required info from your models. Such objects would be tracked by your Controller and then copied to the corresponding View. The MVC pattern can successfully model such scenario.
You will need to add another layer of indirection to solve your design problem (and still be MVC compliant). A possible solution follows:
Add a new interface with your view data model requirements:
/**
* This interface is adopted by an object that mediates
* the application’s data model for a SpaceView object.
*/
public interface SpaceViewDataSource {
List<Pawn> getPawns();
Card getCard()
...
}
In your View, store the current data source:
public class SpaceView {
private SpaceViewDataSource dataSource;
public void setDataSource(SpaceViewDataSource dataSource) {
this.dataSource = dataSource;
reloadData();
...
}
/** The data source has changed. */
public void reloadData() { ... }
...
}
Finally, your Controller should implement the SpaceViewDataSource interface and bind itself as SpaceView data source:
public class SomeController: SpaceViewDataSource, Observer {
private SpaceView spaceView;
private Space spaceModel;
private void configureSpaceView() {
spaceView.setDataSource(this);
spaceModel.addObserver(this);
...
}
List<Pawn> getPawns() { /* delegate to spaceModel */ }
Card getCard() { /* delegate to spaceModel */ }
void update(Observable o, Object arg) {
if (o == spaceModel) {
// A fine grained API may be required if
// this full reload doesn't perform well.
spaceView.reloadData();
}
...
}
...
}
In doing so, I added your Controller as a Space model observer as well.
All these refactorings puts you back on the MVC wagon, buying you:
a more reusable SpaceView component (no longer highly coupled with Space Model)
explicitly documented View data model requirements (the SpaceViewDataSource interface)
a View-Model communication that won't bypass the Controller layer
the Controller tracks the big picture, providing greater flexibility
This question more towards paradigm. Why is that we don't use Event Bus instead of listeners in an MVP environment ? Typically, the "P" part has dependency injection of view and model references. Sure this has an advantage of showing explicit contract between the view and model via presenter, which is more readable.
However, wouldn't it be a cleaner approach to have presenter listen to events from views and events carry the view payload (eg: json representation). Same is the case with presenter talking back to the view. View will listen for events from presenter. Major advantage is, we don't have to write interfaces for each contract between view and presenter. If you look at the code you will see that presenter is getting exposed to view details like Text Fields, which i believe is increasing coupling between view and presenter. Say, if i'm replacing front end JavaFx instead of Vaadin, i will have to alter presenter as well.
This class is an example from a live project. Here we have different types of events ie i don't create event class for different cases. Eg: LoginViewEvent , DashBoardEvent etc which i believe is a maintenance pain.
public class UrayEvent {
public static enum EventType {
SESSION_SELECTED(1),
DOCUMENT_SELECTED(2),
DOCUMENT_EDIT_COMPLETE(3),
DOCUMENT_EDIT_CANCELED(4),
SHOW_SESSION_TABLES(5),
SHOW_SESSION_DOCUMENTS(6),
SHOW_SESSION_COLLABORATORS(7),
USER_REQUESTED_REFRESH(8),
AUTO_REFRESH(9),
TABLE_SELECTED(10),
DETACHED(11),
SCHEDULER_NAVIGATION(12),
JIRA_USER_SELECTED(13),
DOCUMENT_SAVE_SUCCESS(14),
DOCUMENT_SAVE_FAILURE(14);
private final int value;
private EventType(int value) {
this.value = value;
}
public int getValue() {
return value;
}
}
public static class Event {
private final EventType type;
private final Object payload;
public Event(EventType type, Object eventPayload) {
this.type = type;
this.payload = eventPayload;
}
public EventType getEventType() {
return type;
}
public Object getEventPayload() {
return payload;
}
}
}
Simple enough, the view send the event DOCUMENT_EDIT_COMPLETE .The presenter layer handles this event. I found this way, a better way to decouple views from presenter.
#Subscribe
public void handle(UrayEvent.Event event) {
switch (event.getEventType()) {
case DOCUMENT_EDIT_COMPLETE:
// event payload contains document model data
// like document id etc
saveDocument(event.getEventPayload);
break;
default:
break;
}
}
Advantage
Less boiler plate code, for n-views we don't need n-interfaces
New event means adding event element to enum and updating respective
subscribe methods handling this event.
Disadvantage
Memory leak if we forget to unregister from eventbus (faced it plenty of time)
Questions
1) This approach means, there would larger set enum elements as the application grow. Is this approach an anti pattern ?
2) As we saw it uses Event Bus extensively are there any drawbacks of
using bus system instead of interface-listener pattern ?
Wanted your valuable suggestion on this regard. The main issue is, if i blindly apply this pattern extensively across the project i shouldn't regret doing so, what would be a possible pitfall in this approach.
1) This approach means, there would larger set enum elements as the
application grow. Is this approach an anti pattern ?
If there are many events you need many event identifiers. They can be simple ints or enums or Interfaces.
The mechanism you demonstrated is simple and works well with small applications. It has been proven many times over with multiple frameworks. Take for example Microsoft's Win32 API and MFC.
In some projects I have seen the event interceptors implemented with Annotations which provides an elegant way for handling the events. The previous time was in a project utilizing the Apache Wicket framework.
2) As we saw it uses Event Bus extensively are there any drawbacks of
using bus system instead of interface-listener pattern ?
It is basically the same thing in a different package. In Java world it is de facto standard to use listener interfaces. Take for example Swing and Android.
The event bus approach is used in Facebook's Javascript based React framework. It is interesting to notice the similarity of Model-View-Presenter and Flux design patterns. Particularly the unidirectional data flow is highlighted in both architectures.
You mentioned the use case of replacing JavaFx with Vaadin as the UI framework. In my opinion, changing the UI framework so that you are able to reuse even some portions of it very rarely happens. I would not pay the price of added abstraction layers and complexity upfront just because the framework might change. Rather you should start with KISS and YAGNI principles. If you want to change the UI framework later, then you just implement the UI layer again from scratch.
I am developing an editor following the general MVC design: the model holds the data, the controller knows how to change it, and the view issues calls the controller to query and modify the model. For the sake of argument, let us use
public class Model {
public Object getStuff(String id);
public void setStuff(String id, Object value);
}
public interface Controller {
public void execute(Command command);
public void redo();
public void undo();
public void save();
public void load(File f);
}
The class that actually implements the controller holds a reference to the model; commands need to access it too, so they must all provide a void execute(Model m); interface that actually grants them this access only when needed.
However, views generally need access to the model - when building themselves and, later on, to listen for changes and refresh themselves accordingly. I am afraid that adding a "Model getModel()" call to the Controller will result in a great temptation to bypass the execute() mechanism; and I am not the only developer working on the project. Given this scenario, how would you enforce an "all changes go through the controller" policy?
Two alternatives I am considering:
An interface called "ReadOnlyModel", returned by the getModel() call instead of the real model, that catches any such attempts.
Lots of comments to clue incoming developers as to the Correct Way of Doing Things
I recommend modeling the access to the model as a set of classes. For example, if the view needs to modify a customer's attributes, there would be a ModifyCustomerCommand class that would have as properties all of the information needed in order to perform the update. The view would construct an instance of the class with values and pass it back to the controller which, in turn, would pass the command back to the model for the actual update.
A benefit from this approach is that each of these model access commands can implement undo behavior. If the controller keeps an ordered collection of these commands as they get sent back to the model, the controller can back off the changes, one at a time, by invoking the undo method on the most recently executed command.
What if you take a look at Observer Pattern http://en.wikipedia.org/wiki/Observer_pattern, your view only listen for events from model.
Hope it helps.
I've been reading about MVC a lot recently, because I need to learn how to separate model and GUI for a project in school. (The teacher has said nothing about it, so I'm trying to learn it myself.)
I believe I understand the bacis principles with the view "registering" with the model with actionlisteners, or something along those lines. But I just can't get it into code. I've looked at several small programs, but they are somehow still too big for me to understand the basics.
Could someone please explain it as if explaining to a 5 year old, or give me some links or a really simple example program or something? Thanks a lot!
First, you need to understand the Observer pattern.
The basic idea is that you define an object that notifies interested parties when it changes. (Note that the Observer pattern is a bit more general - Observables notify Observers about "some event". For MVC, that event is "something changed")
First you define a contract between the OBSERVABLE and OBSERVER
package aaa;
// AN OBSERVER INTERFACE
// This is a contract between an interested party (the OBSERVER) and
// the thing it would like to know has changed (the OBSERVABLE)
// The OBSERVABLE will call this method whenever its data changes
public interface SomethingChangedListener {
void somethingChanged(String name, Object newValue);
}
Then you define the OBSERVABLE
package aaa;
import java.util.ArrayList;
import java.util.List;
// An OBSERVABLE class
public class Person {
// STEP 1: keep track of "who cares"
// outsiders with interest implement the observer interface
// and register with the person to indicate that they care
private List<SomethingChangedListener> listeners = new ArrayList<SomethingChangedListener>();
public void addSomethingChangedListener(SomethingChangedListener scl) {
listeners.add(scl);
}
public void removeSomethingChangedListener(SomethingChangedListener scl) {
listeners.remove(scl);
}
// STEP 2: be able to notify those observers by calling a method in the observer interface
protected void fireSomethingChanged(String name, Object newValue) {
for (SomethingChangedListener scl : listeners) {
scl.somethingChanged(name, newValue);
}
}
// STEP 3: whenever the data changes, notify the observers
private String name;
private int age;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
fireSomethingChanged("age", name);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
fireSomethingChanged("name", name);
}
}
This allows any other object to "listen" for changes on the thing it's interested in, as long as it implements that observer interface.
For example:
package aaa;
public class Test1 {
private static class TestObserver implements SomethingChangedListener {
#Override public void somethingChanged(String name, Object newValue) {
System.out.println("Property '" + name + "' changed to '" + newValue + "'");
}
}
public static void main(String[] args) {
Person p = new Person();
p.addSomethingChangedListener(new TestObserver());
p.setName("Scott");
p.setAge(43);
}
}
Creates an instance of the observable (the Person), registers an observer (TestObserver), and then interacts with the Observable. When run, we see
Property 'name' changed to 'Scott'
Property 'age' changed to 'Scott'
So far so good.
Now let's call the Person our MODEL. The MODEL represents the data that we want to manipulate and view.
We can do this in a "user interface". The user interface can be, but is not limited to:
A Graphical User Interface (GUI)
A Command-Line Interface (CLI)
A Web Application (HTML, JSP, ASP, etc)
A Web Service (SOAP, REST, etc)
The code for each of these types of user interfaces (UIs) can be drastically different, but the concepts are the same.
The user interface (UI) allows a user (a person or another computer for example) to see information about the model and make changes to that information.
The "View" is the part of the UI that displays the information for the user. It reads data from the model and formats it in some way to present it.
If the model changes, the View must be updated. To accomplish this, it registers observers with the model. Those observers simply refresh the relevant parts of the presentation in the View.
Now what happens if the user wants to make a change?
We define a "Controller" in the UI as code that interprets user interaction with that UI. For example, if the user types in the "name" field, the controller may interpret that as "change the value of 'name' to the text the user has typed. The controller makes a
person.setName(textFromField);
call to update the model.
Remember what that setName() method does? It notifies the observers of the change. This will cause the UI to update its view.
Note that "view" and "controller" do not need to be separate classes; they're often combined. It's really the roles of "view" (the part of the UI that displays model data) and "controller" (the part of the UI that interprets user interaction and updates the model) that are important to understand.
In some settings, such as Web Applications, the view and controller are very separate. The controller interprets the HTTP requests that are made to the server and updates the mode. The view renders HTML responses to the user. (If you're doing an AJAX application, the design is a bit more similar to a GUI)
The cool thing about the MVC separation (Model vs UI) is that you can add or remove UIs from the Model at any time, and can have multiple UIs on the same model. If data is changed in one UI, all other UIs are updated to reflect the change.
Cool, eh?
Now, the very basic thing about MVC is to separate M, V and C.
On one side you have your classes, and code that does something, like calculate sum of two input numbers, or does something with database, whatever. That's your Model.
On the other side you have some other classes which are responsible for forms, text inputs, buttons and things visible on the screen. That's the View.
Now, Controller is the one linking these two. Usually (in say Swing) you would have your controller implement the Listener interfaces, then you would add the controller as your listener to the screen components you want your software to react on, like buttons. And the implemented handler method wouldn't do anything else except calling whichever method you have implemented in you Model.
I hope this made it more clear..
This diagram might help you to understand the relationship of MVC in Java
UI component is the View, Control servlet (just catch all the incoming requests here and redirect them to the correct business object) is the Controller and the business objects is the Model.
That is my interpretation of MVC in java. Other answers are welcome.
If I am using the MVP pattern with GWT, as in the GWT architecture best practices talk from Google I/O from 2009, but have spread out the information into multiple widgets, how should the value object be populated?
Say I have a EditPersonView/Presenter, a EditPetView/Presenter and an EditAddressView/Presenter and the last two are widgets as a part of a panel in the EditPersonView. With these I have the following class:
class PersonDetails {
private PetDetails pet;
private AddressDetails addressDetails;
// ...
}
The PetDetails and AddressDetails instance variables are managed in their presenter counterparts. When the user clicks the "Save" button in the EditPersonView, how should the communication between the widgets be done so that the PersonDetails is filled with information from its child widgets?
If you look at page 42 of the presentation by Ray Ryan from Google IO 2009 you should find the solution to your question. You use an "event bus" (shared instance of HandlerManager) and fire your custom PetDetailsChangedEvent event and listen for that event from your child widgets (page 45). Also, remember that while decoupling, etc is great and all, some coupling is not a bad thing and might actually be a better solution than trying to force everything to be loosely coupled - RR says so in that presentation himself :)
I've faced this same problem in a few different GWT applications that I've designed using Ray Ryan's approach.
My preferred solution is to create a Singleton "session object" that stores the state of that part of the application. In your example, it might look like this:
interface EditPersonSession {
void fetchPerson(PersonId id);
PersonDetails getCurrentPersonDetails();
void updatePersonDetail(PersonDetail<?> detail);
void updatePetDetail(PetDetail<?> detail);
void updateAddressDetail(AddressDetail<?> detail);
void save();
}
All three presenters contain a reference to the session object (perhaps injected by Gin). Whenever the UI (view) is manipulated by the user, the presenter associated with that view immediately pushes the state to the shared session object. For example, inside EditAddressPresenter:
view.getStreetNameTextBox().addValueChangeHandler(new ValueChangeHandler() {
void onValueChange(ValueChangeEvent<String> event) {
editPersonSession.updateAddressDetail(new StreetNameAddressDetail(event.getValue()));
}
}
When it is time to save, the state object is told to save the state to the server. At this point, the session object has up-to-date representations of the data, and can save it all at once. So, in EditPersonPresenter:
view.getSaveButton().addClickHandler(new ClickHandler() {
void onClick(ClickEvent event) {
editPersonSession.save();
}
}
This way, the presenters need not contain any references to each other, but can send consistent information to the server.
If the presenters need to know when information that they display has been updated (either by other presenters, or by the server), the session object can notify them by firing events on the event bus (shared Singleton HandlerManager). The presenters can then pull the most current PersonDetails from the session object.
I've also come to the conclusion that I can have one model that corresponds to each presenter. So a PetWidget may create a Pet instance and a PersonWidget may create a Person instance. The PersonWidget may then contain one or more PetWidgets which in turn means that the Person class can have a list of Pet instances.