Question

As a Java Swing newbie, I have some trouble separating the user interface logic from the domain logic.

I have a small (trivial?) Swing app with a JFrame that contains a JLabel, JTextField and a JButton. When pressing the JButton a JFileChooser dialog pops up. After selecting a file, the JTextField contains the absolute path to the file. Nothing spectaculair so far. The next thing I want to accomplish is that this absolute path of the file is 'injected' into a file manager class that will handle the actual processing of the file when the selection is made and the JTextField is updated (each time a file is selected using the JButton).

Questions I have:

  1. How do I let the file manager know when to start reading the file? (for example count the number of lines within that file)
  2. How can I implement the domain layer in such a way that minimal information is shared within the UI layer? Should I add a filemanager instance to the UI?
  3. Should I use the value of the JTextField as the reference towards the file manager, or should I use the JButton action to set the value into the file manager? What I mean by that is: use propertychangelistener of JTextField OR use actionlistener of JButton?
  4. Should I use a filebean to store the absolute path of the file within the domain layer or just directly insert it to the file manager? The difference is: when I use a property change listener the value of the absolute file path can be updated when the UI input changes, but when I insert the value directly using a contructor or setter, I have to handle the change in the file manager instead of handle the change in the filebean.
  5. How can I reference the filebean that is used in the UI within the file manager within the domain logic?
  6. Is the domain logic the same as the business logic? I mean: file manager class should be in package whatever.b-logic and filebean class should be in package whatever.domain??

The application is divided into several packages:

  • whatever : main class
  • whatever.presentation : swing stuff
  • whatever.domain : data stuff
  • whatever.logic : application logic

I hope I am clear enough...

Thanks in advance for clearing things up.

Was it helpful?

Solution

Personally, when I approach these kind of problems I try and look at re-usability and responsibility (who's responsible for what) as primary requirements.

That is, I try and get my models set up in such away so that they don't care about how or where the data is coming from or going to, they simple provide the interface access to make it happen.

To connect all the elements to together, I rely on the model providing events back to the client, cause the model shouldn't care about who wants to know, just provide the required functionality. So, in order to provide feedback to the client, I'd rely on a series of listeners.

I would break the listeners down into specific jobs, such notification of the file reading would be it's own listener, changes to the model (adding/removing/updating) the file beans would be another. Other notifications would be require different listeners, this stops you from creating monster listeners for which implementations don't really want to know about.

For setting values in the model, I would err on the side of property setters/getters. This decouples your model from the implementation (what if you are using the model in an automated fashion??)

Internal data would be best managed by the model if possible. That is, if you change a property on a file bean that the model is managing, the model should be capable of monitoring the change and dealing with it. Having said that, you may want a dumb model at some time in the future, where you could batch update a series of file beans and then ask the model to update itself.

I, personally, would probably provide the means for the model to be updated externally while providing at least one implementation capable of providing self monitoring, this gives you flexibility to chose the right model for the right situation.

There is also the danger of memory leaks here. If you don't properly remove any listeners from the file bean when you no longer need them, you could end up preventing the bean from been garbage collected at a later time.

Where possible, work with interfaces. This provides an great deal of flexibility when trying to pull these models together.

For what you describe, I would allow the file bean to be the responsibility of the file manager, such that the file manager becomes a container of file beans.

Depending on how large your project is and how you might want to reuse the code in the future will greatly effect the layout of the code.

I usually put UI code in a UI package and sub packages, but that's just me. I tend to separate interface content from implementation content (usually physically in separate Jar files, but again, that's me). This means that I only need to include the interface library and what ever implementation I might be using, using a factory of some sort to actually instantiate the implementation if required (or directly as is required). Think JDBC driver for example.

You want to look towards sphere's of responsibility. From what you describe, I feel that the file bean falls in the file manager's sphere of responsibility so I would bind the two together.

That's just my point of view

OTHER TIPS

Here are a few suggestions:

  • Use SwingWorker, illustrated here, to keep the GUI lively while listening for progress.

  • Use Action, illustrated here, to encapsulate functionality.

  • Use File, a convenient, cross-platform abstraction. Use it to compose new abstractions, rather than pulling out non-cross-platform pieces.

Addendum: See also A Swing Architecture Overview and the answer.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top