Generally in the Enterprise Applications like ERP or ERM, CRM, BP etc. we see two things a lot, one of them is Role and the other one is User. What happens is that in the real world we have some persons as the Audiences of the Organization and also we have some roles that each person do his duty as that role. Actually each person has his own information in his file, dependent on the role that he has. Notice that one person can has more than one role.
The question is that How can we model this topic as the OO (Object Oriented) viewpoint?
One way is that we have an Inheritance Hierarchy of Users which each one has his own data and his own behaviors (for example in one clinic we have doctor, patient and Secretary that all of them are derived of the user.) User has list of roles. In this case roles are more likely to Enum and does not have any behavior and the main use of them is Access Control.
The problem of this method is that if a real person wants to have different roles and this issue is completely dynamic, modeling of this wouldn’t be clear.
Second method is that we have one user and an Inheritance Hierarchy of roles that each role has his own duty. We assign this roles to the users. Actually we see the roles in the program and the main operant for us are the roles.
The problem of this method is that for some roles it is necessary that users have other personal information (for example about the doctor the field of study should be defined.) and it is not clear that where we should store these data.
The third method that is not obvious for us is a combination of the two method above.
1
Why don’t you separate the concepts?
Have one bounded context to handle the user identity. This BC will have all data related to the person itself. This should answer “Who is that user?”
Have another BC to control the roles which each user have. This BC will be responsible for answering “Is this user allowed to do that?”
And a 3rd BC for the operations that you need the entity to do. Now you have 3 models for the same concept, but in different contexts. This may sound really complicated, but each BC has a clear definition of what the entity is (different attributes) and what it can do (its responsibilities)
What is dangerous about your approach is that an entity will have many responsibilities. This violates the Single Responsibility Principle and will go out of hands really fast once the applications grows significantly.
1
One way is that we have an Inheritance Hierarchy of Users which each one has his own data and his own behaviors (for example in one clinic we have doctor, patient and Secretary that all of them are derived of the user.)
That’s IMHO not a good approach. You have persons (IMHO a better term than “users”), and “doctor”, “patient”, and “secretary” are clearly roles of a person, because a person can be simultanously a doctor, a patient, and / or a secretary.
Second method is that we have one user
I would call it a person …
and an Inheritance Hierarchy of roles
… yes if your roles are derived from a common “role” class. Now you can have a 1:n relationship between persons and roles.
… The problem of this method is that for some roles it is necessary that users have
other personal information (for example about the doctor the field of study should be
defined.) and it is not clear that where we should store these data.
This depends. At a first glance, a “field of study” is a personal qualification. You gain it independently of beeing a Doctor, maybe at a different point in time. So the natural solution seems to be a 1:n relationship between “person” and a qualification object (or a “Field of Study” object, if that is the only form of qualification you ever need to store).
If you really need that information exclusively for doctors, and only as long as the “Doctor” role is assigned to a specific person, then you can assign it to the Doctor object instead, but I would not recommend it. The functional dependency “each doctor needs to have a field of study” can be enforced by the surrounding application, as part of the role assignment process, it is not mandatory to make “Field of Study” an attribute of “Doctor” for that purpose.
EDIT: here is an example class diagram as a rough scetch, probably some details don’t match your exact requirements, but I hope you get the general idea:
6
Firstly, congratulations on recognising that inheritance is a poor choice in this situation. You are 100% correct. Changing the type of an entity at run-time is definitely code smell!
@Doc Brown’s answer is getting to the heart of the matter, especially the comment about using Person rather than User, and allowing a 1:many between Person and roles.
What is missing here is the period for which the role is valid. For instance, a doctor may also become a patient in middle age, and the patient role may be valid after he retires as a doctor. Similarly, a person may be an employee several times, and may be a manager for one or more periods. The take-out is that roles are time constrained, and as such require their own entity in the model.
I see you are concerned about complexity, and that is natural. My experience has been that if you get the data modelling 100% correct, then there is little complexity. The special cases that require tens of lines of code just disappear – the model reflects reality. For instance it will be able to answer quite complex queries like “what doctors are still on staff that were staff doctors during the Ebola epidemic in 2014?”
The guru in this modelling area is Peter Coad. I suggest http://www.step-10.com/SoftwareDesign/ModellingInColour/ as a suitable introduction to his ideas.
1