Win a copy of Testing JavaScript Applications this week in the HTML Pages with CSS and JavaScript forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Bear Bibeault
  • Ron McLeod
  • Jeanne Boyarsky
  • Paul Clapham
Sheriffs:
  • Tim Cooke
  • Liutauras Vilda
  • Junilu Lacar
Saloon Keepers:
  • Tim Moores
  • Stephan van Hulst
  • Tim Holloway
  • fred rosenberger
  • salvin francis
Bartenders:
  • Piet Souris
  • Frits Walraven
  • Carey Brown

Instance variable or inheritance?

 
Bartender
Posts: 10777
71
Hibernate Eclipse IDE Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Junilu Lacar wrote:Parent is a role, as is son, brother, sister, cousin, etc.
One person can have multiple roles depending on the context, just as you are half-brother, son, and stepson to different people.


OK, so that suggests to me that it's a method (or possibly an enum), but it doesn't explain how I would model it.

With databases - or rather, RDBs - I know exactly how I'd do it, but I'm still mulling over the problem when it comes to objects.

Perhaps you could show us what a Role class (or interface, or method) would look like?

@Sangel: BTW, I've given you a cow for sparking this interesting discussion.

Winston
 
Rancher
Posts: 4625
47
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
From what I can remember of how these things tend to be structured, most data structures for genealogy use events rather than direct relationships.
So you have a Person, which is the basic data (usually just name, gender, that sort of thing). Their status relative to other people (and some of their own data) is handled by events, including things like 'birth', 'death', 'marriage', 'divorce', 'adoption'.

IIRC (and this is a bit hazy) a relationship then is defined by these events.
Who are your parents? Look up your birth event and see who's tagged in there.
Are you alive? See if there's a death event...though I think there might be a 'probably dead' flag on a person, not sure.

Just throwing that out there to give an idea of how some of these things have been modelled.
 
Winston Gutkowski
Bartender
Posts: 10777
71
Hibernate Eclipse IDE Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Dave Tolls wrote:From what I can remember of how these things tend to be structured, most data structures for genealogy use events rather than direct relationships.


Aaah. Now THAT makes a lot of sense. Cheers Dave. Have cow too.

Winston
 
Saloon Keeper
Posts: 12165
258
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Dave Tolls wrote:I've seen simple things like remarriages being a pain in some freebie genealogy software (for example), resulting in a step-parent who has no kids simply not appearing in the tree, which seems an odd thing to do. They may not be part of the DNA line, but that's no reason to have them vanish from the picture like some Stalinist bit of photo-editing...


I think this also has to do with the difference between "Family" and "Blood". Do you include adopted children, etc.
 
Winston Gutkowski
Bartender
Posts: 10777
71
Hibernate Eclipse IDE Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Stephan van Hulst wrote:I think this also has to do with the difference between "Family" and "Blood". Do you include adopted children, etc.


To me that's a semantic issue. What (I think) we've all been mulling over is "how do you model a family tree?" and I was going down the "relationship" route - ie, trying to create dynamic connections between different Person objects; and Junilu (and others) pointed out the limitations of that path.

Dave's "event-driven" model though, makes perfect sense.

Winston
 
Sheriff
Posts: 15815
264
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Here are my ideas so far:

Foundational relationship is biological parent-child. This is an irrevocable and absolute relationship. Use a non-binary tree to represent this. Trees will be very simple, just parent-children. Person know two biological trees: the one where he/she is a child and the other in which he/she is a parent. Tree nodes can represent one or two people.

Edit: I guess you could be a parent in multiple trees. That event list that Dave suggested is really a key design component.

Non-biological relationships are temporal: marriage, divorce, adoption, etc. - same concept as the event idea suggested by Dave. These would be tracked through a combination of the biological tree relationships joined by some logical way to a person's collection of relevant events.

All other relationships can be calculated based on the foundational parent-child relationship and available event information.
Since they can be calculated, it makes sense that different calculations can be made by Strategy objects. Want to see who your great great grandparents are? Then call on the FindForebears Strategy. That strategy doesn't exist? Well, write one that traverses the tree through your parents and plug it into the RelativeFinder module.

A Relationship enum with a reverse() method could be useful. I would make it with a finite set of values though and leave determination of "distance" to the Strategy. That is, adding "Great great great great" to a Grandmother role would be left to something like the FindForebears strategy object, while the same prefix would be added to a Grandson role by a FindDescendants strategy object.

I always say that "thought exercises don't prove anything, working code does," but there's nothing I can think of right now that can't be covered by this.
 
Dave Tolls
Rancher
Posts: 4625
47
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Winston Gutkowski wrote:
Aaah. Now THAT makes a lot of sense. Cheers Dave. Have cow too.

Winston



Ta!
I looked into it years ago when I wanted somewhere to stick all the stuff I'd ferreted out from the old Finnish records, and wanted something standardised.
 
Winston Gutkowski
Bartender
Posts: 10777
71
Hibernate Eclipse IDE Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Junilu Lacar wrote:Foundational relationship is biological parent-child. This is an irrevocable and absolute relationship. Use a non-binary tree to represent this. Trees will be very simple, just parent-children. Person know two biological trees: the one where he/she is a child and the other in which he/she is a parent. Tree nodes can represent one or two people.


Hmmm. So a collection of interconnected 1-level (or 2 if you include the root) Parent->Children trees? Oddly enough, that's sort of along the lines that I was thinking too.

I disagree however, that it's absolute (at least in database terms). Some people may not have children; and that makes it optional (the difference between 0:1 and 1:1 cardinality which, sadly, doesn't seem to be taught any more).

The ONLY absolute biological relationship that exists for any Person is a binary tree of antecedants.
It's also the structure that makes most sense to me in terms of creation; but how you interconnect them to produce traceable downward paths I'm not quite sure. However, a HashMap<Individual, Set<Individual>> doesn't seem like a bad place to start.

And in the meantime, I like Dave's event model, because it doesn't make any assumptions about how it might be used.

Winston
 
Winston Gutkowski
Bartender
Posts: 10777
71
Hibernate Eclipse IDE Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Winston Gutkowski wrote:And in the meantime, I like Dave's event model..


And on a lighter note, I believe I have the perfect test case.

If your model accurately depicts the Hapsburg family tree - which has hundreds of members, most of whom are very well documented since they ruled half of Europe at one time - you're onto a winner.

Because the "Hapsburg chin" didn't come about by accident.

Winston
 
Stephan van Hulst
Saloon Keeper
Posts: 12165
258
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
There's also a chance that any strategies you implement will list you as your own grandpa :P
 
Ranch Hand
Posts: 162
1
Android Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
@Winston : Thanks for the Cow.

Seems like I need to pitch in and explain exactly what I did, not saying did it in a perfect way but saying it again because what is being said about the code is wrong due to probably less information provided by me .
Let me try to recite clearly what I did exactly

1. First of all this problem is about "Graphs" and not Tree Data Structure ( Forest) from my perspective. That said it means 2 things , First it does not mean that we can't solve this by Tree DataStructure, Secondly, it does not mean I am using Graphs in my Project as a Data Structure . I am not using both to model it elegantly .
I am exactly using which is well encapsulated inside FamilyTree ADT , I made for use.

2. Now, to start with I have given FamilyTree some API's so that I could use it in abstraction.





3. First confusion point, it is NOT Tree inside , it is HashMap of Relationship .
Second confusion point , FamilyTree belongs to some person. So every person in my project would have its own UNIQUE FamilyTree. Again its FamilyTree ADT and not Tree, so essentially I am not keeping Forest.

So it means, Sangel Family Tree would look like the follwing

SPOUSE : Sally
SIBLINGS : A, B , C, D
FATHER : Z
MOTHER : X

and....

Sally Family Tree would look like

SPOUSE : Sangel
SIBLINGS : L,K


4. Let me come to RELATIONSHIP now, it looks like as follows




Again Relationship has given simple API for checking weather a particular Relationship is possible or not and finding reverse relationship of a particular relationship.


5.



6. [Important One] : I have not planned or done to add all the "can deduced" relationships. I am using just direct "non-deducible" relationships. For instance FATHER, MOTHER, SPOUSE, SIBLING . I am not adding any specific class for FATHER FATHER FATHER FATHER or FATHER MOTHER SISTER DAUGHTER.
I will very well trace down and map those relationships to COUSIN, GRAND GRAND FATHER and so on.


7. Coming over to "FamilyTree Registrar" . Thoughts are like : You hold your Passport and go to Passport office officials for VISA STAMP. 2 things to mark

1. You HOLD passport.
2. You go to PASS PORT office who has the right to mark VISA stamp on it. You go to UPDATE your Passport.

Similarly ....

1. Person HOLD FamilyTree ADT.
2. Person will go to FamilyTree Registrar to UPDATE his Family Tree.


8. Family Tree registrar has additional responsibilities , it is not there just to delegate responsibilities to FamilyTree ADT. and that additional responsibility is .............. adding the reverse relationship too. This is the place where I can do additional things later, what is coming to my mind is to remove FamilyTreeADT from Person class and keep track here
of Person family Tree and that is why I started giving UUID which Junilu Lacar commented to be very early to introducer that. Nevertheless, We should not give this responsibilities to FamilyTreeADT . Atleast that is not the right place and it wont be cohesive and Single responsibility class any more.




9. Finally to the users of this Application, API would look like as follows and I am not there yet, but I know it will look like as follows

Person oshin = new Person("Oshin",Sex.Male,familyTreeRegistrar);
oshin.addFather(sahil);
oshin.addChildren(x);

sahil.addMother(parul);

parul.addSibling(sahil);


What I had shown you earlier is inside familyTree registrar class .
These calls inside Person class would resolve down to



and then family tree registrar will make two calls to FamilyTreeADT for adding the forward relationship and adding reverseRelationship.

Example of usage with Final FamilyTreeADT snapshot to clear what mess I did :-D


1. Consider oshin, sahil, isha, neha, varun, parul....... all these as Persons defined with some sex.

2. Consider Following Calls

A. oshin.addFather(sahil);
B. oshin.addMother(neha);
C. neha.addSibling(varun,menka);
D. varun.addFather(sahil);
E. sahil.addFather(joe);


View of Family Trees inside Application is as follows


OSHIN FamilyTreeADT

FATHER : sahil
MOTHER : neha


SAHIL FamilyTreeADT

SON : Oshin, Varun
FATHER : joe



Now , you can see that I dont need to store GrandFather relationship explicitly as I can trace that down. For instance who is grandfather of oshin ?? I will go to familyTree of oshin and will find father as sahil and then I will go to sahil family tree and get his father as a result.
I hope I made clear various things and confusions that arises .


Also, it would be awesome if someone would come up with the "challenge relationship" that could be not be described with this model. OR if someone could say that this application has larger complexity than .....(whatever you say) .
As far as our specs are concerned, which is as follows

1. I should be able to describe relationships with others upto GRANDFATHER ( Thats is the reason I made GRANDFATHER explicit to make algo fast )
2. given person name , give his relationships with other person.


Given above specs my program is running perfectly.
But, let us think and discuss in a way we are doing, to model any given relationship in this world and all the possibilities of API that one can practically perform. From that perspective, if this code is not maintainable or extensible then WHY ???
What is that scenario which you would like to add and this application will bloat. I want to understand it because I would like to make it as flexible as possible so that it could model any relationship.

Cheers!!!

 
Junilu Lacar
Sheriff
Posts: 15815
264
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Winston Gutkowski wrote:I disagree however, that it's absolute (at least in database terms).


I think you're using "absolute" in a different context from what I had in mind. I meant it in the sense of "absolute vs. relative".

If I have many small Parent-Child trees, then the relationship between parent(s) and child will be inherent in the tree structure; it is absolute. All other relationships can be inferred from this. So if another child is added to the parent node, the relationship between the children can be calculated from one child, going up to its parent, then getting all other child nodes. Those would be the child's siblings. If you throw in gender, then you can also tell whether the sibling is a brother or sister.

I don't know if "absolute" is the really right term to use here but anyway, that's what I meant. Maybe "inherent" would be clearer, that is, the relationship is inherent to the Tree structure whereas any other relationships can be inferred/calculated and hence are "relative" to the absolute/inherent parent-child relationship. ¯\_(ツ)_/¯

This is indeed quite an interesting exercise. I think I might even start actually working on some code for it to see what kind of insights I might gain from doing TDD on this. I'd be curious to see if the code and refactoring would lead me to the idea of "Events" - I suppose it's likely since I already had the idea of Moment-Intervals for marriage, adoption, and other socially/legally-formed relationships.
 
Sangel Kapoor
Ranch Hand
Posts: 162
1
Android Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
"marriage, adoption," Is this relationship ?? I feel SPOUSE and CHILDREN or ADOPTED-CHILDREN is relationship
 
Sangel Kapoor
Ranch Hand
Posts: 162
1
Android Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Dave Tolls wrote:From what I can remember of how these things tend to be structured, most data structures for genealogy use events rather than direct relationships.
So you have a Person, which is the basic data (usually just name, gender, that sort of thing). Their status relative to other people (and some of their own data) is handled by events, including things like 'birth', 'death', 'marriage', 'divorce', 'adoption'.

IIRC (and this is a bit hazy) a relationship then is defined by these events.
Who are your parents? Look up your birth event and see who's tagged in there.
Are you alive? See if there's a death event...though I think there might be a 'probably dead' flag on a person, not sure.

Just throwing that out there to give an idea of how some of these things have been modelled.




This seems another different approach. I have done work on event based Architecture but still I am not getting it properly. Could you please elaborate. ??

Is it like you will keep saving events for each person and then track down relationships based on events stored ? ?? If I need to find Grandfather of X , then I will find Father Event of X and then see who is tagged as father and then find Father Event again for him.

How costly it is to find Event from Event Store ???


 
Dave Tolls
Rancher
Posts: 4625
47
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Sangel Kapoor wrote:"marriage, adoption," Is this relationship ?? I feel SPOUSE and CHILDREN or ADOPTED-CHILDREN is relationship



Depends how you look at it.
From an event driven view the relationship is the result of an event (spouse due to a marriage event for example).

I think one of the reasons things like GenXML and Gen-whatever-that-other-one-is use events is that is what you encounter when plowing through records. Births, marriages and deaths are all events and the relationships come out of those (well, maybe not so much that last one), and that is what you end up looking through when tracking ancestors.

Obviously, you're not looking at it from quite that viewpoint.
 
Junilu Lacar
Sheriff
Posts: 15815
264
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Sangel Kapoor wrote:
7. Coming over to "FamilyTree Registrar" . Thoughts are like : You hold your Passport and go to Passport office officials for VISA STAMP. 2 things to mark

1. You HOLD passport.
2. You go to PASS PORT office who has the right to mark VISA stamp on it. You go to UPDATE your Passport.

Similarly ....

1. Person HOLD FamilyTree ADT.
2. Person will go to FamilyTree Registrar to UPDATE his Family Tree.

...

Given above specs my program is running perfectly.


I find that a very strange way to think but, hey, if it works for you then I guess that's good enough. I just don't think it would make a whole lot of sense to many people. But then again, the only other people who matter are those who will use the API you created and the people who would have to work with and maintain/extend this design.
 
Sangel Kapoor
Ranch Hand
Posts: 162
1
Android Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

I find that a very strange way to think .



Are there any RULEs for thinking too
Thinking should not have any boundaries.


I just don't think it would make a whole lot of sense to many people.



I would love to hear it from others directly :-)
 
Junilu Lacar
Sheriff
Posts: 15815
264
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
A few posts back, I cited Peter Coad, et. al, and their book, Java Modeling in Color with UML. The book is all about four interconnected "Archetypes" that form a domain-neutral component:

1. Moment-Interval
2. Role
3. Catalog-Entry-like Description
4. Party/Place/Thing

All classes that they model in the book fall under one of these archetypes. The deal with the color is that by assigning a different color to each archetype, you have an additional layer of information in your model that increases the amount of content you can express. The colors they use correspond to common Post-It colors: pink (Moment-Interval), pastel yellow (Role), pastel blue (Description), pastel green (Person/Place/Thing). Since I usually model on a whiteboard, I use red, black, blue, and green markers instead. That is, when I need to have any of those additional dimensions at all. I sense that these four archetypes will come in handy when trying to model this problem.

When I first started using these archetypes and colors, I found myself thinking more about whether I was using the right color or not rather than how classes were related to each other. Since there are only four colors, however, you quickly get over that and the added visual dimension can actually be pretty useful.

Anyway, I just thought I'd share that in case anyone was curious enough to try it themselves or even check out the book if it was available in the local library. I wouldn't necessarily recommend buying the book since it's a bit dated (published in 1999) and it's heavy on UML, which I don't particularly find useful. I use a simplified notation, adapted from Scott Ambler's agile modeling work, only simpler. I think many of the ideas Coad et.al. discuss in their book about OO modeling are based on sound design principles and thus have withstood the test of time.
 
Junilu Lacar
Sheriff
Posts: 15815
264
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Sangel Kapoor wrote:


There are a few things I can say about this code and the method's design. I've already pointed out before that it could be more OO.

Here's another thing: I find designs where private methods throw domain-specific exceptions like IllegalRelationshipException are questionable on the basis of the principle of separation of concerns. Something unavoidable like IOException is acceptable to throw from a private method but a domain-specific exception like that certainly can be avoided simply by validating the input values before calling the private method. It's the public methods of the API that should be declared to throw the domain-specific exceptions. Since the method is private, you have full control over the conditions (with respect to the domain-specific exception) under which it will be called. You should ensure that the preconditions for calling the private method are met before calling it. That leaves the private method focused solely on the success scenario. The check for invalid values is a separate concern and would be tested separately.

Here's what I mean:

The advantage of separation of concerns is that you won't have to worry too much about affecting the success scenario code if you needed to add validation criteria. You'd simply modify and retest the input validation method and related scenarios. Conversely, if you had to change the success scenario logic, you can do that independently of the input validation logic and not have to worry too much about breaking that part.
 
Winston Gutkowski
Bartender
Posts: 10777
71
Hibernate Eclipse IDE Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Junilu Lacar wrote:I think you're using "absolute" in a different context from what I had in mind. I meant it in the sense of "absolute vs. relative".


Very likely.

If I have many small Parent-Child trees, then the relationship between parent(s) and child will be inherent in the tree structure; it is absolute.


Yes, but as I said above, not everybody will fit into that kind of "tree" concept, since not everybody has children.

All other relationships can be inferred from this.


Again, I disagree. Some relationships can be inferred from it, but not all.

Here's my very threadbare initial cut at this;That's as far as I've got, but I think it contains the basics of my "biological" model.

1. An Indivdual is a specialization of a Person for the purposes of creating a family tree.
2. Each Indivdual is the root of an unbalanced binary tree, either of whose branches can be null if parentage is unknown. This is the primary tree of the structure.
3. FamilyTree is a container that keeps track of:
a. Everyone in that tree (people).
b. A Map of each person who has a child, along with their offspring. This is the secondary "tree" of the structure that gives us our "downward" relationships.

Hopefully, you can see the idea. When you create a new entry in the tree, it will presumably be based on information about a person, along with their mother and/or father. Whatever, for each person for whom we have information:

1. Check if they are already in 'people'. If so, add/update any new information.

Otherwise, create a new Individual and:

2. For each "parent" provided, check if they are already in 'people', and:
a. If not, create a new Individual with null parents, and add them to 'people'.
b. Link the Individual in 'people' to our new entry as 'mother' or 'father'.
c. Update/add them to 'children' with our new entry as the "child" (ie, in the value).

3. Add our new entry to 'people'.

Note that this is ONLY for biological relationships. Things like marriage, spouse and adoption are legal ones, which I suspect are better covered by an event model (which could also allow you to supply supporting documentation). Indeed there's no reason that some of the information included above is also contained in the event model (eg, Births and Deaths).

Obviously, matching up people is going to be fairly important, so I suspect you'd need a periodic "housekeeping" function for the 'people' Set.

Getting stuff out?...That's for someone else to work out.

Winston
 
Junilu Lacar
Sheriff
Posts: 15815
264
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Winston Gutkowski wrote:

If I have many small Parent-Child trees, then the relationship between parent(s) and child will be inherent in the tree structure; it is absolute.


Yes, but as I said above, not everybody will fit into that kind of "tree" concept, since not everybody has children.


No, but everyone is a child. The degenerate cases are pretty easy to handle. A childless couple is simply a tree with a null set of child nodes. A person whose parents are not known can still be handled in much the same way as the Akka root guardian. The scheme I have in mind is recursive and it involves seeing a Person first and foremost as a child of a couple. A person will always be represented as a child node of a specific parent node comprised of his/her biological parents, neither of whom need to be known (as would be with the Akka-esque Root node where the identities of the two individuals who make up the couple are basically "whoever/don't care"). A person who has no children simply does not belong to any tree as a parent. Like I said, I'd only have small trees and you'd simply jump from tree to tree by flipping your perspective between seeing a Person as either a parent or a child.

This can actually translate directly to a self-joined table in an RDB with one row representing the "Root Parent" where all recursion eventually will stop.
 
Winston Gutkowski
Bartender
Posts: 10777
71
Hibernate Eclipse IDE Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Junilu Lacar wrote:No, but everyone is a child. The degenerate cases are pretty easy to handle. A childless couple is simply a tree with a null set of child nodes.


Yes, but that's not modelling what you initially said, which is that everyone is a child. A tree with no nodes, to me, is saying that everyone is an "optional" parent.

My model, OTOH, does assume that everyone is a child, and also allows for the fact that parents may be unknown, or irrelelvant for the purposes of a tree; and the "downward" model (children) is only populated when a child relationship is (a) known to exist, and (b) we know who at least one parent is.

Fun stuff.

Winston
 
Junilu Lacar
Sheriff
Posts: 15815
264
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Winston Gutkowski wrote:Note that this is ONLY for biological relationships. Things like marriage, spouse and adoption are legal ones, which I suspect are better covered by an event model (which could also allow you to supply supporting documentation). Indeed there's no reason that some of the information included above is also contained in the event model (eg, Births and Deaths).


Yup, like I said, the Event piece is a key design component, even in the recursive scheme I'm turning over in my mind. It fits in very nicely though, as far as the thought exercise goes. Unit testing and TDD will bear out whether that's really true.
 
Sangel Kapoor
Ranch Hand
Posts: 162
1
Android Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

The advantage of separation of concerns is that you won't have to worry too much about affecting the success scenario code if you needed to add validation criteria. You'd simply modify and retest the input validation method and related scenarios. Conversely, if you had to change the success scenario logic, you can do that independently of the input validation logic and not have to worry too much about breaking that part.



This idea is nice I got your point. :-)

Still, how would you do that in my case, the line for finding the reverse relationship throws an exception.
(which is validation step and main concern of private method) . I have refactored to the following in accordance to what you have mentioned above but still see
private methods have to declare exception in order to make compiler happy :-)




New Query : While doing this , I recall one issue at which I got stuck as follows :-

See following Relationship Interface



While designing this , I had 2 school of thoughts as follows

1. Should I assume "getReverseRelationship" is called with Legitimate relationship and hence should not throw an exception.

I did not went this way because, clients of this interface then need to know that they should first call isLegitimate and then call getReverseRelationship.
Doing this will certainly then avoid exception on the private method above.


2. The way I have done. With this approach, private method need to declare that Exception even when it will never occur. :-)

What would you suggest ???
 
Junilu Lacar
Sheriff
Posts: 15815
264
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Winston Gutkowski wrote:

Junilu Lacar wrote:No, but everyone is a child. The degenerate cases are pretty easy to handle. A childless couple is simply a tree with a null set of child nodes.


Yes, but that's not modelling what you initially said, which is that every person is a child. A tree with no nodes, to me, is saying that everyone is an "optional" parent.


It seems to me that you're stuck looking at just one perspective. Each of the individuals who make up a childless couple are part of a Parent node that has a null set of child nodes. Each of them in turn is part of another tree where they are represented as the child of their own parents. It goes back to that Role archetype I mentioned. You're always a Child and optionally, you can be a Parent.

And the reason I call Parent-Child relationship foundational and inherent is because you can always tell from looking at a Tree whether a Person in that tree has the role of parent or child. Once a person gets married or "shacks up" with another person, he/she gets put into the Parent node of another tree with his/her other half, thus completing the couple that occupies that parent node.

I'll start playing around with this idea and some tests/code when I have more time.
 
Marshal
Posts: 25682
69
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Winston Gutkowski wrote:If your model accurately depicts the Hapsburg family tree - which has hundreds of members, most of whom are very well documented since they ruled half of Europe at one time - you're onto a winner.



Those were the people I had in mind when I mentioned the possibility of marrying your niece earlier in the thread.
 
Junilu Lacar
Sheriff
Posts: 15815
264
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Sangel Kapoor wrote:
Still, how would you do that in my case, the line for finding the reverse relationship throws an exception.


Bottom line, I wouldn't have to deal with that. I tried to go down that design path just to give you the benefit of the doubt but like I warned you before, it quickly became untenable. The code just gets uglier and uglier.

What I'm finding is that the only relationship that you can hard-code is Parent/Child. All the rest have to be calculated/inferred relative to this relationship in the recursive scheme I've been describing in other posts. A limited Relationship enum would have Parent, Child, and Sibling. Those are the only inherent relationships that can be inferred from a very small Parent/Child tree.

Maybe I'm just blinded to opportunities to refactor your design because I already have something that I think is better. At any rate, I have no suggestions for you other than to throw away your design and start a new one that's more in line with the ideas that Winston, Dave, and I have put forward. Those don't have the same kind of smells that I'm finding in your current design. At least not right away at face value.
 
Winston Gutkowski
Bartender
Posts: 10777
71
Hibernate Eclipse IDE Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Junilu Lacar wrote:It seems to me that you're stuck looking at just one perspective.


Funny. I was going to say the same thing.

Each of the individuals who make up a childless couple are part of a Parent node that has a null set of child nodes.


And each Individual in my model is linked directly to their parents.

Each of them in turn is part of another tree where they are represented as the child of their own parents.


Have another look at my 'children' Map, because that's precisely what it does.

It goes back to that Role archetype I mentioned. You're always a Child and optionally, you can be a Parent.


And my model says that you are a child, and that you may be a Parent. The main difference between our approaches is that mine doesn't create anything if an Individual doesn't have a child, or for a child whose parents are unknown.

And the reason I call Parent-Child relationship foundational and inherent is because you can always tell from looking at a Tree whether a Person in that tree has the role of parent or child. Once a person gets married or "shacks up" with another person, he/she gets put into the Parent node of another tree with his/her other half, thus completing the couple that occupies that parent node.


Ah, but to me that's premature. Just because you marry, or get "shacked up" with someone has nothing to do with whether you're a parent or not. The only determining factor of "parenthood" in my model is whether you have a kid or not - ie, children.keySet() returns a list of all "parents".

Now I could certainly see a possibility for Roles when the "event" stuff like marriage or adoption gets involved, but biologically, parenthood means you have a kid. At least in my world.

Winston
 
Junilu Lacar
Sheriff
Posts: 15815
264
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
@Sangel: Throwing away designs can be very cathartic, you know. You should try it.

I do it all the time and I think I'm a better designer because of it. Once you accept the idea that you're like everyone else who doesn't come up with great designs right off the bat, it's easy to do. Always treat your first few design attempts as throwaways. That way, you won't get too attached to one idea and feel that you've wasted your time and effort when you abandon it. Also, when you find that you found something that actually works and it happens to be one of the first few that you tried, you'll be pleasantly surprised that you got it so soon.
 
Junilu Lacar
Sheriff
Posts: 15815
264
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Winston Gutkowski wrote:
Ah, but to me that's premature. Just because you marry, or get "shacked up" with someone has nothing to do with whether you're a parent or not. The only determining factor of "parenthood" in my model is whether you have a kid or not - ie, children.keySet() returns a list of all "parents".


Being a couple makes the questions like "Did Bill and Sue ever have any kids?" applicable and easy to answer. You just find the parent node that represents the couple "Bill & Sue" and see if there are any child nodes.

Don't get me wrong, Winston, I'm not saying there's anything wrong with your model. It's a different approach from what I have in mind but it could be workable. It would be interesting to see what test-driving some of these ideas would bear out.
 
Junilu Lacar
Sheriff
Posts: 15815
264
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Winston Gutkowski wrote:

Junilu Lacar wrote:It seems to me that you're stuck looking at just one perspective.


Funny. I was going to say the same thing.


No, I see where you're going with your scheme. It just seems like you're looking at my scheme with the same lens that you're using to view yours.
 
Winston Gutkowski
Bartender
Posts: 10777
71
Hibernate Eclipse IDE Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Junilu Lacar wrote:Being a couple makes the questions like "Did Bill and Sue ever have any kids?" applicable and easy to answer. You just find the parent node that represents the couple "Bill & Sue" and see if there are any child nodes.


Yes, it's true that some of my queries might be a bit more indirect. To answer that, I'd do children.get(Sue), then look for a child whose father is Bill.

However, I suspect that my setup might be better for something like getting all siblings (including halves).

Swings and roundabouts I suspect.

Winston
 
Winston Gutkowski
Bartender
Posts: 10777
71
Hibernate Eclipse IDE Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Junilu Lacar wrote:No, I see where you're going with your scheme. It just seems like you're looking at my scheme with the same lens that you're using to view yours.


It's probably my RDB background. I was always taught to favour enforced relationships (ie, 1:1 or 1:many) for anything other than foreign keys, and to be wary of 'nulls' - "the key; the whole key; and nothing but the key".

Winston
 
Junilu Lacar
Sheriff
Posts: 15815
264
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Just posting this to try to articulate the picture I have in my head.

I'm looking at the Tree concept somewhat like an Iterator, as an abstraction and a "lens" to an underlying set of data. It's from the idea that Campbell gave about a Person having two trees, one for parents, another one for offspring. That's where the idea of using two different "lenses" came where I could go to a Person and ask him for a Tree view where that person has a child role or for others where they are have the parent role, or at least are part of a couple that makes up a Parent node. The Tree would then allow me to access the Parent and Child nodes directly and I can recurse from there. That's why the Role enum, if I found that it was really necessary, would have only Parent, Child, and possibly Sibling but probably not, as its values.

From a Parent or Child node, I can traverse the underlying collection by moving between Child and Parent nodes and invoking a relatively small API (getParentTree(), getChildTree(), getChildren(), getParent(), hasMother(), hasFather(), hasChild()) on the Tree/Node interface. Visitor pattern and the Strategy pattern are already vaguely creeping into the design picture at this point.

As I move from one person to another asking for one Tree view or another, I am able to move from person to person, child to parent and vice versa. This can all be done recursively or iteratively if you don't like recursion. The notion of the Akka-esque Root parent node comes in very handy in stopping the recursive or iterative traversal and of course when a Parent node (representing a couple) has no Child nodes, the recursion stops with the childless couple as well.

Now where Dave's Event idea comes in is that once the biological connections have been made, you can layer on the event-related connections. Say Bill and Sue adopted a child named Jim. Jim gets added to a Child of the "Bill & Sue" Parent node with an "adoption event" marker. Bill cheats on Sue and has a child with Mary so now Bill and Mary become a couple in Parent node with a Child node that represents their love child, Connie.

With the combination of Couple/Parent/Child connections and Event markers, I think I can come up with something that reflects what happens when the guy in the song becomes his own grandpa.
 
Winston Gutkowski
Bartender
Posts: 10777
71
Hibernate Eclipse IDE Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Junilu Lacar wrote:I'm looking at the Tree concept somewhat like an Iterator, as an abstraction and a "lens" to an underlying set of data. It's from the idea that Campbell gave about a Person having two trees, one for parents, another one for offspring...


I suspect we're not really that far off from each other, you know. I've just made my Individual the "child" and implemented my "parent" view as a Map.
As I said earlier, my first thought was along the same lines as yours (a bunch of mini-trees), but it seemed to me that a Map achieves the same thing, and has the added advantage of being easily "recursable", since all the info is in the same place.

That wasn't where I imagined it would end though, and I suspect that "events" could well superimpose more structures on top. The only thing I felt was worth adding was the 'people' Set, so that I have a single place to check if a person is already in the "tree".

Winston
 
Junilu Lacar
Sheriff
Posts: 15815
264
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Winston Gutkowski wrote:I suspect we're not really that far off from each other, you know. I've just made my Individual the "child" and implemented my "parent" view as a Map.


Great minds and all, y'know These are all good ideas that present various routes you can take to the same destination. You could probably spend a few nights just playing around with all of the different options we've put forward collectively.
 
Sangel Kapoor
Ranch Hand
Posts: 162
1
Android Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I doubt how I am different from Winston approach and you are liking his design but not mine :-D


Just posting this to try to articulate the picture I have in my head.

I'm looking at the Tree concept somewhat like an Iterator, as an abstraction and a "lens" to an underlying set of data. It's from the idea that Campbell gave about a Person having two trees, one for parents, another one for offspring. That's where the idea of using two different "lenses" came where I could go to a Person and ask him for a Tree view where that person has a child role or for others where they are have the parent role, or at least are part of a couple that makes up a Parent node. The Tree would then allow me to access the Parent and Child nodes directly and I can recurse from there. That's why the Role enum, if I found that it was really necessary, would have only Parent, Child, and possibly Sibling but probably not, as its values.

From a Parent or Child node, I can traverse the underlying collection by moving between Child and Parent nodes and invoking a relatively small API (getParentTree(), getChildTree(), getChildren(), getParent(), hasMother(), hasFather(), hasChild()) on the Tree/Node interface. Visitor pattern and the Strategy pattern are already vaguely creeping into the design picture at this point.

As I move from one person to another asking for one Tree view or another, I am able to move from person to person, child to parent and vice versa. This can all be done recursively or iteratively if you don't like recursion. The notion of the Akka-esque Root parent node comes in very handy in stopping the recursive or iterative traversal and of course when a Parent node (representing a couple) has no Child nodes, the recursion stops with the childless couple as well.

Now where Dave's Event idea comes in is that once the biological connections have been made, you can layer on the event-related connections. Say Bill and Sue adopted a child named Jim. Jim gets added to a Child of the "Bill & Sue" Parent node with an "adoption event" marker. Bill cheats on Sue and has a child with Mary so now Bill and Mary become a couple in Parent node with a Child node that represents their love child, Connie.

With the combination of Couple/Parent/Child connections and Event markers, I think I can come up with something that reflects what happens when the guy in the song becomes his own grandpa.




Am I not doing exactly the same except , I am keeping SPOUSE as extra relationship . You are talking about keeping it in small trees and I am keeping it in HashMap.
Not a big deal and in fact I feel it is easy and natural to represent SPOUSE in HashMap than keeping one node for couple which is not natural because , some nodes in
your tree are singular and some are plural, no consistency. Also if you put new developer on your code, it will take a while to understand that you are representing one node for couple and that is why I insist on NATURAL design.

I can throw away my design any time, it is not a big deal, its my attempt and not life thesis. But at least I should feel how your design is making a difference.

Only difference I have seen so far is with that "Event design" thing. That model might be helpful if it is easy to find particular event associated with person.

Do you have any concrete case where I wont be able to add easily or extend my design but yours. We differ only inside FamilyTreeADT .


NOTE : I am not defending my design . I am just discussing because I am not yet impressed !

Since this discussion is going in all directions with hypothetical theories , why not you code your concrete classes and show the World !! I would love to see your Person class and FamilyTreeADT .


 
Winston Gutkowski
Bartender
Posts: 10777
71
Hibernate Eclipse IDE Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Sangel Kapoor wrote:Am I not doing exactly the same except , I am keeping SPOUSE as extra relationship . You are talking about keeping it in small trees and I am keeping it in HashMap.


Any chance you could show us what that looks like? Just the definition, you don't have to show us all the methods (unless you want to).

I certainly think that this is a separate structure from our "biological" one (although Junilu may not agree) because:
(a) "Spouse" is not a biological relationship.
(b) It may not even be needed for the "tree". Family trees are usually used to trace lineage, so are you really interested in a marriage (or partnership, depending on your definition of "spouse") that didn't produce any children?
Maybe so for completeness, or interest; but I'd say that it comes under the heading of "additional information".

I've been thinking about exactly how I'd model a "spouse" relationship, because it's a many:many one. I suspect, for my model, that a
  Map<Individual, Set<Individual>> spouses;
with a key for each half of a "couple" would be most consistent; but a Set of "couple" Relationships (or, in Junilu's case, "Nodes") would probably also work.

Great exercise; and well done for starting the discussion.

Now onto adoptions...

Winston
 
Junilu Lacar
Sheriff
Posts: 15815
264
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The main difference between your design and Winston's is the way you are representing relationships.

Your relationships are represented as classes, like that GrandSon relationship example you first showed. Winston tracks a limited number of basic relationships as fields in his object. Other relationships are inferred from these basic ones. In your design, it seems to me that there's too much overlap in being able to infer vs having to specify the relationship between two people. Going back to the relationship example you shared, the grandson relationship can actually be inferred from being the male child of someone's child. In your design, you specify that directly, thus creating the possibility of leaving a "generation gap" between a grandparent and the grandchild because the child/parent that connects them wasn't specified. Now that's inconsistent.

Also, the fact that the scheme I'm thinking about would have nodes that can represent either two individuals seen as a couple or just one individual is not inconsistent at all. If a person in a node is viewed as part of a couple, then that node is treated as a Parent node. If you view the person in a node as a single individual, then you're treating that node as a Child node. It is pretty consistent if you think about it as viewing the person and the node that he's in through either one of two lenses, either as a parent or as a child, and that can be done consistently with all nodes in the family tree. The degenerate case for leaf nodes is easy too and I've already explained how to handle those.

For example, Bill is in a node with Sue. When you view Bill as part of a couple, you are treating the node as a Parent node and perform operations like getChildren(). When you view Bill as just an individual, you're treating that same node as a Child node and perform operations like getParent(). The design principle that applies here is the Interface Segregation Principle.

So let's say Bill and Sue have a child, Mary, and Mary isn't married. If you try to view the node with Mary in it as a Parent node and call the getChildren() method, I have a couple of options for the design: I can throw an IllegalStateException, which is runtime exception to indicate a bug, or I could just return an empty list. I'd probably be inclined to go with throwing the runtime exception.

Additionally, coming back to the difference between Winston's and your design, the limited amount of code that Winston has shared hasn't triggered any warning bells or given off any strong code smells for me. All the code you have shared so far, however, does have quite a number of code smells and design principle violations, as I've already pointed out to you.

I think I will try to work on implementing some of these ideas just to see if they can withstand trial through TDD.
 
Junilu Lacar
Sheriff
Posts: 15815
264
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
To give a concrete example of that generation gap issue, let's say you call addRelationship(joe, grandson, peter). First of all, it's not very clear how to read this: is Joe the grandfather or grandson? Before you answer that, again that's the point. Somebody needs to tell you or you have to go look at the documentation and if there is none, you have to dig through the source code. This design makes the API ambiguous and unintuitive. This could be read as either "Joe is the grandson of Peter" or "Joe's grandson is Peter."

So, with just that one call you have created a generation gap because no intermediate relationship has been defined. Where is the grandparent's child who is the parent of the grandchild? That is, if Joe is the grandfather, then where is Joe's child who is Peter's parent?
 
With a little knowledge, a cast iron skillet is non-stick and lasts a lifetime.
    Bookmark Topic Watch Topic
  • New Topic