A book on JavaBeans wouldn't be of much use if it didn't begin by explaining the conceptual foundations of software components, which form the basis of the JavaBeans technology. Through its specific approach at providing a software component technology, JavaBeans enables software developers to design and create reusable pieces of software that easily integrate with each other, with applications, and even with development tools. If this description of JavaBeans makes sense to you, then great. If not, don't feel discouraged, because I deliberately jumped ahead by describing JavaBeans in this manner. Even though it lies at the heart of JavaBeans, the concept of a software component is not something you are expected to know going into this book. In fact, the purpose of this chapter is to start off the book on a proper footing by exploring software components and why they are important to the future of software.
The best place to begin when uncovering the magic behind software components is to look at the reason why they were invented to begin with; in other words, what problems are software components trying to solve? The most simple and direct answer to this question is software reuse, which is the challenge of leveraging as much previous work as possible in each new development project. Even though a variety of different software component approaches have evolved, until recently none have come far enough in offering a means to create fully reusable software. In this chapter, you learn a great deal about this problem and the fundamental concept employed to solve it: the software component. You learn how software components improve software development in a variety of ways, which enables developers to spend more time leveraging existing code instead of hacking it or throwing it away in lieu of new code. Most important, this chapter lays the groundwork for JavaBeans, which is perhaps the most exciting and promising software component technology available.
In this page, you learn the following:
•Problems facing the software industry
•Software component basics
•Visual and non-visual components
•Component models
In their quest to deliver feature-packed applications in a short period of time, software developers often are forced to cut corners in the midst of turning out applications. These cut corners typically result in code that is highly dependent on the specific application, with little usefulness beyond that particular project. Although this is acceptable in most cases, the end result is that the efforts put into a finished project offer little to aid in the development of future projects. In other words, it's back to the drawing board, or keyboard, for each new project. Wouldn't it be nice if you could somehow reuse similar features developed for one application in another application requiring the same functionality? Of course it would, but I'm getting ahead a little.
Regardless of how careful developers are about not cutting corners throughout a project's development, the mere size of a project often can lead to a great deal of problems. The most careful and thought-out design can lead to utter confusion when a project grows beyond a certain manageable size. In this situation, it becomes extremely difficult to make sense of a bloated application that has reached an unmanageable state of confusion and complexity. More than a few software development teams have thrown up their hands and started anew on projects after realizing that they were heading down a winding path of complexity with an obfuscated code base. Even if the code is well written, there simply are limits to the degree in which organization can help in making sense of things at the code level.
Lest you think I'm behind the times or just being overly negative and ignoring recent advances in software development technologies, let me say that object-oriented design methodologies and programming languages have come a long way toward improving this scenario. Even so, none of these languages has truly answered the need for a fully reusable software standard. As nice as C++ classes are, they still are inherently limited by the address space in which they execute, the specific protocol within which they communicate, and the platform for which they are compiled. In other words, programmers can reuse C++ classes only within the specific context of the applications they are developing, which is sometimes useful but nonetheless limiting. The same thing applies to Java classes, which are functionally similar to C++ classes, although they do add the benefit of being cross-platform in most situations.
OK, so I've painted a fairly ugly picture of the software world and left you feeling hopeless and desperate, right? Maybe not, but hopefully I've gotten the point across that there are some big problems with the way software is developed, and something must be done to improve things. Object-oriented programming languages are a huge step in the right direction, because they enable programmers to deal with objects instead of worrying about procedures and data. This fits in much better with the human way of thinking, because we all live in a world full of objects.
The problem is that object-oriented programming languages enforce an
object paradigm only within the bounds of a particular programming model
such as C++ or Java. Although this certainly enables you to reuse code
easier when you are working within the same programming language on a specific
target platform, it doesn't offer much for the wider view of software where
there are many different programming languages and platforms. The problem
is that the object-oriented idea hasn't been fully realized beyond the
code level, which is a shame.
The software world has been inching toward the idea of wide-scale reusability for some time, but no single technology has emerged that provides answers to the many problems inherent in software reuse. The reason is that a real solution must not only enable developers to easily reuse code within a particular application, but also across different platforms and even in a distributed network environment such as the Internet. Ultimately, a realistic software technology for the future must easily integrate into the client/server model, which has become standard in most modern computing systems.
In addition to these requirements, a long-term solution to code reuse
must provide an elegant solution to the existence of multiple versions
of a piece of software. As stated earlier, software is in a constant state
of change, which facilitates a need for handling multiple versions. Giving
software a path to grow and expand is a crucial point because it enables
developers to continue their endless crusade of improving on last month's
bright idea.
Software Component Beginnings
The software development community has been exploring the idea of reusable
software for a while. You might have heard reusable software referred to
under its more popular name, software components. In case you've missed
the hype, a component is a reusable piece of software that can be assembled
easily to create applications with much greater development efficiency.
Just in case you think this idea sounds groundbreaking, it is not. You
only need to look back roughly a century to see this same idea applied
to a very different type of application. I'm referring to the industrial
revolution, in which the assembly-line approach to developing and assembling
mechanical machinery was introduced. The idea as applied to software is
to build small, reusable components once and then reuse them as much as
possible, thereby streamlining the entire development process.
Although component software certainly has its merits, fully reusable software has yet to really establish itself, for a variety of reasons. Not the least of which is the fact that the software industry is still very young compared to the industries carved out in the industrial revolution. It only stands to reason that it would take time to iron out the kinks in the whole software production process. If you're like me, you'll embrace the rapid changes taking place in the software world and relish the fact that you are a part of a revolution of sorts--an information revolution.
Perhaps the hardest thing component software has had to face is the wide range of disparate microprocessors and operating systems in use today. There have been a variety of reasonable attempts at component software, but they've always been limited to a specific operating system. Microsoft's VBX and OCX component architectures have had great success in the PC world, but they've done little to bridge the gap between other types of operating systems. Weighing in the amount of work required to get an inherently platform-dependent component technology running on a wide range of operating systems, it only makes sense that Microsoft has focused solely on the PC market.
Before the explosion of the Internet, the platform-dependency issue wasn't all that big a deal. PC developers didn't necessarily care too much that their products wouldn't run on a Solaris system. Some PC developers hedged their bets and ported their applications to the Macintosh platform, but most with considerably lengthy and resource-intensive development efforts. The whole scenario changed with the operating system melting pot created by the Internet. The result was a renewed interest in developing software that everyone could use, regardless of which operating system they happened to be running. Java has been a major factor in making truly platform-independent software development a reality. However, until recently Java has not provided an answer to the issue of component software--you'll get to that in just a moment, and in fact throughout the rest of the book.
As if the platform dependency issue weren't enough, some existing component technologies also suffer because they must be developed using a particular programming language or within a particular development environment. Just as platform dependency cripples components at runtime, limiting component development to a particular programming language or development environment equally cripples components at the development end. Software developers want to be able to decide for themselves which language is the most appropriate for a particular task. Likewise, developers want to be able to select the development environment that best fits their needs, instead of being forced to use one based on the constraints of a component technology.
Therefore, any realistic long-term component technology must deal with
both the issue of platform dependency and language dependency. This brings
you to JavaBeans: JavaSoft's JavaBeans technology is a component technology
that answers both of these problems directly. JavaBeans is implemented
as an
architecture-independent and platform-independent application programming
interface (API) for creating and using dynamic Java software components.
JavaBeans picks up where other component technologies have left off, using
the portable Java platform as the basis for providing a complete component
software solution that is readily applicable to the online world. Before
I get carried away, let me stop and mention that you have the rest of the
book to worry about the details of JavaBeans; for now, continue with software
components in general.
Visual Software Components
If the discussion of software components thus far has left you a little
confused, hopefully this section will clear things up. So far you've learned
software components in a relatively abstract sense, which can sometimes
be difficult to grasp. An easier way to understand software components
is to look at a specific subset of components: visual components. Visual
components are software components that have a visual representation that
requires physical space on the display surface of a parent application.
Parent applications are sometimes more generally referred to as containers.
You learn more about containers later, in the "Component Models" section
of this page.
Many other types of visual components are supported in visual development environments such as Visual J++. These components include checkboxes, list boxes, and text edit boxes, to name a few. Keep in mind that the visual components used in Visual J++ are limited in that they actually are based on standard Java classes. One exception to this is the use of ActiveX controls, which provide some of the advanced capabilities required of true software components. Of course, JavaBeans components are an exception as well, but I don't want to jump ahead too much at this point.
Non-Visual Software Components
If visual components sound like the ideal use for software component
technologies, understand that there are also situations in which non-visual
components can be very useful. A very popular Visual Basic control is the
Timer control, which is completely invisible at runtime. The Visual Basic
Timer control can be set to trigger an event at periodic intervals, such
as once every second. The Timer control is very useful in creating timing
loops such as those that control animations. Because the Timer control
is used entirely at the programming level, there is no meaningful reason
to provide a graphical view of the component at runtime. The nice thing
about the Timer control is that an application using the control doesn't
have to be concerned at all about how the control is implemented internally;
the application lets the control take care of its own business. That's
the beauty of software components!
Another good example of a non-visual software component is a hypothetical spell checker component that processes text and finds misspelled words. Because this spell checker is a self-contained component, it can easily be integrated into any application that might benefit from spell checking functionality. For example, the same spell checker component could be used in both a word processor and an e-mail application. This saves the developers of each application the trouble of designing and implementing their own spell checker from scratch. Instead, they are free to purchase the spell checker component from a third-party component vendor. Or, if they so choose, they can develop their own spell checker component and reuse it however they want. The point is that the spell checker functionality is isolated into a self-contained unit, a component, that can be plugged into an application with minimal effort.
Software Building Blocks
The bottom line to this discussion is that components, both visual
and non-visual, are the equivalent of software building blocks. Using components,
you can build applications one discrete, functional piece at a time. To
get a better grasp of why this is such a significant leap in the evolution
of software design, consider some real-world building blocks. If you wanted
to take up masonry as a side profession, you would first buy bricks, mortar,
and a trowel. Using the trowel and a little know-how, you could start building
walls without too much difficulty.
In the world of software, things just aren't that simple. First of all, you would be hard pressed to find software off the shelf that is as ready to assemble as bricks and mortar are for wall construction. More than likely, the software you find would be at a level of detail significantly lower than you had planned, and as a result you would have to spend a great deal more time developing the low-level parts of your application. The parallel in the masonry world would be if you had to create your own bricks, which is obviously well beyond the skills necessary to be a successful wall builder.
And it doesn't stop there! Back on the software side of things, most software you buy is limited to a particular platform, which means that you are often on your own if you choose to develop for a different platform. In your masonry profession, this leaves you with having to learn how to create a completely different type of brick each time you want to build a wall that looks a little different. Additionally, you would potentially have to buy a new trowel specifically designed for that type of brick.
OK, so my analogy went a little astray there, but I think you get the idea. Just as bricks and mortar form the building blocks of masonry, software components form the building blocks of software development.
Component Models
Now that you have a pretty good idea about what a software component
is, it's time to look a little closer at what makes one work. At the heart
of every software component technology is a component model, which defines
the architecture of components and how they are manipulated and interacted
with externally. The architecture defined by a component model is responsible
primarily for determining how components are able to interact in a dynamic
environment. Understanding component models and their related architecture
is critical in seeing the big picture surrounding software components and
how they work.
All software component models define two fundamental elements: components and containers. The component part of a component model lays the foundation for how different components are created and used. In other words, the component model provides the template from which practical components are created. The container part of the component model equation defines a method of combining components together into useful structures. Containers provide the context for components to be arranged and interacted with one another. For example, an application using a group of components acts as a container for the components.
Containers also are sometimes referred to as forms, pages, frames, or
shells, and can serve as the basis for applications. Just to confuse things
a little more, containers also can be components themselves. Even though
this might sound strange at first, this capability is important because
it enables components to be nested within each other, resulting in complex
visual interfaces.
Besides defining the structure of components and containers, a component
model also is responsible for providing a variety of services. More specifically,
a full-featured component model is responsible for supporting the following
six major services:
•Introspection
•Event handling
•Persistence
•Layout
•Application builder support
•Distributed computing
support
Introspection
Introspection is the mechanism that exposes to the outside world the
functionality of components. Through introspection, an application can
query a component to find out its capabilities and then interact with the
component accordingly. Introspection is one of the most critical aspects
of a component model because it is responsible for dictating how a component
appears to
applications and other components. If you recall, one of the key requirements
of a component is that it be completely self-contained. For a component
to
be both self-contained and useable from the outside, it must fully
support
introspection.
Typically, the spatial requirements for a component consist primarily
of giving the component a rectangular area in which it can render itself
visually. A parent application enables the component to render itself within
this area however it chooses. Likewise, the parent application provides
a facility by which the component's rectangular surface can be managed
in the context of a container that houses other components. This facility
is typically used by application builder tools, where a developer lays
out components while constructing an application.
Application Builder Support
Throughout the chapter you've learned about application builder tools
and how they relate to software components. Support for application builder
tools happens to be a major requirement for component models. This support
gives users the ability to graphically build complex applications out of
components. The specific support required at the component model level
is the capability for components to expose their properties and behaviors
to application builder tools such as Visual J++. Development tools use
these properties and behaviors to enable users to integrate and customize
components in the context of a meaningful application.
Most application builder tools enable the user to not only lay out and edit individual components, but also to specify how the components relate to each other, both visually and programmatically. The layout support provided by a component model aids in laying out components visually, the introspection support helps application builder tools determine the capabilities of a component, and persistence enables the user to save components that have been customized. Specific application builder tool support often consists of dialog boxes that enable the user to graphically edit a component's properties.
Distributed Computing Support
The last major part of a component model is support for distributed
computing, which has become important recently with the increased popularity
of the Internet. It is now becoming not only realistic, but at times imperative,
to build applications that are capable of executing in a distributed environment
connected across vast networks. Consequently, it is important for component
models to address the challenges inherent in building applications engaging
in distributed computing.
Not surprisingly, distributed computing brings on a wide range of problems that aren't present in a single-system environment. Distributed systems are subject to both transmission errors and failure, along with limitations on communication speeds. The capability to handle these problems and limitations comes at no small cost; it requires significant overhead to deal with the problems brought on by distributed computing. The overhead is so significant, in fact, that adding it to an object model must be heavily weighed against the added complexity. Directly adding extensive support for distributed computing simply doesn't make sense when a developer is trying to make component models as lightweight and simple as possible.
Another option to implementing direct support for distributed computing
is for an object model to leverage this support from an existing technology.
With this approach, the single system component model is kept simple and
lightweight, while the distributed model is still available via access
to a leveraged solution. You learn more about distributed computing and
how it affects a real component model in Chapter 15. For now, just understand
that support for distributed computing is important in any object model,
regardless of whether that support is implemented directly or leveraged
from another model.
Final
Words About Java beans
Previously we introduced you to a concept fundamental to the
JavaBeans technology, software components. You first learned a little background
on the state of software and why the software development community is
adopting the paradigm of reusable software. You learned that the idea of
software reuse is neither unique nor new, but that suitable technologies
for exploiting it have only recently surfaced. The premise behind software
components was then presented, with explanations of how components can
provide an answer to the software reusability problem. You followed up
this discussion by learning about the architectural heart of a component,
the component model.
Although we hinted at some things to come, it deliberately avoided getting into the specifics of the JavaBeans technology. The reasoning is that by being fully presented with the issues surrounding component software, you'll be better able to judge JavaBeans and decide for yourself how it fares as a component technology. That's not to say I won't have something to say about JavaBeans and how it relates to other component technologies such as ActiveX; I just want you to understand the big picture before jumping into the details of JavaBeans.