Reusable Components
- Reusable Components
- Introduction
- Concepts and Ontology
- Functionality and Interfaces
-
Put it all together
- Step 1 - Specify a high-level requirement for the component
- Step 2 - Write a draft list of Provided Interfaces
- Step 3 - Write a draft list of Required Interfaces
- Step 4 - Put all interfaces into a draw, and review if there is something …
- Step 5 - Detail the Interfaces
- Step 6 - Specify the Component Behaviour
- Step 7 - Specify the Sequence Interaction
- Step 8 - Specify the Expected Quality
- References
Introduction
When developing new features for Project.net, there are some common tasks developers must do before start coding:
- To define the environment in which the new feature will be place, looking for other features to interact with.
- To research how to interact with other features, trying to realize which functionality is available, and in the best scenario, use them as is
- To look for already implemented features source code in order to try to reuse "something"; to deal with different implementations for same or similar functionality, and deciding which one should be taken as a "template".
- Etc.
As the application gets bigger and bigger, this kind of problems happens more frequently, turning on the Features development to very complex task.
Here will be explained a very common approach to break the application into manageable modules (a module can be a feature), where each module is known only by the functionality it provides, making it "replaceable" by other module with same functionality without affect the its dependants.
In such a way, the feature development process will be easier, as the developers will only required to search already implemented features to use, but not to investigate what is under the hood, because what matters here is the provided functionality.
About the "how-to" implement a feature, this approach will remove such decision the developer have to take about "how to technically implement it". In any case, the feature could be replaced for a "better implemented" feature without affecting the application.
NOTE: it is no the intention to incite a free-will development, but delegating such aspects to other areas, as it could be to set a well defined architecture, coding styles, dos and don'ts, and better: Analysis and Design Patterns
Concepts and Ontology
There are a lot of terms that Functional people have in their vocabulary, that Technical people don't, what usually interferes in the requirements transfer from former to later.
Also, there are terms that while different, mean same thing. And worst, there are terms that while same, mean totally different, and sometimes opposite.
In order to reduce this gap, it is needed the definition of an ontology, to relate terms and concepts from both areas (Functional and Technical... and perhaps we should include Marketing, User and others).
Example: Feature term
- From the Functional perspective, a feature is something the application does. It does not matter how it is done, but expected results.
- If we move to the Technical perspective, a feature is something to implement (to code). So, it will be composed by a set of Java Classes, JSPs, tables, etc.
Here is the first candidate entry for our Ontology: the Feature term. We have to find something meaningful to the Technical people.
What is proposed in this presentation (paper, article, or the name you would like to set), is to match the term Feature with the Component concept:
- A component represents a modular, deployable, and replaceable part of a system that encapsulates implementation and exposes a set of interfaces (www.omg.org).
Functionality and Interfaces
The functionality provided by the a component will be specified by a set of provided interfaces it realizes, and a set of required interfaces the component needs to function.
| In other words a component can be logically considered both as a server that offers services and as a client that requests services |
In order to accomplish with our objective of replaceable components, we need to specify interfaces as a black-box. Also, we need to model them pursuing the understanding of uninvolved developers, who might ever heard about the component.
To do so, we can specify the component with the UML notation, using assembly connectors for required interfaces (socket icon) and provided interfaces (ball icon).
In such a way, we will be providing more details about the actual relationships between components than simply put dependency relations.
Put it all together
Our main goal will be to describe a set of common steps to design and further implement a reusable component, in a way we are able to answer all these next questions:
- What services are requested by the component?
- What services are offered by the component?
- How can these services be used?
- Is there some dependency with other component?
Next will be presented a set of recommended steps to design a reusable component from scratch.
Step 1 is a mandatory step dedicated to define what's obvius but nobody writes: the requirements.
Steps 2, 3 and 4 are related to the create a draft list of interfaces (required and provided), further represent them into a picture (optional).
Step 5 is an very important step: to formally describe the interface. When somebody want's to evaluate whether a specific component would be of interest, a reading of this step's output is mandatory.
Steps 7 and 8 are optional, but adds some meaninful information, as to details the sequence in which the services are allowed to be used, as also an explanation of the component expected quality.
After having a good understanding of these steps, it is recommended to visit Project.net Component List to access detailed specification of components.
Step 1 - Specify a high-level requirement for the component
In order to state a high level requirement, we might use the user story as a starter (written by a business owner), and add some minor details in case of need.
Look a the next high level requirement, taken from the Grid Component:
The user needs to see all tasks related to a project, displayed on a table, where he/she could add/remove columns as per him/her need, order by column, move columns, as also add/update/remove data.
Step 2 - Write a draft list of Provided Interfaces
By reading the high-level requirements, identify all possible actions it would make sense. Then, check them with the business owner, and add/remove as needed.
Based on our Grid Component example, we could define next interfaces (go to the component page to see the full specification):
Now we have the high level requirement, we are able to write a draft list of what the component will provide:
- Display the grid data
- Add a column: it means show a column
- Remove a column: it means hide a column
Step 3 - Write a draft list of Required Interfaces
Next step is to write the services required to fulfill a smooth operating of the component. For instance:
- Specify from where the data will be retrieved: a data store.
- Specify a way to add columns.
Step 4 - Put all interfaces into a draw, and review if there is something missing
Step 5 - Detail the Interfaces
We have to set the name of different services, its signatures, as well as the declaration of error messages. The resulting specification (contract) will guarantee that client and provider will technically communicate with each other.
It is proposed to use the IDL (Interface Definition Language -- www.omg.org) as a notation to detail the interface:
interface ExampleCopmonent{ typedef string URL; struct Column{ unsigned short ID; string dataIndex; string header; boolean hidden; any renderer; unsigned short width; } sequence <Column> Columns; void init(in string placeToBeRendered); void showColumn(in unsigned short columnId); void hideColumn(in unsigned short columnId); }; interface extern{ void setDataStore(in URL url); void addColumn(in string dataIndex, in header header, in boolean hidden, in any renderer, in unsigned short width); }
Step 6 - Specify the Component Behaviour
In order to improve the confidence of using a component, it is needed to describe the services which are offered by it.
Whereas the Steps 5 primarily addresses syntactic issues of using the component, in this step we will specify the behaviour of the component services in a general way, and specifically in worst case scenarios. For that purpose "pre" and "post" conditions of using a service and possible invariants are defined.
It is proposed the OCL (Object Constraint Language -- www.omg.org) as a notation for the component behaviour. Also, it is recommended to annotate each OCL expression with comments.
For example, next expression specifies that service "hideColumn" may only be called if a column with the given ID exists:
ExampleComponent::hideColumn(id:columnId)
pre : self.Columns->exists(col:Column | col.ID = columnId)
Step 7 - Specify the Sequence Interaction
Sometimes it is necessary to define sequences in which the services of a component are allowed to be used. For instance, the service show me that column may only be called after the sercive init and display the component. Defining these interaction sequences aims to specify dependencies among the services.
As in Step 6, it is recommended to use the OCL notation, adding some temporal operators (see Reference [CON]):
- sometime_past condition: condition was true at one point in the past.
- always_past condition: condition was always true in the past.
- condition1 sometime_since_last condition2: condition1 was true sometime in the past sincethe last time condition2 was true.
- condition1 always_since_last condition2: condition1 was always true since the last time condition2 was true.
- sometime condition: condition will be true sometime in the future.
- always condition: condition will be true always in the future:
- condition1 until condition2: condition1 is true until condition2 will be true in the future.
- condition1 before condition2: condition1 will be true sometime in the future before condition2 will be true in the future.
- initially condition: At the initial state conditition is true.
Please note you may specify interactions with free text, of other notation, what's important is interactions must be clearly specified.
Based on our example, we may specify the sequence of show me that column - init and display the component, as follows:
ExampleComponent::showColumn(id:columnId)
pre : sometime_past
(ExampleComponent::init(place:placeToBeRendered))
Step 8 - Specify the Expected Quality
Now the functional characteristics were addressed, it is time to define the non-functional qualities of the component.
Such characteristics could include availability, error recovery time, throughput itme, response time, etc.
Various quality parameters depend on the boundary conditions of the runtime environment (i.e.: memory size, processor type and number, etc.). Therefore, it is essential to define these boundary conditions accurately. If the boundary conditions are only fuzy, then it is impossible to measure objective quality criteria.
It is not the intention to define a overall procedure for quality measuring, but in general, we should take into account this next steps:
- Define the quality framework: portability, applicability, efficiency, reliability, maintainability, etc. (we could use the ISO 9126 model for this purpose)
- Identify the quality criteria: response time, throughtput time, CPU workload, network load, etc. (we could use the Goal/Question/Metric method -- see Reference [SOL])
- Determine the measurement methods: expertise, estimation, analysis model, benchmark, etc.
- Speciry the quality criteria: formula notation, UML diagrams, etc.
For example, the quality of the service orderColumn, when the service is called for the work column with randomly numbers with uniform distribution which lie in the interval 1 to 10000, we could specify the quality for this service as follows:
| Quality criteria | Specification |
| response time | 10 ms |
| response time distribution | 0.0021 ms |
References
[CON]: Conrad, S.; Turowski, K.: Vereinheitlichung der Spezifikation von Fachkomponenten auf der Basis eines Notationsstandards. In: J. Ebert; U. Frank (Eds.): Modelle und Modellierungssprachen in Informatik und Wirtschaftsinformatik - Beiträge des Workshops "Modellierung 2000", St. Goar, 5.-7. April 2000. Koblenz 2000, pp. 179-194.
[SOL]: Solingen, R. v.; Berghout, E.: The Goal/Question/Metric Method - A Practical Guide for Quality Improvement of Software Development. London et al. 1999.
See also: Project.net Component List
Attachments
- ExampleComponent.JPG (9.1 kB) -
Example Component
, added by carlos on 05/15/08 06:56:44.
