Building Components

Since COM components can be created in a number of high-level programming languages, such as Visual C++, Java, and Visual Basic, if you are proficient in any of these languages, you can create your own custom COM components (or COM objects, as they are sometimes called). For an object to be considered a COM object (and therefore to be able to be instantiated from the wide range of development tools and programming languages), it must follow certain guidelines. These low-level guidelines are far past the scope of this book, and will not be discussed in detail.

Thankfully, high-level programming languages ensure that most of these low-level implementation details are taken care of for you. For example, when creating a COM component in Visual Basic, these low-level details can be completely ignored, and the developer can focus on creating classes that will be translated into full-fledged COM components by Visual Basic.

This book also refrains from stepping through the process of creating a COM object with any programming language. There are already several great books on the topic. If you are looking for an entire book dedicated to building COM objects in various languages, let me recommend Shelly Powers’s Developing ASP Components (O’Reilly), which shows how to create components in Java, Visual C++, and Visual Basic in great detail.

What this book does focus on is a particular type of custom COM component, one used to ensure business logic integrity.

Wrapping Business Logic Within a COM Object

Custom COM components usually fall into one of two categories:

  • Components that provide some type of added functionality to the web site

  • Components that define the business logic a site must abide by

The two Microsoft COM components we examined earlier in this chapter were both examples of COM components that provided added functionality. The Ad Rotator component provided a generic advertising banner rotation system, while the Content Linker provided a simpler means for adding and updating content to a large web site. In Chapter 8, we’ll look at a number of commercially available COM components that also fall within this category.

The second category of custom COM components is not nearly as glamorous as the first, but in large web sites, is incredibly important. Pause for a moment and think of any large e-commerce web site. When purchasing an item from that site, a number of complicated transactions must occur: taxes must be computed; credit card balances must be checked; orders must be sent to the warehouse via some mechanism. Now, imagine that all of these complicated transactions were handled by logic in each ASP page from which a user could purchase an item.

While ASP may be able to handle such complex business rules, it would not be wise to place complicated business rules within an ASP page, for a number of reasons. Imagine, for a moment, that all the business rules were hardcoded into the applicable ASP pages. What would happen if a tax law changed, requiring the taxes to be calculated differently? Since the tax calculations were hardcoded into a number of ASP pages, a developer must hunt through the site, making the needed changes. The more changes the developer is required to make, the more likely he is to miss a needed change or commit a typo, resulting in a tax-calculation error.

As we’ve seen throughout this book, complex tasks become incredibly simpler when the task is wrapped inside of a class. With a class, the end developer can treat the class like a black box and not worry about how the black box performs its tasks. With classes, the responsibility for a particular task is removed from the developer and placed squarely on the shoulders of the class. Custom COM components that handle business logic provide a similar black box interface.

In an e-commerce web site, business logic might include tax information, credit card handling, shipping procedures, and mechanisms to notify complementary computer systems (such as sending an order to the warehouse, which might use a different computer system). If changes occur in the business logic, only the custom COM component’s code needs to be modified. All the ASP pages using the COM component are unaware of the business logic changes that occurred.

Custom COM components responsible for business logic also provide a level of abstraction between an ASP page and the database. In a large, data-driven web site that does not use COM objects for business logic, when some piece of information needs to be committed or retrieved from the database, the ASP page is responsible for executing the SQL statement. In this book, we’ve looked at several examples of using the ADO objects to insert, update, and delete database records.

However, in a large site with several developers and a complex data model, having the ASP pages handle database transactions is asking for trouble. Since similar database actions are taken on various ASP pages, there are bound to be typos or mistakes, resulting in database or ASP errors. Granted, stored procedures could be used to help alleviate this problem, but what happens if the data model is changed? Those ASP pages that reference tables that no longer exist or have been altered need to be fixed to reflect the changes in the data model.

On a large web site, where there may be hundreds of ASP pages, such a data model change can be a logistical nightmare. When custom COM components are involved, the ASP pages make calls to the COM component; it is then the responsibility of the component to make the appropriate database access calls. That way, if there is a data model change, only the custom COM object needs to be modified; the ASP pages that reference the COM component can go unchanged!

Custom COM components can therefore encapsulate the database and business logic, providing a black box for ASP pages to use. Custom COM components make up the middle layer of a three-tiered web site . A three-tiered web site is one that consists of three parts, each distinct from one another and responsible for a unique set of tasks. The three tiers, which are illustrated in Figure 7.6, include:

  • A Data Services tier, which includes data storage tools, such as databases.

  • A Business Services tier, which includes components that contain business logic information.

  • A User Services tier, which contains the front end of the application that is presented to the user.

Large, robust web sites should consist of three distinct tiers

Figure 7-6. Large, robust web sites should consist of three distinct tiers

Tip

For a more detailed explanation of the motivation behind and the advantages of a three-tiered client-server application, be sure to read “Building Three-Tiered Client-Server Business Solutions,” a Microsoft white paper available at http://www.microsoft.com/TechNet/Analpln/3tierwp.asp.

Imagine the steps that occur when a user visits an order-tracking page in a three-tiered e-commerce web site. When a user enters his or her ordering specifics, the ASP page creates an instance of the OrderTracking component (see Figure 7.6). This component may interact with other custom COM components (such as the InventoryInfo component). The order-tracking ASP page, though, is not concerned with how the OrderTracking component provides the order information details.

As illustrated in Figure 7.6, the OrderTracking component performs some calculations and then requests information from the InventoryInfo component. This component grabs the requested information from the Inventory database, which is in the Data Services tier.

Using custom COM components also makes for easier-to-read, simplified ASP code. Imagine the several lines of cryptic ASP code that would be needed to handle a sale from an e-commerce web site. Using custom COM components that assume responsibility for the business logic, the ASP code would be greatly simplified to something like:

'Instantiate the object
Dim objBuySomething
Set objBuySomething = Server.CreateObject("Product.Purchase")

'Set the properties
objBuySomething.ProductID = 458734582
objBuySomething.Quantity = 1
objBuySomething.CreditCardNumber = 1234432112344321
objBuySomething.AddressLine1 = ...
'...

'Now that all the properties have been set, make the purchase
objBuySomething.Purchase

Using COM Objects in a Multienvironment Scenario

One of the major advantages of COM components is they can be used by a vast array of high-level languages and programming tools. This enables developers to create a single COM component that can be used in a wide array of situations. This fact is especially useful when creating custom COM objects to encapsulate business logic.

In Section 7.4.1, we looked at how to wrap the business logic involved in an e-commerce web site into a set of COM objects. These COM objects housed business logic like sales tax information, and were used as a layer of abstraction between the ASP pages and the data store.

Might there be other applications besides an ASP web site that need access to these business rules? For example, imagine that besides having an e-commerce site, the company also takes orders over the phone. Employees using a simple Visual Basic program would likely fill these phone orders. This Visual Basic program would need to adhere to the same business logic rules that customers shopping on the web site follow. Therefore, the custom COM components developed for the e-commerce site could also be used in the phone-ordering program.

Building COM Components with Script

Despite the performance and reusability advantages of custom COM components written in a high-level programming language in your ASP pages, such COM components suffer a couple of shortcomings that make them difficult and annoying to use.

For starters, ASP pages are not written in the existing programming languages that can create compiled COM objects. While this may seem irrelevant, imagine that you already have a complex routine written in VBScript in an ASP page that performs the business logic your site needs to adhere to. To put this in, say, a Visual Basic COM object, you must translate the VBScript to Visual Basic syntax. While such a translation may be light work, what if you wrote your ASP code in JScript or PerlScript, or if you needed to create your COM component using Java or Visual C++? Such a translation would be exceedingly difficult.

Another shortcoming of COM components occurs when you need to make a change to an existing component that’s currently in use. Making a change requires, at minimum, recompilation and reregistration of the component, and at worst, a restart of the web services. Anyone who’s developed COM components with a high-level language is far too familiar with this annoyance.

To address these shortcomings, Microsoft offers Windows Script Components (WSC), which, as the name implies, are COM components created with script as opposed to a high-level programming language. Since Windows Script Components can be created using any ActiveX scripting engine, you can simply cut and paste your ASP code and create a COM component, regardless of what scripting language you used to create your ASP page! Also, since these are scripts, no lengthy recompilation process is needed when changes need to be made to an existing component.

Warning

Once you create a COM object and make it publicly available, any future changes made to the object must not break existing code. If you need to make changes to a COM object that will cause existing code to break, it is essential that you create a new component rather than alter the existing one.

To be able to create COM components with script, you must download and install the Windows Script Component from Microsoft’s Script site, http://www.microsoft.com/msdownload/vbscript/scripting.asp. Windows Script Components are simple text files and must be created using a predefined XML format. Rather than forcing developers to fully learn the rather terse XML format, Microsoft provides a freely available Windows Script Component Wizard. In this section we’ll look at how to create Windows Script Components using this wizard.

For starters, you’ll need to get yourself a copy of the Windows Script Component Wizard from the Microsoft Scripting Site, http://msdn.microsoft.com/scripting. At the time of this writing, the wizard was directly available at http://msdn.microsoft.com/scripting/scriptlets/wz10en.exe.

For this example, let’s create a COM component that would be similar to a compiled custom COM component. Assume we have a database table named Employee that has the following columns:

FirstName

The employee’s first name

LastName

The employee’s last name

Salary

The employee’s salary

BirthDate

The employee’s date of birth

Our COM component will contain a property for each column in the Employee table and a single method, AddEmployee, that will add a new row to the Employee table. The COM component will apply some business logic, ensuring that the employee is over 18 years of age and that the Salary is greater than or equal to $25,000. By placing this database insertion into a component, we are encapsulating the database complexity from the ASP developer. The developer does not need to concern himself with the structure of the Employee table or worry about adhering to any business rules.

Now let’s create our Windows Script Component! Once the Windows Script Component Wizard has been downloaded and installed, start the wizard by going to Start Programs Microsoft Windows Script Windows Script Component Wizard. The first step of this six-step wizard prompts for the name and ProgID of your component, as well as the version and filename for the script file.

Tip

The ProgID is what you will use in an ASP page to instantiate the Windows Script Component:

Dim objInstance
Set objInstance = _
         Server.CreateObject("ProgID")

Let’s name our component Employee and give it a ProgID of Employee.Insert. A screenshot of the first page of the Windows Script Component Wizard can be seen in Figure 7.7.

Enter the component’s registration and file information in Step 1 of the wizard

Figure 7-7. Enter the component’s registration and file information in Step 1 of the wizard

In Step 2 of the wizard, we are asked to specify the scripting language to use, as well as what special implementations to support. To have access to the built-in ASP objects, be sure to select the “Support Active Server Pages” option. Note that the Error checking and Debugging options have been disabled. These should be enabled only when in the development stages of the component, and not when the component is ready to be publicly used. If selected, the Error checking option will display error messages interactively; if the debugging option is selected, the Microsoft Script Debugger can be launched when an error occurs.

Figure 7.8 shows what Step 2 of the wizard should look like.

In Step 2 of the wizard, specify the scripting language that you wish to use and whether to implement ASP support

Figure 7-8. In Step 2 of the wizard, specify the scripting language that you wish to use and whether to implement ASP support

Step 3 prompts for the properties of the component and allows us to define whether the property is read/write, read-only, or write-only, as well as to set the property’s default value. For this example, we need a read/write property for each database column in the Employee table. Figure 7.9 provides a screenshot of Step 3 of the Windows Script Component Wizard.

Specify the component’s properties in Step 3 of the wizard

Figure 7-9. Specify the component’s properties in Step 3 of the wizard

Step 4 prompts for the component’s methods. Since we will only have one method, AddEmployee, there is only one entry here. Furthermore, this method expects no parameters, since there is a property for each database column; therefore, the parameters entry is left blank for the AddEmployee method. A screenshot of Step 4 of the wizard can be seen in Figure 7.10.

Specify the component’s methods in Step 4 of the wizard

Figure 7-10. Specify the component’s methods in Step 4 of the wizard

Step 5 of the wizard prompts for any events for the component. For this example, we will not add any events, so proceed on to the next step. Step 6, which is the final step in the wizard, provides summary information. Once you’ve checked to make sure everything is in order, go ahead and click Finish. This will create a shell for the Windows Script Component. It is now up to us to fill in the code for the AddEmployee method. The wizard has already written the rest of the component’s code for us!

Dissecting the Windows Script Component file

The generated Windows Script Component file contains several sections. Take a moment to look at the component’s source. At the start of the document there is the XML tag, since Windows Script Components are XML-formatted documents:

<?xml version="1.0"?>

The remainder of the file’s contents are placed within a <component> ... </component> block.

The first tag in the <component> tag is the <?component?> tag. This tag indicates whether or not the component supports error checking and debugging. The <?component?> tag has the following form:

<?component error="boolean" debug="boolean" ?>

Tip

If error checking and debugging were not selected in Step 2 of the wizard, as was the case in our example, then this tag will not exist. For completeness, feel free to add it in:

<?component error="false" debug="false" ?>

Next, a <registration> tag defines the description of the class, its ProgID, ClassID, and version number. Note that except for the ClassID, these values were entered into Step 1 of the wizard:

<registration
   description="Employee"
   progid="Employee.Insert"
   version="1.00"
   classid="{b31aab60-1fb8-11d4-8013-0000216d54d6}"
>
</registration>

The next block of code defines what properties and methods are public. Public properties and methods in a Windows Script Component are synonymous to public properties and methods in a VBScript class. Also note that each of the properties is marked as both read and write with the <get/> and <put/> tags:

<public>
   <property name="FirstName">
      <get/>
      <put/>
   </property>
   <property name="LastName">
      <get/>
      <put/>
   </property>
   <property name="Salary">
      <get/>
      <put/>
   </property>
   <property name="BirthDate">
      <get/>
      <put/>
   </property>
   <method name="AddEmployee">
   </method>
</public>

Next, the <implements> tag is used to indicate that this component has access to the built-in ASP objects:

<implements type="ASP" id="ASP"/>

The remainder of the file is a <script> block that contains the actual code for the component (in this case, VBScript code). Note that the <script> block is immediately followed by a funky-looking <![CDATA[ tag, and right before the closing script tag, its ending ]]> tag. This is a special XML reference indicating that the text between the <![CDATA[ and ]]> tags is source code and not to be interpreted by the XML parser. If the <![CDATA[ tag were left out, the parser would raise an error if any reserved XML names or characters were found in the component’s source code.

Tip

The CDATA tag is similar to the opening and closing HTML comment tags (<!-- and //-->) that should be used when writing client-side JavaScript. Both indicate to the parser that the content between these tags is not to be interpreted by the parser.

At this time, the AddEmployee method is just a skeleton function:

function AddEmployee(  )
   AddEmployee = "Temporary Value"
end function

It is up to us to add the necessary code. We do need to make one other slight modification to the WSC file before writing our code. Since the AddEmployee method will add a record to a database, we will need an instance of the ADO Connection object. This should be declared using the <object> tag after the <implements> tag and before the <script> tag:

<object id="objConn" progid="ADODB.Connection" />

The ID parameter in the <object> tag defines how the object will be referred to in our component’s code.

Now that everything is ready to go, let’s write the code for the AddEmployee method. This method needs to insert a record into the Employee table based upon the four properties. If one of these properties is not supplied, or if the supplied value of the property violates one of the business logic rules, an error will be raised. Otherwise, if the data is valid, a record will be inserted into the database.

Example 7.13 contains the source code for the AddEmployee method.

Example 7-13. The AddEmployee Method, upon Validating the Inputs, Inserts a Row into the Employee Table

function AddEmployee(  )
  'Ensure that all of the properties have been entered
  If Len(CStr(FirstName)) = 0 or Len(CStr(LastName)) = 0 _
     or Len(CStr(Salary)) = 0 or Len(CStr(BirthDate)) = 0 then
   'Raise an error
   Err.Raise vbObjectError + 1000, "Employee.Insert", "Property not supplied."
  End If

  'Ensure that the business logic rules have not been violated
  'Is employee 18 or over as of today?
  If DateDiff("yyyy", BirthDate, Date(  )) < 18 then
    'Raise an error
    Err.Raise vbObjectError + 1001, "Employee.Insert", "Employee under 18!"
  End If

  'Is the salary under 25k?
  If Salary < 25000 then
    'Raise an error
    Err.Raise vbObjectError + 1002, "Employee.Insert", _
              "Employee Salary cannot be less than $25,000!"
  End If


  'OK, there is no problem with the insertion data, so insert a
  'record into the Employee table!
  Dim strSQL
  strSQL = "INSERT INTO Employee (FirstName, LastName, Salary, BirthDate) " & _
           "VALUES('" & Replace(FirstName, "'", "''") & "','" & _
           Replace(LastName, "'", "''") & "'," & Salary & ",'" & _
           BirthDate & "')"

  'Open the connection to the database
  Const strConnection = "DSN=EmployeeDatabase"
  objConn.ConnectionString = strConnection
  objConn.Open

  objConn.Execute strSQL         'Add the record

  objConn.Close                  'Close the database connection
end function

Note that the AddEmployee method begins by checking to ensure that all data is passed in, that the Employee being added is at least 18 years of age, and that the salary is at least $25,000. If any of these checks fail, an error is raised using the Raise method of the Err object. Since the error-checking option was not selected in Step 2 of the wizard, when an error is raised it will be passed to the calling application (the ASP script using this component). Assuming these checks all pass, a row is added to the Employee table.

Warning

The validation in the AddEmployee method is far from complete. Measures should be taken not only to ensure that values were entered for each of the parameters, but that they match their expected datatypes. For example, an error should be raised if the Salary property is assigned a value of “More, please.”

Before using this component in an ASP page, we must register it. To register a Windows Script Component, right-click on the Windows Script Component file and select the Register option. Figure 7.11 shows how to register the component.

To register a Windows Script Component, right-click the .wsc file and choose Register

Figure 7-11. To register a Windows Script Component, right-click the .wsc file and choose Register

Once the component is registered, you can create an instance of the object in an Active Server Page (or in a Visual Basic, Visual C++, or Java program). Also, if you ever need to alter the component, all you need to do is simply edit the appropriate .wsc file! There is no complicated unregistering/reregistering as there can be with compiled COM objects, and you don’t need to stop and restart the web services when making changes to an existing Windows Script Component.

Example 7.14 provides a quick example of how to use the Windows Script Component we just created within an ASP page. Note that instantiating and using a Windows Script Component is identical to instantiating and using a compiled COM component. The ASP developer does not need to concern herself with whether the COM component was created as a binary or is in script form. Note that an instance of the Windows Script Component we just created is instantiated using the ProgID that we specified in Step 1 of the wizard (Employee.Insert).

Example 7-14. Using a Windows Script Component Is Identical to Using a Classical, Binary COM Component

<% @LANGUAGE="VBSCRIPT" %>
<% Option Explicit %>
<%
  'Create an instance of the Employee.Insert Windows Script Component
  Dim objEmployeeInsert
  Set objEmployeeInsert = Server.CreateObject("Employee.Insert")

  'Set the Employee.Insert properties
  objEmployeeInsert.FirstName = "Scott"
  objEmployeeInsert.LastName = "Mitchell"
  objEmployeeInsert.Salary = 78000
  objEmployeeInsert.BirthDate = "8/1/78"

  objEmployeeInsert.AddEmployee          'Add the employee to the database

  Set objEmployeeInsert = Nothing        'Clean up!
%>

Windows Script Components versus classical, binary COM components

Since Windows Script Components are interpreted scripts as opposed to compiled binary files, they will obviously suffer from poor performance when compared to binary files. Therefore, if you expect your site to have many concurrent users, it is best to stick with binary COM objects.

Also, since classical COM components are created using high-level languages, chances are you will be developing them using a mature development environment. With Windows Script Components, however, you will likely be using a development tool like Notepad to edit the component! While this is not a huge issue when dealing with a single, small component, imagine that you needed to develop a slew of large, robust, interactive components. Managing these large, interrelated files using Notepad would be difficult, at best, especially if a team of developers were working on the project.

Tip

A side benefit of compiled COM components is the source is hidden from prying eyes. Developers creating COM components for sale would want to make sure that the final COM component product is in binary form so that those purchasing the components cannot share the component’s source code with other potential customers.

The advantages Windows Script Components have over compiled COM components include the ease in making changes to existing components and the ability to dump ASP code into a component with little or no translation. Windows Script Components should be used as a stepping-stone to compiled COM objects. For example, in the development stages, use Windows Script Components. During development, you’ll enjoy being able to quickly make changes to existing, in-use components. As the project grows larger and moves toward shipping, be sure to move the components to a compiled, binary form, where they’ll benefit from improved performance.

Personally, I find Windows Script Components to be very neat and cool. In smaller projects, I have a hard time convincing myself that the advantages of using COM objects outweigh the burdens involved in needing to make changes to the COM object as the project progresses. Since altering an existing COM object requires recompilation and reregistration, it’s much easier to not use components. With Windows Script Components, however, that is no longer true! Also, I find it really cool that you can grab a snippet of useful ASP code and quickly stick it into a Windows Script Component, creating a COM component from working ASP code with little or no translation .

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.118.30.253