You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Is your feature request related to a problem? Please describe.
Writing comments on functions was good enough when I had one or two converters. But now, with 10s of converters and after using goverter in our mainstream toolchains, writing the mapping comments became very hard, error prune, and time consuming.
I may summarize our problems in the following points:
New comers need to learn new DSL (comments) and usage hacks to get around corner cases in our case.
IDE don't help with autocomplete for available actions (map, autoMap, default, ...etc)
We can't share reusable code mappings between different converters while the mapping is exactly the same. Similar to Support interface embedding for seperation of concerns #189 . But one big different from Support interface embedding for seperation of concerns #189 is that in our case the mapping itself is the same but the mapped types are not (for example, SourceA -> TargetA and SourceB -> TargetB should have the same comments to map fields, but they are different types).
At the moment, I have couple of approaches in mind:
Keep the interface/vars definitions and write code in the same file to define mappings
Like goa and gorm/gen, completely abstract the converter definition and generate everything.
I prefer the second approach for better abstraction and I gain no value of managing the interface definition myself.
Maybe something like the following:
Details
package def
// Below is very basic illustration of definition builder.typeConverterstruct {
// config holds all configurations that normally added as interface commentsconfigany// methods holds definitions for all methods for that converter interfacemethods []*Method
}
// NewConverter creates a new converter instance.// config may be omitted as AFAIK there is no required configurations that must be provided in the converter levelfuncNewConverter(configany) *Converter {
return&Converter{config: config}
}
func (c*Converter) Extend(pathstring) *Converter {
// ...returnc
}
// Method creates a new method on this converter instance.// config may be replaced by multiple arguments to properly model the method Signature.func (c*Converter) Method(configany, builders...func(*Method) *Method) *Converter {
c.methods=append(c.methods, NewMethod(config).Builders(builders...))
returnc
}
typeMethodMapsstruct {
source, targetstring
}
funcNewMethodMaps(sourcestring, targetstring) *MethodMaps {
return&MethodMaps{source: source, target: target}
}
typeMethodstruct {
configanymaps []*MethodMaps
}
funcNewMethod(configany) *Method {
return&Method{config: config}
}
func (m*Method) Map(source, targetstring) *Method {
m.maps=append(m.maps, NewMethodMaps(source, target))
returnm
}
func (m*Method) Builders(fns...func(*Method) *Method) *Method {
mm:=mfor_, fn:=rangefns {
mm=fn(mm)
}
returnmm
}
func (m*Method) AutoMap(source, targetstring) *Method {
// ...returnm
}
func (m*Method) Ignore(fields...string) *Method {
// ...returnm
}
funcGenerate(converters []*Converter) error {
// do the magicreturnnil
}
// In my code, I should have an entrypoint that constructs the converters and pass them to Generate func.// goverter may also support this mode somehow in its CLI.funcmain() {
converters:= []*Converter{
NewConverter("converterA").
Method("ConvertAToB", aToBMapField),
NewConverter("converterB").
Method("ConvertAToB", aToBMapField),
}
err:=Generate(converters)
iferr!=nil {
panic(err)
}
}
funcaToBMapField(m*Method) *Method {
mappings:=map[string]string{
"id": "ID",
"created_at": "Audit.CreatedAt",
}
forsource, target:=rangemappings {
m.Map(source, target)
}
returnm
}
Describe alternatives you've considered
None
Please 👍 this issue if you like this functionality. If you have a specific use-case in mind, feel free to comment it.
The text was updated successfully, but these errors were encountered:
It may not be easily usable because it the data is structured in a way that makes it easy to use in the implementation, and not to instantiate it. There are probably some private fields that must be set, so I don't think it's usable without modifying goverter. Also keep in mind that this api is not versionized.
Have you considered building a small pre code generator that uses your go code dsl and produces an interface usable by goverter? This likely solves most of your issues and shouldn't be too much effort.
I'll see this supported in goverter, but native support will be quite some effort and needs some refactoring. So I'd wait for more user feedback for native support.
Thanks @jmattheis. I'm not familiar with goverter internals, but I took a quick look and yeah that seems very close.
Have you considered building a small pre code generator that uses your go code dsl and produces an interface usable by goverter? This likely solves most of your issues and shouldn't be too much effort.
Nope. We're into simplifying our toolchain here. Adding another generation step that our team manages directly doesn't seem a good fit for us.
I'll see this supported in goverter, but native support will be quite some effort and needs some refactoring. So I'd wait for more user feedback for native support.
Awesome! Totally agree, no need to put an effort without a clear value. 👍
Is your feature request related to a problem? Please describe.
Writing comments on functions was good enough when I had one or two converters. But now, with 10s of converters and after using goverter in our mainstream toolchains, writing the mapping comments became very hard, error prune, and time consuming.
I may summarize our problems in the following points:
// goverter:
prefix.Describe the solution you'd like
Well, I don't have a full solution in mind. I was just thinking if we can use something like https://github.com/goadesign/goa or https://gorm.io/gen/database_to_structs.html (which I already use 😁).
At the moment, I have couple of approaches in mind:
I prefer the second approach for better abstraction and I gain no value of managing the interface definition myself.
Maybe something like the following:
Details
Describe alternatives you've considered
None
Please 👍 this issue if you like this functionality. If you have a specific use-case in mind, feel free to comment it.
The text was updated successfully, but these errors were encountered: