on because doing so would wreak havoc—all the code that uses the interface would need to be updated。 In general; if you feel the need to change an interface; create a new one。 With base functionality plete; we are ready to implement a tax system for a particular country。 Using the Base Functionality of the Tax Engine to Calculate Taxes We will use the base functionality of the tax engine to calculate Canadian taxes。 I chose the Canadian tax system because that is the system that I happen to know and understand; and there is plenty of online documentation on how to calculate the tax rate。 SOME BACKGROUND ON CANADIAN TAXES The first thing I would like to say about Canadian taxes is that Canadians pay too much—way too much。 The second ment is that Canadian taxes are simple; in that they don’t let you write off many deductions (for example; interest payments on your house); which brings us back to the first point that Canadians pay way too much。 Of course; people in other countries would probably say the exact same thing。 Canadian taxes are based on calculating the tax rate at the federal level and at the provincial level。 Thus; to calculate your taxes; you need to know in which province and in which year you are paying your taxes。 Canadian taxes change quite a bit depending on the year。 From an implementation perspective; it means the tax engine must know about provincial taxes; federal taxes; and which year。 Capital gains in Canada are calculated on a 50% basis。 This means if I made a capital gain of 200 Canadian dollars; then only 100 Canadian dollars are declared as taxable monies。 Implementing a Tax Engine and Tax Account Implementing a Canadian tax engine means deriving a class from BaseTaxEngine; and that means implementing the CreateTaxAccount() method。 The implementation of the Canadian tax engine will be in a new namespace; and a good name would be Canada (as this is in the LibTax project; it will have a root namespace of LibTax; so LibTax。Canada is the full namespace)。 The code will not show the namespace details; as they are implied。 The implementation is as follows: Friend Class TaxEngine Inherits BaseTaxEngine Public Overrides Function CreateTaxAccount() As ITaxAccount Return New TaxAccount() End Function …………………………………………………………Page 205…………………………………………………………… CH AP T E R 7 ■ L E AR N IN G AB O U T CO M P O N E N TS AN D C L AS S H I E R AR C HI E S 183 End Class In the implementation of the CreateTaxAccount() method; the TaxAccount class is instan tiated。 TaxAccount is a class that derives from BaseTaxAccount and thus implements the ITaxAccount interface。 The implementation of TaxAccount is as follows: Friend Class TaxAccount Inherits BaseTaxAccount Private _province As Province Private _year As Integer Public Overrides Function GetTaxRate(ByVal ine As Double) As Double If _year = 2008 Then If _province = Province。Ontario Then Return OntarioTax2008。TaxRate(ine) End If End If Throw New NotSupportedException(〃Year 〃 & _year & 〃 Province 〃 & _ _province & 〃 not supported〃) End Function End Class The purpose of the GetTaxRate() method is to return the applicable tax rate for the given amount。 In Canada; the tax rate is determined by which province you live in and the year。 The calculation in GetTaxRate() has the ability to calculate the taxes for the year 2008 in the Ontario province。 Here’s the skeleton of the OntarioTax2008 class: Public Class OntarioTax2008 Public Shared Function TaxRate(ByVal ine As Double) As Double " Return the appropriate rate End Function End Class Yet there is a problem; and it involves the data members _province and _year。 The data members are used in the calculation GetTaxRate(); but they are not assigned。 This is a problem。 Assigning State When the Interface Cannot The problem of the Canadian tax account is a mon one that you will encounter in many situations。 The essence of the problem is the need to assign state that is specific to an imple mentation without violating the intention of the general interface。 To illustrate the problem; let’s say that the method GetTaxRate() will include a reference to the province and year。 The rewritten ITaxAccount interface would be as follows: Public Interface ITaxAccount Sub AddDeduction(ByVal deduction As ITaxDeduction) Sub AddIne(ByVal ine As ITaxIne) Function GetTaxRate(ByVal ine As Double; ByVal province As Province; _ ByVal year As Integer) As Double …………………………………………………………Page 206…………………………………………………………… 184 CH AP T E R 7 ■ L E A R N IN G AB OU T CO M P O N E N TS AN D C L AS S H I E R AR C H IE S ReadOnly Property Deductions() As ITaxDeduction() ReadOnly Property Ine() As ITaxIne() End Interface The bolded code illustrates the added parameters that are used to calculate Canadian taxes。 But is this a good solution? No; it’s a particularly bad solution。 The parameters are specific to an implementation; and particularly to a Canadian implementation。 The parameter year could be justified because most countries do have specific tax rates and implementati