Extension Point Overview

Extension-Points (ext folders)

The Jiffy application generates a working services application based on the provided model files. While the generated application should be runnable immediately following generation, there is often a need to perform validation and normalization of the incoming data. This is best coded in the model-layer within the generated validation methods, but sometimes this is not sufficient.

There may be a need to inspect the request details immediately once the request has been passed to the controller. There may be a need to perform crucial validations of the request-body in the controller layer prior to calling the model-layer (i.e. in advance of the validator). There may be a need to influence the value of an entity’s fields prior to returning the read or created entity back to the caller. For reasons such as these, so-called ‘extension-points’ have been embedded in the model and controller layers of the code.

Each extension-point offers the developer the ability to code their own method in a regeneration protected code-body in order to perform checks or data manipulations. Consider that regeneration of an application will overwrite the current controller and model files if the same target destination is used. If an application developer were to extend the controller or model directly in the generated code, their additions would be lost if the application were to be regenerated. By introducing the extension-point concept and separating the related code from the generated code the application developers enhancements are protected from being over-written by an inadvertent application regeneration.

FirstApp
├── appobj
│   ├── appconf.go
│   └── appobj.go
├── controllers
│   ├── authc.go
│   ├── controllerfuncs.go
│   ├── groupauthc.go
│   ├── person_relationsc.go
│   ├── personc.go
│   ├── usrc.go
│   ├── usr_groupc.go
│   └── ext
│       ├── extc_interfaces.go
│       └── personc_ext.go
.
.
.
├── models
│   ├── authm.go
│   ├── errors.go
│   ├── group_authm.go
│   ├── modelfuncs.go
│   ├── personm_ext.go
│   ├── personm.go
│   ├── servicesm.go
│   ├── usr_groupm.go
│   ├── usrm.go
│   └── ext
│       └── model_ext_interfaces.go
├── util
│   └── strings.go
├── .dev.config.json
├── .prd.config.json
├── main_test.go
└── main.go

Extension-points are declared in the generated codebase as a specific set of controller and model interfaces. The interface declarations are contained in the ext sub-folders of the model and controller folders. The ext sub-folders also contain sample (empty) implementations of the interfaces are provided for each modeled entity.

The extension-point interfaces rely on the use of the empty interface{} in order to facilitate the passing of a pointer to the data structure being inspected/updated. Use of interface{} allows us to embrace the concept of a general extension-point API at the cost of strict typing. Additionally, the implementer must make use of reflection in order to assign a type to the value of the interface{} underlying data structure. As of this writing, the use of interface{} and reflection is the best way to implement a general extension-point API with Go. If generics and algebraic types are added to Go, all empty interface{} code will be unceremoniously dumped and replaced with something nicer.

Extension-points are generated on a per-entity-basis controlled by the inclusion of the ‘ext_points’ block in the entity’s model declaration. See the Annotated Simple Single Entity Model for an overview of the extension-point model elements.