*** Note I'm doing this post series using Orcas Beta2. So most of my code samples will be using whatever new baked in goodness I can garner from new VS. So far I'm really amazed with this release of VS 2008, aside from awesome JavaScript Intellisense, and a generally lighter, faster feel, the big thing for me is that the 2 Deal Breaker issues I've had with the VS Unit Testing facilities have been fixed. As A long time TestDriven.Net user, It was an absolute requirement to have a right click Run Tests, that would either execute a full TestFixture or single Test based on Context. Second was the ability to double click on the Error output and go straight to the line of Code that barfed. Glory be, they are both fixed (I always thought of them as bugs, not missing features), and I now am sold on the VS way, I am not worthy…
The first part of the Plebian U domain I want to work through is the "person." I want to see if it's possible to encapsulate the full range of Employees and Students into a single object. I'm pursing this for my model as for the most part employees do not differ from students until the business logic layer. Sure employees get a salary or wage, and students pay tuition, but those are either actions of the University or students, not attributes of a person.
There are differences to be sure, but I think that I can encapsulate those within the bounds of a Role object. This allows me to define a person who has 0-n Roles, and not have to maintain separate objects to represent the same actual person. Another key constraint I'm placing on myself is that I'm not going to be using Interfaces. This is partly to help maintain as simple of a structure as possible, and partly because I'm not worried about things like lazy loading or late binding. In general those are very useful considerations for a large application, but my overriding principle here is to have something I can very quickly customize to my current needs, without getting hung up on things like Versioning or configuration headaches that go hand in hand with those wonderful runtime typed domains.
So I'm going to start by trying to identify everything that I think all employees and students have in common:
- Names – First, Last and Middle<opt>
- Date Of Birth
- Unique Id – something the student/employee can use on forms (often this is an SSN, but I'm thinking more generic)
- Status – Active, Inactive or Current/Former, I see the roll object distinguishing Full-Time or Part-Time
- Addresses – Mailing, Home, Billing, Emergency, other,
- Phone-Numbers – Residence, Cell, Work, Emergency
- Email Addresses – Personal, Work, Emergency
What about the differences, like the students' grades, or class schedule, or a professor's class schedule or Start Date? Those are all really just other Domain objects. Employees will have an EmployeeRecord, and students will have things like an EnrollmentRecord, CurrentSchedule, and Transcript. By keeping things simple like this I'm getting at least 2 benefits, first is the ability to have my domain follow a reasonable pattern of normalization, and second Flexibility. If I create a Person with Roles, and Contact info, and basic Bio info, I can use that person object in an application for say a Gym. A person really is just a person, and it's useful not to clutter the domain with specifics that are not really necessary. It should be the Data not the format that tells us what we need.
Say I was making an application for an auto dealer. One of the objects I certainly have is a Car. It wouldn't make much sense to track something like "SellerID" as a property of the Car, it's totally unrelated. The same applies to our Person. A Person can do and posses many things, but neither the Actions, nor the Possession are actual properties of the Person.
One thing I've done thought is decided that I want to encapsulate a Person's Addresses, Phone-Numbers and Email Address as ContactInfo. It's a natural division, partly following the idea above, and partly violating it. Since the U cannot have a Person without some ability to contact them, it's fair to make it a property of the Person. Yet as both a nod to flexibility and separation of Domains, I see benefit in pulling it off as its own group. I may be totally wrong about this, but here's how I see my person domain object.
public class Person<T>
{
public int PersonID { get; set; }
public PersonReadableID<T> ReadableID { get; set; }
public Status Status { get; set; }
public List<PersonRole> Roles { get; set; }
public ContactInfo ContactInfo { get; set; }
public string FirstName { get; set; }
public string MiddleName { get; set; }
public string LastName { get; set; }
public DateTime? BirthDate { get; set; }
}
Some things to note: Status is an Enum; PersonReadableID<T> will likely die an untimely death, I'm looking for a way to give a person a unique ID like an SSN, that we can persist with the person Record, and this gets me that for now, but I don't like it too much; List<PersonRole> is a placeholder, I haven't gotten to Roles yet, but I know I need them; ContactInfo is also mostly just a stub, but here's a look at where I think I'm going.
public class ContactInfo
{
public int ContactInfoID { get; set; }
public List<PhoneNumber> PhoneNumbers { get; set; }
public List<Address> Address { get; set; }
}
public class PhoneNumber
{
public int PhoneNumberID { get; set; }
public string Number { get; set; }
public PhoneNumberType PhoneNumberType { get; set; }
}
public class Address
{
public int AddressID { get; set; }
public AddressType AddressType { get; set; }
public string Street { get; set; }
public string City { get; set; }
public string State { get; set; }
public string Zip { get; set; }
}
With the Contact Info I'm not sure how I want to enforce grouping. IE should an Emergency Phone-Number and Address be treated as a single unit, or should it be the responsibility of the BLL to extract that info on demand, but that's for a later post, I've got some code, and some unit tests (won't bother posting most of those as they're very plain at this point).
Print | posted on Thursday, October 25, 2007 10:36 PM