Building Mobile Business Objects

Building Mobile Business Objects

Download Samples

 

Download PDF

Overview

The drive to connect people, process and devices is a never ending cycle of development. Enterprises are demanding applications that deliver seamless communication with their partners and customers without sacrificing security, transactions, reliability and performance. Distributed application systems are quickly becoming the norm. Service orientation is an approach to software design and development that helps to solve this problem.

 

Service oriented (SO) design defines message oriented programs called services that are the fundamental solution building blocks. Service oriented architecture results in loosely coupled application systems that enable business to respond faster to change. SOA allows for a more natural depiction of the business process, real life events and system boundaries in software, improving the ability to respond to changes in the business. Also, the closer modeling of application systems to reality allows for relevant and actionable business data and loose coupling between services that reduce the ripple effect of changes.

 

The ever increasing complexity of enterprise systems has tested the limits of the OO architecture and design and paved the way for the evolution of SOA. Service orientation is a compliment to object orientation not a replacement. The primary distinction between SO and OO is in how you view applications. In a solely object oriented approach, an application is a tightly coupled program built from class libraries that have dependencies on each other. An SO based application is a different entity entirely, composed of loosely coupled autonomous services programs. SOA defines the message oriented services to build distributed solutions, created with object orientation.

 

It’s the combination of OO and Service oriented that are important to understand when building not only mobile applications but any type of .NET application. In this article we will look at how these types of objects are built and the ways they can be used within mobile applications using Visual Studio 2005.

Introduction to mobile business objects

Object oriented principles were developed to solve the problems of modern day programming. As shown in Table 1, OO is based on a set of design principles that define behaviors that are common to objects. By definition an object is a set of software that contains properties, variables and methods that describe something. For example, objects are used to describe a customer, invoice or a purchase order. Business objects are built using these same core principles with differences in architecture and methodology to overcome the shortcomings of OO within a distributed architecture.

Table 1: Principles of Object Oriented Development

OO Concept

Definition

Abstraction

Implementation of code to mimic actions and characteristics of any real world entity

Encapsulation

Defines that a group of related properties, methods, and other members are treated as a single unit or object. Encapsulation also makes it easier to change the implementation at a latter date by hiding the object specifics.

Polymorphism

Defines that you can have multiple classes that can be used interchangeably, even though each class implements the same properties or methods in different ways. Polymorphism is essential to object-oriented programming because it allows the use of items with the same names, no matter what type of object is in use at the moment.

Inheritance

Defines the ability to create new classes based on an existing class. The new class inherits all the properties and methods and events of the base class, and can be customized with additional properties and methods.

For example, one of the most common OO design problems in a distributed system is that objects become chatty. A chatty system is one where there is a lot of unnecessary communication between the client and the services. This often occurs because clients have to call multiple methods for each action they need to perform. This leads to excessive network load. Given that mobile devices already have resource limitations this can lead to a poorly scaled application and poor end user experience.

 

By definition business objects are encapsulated units of information and methods that relate to business data or functionality. Fundamentally, they are about separating the logic from the database and allowing developers to build self contained units of business logic. Technically, business objects may operate independently or encapsulate lower level OO based objects that implement a business process.

Figure 1 A logical application architecture

 

Using business objects as the base of your application requires a shift in thinking about application architecture. Traditional applications are considered an autonomous entity that is composed of layers and then deployed into tiers. However, business objects have changed this paradigm to a service model that is based on message based interaction where services are considered actors and data is passive. This allows for a separation between different layers of the application and leads to a logical architecture as shown in Figure 1. In this model objects become smart data containers.

Figure 2 The basic property declaration

 

An Object is a structure containing data and methods that manipulate data. A class is the simplest example of an object. By definition a class is a blueprint that defines variables, properties and methods common to objects of a certain kind. A class is considered an abstract representation where an object is a useable example of the thing that the class represents. Properties are part of the program interface and describe the characteristics of a class. Properties hold information about a class when loaded into memory. The body of the property declaration contains Get and Set properties that describe the object as shown in Figure 2. The actual value of the property is stored outside of the property in variables and is accessed externally through the Get and Set properties.

 

Objects are often data centric in distributed systems. A data centric object is designed to treat data as passive. Good development practice means that you don’t necessarily map exactly to what is in the database. This creates a level of abstraction. The object provides a transport for data and contains no behavior. These simple business objects contain one or more simple attributes and a list of supported verbs. For example, Listing 1 shows an example of a data centric customer class.

Listing 1: A data centric customer class.

Public Class clsCustomer

    Private _Cust_Address As String

    Private _Cust_Name As String

    Private _Cust_ID As String

    Private _Cust_Phone As String

    Private _Cust_State As String

    Private _Cust_Zip As String

    Private _Cust_City As String

 

    Public Sub New(ByVal Cust_address As String, ByVal Custname As String, ByVal Cust_ID As String, ByVal cust_phone As String, ByVal Cust_state As String, ByVal Cust_zip As String, ByVal Cust_city As String)

        Me.Cust_Address = Cust_address

        Me.Cust_Name = Cust_Name

        Me.Cust_ID = Cust_ID

        Me.Cust_Phone = cust_phone

        Me.Cust_State = _Cust_State

        Me.Cust_zip = _Cust_Zip

        Me.Cust_City = _Cust_City

    End Sub

    Public Property Cust_Address() As String

        Get

            Return _Cust_Address

        End Get

        Set(ByVal value As String)

            _Cust_Address = value

        End Set

    End Property

 

    Public Property Cust_Name() As String

        Get

            Return _Cust_Name

        End Get

        Set(ByVal value As String)

            _Cust_Name = value

        End Set

    End Property

    Public Property Cust_ID() As String

        Get

            Return _Cust_ID

        End Get

        Set(ByVal value As String)

            _Cust_Name = value

        End Set

    End Property

 

    Public Property Cust_Phone() As String

        Get

            Return _Cust_Phone

        End Get

        Set(ByVal value As String)

            _Cust_Phone = value

        End Set

    End Property

 

    Public Property Cust_City() As String

        Get

            Return _Cust_City

        End Get

        Set(ByVal value As String)

            _Cust_City = value

        End Set

    End Property

    Public Property Cust_State() As String

        Get

            Return _Cust_State

        End Get

        Set(ByVal value As String)

            _Cust_State = value

        End Set

    End Property

 

    Public Property Cust_zip() As String

        Get

            Return _Cust_Zip

        End Get

        Set(ByVal value As String)

            _Cust_Zip = value

        End Set

    End Property

End Class

 

This type of business object is designed to encapsulate the data definition of a business object. For example, when describing a customer this would include the customer name and address information. Each defined property represents a value that describes an spect of the customer. All the properties contain simple attributes that represent a value for the object such as a string or integer. This object is instantiated and a customer is added using the code in listing 2.

Listing 2:Adding a customer to the object.

Dim Customer As New clsCustomer(Cust_Address:="123 Anywhere St.", _

                                        Custname:="Mondo Corp Inc.", _

                                        Cust_id:="Q1234", _

                                        Cust_phone:="6033452345", _

                                        Cust_State:="New Hampshire", _

                                        Cust_zip:="03110", _

                                        Cust_city:="New Hampshire")

 

Figure 3 Adding Methods to a class

 

Object may also contain behaviors. This enables objects the ability to perform actions.

These are implemented by Methods exposed by a class in either a function or sub. Both are responsible for executing code on behalf of the calling application. However, the sub procedure does not return a value while the function does. For example, we can add the following two methods as shown in Figure 3.

The Array Class

Found in the System namespace, the array is one of the basic types of system classes. By default arrays are declared as a fixed size. This means that the total number of items they can contain is declared during initialization. Listing 3 shows how to declare an array based on the customer class and then add two entries.

Listing 3: Declaring and adding two customers to the array.

Dim customers(1) As clsCustomer

customers(0) = New clsCustomer("123 Anywhere St.", "Alfred Industries", "ALFRE", "123-456-7890", "NH", "03110", "Bedford")

customers(1) = New clsCustomer("456 Main St.", "General Industries", "GENERAL", "123-764320", "NH", "03110", "Bedford")

 

Figure 4 Arrays are strongly typed

 

When combined with a class object, arrays are considered strongly typed as shown in Figure 4. This means that they can only contain objects of a specific type. For example the following code shows how to set the first customer name.

customers(0).Cust_Name = "Alfred Industries"

 

Arrays are an ideal solution for transporting data when you know ahead of time how many items are contained. Arrays are often used when passing a number of similar objects to a method or function call as a parameter. Listing 4 shows an example of how the customer array can be passed to another function and then accessed.

Listing 4: Passing an array structure

Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click

        Dim customers(1) As clsCustomer

        customers(0) = New clsCustomer("123 Anywhere St.", "Alfred Industries", "ALFRE", "123-456-7890", "NH", "03110", "Bedford")

        customers(1) = New clsCustomer("456 Main St.", "General Industries", "GENERAL", "123-764320", "NH", "03110", "Bedford")

        Call ReceiveArray(customers)

    End Sub

 

    Private Function ReceiveArray(ByVal CustArray As Array)

        ' get the size of the array and subtract one

        ' as arrays always start with zero

        Dim receiveSize As Integer = (CustArray.Length - 1)

        ' instantiate the array with customer information

        Dim customers(receiveSize) As clsCustomer

        CustArray.CopyTo(customers, 0)

 

        ' iterate through the customer names

        Dim i As Integer

        For i = 0 To (customers.Length - 1)

            MsgBox(customers(i).Cust_Name)

        Next

    End Function

Defining Interfaces

The greatest percentage of development time is spent on the business specific parts of an application. This makes business rules and objects the heart of most applications. Also, this makes these groups of objects an ideal unit of reuse. Business components are encapsulated in two directions. The external world must not know anything about component internals. Internally the object must not know anything about external components other than allowing interested objects to register for notification of specific events or exception conditions.


Figure 5 Adding an interface to a project

 

Given these requirements distributed objects are not architected as traditional objects. Rather they have a few course grained methods and carry no client specific state. These are the same design considerations for architecting Web Services, which is the primary reason why Web services and distributed objects are so similar. There are more similarities between the two. For example, each Web services specify a contract, described by WSDL. Distributed objects also specify a contract which is their interface defined in some form of an Interface Definition Language (IDL). Both also face similar complexities surrounding security, identity, concurrency and transaction management. Visual Studio provides the Interface file as shown in Figure 5.

 

Interfaces like classes define a set of properties, methods and events. But unlike classes, interfaces do not provide an actual implementation. They are implemented by classes and defined as separate entities from the class. Interfaces define a contract that requires any class to implement the entire definition. Listing 5 shows the interface file for the customer class.

Listing 5: The customer interface file

Public Interface ICustomer

    Sub AddCustomer()

    Function GetCustomerBalance() As Integer

 

    Property Customer_Name()

    Property Customer_ID()

    Property Customer_Address()

    Property Customer_City()

    Property Customer_State()

    Property Customer_ZipCode()

    Property Customer_Phone()

End Interface

 

Figure 6 Implementing the customer interface

 

Interfaces define features as small groups of closely related members. This allows the creation of enhanced implementation for interfaces without jeopardizing existing code. Also, this minimizes the possible version compatibility problems. Additional features can be added by implementing additional interfaces as shown in Figure 6.

 

Although the classes that implement an interface are able to evolve, the actual interfaces themselves cannot. Any changes to a published interface may break existing code. Like a contract, both the implementing class and the interface have a role to play. The publisher of an interface agrees to never change the interface and the implementer agrees to implement the interface as it was designed.

Introducing Collections

Business objects have both structure and definition. A collection is an object that allows the grouping of other objects. It is a set of similarly typed objects grouped together. The .NET Compact Framework contains a variety of built in collection types that can be found in the System.Collections namespace as shown in Table 2.

Table 2: The System.Collection Namespace

System.Collections

Provides interfaces and classes that define various collections of objects

System.Collection.Specialized

Contains specialized and strongly typed collections.

System.Collections.Generic

Contains specialized interfaces and classes that define generic collections

 

This namespace contains interfaces and classes that define various types of pre-built collections. These system defined collections are useful for storing heterogeneous data. Depending on the type of collection they may be either strongly or weakly typed. However, when using a strongly typed class the type of the item is known and doesn’t require any additional conversion. Listing 6 shows an order class that will be used to demonstrate the various types of collections.

Listing 6: An example of an order class

Public Class Order

    Private _OrderDate As Date

    Private _OrderNumber As Integer

    Private _OrderAmount As Decimal

    Private _CustomerName As String

 

    Public Sub New(ByVal orderdate As Date, ByVal ordernumber As Integer, ByVal orderamount As Decimal, ByVal customername As String)

        Me.OrderDate = orderdate

        Me.OrderNumber = ordernumber

        Me.OrderAmount = orderamount

        Me.CustomerName = customername

    End Sub

    Public Property CustomerName() As String

        Get

            Return _CustomerName

        End Get

        Set(ByVal value As String)

            _CustomerName = value

        End Set

    End Property

    Public Property OrderAmount() As Decimal

        Get

            Return _OrderAmount

        End Get

        Set(ByVal value As Decimal)

            _OrderAmount = value

        End Set

    End Property

    Public Property OrderDate() As Date

        Get

            Return _OrderDate

        End Get

        Set(ByVal value As Date)

            _OrderDate = value

        End Set

    End Property

 

    Public Property OrderNumber() As Decimal

        Get

            Return _OrderNumber

        End Get

        Set(ByVal value As Decimal)

            _OrderNumber = value

        End Set

    End Property

End Class

System.Collections Namespace

Closely related data can be handled more efficiently when grouped together into a common collection. Instead of writing separate code to handle each individual object, you can use the same code to process all the elements of a collection. Managing a collection is done with a combination of the array class and the System.Collections classes. This combination is used to add, remove, and modify individual elements of the collection or a range of elements. By default memory management is handled automatically and the capacity of a collection is expanded as required. Additionally collections provide thread safety when accessing member of the collections. Collections also generate an enumerator that makes it easy to iterate through individual elements.

 

The .NET Framework Base Class Library offers a formal definition of a collection as defined by the System.Collections.ICollection interface. All of the types in the System.Collections namespace implement the ICollections interface. Table 3 shows the methods that are made available when implementing this interface.

Table 3: The ICollection interface features

Name

Description

CopyTo

This method allows the user of the collection to obtain an array of the collection's items. This is useful since it is typically easier to manipulate an array of items versus using an enumerator.

Count

This read-only property returns the number of items currently in the collection

IsSynchronized

This read-only property returns true if the collection type has been designed to be thread safe. If you are using a single collection object from multiple threads, and this property is false, then you must add the code to synchronize operations on this object.

SyncRoot

This read-only property returns the object, which can be used to manually synchronize the collection.

 

These built in collections include the ArrayList and HashTable collections, along with the CollectionBase class which enables the extension of strongly typed collections. This namespace also contains a variety of pre-built collections as shown in Table 4. These include the Stack and Queue which are essentially an ArrayList underneath the covers, but also places restrictions on the order that elements can be accessed from the collections. There’s also a BitArray class for effectiently storing a collection of Boolean values.

Table 4: Collections of the System.Collections namespace.

Collection Type

Description

ArrayList

Used to manage an array whose size is dynamically increased as required

BitArray

Used to manage a compact array of bit values which are represented as Booleans

HashTable

Represents a collection of key/value pairs that are organized based on the hash code of the key

Queue

Represents a first in, first out collection of objects

Stack

Represents a simple last in, first out collection of objects.

SortedList

Represents a collection of key/value pairs that are sorted by the keys and are accessible by key and by index.

 

The ArrayList

The ArrayList collection is similar to the standard array class. The major difference is that the Array List is not strongly typed and the Arraylist size can be changed dynamically. For example Listing 7 shows how to instantiate an ArrayList and add two order objects.

Listing 7: Creating an ArrayList collection.

Dim orders As ArrayList = New ArrayList

orders.Add(New Order("1/1/2006", "1234", 1200.54, "ALFKI"))

orders.Add(New Order("1/31/2006", "4567", 1895.54, "CAPI"))

 

When accessing an item in the collection there is no available IntelliSense. This is because the ArrayList is weakly typed. In order to use the arraylist and access items with intellisense requires an object cast as shown below.

 

ctype(orders(0), Order).CustomerName = "ALFKI"

 

Figure 7 IntelliSense on the cast object.

 

Once the cast is complete IntelliSense becomes available as shown in Figure 7. Also, collection enumeration is available as shown in Listing 8.

Listing 8: Enumerating an ArrayList

Dim i As Integer

For i = 0 To (orders.Count - 1)

  MsgBox(CType(orders(i), Order).CustomerName)

Next

 

The major advantage of the ArrayList is that you do not need to know in advance how many items it will contain. One of the more important methods of the ArrayList is the ToArray function. This function is used to copy collection items to an array. When called use the type of item you want in the array as a parameter. Listing 9 shows how to place orders into the ArrayList and then copy them into an array.

Listing 9: Copying order items to an array

Dim orders As ArrayList = New ArrayList

orders.Add(New Order("1/1/2006", "1234", 1200.54, "ALFKI"))

orders.Add(New Order("1/31/2006", "4567", 1895.54, "CAPI"))

Dim orderarray() = orders.ToArray(GetType(Order))

 

Dim OrderArray() = orders.ToArray(GetType(Order))

HashTable Class

The HashTable class provides a weakly typed collection of key-value pairs. The HashTable is designed to retrieve items key. Each HashTable object consists of buckets that contain the individual elements of the collection. A bucket is a virtual subgroup of elements within the collection that is used for searching and retrieving the data elements. Each bucket is associated with a hash code, generated using a hash function based on the key element.

 

When an object is added to a Hashtable it is stored in a bucket that is associated with the hash code that matches the object’s hash code. When a value is being searched for in the Hashtable the hash code is generated for that value and the bucket associated with that hash code is searched. Listing 10 shows an example of how to add orders to a Hashtable.

Listing 10: Adding orders to a HashTable

Dim orders As New Hashtable

orders.Add("AlFKI", New Order("1/1/2006", 1234, 1200.54, "ALFKI"))

orders.Add("CAPI", New Order("1/31/2006", 4567, 1954.12, "CAPI"))

 

As each item is added to the collection the customer name is used as the key. This value is used to calculate the hash. The hash function is an algorithm that returns a numeric hash code based on a key. By default the hash function always return the same code for the same key. The hash is a numeric value that is used to uniquely identify an item’s key. The actual key is not stored in the collection only it’s hash value. To set the value of an item within the collection a combination of the key and casting is used as shown below

 

CType(orders("ALFKI"), Order).CustomerName = "ALFKI"

 

The key can also be used to quickly locate items contained in the collection. Listing 11 shows an example of how this can be done.

Listing 11: Locating a key within the collection

If orders.ContainsKey("CAPI") Then

    txtbox.text = "Value found"

End If

Queue Class

The Queue class functions like a line of people of waiting to purchase concert tickets. When the ticket window opens the first person is sold their tickets and each person is served in the order they are in line. The Queue class creates a weakly typed collection that orders items as they are added. This type of service mechanism is called First in First Out (FIFO).

 

Internally, the queue class maintains an array of objects and two integers that mark the beginning and ending positions. When an item is added to the queue the internal capacity is checked to determine whether the array has enough room to store the new item. If it doesn’t the size of the array is automatically increased. New items are added at the position specified by the ending integer. As each item is added this integer is then incremented. The Queue class exposes an Enqueue method to add new items to the collection. For example, Listing 12 shows how to add two order items to a Queue class.

Listing 12: Adding order items to the Queue class

Dim orders As New Queue

orders.Enqueue(New Order("1/1/2006", 1234, 1200.54, "ALFKI"))

orders.Enqueue(New Order("1/31/2006", 4567, 1954.12, "CAPI"))

 

By default, the Queue class provides no index, items are accessed by the order they are added. The Dequeue method accesses and removes order items from the queue. The following code shows how to retrieve the first entered order item.

 

Dim firstOrder As Order = orders.Dequeue

 

***Insert Note***

The next call of the Dequeue method will retrieve the second item.

 

 

The Peek method provides a way to review items without removing them from the collection. For example, the following code will access the first item but not remove it from the collection.

Dim firstOrder As Order = orders.Peek

 

The use of the queue class is limited to specific business situations that require this type of behavior. For example, where you need to access messages and processes them in the order they arrive.

Stack Class

Opposite of the queue is the Stack class. This stack class creates a weakly typed collection where the last item added to the stack is returned first. Like a stack of papers on your desk, the top paper in the stack is the last one added. This type of service mechanism is called Last in First Out (LIFO). The stack class exposes the push method to add new items to the collection. Listing 13 shows an example of adding two order items to the Stack class.

Listing 13: Adding order items to the Stack class.

Dim orders As New Stack

orders.Push(New Order("1/1/2006", 1234, 1200.54, "ALFKI"))

orders.Push(New Order("1/31/2006", 4567, 1954.12, "CAPI"))

 

Like the Queue class items in the Stack can’t be accessed directly. The last added item is accessed in the stack class by using either the Push or the Pop method. The Pop method retrieves and then removes the item from the collection as shown below.

Dim FirstOrder As Order = orders.Pop

 

 

The Peek method is used to retrieve the item but doesn’t remove it from the stack as shown below.

Dim Secondorder As Order = orders.Peek

 

 

Like the queue, stack objects are only used in specific business situation that require their special behavior.

SortedList Class

The SortedList class combines the features of both the array and hashtable. By default, it exposes class items by index and unique key. The SortedList class maintains two arrays, one for keys and the other for values. The value array is used when a value is requested by index, like an array. When a value is requested by key, the index is obtained by searching the key array. Once the proper key is found then the matching value is obtained from the value array, which behaves like a HashTable with additional operations. Listing 14 creates a new SortedList collection and adds two order items to it.

Listing 14: Creating a sorted list with two order items

Dim orders As New SortedList

orders.Add("AlFKI", New Order("1/1/2006", 1234, 1200.54, "ALFKI"))

orders.Add("CAPI", New Order("1/31/2006", 4567, 1954.12, "CAPI"))

 

As a new item is added, the key array is re-sorted and the value array is adjusted to reflect the changes. In general requesting values by key is slower with a SortedList than a HashTable. However, the advantage of being able to request a value by index makes this valuable in certain business situations. Listing 15 shows an example of retrieving data using either the index or key.

Listing 15: Retrieving data from the SortedList collection

Dim orderALFKI As Order = orders("ALFKI")

Dim OrderSecond As Order = orders.GetByIndex(1)

 

 

When retrieving data the GetKey(index) method as shown below is used to retrieve an item specified by the key.

txtMessage.Text = "The key for this is " & orders.GetKey(0)

 

The other way around is the IndexOfkey(key) method. This method retrieves the index of the specified key as shown in the following.

txtMessage.Text = "The index for this is " & orders.IndexOfKey("CAPI")

 

This collection is useful for business situations where item access is based on either the key or the index. However, be aware that these additional features come with a performance penalty. If the business requirements specify a simple key-value pair and no need for an item index then a HashTable would make the better choice.

Implementing Custom Collections

Not all business data fits neatly into the set of built in system collections. Custom collection classes provide a strongly typed business object that defines the underlying data while abstracting out the ADO.NET and XML programming models. This is particularly effective in large systems when an architect designs a data access layer that contains custom business classes and then distributes the assemblies to other developers within the organization. Custom collections start with a business definition class that describes the entity. For example, listing 16 contains a class that provides an entity definition of a book.

Listing 16: The book collection

Public Class Book

    Private _Author As String

    Private _Title As String

    Private _ISBN As String

 

    Public Sub New(ByVal Author As String, ByVal Title As String, ByVal ISBN As String)

        _Author = Author

        _Title = Title

        _ISBN = ISBN

    End Sub

 

    Public Property ISBN() As String

        Get

            Return _ISBN

        End Get

        Set(ByVal value As String)

            _ISBN = value

        End Set

    End Property

    Public Property Title() As String

        Get

            Return _Title

        End Get

        Set(ByVal value As String)

            _Title = value

        End Set

    End Property

    Public Property Author() As String

        Get

            Return _Author

        End Get

        Set(ByVal value As String)

            _Author = value

        End Set

    End Property

End Class

 

***Insert Note***

Custom Collections are actually made up of two separate class files.

 

Custom collections are based on inheritance from the CollectionBase, ReadCollectionBase or DictionaryBase class. For example, the .NET framework uses the CollectionBase as the base class for a large portion of the built in strongly typed classes. Listing 17 contains the shell code for implementing a strongly typed books collection.

Listing 17: The shell of a strongly typed books collection

Public Class books

    Inherits CollectionBase

End Class

 

***Insert Note***

A common naming convention is to provide a plural name for the collection based on the name of the object that is being stored. In this example this means that the collection named books will contain an object of book.

 

The CollectionBase contains an InnerList and List property that represent the internally stored collection of data. This property is accessed by implementing a Default Property indexer that returns a strongly typed object. Listing 18 contains the updated Books class.

Listing 18: Adding a default indexed property to the strongly typed collection.

Public Class books

    Inherits CollectionBase

 

    Default Public Property Item(ByVal Index As Integer) As Book

        Get

            Return CType(List.Item(Index), Book)

        End Get

        Set(ByVal Value As Book)

            List.Item(Index) = Value

        End Set

    End Property

 

End Class

 

The CollectionBase provides the basic implementation of the IList, IListSource and IEnumerable. Both the IList and IEnumerable interface require consumers to implement methods and properties that support binding, enumerating and looping using the For/Each construct. IList declares methods for adding, inserting, removing and clearing elements from a list. The IListSource declares methods that return a Boolean indicating if there is a list in the object and a method that returns an object that implements the IList interface. The IEnumerable interface declares one method GetEnumerator. These enumerators are based on an interface that supports iterating elements in a collection. Custom collections provide the ability to create a variety of options including custom persistence and custom lookups based on business specifications. The full books custom collection is shown in Listing 19.

 

Listing 19: The books custom collection

Imports System.Data

Imports System.Xml

Imports System.Xml.Serialization

Public Class books

    Inherits CollectionBase

    Private dataFile As String = "books.xml"

 

    Default Public Property Item(ByVal Index As Integer) As Book

        Get

            Return CType(List.Item(Index), Book)

        End Get

        Set(ByVal Value As Book)

            List.Item(Index) = Value

        End Set

    End Property

 

    Public Function Add(ByVal Item As Book) As Boolean

        List.Add(Item)

        SaveData()

    End Function

    Public Function Contains(ByVal value As String) As Boolean

        Return List.Contains(value)

    End Function

    Public Sub Remove(ByVal value As Book)

        List.Remove(value)

        SaveData()

    End Sub

    Private Sub BulkAdd(ByVal Item As Book)

        List.Add(Item)

    End Sub

    Public Sub LoadData()

 

        If System.IO.File.Exists("books.xml") Then

 

            Dim xmlFileStream As New IO.FileStream(dataFile, IO.FileMode.Open)

            Dim xmlRead As New XmlTextReader(xmlFileStream)

 

            xmlRead.WhitespaceHandling = WhitespaceHandling.None

 

            While xmlRead.Read

                If xmlRead.IsStartElement Then

                    If xmlRead.Name = "ArrayOfBook" Then

                        xmlRead.ReadStartElement()

                        Do While xmlRead.Name = "Book"

                            Dim xmlAuth As String = ""

                            Dim XMLTitle As String = ""

                            Dim XMLISBN As String = ""

 

                            xmlRead.Read()

 

                            If xmlRead.Name = "Author" Then

                                xmlAuth = xmlRead.ReadString

                                xmlRead.Read()

                            End If

 

                            If xmlRead.Name = "Title" Then

                                XMLTitle = xmlRead.ReadString

                                xmlRead.Read()

                            End If

 

                            If xmlRead.Name = "ISBN" Then

                                XMLISBN = xmlRead.ReadString

                                xmlRead.Read()

                            End If

                            If xmlAuth <> "" And XMLTitle <> "" And XMLISBN <> "" Then

                                'add the item to the collection using the bulkadd

                                Call BulkAdd(New Book(xmlAuth, XMLTitle, XMLISBN))

                            End If

                            xmlRead.Read()

                        Loop ' while book

                    End If

                    xmlRead.Read()

                End If

            End While

            xmlRead.Close()

        End If

 

    End Sub

    Private Sub SaveData()

 

        Dim serializer As System.Xml.Serialization.XmlSerializer = New XmlSerializer(GetType(books))

        Dim stream As IO.MemoryStream = New IO.MemoryStream()

        serializer.Serialize(stream, List)

 

        Dim BookData As DataSet = New DataSet("Books")

        stream.Position = 0

        BookData.ReadXml(stream)

        stream.Close()

 

        BookData.WriteXml(dataFile)

    End Sub

 

End Class

 

Once implemented the books custom collection can be used to bind to a dropdown list as shown in Listing 20.

Listing 20: Binding the books collection to a dropdown list.

Dim colbooks As books = New books()

CmbBooks.ValueMember = "Title"

CmbBooks.DisplayMember = "Title"

CmbBooks.DataSource = colbooks

 

System.Collections.Specialized

The System.Collections.Specialized namespace contains a set of specialized and strongly-typed collections as shown in Table 5. Within the Compact Framework this namespace contains fewer collections than are available within the desktop framework.

 Table 5: Collections available in the CF System.Collections.Specialized namespace.

Collection Type

Description

HybridDictionary

Implements the IDictionary interface while the collection contains less than ten items and then switches to a HashTable.

ListDictionary

Implements the IDictionary interface using a single linked list. Recommended for collections that contain ten or less items.

NameValueCollection

Represents a collection of associated string keys and string values that can be accessed either with the key or with the index

BitVector32

Represents a collection that hold up to 32 boolean values, or a set of small integers that can take up to 32 consecutive bits

 

Dictionary Objects

By definition a dictionary object is a data structure that stores a set of key/value pairs. By default dictionaries expose add, find an item by key and remove methods. For example, when adding an element to a dictionary based HashTable, it maintains an array that stores the individual values. These values are added to the Hashtable by converting the key into an integer and storing it within the array bounds. This approach makes it very quick to find, insert, or retrieve any element from the HashTable. Dictionaries can also be implemented as a linked list. Linked lists are similar to an ArrayList. New items are added to the dictionary at the end of the list. However, finding an element by a key in the list, takes more work. With a HashTable the element is quickly located because there was a function to map the key to the array index. With the linked list the entire list is searched, one element at a time until the requested key is found.

 

Clearly there's a performance difference between a dictionary implemented as a Hashtable and a linked list. The Hashtable provides better performance in adding, finding, and removing elements. So it would seem to make sense to use a Hashtable for a dictionary in all circumstances, right? Well, no, actually. While the Hashtable's performance may beat the linked list, it only does so with larger collections. If you are only storing, five elements in your collection, the overhead that comes with the Hashtable will render it slower than the linked list implementation. For this reason the framework implements a dictionary based on a linked list. The ListDictionary is the optimal implementation to use for a dictionary when there are ten or less items. When there are more than ten items, the HashTable is the better option.

 

In most cases it is impossible to know ahead of time the total elements in a collection. For these situations the HybridDictionary is the appropriate implementation. While a collection has ten or fewer items, the HybridDictionary internally uses a ListDictionary to maintain the elements. Once over ten elements, it automatically switches over to a Hashtable. Listing 21 shows how to create a HybirdDictionary that contains basic catalog information.

Listing 21: Creating a HyrbidDictionary collection

Dim OfficeCatalog As New Specialized.HybridDictionary()

OfficeCatalog.Add("100 No 12 Pencils", "1.49")

OfficeCatalog.Add("100 No 5 Pencils", "1.29")

OfficeCatalog.Add("100 Red Pens", "1.49")

OfficeCatalog.Add("100 Blue Pens", "1.29")

OfficeCatalog.Add("100 Green Pens", "0.89")

 

The HybridDictionary class takes advantage of the improved performance of a ListDictionary with small collections, and offers the flexibility of transparently switching to a HashTable when the collection grows. If the initial size of the collection is greater than the optimal size for the ListDictionary the collection is stored in a HashTable right away to avoid the overhead of copying elements from the ListDictionary to a HashTable. Like any collection it implements the IEnumerable interface that allows the use of the For/Each construct as shown in Listing 22.

Listing 22: Iterating over a HybridDictionary collection

Dim de As DictionaryEntry

        For Each de In OfficeCatalog

            MsgBox("The Key is - " & de.Key & " and the value is -" & de.Value)

        Next de

 

The HybridDictionary also exposes a “contains” method that is used to locate a specific key. Listing 23 shows an example of how this is done.

Listing 23: Searching for an item in the HybridDictionary

If OfficeCatalog.Contains("100 Blue Pens") Then

            MsgBox("The collection contains the key - 100 Blue Pens")

        Else

            MsgBox("The collection does not contain the key - 100 Blue Pens")

End If

ListDictionary

The ListDictionary is the implementation of the IDictionary interface based on a single linked list. By default it is smaller and faster than a HashTable for collections that contain ten or less elements. Listing 24 shows an example of how to create a ListDictionary class that contains a set of office catalog items.

Listing 24: Creating a ListDictionary

Dim officecatalog As New Specialized.ListDictionary()

OfficeCatalog.Add("100 No 12 Pencils", "1.49")

OfficeCatalog.Add("100 No 5 Pencils", "1.29")

OfficeCatalog.Add("100 Red Pens", "1.49")

OfficeCatalog.Add("100 Blue Pens", "1.29")

OfficeCatalog.Add("100 Green Pens", "0.89")

 

Because this collection is designed for smaller lists, it is often used to copy items into a array for retrieval. Listing 25 shows an example of how this can be done.

Listing 25: Copying a ListDictionary to an array and then iterating the values

' Copies the ListDictionary to an array with DictionaryEntry elements.

        Dim CatArr(officecatalog.Count) As DictionaryEntry

        officecatalog.CopyTo(CatArr, 0)

 

        ' Displays the values in the array.

        Dim i As Integer

        For i = 0 To (CatArr.Length - 1 - 1)

            MsgBox("Item Key - " & CatArr(i).Key & " Value - " & CatArr(i).Value)

        Next i

 

NameValueCollection

The NameValueCollection is an association of string keys and values. Inherited from the NameObjectCollectionBase items are accessed by either key or index. As individual elements are added to the collection the capacity is automatically increased. Listing 26 shows an example of how to create a NameValueCollection class that contains a set of office catalog items.

Listing 26: Creating a NameValueCollection

Dim CatInfo As New NameValueCollection

CatInfo.Add("Red Pencils", "1.49")

CatInfo.Add("Green Pencils", "1.75")

CatInfo.Add("Yellow Pencils", "1.98")

CatInfo.Add("Blue Pencils", "1.17")

 

By default, the .NET Compact Framework doesn’t provide an AppSetting class similar to the full framework. Within the desktop environment a developer access stored application settings by creating a NameValue collection derived from the System.ConfigurationSettings.AppSetting class.


Figure The application settings file

 

Using a combination of the NameValueCollection and an XML file a similar solution can be created for mobile applications. Within the application first add an XML file that contains the application settings as shown in Figure 8. Listing 27 contains the custom class definition for use in a Compact Framework application.

 

Listing 27: Application setting class for the Compact Framework

Imports System

Imports System.IO

Imports System.xml

 

Public Class ClsSettings

    Private app_settings As Specialized.NameValueCollection

    Private Settings_path As String

 

    Public Function GetAllSettings() As Specialized.NameValueCollection

        Return app_settings

    End Function

    Public Function GetSetting(ByVal keyName As String) As String

        Return app_settings(keyName).ToString

    End Function

 

    Public Sub UpdateSetting(ByVal KeyName As String, ByVal SettingName As String)

        app_settings.Item(KeyName) = SettingName

        UpdateSettings()

    End Sub

    Private Sub UpdateSettings()

        Dim tw As XmlTextWriter = New XmlTextWriter(Settings_path, System.Text.UTF8Encoding.UTF8)

 

        tw.WriteStartDocument()

        tw.WriteStartElement("configuration")

        tw.WriteStartElement("appSettings")

 

        Dim i As Integer

 

        For i = 0 To (app_settings.Count - 1)

            tw.WriteStartElement("add")

            tw.WriteStartAttribute("key", String.Empty)

            tw.WriteRaw(app_settings.GetKey(i))

            tw.WriteEndAttribute()

 

            tw.WriteStartAttribute("value", String.Empty)

            tw.WriteRaw(app_settings.Get(i))

            tw.WriteEndAttribute()

            tw.WriteEndElement()

        Next

 

        tw.WriteEndElement()

        tw.WriteEndElement()

 

        tw.Close()

 

    End Sub

    Public Sub New()

        Settings_path = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetName.CodeBase) & "\appsettings.xml"

 

        If File.Exists(settings_path) Then

            Dim xdoc As XmlDocument = New XmlDocument

            xdoc.Load(settings_path)

            Dim root As XmlElement = xdoc.DocumentElement

            Dim nodelist As System.Xml.XmlNodeList = root.ChildNodes.Item(0).ChildNodes

 

            app_settings = New Specialized.NameValueCollection

            Dim i As Integer

 

            For i = 0 To (nodelist.Count - 1)

                app_settings.Add(nodelist.Item(i).Attributes("key").Value, nodelist.Item(i).Attributes("value").Value)

            Next

        End If

 

    End Sub

End Class

 

Additionally, Listing 28 shows how to retrieve and display the available application settings within a list box from the front end application.

Listing 28: Retrieving all the application settings

Dim lvarSettings As New ClsSettings

        Dim lvarItems As Specialized.NameValueCollection

 

        lvarItems = lvarSettings.GetAllSettings

 

        ' print out

        Dim myEnumerator As IEnumerator = lvarItems.GetEnumerator()

        Dim s As String

        For Each s In lvarItems.AllKeys

            txtSettings.Text = txtSettings.Text & vbCrLf & "Key: " & s & " value:" & lvarItems(s)

        Next s

 

Once loaded into the list box, the setting item can be selected. Listing 29 shows how the selected value is then used to retrieve an individual application setting.

Listing 29: Retrieving an individual application setting.

  Dim lvarSettings As New ClsSettings

        Dim lvarItems As Specialized.NameValueCollection

 

        lvarItems = lvarSettings.GetAllSettings

 

        ' load the items

        Dim myEnumerator As IEnumerator = lvarItems.GetEnumerator()

        Dim s As String

        For Each s In lvarItems.AllKeys

            CmbItems.Items.Add(s)

        Next s

BitVector32

TheBitVector32 collection implements a data structure that stores Boolean values and small integers in thirty two bits of memory. This collection is based on the BitArray class that stores one bit Boolean values. However, because the BitVector32 is implemented as a data structure instead of a class it is inherently more efficient. Listing 30 shows an example of defining a BitVector32 collection that holds a series of Booleans.

 

Listing 30: Creating a BitVector32 application

Dim bv As New BitVector32()
bv(1) = True

 

BitVector32 exposes a CreateSection method that is used to create a series of smaller more manageable integer sections. By definition a section is a series of the smallest number of consecutive bits that contain the maximum value defined in the CreateSection method. Creating more than one BitVector32.Section defines separate data structures that are longer than one bit. Listing 31 contains an example of how this can be done.

Listing 31: Creating three sections within a BitVector32 collection

Dim bv As New BitVector32()

 

' create three sections, of 4, 5, and 6 bits each

Dim se1 As BitVector32.Section = BitVector32.CreateSection(15)

Dim se2 As BitVector32.Section = BitVector32.CreateSection(31, se1)

Dim se3 As BitVector32.Section = BitVector32.CreateSection(63, se2)

 

' set each section at a given value

bv(se1) = 10

bv(se2) = 20

bv(se3) = 40

 

' read them back

msgbox(bv(se1))

msgbox(bv(se2))

msgbox(bv(se3))

 

By default a BitVector32.Section created with a maximum value of one acts as a Boolean. Passing a single 32-bit integer to the default constructor initializes all the elements into a single section using the following code.

bv = new BitVector32(-1)

 

 

The Data property is used to set or return the internal 32-bit value. Using this property enables the formatting of the Boolean as shown in the code below.

Textbox1.text = bv.Data.ToString("X")

 

System.Collections.Generic

The term generic is defined as an item that isn’t tied to a specific brand name. Generic items are available as close as the nearest grocery store. Stored next to the name brand items are usually the plainly packaged generic versions of these same items. These generic items expose a set of known properties and behaviors. For example, generic laundry soap guarantees that it will clean our clothes. Many times we may opt to purchase a name brand item because we know that it guarantees additional or enhanced properties over basic generic items.

 

The System.Collections.Generic namespace contains interfaces and classes that define generic collections. Fundamentally, generics are classes, structures, interfaces, and methods that have placeholders or type parameters for one or more storage types. For example, a generic collection class might use a type parameter as a placeholder for the type of objects it stores. These generic type parameters appear as the types of its fields, and the parameter types of its methods. A generic method might use its type parameter as the type of its return value, or as the type of one of its formal parameters. The keyword Of is used to create generics. Listing 32 illustrates a generic class definition.

Listing 32: A simple generic class definition

Public Class Generic(Of T)

    Public Field As T

End Class

 

Generic types are parameterized with one or more data types. This allows the application developer to tailor the data types to specific requirements. During development each generic type can declare several different elements. However, each declared elements all perform the identical logic, no matter what data types they are using. For example, Listing 33 shows an example of a generic class.

 

Listing 33: A generic class

Public Class Gen(Of T)

    Dim dataType As T

    Public Property Val() As T

        Get

            Return dataType

        End Get

        Set(ByVal value As T)

            dataType = value

        End Set

    End Property

End Class

 

The Gen class is defined as a generic class. As described above the Of keyword is used to declare it as generic. The T next to the Of represents a place holder for the data-type that will be passed when an instance of the class is created. The actual data types are defined as a substitute for the type parameters when the class is initialized. This establishes a new generic class with the chosen types substituted everywhere that the type parameters appear. For example, listing 34 shows an example of creating an instance of the Gen class using a string.

Listing 34: Initializing a string based generic class.

Dim mystring As New Gen(Of String)

mystring.Val = "hello world"

msgbox(mystring.Val)

                       

This same class can be initialized using an integer as shown in Listing 35.

Listing 35: Initializing an integer based generic class.

Dim myInt As New Gen(Of Integer)

myInt.Val = 5

msgbox(myInt.Val)

 

Figure 9 The terms used in a Generic Type

 

A generic type definition as shown in Figure 9 is a class structure or interface declaration that functions as a template, with placeholders for the types it can contain or use. Generic type parameters are the placeholders in a generic type or method definition. A generic method definition is a method with two parameter lists: a list of generic type parameters, and a list of formal parameters. Type parameters can appear as the return type or as the types of the formal parameters.

 

A constructed generic type is the result of specifying types for the generic type parameters with a generic type definition. The general term "generic type" includes both constructed types and generic type definitions. A generic type argument is any type that is substituted for a generic type parameter. For example, Listing 36 creates a generic method that returns the highest value in a series.

Listing 36: Generic method for returning largest number

Public Function Max(Of T As IComparable)(ByVal val1 As T, ByVal val2 As T) As T

        Dim retVal As T = val2

        If (val2.CompareTo(val1) < 0) Then

            retVal = val1

        End If

        Return retVal

    End Function

 

Listing 37 shows an example of calling this generic method with a double and integer data type.

Listing 37: Calling the generic method

Dim MaxInt As Int32 = Max(Of Double)(64, 3)

Dim MaxDouble As Double = Max(Of Double)(12.48, 99.12)

 

Although the code in a generic type definition should be as type independent as possible, in certain situation their may be a certain capability required for any data type that is supplied to the generic type. For example, if you want to compare two items for the purpose of sorting collating, their data type must implement the IComparable interface. This type of restriction is enforced by adding a constraint to the type parameter as shown in Listing 38.

Listing 38: Implement a generic constraint.

Public Class StudentInformation(Of t As {IComparable, IDisposable, Class, New})

    ' Insert code that defines class members.

End Class

Generic Collections

As we have seen earlier except for a few specialized collections the majority of collections provided by the .NET Framework are weakly typed and not type safe. Weakly typed collections can cause both performance and maintenance issues with a business object. Mainly because there are no inherent safeguards for limiting the types of objects stored in the collection. Essentially a weakly typed collection is only capable of handling the type it’s defined for. These types of collections aren’t generic – they have to declare their brand name up front. If you build and expose a collection of integers, then inadvertently pass that collection a date the running code fails.

 

Type safe means that whenever you add an object to the collection it is checked at compile time. This means that the generic type should be safe if you pass a wrong data type to the collection. It will throw an error during the compile time and not in the run time code. This simple change improves performance because no type casting is necessary at run time. However, performance and speed are not the main aspects to use generics, but the maintainability and cleaner code.

 

The Generic namespace class also provides some predefined generic classes as shown in Table 6. For example, the List generic class within that namespace is synonymous with the typical System.Collections.ArrayList class. Listing 39 shows an example of adding items to a string based instance of this class.

Listing 39: A string based instance of the List generic class

Dim CustList As New List(Of String)

CustList.Add("CEPF")

CustList.Add("JACK")

CustList.Add("MAYN")

CustList.Add("JACK")

 

Table 6: Built in generic namespaces

Generic Class

Description

Dictionary

The Dictionary generic class provides a mapping from a set of keys to a set of values.

KeyValuePair

The KeyValue generic class defines a key/value pair that can be set or retrieved.

LinkedList

LinkedList is a general-purpose linked list that supports enumerators and implements the ICollection interface.

LinkedListNode

Each element of the LinkedList collection is a LinkedListNode. The LinkedListNode contains a value, a reference to the LinkedList that it belongs to, a reference to the next node, and a reference to the previous node.

List

The List class is the generic equivalent of the ArrayList class. It implements the IList generic interface using an array whose size is dynamically increased as required.

Queue

The Queue generic class defines a first-in, first-out collection of objects.

SortedList

The SortedList generic class defines a a collection of key/value pairs that are sorted by key based on the associated IComparer implementation.

Stack

The Stack generic class defines a variable size last-in-first-out (LIFO) collection of objects. By default the default initial capacity for a Stack is ten.

 

This namespace also exposes the same types of collections we have seen before like the Queue class. For example, the following creates a queue class that operates on a string.

Public stringQ As New System.Collections.Generic.Queue(Of String)

In this Queue class the stringQ works exclusively with String values. Because stringQ is specific for String instead of being generalized for Object values, this removes the need to have late binding or type conversion. Ultimately this saves execution time and reduces run-time errors.

Summary

Business objects are an important aspect of application development. In this chapter we looked at how they are developed using the concepts of OO adapted for the SOA architecture. This combination helps solves the traditional problems that are associated with a strictly OO based architecture and creates a set of loosely coupled services for mobile applications. Collections and generics are used to help further create more scalable applications that more closely match the data structures they describe. Ultimately, the goal is to abstract out the underlying storage architecture for better code reuse. When building mobile applications these are the key ways to manipulate and store application data.