Edgewall Software

Changes between Version 3 and Version 4 of TracDev/ComponentArchitecture


Ignore:
Timestamp:
Jun 22, 2006, 11:06:12 AM (18 years ago)
Author:
Christopher Lenz
Comment:

Minor updates

Legend:

Unmodified
Added
Removed
Modified
  • TracDev/ComponentArchitecture

    v3 v4  
    1717== Public classes ==
    1818
    19 {{{trac.core.ComponentManager}}} [[BR]]
     19`trac.core.ComponentManager` [[BR]]
    2020  Manages component life cycle, instantiating registered components on demand
    2121
    22 {{{trac.core.Component}}} [[BR]]
     22`trac.core.Component` [[BR]]
    2323  Abstract base class for components.
    2424
    25 {{{trac.core.ExtensionPoint}}} [[BR]]
     25`trac.core.ExtensionPoint` [[BR]]
    2626  Declares an extension point on a component that other components can plug in to.
    2727
    28 {{{trac.core.Interface}}} [[BR]]
    29   Every extension point specifies the contract that extenders must conform to via an {{{Interface}}} subclass.
     28`trac.core.Interface` [[BR]]
     29  Every extension point specifies the contract that extenders must conform to via an `Interface` subclass.
    3030
    3131[[Image(comparch.png)]]
     
    3333== Declaring a component ==
    3434
    35 The simplest possible component is an empty class derived from {{{trac.core.Component}}}:
     35The simplest possible component is an empty class derived from `trac.core.Component`:
    3636
    3737{{{
     
    4949}}}
    5050
    51 Remember that components follow the singleton pattern. There is only one active instance of any component per component manager. The component constructor is "magic" in that it checks with the component manager whether there's already an active instance before allocating a new instance. If the component was already instantiated, the existing instance is returned:
     51Remember that components follow the singleton pattern. There is only one active instance of any component per component manager. The component constructor is “magic” in that it checks with the component manager whether there´s already an active instance before allocating a new instance. If the component was already instantiated, the existing instance is returned:
    5252
    5353{{{
     
    5757}}}
    5858
    59 If a component needs to initialize data members, it can override the {{{__init__}}} method. But because the component manager needs to be able to instantiate the component on demand, {{{__init__}}} must ''not'' require any extra parameters, ''including'' the reference to the component manager passed into the constructor:
     59If a component needs to initialize data members, it can override the `__init__` method. But because the component manager needs to be able to instantiate the component on demand, `__init__` must ''not'' require any extra parameters, ''including'' the reference to the component manager passed into the constructor:
    6060
    6161{{{
     
    7070}}}
    7171
    72 Direct {{{Component}}} sub-classes also do not need to worry about invoking the base classes {{{__init__}}} method (which is empty).
     72Direct `Component` sub-classes also do not need to worry about invoking the base classes `__init__` method (which is empty).
    7373
    7474== Declaring an extension point ==
     
    9898}}}
    9999
    100 Here, the {{{TodoList}}} class declares an extension point called {{{observers}}} with the interface {{{ITodoObserver}}}. The interface defines the ''contract'' that extending components need to conform to.
     100Here, the `TodoList` class declares an extension point called `observers` with the interface `ITodoObserver`. The interface defines the ''contract'' that extending components need to conform to.
    101101
    102 The {{{TodoList}}} component notifies the observers inside the {{{add()}}} method by iterating over {{{self.observers}}} and calling the {{{todo_added()}}} method for each. The {{{Component}}} class performs some magic to enable that: Conceptually, it intercepts access to the extension point attribute and finds all registered components that declare to extend the extension point. For each of those components, it gets the instance from the component manager, potentially activating it if it is getting accessed for the first time.
     102The `TodoList` component notifies the observers inside the `add()` method by iterating over `self.observers` and calling the `todo_added()` method for each. This works because the `observers` attribute is a [http://users.rcn.com/python/download/Descriptor.htm descriptor]: When it is accessed, it finds all registered components that declare to extend the extension point. For each of those components, it gets the instance from the component manager, potentially activating it if it is getting accessed for the first time.
    103103
    104104== Plugging in to an extension point ==
     
    115115}}}
    116116
    117 This class {{{implements}}} the {{{ITodoObserver}}} interface declared above, and simply prints every new to-do item to the console. By declaring to implement the interface, it transparently registers itself as an extension of the {{{TodoList}}} class.
     117This class `implements` the `ITodoObserver` interface declared above, and simply prints every new to-do item to the console. By declaring to implement the interface, it transparently registers itself as an extension of the `TodoList` class.
    118118
    119 ''Note that you don't actually derive the component from the interface it implements. That is because conformance to an interface is orthogonal to inheritance; and because Python doesn't have static typing, there's no need to explicitly mark the component as implementing an interface.''
     119  ''Note that you don't actually '''derive''' the component from the interface it implements. That is because conformance to an interface is orthogonal to inheritance; and because Python doesn't have static typing, there's no need to explicitly mark the component as implementing an interface.''
    120120
    121 You can specify multiple extension point interfaces to extend with the {{{implements}}} method by simply passing them as additional arguments.
     121You can specify multiple extension point interfaces to extend with the `implements` method by simply passing them as additional arguments.
    122122
    123123== Putting it together ==
     
    144144}}}
    145145
    146 This output obviously comes from the {{{TodoPrinter}}}. Note however that the code snippet above doesn't even mention that class. All that is needed to have it participating in the action is to declare the class. ''(That implies that an extending class needs to be imported by a python script to be registered. The aspect of loading components is however separate from the extension mechanism itself.)''
     146This output obviously comes from the `TodoPrinter`. Note however that the code snippet above doesn't even mention that class. All that is needed to have it participating in the action is to declare the class. ''(That implies that an extending class needs to be imported by a python script to be registered. The aspect of loading components is however separate from the extension mechanism itself.)''
    147147
    148148----