Design patterns to reduce coupling in Swing application - java

Hey all, I'm currently working on a Java Swing application and I was looking for some guidence. The application is fairly small, but I'm noticing that as the code base is growing larger, that I have an awful lot of coupling in my object graph. I'm relatively new to Swing, but I've been programming long enough to know where this is headed.
The biggest problem I'm having is setting up my event handling. How should my child windows and objects be communicating events to my higher level objects without having references to them? I've done a fair amount of MVC web coding. Does this pattern lend itself well to Swing? Should I be building my own controller? I guess I'm just fishing for patterns that people have found useful working with Swing.
Thanks in advance for your help.

The best way to reduce coupling in a GUI, I think, is to use an Event Bus.
There are several existing implementations out there, including some supporting Swing specifically.
Just google for swing event bus and you'll find.
If you use Guice in your GUI, you may also want to take a look at guts-events.

Yes. MVC is what you have to use. Here is a very good article about MVC and Swing:
http://java.sun.com/products/jfc/tsc/articles/architecture/

Another Pattern that might be interesting for you is the MVP (Model View Presenter)-Pattern. This is great for coupling views more loosely to the model. A good explanation by Todd Snyder can be found here.

As you already said your intent to use MVC , or you may be already using. Once you have seperated out data (I call it as data model layer). Now you need to apply OBSERVER pattern on these data model classes. All the views (your ui components) using this data model are observing this model objects for any change (Via observer pattern).
I hope this is what you are looking for.

MVC !!! Then you can use also a variant of Observer called Publish/Subscribe in order to implement the event flow inside your app.

I don't agree with the people who suggest to use Event bus, because
because of code like EventBus.subscribe(SymbolListChangeEvent.class, this); your whole code will depend on a single event bus instance which makes it very hard to test,
it is hard to find out where a specific event is used.
Instead I suggest to use interfaces to encapsulate external dependencies of a module. If you like, you can use them with the listener pattern, but generally are free to refactor everything if you like.

If you want to communicate with other GUI components in the hierarchy then you should consider something like singleton that mediates calls between branches. See :
http://blue-walrus.com/2013/06/mediator-pattern-in-swing/

Related

Advanced wicket programming

I am currently involved in a medium-scale (300-400k lines) project written in Apache Wicket. At this time, majority of it's source code is not really reusable, breaks a lot of wicket's "best practices" (like passing raw objects instead of models or passing whole components/pages to other components), it's prone to all kinds of errors and does not handle extending functionality well. As far as Wicket's documentation goes, it is great way to scratch the surface, but I can not really say it's sufficient source of information for projects of this scale. What I am interested in is, how large scale applications are actually written in Wicket? Are there any sources/examples you could recommend?
And as for something specific, I also have few questions:
How to handle communication between several components? Are events preferred over abstract/no-op methods or vice versa?
Are anonymous implementations considered bad practice? How to establish a boundary on what should stay in a component and what should go into services (ie. when overriding onClick())?
How to properly encapsulate component functionality, if it depends on other components?
How to avoid conditional adding of componenta (ie. if(...) add.(A) else add(B))? Is there any other way around this except setting either one to visible=false?
I would really wish to dig deeper into wicket and take few more steps to mastering it, but I feel like there is not much to learn from.
Thank you in advance for your answers, anything will be appreciated :)

Does the use of ObservableList in JavaFX go against Model-View-Controller separation?

I am attempting a study of JavaFX because I want to use it as the GUI of my program. My question is essentially a conceptual one:
To date my program is mostly the "Model" part of the MVC pattern; that is, almost all of my code is the OO-representation of abstractions in the sense of classes, and all of that code is logical code.
Since I do not want to be the only user of my program, I want to add the "View" part of MVC so that people can easily use and manipulate the "Model" part of my program. For this, I want to use JavaFX.
In my "Model" classes I obviously use various Lists, Maps, and other classes from the Java Collections API. In order to let the users of my program manipulate these underlying Lists and Maps I want to use the Observable(List/Map) interfaces in JavaFX.
A concrete example to bring clarity to the situation:
Let's say that I have a MachineMonitor class that every 3 minutes checks certain properties of a Machine, such as if the connection is still good, the speed that the gears are turning, etc. If certain inequalities are met (say that the speed of the gears has fallen to a rate of 1 turn/sec) the MachineMonitor fires a RestartMachineEvent.
Currently I use an ArrayList<MachineMonitor> to keep track of all of the individual MachineMonitor's. Now extending to the "View" part of MVC, I want the User to be able to manipulate a TableView that displays the list of MachineMonitors so that they can, for instance, create and remove new MachineMonitor's to monitor various Machines.
So that I can keep track of what the user of my program wants to do (say, create a MachineMonitor for Machine #5 that checks to see if the turn/sec of the gears falls below 0.5) I use an ObservableList<MachineMonitor> as the underlying List for the TableView.
The easiest way to link the "Model" and "View" of my program would simply be to change the "Model" class to have an ObservableList<MachineMonitor> and not an ArrayList<MachineMonitor> but (getting to the topic of the question) I feel that this is very messy because it mixes "Model" and "View" code.
A naïve approach would be to use an ObservableList<MachineMonitor> for the TableView and retain the use of my ArrayList<MachineMonitor>. However, changes made to the ObservableList<MachineMonitor> do not affect the underlying List as per the JavaFX specifications.
Given this, is the best way to solve this conundrum to make a ChangeListener for the ObservableList<MachineMonitor> that "propagates" the changes made to the ObservableList<MachineMonitor> to the underlying "Model" ArrayList<MachineMonitor>? Perhaps put this in a class called MachineMonitorController?
This ad-hoc solution seems very messy and non-ideal.
My question is: What is the best way to retain nearly complete separation between the "Model" and "View" in this scenario?
Briefly, I don't think use of ObservableList breaks the MVC contract.
The rest, you may read or not as you wish, as it is quite annoyingly long.
Architectural Pattern Background
Observables are useful in MVC style architectures because they provide a way of feeding data back and forth between the MVC components through loose couplings where the model and view classes don't need to refer directly to each other, but can instead work with some shared data model which communicates data flow. It's not a coincidence that the Observable pattern and the MVC style architecture concept both originated around the same time at Xerox PARC - the things are linked.
As noted in Martin Fowler's GUI architectures, there are numerous different approaches to building GUIs. MVC is just one of these, kind of the granddaddy of them all. It is nice to understand MVC well (it is often misunderstood) and MVC concepts are applicable in many places. For your application you should use the system which feels best for you rather than rigidly following a given pattern (unless you are using a particular framework which enforces a given pattern) and also be open to adopting different patterns within an application rather than trying to shoehorn everything into a single conceptual framework.
Java Beans are a fundamental part of almost all Java programs. Though traditionally often only used in client apps, the observer pattern, through PropertyChangeListeners, has been, for good reason, a part of the Java Bean specification since it was created. The observable and binding elements of JavaFX are a rework of that earlier work, learning from it to build something that is both more convenient to work with and easier to understand. Perhaps, if the JavaFX observable and binding elements had existed ten or twelve years ago as part of the JDK, such concepts would be more generally used in a wider variety of libraries and frameworks than a couple of pure GUI frameworks.
Advice
I suggest considering the MVVM model and other GUI architectures.
If you want a dead-easy framework which follows a model, view, presenter style, definitely give afterburner.fx a spin.
I think the correct choice of architecture depends on your application, your experience and the size and complexity of the problems you are trying to solve. For instance, if you have a distributed system, then you could follow REST principles rather than (or in addition to) MVC. Whichever you choose, the architecture should aid you in solving the problem at hand (and possibly future problems) and not the converse. Over-architecting a solution is a common trap and is very easy to do, so try to avoid it.
Caveat
One caveat to consider is that observables necessarily work via side-effects which can be difficult to reason about and can be antithetical to the concept of isolation. JavaFX features some good tools, such as ReadOnlyObjectWrapper and ReadOnlyListWrapper, to help limit the impact (damage control if you like) on observables so they don't run amok in your system. Use such tools (and immutable objects) with reckless abandon.
Learn from Examples
For a simple JavaFX application which is built using observables, refer to tic-tac-toe.
For a good way to structure a large and complex JavaFX application with FXML based components, refer to the source code for SceneBuilder and SceneBuilderKit. The source code is available in the JavaFX mercurial source tree, just check it out and start learning.
Read up on the JavaFX UI controls architecture. Examine the JavaFX controls source code (e.g. Button and ButtonSkin or ListView and ListViewSkin) to see how concepts such as MVC can be applied using JavaFX structures. Based on that learning, try creating some of your own custom controls using the architecture that the JavaFX controls framework provides. Often, when you are building your own application you don't need to create your own controls (at least ones which derive form JavaFX Control). The JavaFX Controls architecture is specially crafted to support building libraries of reusable controls, so it is not necessarily generally suitable for all purposes; instead it provides a concrete demonstration of one proven way to get certain things done. Adopting and adapting proven solutions goes a long way to ensuring you don't reinvent stuff needlessly and allows you to build on a solid base and learn from the trials of others.
Regarding your Concrete Example
I advise you to go with:
The easiest way to link the "Model" and "View" of my program would simply be to change the "Model" class to have an ObservableList and not an ArrayList
Maybe use a ReadOnlyListWrapper to expose the ObservableList from the MachineMonitor to the outside world, so that nothing can modify it unduly.
Setup some other structure which encapsulates the view (for example a ControlPanel and ControlPanelSkin) and provide it a reference to the read only observable list of MachineMonitors. The ControlPanelSkin can encapsulate a TableView, a graph or whatever visual knobs and widgets you want to use for the user to monitor the machines.
Using such a structure effectively isolates your view from the model. The model really doesn't know anything about the UI at all and ControlPanelSkin implementation could be changed out to a completely different visual representation or technology without changing the core MachineMonitor system at all.
The above just outlines a general approach, you'll need to tweak it for your specific example.
I disagree that using an ObservableList in your "model" class violates MVC separation. An ObservableList is purely data representation; it is part of the model and not part of the view. I (and others) use JavaFX properties and collections in model representations in all tiers of my applications. Among other things in there, I point out how I use JavaFX properties that are (or can be, at least) bound to JSF. (I should mention that not everyone agrees with the approach of using FX properties on the server side; however I don't really see any way to make the argument that they are somehow part of the view.)
Also, if you do
List<MachineMonitor> myNonObservableList = ... ;
ObservableList<MachineMonitor> myObservableList = FXCollections.observableList(myNonObservableList);
myObservableList.add(new MachineMonitor());
the observable list is backed by the non-observable list, so the change occurs in myNonObservableList too. So you can use this approach if you prefer.

Swing - Best Way to Interact between views?

In a Swing application, what is the best way to send data (interact) between two views?
Looking at the Coupling session in the Study Guide to the SCJP 6, it says:
All nontrivial OO applications are a mix of many classes and
interfaces working together. Ideally, all interactions between objects
in an OO system should use the APIs, in other words, the contracts, of
the objects' respective classes.
If I understood this correct, the better way would be create interfaces (contracts) to each view, and if needed use this interfaces methods to retrieve data. Is this a good way? Spending a good time creating a lot of interfaces to say what is exposed by a view is ok?
Another way that I think is to have classes to hold the data (Model) of a view. In this case, is a good approach access directly this model classes?
Thanks in advance.
The notion of a separable model pervades Swing, as outlined in A Swing Architecture Overview. Typically, each model is represented by an interface; a few include an AbstractXxxModel with some basic event plumbing; and many have a DefaultXxxModel with a standard implementation.
It completely depends on what design choice you are making. There are times where the design choice we will suggest is better for View's data sharing but it demolishes the other aspect of your software. So in order to balance you have make design choice in order to make your application run smoothly.
I personally prefer MVC design pattern. It works for me every time! read more about MVC on :
Model View Controller
Good luck!
Note : In MVC two views never interact with each other but rather they use controllers to get data from model and basically each view has controllers with a reference to it's data model.

Implementing MVP when you don't own the model?

I am working on my first Java GUI and I think I've decided on a MVP architecture (thanks in part to this great article).
However, a key component of this architecture appears to be that the model notifies the presenter when a change to the model occurs. I'm working with a database API for the model that I don't control. Therefore I have no way of forcing the model to implement any sort of event notification.
In this situation, how is this generally handled? Do I make wrapper classes around the API that implement event notifications? This seems costly and doesn't handle the case when the model is modified outside of the GUI.
Update: I think I've found the answer to my own question. What I'm going to be dealing with is a passive model that doesn't participate with the view or presenter at all. I found my answer here.

GUI guidelines for swing

Is there a resource where GUI design for swing is explained? Like best practices and such.
Design guidelines aren't exactly followed much anymore because Swing works on so many different platforms. Sun wrote up some a long time ago, and never changed them so I'd say read it if you think it will help. Here is some practical knowledge about doing swing development.
Never use GridBagLayout. Grab TableLayout. It radically simplifies layout for you Swing UI. GridBagLayout is the devil.
Don't over embed components just to get a layout right (i.e. embedded BoxLayout, etc). See point 1 for how to do this. There are performance issues having components on the screen.
Separate your program along MVC lines. Swing has View and Model separation, but in large programs the View (i.e. what subclasses a Swing Component) turns into a psuedo View/Controller only making things complicated to reuse and maintain. It turns into spaghetti code fast. Break the habit and create a Controller class that DOES NOT extend Swing. Same goes for the Model (no swing). Controller instantiates high level view classes, and wires itself as a listener to views.
Simplify popup dialogs using simple panels only. Don't subclass JDialog. Create a reusable dialog class that wraps a panel that can be used something like JOptionPane. Your panels will not be tied to dialogs only and can be reused. It's very easy when you work this way.
Avoid actionlistener/command. This is old junk and not very reusable. Use AbstractAction (anon classes are your choice I don't have a problem with them). AbstractAction encapsulates text, icon, mneumonics, accelerators, reusable in buttons, popups, menus, handles toggling enabled/disabled states, can be shared among multiple components, it also is the basis for InputMap/ActionMaps for mapping keyboard strokes to actions. ActionMaps give you loads of power for reuse.
It's best to have to view dispatch events to the controller. I'm not talking about mouse/keyboard junk, but high level events. Like NewUserEvent, AddUserEvent, DeleteUserEvent, etc. Have your controller listen for these high-level business events. This will promote encapsulation by keeping the concerns of the view (should I use a table, list, tree, or something else?) separated from the flow of the application. The controller doesn't care if the user clicked a button, menu, or checkbox.
Events are not just for the Controller. Swing is event programming. Your model will be doing things off the SwingThread or in the background. Dispatching events back to the controller is a very easy way to have it respond to things going on in the model layer that might be using threads to do work.
Understand Swing's Threading rules! You'd be surprised how few people actually understand that Swing is single threaded and what that means for multi-threaded applications.
Understand what SwingUtilities.invokeLater() does.
Never* ever use SwingUtilities.invokeAndWait(). You're doing it wrong. Don't try and write synchronous code in event programming. (* There are some corner cases where invokeAndWait() is acceptable, but 99% of the time you don't need invokeAndWait() ).
If you're starting a fresh project from scratch skip Swing. It's old, and it's over. Sun never really cared for the client like it did the server. Swing has been maintained poorly and not much progress has taken place since it was first written. JavaFX is not yet there, and suffers from lots of Swing's sins. I'd say look at Apache Pivot. Lots of new ideas and better design and an active community.
I have written a list of recommendations here.
In larger swing projects I do partinioning of the app like that:
Have one class per GUI element like JPanel,JDialog etc.
Use a separate package for each screen, especially if you have to implement customized TableModels or other complex data structures
Don't use anonymous and inner classes, implement instead an ActionListener and check ActionEvent.getActionCommand() in there.
EDIT: If you're rather looking for a tutorial or introduction you could start here
Maybe not exactly what your looking for but it won't hurt to take a peek at Java Look and Feel Design Guidelines
You can check the ideas behind FEST - a swing testing framework. It's main site is here and the project is hosted here
You can find some of best practices in chapter 4 of Professional Java JDK6 Edition
I have some guidelines too:
1) Use Maven and seperate your application into modules (view, controller, service, persistence, utils, model). Be sure you put your Swing components and dependencies only in view package, so if you want to change view framework some day, you can just reimplement view module but you can leave your business logic, controllers, etc... intact.
2) Use GridBagLayout because its very flexible and most configurable
3) Use a SwingTemplate (i can give you an example if you want)
4) Create a SwingFactory that creates components so you can reduces the amount of lines of codes since JFrames orso intend to be very large classes...
5) Let the view (JFrame, JDialog, etc...) have a dependency on controllers. Only do validation input on JFrames but then pass parameters to controllers. They will decide which business logic (service, processors, etc...) will be triggered.
6) Use lots of enumerations
7) Always think how your application can change or how it can be maintained. Therefore, use always code against interfaces or abstract classes. (Think abstract)
8) Use design patterns in your application because they provide confort and maintainability of your code. Make for instance all your controllers, services, dao's singleton classes. Make factories (swingfactory, ...) so you have to write less code over and over again.... Use observers so actions can be processed automatically.
9) Test your appliction: Make a choice between: TDD (Test Driven Design) or DDT (Design Driven Testing)
10) Never put any business logic on JFrames, because it is ugly and its not very Model-View-Controller design. JFrames are not interrested on how the data has been processed.
Hope that helps.

Categories