Domain Objects and Interfaces
I have a question regarding using interfaces, in particular for domain objects, and visbility regarding bidirectional associations.
Let me explain the problem I am having using this example
interface INode {
INode getParent;
void addNode(INode node);
}
class Node implements INode {
private INode parent;
private List children;
public INode getParent() {
return parent;
}
private void setParent(INode node) {
parent = node;
}
public void addNode(INode node) {
children.add(node);
node.setParent(this); // compile error
}
}
With INode objects you can create a tree structure.
Because it is important to keep the child to parent relationships in sync the parent association is set during the addNode call. Unfortunately it does not compile, because the setParent method is not known to INode.
I however do not want the setParent method to be public, because it means that the setParent could be called from outside INode and damaging the structure.
Is it better to not use interfaces for domain objects at all?
And what do people do who use interfaces for domain objects? They are just careful not to call setParent from outside?
[1278 byte] By [
SmellyCata] at [2007-11-27 11:16:16]

# 1
> I have a question regarding using interfaces, in
> particular for domain objects, and visbility
> regarding bidirectional associations.
I don't usually use them that way.
Use an interface to separate method signatures from implementations.
If the implementation will never, ever change, why have an interface just for its own sake? Doesn't sound like it's buying you anything here.
> Is it better to not use interfaces for domain objects at all?
I wouldn't say never. But in this example it doesn't seem to make much sense.
> And what do people do who use interfaces for domain
> objects? They are just careful not to call setParent
> from outside?
"Careful"? Nope, the interface should define the appropriate methods, no more and no less. If a client has a reference that is the interface type, they CAN'T call that method without casting. If they have to cast, it defeats the purpose of having the interface in the first place.
%
# 2
> I don't usually use them that way.
What way are we exactly talking about and what way do you use them?
> > Is it better to not use interfaces for domain
> objects at all?
>
> I wouldn't say never. But in this example it doesn't
> seem to make much sense.
But isn't this true for all but the most simplest domain models?
I mean just having one bidirectional association somewhere makes it impossible for me to use interfaces now.
> > And what do people do who use interfaces for
> domain
> > objects? They are just careful not to call
> setParent
> > from outside?
>
> "Careful"? Nope, the interface should define the
> appropriate methods, no more and no less. If a
> client has a reference that is the interface type,
> they CAN'T call that method without casting. If they
> have to cast, it defeats the purpose of having the
> interface in the first place.
I'm a little bit confused by this, because on the one hand you seem to imply that it is possible to use interfaces, but on the other hand that it is not.
# 3
Here is a slightly more elaborate example using two classes, Topic and Forum.
In this case the setForum has been given package visibility, so that Forum has access to it. That's actually to open for me, but I could live with that.
However it does not compile because setForum is not known by IForum.
So my question still is if it is beneficial and/or possible to use interfaces for domain objects if you have a bidirectional association in your domain model, which to me seems to happen always for but the most simplest models.
interface ITopic {
IForum getForum()
void move(IForum forum);
}
interface IForum {
void addTopic(ITopic topic);
void removeTopic(ITopic topic);
}
class Topic implements ITopic {
private IForum forum;
public IForum getForum() {
return forum;
}
void setForum(IForum forum) {
this.forum = forum;
}
void move(IForum newForum) {
forum.removeTopic(this);
newForum.addTopic(this);
}
}
class Forum implements IForum {
private List topics;
public void addTopic(ITopic topic) {
topics.add(topic);
topic.setForum(this); // compile error
}
void removeTopic(ITopic topic) {
topics.remove(topic);
topic.setForum(this); // compile error
}
}
# 4
> > I don't usually use them that way.
>
> What way are we exactly talking about and what way do you use them?
DAOs and services are certainly based on interfaces. Anything that has changing behavior is a candidate for interfaces.
An Address class (street1, street2, city, state, zip) is unlikely to change. It wouldn't have an interface. Any class that's mostly a DTO with little or no behavior would not have an interface.
> > I wouldn't say never. But in this example it doesn't
> > seem to make much sense.
>
> But isn't this true for all but the most simplest
> domain models?
See above.
> I mean just having one bidirectional association
> somewhere makes it impossible for me to use
> interfaces now.
So what have you lost? Please explain to me what using an interface has bought you? Are you just doing it out of blind adherence to somebody's dictum that "Interfaces are good"?
I think the interface you've designed doesn't work because you haven't gotten close to the right abstraction. Are you trying to abstract a tree or bidirectional association? Maybe you really have two interfaces here.
There are lots of ways to implement a Tree: Binary, RedBlack, etc. All those have parent/child relationships. Do you think you could come up with a common interface that could hide different implementations? That would be a start.
> I'm a little bit confused by this, because on the one
> hand you seem to imply that it is possible to use
> interfaces, but on the other hand that it is not.
I'm implying no such thing. But yes, you do sound confused.
%
# 5
> > > I don't usually use them that way.
> >
> > What way are we exactly talking about and what way
> do you use them?
>
> DAOs and services are certainly based on interfaces.
> Anything that has changing behavior is a candidate
> for interfaces.
Yes I agree. And interfaces has been helpful in that area.
> So what have you lost? Please explain to me what
> using an interface has bought you? Are you just
> doing it out of blind adherence to somebody's dictum
> that "Interfaces are good"?
The only thing that I have lost is that interfaces are a nice way to start without having to think about the implementation.
Considering they have been helpful in other areas I tried to use them for the domain model too. At the start they helped, but then they worked against me.
Also I saw them being used in some examples (about domain model), so I just wondered how those people would deal with such issues. Maybe I am missing something, but it seems that I did not.
So your stand is that I simply should not use them in this case, like I thought so too.
Anyone have a different opinion?
# 6
> > So what have you lost? Please explain to me what
> > using an interface has bought you? Are you just
> > doing it out of blind adherence to somebody's
> dictum
> > that "Interfaces are good"?
>
> The only thing that I have lost is that interfaces
> are a nice way to start without having to think about
> the implementation.
I disagree with that. You have to think about how the implementation may or may not change to decide whether an interface is appropriate.
> Considering they have been helpful in other areas I
> tried to use them for the domain model too. At the
> start they helped, but then they worked against me.
> Also I saw them being used in some examples (about
> domain model), so I just wondered how those people
> would deal with such issues. Maybe I am missing
> something, but it seems that I did not.
I think you did. If the implementation doesn't change, and never will, there's no advantage to an interface.
> So your stand is that I simply should not use them in
> this case, like I thought so too.
Looks like you did think you should use them. Which is it?
%
# 7
> > The only thing that I have lost is that interfaces
> > are a nice way to start without having to think
> about
> > the implementation.
>
> I disagree with that. You have to think about how
> the implementation may or may not change to decide
> whether an interface is appropriate.
What has that to do with what I said?
> > Also I saw them being used in some examples (about
> > domain model), so I just wondered how those people
> > would deal with such issues. Maybe I am missing
> > something, but it seems that I did not.
>
> I think you did. If the implementation doesn't
> change, and never will, there's no advantage to an
> interface.
What does that have to do with my question?
I never said the implementation would not change.
> > So your stand is that I simply should not use them
> in
> > this case, like I thought so too.
>
> Looks like you did think you should use them. Which
> is it?
At first I thought they would be helpful. Then I did not see any way I could use them. And then I posted this topic.
# 8
> > > The only thing that I have lost is that
> interfaces
> > > are a nice way to start without having to think
> > about
> > > the implementation.
> >
> > I disagree with that. You have to think about how
> > the implementation may or may not change to decide
> > whether an interface is appropriate.
>
> What has that to do with what I said?
"...interfaces are a nice way to start without having to think about the implementation..." - I read this to say that you wanted to throw in an interface without thinking about implementation. I say that's incorrect, because deciding whether or not an interface is appropriate means you've put some thought into one or more possible implementations that share a common abstraction.
> What does that have to do with my question?
> I never said the implementation would not change.
I'm saying that if the implementation doesn't change, as it sometimes doesn't with domain objects, then there's no need for an interface.
Certainly a bidirectional parent/child relationship between two classes won't change, if that's a part of your model. So what benefit do you derive by abstraction that with an interface?
> At first I thought they would be helpful. Then I did
> not see any way I could use them. And then I posted this topic.
So what do you think now? Still confused?
%
# 9
What does it all matter anyway whether I think interfaces for the domain model are beneficial or not.
I can't use them anyway.
# 10
> What does it all matter anyway whether I think
> interfaces for the domain model are beneficial or
> not.
You're right, it doesn't matter.
> I can't use them anyway.
I guess not.
I'll ask again: What for? Please explain what you think they're buying you, and why you thought it was a good idea in the first place.
Or don't bother. Your choice.
%
# 11
Reasons I thought interfaces were a good idea:
- Easier to design the whole model
- Able to supply an alternative implementation for one of the interfaces
- Easier to test the application, by providing a mock implementation
- Easier to see an overview of the model, by looking at the interfaces (in code)
# 12
> Reasons I thought interfaces were a good idea:
> - Easier to design the whole model
Why? What about interfaces makes it easier?
> - Able to supply an alternative implementation for
> one of the interfaces
Yes, that's one good reason.
> - Easier to test the application, by providing a mock
> implementation
Another good reason.
> - Easier to see an overview of the model, by looking
> at the interfaces (in code)
Not sure I agree with this.
%
# 13
I understand your problem. I covered this several years ago on these forums. Nobody really had a sufficient reply. I think most did not grasp the issue.
My solution is to cast the object to the concrete type and call the node.setParent(this) method that way. I do not expose that method on the interface as how parents get set is an implementation detail to me.
The only issue is that you have to then ensure your library is homogeneous so you do not get the wrong type of INode object.
In this way, INode is the 'domain object' and the implementation of INode is an implementation of the domain object, but is not in and of itself the domain object.
# 14
>
> The only thing that I have lost is that interfaces
> are a nice way to start without having to think about
> the implementation.
That has nothing at all with whether one uses interfaces.
An interface is code.
If you are writing code then you are implementing it.
If you want to create a design then do the design.
# 15
> I understand your problem. I covered this several
> years ago on these forums. Nobody really had a
> sufficient reply. I think most did not grasp the
> issue.
Or you didn't do nearly as memorable job at explaining as you think you did.
%
# 16
> My solution is to cast the object to the concrete
> type and call the node.setParent(this) method that
> way. I do not expose that method on the interface as
> how parents get set is an implementation detail to
> me.
Casting is your grand solution? How novel.
%