Why are People so complicated?

That isn’t a rhetorical question; I really would like to know.

I ran into an old collegue of mine who had just accepted a gig creating your garden variety customer management app (basically a very light CRM and shopping cart). Normally she would have recommended using something off-the-shelf and customizing it rather than wasting time building something from scratch. But the back end was already so simple, and their need to change things in the front end was so frequent, that she needed to write it herself.

She was describing how she will implement the “Person” classes, when I felt a sudden wave of déjà vu as if I was transported back to a previous lifetime as a Soviet Scientist creating the N1 rocket. She was using the Table Profile Provider sample for most of the custom data fields, which would mean that adding a new field or property would have actually created a new column in the data table. The client would then augment the basic properties by editing the Web.config later on.

From the introduction :

The first sample provider (SqlTableProfileProvider) stores each Profile property in a separate database column. Furthermore the provider stores the Profile data without serializing it, which means that the Profile property type needs to be compatible with the target database column.

The second sample provider (SqlStoredProcedureProfileProvider) maps each Profile property to a parameter on a custom stored procedure. Like the table based provider, this provider expects that each Profile property is of a type that is compatible with its corresponding stored procedure parameter. The powerful aspect of the stored procedure based provider is that other than the requirement to implement some stored procedures with a specific set of parameters, you can implement whatever business logic you need in the stored procedures to map the Profile data to your own database schema and database logic.

OK, so she won’t know all the possible profile options the client would need, but there has to be some she just knows would be necessary. I had to ask her why she didn’t just map all possible combinations of profile properties into a couple of extra tables instead.

Now this isn’t the first time I a girl had given me the “wow, he’s a an idiot” look (I’ve lost count of those, really), but it was the first time in a long time, I felt it wasn’t deserved.

Why are People so complicated?

Two very important questions you need to ask when outlining a person in your app….

Which properties would a person have? And which of those would be more than one?

These two interdependent questions will really determine how you define people in your application since the rest is just fluff you can get away with by using the Provider Model for the most part.

  • A person may have several different street addresses for example. Maybe one for shipping and one for billing, and perhaps yet another for separate billing purposes or a separate shipping destination.
  • A person may have several different email addresses; one primary, one personal, one for work, one for spam etc…
  • A person may have several different phone numbers as well. One for daytime, one for evenings, one mobile, one fax etc…

Since as far back as I can remember, from the day I started programming, I’ve adhered to the age old philosophy : I’m a programmer = I’m lazy. But the good kind of lazy. The lazy that doesn’t want to hard-code properties in case they need to be changed. The lazy that doesn’t re-invent the wheel, but only wants to add better rims.

I’ve never believed that it’s prudent nor practical to access or store complex profile properties using the Profile Provider. While this might seem ironic, you also need to consider that it doesn’t have native knowlege of how you’re storing the data. That how is what should determine whether the Profile Provider is appropriate.

A little complexity now will save more of it later on

Consider the following model…

Membership and Profile model

This is an example layout from the Linq to SQL class using the database I created for the OPAR project. I’ll the other tables and matching classes at a later date.

Instead of creating a new column for each profile property, you essentially implement a property bag per member. The MemberProfileField stores all your data with one entry per field. The drawback is that your MemberProfileFields table will get quite large over time, however you’re not altering the schema in any way which means all your content will still be safe. Which brings me to another programming philosophy…

Try to keep your data out of your provider

Tell your data what type it’s storing but nothing else; In this case, I have a field in MemberProfileFields called “FieldType”. This isn’t int, bool, xml etc… It’s actually textbox, multiline, option and so on. You’re creating a web application, so store what input type you’re using to get and store the data. This is very handy for the future as you can add new HTML form types at a later date. The provider logic dictates which field it will tap to store the data.

And back in your profile, you can have a helper class with the following mappings :

text = <input type=”text” id=”{FieldName}” name=”{FieldName}” value=”{ContentText}” />
multiline = <textarea id=”{FieldName}” name=”{FieldName}”>{ContentLongText}</textarea>
option = <input type=”checkbox” id=”{FieldName}” name=”{FieldName}” value=”{ContentBool}” />
… And so on.

Of course, you can do one better by adding a ProfileFieldTypes table to extend this a lot further and substitute FieldType for FieldTypeId with a matching foreign key as well. By branching out the schema to tables, you can actually dynamically create profile properties without ever having to touch the Web.config .