Home All Groups Group Topic Archive Search About

OO & Interface question

Author
27 Feb 2006 8:07 PM
Eric
Hi,

I am kind of new to OO and I have the following problem :

I have a class containing a huge list of functions for accessing an SQL
database.
Public Class Transaction
#region "Client"
  Public function GetClientInfos() as Dataset ...
  Public sub InsertClientInfos() ...
#end region
#region "Employe"
  Public function GetEmployeInfos() as Dataset ...
  Public sub InsertEmployeInfos() ...
#end region
  ...
End Class

However now, those functions could optionnaly call web services instead of
direct sql requests. I thougt of doing something like this, using and
Interface :

Public Interface ITransaction
  function GetClientInfos() as Dataset
  sub InsertClientInfos()
  function GetEmployeInfos() as Dataset ...
  sub InsertEmployeInfos() ...
  ...
End Interface

Public Class TransactionSQL
  Implements ITransaction
....
End Class

Public Class TransactionWeb
  Implements ITransaction
....
End Class

A call to an instance of this Interface would look like :
Dim transaction as ITransaction
transaction = new TransactionSQL
dgClient.Datasource = transaction.GetClientInfos()


Since there a LOT of functions, I'ld really like to be able to use my
ITransaction Interface, but by adding levels to it. So a call to an
ITransaction instance would look like :

Dim transaction as ITransaction
transaction = new TransactionSQL
dgClient.Datasource = transaction.Client.GetInfos()
dgEmploye.Datasource = transaction.Employe.GetInfos()

How should I implement my classes and interfaces to be able to call my
procedure like that???

Hope it was clear enough
Thx

Author
28 Feb 2006 12:12 AM
Dennis
Not really into interfaces so can't really answer your question but my
compliments on your question as it's one of the best examples of where
interfaces are useful.  I have a windows application that I want to later
port to a web site and I wish I'd thought of this technique for my database
access class.  Looking forward to the replies you get.
--
Dennis in Houston


Show quoteHide quote
"Eric" wrote:

> Hi,
>
> I am kind of new to OO and I have the following problem :
>
> I have a class containing a huge list of functions for accessing an SQL
> database.
> Public Class Transaction
> #region "Client"
>   Public function GetClientInfos() as Dataset ...
>   Public sub InsertClientInfos() ...
> #end region
> #region "Employe"
>   Public function GetEmployeInfos() as Dataset ...
>   Public sub InsertEmployeInfos() ...
> #end region
>   ...
> End Class
>
> However now, those functions could optionnaly call web services instead of
> direct sql requests. I thougt of doing something like this, using and
> Interface :
>
> Public Interface ITransaction
>   function GetClientInfos() as Dataset
>   sub InsertClientInfos()
>   function GetEmployeInfos() as Dataset ...
>   sub InsertEmployeInfos() ...
>   ...
> End Interface
>
> Public Class TransactionSQL
>   Implements ITransaction
> ...
> End Class
>
> Public Class TransactionWeb
>   Implements ITransaction
> ...
> End Class
>
> A call to an instance of this Interface would look like :
> Dim transaction as ITransaction
> transaction = new TransactionSQL
> dgClient.Datasource = transaction.GetClientInfos()
>
>
> Since there a LOT of functions, I'ld really like to be able to use my
> ITransaction Interface, but by adding levels to it. So a call to an
> ITransaction instance would look like :
>
> Dim transaction as ITransaction
> transaction = new TransactionSQL
> dgClient.Datasource = transaction.Client.GetInfos()
> dgEmploye.Datasource = transaction.Employe.GetInfos()
>
> How should I implement my classes and interfaces to be able to call my
> procedure like that???
>
> Hope it was clear enough
> Thx

>
>
Author
28 Feb 2006 7:31 AM
Cor Ligthert [MVP]
Dennis,

I don't expect many replies on this.

In my opinion is it to complex to give and goes wrong in maintainability to
give it a change on a life.

A baby born with ten hearts.

However just my idea.

Cor
Author
28 Feb 2006 3:31 PM
Eric
Actually I think the initial interface would simplify my life considerably.

I am just trying to enhance it so it would be simpler to use and more
intuitive for the consumer of the class.

But I guess sometimes, you can make things more complex while trying to make
them simpler :)


Show quoteHide quote
"Cor Ligthert [MVP]" wrote:

> Dennis,
>
> I don't expect many replies on this.
>
> In my opinion is it to complex to give and goes wrong in maintainability to
> give it a change on a life.
>
> A baby born with ten hearts.
>
> However just my idea.
>
> Cor
>
>
>
Author
28 Feb 2006 12:28 PM
AMercer
Show quote Hide quote
> I have a class containing a huge list of functions for accessing an SQL
> database.
> Public Class Transaction
> #region "Client"
>   Public function GetClientInfos() as Dataset ...
>   Public sub InsertClientInfos() ...
> #end region
> #region "Employe"
>   Public function GetEmployeInfos() as Dataset ...
>   Public sub InsertEmployeInfos() ...
> #end region
>   ...
> End Class
>
> However now, those functions could optionnaly call web services instead of
> direct sql requests.
....
> Since there a LOT of functions, I'ld really like to be able to use my
> ITransaction Interface, but by adding levels to it. So a call to an
> ITransaction instance would look like :
>
> Dim transaction as ITransaction
> transaction = new TransactionSQL
> dgClient.Datasource = transaction.Client.GetInfos()
> dgEmploye.Datasource = transaction.Employe.GetInfos()

If I understand this correctly, you have two types of info (client and
employee, and maybe more to follow) and you have two types of access (sql and
web, and maybe more to follow).  You have a big list of functions (GetInfos,
InsertInfos, and many more) that apply to all types of info and types of
access.  You would like to freely mix and match info and access - you need to
call GetInfos for a client via sql or the net, and ditto for employee. 
Furthermore, the list of functions is broadly the same for all mix and match
cases (not necessarily identical, but similar).

If the above is generally a correct assessment, then I urge you to drop
interfaces and use class inheritence instead.  The documentation uses the
terms abstract and concrete, so I will too.  You write an abstract base class
that serves the purpose of your interface and does other things as well. 
Then you write a concrete class that inherits from the abstract class and
provides specific functionality for client via sql.  You write another
concrete class for client via net.  Dito for employee.  The class hierarchy
looks something like this:

  TransactionBase
    TransactionEmployeeSql
    TransactionEmployeeNet
    TransactionClientSql
    TransactionClientNet

In TransactionBase, you provide a Create function that instantiates one of
the concrete classes and returns it cast as TransactionBase.  In you code,
you declare a variable of type TransactionBase, but once instantiated, it is
really one of the concrete classes, something like this:

    Dim How as string
    ' set how to "Sql" or "Net" depending on what your program is doing
    ' maybe at program start, you decide on Sql or Net?
    Dim cl As TransactionBase = TransactionBase.Create("client", How)
    cl.InsertInfos() ' does a client InsertInfos via Sql or Net

A sample of how to do all of this is as follows:

Public MustInherit Class TransactionBase ' abstract base class

  Protected Sub New()
    ' abstract types are not instantiated and should not have constructors
  End Sub

  Public MustOverride Function GetInfos() As Integer ' should be As DataSet
  Public MustOverride Sub InsertInfos()

  Public SomeVariable as Integer ' a name common to all concrete classes
  Public CreateType As String = "" ' how this instance was created, a debug
assist

  Public Shared Function Create(ByVal Who As String, ByVal How As String) As
TransactionBase
    ' return a reference to a new TransactionBase subclass
    Dim z As TransactionBase = Nothing
    Dim CreateType As String = LCase(Who & "." & How)
    Select Case LCase(Who & "." & How)
      Case "employee.sql"
        z = New TransactionEmployeeSql
      Case "employee.net"
        z = Nothing
      Case "client.sql"
        z = Nothing
      Case "client.net"
        z = Nothing
      Case Else
        Debug.Assert(False)
    End Select
    z.CreateType = CreateType
    Return z
  End Function

  Public Sub UtilitySub()
    ' some function that is common to all subclasses
    ' may be shared or not
  End Sub

End Class

Public Class TransactionEmployeeSql ' ditto for empnet, clientsql, clientnet
  Inherits TransactionBase

  Public Overrides Function GetInfos() As Integer
    ' whatever
  End Function

  Public Overrides Sub InsertInfos()
    ' whatever
  End Sub

End Class

Public Module Sample
  Public Sub test()
    Dim x As TransactionBase = TransactionBase.Create("employee", "net")
    x.GetInfos()
    x.InsertInfos()
  End Sub
End Module
Author
28 Feb 2006 2:17 PM
Eric
That is a pretty smart way to do it. Many thx for your input. (sigh) But I
wish I could use interfaces one of these days. Each time I try to do it, I
end up using class inheritance instead.

Oh well, it'll have to wait for another day I guess!!!



Show quoteHide quote
"AMercer" wrote:

> > I have a class containing a huge list of functions for accessing an SQL
> > database.
> > Public Class Transaction
> > #region "Client"
> >   Public function GetClientInfos() as Dataset ...
> >   Public sub InsertClientInfos() ...
> > #end region
> > #region "Employe"
> >   Public function GetEmployeInfos() as Dataset ...
> >   Public sub InsertEmployeInfos() ...
> > #end region
> >   ...
> > End Class
> >
> > However now, those functions could optionnaly call web services instead of
> > direct sql requests.
> ...
> > Since there a LOT of functions, I'ld really like to be able to use my
> > ITransaction Interface, but by adding levels to it. So a call to an
> > ITransaction instance would look like :
> >
> > Dim transaction as ITransaction
> > transaction = new TransactionSQL
> > dgClient.Datasource = transaction.Client.GetInfos()
> > dgEmploye.Datasource = transaction.Employe.GetInfos()
>
> If I understand this correctly, you have two types of info (client and
> employee, and maybe more to follow) and you have two types of access (sql and
> web, and maybe more to follow).  You have a big list of functions (GetInfos,
> InsertInfos, and many more) that apply to all types of info and types of
> access.  You would like to freely mix and match info and access - you need to
> call GetInfos for a client via sql or the net, and ditto for employee. 
> Furthermore, the list of functions is broadly the same for all mix and match
> cases (not necessarily identical, but similar).
>
> If the above is generally a correct assessment, then I urge you to drop
> interfaces and use class inheritence instead.  The documentation uses the
> terms abstract and concrete, so I will too.  You write an abstract base class
> that serves the purpose of your interface and does other things as well. 
> Then you write a concrete class that inherits from the abstract class and
> provides specific functionality for client via sql.  You write another
> concrete class for client via net.  Dito for employee.  The class hierarchy
> looks something like this:
>
>   TransactionBase
>     TransactionEmployeeSql
>     TransactionEmployeeNet
>     TransactionClientSql
>     TransactionClientNet
>
> In TransactionBase, you provide a Create function that instantiates one of
> the concrete classes and returns it cast as TransactionBase.  In you code,
> you declare a variable of type TransactionBase, but once instantiated, it is
> really one of the concrete classes, something like this:
>
>     Dim How as string
>     ' set how to "Sql" or "Net" depending on what your program is doing
>     ' maybe at program start, you decide on Sql or Net?
>     Dim cl As TransactionBase = TransactionBase.Create("client", How)
>     cl.InsertInfos() ' does a client InsertInfos via Sql or Net
>
> A sample of how to do all of this is as follows:
>
> Public MustInherit Class TransactionBase ' abstract base class
>
>   Protected Sub New()
>     ' abstract types are not instantiated and should not have constructors
>   End Sub
>
>   Public MustOverride Function GetInfos() As Integer ' should be As DataSet
>   Public MustOverride Sub InsertInfos()
>
>   Public SomeVariable as Integer ' a name common to all concrete classes
>   Public CreateType As String = "" ' how this instance was created, a debug
> assist
>
>   Public Shared Function Create(ByVal Who As String, ByVal How As String) As
> TransactionBase
>     ' return a reference to a new TransactionBase subclass
>     Dim z As TransactionBase = Nothing
>     Dim CreateType As String = LCase(Who & "." & How)
>     Select Case LCase(Who & "." & How)
>       Case "employee.sql"
>         z = New TransactionEmployeeSql
>       Case "employee.net"
>         z = Nothing
>       Case "client.sql"
>         z = Nothing
>       Case "client.net"
>         z = Nothing
>       Case Else
>         Debug.Assert(False)
>     End Select
>     z.CreateType = CreateType
>     Return z
>   End Function
>
>   Public Sub UtilitySub()
>     ' some function that is common to all subclasses
>     ' may be shared or not
>   End Sub
>
> End Class
>
> Public Class TransactionEmployeeSql ' ditto for empnet, clientsql, clientnet
>   Inherits TransactionBase
>
>   Public Overrides Function GetInfos() As Integer
>     ' whatever
>   End Function
>
>   Public Overrides Sub InsertInfos()
>     ' whatever
>   End Sub
>
> End Class
>
> Public Module Sample
>   Public Sub test()
>     Dim x As TransactionBase = TransactionBase.Create("employee", "net")
>     x.GetInfos()
>     x.InsertInfos()
>   End Sub
> End Module
>