Starting Out With Components
As our customers, our managers and the sales team ask for
increasingly complex applications, the demands made of software
developers are growing at an ever-increasing rate. Lately, the
vogue for companies, quite rightly, has been to automate their
business processes. Now the drive is to integrate all of these
disparate systems together, often with the addition of a web
interface so that access to these products and services is more
widely available.
The continual growth in the adoption and expansion of
computer-based systems leads to more sophisticated (or
complicated) applications—some of which take years to develop,
or evolve without direction into unmanageable systems that no
single developer fully understands. When the system requires
maintenance or an upgrade, where's the developer who built the
thing in the first place? They're either 'too busy', or they've
moved on to richer pastures (not uncommon in today's market).
That means that some other poor developer has to bear the pain
and hardship of working out where changes need to be made—and
the ramifications that these changes will have on other parts of
the system.
Concerns over scalability, structure and maintenance of these
increasingly complex systems, coupled with the demands that are
the very nature of software development, mean that something is
needed to ease the burden. Components have got a lot to offer
us. If you think of a component as a small, self-contained
nugget of code that we write to sit at a well-defined point in a
system's architecture and perform certain (related) tasks, we
can begin a list of the benefits of components right here:
q Because by itself it is a lot simpler than the entire
application, we can maintain it easily.
q Because it's self-contained, we can upgrade simply by
taking out the old component and putting the new one in its
place. The same applies to components that we discover to
contain bugs.
q If it's useful elsewhere, we can reuse it—we may borrow
it for our own purposes, or put it on the market.
We could go on, but we'll save that for later. The point is
this: everything we've said so far is just as applicable to ASP
and web development as it is to any other kind of development.
Web sites are becoming more complicated: our ASP applications
are being asked to incorporate the functionality of traditional
applications; to centralize the point of access for end users
who need to get at different applications; to handle increasing
numbers of users. The fact is, we need to give components some
serious consideration.
Components are already an important part of programming and
software development, and the ability to build and use
components is a valuable tool in any programmer's arsenal. In
fact, these days, component building is arguably an essential
skill.
In this chapter, we're going to convince you that you already
know quite a bit about programming with components; we'll look
at some typical scenarios in which components are used; and
we'll begin to investigate the impact that component programming
has on application design. By the end of the chapter, you should
understand that componentization isn't just about code reuse—it
implies a new way of creating applications, opening the door to
techniques and technologies that aren't available in
'traditional' programming. Specifically we will see:
q The advantages of using components
q The basics of COM—Microsoft's Component Object Model
q An introduction to 3-tier and n-tier application
development
q Examples of situations where you're probably using
components already
q How to build and use our first component
The Advantages of Componentization Consider the question,
"What's the best approach to the solution of a complex
problem?" Perhaps the most obvious answer is this:
q Break it up into a number of smaller parts, each of which
is self-contained and can be easily understood
q Solve each of the smaller parts (or use a ready-written
solution—you might have a solution lying round from a previous
project, or you might buy in a third-party solution)
q Bring each of the smaller parts together to create the
overall solution
This approach generally works very well—and programming is
no exception. The reason is probably its simplicity—but this
simplicity is the key to good software engineering and
development.
COM—the Component Object Model The good news is that there
is an established technology available to us today that allows
us to build our applications this way. It is called COM—the
Component Object Model. COM is the software industry's favored
solution for solving the complex problems relating to large
applications and code reuse on the Windows platform. Using
componentization, large applications can be assembled from
smaller, self-contained packages of software, each of which
performs a particular task.
By using components, we only need to write a small amount of
application code to act as 'glue', sticking the pieces together.
The 'glue' then simply calls the components into being, provides
them with the information they need to do their work, and then
either lets them get on with it or waits for them to produce a
result. In this sense, they can be like little "black
boxes" of functionality: you don't need to know how each
component achieves its task; you just need to know what it's
capable of doing and what values you can provide it so that it
will accomplish the task it is built for.
A Couple of Analogies If that sounds a bit esoteric, consider
what happens when you need to ask the operator for your uncle's
telephone number. You call the operator, and you give the name
and address of your uncle. Then, they go away and do their
thing... and eventually they come back with a number (or not, if
your uncle has no telephone). In this sense, the operator is
acting like a component—maybe the request would be programmed
like this:
Dim objOperator
Set objOperator = Server.CreateObject("Operator")
Response.Write "The phone number you require is "
& _
objOperator.GetNumberFor("Uncle Brian",
"Chicago")
The point here is that we're not particularly worried about
how the operator finds the number—we just give them the
information and expect them to do the job.
As another example, think about hi-fi 'separates'. You buy an
amplifier, a pair of speakers, a CD player, and you wire them
all together with some leads. Then, a month later, you decide
that you wanted a turntable so that you can play all your old
vinyl. But you don't go out and buy a whole new system—after
all, you already have an amplifier and speakers. You just expand
the existing system by purchasing the turntable and plugging it
into your amplifier.
In your average software house, this is how customers and the
sales/marketing department think that application development
works. Wouldn't it be nice if it really did?
Well, there can be a strong similarity. You may not have
realized it, but you're already using COM components. For
example, in your software development, you've probably already
come across ActiveX Data Objects (ADO)—a set of components for
data access. Or perhaps you've used the Ad Rotator component,
the Content Rotator component, or some of the other components
that are provided as standard with ASP?
Better still, look at the software you use every day—things
like Microsoft Word and Internet Explorer. Many of these kinds
of application are written using components. The Internet
Explorer executable (Iexplore.exe) is only 77Kb in size; all of
its sophisticated functionality is handled by numerous other
components, which the executable only calls into action when
necessary.
What Do Components Do for Us? Hopefully, we've given you an
incentive for wanting to learn about components. The advantages
of packaging up our code into components rather than using
script are numerous, and we'll outline the main ones here.
Code Reuse and Distribution Possibly the two most common
reasons for using components are:
q Breaking up a complex application into manageable chunks,
as we've already discussed
q Packaging up code that you are likely to need more than
once so that it can be re-used
Having written a piece of code that performs a specific
function, cutting and pasting the appropriate pieces into
another program can often be difficult. If you've ever done this
with your own code, you'll know how tricky it is to remember how
you originally intended the code to work—you may have to work
out what each line is doing in order to select precisely the
correct lines. And if you've ever done it with someone else's
code, you'll know that it's even harder!
When you package code into a COM component, you are
automatically providing a clear definition of precisely how to
use the functionality of that component. You'll still need to
document it, but you won't need to do any cutting and pasting of
code.
Easy Distribution Of course, this also makes for a convenient
code distribution technique. When passing your neatly packaged
component to your colleagues and customers, they don't need to
understand the code behind it to get it to work—you just tell
them what tasks it can achieve and what information they'll need
to pass to it.
For example, we don't need to know how the ADO components
work in order to use them. We can just retrieve them from the
Microsoft web site, install them, and let Microsoft's
documentation tell us the rest.
Binary Distribution and Reuse As we'll discuss in more detail
later on, COM components are language neutral—they can be
written in one language and used in another. If you ask a Visual
Basic compiler to compile some C++ code, you'll see some
interesting errors and it won't work. Ask a Visual Basic
application to use a COM component that was written in C++, and
it will work fine.
Maintenance and Replacability Here's a case in point: if you
have to do a lot of form field validation, you can write a
component that performs the task for you—that way, you
centralize the code in a component, and you can simply reuse it
time and time again.
If you ever find a problem with your validation code, you can
just correct the component and reinstall it in place of the
faulty one. Drawing an analogy with our telephone operator
example, this is comparable to the operator being off work. The
telephone company just installs another operator as a stand-in.
We, as clients, don't care which operator is on the other end of
the 'phone—so long as they can do the job.
Commercially Available Components There are an ever-growing
number of components that are available commercially. If you
have a programming task to achieve, it's quite possible that
there's already a component out there in the marketplace that
will help you to achieve you goal, or even provide a complete
solution. Buying a suitable third-party component means that we
don't need to research, write and test the component ourselves—this
brings three immediate advantages:
q We can acquire the component immediately, and therefore we
should be able to deliver our final solution faster
q We've effectively replaced the cost of development and
testing (for that part of the project) with the cost of a
fixed-price lump of pre-written code—which is usually cheaper
q Highly specialized components are usually written in
consultation with specialists in the field. In that case, we
also avoid the cost of employing a specialist
In addition, commercial components should be tried and tested
in their market situations, so you can be fairly confident that
it will perform well at the task it is intended to achieve
(although it's worth restricting yourself to buying components
only from trusted suppliers, as you generally don't get to see
the source code). One very popular example of such a component
would be a credit card verification component for use in
e-commerce sites.
To get an idea of the number of components on the market,
check out some sites that specialize in selling components over
the Web. For starters, try http://www.componentsource.com,
http://www.greymatter.co.uk, and http://www.serverobjects.com.
Performance Advantages When you're executing complicated
code, you're always looking to reduce the time it takes to
process. However, if your code is in the form of ASP or some
other script, you can reasonably expect it to take a while.
That's because scripting languages are interpreted. That is to
say, each line of code needs to be converted into more
elementary instructions (binary code) that the processor can
understand, before that line can be executed. That happens every
time a script is run.
By contrast, components are usually already compiled, which
means that they have already been converted into the binary
format. This means that the component's methods—the functions
that it makes available—can be executed straight away. The
result is that components often execute much more quickly than
plain scripts do.
Hiding Sensitive Code If you're distributing code, then you
need to think about whether you want other people to see it. If
they can see it, they can figure out how it works, and they can
probably also tamper with it. If you're distributing script
files, your code is open to these kinds of threat.
Writing components in languages such as Visual Basic and C++
requires you to compile them. By compiling the component, you
produce the binary representation that we mentioned in the
previous section—not only does this execute efficiently, but
also it protects your code from snoopers and code-changers. Your
component's business logic is safe from anyone who may wish to
meddle with it.
Splitting Tasks Into Distinct Areas If you have several
developers or teams working on an application that is split up
into discrete chunks, componentization makes it possible for
each of the different groups to work on a different part of the
application. Each task can be clearly defined, and you can
specify the values that the different parts of the application
need to share in order for the application to come together as a
whole afterwards.
Ease of Debugging While the Script Debugger is a very useful
tool, it isn't nearly as sophisticated as the debuggers in
Visual Basic and (in particular) Visual C++ . The debugging tool
in the Visual C++ development environment, for example, allows
you to look right down into the computer's memory to see what is
being stored where.
This kind of capability means that, if you're using Visual
C++ or Visual Basic to write components that are intended to
perform complex tasks, you gain the edge in terms of finding out
exactly why your code isn't working properly.
That covers some of the major advantages of componentization,
although we will see others as we go through the book—in fact,
we'll see some more in this very chapter. If you take all of
these advantages into account as you write your ASP
applications, you may soon find yourself writing less of your
programming logic in script, and placing more of it into
components. The ASP script becomes the 'glue' that binds the
component pieces of your application together.
How It All Comes Together So, to recap: COM stands for the
Component Object Model, which is a framework for creating and
using components.
Microsoft introduced the COM framework back in 1993, as a
model for describing and implementing components in such a way
that they could interact with each other and with all
COM-enabled platforms and applications. COM is the specification
to which components are written and used on the Windows platform—and
there are now implementations of COM on many non-Microsoft
platforms. Every component that we develop in this book will be
a COM component, and will therefore conform to this
specification.
Let's backtrack a little. We've just made a rather lofty
claim. All COM components will be able to interact with all
other COM-enabled platforms and components? How do they do that?
The foundation of COM is a binary specification that defines
how the code using a component—usually called a client—can
use the functionality that a component makes available. On the
flip side, it also defines how a component exposes that
functionality to a client.
Because COM is a binary specification, it allows language
neutrality. As long as a given language can produce compiled
code that complies with the binary specification, it can be used
to write COM components—and it can also interact with COM
components written in any other COM-enabled programming
language.
There are a number of languages in which you can write COM
components. In this book, we will mainly see how to write COM
components in Visual Basic and C++, although there are many more
languages you could use, including Visual J++, SmallTalk and
Delphi.
So, while this book is about components for ASP, the
components that we'll develop are all COM components—and that
means that (with some exceptions) they can be used in other
COM-aware programs, such as standalone applications written in
Visual Basic or Visual C++. As we will see in Chapter 3, the
ability to do this is dependent upon whether our components are
designed to interact with the environment that calls them. If we
develop a component that relies on some functionality of the ASP
object model, for example, we will only be able to use it within
with ASP applications. There are, however, very many occasions
when our components will be reusable in different environments.
COM is not the only specification for components—CORBA and
JavaBeans are two others. However, as this book is about
components for ASP, we will be focusing on COM components.
ActiveX and COM A term that you may have come across in the
context of component-based development is ActiveX, and we should
make clear that in most situations, ActiveX means pretty much
the same thing as COM. An ActiveX component is the same as a COM
component. In addition, an ActiveX control is the same as a COM
control, and an ActiveX server is the same as a COM server. But
don't let all that confuse you—we'll come back to these terms
shortly.
Today, ActiveX is little more than an outdated brand name
that was introduced by Microsoft a few years ago when they
redirected folks towards the Internet and revamped and optimized
some of their technologies to meet the low-bandwidth
requirements of the Net. There was ActiveX Scripting, ActiveX
Components, ActiveX Data Objects, ActiveX Controls, and ActiveX
Documents.
ActiveX achieved its original goals and got lots of media
attention, but since then people have been confused about the
differences between COM and ActiveX. Essentially, however, in
modern-day parlance and as far as ASP component development is
concerned, ActiveX implies COM.
Components and Objects We've established that a COM component
describes a set of related functionality and the code required
to achieve that functionality. When we want to use a component's
functionality, however, we don't make constant references to the
component itself. Rather, we use the component as a blueprint,
and we use it to create an entity that we refer to as an object.
The process of creating an object from a component is called
instantiation. An object is a single instance of a component.
The object is created in the image of the component, and is the
vehicle by which we make use of the component's functionality.
In code, we use objects. An object represents a single entity
within our code; we use a component as the blueprint for
creating an object.
We may want to use several instances of a single component at
any one time, within different applications. Or we may have a
single application that uses several instances of the same
component—just like having many variables (or 'instances of
variables') to hold different strings.
You should be aware that the term 'component' is often used
to refer both to the COM component and to the instance—relying
on the context to imply the exact meaning.