How to setup a (ui) class in a readable way ?

I'm pretty new to java (and java's OO model) and i can't really think of a nice way to do this :

I'm creating a UI, a JFrame which has a JTabbedPane (with 8 tabs)

and each of these 8 tabs contains either a few listboxes or a pretty complex form (think: 8 textboxes, dragdrop lists, buttons, labels, etc.).

now i know how to code this but tossing it all in a single class will make it HUGE and thus pretty unmaintainable (i'm a pretty 'clean' programmer but still, thousands of lines in a method never looks good).

Does anyone have any tips on how to organise my "ui building" code in multiple classes or interfaces or something else.

When push comes to shove and the application is running the tabs do share some functionality (example: if you choose an item from a list in tab2 then the complex form on tab3 gets filled with the values of that item), so they are not truely separate entities.

I usually have no trouble organising my code in a nice manner but visual/ui code in java doesn't really seem to fit into my way of thinking :)

Any help would be appreciated !

[1125 byte] By [buggymana] at [2007-10-2 13:20:24]
# 1

> I'm pretty new to java (and java's OO model) and i

> can't really think of a nice way to do this :

>

> I'm creating a UI, a JFrame which has a JTabbedPane

> (with 8 tabs)

> and each of these 8 tabs contains either a few

> listboxes or a pretty complex form (think: 8

> textboxes, dragdrop lists, buttons, labels, etc.).

>

> now i know how to code this but tossing it all in a

> single class will make it HUGE and thus pretty

> unmaintainable (i'm a pretty 'clean' programmer but

> still, thousands of lines in a method never looks

> good).

Good instinct.

> Does anyone have any tips on how to organise my "ui

> building" code in multiple classes or interfaces or

> something else.

>

> When push comes to shove and the application is

> running the tabs do share some functionality

> (example: if you choose an item from a list in tab2

> then the complex form on tab3 gets filled with the

> values of that item), so they are not truely separate

> entities.

Read up on Model-View-Controller separation.

Command pattern might help here. Tabs can share patterns.

DON'T put all the behavior into the UI. I wouldn't start with JFrame, either. Break up the UI into discrete chunks contained by JPanel. Put all your JPanels in a package (e.g., "view"). Each one should be a pretty independent piece. You should be able to mix and match these JPanel subclasses in different frames.

I'm imagining that there might be more than one JFrame in your app eventually. They might want to share a header, footer, and left menu. (The body of each JFrame will change, of course.) Break up your JPanels this way.

No behavior in the JPanels. These are usually triggered events that are handled by Listeners, right? Make the Listeners something that you'll pass into each JPanel.Put these Listeners in another, separate package (e.g., "controller").

> I usually have no trouble organising my code in a

> nice manner but visual/ui code in java doesn't really

> seem to fit into my way of thinking :)

>

> Any help would be appreciated !

Your application will now be a master Controller that will have the main() method that is the entry point to the app. It'll instantiate all the JFrames you need and compose them out of the view JPanels that it wants. It'll tell the JPanels what Listeners to use to drive the action - it'll be the only one that "knows" what Listeners are needed.

You'll have a "model" package that will contain the classes that have business logic (e.g., Order, LineItem, etc.).

You'll have another "persist" package that will contain the classes that persist model classes in relational databases (e.g., OrderDAO, etc.)

The Listeners in the controller package will use the model and persist packages to accomplish the task that you want fired off when you hit a JButton in a JPanel.

Does that help?

I like your instinct to keep the classes small and the application partitioned. A skilled programmer thinks that way. Well done.

%

duffymoa at 2007-7-13 10:55:22 > top of Java-index,Other Topics,Patterns & OO Design...
# 2

> I'm creating a UI, a JFrame which has a JTabbedPane

> (with 8 tabs)

There's a start. You just listed at least ten different places your code can be broken up.

> and each of these 8 tabs contains either a few

> listboxes or a pretty complex form (think: 8

> textboxes, dragdrop lists, buttons, labels, etc.).

Do you want to reuse this complex form? Move it to another class.

> now i know how to code this but tossing it all in a

> single class will make it HUGE and thus pretty

> unmaintainable (i'm a pretty 'clean' programmer but

> still, thousands of lines in a method never looks

> good).

I think thousands of lines per class is a good indication something's amiss, let alone in a single method.

> Does anyone have any tips on how to organise my "ui

> building" code in multiple classes or interfaces or

> something else.

It depends a lot on your requirements. Start by moving the UI code away from the business logic, look at the MVC pattern. Consider moving different elements of the GUI to different classes, especially the things you want to be reusable. Even if it's not reusable there's no reason you can't move it to an inner class to make things easier to understand.

> When push comes to shove and the application is

> running the tabs do share some functionality

> (example: if you choose an item from a list in tab2

> then the complex form on tab3 gets filled with the

> values of that item), so they are not truely separate

> entities.

Well, yes and no. It sounds like the data they represent is the same, yet the GUI components are two separate entities. This is where the value of a pattern like MVC comes into play. You may need to look into something like the Observer pattern to handle event notification. For example, both GUI components are operating off the same data, but they don't know when it's changed. The Observer pattern can be used to notify them that it's changed. Be wary of cycles though.

> I usually have no trouble organising my code in a

> nice manner but visual/ui code in java doesn't really

> seem to fit into my way of thinking :)

Sometimes the hardest part is working with Swing. The architecture tends to force you into a compromise and can make your attempts at "good design" very confusing. For example, say I have an AddressPanel and no other components should have or care about it's internals. Yet, unfortunately, at some point they probably have to. How are you going to display it after all? Unless it can somehow install itself it's going to either have to be a JComponent or return one, and as soon as it does it's probably exposing internals in some way or another. I just accept it as part of the solution, despite the fact that I don't like it, and move on with life.

Most importantly, when it comes to dealing with GUI I've learned to not try and overthink the design. Once I have a basic idea of what I want to do I just go at it, then refactor as I need to. I'm not sure how closely my work resembles agile programming, but it's more or less the same idea. Write your code a bit at a time and refactor when you see something going bad.Until you gain a lot of experience I'm not sure there's much point in trying to think through the entire design from the get go.

kablaira at 2007-7-13 10:55:22 > top of Java-index,Other Topics,Patterns & OO Design...
# 3

First of all, thanks for the great replies , certainly helps a lot !

I agree about the MVC separation, and i kind of already made an attempt to that. The 'Command pattern' tip is a great pointer for this subject too, thanks.

Anyway, my problem is not so much the separation between the Model, View & Controller. but more how to manage code in a clean way within the "View" part.

I'm typing the UI swing code manually. At present this is because i want to understand swing a little better but also because the 'visual editors' i've seen so far

A) produce pretty repulsive code. (and i've had enough non-java experience to know that shitty code is useless in the long run), and

B) aren't very easy to work with (imho, but then again i'm a programmer, i like text editors and hate wizards/dragdrop stuff)

If a panel/tab has about 10 input components (input boxes, lists, buttons, etc.) and each of them has a label (pretty common) then you're easily talking about 25+ swing components (10x component, 10x label, some additional scrollpanes e.a.). Now imagine the form with 8 of these tabs , and we're talking about a few hundred of components.

A typical Swing component needs about 5 (for a JButton) to 15 (for a JList in a scrollpane) lines of code to be initialized and tossed in the panel/layoutmanager. This means that my hundreds of components (together) need thousands of lines of code, just to place them.

For this reason, im looking for a good way to separate the UI (The view part of MVC) into sub-components. Reusability isn't really my concern at the moment, maintainability and good practise is. Besides, my skills with swing are too limited at the moment to be thinking about abstraction/reusability within the UI anyway.

I guess the real trouble is with me anyway, i'm pretty new to java (and swing) and although i really like the things it CAN do, i don't like the amount of code it takes to do it (mostly a swing problem i guess). I'm a big fan of abstraction and interfaces and all, but the amount of code needed to use simple components (such as listboxes) and placement on the form (whole layoutmanagers paradygm) just keeps the codebase huge and ugly.

Maybe instead of worrying too much how to separate stuff in the "View" part of MVC), i should be looking at alternatives to Swing that are more appealing to my desire of having a clean codebase (maybe SWT or Buoy is any better? honoustly haven't looked yet) or maybe i should just ride it out and write a little wrapper/framework around swing myself (step by step).

A typical java project of mine is (imo) pretty nicely setup (overall model, separation of functionality, codestyle, the use of 3rd party packages etc.) but has the UI in there as the ugly black sheep ;p (with either big classes or lots of classes).

I'm just coding java applications for myself (usually more into non-UI programming) so i have the luxury of being able to try different approaches without worrying about a timetable. Best thing to do now is to think my current model over (compare it to true MVC and see what's different) and try to implement the "Command pattern" stuff and see where that gets me.

Thanks for the great feedback !

buggymana at 2007-7-13 10:55:22 > top of Java-index,Other Topics,Patterns & OO Design...
# 4

> If a panel/tab has about 10 input components (input

> boxes, lists, buttons, etc.) and each of them has a

> label (pretty common) then you're easily talking

> about 25+ swing components (10x component, 10x label,

> some additional scrollpanes e.a.). Now imagine the

> form with 8 of these tabs , and we're talking about a

> few hundred of components.

Once again, break them up. Why do all eight tabs have to be in the same class? You could easily define eight different classes that return or are eight different JComponent or JPanel instances and add each as a tab. Making each it's own class might not be appropriate in your case, but the point is they don't need to be in the same class or even the same source file.

> A typical Swing component needs about 5 (for a

> JButton) to 15 (for a JList in a scrollpane) lines of

> code to be initialized and tossed in the

> panel/layoutmanager. This means that my hundreds of

> components (together) need thousands of lines of

> code, just to place them.

Where do you see redundancy in your code? Can you extract any of this redundancy to a separate method that can be called once for each component? Why does the initialization even have to be in the same place as the actual placement?

> For this reason, im looking for a good way to

> separate the UI (The view part of MVC) into

> sub-components. Reusability isn't really my concern

> at the moment, maintainability and good practise is.

> Besides, my skills with swing are too limited at the

> moment to be thinking about abstraction/reusability

> within the UI anyway.

I don't think your knowledge of Swing matters. We're not talking about creating a robust custom table widget. We're talking about something as simple as moving code that creates a JPanel to show an address to another class called "AddressPanel" for example.

> I guess the real trouble is with me anyway, i'm

> pretty new to java (and swing) and although i really

> like the things it CAN do, i don't like the amount of

> code it takes to do it (mostly a swing problem i

> guess). I'm a big fan of abstraction and interfaces

> and all, but the amount of code needed to use simple

> components (such as listboxes) and placement on the

> form (whole layoutmanagers paradygm) just keeps the

> codebase huge and ugly.

There were many design decisions made with Swing that I disagree with. For example, it's massive depedency on concrete inheritance and the implications it has, forcing you into concrete inheritance yourself. However, in the end it's pretty powerful and you can use these things as a benefit. For example, separate intialization and layout. They do not need to be in the same place.

> Maybe instead of worrying too much how to separate

> stuff in the "View" part of MVC), i should be looking

> at alternatives to Swing that are more appealing to

> my desire of having a clean codebase (maybe SWT or

> Buoy is any better? honoustly haven't looked yet) or

> maybe i should just ride it out and write a little

> wrapper/framework around swing myself (step by

> step).

I am not aware of any solution out there as robust and consistent as Swing that is supported on all Java platforms. SWT sounds nice, but you rely on Eclipse to continue to support it on your target platforms. Maybe that's acceptable to you, but if it's not you're probably stuck with Swing.

> A typical java project of mine is (imo) pretty nicely

> setup (overall model, separation of functionality,

> codestyle, the use of 3rd party packages etc.) but

> has the UI in there as the ugly black sheep ;p (with

> either big classes or lots of classes).

Refactoring is the best approach in my opinion. Check out Martin Fowler's book "Refactoring" if you're not familiar with what I mean. It doesn't require you to completely rethink your design or make massive changes.You just need to make little improvements, and in the end it adds up to a good solution. At least that's my experience.

> I'm just coding java applications for myself (usually

> more into non-UI programming) so i have the luxury of

> being able to try different approaches without

> worrying about a timetable. Best thing to do now is

> to think my current model over (compare it to true

> MVC and see what's different) and try to implement

> the "Command pattern" stuff and see where that gets

> me.

The hardest part is figuring out how to implement MVC well using Swing. Or at least that's been the most difficult thing for me. I understand MVC. I understand Swing. Combining the two to meet my requirements has been a challenge and I still don't have the answer. After the fifth "re-design" I gave up the notion of figuring it out and decided to just do it and refactor whenever I saw something that smelled. So far it's working out pretty well.

kablaira at 2007-7-13 10:55:22 > top of Java-index,Other Topics,Patterns & OO Design...