Figuring out OOP principles

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

    Figuring out OOP principles

    I'm trying to develop a bunch of classes and want to do it the right
    way.

    Say I have 5 classes:

    City,
    Neighborhood,
    NeighborhoodCol lection,
    House,
    HouseCollection

    The collection classes are strongly typed collections which inherit
    System.Collecti ons.CollectionB ase

    So once I instanciate everything I need, I may use it as follows:

    City.Neighborho odCollection(2) .Housecollectio n(3).value

    So here's my question:

    I have a sub in the House class which needs to access some property of
    the City class. For example, when calling house.GetAverag eIncome(), the
    sub needs to know which City the house is in. Make sense?

    The only way I was able to figure out how to do this was to pass a
    reference down to each child object (when sub new() was called in City,
    it populated its NeighborhoodCol lection members and created a
    NeighborhoodCol lection.MyParen t reference to itself):

    dim NeighborhoodToA dd as Neighborhood = new Neighborhood
    NeighborhoodToA dd.MyParent = City
    City.Neighborho odCollection.Ad d(NeighborhoodT oAdd)


    This got ugly fast. How should I be referencing the properties in a
    class' parent?



    Thanks!



    =============== =
    Jordan Bowness
    =============== =

    *** Sent via Developersdex http://www.developersdex.com ***
    Don't just participate in USENET...get rewarded for it!
  • Scott M.

    #2
    Re: Figuring out OOP principles

    I know you didn't ask this but why not make a House class that has a City
    and a Neighborhood property. The Neighborhood property could hold a value
    from an Enum and you could place each house in a Houses collection.


    "Jordan Bowness" <jordan@sapient .ca.nospam> wrote in message
    news:%23nDSEvlx DHA.2396@TK2MSF TNGP09.phx.gbl. ..[color=blue]
    > I'm trying to develop a bunch of classes and want to do it the right
    > way.
    >
    > Say I have 5 classes:
    >
    > City,
    > Neighborhood,
    > NeighborhoodCol lection,
    > House,
    > HouseCollection
    >
    > The collection classes are strongly typed collections which inherit
    > System.Collecti ons.CollectionB ase
    >
    > So once I instanciate everything I need, I may use it as follows:
    >
    > City.Neighborho odCollection(2) .Housecollectio n(3).value
    >
    > So here's my question:
    >
    > I have a sub in the House class which needs to access some property of
    > the City class. For example, when calling house.GetAverag eIncome(), the
    > sub needs to know which City the house is in. Make sense?
    >
    > The only way I was able to figure out how to do this was to pass a
    > reference down to each child object (when sub new() was called in City,
    > it populated its NeighborhoodCol lection members and created a
    > NeighborhoodCol lection.MyParen t reference to itself):
    >
    > dim NeighborhoodToA dd as Neighborhood = new Neighborhood
    > NeighborhoodToA dd.MyParent = City
    > City.Neighborho odCollection.Ad d(NeighborhoodT oAdd)
    >
    >
    > This got ugly fast. How should I be referencing the properties in a
    > class' parent?
    >
    >
    >
    > Thanks!
    >
    >
    >
    > =============== =
    > Jordan Bowness
    > =============== =
    >
    > *** Sent via Developersdex http://www.developersdex.com ***
    > Don't just participate in USENET...get rewarded for it![/color]


    Comment

    • Jeremy Cowles

      #3
      Re: Figuring out OOP principles

      "Jordan Bowness" <jordan@sapient .ca.nospam> wrote in message
      news:%23nDSEvlx DHA.2396@TK2MSF TNGP09.phx.gbl. ..[color=blue]
      > I'm trying to develop a bunch of classes and want to do it the right
      > way.
      >
      > Say I have 5 classes:
      >
      > City,
      > Neighborhood,
      > NeighborhoodCol lection,
      > House,
      > HouseCollection
      >
      > The collection classes are strongly typed collections which inherit
      > System.Collecti ons.CollectionB ase
      >
      > So once I instanciate everything I need, I may use it as follows:
      >
      > City.Neighborho odCollection(2) .Housecollectio n(3).value
      >
      > So here's my question:
      >
      > I have a sub in the House class which needs to access some property of
      > the City class. For example, when calling house.GetAverag eIncome(), the
      > sub needs to know which City the house is in. Make sense?[/color]

      This sounds like a problem, why does a house know about AverageIncome? That
      doesnt seem like a function that my house can provide for me, you know? This
      causes a dependency between a house and then entire neighborhood. Seems to
      me like you should push this functionality up to the neighborhood, and then
      to the city. This way, it makes more sense, if it is part of a house, the
      only thing that it *should* average is the income of the inhabitances (spell
      check).

      If up push the functionality back where it belongs, then the rest of your
      code will un-f*ck it's self.


      HTH,
      Jeremy

      Comment

      • Mythran

        #4
        Re: Figuring out OOP principles

        Public Class City
        Private mNeighborhoods As NeighborhoodCol lection
        Private mName As String

        Public ReadOnly Property Neighborhoods As NeighborhoodCol lection
        Get
        Return mNeighborhoods
        End Get
        End Property

        Public Property Name As String
        Get
        Return mName
        End Get
        Set(ByVal Value As String)
        mName = Value
        End Sub
        End Property

        Public Sub New(ByVal CityName As String)
        mNeighborhoods = New NeighborhoodCol lection
        mName = CityName
        End Sub
        End Class

        Public Class Neighborhood
        Private mName As String = String.Empty
        Private mCity As City

        Public Property Name As String
        Get
        Return mName
        End Get
        Set(ByVal Value As String)
        mName = Value
        End Set
        End Property

        Public ReadOnly Property City As City
        Get
        Return mCity
        End Get
        End Property

        Public Sub New(ByVal City As City, ByVal NeighborhoodNam e As String)
        mCity = City
        Me.Name = NeighborhoodNam e
        End Sub
        End Class

        Module MainRoutine
        Sub Main()
        Dim neighborhood As Neighborhood
        Dim city As City

        city = New City("MyCity")
        neighborhood = New Neighborhood(ci ty, "MyNeighborhood ")
        city.Neighborho ods.Add(city)
        End Sub
        End Module


        ' ---------------------------------------------------------------

        The above code should give you an idea of what to do, free-hand
        code in newsgroup editor so it's buggy :)


        Hope it helps


        Mythran


        Comment

        • One Handed Man [ OHM# ]

          #5
          Re: Figuring out OOP principles

          Why not declare those members Protected Friends

          OHM

          Jordan Bowness wrote:[color=blue]
          > I'm trying to develop a bunch of classes and want to do it the right
          > way.
          >
          > Say I have 5 classes:
          >
          > City,
          > Neighborhood,
          > NeighborhoodCol lection,
          > House,
          > HouseCollection
          >
          > The collection classes are strongly typed collections which inherit
          > System.Collecti ons.CollectionB ase
          >
          > So once I instanciate everything I need, I may use it as follows:
          >
          > City.Neighborho odCollection(2) .Housecollectio n(3).value
          >
          > So here's my question:
          >
          > I have a sub in the House class which needs to access some property of
          > the City class. For example, when calling house.GetAverag eIncome(),
          > the sub needs to know which City the house is in. Make sense?
          >
          > The only way I was able to figure out how to do this was to pass a
          > reference down to each child object (when sub new() was called in
          > City, it populated its NeighborhoodCol lection members and created a
          > NeighborhoodCol lection.MyParen t reference to itself):
          >
          > dim NeighborhoodToA dd as Neighborhood = new Neighborhood
          > NeighborhoodToA dd.MyParent = City
          > City.Neighborho odCollection.Ad d(NeighborhoodT oAdd)
          >
          >
          > This got ugly fast. How should I be referencing the properties in a
          > class' parent?
          >
          >
          >
          > Thanks!
          >
          >
          >
          > =============== =
          > Jordan Bowness
          > =============== =
          >
          > *** Sent via Developersdex http://www.developersdex.com ***
          > Don't just participate in USENET...get rewarded for it![/color]

          Regards - OHM# OneHandedMan{at }BTInternet{dot }com


          Comment

          • One Handed Man [ OHM# ]

            #6
            Re: Figuring out OOP principles

            Forget that !, Just protected will do the trick, then you can use a public
            function in the lower classes to get at it.

            OHM


            One Handed Man [ OHM# ] wrote:[color=blue]
            > Why not declare those members Protected Friends
            >
            > OHM
            >
            > Jordan Bowness wrote:[color=green]
            >> I'm trying to develop a bunch of classes and want to do it the right
            >> way.
            >>
            >> Say I have 5 classes:
            >>
            >> City,
            >> Neighborhood,
            >> NeighborhoodCol lection,
            >> House,
            >> HouseCollection
            >>
            >> The collection classes are strongly typed collections which inherit
            >> System.Collecti ons.CollectionB ase
            >>
            >> So once I instanciate everything I need, I may use it as follows:
            >>
            >> City.Neighborho odCollection(2) .Housecollectio n(3).value
            >>
            >> So here's my question:
            >>
            >> I have a sub in the House class which needs to access some property
            >> of the City class. For example, when calling
            >> house.GetAverag eIncome(), the sub needs to know which City the house
            >> is in. Make sense?
            >>
            >> The only way I was able to figure out how to do this was to pass a
            >> reference down to each child object (when sub new() was called in
            >> City, it populated its NeighborhoodCol lection members and created a
            >> NeighborhoodCol lection.MyParen t reference to itself):
            >>
            >> dim NeighborhoodToA dd as Neighborhood = new Neighborhood
            >> NeighborhoodToA dd.MyParent = City
            >> City.Neighborho odCollection.Ad d(NeighborhoodT oAdd)
            >>
            >>
            >> This got ugly fast. How should I be referencing the properties in a
            >> class' parent?
            >>
            >>
            >>
            >> Thanks!
            >>
            >>
            >>
            >> =============== =
            >> Jordan Bowness
            >> =============== =
            >>
            >> *** Sent via Developersdex http://www.developersdex.com ***
            >> Don't just participate in USENET...get rewarded for it![/color]
            >
            > Regards - OHM# OneHandedMan{at }BTInternet{dot }com[/color]

            Regards - OHM# OneHandedMan{at }BTInternet{dot }com


            Comment

            • One Handed Man [ OHM# ]

              #7
              Re: Figuring out OOP principles

              You write with such 'fineness' , I assume this is a technical term used in
              the Framework ?
              [color=blue]
              > your code will un-f*ck it's self.[/color]

              :-)

              Regards - OHM


              Jeremy Cowles wrote:[color=blue]
              > "Jordan Bowness" <jordan@sapient .ca.nospam> wrote in message
              > news:%23nDSEvlx DHA.2396@TK2MSF TNGP09.phx.gbl. ..[color=green]
              >> I'm trying to develop a bunch of classes and want to do it the right
              >> way.
              >>
              >> Say I have 5 classes:
              >>
              >> City,
              >> Neighborhood,
              >> NeighborhoodCol lection,
              >> House,
              >> HouseCollection
              >>
              >> The collection classes are strongly typed collections which inherit
              >> System.Collecti ons.CollectionB ase
              >>
              >> So once I instanciate everything I need, I may use it as follows:
              >>
              >> City.Neighborho odCollection(2) .Housecollectio n(3).value
              >>
              >> So here's my question:
              >>
              >> I have a sub in the House class which needs to access some property
              >> of the City class. For example, when calling
              >> house.GetAverag eIncome(), the sub needs to know which City the house
              >> is in. Make sense?[/color]
              >
              > This sounds like a problem, why does a house know about
              > AverageIncome? That doesnt seem like a function that my house can
              > provide for me, you know? This causes a dependency between a house
              > and then entire neighborhood. Seems to me like you should push this
              > functionality up to the neighborhood, and then to the city. This way,
              > it makes more sense, if it is part of a house, the only thing that it
              > *should* average is the income of the inhabitances (spell check).
              >
              > If up push the functionality back where it belongs, then the rest of
              > your code will un-f*ck it's self.
              >
              >
              > HTH,
              > Jeremy[/color]

              Regards - OHM# OneHandedMan{at }BTInternet{dot }com


              Comment

              • Jeremy Cowles

                #8
                Re: Figuring out OOP principles

                "One Handed Man [ OHM# ]" <OneHandedMan{a t}BTInternet{do t}com> wrote in
                message news:eAy21KmxDH A.2448@TK2MSFTN GP12.phx.gbl...[color=blue]
                > You write with such 'fineness' , I assume this is a technical term used in
                > the Framework ?
                >[color=green]
                > > your code will un-f*ck it's self.[/color]
                >
                > :-)
                >[/color]

                lol, yup.


                Comment

                • Jeremy

                  #9
                  Re: Figuring out OOP principles

                  "One Handed Man [ OHM# ]" <OneHandedMan{a t}BTInternet{do t}com> wrote in
                  message news:%23vnW5Amx DHA.1912@TK2MSF TNGP09.phx.gbl. ..[color=blue]
                  > Why not declare those members Protected Friends[/color]

                  But does that really fix the problem? It seems to me that the "House" is
                  doing something that it shouldn't do, that is, why would a house object
                  return the average income of the neighborhood? Shouldn't it be the otherway
                  around?

                  -
                  Jeremy

                  Comment

                  • Jay B. Harlow [MVP - Outlook]

                    #10
                    Re: Figuring out OOP principles

                    Jordan,
                    In addition to the others comments about the location of GetAverageIncom e.
                    [color=blue]
                    > This got ugly fast. How should I be referencing the properties in a
                    > class' parent?[/color]
                    I find passing the "parent" object as a parameter to the constructor of the
                    child object helps prevent things from getting ugly...

                    Also having a clear idea of which class encapsulates what attributes &
                    behaviors also helps (the location of the GetAverageIncom e method). I would
                    expect a House to have an Income amount, while a Neighborhood would have
                    both an Average Income & Total Income amount, based on the houses in that
                    Neighborhood, while a City has both an Average Income & Total Income amount
                    based on the Neighborhoods in the city. Note that City would not know about
                    the houses, as houses are the Neighborhood's responsibility!
                    [color=blue]
                    > dim NeighborhoodToA dd as Neighborhood = new Neighborhood
                    > NeighborhoodToA dd.MyParent = City
                    > City.Neighborho odCollection.Ad d(NeighborhoodT oAdd)
                    >[/color]

                    I would pass City as a parameter to the constructor of Neighborhood, I would
                    consider making NeighborhoodCol lection.Add a factory method.

                    Something like:

                    Public Class City

                    Private Readonly m_name As String
                    Private Readonly m_neighborhoods As NeighborhoodCol lection

                    Public Sub New(ByVal name As String)
                    m_name = name
                    m_neighborhoods = New NeighborhoodCol lection(Me)
                    End Sub

                    Public Readonly Property Neighborhoods As NeighborhoodCol lection
                    Get
                    return m_neighborhoods
                    End Get
                    End Property

                    End Class

                    Public Class NeighborhoodCol lection
                    Inherits CollectionBase

                    Private Readonly m_city As City

                    Friend Sub New(ByVal city As City)
                    m_city = city
                    End Sub

                    Public Readonly Property City As City
                    Get
                    Return m_city
                    End Get
                    End Property

                    Public Function Add() As Neighborhood
                    Dim value As New Neighborhood(m_ city)
                    Me.InnerList.Ad d(value)
                    Return value
                    End Function

                    End Class

                    Public Class Neighborhood

                    Private Readonly m_city As City

                    Friend Sub New(ByVal city As City)
                    m_city = city
                    End Sub

                    Public Readonly Property City As City
                    Get
                    Return m_city
                    End Get
                    End Property

                    End Class

                    Making the constructors Friend, restricts creating the child objects to the
                    Cities class library

                    Then you can use it like

                    Dim myCity As New City("New City")
                    Dim myNeighborhood As Neighborhood = myCity.Neighbor hoods.Add()
                    Dim myHouse As House = myNeighborhood. Houses.Add()

                    I would have HouseCollection & House both have Neighborhood "parents", House
                    could then implement its City property, by delegating to the Neighborhood.

                    If Neighborhood or House required other parameters to their constructors the
                    NeighborhoodCol lection.Add & HouseCollection .Add methods would have the
                    respective parameters.

                    Hope this helps
                    Jay


                    "Jordan Bowness" <jordan@sapient .ca.nospam> wrote in message
                    news:%23nDSEvlx DHA.2396@TK2MSF TNGP09.phx.gbl. ..[color=blue]
                    > I'm trying to develop a bunch of classes and want to do it the right
                    > way.
                    >
                    > Say I have 5 classes:
                    >
                    > City,
                    > Neighborhood,
                    > NeighborhoodCol lection,
                    > House,
                    > HouseCollection
                    >
                    > The collection classes are strongly typed collections which inherit
                    > System.Collecti ons.CollectionB ase
                    >
                    > So once I instanciate everything I need, I may use it as follows:
                    >
                    > City.Neighborho odCollection(2) .Housecollectio n(3).value
                    >
                    > So here's my question:
                    >
                    > I have a sub in the House class which needs to access some property of
                    > the City class. For example, when calling house.GetAverag eIncome(), the
                    > sub needs to know which City the house is in. Make sense?
                    >
                    > The only way I was able to figure out how to do this was to pass a
                    > reference down to each child object (when sub new() was called in City,
                    > it populated its NeighborhoodCol lection members and created a
                    > NeighborhoodCol lection.MyParen t reference to itself):
                    >
                    > dim NeighborhoodToA dd as Neighborhood = new Neighborhood
                    > NeighborhoodToA dd.MyParent = City
                    > City.Neighborho odCollection.Ad d(NeighborhoodT oAdd)
                    >
                    >
                    > This got ugly fast. How should I be referencing the properties in a
                    > class' parent?
                    >
                    >
                    >
                    > Thanks!
                    >
                    >
                    >
                    > =============== =
                    > Jordan Bowness
                    > =============== =
                    >
                    > *** Sent via Developersdex http://www.developersdex.com ***
                    > Don't just participate in USENET...get rewarded for it![/color]


                    Comment

                    • Kevin Halverson [MSFT]

                      #11
                      Re: Figuring out OOP principles

                      In my humble opinion, you had it right to begin with (passing a self
                      reference to the collection member's constructor).

                      Since House does not logically inherit from Neighborhood and Neighborhood
                      does not logically inherit from City, I don't see how declaring the member
                      variable "Protected" will do any good. You could declare the variable as
                      "Friend" or "Public", but when you share data like this, the functionality
                      of the class becomes reliant on logic in another class with which it does
                      not share an inheritance relationship. This is called coupling, and In
                      general, this indicates BAD OO design. You don't want classes to rely on
                      one another to "do the right thing". For example, what if the variable is
                      Nothing? Should I leave it alone or initialize it to a default instance of
                      an object? You might know the answer to this question, but chances are,
                      the next person who works with this code won't.

                      For the Neighborhood and House constructors, pass an instance of the
                      Collection that houses it. For example, the House Class would look like
                      this:

                      Class House
                      Private m_parentCollect ion As HouseCollection

                      Sub New(ByVal parent As HouseCollection , ...other...para ms...)
                      m_parentCollect ion = parent
                      End Sub
                      End Class

                      For the NeighborhoodCol lection and HouseCollection constructors, pass an
                      instance of the City or Neighborhood. For example the
                      NeighborhoodCol lection would look like this:

                      Class NeighborhoodCol lection : Inherits CollectionBase
                      Private m_parentCity As City

                      Sub New(ByVal parent As City, ...other...para ms...)
                      m_parentCity = parent
                      End Sub
                      End Class

                      In your code, you'll declare the City first and then pass each object down
                      to the next class in the organizational heirarchy.

                      Hope that helps!

                      --
                      Kevin Halverson, VBQA Team
                      This posting is provided "AS IS" with no warranties, and confers no rights.

                      Comment

                      • Kevin Halverson [MSFT]

                        #12
                        Re: Figuring out OOP principles

                        I'm sorry. As soon as I hit send, I realized that I hadn't really answered your question. However, I was afraid that I was going to miss my ride to the airport, so I had to wait to reply.

                        My first answer is only half an answer. Once you have constructed your "parent aware" objects, you obviously still need to be able to access that information. For your problem, the preferred way to go about doing this in VB.NET would be to use a ReadOnly Property. For example, the House Class from my first response would be modified to look like this:

                        Class House
                        Private m_parentCollect ion As HouseCollection

                        Sub New(ByVal parent As HouseCollection , ...other...para ms...)
                        m_parentCollect ion = parent
                        End Sub

                        Friend ReadOnly Property Parent() As HouseCollection
                        Get
                        return m_parentCollect ion
                        End Get
                        End Property
                        End Class

                        You may ask, "How is this much different from marking m_parentCollect ion as Friend?" In this case it is not, except that you cannot assign a value to the property (because it's ReadOnly). For example:

                        MyHouse.Parent = New HouseCollection (...)

                        would generate a compile error. The benefit to using a property is that it allows for more flexibility when it comes to future implementation changes/extensibility. Right now, determining a House's parent only involves returning the value of a member variable, but at some point this might require a different set of operations. If you wrap the functionality in a property to begin with, you won't break the class's interface when you change the underlying logic. I marked the property "Friend", because it is probably best to start with a more restrictive access modifier and only move to "Public" if necessary. You probably won't break anything by changing "Friend" to "Public", but the opposite is not true.

                        Well, I think I've rambled on quite enough. I hope that some of this helps :-) Best of luck with your application!


                        ----- Kevin Halverson [MSFT] wrote: -----

                        In my humble opinion, you had it right to begin with (passing a self
                        reference to the collection member's constructor).

                        Since House does not logically inherit from Neighborhood and Neighborhood
                        does not logically inherit from City, I don't see how declaring the member
                        variable "Protected" will do any good. You could declare the variable as
                        "Friend" or "Public", but when you share data like this, the functionality
                        of the class becomes reliant on logic in another class with which it does
                        not share an inheritance relationship. This is called coupling, and In
                        general, this indicates BAD OO design. You don't want classes to rely on
                        one another to "do the right thing". For example, what if the variable is
                        Nothing? Should I leave it alone or initialize it to a default instance of
                        an object? You might know the answer to this question, but chances are,
                        the next person who works with this code won't.

                        For the Neighborhood and House constructors, pass an instance of the
                        Collection that houses it. For example, the House Class would look like
                        this:

                        Class House
                        Private m_parentCollect ion As HouseCollection

                        Sub New(ByVal parent As HouseCollection , ...other...para ms...)
                        m_parentCollect ion = parent
                        End Sub
                        End Class

                        For the NeighborhoodCol lection and HouseCollection constructors, pass an
                        instance of the City or Neighborhood. For example the
                        NeighborhoodCol lection would look like this:

                        Class NeighborhoodCol lection : Inherits CollectionBase
                        Private m_parentCity As City

                        Sub New(ByVal parent As City, ...other...para ms...)
                        m_parentCity = parent
                        End Sub
                        End Class

                        In your code, you'll declare the City first and then pass each object down
                        to the next class in the organizational heirarchy.

                        Hope that helps!

                        --
                        Kevin Halverson, VBQA Team
                        This posting is provided "AS IS" with no warranties, and confers no rights.


                        Comment

                        Working...