Component architecture approach
The main idea in the Zope Component Architecture is the use of components, rather than multiple-inheritence for managing complexity. This page discusses key advantages of a component based approach and shows how a component-based approach differs from the usual way of creating Zope applications.
Currently, Zope relies on multiple inheritance to manage complexity. Object responsibilities are spread over many separate mix-in classes. Many of the mix-in classes require subclasses to provide specialized meta-data or methods to customize the behavior of the mix-in. Classes typically have a large number of base classes and many bits of meta-data and special methods that are unrelated to the object's core functionality. In addition, object responsibility typically includes providing specialized interfaces, including Web (browser) interfaces, and often including other interfaces, such as FTP interfaces.
An alternative for managing complexity is to spread the complexity
over multiple cooperating objects. Figure 1 illustrates the
difference between the inheritance- and component-based
ZDocument class provides a number of features:
- A DOM interface
- A web presentation of the DOM interface
- An HTML representation of the document
- A web interface for working with the HTML representation
- A structured text representation of the document
- A web interface for working with the structured-text representation.
In the figure these features are shown as operations for simplicity, but each feature would, in practice, be provided by several operations.
Figure 1: Example class with mix-in behavior and componentized behavior.
The features provided by the
ZDocument class can be spread over many
simpler classes as shown in the figure. We've used UML stereotypes
to classify the different kinds of classes:
Documentclass is a content class, meaning that it is responsible for managing the structured content of a document and for making it available for reading and update through a DOM interface.
StructuredTextDocumentclasses provide alternate representations of documents. They don't provide any data storage, but use content stored in
StructuredTextDocumentare "application functionality" classes because they provide additional application-specific functionality for classes that store content.
StructuredTextWebclasses are responsible for providing web user interfaces for documents in various formats. We call these classes "presentation" classes, because they present an application or content class in some way. We could also provide presentation classes for FTP, WebDAV?, XML-RPC, wxWindows, and so on.
Two important advantages of spreading responsibility over multiple components are:
- Individual classes are much simpler, and thus, easier to maintain.
- Functionality can be added and changed without modifying
To add another representation or presentation to the
ZDocumentclass, you must either modify the class or subclass it. Modifying the class may be extremely complicated, considering all of the class responsibilities that must be maintained. If the class is maintained by someone else, modifying it may not be an option. Sub-classing the class may still be complex and won't allow new functionality to be provided for existing instances of the old class without performing complex data conversion.
If responsibilities are spread over many classes, you can add functionality by simply adding more classes. Similarly, you can provide alternate presentations by replacing existing presentation classes with new ones.
One problem with the distribution of responsibilities in figure 1 is that there are dependencies on specific classes. You can replace the presentation classes to provide alternate presentations, but you can't replace the application functionality or content classes without modifying the presentation classes. This is a slight exaggeration, since the presentation classes probably depend on the behavior of the classes they depend on, not on the actual classes. We can express the behavioral dependency through interfaces, as shown in figure 2.
Figure 2: Components connected via interfaces
In figure 2, the application-functionality and content classes depend realize interfaces that express their behavior. The presentation and application-functionality classes depend on interfaces, not on specific classes. This makes it much easier to replace application-functionality and content classes, because all we have to do is provide classes that realize the same interfaces.
The remaining problem is how to stitch the various objects together. This is where the Zope Component Architecture comes in. The Zope component architecture provides machinery that makes it relatively easy to assemble cooperating objects. To a significant degree, objects are connected based on interfaces, as shown in figure 2. This brings us to the concept of "component".
In the Zope component architecture, a component is an object with introspect-able interfaces. Specifically, a component is any object that asserts that it implements interfaces as defined by ZopeInterfaces.
The component architecture provides ways to look up various kinds of
components based on interfaces and names. For example, when
Document content object to access a web interface for
editing the document in structured text format, the structured-text
presentation component will be looked up based on the content
DocumentInterface and on the presentation name
structuredText). In turn, the structured-text web interface
will look up the
StructuredTextDocument component based on the
Documentinterface and either the application
StructuredTextSourceInterface or the
application component name (e.g.
rational for using names or interfaces will be explained elsewhere.
We never look up components based on the component class, because we
want to make it easy to plug in different implementations.
There are some details worth mentioning here. First, the classes shown in figure 2 are not components. The instances of the classes in figure 2 are components. This is an important distinction. (Classes can be components, if the classes implement interfaces. For example, classes are sometimes uses as factory components, responsible for creating other components, the instances of the class.) Second, you might be wondering if the presentation classes in figure 2 implement any interfaces. In fact they do. They implement a web publishing interface and the instances of the class are, therefore, components.
You don't need to change
The component-based approach offers some real advances over an inheritance-based approach, but inheritance will still work. You don't have to use components, existing Zope objects will still work. You could also use a hybrid approach. For example, we could have chosen to extract only the web behavior from the ZDocument? class.
Suggestion for clearer expression. SEE 1st PARAGRAPH - COMPONENTS --guido1st, 2003/10/10 02:01 EST reply
This is a slight exaggeration, since the presentation classes probably depend on the behavior of the classes they depend on, not on the actual classes themselves
Suggestion for clearer expression. SEE 2nd PARAGRAPH - COMPONENTS --guido1st, 2003/10/10 02:13 EST reply
In figure 2, the application-functionality and content classes depend on realize interfaces that express their behavior.
... --RMattB?, Mon, 21 Jun 2010 11:28:41 -0400 reply
"In figure 2, the application-functionality and content classes depend on realize interfaces that express their behavior." This sentence could use further clarification. It seems that there is either a missing conjunction between "depend [on]?" and "realize", or perhaps a missing "which is/are" to show what's dependent. Thanks!