I have a class which extends JFrame and forms the GUI of my program. I want to use the GUI for two main purposes:
I want the user to be able to input values to the program.
I want the GUI to display values created by my program.
Considering my class has a lot of GUI elements, the source file is already rather large and It does not seem like good practice to bundle all the program code in with the GUI code. I'm wondering what is the best way to structure my code? I believe there is an issue where requirement 1 creates a dependency from the GUI to the program code, and the second requirement does the opposite.
So, I want one class for my GUI which contains all my GUI related tasks. I then want another class for my program logic. I should then be able to call methods from the program logic class from the GUI and vice versa.
Sounds like you are looking for a textbook MVC (Model-View-Controller) design pattern. I recommend you google "MVC Design Pattern" for summaries and use cases. That being said, you might want to put your program logic into a "Singleton" class (again, google "Singleton Design Pattern"). A properly implemented Singleton should be accessible from any other class in your code.
Consider also a third middle class which acts solely for data storage, you put values into it for storage, and you fetch values from it for work. This now creates 3 clear segments for your code, the Data (the Model), the GUI (the View), and the logic (the Controller). Voila, you've just implemented the MVC (Model-View-Controller) design pattern...
The business logic should not depend on the GUI logic.
Have your GUI take inputs from the user. Call business logic methods with these inputs as method arguments, and use the values returned by the methods to display the result in the GUI. The GUI thus depends on the business logic, but the reverse is not true.
If the business logic must callback the GUI, it should do so via well-defined GUI-agnostic callback interfaces, or listeners. For example, you could register a ProgressListener on some business logic object, and this object would call back the progress listener. The GUI would have an implementation of the ProgressListener which would in fact update some progress bar or text area. But the business logic only depends on the interface, and not on the specific implementation.
I'm not sure there is one "best" way to structure GUI code. As a general rule though, you should follow MVC. Your program (Model) should never directly depend on your View code. What it's allowed to do is notify the controller that the model (or parts thereof) changed, and that whichever views are currently displaying said part of the model should be updated.
Swing already provides this abstraction layer for some of its types of component, most of the classes are (somewhat confusingly) suffixed with Model. A simple example you could look at would be BoundedRangeModel. There should be only one instance of such a Model for every "unit" of data your program manages, and different views displaying this data should share this instance. Your business code manages this object, and whenever this piece of data changes, the GUI is notified using it by firing off some event listeners.
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.
Let's say I have a class that builds a GUI and has a method updateMainUI(String text) that appends text to a JTextArea. Currently, I'm using abstract classes and methods to update the field from a different class, but I'm wondering if this is the 'right' way to do it?
I now have three abstract classes that have an protected abstract updateUI(String text) method that I override in my GUI class to update the field whenever I need to, but I'm doing the same thing in multiple classes and now I feel like I need another class that does the exact same thing.
Is there a better or more acceptable way of doing this?
From you question, it's difficult to be 100% sure, but, it is generally encouraged to use a Model–view–controller approach to these types of problems.
This is, the model defines the "virtual" state, the view represents this state to the user and the controller controls changes to the model initiated from the view...
The view is notified, by the model, when it changes, so it can update the state and the view notifies the controller when some part of its view/state has changed and may be reflected in the model.
To this end, I would encourage you to define some kind of model, which is normally described by a interface which can be used by the various aspects of your program. Updates to the model don't need to come from the user/UI, but you will need to ensure that you clearly document when notifications might come from a different thread other than the Event Dispatching Thread, so your UI code can take correct actions and synchronise the updates.
So, based on you example, your model might have a method call setText (or some such), which triggers some kind of event notification to registered listeners.
This instance of the model would be shared amongst the various classes of your application
You main UI would be one of these classes listening for a change in the models state, when it detected a change, it would update its state accordingly.
This is an example of the observer pattern and you see this in use all over Swing (via it's listener/event API)
I am looking for advice in structure rather than particular coding.
My program has a Main class that initializes a GUI and then, after puting the name of the files that are going to be read, I click one button. I attached a listener with the respective mouseClicked event handler and I do all my routines INSIDE the handler.
This doesn't seem a good approach, is it? Is it usual to do things this way? All my program inside an event handler?
Is it usual to do things this way?
UI programming is event-based in Swing. Twisting it into any other style will not make it easier for you. What you might mean is that you should minimize the code in that UI part.
This means that you shouldn't tie the UI to the logic, therefore creating dense coupling. In this example, the file-reading code should be moved into another method, ideally in another class.
All my program inside an event handler?
To answer this specific question: No, that'd be terrible! It's okay to invoke your program from there, but don't write the code in the event-handler!
This doesn't seem a good approach, is it? Is it usual to do things this way? All my program inside an event handler?
You are right, this isn't a good approach. Instead look into implementing a Model-View-Control (MVC) type structure or one of its variants.
The Model: this is the brains of your program, the one that holds the program state. This should contain no GUI code, no listener code, just the data and the logic that goes with the data. The model should not implement a handler interface
The View: this is the GUI, here your Swing components and related code. The view should not implement a handler interface.
The Control: this is the connecting code between the two above, the code that handles user interactions, asks the model to change state. This may implement a handler interface, or have inner classes that do, or be composed of objects that do. Your control for instance could read in the file (in a background thread), supply the text to the model, and then the model could notify the view (or the control -- there are many variants of this) that its state has changed.
As an aside: don't give a JButton a MouseListener. Use an ActionListener instead.
There is no rules but only good practices.
And from Good Practice ethics, it is always advised to divide your code into small chunks, each one responsible for some stuff.
So you would better move your code outside the event handler and delegate the job to some method called readFiles() and call the later within your handler.
And even if this method can be cut into pieces you can do the same, e.g. it can only iterate over the files to be read and call a readFile() method for each one:
private void readFiles(Files[] files)
{
for(File file : files)
{
readFile(file);
}
}
Just a simple snippet and all should be updated to follow your model.
Firstly instead of providing a path to the file you can use
JFileChooser to do file selection operations. Especially since you
are using Swing.
Secondly one should attempt to modularize the code to an extent it
makes code looks simpler a d understandable. So you can create a
separate method that handles your file operations. The you can call
this function from any event handler. Be it mouse or keyboard. This
will avoid code duplication and will enable module reude.
I was wondering whether the use of a decorator pattern is good in case I want my model ("M part" of MVC) to raise Exceptions depending on their origin. I explain myself.
I have a class called Game which is a part of the Model. I have two Views : a GUI and a command line. I want my model to raise an Exception for command line view when the user enters a character instead of a number (for example). Of course I don't want this Exception to be handled by the model as it "belongs" to the command line and not to the Model itself.
To encapsulate those two different behaviors, I plan to decorate the Game class with two classes : CommandLineGame and GUIGame which have only one attribute : Game and handle their own kind of Exception. Is it a good idea ? Is there a better one ? The problem of such a solution is that every model class raising Exception depending on its origin has to be decorated...
What you are describing in the example is "input validation". Strictly speaking*, this belongs in the Controller ("C Part") of MVC.
The separation of concerns for MVC decomposes as follows:
View is there to 1) present a UI for the user to evaluate the state of the program (Also, what your program looks like visually) and 2) to receive the user's expression of intent (receive raw instructions on what they may want to do)
Controller is the actual interpreter of these "actions" or "intentions" from the user. It decides what it means for a user to click a particular button and what to call in your model. It decides whether a particular input actually makes sense given context from the UI (and in some case from the model).
Model should be View/Controller agnostic (Meaning the model should have no knowledge of the View/Controller). It should only be about the internal representation of what you are trying to "model". The advantage of doing it this way: you can have many different UIs, or change your existing UIs without affecting the model.
Overall, the idea is to lower coupling and increase cohesion.
I hope that makes sense =)
Depending on the language / framework, the lines between MVC components get blurred a bit. Some idioms will lump most of Controller into the View, but the encapsulation of logic should stay relatively similar.
*In practice, for defensive programming, input validation is done twice for mutual suspicion: they are broken down into client-side mediation and server-side mediation:
In this case, the Model part should handle the "server-side" mediation: it should check that the arguments passed to its functions actually make sense before proceeding.
Similarly, the Controller/View part should check the input as part of "client-side" mediation, so that it can warn the user right away, without passing it back to the model, and then eventually back to the view.
It will keep your code very clean, something i like a lot from an academic perspective.
On the other hand do you need to introduce this kind of design complexity for a simple problem like this?
So, if you need the code to be clean... GO for it.
if i have a class gui and a class for the logic, is holding a reference in gui to logic and logic to gui very bad?
As a general rule it is bad to have the "logic" class having knowledge of the "gui" class. The idea behind the separation is the Model/View design pattern (or Model/View/Controller). The view will need a reference to the model. Look really closely at why the model needs a reference to the view. Usually when the model needs to send information to the view event listeners are used (see javax.swing table and list models for an example).
It should be avoided.
In your GUI, you can have a reference to your Domain Logic, but you should not have a reference to your GUI in your domain logic.
Why ?
Because otherwise, you have no advantage of splitting GUI & Domain logic up in separate files. When your Logic has a dependency to your GUI, then you cannot use your Logic with another GUI.
So, you should try to avoid this dependency from your logic to your gui, or, you should make abstraction of it.
I hope i'm making myself clear here. :)
If you can avoid it, you probably should. Otherwise you might get into a lot of problems with circular dependencies later.
Do they really have to know about each other, or could you have a third "control" concept referencing the two?
The GUI probably needs to expose some kind of interface to the logic class, to have the GUI update when the logic class changes something.
The logic should not have direct knowledge of the the GUI implementation, only its interface.
The Observer Pattern is sometimes used for this.