IoCC in Java: First-Class Module
IoCC in Java: First-Class Module
This article discusses a more general module type system than the previous article's First-Class Procedure Type.
Join the DZone community and get the full member experience.Join For Free
This is the second in a series looking at the Inversion of Coupling Control type system for composition. This article discusses a more general module type system than the previous article's First-Class Procedure Type.
Note: Some functional programming languages also attempt to define First-Class Modules. The First-Class Modules defined in this article are created from inverted functions.
To recap the last article, the First-Class Procedure's type is defined as follows. Note that we exclude the dependency type, as dependencies are auto-wired.
This defines the First-Class Procedure to have a single input parameter and multiple continuations out for further composition of logic and handling of exceptions.
You may also like: Function IoC for First-Class Procedure
Having a single input with multiple outputs is fine for methods, functions, etc. wrapped in First-Class Procedures. However, when systems grow, we don't want the complexity to make the inputs/outputs suffer similar increased complexity. We want the inputs/outputs to provide an interface to encapsulate the complexity of the Module. Note that without encapsulation, we don't get the ability to modularize the complexity of the application.
To enable an interface to the Module, let's create the following input/output types:
To understand why these types are created, we are going to use the visual configuration of the Inversion of Coupling Control to better aid our understanding of what is happening.
The following Module configuration represents a single input, handled by a First-Class Procedure that sends its result to an output:
In the above configuration, the First-Class Procedure is encapsulated in the Module. All that is exposed from the Module is the Inputs and Outputs. The resulting type of the above Module would be the following:
- Input named "Input" with a parameter passed to the First-Class Procedure
- Output named "Output" with the argument provided by the result of the First-Class Procedure execution
This, however, provides little improvement on the First-Class Procedure interface.
What becomes useful is the encapsulation of multiple First-Class Procedures to undertake functionality of the Module:
While a new procedure was included within the Module, there was no change to the interface of the Module. Other configurations using the Module would be unaware of the internal addition of another First-Class Procedure.
We also need not limit ourselves to single inputs and outputs. We could have an arbitrarily complex Module that has multiple Inputs and Outputs:
The resulting Module encapsulated the detail to have the following interface:
- Input "Input"
- Input "Input-2"
- Output "Output"
- Output "Output-2"
- Output "Output-3"
The resulting type for the Module is the following:
The Module (Section) has multiple inputs and multiple outputs. These inputs/outputs can then be connected to respective outputs/inputs of other Modules.
Furthermore, Modules may themselves contain other Modules. As inputs/outputs are connected for composition, Modules have the same input/output connectivity as First-Class Procedures. The following configuration demonstrates embedding the Module at the start of this article within another Module:
Whether it is the Module containing a single First-Class Procedure or two, a First-Class Procedure is encapsulated and not of concern within the above configuration. The use of the Module is only on the Inputs/Outputs exposed by the Module. The rest of the complexity of the Module is encapsulated. This allows modularising the application's complexity.
So, the title mentioned is "First-Class Modules," yet we've only discussed visually wiring together the Modules.
To essentially be "First-Class," the Module needs to be assigned to a variable. Yes, there are other conditions. However, for me, this is the simplest way of thinking about something being first-class.
The above graphical configuration is built on Sections (Modules) being configured together programmatically. The graphical configuration is actually a layer above the First-Class Modules (Sections) to enable easier comprehension of how the application is modularized.
You can see this in OfficeFloor's implementation of the graphical configuration used above in this article. The above graphical configuration is via an Activity. An Activity is a specific specialization of a Section (ActivityLoaderImpl source here). The Activity translates the XML from the graphical configuration into the creation of Sections, First-Class Procedures, Inputs, Outputs. Each of these in the Activity implementation is assigned to variables, stored in data structures, passed to functions, returned from functions, etc. This makes the Section (Module) essentially "First-Class."
This input/output interface based on continuations is extremely flexible. It is so much so that First-Class Procedures themselves are also just a specialized implementation of a Section (see ProcedureEmployer).
We have seen how we can encapsulate First-Class Procedures within First-Class Modules, and even First-Class Modules within themselves.
We have shown how the graphical configuration is actually taking advantage of the "First-Class" nature. The graphical configuration is actually a higher-level composition that provides both:
- Easier-to-comprehend modularizing of the application
- Quicker configuration of the application (effectively just draw lines for composition)
Note that it is quite possible to programmatically configure up our application. However, this requires understanding First-Class Procedures/Modules in significantly more depth — much more than junior developers may want to initially.
The graphical configuration of First-Class Modules, therefore, provides the simplicity for building modularized applications. This is without having to deal with the complexity of the underlying constructs. Something in which other composition strategies are still having trouble.
In the next article, we will look at how First-Class Modules can provide a composition of varying existing composition strategies. You may find that existing composition strategies only really consider programming in the small, rather than programming in the much larger — where First-Class Modules become a lot more effective in modularising and simplifying your applications.
Published at DZone with permission of Daniel Sagenschneider . See the original article here.
Opinions expressed by DZone contributors are their own.