Application Components¶
Basic Component¶
A component is a modular, reusable piece of code that performs a specific function in a larger application. Components are designed as independent, self-contained units that can be easily integrated into an application.
Components are not microservices. They are folders that contain different functionalities. We use a struct with a set of methods to describe the functionalities a component depends on and the functionalities it provides.
The basic component looks like this:
package component
import (
"github.com/componego/componego"
)
type Component struct {
}
func NewComponent() *Component {
return &Component{}
}
func (c *Component) ComponentIdentifier() string {
return "company-name:component-name"
}
func (c *Component) ComponentVersion() string {
return "0.0.1"
}
var (
_ componego.Component = (*Component)(nil)
)
Pay attention to methods that the component can provide in the documentation below in the next section. Look at the example below to see how you can add a component to your application:
package application
import (
"github.com/componego/componego"
)
type Application struct {
}
// ...
func (a *Application) ApplicationComponents() ([]componego.Component, error) {
return []componego.Component{
NewComponent(),
}, nil
}
var (
_ componego.Application = (*Application)(nil)
_ componego.ApplicationComponents = (*Application)(nil)
)
Mandatory methods¶
ComponentIdentifier¶
This function returns the component ID:
If the identifier in multiple components is the same, the last one will be used. You can use it for overwriting components.ComponentVersion¶
This function returns the version of the component:
The version must match the SemVer format.Note
It is always recommended to increment the component version when making changes to the component.
Optional methods¶
Note
Any component struct is similar to the application struct. However, there are slight differences in their methods.
ComponentComponents¶
Any component may depend on other components:
func (a *Component) ComponentComponents() ([]componego.Component, error) {
return []componego.Component{ /* ... */ }, nil
}
// ...
Note
The order in which components are loaded depends on their dependencies.
This also affects the component overwriting rules: components listed last will overwrite those listed first if they share the same identifier.
ComponentDependencies¶
Like an application, it can provide dependencies:
func (a *Component) ComponentDependencies() ([]componego.Dependency, error) {
return []componego.Dependency{ /* ... */ }, nil
}
// ...
ComponentInit¶
This function is called in the order of dependencies between components. You can add custom logic to this method:
ComponentStop¶
This method is called when the component stops. You can handle the previous error by returning either a new or the original error:
func (a *Component) ComponentStop(env componego.Environment, prevErr error) error {
// ...
return prevErr
}
// ...
Note
For greater clarity and compile-time validation, you can add the following code:
These names correspond to the logic they implement. It is always recommended to add such validation to easily find and fix problems in the code, especially if changes are made to interface methods in future versions of the framework.Initialization & Rewriting¶
Pay attention to the following example:
package application
import (
"github.com/componego/componego"
"secret.com/project-x/components/database1"
"secret.com/project-x/components/database2"
)
type Application struct {
}
// ...
func (a *Application) ApplicationComponents() ([]componego.Component, error) {
return []componego.Component{
database1.NewComponent(),
// ...
database2.NewComponent(),
}, nil
}
var (
_ componego.Application = (*Application)(nil)
_ componego.ApplicationComponents = (*Application)(nil)
)
Note
You can get a list of active components through the environment.
We print the unique ID in the loop so you can see which components are currently in use.It also supports overriding components that have multiple levels of nesting. You can observe how it works in the project code.
Component Factory¶
There is also a brief code snippet for creating the component. This is the same thing as for an application.
package component
import (
"github.com/componego/componego"
"github.com/componego/componego/impl/environment/managers/component"
)
func NewComponent() componego.Component {
factory := component.NewFactory("identifier", "0.0.1")
factory.SetComponentInit(func(env componego.Environment) error {
// ...
return nil
})
// ... other methods.
return factory.Build()
}