Skip to content

Latest commit

 

History

History
138 lines (113 loc) · 5.5 KB

ClientConfiguration.md

File metadata and controls

138 lines (113 loc) · 5.5 KB

Design: Convention, Status: Accepted

Client Configuration

This page describes the structure and conventions used for client configuration objects. Client configuration objects are any objects used to configure an AWS client builder.

Example

This section walks through an example configuration class structure and describes each of its components at a high level.

/**
 * Configuration Description // (1)
 */
@Immutable
@ThreadSafe // (2)
public final class SdkConfiguration // (3)
        implements ToCopyableBuilder<SdkConfiguration.Builder, SdkConfiguration> { // (4)
    private final String option; // (5)

    /**
     * @see #builder() // (6)
     */
    private SdkClientConfiguration(DefaultSdkConfigurationBuilder builder) {
        this.option = builder.option;
    }

    public static Builder builder() {
        return new DefaultSdkConfigurationBuilder();
    }

    /**
     * @see #Builder#option(String) // (7)
     */
    public String option() {
        return this.option;
    }

    @Override
    public ClientHttpConfiguration.Builder toBuilder() {
        return builder().option(option);
    }

    @NotThreadSafe
    public interface Builder extends CopyableBuilder<Builder, SdkConfiguration> { // (8)
        /**
         * Configuration Option Description // (9)
         */
        Builder option(String option);
    }

    private static final class DefaultSdkConfigurationBuilder implements Builder { // (10)
        private String option;

        @Override
        public Builder option(String option) { // (11)
            this.option = option;
            return this;
        }

        public void setOption(String option) { // (12)
            this.option = option;
        }

        @Override
        public SdkConfiguration build() {
            return new SdkConfiguration(this);
        }
    }
}
  1. A detailed description should be given of what types of options the user might find in this object.
  2. Configuration objects should be @Immutable, and therefore @ThreadSafe.
  3. Configuration classes should be defined as final to prevent extension.
  4. Configuration classes should extend ToCopyableBuilder to ensure they can be converted back to a builder object.
  5. All configuration fields should be defined as private final to prevent reassignment.
  6. Configuration constructors should be private to enforce creation by the Builder and refer curious eyes to the builder() method for creating the object.
  7. One "get" method should be created for each configuration field. This method's name should exactly match the name of the field it is retrieving.
  8. Each builder should have its own interface. This allows hiding certain public methods from auto-complete (see below).
  9. A detailed description of each option should be given, including what it does, and why a user could want to change its default value.
  10. A private static final implementation of the Builder interface should be created that is not exposed outside of the scope of the configuration class.
  11. One "set" method should be created for each option to mutate the value in this builder. This method's name should exactly match the name of the field it is setting.
  12. Each option should have a bean-style setter to allow configuring the object reflectively using Inspector-based frameworks, like spring XML.

Configuration Fields

This section details the semantics of configuration fields.

  1. Configuration fields must be immutable.
    1. Fields must be marked as final.
    2. Mutable types, like List and Set should be wrapped in a type that prevents their modification (eg. Collections.unmodifiableList) when referenced through the "get" method.
    3. Mutable types, like List and Set should be copied in the "set" method to prevent their modification by mutating the original object.
  2. Configuration fields must be reference types. Primitive types like boolean or int should not be used because they can not convey the absence of configuration.
  3. Configuration field names should not start with a verb (eg. config.enableRedirect() should instead be config.redirectEnabled()). This is to avoid confusing their "get" methods for a mutating action.

Special notes for collection types, like List, Set, and Map:

  1. Collection type field names must be plural.
  2. There should be two methods provided to modify the collection.
  • method with plural field name which permits adding a collection. It should override any values currently configured in the builder.
  • method that permits adding one item to the collection.
    • If the collection is a list, the method name should use add prefix, eg: addApiName
    • If the collection is a map, the method name should use put prefix, eg: putHeader
public interface Builder {
    
    /**
     *  Sets options.
     *  
     *  <p>
     *  This overrides any option values already configured in the builder.
     */
    Builder options(List<String> options);
    
    /**
     * Add a single option to the collection.
     */
    Builder addOption(String option);

    /**
     *  Sets headers to be set on the HTTP request. 
     *  
     *  <p>
     *  This overrides any header values already configured in the builder.
     */
    Builder headers(Map<String, String> headers);
    
    /**
     *  Add a single header to be set on the HTTP request.
     *  
     *  <p>
     *  This overrides any values already configured with this header name in the builder.
     */
    Builder putHeader(String key, String value);
}