The previous sections of this chapter have given hints and guidelines for the process of developing frameworks. We now shift focus and discuss the novel techniques called 'adaptation cases' and 'adaptation reports' that have proven useful in the creation of applications from a framework. Before launching into this, it is worthwhile briefly discussing how these concepts relate to each other and to cookbook recipes as presented in Chapter 5 and Chapter 6.
Remember that implementation cases are a means of 'test-driving' a framework design as it evolves. When the framework is ready for use by application developers, the implementation cases used during framework development will have themselves evolved into cookbook recipes. The framework user need not know or care whether a particular cookbook recipe comes from an implementation case or was generated independently. This observation allows us to eliminate the distinction between implementation cases and cookbook recipes. We refer only to cookbook recipes, with the understanding that we are, by implication, also referring to any implementation cases that have generated the recipes.
Adaptation cases are used during the process of creating an application through adapting a framework. They build on cookbook recipes and make the relationship between application requirements and cookbook recipes explicit. They might lead to the definition of composite recipes (see Chapter 5). Adaptation reports are used during application creation. They are a means of reporting a developer's experiences while trying to create an application from a framework.
The users of a framework adapt the framework to create an application that meets a set of application requirements. Following the common terminology of object-oriented design, in which an object is said to be instantiated from a class and the object is referred to as an instance of the class, we refer to an application created by adapting a framework as an instance or instantiation of the framework. The process of creating the application is referred to as instantiating or adapting the framework.
As a design tool, each implementation case provides the framework developer with an opportunity to answer a question of the form, 'If a user of my framework needs to create an application that does X, how would the user need to adapt my framework to achieve that goal?' For example, in our earlier sample implementation case, the question the framework developer was asking can be stated as, 'If a user of the AOCS framework needed to create an application that includes an attitude controller with both a high accuracy and a low accuracy control mode, and have the control mode change based on the size of the attitude control error, how would the framework user need to adapt the AOCS framework?' The answer to that question can be found primarily in the Implementation Description section of the implementation case.
At the point at which an application developer is actually instantiating an application from the framework, the question is no longer the theoretical, 'If a user needs to .' The question then becomes the related, but more concrete, 'I need to create an application from this framework that does X; what do I need to do?' This is where adaptation cases are helpful.
In order to even ask such questions, the application developer must have a set of requirements for the application to be developed. Use cases are a common technique of capturing, representing, and discussing application requirements. Thus, we start our discussion of adaptation cases with the assumption that our application requirements are represented as use cases.[6]
[6] There is very little in the adaptation case concept that ties it directly to use cases. Application requirements presented in some other form, even as just a simple requirements list, can also be used as a starting point for the creation of adaptation cases with only slight modifications to what is presented here.
An example use case provides a starting point for our discussion. Table 7.3 sketches an example use case for an AOCS application to be instantiated from the AOCS framework.
Use case |
Stabilization of the attitude of an astronomical observation satellite during ejection from launch vehicle. |
Actors (external entities) |
Launch vehicle (initiator), ground station, astronomical object (object to be observed). |
Pre-conditions |
|
Post-conditions (objectives) |
|
Basic flow |
|
Note that this use case is somewhat less detailed and precise than what might be available in reality. Such details as which exact control algorithms are to be used in the low and high accuracy modes, whether or not there is a limit on the time that should be spent in low accuracy mode, and what actions should be taken if that time limit is exceeded (an alternative flow) are missing from this use case. It is also possible that this particular use case might, in reality, be broken up into a number of smaller use cases.[7] However, the point here is not to understand the requirements of an AOCS for a particular satellite in detail. This examplar use case is adequate for our current purpose.
[7] It should be noted that the objective of the post-ejection phase for a satellite is usually more modest than acquiring an astronomical object with full accuracy, as in the given objective of the use case.
Our next step is to find the set of cookbook recipes that provide us with the steps needed to adapt the framework to create an application that will behave as the use case dictates.
We can define an adaptation case as a relation between the subset of application requirements expressed by a use case and the set of cookbook recipes for the framework we are instantiating. This relation is such that each requirement is related to the cookbook recipes that provide the steps for meeting that requirement.[8] This is illustrated in Figure 7.18.
[8] As was mentioned in a previous footnote, we are not tied to requirements that are presented in the form of use cases. The important thing to note is that an adaptation case is a relation between a subset of application requirements and the set of cookbook recipes. As presented, the use case is the organizing unit for our requirements. If requirements are organized differently, then adaptation cases can also be organized differently.
It is worth noting that we have carefully defined the adaptation case as a relation and not as a mapping. If we had defined it as a mapping, we would be dictating that each requirement maps to a single recipe. As Figure 7.18 shows, we allow for the possibility that a requirement can only be met by performing the adaptations called for in multiple recipes.
Just as an individual use case does not show all the possible uses of an application, an individual adaptation case does not show all the necessary adaptations of a framework to create the desired application. A set of use cases is essential to fully specify an application, and a set of adaptation cases is essential to fully specify a framework instance. Once we have defined an adaptation case for each use case, which specifies our application, then we have discovered the set of adaptations necessary to create our desired application from the framework.
Returning to our example use case, let us begin to create its corresponding adaptation case. Within a use case, the requirements can most often be found by examining the flow section(s). Sometimes, to get a complete picture of the requirements we need to look in the Post-conditions section also, but requirements found here generally overlap with those found in the flow section(s).
In our examplar use case, step 1 of the Basic Flow shows the external entity (Launch vehicle) initiating the use case. Step 2 begins to show what our system is supposed to do in response. From steps 2 and 4 we see that there is a need for an attitude controller that can switch between two control algorithms ('high accuracy' and 'low accuracy') depending on the size of the attitude control error. The examplar implementation case presented in Section 7.8 provides us with a recipe to meet this requirement. Thus we see that steps 2 and 4 of this use case are related to that implementation case/recipe. Let us call the recipe Recipe 1: Implementing Multi-mode Controllers.
From steps 3 and 5, we see that there is a need for a telemetry system that can buffer telemetry data and send it to the ground station at some later time. To meet this requirement, we would look for a recipe in our cookbook that shows us how we can create an implementation of the TmStream interface that stores data written to it using its write() methods and then transmits that data to the ground when its flushBuffer() method is called.
In searching for such a recipe, we may indeed find that there is an existing component, provided as part of the framework, that meets our need. In this case, the recipe should show us how to 'plug in' that existing component. Let us suppose we have such an existing component and a recipe showing how to make use of that component. We'll call that recipe Recipe 2: Configuring and Using the Provided Buffered Telemetry Stream.
From steps 3 and 6, we see that there is a need for a telemetry system that supports changing the rate of collection of telemetry data. Again, to meet this requirement, we would look for a recipe in our cookbook that shows the adaptations we need to make. It is not obvious from the presentation of the AOCS framework in the previous sections how the framework would be adapted to meet this requirement. However, let us assume for now that we have a recipe that provides us with the necessary steps. We'll call that recipe Recipe 3: Implementing Multi-rate Telemetry.
From step 3, we see that telemetry data must be provided about attitude controllers. Therefore, we note that the framework calls for making an object implement the telemeterable interface and adding that object to the list of telemeterable objects held by the telemetry manager. We'll call the recipe providing these steps Recipe 4: How to Collect and Send Telemetry Data for an Object.
Given this use case, set of requirements, and set of recipes, a textual representation of the adaptation case would look like Table 7.4. This is very likely incomplete. Other requirements and recipes may also be associated with this use case. For example, the need for objects that interact with and read data from particular types of sensors (perhaps star sensors) could be inferred from this use case. Similarly, the need for objects that interact with and send commands to actuators in order to apply forces or torques to a satellite could also be inferred from this use case. Each of these requirements will also be related within the adaptation case to a cookbook recipe.
The inevitable question arises, 'What if we encounter a requirement for which we cannot find a related recipe for guiding us as to how to adapt the framework?' There are three foreseeable situations in which this will occur:
The adaptation is possible, but is deemed too easy or trivial to rise to the level of deserving its own recipe.
The adaptation is possible and somewhat complicated, but no recipe has been written for it.
The adaptation is not possible because the framework was not designed around the variation point or behavior required.
In the first situation, we can simply embed the adaptation instructions (a 'mini-recipe') into the adaptation case in the table where we would normally have referenced a separate recipe.
In the second situation, we can investigate the necessary adaptations and create our own recipe. Alternatively, depending on our level of access to the framework developer(s), we can report the situation to them and request that a recipe be provided. In either case, if a new recipe is created it should be added to the cookbook for the framework.
Adaptation Case 1 |
---|
Associated use case |
Stabilization of the attitude of an astronomical observation satellite during ejection from launch vehicle. |
Framework: AOCS framework |
Requirement recipe relation |
Requirement |
(Flow steps, post-conditions, etc.) |
Related recipes |
(used to meet requirement) |
Flow steps 2 and 4: multi-mode attitude controller |
Recipe 1: Implementing Multi-mode Controllers |
Adaptation notes: |
|
Flow steps 3 and 5: buffering telemetry data |
Recipe 2: Configuring and Using the Provided Buffered Telemetry Stream |
Flow step 3: Collection of telemetry data for attitude controllers |
Recipe 4: How to Collect and Send Telemetry Data for an Object |
Adaptation notes: |
|
Flow steps 3 and 6: collection of telemetry data at various rates |
Recipe 3: Implementing Multi-rate Telemetry |
Adaptation notes: |
|
In the third situation, we should report the situation to the framework developer(s) and to other developers who may want to adapt the framework in a similar way. If the adaptation is deemed appropriate, the framework developer(s) might change the framework to allow for the new adaptation.
The second and third of these situations call for us to report our findings. How should we do this reporting? That is one of the areas in which the technique presented in the next section can be helpful.
Adaptation reports are inspired by a type of report used by airplane pilots to help each other avoid weather-related surprises and other difficulties while flying. Called pilot reports (or sometimes PIREPS), these are brief reports, given in flight, by a pilot about weather conditions actually being experienced. Observations of weather conditions made by ground stations give an incomplete picture of the actual conditions aloft. Thus, pilot reports supplement the weather information from ground stations and are a valuable source of information for other pilots in the vicinity.
Predictions about the feasibility and practicality of a certain framework adaptation are analogous with the weather reports from a ground station. They cannot always give the whole picture and need to be supplemented by reports from developers trying to adapt the framework. These developers are like the pilots flying through and experiencing specific weather conditions. Adaptation reports provide a mechanism for these developers to report on their experience so that other developers needing to make similar framework adaptations can benefit.
A pilot report that essentially indicates that conditions in the air are exactly as the ground station predicted is of less value to other pilots than a report that indicates how conditions aloft are different from those expected. This is particularly true when conditions aloft are worse than predicted from the ground. Similarly, an adaptation report which indicates that the developer's adaptation experience was just as expected (based on the existing framework documentation) is of less value to future adapters of the framework than one pointing out how the developer's experience differs from that expected. Again, this is particularly true when the experience was somehow worse than expected.
Thus, adaptation reports focus primarily (although not solely) on problems that occur during framework adaptation. A developer should create an adaptation report in situations such as when a necessary adaptation could not be made, when no recipe was found for an adaptation, or when an adaptation (or set of interacting adaptations) had an unforeseen side effect. Another case in which an adaptation report should be created is when the developer has successfully implemented a difficult or tricky adaptation so that other developers can save time and effort by mimicking or reusing his adaptation. Table 7.5 describes a proposed template for adaptation reports.
Adaptation report title | |
Framework | The framework being adapted. |
Application | Brief description or name of application being developed. |
Requirements |
|
Recipes involved |
|
Framework classes/interfaces | Details of which, if any, framework classes or interfaces were used or adapted. |
Application classes |
|
Adaptation Success? | Was the adaptation successful? |
Reason for report | Choose one of the following: |
| |
Discussion | General discussion of the reason for the report. |
This may include, but is not limited to, such things as:
|
Returning to our example use case and adaptation case, let us suppose that we discover, while trying to create an adaptation case, that there is no recipe available that provides steps for the collection of telemetry data at various rates. On further investigation, we eliminate the possibility that this adaptation is so trivial that no recipe is required in fact, as far as we can tell, such an adaptation is simply not possible given the existing framework. This is an occasion that calls for generating an adaptation report. Table 7.6 provides an example of such a report.
Collecting Controller Telemetry Data at Multiple Rates | |
---|---|
Framework | AOCS Framework. |
Application | AOCS for astronomical observation satellite. |
Requirements |
|
Recipes | No recipe found. |
Framework classes/ interfaces | Not applicable. |
Application classes | Not applicable. |
Adaptation success? | No. |
Reason for report | Recipe not found adaptation not possible (?) |
Discussion |
|
Ideally, such a report would be forwarded to the framework developers. The framework developers could either respond that the adaptation is indeed possible and provide a recipe for it, or that the adaptation is not possible and that a variation point will be added to the framework to allow such an adaptation, or that the adaptation is not possible and will not be added.[9]
[9] Recall the discussion at the beginning of the chapter, which pointed out that adding unneccessary variability to a framework does not result in a better framework.