Coupling in OOP design?

H

howa

Consider the simplfied code below, do you think the design is good, or
bad?




class Person {

...

setMother(Person p) {
p.setSon(this);
this.mother = p;
}

...
}


any suggestions on improving the design?
 
A

andrewmcdonagh

Consider the simplfied code below, do you think the design is good, or
bad?

class Person {

...

setMother(Person p) {
p.setSon(this);
this.mother = p;
}

...

}

any suggestions on improving the design?

Nothing wrong with this.

Its not 'coupling', as there is only one class 'Person' that
references (given the code above) other 'instances' of the same class.

Its a data (runtime) relationship.

hth

Andrew
 
L

Lew

andrewmcdonagh said:
Nothing wrong with this.

Its not 'coupling', as there is only one class 'Person' that
references (given the code above) other 'instances' of the same class.

Its a data (runtime) relationship.

OTOH there are many ways to model the relationahips implied in the example.
Not shown is whether the "son" attribute also handles "[step]daughter", or
"mother" encompasses "guardian/[step]father" as well.

Modeling every kind of relationship as an attribute in Person is valid but
potentially unwieldy. What if you decide to model aunts later? Cousins? At
least you have incest covered - if a girl marries her son and becomes her own
mother you can model it.

Other approaches include modeling the relationship as a composed object, or
member of a Collection of composed objects:

class Person
{
Collection<Relationship> relationships;
....
}

where Relationship has attributes of a Relation Enum and a target Person (or
tuple of Persons).

There are more ways to skin that cat as well.
 
A

andrewmcdonagh

Nothing wrong with this.
Its not 'coupling', as there is only one class 'Person' that
references (given the code above) other 'instances' of the same class.
Its a data (runtime) relationship.

OTOH there are many ways to model the relationahips implied in the example.
Not shown is whether the "son" attribute also handles "[step]daughter", or
"mother" encompasses "guardian/[step]father" as well.

Modeling every kind of relationship as an attribute in Person is valid but
potentially unwieldy. What if you decide to model aunts later? Cousins? At
least you have incest covered - if a girl marries her son and becomes her own
mother you can model it.

Other approaches include modeling the relationship as a composed object, or
member of a Collection of composed objects:

class Person
{
Collection<Relationship> relationships;
...

}

where Relationship has attributes of a Relation Enum and a target Person (or
tuple of Persons).

There are more ways to skin that cat as well.

Sure we 'can' do this...but the OP wanted to know if there was
anything intrinsically wrong with what they have, and given that its a
snippet of code there's little point over analysing it.

Andrew
PS: Besides, your enum Relationship is is a static state, which won't
take care of the dynamic happenings of real life. E.g. Mum becoming
Stepmum of her new husband's children, Step-sister becoming
Wife,etc. ;-)
 
D

Daniel Pitts

OTOH there are many ways to model the relationahips implied in the example.
Not shown is whether the "son" attribute also handles "[step]daughter", or
"mother" encompasses "guardian/[step]father" as well.
Modeling every kind of relationship as an attribute in Person is valid but
potentially unwieldy. What if you decide to model aunts later? Cousins? At
least you have incest covered - if a girl marries her son and becomes her own
mother you can model it.
Other approaches include modeling the relationship as a composed object, or
member of a Collection of composed objects:
class Person
{
Collection<Relationship> relationships;
...

where Relationship has attributes of a Relation Enum and a target Person (or
tuple of Persons).
There are more ways to skin that cat as well.

Sure we 'can' do this...but the OP wanted to know if there was
anything intrinsically wrong with what they have, and given that its a
snippet of code there's little point over analysing it.

Andrew
PS: Besides, your enum Relationship is is a static state, which won't
take care of the dynamic happenings of real life. E.g. Mum becoming
Stepmum of her new husband's children, Step-sister becoming
Wife,etc. ;-)

Alternatively, you could say

Map<Person, List<Relation>> relationships;

At this point, we're talking about modeling the person and their
relationships as a Graph, and it might make sense to consider other
data model approaches.

Perhaps instead of the above map, we have:
final class Relation {
/* enum RelationType is defined somewhere else.
It defines the reciprocal as well:
RelationType.PARENT.reciprocal() == RelationType.CHILD;
Note: we leave gender out of the relationship type for many
reasons.
*/
private RelationType type;
private final Person person;
private Person relative;

public Relation(RelationType type, Person relative, Person person)
{
/* initialize here */
}

/* snip other constructors/accessors */


Relation reciprocal() {
return new Relation(type.reciprocal(), person, relative);
}
}

class Person {
final Collection<Relation> relationships =
new ArrayList<Relation>();
}


What we've ended up with here is a specific class of a Node (person)
and Edge (Relation).

So, my point is that there are many ways to model this. It all
depends on what you need from your model. A good engineer will likely
start with the easiest/simplest approach (such as the OP solution),
and refactor into the other models as they become appropriate for the
project.
 
O

Oliver Wong

howa said:
Consider the simplfied code below, do you think the design is good, or
bad?




class Person {

...

setMother(Person p) {
p.setSon(this);
this.mother = p;
}

...
}


any suggestions on improving the design?

I'm guessing (since you don't explicitly state it) is that your
concern might have something to do with the storing of relationships in
two locations (the son having a link to the mother, and the mother having
a link to the son), and these may go out of sync.

I recommend you read up on Model Driven Architecture (MDA). Eclipse
has a framework, EMF, which allows you to define models (either as XSD
files, or as Java code with annotations). Using EMF, you can quickly
define the models, and EMF will generate all the code for you. In
particular, you could say that there is a "Person" class of model objects,
and it can have a relationship called "mother" with another instance of
"Person". You can also define a "son" relationship, and you can define
that the "son" relationship is the "inverse" of the "mother" relationship,
so that if P1 is the mother of P2, and you call P2.setMother(null), the
EMF generated code will know to automatically remove the son relationship
from P1 to P2.

If your program is mostly dealing with manipulating model objects,
then it may be a good candidate for MDA and EMF.

- Oliver
 
T

Tom Hawtin

Daniel said:
Map<Person, List<Relation>> relationships;

List? Wouldn't Set be more appropriate? Why do people go out of their
way to use Lists instead of having Sets.

Tom Hawtin
 
T

Tom Hawtin

Daniel said:
Map<Person, List<Relation>> relationships;

List? Wouldn't Set be more appropriate? Why do people go out of their
way to use Lists instead of having Sets.

Tom Hawtin
 
P

Patricia Shanahan

Tom said:
List? Wouldn't Set be more appropriate? Why do people go out of their
way to use Lists instead of having Sets.

Often, I think it is because a List can be used as a form of bag, like a
set but allowing multiple instances of the same value.

Patricia
 
C

chrisdcheng

You make every kind of relationship as an attribute, when we got a
large family or we need to record many generations of someone, we run
out of gas. Why not consider using the Design Patterns. Think about
the Iteration and Composite Pattern.
 
?

=?ISO-8859-1?Q?Arne_Vajh=F8j?=

Tom said:
List? Wouldn't Set be more appropriate? Why do people go out of their
way to use Lists instead of having Sets.

(Hash)Map and (Array)List is in any Java beginner book, so everybody
knows them.

Guess what get chosen.

Arne
 
D

Daniel Pitts

(Hash)Map and (Array)List is in any Java beginner book, so everybody
knows them.

Guess what get chosen.

Arne

Actually, I generally choose them when I don't care about uniqueness
of entries.
 
?

=?ISO-8859-1?Q?Arne_Vajh=F8j?=

Daniel said:
Actually, I generally choose them when I don't care about uniqueness
of entries.

There are cases where they are the correct choice.

I was just trying to explain why the sometimes get chosen even
when they are not.

Arne
 

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

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,901
Latest member
Noble71S45

Latest Threads

Top