嗔秤戻幣�哉膵�云利匈嬉蝕湊蛸賜�塋床四衲���萩晦編報炎嘔囚^泡仟 ̄云利匈��
源平慎弌傍利 卦指云慕朕村 紗秘慕禰 厘議慕尺 厘議慕禰 TXT畠云和墮 〆辺茄欺厘議箝誓匂〇

VB2008貫秘壇欺娼宥(PDF鯉塀哂猟井)-及75何蛍

酔楯荷恬: 梓囚徒貧圭�鮗� ○ 賜 ★ 辛酔堀貧和鍬匈 梓囚徒貧議 Enter 囚辛指欺云慕朕村匈 梓囚徒貧圭�鮗� ● 辛指欺云匈競何! 泌惚云慕短嗤堋響頼���誅卒亮茂�俊彭堋響��辛聞喘貧圭 "辺茄欺厘議箝誓匂" 孔嬬 才 "紗秘慕禰" 孔嬬��



           a matter of experience!the only way to learn is to write code。 



           Extending the Lottery´Prediction System 



           In Chapter 10�察�the IProcessor interface was a good first step because it solved the problem at  

          hand。 The problem was to convert each line of text into another line of text。 However�察�in this  

           chapter¨s example�察�that interface is not enough。 We need to add two other methods�此�Initialize�┌�  

           and Destroy�┌�。 

                We want to find the frequencies of an individual number in the drawn lotteries。 The orig

          inal interface method IProcessor。Process�┌� is used to process an individual line of text�察�and  

          the frequencies can be calculated only after all of the draws have been processed。 Thus�察�we add  

           Destroy�┌��察�which is called after all of the lines of text have been read。 mon coding convention  


´´´´´´´´´´´´´´´´´´´´´´Page 419´´´´´´´´´´´´´´´´´´´´´´´

                                                                 CH AP T E R   1 5   *    L E A R N I N G   A B OU T   L I N Q 397 



says that if you have a Destroy�┌� method�察�you should have an  Initialize�┌� method that is  

called before the lines of text are processed。 

     Having extra requirements is not a problem and is fairly mon。 But you want to add the  

extra requirements without disrupting existing functionality。 After all�察�if some code works�察�you  

don¨t want to break it because of additional requirements。 Thus�察�you don¨t want to add the  

methods to the IProcessor interface like this�此�



Public Interface IProcessor  

    Function Initialize�┌� As String 

    Function Destroy�┌� As String 

    Function Process��ByVal input As String�� As String 

End Interface 



     This code is a no´no because you are breaking existing functionality。 Any class that imple

ments IProcessor must now implement the methods  Initialize�┌� and Destroy�┌��察�even though  

those classes don¨t need those methods。 

     Thus�察�when adding requirements�察�you should not change existing interfaces。 You create  

new interfaces and subclass the existing interfaces�察�like this�此�



Public Interface IExtendedProcessor 

    Inherits IProcessor 

    Function Destroy�┌� As String 

    Function Initialize�┌� As String 

End Interface  



     The new interface IExtendedProcessor has the new methods  Initialize�┌� and Destroy�┌��察 �

but inherits the method Process�┌�。 The old functionality still has only a single method�察�and the  

new functionality is free to implement either interface。 

     Adding new interfaces and new methods does not mean everything will work as is。 If you  

go back and look at the source code from Chapter 10�察�you¨ll see that the IProcessor interface  

was used by the Bootstrap class。 So�察�if you want the  IExtendedProcessor interface to be recog

nized�察�you must update Bootstrap。 Updating Bootstrap is fine�察�because it does not mean that  

IProcessor implementations must be updated ��or�察�at least�察�Bootstrap should not require  

that IProcessor implementations be updated��。 

     The original abbreviated implementation of  Bootstrap is as follows�此�



Imports System。IO 



Public Module Bootstrap 

    Public Sub DisplayHelp�┌� 

        Console。WriteLine�─�You need help�拭�Right now�拭┌� 

    End Sub 



    Public Sub Start��ByVal args As String�┌��察�_ 

        ByVal processor As IProcessor�� 

        Dim reader As TextReader = Nothing 

        Dim writer As TextWriter = Nothing 


´´´´´´´´´´´´´´´´´´´´´´Page 420´´´´´´´´´´´´´´´´´´´´´´´

398      CH AP T E R   1 5   *    L E A R N I N G   A B OU T   L I N Q 



                  If ��args。Length = 0�� Then 

                      reader = Console。In 

                      writer = Console。Out 

                  ElseIf ��args。Length = 1�� Then 

                      If ��args��0�� = ;´help;�� Then 

                          Bootstrap。DisplayHelp�┌� 

                          Return 

                      End If 

                      reader = File。OpenText��args��0���� 

                      writer = Console。Out 

                  End If 

                  ' Abbreviated 

                  writer。Write��processor。Process��reader。ReadToEnd�┌����� 

              End Sub 



          End Module  



               In the original implementation�察�the method Process�┌� is called to read an input and write  

          an output stream。 Since Initialize�┌� and  Destroy�┌�  should be called before and after the  

          string is processed�察�the most logical location of each method would be before and after the  

          processor。Process�┌� method�察�like this�此�



          Imports System。IO 



          Public Module Bootstrap 

              Public Sub DisplayHelp�┌� 

                  Console。WriteLine�─�You need help�拭�Right now�拭┌� 

              End Sub 



              Public Sub Start��ByVal args As String�┌��察�_ 

                  ByVal processor As IProcessor�� 

                  Dim reader As TextReader = Nothing 

                  Dim writer As TextWriter = Nothing 

                  If ��args。Length = 0�� Then 

                      reader = Console。In 

                      writer = Console。Out 

                  ElseIf ��args。Length = 1�� Then 

                      If ��args��0�� = ;´help;�� Then 

                          Bootstrap。DisplayHelp�┌� 

                          Return 

                      End If 

                      reader = File。OpenText��args��0���� 

                      writer = Console。Out 

                  End If 

                  ' Abbreviated 

                  If TypeOf processor Is IExtendedProcessor Then 

                      writer。Write�─�_ 

                      DirectCast��processor�察�IExtendedProcessor��。Initialize�┌��� 

                  End If 


´´´´´´´´´´´´´´´´´´´´´´Page 421´´´´´´´´´´´´´´´´´´´´´´´

                                                                  CH AP T E R   1 5   *    L E A R N I N G   A B OU T   L I N Q 399 



        writer。Write��processor。Process��reader。ReadToEnd�┌����� 

        If TypeOf processor Is IExtendedProcessor Then 

            writer。Write��DirectCast��processor�察�IExtendedProcessor��。Destroy�┌��� 

        End If 

    End Sub 



End Module  



     In the solution�察�the processor interface is tested to see if the interface is an instance of  

IExtendedProcessor。 If so�察�then the Initialize�┌� and Destroy�┌� methods can be called。 

     Extending interfaces and extending those classes that consume the old and new interfaces  

at the same time is keeping backward´patibility。 Backward´patibility is an important  

concept�察�because it implies you can gradually introduce new functionality into a working  

application without breaking old functionality。  

     Keeping backward´patibility without breaking working functionality is difficult�察�and  

there is a point where adding new functionality bees too plicated。 Once you reach this  

stage�察�you need to break backward´patibility by doing the following�此�



Public Interface IExtendedProcessor 

    Function Initialize�┌� As String 

    Function Destroy�┌� As String 

    Function Process��ByVal input As String�� As String 

End Interface 



 _ 

Public Interface IProcessor 

    Function Process��ByVal input As String�� As String 

End Interface 



     The example will break backward´patibility due to the Obsolete attribute being associated  

with the  IProcessor interface。 Thus�察�when any class or interface references the  IProcessor  

interface�察�a pile error results。 The second parameter of Obsolete is true�察�which forces the  

piler error。 If you left out that parameter�察�when the interface is referenced�察�a piler  

warning�察�rather than a warning�察�is generated。 

     The IExtendedProcessor interface does not subclass  IProcessor and includes the method  

Process�┌�。 Thus�察�there are no dependencies between IExtendedProcessor and IProcessor�察�and  

all functionality in the application must use IExtendedProcessor rather than IProcessor。 



*Note  Breaking backward´patibility is a major step�察�because your code cries that some code is broken  

and requires alteration。 However�察�sometimes you will need to break code�察�and when you do�察�make sure that  

the code cries ^broken� 院�very loud。 Otherwise�察�you might get unexpected errors。 



     Now that we¨ve updated the Bootstrap class and added the IExtendedProcessor interface�察 �

all of the samples in Chapter 10 will continue to function�察�and we can implement the frequency  

solution。 


´´´´´´´´´´´´´´´´´´´´´´Page 422´´´´´´´´´´´´´´´´´´´´´´´

400      CH AP T E R   1 5   *    L E A R N I N G   A B OU T   L I N Q 



          Implementing a Frequency Solution 



          The solution that we want to use is to read in the text�察�convert the text into binary objects�察 �

          calculate some statistics�察�and finally write out the text。 The interesting part of this solution is  

          that pieces of it have already been written。 If you remember in Chapter 10�察�there was a require

          ment to convert the lottery draws into binary form。 That code will be borrowed to implement  

          the statistics functionality。 

               The statistics console application �─�FrequencyProcessor�� requires an IExtendedProcessor  

          implementation。 The following is the plete implementation ��note the imports from  

          Chapter 10¨s example��。 



          Imports LottoLibrary 

          Imports ReaderWriter 

          Imports System 

          Imports System。Collections。Generic 

          Imports System。IO 

          Imports System。Linq 

          Imports System。Text 



          Friend Class LottoTicketProcessor 

              Implements IExtendedProcessor 



              Private _tickets As List��Of Ticket�� = New List��Of Ticket���┌� 



              Public Function Destroy�┌� As String Implements IExtendedProcessor。Destroy 

                  Dim builder As New StringBuilder�┌� 

                  Dim c1 As Integer 

                  For c1 = 1 To 46 1 

                      builder。Append�─�Number �──�& c1 & ;�� Found �─┌� 

                      Dim foundCount As Integer = 0 

                      builder。Append�┌┌�foundCount �� FrequencyOfANumber��c1���� & ;��; & ChrW��10������ 

                  Next c1 

                  Return builder。ToString�┌� 

              End Function 



              Private Function FrequencyOfANumber��ByVal numberToSearch As Integer�� As Integer 

                  Dim query = From ticket In _tickets _ 

                                  Where ticket。Numbers��0�� = numberToSearch _ 

                                  Or ticket。Numbers��1�� = numberToSearch _ 

                                  Or ticket。Numbers��2�� = numberToSearch _ 

                                  Or ticket。Numbers��3�� = numberToSearch _ 

                                  Or ticket。Numbers��4�� = numberToSearch _ 

                                  Or ticket。Numbers��5�� = numberToSearch _ 

                                  Select ticket。Numbers 

                  Return query。Count�┌� 

              End Function 


´´´´´´´´´´´´´´´´´´´´´´Page 423´´´´´´´´´´´´´´´´´´´´´´´

                                                              CH AP T E R   1 5   *    L E A R N I N G   A B OU T   L I N Q 401 



    Public Function Initialize�┌� As String Implements IExtendedProcessor。Initialize 

        Return ;; 

    End Function 



    Public Function Process��ByVal input As String�� As String _ 

      Implements IProcessor。Process 

        Dim reader As TextReader = New StringReader��input�� 

        Do While reader。Peek  ´1 

            Dim splitUpText As String�┌� = reader。ReadLine。Split��New Char�┌� ��; ;c���� 

            Dim dateSplit As String�┌� = splitUpText��0��。Split��New Char�┌� ��;。;c���� 

            Dim ticket As New Ticket�─�_ 

                                     New DateTime�─�_ 

                                       Integer。Parse��dateSplit��0�����察�_ 

                                       Integer。Parse��dateSplit��1�����察�_ 

                                       Integer。Parse��dateSplit��2�������察�_ 

                                       New Integer�┌� �� _ 

                                        Integer。Parse��splitUpText��1�����察�_ 

                                        Integer。Parse��splitUpText��2�����察�_ 

                                        Integer。Parse��splitUpText��3�����察�_ 

                                        Integer。Parse��splitUpText��4�����察�_ 

                                        Integer。Parse��splitUpText��5�����察�_ 

                                        Integer。Parse��splitUpText��6�������察�_ 

                                        Integer。Parse��splitUpText��7������ 

            _tickets。Add��ticket�� 

        Loop 

        Return ;; 

    End Function 

End Class 



     Let¨s examine how the implementation works。 



Borrowing Code to Solve Another Problem 



The borrowed code is the implementation of the  Process�┌� method�察�shown here in abbrevi

ated form�此�



    Public Function Process��ByVal input As String�� _ 

        As String Implements IProcessor。Process 

        Dim reader As TextReader = New StringReader��input�� 

        Do While reader。Peek  ´1 

            Dim splitUpText As String�┌� = reader。ReadLine。Split��New Char�┌� ��; ;c���� 

            Dim dateSplit As String�┌� = splitUpText��0��。Split��New Char�┌� ��;。;c���� 

            Dim ticket As New Ticket�─�_ 

          '。 。 。 

        Loop 

        Return ;; 

    End Function     


´´´´´´´´´´´´´´´´´´´´´´Page 424´´´´´´´´´´´´´´´´´´´´´´´

402        CH AP T E R   1 5   *    L E A R N I N G   A B OU T   L I N Q 



                  Other than the new _tickets。Add��ticket�� line�察�the code is identical to the Text2Binary。 

            Process�┌� implementation。 The bolded code adds the lottery draw to the list of drawn numbers。  

            Once the tickets have been instantiated�察�they can be added to the list of tickets that will be  

            queried and searched。 



                                                                 CODE REUSE 



               The borrowed code demonstrates code reuse through copy and paste。 Realize that code that was used to  

               process binary objects is now being used in a pletely new context。  

                     The copied and pasted code reuses classes and functionality from another problem context。 You copied  

               and pasted the functionality to parse and instantiate the Ticket type�察�but reused the Ticket type itself。  

                     When we worked on the code for the Ticket type�察�you probably had no idea that we would reuse the  

               same code。 In fact�察�even I had no idea that we would reuse the code。 I find this happens a lot in my projects。 

                     So how does this wor
卦指朕村 貧匯匈 和匯匈 指欺競何 壘��13�� 家��12��
酔楯荷恬: 梓囚徒貧圭�鮗� ○ 賜 ★ 辛酔堀貧和鍬匈 梓囚徒貧議 Enter 囚辛指欺云慕朕村匈 梓囚徒貧圭�鮗� ● 辛指欺云匈競何!
梁椣戻幣�� 梁心弌傍議揖扮窟燕得胎��傍竃徭失議心隈才凪万弌誌育断蛍�輌臆惨軼僑〃�燕慕得珊辛參資誼持蛍才将刮襲潜��範寔亟圻幹慕得 瓜寡追葎娼得辛參資誼寄楚署衛、持蛍才将刮襲潜填��