Announcement Announcement Module
Collapse
No announcement yet.
RCP Commands - why aren't they decoupled from the UI? Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • RCP Commands - why aren't they decoupled from the UI?

    I understand the idea of factories, and please be patient with me when I ask these questions and make these comments - they are meant as what is *hopefully* constructive feedback.

    So here goes.

    I was looking at the 'Commands' in Spring RCP, and I noticed they seemed to follow the factory pattern of some (many?) of the other RCP classes in that they looked more like factories than what I am used to as a command. The first thing that caught my eye in this regard was the fact that they were coupled to various UI components via the 'createButton', 'createMenuItem', et. al., type methods.

    This seems wrong to me for several reasons:

    a) What happens when I (or someone else) needs/wants to add a new type of GUI control? Or maybe even a non-GUI control, like a voice control for the disabled to invoke some action in the UI via a verbal command? I have to either extend the command framework (often not desirable), or I would have to write my own. Either way, highly coupled and not very bean/Spring like.

    b) Not good for reuse. In a previous gig, we had commands that were used in the Swing app. They could also be used elsewhere. They were not coupled to any kind of UI from the perspective of the commands - they knew nothing about UI components. They simple knew how to do something. I need to go back and look, but as I recall, we simply had UI controls that invoked a command when the user caused them to invoke the command. This was before I started using Spring, so the commands to be invoked were hard coded into the UI control, but somewhat like Spring RCP, we could attach them to menus, buttons, whatever.

    In a gig before that, we had commands that knew how to undo, and command groups that kept a history of past commands so you could do multiple undos (or not - sometimes commands could not be undone so we provided feedback in the UI for that). That was too long ago for me to remember how coupled they were to the UI, but I am going to be generous and say they weren't.

    I have also seen transactional type behavior, and behavior where listeners could veto the execution of a command. Other aspects of commands, like whether they are enabled, progress, security and so on, could be provided *without* coupling them to the concept of a UI, much less a UI component.

    What I am getting at here is that I would prefer to see and use a different type of command framework, one more decoupled, more flexible and more abstract/generic than that provided by Spring RCP. I would like to see some kind of framework for connecting that command framework to UI components, but in a generic and bean like manner.

    Thanks for listening.

  • #2
    http://sourcemaking.com/design_patterns/command

    Comment


    • #3
      Yes, this sounds good.
      Maybe we should concentrate together and relaunch Spring Desktop?
      More Spring, no Application.instance, but with the full advantage of the existing Spring RC ;-) This is a major thing, but would be great!

      To come to the point: I extend the ApplicationWindowAwareCommand class more and use it like a connector between the 'real' command and the UI.
      This way I can have several presenations ('gui commands') of the same 'action' (but maybe I have misunderstood the spring rc stuff)

      So, to design the next generation SpringRc how would you like to see it (as code)? could you be more specific?

      Comment


      • #4
        I mean, the only way to really get GUI independent code is, to write two implementations of your idea.
        E.g. for SWT, Swing and javascript or whatever.

        With such an abstract you have to think about swing's event dispatching thread and keep in mind other 'workflows' as well (not that easy)

        The only project I know which handle this is GWT (with js-compiler, so not a real solution) and Riena from eclipse ... and there exists a lot of other (mostly abandoned) projects where swing and DI (with picocontainer, spring or guice) are combined:
        http://sourceforge.net/projects/clico/
        mailing list entry
        mailing list entry2
        https://spar.dev.java.net/
        http://sourceforge.net/projects/daro/
        http://max-server.myftp.org/trac/pm

        So nice Spring + Swing is doable but takes time :-)

        Comment


        • #5
          First, to the most relevant question: how do you decouple commands from the UI?

          It isn't that hard - mostly you use interfaces and the UI calls the command, not the other way around. This allows you to reuse the command regardless of the UI. A little bit of hand waving there, but that's the idea.

          The non-trivial part is when the UI needs feedback from the command, such as errors/exceptions or progress. This too can be done with generalized interfaces - my current attempt at this will use callbacks. It might get a bit messy with callbacks on different threads, especially the EDT v. a worker thread, but I've done it before and basically the callback assumes it is not called on the EDT so it does an invokeLater().

          But the idea, in this particular case, would be to have the biz/persistence/etc. logic separated from the presentation layer, and reusable other places. Then you can reuse the same command in a Swing/SWT GUI, web client, or a console app. I have to deal with all three right now *and* I have servlets/server apps that run headless or almost headless (for example, an app that exports reports from Jasper Server to an FTP folder - periodically kicked off with Quartz). In my previous gig we had the web client, the Swing client and the server side logic.

          I could see that a command layer like what I am currently writing could be plugged into the RCP command logic, and then could be reused later in some evolution or rework of RCP => Spring Desktop (if that ever happened).

          Comment


          • #6
            As for Spring Desktop. Maybe.

            As I said in another thread, writing Swing or even desktop logic in my spare time is low on my list of things to do. If I can or have to do it at work then I could maybe adapt some of that and use my own personal version of the ideas/logic to contribute - but beyond that I don't see myself getting deeply involved.

            I've been burnt before in the job marketplace. If you do a search on Indeed/Monster/etc. for Java Swing jobs in the Seattle area you will get, on average, about 3 hits, and some of those are probably duplicates. That is out of about 3000 Java hits, the majority of which are server side jobs, the remaining jobs are web client jobs with some aspect of talking to the server.

            I've been blindsided by employers before with regards to whole dev teams or even whole companies being gutted or failing, so I am always keeping an eye on how anything I am working on is going to help me when (not if) I find myself looking for another job.

            I now have some server side experience, which is actually easier than client side work and a nice change. I need to get more SQL under my belt and other non-Swing UI technologies, so the things I have on my short list to do in my copious spare time (hah!) don't generally involve Swing.

            Many of them could use a Command API implementation though. Some of the work I do at my current job will probably involve some things like constraints on fields and such, so maybe I will be able to contribute some evolution of what I did before in that regard that involves Spring validation and RCP.

            As for what I would like to see RCP evolve into, is a move towards more bean like beans. I know that can be hard to do with Swing since I would think some kind of wrapper/interface to allow things like listeners to set instead of added, maybe some way to externalize layout of the component completely (or not), some way to set child components - that is all hard stuff that I haven't gotten my head around yet (or really thought about that much).

            As for being GUI toolkit agnostic - hmmm, I remember that being mentioned as one of the goals of SRCP somewhere, but when you dig into it you see a lot of coupling. Personally, I am not sure of the ROI - being able to go between GWT and Swing might be of value, and I think I recall something somewhere along those lines, but personally I think if you decouple your biz/persistence/etc. logic as much as possible, then that would be of most value, and you could put a different UI on top of that as needed.

            Right now, and for the foreseeable future, I don't see a big revival of Swing interest. Occasionally you see some company that sees the light in that they just can't get there from here with a web client, and then they start a Swing or SWT project, but not very often.

            I can understand the need for a web client, and until Java/Swing becomes lightweight enough (especially with regards to modules) to compete with web client tech, you won't see Swing applets either, except inside enterprises (like where I work now). It's too bad because Swing had the potential, as did Java, to be the premiere client technology, but for various reasons it didn't work out that way. Now with Sun basically saying they will do no more Swing dev, and pushing JavaFX, I don't see that changing. Maybe Oracle might change that, but I wouldn't hold my breath.
            Last edited by Developer Dude; Sep 25th, 2009, 11:33 AM.

            Comment


            • #7
              Here is where I am at now:

              I have a Command interface. Often, you will see this interface just have a single 'execute()' method (this is what the Apache Commons Command is). My philosophy is to use interfaces as much as possible - especially with regards to reuse - much better for decoupling. This single method is not very useful. If that is all there is in a Command, you will either see one of two things:

              a) Sub-interfaces that will get used a lot more than the base interface, if the base interface gets used at all. Why define an interface if it isn't going to be used??

              b) Some hierarchy of abstract/default classes that get used/extended. If you are going to always be using the base class and not the interface, why define the interface at all? I see this all the time, including in some Spring modules.

              I say all this so you will understand my philosophy and why my Command interface has ten methods in it that I think most Commands will implement (some may be optional). All but two methods are setters/getters - set/get Callbacks, the Context (Object), whether the Command is interruptible (getter only), and the name of the command, and the current progress percentage (0 to 100). The two other methods are 'execute()' and interrupt() (can be the same as pause, cancel).

              At this point, the Command can be very lightweight and used almost anywhere. Much of the interface is optional except for 'execute()' and maybe 'interrupt()'. I am considering whether to add 'setup()' methods.
              Last edited by Developer Dude; Sep 25th, 2009, 12:22 PM.

              Comment


              • #8
                Callbacks are essentially listeners for Command events (started, interrupted, paused, finished), but they also serve as glue to other components that call the Commands and Callbacks are the only thing that can interrupt a Command.

                The 'glue' is so a Command can be decoupled and yet provide feedback with regards to status, events and errors. This will also help when threading is involved, as is often the case with regards to most UI kits.

                Another bit of glue I used before and will use again is a DelegateCommand. The DelegateCommand is just a wrapper around the Command. There will be a couple of different base default Delegates - non-threaded with the default behavior of just calling 'execute()', threaded such as using SwingWorker or Spin to invoke the Command.

                This way a Command doesn't necessarily have to know about threading issues and can concentrate on what it has to do without having to subclass every specific Command for Swing v. SWT v. console app v. server app. This facilitates reuse of the biz/persistance logic and the environ/threading logic is reused via the delegate. The delegate is a bean so you can plug any Command into it.

                Comment


                • #9
                  I agree with you guys, but from what I've read, business logic (or god forbid persistence logic) has no place in a GUI command in the first place. It reminds me of VB6 programming where the click of a button would directly save stuff in the database. I hope none of you guys still write 1 or 2 tiered applications... If you have a decently decoupled architecture, the only things your GUI commands will contain are service calls and GUI specific behavior, and if that's the case, I don't really see the need for another abstraction or UI decoupling.
                  When creating a 3 tiered server-client application (which most Swing apps in enterprises are), most logic should be executed on the server side, and if logic needs to be done on the client side, it should be through a service call or some sort of UI-decoupled command class, providing the necessary abstraction in the UI command and the reuse you're looking for.
                  Spring RCP is pluggable towards its commands through the existence of wrapppers. For example, there's an RCP wrapper for Swing's Action class. It would be really easy to create a wrapper class for Apache's Command class, feel free to contribute.
                  The heart of the case is: there are a lot of UI decoupled command frameworks out there. At the moment, its a whole lot easier to provide wrappers for those frameworks instead of inventing yet another command framework (DRY). Spring RCP is a GUI framework, and it's commands are UI coupled, which is quite logical.

                  Comment


                  • #10
                    Originally posted by LievenDoclo View Post
                    I agree with you guys, but from what I've read, business logic (or god forbid persistence logic) has no place in a GUI command in the first place. It reminds me of VB6 programming where the click of a button would directly save stuff in the database. I hope none of you guys still write 1 or 2 tiered applications... If you have a decently decoupled architecture, the only things your GUI commands will contain are service calls and GUI specific behavior, and if that's the case, I don't really see the need for another abstraction or UI decoupling.

                    When creating a 3 tiered server-client application (which most Swing apps in enterprises are), most logic should be executed on the server side, and if logic needs to be done on the client side, it should be through a service call or some sort of UI-decoupled command class, providing the necessary abstraction in the UI command and the reuse you're looking for.
                    Spring RCP is pluggable towards its commands through the existence of wrapppers. For example, there's an RCP wrapper for Swing's Action class. It would be really easy to create a wrapper class for Apache's Command class, feel free to contribute.
                    It depends on the app. I agree that the GUI should not be coupled to biz logic, which is one of the reasons I am saying that I would prefer that there be yet another more generic 'command' layer. And there aren't always services either - not to mention it is nice so have some separation from services. Not everything is client/server - sometimes apps don't talk to a server at all, there is no 'service', and sometimes yes you do need some biz logic that you want to wrap inside *something* to do something, and it is nice to be able to reuse that.

                    The heart of the case is: there are a lot of UI decoupled command frameworks out there. At the moment, its a whole lot easier to provide wrappers for those frameworks instead of inventing yet another command framework (DRY). Spring RCP is a GUI framework, and it's commands are UI coupled, which is quite logical.
                    I have been looking at a number of various implementations and I haven't found one I liked yet. This is always something I try to do before going off and reinventing one myself because I know there is a lot of duplication out there and I hate reinventing the wheel - I would much rather use something someone else wrote and has tested and been reviewed.

                    I agree that there should be an adapter for the UI layer, and the way I am writing mine there will be a fairly simple one - that is what I did before - an ActionCommandListener class which basically was the adapter between the UI component and the Commands. I will also write a very simple adapter/delegate for hooking into the current SRCP command framework so it complements it instead of replacing it.

                    The way I am writing my commands they are very much decoupled from any idea of a UI, with some delegates to serve as adapters for whatever use. Also, they are lightweight in the sense that you can just use as little of them as you wish. Maybe yes they will feel redundant to some, but I think some will find them useful.

                    I still feel the problem of building in the specific UI components into the SRCP command framework is not desirable for the reasons I mentioned.

                    Thanks for the feedback.

                    Comment


                    • #11
                      The methods createButton, createMenuItem, ... are actually convenience methods . You can create JButton without them too:

                      Code:
                      public static AbstractButton createAButton(AbstractCommand command)
                          {
                              ButtonFactory factory = (ButtonFactory) ApplicationServicesLocator.instance().getApplicationServices().getService(ButtonFactory.class);
                              CommandButtonConfigurer configurer = new DefaultCommandButtonConfigurer();
                              AbstractButton button = factory.createButton();
                              new CommandFaceButtonManager(command, command.getDefaultFaceDescriptorId()).attachAndConfigure(button, configurer);
                              button.setEnabled(command.isEnabled());
                              button.setVisible(command.isVisible());
                              return button;
                          }
                      So we could omit those methods, but as I said, they're there for the convenience of the developer. The above method is even more elaborate when hooking an ActionCommand to a Button.
                      Last edited by LievenDoclo; Sep 26th, 2009, 10:31 AM.

                      Comment

                      Working...
                      X