Multiple Inheritance in the AOCS Framework


The AOCS framework is designed as a truly object-oriented system.  The design process then proceeds in three major steps.

First Design Step

The first step in the design process consists in identifying abstract functionalities. To illustrate, three examples of such functionalities could be:

Second Design Step

The second step in the design process consists in encapsulating the abstract functionalities in abstract interfaces. In this context, an abstract interface is a class with no data that exposes only abstract methods. In C++ this is realized as a pure virtual class with no data. In Java, abstract interfaces are realized through the Interface construct.

Very simplified versions of the abstract interfaces corresponding to the abstract functionalities listed above are (using C++ syntax):

     class Telemeterable {
          virtual void writeToTelemetry()=0;
     }
A call to method writeToTelemetry causes an object to write its own state to the telemetry stream.
 
  • ConsistencyCheckable Functionality
  •      class ConsistencyCheckable {
             virtual bool doConsistencyCheck()=0;
         }
    A call to method doConsistencyCheck causes an object to perform a consistency check upon itself. The return value indicates whether the consistency check failed or succeeded.
     
  • Resettable Functionality
  •      class Resettable {
             virtual void reset()=0;
         }
    A call to method reset causes an object to reset its internal state.

    Third Design Step

    The third step in the design process consists in defining concrete classes. In general, each concrete class will implement several abstract interface corresponding to the functionalities to be implemented by the set of objects that the class is intended to model. As an example, consider the class modelling the fine sun sensors. Fine sun sensors are objects that are liable to have their state written to telemetry, to be reset and to be subjected to consistency checks. Their class in the AOCS framework could be derived as follows (NB: this is a simplified class diagram used for illustration purposes only):
     

    In the figure, abstract interfaces are shown in red with the class name in italic and concrete classes are shown in yellow with the class name in normal type. Arrows represent inheritance relationships.

    Class FineSunSensor is derived from class AocsUnit that represents generic AOCS units (either sensors or actuators). Class AocsUnit is in turn derived from class AocsObject which in the AOCS framework is used as the common base class for all non-trivial objects and additionally implements interfaces Resettable, Telemeterable and ConsistencyCheckable. Note that class AocsUnit only has single inheritance of implementation (although it has multiple inheritance of interfaces).

    Note also that the proposed class hierarchy ensures that, as desired, fine sun sensor objects implement the Resettable, ConsistencyCheckable and Telemeterable functionalities. This same fact can be alternatively expressed by saying that objects instantiated from class FineSunSensor can have several dynamic types. Thus, a fine sun sensor object will be seen by its clients as an instance of type Resettable, by other clients as an instance of type Telemeterable, by still others as an instance of type ConsistencyCheckable, etc. 

    Functionality Management

    The AOCS Framework aims to build reusable software components for the AOCS. Reusability is achieved by splitting the management of a functionality from its implementation. Use of multiple inheritance is crucial to attaining this goal.

    Consider for instance the management of failure detection tests. In many current AOCS systems, this functionalities is spread over the entire software. With the approach taken in the AOCS Framework, instead it is possible to concentrate this functionality in a single, application-independent, component. The consistency checks (one important part of the failure detection tests) could for instance be carried out as follows;

        ConsistencyCheckable* consistencyCheckableList[N];
        . . .
        for (int i=0; i<N; i++)
        {    if (consistencyCheckableList[i]->doConsistencyCheck())
             . . .    // check failed, report failure
        }
     
    Obviously, the failure detection manager would have to expose methods to allow objects to be (dynamically) added or removed from consistencyCheckableList. The important point, however, is that the consistency checks are managed in a completely application-independent manner.

    Telemetry management would be performed in a similar manner. The core of the telemetry manager object would be something like:

        Telemeterable* telemeterableList[N];
        . . .
        for (int i=0; i<N; i++)
            telemeterableList[i]->writeToTelemetry()

    Once again, telemetry management is completely mission-independent.

    A point worthy of note is that, thanks to the use of multiple inheritance, the same concrete object can be simultaneously present on both consistencyCheckableList and telemeterableList. In one cases it is treated as an instance of type ConsistencyCheckable*, whereas in the secon case it is treated as an instance of type Telemeterable. Multiple inheritance is used to allow this multiplicity of views of the same concrete objects.

    Thus, for instance, a fine sun sensor object can be declared as follows:

        FineSunSensor fss;
        FineSunSensor* ptr_ss=&fss;

    The pointer ptr_fss can be passed both to the telemetry manager and to the failure detection manager. This is possible because variable ptr_fss can have different dynamic types corresponding to all the classes from which fss inherits (either directly or indirectly). In other words, ptr_fss is declared as a pointer to FssSunSensor but it can be used wherever pointers to any of its superclasses are required. This is expressed by saying that the static type of ptr_fss is FssSunSensor* but its dynamic type can be pointer to any of the superclasses of  FssSunSensor.

    In summary then, the AOCS Framework provides functionality manager components that are mission independent because they operate on abstract interfaces. Concrete objects use multiple inheritance to implement several abstract interfaces corresponding to their various functionalities. This allows them to play different roles depending on the context in which they are used.

    Finally, it is hardly necessary to stress that the code examples given above are highly simplified. The abstract interfaces in the AOCS Framework are richer than shown here and the functionality managers consist of much more than simple loops.

    An Over-Complex Class Structure?

    A naive observer might argue that the class structure of the figure above is unnecessarily complex. Why not combine the three abstract interfaces into class AocsObject? This would streamline the class tree and remove the need for multiple implementation of interfaces (it would notably make implementation in a language like Ada95 possible). There are at least two reasons why this type of simplification would lead to a deeply flawed design.

    First, not all classes in the AOCS Framework need to implement all three abstract functionalities. There are for instance some classes that should be telemerable and resettable but that should not be consistency checkable. There are also classes that should be resettable without being either telemeterable or consistency checkable. Thus, keeping the abstract interfaces separate allows to allocate responsibilities to classes in a more finely grained manner.

    Secondly, some of the clients that need to access objects instantiated from class FineSunSensor only need to have access to services of a certain type. For instance, the telemetry manager only needs access to the services defined by the telemeterable functionality. With the proposed architecture, the telemetry manager sees instances of class FineSunSensor as objects of (dynamic) type Telemerable. There is therefore a syntactical check, statically enforced by the compiler, that it will only have access to the telemeterable operations. Mistakes arising from the fact that the telemetry manager tries to access operations that are outside its competence simply cannot occur. Thus, keeping the abstract interfaces separate helps avoid design mistakes and enforces clean software architectures.

    Back to Top, Back to Aocs Framework Project Home


    Last updated on Feb. 5-th 2002 by Alessandro Pasetti