Fog Creek Software
Discussion Board




Have I misunderstood .Net classes?

I'm starting my first .Net application after many years of traditional ASP. I reckon I've got my head around the basic aspects of OO but I'm unsure whether I'm using classes as they should be.

An simple example: let's say for every time a page is accessed on my site, I want to create a GUID. So I've got a class that creates a guid and stores it as a property. I've got a bunch of other classes that encapsulate functionality that use that GUID. Now this is where the whole Inherits thing goes out of the window. I don't need to 'inherit' the CreateGuid functionality - I want my other classes to be able to access the instance of this class so they can all use the same GUID.

In fact, all my classes are built to hold some sort of state. Thus the Product class might have a CurrentProduct property that is based on a parameter from a querystring. A bunch of other classes might want to use this class - obviously, I don't want to create a new instance of the class each time I need to access its properties and methods.

What I've done is create a sort of metaclass which has references to all the other classes, and I can punt this around knowing I'll never create more than one instance of the subclasses. It works quite well. I'm just concerned that I've misunderstood OO in some fundamental way - I've not seen my workaround reproduced, and I'm not using any of those funky Protected Static Inherited stuff.

I appreciate that since it works for me and I understand it you might ask what's the problem? The question is how this issue - of using classes for 'state' as well as pure functionality - is tackled elsewhere.

Thanks for any input.

AJP
Tuesday, August 17, 2004

You might find it easier to get your head around OO if you try some of the concepts out in a WinForms (or console) application. I think that ASP.NET complicates matters somewhat (for people learning OO).  Why? Becasue of issues around statelessness in web apps.  Basically, if you do some experiements in WinForms or Console apps you'll be able to avoid unnecessary complications in the lifetimes of your objects.

John Rusk
Tuesday, August 17, 2004

PS: regarding your specific examples, could you post a few more details about one example?  Either the GUID one or the product one.  That might help readers to answer your questions better.

John Rusk
Tuesday, August 17, 2004

There is already a GUID class.  System.Guid.

In all my .NET work, I've never actually had to use a GUID though, for persistance or otherwise, unless I was interacting with COM or the GAC.

I think what you're having difficulty with, specifically, is the OO nature of ASP.NET.  It's OO, but it's also web-based.  Everything you create is destroyed after every request, but there is some glue to make some of that seem like it doesn't happen.

I'd recommend taking a class.  A decent class will jumpstart your understanding much more quickly that stumbling around in the dark on it.

I'd also recommend learning .NET in C# instead of VB.  You seem to be carrying a lot of your VBisms into .NET and that can get you into trouble.  Learn .NET in C#, so you can have a clear seperation of concepts.  Once you've got C# and .NET down, then you can go back to VB.NET if you like the syntax better.

As for persistance, an easy way to do it is to just mark all your classes with the Serializeable attribute (the SDK docs are your friend) and then stick it in ViewState.  You can use Session and Application too, but don't do that until you are sure you know enough to know when to break the "Do not use Application or Session variables" rule.

Hope this helps.

Richard P
Tuesday, August 17, 2004

I am a bit confused by your descriptions, so this might be not what you want, but anyways.

If I get it right you are duplicating inbuild functionalities.

What you want is static members. These are associated with the class, not any instance of it. You initialise the values for the static fields through a static constructor.
If you wish you can prevent creating any instances of the class by putting in a default constructor which you leave empty and mark private.

Just me (Sir to you)
Tuesday, August 17, 2004

You're on the right track. Success will come earlier from error than off confusion. You've created a little framework. Now, as a post-analysis, you need to retrofit the framework.

While it is true that starting out an object framework on a Windows or Console application will be more discerning for you as a developer, yet, at the architectural level, I see some confusion on your part. OO programming is an orientation of thought. Start by thinking in terms of objects. Stop thinking in terms of access level specifiers/modifiers, qualifiers and inheritence.

A class of yours generates and supplies GUIDs to other class objects. Stop mingling programming qualifiers and inheritence for some time. This class is an independant vendor. You're right in thinking you don't need to inherit from this class. This is just a black box object and other objects of yours will call for its service as and when they need it.

You mentioned the Product class. I would guess it represents "one" product. If it doesn't, or does represent more than "one" product, you've not named it, or perhaps modelled it after real life. Think again, in terms of real life. You add that the Product class contains a member called CurrentProduct that holds the "currently selected product" from the QueryString. I tend to think, as an OO developer, that the "type" of the member CurrentProduct ought to be Product. So, if this is the case, you've one of the two anomalies in your design:

(1) If the Product class represents only 1 product, should it really contain a member property of it's own type called CurrentProduct? What is the type of CurrentProduct? If it is not type Product, you're in trouble. If it is, then you've got a circular reference problem, in a self-referencing object.

(2) If the Product class represents more than a single product, then you intended to have a collection here, actually. So, either the name Product doesn't hold good, or the model you've designed the Product class in is fallible.

Ideally, you would have a collection called Products or ActiveProducts, or something. The collection may implement ICollection. It may then contain a CurrentProduct of Product type. Real life is the key.

Our product or our catalog of products has nothing to do with GUIDs. GUID is a service shop that we visit once in our lifetime. Create an object of GUID whenever you want to locally within the routine that requests the GUID and destroy the GUID object then and there. Use it like a Just In Time (JIT) object.

Because you wish to persist (not serialize) the object CurrentProduct throughout the session or lifetime of your application and not create more than one instance of the class, declare the CurrentProduct object globally. Then dereference the member/property CurrentProduct of the Products collection to this global CurrentProduct object. This, so that even if you have to flush your Products collection everytime you run an SQL query to fetch the refreshed product list, you could still hold a reference to the previously selected product, even if you do not need to use it.

As the other members have expressed, tackling statefullness with Web applications is not as straight-forward as on Windows or Console applications. However, we could work-around it by causing a shift in our orientation of thought towards real life objects.

Sathyaish Chakravarthy
Tuesday, August 17, 2004

Thanks for the tips.

The GUID thing may have been a red herring - I was trying to keep the hypothetical small. Here's a bit of pseudo-code which might give a better example - I'm not too fussy about vb or c# (apologies if this is a bit of mess when I post it :( ):

-- Here's my base class - ensure that only one instance of the sub classes are created; note how using 'this' to pass the base class to other sub-classes:
public class BaseClass
{
private Product p_prod;
public Product Prod {
  get {
    if (p_prod == null) { p_prod = new Product(this); }
    Product = p_prod;
  }
}

// same sort of thing for the category class
private Category p_category;
public Category Cat ... etc.

}

-- Here's a class which represents our current category
public class Category
{
public string CurrentCatgory { set... }

public string ParentCategoryForCurrentProduct = GetParentCategory(base.CurrentProductID);

private BaseClass base;
// give access to the base class so this class
// can access other class methods
public Category(ref BaseClass baseClass)
{ baseClass = base;}

}


-- Here's a class which represents a product
public class Product
{

public string CurrentProductID = Request.QueryString("productid");

public xpathdocument CurrentProductXML = GetProductDetails(base.CurrentCategoryID, CurrentProductID);

private BaseClass base;
// give access to the base class again
public Product(ref BaseClass baseClass)
{ baseClass = base;}
}

-- now here's one of my pages - what I can now do is assign a 'current category' to the category class, and then get some product details based on that assignment:

BaseClass baseClass = new BaseClass();
baseClass.Cat.CurrentCategory = "ACME Flanges";
[do something with] baseClass.Prod.CurrentProductXML;

here, the current product xml is dependent on first setting the current category.

====

Essentially I'm shuttling around my base class so that my sub classes can access the properties of other classes. Is this smart / weird / idiotic :) ? At the very least, it allows me to only have to reference one class (baseclass) on my pages without having to create instances of other classes.

AJP

AJP
Tuesday, August 17, 2004

No, the BaseClass here doesn't serve any purpose. You're only using it as a container to contain two other objects.

The answer is in thinking about real life objects. What is your product. It is a thingy. Okay!

What is a category? How does it relate to a product? A category, I would guess, is an attribute of a product such that:

(1) A product belongs to a category.
(2) Zero or more products may belong to a particular category.

Wouldn't it make sense, then, to:

(1) Do away with a BaseClass
(2) Have the category class as a member of the product class.

That way again, you have just one class, namely Product.

Sathyaish Chakravarthy
Tuesday, August 17, 2004

If I get it right you are worried about two things:
- having singleton objects (their can be only one catagory object etc.)
- having access to the collection of those singletons

For the former thing have a look at this discussion on implemeting singletons in C#: http://www.yoda.arachsys.com/csharp/singleton.html

for the latter: since the singletons are easily accessed through the class name, I don't see what exactly your "base" class is there for. It seems fully redundant.

Just me (Sir to you)
Tuesday, August 17, 2004

Okay, I'll have a close look at singletons.

The idea behind the base class was twofold: first, to allow all classes to access 'helper' classes. Some of those helper classes don't just encapsulate functionality, but might have values set by the calling page.

Second, it was a shorthand way of not having to instantiate new instances of the classes every time I want to use them. I only have to instantiate one class on my page.

AJP

AJP
Tuesday, August 17, 2004

Thanks for all your help everyone. It's really good to know that people are willing to spend a few minutes helping out. Everyone has helped me move forward.

Singletons look promising for some of the stuff I want to do. Otherwise, it looks like I need to make my objects reflect more of what they need to encapsulate.

AJP

AJP
Tuesday, August 17, 2004

> it looks like I need to make my objects reflect
> more of what they need to encapsulate.

That was funny!

Jon Dinlea
Tuesday, August 17, 2004

I recommend two books: _Design Patterns_ by Gamma et. al., and _Refactoring_ by Fowler.

Christopher Wells
Tuesday, August 17, 2004

Those two books are probably a little advanced.

Try Demystifing OOP, available on your friendly neighborhood P2P filesharing network.

Dutch Boyd
Tuesday, August 17, 2004

*  Recent Topics

*  Fog Creek Home