nes1983
nes1983

Reputation: 15756

Proper OO modelling of correspondences

Something keeps showing up in my programming, and it is that two things are the same from some viewpoint, but different from another. Like, imagine you build a graph of rail stations, connected by trains, then the classes Vertex and RailStation are sometimes the same, other times not.

So, imagine I have a graph that very much represents rail stations and trains. Then I hand this graph to another object, which deletes some vertices, and then I want the corresponding rail stations to be gone.

I don't want to make rail stations "properties" of vertices, they're not. Also, the problem is symmetrical: If I erase a railstation, I want the corresponding vertex to be gone. What is the proper OO way to model or correspondences. I'm willing to go a few extra miles by writing some support methods or classes, if in the end the overall usage is simple and easy.

I'm currently using the Smalltalk programming language, but the question isn't really smalltalk-specific, I think. I just mention it because in Smalltalk, you can do cool tricks like examining the call stack, which might be helpful in this context.

Update: Well, RailStations aren't Vertices! Are they?

Ok, let us consider real code, as demanded in the answers. Let me model a person with children. That's the easiest thing, right? Children should also know their parents, so we have like a doubly linked tree. To make disbanding parents from children easier, I model the link between parent and child as a Relationship, with properties parent and child.

So, I could implement parent>>removeChild: perhaps like this

removeChild: aChild
    (parent relationshipWith: aChild) disband.

So, a parent has a collection of relationships, not of children. But each relationship corresponds to a child. Now I want to do things like this:

parent children removeAllSuchThat: [:e | e age < 12]

which should remove the relationship and the child.

Here, relationships and children correspond in some sense. So, what do I do now? Don't get me wrong, I'm fully aware that I could solve the problem without introducing Relationship classes. But indeed, parents and children actually do share a relationship, so why not model that and use it to help disbanding double links less imperatively?

Upvotes: 3

Views: 217

Answers (5)

akuhn
akuhn

Reputation: 27793

Take a look at Fame, see http://www.squeaksource.com/Fame.html

We use a specialized subclass of Collection that updates the opposite end when you add or remove elements. Also, you can annotate your classes with pragmas to annotate relations. These pragmas are used by the Fame framework to do all kind of nice stuff.

Upvotes: 1

Federico Zancan
Federico Zancan

Reputation: 4884

Having a Relationship object is a good idea.

I think the appropriate question here is "which use should be made of it?".

Probably Parent and Child classes are extending the same Person superclass, so they'll have some attributes in common, age for example.

In my idea, I can see the following: Parent and Child objects have to know each other, so both classes have to keep a link to the same Relationship. The Relationship object keeps a one-to-many relation between a single parent and a certain number of children, and it'll keep a reference to each Person object.

This way you can implement the whole disbanding logic within the Relationshp object, more or less sophisticated as you wish. You can query the Relationship object to know which members of the family match your requirements to do something. You can make the relationship to disband (and destroy) safely, as it will know all members and would ask them to break the reference and then it would be ready to destroy, or ask to some member to leave the family, keeping the Relationship object alive.

But that's not all. Relationship should be really a superclass, extended by HierarchicalRelationship and PeerRelationship (or FriendRelationship).

This specialization lets you have Parent(s) and Child(ren) to link between other hierarchies in a completely traversal way.

The true concept behind this is that your Relationship objects are the key to query and organize the whole bunch of Person objects (or Vertex objects) in a scalable and structured way, so the whole data domain you end up with is usable in any sense you like, whether you want to disband groups or walk a certain path (or railroad) between them.

Sorry for the huge amount of metaphores.

Upvotes: 1

Dave Sherohman
Dave Sherohman

Reputation: 46187

From your description of the problem, you have a one-to-one correspondence of stations to vertices and deleting a station should automatically delete the corresponding vertex (and vice-versa). You also mentioned building "a graph of rail stations, connected by trains", by which you apparently mean a graph in which stations are vertices and trains are edges.

So, in what way is a station not a vertex? If the station does not exist except as a vertex, and if a vertex does not exist except as a station, then what benefit do you see in maintaining them as two distinct-but-linked entities?

As I understand your situation, station-isa-vertex and inheritance is the way to model that.

Upvotes: 2

anon
anon

Reputation:

In your problem domain, aren't stations a kind of vertex? In which case, why not derive Station from Vertex?

Notice the use of the phrase "in your problem domain". Your problem appears to be about the use as railway stations appearing in a graph. So yes, in that domain, stations are vertexes. If it was a different problem domain, say a database on railway station architecture, they may well not be. Most modern languages support some idea of namespaces to allow you to have different kinds of entity with the same names in different domains.

Regarding your parent/child problem, once again you are being too general. If I were modelling mathematical expressions and sub expressions, if I remove a parent I would want to remove and delete/free all subexpressions. OTOH, ff I were modelling legal responsibility relationships in the UK population, then when a responsibility isis dissolved (say because of a divorce), I only want to remove the relationship, and NOT delete/free the child, which has its own independent existence.

Upvotes: 3

Matthew Flaschen
Matthew Flaschen

Reputation: 284796

It seems like you just want RailStation to inherit from Vertex (is-a relationship). See this smalltalk tutorial on inheritance. That way, if you have a graph of RailStations, an object used to dealing (generically) with graphs of Vertexes would handle things right naturally.

If this approach won't work, be more specific (preferably with real code).

Upvotes: 2

Related Questions