code: func joinNames(useNil bool, atts ...*design.AttributeDefinition) string {
  	var elems []string
  	for _, att := range atts {
  		if att == nil {
  			continue
  		}
  		obj := att.Type.ToObject()
  		var names, optNames []string
  
  		keys := make([]string, len(obj))
  		i := 0
  		for n := range obj {
  			keys[i] = n
  			i++
  		}
  		sort.Strings(keys)
  
  		for _, n := range keys {
  			a := obj[n]
  			field := fmt.Sprintf("cmd.%s", codegen.Goify(n, true))
  			if !a.Type.IsArray() && !att.IsRequired(n) && !att.IsNonZero(n) {
  				if useNil {
  					field = flagTypeVal(a, n, field)
  				} else {
  					field = "&" + field
  				}
  			} else if a.Type.IsArray() {
  				field = flagTypeArrayVal(a, field)
  			} else {
  				field = flagRequiredTypeVal(a, field)
  			}
  			if att.IsRequired(n) {
  				names = append(names, field)
  			} else {
  				optNames = append(optNames, field)
  			}
  		}
  		elems = append(elems, names...)
  		elems = append(elems, optNames...)
  	}
  	return strings.Join(elems, ", ")
  }
docs: // joinNames is a code generation helper function that generates a string built from concatenating
  // the keys of the given attribute type (assuming it's an object).