I am attempting to develop a "Person database" Java Swing application, using MVC design paradigm with Observer/Observable. Here is a simplified abstract of M/V/Cs I am using:
App
AppModel
(Empty right now, possibly i'll store certain static application info such as version number here)
AppView
(Creates a JFrame and a few other Swing components)
AppController
(Instantiates AppModel, AppView and also a PersonController and a PersonListController)
Person
PersonModel
(Stores info for 1 person)
PersonView
(Displays a number of form fields inside a JPanel (i.e Name, Age, Phone number). Observes PersonModel.)
PersonController
(Instantiates PersonView. Observes PersonView. Instantiates PersonModel. Updates PersonModel.)
PersonList
PersonListModel
(Stores a list of Persons)
PersonListView
(Displays a list of persons with appropriate Add / Delete buttons. Observes PersonList.)
PersonListController
(Instantiates PersonListView. Observes PersonListView. Instantiates PersonListModel. Updates PersonListModel)
Also, a 'bootstrap', where the app starts. It creates a new AppController.
In the real application, there will be more (and different) Model/View/Controller objects but I want to keep this example simple.
I dont understand how I can go about 'merging' these seperate views into one UI while maintaining a good seperation of concerns.
Take for example the PersonListView. IMHO it doesn't need to care about the AppView (with the JFrame etc). PersonListView just needs to look at its own model and update itself accordingly. However, I cannot enforce that because the PersonListView's own Swing components need to be added to the Swing components of another view, the AppView.
So at the moment the AppController is instantiating its own View, plus indirectly a PersonView and PersonListView (via instantiation of their controllers). AppController then grabs the 'main' Jpanel for each view, grabs the 'parent' Swing components they should be added to on the AppView, and adds them.
This just doesnt seem the right way to do it to me. Im pulling Swing-related members from their hiding places and messing with them around inside a controller. In fact instantiating the model and view within the controller seems bad too, but I cant figure out a better way.
I've seen enough 'simple MVC' tutorials recently that I'm dreaming of the bloody things - but not one tutorial seems to go into the relationships of multiple models, views, controllers, especially where it concerns Swing. Maybe I am wrong and the App should have just one view? Maybe I need a 'Relationship' class that sort of takes every single Model/View/Controller and instantiates stuff appropriately?
Any advice would be most appreciated as Im completely at a loss!
This is where a strict MVC paradigm falls down (in Swing anyway, and it may explains why Swing is written the way it is).
Swing combines the view and control elements together, leaving the model separate. That means, you are free to add a view to any other view and the control follows (the model remains dynamic).
I have a developer who insists on using the strict approach to MVC and they still can't tell me the order of precedence. ie should the control know about the view or should the view know about the control - which one plugins into the other. Personally, I'm to lazy and simply follow the Swing implementation.
To my mind, if you want to follow a strict MVC, I'd basically allow for a public method in your controller that allows access to the overall view (say a JPanel with all the components on it that makes up the view for example).
Think about the JComboBox or JSpinner for example. They both have a number of components that make up the view (editors, buttons, etc), but you have single access point, the component itself...
Your next problem is going to be how to combine various views into a single over all view.
Personally, I would create a group controller of some kind that allowed you to supply the various, known, controllers together (setPersonList for example), as the "master" controller is going to need to know about these other controllers any way, as it needs to know how to layout them out.
IMHO
Related
In my program the controller just hooks keypresses with a function.
So should ikeep a reference to it?
E.g.
keeping a reference
Model model = new Model();
View view = new View(model);
Controller controller = new Controller(model,view);
or no
Model model = new Model();
View view = new View(model);
new Controller(model,view);
Inside Controller
public Controller(Model model, View view)
{
this.model = model;
this.view = view;
view.setOnKeyPressed(this::doSomething);
}
public void doSomething(KeyEvent event)
{
System.out.println("key pressed");
}
Maybe I implemented the Controller class wrong and misunderstood mvc pattern. But with what i wrote so far there is no reason for me to keep a reference to the controller object.
I'm not sure this question is really answerable, as it is probably too broad and/or too opinion-based. However...
MVC is a very loosely defined pattern. It really goes back about 40 years (or more) to the very early days of research into GUI development at Xerox PARC. Since it's been around so long and its primary use case (GUI architecture) has evolved significantly, it has branched into a number of sub-patterns and variations. Consequently, you'll find that "MVC" means many different things to different developers. In particular, MVC in a web application environment is somewhat different (imo) to MVC in the context you are talking about, because in a web application environment it has to sit on top of the request-response cycle. The rest of this answer/discussion focuses on the original "thick client" version of MVC, in which the view and controller are both in memory within the same process,and can communicate directly (rather than via a request-response protocol such as HTTP).
For me, the definitive guide to MVC in a desktop GUI context is Martin Fowler's essay on GUI architectures.
I would say that "classical" MVC is characterized by:
Having three components:
A model, which provides access to the data, may provide mechanisms for registering listeners for notification of changes to the data, and has no knowledge of the presentation of the data
A view, which observes the data in the model and updates itself when the data changes (this distinguishes classical MVC from some forms of MVP)
A controller, which provides the "view logic": typically this means it responds to user input and updates the model (not the view) as a result
So the model should know nothing at all about the view and the controller. The view doesn't know anything about the controller, but needs a reference to the model so it can display the data, and observe the data for changes, updating the presentation accordingly. The controller also needs a reference to the model, so it can update the data according to user input. Usually, the controller also needs a reference to the view, as it typically needs to register event handlers with the widgets in the view in order to know about user input it has to process.
The driving force behind this design is to allow multiple presentations (think of presentations as a combination of a view and controller) of the data which are kept synchronized. The pattern achieves this by referring everything though the model: one presentation's controller might update the model; since all the views observe the model, they all see those changes and each responsible for updating themselves accordingly. The controller that changed the view does not need to know about any other views that may be observing the data in order to keep all views in sync.
Your application itself will certainly need access to the model; it probably needs to access the data, maybe modify it from external (i.e. not user-driven) factors, persist the data at shutdown, etc. Your application probably needs access to the view (it needs to display it somewhere, may need to dispose of it at shutdown, etc). Your application may or may not need access to the controller. In its purest form, once the controller knows how to observe the view for user events, and knows how to update the model, you never need to communicate with it again. (If you want to change states from "external" events, you do so through the model, not through the controller(s).)
Several variations of this idea have emerged (see Fowler). One popular one (which also have several variations of its own) is Model-View-Presenter. In this variation, the controller is replaced by a "Presenter" which takes on some, or even all, of the responsibility of updating the view. In one form of this (which Fowler calls "Passive View"), the view is completely free of logic and merely lays out the controls. The presenter processes user input, updating the view and the model when user input occurs on the view, and observes the model, updating the view if it changes. This variant has advantages in terms of testability and ability to debug, but there is arguably tighter coupling between the view and presenter than there is between the view and controller. (It is relatively easy to provide multiple controllers for a view; providing multiple presenters for a passive view gets much more complex, and the presenters usually have to have some knowledge of each other.)
JavaFX actually provides "out-of-the-box" support for this style of architecture, using FXML as a (usually passive) view, and providing convenient ways to hook into what it calls the controller (which is perhaps more of a presenter). JavaFX properties make it easy to write models which can readily be observed by a view or by a presenter as needed.
In practice, you'll usually find a hybrid of these works best in most cases. A medium-large scale application will use MVC/MVP-type patterns in multiple places, on multiple different scales. You will often find that it is convenient for the controllers/presenters to have some knowledge of each other and to communicate between them, in which case you will obviously need to keep references to the controllers.
So the answer to your question is probably just "it depends what you need". If you don't need a reference to the controller, there is no need to keep one. Indeed, in the standard use of FXML in JavaFX, the controller class is simply specified in the view (the FXML); the FXMLLoader instantiates the controller from that information and wires the view and controller together as needed. You often never even have a reference to the controller instance in your code at all. Though, as seen in this popular JavaFX question you can certainly get one if and when you need. In a completely "pure" classical MVC, all state change is made through the model, and the views observe it, so you would never need access to a controller. Fowler points out some nice examples where this doesn't work as cleanly as it sounds: firstly that some state, and associated logic, is really part of the view and has no place in the model, and secondly that the registration/notification mechanisms can make it very hard to debug your application.
You will need for a controller instance be created for you when a key is pressed on the GUI. So you will need it to be a Listener which listens to key presses.
Once you have a GUI listener registered, its the framework's responsibility to instantiate that controller and pass the view to that controller.
(So, you never need the handle to a controller - its handle is always with the framework.)
Next, when you are in the controller with the view, you determine which model to create or fetch based on the values in the view...
This is how all MVC's work...
I'm using MVC to organise an Maths Game application that has multiple classes that are the following:
MathsGame.java: Main class. Currently holds CardLayout which screen classes are contained in and runs the application along with other controller-like actions.
DiffScreen.java: Implements components and contains methods for use on the difficulty selection screen. Is extended from MigJPanel and is essentially a mix of a Model/View.
GameScreen.java: Implements components and contains methods for use on the game screen. Is extended from MigJPanel and is essentially a mix of a Model/View.
EndGameScreen.java: Implements components and contains methods for use on the end game screen. Is extended from MigJPanel and is essentially a mix of a Model/View.
MigJPanel.java: Extends JPanel and sets layout to MigLayout and adds a matte border.
ScreenInterface.java: Is implemented by DiffScreen, GameScreen, and EndGameScreen and contains final variables and an enum.
I've watched some tutorials and read up on MVC, but a lot of the resources I've found on it deal with very basic programs; having one model, one view, one controller, and a main class.
I have an idea of how I must go about refactoring my program to work with MVC, but I'm unsure about a couple of things.
Am I right in saying that from what classes I have above, I should split DiffScreen, GameScreen, and EndGameScreen into Model and View classes for each? Additionally, would it be better to create one Controller class or—as I've seen suggested—not bother and instead combine it with my Main MathsGame class? An approach I was suggested to use in a previous question here whereby I could implement a Controller interface seems useful too, but I'm not exactly sure if/how that would work with my new code.
Would it be helpful/needed for a project this small to split the Model, View, and Controller classes into their own sub-packages and keep MathsGame in the main package?
Further Clarification:
I'm essentially wondering if having these classes would be a good implementation of MVC:
MathsGame.java: As a main class, or possibly being my controller. Could also possibly implement a controller interface as suggested in the linked answer above.
These 3 possibly being inside their own sub-packages, let's say GamePackage.Views
DiffView.java
GameView.java
EndGameView.java
These 3 possibly being inside their own sub-packages, let's say GamePackage.Model
DiffModel.java
GameModel.java
EndGameModel.java
Controller.java: Won't be needed if MathsGame is both my main class and controller class. Could be in its own sub-package GamePackage.Controller if needed.
MigJPanel.java
ScreenInterface.java
Additional:
I've looked up on Model-View-Presenter. It looks to be similar and better suited to whole applications. It seems these questions are valid for that too. If this would be more fitted to what I want to do, I would be okay with that too.
I'm hope I've explained myself well enough. It is for a college project but I missed a lot last year due to illness so I'm a bit confused on these aspects. If I can clarify any part better, please leave a comment. Thanks in advance for any suggestions!
I'm answering based on the assumption that your user interfaces(GameView, EndGameView) contain Swing components such as JTextPane, JTextField, JTable etc..
Do you need a separate model?
The Swing components have their own models. For example a JTable has a TableModel and a JComboBox will have its own ComboBoxModel.
So I would say that having your own models that you synchronize with the UI changes are not the best way to handle things. For example if you have a list of numbers in a JList, and the sum in JTextField in your GameView, having a GameViewModel that has int sum and List<Integer> numbers will duplicate things since the JList and JTextField already have their own models.
But if you are saving this data to some persistent storage (the database maybe) and fetching the data back to show on the user interface, then having a GameData object that has int sum and List<Integer> numbers will be useful for that purpose. But synchronizing that object with the changes that happen in the UI is still not appropriate. This object should only be filled when the user saves the data(clicks on the save button).
Do you need a separate controller?
Swing already has ways to communicate between user interface components and its model via *Listeners(ActionListener,ItemListener etc..). So I don't think that you need a separate class to communicate between the user interface and the UI other than a Listener that comes with Swing.
Should you put models/views and controllers in different packages?
No. Why? Classes that communicate with each other should be in the same package. So if you have GameView, GameModel and GameController they should be in the same package. DiffView, DiffModel and DiffController should be in the same package etc.. You shouldn't put GameView and DiffView in the same package because they are both views and all models in another package etc... If you do that you will have to make most methods public in order for GameModel and GameView to communicate whereas if you had those in the same package, you could have given them default access. Why is this useful? Because the users of your classes(people who will make changes in the future) will know which methods are meant for use outside the package and which methods are not.
MathsGame.java = your most bottom layer
Views: DiffView.java, GameView.java, EndGameView.java
Model: DiffModel.java, GameModel.java, EndGameModel.java
Controller: Controller.java (must)
MigJPanel.java = layer on top of MathsGame.java
ScreenInterface.java = Interface to connect between your MigJPanel.java with your MVC presentation layer.
Please remember to implement Single-Responsibility pattern, in that one class serves only for one purpose only. You cannot mix your main code with controller code. Confusing and not recommended.
Thank you,
I have read about MVC but am having doubts on how to implement the concept in Java with Swing. Here's what I'm going for:
The model:
ListOfThings contains a Collection of Thing objects.
The controller:
Controller instanciates ListOfThings and populates it with a "add" method (internally creates a new Thing and adds it to the Collection)
The view:
A Swing interface with a ListOfThingsPanel which will contain ThingPanel components to represent the model. Both extend JPanel. ThingPanel contains various components meant to display the data of the Thing it's linked to.
It also has a button which adds a new (empty) thing to the list.
The click event calls the Controller's addThing() method which asks ListOfThings to add a new Thing to its list. ListOfThings has an event/listener system and ListOfThingsPanel listens to it to know when it should refresh the view.
Am I properly following the MVC concept by doing it like this?
Update:
I'm still learning Java but I have coding experience and would prefer to learn the theory and attempt it by my own means before using premade frameworks. While I'm aware Swing implements the MVC pattern, I have read it does it in a specific way (View and Controller combined) which might not be the best and not applicable in other circumstances. I'm a bit wary until I can make sure "Swing MVC" is not different from "MVC", or that the differences won't impact my understanding of the underlying ideas.
One thing of import to me is to learn to really separate the model from the view to allow me to ultimately create various views of various types (Swing but also console or update to JavaFX for example) This is why I'd like to avoid anything Swing specific outside of the view part itself.
While the Swing framework already implements a form of MVC (explicit models; JXyz & UI classes = controller & view), this strict separation is rarely used on application level and looks rather weird.
To start I suggest to follow the following design:
implement the client-side business logic with POJOs
wrap the POJOs with custom Swing models where needed (ListModel, TableModel)
Use a GUI builder to design the GUI
Use the Mediator pattern to listen for events (a custom subclass of JPanel listens for events of its children and updates other children or fires own custom events if needed)
If you want to go a step further, use a RCP such as the NetBeans Platform (very recommended).
Edit:
And here is the article explaining MVC in Swing:
http://www.oracle.com/technetwork/java/architecture-142923.html
This is a follow up question to The MVC pattern and SWING. I am trying to implement the MVC pattern in an existing piece of code. The existing code creates a JFrame which acts as both the view and the controller. The JFrame has a table, and the table's model is an adapter to a custom data model. Whenever the user performs an action, the model would be updated by doing something like the following:
CustomDataTableModel cdtm = (CustomDataTableModel) DataTable.getModel();
CustomDataModel cdm = cdtm.getModel();
cdm.delete(1);
I've tried to visualise how it currently works, but I've also visualised how I imagine the relationships with the future controller and model should be.
Now, my question is simply whether I can continue using the model as it is now? Could I implement the following and still "adhere" to the MVC pattern?
The user selects an element in the table, and clicks on a delete button.
The view delegates the action to the controller.
The controller access the table through an accessor on the view, and performs the update.
The model, when it is updated, notifies the JTable that it has been changed.
If any other components in the view displays data from the table, then this could be solved by registering listeners on the JTable's table model.
Update 1
I've been thinking about the existing code in light of the MVC pattern, and I've redrawn the relationships a little. The point is that the controller is the behaviour of the view, thus the controller updates the model when users do stuff, and the view listens for changes in the model. However, nothing in the MVC pattern stops the view from listening to the model through a tablemodel - right?
Now, the user clicks the add button. The view notifies the controller that the add button has been clicked, and the controller takes care of creating a new item by invoking some method on the model. The view is registered as a listener on the model (through a table model) and updates its view. The controller may also be a listener on the model in case it needs to take care of disabling or locking fields. Have I not achieved what the MVC is all about; separation of concerns? As far as I can see, I've even introduced the adapter pattern to decouple the view even more from the model? It is late and I am tired, so that might be why it makes sense :-)
In the general sense, I would advise you the following:
take a look at JGoodies Binding,
it is not MVC but uses the
"PresentationModel" pattern
which is, in my opinion, better
adapted to a whole application than
MVC (which I find suitable for
individual widgets only). This should
solve your problem between your
Domanin Model and the TableModel
if your application has only tables,
then GlazedLists also makes a
lot of sense: it will also isolate
your Domain Model from your
TableModel (but it doesn't enforce
any global pattern, MVC or PM)
Regarding the current design you show, I would rather suggest that the View asks the Controller for an Action that the View will assign to the Delete button. Then the Controller can act on the Domain Model.
That gets messy and confusing fast, alas, and the code base is already confusing due to lack of separation.
I suggest instead migrating distinct components to a clean, simple MVC design. Such a component (which is currently a view, controller, and model all mixed up together) would then be separated in a clean fashion, however you will then have the difficulty of how to handle the controller and model?
As a temporary workaround, you'll be forced to designate the owner view as the controller, so the owner arguably has more responsibility. I think that this is a suitable workaround, because you will eventually separate more and more components into an MVC design, and the views that are also controllers will eventually become refactored as well.
In other words:
For a large application, identify a small component. (The low-hanging fruit).
Identify what code effectively controls that component. This is probably another 'view' class in this case.
Separate the component identified in step one into a clean design.
Explicitly configure the owner (view) identified in step to as the controller for the newly refactored component.
Repeat until there is clean separation between ALL views and controllers.
Be careful to ensure that the application is still working at the end of every 'step 4' above, otherwise, you'll find yourself in a mess that just gets longer and longer to fix. (Even if the end result is nice and clean, you may have missed your deadline).
Keep in mind that it may be difficult to extract the 'model' from the code at first - the controllers and views will be easiest to separate, but eventually, the models will become easier to separate as well. Whenever you manage to extract a model, write unit tests that test that model in isolation.
The presence of a well written suite of unit tests will help ensure that the application continues to have well-defined separation of concerns. (If concerns are not separated, then it becomes very hard to unit test), so the unit testing approach serves as a motivator.
I hope that makes sense.
i've started on some basic java coding with gwt, and im getting a bit concerned about the heft of my main class.
For instance - how does one compartmentalize the keyhandlers, since they trigger a number of changes to the UI, how could i move this into a separate .class file and still be able to access all the various widgets in the main class, without having to pass everything to the handler (ie. all the widgets i manipulate after the click event).
i've googled but didnt come across any particularly good examples - know of any readily legible code-bases i could read to see how it should be done? (gwt's own tuts are pretty basic, and just kitchen-sink every thing into a single file)
thanks!
I hate to say something so unimaginative, but MVC works--it's not the ultimate, but it can start getting you organized.
EDIT: While searching on a semi-related topic, I came across this which has similar ideas to mine but goes into more detail.
What that means in terms of GWT is that you should think of just laying out your GUI components in one class, put all your event handling in a second and put your object model objects separate from the other two.
One way to accomplish this is to make most or all the controls on your GUI public members. This sounds kind of lame, but their usage is encapsulated inside the controller so it's not like you have uncontrollable access--in fact your access is clearer/better defined than if all your members were private but your view code was combined with the controller.
Specific tricks:
Have listeners be their own class. You can often reuse them-- in other words, avoid anonymous inner classes. I sometimes create a listener class and instantiate a new instance for each button/control that needs to have a similar effect when pressed. If I need it to act slightly differently for a given button, I'll pass something into the constructor of the "special" handlers so that they know to act a little differently. You can also create different handler sub-classes if necessary--I'm just saying don't forget that event handlers are classes, you can use inheritance and everything if need be.
One Very Old GUI Trick I learned a long time ago, try not to have various mini-handlers modifying the GUI in different ways, instead have all the "active" buttons and controls set a state within your GUI and then call a single method that applies that state to ALL the controls on your GUI. When you get beyond a trivial GUI this can be a life-saver. If I'm not being clear, leave a comment and I'll leave an example for you.
Property sheets:
There is a special case for GUIs--the property sheet style GUI. I've done a LOT of these and they are irritating as HELL. They tend to have dozens or hundreds of controls on them, each GUI control tends to be tied to a specific field in your model and there are just hundreds of lines of copy and paste boilerplate code connecting them, each group copied and pasted with a few items changed--at minimum it's like 3 lines of code per control (Create control, copy value in and copy value out).
I always write these with a "Smart" controller--one that can intelligently bind the control to some data without any unique code. This can get tricky and if this is your problem let me know in the comments and I can give you some general advice as to some tricks you might try. I've gone from a minimal reflective solution to a full-on XML based solution. Were I to do it again, I might consider annotation-based.
Example of MVC:
Note, this is just an example, there are a MILLION ways to do MVC.
In your MAIN:
Instantiate MyView
Instantiate MyModel
Instantiate MyController(myView, myModel)
myView.setVisible(true)
in MyView
probably extends Frame
Most components are public final (public final Button b=new Button())
If public members make you nervous, use getters--same EXACT effect as public final members with a little extra syntax.
Remember that you can set final members in your constructor.
May have general methods such as reset(), but MyController may be a better place for this.
in MyController
saves references to myView and myModel
adds listeners to myView where necessary (see advice on listeners above)
configures myView based on state of myModel
when "done" button pressed, copies state from myView to myModel
notifies myModel that it's data has been updated and destroys itself.
in MyModel:
This would be a typical model class, it would contain your business logic (mostly not used as part of the GUI, that's more like GUI logic in MyController. The controller would tend to set values in your business logic then call some method like updated() to cause some business logic to take control. It should know nothing of a GUI--this is your "pure" business class.
Sometimes the GUI might call an update() or some other method to trigger some data change and then reload the GUI controls from the Model--this is a fairly good way to integrate your business logic with your GUI without your model knowing about the GUI...
Also, as I said above, I would put more work into MyController if I was working with property sheets just due to the sheer number of lines of boilerplate that you end up with if you aren't smart about it.
Note that View and Controller are nearly always paired. You can't just replace a Swing view with a web view and expect the controller to remain unmolested--but the model should not ever change for the view or controller.
You should take a look at the best practices for GWT applications first:
http://code.google.com/events/io/2009/sessions/GoogleWebToolkitBestPractices.html
One of the concepts they talk about is that of MVP (not MVC) to structure your application. There's a sample project on Google Code that you can look at to understand how to structure a GWT application in this way:
http://code.google.com/p/gwt-mvp/