# Understanding the SDK API

This guide explains the design philosophy behind the Developer SDK and how to use its patterns effectively.

## Why fluent design?

The Developer SDK uses a **fluent interface** pattern—methods return the object itself, enabling method chaining that reads like natural language.

### Classic client vs. SDK client

-   [Java](#tab-panel-3032)
-   [Python](#tab-panel-3033)

```java
import java.time.Duration;

import com.aerospike.client.sdk.DataSet;

// Classic Client - verbose, configuration-heavy

WritePolicy policy = new WritePolicy();

policy.sendKey = true;

policy.expiration = 3600;

Key key = new Key("test", "users", "user-1");

Bin bin1 = new Bin("name", "Alice");

Bin bin2 = new Bin("age", 28);

client.put(policy, key, bin1, bin2);

// Developer SDK - chainable, readable

DataSet users = DataSet.of("test", "users");

session.insert(users)

    .bins("name", "age")

    .id("user-1").values("Alice", 28)

    .sendKey()

    .expireRecordAfter(Duration.ofSeconds(3600))

    .execute();
```

```python
from aerospike_sdk import DataSet

# Classic Client - verbose, configuration-heavy

policy = {"key": aerospike.POLICY_KEY_SEND}

key = ("test", "users", "user-1")

bins = {"name": "Alice", "age": 28}

client.put(key, bins, policy=policy)

# Developer SDK - chainable, readable

# (`send_key` is a Behavior setting, not a builder method, and Behavior.DEFAULT

# already stores the original user key alongside the digest.)

users = DataSet.of("test", "users")

await session.insert(key=users.id("user-1")).put(

    {"name": "Alice", "age": 28}

).expire_record_after_seconds(3600).execute()
```

## Method chaining philosophy

Fluent interfaces follow these principles:

1.  **Discoverability**: IDE autocomplete guides you through available options
2.  **Readability**: Code reads like a sentence describing what it does
3.  **Immutability**: Each chain step returns a new builder (no mutation)
4.  **Terminal Operations**: Chains end with an action (`execute()`, then stream iteration for queries)

## Builder pattern integration

The Developer SDK uses builders for complex configuration:

-   [Java](#tab-panel-3034)
-   [Python](#tab-panel-3035)

```java
import com.aerospike.client.sdk.Cluster;

import com.aerospike.client.sdk.ClusterDefinition;

import com.aerospike.client.sdk.Host;

// Cluster connection (multiple seed hosts)

Cluster cluster = new ClusterDefinition(

    new Host("localhost", 3000),

    new Host("localhost", 3001)

).connect();

// Session from cluster

Session session = cluster.createSession(Behavior.DEFAULT);
```

```python
from aerospike_sdk import Behavior, ClusterDefinition, Host

# Cluster connection (async; multiple seed hosts)

cluster = await ClusterDefinition(

    hosts=[

        Host.of("localhost", 3000),

        Host.of("localhost", 3001),

    ]

).connect()

# Session from cluster

session = cluster.create_session(Behavior.DEFAULT)
```

## When fluent shines

The fluent pattern is most valuable when:

-   Operations have many optional parameters
-   Configuration is complex but has sensible defaults
-   Code readability is important for maintenance
-   IDE support can guide developers

## Next steps

-   [Quickstart](https://aerospike.com/docs/develop/client/sdk/quickstart)
-   [Behaviors](https://aerospike.com/docs/develop/client/sdk/concepts/behaviors)
-   [Configuration](https://aerospike.com/docs/develop/client/sdk/concepts/configuration)