modularize interfaces
0.9.3Programmatical interfaces extension for Modularize
Table of Contents
About Modularize-Interfaces
This is an extension to Modularize that allows your application to define interfaces in-code that serve both as a primary documentation and as compliance control. Other modules can then implement interfaces to provide the actual functionality as outlined in the definition. A good example for a scenario in which this would be useful is databases. If other parts of the application can rely on a standardised interface it won't matter which database is really connected underneath and the type of database connection can be switched without having to change any of the other modules that rely on this functionality.
How To
Interfaces are defined through DEFINE-INTERFACE. These calls consist of a name (or a list of names) for the interface and a body of component definitions. You can define your own components, but more on that later. By default there are components for functions, macros, generic functions, methods and classes. A simple interface might look like so:
(define-interface radio
(defun listen (frequency)
"Listens on a given frequency for radio signals and outputs them.")
(defun scan ()
"Attempts to search the radio frequency range for recognisable signals.")
(defun broadcast (station)
"Starts up the given radio station to broadcast.")
(defmacro define-station ((name frequency) &body body)
"Defines a new radio station on the given frequency.")) This will generate you an interface with the specified stub forms. Calling any of these functions before an implementation actually implements the interface will result in an error. In the back, DEFINE-INTERFACE creates a module through DEFINE-MODULE and then expands the specified components.
If a module wants to implement an interface, it can define this in the :IMPLEMENTS module-option. It will then be automatically set up as the current implementation. Otherwise you can also directly do (SETF (IMPLEMENTATION :interface) :my-module). If an interface is already implemented by another module, a condition is raised with restarts to either abort, delete the old module or override it. After an implementation is set, TEST-INTERFACE is called to check for compliance. Compliance checks must be implemented by the respective components and may or may not be sufficient to test for true interface compliance. If an implementing module gets deleted, RESET-INTERFACE is called, which returns it to its old state with error-ing stub definitions.
Defining the actual components of the interface in your module works just like writing any other function or whatever part it is in effect. You may want to use the provided I-* macros for the standard components though to make the intent more visible.
Adding new components to use in interface definition happens through DEFINE-COMPONENT-EXPANDER. This should evaluate to whatever stub forms you need, optimally resulting in an error if a user tries to access it without a conforming implementation in place. Additionally you will most likely want to add a DEFINE-COMPONENT-TESTER for each of your components. This is a simple function definition that is called whenever TEST-INTERFACE is invoked and should return two values, a boolean whether the test failed or not and a string that explains the reason for failure or passing. TEST-INTERFACE will convert this into warnings. It is discouraged to signal errors as this would prevent other components from being tested too and may interfere while developing an implementation.
For a super small sample use of an interface, have a look at interfaces-test-implementation.asd, interfaces-test-interface.lisp and interfaces-test-implementation.lisp.
System Information
Definition Index
-
MODULARIZE-INTERFACES
- ORG.SHIRAKUMO.RADIANCE.LIB.MODULARIZE.INTERFACES
- INTERFACES
No documentation provided.-
EXTERNAL CONDITION INTERFACE-ALREADY-IMPLEMENTED
Condition signalled if an interface is already implemented by a different module than was attempted to register as an implementation.
-
EXTERNAL CONDITION INTERFACE-NOT-FOUND
Condition signalled if an interface was requested but could not be found.
-
EXTERNAL FUNCTION COMPONENT-ALIAS
- ALIAS
Returns the actual component name the given alias points to or itself if it is not resolved..
-
EXTERNAL FUNCTION (SETF COMPONENT-ALIAS)
- COMPONENT
- ALIAS
Sets a new alias for the given component-name.
-
EXTERNAL FUNCTION GENERATE-INTERFACE-STUB
- INTERFACE
- &OPTIONAL
- PACKAGE
Generates a stub for the INTERFACE that you can use as an implementation starting point. Symbols are interned into PACKAGE where appropriate.
-
EXTERNAL FUNCTION IMPLEMENTATION
- INTERFACE
Returns the currently active implementation of the interface.
-
EXTERNAL FUNCTION (SETF IMPLEMENTATION)
- IMPLEMENTATION
- INTERFACE
Attempts to set the implementation of an interface. Interfaces can only be implemented by modules and if a different module already implements the interface a condition is signalled. The following restarts are available: DELETE Deletes the old implementation through DELETE-MODULE. OVERRIDE Overrides the implementation and leaves the old module. ABORT Aborts the setting of the implementation completely. If the implementation setting was successful, TEST-INTERFACE is called. If the implementation is set to NIL, RESET-INTERFACE is called.
-
EXTERNAL FUNCTION IMPLEMENTS
- MODULE
Returns a list of interfaces this module implements.
-
EXTERNAL FUNCTION INTERFACE
- OBJECT
Returns the interface package module as identified by the object. See MODULE for more.
-
EXTERNAL FUNCTION INTERFACE-P
- OBJECT
Returns T if the passed object is or names an interface, otherwise NIL.
-
EXTERNAL FUNCTION PRINT-INTERFACE-STUB
- INTERFACE
- &OPTIONAL
- PACKAGE
Print the stub of GENERATE-INTERFACE-STUB in a way that is easily copy-pastable.
-
EXTERNAL FUNCTION RESET-INTERFACE
- INTERFACE
Resets the interface by redefining it with stubs as per its component definitions.
-
EXTERNAL FUNCTION TEST-INTERFACE
- INTERFACE
Tests the interface for definition conformity. See TEST-COMPONENTS.
-
EXTERNAL GENERIC-FUNCTION EXPAND-COMPONENT
- TYPE
- ARGS
- &KEY
- INTERFACE
- &ALLOW-OTHER-KEYS
Generic function used to expand components into their proper forms.
-
EXTERNAL MACRO DEFIMPL
- NAME
- &REST
- ARGS
Expands to I-DEFMACRO, I-DEFMETHOD or I-DEFUN depending on what kind of symbol it names.
-
EXTERNAL MACRO DEFINE-COMPONENT-EXPANDER
- NAME
- INTERFACE
- &REST
- ARGUMENTS
- &BODY
- BODY
Defines a new component expander for interface definitions. The NAME can be a list of names that will be aliased to the first one. All names will be turned into keywords to allow for differing naming schemes in the component definitions. INTERFACE should be a symbol to which the interface package is bound. ARGUMENTS is the lambda-list used to deconstruct the arguments of the component definition.
-
EXTERNAL MACRO DEFINE-COMPONENT-TESTER
- NAME
- INTERFACE
- &REST
- ARGUMENTS
- &BODY
- BODY
Defines a new testing method for a component type. The structure of this macro is the same as for DEFINE-COMPONENT.
-
EXTERNAL MACRO DEFINE-INTERFACE
- NAME
- &BODY
- COMPONENTS
Defines a new interface. This defines a new module with the given name and nicks, as well as a fully qualified interface identifier which is the name prefixed by MODULARIZE.INT. . It then calls EXPAND-INTERFACE on the new module and finally expands the component definitions as per EXPAND-COMPONENTS.
-
EXTERNAL MACRO DEFINE-INTERFACE-EXTENSION
- NAME
- &BODY
- COMPONENTS
Currently not implemented.
-
EXTERNAL MACRO DEFMACRO*
- NAME
- ARGS
- &BODY
- BODY
Expands to a conditional macro definition that only happens if either *REDEFINE* is T or the macro has not yet been defined.
-
EXTERNAL MACRO DEFMETHOD*
- NAME
- &REST
- ARGS
Expands to a conditional method definition that only happens if either *REDEFINE* is T or the method has not yet been defined.
-
EXTERNAL MACRO DEFUN*
- NAME
- ARGS
- &BODY
- BODY
Expands to a conditional function definition that only happens if either *REDEFINE* is T or the function has not yet been defined.
-
EXTERNAL MACRO I-DEFMACRO
- NAME
- ARGS
- &BODY
- BODY
Expands to an interface macro definition.
-
EXTERNAL MACRO I-DEFMETHOD
- NAME
- &REST
- ARGS
Expands to an interface method definition.
-
EXTERNAL MACRO I-DEFUN
- NAME
- ARGS
- &BODY
- BODY
Expands to an interface function definition.