MVC Couplings

I've been reviewing some of the GUI code I've developed over the past month. I didn't try to conform to any specific pattern, I just went with what looked best. Looking at the couplings and dependencies I've noticed several things:

1. The model has no knowledge of the view.

2. The view has no knowledge of the model.

3. The view is not coupled to the controller in any way.

4. The model is not coupled to the controller in any way.

5. The controller has knowledge of both the model and the view and is very tightly coupled to both. With the model it is tightly coupled to an interface and model implementations could change easily. With the view it is coupled to an interface and actual implementation could change.

As I said I didn't try to make it MVC, but is that how it ended up? Is the coupling and dependency how MVC normally works out? I'm a little concerned that I would have to change the controller if I made big changes to the view (needing to change the view's interfaces), but I'm wondering if trying to accomplish loose coupling between the controller and the view/model is a fool's errand.

[1157 byte] By [kablaira] at [2007-10-2 9:29:21]
# 1

I have not had a formal education either, but it sounds like your design meets my idea of MVC.

Personally, I have never understood the fuss about cleanly separating the controller and the view. You have to have something to hear the events that your Swing components generate, so if you want an agnostic controller you are going to have to define your own event paradigm and write an adapter that sits between the Swing and the controller. Considering that most controller logic is extremely simple it is a little like killing a fly with a bazooka.

Here is a heavily abbreviated example from a project I am working on.

public class ManageKanjiGUI {

private final ManageKanjiGUI.InnerListener theListener = new ManageKanjiGUI.InnerListener();

private final Engine theEngine; // this is the only piece of the model that the view/controller knows about

private final JFrame owner;

private final FileSelector theFileSelector; // another piece of the view/controller responsible for selecting files

private JButton importButton = new JButton("\u5165");

public static JPanel getInstancePanel(Engine theEngine, FileSelector theFileSelector, JFrame owner) {

ManageKanjiGUI theGUI = new ManageKanjiGUI(theEngine, theFileSelector, owner);

return theGUI.mainPanel;

}

private ManageKanjiGUI(Engine theEngine, FileSelector theFileSelector, JFrame owner) {

this.theEngine = theEngine;

this.theFileSelector = theFileSelector;

this.owner = owner;

importButton.setActionCommand("importKanji");

importButton.addActionListener(theListener);

}

private class InnerListener extends ActionSwitch { // ActionSwitch is a reflection switch which directs to a method with a name the same as the action command

public void importKanji() {

File selected = theFileSelector.selectFile(FileSelector.OPEN);

if (selected != null)

theEngine.importKanji(selected);

}

}

}

So the view and controller are not only tightly coupled, but they are even in the same class. It is pretty much how they do things in the tutorials, if you leave out the fancy reflection switch. I cannot really think of any reason not to do things this way.

Drake

Drake_Duna at 2007-7-16 23:35:54 > top of Java-index,Other Topics,Patterns & OO Design...
# 2

If your controller and view are so tightly coupled what's the point in having the controller? You might as well just couple the view to the model since at that point the controller doesn't seem to serve any purpose.

I believe the most important thing to accomplish is decoupling the model. The model must have no knowledge of the controller and certainly no dependency on it. That should be first and foremost so that the model doesn't have to change when a controller does, which implicitly includes changes to the view if the controller and view are coupled. When I talk about the model I'm talking about all of the business logic and basically everything not part of the GUI.

The next most important thing to accomplish is ensuring the controller is not tightly coupled to the model either. I think we can expect the model to change often in ways that shouldn't necessitate a change in the GUI so the controller shouldn't be coupled to the model's implementation. I don't see anything wrong with it using an API defined by interfaces for example. The interfaces need to be well thought out and something that can be extended upon in the future. Then the controller won't break if the model changes. If major new functionality is needed then you refactor the API and the controller. A user is never going to see an application with one version of the model and another version of the controller, so backwards compatibility shouldn't be an issue. At least in applications where you have that control I mean, there may be other situations that don't fit into my context where it would be an issue.

Keeping in mind that I would never give up a more important issue that I've mentioned to accomplish a less important issue, what's the next thing you would tackle? I'm very torn between whether or not it is more important for the view to not be dependent on the controller, or for the controller to not be dependent on the view.

My initial reaction is to say that the view should have no knowledge of the controller. The logic being that the controller will have some idea of how to handle user actions irrespective of which particular view happens to be in use at the moment. Let the view propogate up relevent events and have the controller respond. The controller isn't going to care about a mouse click, but it is going to care that the view has determined that a user has performed some action that indicates a search should occur. In non-trivial applications this seems to deteriorate very fast though. What happens when something like this fabled search function requires direct access to the GUI to achieve a desired result. For example, in one view the search window might need to be placed in one part of the window, in another view it might be placed in a completely different part. Sure, you can add some sort of "Rectangle getWindowPlacement()" to determine it, but then you find yourself being forced to add this everywhere. What if in one part of the view this search function isn't even possible, they have to implement a silly getWindowPlacement() method for nothing? What if you had a window with an image and a window with a form. When the user moves to different fields on the form different parts of the image are highlighted. Great, but the form doesn't know about the image. The form is one view, the image another. So the controller has to do it, but it doesn't know how to determine what field it's on or when it gets there. Suddenly you have to define an enumeration for every possible field. Results in a long line of if/else statements and just plain ugly code. Plus, if you for example wanted to scroll the image to be horizontally even with the field you'd be in even more trouble. The result is the view and controller are very much tightly coupled. Sure, the view still doesn't know anything about the controller, but it's ended up with a thousand methods that only have meaning to the controller so what did you achieve?

Perhaps then the view should be coupled to the controller. If the controller has no knowledge of the view, or if the controller's only coupling is to a simple API, then it doesn't need to get involved in the petty day to day affairs of views or their communication with each other. That should mean the controller can simply deal with translating to and from the model's API. It will have to convert whatever it can get from the model into something the view can understand. This seems okay at first, but I've noticed issues with it personally. For one thing, the controller has to provide this data in a way the view can access it. The problem I have with this is: what is it the view can access? Does it have to convert everything to Strings? How can the controller predict what the view might need? The only solution I see is to provide access to everything. In my case, that quickly results in a gigantic controller with far too many getXXX() and setXXX() methods. Plus everytime the model changes (such as the view changing the model) every view has to be notified of the change.

This is basically where I usually get stumped. I suppose I'm just not totally clear on the controller's role or how it can be implemented well without the issues I've run into.

kablaira at 2007-7-16 23:35:54 > top of Java-index,Other Topics,Patterns & OO Design...
# 3
I definitely want to continue this conversation but I am going on vacation for a couple of weeks, so keep it on your watch list if you would!Drake
Drake_Duna at 2007-7-16 23:35:54 > top of Java-index,Other Topics,Patterns & OO Design...
# 4

> I've been reviewing some of the GUI code I've

> developed over the past month. I didn't try to

> conform to any specific pattern, I just went with

> what looked best. Looking at the couplings and

> dependencies I've noticed several things:

>

> 1. The model has no knowledge of the view.

The model should only be dependent on the persistence strategy. This is possible to decouple, but usually not worth the effort.

> 2. The view has no knowledge of the model.

How did you manage that? A series of 'decoupled' transfer objects? IMO, this is overkill. A given view *is* dependent on a given model object (from this point forward when I say 'model object' it could also mean 'graph of model objects').

It should not be a design goal to make the view independent of the model. Think of the classic controller paradigm, "executes model functionality based on user request; dispatches model result to view". The view in nearly all cases will use model data. You can add levels of indirection via transfer objects (or serializing model data as XML or whatever), but it is still model data. Assuming the view is not static, it will be dependent on model data.

Note: the reverse is *not* true. The model should in no way be dependent on the view.

> 3. The view is not coupled to the controller in any

> way.

Difficult to achieve and, IMO, only valuable when you are supporting multiple view types. Again, think of the classic controller paradigm, "executes model functionality based on user request; dispatches model result to view". It is possible to decouple the dispatching to a given view. The Struts configuration file is an example of this.

However, it is extremely hard to separate the controller and the view when parsing a user request. Again, think of Struts. What tier is ActionForm in? Clearly, it is totally coupled to the underlying markup on the page (or JSTL). So, that puts it in the view category. However, it also validates and is used to pass request parameters to a given Action class. This is more of a controller responsibility.

So, even within ActionForm itself, you can see the line between view and controller is fuzzy. One can say with certainty that the controller is dependent on both the model and the view. The view should not be dependent on the controller, though again, it is dependent on the model, which in turn depends on nothing.

> 4. The model is not coupled to the controller in any

> way.

Good. The model is dependent on nothing. However, the controller is certainly dependent on the model. It first responsibility is to execute model functionality in response to a request. After receiving the result, dispatch that value(s) to a view. So, the controller is certainly dependent on the model. Again, you can add levels of indirection.

> 5. The controller has knowledge of both the model and

> the view and is very tightly coupled to both. With

> the model it is tightly coupled to an interface and

> model implementations could change easily. With the

> view it is coupled to an interface and actual

> implementation could change.

>

Whether it is an interface or a concrete class is a separate design decision. A good one, IMO, but not required by MVC per se.

> As I said I didn't try to make it MVC, but is that

> how it ended up? Is the coupling and dependency how

> MVC normally works out? I'm a little concerned that

> I would have to change the controller if I made big

> changes to the view (needing to change the view's

> interfaces), but I'm wondering if trying to

> accomplish loose coupling between the controller and

> the view/model is a fool's errand.

Just to recap, if I were to draw the tiers with dependency notation ala UML:

C -> M

C -> V

V -> M

- Saish

Saisha at 2007-7-16 23:35:54 > top of Java-index,Other Topics,Patterns & OO Design...
# 5

> The model should only be dependent on the persistence

> strategy. This is possible to decouple, but usually

> not worth the effort.

I'm not familiar with what a "persistence strategy" means. I'll look it up when I get some time later but feel free to elaborate if you have time. Until I understand what this is I don't know what to say.

> How did you manage that? A series of 'decoupled'

> transfer objects? IMO, this is overkill. A given

> view *is* dependent on a given model object (from

> this point forward when I say 'model object' it could

> also mean 'graph of model objects').

Once again I don't know what you mean by "decoupled transfer object" but if I had to make an inuitive guess I'd say yes. Currently it's what I would call 'tiered". At each tier the "model" is in essence the tier above it. At each tier the "view" is in essence the tiers below it.

> It should not be a design goal to make the view

> independent of the model. Think of the classic

> controller paradigm, "executes model functionality

> based on user request; dispatches model result to

> view". The view in nearly all cases will use model

> data. You can add levels of indirection via transfer

> objects (or serializing model data as XML or

> whatever), but it is still model data. Assuming the

> view is not static, it will be dependent on model

> data.

Unfortunately I'm not familiar with the classic controller paradigm. The model data is in essence "interpreted" by the controller from the model's exposed API to something the view would expect. In most cases the view expects a String of some sort. In other special cases it might expect a different object.

> Note: the reverse is *not* true. The model should

> in no way be dependent on the view.

So I'm at least partially right in my assertion that the most important thing to do is not make the model dependent on the view/controller.

> Difficult to achieve and, IMO, only valuable when you

> are supporting multiple view types. Again, think of

> the classic controller paradigm, "executes model

> functionality based on user request; dispatches model

> result to view". It is possible to decouple the

> dispatching to a given view. The Struts

> configuration file is an example of this.

I am supporting multiple view types. At least I think I am, definitions get sketchy. For example, when a user opens a file at the top most level is a view that is opened for that file, we actually call it a "Bundle" because a file is more or less a bundle of records (bills really). For each record, however, a completely different view may be needed. So as each record is parsed, this "file" view displays a view specific to that type of record which can display all relevent data for that record. A user could then just as easily open a second view that has to operate off that record as well and display it in a completely different way. Even how this more specific view operates migh be dependent on further data in record, displaying portions of the view only if the record is of certain subtype (what kind of whatever type of bill it is). It's very similar to what Eclipse does with Perspectives and Views, though I have no idea if the architecture is even remotely the same.

> <b>However, it is extremely hard to separate the

> controller and the view when parsing a user request.</b>

> Again, think of Struts. What tier is ActionForm in?

> ? Clearly, it is totally coupled to the underlying

> markup on the page (or JSTL). So, that puts it in

> the view category. However, it also validates and is

> used to pass request parameters to a given Action

> class. This is more of a controller responsibility.

This is where I get bogged down in confusion as to how to accomplish things.

> Good. The model is dependent on nothing. However,

> the controller is certainly dependent on the model.

> It first responsibility is to execute model

> l functionality in response to a request. After

> receiving the result, dispatch that value(s) to a

> view. So, the controller is certainly dependent on

> the model. Again, you can add levels of

> indirection.

Yes. I when I say the model is not coupled to the controller I do not necessarily mean the controller isn't very dependent on the model. I'm probably using "coupled" somewhat inaccurately.

> Whether it is an interface or a concrete class is a

> separate design decision. A good one, IMO, but not

> required by MVC per se.

Noted, but what do you think about it?

kablaira at 2007-7-16 23:35:54 > top of Java-index,Other Topics,Patterns & OO Design...
# 6

I'm not familiar with what a "persistence strategy" means. I'll look it up when I get some time later but feel free to elaborate if you have time. Until I understand what this is I don't know what to say.

Database, XML files, storage area network, you name it. Whatever stores and retrieves your data. You generally want to separate persistence logic from business (or more generally, model) logic. That allows a given model object to only concern itself with normal processing. Persistence is another matter. Regardless of your persistence strategy, there will be a mis-match between the best way to represent a model object in Java (encapsulation, inheritance, polymorphism, etc.) versus say a database (relational integrity, minimal data storage, query speed, etc.)

Once again I don't know what you mean by "decoupled transfer object" but if I had to make an inuitive guess I'd say yes. Currently it's what I would call 'tiered". At each tier the "model" is in essence the tier above it. At each tier the "view" is in essence the tiers below it.

I mis-read what you were stating earlier. Generally, when one tries to de-couple two tiers, you introduce an intermediate object called a Data Transfer Object or a Value Object. Now both tiers are dependent on the intermediary and not on the other tier. Another way to achieve this are the Facade and Strategy patterns. If looser coupling is desired across all tiers, consider the Command pattern.

Unfortunately I'm not familiar with the classic controller paradigm. The model data is in essence "interpreted" by the controller from the model's exposed API to something the view would expect. In most cases the view expects a String of some sort. In other special cases it might expect a different object.

Still true? Not sure if you were replying as you read the post.

So I'm at least partially right in my assertion that the most important thing to do is not make the model dependent on the view/controller.

Yes, yes, yes. (Did I say, yes?) If you take nothing away from this thread, remember that. Your model is what makes your system unique. It should not be coupled to a particular view (or hence controller).

I am supporting multiple view types. At least I think I am, definitions get sketchy. For example, when a user opens a file at the top most level is a view that is opened for that file, we actually call it a "Bundle" because a file is more or less a bundle of records (bills really). For each record, however, a completely different view may be needed. So as each record is parsed, this "file" view displays a view specific to that type of record which can display all relevent data for that record. A user could then just as easily open a second view that has to operate off that record as well and display it in a completely different way. Even how this more specific view operates migh be dependent on further data in record, displaying portions of the view only if the record is of certain subtype (what kind of whatever type of bill it is). It's very similar to what Eclipse does with Perspectives and Views, though I have no idea if the architecture is even remotely the same.

Hmm... when I think of 'supporting multiple view types', I think that the app may have, say a web interface and a Swing standalone client. If you are using the same general type of view (e.g., web, Swing, applet, etc.) then these Bundles and Files are different 'views'. Not necessarily different 'view types'.

It's hard to say without more specifics, but your controller would be responsible for determining which type of view to display. The controller would also be responsible for determining what model functionality to invoke for a given request. The normal flow is:

> Parse request and determine type

> Delegate request to model

> Receive model results

> Dispatch to appropriate view based on request type and/or model result

The controller 'seems' like it is doing a lot. But think of it another way. In a standard Swing app, my controllers are listeners for mouse or button or key events (or other system events). If say, a mouse click and a menu click invoke the same type of request, it would make sense to re-factor those listeners to use common code. If enough of your system started to have this type of common code, it might make sense to add an entire layer containing 'controller' code that listeners simply invoke.Another way to achieve this is the Observer-Observable pattern.

Yes. I when I say the model is not coupled to the controller I do not necessarily mean the controller isn't very dependent on the model. I'm probably using "coupled" somewhat inaccurately.

No, you were using it fine. I just wanted to add a direction to the notion of coupling, that of dependency.

Noted, but what do you think about it?

It's a core GoF precept to code to interfaces rather than implementations, so I totally approve of the idea. The only rub comes in terms of time. Since a view 'object' is usually written for a specific purpose, I do not bother with an interface. Same with a controller object. As soon as common functionality is encountered, I simply refactor. At that point, now I have multiple implementations, and I would consider 'upgrading' to an interface.

The above is NOT true, IMO, for service layer (high-level, public API's) or model layer (low-level, internal API's) objects. These should *always* have an interface and an implementation. The model and service tiers are where your OO design should shine. The persistence tier invariably acts as a storage and retrieval tool. The view and controller are coded for a specific use and generally are not reusable until you write an additional, like component.

So... if you are going to invest your time on good OO, concentrate on the service and model tiers. The remaining tiers can, of course, also have excellent OO design and dedicated efforts towards doing so. Just, in my experience, if you are going to take an OO shortcut, do it in those other tiers.

Hope that helps.

- Saish

Saisha at 2007-7-16 23:35:54 > top of Java-index,Other Topics,Patterns & OO Design...
# 7

> Database, XML files, storage area network, you name

> it. Whatever stores and retrieves your data. You

> generally want to separate persistence logic from

> business (or more generally, model) logic. That

> allows a given model object to only concern itself

> with normal processing. Persistence is another

> matter. Regardless of your persistence strategy,

> there will be a mis-match between the best way to

> represent a model object in Java (encapsulation,

> inheritance, polymorphism, etc.) versus say a

> database (relational integrity, minimal data storage,

> query speed, etc.)

Alright, I see what you mean. In my case persistance has at least three different possible implementations: local file, database, XML-RPC. It uses what I call an "Importer" and an "Exporter" to interact without having knowledge of exactly how it's stored. The implementation itself deals with that, obviously, but I guess the model is still very dependent on that Importer/Exporter API and the data structures it gets converted to.

> I mis-read what you were stating earlier. Generally,

> when one tries to de-couple two tiers, you introduce

> an intermediate object called a Data Transfer Object

> or a Value Object. Now both tiers are dependent on

> the intermediary and not on the other tier. Another

> way to achieve this are the Facade and Strategy

> patterns. If looser coupling is desired across all

> tiers, consider the Command pattern.

That sounds like what I'm doing.

> Still true? Not sure if you were replying as you

> read the post.

I would say I have some idea of what it is as you described it, but I have not gone and researched it for more information. I'm waiting on my GoF book to arrive. I read the Java Patterns version but I prefer the source.

> Yes, yes, yes. (Did I say, yes?) If you take

> nothing away from this thread, remember that. Your

> model is what makes your system unique. It should

> not be coupled to a particular view (or hence

> controller).

*nod*

> Hmm... when I think of 'supporting multiple view

> types', I think that the app may have, say a web

> interface and a Swing standalone client. If you are

> using the same general type of view (e.g., web,

> Swing, applet, etc.) then these Bundles and Files are

> different 'views'. Not necessarily different 'view

> types'.

Based upon that description no, I'm not.

> It's hard to say without more specifics, but your

> controller would be responsible for determining which

> type of view to display. The controller would also

> be responsible for determining what model

> functionality to invoke for a given request. The

> normal flow is:

>

> > Parse request and determine type

> > Delegate request to model

> > Receive model results

> > Dispatch to appropriate view based on request type

> and/or model result

>

> The controller 'seems' like it is doing a lot. But

> think of it another way. In a standard Swing app, my

> controllers are listeners for mouse or button or key

> events (or other system events). If say, a mouse

> click and a menu click invoke the same type of

> request, it would make sense to re-factor those

> listeners to use common code. If enough of your

> system started to have this type of common code, it

> might make sense to add an entire layer containing

> 'controller' code that listeners simply invoke.

> Another way to achieve this is the

> he Observer-Observable pattern.

I used Observer at one point but it became somewhat unmanageable. Of course, that was before I refactored and began this "tiered" approach. The old architecture's initial design dated back to two weeks after I first started with Java which is the first OO language I've coded in extensively.

> No, you were using it fine. I just wanted to add a

> direction to the notion of coupling, that of

> dependency.

>

> It's a core GoF precept to code to interfaces rather

> than implementations, so I totally approve of the

> idea. The only rub comes in terms of time. Since a

> view 'object' is usually written for a specific

> purpose, I do not bother with an interface. Same

> with a controller object. As soon as common

> functionality is encountered, I simply refactor. At

> that point, now I have multiple implementations, and

> I would consider 'upgrading' to an interface.

>

> The above is NOT true, IMO, for service layer

> (high-level, public API's) or model layer (low-level,

> internal API's) objects. These should *always* have

> an interface and an implementation. The model and

> service tiers are where your OO design should shine.

> The persistence tier invariably acts as a storage

> e and retrieval tool. The view and controller are

> coded for a specific use and generally are not

> reusable until you write an additional, like

> component.

>

> So... if you are going to invest your time on good

> OO, concentrate on the service and model tiers. The

> remaining tiers can, of course, also have excellent

> OO design and dedicated efforts towards doing so.

> Just, in my experience, if you are going to take an

> n OO shortcut, do it in those other tiers.

>

> Hope that helps.

>

> - Saish

Yeah, I've had to refactor a LOT of code that was written by another developer here. He's very good, but most of the code and design dates back to when he first started with Java as well and he hadn't done anything OO at that time either, rather he did mostly COBOL. The biggest problem has been an an inverse approach to concrete classes and interfaces. What I mean by this is the heirarchies and APIs are made up of high level classes and everything is a subclass. Then interfaces are used here and there for things like exporters.

This has led to an absolute inheritance nightmare, which is no surprise. I had to refactor everything to build the heirarchy on interfaces rather than concrete classes. Then I converted his to be a specific implementation of that. There's at least three other areas where I really need to do this too, but I haven't had the time unfortunately. I think those API defects are part of what's led to the GUI being so difficult at times. Plus Swing is kind of hard to work with as well due to it's own inheritance.

I know what you mean with the extra work. It's not just that either. Defining interfaces willy nilly can be a bad thing when that interface needs to change and all the implementations have to change too or they won't even compile. That being said, whenever I have any kind of situation where the behavior is not unique to a specific implementation you're going to see that implementation named something else and an interface in it's place. Sometimes DefaultInterface, sometimes something more descriptive.

kablaira at 2007-7-16 23:35:54 > top of Java-index,Other Topics,Patterns & OO Design...
# 8

Alright, I see what you mean. In my case persistance has at least three different possible implementations: local file, database, XML-RPC. It uses what I call an "Importer" and an "Exporter" to interact without having knowledge of exactly how it's stored. The implementation itself deals with that, obviously, but I guess the model is still very dependent on that Importer/Exporter API and the data structures it gets converted to.

Model is not monolithic. Within the model 'tier', one could have a service layer, model layer, persistence layer and/or integration layer. Now, we have only talked about the model and persistence layers (I am using the term 'layer' just to differentiate that from a proper MVC 'tier').

A service layer is generally used to abstract away implementation details to outside systems. For example, I might involve 10-12 model objects (including persistence data access objects) in a given request. However, if someone is invoking this remotely from another machine, I would probably want only one call to occur, due to the latency in remote requests. Thus, my 'service' API will have coarse-grained methods (high-level API), whereas the actual model will have fine-grained methods (low-level API).

Okay, the above was interesting, but it had nothing to do with my problem. Fair enough. What you might need is an 'integration' layer. These are to mesh your idealized, object-oriented model classes with legacy or external API's that you must use (think of it as you are now on the calling side of a service layer). You can either refactor the existing code, or create integration classes which would basically act as adapters between the new and improved model classes and the legacy classes that are too difficult or time consuming to refactor (or in most cases, you do not have access to the source yourself anyway).

So, I would recommend either refactoring the 'importer' and 'exporter' code, or write integration layer adapters between the model you actually want in the system and the legacy classes you are forced to use.

BTW, if XML-RPC a persistence scheme? I always think of it as a remoting protocol.

Yeah, I've had to refactor a LOT of code that was written by another developer here. He's very good, but most of the code and design dates back to when he first started with Java as well and he hadn't done anything OO at that time either, rather he did mostly COBOL. The biggest problem has been an an inverse approach to concrete classes and interfaces. What I mean by this is the heirarchies and APIs are made up of high level classes and everything is a subclass. Then interfaces are used here and there for things like exporters.

This has led to an absolute inheritance nightmare, which is no surprise. I had to refactor everything to build the heirarchy on interfaces rather than concrete classes. Then I converted his to be a specific implementation of that. There's at least three other areas where I really need to do this too, but I haven't had the time unfortunately. I think those API defects are part of what's led to the GUI being so difficult at times. Plus Swing is kind of hard to work with as well due to it's own inheritance.

I know what you mean with the extra work. It's not just that either. Defining interfaces willy nilly can be a bad thing when that interface needs to change and all the implementations have to change too or they won't even compile. That being said, whenever I have any kind of situation where the behavior is not unique to a specific implementation you're going to see that implementation named something else and an interface in it's place. Sometimes DefaultInterface, sometimes something more descriptive.

Concrete implementation hierarchies more than 2-3 levels deep (and three is pushing it, IMO) is a sign of bad design. The usual motivation is to 'place common code in an ancestor'. This is valid for maybe 1-2 ancestors. But anything more and it becomes *very* difficult to really see what is going on. It also makes modifying anything within the hierarchy require analysis on the impact of the rest of the hierarchy. So, in short, bad idea.

The solution is to always code to interfaces wherever possible. I will use one abstract ancestor if, for example, I want every sub-class to follow a cetrain workflow or provide callback methods or events. However, even so, I still have an interface in case at some later point there is another type of workflow or different callback model. Subclasses then only have to implement what makes them unique. Many times, I do not even bother with the abstract ancestor. It is trivial to put common code in a helper class and have implementations simply delegate their call to the helper. Complex algorithms or rule evaluations are excellent candidates for this.

You really lost me on DefaultInterface. Is it a marker interface? The abstract ancestor of all sub-interfaces? The name itself confuses me. What would be offered to an implementor of, say, any arbitrary class that would be applicable to a 'default' interface?

- Saish

Saisha at 2007-7-16 23:35:54 > top of Java-index,Other Topics,Patterns & OO Design...
# 9

> Model is not monolithic. Within the model 'tier',

> one could have a service layer, model layer,

> persistence layer and/or integration layer. Now, we

> have only talked about the model and persistence

> layers (I am using the term 'layer' just to

> differentiate that from a proper MVC 'tier').

>

> A service layer is generally used to abstract away

> implementation details to outside systems. For

> example, I might involve 10-12 model objects

> (including persistence data access objects) in a

> given request. However, if someone is invoking this

> remotely from another machine, I would probably want

> only one call to occur, due to the latency in remote

> requests. Thus, my 'service' API will have

> coarse-grained methods (high-level API), whereas the

> actual model will have fine-grained methods

> (low-level API).

>

> Okay, the above was interesting, but it had nothing

> to do with my problem. Fair enough. What you might

> need is an 'integration' layer. These are to mesh

> your idealized, object-oriented model classes with

> legacy or external API's that you must use (think of

> it as you are now on the calling side of a service

> layer). You can either refactor the existing code,

> or create integration classes which would basically

> act as adapters between the new and improved model

> classes and the legacy classes that are too difficult

> or time consuming to refactor (or in most cases, you

> do not have access to the source yourself anyway).

>

> So, I would recommend either refactoring the

> 'importer' and 'exporter' code, or write integration

> layer adapters between the model you actually want in

> the system and the legacy classes you are forced to

> use.

>

> BTW, if XML-RPC a persistence scheme? I always think

> of it as a remoting protocol.

I was just saying that's one of the ways I have to get the data. Get it from a database, from a local file, from an XML-RPC server (which may get it from God knows where), etc. I really hate XML-RPC to be honest, but it's out of my hands.

> Concrete implementation hierarchies more than 2-3

> levels deep (and three is pushing it, IMO) is a sign

> of bad design. The usual motivation is to 'place

> common code in an ancestor'. This is valid for maybe

> 1-2 ancestors. But anything more and it becomes

> *very* difficult to really see what is going on. It

> also makes modifying anything within the hierarchy

> require analysis on the impact of the rest of the

> hierarchy. So, in short, bad idea.

The developer in question has some heirarchies that goes as much as six or seven levels deep. The motivation was clearly to put common code in a common place, but it would have been had he used interfaces and composition instead. Achieve the same benefits without the drawbacks and only trivial amounts of extra typing, most of which can be copy and paste anyway.

> The solution is to always code to interfaces wherever

> possible. I will use one abstract ancestor if, for

> example, I want every sub-class to follow a cetrain

> workflow or provide callback methods or events.

> However, even so, I still have an interface in case

> e at some later point there is another type of

> workflow or different callback model. Subclasses

> then only have to implement what makes them unique.

> Many times, I do not even bother with the abstract

> t ancestor. It is trivial to put common code in a

> helper class and have implementations simply delegate

> their call to the helper. Complex algorithms or rule

> evaluations are excellent candidates for this.

>

> You really lost me on DefaultInterface. Is it a

> marker interface? The abstract ancestor of all

> sub-interfaces? The name itself confuses me. What

> would be offered to an implementor of, say, any

> arbitrary class that would be applicable to a

> 'default' interface?

>

> - Saish

No. What I was talking about is it's not uncommon to see a Foo interface and an associated DefaultFoo implementation. It usually happens when I see that a particular behavior or responsibility can be implemented in any number of ways and should be an interface, but have to provide an implementation and find nothing distinct about it to use as a name. So I just juse Default[Interface Name]. Other cases there's something distinctive about it, for example a ResultSet that uses an array is named an ArrayResultSet. An ImageRenderer that uses AWT is named ImageRendererAWT and one that uses JAI is named ImageRendererJAI. The default implementation of ServiceTable is just DefaultServiceTable because it's just the default implementation I created with nothing distinct about it. At least nothing significant enough to be in the name that would indicate some crucial difference between it and others.

kablaira at 2007-7-16 23:35:54 > top of Java-index,Other Topics,Patterns & OO Design...
# 10
I've seen the 'interface to default implementation' naming convention vary widely. Some examples:class Foo implements IFooclass FooImpl implements Fooclass DefaultFoo implements Fooclass OracleFoo implements Foo // example of vendor-specific- Saish
Saisha at 2007-7-16 23:35:54 > top of Java-index,Other Topics,Patterns & OO Design...
# 11

I have refactored the libraries in question and they're now 2-3 levels deep.

I see what you mean by the view being dependent on the model. For example, in the model a birthdate field may be stored as a java.util.Date. In order for the view to know how to display this in a meaningful way it must be dependent on the model and have knowledge of how it is stored. I felt that having the view dependent on the controller was a bad idea because I didn't want to be able to reuse the view even if the controller changed. To that end I made a heirarchy of interfaces to wrap the GUI components so that the values could be set and retrieved simply as a String.

If the view is dependent on the model then why is a controller needed? Can the view not directly store and retrieve the data? I keep thinking of the "classic controller paradigm" and I'm not seeing what the point is if the view is dependent on the model to begin with.

kablaira at 2007-7-16 23:35:54 > top of Java-index,Other Topics,Patterns & OO Design...
# 12
That should read "because I wanted to be able to reuse the view even if the controller changed."
kablaira at 2007-7-16 23:35:54 > top of Java-index,Other Topics,Patterns & OO Design...