MVC design questions

M

Martin Gregorie

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
 
S

Stefan Ram

Martin Gregorie said:
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.
 
R

RedGrittyBrick

Martin said:
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%).
 
M

Martin Gregorie

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.
 
S

Stefan Ram

Martin Gregorie said:
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.
 
M

Martin Gregorie

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.
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.
 
L

Lew

Martin said:
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.
 
T

Tom Anderson

[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.]

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
 
M

Martin Gregorie

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.
 
M

Martin Gregorie

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.
 
S

Stefan Ram

Martin Gregorie said:
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.
 
M

Martin Gregorie

[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.
'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.
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 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?
 
L

Lew

Martin said:
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.
 
M

Martin Gregorie

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
 
M

Martin Gregorie

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.
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.
 
L

Lew

Martin said:
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?
 
R

RedGrittyBrick

Lew said:
Martin said:
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.
 
J

John B. Matthews

RedGrittyBrick said:
Lew said:
Martin said:
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.
 
M

Martin Gregorie

RedGrittyBrick said:
Lew said:
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.
 
T

Tom Anderson

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.
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.


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!
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.
Would that be better than creating a system-wide model?

Don't know. I'd have to try it.
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.
Yes - my class structure fits your first example requiring concrete stubs.

Right. Get your backspace key out.
Is this by James W Cooper, David Geary or some other author?


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
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,014
Latest member
BiancaFix3

Latest Threads

Top