aspose file tools*
The moose likes Developer Certification (SCJD/OCMJD) and the fly likes NX: A brand new MVC, need your comment. Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Certification » Developer Certification (SCJD/OCMJD)
Bookmark "NX: A brand new MVC, need your comment." Watch "NX: A brand new MVC, need your comment." New topic
Author

NX: A brand new MVC, need your comment.

Bigwood Liu
Ranch Hand

Joined: Feb 26, 2003
Posts: 240
Hi,
I use MVC, but I created almost every component by myself.
For example: OpenMenuItem extends JMenuItem implements Actionlistener. My purposs is that the OpenMenuItem can listen to its own action event. I add the listener in its own constructor by addActionListener(this). And all buttons have the same structure. I also create my ResultTable, so the table can listen to its own list selection event and have is own look: the column number etc. My NameComboBox fills itself, so does the LocationComboBox. I have a mediator to associate these components and main view.
The advantage is that it is easy to manage the main view and easy to add a new button or whatever else. The disadvantage is I have to write every component. Need your comment!
Best,
Damu
Jim Yingst
Wanderer
Sheriff

Joined: Jan 30, 2000
Posts: 18671
I did something similar. I made a custom Action subclass; a simple version of it is:

This makes it easy to define a new Action quickly, and get good standardized error handling for any exceptions which you failed to catch before they reached the action listener. (See my last post (Oct 25) in this thread for more about exception handling here; "catch Exception" is a simplification.) Since JButtons and JMenus can be constructed from Actions, it becomes easy to make controls in just a few lines. My StandardAction also has a few other conveniences, like constructors that make it easier to associate a parent Window and tooltip text (short description) with a given Action, as well as the usual Icon. But as far as the event listening part - I actually haven't had a need for any listeners other than ActionListener, so that's the only event listener class I've coded. Actions work for buttons and menu items; I haven't needed anything else. Well, there was exactly one place where I wanted a MouseListener to detect double clicks on a table - but since it only occurred in one place, I just created a StandardAction for the response action, and made a MouseListener which simply forwards calls to the Action:

In addition to the StandardAction class, I have a Controls utility class which has some methods to set up other controls quickly, like a JButton or JMenuItem with a mnemonic. It's quite easy once you've got the Action, since it already has a name, Icon, and short description. (Hmmm... I should add the mnemonic to the StandardAction; dunno why they didn't support that in the first place.)
So, the point is: I agree that it can be useful to create a few custom classes to simplify event handlers and controls. But you probably don't need to create very many, if you're careful. Remember that Sun also likes to see standard solutions. Every time you create a custom class, i's something that a junior programmer hasn't seen before, and will require time to understand. So if you have one or two custom classes that you use frequently and they significantly reduce the complexity of the rest of your code, that's good, because it's worth the time for other programmers to look at your custom class and understand it. But if you've got five different event litener classes that are only used once, that may not be so good, because it takes time to understand each one. (And you will have to document each one too.) So, I think this is a good idea, but try to design your classes so you don't need too many of these custom GUI classes.


"I'm not back." - Bill Harding, Twister
Bigwood Liu
Ranch Hand

Joined: Feb 26, 2003
Posts: 240
Hi Jim, thank you for reply.
Actions work for buttons and menu items

So can I suppose that all your buttons and menu items are custom classes? If so, every Action will be processed by itself in actionPerformed() method, I think we are all using command pattern.
But if you've got five different event litener classes that are only used once, that may not be so good
I agree with you. But I am a little confused here. Since you have Actions customized components, don't you use five diffrent event processor and use it only once? The little change I make is to add the listener in its constructor because I think it is convenient, or I can add listener in main view. The same is the JTable, it listen its own ListSelectionEvent
if you're careful. Remember that Sun also likes to see standard solutions.
This is what I am concerning.
Best,
Damu
PS, where do you fill nameJcombobox and locationJCombobox? I wanted to write two custom JComboBoxModel initially, but it is still custom class. So I wrote two custom JcomboBox instead which fill itself.
Jim Yingst
Wanderer
Sheriff

Joined: Jan 30, 2000
Posts: 18671
So can I suppose that all your buttons and menu items are custom classes?
No, they're plain JButtons and JMenus, created from StandardActions. I recently refactored that code a little bit from what I previously described. The usage now is:

The StandardAction has everything it needs to allow JButton and JMenuItem to set up name, tooltip text, mnemonic key, and icon. The parent window is an optional anchor for any error message popups that need to be displayed.
If so, every Action will be processed by itself in actionPerformed() method, I think we are all using command pattern.
Yes, it's a form of command pattern.
[Jim]: But if you've got five different event litener classes that are only used once, that may not be so good
[Damu]: I agree with you. But I am a little confused here. Since you have Actions customized components, don't you use five diffrent event processor and use it only once?

Well, there's only one new named class, StandardAction. Now that's intentionally an abstract class - every time you want to use it, you need to provide an execute() method to tell it what action to take. Which I always do in an anonymous class. You could call these anonymous classes "custom classes" to I suppose, but that's not what I meant. When I said "custom classes" I really meant new named classes that the reader would need to look at in a separate file and understand in order to interpret the code. I don't count anonymous classes because the code that they call is right there for anyone to look at, right next to wherever it's being used.
[Damu]: The little change I make is to add the listener in its constructor because I think it is convenient, or I can add listener in main view. The same is the JTable, it listen its own ListSelectionEvent
Mmmm, I've always preferred to use small anonymous classes as listeners. Most GUI classes are too big & complex for my taste, with too many different methods already; to avoid adding to that I prefer to make new classes rather than add public methods to the API of existing classes. But that's a matter of taste; the StandardAction class could easily decouple the ActionListener so that you could call action.setListener(someOtherListner) to redirect the handling anywhere else you want. And you can still get the benefits of automatic error handling for any unchecked exceptions. (The ActionListener API forces you to handle any checked aceptions inside actionPerformed(), which I found inconvenient, so I made the execute() method which allows other exceptions too.
[Damu]: PS, where do you fill nameJcombobox and locationJCombobox? I wanted to write two custom JComboBoxModel initially, but it is still custom class. So I wrote two custom JcomboBox instead which fill itself.
Each combo box is a regular JComboBox. When I need to do anyting with them, I just access them using private methods. Note - I have little objection to adding private methods to a class, as in this case; I just try to minimize public methods.
Hope that helps...
Bigwood Liu
Ranch Hand

Joined: Feb 26, 2003
Posts: 240
Hi Jim, thank you.
How do you think mediator pattern. What I am using is pure mediator pattern.
Best,
Damu
[ October 28, 2003: Message edited by: damu liu ]
Bigwood Liu
Ranch Hand

Joined: Feb 26, 2003
Posts: 240
Hi Jim, after studied your post, I have some new question:
public void execute() { doFoo(); }

1. Where are your inner Action classes in? If it is in the main view class, then don't you think it is too big to hold so many classes for the main view class?
2. If your doFoo() will call corresponding method in controller?
3. I think the code in execute() could be put into actionPerformed().
This is from Mark:
I always look at it this way. The GUI code only knows one thing and one thing only, How to display itself. If you put any other code that does action, business logic, or instantiation of any object other than display type objects then you have coupled those other classes.

So I think it's better to put the Actions outside of the main view class. And the controller should register all the components that have relation with others.

Thank you for reply
Regards,
Damu
Jim Yingst
Wanderer
Sheriff

Joined: Jan 30, 2000
Posts: 18671
How do you think mediator pattern. What I am using is pure mediator pattern.
Um, that's fine. I don't really have an opinion on it here; I imagine it's possible to use it successfully here though.
1. Where are your inner Action classes in?
In the main view class. All the Actions are class members, initialized with anonymous StandardActions.
If it is in the main view class, then don't you think it is too big to hold so many classes for the main view class?
No. But if you think so, it's certainly possible to define them in separate classes, or in the controller.
2. If your doFoo() will call corresponding method in controller?
Yes.
3. I think the code in execute() could be put into actionPerformed().
Well, one of the main reasons I wrote StandardAction the way I did was because the actionPerformed() method was annoyingly long to write. My try/catch clock takes several lines, catching differnt types of exceptions and errors and doing slightly different things. I didn't want to put that into every single actionPerformed() for every single Action; it was tedious and took up too much space. In comparison, my execute() method can be defined quickly and easily, with less visual noise. People looking at it will immediately see that it's primary purpose is to call whatever method is inside the execute() definition.
In addition to error handling, I also put in code in StandardAction so that for every action, just before execute, the cursor changes to an hourglass, and when it's done, the cursor goes back to normal. It's a nice effect, but would've been way too much work to put it in each actionPerformed() separately. So that's additional reason to creaate a single actionPerformed() which is inherited by all the other StandardActions. Custom behavior can easily be put into execute() instead.
Personally I don't care very much exactly where the border is between the view and the controller. There seem to be several different viewpoints on it. In my design, the StandardAction includes the displayed name of the action, the icon for the action, the mnemonic key, the short desctription, and the parent frame, in addition to the execute() method. Most of those things are part of the GUI more than the controller, so I put the StandardAction in the GUI, with calls to the controller made from the execute() method. It would be simple to refactor this so that execute() is a method of an interface which is separate from the Action, so that the controller could define the execute() method but not the other GUI-related parts of the action. E.g. something like
Bigwood Liu
Ranch Hand

Joined: Feb 26, 2003
Posts: 240
Hi Jim, thank you very much. You give me a perfect example. It is wonderful!
Best,
Damu
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: NX: A brand new MVC, need your comment.