按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!
Console。WriteLine(toString)
toString = item3。ToString()
Console。WriteLine(toString)
Console。WriteLine(〃TestInsert: End〃)
End Sub
End Module
…………………………………………………………Page 233……………………………………………………………
C H AP TE R 8 ■ L E AR N IN G AB O U T CO M P O N E N T O R IE N TE D A R CH I TE C TU R E 211
This test generates pretty output like this:
**************
TestInsert: Start
Me (item1) next(Nothing) prev(Nothing)
Me (item1) next(item2) prev(Nothing)
Me (item2) next(Nothing) prev(item1)
Me (item2) next(item3) prev(item1)
Me (item3) next(Nothing) prev(item2)
Me (item1) next(item2) prev(Nothing)
Me (item2) next(item3) prev(item1)
Me (item3) next(Nothing) prev(item2)
TestInsert: End
The pretty output is not a verification of what went right。 Rather; the extensive output
makes it simpler to perform postmortem debugging to understand why something failed。
In the TestInsert() method; a situation is created where three LinkedItem instances are
instantiated: item1; item2; and item3。 Initially; the three items are not linked; but we use the
Insert() method to link them into a structure; as shown in Figure 8…4。
Figure 8…4。 Testable doubly linked list structure
But to get to the structure in Figure 8…4; some intermediate steps are required; and in the
implementation of the method TestInsert(); those intermediate steps are tested。 The NextItem
and PrevItem properties for each and every item are tested for the proper values at each step。 If
some of the values don’t match; an exception is thrown to indicate an improper structure。 If an
exception is thrown; the generation of the visual structure bees important。 As an aside;
while developing the Insert() and Remove() algorithms; the visual structures and test code
helped me figure out a bug。
The TestInsert() method is an example of an exhaustive test of a context。 The download
able source code contains several other examples of exhaustive tests。
…………………………………………………………Page 234……………………………………………………………
212 CH AP T E R 8 ■ L E A R N IN G AB OU T CO M P O N E N TO R IE N T E D AR C HI TE CT U R E
DEBUGGING AND TESTING TOOLS
Some of you might be thinking that to figure out why a test failed; you should use a debugger。 However; with
proper tests that are part of an extensive testing framework and that generate extensive output; the need for
a debugger is reduced。 Among the people who believe in a test…driven development (TDD) environment (including
me); there is a question on the merits of a debugger。 According to Wikipedia’s Test…Driven Development entry
(http://en。wikipedia。org/wiki/Test…driven_development); “Programmers using pure TDD on
new (‘greenfield’) projects report they only rarely feel the need to invoke a debugger。 Used in conjunction with
a Version control system; when tests fail unexpectedly; reverting the code to the last version that passed all
tests may often be more productive than debugging。”
A debugger is good for finding problems; but bad for understanding the nature of the problem。 Good tests
verify scenarios。 The more scenarios; the more tests; and the more tested your code is。 If a particular scenario
fails; you know that you have a problem。 And if everything was OK until you made a slight change that caused
the tests to fail; you know you have a problem。 Test scripts are signposts that tell you what is working and
what might not be working。 By using a debugger; you are often testing large chunks of code where you need
to labor to find the bug。 A debugger has its uses; but when writing good tests in many scenarios; you will rarely
need to use it。
And speaking of writing tests; as I noted in Chapter 6; in this book; I could introduce a testing framework
like NUnit (http://nunit。org) or Microsoft Visual Studio Team System (http://
msdn2。microsoft。/en…us/vstudio/default。aspx)。 When you are writing production code; you
will probably use such a testing framework。 Testing frameworks do not help you to write your tests; but rather
help you by providing support code to generate errors; log problems; and indicate progress of the tests。 Do
not get misled by tools that say they can write the tests for you。 No tool can write your tests; because that
would imply the tool understands the context of your code。 And since such a tool does not yet exist; you will
need to write your own tests。
Implementing Room Groupings
Room groupings are collections of rooms that fall into a specific organization。 The idea behind
a grouping is to perform group operations without having to explicitly examine a room before
performing an operation。 For example; in the case of the museum; we don’t need to figure out
whether a room is public or private each time a global operation is being performed。
The organization of the collection is that there can be multiple room groupings that are
linked together; and within a grouping; there are multiple rooms that can be grouped together。
The linked list structure has two levels and is coded as follows (in LibLightingSystem):
Class RoomGrouping
Inherits BaseLinkedListItem
Public Rooms As Room
Public Description As String
End Class
Class Room
Inherits BaseLinkedListItem
Public ObjRoom As IRoom
End Class
…………………………………………………………Page 235……………………………………………………………
C H AP TE R 8 ■ L E AR N IN G AB O U T CO M P O N E N T O R IE N TE D A R CH I TE C TU R E 213
The class declaration Room represents an individual room。 But notice how it derives from
BaseLinkedListItem; which seems to imply that Room is actually many rooms。 This is part of the
linked list implementation; it is like a chain; where the chain is created by individual links。
The RoomGrouping class has two data members: Rooms; which represents the list of rooms in
the grouping; and Description; which represents an easy…to…understand description of the
grouping。 The single data member for Room is a reference to an IRoom interface instance。
The room groupings are managed by the LightingController class。 An initial implemen
tation of LightingController is as follows:
Public Class LightingController
Private _roomGroupings As BaseLinkedListItem = New RoomGrouping()
End Class
When dealing with linked lists; you have a problem: which is the first element of a list? When
you use arrays; an empty list of arrays is an array with no references。 But there is an explicit
array object。 Using the linked list; an empty linked list is a list that does not exist。 Thus; when
you want to create a list; you need a room。 In LightingController; the first element is an instance
of RoomGrouping; which is not a room grouping; but serves as a placeholder。 To insert a room
grouping; you could simply use this code:
_roomGroupings。Insert(NewRoomGroup())
Without the placeholder; you would need to write the following code whenever you
wanted to add an element into the list。
If _roomGroupings Is Nothing Then