I want to create a game that will work both locally and online.
My first thought was to create an interface that would have all the methods that will be needed by the GUI for the business logic and then have a network implementation and a local implementation.
This works fine for request-response messages. But what about messages that the server sends, where I have to update some GUI components (i.e. JLabels)?
My first solution to this was to implement listeners, where each change in the implementation will fire an event. The GUI would register and change it's components appropriately. However, calls to fire events in the business logic looks a little wrong.
Am I in the right track? Because I think I'm not. Any suggestions?
Thank you.
NOTE: The client is a simple Java Swing GUI.
What you have described will serve the goal of keeping the model independent of presentation issues, which is A Good Thing. This will also help you during design, development, and maintenance of the model, because you can write unit tests on the basis that certain changes in the model should fire specific events, without worrying about what that might look like on a screen.
And, of course, it frees you up to have different GUI designs for different environments.
The key is that the events should be about changes in the state of the model, and not about intended actions/representations at the presentation level. Let the presentation layer deal with whether/how to respond to a model event.
I'll admit that I do web development, so I don't have much experience with Swing.
But I've always thought that the way I'd approach it would be to break the app into packages /view, /model, and /controller. The relationships would be unidirectional: /controller would know about both /model and /view, but neither would import any classes from /controller or each other.
The /view layer components would never be JFrames; they'd always be JPanel or another suitable container that could be composed together into JFrames as needed. Each would have references to Listener interfaces, initialized in constructors, and would defer to these for event handling:
public class ExamplePanel extends JPanel implements ActionListener
{
private JButton button;
private ActionListener buttonListener;
public ExamplePanel(ActionListener buttonListener)
{
this.button = new JButton("Do Something");
this.buttonListener = buttonListener;
this.button.addListener(this.buttonListener);
}
public void actionPerformed(ActionEvent e)
{
this.buttonListener.actionPerformed(e);
}
}
This arrangement works well with dependency injection, because now the controller can choose to use a local or remote implementation of that Listener interface, changing the behavior in a way that doesn't affect the client at all.
I'll admit that I've never followed it all the way through.
The Spring folks have a rich Swing client module, but it appears to have fallen out of favor. It looks like they've decided that a BlazeDS direction is a better choice for rich clients. But perhaps you can glean some design ideas from their approach.
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.
On my personal proyect, I want to make unit-tests but I'm having troubles with that.
My project does not have a big logic layer. The most important logic is the interaction between UI and entities. Some exception are calculate some day from payments and others things. Those things rarely change and, I want to start with things that change frecuently.
For example, please look this class:
public class TabClient extends JPanel{
private JDateChooser dateChooser = ...
private JButton update = ...
private JButton search = ...
private JButton delete = ...
//other components specific for this panel/component
private SomeOtherClassComponent subComponent = ...
private void initComponents()
{
update.addActionListener(ClientHandler.getUpdateListener());
//Others buttons
}
protected void mapFrom(Entitie entitie){
subComponent.mapFrom(entitie);
dateChooser.setDate(entitie.getDateFor...());
//specific components mappings
}
protected void mapTo(Entitie entitie){
subComponent.mapTo(entitie);
entitie.setDateFor...(dateChooser.getDate());
//specific components mappings
}
}
This class is an example of a Tab (TabbedPane item) from my project.
The class ClientHandler is like a Mediator pattern who creates (and returns) EventListener to encapsulate the UI events. Some events call methos from Tab component like mapFrom
I want to write tests for the methods but I don't know where to start. If test with UI frameworks or refactor clasess to separate some things (what to separate? and where?) or what to do to start with unit-tests.
Nowdays, the test is made by hand using the app.
What I have to do to start with unit tests?
What I should test? Methods that interact with UI or what?
In order to have an (easily) testable class, they need to have a high degree of cohesion, which may not be your case
You may want to consider moving any business logic to specific services or to the domain layer so that you can more easily test them.
As you mentioned the most import part of your application is the UI, I would try to mock the TabClient dependencies, simulate (say) the press of a button by calling its action methods and then checking the mocked objects to make sure the appropriate flow was invoked (ie, assert the right methods of the right objects were called). You may need to refactor your classes a bit to make possible to mock their dependencies. Likewise, I would write tests for all relevant UI objects.
I have never tested Swing applications to be honest, nevertheless I found the following links that might shed some light on your question (though some of them might require UI creation):
UISpec4J
Java World
Stack Overflow
I have been asked to revamp an existing JDialog that is a child container of an in-house Swing app. I will be re-writing the dialog from scratch and have been asked to lead the charge towards making the Swing app resemble a true MVC/MVP architecture (so my JDialog revamp will be the first of many pro-MVC changes to the app itself).
I understand MVC/MVP as it pertains to web apps:
Controller - is what the web app framework dispatches to handle HTTP requests; typically consists of multiple methods, where each "controller method" handles the request for a slightly different URL
Model - the DAO or POJO/bean representing call-specific data; controller fetches the Model from the DB and injects it into the View
View - the mechanism that ultimately produces HTML/JSP that will be sent back to the client/requester
This is not how all MVC/MVP web frameworks operate, but is the general idea.
But I'm struggling trying to determine how to translate this to a Swing app. In the Swing app, you have:
The JDialog itself
All the UI widgets (JButtons, JTextFields, etc.) that make up the "view" of the dialog
The action/event listeners for all the UI widgets which collectively make up the "business logic" for how the dialog will operate when the user interacts with the view
All the other "UI glue code" (setting which widgets will be enabled/disabled, setting their sizes and positions on screen, setting their tooltip texts, etc.)
Plus a lot of other stuff
So I ask: how do I organize all the code necessary for a functioning JDialog using an MVC/MVP architectural pattern? Also, if there are any articles, tutorials, or existing open souce projects that showcase MVC/MVP Swing apps, I am interested in them as well. Thanks in advance!
As discussed here, Swing MVC hinges on the observer pattern used to propagate model changes back to any listening view(s). As a result, much depends on the components in your JDialog. If your dialog must be modeless, the examples here and here may be helpful.
Since there are many valid recipes out there, I'll only discuss what I use: a modified MVP design which also borrows ideas from The Humble Dialog Box.
Basically, create your GUI with as little application logic as possible (zero is the goal). Create "presenter" classes (similar to Controllers) that have a handle to the GUI and inject the appropriate listeners onto the UI.
Some benefits:
Since all application code is out of the UI, your code is now 100% testable.
You can quickly prototype your GUI without having to launch your app everytime, which can be a big time-saver.
Separation of concerns makes code easier to read/maintain.
Your GUI code will be Swing only. A new team member who isn't familiar with your app but is familiar with Swing can jump right in.
With regard to Swing's implementation of MVC, we actually don't care. That's Swing's business. We assume Swing works (which it usually does). True, we need to know these sorts of things for writing custom renders, editors, models, etc., but those are details that the application framework (which is what I think you're asking about) doesn't need to know or care about, for the most part.
I would do like this:
MyModel model = engine.getDataFromDatabase();
myController.displayDataOnMyCustomView(myPresenter, model);
And at controller side, probably will remove a lot of listeners, set the data based on model, set sizes, locations and any other state representing stuff and finally re-add the listeners.
The myPresenter should be a custom JDialog with various basic ui elements (Component)on his UI tree.
I am attempting to design my first, super-simple GWT app, that takes advantages of most of GWT's major API features. I think I'm about 70 - 80% of the way there, but after pouring over the GWT docs, countless articles, and posting many other GWT-related questions here on SO, I am still having a tough time understanding the last 20 - 30% needed to put this app altogether.
I have called this first test app ClickItToWinIt, and I want it to look like this:
When the user clicks the "Win" button, a picture ("win-pic.png") pops up in the image frame on the left-hand side. When the user clicks the "Lose" button, a picture ("lose-pic.png") pops up in the same frame. The user can click back and forth between the buttons to make the different pictures display. This would be a single-page app, hosted locally on my machine, and would only need to contain 1 homepage, 1 module/entrypoint, etc.
Please note that the packaging/class structure proposed below is surely overkill for such a simple ClickItToWinIt app. However, before long I want to be moving on to bigger and better things with GWT, so it's important to me that I have an understanding of proper GWT coding before I start to tackle bigger apps with more complex UIs.
Also, the proposed structure below is based on 3 GWT principles that Google seems to encourage tirelessly:
Performance; client-side speed
Security
Separation of concerns (MVP, etc.) for ease of testing
One last item here: normally, in my PHP webdev days, I used the concept of "themes/skins" in some of my sites by deploying the site with a different CSS file that simply applied different styling rules to the same DOM elements. Thus I might have a "normal-styles.css" file that makes the site look "normal", but also have a "facebook-styles.css" file that gives the site the look-and-feel (colors, fonts, etc.) of Facebook, etc. I'd like to accomplish the same thing here and am proposing a net.bfodder.c2w.client.views.themes package that will have AbstractTheme subclasses in it. These subclasses would somehow be injected/baked into the view/presenter at build-time and would give me a way to deploy the app with a different theme or skin. I believe this is the right approach because (if my understanding of ClientBundle and CssResource is correct) GWT seems to have object-ified CSS styles into GWT POJOs. My AbstractTheme subclasses would somehow tie into CssResource and defined styles for all my Widgets.
So here is the proposed src/main/java structure of ClickItToWinIt (I'm developing in Eclipse 3.7 Indigo with the Google-Eclipse plugin):
ClickItToWinIt/
src/main/java/
net.bfodder.c2w
net.bfodder.c2w.client
MainModule (implements EntryPoint)
AppController
ClientFactory
net.bfodder.c2w.client.views
net.bfodder.c2w.client.views.ui
WinButton (extends Composite implements ClickHandler; hasA TextButton)
LoseButton (extends Composite implements ClickHandler; hasA TextButton)
ImageViewer (extends Composite; hasAn Image)
net.bfodder.c2w.client.views.containers
MainContainer
ButtonContainer
ImageContainer
net.bfodder.c2w.client.views.displays
WinActivity (extends AbstractActivity implements AcceptOneWidget)
LoseActivity (extends AbstractActivity implements AcceptOneWidget)
net.bfodder.c2w.client.views.themes
AbstractTheme
NormalTheme
FacebookTheme --> I really dont't care about FB, just using as an example of a well-known theme/skin
net.bfodder.c2w.client.presenters
IPresenter
ButtonPresenter (extends AbstractActivity implements IPresenter)
ImagePresenter (extends AbstractActivity implements IPresenter)
net.bfodder.c2w.client.history
InitialPlace (corresponds to http://localhost/clickittowinit)
WinPlace (corresponds to http://localhost/clickittowinit/#winning)
LosePlace (corresponds to http://localhost/clickittowinit/#losing)
net.bfodder.c2w.client.events
EventBus impl and GwtEvent impls
net.bfodder.c2w.server
Not worried about server-side for now; I think I "get" that much!
The AppController is for any oddball app-level business logic that doesn't belong to any one particular IPresenter subclass. The MainModule is where everything kicks off (DI, starting preliminary Activity, etc.). The buttons get placed inside ButtonContainer, the ImageViewer gets placed inside the ImageContainer, and both those inner containers get placed inside MainContainer (which I assume is created up in MainModule). As far as layout and style of these UI components, like I said this would be up to whatever the injected/configured AbstractTheme defines in its rule set.
I'm using the ClientFactory as recommended here for convenient access to major parts of the app's GWT plumbing.
As for the MVP "stuff", here's what I was thinking:
public class WinActivity extends AbstractActivity {
private final ClientFactory clientFactory;
private final WinPlace place;
public WinActivity(ClientFactory clientFactory, WinPlace place) {
this.clientFactory = clientFactory;
this.place = place;
}
#Override
public void start(AcceptsOneWidget panel, EventBus eventBus) {
ImagePresenter presenter = clientFactory.getImagePresenter();
// Inject the presenter with any stateful data here
// presenter.setImage(getWinImageUri());
presenter.go(panel);
}
}
The Question(s)!
Like I said up above, I believe I'm almost there, I'm just having a tough time bridging the gaps on some things. So I ask:
How do I wire up my AbstractTheme subclasses to use CssResource and ClientBundle so that my app gets injected/configured with the correct theme, and client browser download the correct CSS file (normal-style.css or facebook-style.css)?
Can someone properly explain the relationship between IPresenter (from classic MVP), AbstractActivity, "display regions" (AcceptsOneWidget) and Places? Is there a 1-to-1-to-1-to1 relation here, or is the intention with GWT to have, say, multiple display regions for every AbstractActivity, or some other set of ratios?
How do I connect the WinPlace with GWT's History API? So if the user clicks WinButton, LoseButton, WinButton, how to have that saved in browser history so they could hit the forward/back browser buttons and recreate this usage pattern over and over again?
When the WinButton gets clicked, it places a some click event on the Event Bus. Where and how do I wire up a handler/listener to the EventBus that will know: (a) to change the image in the ImageViewer, and (b) to store this state change in the History API?
I got the idea for the AppController from this article, which unfortunately never provides any code snippets for what the AppController might actually look like. Can anybody (who is familiar with the AppController pattern for GWT) shine some light as to what this would look like? Perhaps its somehow an IPresenter subclass with no particular Activity or view components?
In general, and I know that these kinds of "amidoinitrite?"-style questions are discouraged on SO, but I have to ask any battle-worn GWT veterans out there: am I way off-base here, or am I more or less on track with GWT best practices? Any suggestions?
I hate to ask such a "super-question" here, but I'd rather do this than clutter SO with 6 medium-sized questions, and just keep repeating the same problem setup over and over again. Plus, with a good code example, it's probably possible to answer all 6 in one fell swoop, so I took a chance here.
Thanks in advance.
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.