• 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 Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Tim Cooke
  • paul wheaton
  • Jeanne Boyarsky
  • Ron McLeod
Sheriffs:
  • Paul Clapham
  • Liutauras Vilda
  • Devaka Cooray
Saloon Keepers:
  • Tim Holloway
  • Roland Mueller
Bartenders:

Instance variable or inheritance?

 
Bartender
Posts: 10780
71
Hibernate Eclipse IDE Ubuntu
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Winston Gutkowski wrote:Now onto adoptions...


I have a feeling that this is just another "child" entity - on the basis that an adoption can't exist without a child being involved - which suggests to me that perhaps I'm missing a Child interface.

So let's plug that in:
Not too bad, but I think it can be improved. We now have two different types of Child, one biological, the other not, so the second one has no biological linkage. But what if we add that to our interface? Viz:Now the next two become:and now our two "groups" (people/children and adoptees/adoptions) start to look quite generic.

Specifically, the Map can be defined as:
  Map<Individual, ? extends Child>
and I suspect that each group could even be encapsulated in a container class (Family?).

I haven't thought that part through completely yet, but it feels interesting; and I'm very happy that nothing seems to be "smelling" yet.

Winston
 
Winston Gutkowski
Bartender
Posts: 10780
71
Hibernate Eclipse IDE Ubuntu
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Sangel Kapoor wrote: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.


I think the great things about it is are:
1. It can be used to define the "semantics" of your family tree (ie, the sorts of things you're interested in).
2. It can store supporting documentation - a lot of which is event-driven (birth/marriage/death certificates, changes of name/title, etc).
3. It just kind of makes sense. Changes to a family structure are likely to involve an event - and moreover, one that probably has to be legally documented these days.

The fact is that any event is likely to involve people (which I still think is the foundation-stone of any family tree), so it's simply a matter of organizing them in a way that allows you to extract the maximum benefit. And from a historical standpoint, events also help you to reconstruct timelines.

My 2¢.

Winston
 
Winston Gutkowski
Bartender
Posts: 10780
71
Hibernate Eclipse IDE Ubuntu
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
And just as a final point (for now), I think I've found the name for my 'Individual' class: Life.

Family trees (IMO) are concerned with "lives": Who someone was, what they were called, when they were born, married, died, etc; and what children they had. Each person in a family tree is a mini-"life story", and that's one of the reasons they interest us.

I'd always been dissatisfied with 'Individual', because it was simply a synonym for 'Person'; but 'Life', to me, encapsulates what family trees are all about.

So that's what I'll be using in future.

Winston
 
Sheriff
Posts: 17734
302
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Winston Gutkowski wrote:
I haven't thought that part through completely yet, but it feels interesting; and I'm very happy that nothing seems to be "smelling" yet.


That Adoptee thing actually smells a little bit. It violates the Open-Closed Principle, specifically the adoptions field in FamilyTree. And it seems out of place in the FamilyTree class.

On the other hand, if you think back to Dave's Event model, an Adoption would be a life event, a Marriage another life event, a Birth is a (special? because it establishes a biological relationship rather than a legal/temporal one) life event. Also, life events happen to people so it seems like the best entity to track life events is the person to whom the event applies. This will not violate OCP when you have to consider additional kinds of events in the future. Again, this vaguely suggests the involvement of the Visitor and Strategy patterns to me.

With that in mind, I think each Person should keep track of the life events that apply to him with the one side of the life event implied by whoever is tracking it and the other half of the relationship being referenced by the event itself. At least that's how it would work in my model.

For example, Bill & Sue adopt Mary. Bill & Sue are a couple in a Parent node. Mary is an individual in a Child node to Bill & Sue's Parent node. Mary has an "adoption event" that references the Bill & Sue Parent Node. This way, the semantics of Person.mother and Person.father are kept strictly biological. The children set can be mixed biological and event-based.

This allows me to answer these questions:

1. Do Bill & Sue have adopted children?
2. Is Mary adopted?
3. Who are Mary's adoptive parents?
4. Who are Mary's adoptive siblings?
5. Does Mary have any adoptive siblings who were themselves adopted?
6. Who are the biological children of Mary's adoptive parents?
7. Who are Mary's biological parents? (could later be filled in once that is known)

Thinking about how to answer #4 made me think that I needed another field in Person but that would have smelled. Then I realized that if you go through the set of children of the couple, you could just check if the child has an adoptive relationship with the parent node or a biological one. The check for biological parent that is to see if any one of the individuals of a couple is the child's Person.father or Person.mother. Otherwise, you find the child's adoption event that references the Parent node. Even a more complicated case where one person in a couple is the biological parent and the other one is an adoptive parent (e.g. a woman who retained custody of her biological child, divorces the child's biological father, then remarries another man who then legally adopts the woman's biological child) can be handled. Now I'm thinking of RelationshipFinder objects, each one knowing how to evaluate a particular kind of relationship by traversing nodes in a particular manner.

I think the merit of seeing biological relations as inherent/absolute and social/legal relationships as relative/temporal/inferred really starts to show here. It promotes consistency and separation of concerns. At least it still does in my mind. I have to do something else today but I'll play around with writing some tests and code over the weekend and share what I come up with.
 
Junilu Lacar
Sheriff
Posts: 17734
302
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
The Event idea also falls nicely under the Coad Moment-Interval archetype I mentioned previously. That is, an event occurs at some moment in time and is what keeps a relationship in force for a certain interval of time. In the case of a Birth, that interval is basically forever. In the case of Adoption, it starts at some point in time when the adoption occurs and terminates never or when the adopted child gets "returned" or emancipated. Same deal with Spouse, whether legal or common-law, the termination of which is recorded with a Divorce/Split/Separation. This is why Strategy and Visitor come to mind since there will be different ways you can process these events using the same List<Event> lifeevents that a Person tracks. You can neatly sort the events by the startDate to produce a chronological narrative of a person's life. You can validate sequencing based on the intervals, durations, overlaps, etc. You can handle people like Liz Taylor and Zsa Zsa Gabor, who married several times, sometimes to the same man from a previous marriage.
 
Ranch Hand
Posts: 4716
9
Scala Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I did this same thing when i learned C++. I wrote the a abstract class human. And inherited.
 
Winston Gutkowski
Bartender
Posts: 10780
71
Hibernate Eclipse IDE Ubuntu
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Junilu Lacar wrote:That Adoptee thing actually smells a little bit. It violates the Open-Closed Principle, specifically the adoptions field in FamilyTree.


Explain please.

And it seems out of place in the FamilyTree class.


As far as I'm concerned, it's entirely optional, unless the semantics of a "family tree" require it.

All my model does (I think) is separate biological families from non-biological ones - which I thought was one of the things we agreed on. How the "family tree" actually handles them, or delivers results, is up to the designer.

On the other hand, if you think back to Dave's Event model, an Adoption would be a life event...


Yes, that is a quandry; but only in terms of naming. My thought (perhaps romantic) was that a family tree is about "lives that we're interested in"; not simply people that have events (life or otherwise) attached to them.

I hope you also understand that I haven't even considered any Event model that might be superimposed yet. I'm simply trying to model the people that are relevant to a family tree.
And the reason I like Adoptee is that it makes the distinction I'm interested in, with no other assumptions. It is simply a Child who is not biologically related to its legal parents - and is therefore allowed to have 4 parents instead of 2.

On the other hand, I may be violating my own principle, by creating a structure that may never be used. But such are the things of design.

Winston
 
Winston Gutkowski
Bartender
Posts: 10780
71
Hibernate Eclipse IDE Ubuntu
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Randall Twede wrote:I did this same thing when i learned C++. I wrote the a abstract class human. And inherited.


Ooof.

Winston
 
Ranch Hand
Posts: 162
1
Android Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • 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?



1. addRelationship(joe, grandson, peter). If it is creating confusion then Math.pow(a,b) is also a confusion but it is still there in JAVA API . Of-course you need to read documentation to use any API or you should use microtypes to avoid it as much as possible. What about Account.transfer(Account acc1, Account acc2), same problem.

You can add another parameter called Direction which I thought of but I thought its not required as of now. We can change this to addRelationshipFor() or can use Microtypes as Parameters to resolve this further though. For instance
addRelationship(Source person, Relationship, Target person). I think that is more of clean-coding issue rather than API signature issue.

2. Secondly whatever you said about Relationship classes in my code is not correct , seems like you have not read my long post with code before, where I mentioned that I have just used basic relationships in my Code which are direct and are immediate meaning if you draw out any family tree on paper then all the direct links of any node are represented as Relationship classes in my code. As of now these are , FATHER, MOTHER, SPOUSE , SIBLING.

Grandson and Grandfather were intentionally added as an exception to my code to make things fast but those are removed now as well. We are inferring all the second neighbors and neighbors of neighbors in GRAPH by moving from familyTree of one person to another person family tree and so on....

 
Junilu Lacar
Sheriff
Posts: 17734
302
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Sangel Kapoor wrote:
1. addRelationship(joe, grandson, peter). If it is creating confusion then Math.pow(a,b) is also a confusion but it is still there in JAVA API . Of-course you need to read documentation to use any API or you should use microtypes to avoid it as much as possible. What about Account.transfer(Account acc1, Account acc2), same problem.

You can add another parameter called Direction which I thought of but I thought its not required as of now. We can change this to addRelationshipFor() or can use Microtypes as Parameters to resolve this further though. For instance
addRelationship(Source person, Relationship, Target person). I think that is more of clean-coding issue rather than API signature issue.


I don't think even the creators of the standard Java API can claim perfection. Just look at java.util.Date and the pain and suffering that caused countless programmers before. Your argument that the Java API has equally confusing parts by no means mitigates the smell in your API much less validates your choice. At least with Math.pow(a,b) there's a natural order that one can infer from experience with expressions like a**b, where the first number is the base and the second number is the exponent. Naturally, with pow(a, b), you can correctly infer from the order of the arguments. that a is the base and b is the exponent.

On the other hand, it's true that Account.transfer(Account, Account) is not intuitive either and it suffers from the same ambiguity as your API. Is it "from accountA to accountB" or "to accountA from accountB"? Either way seems natural enough. In this instance, you can mitigate the smell with a proper choice of parameter names like transfer(Account source, Account target) so that at least it's easy to dispel the ambiguity using smart IDEs like Eclipse that will show you a hint when you hover over the method signature. However, your suggestion to create "microtypes" so that you can write addRelationship(Source person, Relationship, Target person) is even smellier to me. Sorry I can't explain it further by referencing a catalog name for the smell but it's just something that doesn't look right to me.

I already told you that I thought that addRelationship(Person, Relationship, Person) is not very OO but more procedural in nature. I tried to code and refactor down the path that I suggested to make it more OO but the coding for Relationship.reverse() just got uglier and uglier. That's why I abandoned it and discarded it as a design option. The more OO design for that would have been Person.add(Relationship, Person) and similarly, this would be more OO: Account.transferTo(Account target, Amount amt) or Account.transferFrom(Account source, Amount amt)

Have you tried answering some of the questions I posed in the hypothetical scenarios above? How well did your model hold up? What kind of changes did you have to make to be able to handle those types of queries?

If it makes you feel any better, even the model I thought out so carefully in these last couple of pages of posts has quickly run into problems when I tried to implement it. To mash up a couple of sayings: The best-laid designs never survive contact with the tests. (The best-laid plans of mice & men often go awry + No battle plan survives contact with the enemy). It looks like I'll have to throw away some of my ideas as well but at least there's still a foundation that I can back up to and try to go another way.
 
Junilu Lacar
Sheriff
Posts: 17734
302
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Winston Gutkowski wrote:
Not too bad, but I think it can be improved. We now have two different types of Child, one biological, the other not, so the second one has no biological linkage. But what if we add that to our interface? Viz:Now the next two become:and now our two "groups" (people/children and adoptees/adoptions) start to look quite generic.


It took me a while but I finally realized what was smelly to me about this. Actually, since it wasn't very obvious at first glance, there are two smells:

1. It's confusing and hides a design flaw
2. The relationship between Child and Individual, as defined, is not right.

Here's an analogy:

Do you see how this is bad? The best way I can describe the smell where a general contract is defined in terms of a specific implementation is "incestuous". That is, the supertype has inappropriate knowledge of one of its subtypes. In design, as it is in families , that is quite yucky.

The damage can be seen in lines 14-23. The design and the names chosen make it difficult to figure out the intent of the code. Was the intent to get back a Child or Individual? When I read return child but see that it's an Individual, it's like looking at the GIF illusion of a train that's either arriving or leaving.
 
Junilu Lacar
Sheriff
Posts: 17734
302
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
It's interesting how that Child in terms of Individual definition didn't immediately jump out as bad. One of the things that crossed my mind as I was analyzing it was that having the method Individual getIndividual() in Child would then allow you to convert types without casting. Most of time, you see casting as a possible red flag, so maybe naturally, a design that helps you avoid a cast can be seen as a good design. Then I realized that what it's really doing is masking the smell of downcasting and subverting our ability to detect a potentially bad practice when we see one. Rather than discourage it, the design enables the potentially bad practice of converting from a general type to a more specific type. The effect is that it couples all other implementations of Child to a specific implementation, Individual.

I think the term incestuous is quite fitting for this smell at both levels, from the supertype as well as from all other sibling types. Thinking about it like that kind of makes it even more , doesn't it?
 
Junilu Lacar
Sheriff
Posts: 17734
302
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I think the names helped mask the yuckiness.

With List as ArrayList, you immediately see the danger and call foul.

However, the semantics of Child as Individual in our daily spoken language doesn't have quite the same offensive look to it. After all, every individual is somebody's child. Likewise, every child is an individual.

I think this shows a pitfall in translating spoken language, which often has some nuance to it, directly into our designs. While the semantics of daily spoken language can often be very helpful in clarifying a design, this is one case where a tacit qualifier, i.e., [somebody's] child, inadvertently led to a poor design choice. If you really think it about it, in a software design that defines a public interface Child and public class Individual implements Child, every Individual is a Child but the converse is not true: every Child is not necessarily an Individual.
 
Winston Gutkowski
Bartender
Posts: 10780
71
Hibernate Eclipse IDE Ubuntu
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Junilu Lacar wrote:It took me a while but I finally realized what was smelly to me about this. Actually, since it wasn't very obvious at first glance, there are two smells:
1. It's confusing and hides a design flaw


Yes, just one reason I'm not wild about my naming; but IMO the definition isn't easy.

2. The relationship between Child and Individual, as defined, is not right.


There I don't agree, although I understand your point about "incest".

The fact is that ALL the following statements are true:
1. Every person is a "child" - ie, someone with "parents".
2. Every person is also a biological child, even if one or both biological parents are unknown.
3. Some people are ALSO adoptees, which defines a legal child - ie, someone with legal parents.

Since we have two types of "child", it makes sense to me to define Child as an interface; and since the primary business of a family tree is to store biological relationships, it seems reasonable to have some mechanism to equate an "adoptee" to a biological person. Then you can reuse navigation logic for both biological and adoptive families, since the "parent" of any child must be a biological child.

I think the distinction is important, particularly in historical trees like the Roman Imperial family, because a pile of them, from Augustus right down to Marcus Aurelius became emperors solely because they were adopted - many as adults.

But if you can come up with better names - or indeed a better structure - that allows both biological and adoptive relationships, and an adopted child to have 4 parents, let me know.

As ever, fun discussion.

Winston
 
Junilu Lacar
Sheriff
Posts: 17734
302
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Winston Gutkowski wrote:

2. The relationship between Child and Individual, as defined, is not right.


There I don't agree, although I understand your point about "incest".

The fact is that ALL the following statements are true:
1. Every person is a "child" - ie, someone with "parents".
2. Every person is also a biological child, even if one or both biological parents are unknown.
3. Some people are ALSO adoptees, which defines a legal child - ie, someone with legal parents.


There's no arguing that these statements are true; they are indeed.

What's not "right" is how the real-world statements are translated into something that violates the semantics of Supertype-Subtype definitions in software design. While all those statements are true in the real world, Individual implements Child implies that "Not every Child is an Individual", which is true in the context of the software design but it is also in direct conflict with the statement that "Every Child is an Individual" in the real-world context. The conflict between real-world semantics and software design semantics is what makes it "not right", IMO. The two need to be aligned so that there's no cognitive dissonance.
 
Winston Gutkowski
Bartender
Posts: 10780
71
Hibernate Eclipse IDE Ubuntu
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Junilu Lacar wrote:While all those statements are true in the real world, Individual implements Child implies that "Not every Child is an Individual", which is true in the context of the software design but it is also in direct conflict with the statement that "Every Child is an Individual" in the real-world context.


That's true; however, it can be mitigated with encapsulation - specifically package encapsulation - and documentation. Albeit maybe at the expense of some flexibility.

The conflict between real-world semantics and software design semantics is what makes it "not right", IMO. The two need to be aligned so that there's no cognitive dissonance.


OK, so what I think you're telling me is that, to satisfy software-design semantics, we need a type that denotes a Parent who can be either biological or adoptive, and contains a Set of "children" - do tell me if I'm wrong.

So now we have two choices:
1. We make every person an implicit Parent.
2. We create a Parent object for every person who actually IS a Parent.

Let's take the first case:
This says that "every person is a parent", which is patently untrue. So instead we say that "they are only a parent if they have children" - so rather than checking a type (which is what I thought OO was all about), we make a logical distinction between a Parent with 0 children and all others.

Now the second case (my preference):
This says "every parent has children", which seems perfectly reasonable to me. But then you have a problem: you now have two objects (of two different types) that refer to the same person.
And since you have no idea whether a child IS a Parent or not at the time you create them, and the Parent relationship is static, you then need an action to substitute every child object with its equivalent Parent one in every relevant "child" Set in your tree - including adoptees.

Now admittedly, I'm only looking at "person" objects here; you seem to have added a "role" on top of this for the purposes of creating a node-like structure.
My argument is that - at least for the moment (and for me) - it's superfluous. I have three types:
  interface Child (and I agree that I shouldn't have made this public; but that's why we design )
  public final class Individual
  public final class Adoptee
and all the public needs to know is that Adoptee is a "wrapper" that ties an Individual to their legal parents.
Child can be documented - for "those who need to know" - to explain that, for the purposes of a family tree, every Child IS an Individual, but may also be an Adoptee.

I'm also kind of glad that that, at least for now, my downward relationships are defined by collections, not by members, because this gives me the flexibility to add new types - maybe even Parent - as I see fit.

And BTW, thanks for the input. It's cleared up several errors I've made.

Winston
 
Winston Gutkowski
Bartender
Posts: 10780
71
Hibernate Eclipse IDE Ubuntu
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Winston Gutkowski wrote:Child can be documented - for "those who need to know" - to explain that, for the purposes of a family tree, every Child IS an Individual.


And one further thought: a crucial thing that my model covers is that the "parent" relationship is polymorphic. Any method that needs to can accept a Child, and its parents will be returned according to whatever relationship they need to be (legal or biological).

Winston
 
Bartender
Posts: 5584
213
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Well,

after nearly 140 posts in which each has highlighted the superiority of his design, compared to the rubbish of the others , why not put the ideas to the test?
Say, before June 1st, send your FamilyTree (or whatever) to OP, complete with instructions, let him/her apply it to whatever he/she has, and then let OP decide the winner.

Of course, anyone can join this "contest". There are no strict requirements, as far as I can tell, but there is enough discussion for anyone to invent something nice. As said: OP will be the jury.
 
Junilu Lacar
Sheriff
Posts: 17734
302
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I think you may have found a better way to look at this. Parent, Child, Adoptee, Husband, Wife, Spouse/Partner, etc. are all Roles that the same person can take on.

If you have

You can cover both roles that a Person as a "Node in a Tree" can take. For me, the fact that in the real world, a person only becomes a parent when he actually has a child is immaterial in the software design context. You may think I'm contradicting myself now from what I said before but I have a sense that it's not quite analogous in this case. The semantics of Parent vs Child in the software design context is about perspective. Each Person as a Node in the design context has the potential to be viewed as a ParentNode to a ChildNode. I don't see this as in direct conflict with the real world semantics of "every person can potentially be the parent of someone else."

Going the opposite way, Child to Parent, is a little problematic though, when it comes to real-world vs software context. If you say that each Person as a Node in the design context has the potential to be viewed as a ChildNode to a ParentNode, then it doesn't quite line up with a person in the real world having two biological parents because in a design context, a ChildNode can only have one ParentNode. I think this is where Campbell's idea of the Child-Parent relationship being an "inverted" tree, where the child (biological relationship sense) is the ParentNode (design sense) to the two ChildNodes (design) that represents that child's parents (biological). It may be a little bit counterintuitive and confusing but it's not an "incestuous" design but rather just a matter of an "upside-down" perspective.

The role of Spouse or Partner is a social/legal association and I think is more appropriately modeled with a life event. Adoption would be another life event. Evaluating whether a person is a Spouse or Adoptee or whatever involves going through that Person's list of life events and figuring out they play a specific role in that life event. So an Adoption would have a list of people involved where each entry is a reference to the person and their role. This way, you can neatly keep the biological relationships firmly in the Person class while the social/legal relationships being define in each person's list of LifeEvents. Two-way links would exist to each life event and the people involved who play a role in that event. For example a Marriage event will involve two people, normally one Person has the Husband role and another Person the Wife role. If you want to support same-sex marriages, then you could have a Marriage event that allowed a Spouse role for both people involved. Implementation-wise, I'd probably have the LifeEvent keep a Map<Person, Role> to track who is involved in that event and what their particular roles were in it. Then a Person would just have a List<LifeEvent>. Then it's easy to answer "Is John adopted?" and "Who are John's adoptive parents?" and "When was John adopted by Bill and Sue?"

Regarding a Birth event, it may be necessary to treat this as a special case, since you're not only creating a social/legal association but also a biological one. It might lead you to create role(s) for BioParent / BioFather / BioMother. This means that you might have other roles like LegalParent / LegalFather / LegalMother. I don't know. Maybe a Person as Node doesn't even need Parent/Child fields at all then and just needs a List<LifeEvents> to allow inference of all of a person's relationships, biological or otherwise. I'd have to experiment with these ideas with some actual code to know for sure.
 
Winston Gutkowski
Bartender
Posts: 10780
71
Hibernate Eclipse IDE Ubuntu
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Piet Souris wrote:after nearly 140 posts in which each has highlighted the superiority of his design, compared to the rubbish of the others , why not put the ideas to the test? Say, before June 1st, send your FamilyTree (or whatever) to OP, complete with instructions, let him/her apply it to whatever he/she has, and then let OP decide the winner.


June 1st? You must be joking. I'm still faffing around with the model; you can't expect me to come up with an app before ... oooh ... September.

That said, it does kind of intrigue me as an app (son of a szlachta Pole, who are obsessed with family trees), so I may take up your challenge.

But the thing I enjoy most is discussing stuff like this - especially since Junilu and I come from very different backgrounds.
I had 35 years years of doing; let me enjoy my dotage.

Winston
 
Winston Gutkowski
Bartender
Posts: 10780
71
Hibernate Eclipse IDE Ubuntu
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Junilu Lacar wrote:I think you may have found a better way to look at this. Parent, Child, Adoptee, Husband, Wife, Spouse/Partner, etc. are all Roles that the same person can take on.


Me? I thought it was you. I've tried to be as minimalist as I can all through this.

I hate to say, because I'm enjoying the discussion, but Piet does have a good point: Do it.

And for me, that comes back to first principles: What is a family tree?
What information do we want it to hold?
What do we want to do with it?

All the esoteric stuff can be put on hold (but not forgotten) until we know what our family tree is supposed to do.

So I'm gong to have a look at a few sites (I'm a member of one) before I make any more pronouncements. I think we're on the right lines; I just need some confirmation.

But thanks for all the input; you make a great "sparring partner".

Winston
 
Junilu Lacar
Sheriff
Posts: 17734
302
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Piet Souris wrote:
after nearly 140 posts in which each has highlighted the superiority of his design, compared to the rubbish of the others , why not put the ideas to the test?
Say, before June 1st, send your FamilyTree (or whatever) to OP, complete with instructions, let him/her apply it to whatever he/she has, and then let OP decide the winner.


I'm sorry, I didn't realize this was a contest although I can understand how it might be perceived as such. I never meant any of my comments to imply correctness/superiority of my ideas over those of others. I'm merely pointing out flaws/smells that I'm detecting. Even the things I have thought out have flaws, which I have readily admitted. I don't see this as a contest at all. It's just an interesting discussion about the merits and/or gaps in ideas that have been put on the table.

I'm not even concerned about whether or not OP decides to go with one or any combination or none of the design choices we've discussed.

If you're going to think that this is a contest where each person tries to prove the superiority of his ideas over everyone else's then I don't think you're going to get much out of this discussion. I have gotten so much out of it so far precisely because I don't see it as a contest or one of "I'm right and all you guys are wrong." I have in fact, as pointed out previously, tried to implement some of my ideas and those of the OP. I quickly ran into problems with some of my ideas. I definitely ran into problems with the ideas that the OP presented, pretty much as I had warned. With respect to OP's ideas, I think I gave it my best good-faith effort to refactor some of the code he shared and make it work but have to admit that some of my prior comments may have made me inherently biased and led me to conclude that it just wasn't a workable design.

I haven't tried any of Winston's ideas out but I trust he'll try to do or already has done it himself.

I actually used the idea that Campbell shared about two relationship and I also used Dave's suggestion for an event model. So really, the idea that we're trying to outdo and beat each other down is really just a matter of a perception which I don't think is right.
 
Junilu Lacar
Sheriff
Posts: 17734
302
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Winston Gutkowski wrote:

Junilu Lacar wrote:I think you may have found a better way to look at this. Parent, Child, Adoptee, Husband, Wife, Spouse/Partner, etc. are all Roles that the same person can take on.


Me? I thought it was you. I've tried to be as minimalist as I can all through this.


Ok, then I'll rephrase: Your comments/ideas have made me pivot in a direction that seems to be a better way to look at this.
 
Winston Gutkowski
Bartender
Posts: 10780
71
Hibernate Eclipse IDE Ubuntu
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Piet Souris wrote:Why not put the ideas to the test?


After looking at the site I'm a member of, I started ... and almost immediately ran into a problem: How to specify "partial" dates for events that you don't know exactly.

So I'm currently working on an EventDate class that allows you to do precisely that - which is a fun exercise in itself.

But like I say: September is looking much more likely than June.

Winston
 
Happily living in the valley of the dried frogs with a few tiny ads.
New web page for Paul's Rocket Mass Heaters movies
https://coderanch.com/t/785239/web-page-Paul-Rocket-Mass
reply
    Bookmark Topic Watch Topic
  • New Topic