3.8. The Component-based Model

To write applications for an OSGi service framework is to develop bundles. The programming model is component-based, in contrast to the library-based model. Figure 3.12 illustrates the typical structures of the two models.

Figure 3.12. The library-based model (a) and the component-based model (b)


In a library-based model, we approach an application such as a word processor by designing and developing a collection of classes that are roughly divided into various functional modules or libraries (for example, print, format, utilities, and so on; see Figure 3.12a). Although the modules could be designed into components that have well-defined and controlled interfaces, they are not required to be that way. Real-world factors such as deadlines, inexperience, and expediency usually intervene and lead to an end product comprising modules that are arbitrarily accessible, tightly coupled, and inflexible.

In the best of times, even if a module is carefully crafted, it must be combined with a larger application to be reused. For example, suppose that the print module is designed to be shared with a diagnostic agent, which also needs the print functionality. We would have to make the print classes a permanent part of the diagnostic application.

After the application has been deployed, bug fixes or new features customarily require a new release. Customers have to bring down their running systems for the upgrade.

The library-based approach also imposes a “take-it-or-leave-it” situation from the user's point of view: Each new release of an application packs in more features, maintains backward compatibility, and consumes more hardware horsepower. Although many of us do not need the new features—we may not even know their existence—we must still pay the price for the added slowdown, incompatibility problems, and unreliability. We simply cannot rip out the part that we don't need and keep those that we like and know well. For instance, suppose we don't need the grammar checker in Figure 3.12a. Regardless, it is not an option to do without it.

In a component-based model, a run-time hosting framework makes a big difference. Because bundles may go through life cycles, their coupling points must be consciously made minimal and their interaction controlled. In this model, new applications naturally form themselves as bundles are plugged in. For example, in Figure 3.12b, the system, utilities, format, speller, and print bundles form a word processor application, whereas the system, utilities, print, and test bundles form a diagnostic agent application. Depending on whether the grammar checker is needed, its bundle can be installed or removed dynamically.

The envisioned operational environment of residential gateways requires a component-based model because pieces of the software come from multiple vendors and at different points in time. The static library-based approach is clearly inappropriate in this context.

In the component-based model, bundles should be “unbiased” to a wide range of application contexts; otherwise, their usefulness is limited. For example, if the print bundle expects fancy formatting specific only to the word processor, it may not be suitable for the diagnostic agent. This aspect makes design more difficult in the component-based model than the library-based model, because with the library-based mind-set a designer would never anticipate that a word processor and a diagnostic agent—applications that are world apart—may share commonalities.

Many developers do not appreciate this shift of mental models, which can cause much frustration when they start programming for service gateways. This is because we are used to writing monolithic software for which all pieces are present at run-time.

In summary, here are the main distinctions between the two models:

  • In a library-based model, multiple layers of software abstractions stack up one on top of another, whereas in a component-based model, multiple software components plug in side by side with one another.

  • In a library-based model, once a module is compiled into the software, it is always available at run-time. In a component-based model, a component can come and go dynamically at run-time.

  • In a library-based model, the sum of all libraries must be packaged together for the product to work. In a component-based model, a subset of components can be packaged together and can serve useful functionality as a product.

  • In a library-based model, one most likely must rebuild and repackage the entire set of libraries to fix bugs and add features at compile-time. In a component-based model, new components can be added or existing components can be updated in an incremental way at run-time.

  • In a library-based model, changes made to public interfaces have less impact because one has to rebuild the software in its entirety. In a component-based model, the cost of redoing public interfaces can be prohibitive because other components may have relied on them at run-time.

  • In a library-based model, the flow control of an application usually starts at one entry point (e.g., public static main(String[] args)). In a component-based model, components are controlled by a hosting environment and they interact with one another to function.

It is essential to realize that the component-based model requires more discipline on the part of developers during the design stage but provides more stability, extensibility, and flexibility over the library-based model at run-time. Two important issues are the following:

  1. In the component-based model, the service on which you depend may not always be there. You must program your bundles in anticipation of this possibility. In the OSGi framework, the main solution is to use the service registration/unregistration events, which you should monitor and handle accordingly. More in-depth treatment of these topics is given in Chapter 5.

  2. You must strike a balance between insulation and sharing among bundles. At one extreme, total isolation causes common functionality to be duplicated in many bundles, which increases footprint and reduces maintainability. At the other extreme, sharing everything reverts back to the library-based model with all its stated evils. As a rule, you must follow the principle of separating interfaces from implementations for services, and you must have interbundle coupling embodied in service interfaces only. This way you can achieve the best results. We follow up on more involved design issues in Chapter 6.

Other component-based Java technologies also exist. For example, an applet is a component that has life cycle operations and it is hosted by a Web browser. Its application, however, is mostly limited to a user interface. JavaBeans™ defines reusable components, but they are mainly geared toward manipulability using a visual builder tool during development. Enterprise JavaBeans™ defines a distributed component model, but its complex features such as transactional and distributed processing and persistence are not needed by many applications in resource-constrained environments.

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

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