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/423c6b23-32ca-456a-833c-602257c07d04n%40googlegroups.com.

Reply via email to