April 2005 - Posts

about www.everyvideogame.com ?

wow... My night is ruined <grin />

Posted by taganov | with no comments
Filed under:

I have a friend that needs to convert some old fortran engineering code to a more modern language for maintainability purposes. Any ideas?

Posted by taganov | 2 comment(s)
Filed under:

This is a great piece of fan-film. Hilarious.

http://www.atomfilms.com/af/content/sith_apprentice

Posted by taganov | with no comments
Filed under:

Nice blog from David Mauri on explaining the importance of a Data Access Layer.

The reward of a thing well done is having done it.
Ralph Waldo Emerson

Posted by taganov | 3 comment(s)
Filed under:

A friend from Atlanta passed this on to me:

"The fantasy element that explains the appeal of dungeon-clearing games to many programmers is neither the fire-breathing monsters nor the milky-skinned, semi-clad sirens;  it is the experience of carrying out a task from start to finish without user requirements changing."

:-P

Posted by taganov | 1 comment(s)
Filed under:

When I composed yesterday's blog, I was focused primarily on the issue of implementing the Interface of the target object in the UI element that edits that object. In my head I was calling it the User Interface Interface pattern, or UI^2. The 7 layers in the system are: UI, FACTORY/FACADE, Security, Data Object, Data Rules, Data Access, and Data Store.

After the quantity and quality of comments that I received on that blog, I have completely shifted focus to the idea of separating Business Rules from Business Objects. I had written no actual code for yesterday's blog--I was simply sandboxing. I took the time tonight to create a VB 2005 solution with all the major working parts. It's still in the rough draft phase, so I haven't fully separated all my tiers yet. I'm going to take some time and do some refactoring of my code based on some of the comments I received, as well as some new ideas I've been thinking about.  Then I'm going to get some web space and post my working solution with each successive blog on this subject.

Design patterns are fascinating.

Posted by taganov | 2 comment(s)
Filed under:

Matt Berther is doing something similar to what I was talking about in my previous post.

Where we differ is where to do the validation of the business rules. He's wrapping his IMyView in a class that knows how to perform the Business Rule validation. I didn't discuss my validation method in my last post, so I'll discuss it here:

Let's say I have a class that knows how to save an IPerson to a DataStore. The Save Method signature looks like:

Public Function Save(p as IPerson) as Boolean

If my Web page or UserControl implements IPerson, I can simply pass the entire page or UserControl to the Save method of my Data Access object. But where does the validation get done?  It gets done during the save attempt.  The UI layer does not have direct access to the Data Access layer. It has indirect access via a set of FACTORY objects. When the UI attempts to save, it does so through a FACTORY class that first performs validation of the Business Rules, and if everything is okay, continues with the save. If the validation fails, then a list of errors is returned to the UI via an event handler.

This separation of Business Rule Objects (policy) from Business Data Objects (data) and Data Access objects (persistence) allows for easily turning various business rules on and off. As new rules are added, old ones are removed, or existing ones change their optional status, only one layer has to be modified: the validation layer. Additionally, this layer can itself be stored in the Data Store and configured dynamically. The UI can and should perform its own validation, but if it doesn't, no harm is done to the underlying system.

Consider the following example. Assume an interface IPerson defined as follows:

Public Interface IPerson

   Property IsACompany() As Boolean

   Property CompanyName() As String

   Property FirstName() As String

   Property MiddleName() As String

   Property LastName() As String

   Property Address() As IAddress

   Property Contact() As IContactInformation

End Interface

 

Public Interface IAddress

   Property Address1() As String

   Property Address2() As String

   Property City() As String

   Property State() As String

   Property PostalCode() As String

End Interface

 

Public Interface IContactInformation

   Property PhoneNumbers() As System.Collections.Specialized.NameValueCollection

   Property EmailAddresses() As System.Collections.Specialized.NameValueCollection

End Interface

 

Consider the following Business Rules: In IPerson, the LastName is required if it is, if fact, a person. The CompanyName is required if the IPerson is a company (anybody have a better name for IPerson that supports it being either a human or a company?)

My FACTORY Object might look like this:

Public Class FactoryObject

   Public ReadOnly Property SecurityContext() As SystemUser

' snipped for brevity

   Public Function Save(ByVal p As IPerson) As Boolean

      Dim V As New IPersonValidator(p)

      Dim pm As New PersonManager(Me.SecurityContext)

      Return pm.Save(p, V)

   End Function

End Class

The FACTORY Object simply instantiates the validator as a required parameter to the DataAccess Object's Save() method, hiding this complexity from the client code. The Validator Object might look like this:

Public Class IPersonValidator

   Public ReadOnly Property Person() As IPerson

   ' snipped for brevity

   Public ReadOnly Property IsValid() As Boolean

      Get

         Return Me.ValidateNames

      End Get

   End Property

   Public Function ListErrors() As String()

      ' snipped for brevity

 

   Protected Function ValidateNames() As Boolean

      Dim Result As Boolean = True

      If Me.Person.IsACompany Then

         Result = Me.Person.CompanyName.Trim <> String.Empty

      Else

         Result = Me.Person.LastName.Trim <> String.Empty

      End If

      Return Result

   End Function

   Public Sub New(ByVal p As IPerson)

    ' snipped for brevity

End Class

And finally, the Save() method on the Data Access object might look like:

Public Function Save(ByVal p As IPerson, ByVal V As IPersonValidator) As Boolean

   Dim Result As Boolean = False

   If Not V.IsValid() Then

      'Raise a ValidationError event

      'snipped for brevity

   Else

      Result = Me.SaveToDataStore(p) ' execute SQL to store IPerson in Database

   End If

   Return Result

End Function

I'd be interested in any feedback from the community on this approach. This is something that I've started doing recently and so far it's working out rather nicely. There may be pitfalls that I can't see yet, so if you see any major problems with this, ping me :-). You can ping me if you like it too :-P.

More Posts