Defining Software Structure, Software Skin and Software Services

Software Structure.

The next major task is to define the Software Structure of the software system. At this stage, this means finding a high-level subdivision of the system into constituent components. These components should use semantics from the application domain, and they result as part of the decision of which Software Structure to use. However, eventhough we are aware of the different aspects, it is difficult to organize all of them into a workable structure. Some architectural patterns may be helpful here to perhaps obtain a useful organization previously used. Due to the characteristics of this problem, potential solutions could be the Blackboard pattern and the Layers pattern [POSA96]. As we are trying this example to be illustrative of the architectural approach to the present problem, a two layered Software Structure is simple enough to be proposed. Therefore, our initial approach is to divide the set of components between two groups: those which hold the state of the system, and those which perform functionality. We start following this order.

First, let us provide a place to keep the system state. Data components seem a good place to allocate behaviours related to looking up specific components and creating new system state components. Basically, they provide entry points into the system state for the application. At this stage, without detailed static or behaviour definition, the best we can do is to guess at what the main entry points are. We can check those guesses with other similar cases, or perhaps some design patterns related with the chosen Software Structure. However, a complete evaluation will have to wait until results of the detailed behaviour design are available.

In addition to defining data components, we should have some idea of their contents and responsibilities, as they will hold the system state, and can serve system state components to whomever asks for them. On the other side of the data components we should have a database interface. The design decision is that there should be no explicit database dependencies in the data components. They should be responsible only for maintaining their own state as long as the state can be determined with information available within the component itself. All of those opinions on the behaviours of the data components represent behaviour allocation definitions. They are not final specifications and will have to be confirmed by evaluation against external requirements that our system is supposed to support.

Next, we define functional components to provide for functional extensions. This definition process is subject to the additional constraint that the functional components must provide the units of functional growth, change and configuration. The final Software Structure components obtained from the functional requirements are as follows:

When we developing the functionalities list, we have concentrated on handling extensions, so we can take this list as good enough for now. However, having the whole picture to look at makes a potential problem when defining connections between components in subsequent layers visible: how to arrange the connections between the future Software Skin dialogues and the functional components. Changing which functionalities are available to an individual user, and adding new functionalities in the future, are common change cases, and we aim to keep Software Structure as stable as possible during the system's lifetime. Those changes will take place on either side of the connections that relate the functionalities to the dialogues. The question is, do we need one connection, that is, one set of messages, for each kind of functional component, or can we use the same connection for all functional components?

The advantage of the one-connection approach is that adding a new functionality will not require changes to the external interfaces of the Software Skin dialogue components. Whether it requires changes to the internal interfaces of the dialogue components depends on where we allocate the responsibility for keeping the list of available actions for each functional component. The most flexible arrangement would be for the functional components to provide the command choices to the dialogues. This would make adding a new service a matter of registering the functionality with the dialogues that will offer it. This behaviour allocation scheme should be kept in mind when we define the Software Skin dialogues, and allocate the detailed behaviour to each one of them. This seems a good solution. However, we will return to this problem when defining the Software Skin of the system. The architectural description of the software system look now like Figure 3.

Software Skin.

Software Skin should provide the system for user independence. Dialogue components are responsible to carry out the mapping between events and requests from outside users and the functionalities and resources inside the system. Functionalities visible to the user may be provided by coordinating the outputs of several of the internal functional components.

Initially, dialogue components may be associated with the user they serve or with the functionalities they coordinate. The user dialogues will include sales clerk, inventory clerk, manager, and accountant. The usage-sequence dialogues are check out, check in, inventory access, reporting, and administration.

This set of dialogue components was arrived with some written ideas on our part of what kinds of responsibilities they will have. The user dialogues will be responsible for indicating which functionalities are available to their respective users, interpreting the users' requests and for invoking the appropriate sequence of control signals to have those requirements carried out. The operation-sequence dialogues will be responsible for actually managing the interaction between user and system while the user is checking out a video or adding to inventory. They will also be responsible for invoking the proper sequence of internal functionalities to provide the external services the user is requesting. This responsibility allocation will leave the user dialogues as "menu servers" for the users, which may be all right.

This meditation leads to the conclusion that the main unit of configuration should be the user, and perhaps the architecture should reflect that fact. Since it seems like the operation-sequence dialogue information will have anyway to be replicated for multiple users, the responsibilities originally allocated to the operation-sequence dialogues could be reallocated to user dialogues. This will leave us with a single level of dialogue components (Figure 4).

The responsibility description then is as follows: the user dialogues are responsible for all dialogue management with each kind of user. Each dialogue component will be configured with the appropriate controls for that user. The dialogue will invoke the appropriate sequence of operation and resource requests to provide the requested functionality. At this stage, the name and number of each port are just a guess, but they should correctly reflect the fact that the functionality allocated to the operation-dialogue components has not been reallocated to the user-dialogue components. Therefore, the Software Skin dialogue components obtained are as follows:

Software Services.

In general, Software Services are responsible for receiving and sending information to the system outside, so they are usually associated with a port and their behaviour is dependent primarily on the nature of the device connected to the port, or ports, they are serving. There should be at least one per port, unless two ports share the same information (for example if the connection is a network with several different kinds of users on the other end). In particular, Software Service components are appropriate for any interface that requires significant translation between the formats on the inside of the system and the formats on the outside. Printers, networks, and databases are examples of external systems that can use a separate Software Service (Figure 5).

In order to provide for services independence in this system, we propose to define one Service component for each of the ports connected to peripherals. The network port, for instance, may have several kinds of devices connected to it (for example storage systems and remote users). For now, we will assume that the component needed for remote users is different from the component needed for local terminals, so we define a remote user component and a storage component to serve the network port as Software Service components. When the design is more stable, these component definitions can be changed with little effect on the neighbouring systems.


Contact Information

Jorge Luis Ortega Arjona

E-mail jortega-arjona@acm.org