refractionPOINT / usp-adapters

LimaCharlie Universal Sensor Protocol (USP) Adapters to ingest from various sources.
https://limacharlie.io
Apache License 2.0
2 stars 1 forks source link

USP Builder #148

Open derickdiaz opened 6 months ago

derickdiaz commented 6 months ago

To build an adapter within this project you must define struct that integrates all the functions within the USPAdapter interface, currently this would only be close() error. Additionally, the adapter must be constructed within the runAdapter function in the tools.go file. The runAdapter function has a big if/else if/else statement that can grow in size and become problematic as more adapters are build. I would like to propose an ideas to help keep this function small and define what it means to build an adapter:

  1. Create an AdapterBuilder interface

The AdapterBuilder of any struct has the purpose of building the adapter. For example, the AdapterBuilder struct will take any information required to build the adapter, i.e the clientConfigs. Below is an example of the interface

type USPAdapterBuilder interface {
    NewAdapter() (USPAdapter, error)
    GetMethodName() string
    GetClientOptions() *ClientOptions
}

The GetMethodName will return a string correlating to the string comparison within the current configuration of the runAdapter function. This will allow the runAdapter method to be shorten like this:

func buildAdapter(method string, healthChecks bool) (USPAdapter, error) {
    builders := []USPAdapterBuilder{
        &MicrosoftUSPAdapterBuilder{},
    }

    builder, err := getBuilderByMethodName(method, builders)
    if err != nil {
        return nil, err
    }

    configureBuilderClientOptions(builder.GetClientOptions())
    adapter, err := builder.NewAdapter()
    if err != nil {
        return nil, err
    }

    if healthChecks {
        performHealthChecksOnAdapter(adapter)
    }

    return adapter, nil
}

func getBuilderByMethodName(method string, builders []USPAdapterBuilder) (USPAdapterBuilder, error) {
    for _, builder := range builders {
        if builder.GetMethodName() == method {
            return builder, nil
        }
    }
    return nil, fmt.Errorf("Unable to find builder for method name: %s", method)
}

User will define a builder based on the UserAdapterBuilder interface and to integrate It to the application, they would have to update the list. I'm sure there's a better way to handle by treating adapters as plugin that way the code does not have to re-compile every time a new adapter is added. Additionally, this solution would require all the adapters to change.

derickdiaz commented 6 months ago

In this example builder is not the correct term. Factory is a better term since it matches that design pattern.