Moving the Test Stubs

[Previous] [Next]

The next step in implementing this function—fetching the country list—should be to have the private method call a data access object to get the countries from the database. But we don't want to do that just yet. Instead, we want to take one step at a time, making sure that we cover everything we must cover in every tier of the application before we dive into the next tier. So our next action will be to move the test stub code we created for the facade class into this main business class. Let's do it and see what happens.

As you might (or might not) remember from Chapter 6, the facade class test stub for fetching countries had the following code:

Public Function GetCountryList() As Recordset Dim rs As ADOR.Recordset Set rs = CreateObject("ADOR.Recordset") rs.Fields.Append "CountryCode", adVarChar, 3 rs.Fields.Append "Country", adVarChar, 20 rs.Open rs.AddNew rs!CountryCode = "USA" rs!Country = "USA" rs.AddNew rs!CountryCode = "GB" rs!Country = "Great Britain" rs.AddNew rs!CountryCode = "SWE" rs!Country = "Sweden" Set GetCountryList = rs End Function

All we have to do now is move that code to our main business entity management class. Then we'll adjust it slightly to fit its new environment:

'The GetAllAsRS method takes no arguments. It returns a recordset 'containing data about all the countries registered. 'Arguments: '========= 'None 'Returns: '======= 'An ADO Recordset that contains the following fields: '- CountryCode '- Country ' '##ModelId=3749207D033C Private Function GetAllAsRS() As Recordset Dim rs As ADOR.Recordset Set rs = CreateObject("ADOR.Recordset") rs.Fields.Append "CountryCode", adVarChar, 3 rs.Fields.Append "Country", adVarChar, 20 rs.Open rs.AddNew rs!CountryCode = "USA" rs!Country = "USA" rs.AddNew rs!CountryCode = "GB" rs!Country = "Great Britain" rs.AddNew rs!CountryCode = "SWE" rs!Country = "Sweden"  Set GetAllAsRS = rs End Function

The only line we had to change was the one printed in boldface type. It took us less than a minute to change this method into a test stub, allowing us to keep the same prototype functionality even though our code now goes deeper, and also allowing us to postpone creating the data access classes.

This code, however, is still present in the facade class as well. To be able to test what we've done so far in the entity class, we need to remove it and replace it with a real call to the main business tier.

Implementing the Facades

Implementing this call in the facade class is easy. All we have to do is delegate the work of the method to the CountryManager class, using the IViewer interface. Here's the code:

Public Function GetCountryList() As Recordset Dim objCountry As HorseMaintInterfaces.IViewer Dim vntConditions As Variant Set objCountry = _ CreateObject("HorseMaintEntities.CountryManager") Set GetCountryList = objCountry.GetList(vntConditions) 'NOTE: the vntConditions variable is empty! End Function

All we had to do was ensure that the facade project had a reference to the HorseMaintEntities and HorseMaintInterfaces projects. It must also have a reference to ADO, either to the full ADODB library or to the special ADOR recordset–only library.

If you wonder why we use the CreateObject function rather than the New keyword to create the CountryManager object, the answer is that New is a Visual Basic keyword for creating objects, whereas CreateObject is a COM function. Later, when we install our server classes in MTS, we'll need to use COM as much as we can. Using New may, as Ted Pattison explains, lead to erratic results.

Easy to call facade, less easy to call Business Entity object

One of the great advantages of using facade objects is that their methods can be made so easy to call, compared with the more generalized main business object interfaces. Here, for instance, the client can very easily call the method that supplies a list of countries. In our test form, we used the following one-liner:

Private Sub GetCountryList() Set adcCountries.Recordset = objFacade.GetCountryList End Sub

In contrast, the facade class had to declare a variable for the separate interface, declare a Variant variable for the filtering condition, create an object from the real CountryManager class, and then call the GetList method with the empty filtering Variant variable. Even though this is a very simple example, it's clearly more complicated than the code in the client for creating and calling the facade object.

Simplicity is also the purpose of facade objects; they should insulate client programs and client programmers from the complexities of server objects.

Testing the Result So Far

If you have done everything right so far, you have moved the test stub into the main business tier. The test form application should now behave exactly as before, even if the test stub processing has been moved to another class in another tier. You'll probably have to change a few things, such as setting up and correcting a few references, but then your test form should be able to do exactly the same job as before and also behave exactly the same as it did before.

Figure 10-4 is our proof. The form is still able to fetch all the countries from the new test stub, putting them in the correct combo box.

Figure 10-4. The test stub delivering countries now behaves well in its new place.

The real GUI prototype (displayed in Figure 10-5), the one based on dynamic HTML (DHTML), also behaves well after our enhancements. This, however, should go without saying. After all, we haven't changed anything that would affect the behavior of the GUI prototype more than it would our test form.

In fact, there's no point in releasing a new version of the server application until we've made significant changes, significant from the perspective of the GUI prototype. And we won't have done that until we have code that accesses the real database.

click to view at full size.

Figure 10-5. The dynamic HTML GUI prototype running against the new and enhanced server version. (The form part of this screen shot might seem a bit funny since it indicates USA as Sex and Sweden as Birthyear. The reason is that the Bred In combo box is open for selection at this point.)

The Remaining Methods

Now we've probably made our point. We've designed first-line support for the facade object's GetCountryList method by means of these innovations:

  • We now have a Visual Basic CountryManager class with an IViewer interface.
  • This class contains a GetList method, which through the IViewer interface serves the facade's GetCountryList method.
  • The GetList method has a test stub that simulates database action in this method. The test stub code in the facade is removed and replaced with real code that calls the main business object through a separate COM interface.

We've also designed an IMaint interface, but we haven't used it yet. There will be another use case for maintaining country information, and when we design support for that use case, we'll have to implement the methods of the IMaint interface as well. But that's a later issue, which, in the case of the CountryManager class, this book doesn't cover.

Instead of tiring you with more code examples from the CountryManager class right now, why don't we see what we need to do for the other facade class methods?



Designing for scalability with Microsoft Windows DNA
Designing for Scalability with Microsoft Windows DNA (DV-MPS Designing)
ISBN: 0735609683
EAN: 2147483647
Year: 2000
Pages: 133

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net