I'm trying to put together some basic models in OOP (C#), and apparently I've got the wrong idea.
If I have a Workman's Comp case, it is applied to a Patient. It also has one or more PatientVisits applied to the case. Each PatientVisit though, also has a Patient associated with it, and of course a Patient can have any number of Visits associated with it.
My original thought was to create basic, real-world reflections of the business models by doing something like:
class Patient {
int ID;
string FirstName;
string LastName;
List<Visit> Visits;
}
class Visit {
int ID;
DateTime VisitDate;
Patient Patient;
List<DxCode> DxCodes;
}
class WCCase {
int ID;
Patient Patient;
DateTime DateEntered;
List<Visit> Visits;
}
I naively thought that'll be nice, I'll just load up my model and have everything at hand, very semantic and representative of the domain/real-world, right?
So, I can go the opposite route and fill the parent object and store lists of IDs for related models:
class Patient {
int ID;
string FirstName;
string LastName;
List<int> VisitIDs;
public static Patient GetPatient(int id) {}
}
class Visit {
int ID;
DateTime VisitDate;
int PatientID;
List<DxCode> DxCodes;
public Static Visit GetVisit(int id) {}
}
class WCCase {
int ID;
int PatientID;
DateTime DateEntered;
List<int> VisitIDs;
public static case GetCase(int id) {}
}
This of course allows me to load everything on demand (get an ID and grab the object through it's Get*() method), but seems a bit of a step away from the idea of a nicely representative real-world model and more like a mirror of a database table representation.
I'm guessing there must be some middle ground, but I'd sure like some advice on finding it… Can anyone give some basic examples of how we'd model this without going nuts with references and circulars, etc?
Thanks in advance.
Best Answer
Addressing the Basic Question
It depends. (thanks Bob?)
Whatever. This is an implementation detail. It should not drive domain design. I am not saying either of the (as of this writing) two answers is wrong. I'm saying this aspect should be better incapsulated and then exposed in domain terms.
Encapsulating Data Fetching
Domain Analysis
As with any good Gummit bureaucracy you are just a number to them. And so a workers comp thing is who you are, what you do, what they do (to you), etc. This thing sounds like a class and this thing is a number. But it is not an
int
, it is a "Workers Comp Case File" let's say.Further, we have all these circular references. Nothing wrong with these per-se from an OO design perspective.
Data Points
IDataFetch
interface that all classes implement. There could be delegates or event handlers soWorkersCompCaseFile
transparently does it for it's components.protected
vicepublic
propertiesprotected int ID
- do not expose the ID period. It's an internal unifying concept.Patient
,Visit
, all have a reference to their containingWorkersCompCaseFile
Patient.Visits
is a pass-through reference to the case file object.MyHardCase.Name
viceMyHardCase.Patient.Name