Too Much Sharing
Too Much Sharing
Too Much Sharing
Too Much Sharing
Too Much Sharing
Too Much Sharing Too Much Sharing Too Much Sharing Too Much Sharing Too Much Sharing Too Much Sharing Too Much Sharing Too Much Sharing
Too Much Sharing Too Much Sharing
Too Much Sharing
Go Back  Xtreme Visual Basic Talk > > > Too Much Sharing


Reply
 
Thread Tools Display Modes
  #1  
Old 09-24-2011, 11:19 PM
CodeCruncher CodeCruncher is offline
Junior Contributor
 
Join Date: Jul 2006
Posts: 355
Default Too Much Sharing


Having a small problem with trying to avoid too many Shared’s. The following is in one class... (MainAlter)
Code:
Public iPercent As Integer
Private iCountMe As Integer

    Public Sub CheckBox_Checked()

        Dim Ticked As Int16 = 0
        Dim FN As Integer = Main.cbClientFriendlyName.SelectedIndex + 1

        For i = 0 To iQuery
            If CBool(Databases.dtChecked.Rows(i).Item(FN)) Then
                cbMain(i).Checked = True
                Ticked = CShort(Ticked + 1)
            End If
        Next
        iPercent = CShort(100 / Ticked)

    End Sub

    Public Sub ProgressBar()

        iCountMe += 1
        Main.pbRun.Value = iCountMe * Me.iPercent
        My.Application.DoEvents()

    End Sub
And this is in another... (QueriesRun)
Code:
Private _mA As New MainAlter

‘Some looping code that calls the Progress bar
_mA.ProgressBar()
The CheckBox_Checked() runs first and gives me a value for iPercent i.e. 25. When a query is run and _mA.ProgressBar() makes a call to ProgressBar() iPercent = 0, if I Public Shared iPercent As Integer then it is there as 25.

Even though both CheckBox_Checked() and ProgressBar() are in the same class, I still need to have iPercent shared for it to work.

Seems any time I need a value to span across a few classes it must be shared.

Is there another way to avoid sharing so much?

Edit:
I should mention that I tried making it a Function and passing the iPercent value to it, but still got the same result.

Last edited by CodeCruncher; 09-24-2011 at 11:26 PM.
Reply With Quote
  #2  
Old 09-25-2011, 02:09 AM
CodeCruncher CodeCruncher is offline
Junior Contributor
 
Join Date: Jul 2006
Posts: 355
Default

Hmm probably wasn't the best example of what I was trying to do as I managed to eliminate both variables.

Private Shared Percent As Integer
Private Multiplier As Integer

but the problem remains in other code... still can't work out how to share the same variable across mulitple classes without using Shared... maybe I'm am meant to use it?

Code:
Public Sub CheckBox_Checked()

        Dim Ticked As Int16 = 0
        Dim FN As Integer = Main.cbClientFriendlyName.SelectedIndex + 1

        For i = 0 To MainLoad.iQuery
            If CBool(Databases.dtChecked.Rows(i).Item(FN)) Then
                cbMain(i).Checked = True
                Ticked = CShort(Ticked + 1)
            End If
        Next
        Main.pbRun.Step = CShort(100 / Ticked)

    End Sub

    Public Sub ProgressBar()

        Main.pbRun.PerformStep()
        My.Application.DoEvents()

    End Sub
Reply With Quote
  #3  
Old 09-25-2011, 09:19 AM
AtmaWeapon's Avatar
AtmaWeaponToo Much Sharing AtmaWeapon is offline
Fabulous Florist

Forum Leader
* Guru *
 
Join Date: Feb 2004
Location: Austin, TX
Posts: 9,500
Default

Quote:
Seems any time I need a value to span across a few classes it must be shared.
I'm pretty sure we've been over this, I'll explain it one more time. The Shared specifier has nothing to do with whether you can access a variable from another class. That's what the access modifiers Public/Protected/Friend/Private control. Shared controls whether the variable is an instance variable or a static variable. (I wish VB would call them "static" and I'm going to refer to them as such in this post.) There's no "too many" static variables, but they aren't something you should be using at all times. Let's use analogy to learn the differences.

Instance Members
Imagine a playroom in a nursery. Let's say it has room for three toys in it. The class might look like this:
Code:
Class Playroom
    Public toy1 As Toy
    Public toy2 As Toy
    Public toy3 As Toy
    
    Public playingChildren() As Child
End Class
Now imagine the nursery is in a day care center with 5 of these playrooms:
Code:
Class Nursery
    Public playrooms(4) As Playroom
End Class
The nursery could put a stuffed animal in playroom 1's toy1 slot like so:
Code:
playrooms(1).toy1 = New TeddyBear()
When I do that, I'm only changing playroom 1. Playroom 0's toy1 slot will still be empty. Going further, if 3 children start playing in playroom 2, the other playrooms will still be empty.

Instance members are so named because they belong to an instance of a class. If you have more than one instance, changing the value of one instance member will not affect the instance members of the other.

Static Members
You'd probably implement Playroom this way since you believe Shared means "other classes can see this":
Code:
Class Playroom
    Public Shared toy1 As Toy
    Public Shared toy2 As Toy
    Public Shared toy3 As Toy
    
    Public Shared playingChildren() As Child
End Class
Static members do not belong to an instance of a class. Static members belong to the class. The "Shared" part in VB comes from the "clever" observation that every instance of a class shares the same copies of a static member. Like so many other situations, picking a clever metaphor confuses those who don't understand the fundamentals.

Let's say I again set playroom 1's toy1 to a teddy bear:
Code:
playrooms(1).toy1 = New TeddyBear()
You ought to get at least a compiler warning for this: "Access of shared member through instance" or something like that. You get the warning because this is a common mistake and the compiler would like you to double-check. What's the mistake? Since toy1 is shared between all instances of Playroom, setting toy1 updates *all* playrooms. Instead of 5 playrooms that can each hold 3 toys (15 total toys), we've created 5 playrooms that have to share 3 toys (3 total toys). It's more like all 5 playrooms are connected to a shared toybox. We're going to have some bored kids. This is why the compiler warns you: it makes no sense to say "set this specific playroom's toy1 slot to a teddy bear" because that slot doesn't belong to the playroom: it belongs to Playrooms in general.

Now imagine what happens when we try to put Bobby in playroom 3. Since playingChildren() is static, Bobby will be in all 5 playrooms at once! Suboptimal. In fact, this is an error in the code you've described: if you have two instances of whatever holds Percent, when one updates you'll see the other update too.

Shared members have nothing to do with whether you can see a variable from another class. Shared members indicate all instances of a class use the same variable. Shared members are least harmful for read-only members. If you want to change a Shared member you almost certainly should not be using a shared member. Shared members only work if there's ever a need for only one copy of a variable in the entire world.

So, how do you use instance members from another class? Time for more metaphor.

Imagine you've got a pretty friend named Rarity. She's a seamstress. You bought some pants the other day, but the legs are a little too long. You'd like Rarity to hem the pants for you. So you take your pants to Rarity's office and ask her to hem them for you. When she's done, she calls you and you return to pick up your pants.

What's happening here is a transaction between objects. You are a Person. Rarity is a Seamstress. The transaction goes something like:
Code:
rarity.AcceptPants(you.Pants)
rarity.HemPants()
rarity.NotifyComplete(you)
you.AcceptPants(rarity.HemmedPants)
Think about this. Rarity is a *specific* instance of a Seamstress:
Code:
Dim rarity As New Seamstress()
Thus, if you want to do something with Rarity, you need to use her instance members. If you use Seamstress shared members, you're saying "I want some seamstress but I don't care if it's Rarity." That'd hurt her feelings, and she's the best anyway.

Also, if you want Rarity to do something with *your* pants, you need to take note that the pants belong to you and you are a specific Person:
Code:
Dim you As New Person()
you.Pants = New Pants()
For Rarity to work on your pants, you have to tell her which specific pants to use. Once she has those pants, she can do whatever with them. When she's done, she needs to give you the pants she's modified back. This *only* works smoothly if everything in the transaction is an instance member; if we used static members it's like there's only one seamstress and one pair of pants in the entire world: it'd work for this example but it'd be impractical in the real world. So the Seamstress class could work if it looked like this:
Code:
Public Class Seamstress
    Private _hemmedPants As Pants
    
    Public HemmedPants As Pants
        Get
            Return _hemmedPants
        End Get
    End Sub
    
    Public Sub HemPants(ByVal owner As Person, ByVal pants As Pants)
        ' Do stuff with the pants here...
        _hemmedPants = pants
        owner.NotifyComplete()
    End Sub
End Class
The code for you could look something like this:
Code:
Public Class Person
    Private _pants As Pants
    Private _rarity As Seamstress
    
    Public Sub GetPantsAltered()
        _rarity = Phonebook.Find("Rarity the Seamstress")
        rarity.HemPants(Me, _pants)
    End Sub
    
    Public Sub NotifyComplete()
        _pants = _rarity.HemmedPants
    End Sub
End Class
When you want to call Rarity's HemPants(), you need to have an instance of Seamstress that represents Rarity. This is likely why you think you need Shared; you likely tried this:
Code:
Dim rarity As Seamstress
rarity.HemPants(...)
That doesn't work because you haven't created Rarity yet. Someone somewhere needs to create an instance:
Code:
Dim rarity As New Seamstress()
Once that instance exists, its HemPants() and HemmedPants members are accessible, so long as the caller has a reference to the instance. In Person.GetPantsAltered(), I got a reference to Rarity by looking her up in an imaginary Phonebook class. Once I have the Seamstress named Rarity, I ask her to hem my pants. To do so, she needs to know a specific instance of Pants, and she needs to know who to call when she's finished. I provide these via parameters to the HemPants method. When she's done with the pants, she updates her HemmedPants property and calls the pants' owner's NotifyComplete(); this causes the owner (you) to pick up the pants.

Aside: Note that Phonebook.Find() is a static method; this is an appropriate use because even though there's hundreds of phone books, they're all the same. It doesn't matter if I use my phone book or yours, Rarity's going to be listed the same in all of them. So why bother creating a specific phone book?

Sharing objects is easy. You need to remember you want specific instances. When you're writing code that needs an instance, you can express "this code needs an instance" via parameters to the method. That tells anyone calling the method what you need to work. They can find the objects they want you to work with and provide them. Alternatively, you can use properties to reduce the number of paramters; I won't demonstrate it because it has its own complexities.

I'd write a demo, but I'm quite busy today. Try to write something that implements a transaction like this between objects. If you get a NullReferenceException, it means you were supposed to use New to create an instance and you didn't. If it fails, post the *entirety* of the code and we'll see where you went wrong.

Shared doesn't affect whether you can use a variable from another class. I wanted to say it once more for good measure. When you create a Shared member, you are saying, "No matter how many objects there are, there's only one of this variable." This is rarely true, unless you're talking about Tiggers. (That's the most wonderful thing about Tiggers: Tigger is the only one!)
__________________
.NET Resources
My FAQ threads | Tutor's Corner | Code Library
I would bet money 2/3 of .NET questions are already answered in one of these three places.
Reply With Quote
  #4  
Old 09-26-2011, 12:56 AM
CodeCruncher CodeCruncher is offline
Junior Contributor
 
Join Date: Jul 2006
Posts: 355
Default

Another great write up... I can’t say I have it 100% down pat just yet, but I can visualise much of what you said so that is a great step towards remembering it.

Not sure I can quote it back to you verbatim but there are a few very important things I picked up from it.

Shared has absolutely nothing to do with whether a variable can be seen in another Class, that is strictly the domain of Public, Protected, Friend & Private. (Public can, Private can’t, not sure about Protected & Friend as I have never used them before).

An instance is like a photocopy of the Class... if you draw all over its members it won’t affect the original.

Shared is Class level; and any instances of the Class will have the same static value assigned to the Shared variable “pre populated” or Shared is like a blotch on your original, all photocopies will have a copy of the same blotch, you can’t pick which copies will and won’t have it. You only use shared when every copy of it needs to be the same.

You can’t update a Shared variable through an instance without an error popping up, because an instance is once and shared belongs to many. You have to update at the source.

And lastly if I need my pants taking up Rarity is the best person to do it, and don’t get any seamstress.

I need to go over it a few more times in my head to make sure I am using the shared’s I have properly but I think I still need a couple...

The amount of queries never changes (not without manually altering the Access db and restarting the app) so I need that same number for working out how many group boxes, labels and checkboxes to draw to screen... To work out how many columns and rows of group boxes... For loading ticks into the check boxes, for clearing the labels, for setting forecolor and back color of the labels, for setting the forecolor of the group boxes and check boxes. For resizing the group boxes, labels etc, and numerous other things across multiple classes (not that shared is used for spanning classes, I just need the same value in each of the classes).
Reply With Quote
  #5  
Old 09-26-2011, 07:26 AM
CodeCruncher CodeCruncher is offline
Junior Contributor
 
Join Date: Jul 2006
Posts: 355
Default

I went through some saved code... You had tried to explain this before... I found your dog breed example and tried to get it to work.

I tried to add a button and a text box so I could enter a dog type but can’t quite get it to work.
Code:
Public Class Form1
    Private Property GetBreed As String
    Public Property _breed As String
    Private Text1 As New TextBox

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

        Dim Label1 As New Label
        Dim Button1 As New Button

        Me.Controls.Add(Label1)
        Me.Controls.Add(Text1)
        Me.Controls.Add(Button1)

        With Label1
            .Location = New Point(100, 25)
            .Text = "Favorite Dog Breed"
        End With
        With Text1
            .Location = New Point(100, 50)
            .Text = "Poodle"
        End With
        With Button1
            .Location = New Point(100, 100)
            .Text = "Enter"
        End With

        AddHandler Button1.Click, AddressOf Button1_Click

    End Sub

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)

        Dim _person As New Person
        _person.LikesDog(Text1.Text)

    End Sub

End Class
Code:
Public Class Dog
    Private _breed As String

    Public Sub SetBreed(ByVal breedName As String)
        _breed = breedName
    End Sub

    Public Function GetBreed() As String
        Return _breed
    End Function

    Public Sub CopyTo(ByVal otherDog As Form1)
        otherDog._breed = _breed
    End Sub

End Class
Code:
Public Class Person
    Public Function LikesDog(ByVal dog As Dog ) As Boolean

        If dog.GetBreed = "Poodle" Then         'If dog._breed = "Poodle" Then
            Return False ' No one likes poodles!
        Else
            Return True
        End If
    End Function

End Class
Reply With Quote
  #6  
Old 09-26-2011, 08:57 AM
PlausiblyDamp's Avatar
PlausiblyDampToo Much Sharing PlausiblyDamp is offline
Ultimate Contributor

Forum Leader
* Expert *
 
Join Date: Nov 2003
Location: Newport, Wales
Posts: 2,058
Default

Do you have
Code:
Option Strict On
at the top of your source files? It doesn't look it....

The line
Code:
 _person.LikesDog(Text1.Text)
is expecting you to pass in an instance of the Dog class however you are simply passing in a string.

At a minimum you would need to do something like
Code:
Dim d as new Dog()
d.SetBreed(Text1.Text)

if _person.LikesDog(d) Then 
    'do something
End If
__________________
Intellectuals solve problems; geniuses prevent them.
-- Albert Einstein

Posting Guidelines Forum Rules Use the code tags

Last edited by PlausiblyDamp; 09-26-2011 at 09:07 AM.
Reply With Quote
  #7  
Old 09-27-2011, 06:54 AM
CodeCruncher CodeCruncher is offline
Junior Contributor
 
Join Date: Jul 2006
Posts: 355
Default

I dont have it set at form level, I have it set in VB configuration to force me to program better and not take shortcuts...

Yes that was exactly the message I was getting but was too tired to figure it out.

Code:
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)

        Dim _person As New Person
        Dim dogtype As New Dog()
        dogtype.SetBreed(Text1.Text)
        _person.LikesDog(dogtype)

    End Sub
Works a treat thanks for that PD. If it wasn't for AtmaWeapons Seamstress example I probably would have never been able to understand the breed example a bit better this time round.

Time to get off the PC before my eyes get sore again... Thanks again guys.
Reply With Quote
  #8  
Old 09-27-2011, 08:49 AM
AtmaWeapon's Avatar
AtmaWeaponToo Much Sharing AtmaWeapon is offline
Fabulous Florist

Forum Leader
* Guru *
 
Join Date: Feb 2004
Location: Austin, TX
Posts: 9,500
Default

Quote:
Originally Posted by CodeCruncher View Post
Works a treat thanks for that PD. If it wasn't for AtmaWeapons Seamstress example I probably would have never been able to understand the breed example a bit better this time round.
Just because Rarity's a lady doesn't mean she can't be useful in a software development metaphor. Or something.
__________________
.NET Resources
My FAQ threads | Tutor's Corner | Code Library
I would bet money 2/3 of .NET questions are already answered in one of these three places.
Reply With Quote
  #9  
Old 09-28-2011, 06:26 AM
CodeCruncher CodeCruncher is offline
Junior Contributor
 
Join Date: Jul 2006
Posts: 355
Default

Rarity did her bit in making things clearer

However I am still having problems... I tried unsharing iQuery and iClient but unlike the Dog example where _breed seemed to keep the string variable value, when I tried it in my app the integer reverts to zero again.

I have hacked out a whole heap of non related code and forms to keep it simple, and attached a version of the code I am working on to give you an idea of what I'm trying to do.

I remmed out all the bits I put in to get it working again, but you should be able to see what I've attempted.
Attached Files
File Type: zip MyClientz.zip (76.2 KB, 1 views)
Reply With Quote
  #10  
Old 09-29-2011, 12:41 AM
CodeCruncher CodeCruncher is offline
Junior Contributor
 
Join Date: Jul 2006
Posts: 355
Default

Ok think I am a step closer to working this out... running my app alongside AtmaWeapons Dog example.

I was stepping through each of them to see why the Dog example retained a _breed value where my app seemed to be losing the value.

Basically I need to set the Client and Query counts from one class, and get the value from other classes.

I noticed that when I set the value on Client and straight after that I set the value on Query, I can’t see a value for Client, which made me realise that I am declaring a “New MainLoad” in each of the Client and Query methods.

Code:
 Dim _mL As New MainLoad
So I took the declaration out of both the methods and placed it at form level. Hey presto after loading Query I now see both Client and Query values when I click on _mL.

Light bulb moment (globe to you guys) I am creating a new instance of MainLoad in each of the classes, no wonder the values for Client and Query are 0 when I look at the _mL in a different class, I haven’t set any values to them, only in the one instance.

I looked back at the Dog example and yep both Dog and Person are in the same Form1 class, and are not being re-declared in any other class. So the values set in this instance are the only ones being used.

Code:
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)

        Dim _dogtype As New Dog
        Dim _person As New Person
        _dogtype.SetBreed(Text1.Text)
        _person.LikesDog(_dogtype)

    End Sub
So now that I have worked out what went wrong I now need to know how I can make all the instances of _mL in the various classes get and retain the same value without using Shared?

Just had an idea... instead of trying to set the values in another class, and then access that class from other classes, why don’t I put the variables in the class that produces the values, and call an instance of that class from each of the other classes?

Hmmm don’t understand why that didn’t work... I set the variables in the class that created the value for them.

Code:
    Private ClientQty As Integer
    Private QueryQty As Integer

    Public Function GetClientQty() As Integer
        Return ClientQty
    End Function

    Public Function GetQueryQty() As Integer
        Return QueryQty
    End Function

   Public Function Check_Client_Rows() As Boolean

        If dtClients.Rows.Count > 0 Then
            ClientQty = dtClients.Rows.Count - 1
            Return True
        Else
....
 Public Function Check_Query_Rows() As Boolean

       If dtQuery.Rows.Count > 0 Then
            QueryQty = dtQuery.Rows.Count - 1
            Return True
        Else
....
And I called that class with a New instance of the class...

Code:
    Private Sub Load_Friendly_ComboBox()

        Dim _d As New Databases
        Dim x As Integer = _d.GetQueryQty()
...
But when I go back to class Databases to "Return QueryQty" to my calling instance, QueryQty is now 0, where it was > 0 when I was last in that class.

Nothing over wrote the value, so I don't know where my value went.
Reply With Quote
  #11  
Old 09-29-2011, 03:11 AM
CodeCruncher CodeCruncher is offline
Junior Contributor
 
Join Date: Jul 2006
Posts: 355
Default

I was still missing the big picture...

I’ve arrived back at the Databases class by virtue of using “_d.” So I am still working with an instance of Databases variables that are not the originals... which I think can only be accessed from the Databases methods, unless shared.

So the only way I can assign a value to my calling instance is if I use a “static” as AtmaWeapon calls them such as Shared or Const. I tried using Const but because I can’t set the value immediately (because I don’t know it) I can’t use Const.

I can pass a value to another class by using a Function with a parameter, and I can update variables within that class from the body of the Function, but I can’t get a value back from another class...
I am still missing some pivotal part here... So going back to the Dog...

I create an instance of Dog
I create an instance of Person
I pass Text1.Text to the Dog class and set Dog.SetBreed, which updates _breed
I then call Person.LikesDog passing my instance of Dog to it, which then makes a call to Dog.GetBreed passing the same instance of dog.
Returns the value of _breed and checks it to see if it equals “Poodle”

The whole time the same instance of Dog was used, but this only seems to work while you can keep the same instance moving around. If I call it from unrelated classes, I lose the connection to the set data.
Reply With Quote
  #12  
Old 09-29-2011, 10:11 AM
AtmaWeapon's Avatar
AtmaWeaponToo Much Sharing AtmaWeapon is offline
Fabulous Florist

Forum Leader
* Guru *
 
Join Date: Feb 2004
Location: Austin, TX
Posts: 9,500
Default

Gah I really don't have time for this but I felt bad because I forgot to look it over last night. Just had a quick look but it's a little too much for me to handle. I'll focus on #11 instead.

You are on the right track with this:
Quote:
The whole time the same instance of Dog was used, but this only seems to work while you can keep the same instance moving around. If I call it from unrelated classes, I lose the connection to the set data.
Yes!

Think of your program like a set of machinery. When I say "class", I'm talking about blueprints for building the machinery. When I say "object", I'm talking about the actual piece of machinery. You can say calling Sub New() is like using the blueprints to build a machine.

Every class needs certain materials for it to work. The class declares these needs in many ways:
  • Constructor parameters
  • Properties
  • Method parameters
Constructor parameters are like saying, "I can't even build this machine unless you give me these things first." Method parameters are like saying, "this machine can do X, but only if you give it these things first." Properties don't fit the analogy well; I guess you could say they're like batteries in that the machine won't work without them but you won't find out until you try. So most software engineers argue that constructor parameters and method parameters are the best way to provide the prerequisites.

The art of OOP programming involves several steps. First you build several small, preferably single-purpose machines that declare their prerequisites and what kinds of outputs they produce. Next, you create more machines with the purpose of providing inputs to the right machines and sending their outputs to the right places. The final product is like a pocketwatch: many small components cooperate in an organized fashion to produce a precise result.

It *sounds* like your problem is you can create an object, pass it along, modify it, but then you want someone in an isolated part of the program to get back at it again. What you need is a third party that's always aware of the object as it moves along. You've already got a good example: Application.OpenForms. No matter where you are in your application, you can get to every other form through this collection. Trouble is it works by magic so you don't necessarily get to see how it works.

Suppose you want to keep track of specific dogs for the lifetime of the program (or forever.) Imagine a class like this:
Code:
Public Shared Class Kennel
    
i   Private Shared _dogs As New List(Of Dog)()

    Public Shared Function GetDog(ByVal name As String) As String
        If (_dogs contains a dog with this name) Then
            Return that dog
        End If

        ' We haven't seen this dog yet, keep track of it
        Dim newDog = New Dog(name)
        _dogs.Add(newDog)
        Return newDog
    End Function

End Class
This is more or less my magic PhoneBook class. The whole class is Shared, so there's only one in the entire program and you access it via the class name. Instead of calling New Dog() directly from your code, now you ask for dogs through this class:
Code:
Dim fido = Kennel.GetDog("Fido")
fido.Pet()
fido.Feed()

' somewhere else
Dim fido = Kennel.GetDog("Fido")
If fido.IsHungry Then
    fido.Feed() ' Won't happen because he's already been fed
End If
The first time, Fido doesn't exist so the Kennel creates a new dog and stores it. The second time, Fido exists so you get the original Fido who has been fed. You can add code to save/load the kennel to a file/database so Fido's still around the next time you run the program.

This does represent a shift; now no one but Kennel should be allowed to create a Dog. If you let anyone else create a Dog, the Kennel won't know about it. There's alternate designs where creating a Dog requires a Kennel and the dog adds itself, but I don't like them. The reasons are myriad, but it comes down to not liking the idea that a Dog has to require a Kennel.

Kennel doesn't need to be a Shared class with Shared members. You can make it a class with instance members and then you can have multiple Kennels. But then the classes that need to get dogs from Kennels need to be fed the right Kennel. I actually avoid Shared classes like Kennel in my code because it makes it harder to understand which classes use it.

If I see this, it's clear the class wants to know about a Kennel:
Code:
Public Sub New(ByVal kennel As Kennel)
If the class uses a Shared Kennel, I don't get any clues that a Kennel is involved. In large programs, lack of clues can cost you more time than the effort required to leave the clues. It's my job to ensure the machine that creates a Kennel only creates one, and everyone else has to ask it for a Kennel.

I can't quite envision a demo, but that last sentence is kind of important. I think it comes from reading lots of articles about Inversion of Control. I build my applications like the machine analogy: it's rare that any given class can function without receiving instances of other classes from someone else. The chain might be complicated; C might require a D and E created by B to function, and B might require an A. That means somewhere someone creates an A and uses it to create a B. I call the type responsible for getting everything set up the "bootstrapper". It knows about rules like "the program can't function without an A" and "there can only ever be one A", and it enforces them.

When you think about it, your programs already work this way. The default project uses Form1.vb as a startup form. VB automatically generates a bootstrapper for you that creates an instance of Form1 and shows it. From there, Form1 is responsible for creating the rest of the objects needed in the application, and some of those objects might have requirements Form1 needs to satisfy.

Now I'm just babbling over and over about the same point. TL;DR: if you can't figure out how to get to object B when you're deep in object D, you need to build a bridge.
__________________
.NET Resources
My FAQ threads | Tutor's Corner | Code Library
I would bet money 2/3 of .NET questions are already answered in one of these three places.
Reply With Quote
Reply


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off

Forum Jump

Advertisement:





Free Publications
The ASP.NET 2.0 Anthology
101 Essential Tips, Tricks & Hacks - Free 156 Page Preview. Learn the most practical features and best approaches for ASP.NET.
subscribe
Programmers Heaven C# School Book -Free 338 Page eBook
The Programmers Heaven C# School book covers the .NET framework and the C# language.
subscribe
Build Your Own ASP.NET 3.5 Web Site Using C# & VB, 3rd Edition - Free 219 Page Preview!
This comprehensive step-by-step guide will help get your database-driven ASP.NET web site up and running in no time..
subscribe
Too Much Sharing
Too Much Sharing
Too Much Sharing Too Much Sharing
Too Much Sharing
Too Much Sharing
Too Much Sharing Too Much Sharing Too Much Sharing Too Much Sharing Too Much Sharing Too Much Sharing Too Much Sharing
Too Much Sharing
Too Much Sharing
 
Too Much Sharing
Too Much Sharing
 
-->