Techniques and issues for modeling people, organizations, locations, contacts, and addresses in a flexible way.
Martin Fowler's "Party Pattern"
Why do it this way? To share "address" structure? It is possible for a "party" to have multiple addresses (multiple contacts). Thus, I usually have a "Contact" entity, and then people or companies can be linked to one or many Contact records/objects as needed.
This pattern is a part/whole aka CompositePattern variant. A Party can be composed of multiple other Party instances, thus representing a Company of Companies or a Company of Persons. Whether or not a Party instance that is a Person can have sub-Persons is a question for the philosophers.
Then why does it say "inherits from"? Read it as "is-a-kind-of".
Also, a customer could be a person one day, and then a group of people the next as his/her/their business expands or multiple family members handle issues. A "person" and "contact" should not be confused. You should only track something as a "person" if the law requires it or we are dealing with physical bodies, such as for medical reasons. For example, employees are required to be persons, but customers are not. (An "employee" entity could still reference one or more Contact records.) Thus, we should not dichotomize customers into persons or organizations because of the fuzzy border between the two. If we know, we may track it (as an attribute) for marketing research reasons, but otherwise we don't have to care. I smell LimitsOfHierarchies coming into play if we do some IS-A things like that above.
I think the above discussion misses the point. Here is my summary of the PartyPattern.
When you are building business systems, you often need to refer to a person, like a customer, a supplier, or an employee. Wait! Are you sure you want to refer to a person? Perhaps that entity might be a corporation, or a role played by different person each day. Maybe you should instead talk about the "party", like the "party that bought the item" or "the party that we should pay". If you are sure that the entity will always be a person, fine. But if not, make "Party" be the supertype of the different entities that could fill that role.
Exactly. In my experience, the PartyPattern is used in conjunction with RoleAndPlayer. Together they cleanly model situations in which roles in the problem domain (such as buyer, supplier, etc.) might be played by either people or organizations. --RandyStafford
Party might have attributes like address, or it might be entirely an interface. The implementation of Party will vary and is not really important. What is important is not painting yourself into a corner.
I don't see how this addresses multiple contacts or the possibility of adding multiple contacts in the future; and which is "primary" contact may be relative to user. I just don't think IS-A is appropriate here. We have entities like Employee, Customer, Vendor, etc., but whether they have one address/contact or a thousand should not be hard-wired up front.
Perhaps the role a thing plays and whether they are a person or an organization are orthogonal, or should be treated as orthogonal if we want a truly "generic" system. However, for smaller systems it may not make sense to have this much indirection. We have (at least) 3 factors to consider:
After thinking about this over the years, I don't think there is any One Right Way to model people and organizations. EverythingIsRelative. A person can grow into a big company or organization and visa versa. Different roles can have the same contact and the same role can have different contacts. The change patterns and potential combinations are full of many-to-many situations. The best we can hope for is to find a UsefulLie for specific situations or organizations (viewpoints). The only common pattern I see is some kind of address or contact record/object (street address and phones, etc). And even that is changing with all the different ways to contact people these days (email, fax, pager, blackberry, etc.) What references such a contact thing is sky open. Open or company-specific questions include:
-- top
I remember using a primitive name-and-birthday application to remind me of important days. One of the FAQs was "how do I put in wedding anniversaries ?". The work-around was to put the married couple in as if they were one party, in the terminology of this page.
So its primitive database has something like
1980-06-27: Mr. John Doe 1981-02-12: Mrs. Jane Doe 2001-03-19: Mr. and Mrs. John and Jane DoeWhen the app reminded me that "Mr. and Mrs. John and Jane Doe will be 3 years old tomorrow", I'd have to mentally translate that to "Mr. and Mrs. John and Jane Doe will have their 3rd wedding anniversary tomorrow".
Well, that is a poorly designed tool IMO. It is not much of a leap to make it more generic for other types of events. BargainFutureProofing. Then again, if you'd put "Mr. and Mrs. Doe's Marriage", then it would technically give the right answer because it is the marriage's "birthday", which is just a long way to say "anniversary".
One practical approach I've seen for dealing with all the little values such as phone numbers and email addresses is to have those in a separate table from the street addresses (not shown here).
table: phone_and_misc ------- customerID numType // day-phone, night-phon, email, fax, etc. theValue priority // numeric notesIf you need to reference back to the street address(es), then more columns or a link table may be needed. If you want a "slotted" version, then you may need more entity tables. I personally avoid those unless there is a specific business need. The client UI should format and check those. A compromise if you have mostly US numbers may be something like:
table: phone_and_misc ---------- customerID numType areaCode prefix // "123" of 123-4567 core // "4567" of 123-4567 extension nonPhone // for email or foriegn numbers priority notes
This topic used to have a sample schema, did somebody delete it? It was at least useful for illustrating the international representation debate. --top
See: CampusExample, ArePhysicalPostalAddressesArchaic, NoSqlCogswellArticle