• No se han encontrado resultados

SECTOR DE FORTALECIMIENTO INSTITUCIONAL

RECURSO PROPIO.

When programs first started becoming large, composed of hundreds of procedures, it became necessary to process them in chunks, both for practical implementation considerations and for better structuring. Eventually this trend led to modules and interfaces.

Today programs are starting to become huge, composed of hundreds of interfaces, and the same problems are reappearing one level up. Modules and interfaces, as we have considered them so far, have a flat structure; when there are too many of them it is hard to figure out the organization of a system. More importantly, a group of interfaces may be intended to be private to a given subsystem, and should not be accessible to other subsystems.

It would clearly be desirable to be able to group interfaces into systems which could then be grouped into larger systems, and so on. We cannot just syntactically nest modules and interfaces and hope to solve the problem: separate compilation is then prevented. Also remember that the flat structure of modules is an advantage because it escapes the strict block scoping rules.

In this section, we examine a way of describing systems of interfaces, while remaining compatible with our previous notions of modules and interfaces. One of the main goals is to be able to reorganize the structure of a subsystem (including its inner interfaces) without affecting the other subsystems that use it; this is similar to a separate compilation criterion for modules.

We classify systems as open, closed, and sealed. To make an analogy with hardware, an open system is like a hardware box without a cover; anybody can plug wires into it. A closed system is a hardware box with a cover but with expansion slots: one can plug wires only into the outside connectors, but one can also add a new piece of hardware (with related external connectors) that has internal access to the box. Finally, a sealed system can be used only through the provided connectors.

8.1. Open systems

Consider the following system organization, illustrated in the diagram. A system U is composed of two (sub-) systems S and T. System S is composed of three interfaces A, B, and C (where A imports B and C) with corresponding modules a, b, and c. System T is composed of a single exported interface D, which imports A and C.

A

B

C

D

U

S

T

We express this arrangement by the following notation:

system Usystem S of Usystem T of U

end; end; end;

interface A of Sinterface B of Sinterface C of S

import :B :C export ... export ...

export ... end; end;

end;

interface D of T

import :A :C

export ...

end;

Each interface can import all other interfaces directly, without mentioning which systems they belong to; this seems necessary to facilitate system reorganizations. Moreover, a new interface E could join system T just by claiming to belong to it.

The reason these systems are open is that there are no restrictions regarding membership or visibility. Their structure can be reorganized very easily just by changing membership claims and without affecting unrelated parts; this flexibility is important in large evolving systems. At the same time, the membership claims provide some degree of structuring.

8.2. Closed systems

The next step is to restrict visibility across system boundaries; system S may declare that only interfaces A and

B and module a:A are exported, thereby preventing D from importing C. Similarly, system U may declare that only the interface A of S is available outside U. In general, when an interface I imports another interface J, either there

must be no closed system barriers between I and J, or if there are such barriers, J must be exported through all of them.

system Usystem S of U

export :A of S export a:A :B

end; end;

interface D of T

import :A

export ...

end;

A closed system still does not prevent interfaces from spontaneously joining it. Moreover we allow interfaces to be members of multiple systems. Hence interface D could counteract the closure of system S by claiming to belong to S too, thereby being able again to import C:

interface D of T,S

import :A :C

export ...

end;

What is the point of closing a system and still allowing interfaces to join it? The idea is that in joining a system one explicitly declares the intention of depending on its internal structure, while simply importing an interface provided by a system declares the intention of not depending on any implementation details of that system.

Note that we still have a single name space for interfaces and modules. This is a doubtful feature, but this way interfaces and modules can be moved from one system to another without the programmer having to modify all their clients.

8.3. Sealed systems

The final step is then to prevent "unauthorized" membership in a system. To seal system S, a line is added that explicitly lists all the interfaces (and modules) that are allowed to belong to S, in this case A, B and C (and modules

a and c). At this point D is again cut out of S and prevented access to C, although D could be added to the component list of S if desired:

system S of U

components a:A :B c:C export a:A :B

end;

A sealed system provides a solution to the problem of implementing large abstract data types. In ordinary module systems, if the implementation of an abstract type T spans several modules, say m1 and m2, then the representation of T must be made public through an interface, say I, to be imported by m1 and m2. This way the type ceases to be abstract, because everybody can see T through interface I.

The solution now is to add a new interface J exporting a real abstract type T and its operations; the implementation of J realizes T by I_T, imported from I, and implements the operations by importing them from

interface I of Wmodule m:I

export export

Def T = ... end;

end;

interface I1 of Wmodule m1:I1

import I import I

export export

f: ... let f = ...

end; end;

interface I2 of Wmodule m2:I2

import I import I

export export

g: ... let g = ...

end; end;

interface J of Wmodule n:J

export import :I m1:I1 m2:I2

T::TYPE export

f,g: ... Let T = I_T

end; let f = m1.f and g = m1.g

end;

system W

components m:I m1:I1 m2:I2 n:J export n:J

end;

The process of closing a system may reveal unintentional dependencies that may have accumulated during development. The process of sealing a system may reveal deficiencies in the system interface that have to be fixed.

It is expected that, during its evolution, a software system will start as open to facilitate initial development. Then it will be closed when relatively stable interfaces have been developed and the system is ready to be released to clients. However, at this stage developers may still want to have easy access to the closed system, and they can do so by joining it. When the system is finally quite stable it can be sealed, effectively forming a large, structured abstract type, for example an operating system or file system interface.