- On Tools
- On Open Source
- The Apache Software Foundation and the Jakarta Project
- On Application Development
- Further Reading
1.4 On Application Development
The final element that must be considered before looking at the tools is the general process of development. This will help clarify a number of ways in which a tool can fit into a project.
Engineering is an inherently difficult enterprise; clearly no one person could build a bridge, plane, or skyscraper. The same is true of software engineering beyond fairly small projects. Often a project is so big and complex that it simply cannot all fit into a single human brain.
For a large project to be manageable it must be split into smaller pieces. This is true when there are many members of a team working on the same project so that each knows what part of the whole they will create. It is even true when a project is being undertaken by a single person because it allows the developer to concentrate on one thing at a time. Usually the smaller pieces are easier to design, build, and test, and once built, the individual components can be updated or changed without worrying about how that change will affect the rest of the system.
While using toolkits can be a great time saver, it does require some additional thought at the beginning when deciding how to split up a project. This is because some attention must be given to what pieces the toolkit can provide. If this is not done properly, it may turn out that there is some overlap between what is being developed and what the tool provides. Besides being inefficient, this can lead to problems when integrating the tools into the rest of the code.
Metaphorically, if the whole project is to build a cube, one particular tool may look like a pyramid. This then defines the shape for the remainder of the project that the in-house developers must build.
1.4.1 Modularity in Java
One obvious way to divide a project is by splitting it into individual classes. Classes are Java's natural unit of work and may be thought of as Lego blocks that are ultimately connected together to build the final product. Each individual block can be written by one person or a small team without needing to know the details of how the other blocks work. Each block can also be individually tested to ensure that it exhibits the correct behavior. All that is needed for this approach to work is to ensure that the "connectors" of each block, which typically means the public methods, are stable and well documented.
Indeed, this is how many toolkits work. It is very common for a toolkit to consist of a large collection of classes or, metaphorically, a set of blocks with a variety of shapes and colors. When faced with the need to create one such block, one can save time by using an already-existing block provided as part of a toolkit.
This idea of using existing blocks goes well beyond the question of toolkit use. Such code reuse is fundamental to the whole idea of object-oriented programming. The Java core libraries provide many such blocks. Good developers will try to generalize their tasks and so create additional general-purpose blocks, and other blocks will come as part of toolkits.
What has been called "blocks" would more correctly be called JavaBeans. At one level beans are just classes whose methods conform to certain naming conventions. A bean can expose a property by providing a method that sets the property and/or a method that obtains the current value. For example, a bean might have a property called "color" and corresponding methods called getColor() and setColor(). A bean can also designate itself as the source of any number of events that can be registered with other classes that will react to such events.
Note that the notion of bean properties is fairly abstract. They may be simple values, such as a name or color or price, which can be represented as a Java primitive type. A property may also be some compound value represented as another bean or even an array of beans. Beyond this, invoking a get or set method may perform any operation that can be done in Java, from sending an e-mail to updating a database to accessing an external Web page. None of these things are properties in the dictionary sense, but the notion of properties is a useful way of unifying access to beans or toolkits composed of beans.
As powerful as classes are, Java's interfaces are even more powerful. A class represents what a component is, but an interface specifies what a component does. This idea is often referred to as "programming by contract," and it is discussed in many good books on object-oriented programming, including The Object of Data Abstraction and Structures (Using Java) by David Riley.
The interface concept is powerful for two reasons. First, a single object may do several things, which is why any class may implement any number of interfaces. More significantly, interfaces provide for a very loose connection between components. While a loose connection may sound like a bad thing, in fact it allows for a great deal of flexibility.
One common design pattern that captures this flexibility is called a factory. A factory is a class whose job is to build an instance of a class that implements an interface. Typically there will be many possible implementations to choose from, and the factory will decide which to use based on some configuration file or internal logic.
Such factories are a natural integration point for using toolkits, and this integration can take two forms. The common model where user code calls out to the toolkit can be slightly modified by using a factory as an intermediary. It is also possible to turn this model "inside out." Many of the tools in this book provide complete frameworks into which users plug some of their own code. Often this is accomplished by creating a class that implements an interface provided by the toolkit and then notifying a factory about the presence of this class. When the framework runs, the factory will create an instance of the class, and one of the interface methods will then be invoked automatically.
This is even how servlets work: The configuration files used by application servers associate a URL or URL pattern with a servlet. Internally when a request comes into the server, something akin to a factory uses the configuration information to determine which class that implements the servlet interface should be invoked, and the request is then passed to this servlet.
1.4.2 Model/View/Controller
Beyond the division into such fine-grained units such as classes and interfaces, it often makes sense to divide projects into major functional units. After all, this is the way most physical engineering is done. When building a car one team is likely to be responsible for the engine, another for the electronics that control everything, and a third with the exterior. These are natural ways to divide up the work, partly because each piece is somewhat independent of the others but also because very different skills are required for each.
There is no set recipe for the way in which a software project should be divided, but there is an important pattern that has emerged over time that advocates identifying three major pieces. The first piece will be responsible for modeling the problem to be solved, so it is called the model. This model might be a virtual shopping cart for an online catalog, a database representing a CD collection, or a set of equations representing some complex scientific simulation. In each case, the model contains all the information about how the data is internally stored and the operations that may be performed on that data.
The second piece is responsible for allowing users to interact with this data. This could be a desktop application written in Java using the Swing API (application programming interface), or it could be an applet, or a class that generates HTML, or even a program that controls a huge electronic billboard. The code for this piece contains everything needed in order to navigate through the data, display the values, modify the display as needed, and possibly allow the user to make changes to the model. Ideally, the presentation should also be aesthetically pleasing and intuitive to use. This piece is known as the view.
Finally, the third piece acts to mediate between the first two. Although the view allows the user to request particular data, it will not itself load that data into the model. In addition, some data may be restricted to certain users. This kind of information should not reside in either the model or the view. So the third piece, called the controller, is responsible for controlling the model based on instructions from the view, and it may also tell the view to hide certain information based on data in the model.
Once these three pieces have been defined, the only remaining work is to ensure that they all fit together and can interoperate. This is done by providing well-defined interfaces between each pair of components. The view will know how to get data from the model, the controller will know how to configure the view and the model, and so on.
Splitting the work in this way is known as the model/view/controller paradigm, and it is very powerful. Generally it is used in the context of Web applications, where beans play the role of the model, Java Server Pages and servlets act as the view, and typically a master servlet acts as the controller. Many of the toolkits to be examined are also organized along model/view/controller lines. Some assist in the construction of one of these elements, while others provide entire frameworks comprising integrated implementations of all three into which developers can plug their own code.
This completes the groundwork for this book. In what follows keep in mind the general concept of tools, the motivations and benefits behind open source, and the ways in which tools can integrate with the larger application. And now, on to the tools!