Unless, of course, you need to add/remove roles at runtime. Then you might use something like ERRole and role based permissions provided in ERAuth :-)
On Nov 15, 2013, at 8:34 AM, David Avendasora <[email protected]> wrote: > On Nov 15, 2013, at 7:47 AM, Ken Anderson <[email protected]> wrote: > >> As much as I hate to admit it - David’s right :) > > I understand the feelings of discomfort and outright-filthiness that such a > statement has caused you in writing it, and everyone who read it. I hope that > someday I can do something to make up for it. Maybe I can make today that > day! :-) > >> Inheritance is useful in some places, but you should really use a different >> pattern when dealing with people, companies, and roles. >> >> One place I DO use inheritance is when Roles have different attributes. So, >> I might have something like: >> >> Role >> AccountingRole >> SuperuserRole >> PersonnelRole > > Yeah, once you’ve abstracted the different properties and behaviors to > different Roles, those can all inherit from a common Role superclass, but > that is only really useful if there are attributes and relationships that you > need to save in the database that the different subclasses all have in > common, otherwise you are again forcing an architecture on something that > doesn’t really need it, and could become a limitation in the future. > > If Role is an abstract superclass, then just make it an Interface instead. > You can add an abstract “DefaultImplimentation” inner class to the Interface > that has any common business logic for the defined interface so you don’t > have to write duplicate code (since an interface can’t have method > implementations). DefaultImplimentation would itself extend > “ERXGenericRecord”. > > In this situation, AccountRole, SuperuserRole, etc. would implement IRole, > and extend IRole.DefaultImplementation. The hardest part about doing this is > that you’ll have to modify the EOGenerator templates to make this work > because the EOModel has no understanding of Interfaces, or that some EOs > might extend something other than another Entity or EOGenericRecord. > > Then, of course, there is the “opportunity" to use Generics so you aren't > constantly casting IRole object into one of its implementors... > > But, this could be an example of too much abstraction… in which case, maybe > now you’ll sleep better, Ken! > > Dave > > >> On Nov 14, 2013, at 8:49 AM, David Avendasora <[email protected]> >> wrote: >> >>> Hi Ted, >>> >>> Here’s my opinion (hey, you did ask for it!): >>> >>> I believe the kinds of inheritance being suggested here are all the wrong >>> way to model it. It is almost always better to model an association as >>> “has-a” rather than “is-a”. (keep reading to see what I mean by that) >>> >>> I, personally, avoid inheritance in the EOModel if at all possible. Not >>> because it is bad or hard to work with, but because in most cases it is not >>> the *right* thing to do. Just like if I write non-UI code that uses >>> “instance of” I know that I’m almost certainly doing something wrong. Not >>> always, but often enough that I will stop and take a step back and REALLY >>> look at how it is architected. >>> >>> If you model the Person/Client correctly you will have no problem with how >>> to model the relationship to Address. That issue will solve itself. >>> >>> Okay, let’s get started: >>> >>>>>>> Except Clients tend to be businesses with EINs instead of SSNs. So >>>>>>> there really are Clients. >>> >>> Bzzzzzt. Tend to be?! If you are going to use a structure as inflexible as >>> inheritance on this they MUST ALWAYS BE, or there must be a very important >>> business rule that keeps them separate. Is it really true that you never, >>> ever, ever have a client that is just one guy and he doesn’t have an EIN? >>> Or have a Person that has a relationship to other People? Those are >>> perfectly legitimate concepts, yet you are forcing it to not be workable. >>> >>> I think being a client is a role that an Object has (has-a) not what it is >>> (is-a). Sometimes it acts like a “Client", at other times it could act like >>> a “Vendor” and maybe, just maybe, if the Organization is a very simple one, >>> it acts like a “Person" >>> >>> I think Marcus’ suggestion of LegalEntity is great, I’ve also used “Actor” >>> in the past. “Entity" would be ideal, but well, that’s a bit overloaded >>> here in WOWorld! :-) >>> >>> But! Instead of extending LegalEntity with subclasses for Person, Client, >>> Vendor, WOGod, etc. You have a “Role” table that has one row for each of >>> those. Now instead of a LegalEntity needing to be (is-a) one *and only one* >>> of those subclasses, it can take-on any (has-a) Role (LegalEntity <<=> >>> Role)s or even have multiple *simultaneous* roles (LegalEntity <<=>> Role)! >>> So a Person could also be a Client and would have all the attributes and >>> behaviors of both. >>> >>> This allows your to abstract away all the behaviors and such that are >>> Person-specific, Client-specific or Vendor-specific to delegate classes for >>> each Role. The delegate classes are where you have the role-specific >>> implementations. >>> >>> For example, LegalEntity's method taxIdentifier() simply asks the delegate >>> for the value. >>> >>> public String taxIdentifier() { >>> return delegate().taxIdentifier(); >>> } >>> >>> The CLIENT delegate’s implementation of taxIdentifier() is: >>> >>> public String taxIdentifier() { >>> return employerIdentificationNumber(); >>> } >>> >>> The PERSON delegate’s implementation is: >>> >>> public String taxIdentifier() { >>> return socialSecurityNumber(); >>> } >>> >>> Now imagine something much more complicated such as “exportAllContactInfo” >>> where “Client” needs to iterate over all the employees parse their contact >>> info, flag which ones may perform a specific role and add them all >>> individually to to a single .vcf file that holds multiple contacts. The >>> Person simply writes writes out their own contact info into the .vcf. Each >>> implementation goes in the delegate and the LegalEntity doesn’t know >>> anything about what it takes to put each one together. It’s totally >>> encapsulated in the delegate. >>> >>> You can enforce what actions a delegate must be able to perform by creating >>> Interfaces that both the LegalEntity and Delegate implement. The >>> LegalEnity’s action() implementation will simply be to call >>> delegate().action() >>> >>> The biggest drawback to this architecture is the level of abstraction is >>> much higher and therefore can be more complicated to get setup, but it is >>> soooo much more flexible and much more future-proof. >>> >>> The art of software architecture is knowing when to stop adding levels of >>> abstraction. I think this level of abstraction is always preferable to >>> Inheritance. >>> >>> Now, back to Address (finally) >>> >>> You are left with: LegalEntity =>> Address >>> >>> Easy, no? >>> >>> (you can model the back pointing relationship if you need a delete rule >>> other than “nullify” when you delete an Address. >>> >>> Now for some un-asked-for advice! :-) >>> >>> Do NOT normalize Address! It does not matter if the same address is both >>> billing and shipping. Put it in there twice - even if UI makes it look like >>> it is just one. >>> >>> This avoids the problem of someone wanting to change only their shipping >>> address but because that one record was both, they end up editing their >>> Billing address too. The UI design needed to deal with one Address with >>> multiple “types" is much more complicated than the UI design needed to >>> manage multiple identical ones. >>> >>> Dave >>> >>> >>> On Nov 13, 2013, at 11:37 PM, Ray Kiddy <[email protected]> wrote: >>> >>>> >>>> On Sep 16, 2013, at 9:51 AM, Joel M. Benisch <[email protected]> wrote: >>>> >>>>> Markus: >>>>> >>>>> As per the private email I sent you over the weekend, which you can most >>>>> certainly send to the list if you like, I believe that you are confusing >>>>> things that occur in nature (Organizations, People and Addresses) with >>>>> the "Roles" that they play in your (or any) environment and >>>>> implementation. >>>>> >>>>> Have an Entity Object/Table that can contain two types of objects, People >>>>> and Organizations. A variable in the object will tell you which type >>>>> "this" object happens to be. >>>>> >>>>> Have an object/table that defines the role that any Entity is "playing" >>>>> in any given situation. You can therefore have in infinite number of >>>>> Role Types. >>>>> >>>>> Than have an "EntityAggregate" object/table if you need it. This would >>>>> be used to relate multiple Entities together into any type of group you >>>>> may need. Include an AggregateType variable and you can have an infinite >>>>> number of aggregate types. This allows you to handle Departments, >>>>> Offices, Spouses, Families or any other type of combination of people you >>>>> may need. It also allows you to aggregate organizations should you need >>>>> to do that, like all Vendors of a given type, or all Clients that are >>>>> serviced by a given employee, or whatever. >>>>> >>>> >>>> The entire bit above can be summarized as "use single-table inheritance". >>>> Just FYI. Different sub-entities, even if in the same table, can have >>>> different attributes, and it is simple if the attributes are not mandatory. >>>> >>>>> Then you have an Address Object/Table. Addresses can then be associated >>>>> with any member of the Entity Table, or any number of members of the >>>>> Entity Table, and you're all set. When an employee or Vendor or Client >>>>> moves, you don't delete or change the existing (now old/obsolete) address >>>>> from the table, you add the new one and flag it as "current" if you want. >>>>> This way, old data will still display and associate to the correct old >>>>> address that was valid at the time the invoice, or purchase order, or >>>>> whatever was processed. It also allows you to use the "old" address on >>>>> another Entity when some other Client or Vendor happens to rent the same >>>>> space that had previously been occupied by the first one. >>>>> >>>> >>>> I tend to add a deletedDate attribute here. Then, adding a "and the >>>> deletedDate is null" qualifier whenever I fetch objects ensures I only see >>>> the current ones. >>>> >>>>> We work in the Insurance Industry. This approach has stood the test of >>>>> time (three decades) quite well. >>>>> For instance, a person can be a Client, and also a spouse of another >>>>> Client, and also the Parent of another Client, and therefor a member of a >>>>> Family Aggregate. That same person can be a Driver on an Auto Policy, an >>>>> Insured on various policies, an officer of a Client that is an >>>>> Organization Entity, etc. These are all Roles that this Person Entity is >>>>> playing. >>>>> >>>> >>>> Wow. Why can't my insurance company do this? My insurer has an idea that >>>> my wife is primary on the account and they can't figure out how I relate >>>> there. We kept separate last names. What were we thinking. :-) >>>> >>>> >>>>> The person appears once in the Entity Table, but can be used for an >>>>> unlimited number of Roles. >>>>> >>>> >>>> Just remember, entity inheritance can be your friend, especially if done >>>> right. >>>> >>>> - ray >>>> >>>> >>>>> Hope this helps, >>>>> Joel >>>>> >>>>> On Sep 16, 2013, at 8:59 AM, Markus Ruggiero wrote: >>>>> >>>>>> >>>>>> On 15.09.2013, at 06:28, Theodore Petrosky <[email protected]> wrote: >>>>>> >>>>>>> Except Clients tend to be businesses with EINs instead of SSNs. So >>>>>>> there really are Clients. But sometimes in accounting an employee is a >>>>>>> vendor because you need to draw a check outside of the normal employee >>>>>>> employer relationship. >>>>>>> >>>>>>> I am trying to normalize this structure. Maybe I shouldn't. I would >>>>>>> love to hear other people's solutions. but to reiterate, Clients need >>>>>>> addresses, People need addresses. if I create a table Address, I could >>>>>>> relate it back to Client, and relate it to Person. >>>>>>> >>>>>>> So maybe I should change the name to: >>>>>>> >>>>>>> Business >>>>>>> Person >>>>>>> >>>>>>> Person will have two booleans 'isEmployee', and 'isClient', with a SSN >>>>>>> Business will have two booleans 'isClient', and 'isVendor' with an EIN >>>>>>> >>>>>>> both will have a to-many to Address and each address will have a type >>>>>>> (i guess a business address will not be a 'love-nest'). >>>>>>> >>>>>>> I just never created an Entity that related back to two other Entities. >>>>>>> So does that mean >>>>>>> >>>>>>> Business <=>> Addresses >>>>>>> Person <=>> Addresses >>>>>>> >>>>>>> and because of the structure, the relations have to be optional. >>>>>>> although an address will always be related to either a Business or a >>>>>>> Person. >>>>>>> >>>>>>> >>>>>>> Or how about an Entity Address and a subclass PersonAddress and another >>>>>>> subclass BusinessAddress? >>>>>>> >>>>>>> Opinions? >>>>>>> >>>>>> >>>>>> >>>>>> I would model this like so: >>>>>> >>>>>> Entity "LegalEntity" with "Client" extending "LegalEntity" and >>>>>> "Business" extending "LegalEntity". Both, Client and Business share many >>>>>> common attributes like name etc, Both can have individual attributes >>>>>> like SSN for Clients and EIN for Businesses. >>>>>> Now the addresses: How to model these depends on the answer to the >>>>>> following question: Can the same address be used for different purposes? >>>>>> If no: >>>>>> Create an entity "Address" and have one attribute called "addressType" >>>>>> or some such. AddressType is one out of "home", "work", "love nest" etc. >>>>>> and model "LegalEntity" <-->> "Address" >>>>>> if yes: >>>>>> Create an entity "Address" without a type specifier. Create an >>>>>> intermediate entity like "LegalEntityAddress" with an attribute to >>>>>> specify the type. Model the following relationships: >>>>>> "LegalEntity" <-->> "LegalEntityAddress" <<-> "Address" >>>>>> >>>>>> Hope this helps. >>>>>> Have fun >>>>>> ---markus--- >>>>>> >>>>>> >>>>>>> >>>>>>> On Sep 14, 2013, at 10:29 PM, Ramsey Gurley <[email protected]> >>>>>>> wrote: >>>>>>> >>>>>>>> Personally, I would look more closely at your person class. Is a >>>>>>>> client actually a person too? It sounds like it. If so, I would not >>>>>>>> have a client entity. I would simply make a person entity and assign >>>>>>>> each person one or more roles. A person might have a client role, a >>>>>>>> vendor role, and a customer role. Then you simply have a relationship >>>>>>>> between person and address. >>>>>>>> >>>>>>>> >>>>>>>> On Fri, Sep 13, 2013 at 9:29 PM, Theodore Petrosky <[email protected]> >>>>>>>> wrote: >>>>>>>> I need an opinion about relationships. >>>>>>>> >>>>>>>> I want to have an entity Person with a to-many to address. a Person >>>>>>>> could have many addresses (home, second home, weekend place, love >>>>>>>> nest). >>>>>>>> >>>>>>>> And I have clients. a Client needs addresses too (billing, main >>>>>>>> office, act rep, etc) >>>>>>>> >>>>>>>> how would you model this? >>>>>>>> >>>>>>>> a person entity with a to-many relationship to address >>>>>>>> a client entity with a to-many relationship to address >>>>>>>> >>>>>>>> or would you create a subclass of address and map that to the clients. >>>>>>>> >>>>>>>> is it 'bad' to have two to-many relations to an entity, (both person, >>>>>>>> and client mapped to entity address). >>>>>>>> >>>>>>>> Ted >>>>>>>> >>>> _______________________________________________ >>>> Do not post admin requests to the list. They will be ignored. >>>> Webobjects-dev mailing list ([email protected]) >>>> Help/Unsubscribe/Update your Subscription: >>>> https://lists.apple.com/mailman/options/webobjects-dev/webobjects%40avendasora.com >>>> >>>> This email sent to [email protected] >>> >>> >>> ————————————————————————————— >>> WebObjects - so easy that even Dave Avendasora can do it!™ >>> ————————————————————————————— >>> David Avendasora >>> Senior Software Abuser >>> Nekesto, Inc. >>> >>> >>> >>> >>> >>> _______________________________________________ >>> Do not post admin requests to the list. They will be ignored. >>> Webobjects-dev mailing list ([email protected]) >>> Help/Unsubscribe/Update your Subscription: >>> https://lists.apple.com/mailman/options/webobjects-dev/kenlists%40anderhome.com >>> >>> This email sent to [email protected] > > > ————————————————————————————— > WebObjects - so easy that even Dave Avendasora can do it!™ > ————————————————————————————— > David Avendasora > Senior Software Abuser > Nekesto, Inc. > > > > > > _______________________________________________ > Do not post admin requests to the list. They will be ignored. > Webobjects-dev mailing list ([email protected]) > Help/Unsubscribe/Update your Subscription: > https://lists.apple.com/mailman/options/webobjects-dev/rgurley%40smarthealth.com > > This email sent to [email protected]
_______________________________________________ Do not post admin requests to the list. They will be ignored. Webobjects-dev mailing list ([email protected]) Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/webobjects-dev/archive%40mail-archive.com This email sent to [email protected]
