Discussions

News: New Article: Java GUI Development: Reintroducing MVC

  1. Finding the MVC in Swing can be difficult. Andrus Adamchik discusses how you can add a separate MVC layer on top of Swing, treating Swing components as a "view". Scriptable dynamic bindings are used inside this layer for declarative component assembly and communication between various related application parts.

    Read the Article

    Threaded Messages (33)

  2. reintroducing?[ Go to top ]

    I kind of get the feeling this is being presented as a new idea. I apologize if that is off-base. As far as I am concerned, you can't build a decent Swing app without using this approach and I know many people have been doing this for years.
  3. reintroducing?[ Go to top ]

    http://www.javadude.com/articles/vaddmvc1/mvc1.htm
    http://www.javadude.com/articles/vaddmvc2/mvc2.html
  4. Classic MVC[ Go to top ]

    As far as I am concerned, you can't build a decent Swing app without using this approach and I know many people have been doing this for years.

    Exactly my point. Please read http://www.objectmentor.com/resources/articles/taskmast.pdf
    It is quite long though.

    This article is classic MVC. Isn't it ? Now try mentally porting this to Java. Your 'short range' in-built events don't ever cross the view tier(Swing components). They are transformed into commands. The controller( not the swing controller. You have to write it ) would actually update the model. When the model changes the view pulls it and updates itself. Even if you implement a 'ViewChangeListener' to connect the model and view to enable it to pull it, this listener is not swing. It is a general custom listener.

     PropertyChangeListeners can be used to notify the view of domain model changes. If you want POJO's to become this type of listeners weave an aspect.

     I don't see any reason why this original MVC can't be used to solve the problem. We can always isolate the Swing MVC to the "view" and build our own on top of it.
  5. Ugh[ Go to top ]

    The example in Problem #1 is not the correct solution. The correct solution is to create a custom renderer that shows the label you want. It is one class of about 4 lines of code. Your model is a list of your objects, and the renderer just access the property you want to be displayed.

    For Problem #2, you again overcomplicate things. If your UI is a typical "type stuff in and hit "OK" button", then your action listener for your OK/Update/Doit button can query the fields for their values and populate your javabean or whatever. It's not the most elegant, but it's a hell of a lot cleaner than the approach in the article.

    The article really doesn't clarify Problem #3. I've not found that I needed to always register for the same events over and over again. I register for what I need, nothing more.

    As for the meat of the article, I think a design smell is the mickeymouse scripting language. The code is not very clear (which isn't helped by the numerous references to undefined classes and member variables), and overcomplicates things which are actually quite simple.

    I've gotten around writing endless custom models by writing one model/renderer for each component that deals with a javabean. They use reflection to get values, and it's all very straightforward. The solution proposed here is yet another unreadable mess, justified presumably by someone's desire to "code up something cool" rather than use what the API has to offer.
  6. Bigger Picture [Re: Ugh][ Go to top ]

    Surely I am aware of the renderer solution (couldn't show them all in one small article). And JStaple is still a prototype, not a production framework, so most things are very raw.

    But that's not the point!! Basically whenever you have any barebone API (say Swing or JDBC) and you need to build a consistent application architecture around it, you'd normally take one of the two possible directions - (1) create a number of utilities around the existing implementation or (2) create a better design [see my other comment o this thread about JDBC vs. ORM - it demonstrates the idea using a less controversial (?) topic].

    Your comment makes sense if you are taking the first approach. And that's fine. It will definitely cost you less and there is a smaller chance of screwing things up. But sometimes you reach the point when you can't do it anymore. This was certainly the case for me when writing CayenneModeler (just like the first time when I tried doing DB work with "object oriented" JDBC utilities instead of an ORM)... Things simply didn't look right no matter how many "swing utilities" I could come up with.

    So look at the bigger picture ;-)

    Andrus
  7. Ugh[ Go to top ]

    The solution proposed here is yet another unreadable mess

    I don't know about the solution, because I just couldn't read that far. What I saw being bashed in the article was some sort of straw-man. It certaintly wasn't the Swing I know and love.

    I would have taken almost the exact same approaches Dave suggests. As far as redundancy is concerned, the way my team currently takes care of that is with some annotation magic on both the view and domain classes, along with some judicious use of base classes.

    God bless,
    -Toby Reyelts
  8. Re: reintroducing?[ Go to top ]

    I kind of get the feeling this is being presented as a new idea. I apologize if that is off-base. As far as I am concerned, you can't build a decent Swing app without using this approach and I know many people have been doing this for years.

    No, I am not claiming a new invention here ;-) Actually the main point of the article is to bring developers attention to this pattern. When I started looking at Swing some time back you couldn't find how to do things right even if your life depended on it. Take *any* Swing book... What does it teach you? How to write a better ActionListener! And I don't think the situation now is much better than it was 3-4 years ago when I originally ran into this problem. So if you think there are existing solutions that "do it right" already, by all means please post more links. Here is my contribution:

    http://binding.dev.java.net/
    http://martinfowler.com/eaaDev/PresentationModel.html (this one seems to be down from where I'm now)

    In other words there is a huge difference between a great design idea and a design idea well understood by the majority (or at least a big number) of developers. Let me illustrate this with an example. Lets take Object Relational Mapping. I observed its Java evolution over the years, when working on Cayenne and before that when using commercial ORMs. Around 2000-2002 *nobody* in the Java community understood ORM outside of this small group of individuals who came from NeXT/Objective C or SmallTalk background. This doesn't mean there was no solutions available back then (TopLink, EOF, CocoBase - its not like Hibernate was an invention of ORM, whatever people might think ;-)). It wasn't even funny. Whenever you'd mention an ORM in reply to someone's question about a persistence solution on a technical forum, you'd get flamed by all these "it's too slow, it is not flexible, are you stupid" clueless people (what they were really saying of course is: "we have no idea what we are talking about"). Sun "official" solution was JDBC + EntityBeans, and its whole marketing machine was blindly supporting it. So you could argue all you want about the wonders of ORM, nobody would listen. It took a number of years and a critical mass of dissatisfied developers to break through this wall in the public perception. So now ORM is all hype and once it makes it to EJB 3.0 spec I guess even the most conservative (or should I say lazy) programmers will notice it.

    So my goal is really to start the discussion and point to the problem at hand... Then maybe someone can implement a solution and I won't have to code it all the way on my own ;-)

    Andrus
  9. Re: reintroducing?[ Go to top ]

    No, I am not claiming a new invention here ;-) Actually the main point of the article is to bring developers attention to this pattern.

    OK. Actually thanks for putting this out there in this framing. I've had people tell me "Swing is already MVC" right before designing a complete train wreck and refusing to listen to reason.
  10. What sense it makes to separate logic into 3 classes if all 3 of them wont be used separately.

    Easy to maintain? I dont think so.

    Just put all the code into one class as long as it cannot be rafactored into seeparate STANDALONE class.
  11. Why separate[ Go to top ]

    One of the advantages of separating the code is to prevent clashes in version control when you are working on a large team.

    Actually the approach I think looks similar to what I already blogged a while back.

    http://www.livejournal.com/users/trajano/12943.html

    Any idea on how to submit an article to TSS?
  12. RE:Why separate[ Go to top ]

    You mean this type of code separation is to separate code into 3 source files to easy tracking changes done by more than one team memebr?
  13. RE:Why separate[ Go to top ]

    Separation helps when developing because in intial phase of project you can have in memory versions of model components and just later connect model to the database. This gives you ability to have UI flow wihtout any backend support and you can add backed support later.
  14. RE:Why separate[ Go to top ]

    Yup because its easier to work and version smaller files than one large one as it avoids collisions with the version control.
  15. Didn't read that but MVC ...[ Go to top ]

    What sense it makes to separate logic into 3 classes if all 3 of them wont be used separately

    because 2.5 of these classes are already written for you?
  16. What sense it makes to separate logic into 3 classes if all 3 of them wont be used separately.Easy to maintain? I dont think so.Just put all the code into one class as long as it cannot be rafactored into seeparate STANDALONE class.
    MVC is used not to separate locig into 3 classes. The point is to build model (data, commands and constraints) without dependency on 'window'. There are many ways to edit and to dispaly model, UI is one of ways to do it (it can be many UI implementations for the same model too). The same UI can edit many models too (dynamic data binding). It is about UI and model reuse, separation is a way to make it possible. There are many ways to design applications, but
    MVC makes sence in all typical applications I have ever saw.
  17. As far as I can tell, most people do realize with the benefits of separation. But "raw" MVC can be really frustrating, and I somewhat understand why. Maintaining triplets for each view and subview you have in your system is really painful. So do-it-yourself MVC can be scary, and I can see how some are tempted to simply put all the code in one place [isn't it what your Swing tutorial tells you to do anyway ;-)].

    So the best MVC enviroment is when the framework does it for you... As Ana Greenspan put it in another message on this thread "because 2.5 of these classes are already written for you" ;-) So it still comes down to a smart framework and ease of wiring things together.

    Andrus
  18. Eclipse GEF is a good framework to develop tools like Cayenne, it must be trivial to integrate this modeling tool with eclipse if you use MVC. It can be a very good test for Cayenne design ;)
  19. Still not getting 2.5.[ Go to top ]

    Can you explain what you mean by 2.5?
  20. What sense it makes to separate logic into 3 classes if all 3 of them wont be used separately.Easy to maintain? I dont think so.Just put all the code into one class as long as it cannot be rafactored into seeparate STANDALONE class.

    How much maintenance have you done? This is horrible advice. Monolithic classes are never the way to go. Nothing is worse to maintain than a class with thousands of lines of code. You are ignoring the whole point of a class in OO design. Each class should have a single core responsiblity. One big class will be extremely difficult to modify as the application evolves and I find it to be much more likely to be plagued with bugs.

    For example: I had to create a window that had three interdependent views of the same data. I used an approach roughly similar to what the author is describing. After initial developement, my GUI components never had a single bug. The rest of the team used the monolithic window class technique and have never stopped dealing with problems the started with the initial development and new bugs that occured everytime an enhancement was required.

    People think GUIs are easy to write. But creating a really good GUI is actually very difficult. Most GUIs I deal with are poorly constructed. I think this is part of the reason so many applications are being written as web apps these days. The limitations make for more reliable interfaces.
  21. Have you ever heard about OOP concepts of derivation and inherithance. Think at it from this point of view....
  22. Am I mistaken, or doesn't Spring apply just as well to the client side? Why not use that instead?
  23. a good article for thought[ Go to top ]

    now I am meeting the problem converting domain model to Swing model. this article gives me a quite good referring.

    And also, combine v & c by using configuration file & IoC container are good idea for big project.

    all in all, it's an article for thought.
  24. The way things are going...[ Go to top ]

    I hadn't heard of JStaple before, and the article made an interesting read. I can understand why some people are complaining about your implementation, I use this style of Swing and questionit every day - as it goes against 'traditional' Swing development. However I've found that it stands up to my questions with more conviction every time I look at it.

    The main benefit I see from the approach described is that it is easily driven by tests. This is always a good thing. We can actually check that the components are indeed going to be bound to various aspects of the model every time we check in a change. I'd love to see a standard Swing application built around listeners, adaptors, editors and renderers being test-driven with true unit tests (and please let me know if you've managed this!).

    In response to the question about whether or not Spring could be applied in this process you might want to read up on the Spring Rich Client Project - I think you'll find it already is being done.

    And if you'd rather play with XWork, you might want to check out Pendulum at http://www.desktopdeveloper.com.

    Have fun...
  25. My opinion...[ Go to top ]

    I don't like the code. Could do better.

    Monolithic application code problem: absolutely. Department combo problem: why not just add a department wrapper that returns the name from toString? Update problem: most of the code can be factored out. But why create models composed from generic, simple models. Bindings: Just set your components up correctly when you create them - no need for a spurious level of indirection.

    Detailed comments in my weblog.
  26. Layers... layers...[ Go to top ]

    Swing is already full of layers... Sometimes I just think that all of the MVC stuff is unnecessary for 90% of applications.

    Try to explain Swing programming to a VB developer and see the results...
    I don't want to add more complexity on a hypercomplex API.

    :)
  27. MVC + Doc/View ?[ Go to top ]

    i would take this a step further.
    In a recent application, we considered swing components as
    toolkit widgets, contained and not inherited in a (compositable) MVC triad.
    The instance were in a one-to-one-to-one relation to avoid event registration dynamic installation.
    In this traid the model was a container for swing components ad controller actions.

    The whole MVC triad played the "View" part in Doc/View pair.

    Business data adapters PME objects
    (Properties+Mothods+Events)
    played the Doc part in the pair.


    The point here is that we move to this level one-many relationship between Doc and View

    After all, MVC is not a TRUE pattern
    (Go4 cite it, but not included MVC in patterns)

    This "paradigm" (?) does not define how to handle MVC respect to "Composition" and "Layers"
  28. MVC + Doc/View ?[ Go to top ]

    MVC is not a TRUE pattern (GoF cite it, but not included MVC in patterns)
    This "paradigm" (?) does not define how to handle MVC respect to "Composition" and "Layers"


    Standard MVC does not address also creation e destruction dependencies.

    In my project i revert to a "multiphase" approach
    (the same adopted in JSF) to handle creation dependencies:

    given a "Doc" reference

    a root controller , create root model, passing doc reference for cache in the model.
    the root controller builds the root view, passing a root model reference, an store it on the root model
    the root controller builds a collection of actions an store it in the model

    the root controller create sub controllers, passing self as parent/owner reference

    and recursively, and MVC triad is built for every subcomponent


    when all is build, a setup method is invoke on root controller

    that starts a multi phase scan of the tree

    widgetsDefined() : to let all MVC triads to (safe) reference Swing widgets in other components for UI composition

    actionsDefined(): to let other every view to (safe) reference controller actions for UI installation

    componentLoaded(): to reload persistence state info, after UI contruction, before realization

    compositionNotification(): to perform additionl setup logic

    ...


    in this context "safe" reference means inter-MVC widget reference without build sequence depencency.
  29. It's kind of an obvious point...[ Go to top ]

    Why is an article on GUIs/Swing pertinent to the server side?
  30. It's kind of an obvious point...[ Go to top ]

    Why is an article on GUIs/Swing pertinent to the server side?

    Because it affects server-side development.
  31. Thanks everybody for comments!

    I knew this will raise some controversy ;-) Besides as it was mentioned, the article is somewhat outside the normal scope of TSS, though it is an important topic to may people in this community. What's interesting is the pattern of replies from those who actually work with Swing (likely spending more hours with it than I do). These replies fall roughly into these two categories:

    1. "Well, but we do this exact thing already. So what's new?"

    I already replied to that - we need more advocacy for this particular alternative. Until more people start talking about it, nobody will know it exists (or understand what you are talking about for that matter).
     
     
    2. "You got it all wrong - all the "problems" with Swing are not really problems and can be solved the Swing-way."

    I agree - they can... Just like everything else in OO programming it is about the right abstraction. And arguing about abstractions is fun, isn't it? Like I mentioned in the article, the variety of flavors of web frameworks actually helped the evolution to proceed in the right direction. Same story with ORM taking over misguided Entity Beans architecture. I am surprised this is not happening in Swing (at least there is nothing that's visible enough). I believe deeply that Swing got its control layer abstractions mostly wrong and bindings combined with "presentation model" pattern is much cleaner. Currently I am in a bit of a disadvantaged position in proving that clearly, as JStaple is still an idea, not a real implementation, while all the "category 2" folks have invested years in making Swing work. I know a few such guys personally - all their solutions are pretty nifty. Still all the Swing grabage is somewhere around in their code, only it is organized much better :-).

    Cheers,
    Andrus
  32. Greetings,

    I'm just reading the article (not finished yet) and on page 3, I have found a strange way of working with JComboBox component.

    This post is not to be treated as a negative one to the article or as a support to the Swing architecture, but more like a practical way of programming to be used by the untrained developers.

    As you can see, from the first example of using a JComboBox, filled with an array of String objects, the DEFAULT BEHAVIOUR is to display those objects in the drop down popup menu.

    This means that internally, the component, will convert the objects passed on the constructor in the form of an array, to String objects.
    The conversion is made simply by calling the method (present through inheritance from Object class in all objects) toString().

    Looking now at the second example, where the result is wanted to be a JComboBox displaying the names of a list of Department objects, the choosen method is to implement a custom model for the JComboBox to aquire this behaviour.

    From my personal experience, I solve this type of issues by simply overriding the toString() method in the Department class definition to return the value of the name property. I don't see the sense of creating custom JComboBox models for each type of object I want to be displayed in different manners, since the component will finally call the same toString() method whatever I'll do to complicate my life.

    To display more than one properties in a specific format (e.g. "<name>, <address>" - "John Doe, John Doe's address"), overriding the toString() method will solve this easily too.

    If instead, I'll want to show a specific image infront of every Department name, to make a distinction between them, there is the need to setup a custom renderer to be used by the JComboBox to solve the problem.


    Ovi, Senior Java developer (ovi_guse at yahoo dot com).
  33. ...To display more than one properties in a specific format (e.g. "<name>, <address>" - "John Doe, John Doe's address"), overriding the toString() method will solve this easily too.

    That is probably ok for the default behaviour. But some people use the toString to output all the values of the object for debugging. And what if in one view you need to display the values one way, and another way in another view? Renderers handle this well.
  34. That is probably ok for the default behaviour. But some people use the toString to output all the values of the object for debugging. And what if in one view you need to display the values one way, and another way in another view? Renderers handle this well.

    Yes, agree with this (mostly :) ). In any case does not seems to me a solution to create a new model every time you want to display something different like the article author does.

    About toString() method purpose, I personally use this method as allready explained, o provide meaningfull and human readable information about an object.

    To print debug information, I generally use loggers, sometimes mine but most of the time the ones integrated in the standard API. I use them "in place" in the method(s) body I want to trace.

    About renderers, I personally believe are to be used to change the way an information looks graphically and is displayed to the final user, and not to manipulate what content the component will show. That is the desired purpose, but I have used renderers in the manner you have suggested too, for the convenience :).

    After finally finishing the article, those examples are looking like a bit of introduction for introducing the framework proposed by the author and not truly Swing MVC pitfalls.

    Swing as it's own minuses in different components, but in general is a well written component library. The framework proposed by the author is to be seen just as a framework and that's all.
    Does not change the core Swing, at least in the terms of architectural and design principles, as I was first expecting when I started reading the article. Instead it is used to manipulate and automate application creation using Swing classes.

    IMHO, Ovi.