When utilizing a UI abstraction, then the data you're displaying is protected from implementation changes in the UI layer. Does/should/can this extend to higher-level things, like for example, display as a tree or a grid? I can't work out how to insulate the abstraction from the higher-level details of how the UI is going to display the data garnered through said abstraction.
You want to start with the Model-View-Controller architecture. This allows you to insulate, as much as possible, your user interface from data changes. The Model layer is your data objects. The View layer is your actual Swing components. The Controller layer is your listeners. The Model layer is written independently of the other two, with no knowledge of the classes. The View layer is written with no knowledge of the Controller layer.
If you require more abstraction than that, you can create interfaces for your Model layer so that several different data models can all use the same interface. This way, it doesn't matter what data you give to the View layer, it just displays it through the use of the interface.
Also realize that it's not always possible to do what you're asking. Sometimes a user interface needs to be written specifically for the data being displayed. A tree isn't always a tree, and a grid isn't always a grid. It works well to customize the View layer to match the data being displayed. This way, you can tailor the functionality specifically to the data being manipulated and create a better interface for your users.
Certainly, though, it should be done where it makes sense. This is where experience and judgment play a big factor.
Related
Hi am using viewmodel in my application. Since my logic is large in single activity. Am implementing that logic in my viewmodel. Anyway i want to separate this logic from my viewmodel. Any idea how to segregate the logic out my from my viewmodel.
Since it's UI logic, you can isolate each piece of code that has to do with the same behavior (or even UI section) into its own fragment/view and corresponding view model (think Single Responsibility Principle). If it makes sense, you can also share view models between the same UI components. Then, you orchestrate everything in the activity. For code that has nothing to do with the Android framework, you can also extract it to its own independent class, and then use it in the view model through composition.
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.
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.
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.
I'm adding some code to my project that allows drag and drop.
The Form used for the actual dropping is obviously part of the view/presentation layer. However, there's a question mark on a TransferHandler class that contains the actual logic which detects and validates objects dropped on the window.
Considering I have presentation, logic and data layers, where could this class be placed in the structure?
If it is totally related to presentation layer, then at presentation layer.
or if the same thing is needed when your presentation changes than at logic (service) layer.
I would suggest a presentation layer, but creating some package for example util, which will contain all classes you use to help your view features like drag-adnd-drop.
Which class is the information expert, meaning the class with the most information pertaining to the operation? It seems like the presentation layer contains the class that is the information expert, thus it would be reasonable to place the code there. Should this action affect domain objects though you may want to look at implementing a use case controller which would be called from the presentation layer.