OOP / 3-Tier development questions

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • iTISTIC

    #1

    OOP / 3-Tier development questions

    Developing a new app and am trying to make this my first truly
    OOP/3-Tier app. I understand the principles of the presentation,
    business, and data layers. I do, however, have some questions on where
    certain functionality should be placed and how some things should be
    implemented.

    Let's use a simple example such as an application to manage customer
    records (customer_id, first_name, last_name). I'd have a Customer
    business object with ID, FirstName, and LastName properties. What I
    don't understand is the following:

    1. How do I obtain a Customer business object pre-loaded with data from
    the database (customer_id 3 for example). I could create a constructor
    in the Customer business class with the customer_id as a parameter and
    have the constructor call the data layer to return a dataset containing
    the customer's data and then set the properties accordingly. Is this
    how this is normally accomplished? I could also have a method in the
    Customer data layer that accepts a customer_id as a parameter and
    returns a Customer business object. My only problem with this is that I
    have it in my head that the presentation layer should never communicate
    with the data layer. Some help here would be great.

    2. How do I obtain a collection or ArrayList of Customer objects in the
    case where I need to return more than one customer object? Such an
    example would be a form that listed all customers. Calling a method in
    the Customer data layer to return an ArrayList of Customer business
    objects would work here as well, but this is breaking the same rule of
    having the presentation layer working with the data layer. The other
    option is to put a method in the Customer business object to return an
    ArrayList of Customer business objects, but then my code has to
    instantiate the Customer object simply to return more Customer objects.
    This is unless I make the method in the Customer business object
    shared.

    3. Data layer methods to insert, update, delete database records -
    Should the insert and update methods accept business objects as
    parameters or should they accept a long parameter list that contains a
    seperate parameter for each of the business object's properties?

    Any help anyone can provide here is more than welcome. These issues
    have been keeping me from developing an OOP/3-tier solution for quite
    some time as I just can't seem to force myself to develop a system
    without truly knowing how these issues should be tackled the proper
    way.

    Thanks in advance for your help!

    Shawn Berg

  • Cor Ligthert [MVP]

    #2
    Re: OOP / 3-Tier development questions

    YTistic,

    The term 3-tier is often used (the writers divide that in physical 3-Tier
    applications and what is more popular a multi layer application).

    What I read from you are you asking for multiple layers application (is that
    true)?

    Cor


    Comment

    • iTISTIC

      #3
      Re: OOP / 3-Tier development questions

      I'm not sure of the difference to properly answer your question. I am
      simply looking to isolate the presentation, business, and data logic
      into seperate entities and my questions are about the proper
      implementation of this.

      Comment

      • Cor Ligthert [MVP]

        #4
        Re: OOP / 3-Tier development questions

        Shawn,
        [color=blue]
        > I'm not sure of the difference to properly answer your question. I am
        > simply looking to isolate the presentation, business, and data logic
        > into seperate entities and my questions are about the proper
        > implementation of this.[/color]

        The physical multi tier environment is in my opinion a very much mainframe
        and because of that Unix approach.

        All processes are done on the mainframe.

        You are making Client/Server windowsapplicat ion a ClientSide application
        that communicates with a ServerSide database. Physical separation on the
        database side does not add much because the databaseserver (where I assume
        SQLServer) is already strong enough.

        On the clientsides in your Client/Server application is every user seperated
        from another, so a physical multitier does add as well much.

        However mixing up your Data and UI means that you will have multiple time
        the same code in your OOP application while it mostly becomes spagethi..

        In VB2002/2003 the designer did it like that. In VB2005 the datalayer is
        seperated from the UI when you use the designer. Why don't you try that once
        in VB2005.

        Click Data->Add DataSource
        Do what the Wizard ask
        Click again Data a new tab is created use DataSource click that.
        Drag it on your form.

        Run.

        Go to solution explorer (a tab in the right if it is not viewed, than use
        that tab) and set in top of that show all files.

        You will see now a nice xxx.vb file with the DataSet/DataAdapter class.
        In that are all the classes needed for the UI to get the data.

        You can create those classes of course yourself as well withouth the
        designer.
        I myself are keeping that dataset and the Dataretrieving part forever apart
        (the last is to make with some statements very generic).

        I hope this gives some ideas

        Cor


        Comment

        • Cor Ligthert [MVP]

          #5
          Re: OOP / 3-Tier development questions

          typo[color=blue]
          > On the clientsides in your Client/Server application is every user
          > seperated from another, so a physical multitier does add as well much.
          >[/color]
          as well *not* much

          Cor


          Comment

          • kchighland@gmail.com

            #6
            Re: OOP / 3-Tier development questions

            iTISTIC wrote:[color=blue]
            > Developing a new app and am trying to make this my first truly
            > OOP/3-Tier app. I understand the principles of the presentation,
            > business, and data layers. I do, however, have some questions on where
            > certain functionality should be placed and how some things should be
            > implemented.
            >
            > Let's use a simple example such as an application to manage customer
            > records (customer_id, first_name, last_name). I'd have a Customer
            > business object with ID, FirstName, and LastName properties. What I
            > don't understand is the following:
            >
            > 1. How do I obtain a Customer business object pre-loaded with data from
            > the database (customer_id 3 for example). I could create a constructor
            > in the Customer business class with the customer_id as a parameter and
            > have the constructor call the data layer to return a dataset containing
            > the customer's data and then set the properties accordingly. Is this
            > how this is normally accomplished? I could also have a method in the
            > Customer data layer that accepts a customer_id as a parameter and
            > returns a Customer business object. My only problem with this is that I
            > have it in my head that the presentation layer should never communicate
            > with the data layer. Some help here would be great.[/color]

            I'm going to assume that you're talking about software tiers (as
            opposed to physical tiers). The way it's usually handled at the firms
            I've worked for is as follows:

            1. Business object just like you described.
            2. Controller object that takes business objects as arguments, and
            passes their properties to data objects.
            3. Data objects that encapsulate stored procedures for inserting,
            updating, deleting, and selecting objects.

            Thus, you mught have the following (abbreviated):

            ' Business Object
            Public Class Employee

            Private m_id As Integer
            Public Property ID As Integer
            Get
            Return m_id
            End Get
            Set(ByVal Value As Integer)
            m_ID = Value
            End Set
            End Property

            Private m_firstName As String
            Public Property FirstName As String
            Get
            Return m_firstName
            End Get
            Set(ByVal Value As String)
            m_firstName = value
            End Set
            End Property

            End Class

            Public Class EmployeeControl ler

            Public Shared Function Load(ByVal ID As Integer) As Employee

            Return MyDataObject.Lo ad(ID)

            End Function

            End Class


            Friend Class EmployeeDac

            Public Shared Function Load(ByVal ID As Integer) As Employee

            Dim cn As New SqlConnection( "server=foo;dat abase=bar;")
            Dim cmd As New SqlCommand(cn)
            Dim dr As System.Data.Sql Client.SqlDataR eader

            cmd.CommandType = CommandType.Tex t
            cmd.CommandText = "SELECT * FROM foo WHERE ID = " & ID

            Try
            dr = cmd.ExecuteRead er()
            If dr.Read() Then
            bo = New MyBusinessObjec t()
            bo.FirstName = CStr(dr("FirstN ame")) ...
            End If
            Catch ex As Exception
            Throw
            Finally
            If dr IsNot Nothing THen
            dr.Close
            End If
            cmd.Close
            cmd.Dispose
            End Try

            Return bo

            End Function

            End Class
            [color=blue]
            > 2. How do I obtain a collection or ArrayList of Customer objects in the
            > case where I need to return more than one customer object? Such an
            > example would be a form that listed all customers. Calling a method in
            > the Customer data layer to return an ArrayList of Customer business
            > objects would work here as well, but this is breaking the same rule of
            > having the presentation layer working with the data layer. The other
            > option is to put a method in the Customer business object to return an
            > ArrayList of Customer business objects, but then my code has to
            > instantiate the Customer object simply to return more Customer objects.
            > This is unless I make the method in the Customer business object
            > shared.[/color]

            Lots of folks use the built-in stuff for returning datasets and
            sprinkling them throughout their code. Personally, I detest the idea of
            referencing ANY object from the System.Data namespaces outside of the
            data layer. I have a program that writes type-safe objects for each
            table in the database, and collections of them. Then I return the
            collections. A LoadAll() method on the controller and data object
            return the multiple rows. (Because I also use inheritance, the derived
            class supports customized selection criteria so I can get just about
            whatever I want.)

            Nowadays, however, I skip the collection classes and use generics. For
            instance, I use List(Of Employee) instead of a custom
            EmployeeCollect ion derived from System.Collecti ons.CollectionB ase, and
            on the DAC:

            Friend Shared Function LoadAll() As List(Of MyBusinessObjec t)

            It's terribly handy.
            [color=blue]
            > 3. Data layer methods to insert, update, delete database records -
            > Should the insert and update methods accept business objects as
            > parameters or should they accept a long parameter list that contains a
            > seperate parameter for each of the business object's properties?[/color]

            SHORT ANSWER: Pass objects. As long as the DAC classes and the
            Controller classes are in the DLL, the compiler can handle it (thanks
            to the miracle that is metadata). You won't have to do much typing, and
            if you decide later on that you want to add fields to the objects, you
            won't have to modify the controller and the DAC -- you'll just have to
            adjust the DAC.

            LONG ANSWER: I was troubled by this question for a while too. For some
            reason, I had it in my head that the parameter lists for my methods
            should all look the same. Thankfully, someone beat that nonsense out of
            me.

            The best answer is, probably, that the ideal parameter list depends on
            the operation being performed. For some operations, you won't have an
            object, or you'll only need a tiny piece of its data. For others,
            you'll need the whole object. For instance, if you're deleting objects,
            or checking whether or not they exist, all you need is the primary key.
            If you're saving the object (either inserting or updating), you'll need
            the whole thing.

            The signatures I use tend to look like this:

            Public Shared Sub Delete([primary key])
            Public Shared Sub DeleteAll()
            Public Shared Function Exists([primary key])
            Protected Shared Sub Insert(MyBusine ssObject)
            Public Shared Sub Load([primary key]) As MyBusinessObjec t
            Public Shared Sub LoadAll() As List(Of MyBusinessObjec t)
            Public Shared Sub Save(MyBusiness Object)
            Protected Shared Sub Update(MyBusine ssObject)

            I also have overloaded versions of Delete, DeleteAll, Insert, Save, and
            Update that include a SqlTransaction as the last parameter, but those
            occur ONLY on the DAC. That way, the controller can combine multiple
            updates under the same transaction. For instance, if saving object A
            also requires an update to object B, then the controller can
            instantiate a transaction, update A, insert into B, and then commit the
            transaction. This keeps knowledge of transactions *out* of the business
            layer. For instance:

            Public Class EmployeeControl ler

            Public Sub Save(ByVal item As Employee)
            Dim cn As New SqlConnection(" Server=foo;Data base=bar;")
            Dim tx As SqlTransaction = cn.BeginTransac tion

            Try
            EmployeeDac.Sav e(item, tx)
            AuditTrailDac.S ave(item,tx)
            tx.Commit()
            Catch(ex As Exception)
            tx.RollBack()
            Throw
            Finally
            cn.Close()
            cn.Dispose()
            End Try

            End Sub

            End Class

            Personally, I find that it's burdensome to pass potentially LOTS of
            parameters around from one procedure to the next (simply from all the
            typing!), so I *tend* to pass the objects around until it's absolutely
            necessary to break them down. There are always exceptions, though, so
            use your best judgement. Don't sweat getting it 100% right the first
            time. If you do that, you'll never finish the product; you're bound to
            make mistakes, and you'll learn from 'em.
            [color=blue]
            > Any help anyone can provide here is more than welcome. These issues
            > have been keeping me from developing an OOP/3-tier solution for quite
            > some time as I just can't seem to force myself to develop a system
            > without truly knowing how these issues should be tackled the proper
            > way.
            >
            > Thanks in advance for your help!
            >
            > Shawn Berg[/color]

            Good luck! And I hope this helps! Drop me a line if you need any more
            help.

            Comment

            Working...