Info

12 Return CType(list.Item(index), Thread)

End Function

The Item property is a little more complex than the average property. Let's review it, line by line. Line 1 creates a variable called myObject of type Object and sets it equal to the object that is at the specified index of the ArrayList. Line 2 compares the type of the object to the type of the Thread class. If they are the same, it does nothing; if not, it enters the Else part of the If statement (lines 5 -9). Next, a Thread variable called myThread is declared and set to a new Thread on line 6, passing in the object that is in the specified index in the ArrayList.That object is cast to a DataRow using CType. Line 9 sets the object at the specified index in the ArrayList to the myThread variable. Finally, on line 12 it returns the Thread that is in the specified index of the ArrayList (and again, is cast to be a Thread object).

You may be wondering to yourself exactly what all of this accomplishes.Well, if you remember from the InitializeThreads method, the ArrayList is filled with DataRow objects.We do not want to directly expose anyone using our objects to DataRow objects, so we need to instead give them Thread objects. So, behind the scenes, every time a new index is requested from the ArrayList, we quietly "switch" the variable in that index from a DataRow to the appropriate Thread object.You may also ask why this class doesn't just put the Threads into the ArrayList from the start instead of doing it this way.The answer is simple: there is no need for the overhead of having multiple Thread objects (each with other objects inside them) in the list when you can save memory and time instantiating objects by just keeping the data for each Thread object until it is actually requested. When developing large-scale applications with many parent-child hierarchical relationships, a technique like this will save you and your application a lot of time.

Designing the Thread class

The Thread class is the "middle child" in our hierarchy of objects. Luckily for us, a lot of its functionality and concepts are borrowed directly from the Board class, so this should be pretty quick. Let's take a look at another UML diagram in Figure 13.30.

Figure 13.30 The Thread Class

Thread

+ID : Long +Subject : String +Creator : User +ChildPost +ChildPosts

+CreatePost()

Private mThreadID As Long Private mSubject As String Private mCreator As User Private myPosts As PostList

Public Sub New(ByVal myRow As DataRow)

inflate(myRow) End Sub

Continued

Like every class we've examined so far, the Thread class shares the same private fields as the Thread table in the database. Like the Board class, the Thread class contains two properties to access its children: ChildPost and ChildPosts. ChildPost retrieves an individual Post object from its list, and ChildPosts returns the entire PostList. PostList will be discussed a bit later.Thread also contains the method to create child Posts. Let's start with the basics in Figure 13.31.

Figure 13.31 The Basics (Thread.vb)

Public Class Thread

Figure 13.31 Continued

Private Sub inflate(ByVal myRow As DataRow) mSubject = CStr(myRow("ThreadSubject")) mThreadID = CLng(myRow("ThreadID")) mCreator = New User(myRow) myPosts = New PostList(mThreadID) End Sub

Public Readonly Property ChildPost(ByVal postId As Long) _ As Post Get

'lookup the correct Post Dim i As Integer

Dim myPost As Post = Me.ChildPosts.Item(i) If myPost.ID = postId Then

Return myPost End If Next i

'if we've gotten to this point, there is no Post 'with that ID in this board, throw an exception Throw New ArgumentException("Post does not exist") End Get End Property

Public Readonly Property ChildPosts() As PostList Get

Return myPosts End Get End Property

Public Readonly Property ID() As Long Get

Figure 13.31 Continued

Return mThreadID End Get End Property

Public Property Subject() As String Get

Return mSubject End Get

Set(ByVal Value As String)

mSubject = Value End Set End Property

Public Readonly Property Creator() As User Get

Return mCreator End Get End Property End Class

First, you'll notice the private fields that are the same as the fields in the database.You'll also notice that a Thread has a Creator field and property that are User objects representing the user that created this Thread. Like the Board class, this class has a constructor that accepts a DataRow as a parameter and then calls inflate to fill up the private fields using that DataRow. Also like Board, you have two child object properties, ChildPost and ChildPosts. ChildPost is used to return a single Post, and ChildPosts is used to return the entire PostList. Let's take a look at the next method in the Thread class, CreatePost, in Figure 13.32.

Figure 13.32 The CreatePost Method (Thread.vb)

Public Sub CreatePost(ByVal subject As String, _ ByVal body As String, _ ByVal creator As User)

Continued

Figure 13.32 Continued

Dim sql As String sql = "INSERT INTO [Posts] ([PostSubject], " & _ "[PostBody], " & _

"[CreatorID], [ThreadID]) VALUES ('" & subject & _ "','" & body & "'," & creator.ID.ToString() & "," & mThreadID.ToString() & ")" DataControl.ExecuteNonQuery(sql)

'reinitialize the thread list myPosts.InitializePosts() End Sub

Taking a look at the CreatePost method, you'll notice that it does almost exactly what CreateThread did in the Board class. It builds a SQL statement to create a new Post, then executes that statement and reinitializes the private PostList object.

Designing the PostList Class

Being that we're almost finished creating our classes, it's time to look at the PostList class.You may be thinking to yourself "I wonder if the PostList class is similar to the ThreadList class". Such thinking should be rewarded. PostList and ThreadList are nearly identical, except for in regards to what type of object they collect. Again, let's take a look at the UML diagram for the class first in Figure 13.33, then in Figure 13.34 we'll review the basics of this class (something which can also be found on your CD as PostList.vb).

Figure 13.33 The PostList Class

PostList

+Count: Integer +Item

+InitializePosts()

Figure 13.34 The Basics (PostList.vb)

Public Class PostList

Private list As ArrayList Private mThreadID As Long

Figure 13.34 Continued

Public Sub New(ByVal ThreadID As Long) mThreadID = ThreadID Me.InitializePosts() End Sub

Public Sub InitializePosts() Dim myData As DataSet Dim sql As String sql = "SELECT [Users].*, [Posts].* FROM " & _ "[Posts] INNER JOIN [Users] " & _ "ON [Users].[UserID] = [Posts].[CreatorID] " & "WHERE " & _

"[ThreadID] = " & mThreadID.ToString() & _ " ORDER BY PostDate DESC" myData = DataControl.GetDataSet(sql)

list = New ArrayList()

Dim myRow As DataRow

For Each myRow In myData.Tables(0).Rows list.Add(myRow)

Next End Sub

Public Readonly Property Count() As Integer Get

Return list.Count End Get End Property End Class

Just like ThreadList, PostList contains a Count property, a method to initialize posts in a thread, and a constructor that accepts the ID of the parent object.The only real difference here is that this class gets values from the User table instead of the Thread table. Next, let's examine the Item function in Figure 13.35.

Figure 13.35 The Item Function (PostList.vb)

Public Function Item(ByVal index As Integer) As Post Dim myObject As Object = list.Item(index) If myObject.GetType() Is GetType(Post) Then

'it is already a post, so nothing further is needed

Else

Dim myPost As Post myPost = New Post(CType(list.Item(index), DataRow)) 'replace the item in the list with 'an actual post object list.Item(index) = myPost End If

Return CType(list.Item(index), Post) End Function

In reviewing this Item function, note that it looks remarkably similar to the Item function in the ThreadList class. In fact, it is exactly the same except that it uses Post instead of Thread. Other than that difference, PostList is exactly the same as ThreadList.

Designing the Post Class

So far, you should have noticed most of the classes in our code share a lot of the same ideas: add, update, lists, mimicking the database tables. Well, the Post class is no different. In fact, it is rather similar to both the Board and Thread classes. Let's take a look at the UML diagram for this class in Figure 13.36.

Just like the other classes, this one is remarkably similar to its brothers—especially the Thread class. The only real difference between this class and the Thread class is that Post has a Body field, pulls its values from the Post table, and doesn't have any child objects. Let's take a look at the whole class in Figure 13.37 (which can be found on your CD as Post.vb), as there really isn't much to it.

Figure 13.36 The Post Class

Post

+ID : Long +Subject : String +Body : String +Creator : User +PostDate : Date +Update()_

Figure 13.37 Post.vb

Public Class Post

Private mPostID As Long Private mPostSubject As String Private mPostBody As String Private mCreator As User Private mPostDate As Date

Public Sub New(ByVal myRow As DataRow)

inflate(myRow) End Sub

Public Sub Update(ByVal requestor As User) If requestor.ID = mCreator.ID Then Dim sql As String sql = "UPDATE [Posts] SET [PostSubject] = '" & _

mPostSubject & "', [PostBody] = '" & mPostBody & _ "' WHERE [PostID] = " & mPostID.ToString() DataControl.ExecuteNonQuery(sql)

Else

Throw New ArgumentException _

("Only the creator of a post can update it")

End If End Sub

Private Sub inflate(ByVal myRow As DataRow) mPostID = CLng(myRow("PostID"))

Continued

Figure 13.37 Continued mPostSubject = CStr(myRow("PostSubject") mPostBody = CStr(myRow("PostBody")) mCreator = New User(myRow) mPostDate = CDate(myRow("PostDate")) End Sub

Public Readonly Property ID() As Long Get

Return mPostID End Get End Property

Public Property Subject() As String Get

Return mPostSubject End Get

Set(ByVal Value As String)

mPostSubject = Value End Set End Property

Public Property Body() As String Get

Return mPostBody End Get

Set(ByVal Value As String)

mPostBody = Value End Set End Property

Public Readonly Property Creator() As User Get

Return mCreator

Figure 13.37 Continued

End Get End Property

Public Readonly Property PostDate() As Date Get

Return mPostDate End Get End Property End Class

As you can see, this class has five private fields with the corresponding five public properties. In addition, it has a constructor that accepts a DataRow parameter which passes the DataRow to the inflate method. Finally, it has an update method, with the rule that only the creator of the Post can actually edit the Post. Doesn't seem too hard, does it?, Especially after all the other classes we've dealt with. It almost seems passé.

Designing the MessageBoard Class

We've finally gotten every class in our message board object library finished; now all we need is a way to get a list of every Board object from our database.This is accomplished using the MessageBoard class.We won't bother to show you a UML diagram of the MessageBoard class, as there is only one method in it: GetBoards. Let's take a look at the code in Figure 13.38 (which can be found on your CD under the name MessageBoard.vb).

sql = "SELECT [BoardName] FROM [Board] ORDER BY [BoardName] Asc"

Continued

Figure 13.38 MessageBoard.vb

Public Class MessageBoard

Public Shared Function GetBoards() As ArrayList Dim list As New ArrayList() Dim sql As String Dim myData As DataSet Dim myRow As DataRow

Figure 13.38 Continued myData = DataControl.GetDataSet(sql)

For Each myRow In myData.Tables(0).Rows Dim myBoard As Board myBoard = New Board(CStr(myRow("BoardName"))) list.Add(myBoard) Next myRow

Return list End Function End Class

This class is fairly easy to understand.What it does is look up each BoardName from the database, and create a new Board object based on that name. It then adds each Board to its list, and finally returns the list.

That's it. Every single one of our objects to be used in dotBoard is completely finished.You may wonder why we did all this work ahead of time instead ofjust jumping into the application itself.That is a very good question, and as such, has a very good answer.We did all this work designing and setting things up so that when we actually build our application, it will go smoothly, quickly, and won't require a lot of coding in the User Interface. Any good application splits the User Interface from the actual implementation of the application, which is exactly what we did.We are about to move on to the user interface of our message board application.You will see that using the work we've already done, the rest of this application is going to be very straightforward and easy.

0 0

Post a comment