In my current project we are using for our Swing client the following patterns:
Business Object (POJO) <--> (mapping) <--> Presentation Model (POJO with property change support) <--> (binding) <--> view components
Everything is fine and works the way we are expecting them to behave.
BUT, we encouter those problems when view begin to grow:
Many events are fired, resulting in cascading events. One update on a field may result in dozens of subsequent property update
When dialog complexity grows, the number of listeners grows as well, and the code begin to be messy and hard to understand.
Edit after first answer:
We don't fire event if there is no change on value.
We don't add listener if we have no need for them.
We have screen with very complexes rules and with a need for notification from other related panels. So we have a lots of useful listeners and a single user change can triggers many underlying events.
The idea about binding the presentation model with the business model is not so good for us: we perform some code in the mapping process.
I'm looking for guides, advices, best practices, etc about building maintainable Swing application, especially for the event management side.
There are many ways of reducing the number of events being sent.
Don't propagate an event when there is no change. A typical example for this one ios the idiomatic way of writing a setter triggering a PropertyChangeEvent (see below) but it is the case for all kind of events you fire by hand.
public void setMyField(Object newValue) {
Object oldValue = myField;
if((oldValue==null && newValue!=null) || (oldValue!=null && !oldValue.equals(newValue))) {
myField = newValue;
propertyChangeSupport.firePropertyChange("myField", oldValue, newValue);
}
}
}
Only register as event listener when you start to be interested in, and unregister as soon as you stop being interested in. Indeed, being a listener, even if it is for no action, forces the JVm to call the various methods used for event propagation. Not being a listener will avoid all those calls, and make the application by far simpler.
Consider replacing your POJO to increased POJO mapping by direct instanciation of increased POJO. or, to say things simpler : make your POJO authentical java beans with PropertyChangeEvent handling abilities. To allow them to be easily persisted, an easy solution is, once "rehydrated", or loaded from the persistence layer, add a persistence updater mechanism as PropertyChangeListener. This way, when a POJO is updated, the persistence layer gets notified, and updates the object in DB transparently.
All these are rather simple advices, requiring only a great dose of discpline, to ensure events are fired only at the right time, and for the right listeners.
I suggest a single event action per model. Don't try breaking it down to fields with the hopeless ProtpertyChangeListener. Use ChangeListener or your own equivalent. (Honestly, the event argument is not helpful.) Perhaps change the 'property' type to be a listenable object, rather than listening to the composite object.
The EventListenerList scheme used by most Swing components is fairly lightweight. Be sure to profile the code before deciding on a new architecture. In addition to the usual choices, another interesting approach to monitoring event traffic is suggested by this EventQueue subclass example.
Related
How should Listeners etc be managed? I've found only examples with one button etc.
I can think of following options:
Extra class for each - doesn't seem right, especially when items
can be created dynamically
Class for each group (such as form1,
form2, controlButtonsOnLeft, controButtonsOnRight, mainMenu,
userMenu, ...) where I'll check which button/component caused this
(via getSource method for example)
Some super (sized) controller,
which will accept all user actions
New anonymous class for each,
which will call controller's method with parameters specifying
details (probably enums)
And another question: I've found many examples for MVC, I was wondering what is better (or commonly used) for app. developed by 1 person (app will not be huge)?
A. Viewer sets listeners to controller (A1-3)
B. Controller calls viewer's methods, which accepts listener as parameter (methods addLoginSubmitListener, addControlBoldButtonListener etc)
All of above are possible to implement and so far I would choose B4.
Meaning in Control I would do something like this:
...
viewer.addLoginButtonListener(new Listener()
{
#Override
public void actionPerformed(ActionEvent e) {
...
someButtonsActionHandler(SomeButtonEnum, ActionEnum);
...
}
});
...
private void LoginActionHandler(LoginElementsEnum elem, ActionEnum action)
{
if (elem.equals(LOGINBUTTON)) {...}
...
}
...
This combines readable code (1 logic part at one place in code), doesnt create any unwanted redundant code, doesnt require any hardly-dynamic checks, is easily reusable and more.
Can you confirm/comment this solution?
To be honest the question comes down to a number of questions...
Do you want reusability?
Do you want configurability?
Are they self contained? That is, does it make sense for anybody else to listener to the component or need to modify the resulting action of the listener in the future?
Personally, I lean towards self containment. A single listener for a given action/task. This makes it easier to manage and change should I need to.
If I don't need reusability (of the listener) or configurability, then an anonymous inner class is generally a preferred choice. It hides the functionality and doesn't clutter the source code with small, once use classes. You should beware that it can make the source code difficult to read though. This of course assumes that the task is purpose built (its a single, isolated case). Normally, in these cases I will prefer to call other methods from the listener that actually do the work, this allows a certain amount of flexibility and extendability to the class. Too often you find yourself wanting to modify the behaviour of a component only to find that behaviour buried within an anonymous or private inner class...
If you want reusability and/or configurability - that is, the listener performs a common task which can be repeated throughout the program or over time via libraries, then you will need to provide dedicated classes for the task. Again, I'd favour a self contained solution, so any one listener does only one job, much easier to change a single listener then having to dig through a compound list of if-else statements :P
This could also be a series of abstract listeners, which can build functionality for like operations, deleting rows from a table for example...
You could considering something like the Action API (see How to Use Actions for more details), which are self contained units of work but which also carry configuration information with them. They are designed to work with buttons, such as JButtons and JMenuItems, but can also be used with key bindings, making them extremely versatile...
The second part of you question (about MVC) depends. I prefer to keep UI related functionality in the view and out of the controller as much as possible. Instead of allowing the controller to set listeners directly to components, I prefer to provide my own, dedicated, listener for the controller/view interaction, which notifies the controller of changes to the view that it might like to know about and visa versa.
Think about it this way. You might have a login controller and view, but the controller only cares about getting the credentials from the view and authenticating them when the view makes the request, it doesn't care how that request is made from the views perspective. This allows you to design different views for different circumstances, but so long as you maintain the contract between the view and the controller, it won't make any difference...But that's just me.
I have an Event Login. I plan to populate that event with information such as this:
// Class A.
Login login = new Login();
login.setUsername(userName);
observer.notifyEvent(login);
The idea is for class B to get this information.
Is this bad practice? If so why?
The only forseable problem is that some other part of the software will be listening to this for no reason. When in reality only one class should be getting the information.
The only advantage is that all my classes are connected to the Observer object, but not connected to each other. In other words, if I wanted to pass the username I would need to connect A and B. Which I would only do in extreme circumstances.
Not much of a problem. - However, you may want to include the "sender" of the event in the event object so that the listener can identify where it comes from and, if needed, can get further state information from the event source.
The Observer pattern allows you to decouple the source of the event from the consumers of an event.
This is generally a good idea, even if you are only going to register one consumer.
However, I'll recommend you not to use the java.util.Observer which uses plain java.lang.Object as events, which means you must check the event object via instanceof and cast to the appropriate class.
I think its better to use an Observer or Listener implementation which supports generic types, such as Spring's ApplicationListener or Guava's EventBus which allow you to register Listener for events of particular class type, such as Login.class in your example.
Well, you probably need to dive a bit deeper into the original GoF book. For such a situation when a developer cares about different components that might be interested in different types of events the book offers the subjects collection that is maintained by the ChangeManager.
So when a component is interested in a specific type of event it passes a specific subject to the Register method so that this component won’t receive the updates for the events that represent a different subject. Additional advantage is the further decreasing of coupling.
Alternatively you might end up with building the system where any component that is plugged to the wire listens to all the events but that solution is too generic and adds lots of risks to the implementation (e.g. in the runtimes with automatic memory management like .NET the garbage collector won’t collect the subscriber while it is listening to any event – just because the ChangeManager still maintains a reference to it). It adds an additional responsibility to the subscriber - it has to do the additional filtering of events analyzing their type.
The rule of thumb is that you don’t need to subscribe for a specific event if you’re not interested to be notified when it occurs.
Referring to your example it is much better to introduce the Login subject and not to subscribe to it any component that is not interested in this specific subject.
I have read the docs for PropertyChange support and EventListenerList.
From my understanding, both serve similar purposes in holding a list of listeners and notifying them when event/propertyChange occurs.
Is it only in case of GUI applications, that EventListenerList becomes handy?. For a simple JavaBean application that does not use GUI components, is there an advantage of using one over the other.
Generally speaking, a PropertyChangeEvent occurs when some property value of the object changes (a property/value which you can read), where a (general) event could describe any kind of event (such as a change in selection or a mouse click), it doesn't have to represent a change in the state of the object
PropertyChangeSupport is part of the bean framework (in particular, but not limited to) GUI editors. This doesn't mean you can't use it, in fact, many objects rely on this functionality, such as SwingWorker and many of the objects from SwingLabs for example.
With that in mind, you should use ProperyChangeSupport when you want to notify interested parties that a property/value of an object changes and EventListenerList when you want to provide general event notification for things that are occurring within the object (but don't have to be related to a specific property or state)
The only issue I have with ProptertyChanegSupport, is it can less obvious which properties are bound and which aren't, sometimes making it difficult to get started with new objects, where as it's reasonably easy to look up all the "addListener" methods, but that's just me
While I'm sure the original intention of the EventListenrerList was for GUIs, I've used them for non-GUI work before, but you might find it easier to to use a List if you only have support for a single listener though, just saying
as PropertyChangeListener is just a specific "subclass" (extending interface) of EventListener - which is a marker interface and defines no methods, it is much easier to work with PropertyChangeSupport than EventListenerList - that is because if you start off with an EventListenerList you'll need to always do instanceof checks and casting to get to the actual "business" methods of your listeners (since the interface they all implement has no methods)
Originally I had the view holding commands for buttons, these buttons calculated this and output text onto JTextAreas after being pushed. What is produced is dependent on the value returned.
I am concerned I am not following standard MVC architecture by setting text like below inside my controller.
At the moment I changed my button commands into my controller as so
private class ReadActionListener implements ActionListener {
public void actionPerformed(ActionEvent l) {
/* there is other code in here, which results in setting text its not
just a set text button*/
/*interactions with model etc etc, outcome true? setText JTextArea like below*/
view.variable.setText("hi there");
}
}
Should I be setting text for the view inside the controller or is this breaking standard MVC architecture?
Thanks,
Jim
In MVC, you should not update the view from the controller. The controller is meant for event handling and altering the model according to these events. The model should then update its observers, ie. the view.
You can read up on the Observer design pattern here: http://javarevisited.blogspot.nl/2011/12/observer-design-pattern-java-example.html
There is a code example provided on that website as well.
In MVC, the model is a layer.
The model layer comprises of multiple objects: domain objects, services and mappers. You can read more in this post (although in PHP, the concepts still hold substance).
That being said, your controller handles the input from the user, sends this to the relevant object within the model layer, which then returns this data to the controller - and then your controller sends this to the view instance which handles the logic for displaying this to the user.
The observer pattern is really interesting and Koen's link above is a good one. I saved this snippet a while back from somewhere on SO:
Have state-setting operations on Subject call Notify after they change the
subject's state. The advantage of this approach is that clients don't have
to remember to call Notify on the subject. The disadvantage is that several
consecutive operations will cause several consecutive updates, which may be
inefficient.
Make clients responsible for calling Notify at the right time. The advantage
here is that the client can wait to trigger the update until after a series
of state changes has been made, thereby avoiding needless intermediate updates.
The disadvantage is that clients have an added responsibility to trigger the
update. That makes errors more likely, since clients might forget to call Notify.
This old but still valid example of the observer pattern may still be useful: http://javanook.tripod.com/patterns/observer.html
I'm building a GUI application and try to adhere to the MVC principle as good as I can.
Therefore my model fires PropertyChangeEvents with the help of PropertyChangeSupport so the GUI knows what to update when.
The model of my application is nested, i.e. I have a main model class that contains some properties or Lists of other model classes which in turn might contain more model classes.
A simple example:
public class MainModel {
private int someData;
private List<Stuff> stuffList;
// imagine PropertyChangeSupport and appropriate getters/setters
// for both MainModel and Stuff
}
Now both MainModel and Stuff have PropertyChangeSupport. If someone listens to events fired from MainModel, it gets changes of someData and from adding/deleting to/from the list stuffList.
But what if someone wants to get events from changes made to the individual elements of stuffList? There are two possibilities:
The observer has to fetch the list of Stuff elements and register as a listener to each element separately.
The main model registers itself as a listener to the elements of stuffList when they are added and forwards these events to the listener of the main model.
This is how it looks like with the first approach:
mainModelInstance.addListener("new stuff element", new PropertyChangeListener() {
public void propertyChanged(PropertyChangeEvent evt) {
Stuff s = (Stuff) evt.getNewValue();
s.addListener( // ... and so on
);
}
});
I think 1. has the advantage of keeping the model clean and dumb but leads to code duplication (many UI elements have to listen to changes to stuffList and add themselves dynamically to the new Stuff elements, see above). With 2. its the opposite: The client code is not as messy but the model acts partly as a listener which somehow doesn't feel right. That's why I currently use the first approach.
What are your thoughts? Maybe I'm too harsh on myself and 2. is okay. Or maybe there is a completely different (and better) way?
For at least 20 years, I've programmed MVC models observing other models (like for doing what is now called MVP[resenter] or MVVM patterns), and here are some heuristics I'd offer...
(1) Views and Controllers are hierarchical, and GUI event handling has long recognized that by letting event listeners listen at different levels of the hierarchy (like directly at a button level, or at the entire web page level). Each event specifies the most specific component associated with the event even if a higher level container was being listened to (aka observed). Events are said to "bubble up".
(2) Models can equally be hierarchical. The Model-generated "update" event can also use the same technique as above, specifying in the event the most specific "inner model" associated with the update event, but allowing observing at the "outer" composite model level. Observer update events can "bubble up".
(3) There is a common paradigm for hierarchical models...the spreadsheet. Each cell is a model that observes the other models/cells referenced in its formula.