# Developing

## Overview

The Cloud Bigtable client is composed of two layers:

* an automatically generated GAPIC base layer
* a handwritten layer


### Generated GAPIC base layer

The GAPIC layer is generated from a combination of protobuf and GAPIC yaml definitions found in 
[googleapis](https://github.com/googleapis/googleapis/tree/master/google/bigtable). This layer is 
split into 2 parts: admin and data apis. The admin part is straightforward enough to be consumed 
directly by the consumer. However the data client is too protocol focused and is too low level to 
be consumed by an application directly. Instead, it's intended to be an implementation detail of the
handwritten layer.


### Handwritten layer

The handwritten layer for the data clients is meant to wrap the GAPIC layer entirely. This is 
necessary because some APIs are too protocol focused (ReadRows chunks vs logical row). Furthermore
by constraining the api, the surface api can be made more ergonomic:

* method calls have an implicit context of an instance
* timestamps can be generated on the client side to make mutations idempotent
* a handwritten api is a lot less verbose than the autogenerated protobuf api


## Structure

* BigtableDataSettings: replaces BaseBigtableDataSettings. It's a simple wrapper of 
  stub/EnhancedBigtableStubSettings. This is meant to be the public facing api of settings.
* BigtableDataClient: replaces BaseBigtableDataClient. It provides an ergonomic wrapper around
  stub/EnhancedBigtableStub. This class is meant to be simple syntactic sugar around the stub.  
* stub/EnhancedBigtableStubSettings: wraps the autogenerated stub/BigtableStubSettings. This class 
  exposes all of the necessary settings. The settings can be categorized as:
  * General settings that affect all RPCs and include things like the target instance and connection 
    pooling
  * Method specific settings that allow the user to tune each RPC individually
* stub/EnhancedBigtableStub: wraps the autogenerated GrpcBigtableStub. It layers logical structure 
  on top of the protocol level requests and responses. It is responsible for adapting ReadRows
  chunks to logical rows and for converting between raw protobufs and user facing wrappers.
* models/: contains user facing wrappers for the protobufs. Each wrapper has a toProto method
  that will return the corresponding proto.
* internal/: contains internal implementation details. The end user doesn't directly interact with
  these classes. It contains things like RequestContext, that is used by all toProto methods to
  contextualize the user facing wrapper with the target instance and app profile.
