Designing for Reusability
Here are some points to consider when creating reusable components:
A reusable component should be designed to be a "good citizen" within the context in which it will be used. Thus, for example, the template file for a reusable component should not start and end with the <HTML> and </HTML> tags (since these tags will be supplied by the parent component). Similarly, it is unlikely that a reusable component's template would contain <BODY>, <HEAD>, or <TITLE> tags.
Further, if you intend your component to be used within a form along with other components, don't declare the form (<FORM...> ... </FORM>) within the reusable component's template file. Instead, let the parent component declare the form. Similar considerations pertain to submit buttons. Since most browsers allow only one submit button within a form, putting a submit button in a reusable component severely limits where it can be used.
Reusable components are identified by name only. See "Search Path for Reusable Components". Those that reside within a particular application's application directory are available only to that application. Those that reside in a framework (for example, WOExtensions.framework) are available to all applications that link to it. Suppose you have a component named NavigationControl in your application and one of the frameworks that your application links to also has a NavigationControl component. Which one will be used in your application? The result is unpredictable.
Reusable component names need to be systemwide unique. Consider adding a prefix to component names to increase the likelihood that they will be unique.
The more customizable a component is, the more likely it is that people will be able to reuse it. For example, if the AlertPanel component discussed in "Intercomponent Communication" let you set the titles of the hyperlinks (say, to OK and Cancel, or Send Now and Send Later), the panel could be adapted for use in many more applications.
Don't require people to set more attributes than are strictly required by the design of your reusable component. In your component's initialization method, you can provide default values for optional attributes. When the component is created, the attribute values specified in the initialization method are used unless others are specified in the parent's declarations file.
For example, the AlertPanel component's init method could set these default values:
- init { [super init]; alertString = @"Alert!"; alertFontColor = @"#ff0000"; alertFontSize = 6; infoString = @"User should provide an infoString"; infoFontColor = @"#ff0000"; infoFontSize = 4; borderSize = 2; tableWidth = @"50%"; return self; }
Then, in a declarations file, you are free to specify all or just a few attributes. This declaration specifies values for all attributes:
Complete Declaration
ALERT: AlertPanel { infoString = message; infoFontSize = 4; infoFontColor = "#500000"; alertString = "New Release"; alertFontColor = "#A00000"; alertFontSize = 6; tableWidth = "50%"; };
This declaration specifies a value for just one attribute; all others will use the default values provided by the component's init method:
Partial Declaration
ALERT: AlertPanel { alertString = "Choice not available."; };
Rather than building a monolithic component, consider how the finished component can be built from several, smaller components. You may be able to employ these smaller components in more than one reusable component.
Take, for example, the AlertPanel example shown in Figure 28. See the ReusableComponents example application to view the source code for this component. The AlertPanel lets you not only set the message displayed to the user, but also the message's font size and color. These font handling features aren't provided by the AlertPanel itself but by an embedded reusable component, FontString. FontString itself is a versatile component that's used in many other components.
If you plan to make your components available to other programmers, you should provide simple documentation that includes information on:
In addition, it's helpful if you provide an example showing how to use your component.