Organizing Code for the Business Logic Layer of an Application

In this second part of a six-part series on building the business logic layer of a .NET application, you'll learn how to organize the code, build a constructor, and more. It is excerpted from chapter five of the book Doing Objects in Visual Basic 2005, written by Deborah Kurata (Addison-Wesley, 2008; ISBN: 0321320492).

Contributed by
Rating: 5 stars5 stars5 stars5 stars5 stars / 2
December 28, 2009
Rate this Article:
MEH MEH++


SEARCH ASP FREE
TOOLS YOU CAN USE

advertisement

Organizing the Code Structure

Code that is organized is much easier to maintain, because you can quickly find the code that needs to be changed. When you standardize this organizational structure, any member of the team can quickly locate and modify any class code, because the code structure of each class is the same.

A class is normally composed of a set of properties and public and private methods. Public methods are methods that can be called from outside of the class, and private methods are those used only within the class.

You define the organizational structure of a class using regions, as described in Chapter 3. If you built a class template using the information in Chapter 3 and then used that template when creating your class, these regions are already defined in your code. If not, you can create the regions as follows:

Public Class Product

#Region " Properties"

#End Region

#Region " Public Methods"

#End Region

#Region " Private Methods"

#End Region

End Class

Add any other regions as needed to define the standard code structure for your classes. For example, if your class has a constructor, you can add a Constructor region as defined later in this section.


NOTE: Once you define the standard set of regions to use in your classes, define a custom class template, as described in Chapter 3. Provide this template to all the members of your team. This ensures that all the classes of your application follow your standard structure.


As you develop the code for the application, properties are added to the Properties region, public methods are added to the Public Methods region, and so on. To further aid in the organization, you can insert the properties and methods within each region in alphabetical order.


NOTE: If you don’t use a region, delete it. For example, if your class has no private methods, delete the Private Methods region. This makes it clear that the class has no private methods without opening the region to see that it has no private methods.


You can also put regions within regions. So, you can put each method in its own region within the Private Methods or Public Methods region. This makes it easier to focus on the code, because you can close all methods except for the one you are working with.  


Building Along

For the Purchase Tracker sample application:

  • Open the Product class in the Code Editor.
  • Add the regions as defined in this section.

In the Code Editor, open and close the regions to see how they hide and show their contents.


Instantiating an Object

Once a class is defined, you can create objects from the class. This is called object instantiation. You then use the object to access the properties and methods defined in the class.

To create an object from a class:

  1. Declare an object variable.

    For example:

    Dim prod as Product 
  2. Create a new instance of the class, and assign the object variable to reference that new instance.

    For example:

    prod = New Product




    NOTE FOR VB6 DEVELOPERS: The Set statement is no longer required when assigning an object reference to an object variable. 



  3. Access the properties and methods for the object by using the object variable and a period (.). For example:

    prod.ProductName

Alternatively, you can accomplish the first two steps in one code line as follows:

Dim prod as New Product

This line declares the object variable and assigns it to reference a new object from the Product class.


NOTE FOR VB6 DEVELOPERS: In classic versions of Visual Basic, it was highly recommended that you not put the New keyword on the declaration because of how instances were created. This is no longer the case, so the preceding syntax is generally recommended.  


Defining the Constructor

A constructor is a built-in method in a class that the .NET runtime executes when an object is first instantiated (created). You add code in the constructor to perform any initialization operations for a new object.

You define a constructor by creating a New method in the class as follows:

#Region " Constructors"
    Public Sub New()

    End Sub
#End Region

The constructor executes when you create an object from the class.

For example:

Dim prod as New Product

When the .NET runtime executes this line of code, it calls the New method in the Product class and runs any code in your constructor.


NOTE FOR VB6 DEVELOPERS: There is no longer an Initialize event for a class. Any code you would have put into the Initialize event can go into the constructor.


You can pass data into the constructor by defining parameters. The constructor is then called a parameterized constructor. For example, this constructor defines a productID as a parameter:

#Region " Constructors"
    Public Sub New(ByVal productID as Integer)

    End Sub
#End Region

You pass the parameter to the constructor when creating the instance of the object:

Dim prod as New Product(1)

or

Dim prod as Product
prod = New Product(1)

Multiple constructors can be defined for a class. For example, you could define a constructor with no parameters and one with a parameter. The .NET runtime knows which constructor to call based on the parameters passed to the constructor. Defining one method (in this case, New) with two different signatures is called overloading and is described in detail later in this chapter.

In many cases, you don’t need any specialized code to be executed when the object is instantiated, so you don’t need to create a constructor. If you don’t create one, the runtime executes an empty constructor for you.

In other cases, you may want a more formal object creation pattern. The most common formal pattern for object creation is called the Factory pattern. A pattern is a reusable solution for a recurring problem. The Factory pattern defines a standard solution for creating objects. Instead of creating an instance of a class using the New keyword, the Factory pattern defines a method that creates and returns an instance of the class.

This makes the process of creating object instances more explicit. See the “Additional Reading” section at the end of Chapter 1, “Introduction to OO in .NET,” for more information on patterns.


NOTE: The Factory pattern has two implementations: one using a factor class and the other using a factory method. This example uses a factory method.


If you elect to apply the Factory method, you no longer use this style of code to create an object:

Dim prod as Product
prod = New Product

You instead use code like this:

Dim prod as Product
prod = Product.Create()

The Create method, and the syntax used to call it, are defined in detail later in this chapter.


NOTE: If you select to use a Factory method pattern, other code in the application should use the Factory method and not directly instantiate an object using the New keyword. To prevent any code from creating an instance of your object without using the Factory method, define an empty constructor and use the Private keyword. For example:

#Region " Constructors"
    Private Sub New()

    End Sub
#End Region


Use constructors or a Factory pattern method to define any code that must be executed when first creating an object from the class. Don’t bother creating a constructor if you have no initialization code.


Building Along

For the Purchase Tracker sample application:

  • Open the Product class in the Code Editor.
  • Add a region for a constructor.
  • Add a private constructor with no code in the constructor.

    This ensures that code outside of the class cannot create objects from the class. Instead, a Factory pattern method is added in a later "Building Along" activity.
  • Open the ProductWin form in the Code Editor.
  • In the Load event for the ProductWin form, add code to create an object from the Product class:

    Dim prod As Product
    prod = New Product

    Visual Studio underlines part of the second code line and displays an error: "‘PTBO.Product.Private Sub New()’ is not accessible in this context because it is ‘Private’".

NOTE: If Visual Studio displays an error on the first line stating "Type ‘Product’ is not defined," either you did not set a reference from the Windows Application project (PTWin) to the business object Class Library project (PTBO), or you did not import the PTBO namespace. See the "Referencing Projects in a Solution" section in Chapter 3 for details.


  • In the Product class, comment out the private constructor by inserting comment markers before each of the two code lines of the constructor. The lines of code added in the preceding step are now syntactically correct.

Leave the private constructor commented out for now. This allows you to try out some of the upcoming features. The private constructor will be uncommented
when the Factory pattern method is added in a later “Building Along” activity.


Defining the Destructor

A destructor is a built-in method in a class that the .NET runtime executes when an object is destroyed. You define a destructor by creating a Finalize method in the class. But using a destructor is not recommended, because it does not necessarily execute when you expect it to, and it may not execute at all.

It may seem that the destructor should execute when you specify that you no longer need the object. For example, the following code defines that you no longer need the specified object reference:

prod = Nothing

But this code does not destroy the object. It just releases the object, making it available for destruction.

Your code does not define when an object is destroyed—the .NET garbage collector does. The garbage collector is a memory manager that manages the allocation and release of memory for all .NET applications. The garbage collector performs garbage collection when it needs to. It then releases the memory allocated to a managed object and destroys the object if that object is no longer used. But because you cannot predict when the garbage collector will perform garbage collection, you don’t know exactly when your object will be destroyed. Therefore, you cannot know when your destructor will be executed. (See the “Additional Reading” section for more information on the garbage collector.)

In most cases, you don’t need to write any cleanup code that executes when an object is destroyed, so you don’t need to care about this. You can just allow the garbage collector to destroy your object when it gets around to it.

But if your object works with unmanaged resources, you do need to write some cleanup code. Unmanaged resources are system resources that are not directly managed by the .NET runtime, such as database connections, window handles, open files, network connections, and graphic resources. You need to explicitly release unmanaged resources when your object is released.

Because the execution of the Finalize method is unpredictable, do not put the code to release unmanaged resources in the destructor. Create a Dispose method instead, and explicitly call Dispose when you release the object. Add code in the Dispose method to perform any cleanup activities required for your object—primarily, releasing any unmanaged resources used by your object. And since you are explicitly calling Dispose, you control when the unmanaged resources are released.


NOTE FOR VB6 DEVELOPERS: There is no longer a Terminate event for a class. Any code you would have put into the Terminate event can go in the Dispose method.


Define a Dispose method by implementing the .NET Framework IDisposable interface. Using the IDisposable interface to define your Dispose method ensures that you have a standardized programmatic interface for disposing of your objects.

To implement a Dispose method, do the following:

  1. Open the class in the Code Editor.
  2. Add the Implements statement to the class definition to implement the IDisposable interface:

    Public Class Product
        Implements IDisposable
     
  3. Press the Enter key after the name of the interface. The Code Editor automatically adds the signatures for all the properties and methods defined in the interface and related code to the class. This generated code uses the recommended design pattern for proper cleanup of any unmanaged resources that your application uses.

Visual Studio adds two sets of generated code as part of the IDisposable interface implementation, defining two Dispose methods. The first part of the generated code provides a Dispose method that you can customize to your requirements:

Private disposedValue As Boolean = False ' To detect redundant
->calls

' IDisposable
Protected Overridable Sub Dispose(ByVal disposing As Boolean)
    If Not Me.disposedValue Then
        If disposing Then
            ' TODO: free unmanaged resources when explicitly called
        End If

          ' TODO: free shared unmanaged
resources
      End If
      Me.disposedValue = True
End Sub

The disposedValue variable keeps track of whether the object has already been disposed so that it won’t dispose it again.

The parameter passed to this customizable Dispose method defines whether Dispose is called from the IDisposable interface Dispose method (shown next). If so, the code should free any unmanaged resources, so put your cleanup code here, by the first TODO Task List comment. If you have shared resources (those defined without a specific instance), put that cleanup code by the second TODO Task List comment.

When all the unmanaged resources are freed, this code sets the disposedValue property so that it won’t dispose again.

The second part of the generated code defines the implemented interface:

#Region " IDisposable Support "
   
' This code added by Visual Basic to correctly implement the
   
' disposable pattern.
   
Public Sub Dispose() Implements IDisposable.Dispose
       
' Do not change this code.  Put cleanup code in
       
' Dispose(ByVal disposing As Boolean) above.
       
Dispose(True)
       
GC.SuppressFinalize(Me)
    End Sub
#End Region

This code is meant to be left unchanged. This interface Dispose method first calls the customizable Dispose method to perform the cleanup. It then calls the SuppressFinalize method on the garbage collector. SuppressFinalize tells the garbage collector that it does not need to perform further cleanup on the object because the object was already cleaned up by the customized Dispose method.


NOTE: Some dispose patterns suggest that you also override the Finalize method. In the Finalize method, you call the customizable Dispose method and pass in False. Overriding the Finalize method is not recommended due to the performance and complexity costs of using a finalizer. See the Framework Design Guidelines book, listed in the “Additional Reading” section, for more information.


Unlike the Finalize destructor, the Dispose method is not called automatically. The code that created the object must manually call Dispose explicitly when destroying the object as follows:

prod.Dispose()
prod = Nothing

If your code creates an object using the Using statement, as defined in the preceding chapter, the .NET runtime automatically calls the Dispose method at the end of the Using block, so you don’t need to explicitly call Dispose. The Using statement also ensures that Dispose is called even if an error occurs within the Using block.

In this example, the Using statement is as follows:

Using prod As Product = New Product
   
' Code to work with the object here
End Using

Or, if you are using a Create Factory pattern method:

Using prod As Product = Product.Create()
    ' Code to work with the object here
End Using


NOTE: You can use the Using statement only if the class (Product in this case) implements the IDisposable interface.


If your class does not have or use any unmanaged resources, it can leave it up to the garbage collector to clean things up, and no Dispose method is needed. If your class does use unmanaged resources, implement a Dispose method using the IDisposable interface, as described in this section. Any code that creates an object from your class must then correctly destroy it when it is finished with it by calling the object’s Dispose method or by using the Using statement.  


 Building Along

For the Purchase Tracker sample application, do not implement the IDisposable interface in the 
Product class. The Product class does
not access any unmanaged resources, so it does not need to have any special dispose processing.


 

  • Please check back tomorrow for the continuation of this article.

     

     

  • blog comments powered by Disqus
    .NET ARTICLES

    - .Net 4.5 Brings Changes
    - Understanding Events in VB.NET
    - Objects, Properties, Events and Methods in V...
    - Install Visual Web Developer Express 2010
    - Microsoft Gadgeteer an Open Source Alternati...
    - Best DotNetNuke Modules
    - Facebook Image Viewer in Visual Basic
    - Murach`s ADO.NET 4 Database Programming with...
    - 5 Must Have Visual Studio 2010 Extensions
    - Dynamic Web Applications with ASP.NET Mono u...
    - PDFSharp: HTML to PDF in ASP.NET 3.5 using V...
    - Using the PDFSharp Library in ASP.NET 3.5 wi...
    - Sending Email in ASP.NET 3.5 using VB.NET wi...
    - ASP.NET 3.5 Role Based Security and User Aut...
    - Creating ASP.NET Login Web Pages and Basic C...

    ASP Web Hosting ASP.Net Web Hosting Windows Web Hosting
     
     
     

    ASP Free Forums 
     RSS  Tutorials RSS
     RSS  Forums RSS
     RSS  All Feeds
    Site Map 
    Request Media Kit
    Write For Us Get Paid 
    Weekly Newsletter
     
    Developer Updates  
    Free Website Content 
    Privacy Policy 
    Support 


    © 2003-2012 by Developer Shed. All rights reserved. DS Cluster 5 - Follow our Sitemap
    Most Popular Topics
    All ASP.Net Tutorials