code: func join(att *design.AttributeDefinition, usePointers bool, pos ...[]string) string {
  	if att == nil {
  		return ""
  	}
  	obj := att.Type.ToObject()
  	elems := make([]string, len(obj))
  	var keys []string
  	if len(pos) > 0 {
  		keys = pos[0]
  		if len(keys) != len(obj) {
  			panic("invalid position slice, lenght does not match attribute field count") // bug
  		}
  	} else {
  		keys = make([]string, len(obj))
  		i := 0
  		for n := range obj {
  			keys[i] = n
  			i++
  		}
  		sort.Strings(keys)
  	}
  	for i, n := range keys {
  		a := obj[n]
  		elems[i] = fmt.Sprintf("%s %s", codegen.Goify(n, false),
  			cmdFieldType(a.Type, usePointers && !a.IsRequired(n)))
  	}
  	return strings.Join(elems, ", ")
  }
docs: // join is a code generation helper function that generates a function signature built from
  // concatenating the properties (name type) of the given attribute type (assuming it's an object).
  // join accepts an optional slice of strings which indicates the order in which the parameters
  // should appear in the signature. If pos is specified then it must list all the parameters. If
  // it's not specified then parameters are sorted alphabetically.