VB2008´ÓÈëÃŵ½¾«Í¨(PDF¸ñʽӢÎÄ°æ)-µÚ44²¿·Ö
°´¼üÅÌÉÏ·½Ïò¼ü ¡û »ò ¡ú ¿É¿ìËÙÉÏÏ·ҳ£¬°´¼üÅÌÉ쵀 Enter ¼ü¿É»Øµ½±¾ÊéĿ¼ҳ£¬°´¼üÅÌÉÏ·½Ïò¼ü ¡ü ¿É»Øµ½±¾Ò³¶¥²¿£¡
¡ª¡ª¡ª¡ªÎ´ÔĶÁÍꣿ¼ÓÈëÊéÇ©ÒѱãÏ´μÌÐøÔĶÁ£¡
The¡¡rewritten¡¡version¡¡of¡¡CurrencyTrader¡¡will¡¡cause¡¡the¡¡test¡¡code¡¡to¡¡break£»¡¡because¡¡it¡¡uses¡¡the¡¡¡¡
MustInherit¡¡keyword£»¡¡and¡¡thus¡¡cannot¡¡be¡¡instantiated¡¡directly¡£¡¡Here¡¡is¡¡the¡¡broken¡¡code£º¡¡
Dim¡¡cls¡¡As¡¡CurrencyTrader¡¡=¡¡New¡¡CurrencyTrader£¨£©¡¡
cls¡£ExchangeRate¡¡=¡¡123¡£44¡¡
¡¡¡¡¡¡¡¡¡¡The¡¡code¡¡will¡¡not¡¡work¡¡for¡¡two¡¡reasons£º¡¡
¡¡¡¡¡¡¡¡¡¡o¡¡¡¡CurrencyTrader¡¡uses¡¡the¡¡MustInherit¡¡keyword¡¡and¡¡thus¡¡cannot¡¡be¡¡instantiated¡£¡¡
¡¡¡¡¡¡¡¡¡¡o¡¡¡¡ExchangeRate¡¡is¡¡protected¡¡and¡¡cannot¡¡be¡¡referenced¡¡externally¡£¡¡
¡¡¡¡¡¡¡¡¡¡This¡¡broken¡¡code¡¡puts¡¡us¡¡in¡¡a¡¡bind¡£¡¡Up¡¡to¡¡this¡¡point£»¡¡whenever¡¡we¡¡tested¡¡code£»¡¡we¡¡assumed¡¡¡¡
all¡¡of¡¡the¡¡pieces¡¡that¡¡were¡¡to¡¡be¡¡tested¡¡could¡¡be¡¡referenced¡£¡¡One¡¡solution¡¡would¡¡be¡¡to¡¡change¡¡¡¡
the¡¡scope¡¡declarations¡¡and¡¡remove¡¡the¡¡MustInherit¡¡and¡¡¡¡Protected¡¡keywords¡£¡¡Yes£»¡¡that¡¡solves¡¡the¡¡¡¡
problem£»¡¡but¡¡it¡¡is¡¡a¡¡cop¡out¡£¡¡The¡¡better¡¡approach¡¡is¡¡to¡¡test¡¡CurrencyTrader¡¡as¡¡it¡¡was¡¡intended¡¡to¡¡be¡¡¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Page¡¡168¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡
146¡¡¡¡¡¡¡¡¡¡¡¡¡¡CH¡¡AP¡¡T¡¡E¡¡R¡¡¡¡¡¡6¡¡¡¡¡¡¡ö¡¡¡¡¡¡¡¡L¡¡E¡¡A¡¡R¡¡N¡¡IN¡¡G¡¡¡¡¡¡T¡¡HE¡¡¡¡¡¡B¡¡AS¡¡IC¡¡S¡¡¡¡O¡¡F¡¡¡¡¡¡OB¡¡J¡¡E¡¡CT¡¡OR¡¡I¡¡E¡¡N¡¡T¡¡E¡¡D¡¡¡¡¡¡P¡¡R¡¡O¡¡G¡¡R¡¡AM¡¡M¡¡IN¡¡G¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡used£º¡¡as¡¡a¡¡class¡¡that¡¡is¡¡derived¡¡from¡£¡¡So£»¡¡the¡¡solution¡¡is¡¡to¡¡use¡¡inheritance¡¡and¡¡create¡¡a¡¡test¡¡class¡¡¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡that¡¡derives¡¡from¡¡CurrencyTrader£»¡¡as¡¡follows£º¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Public¡¡Class¡¡TestCurrencyTrader¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Inherits¡¡CurrencyTrader¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Public¡¡Sub¡¡InitializeExchangeRate£¨£©¡¡¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡ExchangeRate¡¡=¡¡100¡£0¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡End¡¡Sub¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡End¡¡Class¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡TestCurrencyTrader¡¡is¡¡a¡¡test¡¡class¡¡that¡¡is¡¡added¡¡to¡¡the¡¡test¡¡source¡¡code¡£¡¡To¡¡inherit¡¡from¡¡a¡¡¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡class£»¡¡you¡¡define¡¡a¡¡class£»¡¡and¡¡in¡¡the¡¡following¡¡line£»¡¡use¡¡the¡¡keyword¡¡Inherits¡£¡¡This¡¡line¡¡says¡¡that¡¡¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡the¡¡class¡¡TestCurrencyTrader¡¡is¡¡subclassing¡¡CurrencyTrader¡£¡¡¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡To¡¡expose¡¡a¡¡method¡¡outside¡¡the¡¡class¡¡declaration£»¡¡you¡¡use¡¡the¡¡Public¡¡modifier¡£¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Inheritance¡¡means¡¡identifiers¡¡that¡¡are¡¡scoped¡¡¡¡Protected¡¡or¡¡¡¡Public¡¡can¡¡be¡¡referenced¡¡in¡¡¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡the¡¡subclassed¡¡type¡£¡¡For¡¡example£»¡¡notice¡¡how¡¡ExchangeRate¡¡seems¡¡to¡¡be¡¡all¡¡on¡¡its¡¡own£»¡¡without¡¡¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡any¡¡object¡¡reference¡£¡¡The¡¡lonely¡¡reference¡¡to¡¡ExchangeRate¡¡is¡¡fine£»¡¡because¡¡the¡¡base¡¡class¡¡¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡CurrencyTrader¡¡has¡¡an¡¡identifier¡¡with¡¡that¡¡name¡£¡¡The¡¡property¡¡ExchangeRate¡¡can¡¡be¡¡referenced¡¡¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡locally¡¡because¡¡of¡¡its¡¡protected¡¡scope¡¡The¡¡identifier¡¡¡¡ExchangeRate¡¡has¡¡an¡¡implied¡¡Me¡¡reference¡¡¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡£¨Me¡£ExchangeRate£©£»¡¡so¡¡it¡¡is¡¡not¡¡necessary¡¡to¡¡add¡¡that£»¡¡unless¡¡you¡¡have¡¡multiple¡¡identifiers¡¡with¡¡¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡the¡¡same¡¡name¡¡or¡¡you¡¡want¡¡to¡¡explicitly¡¡reference¡¡a¡¡certain¡¡identifier¡£¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡And¡¡now¡¡the¡¡tests¡¡will¡¡not¡¡test¡¡CurrencyTrader£»¡¡but¡¡will¡¡test¡¡TestCurrencyTrader£»¡¡which¡¡¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡should¡¡contain¡¡some¡¡verification¡¡code¡¡to¡¡make¡¡sure¡¡everything¡¡works¡¡correctly¡£¡¡¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Understanding¡¡Private£»¡¡Protected£»¡¡and¡¡Public¡¡Scope¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Let¡¯s¡¡dig¡¡a¡¡bit¡¡deeper¡¡into¡¡how¡¡the¡¡three¡¡types¡¡of¡¡scope¡¡work¡£¡¡To¡¡start£»¡¡consider¡¡the¡¡CurrencyTrader¡¡¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡implementation£º¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Public¡¡MustInherit¡¡Class¡¡CurrencyTrader¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Private¡¡_exchangeRate¡¡As¡¡Double¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Protected¡¡Property¡¡ExchangeRate£¨£©¡¡As¡¡Double¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Get¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Return¡¡_exchangeRate¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡End¡¡Get¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Set¡¡£¨ByVal¡¡Value¡¡As¡¡Double£©¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡_exchangeRate¡¡=¡¡value¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡End¡¡Set¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡End¡¡Property¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Protected¡¡Function¡¡ConvertValue£¨ByVal¡¡input¡¡As¡¡Double£©¡¡As¡¡Double¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Return¡¡_exchangeRate¡¡*¡¡input¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡End¡¡Function¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Protected¡¡Function¡¡ConvertValueInverse£¨ByVal¡¡input¡¡As¡¡Double£©¡¡As¡¡Double¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Return¡¡input¡¡/¡¡_exchangeRate¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡End¡¡Function¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡End¡¡Class¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Page¡¡169¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡CH¡¡A¡¡PT¡¡E¡¡R¡¡¡¡¡¡6¡¡¡¡¡¡¡ö¡¡¡¡¡¡¡¡L¡¡E¡¡A¡¡R¡¡N¡¡I¡¡N¡¡G¡¡¡¡¡¡T¡¡HE¡¡¡¡¡¡B¡¡AS¡¡IC¡¡S¡¡¡¡O¡¡F¡¡¡¡¡¡O¡¡B¡¡J¡¡E¡¡CT¡¡OR¡¡I¡¡E¡¡N¡¡TE¡¡D¡¡¡¡¡¡P¡¡R¡¡O¡¡G¡¡R¡¡AM¡¡M¡¡IN¡¡G¡¡147¡¡
¡¡¡¡¡¡¡¡¡¡The¡¡new¡¡class¡¡ActiveCurrencyTrader¡¡subclasses¡¡CurrencyTrader¡¡and¡¡is¡¡written¡¡as¡¡follows£º¡¡
Public¡¡Class¡¡ActiveCurrencyTrader¡¡¡¡
¡¡¡¡¡¡¡¡¡¡Inherits¡¡CurrencyTrader¡¡
End¡¡Class¡¡
¡¡¡¡¡¡¡¡¡¡The¡¡data¡¡member¡¡CurrencyTrader¡£_exchangeRate¡¡is¡¡declared¡¡as¡¡¡¡Private£»¡¡and¡¡thus¡¡can¡¡be¡¡¡¡
referenced¡¡only¡¡in¡¡CurrencyTrader¡£¡¡If¡¡_exchangeRate¡¡had¡¡no¡¡scope¡¡declaration£»¡¡private¡¡scope¡¡¡¡
would¡¡be¡¡implied¡£¡¡For¡¡example£»¡¡the¡¡following¡¡code¡¡would¡¡not¡¡pile¡£¡¡
Public¡¡Class¡¡ActiveCurrencyTrader¡¡¡¡
¡¡¡¡¡¡¡¡Inherits¡¡CurrencyTrader¡¡
¡¡¡¡¡¡¡¡Public¡¡Sub¡¡Method£¨£©¡¡¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡_exchangeRate¡¡=¡¡100¡£0¡¡
¡¡¡¡¡¡¡¡End¡¡Sub¡¡
End¡¡Class¡¡
¡¡¡¡¡¡¡¡¡¡The¡¡ActiveCurrencyTrader¡¡class¡¡is¡¡not¡¡part¡¡of¡¡CurrencyTrader£»¡¡and¡¡thus¡¡_exchangeRate¡¡¡¡
cannot¡¡be¡¡referenced¡£¡¡¡¡
¡¡¡¡¡¡¡¡¡¡Considering¡¡the¡¡ActiveCurrencyTrader¡¡class£»¡¡¡¡ExchangeRate£»¡¡which¡¡has¡¡been¡¡declared¡¡as¡¡¡¡
Protected£»¡¡could¡¡be¡¡referenced¡¡as¡¡follows£º¡¡
Public¡¡Class¡¡ActiveCurrencyTrader¡¡¡¡
¡¡¡¡¡¡¡¡Inherits¡¡CurrencyTrader¡¡
¡¡¡¡¡¡¡¡Public¡¡Sub¡¡Method£¨£©¡¡¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡ExchangeRate¡¡=¡¡100¡£0¡¡
¡¡¡¡¡¡¡¡End¡¡Sub¡¡
End¡¡Class¡¡
¡¡¡¡¡¡¡¡¡¡Protected¡¡scope¡¡means¡¡only¡¡those¡¡classes¡¡that¡¡derive¡¡from¡¡a¡¡class¡¡£¨and¡¡the¡¡class¡¡itself£©¡¡can¡¡¡¡
view¡¡the¡¡methods£»¡¡properties£»¡¡or¡¡data¡¡members¡£¡¡How¡¡many¡¡times¡¡and¡¡levels¡¡a¡¡class¡¡subclasses¡¡¡¡
another¡¡class¡¡is¡¡not¡¡important¡£¡¡¡¡
¡¡¡¡¡¡¡¡¡¡Public¡¡scope¡¡is¡¡the¡¡loosest¡¡and¡¡simplest¡¡of¡¡all¡¡scopes¡£¡¡You¡¡use¡¡Public¡¡whenever¡¡you¡¡want¡¡¡¡
to¡¡expose¡¡functionality¡¡that¡¡other¡¡classes¡¡or¡¡derived¡¡classes¡¡want¡¡to¡¡reference¡£¡¡¡¡
¡¡¡¡¡¡¡¡¡¡Here¡¡are¡¡some¡¡guidelines¡¡for¡¡using¡¡each¡¡scope£º¡¡
¡¡¡¡¡¡¡¡¡¡Private¡¡scope£º¡¡You¡¡will¡¡use¡¡Private¡¡for¡¡most¡¡data¡¡member¡¡declarations¡¡because¡¡data¡¡member¡¡¡¡
¡¡¡¡¡¡¡¡¡¡declarations¡¡imply¡¡the¡¡state¡¡of¡¡an¡¡object¡£¡¡Sometimes£»¡¡when¡¡developing¡¡algorithms£»¡¡you¡¡will¡¡¡¡
¡¡¡¡¡¡¡¡¡¡break¡¡apart¡¡the¡¡logic¡¡into¡¡several¡¡methods¡£¡¡The¡¡broken¡apart¡¡methods¡¡are¡¡used¡¡to¡¡solve¡¡a¡¡¡¡
¡¡¡¡¡¡¡¡¡¡problem£»¡¡and¡¡thus¡¡should¡¡be¡¡used¡¡only¡¡in¡¡the¡¡context¡¡of¡¡the¡¡class£»¡¡implying¡¡the¡¡methods¡¡¡¡
¡¡¡¡¡¡¡¡¡¡need¡¡to¡¡be¡¡declared¡¡using¡¡Private¡£¡¡¡¡
¡¡¡¡¡¡¡¡¡¡Protected¡¡scope£º¡¡You¡¡will¡¡use¡¡Protected¡¡whenever¡¡you¡¡want¡¡to¡¡enforce¡¡an¡¡inheritance¡¡¡¡
¡¡¡¡¡¡¡¡¡¡architecture¡£¡¡Very¡¡often£»¡¡Protected¡¡and¡¡MustInherit¡¡go¡¡hand¡¡in¡¡hand£»¡¡as¡¡both¡¡are¡¡intended¡¡¡¡
¡¡¡¡¡¡¡¡¡¡for¡¡inheritance¡£¡¡The¡¡main¡¡objective¡¡behind¡¡¡¡Protected¡¡is¡¡to¡¡offer¡¡a¡¡derived¡¡class¡¡access¡¡to¡¡¡¡
¡¡¡¡¡¡¡¡¡¡the¡¡private¡¡state¡¡of¡¡a¡¡parent¡¡class£»¡¡or¡¡to¡¡offer¡¡reusable¡¡functionality¡¡that¡¡should¡¡be¡¡used¡¡¡¡
¡¡¡¡¡¡¡¡¡¡only¡¡by¡¡knowledgeable¡¡developers¡¡who¡¡are¡¡creating¡¡the¡¡subclasses¡£¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Page¡¡170¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡
148¡¡¡¡¡¡¡¡¡¡¡¡¡¡CH¡¡AP¡¡T¡¡E¡¡R¡¡¡¡¡¡6¡¡¡¡¡¡¡ö¡¡¡¡¡¡¡¡L¡¡E¡¡A¡¡R¡¡N¡¡IN¡¡G¡¡¡¡¡¡T¡¡HE¡¡¡¡¡¡B¡¡AS¡¡IC¡¡S¡¡¡¡O¡¡F¡¡¡¡¡¡OB¡¡J¡¡E¡¡CT¡¡OR¡¡I¡¡E¡¡N¡¡T¡¡E¡¡D¡¡¡¡¡¡P¡¡R¡¡O¡¡G¡¡R¡¡AM¡¡M¡¡IN¡¡G¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Public¡¡scope£º¡¡As¡¡a¡¡rule£»¡¡think¡¡carefully¡¡before¡¡using¡¡Public¡£¡¡You¡¡will¡¡use¡¡public¡¡scope¡¡for¡¡the¡¡¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡most¡¡part£»¡¡but¡¡it¡¡is¡¡also¡¡the¡¡scope¡¡that¡¡can¡¡cause¡¡the¡¡most¡¡problems¡£¡¡For¡¡example£»¡¡once¡¡you¡¡¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡declare¡¡something¡¡as¡¡Public£»¡¡trying¡¡to¡¡later¡¡change¡¡the¡¡scope¡¡could¡¡wreak¡¡havoc¡¡in¡¡the¡¡¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡code¡¡that¡¡uses¡¡the¡¡class¡£¡¡It¡¡might¡¡be¡¡harder¡¡to¡¡develop¡¡using¡¡the¡¡other¡¡scopes£»¡¡but¡¡you¡¡will¡¡¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡have¡¡code¡¡that¡¡will¡¡have¡¡fewer¡¡maintenance¡¡issues¡£¡¡It¡¡all¡¡es¡¡down¡¡to¡¡which¡¡methods¡¡¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡and¡¡properties¡¡you¡¡want¡¡to¡¡expose¡¡to¡¡the¡¡outside¡¡world¡£¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Handling¡¡Verification¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡To¡¡run¡¡the¡¡test¡¡class¡¡TestCurrencyTrader£»¡¡the¡¡following¡¡code¡¡is¡¡used¡£¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Dim¡¡cls¡¡As¡¡TestCurrencyTrader¡¡=¡¡New¡¡TestCurrencyTrader£¨£©¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡cls¡£InitializeExchangeRate£¨£©¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡The¡¡modified¡¡test¡¡code¡¡entails¡¡instantiating¡¡TestCurrencyTrader¡¡and¡¡then¡¡calling¡¡the¡¡method¡¡¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡InitializeExchangeRate£¨£©¡£¡¡But¡¡is¡¡this¡¡a¡¡test£¿¡¡After¡¡all£»¡¡the¡¡InitializeExchangeRate£¨£©¡¡method¡¡¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡doesn¡¯t¡¡have¡¡a¡¡parameter¡¡or¡¡return¡¡value¡£¡¡Think¡¡of¡¡it¡¡as¡¡sending¡¡a¡¡letter¡¡via¡¡mail¡£¡¡You¡¡don¡¯t¡¡¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡know¡¡if¡¡the¡¡letter¡¡will¡¡arrive£»¡¡but¡¡it¡¡probably¡¡will¡£¡¡Tests¡¡that¡¡are¡¡probably¡¡passed¡¡are¡¡a¡¡really¡¡¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡bad¡¡idea¡£¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡We¡¡need¡¡to¡¡move¡¡the¡¡verification¡¡code¡¡from¡¡the¡¡test¡¡routine¡¡to¡¡the¡¡TestCurrencyTrader¡¡¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡class£»¡¡like¡¡this£º¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Class¡¡TestCurrencyTrader¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Inherits¡¡CurrencyTrader¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Public¡¡Sub¡¡InitializeExchangeRate£¨£©¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡ExchangeRate¡¡=¡¡100¡£0¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡If¡¡ExchangeRate¡¡¡¡100¡£0¡¡Then¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Throw¡¡New¡¡Exception£¨¡¨100¡£0¡¡verification¡¡failed¡¨£©¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡End¡¡If¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡End¡¡Sub¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡End¡¡Class¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡The¡¡bolded¡¡code¡¡illustrates¡¡the¡¡verification¡¡code¡¡used¡¡to¡¡ensure¡¡that¡¡the¡¡value¡¡assigned¡¡to¡¡¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡ExchangeRate¡¡is¡¡the¡¡same¡¡one¡¡that¡¡is¡¡retrieved¡£¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡öNote¡¡¡¡The¡¡tests¡¡we¡¯re¡¡using¡¡are¡¡being¡¡more¡¡plicated£»¡¡and¡¡you¡¡may¡¡wonder£»¡¡¡°Why¡¡do¡¡it¡¡that¡¡way£¿¡±¡¡¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡For¡¡this¡¡book£»¡¡we¡¡are¡¡writing¡¡tests¡¡and¡¡creating¡¡our¡¡own¡¡testing¡¡framework¡£¡¡Normally¡¡you¡¡would¡¡not¡¡do¡¡that¡£¡¡¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡You¡¡would¡¡use¡¡a¡¡testing¡¡framework¡¡such¡¡as¡¡NUnit¡¡£¨¡¡http£º//nunit¡£org£©¡¡or¡¡the¡¡Microsoft¡¡Visual¡¡Studio¡¡¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Professional¡¡tools¡¡to¡¡help¡¡create¡¡the¡¡tests¡£¡¡But¡¡here¡¡I¡¡want¡¡to¡¡demonstrate¡¡how¡¡to¡¡use¡¡Visual¡¡Basic£»¡¡not¡¡a¡¡¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡testing¡¡tool¡£¡¡By¡¡learning¡¡how¡¡to¡¡write¡¡the¡¡tests¡¡from¡¡the¡¡ground¡¡up£»¡¡you¡¡will¡¡understand¡¡what¡¡to¡¡expect¡¡from¡¡¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡testing¡¡frameworks¡£¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Using¡¡Conditional¡¡Statements¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Having¡¡verification¡¡code¡¡within¡¡a¡¡class¡¡is¡¡acceptable¡¡in¡¡the¡¡context¡¡of¡¡the¡¡test¡¡class¡¡¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡TestCurrencyTrader¡£¡¡However£»¡¡the¡¡problem¡¡of¡¡testability¡¡is¡¡still¡¡present¡¡in¡¡those¡¡classes¡¡that¡¡do¡¡¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡not¡¡expose¡¡their¡¡state¡£¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Page¡¡171¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡CH¡¡A¡¡PT¡¡E¡¡R¡¡¡¡¡¡6¡¡¡¡¡¡¡ö¡¡¡¡¡¡¡¡L¡¡E¡¡A¡¡R¡¡N¡¡I¡¡N¡¡G¡¡¡¡¡¡T¡¡HE¡¡¡¡¡¡B¡¡AS¡¡IC¡¡S¡¡¡¡O¡¡F¡¡¡¡¡¡O¡¡B¡¡J¡¡E¡¡CT¡¡OR¡¡I¡¡E¡¡N¡¡TE¡¡D¡¡¡¡¡¡P¡¡R¡¡O¡¡G¡¡R¡¡AM¡¡M¡¡IN¡¡G¡¡149¡¡
¡¡¡¡¡¡¡¡¡¡To¡¡understand¡¡the¡¡problem£»¡¡let¡¯s¡¡return¡¡to¡¡the¡¡code¡¡for¡¡preheating¡¡the¡¡oven¡¡that¡¡you¡¡saw¡¡¡¡
earlier¡¡in¡¡the¡¡section¡¡about¡¡the¡¡problems¡¡with¡¡properties¡£¡¡Imagine¡¡rewriting¡¡Oven¡¡to¡¡include¡¡a¡¡¡¡
verification¡¡test£»¡¡like¡¡this£º¡¡
Class¡¡Oven¡¡
¡¡¡¡¡¡¡¡Private¡¡_temperature¡¡As¡¡Integer¡¡
¡¡¡¡¡¡¡¡Public¡¡Sub¡¡SetTemperature£¨ByVal¡¡temperature¡¡As¡¡Integer