Monday, June 23, 2014

FW: independence among properties within a class

Let's say I have a class call Person, and in the class I have 2 read / write properties as following:

Public Property Age As Integer
Public Property DateOfBorth As Date



so I would be able to have code like the following:

Dim myself As Person = New Person()
myself.Age = 100
myself.DateOfBorth = DateTime.Today

Will you design a class like that? I bet you would say No. why? ( please pause for a moment to think about the reason before proceed)
When we design a stateful class, at any point of the object's life time, the object holds its state. You want to design your class in such a way, that the state of the class always valid through out the life time of the object. In this case, how can a person who is 100 years old but the date of birth is today. this is clear case of invalid state. we made it posible by defining 2 independ property for 2 pieces of informaiton which is depends on each other..
this is not something made up. we have this kind of problem in our object model almost all of the palce. Take a look at a property we recently added to TitleRegBE.VehicleReplicationFlashType
The principle applied here is : define indenpendant property only for independent data points. if one piece of data can be calculated using other data points, we will say that piece of data is not indenpendant. so do not make it so by defining an indenpendant property.
How to tell this kind of bad smell in the code? let me share with you some tips I got throught many years of programming experience in OOP.
for a state-full class
1) when you add a property without touching presistant layer
2) when you add a property without add a database column ( if you would request the DBO to add the column, a qualified DBO would rejected your request citing normalization rule)
3) when the value of the property is set by using other property of the same class

How to fix it? the following are a few stratgey to fix this kind of problem:
1) make it read only property
2) still make it read/write property, but build some logic in the setter of the respective properties to maintain the relationship
3) make a funciton which take an instance of the class and return the data point you need

The respective code is shown below:
Public ReadOnly Property Age As Integer
Get
Return DateTime.Today.Year - Me.DateOfBorth.Year + 1
End Get
End Property

Public Property Age As Integer
Get
Return DateTime.Today.Year - Me.DateOfBorth.Year + 1
End Get
Set(ByVal value As Integer)
Dim yearOfBorth As Integer = DateTime.Today.Year - value + 1
DateOfBorth = New Date(yearOfBorth, DateOfBorth.Month, DateOfBorth.Day)
End Set
End Property


Public Function GetAge(ByVal person As Person)
Return DateTime.Today.Year - person.DateOfBorth.Year + 1
End Function

No comments:

Post a Comment