Distributed Application Architecture
One of the key elements of any application design is the system
architecture. The system architecture defines how the pieces of the
application interact with each other, and what functionality each piece is
responsible for performing. Whether we like it or not, in the Web-based
world we inhabit, we are more often than not going to be building
applications that exist in a distributed environment. In fact, the
ASP applications are actually distributed applications.
A distributed application utilizes the resources of multiple
machines or at least multiple process spaces, by separating the
application functionality into more manageable groups of tasks that can be
deployed in a wide variety of configurations. There are a number of
benefits to dividing applications up into pieces, not the least of which
are reusability, scalability, and manageability.
Ultimately, dividing up an application in this manner results in the
creation of a series of application layers or tiers, each of which
is responsible for an individual, or atomic, element of the application's
processing.
Tiered Applications
Tiered applications can be characterized by the number of layers that
information will pass through on its journey from the data tier (where it
is stored in a database typically) to the presentation tier (where it is
displayed to the client). Each layer generally runs on a different system,
or in a different process space on the same system, than the other
layers.
Two-Tier Applications (Client/Server)
Let's look briefly at the 2-tier client/server architecture. Typically,
we have a user's PC for the client (front-end) and a network server that
contains the database (back-end). Logic is divided between these two
physical locations. Usually the client contains most of the business
logic, although with the advent of stored procedures, SQL language
routines allow business logic to be stored and executed on the database
server:
The 2-tier scenario works very well when you have a small business that
only uses, or needs, a single data source. However, the goal of most
businesses is to grow. As the business grows, so will the database and its
requirements. Unfortunately, the 2-tier approach does not scale very well.
If your business rules change then the application needs to be rebuilt and
redeployed. In addition, there are factors such as the maximum number of
simultaneous database connections that prevent this architecture from ever
being of much value in a distributed setting with more than a few
users.
Three-Tier and N-Tier Applications
Due to the limitations of the 2-tier client-server architecture,
distributed applications are often divided up into three or more tiers.
Components in each of these perform a specific type of processing –
there's a User Services (Presentation) tier, a Business
Services tier, and a Data Services tier in a 3-tier
application.
The main distinction between this 3-tier architecture and your
traditional 2-tier client-server architecture is that, with a 3-tier
architecture, the business logic is separated from the user interface and
the data source.
Breaking up applications into these separate tiers or sections can
reduce the complexity of the overall application, and results in
applications that can meet the growing needs of today's businesses.
n-tier applications are just 3-tier applications that might further
sub-divide the standard User Services, Business Services, or Data Services
tiers. In any case, an application with more than two tiers can be
considered an n-tier application.
In this type of application, the client should never access the data
storage system directly. If it did, it would be circumventing the business
rules of the application and would thus be unable to ensure that the data
on display to the client was correct.
The separation of the various aspects of an application into n tiers
allows for any part of that application to be modified without having to
change the other parts, allowing developers to specialize in designing and
developing a specific tier or tiers. Similarly, developers can also take
advantage of the development tools that specialize in the development of
that tier, rather than making use of general purpose tools, which are
sufficient to build an entire application but are lacking in terms of
powerful features.
Before we look at the three basic types of services in more detail,
there is one more variation on the n-tier theme we need to look at.
Windows DNA
Windows DNA refers to Microsoft's Windows Distributed interNet
Architecture, and not DeoxyriboNucleic Acid. It is Microsoft's latest
and greatest development model for the Windows platform, the goals of
which are to:
| • |
Provide the architecture to develop and deliver robust, scalable,
networked applications on the Windows server platform |
| • |
Make both new and existing applications and data sources
available to a wide range of clients, from traditional desktop
applications, to Web browsers, to Internet
appliances |
Windows DNA is about Infrastructure
Windows DNA provides a roadmap that helps make developing distributed
applications easier, because it's all about encouraging the use of already
available application and operating system services to minimize the amount
of infrastructure code required to create a distributed application.
Just think about all the times that you wrote hundreds of lines of code
to provide transaction processing, message queuing, security, or custom
database access in your applications. Now imagine all of these distributed
application requirements being lifted off your shoulders. Instead,
Microsoft will take care of these details for you, by providing you with a
set of efficient and programmable services, leaving you to concentrate on
the business requirements of the application.
The bottom line is that developing distributed applications with the
Windows DNA model will result in higher performance, more reliable, and
scalable distributed applications, delivered faster than ever before, at a
lower cost.
Before Windows DNA, usually only large-scale or enterprise applications
distributed application processes. However, because of the application
infrastructure, Microsoft continues to build and enhance its applications,
making it easier to develop distributed applications. Soon many of your
smaller network applications will be using the Windows DNA model instead
of the traditional two-tier client-server model.
Windows DNA is about Interoperability
Windows DNA can interoperate with, or talk to and make use of, existing
legacy systems so you can leverage and extend current technology
investments. Try telling the Chief Information Officer of a medium-size
manufacturing company that you want to scrap all of their existing
software and hardware so you can develop new distributed applications
based on the Windows DNA model.
It won't happen overnight – just like converting all companies that use
Oracle database systems to Microsoft SQL Server 2000 database systems.
Microsoft has finally realized that not everyone will or can afford to
convert every legacy system to run on the newest Microsoft platform. The
legacy systems will remain in place, but will need to be integrated into
our new applications. The evidence of this discovery can be found in the
Windows DNA model, with its interoperability and support for industry
standards. For example, the Windows DNA model supports the open Internet
standards for HTML and XML.
The missing link between systems is DCOM, which allows applications to
communicate across processes and across machine boundaries to compiled
components that provide services, all the while without having to know
where the service is located or how it is implemented. It allows
developers to create service-based applications while using
component-based development methodologies.
While DCOM is mainly a Windows platform service (I say mainly
because DCOM has been ported over to some versions of Unix) the open
Internet standards supported by the Windows DNA model ensure that you can
create cross platform distributed applications.
Windows DNA also makes provisions for the access of legacy data with
its Universal Data Access (UDA) initiative, by allowing you to use the
same data access library to run queries against your SQL Server and your
legacy AS400 databases, for example. This is achieved by several sets of
technologies all knowing how to interact with that same library, and then
having the ability to access both relational and non-relational data from
multiple different sources on their own system.
Windows DNA is about the Internet
When Microsoft introduced the Windows DNA architecture in September
1997, they introduced a framework for creating new Internet applications
as well as integrating the Web with already existing client-server and
desktop systems. The Internet is a great application platform for two main
reasons:
| • |
The Internet allows developers to create applications that are
platform independent without making developers learn a new
proprietary language. |
| • |
The Internet provides a flexible mechanism for deploying
applications. Deployment is a major problem for lots of
organizations, especially when you're talking about deploying a
large-scale, enterprise application to several separated
locations. |
Windows DNA Services
As we've seen, Windows DNA provides a range of services that provide
the necessary plumbing and infrastructure upon which we can build our
application in relative ignorance.
Presentation Services
The presentation services of Windows DNA deal with how the application
interacts with the user. This user can be located on the same computer, on
a different computer on the same LAN, or on a computer on the other side
of the world connected by the Internet. A key concept behind Windows DNA
is that the accessibility of the application is not affected by the type
of client that the user has. In order to provide this flexibility, Windows
DNA supports a wide range of client types and a wide range of tools with
which to build these presentation services.
Even though a Windows DNA application can support many different client
types, we can characterize them into four distinct categories, two of
which are traditional "fat-client" while the other two are
"browser-based". The traditional applications are either written to take
advantage of a network connection, if one is available, or written such
that they simply will not function if a network connection is not present.
The browser-based applications meanwhile can either be browser-neutral or
tailored for a specific browser.
Internet-Enhanced Client
An Internet-Enhanced client is one that takes advantage of the
features of DNA and can also make use of, but is not reliant upon,
Internet connectivity. Take, for example, Microsoft's Office 2000 and
Visual Studio. These applications support unified browsing by embedding
hyperlinks from within the application, host the browser for the display
of documentation written in DHTML, and provide the capability to download
updates over the Internet seamlessly.
Internet-Reliant Client
An Internet-Reliant application is one that is written as a
traditional Windows application, but which requires a network connection
to a server in order to function. This type of application is generally
used when the user interface of the application goes beyond what is
efficiently developed using a Web-based client. It could also be an
enhancement to an existing Windows application to convert it into a
Windows DNA application. The primary characteristic of this type of
application is that it requires a connection to the network in
order to function, as opposed to an Internet Enhanced application, which
will run on a stand-alone machine as well as on a networked one.
"Fat-client" applications can be created using any of the Windows
development tools, such as Visual Basic, Visual C++, Delphi, or any other
tools that will create an executable application. The reliance on a
network connection can be added in several different ways. The application
could link to the Windows Sockets library in order to connect to a server
via TCP/IP over the local network or Internet, for example. Alternatively,
it could host an embedded version of Internet Explorer to provide access
to information on the network. In any case, the application interacts with
(and depends on) a server somewhere on the network in order to function
and won't work without a permanent link to it.
Browser-Enhanced Client
Whereas the two previous application types that we looked at are part
of an executable application, the second two are browser-based
applications, so called because they use HTML as their presentation
mechanism. This HTML is retrieved in real time from a Web server using
HTTP as a data transfer protocol. The HTML provides a user interface to
the client that allows the user to interact with the application using a
Web browser.
Even though HTML is a specification, different browsers often support
extra functionality not found in the ratified standard. When a user
interface is developed that requires the use of extensions to the HTML
specification, this is known as a Browser-Enhanced application. For
a Windows DNA application, this usually means that the user interface is
targeted for delivery in Internet Explorer. With a specific browser as a
delivery target, the developer can utilize technologies such as ActiveX
controls, Dynamic HTML, or IE Behaviors to make the user interface more
like a traditional Windows application. Even in this case, the user
interface is delivered to a Web browser using the HTTP protocol from a Web
server. Applications such as this are generally found on corporate
intranets, where the IT department can control the target browser
platform. If the application developer can expect a certain version of a
browser, then they can create a Browser-Enhanced application and know that
it can be executed successfully.
Browser-Reliant Client
One of the drawbacks of browser-enhanced user interfaces is that they
generally require a specific browser in order for the user to work with
the application. Whenever a new technology, such as a new browser version,
is made available, there is usually a time lag, sometimes up to several
years in length, before a large installed base of that new browser version
becomes available. During that time, if the developer targets these new
features, then they risk making their application unavailable to a large
portion of their audience.
To avoid this problem, the developer can choose to target an earlier
browser version, which will make their application accessible to wider
population. These types of clients are known as Browser-Reliant.
This may sound a bit deceiving, but the name refers to the fact that the
user interface is reliant on a browser and not a specific version of that
browser. It is probably not effective for a developer to develop an
application that works with ALL browsers. Generally, the current standard
for applications requiring a wide deployment will be a browser target of
the version 3.x browsers from Netscape and Microsoft.
By targeting this browser version, the developer will have access to
client-side scripting using JavaScript and the HTML 3.2 specification. It
will also make the presentation compatible with all of the subsequent
browsers, from both Microsoft and Netscape. With the growth in popularity
of Internet Explorer following the release of version 4.0, this has also
become a baseline development target for a number of developers, most
notably those of corporate intranets where IE is becoming the
standard.
Application Services
A Windows DNA application relies on the available application services
to store and execute the core of its application logic. This business
logic tier is where the application-specific processing and business rules
are maintained. The Windows DNA services for developing these application
components include Web services, messaging services, and component
services.
Component Services
Component-based applications have been the standard method for creating
applications for the better part of the last decade. From their earliest
days as DDE, then OLE, OLE2, and finally today's ActiveX, component
applications for the Windows platform have become widespread. It's not
surprising really considering how much easier development is using
components – the whole process now has a new model which consists of
wiring pre-built components together to create an application. Why is this
possible? Because every component has a number of publicly accessible
functions that other components can discover and use. The end effect is
that components are simple to reuse and allow different applications to
work with each other.
To help component-based applications grow into enterprise-level
applications, Microsoft added the Microsoft Transaction Server to provide
services for the development, deployment, and management of
component-based distributed applications. By encapsulating this plumbing
into a system-level service, it freed developers from having to explicitly
add this support to their applications.
With the release of Windows 2000, we saw the introduction of COM+. COM+
unifies the programming models of COM and MTS and makes it even easier to
develop distributed applications by eliminating the need to handle both
services individually. This allows the developer to build applications
faster, easier, and ultimately cheaper by reducing the amount of code
required to make use of these component services.
Messaging Services
Since not all parts of a Windows DNA application need to be located on
the same computer, or even in the same physical location, it is critical
that developers be able to communicate with these disparate systems. And,
in the networked applications paradigm, there also needs to be a way for
disconnected clients to communicate with the application. Messaging is a
technology that permits this communication. Microsoft Message Queue Server
(MSMQ) makes it easy to integrate applications by implementing a message
delivery mechanism between applications. This allows the developer to
build reliable applications that work for both connected and disconnected
clients. MSMQ also offers seamless interoperability with other message
queuing products, such as IBM's MQSeries.
Web Services
The application services of a Windows DNA application need a way to
interact with the presentation layer on the client. In this case, that way
is the Hypertext Transport Protocol, a mechanism which Microsoft's Web
Server, IIS, already provides as a service for anything that cares to use
it. In fact, IIS not only supports the delivery of static Web pages to a
client, it can also be used to dynamically create client presentations
through its integration with Active Server Pages. But you knew that
already, didn't you?
Data Services
As we noted earlier, Universal Data Access is Microsoft's strategy for
providing access to information across the enterprise. It provides
high-performance access to a variety of information sources, including
relational and non-relational data, and an easy-to-use programming
interface that is both tool and language independent. UDA does not require
the expensive and time-consuming movement of data into a single data
store, nor does it require commitment to a single vendor's products. It is
based on open industry specifications with broad industry support, and
works with all major established database platforms. The two primary
components that provide data services are ActiveX Data Objects (ADO) and
OLE DB, both of which we've already covered in this book.
The Structure of the Web
The structure of the Web is a lattice of HTML-formatted pages,
distributed from computers known as Web servers to client computers, and
viewed using tools called Web browsers. At the most basic level, there is
no difference between a server that has thousands of pages and a server
that just has one or two. It is by linking these pages together in some
form that a set of pages becomes a Web site, and by adding some additional
logic, a Web site becomes a Web application.
Web Page
The basic unit of a Web interaction is the Web page itself. A Web page
is a text file that is marked up using HTML. It is sent to a browser from
a Web server based on a request from that browser. The browser parses the
information in the HTML file, and the resulting user interface is
displayed within the browser itself. The role of the Web server is to
listen for a request from the client, parse the request to determine the
page that the client requested, retrieve that file from the server's
storage area, then transmit that file to the client. At this point, the
server forgets everything about sending that file to the client, except
for maybe placing an entry into a log file. It is this "connection-less"
nature that gives a Web server its scalability, but in turn makes it a
challenge to create meaningful applications without some additional
support.
Web Site
A Web site consists of a set of related Web pages grouped together by
some means. Generally, a Web site is all of the pages that exist on a
server, or within a folder on that server. For example, all of the pages
that are on the http://www.wrox.com/
server are considered part of that Web site. The correlation between the
pages on a site is maintained by the links within each page on the site.
The links on each page in the site will take users to other pages within
the site. In this way, the pages that make up the site internally maintain
the hierarchy of the site. These pages are still subject to the
restriction of the Web server architecture, in that the server does not
maintain information about the series of requests from a particular
client. So while this related set of Web pages that make up a Web site are
beginning to look more like an application, there are still some missing
components.
Web Applications
Windows DNA applications are applications in the traditional sense, in
that they provide a service to the user of the application. They are
different in the way that they are created as well as in the components
that make them up. A traditional application requires a special set of
files during development, but distributes different outputs. For example,
a Visual Basic application has a .vbp project file, multiple .frm, .cls,
and .bas files, as well as a set of OCX components that make up the
application project. Prior to the application being distributed, these
files are compiled into a set of executable files for distribution and
execution. The resulting executable does not require the presence of the
source code files that were used to develop it.
Script-based Web applications, on the other hand, are composed of the
same set of files used during development and after deployment. There is
no compiled executable file produced that becomes the Web application. For
example, the .htm, .asp, and .dll files in your Web project are the same
files you deliver to your production Web server. The source code, or
script, in these Web files is executed on the client or server only when a
browser requests the Web page. Creating these applications builds upon the
architecture of the World Wide Web, but there is some added complexity and
functionality in order to have these files function as an application.
Web Application Design
In building a Web application, there are a number of new aspects of
application design and development that the developer must take into
consideration. While the flexibility of Windows DNA allows for a wide
variety of clients accessing a wide variety of services, we will be
focusing on a Web application. In a Web application, we will look at using
a browser as the primary user interface. The information in our Web
application will flow from server to client using the HTTP protocol. Our
Application server will be Microsoft's Internet Information Server
functioning as both a Web and Application server. Finally, our business
and data access logic will be encapsulated within COM+ components and
serve as the plumbing that links our application together.
The Browser as the User Interface
For a Web application, the user interface is presented within a Web
browser. This means that the client presentation can either be
Browser-Enhanced or Browser-Reliant. The type that you choose for your
application should be based on the installed browser base of your target
audience. If you can guarantee that most of your users will be using a
particular browser level, then you should consider leveraging the features
of that browser level. If there are a wide variety of browsers in use,
then you may only be able to support a Browser-Reliant client presentation
type. One of the advantages of using Active Server Pages to deliver the
application is that it has the capability to determine with what browser
the current user is accessing the application. This was covered in Chapter
6 with the Browser Capabilities component. By knowing the browser type of
the current user, you can dynamically change your client presentation to
support the enhanced characteristics of that browser.
HTTP as the Transport
The communication layer between the client and the server is critical
to the design and implementation of the application. The HyperText
Transport Protocol (HTTP) defines how the request made by the client is
received and handled by the server, and then how the information is sent
back to the client. Depending on the type of client presentation being
supported, there can be different types of information that flow using
this protocol. For the basic support of a Browser-Reliant client, the
information that flows over HTTP is limited to the HTML that makes up the
page, graphical images to enrich the interface presentation,
information-bearing cookies, and possibly some client-side scripting to
provide interactivity on the client. With an Enhanced client, special
features such as Remote Data Services or COM over HTTP may also be
communicated over the transport protocol. But support of these is reliant
on the capabilities of the browser at the client. In either case, the HTTP
protocol does not understand the concept of a persistent connection
between client and server.
IIS and ASP as the Application Server
The combination of Microsoft's Internet Information Server as the Web
server and Active Server Pages as the Application server provides the
application component of our Web application. For Web pages and Web sites
that serve up static Web pages for display, IIS can function by itself to
provide the information. But when a Web application demands a dynamic
display of information, we need to link the Web serving capabilities of
IIS with the dynamic page generation and object integration capabilities
of ASP to deliver a more robust and dynamic Web application. The scripting
capabilities of ASP allow us to support business logic inside of our
scripts, link with business logic components, directly access databases
via ADO, and make use of data components to retrieve information.
COM+ as the Plumbing
The component-based design of Windows DNA applications is made possible
by their reliance on COM+ for component services. While a fully functional
application can be constructed out of ASP script and HTML, it is when the
business logic and data access are separated out into components that a
more robust and scalable application begins to emerge. By placing the
business and data access logic inside of components that have been
compiled prior to execution, the performance of the application increases.
And, with the increase in performance, we have laid the path for a
corresponding increase in the number of users that the application can
effectively support.
Components
With all of this talk about components and component-based
applications, it is important to understand just what a component is. We
have seen a number of them used in ASP already in this book – remember
that ADO is a set of components that support access to data sources. There
are six components intrinsic to ASP 3.0 that allow a developer to access
certain parts of the Web application. The concept of components is
critical to the creation of scalable Web applications.
What is a Component
A component is an object that contains code to manipulate data from
one form to another, and which provides access to that code through a
well-specified set of publicly available services.
This is a very literal definition of a component.
In a more practical sense, a component is an encapsulated piece of
code that performs some function for an application.
This function could be the processing of a business rule, like the
computation of a sales tax, or it could be the retrieval of some
information from a database for an application. The key characteristic of
a component is that when it is created for use, the code for the
component, as well as the information associated with the component, are
packaged together. In this way, if there are multiple versions of the same
component in use at one time, each one keeps its information separate from
the others. There is no danger of information in one polluting the
information of another.
In addition to the type of work that it performs, a component is also
defined by its interface. To understand about interfaces in more detail we
need to take a closer look at COM.
COM and COM+
Throughout this chapter, we have talked about components and COM rather
freely. COM stands for the Component Object Model.
COM is an outgrowth of the object-oriented paradigm and is a
specification that is based on a binary standard for reuse through
interfaces.
COM is an object model developed by Microsoft and implemented on all of
the Windows platforms. It forms the basis for all applications developed
for Windows in that nearly all interactions with the base operating system
are through COM-defined interfaces. COM defines a standard for component
interoperability – that is, the ability of components to interact with one
another. It does not specify the language that the components are written
in – it merely specifies how components need to communicate with one
another and with the operating system itself. By specifying the
interoperation standards that components must adhere to, it makes it easy
for components created by different developers, even developers from
competing companies, to work together in an application. This means that
components written for COM can be reused without any dependencies from the
language it was written in. It doesn't matter if an application contains
components written in Visual Basic, C++, Java, or even COBOL, just as long
as these components follow the COM specification.
COM+ is a set of services that combine COM with Microsoft Transaction
Server (MTS) on Windows 2000 systems. MTS provides the facility to manage
the lifetimes of components. Rather than having to worry about the
creation and destruction of objects for their application, COM+ has the
ability to manage that for us, so we can focus on implementing their
business logic. With the introduction of COM+, the functionality of MTS
has been merged into the operating system and is now called Microsoft
Component Services. We'll take a cursory look around this in the next
section, but for a more detailed discussion, you should take a look at
Chapter 15.
Component Services
With the release of COM+, Microsoft Transaction Server has ceased to
exist as a separate entity on Windows 2000. Its functionality is now a
basic part of the operating system under the moniker "Microsoft Component
Services", which should indicate that there's more under this roof than
just the management of transactional services and components'
lifetimes.
Along with a new name, the Component Services also offer some new
functionality in the way that components are handled over MTS. As the
operating system service – and not the developer – handles more and more
of these features, our lives should become much simpler in the pursuit of
developing robust and scalable components. Here's what's on offer.
| • |
Component Load Balancing (CLB) – CLB allows multiple
application servers to provide the same COM+ object for use in an
application. When that object is needed, the creation request is
sent first to the CLB Server which then redirects the request to an
appropriate application server, based on certain criteria (like how
busy and how far away from the machine running the application it
is). The client application then interacts with this server for the
lifetime of the component. Load balancing would be implemented at
the COM class level but at the time of writing it was unclear as to
whether CLB would be included in the initial release of Windows
2000. It may make an appearance as part of a Service Pack, or in a
future release of Windows 200x. (I guess this will become the new OS
naming convention.) |
| • |
Queued Components – Combines the features of COM and MSMQ
to provide a way to invoke and execute components asynchronously.
Processing can occur without regard to the availability or
accessibility of either the sender or receiver. When a client calls
a queued component, the call is made to the Queued Components
recorder, which packages it as part of a message to the server and
puts it in a queue. The Queued Components listener retrieves the
message from the queue and passes it to the Queued Components
player. The player invokes the server component and makes the same
method call. |
| • |
In-Memory Database Support – The In-Memory Database (IMDB)
is a transient, transactional database-style cache that resides in
RAM memory and provides extremely fast access to data on the machine
on which it resides. IMDB can be used by COM+ applications that need
high-speed database lookup capabilities or applications that need to
manage transient state. Data inside an IMDB can be accessed using
ADO or OLE DB interfaces from a COM+ object. As with load-balanced
components, the IMDB technology has not found its way into the first
release of Windows 2000. It will most likely appear in a future
version of Windows 200x, and will probably be enhanced based on
feedback from developers. |
| • |
Object Pooling – Object pooling is an automatic service
provided by COM+ that enables you to have instances of a component
kept active in a pool, ready to be used by any client that requests
the component. Once the application is running, COM+ manages the
pool for you, handling the details of object activation and reuse
according to the criteria you have specified. In order for
components to be pooled, they need to be stateless, have no thread
affinity, and be aggregatable. This means that VB components cannot
be pooled, since they have a thread affinity, while properly written
C++ components can. |
Transaction Manager
Microsoft Component Services can function as a transaction manager for
components. We will look at transactions in detail in Chapter 19. In
managing a transaction for an application, Component Services will examine
the components participating in the transaction to see what their
transactional requirements are. Some components are quite happy to ignore
whatever transaction is going on, while others want to or need to
participate in a transaction. When a component is developed and deployed,
the developer will set this transaction parameter for the component.
Component Services will use that information to determine how the
component should participate in the transaction, if at all.
Component Manager
In addition to managing components in their interactions with
transactions, Component Services can also manage the components
themselves. While this functionality was part of MTS, it was generally not
what came to mind when looking at the features of MTS. Component Services
uses the context of a COM+ component to help manage it during its
lifetime.
A context is a set of run-time properties maintained for a collection
of one or more objects. Each object is associated with precisely one
context during its lifetime. Multiple objects can run within the same
context and multiple contexts can reside within the same COM apartment.
Context properties allow Component Services to provide run-time services.
These properties hold state that determines how the execution environment
will perform services for objects within the context.
Security Manager
Component Services provide a number of security features for your COM+
components as well. There are automatic security features, which are
available without adding one line of code and are configurable
administratively. Other security features can be integrated directly into
the development of the component. Role-based security, which can be
implemented programmatically or administratively, is the central feature
of COM+ security. It allows for security down to the method level of a
particular component, allowing all users to access a component, but
restricting certain methods of that component to certain users.
Data-Centric Components
The bottom tier of our three-tier architecture is the data access
layer. This layer is responsible for integrating with the data sources
that our application needs to be able to function. These data sources
could be SQL Server or Access databases, Exchange message stores, MSMQ
message queues, or UNIX legacy applications. They could exist on the
server itself, on some other server on the LAN, or somewhere across the
Internet. The data component is not only responsible for encapsulating the
access to the data, but also for making the location of that data
transparent to the application as well. All that the application needs to
do is instantiate and use the component – the component itself figures out
the rest.
Why use them?
There are a number of reasons why data-centric components are necessary
portions of a three-tier, and therefore a Windows DNA application.
Obviously, without a data layer, we would only be left with a two-tier
application. But seriously, there are many reasons why encapsulating data
access within a component leads to a more robust application.
| • |
It shields the developer from the inner structure of the
database
This encapsulation is a primary tenet of object-oriented design.
If the internal workings of a component are not exposed to the
developer using the component, then these inner workings can be
changed, updated, enhanced, or replaced depending on the changes to
the physical data store below them. It also means developers cannot
circumvent security or procedures by changing rows in the database
in an incorrect order, etc. |
| • |
It provides consistent data access to different data
sources
By encapsulating the access to disparate data sources in a common
interface, developers can use similar methods to access data
regardless of where the data actually resides. This means that
access to data stored in a SQL Server database can be accomplished
using the same methods as data stored in a flat file on a UNIX
system. |
| • |
It makes the location of the data transparent
With the method to physically access the database encapsulated
within the component, the location of the data does not matter to
the user of the component. They merely access the component, and the
component makes the necessary connections to the data source to
retrieve the data. |
Business Components
The middle of our three tiers is the business component layer –
sometimes referred to as the business logic layer or the application
layer. No matter what it's called, its job is to provide the functionality
for the application. This could mean managing a shopping cart for an
e-commerce application, validating the benefits selection of an employee
on the HR section of the intranet, or calculating the best route between
two locations in a mapping application.
A business component is designed to hide the complicated interactions
that a set of business rules need in order to process and also to shield
the user interface designer from having to know anything about the
underlying data. They simply interact with the methods of the business
components to present information entered by the user and interpret the
results of the component's processing.
Why use them?
Whereas data components are generally the most commonly used of the
three component types in the n-tier architecture, there are also a number
of compelling reasons to use business components as well. Some of these
reasons are similar to, or even identical to, the reasons for using data
components:
| • |
Business Rule Encapsulation
By encapsulating business rules inside a component, the developer
using it does not need to worry about how the rules are actually
processed. The component has a set of well-defined interfaces that
the application developer will interact with. What happens inside
should not matter to them, as long as the component delivers the
proper results. |
| • |
Application Reuse
By encapsulating business logic within components, it makes it
much easier to reuse that business functionality in multiple
applications. For example, a business could have one component to
calculate commissions on sales. This would allow any application
that needs to calculate commissions to do so using the same
component. All commissions would be calculated in the exact same
way, since the same component was used to calculate it. |
| • |
Performance
In developing Web applications, it is very straightforward to use
script to create the business rules of the application. This makes
it easy to get an application up and running quickly. However,
scripting not only violates the first two reasons that we have
already mentioned, but it can also cause performance problems as
well. Since script is interpreted every time it is run, and a
component is executed from compiled code, the performance of the
script cannot begin to match the performance of the compiled
component. |
User Interface Components
The final layer of our Web application is the user interface layer. It
is in this layer that the information generated by the middle tier of the
application is presented to the client. How it's presented is generally
based on a template in HTML or DHTML to which dynamic information is
added. In some instances, the business logic may even select which
presentation template to display too.
There is a lot of debate about the encapsulation of the user interface
creation code into a component. Since ASP script can be embedded within an
HTML page, it is very straightforward to use ASP script to insert the
dynamic values into an HTML template. If that information is part of a
compiled component, then it makes it very difficult to change the
presentation without recompiling the component.
Why use them?
There are a couple of occasions where a user interface component could
make sense for an application. They are generally related to making
repetitive tasks easier for a developer, such as displaying a menu, or
where script alone cannot generate sufficient performance. For each one of
these reasons, there are other, non-compiled, methods that can be used to
nearly duplicate the capabilities of the component-based UI, without many
of its drawbacks:
| • |
Repetitive Presentation
There are usually certain parts of a Web application that are
repeated in a number of different pages – possibly with different
information. A frameless Web site that is trying to replicate a
framed look-and-feel generally has to recreate parts of the page
over and over again. This presentation could be encapsulated into a
component, which would make implementation by a developer quicker
and present a more standardized appearance. However, similar
functionality could be accomplished through the use of an include
file containing methods capable of rendering the information to the
browser. |
| • |
Performance
Performance is always a big issue when it comes to building
scalable Web sites. The more performance we can ring out of any
aspect of the application, the better the application as a whole
will perform. Encapsulating complicated presentation logic within a
compiled component will allow the site to perform faster, but at the
trade-off of limited flexibility to change the presentation without
recompiling the component. Another method, which was covered in
Chapter 3, is to store repeated HTML blocks as strings in script,
and then store that script in an application-level variable. This
gives the performance of compiled code without sacrificing the
flexibility of ASP and HTML integration. |
Component Application Design
In building a component-based application, we need to look first at how
to design an application that will use components. This will include both
a process for breaking the application down into its components as well as
how to design the actual components themselves.
Once we're comfortable with that, we must carry on to look at several
issues related to building component-based applications for the Web.
Specifically, we must address the design of our components and the
interfaces we choose to expose in them, how we will tie out components
together and the tools we'll use to implement all of the above.
Moving to Components
As we begin to move our application from a traditional monolithic or
client/server application, we need to first look at how to break the
application functionality into components. This is known as
decomposition and can be done in a number of different ways. There
are many books available on various object design methodologies, so we
won't go into a detailed discussion about them here. The key thing to look
for in selecting, or creating, a methodology is that it fits in with your
manner of doing business, and also does not radically alter your existing
development processes, unless you are not happy with the way things are
being done now.
There are many advocates for each methodology, but it is up to you as
an application designer and developer to select the one that best meets
your needs. And if you can't find one that you like, then you should feel
free to take parts of existing ones and create your own. As long as you
can deliver a design that not only allows you to create an effective
application, but also provides a roadmap for others to understand your
application, then you have an effective design methodology for
yourself.
As we begin to decompose our application into components, the first
step is to partition the functionality of the application into the three
tiers that make up a component-based application. A good way to begin is
to look at each part of the application, and determine which tier it
belongs in. If you're finding it difficult to select a particular tier for
a piece of the application to fit into, chances are you're not splitting
it up into small enough pieces. At this point, it is time to decompose the
element you are currently looking at into multiple parts, with the goal
that each part will fit nicely within the presentation tier, business
logic tier, or data tier.
As these components begin to fall into our design, we still need to
maintain some semblance of an application in our minds.
If we don't remember to do this at this time, then when it comes time
to wire the components together at the end, the chances are we will have
strayed from the application design as a whole. But by keeping in mind
what the final goal of the design is, then the components we end up with
will readily tie together into an effective application.
Application Design
The application design is important in building a component
application. Without a specified set of application requirements, it will
be very difficult to create the components to support the application. In
designing the overall application, there are a number of methodologies
that can be used. For example, in the Use Cases approach, the application
design is created by defining how the application will be used in specific
instances.
Whichever method is used when we are designing a Web-based application,
there are a different set of challenges that must be overcome that are not
present in a traditional application. First and foremost, we as
application designers have limited control over the tool that a person is
using to access the application. Unless we have a tightly controlled
intranet application, the chances that people will be accessing the site
using different browser types and versions are quite high. This means that
our application has to be designed to support this wide range of
presentation types.
Internet-based applications are also usually accessed through a slow
connection, such as a 33.6k or 56k modem. This has two primary
implications in the design of the application:
| • |
First, the file size of any graphical images, including those
images that make up the user presentation tier, must be such that
they can be transmitted quickly to the client. An application will
quickly lose its usability if the person using the application is
continually waiting for the application to download images. Images
in a Web-based application are fine, and provide many great
benefits, but if they negatively affect usability, then another
method of communicating graphical information to the user must be
found. |
| • |
The speed of the connection also means that every interaction
with the server is going to take some perceptible length of time.
This pause between interactions will have an effect on the perceived
usability and performance of the application. If this delay becomes
too long, or happens too frequently, then the performance of the
application will be more negatively perceived. Thus, as the designer
of a Web-based application, you need to be aware of the number of
"round-trips" that you make between the server and the client. A
system running solely over a higher-speed intranet can survive a
greater number of "round-trips" than a system that relies on the
public Internet in order to function. |
Designing Components for the Web
In addition to some overall design concepts for Web applications, there
are also some specific component design criteria that should be followed
to produce an effective Web application. As applications on the Web need
to be able to scale to handle large numbers of users, without causing a
corresponding decrease in performance, the components used to build the
application need to be able to support these requirements as well. With a
Web-based application, there is also the challenge of creating an
application that has the concept of a "user session," where a series of
discrete user requests are treated as a single interaction with the
application. Though there are multiple tools for maintaining user
sessions, such as the Session object, the application designer needs to
understand how the use of these tools affects the performance of the
system.
Stateless Components
If you go back and look at the basic definition of an object, it is
generally given as a set of code and data treated as a single unit. By
combining the data with the code of the object into a single package,
multiple instances of the same object can exist at the same time, and can
be used to represent different pieces of information. This is a very
effective design for client/server applications, where an application can
create objects that represent a specific entity within the application,
and then through the interface of that object, have it perform the
functions of the application. Since the object itself knows about the data
it contains, it can perform these functions without the need of another
source to provide the data.
This also means that a particular instance of an object is explicitly
tied to the data that it contains. There is no way for that object to
represent itself as holding different information if it needs to
participate in a different interaction. The only way for that to happen
would be for the system to create a new instance of that object and load
it with the required data to perform the interaction. The strength of
object-based applications is that the application simply knows that it
interacts with a certain type of object – the specifics about the
information contained within the object is of no concern to the
application. The drawback is that we now need two objects to represent our
two different pieces of data.
In applications that are supporting a single user, or a limited number
of users, the creation of new objects to represent new items of data will
generally not degrade the performance of the system. But when we start
dealing with Web applications, that are supporting hundreds or thousands
of simultaneous users, the creation of multiple objects for each
user will have serious effects on the performance of the system. Luckily,
our n-tier model for Web-based applications affords us a unique
opportunity to address this issue.
Since each request that a client makes of a Web server is treated as a
unique connection, there is nothing binding the server to the client in
between requests. This means that while the user is viewing a fully
downloaded page of the application in their browser, even if they are
interacting with information on that page, the server does not have to
perform any processing for that particular user during that time. It is
free to go off and work with other users.
But what if the first user has created some objects that are uniquely
linked to that user? The server has to make sure that these objects are
maintained so that the next time the user comes, they will be readily
available for that user to use. This means that server resources will be
tied up just waiting for the next request to come in. If you extend this
out by hundreds or thousands of users, you quickly see a lot of objects
sitting around, chewing up server resources, waiting for the next request
to come in. So what is the solution?
If a component can be designed so that it can perform the same type of
work, but yet doesn't need to maintain any information within the
component to perform the work, then it could be discarded after every use.
Or if the component could be developed such that COM+ could pool the
component, it would just be returned to the component pool. There would be
no need to hold onto a reference to that object while the user is off
working with the client page. The resources that were being consumed by
the object can be returned to the server. By quickly freeing up resources
in this manner, the number of users that the application can support at
any one time will grow dramatically.
If a component does not carry any information around within itself, it
is said to be a stateless component. A stateful component
therefore is one that is said to hold information internally from one
client interaction to the next. There are a couple of ways of making a
component stateful in your Web applications. Conversely, by not doing
these things, a component can be made stateless, and thus more
scalable:
| • |
Saving a reference to a component from one page to another, by
storing its reference in a Session-level variable, will cause a
component to hold state. |
| • |
Setting a series of properties in a component, and then calling a
method to perform some interaction, will cause the component to hold
state. Passing all of the parameters to process a method as
parameters will help to minimize the statefulness of a
component. |
Sessionless Applications
Another design criteria that we need to worry about when designing Web
applications comes from the inherent stateless nature of the Web. As we
mentioned earlier, once a server completes a client's request, it forgets
all about that client. This means that as far as the server is concerned,
that client has no past and no future with the application. Generally, an
application consists of a series of steps that must be linked together in
order to fulfill its tasks. If the server keeps forgetting about the
client in between each step, it makes the design of the application that
much more difficult.
When the application platform only supports sessionless applications,
as a Web server does, we have to maintain the state of the session
elswhere. There are a number of facilities that can do this for us, but
each one has its effects on the scalability of the application. Step
number one however is for a client to identify itself to the application
each time it makes a request.
This identification could take the form of a cookie passed from the
client to the server, a hidden FORM element that contains a unique
identifier, or a parameter appended to the URL when the request is made of
the server. In any case, this number must correspond to some information
on the server that is unique to the client. This number can be a reference
that points to an object with all of the session information in it. It
could be a primary key into a database table that is holding the session
information. It could also be an indication that there is other
information in the request from the client, either in form fields, URL
parameters, or cookies, which contain the state of the current
session.
To put it succinctly, the three ways to maintain session information
are:
| • |
Storing data in the Session object |
| • |
Storing data in a database |
| • |
Passing information between pages via the Request object each
time a new request is made |
Each of these methods has its advantages and disadvantages. The method
that you choose for your application should be based on which has the
least impact on the performance, scalability, and usability of the
application.
When information is stored in the Session object, it can be quickly
retrieved, but it means that the information is local to that particular
server only. If the application is being scaled through the use of a Web
farm, then this session information will only exist on one machine within
the farm. If a user wants to access their session information, then they
must be directed back to that same server each time. As this prevents
balancing the usage of the server based on load, it can lead to some
inefficiencies in the scalability of the application. On the other hand,
accessing and using the Session object is quick and it is a
well-documented method of providing session information.
Storing information about a user session in a database means that
multiple machines within a Web farm can access it. In this way, the client
is not tied to a particular server and the Web farm can operate much more
efficiently. The drawbacks of this method are that the retrieval of
information from the database is orders of magnitude slower than
retrieving information from the memory space on a server. There is no way
to store an instantiated object within a database, as you can do in the
Session object. Finally, there is no easy-to-use interface like the
Session object through which to access the information.
When you use the client to store session information, you are removing
the burden from the server having to maintain that information. By
reducing the processing requirements of the server, you lessen the number
of resources it requires, which in turn increases the number of users the
server can support with the same resources. The drawbacks of this method
include the lack of common interfaces to handle information passed in this
manner, the strain put on the network connection in requiring that this
information be passed back and forth during every request the client makes
of the server, as well as relying on the client to pass you information
that is vital to your application functioning correctly.
In choosing the method for maintaining the session state of an
application, you need to examine each of these possibilities and choose
the one that best meets the needs of your design. As with any system, you
can also choose to use a hybrid that combines elements of these three
choices. For example, if one part of your application is best solved by
having a stateful component used by two pages, then a reference to that
component can be stored in the Session object to pass it from one page to
the other, and then destroyed once it is no longer needed. Note however,
that you will need to abide by the component design issues involved with
component scope that will be examined in Chapter 15. Meanwhile, all of the
other state information about the application session could be being
stored in cookies and hidden form fields. In this way, the three different
methods are complementary, rather than exclusive.
Component Design
There are two key aspects to the design of a component. The interface
of a component is how it communicates with the outside world, and is the
only way that the outside world can work with the services provided by the
component. We also need to look at where the component is physically
located, which will determine how it can participate with the other
components that comprise the application.
The Component Interface
The component interface is the mechanism by which the component
interacts with the rest of the world. It is designed to provide access to
the information and the functionality supported by the component. The
interface is the only way that other components or applications can
interact with the functionality within the component. The interface is
comprised of the public properties and public methods of the component.
Any private properties or private methods of the component will only be
accessible from within the component, and therefore cannot be access via
the component's interface.
We will be looking at COM and interfaces in much greater detail in
the next chapter.
When designing a component's interface, we need to support the other
aspects of the component design that we have already looked at. Namely,
the design of the interface will directly lead to the statefulness or
statelessness of the component. If we create a component interface that
relies on properties being set before the component can perform any
functions, then we are creating a component that is holding some internal
state for some length of time. It will also require multiple calls into
the component – some to set the properties, and then one to execute some
action. You can see from this code sample the number of times we would
have to call into the component: <%
Dim obj As Server.CreateObject("MyComponent.Test")
obj.Property1 = 123
obj.Property2 = 234
obj.Property3 = "abcd"
Call obj.Method1()
Set obj = Nothing
%>
If we were to design this component interface such that the method call
carries with it the values that it needs to perform its function, then we
will have a much more stateless component. There will only be one call
into the component to process the function, and no internal information
will be stored within the component. If we created another method called
Method2 to achieve that, a call to it might look like this: <%
Dim obj As Server.CreateObject("MyComponent.Test")
Call obj.Method2(123, 234, "abcd")
Set obj = Nothing
%>
As you can see, the new interface only requires one call into the
component before the component can be released. This is in comparison to
four calls into the component in the previous example before it could be
released. And in terms of the effect on scalability, the sooner we can
release a component, and let the system have its resources back, the more
scalable the system will become.
Component Location
In addition to the interfaces that a component supports, the physical
location of the component can also affect the scalability of the
application. As our application interacts with its components, it will
want to do so in the fastest and most efficient way possible. Any time
wasted in creating a communication channel with a component will be more
time during which the performance of the application is slightly worse
than if the component was not being used. You always need to remember when
trying to make applications highly scalable, to take any increase in
processing time or increase in resources usage and multiply it by at least
the projected number of concurrent users. Once you do that, it becomes
plain to see how a minute change in resources usage or time can begin to
cause serious problems.
We want to make sure that the interaction between our ASP scripts and
our components, and between our components, happens in the quickest and
most efficient way possible. This generally means that the component
should run within the same process as the ASP application. In the next
chapter, we will look at how COM+ enables you to administratively change
where a component actually executes. As with all potential speed
improvements, running your component in the same process as your ASP
application, while faster, also makes it more likely that a problem with
your component could affect your entire ASP application. When a component
is run within the same process as the ASP application, then all calls into
the component will be done using direct function calls. This is the
fastest way to access the component.
If we run the component in a different process, then any information
that is passed between the component and the application must cross the
process boundary to get from the application to the component. In the
Win32 environment, this is a resource and time intensive operation. It
will take more system resources to make the call, and it will also require
more time. This happens in both directions in the conversation between
object and application as well. So any information, such as method
parameters, that is passed from the application to the object will have to
be marshaled across the process boundary. On the return trip, any
information that the object wishes to send back to the application, such
as a return value, will need to be marshaled as well.
We can also utilize the DCOM capabilities of the Win32 environment to
execute our components on a different physical system than the one running
the application. Even though this connection happens transparently to the
application, there are still major performance penalties to be paid.
Everything that was mentioned about accessing components running in a
different process holds true with DCOM components but more so – the time
it takes for client and server to communicate is greatly increased. This
is especially true as latency increases when you move off of a LAN and
onto a WAN or the Internet. You need to be very careful if you want to use
DCOM components in your ASP application as a result of this.
Tying the Components Together
Once you have constructed all of the components for your application,
you need a way of tying these components together. Without some sort of
glue that tells the components how to interact with each other, you really
don't have an application. You can use other components to serve as the
glue that holds your components together, but in practice this makes
constructing an application as difficult as constructing a component. One
of the advantages of a component-based application is that you can quickly
wire together a set of components to create your application. So to
facilitate this, we can use ASP scripts as the component glue in
our application.
On the system that is hosting your application, you will naturally need
Active Server Pages installed. The system with ASP installed on it now
becomes more than a Web server – it becomes your Application server. And,
in order to serve your Web applications to clients, it will need to access
the components that you need to build the application.
There are two types of components that can be used to build an
application. Those you have custom-built and installed on the server for
the application and those components already existing on the server, be
they by Microsoft, yourself or some other third party.
Reusing Existing Components
When reusing existing components, you must first make sure that your
use of the component does not break any other applications that are
relying on the component. For example, if you were to update the component
to a newer version to support your application, you could potentially be
breaking an existing application that was relying on a particular version
of the component. Also, if the component relies on registry settings to
hold its configuration, and you change those settings to suit your
application, then other applications using the component may no longer
function. Note however, that none of the above should happen if you follow
basic interface development guidelines.
The easiest way to see which other ASP applications are using the
component is through the use of a simple text search routine, such as
GREP, or the Find in Files function of Visual InterDev. Since all ASP
script code is in a text format, you can simply search through all of the
.asp files on your application server for the ProgID of the component that
you are going to reuse. This will help you directly pin-point any
applications using your component. You can then make provisions to test
those applications when you make any changes to the component's
configuration.
Installing New Components
There are a few ways to install newly created components onto your
application server.
One option is to take the file containing your component – typically a
.dll file – copy it to the server and then register it with the operating
system. By doing so, sufficient information is place in the system
registry to allow applications to reference the components and have the
system know which component it's referring to. Installing components in
this way, however, does place the onus on you to make sure that all the
files the component depends upon are also present on the server. Without
them, the component will be unable to function properly, and could
possibly not even be registered properly.
A second way is to first build an installation program on the
development machine, copy it to the application server, and then execute
it. This is usually a foolproof method of ensuring that the dependencies
for the component are installed properly alongside the component. One
downside of this method, though, is that it requires a physical
interaction with the console of the Application server. Also, if the
installation program does not take into account the proper versioning of
components, it can very easily overwrite a version of an existing DLL with
a version that causes other applications to not execute properly, or even
cause the server to crash.
A third method is through the use of a COM+ application. A COM+
application, as we mentioned earlier, consists of a set of components that
the Microsoft Component Services manages as a single group. In Chapter 15,
we will take a look at both how to create a COM+ application, and how to
move that application from one application server to another.
Building your Components
All this talk about building components to encapsulate business logic
or data access logic has hopefully laid the groundwork for you to build
your own components. Well, the first thing you need to know is what tools
you can use to create your components. That is one of the strongest points
about COM – it is language-neutral. This means that you can create your
components using nearly any language you choose. And not only are you free
to select a language, you are also free to choose from a wide variety of
tools with which to write your components.
Tool Selection
There are many development tools available on the market for you to
create components with. The list includes:
| • |
Microsoft Visual C++
This tool creates the highest performing, lightest-weight
components possible. By utilizing the Active Template Library, some
of the intricacies of component creation are taken care of. But all
of this performance comes at a price. This is generally considered
the most difficult way of creating components and has the steepest
learning curve. We will take a look at using Visual C++ in Chapters
17 and 18. |
| • |
Microsoft Visual Basic
At the other end of the spectrum, Visual Basic is one of the
easiest tools to use to create components. These components don't
necessarily have the optimal performance that C++ components do, nor
do they have their flexibility. That being said, most benchmarks
have shown that a VB component, when designed and used properly,
performs at about 90-95% the speed of a C++ component. What they do
have is the ability to be created quickly and easily by a wide group
of developers. We will be looking at creating components in Visual
Basic in the next chapter. |
| • |
Windows Scripting Components
Microsoft has extended the world of component creation to
scripting languages as well. By adding an interface definition
written using XML, we can now create components using the exact same
tools and code that we use to create our ASP scripts. We'll see more
of this in Chapter 16. |
Component Testing
After creating a component, the most important step prior to using the
component is testing it. A component needs to be tested not only to ensure
that it is performing the operations that it was designed for, but that it
is not adversely affecting the rest of the system. There are three types
of testing that you can perform on the component.
| • |
Functional Testing – This type of testing ensures that the
component works as advertised. Testing of this nature is generally
done by applying a set of inputs to the component for which the
proper outputs are already known. The outputs generated by the
component are compared with the known outputs, and any discrepancies
are resolved by changing the functionality of the
component. |
| • |
Stress Testing – To make sure that the component is not
adversely affecting the systems resources, it can be tested under
stress. This is usually done with a testing tool, such as WAS or
WCAT, which simulates a large number of users accessing the
component simultaneously. During this testing, the system resources
are monitored to ensure that there is not any excessive resource
utilization of the component. |
| • |
Integration Testing – Integration testing looks at how the
component interacts with the other components that are going to be
making up the application. This is done to make sure that there are
no issues, such as contending for the same resources, or relying on
different versions of the same DLL in order to
function. |
Once this testing is complete, the component is then ready for
installation onto the Application server, and then for integration into
the application.
An Application Design Case Study
In this chapter, we have looked at a lot of theory concerning the
creation of n-tier Windows DNA applications. This theory should have
covered all the bases necessary to create a component-based, scalable Web
application. The problem with just theory is that it is just that –
theory. It is the practical examples that the majority of us developers
like to work with. Yeah sure, give me the theory, but enough already and
show me how it's done!
In this section we will do just that. With all of the theory on our
plate on creating a Windows DNA application, let's put it to work to
actually build one. Well, that's a bit presumptuous, as we still need to
look at actually coding the components of the application. So, in this
section, we will see how to design a Web-based Windows DNA
application:
| • |
First, we will define the problem that we are going to create the
application to solve. This is generally the most important, but
usually the most neglected step in the design phase. |
| • |
After defining the problem, we will look at the design of the
application. This design will include the component architecture and
the interfaces presented by the components in the
application. |
| • |
Finally, we will look at any design tradeoffs that we were forced
to make and how these tradeoffs will affect the scalability and
extensibility of the application. |
Defining the Problem
WhizzyBang.com, like all small but growing Internet companies, is
dealing with the administrative hassles of continually adding new
employees, employees changing roles and titles, and people spread
throughout the world. These challenges have made it difficult for
WhizzyBang.com to maintain a working human resources support system
without driving the poor HR employees crazy. They have decided to stop
being cobbler's children, embraced the Internet as the way to do business
and created a Web-based human resources information system.
This human resources system will initially need to support the
following functions:
| • |
The hiring manager is responsible for the initial creation of the
employee's record. |
| • |
The human resources manager must validate the information and
process the proper government paperwork for the employee. |
| • |
The employee will need to use the system to select their health
care benefits. This can be used by either new employees or by
existing employees. |
Since the information in this application will be used by other systems
as well as the human resources system, it will need to be stored in a
centralized system. Other information will be required to be sent to
certain agencies outside the company. The data being used by the
application is stored in the following systems:
| • |
The employee database is stored in a SQL Server 7 relational
database. |
| • |
The health care selection information is stored in an Access
database. |
| • |
The government paperwork is delivered to a processor via an
XML-formatted e-mail transmission. |
The users of this application will be located in locations throughout
the country/region. They will all have Virtual Private Network (VPN)
access to the corporate network, but this connection is only over a 128k
ISDN line between the data center and the VPN provider. A VPN allows the
users to dial up to the public internet and then tunnel through the
corporate firewalls to reach servers within the company. The VPN is
configured to allow only the HTTP protocol to pass.
The systems to run the application will be hosted at a centralized
site. These systems will be dedicated to this application, but the
databases that the application will access will be on separate systems.
The users of the application will have Microsoft Windows 98 and 2000
workstations. The application will only be accessible when the
workstations are attached to the corporate network. The application should
always check for the latest version when executed by the user.
Design Implications
Now that we understand the high-level requirements of the application,
we can take a look at how some of these requirements will affect the
design of the application. This is critical to examine at this point. If
we were to design the application, without looking at the implications of
the requirements on the design, then we could design an application that
was difficult or impossible to implement or use.
In looking at these design implications, we will want to understand
certain aspects of the implications. First, we need to know if there are
certain requirements that are mutually exclusive to one another. For
example, if one requirement states that the system must be accessible by
disconnected laptop users, and another states that only HTTP access is
allowed, we have a dilemma. Since HTTP access is only available as a
connected protocol between a client and Web server, we have two
requirements that are in conflict with one another. The requirements will
need to be changed in order to support the realities of the system.
In looking for design implications, we will also look at those aspects
of the requirements that are very precise, such as the type of database
used by the employee database. These very specific points must, by
definition, be carried directly to the final design. Those requirements
that are more general, such as the types of workstations used by the
clients, allow us more flexibility in the design of the application.
In an initial pass at the requirements, the following can be identified
as design implications:
| • |
The workstations will support a Win32 application, but the
requirement that the application be self-updating implies that a
browser-based application will be easier to support. In a
browser-based application, the latest version of the application is
always available by the client. |
| • |
The databases that the system will access both have OLE DB
providers, so we can utilize ActiveX Data Objects to interact with
the database. |
| • |
The human resources manager provides a validation step to the
creation of a new employee, so there needs to be a notification
mechanism to tell this user that a new employee is in need of
validation. |
| • |
Since the same application will be used for both new entry and
update of benefits information, it should support both a guided and
interactive interaction with the data. |
By recognizing these implications, we can guide the design towards the
path of least problems when creating the application, and away from
choices that are impossible to implement. It also makes the actual design
process less fraught, more straightforward and more efficient. We can
always refer back to these implications, as well as the requirements, to
ensure that our design is moving along the correct path.
Application Design
Now that we have established the application's requirements, and taken
account of the resulting implications, we can now get to work on designing
it. At this point we have a number of directions in which we can proceed
with our design exercise. There are almost as many application design
methodologies as there are books on Active Server Pages. The design
methodology that you choose to work with may be one that is thrust upon
you by your employer, one that you have used in the past, or one that you
have looked at and seems interesting. However you select a design
methodology, and whichever one you select, you will eventually end up at
the same point – the design of an application.
You should take into account the size of the application development
effort when choosing a design methodology. Are you going to be the only
developer working on this application? Will you or another developer ever
have to extend and enhance the application? Does your application have to
integrate at the component level with other applications? These questions
and others need to be asked so that you can determine if the methodology
you are using is compatible with the environment your application has to
work in.
For this example, we will not subscribe to a particular published
methodology, such as UML or Use Cases. As a lot of developers have found,
the published methodologies are great in theory, but when it comes down to
actually creating an application design in the real world, the methodology
that works best is usually a hybrid that meets the unique needs of the
application. In our application design methodology, we will be concerned
with five aspects of the design:
| • |
Component Architecture – How the components in this
application are partitioned across the logical tiers, and how these
components work with one another. |
| • |
Data Tier Interface – This describes both how the data
components logically integrate with the physical data stores as well
as how they are accessed by other components in the component
architecture. |
| • |
Business Tier Interface – This describes how the
presentation tier accesses the business components and which data
tier interfaces each component works with. |
| • |
Presentation Logic – This describes the various visual
interfaces that the user will be interacting with in order to
perform the functions specified in the application
requirements. |
| • |
Integration Architecture – The integration architecture
specifies how the components of the application will be tied
together. This will cover the physical location of the components,
the packaging of the components into applications, and the
mechanisms that the components will use to communicate with one
another. |
The design methodology is primarily concerned with the interfaces of
the components of the application, and how these interfaces are tied
together to create the application. The interface of a component specifies
the information that the component will provide based on inputs provided
by a caller. The internal workings of a component are left up to the
developer to implement. As long as the component interacts with its
interfaces in the way specified in the design, the component can be
considered a black box. With components designed in this way, the
primary integration task is to tie the components together, which is the
final step in the design.
Component Architecture
The component architecture of the WhizzyBang.com human resources
application will define the components that make up that application, as
well as how these components are tied together. The component architecture
provides the glue between the presentation layer and the actual data. In
this diagram, we can see the role that the component architecture will
play in the application:
The component architecture in the application represents the business
logic components as well as the data access components. These components
will have their interfaces defined later, so for now we need to decide the
various objects to create. Generally, object decomposition will allow you
to begin with a loosely defined object and break that object into its
component objects until you reach a more discrete size. First, let's take
a look at the data objects.
In this application, there are three primary data sources. These three
data sources are the SQL Server employee database, the Access benefits
information database, and an e-mail box for sending tax information. The
SQL Server database is unique in that it is used for both the retrieval of
information as well as the storage of information. The employee's
information is initially created by the application and stored in this
database and then it is retrieved and used in the application. The
information in the benefits information database is used in a read-only
capacity by the application. There are no requirements in the application
to write information to the benefits database. The tax information
repository is exactly opposite, in that it is a write-only data source.
This means that once information is written to that data store, it can no
longer be retrieved by the application.
These three primary data sources can correspond initially to three
objects. To begin with, we can refer to these as:
| • |
The Employee component |
| • |
The BenefitsInfo object |
| • |
The TaxInfo object |
The Employee component will be responsible for the interaction with any
data inside of the employee database. Since this database contains
different types of data, such as name and address information, dependent
information, and benefits selection, it probably makes sense to have
multiple objects to access this single physical data store. The process of
breaking the Employee component up into a more granular set of objects is
known as object decomposition.
In our example, we will decompose the Employee component into three
separate objects. We will also choose an object-naming schema that will
relate these three granular objects back to the original Employee object.
The name and address information will be accessed via the EmpInfo object.
The dependent information via the EmpDependent object, and the benefits
information via the EmpBenefits object. As the BenefitsInfo object and the
TaxInfo object are already somewhat granular in their nature, we will not
decompose these objects into multiple objects.
The business tier of the application needs to deal with the creation
and validation of an employee record and the selection or modification of
employee benefits. The employee information creation section needs to
enforce certain business rules on the information to ensure that the
information is added correctly to the database. In this case, we can see
the separation of functionality into the data object being only
responsible for the access to the information, and the business logic
serving as the enforcer of the business rules.
We will create three primary business objects to work with the
application. The NewEmployee object will process the business rules
related to the creation of a new employee record by the hiring manager.
The EmpValidation object will be used by the human resources manager to
validate the information related to the new hire, and then to process the
proper taxation information. The final business object will be the
Benefits object, and it will be responsible for enforcing the business
rules regarding benefits for the employee.
As you can see, we have closely related the business object composition
to the required functionality of the application. This allows for a closer
interaction between the business rules and the presentation logic, which
will reduce the number of objects needed to process a given part of the
application. By reducing the number of objects that are involved in the
application, we can increase the scalability of the application, since
fewer resources will be needed by each application session.

You can now see that the business component architecture that connects
our presentation logic with our physical data storage contains a set of
eight objects. In the next two sections, we will apply the interfaces to
the objects so that they can communicate with one another, and with the
rest of the application.
The Data Tier Components
The data tier components are comprised of the interfaces of the five
data access components. These components provide access to the data used
by the application. The data interface will determine the methods in which
the business components will interact with the data components to both
retrieve and set information.
These components will also have an interface to the physical data
itself, but the definition of this interface is not critical to our
application design. The constraints of the methods of accessing the
physical data, along with the specific information required to support the
data tier interface, will determine how this interface to the physical
data store is actually created. This physical interface is also driven by
the system that the data is stored in. For the database information stored
in the SQL Server employee database, this information will be accessed
using the SQL Server OLE DB provider. The data for the benefits
information, stored in an Access database, will be retrieved through an
ODBC connection. Finally, the data transfer requirements needed by the
TaxInfo component, since this data is transmitted via e-mail, will be
performed using an SMTP mail object, like the Collaboration Data Objects
(CDO).
The external interface for these components is important in that this
is the manner in which the object is accessed by the rest of the
application. Once this interface is defined, the business objects that
need to retrieve or set business data can call through these interfaces to
interact with the data that they need. The business objects will in turn
expose an interface to the presentation logic.
For our five data objects, we will define the following methods to be
available through their public interfaces:
| • |
BenefitsInfo object
GetBenefitsForClass, GetBenefitInfo, GetBenefitOptions |
| • |
EmpBenefits object
AddBenefit, CheckBenefitStatus, GetBenefitList, RetrieveBenefit,
UpdateBenefit |
| • |
EmpDependents object
AddDependent, GetDependentList, RetrieveDependent,
UpdateDependent |
| • |
EmpInfo object
CreateEmployee, DeleteEmployee, EmployeeStatus, EmployeeClass,
IsEmployee, RetrieveEmployee, UpdateEmployee |
| • |
TaxInfo object
SendTaxData |
These interfaces are defined to provide access to information stored
within the data sources of the application. All will be through these
objects' methods. If a business object, or a user presentation, needs to
interact with the data sources to access information for display, or to
update information, it must be through these methods.
The Business Tier Components
Now that we have defined how our application will be able to access
data, we need to define the components that will allow the presentation
logic to get access to the data in a way that is consistent with the
business rules of the application. We have defined three business objects
for this application – NewEmployee, EmpValidation, and Benefits – which
correspond to the primary functional requirements of the application.
The interfaces for these components will be called by the presentation
logic and will need to retrieve all the information needed for
presentation by the user interface from the data tier. It will also need
to define a way to update that information if it is changed by the user.
The internal workings of these components will be responsible for
implementing the business rules of the application. For example, it will
be the responsibility of the Benefits component to ensure that the
employee's benefits selections are valid. As with the data objects that we
looked at earlier, the actual inner workings of the component are not
important to us – as long as they perform the business logic processing
correctly.
The three business logic components will support the following
interfaces:
| • |
Benefits object
AddBenefit, AddDependent, DeleteBenefit, DeleteDependent,
RetrieveBenefitList, SetBenefit, UpdateDependent |
| • |
EmpValidation object
GetEmployeeInfo, GetValidationList, LoginEmployee, SetEmpTaxInfo,
ValidateEmployee |
| • |
NewEmployee object
AddEmployee, CheckData |
Through the interfaces we have defined here, the presentation logic for
the application must retrieve and set all of the information that it needs
to function. The three-tier architecture that we have defined means that
there is no direct access between the presentation logic and the data tier
or the physical data itself. In this way, the presentation logic is
shielded from any underlying changes in the data logic or the data
structure itself. As long as the interface to the business components
doesn't change, then the presentation logic doesn't need to be
changed.
Presentation Logic
The presentation logic is the part of the application that actually
ties into a user. This is the section of the application that generates
the user interface and then receives input from the user interface based
on the user's interactions. It is through the business component interface
that the presentation logic communicates with the rest of the application.
The user of the application will only see what is presented by the
presentation logic – there will not be any direct interaction between the
user and the database or the business objects.
The requirements for the application are such that the presentation
layer of this application is going to be a Web application. Even though
the capabilities of the client will support a Win32 executable
application, there are other requirements that would make this a
less-than-optimized solution. One of the requirements is for the
application to always support the latest business logic. This would only
be possible if every time the application requires business functionality,
it requested that functionality from a central location. While this would
be possible in a Win32 application that uses DCOM to communicate with
components on the central server, again another application requirement
prevents this solution.
Based on the analysis of all of the requirements, we have decided that
the best architecture for the application is a Web-based application,
where the user interface is presented as a series of dynamically generated
Web pages. These Web pages will be created by a set of ASP scripts that
will use COM to communicate with the business components. Each ASP page
will generate one or more Web pages based on inputs by the user combined
with information from the business components. The ASP scripts will be
grouped into three categories – roughly corresponding to the three primary
functional areas of the application.
The ASP scripts that form the presentation logic are categorized as
follows:
| • |
New Employee Information
AddEmployee.asp, AddEmployeeForm.asp |
| • |
Employee Validation
DisplayValidationList.asp, EmployeeTaxInfoForm.asp,
SetEmployeeTaxInfo.asp, ValidateEmployee.asp,
ValidateEmployeeForm.asp |
| • |
Benefits Selection
ChangeBenefit.asp, DependentList.asp, DisplayBenefits.asp,
EditDependent.asp, EmployeeLogin.asp,
VerifyEmployee.asp |
Now that we have defined the three layers of the application, we can
take a look at how these three layers are wired together.
Integration Architecture
The integration architecture is where we tie the application together.
This will specify how the interfaces of the business objects are called by
the presentation logic, how the business components will call the
interfaces of the data objects to get the information they need to
process, and where the data components go to get the information they
need. Once the integration architectu |