First-Class Procedure Type System for Object-Oriented Composition
Join the DZone community and get the full member experience.Join For Free
This is the first article in a series looking at the Inversion of Coupling Control type systems for composition. The series will demonstrate how the resulting type system allows for easy composition. This allows us to avoid much of the complexity of functional/object-oriented composition.
This series has four articles:
- This article discussing the First-Class Procedure type system
- First-Class Module
- Demonstration application.
- The underlying theoretical model for composition.
This article will look at the type system and composition of First-Class Procedures.
We've previously talked about the OO Matrix and how the method (and for that matter, the function) suffers from coupling. We've also discussed how this coupling can be reduced by the Inversion of Coupling Control. We've also shown how these inverted methods/functions can be weaved seamlessly together. We've even seen the industry moving towards these concepts with microservices.
What we haven't yet discussed is the type system and composition available with First-Class Procedures.
To discuss this, let's start with the well-known concept of Dependency Injection.
You may also like: Local Microservices: First-Class Procedures.
Meta-data of dependency injection describes a list of dependencies with the following three attributes:
- Field (or constructor parameter) to inject the dependency (providing the dependency's name - e.g. field name)
- Type of the dependency
- Optional qualifier (distinguishes dependencies of the same type)
With this information, the matching to dependencies can be undertaken. Note, some dependency injection frameworks have improvements on this. However, the above meta-data is typically adequate for auto-wiring dependencies of the object.
Continuation Injection reduces a function/method invocation to a similarly simple set of attributes (similarly to Dependency Injection).
As only a single parameter can be passed (remaining are dependency injected), there is only one type required. This is the optional parameter type. Also, the continuations from the First-Class Procedure are all named.
Note that auto-wiring continuations is deemed error-prone. Automatically wiring continuation to matching First-Class Procedures requires different parameter types for each continuation in the system. In practice, most of the time, it is the same simple domain data types being passed around. So, you end up having to qualify every continuation.
Furthermore, qualifying continuations provides little improvement in reducing complexity. In qualifying all continuations, you end up writing configurations for each continuation. In other words, you end up providing a mapping of each continuation name to servicing the First-Class Procedure. This configuration is very error-prone. We will demonstrate how this is made less error-prone and can be easily comprehensible shortly.
Therefore, each required continuation by the First-Class Procedure is described with the following meta-data:
- Name of the continuation.
- Type of the parameter for the continuation (i.e. type of argument sent to continuation).
Note that exceptions from the method/function are also modeled as continuations. The type is the exception type. The name is the name of the exception type.
First-Class Procedure Type System
Putting the Continuation Injection meta-data together with the Dependency Injection meta-data, we get the following meta-data (type) information for the First-Class Procedure:
The above type can describe all First-Class Procedures. As a method/function requires parameters, these are described by the
DependencyType listing. As method/functions require calling other methods/functions, this is described by the
ContinuationType listing. As there is only one parameter to the First-Class Procedure, the parameter type describes the type of argument that must be supplied by invoking
Note that we have not discussed Thread Injection typing. This is actually derived from the
DependencyType listing by matching an object's type to a thread pool. See Thread Injection for more information.
As we now can type the First-Class Procedure, we can look at using this type system for composition.
First-Class Procedure Composition
The composition of First-Class Procedures is focused on wiring continuations together. Dependency Injection provides the objects (state) to the methods/functions. This wiring of dependencies is done separately to the continuations. Therefore, we only need to focus on the continuations being wired to servicing their First-Class Procedures.
Now, it is possible to do this in code and even configuration files. However, as the system grows in complexity, this hard-coded specificataion of continuation name to servicing First-Class Procedures becomes very unwieldy. Trying to decipher the system behavior from lists of linkages becomes very difficult.
Therefore, we look at the First-Class Procedure as the following:
- A processing node with an input anchor.
- A varying number of output anchors for each of its continuations.
- Linkages as lines from the output anchor to input anchor.
This representation makes for a graphical configuration of the composition. The First-Class Procedure is defined by nodes in the graph with lines representing the continuations between them. Therefore, the composition of First-Class Procedures is quite literally drawing lines between them.
As the graphical configuration is easy to comprehend visually, it makes it very easy for other developers to understand the application.
We have demonstrated how Continuation Injection simplifies the invocation of methods/functions. This simple meta-data model for Continuation Injection is similar to Dependency Injections for objects.
This simple meta-data enables a type system for First-Class Procedures. This type system enables the graphical composition of First-Class Procedures.
The next article will discuss how the First-Class Procedure type system is actually made more general to enable modularising of the application. However, these modules still maintain a similar type system for inclusion in the graphical configuration.
Published at DZone with permission of Daniel Sagenschneider. See the original article here.
Opinions expressed by DZone contributors are their own.