Thursday, May 2, 2013

How to Organize Constant Values

We all know that hard coding is a bad thing in programming. So we create a class’s call AppConstants.  Well, that is better than hardcoding in most of cases, but it is far from good enough. In some case, it is even worse.

First of all, let’s say what should not be treated as constants. Anything that is user (included administrator) changeable, editable or maintainable should not be treated as constant. We must understand that any change of these constant values will lead to code change and build and redeployment before the change take effect.

Now let’s move on to the topic of how to organize constants values.

The first question to ask is: is this group of values representing permissible values of certain fields?  e.g.  CreditCardType (MasterCard, Discover, Visa), Gender (Unknown, Male, Female). If the answer is “Yes” we can group them together as an enum and use enum as data type for these fields. The code example as following:
Public Enum CreditCardType
        None
        MasterCard
        Discover
        Visa
       End Enum

Public Enum Gender
         Unknown = 3
         Male = 1
         Female = 2
       End Enum

Inside your class, you use these enum as data type, for example, inside Customer class you will have Gender property defined as following:
Public Property Gender() As Gender
And inside Payment class, you might have a property indicate the CreditCardType as following:
Public Property CreditCardType () As CreditCardType

And then you can assign values to these properties with the enum values or compare the value of these properties with their respective enum values. the following are some examples:

ShoppingCart.Payment.CreditCardType = CreditCardType.Visa
If Transaction.Customer.Gender = Gender.Male


If the answer to the first question is “No”, we then process to the next question. “If the group of values representing certain attributes of certain entity and meant to be accessed by index. For example, they are position offsets of all fields of certain message, or they are length of each field of certain messages” If the answer to this question is “Yes” we could establish a static dictionary within a static constructor of a class with these group of values as value and the index you want to access them with. The following are some sample code:
Public Shared Sub SetDecalMaxLength()
            DecalMaxLength = New Dictionary(Of VehicleTypes, Integer)
            DecalMaxLength.Add(VehicleTypes.Moped, 5)
            DecalMaxLength.Add(VehicleTypes.Snowmobile, 6)
            DecalMaxLength.Add(VehicleTypes.WaterCraft, 7)
        End Sub

Public Structure Field
    Public Offset As Integer
    Public Length As Integer
    Public Sub New(ByVal offset As Integer, ByVal length As Integer)
        Me.Offset = offset
        Me.Length = length
    End Sub
End Structure

Private Shared Sub SeupUDFileds()
        UD = New Dictionary(Of LegacyCDLISUD, Field)
        UD.Add(LegacyCDLISUD.DriverLicense, New Field(0, 13))
        UD.Add(LegacyCDLISUD.SSN, New Field(25, 9))
        UD.Add(LegacyCDLISUD.FirstName, New Field(34, 30))
        UD.Add(LegacyCDLISUD.FirstNameTruncatedCode, New Field(64, 1))
        UD.Add(LegacyCDLISUD.FirstNameTransliteratedCode, New Field(65, 1))
        UD.Add(LegacyCDLISUD.MiddleName, New Field(66, 70))
        UD.Add(LegacyCDLISUD.MiddleNameTruncatedCode, New Field(136, 1))
        UD.Add(LegacyCDLISUD.MiddleNameTransliteratedCode, New Field(137, 1))
        UD.Add(LegacyCDLISUD.LastName, New Field(138, 70))
        UD.Add(LegacyCDLISUD.LastNameTruncatedCode, New Field(208, 1))
        UD.Add(LegacyCDLISUD.LastNameTransliteratedCode, New Field(209, 1))
        UD.Add(LegacyCDLISUD.DateofBirth, New Field(210, 8))
        UD.Add(LegacyCDLISUD.Gender, New Field(218, 1))
        UD.Add(LegacyCDLISUD.HeightFeet, New Field(219, 1))
        UD.Add(LegacyCDLISUD.HeightInches, New Field(220, 2))
        UD.Add(LegacyCDLISUD.Weight, New Field(222, 3))
        UD.Add(LegacyCDLISUD.EyeColor, New Field(225, 3))
        UD.Add(LegacyCDLISUD.TransactionNumber, New Field(228, 4))
        UD.Add(LegacyCDLISUD.PreviousJuridiction, New Field(232, 2))
        UD.Add(LegacyCDLISUD.PreviousDriverLicense, New Field(234, 25))
        UD.Add(LegacyCDLISUD.PreviousSSN, New Field(259, 9))
        UD.Add(LegacyCDLISUD.PreviouseName, New Field(268, 35))
        UD.Add(LegacyCDLISUD.PreviousDateofBirth, New Field(303, 8))
    End Sub

With the code above, you will get 6 by accessing DecalMaxLength(VehicleTypes.Snowmobile), if a member is defined as VehicleTypes enum type, for example, if we have Type property defined in VehicleBE as following:
Public Property Type () As VehicleTypes
We would get the respective Decal Max length with following code:

DecalMaxLength (MyVehcile.Type)

UD(LegacyCDLISUD.PreviousDateofBirth).Offset will get you 303 and
UD(LegacyCDLISUD.PreviousDateofBirth).Lenght will get you 8
If the above 2 scenario do not match the situation you are handing, suggest to defined a static class with proper name and define constants with the static class. Sometime you may want to put all these type of static class into one umbrella class. The following is an example in our AppConstant class

       Public Class TransactionNumberLength
            Public Const TransactionID = 19
            Public Const NewTransactionID = 13
        End Class

We have come out 3 different ways in treating constants, let me finish this article by addressing the naming of constant,  whither we define them as part of an enum, or define them as constants of a static class, when it comes to naming, we MUST exercise Abstraction.  The following are some naming example which did not exercise abstraction:
Public Const ENTRY_APP_TRANS_NUMBER = "ENTRY_APP_TRANS_NUMBER"Public Const SSN = "SSN"Public Const C As String = "C"Public Const PRINT = "Print"Public Const Number_0 = "0"Public Const EMPTY_STRING As String = ""
Public Enum NumberSeries
            MINUS_ONE = -1
            ZERO = 0
            ONE = 1
            TWO = 2
            THREE = 3
            FOUR = 4
            FIVE = 5
            SIX = 6
            SEVEN = 7
            EIGHT = 8
            NINE = 9
            TEN = 10
            ELEVEN = 11
            TWELVE = 12
            THIRTEEN = 13
            FOURTEEN = 14
            FIFTEEN = 15
            SIXTEEN = 16
….
End Enum
        

An easy way to verify if we have exercised abstraction is to see when we change the value of the variables without changing the name, will it cause confusion. If it does, then we did not exercise abstraction.
The following is an example, in which we did not exercise abstraction well.

<Obsolete("Please use MinimumAgeForRenewal")> Public Const AgeForRenewal = 21

In this case, anyone who knows license renewal policy would know that it is not true that you have to be at age of 21 to be able to renew your driving license rather you have to be age 21 or older in order to do so. Sure enough, this constant will be used to compare with customer’s age when doing renewal. It is kind of dangerous to name the constant after the name of the field they are used to compare with.
The guidelines on constant enum naming are exercise Abstraction and use business term to name them.

Thursday, April 25, 2013

Bad Smells in Code -- By Kent Beck

Duplicated Code
Long Method
Large Class
Long Parameter List
Divergent Change
Shotgun Surgery
Feature Envy
Data Clumps
Primitive Obsession
Switch Statements
Parallel Inheritance Hierarchies
Lazy Class
Speculative Generality
Temporary Field
Message Chains
Middle Man
Inappropriate Intimacy
Alternative Classes with Different Interfaces
Incomplete Library Class
Data Class (dumb class)
Refused Bequest
Comments



Monday, April 22, 2013

New Year Resolution ( I have signed up )

http://manifesto.softwarecraftsmanship.org/

100% bug free

In the commercial software development world, 100% bug free code is either does not exist, or should not exist or code without commercial value.
 

Sunday, November 25, 2012

Three Cornerstones of Business Software

Processes
Business rules
Information

User Experience (UX)

User Experience (UX) design team: Hopefully UX design is a core deliverable and not something we leave to the developers to handle. UX design is sadly overlooked and should definitely have a status elevation. It is important to have close collaboration between the UX team (which could be just one person) and the development team. The best solution is obviously to have a UX expert in the development team all through the project, but that is sometimes not possible. The UX design is so important in making sure users can really perceive the value of the system. We can write the best business logic in the world, but if the UX is badly designed, the users will probably never think the system is any good.



Three Pillars of Application Lifecycle Management

Traceability,
Processes Automation
Visibility