MVC design questions

Discussion in 'Java' started by Martin Gregorie, Feb 10, 2009.

  1. I'm developing a database system that includes both command line and GUI
    programs. As both GUI programs need to display fairly large amounts of
    data, much of it dependent on precious decisions by the user, they both
    use a number of screens this type of relationship:
    initial screen - prompt for selection criteria
    pop-up screen displaying a selectable list
    pop-up screen showing the selected item's details

    These programs use the MVC model. Currently each program has one Model
    and one Controller to handle data and refresh requirements for all the
    screens. Pop-ups are controlled by list selection listeners and action
    listeners. The model interacts with the database through a JDBC access
    layer, implemented as a single class that contains all SQL statements and
    JDBC operations.

    Question: Is this a common way of managing a multi-window GUI or is
    it more usual to have a separate MVC triad for each window?


    I've implemented a separate Model class and database access class for
    each program. These are subclasses of Model and database access super-
    classes that were intended to contain just common operations such as db
    open/close and error diagnostics. However, to make some window classes
    usable in both GUI programs, its necessary to use super-class references
    in them and this in turn has required virtually subclass methods to have
    stubs in the super-class. Worse, many have to be concrete, overridable
    stubs rather than abstract or stuff won't compile. The result works OK
    but is getting somewhat untidy.

    Question: Would it be better to get rid of the subclasses by pulling
    their code into the current super-classes in place of the
    method stubs?

    Question: Would the situation be helped by using Interface
    definitions? I'm not using t5hem at present.

    Question: Is there a book you'd recommend that covers these aspects
    of application design?

    The code is running reliably at present and with adequate performance
    apart from a couple of queries that I haven't yet optimized. However, as
    I said, its a bit untidy in places so some refactoring would be
    beneficial. I'm posing these questions now so as to, hopefully, avoid
    diving into some refactoring black hole.

    TIA,
    Martin


    --
    martin@ | Martin Gregorie
    gregorie. | Essex, UK
    org |
    Martin Gregorie, Feb 10, 2009
    #1
    1. Advertising

  2. Martin Gregorie

    Stefan Ram Guest

    Martin Gregorie <> writes:
    >Question: Is this a common way of managing a multi-window GUI or is
    > it more usual to have a separate MVC triad for each window?


    The leading verb »Is« and the trailing question mark »?«
    already mark your sentence as being a question. Some readers
    might be offended when you seem to imply that they may not
    notice this, but need additional markup to recognize questions.

    If someone indeed reads so superficially or is so challenged
    that he will not immediatly recognize a question without
    additional help, does he belong the the intended circle of
    your readers?

    I do not have a good overview, but I assume that usually there
    is a triad per UI element (window, widget, gadget, component,
    ...).

    Swing does not use MVC directly, but a modfication including
    »UI delegates«. In this case, there is on UI delegate per
    UI element.

    >However, to make some window classes usable in both GUI
    >programs, its necessary to use super-class references in them


    I do not really understand this. I used to believe that, in Java,
    each class (possibly, except »java.lang.Object«) would know
    its superclass. Therefore, I can not answer to the rest.
    Stefan Ram, Feb 10, 2009
    #2
    1. Advertising

  3. Martin Gregorie wrote:
    > I'm developing a database system that includes both command line and GUI
    > programs. As both GUI programs need to display fairly large amounts of
    > data, much of it dependent on precious decisions by the user, they both
    > use a number of screens this type of relationship:
    > initial screen - prompt for selection criteria
    > pop-up screen displaying a selectable list
    > pop-up screen showing the selected item's details
    >
    > These programs use the MVC model. Currently each program has one Model
    > and one Controller to handle data and refresh requirements for all the
    > screens. Pop-ups are controlled by list selection listeners and action
    > listeners. The model interacts with the database through a JDBC access
    > layer, implemented as a single class that contains all SQL statements and
    > JDBC operations.
    >
    > Question: Is this a common way of managing a multi-window GUI or is
    > it more usual to have a separate MVC triad for each window?



    I often share a model between a list-view and a detail-view. For viewing
    purposes the detail view doesn't need access to the model, only to a
    single DTO or domain object provided by the model. In the list
    controller, in response to a "view detail" event I instantiate a detail
    view and pass a DTO object to an init() method of the detail view.

    >
    >
    > I've implemented a separate Model class and database access class for
    > each program. These are subclasses of Model and database access super-
    > classes that were intended to contain just common operations such as db
    > open/close and error diagnostics. However, to make some window classes
    > usable in both GUI programs, its necessary to use super-class references
    > in them and this in turn has required virtually subclass methods to have
    > stubs in the super-class. Worse, many have to be concrete, overridable
    > stubs rather than abstract or stuff won't compile. The result works OK
    > but is getting somewhat untidy.


    My experience is probably similar except that I have far more abstract
    methods than overridable ones. The only overridable ones I have are for
    default behaviours and are rarely overridden. My model superclass has
    about ten final methods, ten abstract methods and two overrideable
    concrete methods which essentially return null results.

    >
    > Question: Would it be better to get rid of the subclasses by pulling
    > their code into the current super-classes in place of the
    > method stubs?


    I'm not sure I understand. I've aimed to get *all* common code into the
    super-classes. This doesn't remove the subclasses entirely, at least,
    not without a lot more thought than I've given it.

    In essence, my model subclasses provide the superclass with SQL
    constructs specific to certain tables or business domain contexts. They
    also extract a specific DTO from the ResultSet obtained by the
    superclass. The DTO is basically the generic parameter for the
    superclass. The superclass handles all the common overhead of
    connections, transactions error-handling etc. IIRC It provides all the
    methods needed by my views and controllers. This works well for 95% of
    my cases so far. I have a couple of dozen subclasses. Occasionally it is
    messy (the other 5%).


    --
    RGB
    RedGrittyBrick, Feb 10, 2009
    #3
  4. On Tue, 10 Feb 2009 16:24:23 +0000, Stefan Ram wrote:

    > Martin Gregorie <> writes:
    >>However, to make some window classes usable in both GUI programs, its
    >>necessary to use super-class references in them

    >
    > I do not really understand this. I used to believe that, in Java, each
    > class (possibly, except »java.lang.Object«) would know its superclass.
    > Therefore, I can not answer to the rest.
    >

    Its really being used the other way up at present. Consider a class
    defining a window that can be used either to update, insert or delete
    items in a list or to simply display items from the in response to a
    query. It calls methods in the model superclass to fill its fields and
    has an action listener that can apply changes to the database if the
    window is being used in edit mode.

    The Model superclass delegates these to a program-specific Model subclass
    because, in general the model used by updating program will not be the
    same as that in the query program. For instance, the updating program
    might be maintaining a flat list of all addresses used by a company
    while the query program shows a subset of addresses, e.g. those of
    offices nearest a city or those of employees who are heating engineers.


    --
    martin@ | Martin Gregorie
    gregorie. | Essex, UK
    org |
    Martin Gregorie, Feb 10, 2009
    #4
  5. Martin Gregorie

    Stefan Ram Guest

    Martin Gregorie <> writes:
    >Its really being used the other way up at present. Consider a class
    >defining a window that can be used either to update, insert or delete
    >items in a list or to simply display items from the in response to a
    >query. It calls methods in the model superclass to fill its fields and
    >has an action listener that can apply changes to the database if the
    >window is being used in edit mode.


    »The optional extends clause in a normal class declaration
    specifies the direct superclass of the current class.«
    ¯¯¯¯¯¯¯¯¯¯
    Java Language Specification, Third Edition, 8.1.4

    A window class rarely extends its model.

    You possibly use the word »superclass« in another sense
    than the Java Language Specification, Third Edition.
    Stefan Ram, Feb 10, 2009
    #5
  6. On Tue, 10 Feb 2009 17:18:02 +0000, RedGrittyBrick wrote:

    > I often share a model between a list-view and a detail-view. For viewing
    > purposes the detail view doesn't need access to the model, only to a
    > single DTO or domain object provided by the model. In the list
    > controller, in response to a "view detail" event I instantiate a detail
    > view and pass a DTO object to an init() method of the detail view.
    >

    That's good to know since that's essentially what I'm doing.

    > My experience is probably similar except that I have far more abstract
    > methods than overridable ones. The only overridable ones I have are for
    > default behaviours and are rarely overridden. My model superclass has
    > about ten final methods, ten abstract methods and two overrideable
    > concrete methods which essentially return null results.
    >

    I'd hoped to do exactly that, but most of my initially abstract stubs
    caused compilation errors that would only vanish when I converted them
    into concrete dummy stubs. I don't fully understand why.

    >
    >> Question: Would it be better to get rid of the subclasses by pulling
    >> their code into the current super-classes in place of the
    >> method stubs?

    >
    > I'm not sure I understand. I've aimed to get *all* common code into the
    > super-classes. This doesn't remove the subclasses entirely, at least,
    > not without a lot more thought than I've given it.
    >

    Thanks - for the time being I'll just move the one or two common subclass
    methods into the super-class and then mull over the situation some more.

    FWIW separating out the JDBC layer from the model layer was an early
    decision but I was undecided whether to lump JDBC access for all programs
    into one system-wide class or to have one class per program. I eventually
    decided to go with the second idea plus a super-class to hold the common
    elements but am wondering if that was the right decision.

    > In essence, my model subclasses provide the superclass with SQL
    > constructs specific to certain tables or business domain contexts. They
    > also extract a specific DTO from the ResultSet obtained by the
    > superclass. The DTO is basically the generic parameter for the
    > superclass. The superclass handles all the common overhead of
    > connections, transactions error-handling etc. IIRC It provides all the
    > methods needed by my views and controllers. This works well for 95% of
    > my cases so far. I have a couple of dozen subclasses. Occasionally it is
    > messy (the other 5%).
    >

    This system has a really simple schema - just 5 tables, one sequence and
    one view that's never used by Java code.
    - the sequence is used by one program.
    - all the Java programs need to access the main set of 4 tables,
    which form a star schema with one M:M dimension.
    - the remaining table is used by one program to control the activity
    of a second. The two programs never run simultaneously.


    --
    martin@ | Martin Gregorie
    gregorie. | Essex, UK
    org |
    Martin Gregorie, Feb 10, 2009
    #6
  7. Martin Gregorie

    Lew Guest

    On Feb 10, 1:58 pm,
    RedGrittyBrick wrote:
    >> My experience is probably similar except that I have far more abstract
    >> methods than overridable ones. The only overridable ones I have are for
    >> default behaviours and are rarely overridden. My model superclass has
    >> about ten final methods, ten abstract methods and two overrideable
    >> concrete methods which essentially return null results.

    >


    Martin Gregorie wrote:
    > I'd hoped to do exactly that, but most of my initially abstract stubs
    > caused compilation errors that would only vanish when I converted them
    > into concrete dummy stubs. I don't fully understand why.
    >


    Can you work up and post an SSCCE that demonstrates this issue? I'm
    very intrigued.

    --
    Lew
    Lew, Feb 10, 2009
    #7
  8. Martin Gregorie

    Tom Anderson Guest

    [I think i have rather low levels of blood sugar and caffeine right now,
    so some of what i write may be stupid - apologies if so. I'm also asking a
    lot of questions the answers to which may not have any bearing on the
    solution sought.]

    On Tue, 10 Feb 2009, Martin Gregorie wrote:

    > I'm developing a database system that includes both command line and GUI
    > programs. As both GUI programs


    'Both GUI programs'? Do you have multiple GUI programs, plus the CLI one?
    If so, how do the GUI programs differ?

    > need to display fairly large amounts of data, much of it dependent on
    > precious decisions by the user, they both use a number of screens this
    > type of relationship:
    > initial screen - prompt for selection criteria
    > pop-up screen displaying a selectable list
    > pop-up screen showing the selected item's details


    Can you have several initial windows open at once? Can you have several
    list windows per initial? Several details per list?

    > These programs use the MVC model. Currently each program has one Model
    > and one Controller to handle data and refresh requirements for all the
    > screens. Pop-ups are controlled by list selection listeners and action
    > listeners. The model interacts with the database through a JDBC access
    > layer, implemented as a single class that contains all SQL statements
    > and JDBC operations.
    >
    > Question: Is this a common way of managing a multi-window GUI or is
    > it more usual to have a separate MVC triad for each window?


    I have a definite preference for one model across the whole system. One
    model object per domain entity - the last you thing you want is multiple
    Inmate objects representing the same inmate.

    As for controllers - i tend to think one controller per UI assembly.
    Although if they're stateless, you can share them. But then, if they're
    stateless, they're small, so there's no harm in not sharing them.

    And that just begs the question of what a 'UI assembly' is. You could have
    one per initial window, doing controlling for that window and its list
    popups, or one for each different window, initial and popup. There, i
    think i'd go for one per window - make each controller as simple as
    possible, handling the events and updates for just one window. If your
    windows are complicated, with several panes or widgets or whatever, then
    perhaps even one per part of a window.

    > I've implemented a separate Model class and database access class for
    > each program. These are subclasses of Model and database access super-
    > classes that were intended to contain just common operations such as db
    > open/close and error diagnostics. However, to make some window classes
    > usable in both GUI programs, its necessary to use super-class references
    > in them and this in turn has required virtually subclass methods to have
    > stubs in the super-class.


    I don't follow. You need the methods in the base class which are needed to
    support the windows common to the two apps - by definition, those are the
    the methods which are intrinsically common to the base model. Why are the
    other methods brought in? Are they called from the common methods,
    template-style?

    Or are you making all references to the model object references to the
    base type, even in the app-specific code? That would indeed require all
    methods to be stubbed in the base class, even when they were app-specific.
    Like:

    class BaseModel {}

    class FooModel extends BaseModel {}

    class BaseApp {
    protected BaseModel model;

    private void handleSomeKindOfEvent() {
    model.doGenericThing();
    }
    }

    class FooApp {
    private void handleSomeOtherKindOfEvent() {
    model.doFooSpecificThing();
    }
    }

    If you have code like that, then you need doFooSpecificThing in BaseModel,
    as well as doGenericThing. But the soluion isn't to do that, it's to
    refactor FooApp:

    class BaseApp {
    protected abstract BaseModel getModel();

    private void handleSomeKindOfEvent() {
    getModel().doGenericThing();
    }
    }

    class FooApp {
    private FooModel model;

    protected abstract BaseModel getModel() {
    return model;
    }
    private void handleSomeOtherKindOfEvent() {
    model.doFooSpecificThing();
    }
    }

    That lets you put doFooSpecificThing in FooModel.

    There's another way to do it, with a BaseModel reference in BaseApp, and
    lots of casting, but that's not nice.

    There's also a way to do it involving generics.

    Is that anything like the situation you've got?

    > Worse, many have to be concrete, overridable stubs rather than abstract
    > or stuff won't compile.


    That sounds really odd. Like Lew, i'd love to see some code here.

    > The result works OK but is getting somewhat untidy.
    >
    > Question: Would it be better to get rid of the subclasses by pulling
    > their code into the current super-classes in place of the
    > method stubs?
    >
    > Question: Would the situation be helped by using Interface
    > definitions? I'm not using t5hem at present.


    No. They won't do anything you can't do with classes and abstract methods.
    They might be a better way of doing things, but they won't actually solve
    problems.

    > Question: Is there a book you'd recommend that covers these aspects
    > of application design?


    There are no books that teach the skill of OO design but your own diary,
    and no schools but the school of hard knocks.

    Although Design Patterns and Refactoring are both pretty good.

    tom

    --
    I was employed by a Lacanian and, believe me, you don't want to see what
    a postmodern approach to cashflow entails. -- G'
    Tom Anderson, Feb 10, 2009
    #8
  9. On Tue, 10 Feb 2009 18:37:39 +0000, Stefan Ram wrote:

    > A window class rarely extends its model.
    >
    > You possibly use the word »superclass« in another sense than the Java
    > Language Specification, Third Edition.
    >

    Not intentionally.

    Lets see if a diagram is a clearer explanation of what I'm doing:

    MessageWindow - used by programs MASearch and MAUpdate
    | along with MessageWindowAction
    |
    MAModel (superclass) - contains no data or methods
    | |
    MASModel | - model used by the MASearch query program
    MAUModel - model used by the MAUpdate db maintenance prog


    The methods in the model used to support MessageWindow are implemented in
    MASModel and MAUModel and are not necessarily the same. MAModel is purely
    a shell containing abstract methods (or concrete overridden methods where
    the system won't compile if they are declared abstract). This is done so
    that MessageWindow doesn't know that its actually using MASModel in
    MASearch and MAUModel in MAUpdate.

    The window hierarchy is very different for the two programs:

    MAUpdate MASearch
    address list window[1] search criterion setting window
    AddressDialogue window[2] message list window[3]
    MessageWindow MessageWindow


    [1] this list contains a selectable list of all addresses.
    Selecting one displays its details in an AddressDialogue window,
    ready for amendment or deletion.

    [2] AddressDialogue contents includes a selectable list of messages
    associated with the selected address. Selecting a message displays
    it in a MessageWindow, which allows the message to be inspected
    and optionally deleted.

    [3] this list contains a selectable list of messages meeting the message
    search criteria. Selecting one displays it in a MessageWindow,
    which allows the message to be inspected and optionally sent to
    a recipient.

    The only difference between the appearance of the MessageWindow is that
    when MASearch uses it you see Send and Exit buttons while MAUpdate shows
    Delete and Exit buttons.

    If there is a way to achieve this elegantly without needing the MAModel
    super-class I'd be very pleased to be steered in that direction.


    --
    martin@ | Martin Gregorie
    gregorie. | Essex, UK
    org |
    Martin Gregorie, Feb 10, 2009
    #9
  10. On Tue, 10 Feb 2009 11:17:06 -0800, Lew wrote:

    > On Feb 10, 1:58 pm,
    > RedGrittyBrick wrote:
    >>> My experience is probably similar except that I have far more abstract
    >>> methods than overridable ones. The only overridable ones I have are
    >>> for default behaviours and are rarely overridden. My model superclass
    >>> has about ten final methods, ten abstract methods and two overrideable
    >>> concrete methods which essentially return null results.

    >>
    >>

    > Martin Gregorie wrote:
    >> I'd hoped to do exactly that, but most of my initially abstract stubs
    >> caused compilation errors that would only vanish when I converted them
    >> into concrete dummy stubs. I don't fully understand why.
    >>
    >>

    > Can you work up and post an SSCCE that demonstrates this issue? I'm
    > very intrigued.
    >

    I'll try, but don't hold your breath!

    In the meantime, my understanding is that, if I declare all but the
    common methods as abstract, then I'm free to override the ones provided
    by each subclass and ignore the rest BUT, as I call the subclass methods
    via the super-class, there must be an abstract method declared for every
    method in all subclasses.

    If this is a total misuse/misunderstanding of class hierarchies I'd
    appreciate correction or pointers to suitable tutorials.


    --
    martin@ | Martin Gregorie
    gregorie. | Essex, UK
    org |
    Martin Gregorie, Feb 10, 2009
    #10
  11. Martin Gregorie

    Stefan Ram Guest

    Martin Gregorie <> writes:
    >>You possibly use the word »superclass« in another sense than the Java
    >>Language Specification, Third Edition.

    >Not intentionally.


    > MessageWindow - used by programs MASearch and MAUpdate
    > | along with MessageWindowAction
    > |
    > MAModel (superclass) - contains no data or methods
    > | |
    > MASModel | - model used by the MASearch query program
    > MAUModel - model used by the MAUpdate db maintenance prog


    I am not sure in which direction the superclasses are:

    If MessageWindow /extends/ MAModel, then MessageWindow /is a/
    Model (Liskov-substitution principle). When a part of the view
    /is a/ model, this is not MVC: In MVC the model and view are
    /distinct/ parts, which are loosely coupled (at least) in one
    direction. Inheritance is not such a loose coupling.

    If MAModel /extends/ MessageWindow it also would not be MVC,
    because a model should not know the View, so it can not
    extend it. This also would be not loose coupling.
    Stefan Ram, Feb 10, 2009
    #11
  12. On Tue, 10 Feb 2009 20:08:42 +0000, Tom Anderson wrote:

    > [I think i have rather low levels of blood sugar and caffeine right now,
    > so some of what i write may be stupid - apologies if so. I'm also asking
    > a lot of questions the answers to which may not have any bearing on the
    > solution sought.]
    >

    No problem.

    > On Tue, 10 Feb 2009, Martin Gregorie wrote:
    >
    >> I'm developing a database system that includes both command line and
    >> GUI programs. As both GUI programs

    >
    > 'Both GUI programs'? Do you have multiple GUI programs, plus the CLI
    > one? If so, how do the GUI programs differ?
    >

    I have GUI programs for database maintenance and enquiry.
    See my last reply to Stefan Ram for more detail about them.

    The CLI programs handle bulk loading (the only input data source) and
    application-specific backup. The latter is faster that native DB backup
    because its incremental and supports transfer between different JDBBC
    supported RDBMS implementations, i.e. Postgres to H2 or MySQL.

    >> need to display fairly large amounts of data, much of it dependent on
    >> precious decisions by the user, they both use a number of screens this
    >> type of relationship:
    >> initial screen - prompt for selection criteria
    >> pop-up screen displaying a selectable list
    >> pop-up screen showing the selected item's details

    >
    > Can you have several initial windows open at once? Can you have several
    > list windows per initial? Several details per list?
    >

    Yes. Think of it as a visual stack of windows. Closing the detail screen
    lets you select another item form the list. Closing the detail and list
    lets you change the search criteria and create another list.

    > I have a definite preference for one model across the whole system. One
    > model object per domain entity - the last you thing you want is multiple
    > Inmate objects representing the same inmate.
    >

    So, you'd prefer one model for the whole system? Interesting! I hadn't
    considered that.

    > As for controllers - i tend to think one controller per UI assembly.
    > Although if they're stateless, you can share them. But then, if they're
    > stateless, they're small, so there's no harm in not sharing them.
    >

    That's what I'm currently doing, though the lists, which are all JTables,
    seem to self-adjust as items are changed or deleted without any help from
    the controller.

    The controllers are very simple, possibly because the windows tend to
    have a single method which refreshes all the displayed data in the
    window. Is this a reasonable way to go?

    >> I've implemented a separate Model class and database access class for
    >> each program. These are subclasses of Model and database access super-
    >> classes that were intended to contain just common operations such as db
    >> open/close and error diagnostics. However, to make some window classes
    >> usable in both GUI programs, its necessary to use super-class
    >> references in them and this in turn has required virtually subclass
    >> methods to have stubs in the super-class.

    >
    > I don't follow. You need the methods in the base class which are needed
    > to support the windows common to the two apps - by definition, those are
    > the the methods which are intrinsically common to the base model. Why
    > are the other methods brought in? Are they called from the common
    > methods, template-style?
    >

    Again, my reply to Stefan contains what I hope is a better explanation.

    I note, if I understand you correctly, that you'd sidestep this whole
    issue by having a single model class to support all my programs and a
    single database access class to provide a system-wide JDBC layer.

    As may be clear, I'm a long term C player and am trying to Java write
    Java in a way that doesn't look too much like its been written by a total
    Ctard. I think this system is a good learning tool since its not huge,
    but still has enough complexity to smoke out non-trivial design issues.
    So, feel free to fire away if you think my structures are horrid.

    > Or are you making all references to the model object references to the
    > base type, even in the app-specific code?
    >

    Yes, that's where I've ended up.

    As always, things started off fairly clean with separate, independent
    models both GUIs The CLI programs, of course, lack models, going directly
    to the JDBC layer. Then I realized that one or two windows were so
    similar that writing two program-specific versions was just stupid. Of
    course this forced me to introduce a model super-class as a sort of
    umbrella for the two models.

    > If you have code like that, then you need doFooSpecificThing in
    > BaseModel, as well as doGenericThing. But the soluion isn't to do that,
    > it's to refactor FooApp:
    >

    Would that be better than creating a system-wide model?

    > There's another way to do it, with a BaseModel reference in BaseApp, and
    > lots of casting, but that's not nice.
    >

    I agree. So far I don't think there's any in this system, except possibly
    when forced by 3rd party jar files, and I'd like to keep it this way.


    > There's also a way to do it involving generics.
    >

    I don't really understand generics and (so far) have scarcely used them.
    I know, I should be attending to that.


    > Is that anything like the situation you've got?
    >

    Yes - my class structure fits your first example requiring concrete stubs.

    > No. They won't do anything you can't do with classes and abstract
    > methods. They might be a better way of doing things, but they won't
    > actually solve problems.
    >

    OK. S'what I thought.

    > Although Design Patterns
    >

    Is this by James W Cooper, David Geary or some other author?

    > and Refactoring are both pretty good.
    >

    by Elliotte Rusty Harold?


    --
    martin@ | Martin Gregorie
    gregorie. | Essex, UK
    org |
    Martin Gregorie, Feb 10, 2009
    #12
  13. Martin Gregorie

    Lew Guest

    On Feb 10, 5:09 pm,
    Lew wrote:
    >> Can you work up and post an SSCCE that demonstrates this issue?  I'm
    >> very intrigued.

    >


    Martin Gregorie wrote:
    > I'll try, but don't hold your breath!
    >


    Trouble is, without the SSCCE I'm not understanding your question.

    > In the meantime, my understanding is that, if I declare all but the
    > common methods as abstract, then I'm free to override the ones provided
    > by each subclass and ignore the rest BUT, as I call the subclass methods
    > via the super-class, there must be an abstract method declared for every
    > method in all subclasses.
    >


    This is the part I don't understand - it doesn't match any mental
    model of inheritance that I have. On the face of it, your statement
    seems to bespeak a misunderstanding of method overrides.

    It sounds like you are referring to "classes" when you need to be
    talking about "types".

    You are free to override any supertype method that is not 'final'.

    Calling a superclass method, say 'foo()', via 'super.foo()' is done
    within a subclass implementation of 'foo()' in order to invoke
    superclass behavior in addition to the specialization that the
    subclass provides.

    The type defines the contract of what methods are available to client
    objects. If you want to call methods from a variable of a supertype
    from another class's instance, then the supertype must define those
    methods. If you want the methods only to exist in a subtype, then you
    must declare the variable to be of that subtype. If the supertype is
    a class, then the supertype method need not be 'abstract'.
    Polymorphism guarantees that the method call dispatches to the actual
    run-time implementation.

    So if 'Bar' extends or implements 'Foo', and

    Foo a = new Bar();
    a.doSomething();

    then 'Foo' must declare a (possibly 'abstract') method 'doSomething
    ()', and the 'a' instance will use the 'Bar' implementation of that
    method, if there is one.

    If 'Foo' does not declare a method 'doSomething()', then you'll get a
    compiler error. By declaring 'Foo a', you are committing 'a' to the
    contract provided by the type 'Foo'.

    > If this is a total misuse/misunderstanding of class hierarchies I'd
    > appreciate correction or pointers to suitable tutorials.


    Well, you could look at the standard tutorials on java.sun.com.

    Polymorphism is arguably the most fundamental concept of object-
    oriented programming, and you must master it to master Java. Thinking
    in terms of types helps keep things clear in one's mind.

    --
    Lew
    Lew, Feb 10, 2009
    #13
  14. On Tue, 10 Feb 2009 22:28:49 +0000, Stefan Ram wrote:

    > Martin Gregorie <> writes:
    >>>You possibly use the word »superclass« in another sense than the Java
    >>>Language Specification, Third Edition.

    >>Not intentionally.

    >
    >> MessageWindow - used by programs MASearch and MAUpdate
    >> | along with MessageWindowAction |
    >> MAModel (superclass) - contains no data or methods
    >> | |
    >> MASModel | - model used by the MASearch query program
    >> MAUModel - model used by the MAUpdate db maintenance prog

    >
    > I am not sure in which direction the superclasses are:
    >

    Sorry - I should have said.

    MessageWindow extends JFrame

    I know, I know - slapped wrist. It contains MAModel as a private
    attribute that's initialised by the constructor being passed a reference
    to the program's MAModel instance.

    MASModel extends MAModel
    MAUModel extends MAModel


    --
    martin@ | Martin Gregorie
    gregorie. | Essex, UK
    org |
    Martin Gregorie, Feb 11, 2009
    #14
  15. On Tue, 10 Feb 2009 15:20:45 -0800, Lew wrote:

    > This is the part I don't understand - it doesn't match any mental model
    > of inheritance that I have. On the face of it, your statement seems to
    > bespeak a misunderstanding of method overrides.
    >
    > It sounds like you are referring to "classes" when you need to be
    > talking about "types".
    >

    I've been (mis)using 'method' where you're referring to 'types' like this.

    public class MAModel {
    abstract void method1();
    abstract void method2();
    abstract void method3();
    ....
    }

    public class MASModel extends MAModel {
    public void method1() { ... }
    // no method 2 here
    public void method3() { code for the MASModel version ];
    .....
    }

    public class MAUModel extends MAModel {
    // no method 1 here
    public void method2() { ... }
    public void method3() { code for the different MAUModel version ];
    .....
    }

    public class MessageWindow {
    MAModel model;

    public MessageWindow(MAmodel model) { this.model = model; }

    public void setDisplayData() { model.method3(); }
    }

    The problem is that this generally won't compile because of complaints
    about method1() and method2() not having concrete representations. These
    errors vanish if the MAModel method1() and method2() abstract stubs are
    replaced with concrete dummy stubs, e.g.:

    public void method1() { System.err.printf("method3() not implemented"); }

    Once that's fixed it does what I'd intended.

    >> If this is a total misuse/misunderstanding of class hierarchies I'd
    >> appreciate correction or pointers to suitable tutorials.

    >

    It's probably a pretty bastardised, unpleasant structure. As I said, it
    sort of accreted as I hacked things about to allow me to reuse the
    MessageWindow and its action listener with two different models.

    > Polymorphism is arguably the most fundamental concept of object-
    > oriented programming, and you must master it to master Java. Thinking
    > in terms of types helps keep things clear in one's mind.
    >

    Sure. I think I managed to end up with an inverted version of it. I'll
    probably go with Tom's suggestion and flatten it into a single MAModel
    class (no subclasses) that's usable by both GUI programs.

    Looks like I'll need to do the same to the database access layer too -
    and for pretty much the same reasons.


    --
    martin@ | Martin Gregorie
    gregorie. | Essex, UK
    org |
    Martin Gregorie, Feb 11, 2009
    #15
  16. Martin Gregorie

    Lew Guest

    Martin Gregorie wrote:
    > public class MAModel {
    > abstract void method1();
    > abstract void method2();
    > abstract void method3();
    > ....
    > }
    >
    > public class MASModel extends MAModel {
    > public void method1() { ... }
    > // no method 2 here
    > public void method3() { code for the MASModel version ];
    > .....
    >
    > The problem is that this generally won't compile because of complaints
    > about method1() and method2() not having concrete representations. These
    > errors vanish if the MAModel method1() and method2() abstract stubs are
    > replaced with concrete dummy stubs, e.g.:


    When you declare a method 'abstract', you are promising that you will
    implement it in a subclass before you try to create an instance of the
    subclass. When you didn't implement 'method2()' in 'MASModel' you broke that
    promise.

    Why do you put 'method2()' in the supertype if you don't want to implement it
    in every subclass?

    --
    Lew
    Lew, Feb 11, 2009
    #16
  17. Lew wrote:
    > Martin Gregorie wrote:
    >> public class MAModel {
    >> abstract void method1();
    >> abstract void method2();
    >> abstract void method3();
    >> ....
    >> }
    >>
    >> public class MASModel extends MAModel {
    >> public void method1() { ... }
    >> // no method 2 here
    >> public void method3() { code for the MASModel version ];
    >> .....
    >>
    >> The problem is that this generally won't compile because of complaints
    >> about method1() and method2() not having concrete representations.
    >> These errors vanish if the MAModel method1() and method2() abstract
    >> stubs are replaced with concrete dummy stubs, e.g.:

    >
    > When you declare a method 'abstract', you are promising that you will
    > implement it in a subclass before you try to create an instance of the
    > subclass. When you didn't implement 'method2()' in 'MASModel' you broke
    > that promise.
    >
    > Why do you put 'method2()' in the supertype if you don't want to
    > implement it in every subclass?
    >



    I think this gets to the heart of half of the issues I see in Martin's
    question.

    In the app I mentioned before, my model superclass has abstract methods,
    it absolutely needs the subclasses to implement those - otherwise I'd
    have refactored the code as final methods of the superclass.

    I find this very helpful in Eclipse, as soon as I tell it I'm creating
    FooTableView as a subclass of AbstractTableView Eclipse populates
    FooTableView with stubs for all my abstract classes with TODO comments
    and I just fill in the blanks. I don't have to remember what methods to
    create. I expect NetBeans and other IDEs do the same. Therefore I never
    get the compilation problems that Martin reports - My subclasses
    inevitably override all the abstract methods of the superclass without
    me having to do anything - obviously it helps if I flesh them out :).

    Any methods that are optional in subclasses have concrete stubs in the
    superclass that, unless overridden, do nothing.

    For example I have a concrete method in the model superclass for
    checking referential integrity prior to deleting an object from a list.
    If this method isn't overridden, my superclass calls it's own method
    which says "OK" - I then rely on referential integrity constraints in
    the DBMS to throw an SQL exception which I catch and present to the user
    - the drawback being that SQL error messages are incomprehensible to the
    average user. If my subclass overrides this method it can provide a much
    friendlier message to the user - at the cost of duplicating the checks
    performed by the constraints in the DBMS. Obviously, read-only views
    don't need to override this method.

    I've *never* before struggled with program structure so much as I have
    when I started using Java. I still struggle. It's an OO hurdle, not just
    a Java hurdle but it's in Java that it's hit me. In the past I've
    refactored spaghetti Fortran and revelled in the resulting halving of
    LOC and utter transformation in clarity - this doesn't happen for me yet
    in Java.

    --
    RGB
    RedGrittyBrick, Feb 11, 2009
    #17
  18. RedGrittyBrick wrote:
    > Lew wrote:
    > > Martin Gregorie wrote:
    > >> public class MAModel {
    > >> abstract void method1();
    > >> abstract void method2();
    > >> abstract void method3();
    > >> ....
    > >> }

    [...]
    > > Why do you put 'method2()' in the supertype if you don't want to
    > > implement it in every subclass?

    >
    > I think this gets to the heart of half of the issues I see in
    > Martin's question.


    Interesting. The tutorial suggests, "If an abstract class contains only
    abstract method declarations, it should be declared as an interface
    instead." What I didn't know is that an abstract class may implement
    just some of the methods of an interface, deferring the implementation
    of any remaining methods to the concrete class. I can't recall an
    example, but the approach may suit Martin's need.

    <http://java.sun.com/docs/books/tutorial/java/IandI/abstract.html>

    [...]
    > I've *never* before struggled with program structure so much as I
    > have when I started using Java. I still struggle. It's an OO hurdle,
    > not just a Java hurdle but it's in Java that it's hit me. In the past
    > I've refactored spaghetti Fortran and revelled in the resulting
    > halving of LOC and utter transformation in clarity - this doesn't
    > happen for me yet in Java.


    Your examples have enlightened me. Surely this is similar to the effect
    of acquiring another language: knowing Latin made Spanish easier,
    learning Pascal improved my Fortran, studying Java clarified my object
    orientation in Ada, etc.

    --
    John B. Matthews
    trashgod at gmail dot com
    <http://sites.google.com/site/drjohnbmatthews>
    John B. Matthews, Feb 11, 2009
    #18
  19. On Wed, 11 Feb 2009 08:01:15 -0500, John B. Matthews wrote:

    > RedGrittyBrick wrote:
    >> Lew wrote:
    >> > Martin Gregorie wrote:
    >> >> public class MAModel {
    >> >> abstract void method1();
    >> >> abstract void method2();
    >> >> abstract void method3();
    >> >> ....
    >> >> }

    > [...]
    >> > Why do you put 'method2()' in the supertype if you don't want to
    >> > implement it in every subclass?

    >>
    >> I think this gets to the heart of half of the issues I see in Martin's
    >> question.

    >
    > Interesting. The tutorial suggests, "If an abstract class contains only
    > abstract method declarations, it should be declared as an interface
    > instead." What I didn't know is that an abstract class may implement
    > just some of the methods of an interface, deferring the implementation
    > of any remaining methods to the concrete class. I can't recall an
    > example, but the approach may suit Martin's need.
    >
    > <http://java.sun.com/docs/books/tutorial/java/IandI/abstract.html>
    >
    > [...]
    >> I've *never* before struggled with program structure so much as I have
    >> when I started using Java. I still struggle. It's an OO hurdle, not
    >> just a Java hurdle but it's in Java that it's hit me. In the past I've
    >> refactored spaghetti Fortran and revelled in the resulting halving of
    >> LOC and utter transformation in clarity - this doesn't happen for me
    >> yet in Java.

    >
    > Your examples have enlightened me. Surely this is similar to the effect
    > of acquiring another language: knowing Latin made Spanish easier,
    > learning Pascal improved my Fortran, studying Java clarified my object
    > orientation in Ada, etc.


    Thanks to all of you for your help.

    This thread has clarified my understanding a lot about the pitfalls of
    writing subclasses with fewer methods than their parent, aka declaring
    optional methods in a super-class. I'd echo RedGrittyBrick's comments
    about the OO learning process - that hat fits rather well.

    I've decided in this instance that I'll go with Tom's suggestion and
    condense the two GUI models into one non-subclassed model, adjusting the
    JDBC layer to match. Another good reason for picking this course of
    action is that I expect to pick a certain amount of cruft out of the
    model in the process.


    --
    martin@ | Martin Gregorie
    gregorie. | Essex, UK
    org |
    Martin Gregorie, Feb 11, 2009
    #19
  20. Martin Gregorie

    Tom Anderson Guest

    On Tue, 10 Feb 2009, Martin Gregorie wrote:

    > On Tue, 10 Feb 2009 20:08:42 +0000, Tom Anderson wrote:
    >
    >> On Tue, 10 Feb 2009, Martin Gregorie wrote:
    >>
    >>> I'm developing a database system that includes both command line and
    >>> GUI programs. As both GUI programs

    >>
    >> I have a definite preference for one model across the whole system. One
    >> model object per domain entity - the last you thing you want is multiple
    >> Inmate objects representing the same inmate.

    >
    > So, you'd prefer one model for the whole system? Interesting! I hadn't
    > considered that.


    One of the general rules of thumb (far from being an absolute law) of OO
    design is that you have domain objects, ie objects which model the
    conceptual entities in the problem domain, which resemble those conceptual
    entities as closely as possible. If the concept is that there's a list of
    addresses, then you want your program to have one list object ('a' being a
    singular article) and many address objects ('addresses' being plural).
    Those are the core of your program, and you then build up the behaviour
    and appearance of the system around those.

    That's the classical approach to OO design, anyway. It falls down if
    overextended.

    >> As for controllers - i tend to think one controller per UI assembly.
    >> Although if they're stateless, you can share them. But then, if they're
    >> stateless, they're small, so there's no harm in not sharing them.

    >
    > That's what I'm currently doing, though the lists, which are all
    > JTables, seem to self-adjust as items are changed or deleted without any
    > help from the controller.


    Yes, i think Swing has a kind of observer-observable thing going on.
    That's a traditional part of the MVC paradigm.

    > The controllers are very simple, possibly because the windows tend to
    > have a single method which refreshes all the displayed data in the
    > window. Is this a reasonable way to go?


    Absolutely.

    >>> I've implemented a separate Model class and database access class for
    >>> each program. These are subclasses of Model and database access super-
    >>> classes that were intended to contain just common operations such as db
    >>> open/close and error diagnostics. However, to make some window classes
    >>> usable in both GUI programs, its necessary to use super-class
    >>> references in them and this in turn has required virtually subclass
    >>> methods to have stubs in the super-class.

    >>
    >> I don't follow. You need the methods in the base class which are needed
    >> to support the windows common to the two apps - by definition, those are
    >> the the methods which are intrinsically common to the base model. Why
    >> are the other methods brought in? Are they called from the common
    >> methods, template-style?

    >
    > Again, my reply to Stefan contains what I hope is a better explanation.


    It's still not totally crystal clear, but if i've understood, i think
    you're misapplying inheritance. Posting some actual code would really
    help, if you don't mind sharing it. Don't post it here, upload it
    somewhere like this:

    http://codeviewer.org/upload

    And post a link.

    > I note, if I understand you correctly, that you'd sidestep this whole
    > issue by having a single model class to support all my programs and a
    > single database access class to provide a system-wide JDBC layer.


    No, no - was talking about having a single model *object* - a single
    instance - in any one program. But different programs will need to have
    different classes, to support different behaviour. UpdateApp will have one
    instance of UpdateModel, and SearchApp will have one instance of
    SearchModel.

    If you can refactor so there's no app-specific code in the model classes,
    ie it's all confined to code in the layer outside the model, so there's
    just one model class, that might be even better, but don't sweat that for
    now.

    Hmm. The more i think about it, the more i think a single class might be a
    good idea. But it would involve putting both search- and update-specific
    code in the model. Which isn't necessarily so bad - a well-rounded class
    supporting both read and write operations is a fairly common thing to find
    in a domain object layer. It really depends how complex the code you want
    to put in the model is.

    > As may be clear, I'm a long term C player and am trying to Java write
    > Java in a way that doesn't look too much like its been written by a
    > total Ctard. I think this system is a good learning tool since its not
    > huge, but still has enough complexity to smoke out non-trivial design
    > issues. So, feel free to fire away if you think my structures are
    > horrid.


    Will do!

    >> Or are you making all references to the model object references to the
    >> base type, even in the app-specific code?

    >
    > Yes, that's where I've ended up.


    Okay. Definitely wrong. I'm trying to think of a simple rule that i can
    tell you that says why this is wrong, but it's hard to explain. Basically,
    you have two rules interacting here:

    (1) Types of variables should be as abstract as possible, but no more
    abstract.

    (2) Types should only define methods that are meaningful for that type.

    Here, you've followed rule 1 to the detriment of rule 2. The trick is to
    find a way to follow both.

    > As always, things started off fairly clean with separate, independent
    > models both GUIs The CLI programs, of course, lack models, going directly
    > to the JDBC layer.


    "Of course"! There's no law against CLI programs having object models!
    Although if they exist purely to move data in and out of databases, a
    model may be an unnecessary complication.

    > Then I realized that one or two windows were so similar that writing two
    > program-specific versions was just stupid. Of course this forced me to
    > introduce a model super-class as a sort of umbrella for the two models.


    Perfect. This is how code is sculpted into a perfect form.

    >> If you have code like that, then you need doFooSpecificThing in
    >> BaseModel, as well as doGenericThing. But the soluion isn't to do that,
    >> it's to refactor FooApp:

    >
    > Would that be better than creating a system-wide model?


    Don't know. I'd have to try it.

    >> There's also a way to do it involving generics.

    >
    > I don't really understand generics and (so far) have scarcely used them.
    > I know, I should be attending to that.


    Don't worry about it for now. The idea i have in my head is what might be
    considered a fairly tricksy application of generics, so definitely not
    something to get into now.

    >> Is that anything like the situation you've got?

    >
    > Yes - my class structure fits your first example requiring concrete stubs.


    Right. Get your backspace key out.

    >> Although Design Patterns

    >
    > Is this by James W Cooper, David Geary or some other author?
    >
    >> and Refactoring are both pretty good.

    >
    > by Elliotte Rusty Harold?


    GOOD LORD MAN!

    Are you serious, or is my irony detector broken?

    These are the two most important books about the craft of
    objected-oriented software ever written:

    http://www.amazon.com/Design-Patterns-Object-Oriented-Addison-Wesley-Professional/dp/0201633612
    http://www.hillside.net/patterns/DPBook/DPBook.html

    http://www.amazon.co.uk/Refactoring-Improving-Design-Existing-Technology/dp/0201485672
    http://books.google.co.uk/books?hl=en&id=1MsETFPD3I0C

    tom

    --
    Annoying others means you are wise; it is when you annoy yourself that
    you are truly enlightened. -- The Bullet Proof Monk
    Tom Anderson, Feb 11, 2009
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. winglite
    Replies:
    1
    Views:
    422
    Natty Gur
    Nov 3, 2003
  2. rmn190
    Replies:
    2
    Views:
    2,355
    Arne Vajhøj
    Jan 10, 2008
  3. Miles

    MVC Questions

    Miles, May 28, 2008, in forum: Java
    Replies:
    4
    Views:
    1,006
    Arne Vajhøj
    May 28, 2008
  4. Paulo
    Replies:
    3
    Views:
    476
    Peter Bromberg [C# MVP]
    Dec 4, 2008
  5. Crazy Cat
    Replies:
    1
    Views:
    683
    schepp
    Sep 3, 2009
Loading...

Share This Page