I guess I didn't ask an actual question... is there a more idiomatic way of 
doing this?

Thank you!

-- Salvatore
smile.


On Monday, July 24, 2023 at 4:00:59 PM UTC-4 Salvatore Domenick Desiano 
wrote:

> Ever since 1.18 came out I've been struggling to find an idiomatic way to 
> implement a certain kind of adapter. I'm starting to suspect I'm Holding It 
> Wrong (TM) so here I am.
>
> In short, I have an adapter that is effectively a collection of static 
> methods and it doesn't look right.
>
> Imagine you have a generic key-value database (transaction and life-cycle 
> methods omitted for brevity):
>
> type SimpleDatabase interface {
> Get(t ViewTransaction, key string) ([]byte, bool, error)
> Put(t UpdateTransaction, key string, value []byte) error
> }
>
> You then want to build something more specific on top using generics to 
> avoid repetition of tricky code:
>
> type ApplicationDatabase struct {
>   impl *SimpleDatabase
> }
>
> func (db *ApplicationDatabase) PutProjectRecord(t UpdateTransaction, r 
> *ProjectRecord) error {
>   return put[ProjectRecord](db.impl, projectRecordFactory, t, r)
> }
>
> type recordFactory[V any] interface {
>   dbKey(value V) string
>   encodeValue(value V) []byte
>   decodeValue(data []byte) (V, error)
> }
>
> func put[V any](db *SimpleDatabase, f *recordFactory[V], t 
> UpdateTransaction, value V) error {
>   key := f.dbKey(value)
>   valueBytes := f.encodeValue(value)
>   if err := db.put(t, key, valueBytes); err != nil 
>     return fmt.Errorf("db error: %w", err)
>   }
>   return nil
> }
>
> This is nice and clean -- adding a new record type is just a matter of 
> adding a new recordFactory implementation. Adding more complexity to the 
> put/get (recovery, etc.) only has to happen once. The part that bugs me, 
> though, is that the implementation has no state and really looks like it 
> shouldn't be instantiated:
>
> type projectRecordFactory struct{}
> func (f *projectRecordFactory) dbKey() string { return .... }
> func (f *projectRecordFactory) encodeValue(value V) []byte { 
> json.Marshal(...) }
> func (f *projectRecordFactory) decodeValue(data []byte) (V, error) { 
> json.Unmarshal(...) }
>
> and, frankly, if I didn't instantiate it, it would feel like either Java 
> or C++ metaprogramming.
>
> I'm open to a completely different structure but I am really hoping to add 
> new record types by adding a new package or type.
>
> Thanks!
>
> -- Salvatore
> smile.
>
>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/318e98c2-d13e-4188-b65b-bbc7644e3ab7n%40googlegroups.com.

Reply via email to