Announcement Announcement Module
Collapse
No announcement yet.
Questioning the core component Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Questioning the core component

    Hi folks,

    I dipped into the RCP source-code just for relaxation from another project and I started with the org.springframework.richclient.application.Aplicat ion class.

    Since this is the core class of the framework, I was a bit humbled since I got the feeling that the design smells by first gaze.

    Here is why:

    First of all what is a suitable definition of application?

    Using google "define: application" we get:

    - "a program that gives a computer instructions that provide the user with tools to accomplish a task"
    - "a diligent effort; "it is a job requiring serious application"
    - "the work of applying something;"
    - "lotion: liquid preparation having a soothing or antiseptic or medicinal action when applied to the skin; "a lotion for dry skin"
    - "Application is short for application program, which is a program designed to perform a specific function."

    Ok that should provide us enough to think about applications:

    We can agree that an application in our bounded context is:

    - short form for application program
    - designed to accomplish a certain task (tool aspect)
    - designed to perform specific function

    We can also agree that an application in our bounded context is not a lotion for dry skin!!


    Ok lets take a look at the Application class. The Application class is a class and therefore implicates a type. The type Application looks like this:

    Code:
    public class Application implements InitializingBean, ApplicationContextAware {
        public static void load(Application instance);
    
        public static Application instance();
    
        public static boolean isLoaded();
        public static ApplicationServices services();
        
        public void setDescriptor(ApplicationDescriptor descriptor);
        public void setServices(ApplicationServices services);
    
        public void setApplicationContext(ApplicationContext context);
        public void afterPropertiesSet();
    
        public ApplicationLifecycleAdvisor getLifecycleAdvisor();
        public ApplicationServices getServices();
    
        public String getName();
        public Image getImage();
    
        public void openWindow(String pageDescriptorId);
    
        public WindowManager getWindowManager();
        public ApplicationWindow getActiveWindow();
        public void close();
    }
    Ok this is a type. Now we have to resolve some hazard coming from the aspect the class is also an implementation.

    So we have to question the super types first... .

    It implements ApplicationContextAware and InitializingBean.
    From the import statement we learn:

    import org.springframework.context.ApplicationContext;
    import org.springframework.context.ApplicationContextAwar e;

    So being in the package *.springframework.richclient, these types are not relevant for our application type so we can drop them.

    By simplifying our type, we end with this:

    Code:
    public class Application {
        public static void load(Application instance);
        public static Application instance();
        public static boolean isLoaded();
        public static ApplicationServices services();
        
        public void setDescriptor(ApplicationDescriptor descriptor);
        public void setServices(ApplicationServices services);
    
        public ApplicationLifecycleAdvisor getLifecycleAdvisor();
        public ApplicationServices getServices();
    
        public String getName();
        public Image getImage();
    
        public void openWindow(String pageDescriptorId);
    
        public WindowManager getWindowManager();
        public ApplicationWindow getActiveWindow();
        public void close();
    }
    Ok now lets question the methods.

    public static void load(Application instance);
    public static Application instance();
    public static boolean isLoaded();
    public static ApplicationServices services();

    Boy! Static methods in a type? Misplaced, gotta be moved for sure!

    public void setDescriptor(ApplicationDescriptor descriptor);
    public void setServices(ApplicationServices services);

    Looks like dependency injection -> Implementation detail not type detail. Leave out.

    Actual version:

    Code:
    public type Application {
        public ApplicationLifecycleAdvisor getLifecycleAdvisor();
        public ApplicationServices getServices();
    
        public String getName();
        public Image getImage();
    
        public void openWindow(String pageDescriptorId);
    
        public WindowManager getWindowManager();
        public ApplicationWindow getActiveWindow();
        public void close();
    }
    This is the type Application. So the question goes to the semantic meaning. An application is designed for performing certain tasks. So instances of Application are designed to perform any function/task possible - right generic.

    So what kind of features do we have within our Application and how are they related to applications in a generic viewing?

    public ApplicationLifecycleAdvisor getLifecycleAdvisor();
    public ApplicationServices getServices();

    Um looks something supportive but I lack some knowledge to be sure. A lifecycle advisor looks like an processing detail and may be an implementation detail and should be hidden for non autorized eyes. Not sure.

    ApplicationServices concept looks sweet if you ask me. It looks like a way to iterate the services the application may provide. So we have an application which can be described by the services it offers. Is this right thinking? I like the idea, so I buy it up to now.

    public String getName();
    public Image getImage();

    Ok that looks descriptive. Application please identifiy yourself. Name, image, ok. Can be brought, but I am in doupt if an application need to know its name and its image to identify itself. Maybe this should be moved to a type ApplicationDescription and this is outside of the scope of our Application type for sure -> extract.

    public void openWindow(String pageDescriptorId);
    public WindowManager getWindowManager();
    public ApplicationWindow getActiveWindow();

    Ok this looks interesting! Windows! So we don't talk about an application in general, we talk about applications using windows. We got also an ApplicationWindow type and a window manager and it can open a window.

    First of all, shouldn't the type name of type Application reflect, that we are thinking about applications having windows? Is every application needed to have a window within the rich client framework?

    I wouldn't make openWindow a thing the application should provide as normal function. Also having control about its window manager, I am deeply in doupt. The next thing is getActiveWindow. Should the application care about its view?? We have an intermixing between View and Controller I guess.

    If I would be an application I wouldn't like to fuzz with window details. Opening a window means also solving the problem, no proper window can be opened, so what to do? - throwing an exception?

    As an application I don't like to think about this. I just don't care! And when you ask me, what window is the current active one, I just would say: "I don't care, just look for yourself!". This is view-stuff! I am an application! I am about do-stuff!

    Ok now and finaly:
    public void close();

    What does this mean? Applications don't get closed. Windows, streams etc. get closed. There is no state of an application being named closed. An application may be active or deactive, alive or dead, created or destroyed, new or old. So whats a more abstract verb of close? Well how about dispose? Disposing may be translated to trashing something. Isn't this what this method means (I dont know yet).

    so we and up with:

    Code:
    public type Application {
        public ApplicationLifecycleAdvisor getLifecycleAdvisor();
        public ApplicationServices getServices();
        public void dispose();
    }
    Looks better doesn't it?

    We also get:
    Code:
    public type ApplicationDescription {
        public String getName();
        public Image getImage();
    }

    Also we need to handle the static one.
    Remember we talk about this:
    Code:
        public static void load(Application instance);
        public static Application instance();
        public static boolean isLoaded();
        public static ApplicationServices services();
    This is higher level stuff. A normal application do not deal with it. So we need an object to put those methods in. Eclipse got it's Platform. The platform can be translated to Runtime or Environment. What we need is an object being responsible for application handling and providing the environment the applications swim in.

    Platform sounds good, ApplicationEnvironment would also be nice, ApplicationPlatform sounds and Runtime isn't as sexy as the other three are. Up to you.

    Lets call it ApplicationPlatform for the moment.

    Code:
    type ApplicationPlatform {
        //public static void load(Application instance);
        //We dont load an application object being already created!
        public void initialize(Application instance) 
    
        //public static Application instance();
        //we got singleton behaviour so this may be translated
        public Application getActiveApplication();
    
        //public static boolean isLoaded();
        //This translates to isInitialized() but no its not mmm.
        public boolean isAnyApplicationActive(); //What is this good for?
       
        //Oro? Whats this good for in this context, I dont know... .
        public ApplicationServices services(); 
    }
    Now we have seperated most of the responsibilities.

    The ApplicationPlatform handles the lifecycle of the Application. Maybe the dispose method should go to the ApplicationPlatform, too.

    ApplicationPlatform.dispose(Application) - or destroy, end how ever you call the last state in an application lifecycle (anyone having a state diagram?)

    And ApplicationLifecycleAdvisor may be seen as an aspect describing the application lifecycle behaviour. So it isout of the scope of an Application instance for sure (exists before and after the application's own life). So the application should not know anything about it. So why not making the lifecycle advisor part of the loading process.

    ApplicationPlatform.initialize(Application application, ApplicationLifecycleAdvisor applicationsLifecycleAdvisor).

    Now how does ApplicationDescription fits this into? Uhm this is something the ApplicationPlatform should know, too.


    ApplicationDescription ApplicationPlatform.getDescription(Application application)

    So it should know the application's description. An Application enters the scope (knowledge space) of a ApplicationPlatform within the initialize method (now I would rename this method to something more specific). Since the description should be inmutable we can also extend the initialize method by this detail.

    ApplicationPlatform.initialize(Application application, ApplicationDescription applicationDescription, ApplicationLifecycleAdvisor applicationsLifecycleAdvisor).

    Looks sweet, but what is about the window manager?

    Well a window manager manages the application windows (view aspect). Windows are somewhat related to the ApplicationPlatform.

    WindowManager ApplicationPlatform.getWindowManager(Application application)

    This sounds crazy. A window manager is depending on a single application? Not in my world. Lets rename it to ApplicationWindowManager.

    ApplicationWindowManager ApplicationPlatform.getWindowManager(Application application)

    So the application window manager knows how to open and close ApplicationWindows. Nice isn't it? Also this manager knows what the active window is. It provides a listener service to listen for open/close window events.

    The ApplicationPlatform is not stupid, that's why it listens for all those events the application window managers provide. So the application can be disposed by the platform once once the last window gets closed.

    Now the question? If all windows are closed, the application gets disposed automatically. Nice rule, but we need an exception, don't we?

    When the platform initializes an application, it does not have any windows. Guys you know what? During the initialization of an application we open a default window! If no default window can be opened, we dispose the application right out of the box. No window, no meaning, no life! -> we should rename Application for sure, my guts arn't lying, I guess!

    So how can we give the ApplicationPlatform.initialize method the knowledge about the default window to open? Well what about the ApplicationDescription? It describes the application. I can think of creating an application supporting many diffrent application window perspectives. The application shouldn't care if any of it's windows are initial ones. So it is sure somewhat descriptive and out of the application's scope.

    So now we got a problem. ApplicationDescription is a description now holding informations about the initial application process (initial window to open). This information is only needed once during the initial phase of the application, so it shouldn't be accessible by the ApplicationDescription.

    How about this design:

    Code:
    type ApplicationContext {
        getApplicationDescription
        getInitialWindowToOpen
    }


    Hmm an ApplicationContext. Maybe this is not the right name. We also got already deal with an application context with diffrent meaning.

    The Spring framework seams to deal with applications itself (why else should the framework have objects called ApplicationContext?). So thinking further we know the Spring framework deals with web-applications and generic applications as well.

    RichClient API uses the spring framework to support its special kind(!) of application. This means we are talking about special applications here!

    How about renaming Application to ClientApplication or RichClientApplication? And ApplicationPlatform becomes ClientApplicationPlatform. Boy that sounds! Would solve some of our worst curses poisioning our thinking.

    So now that I described a (in my oppion) clearer design, a typical question is normally thrown at me:

    Your type of ClientApplication is a way too abstract, it would make my implementation quite ugly and complicated.

    Well add support for often needed methods to the AbstractClientApplication service implementation stub. The application's window manager may be visible by its View implements etc. This is implementation detail we are talking about architecture here, so this is nothing which should state against this design.

    Now I have to review my hipshot thoughts! Urgh, long! --- Ok some problems solved. If you have questions or something to add I would like to hear. First of all remember I just reviewed my first type and didn't look for the other types to not poison my first impressions.

    Final Code structure:

    Code:
    type ClientApplication {
        //empty? how did you changed?
    }
    Code:
    public type ClientApplicationDescription {
        public String getName();
        public Image getImage();
    }
    Code:
    type ClientApplicationPlatform {
        public void initializeApplication(ClientApplication, ClientApplicationContext);
        public void disposeApplication(ClientApplication);
    
        public boolean isAnyApplicationActive(); //What is this good for? 
        public ClientApplication getActiveApplication();
        public ClientApplicationDescription getDescription(ClientAppliaction);
        public ClientApplicationWindowManager getWindowManager(ClientApplication);
    }
    Code:
    type ClientApplicationContext {
        ClientApplicationDescription getApplicationDescription();
        getInitialWindowToOpen();
        ClientApplicationLifecycleAdvisor getLifecycleAdvisor();
    }
    Code:
     
    type ClientApplicationWindowManager {
        openWindow(String windowId); //boy must get rid of the String later!
        closeWindow(ApplicationWindow);
        ApplicationWindow getActiveWindow();
        addWindowManagerListener(WindowManagerListener);
        removeWindowManagerListener(WindowManagerListener);
    }
    By seeing this ClientApplicationWindowManager I am questioning my self if ClientWindowManager wouldn't be enough?! ....

    By the way, ApplicationServices was taken out since I don't know what it is up to. (Next target of investigation :-)


    Cheers,

    Martin (Kersten)

  • #2
    Excellent design analysis, Marten. I can tell you have a strong knowledge of the rich client feature domain, and that's the most important thing you need to craft a elegant design.

    I agree Application is a bit bloated now, and client access to it is a bit nilly-willy (it's basically a static entry point to a service locator). I don't think we're doing anything terribly wrong with it design wise now (other than the former comment where its easy for too many other things to depend on it) - as we do ensure it's easily to initialize and configure as construction logic is not hard-wired in (still giving you the benefit of easy unit testing). But I REALLY do like a lot of your points (even after just a quick read now); and hope we can integrate them in.

    Comment


    • #3
      Well I've got a short break again and started to relax then I came up with the following thinking:

      If we get rid of this client application is a singleton stuff, how about this:

      Having more than one ClientApplication per VM? Imagen starting up two applications per default! Would this make scence? Well I dont know. But how about having hierarchical applications.

      You know composing one application out of two or three others. You can run your XML-Editor as a single application or you well, you can put it into something more interesting.

      Inside your BigDaddyApplication you do something like this:

      XMLEditorApplication editor=XMLEditorApplication.create();
      editor.setInput(Document);
      ClientApplicationPlatform.initialize(editorApplica tion, ...);

      Here we go, opened a new XML editor using a default component. I guess if the design supports this odd (in real world terms) scenario, you will have a framework flexible as hell.

      This is a freak use-case scenario great for keep the designers thinking. Someone should write it down :-).

      But from the code above, the Platform.initialize method is still crazy :-).


      When gets the API frozen? I would love to download the rich client API and refactor it so it will meet the design I would favor. I won't go for correctness but for architecture. So it would be quite fast to do it (major improvments (if I find some) would be possible within a week). I guess I can learn much by doing this task, too.

      Once I finish the task, I would contribute this version. Then you can can take a look and see what you like better and deside what you integrate and what not.

      If I am going to be successfull in finding a cleaner design, I would prove most of my critics about the Eclipse design to be right. The Eclipse design has many flaws in my oppinion, but it improved greatly in the 3.x branch.

      But I just want to know if my critics (got a list) are right in first place. I don't want become a guy ranning around and accusing everyone to deliver broken design ;-).


      Cheers,

      Martin (Kersten)

      PS: Sure you folks don't do anything totaly wrong. People like the framework so it can't be old fish, can it?
      PSS: But the singelton stuff smells a bit like old fish. ;-)
      PSSS: Martin not Marten

      Comment


      • #4
        I dipped into the complete source this time and among the things that I noticed are flaws within the package structure and a lot of reversed responsabilities. (hopefully I have dipped into the correct source branch someone should delete the old rcp branch within the springframework cvs).

        I also got the feeling that you folks reviewed much of the Eclipse sources .

        Seeing the code I have to say: "My respect to you folks!" You extended and improved the RCP right a lot since my last visit in late 2004. Also it seams that RCP can really leaverage Swing and make most of the things vanish that drive people away from it. Great respect!

        Also I can say now, that I can provide much value to RCP once I reviewed it fully. This is the opportiunity I have dreamed for since I started to analyse the Eclipse framework. Hopefully you folks buy most of my ideas and don't call it bogus! ;-)

        I can start thuseday with the work since I got some free time then. kDonald, can we have a little chat before thuseday?

        I would like to start with the package structure, which will provide instant gain and can be done in some hours. (well if you buy it, it would take longer to introduce it of cause).


        Cheers,

        Martin Kersten

        Comment


        • #5
          Reviewed the test suite... Are you serious about your test suite? Looks like a lot of tests are missing. Are there anymore tests?

          Comment


          • #6
            :oops:

            Tests and documentation are not up to general Spring quality; please understand that's why we still consider the project @ alpha and why we have yet to release!

            I take responsibility for this, as I alluded to in a previous post here. It was a mistake to continue adding new features/modules -- no matter how good -- without getting closure (from both a code/doc/test POV) on existing stuff first (easier said than done, when we're all faced with deadlines--but I'm not making excuses here).

            So now we're shifting now to the next stage: to get to release quality, we've got to get things stable (addressing one module at a time--I am starting now with the command framework), with each well-tested and clearly documented. The general "platform" or "application" module is a VERY important one as well--right up there with form data binding and validation module. Those 3 are the critical areas for spring rich that once stable/tested/documented, will get us to where we want to be.

            I certainly value your help and your recommendations/suggestions. Drop me a email off-line and I'd be happy to work together with you.

            Keith

            Comment


            • #7
              Ok lets continue our talk in hidden compounds. I sent you an email with a type diagramm I call a minimalistic design for a Rich Client Framework.

              Comment

              Working...
              X