KeywordsProgramming Language Unify Modeling Language Software Module Java Modeling Language Common Object Request Broker Architecture
An interface describes the functionalities exported by an entity such as a software module. These functionalities typically consist in named operations with signatures describing potential arguments and return values, but interfaces may also include the definitions of data types, constants, exceptions, or even describe semantics.
Interfaces shield the internals of corresponding software modules from the outside, providing several benefits. Interfaces provide abstraction, in the sense that the internals of modules may evolve while other modules can still rely on the same functionalities (encapsulation). Safety and security are promoted by interfaces as these define single access points to respective software modules.
In object-oriented programming, software modules often coincide with classes, which also describe data types implicitly. In the case of such a class, an interface is thus roughly made up of the methods exported by the class. Mostly, interfaces are then defined implicitly by the classes as such sets of exported methods, but languages such as Java provide programmers the possibility of declaring interfaces as first class citizens which are then explicitly implemented by classes.
When objects are physically distributed, they can offer specific remote interfaces facilitating invocations potentially coming from remote hosts. Remote interfaces span typically only a subset of all the methods exported by objects.
A set of interfaces which describe an entire software component or framework is more commonly referred to as an application programming interface (API).
The concept of interface has partly evolved out of the header files used with the C programming language. In contrast to several more recent programming languages providing notions of interfaces integrated with the language semantics, those header files served mainly as preprocessing feature.
Interfaces were greatly popularized by programming languages based on modules, such as Pascal, Modula-2, or Ada. A first step towards a more rigorous underpinning of modules and measures for a good decomposition of software into such modules was provided by Parnas . Parnas’ work primarily aimed at achieving a clean separation of duties in software components and an effective decomposition into modules. As a dual of this problem, the design process for interfaces to modules has also been strongly guided by Parnas’ seminal work, coining the term “well-defined interfaces.” The main driving force behind the quest for clear-cut interfaces are safety/security concerns aiming at providing well-defined entry points to given modules in the form of interfaces.
The term interface itself thus emerged from the software engineering community. Ever since, programming languages have been strongly influenced by this notion, in particular because there is a strong overlapping between the notions of interface and type (data type). This culminates in object-oriented programming, where data types and modules are largely unified through classes representing the units for both data abstraction and behavior, and thus a type defines the interface to its instances, even if only implicitly (cf. ).
More recently, modeling languages such as the Unified Modeling Language (UML) have also introduced interfaces aside classes as purely descriptive means of capturing functionalities of objects.
Interfaces describe the functionalities exported by an entity such as a software module. These functionalities typically consist in named operations with signatures describing potential arguments and return values, but interfaces may also include the definitions of data types, constants, exceptions, or even more information.
Interfaces and Classes
Most object-oriented programming languages are class-based, meaning that classes present the main unit of decomposition and as such can be viewed as modules. Interfaces of such classes encompass the functionalities exported by these classes – typically a set of methods which are accessible to other classes. In many integrated development environments (IDEs), there is the possibility to automatically “extract” such an interface view from a class, by only summarizing the names and signatures of its exported features.
Interfaces can be in that sense seen as abstract types, as opposed to classes which may implicitly describe interfaces, but primarily describe the implementation of those. Current programming languages such as Java provide interfaces as a first class construct aside classes. Declaring an interface leads to defining an abstract type. In this case, an object can provide several interfaces if its class implements several instances; the conceptual interface of the instance(s) is then made up of the union of these interfaces.
When collapsed with types, interfaces reap the benefits of the Liskov substitution principle , which states rules under which a type T1 can be considered to be compliant with another type T2. Instances of T1 can then be used whenever entities of type T2 are expected. Transposed to interfaces this means in short that the interface of the latter type subsumes the interface of the former type: any module that builds on the former interface can be presented with an instance of the latter interface.
Conceptual interfaces are sometimes decomposed according to potential beholders of references to the corresponding entities. More precisely, different objects, or more generally different modules, can have access to the same entities through individual interfaces. By supporting different visibility rules (e.g., private, public, protected), possibly at the method level, programming languages provide the ability to restrict interfaces (or parts of such interfaces) to families of classes for example based on containment criteria (e.g., packages). In C++ for instance, a class C1 can be explicitly declared to be a friend of another class C2, providing instances of C1 access to certain methods of class C2 which are otherwise unreachable. Introducing varied levels of protection yields different (accessible) interfaces for different parties.
For languages with weaker inherent support for interfaces and protection levels, design patterns can be used to enforce constraints. The read-only interface pattern for instance is used to explicitly define an interface through which entities can be manipulated without modifications to their state.
In remote method invocations, remote interfaces are used to explicitly offer methods for invocation from remote hosts. Remote interfaces usually span only a subset of the methods provided by a class. The remaining methods however are limited to invocations within the same address space. In that sense, remote interfaces introduce a specific level of protection.
Remote interfaces commonly enjoy descriptions in a dedicated specification language, when interoperability is desired. Such specification languages allow the description of remote interfaces in an interoperable format, and subsequent generation of language-specific versions with corresponding compilers based on well-defined mappings to target languages. Examples are the interface definition language (IDL) used in the Common Object Request Broker Architecture (CORBA), or more recently the web service description language (WSDL). An earlier incarnation is the external data representation (XDR) introduced with the remote procedure call (RPC) protocol. Compilation of such interfaces commonly goes hand in hand with the generation of proxes or stubs which take care of transforming method invocation arguments and return values to and from an interoperable format such as XDR.
Besides methods, interfaces can also include constants, exceptions, and sometimes even fields, though exporting fields is sometimes viewed as going against the principle of encapsulation underlying object-oriented programming. In the Eiffel programming language, methods are unified with field (accesses), implicitly yielding access methods for fields. Eiffel is also the most popular language with further semantic descriptions in the interfaces, consisting in contracts in the form of pre- and postconditions for methods, as well as invariants at the class level. These were introduced as part of the original definition of abstract data type , and have given rise to a design paradigm called design by contract (DbC) .
In the case of Eiffel, its IDE also allows the programmer to view the interface of a given class, in this case including contracts. Contracts have a descriptive flavor in the sense that they augment interfaces and thus represent a specification feature, but also have an implementation flavor since they may refer to fields, and can be monitored at runtime as in Eiffel. Spec# follows the Eiffel approach by providing first class support, while the Java Modeling Language (JML) promotes annotations, which can be viewed as optional semantic interface descriptions, to which programmers only must adhere when making use of specific tools (e.g., for compilation).
Besides contracts, other types of information have been considered for augmenting interfaces. Typestates  capture abstract states associated with instances of a given type and their relationship with exported methods, thus adding state information to interfaces. Interface automata  focus directly on the order in which functionalities exposed by a given interface can be triggered. Such sequences are sometimes also colloquially referred to as protocols. Resource interfaces  are another example of augmented interfaces, describing namely the physical resources necessary for a given module to be able to function properly.
In software engineering, in particular in the component view, interfaces may similarly contain far more information than types. A component usually refers to a subsystem of its own consisting in several modules, whose individual interfaces make up the conceptual interface. The interface of a component can for instance also define what kind of interface the component itself relies upon (while this is usually somewhat embedded in object-oriented code).
When several interfaces are bundled either in the context of a component, or a framework, the term application programming interface (API) is commonly employed. The different levels of technical protection for functionalities offered at the programming language level are in the case of APIs often complemented by simply limiting the disclosure of APIs to selected corporate players only.
Complexity. With the increasing complexity of computer systems, the problem of “efficiently” decomposing/composing software is given more and more attention. Abstraction and encapsulation are key desired properties. In software engineering terms, one attempts to achieve decoupling and increase modularity (For a precise definition of modularity see ). The art of decomposing software is also partly captured by the study of software architectures. There is a clear dependency between the decomposition of software into modules and the discipline of designing interfaces between modules/components to respect modularity and achieve low coupling.
Reuse and maintainability. These are also desired features of any software package. With good design and modularity reflected in rich interfaces, code namely also becomes easier to reuse and maintain.
Safety. Safety has become a major driving force for programming language and software engineering research. Ensuring that interaction between (sub-)modules takes place in a safe manner helps avoiding runtime errors, and is supported by clear-cut and precise interfaces. In the predominant settings with static typing, the goal is to ensure that once successfully compiled, a module contains no calls violating interfaces.
Security. Access rights and confinement can be expressed in interfaces as mentioned above. This becomes particularly visible in distributed settings, i.e., for achieving clean interfaces between entities running on distinct physical hosts.
Interoperability. Not all software is written in the same programming language. With interfaces being described in “neutral” generic languages interoperability can be achieved. Examples are clearly provided by interface definition languages (IDLs) for second class distributed object packages such as DCE, CORBA, or DCOM. The idea of interoperability has more recently flown into service-oriented architectures (SOA) in general and Web Services in particular.
Evolution. Low coupling and modularity definitely support evolution of components, but as mentioned above, only in terms of the internals of components. Evolution of components sometimes also necessitates evolution of their interfaces, which can however break any existing code relying on these. Evolution of interfaces is thus an important area to investigate. In programming language terms, this leads to the problem of extending and changing types, which can be partly addressed by introducing versioning, and by assisting the programmer in the adaptation of code after changes to interfaces it relies upon.
Information. Interfaces describe contracts between modules, i.e., functionalities provided by a module and sometimes also requirements for providing these functionalities. So far, interfaces are mostly described through functional aspects of the modules which in programming language terms boils down to syntactic and typing information. Design by contract (DbC) augments these interfaces with semantics, but further information might be of relevance, which is not even directly materialized in the implementation of modules, as illustrated by resource interfaces .
Discovery. Interfaces and extended interfaces can also be obtained by mining existing modules, e.g., . This is particularly appealing when dealing with legacy code, which might have been described in a programming language with weak inherent support for interface descriptions. Discovery of interfaces has also gained more interest recently in the realm of aspect-oriented programming (AOP), whenever aspects advise code obliviously, i.e., without knowledge or consent from the main code. In the AOP philosophy aspects attempt to achieve a separation of duty by implementing crosscutting concerns in aspects alike modules, separately from the base code. Without clean interfaces for the interaction between base code and aspects however, reasoning about an entire software becomes hard (cf. ).
Discovery can also be understood in the sense of discovering services at runtime. Especially SOAs provide strong support for finding services based on their functionalities, often described as some abstract interfaces. UDDI is an example of a lookup service that supports queries based on a specific notion of interface.
- 1.Beyer D, Henzinger TA, Singh V. Algorithms for interface synthesis. In: Proceedings of 19th international conference on computer aided verification. 2007. p. 4–19.Google Scholar
- 3.Chakrabarti A, de Alfaro L, Henzinger TA, Stoelinga M. Resource interfaces. In: Proceedings of 3rd international conference on embedded software. 2003. p. 117–33.Google Scholar
- 4.de Alfaro L, Henzinger TA. Interface automata. In: Proceedings of 9th ACM SIGSOFT international symposium on foundations of software engineering. 2001. p. 109–20.Google Scholar