sdk-dx について
SDK の設計者向けに、API 設計、エラー処理、型安全性、IDE 対応を案内する開発者体験スキルです。バージョン管理、移行ガイド、リリース前の確認項目も扱います。
主な機能
- 01一般的な用途を簡潔にし複雑さを段階的に提示
- 02明確で対処方法が分かるエラーメッセージの設計
- 03型安全性と IDE の自動補完への対応
- 04セマンティックバージョニングと非推奨化の計画
- 05移行ガイドと品質チェックリストの作成
活用シーン
- 01使いやすい SDK API の設計
- 02SDK のエラーメッセージの改善
- 03破壊的変更とバージョン更新の計画
- 04SDK のリリース準備状況の確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ jonathimer/ devmarketing-skills --skill sdk-dxインストール後、Claude Code で/sdk-dxを入力して読み込まれたか確認します。
同梱ファイルREADME.md
詳細
SDK の設計と開発者エクスペリエンス
最も効果的な SDK のマーケティングは、開発者が話題にせずにはいられない SDK を作ることです。SDK によって開発者が生産的で有能だと感じれば、開発者はあなたの支持者になります。反対に、使いづらさを感じさせてしまえば、どれだけマーケティングに力を入れても挽回できません。
概要
SDK の開発者エクスペリエンス(DX)とは、開発者がライブラリを使うときに感じるあらゆることを指します。
- 見つけやすさ:どれほど簡単に見つけてインストールできますか?
- 学びやすさ:使い方をどれほど早く理解できますか?
- 使いやすさ:日々の作業でどれほど生産的に使えますか?
- デバッグのしやすさ:問題をどれほど簡単に解決できますか?
- アップグレードのしやすさ:新しいバージョンをどれほど負担なく導入できますか?
優れた SDK の DX は競争上の優位性になります。開発者は、自分を賢く感じさせてくれるツールを選びます。
始める前に
developer-audience-context スキルを確認し、次の点を把握してください。
- 対象とする開発者はどの言語やフレームワークを使っていますか?
- 最も一般的な IDE/エディター環境は何ですか?
- 対象分野における開発者の経験レベルはどの程度ですか?
- 競合する SDK を使ったことはありますか?どのような点を好み、または好まないのでしょうか?
SDK の設計上の判断は、ユーザーへの深い理解に基づいて行う必要があります。
API 設計の原則
原則 1:一般的なユースケースを最適化する
最も頻繁に使われるユースケースでは、必要なコードを最小限にします。
良い設計:
# Common case: send a simple message
client.messages.send("Hello world", to="+1234567890")
# Full control when needed
client.messages.send(
body="Hello world",
to="+1234567890",
from_="+0987654321",
status_callback="https://...",
media_urls=["https://..."]
)
悪い設計:
# Every call requires full configuration
message = Message(
body="Hello world",
to=PhoneNumber("+1234567890"),
from_=PhoneNumber(config.get_default_from()),
options=MessageOptions(
status_callback=None,
media_urls=[]
)
)
client.messages.send(message)
原則 2:段階的な情報開示
シンプルな使い方から始め、必要に応じて複雑な機能を使えるようにします。
// Level 1: Simplest possible usage
const result = await client.analyze("Hello world");
// Level 2: Common options
const result = await client.analyze("Hello world", {
language: "en",
features: ["sentiment", "entities"]
});
// Level 3: Full control
const result = await client.analyze("Hello world", {
language: "en",
features: ["sentiment", "entities"],
model: "v2-large",
timeout: 30000,
retries: { max: 3, backoff: "exponential" }
});
原則 3:早期に、明確に失敗させる
実行可能な解決策を示すメッセージとともに、できるだけ早い段階でエラーを検出します。
良い例:
# Validation at construction time
client = MyClient(api_key="")
# Raises immediately: ValueError: API key cannot be empty.
# Get your API key at https://dashboard.example.com/keys
# Clear error at runtime
client.users.get("invalid-id")
# Raises: NotFoundError: User 'invalid-id' not found.
# Use client.users.list() to see available users.
悪い例:
client = MyClient(api_key="") # No validation
result = client.users.get("invalid-id")
# Returns: None (is this an error? empty result? who knows?)
# Or worse: raises generic Exception with stack trace
原則 4:適切なデフォルト値
設定しなくても、ほとんどのケースで使えるデフォルト値にします。
// This should just work without configuration
const client = new MyClient({ apiKey: process.env.MY_API_KEY });
// Sensible defaults:
// - Automatic retries with exponential backoff
// - Reasonable timeouts
// - JSON content type
// - Standard auth headers
// - Connection pooling
問題解決につながるエラーメッセージ
エラーメッセージはドキュメントです。役立つ内容にしましょう。
エラーメッセージのフレームワーク
すべてのエラーメッセージで、次の点を説明します。
- 何が起きましたか?
- なぜ起きましたか?
- どうすれば解決できますか?
良いエラーメッセージと悪いエラーメッセージ
良い例:
AuthenticationError: Invalid API key provided.
The API key 'sk_test_abc...' (test key) cannot be used for
production requests.
To fix this:
1. Go to https://dashboard.example.com/keys
2. Copy your production API key (starts with 'sk_live_')
3. Update your environment variable: MY_API_KEY=sk_live_...
Docs: https://docs.example.com/authentication
悪い例:
Error: 401 Unauthorized
区別すべきエラーの種類
開発者が捕捉できる、具体的なエラー型を作成します。
from myapi.errors import (
AuthenticationError, # Invalid/missing credentials
AuthorizationError, # Valid creds, insufficient permissions
ValidationError, # Invalid input data
NotFoundError, # Resource doesn't exist
RateLimitError, # Too many requests
ServerError, # Our fault, retry might help
)
try:
client.users.get(user_id)
except NotFoundError as e:
# Handle missing user specifically
except AuthenticationError as e:
# Handle auth issues specifically
except MyAPIError as e:
# Catch-all for other API errors
エラーにコンテキストを含める
// Bad: generic error
throw new Error("Invalid parameter");
// Good: contextual error
throw new ValidationError({
message: "Invalid phone number format",
field: "to",
value: "+1abc",
expected: "E.164 format (e.g., +14155551234)",
docs: "https://docs.example.com/phone-numbers"
});
型安全性
型安全性は、古くならないドキュメントです。
TypeScript のベストプラクティス
// Define explicit types for all inputs and outputs
interface User {
id: string;
email: string;
name: string;
createdAt: Date;
metadata?: Record<string, unknown>;
}
interface CreateUserInput {
email: string;
name: string;
metadata?: Record<string, unknown>;
}
// Return types are explicit
async function createUser(input: CreateUserInput): Promise<User> {
// ...
}
// Use discriminated unions for responses
type ApiResponse<T> =
| { success: true; data: T }
| { success: false; error: ApiError };
オートコンプリートを前提とした設計
IDE のオートコンプリートを活用できるように設計します。
// Good: autocomplete shows all options
client.messages.create({
to: "+1...", // IDE shows: (property) to: string
body: "...", // IDE shows: (property) body: string
// User types 'me' and sees 'mediaUrls' autocomplete
});
// Bad: requires memorization
client.send("messages", { /* what goes here? */ });
Enum とリテラル型
// Good: constrained values with autocomplete
type MessageStatus = "queued" | "sending" | "sent" | "failed";
interface Message {
status: MessageStatus; // IDE shows valid values
}
// Bad: any string accepted
interface Message {
status: string; // No guidance, errors at runtime
}
IDE との統合
見つけやすくする
IDE の機能が開発者を支援できるよう、SDK を構成します。
// Namespace methods logically
client.users.get(id)
client.users.list()
client.users.create(data)
client.users.update(id, data)
client.users.delete(id)
// After typing 'client.users.' the IDE shows all user operations
あらゆる場所に JSDoc/Docstring を追加する
/**
* Creates a new user in your organization.
*
* @param input - The user details
* @param input.email - Must be a valid email address
* @param input.name - Display name (max 100 characters)
* @returns The created user with generated ID
* @throws {ValidationError} If email format is invalid
* @throws {ConflictError} If email already exists
*
* @example
* const user = await client.users.create({
* email: "[email protected]",
* name: "Jane Developer"
* });
*/
async createUser(input: CreateUserInput): Promise<User>
インラインの例
def send_message(self, body: str, to: str, **kwargs) -> Message:
"""
Send an SMS message.
Args:
body: The message content (max 1600 characters)
to: Recipient phone number in E.164 format
Returns:
Message object with ID and status
Example:
>>> message = client.messages.send(
... body="Hello from Python!",
... to="+14155551234"
... )
>>> print(message.status)
'queued'
"""
バージョニング戦略
セマンティックバージョニング
semver を厳守します。
- MAJOR:破壊的変更(削除、シグネチャの変更)
- MINOR:新機能(後方互換性あり)
- PATCH:バグ修正(後方互換性あり)
破壊的変更に該当するもの
破壊的変更(メジャーバージョンの更新が必要):
- 公開メソッドまたはプロパティの削除
- メソッドシグネチャの変更
- 戻り値の型の変更
- デフォルトの動作の変更
- 言語/ランタイムのバージョンへの対応の終了
破壊的変更ではないもの(マイナーまたはパッチ):
- 新しいメソッドの追加
- オプションのパラメーターの追加
- 機能の非推奨化(削除はしない)
- 誤った動作を変更するバグ修正
非推奨化のプロセス
import warnings
def old_method(self):
"""
.. deprecated:: 2.3.0
Use :meth:`new_method` instead. Will be removed in 3.0.0.
"""
warnings.warn(
"old_method() is deprecated, use new_method() instead. "
"See migration guide: https://docs.example.com/migrate-v3",
DeprecationWarning,
stacklevel=2
)
return self.new_method()
移行ガイド
移行ガイドの構成
# Migrating from v2 to v3
## Overview
Version 3 introduces [major change] and removes [deprecated feature].
Migration typically takes [time estimate].
## Breaking Changes
### 1. Client Initialization
**Before (v2):**
```python
client = MyClient(key="...")
変更後(v3):
client = MyClient(api_key="...")
理由:他の SDK パラメーターとの一貫性を保つためです。
2.[次の破壊的変更]
...
削除された非推奨機能
client.old_method()- 代わりにclient.new_method()を使用してくださいLegacyClass- 代わりにModernClassを使用してください
新機能
-[移行する価値のある機能]
サポートが必要ですか?
-[移行サポートの連絡先] -[移行に関する質問の相談時間]
### Codemods and Automation
When possible, provide automated migration:
```bash
# Provide migration scripts
npx @myapi/migrate-v3
# Or codemods
npx jscodeshift -t @myapi/codemods/v2-to-v3 src/
SDK を各言語になじませる
言語固有の慣用表現
Python:snake_case、コンテキストマネージャー、ジェネレーターを使用します
# Pythonic
with client.batch() as batch:
for user in client.users.list():
batch.add(user.send_notification("Hello"))
# Not Pythonic
users = client.getUsers()
batch = client.createBatch()
for i in range(len(users)):
batch.addOperation(users[i].sendNotification("Hello"))
batch.execute()
JavaScript:Promise、async/await、分割代入を使用します
// Idiomatic JS
const { data, error } = await client.users.get(id);
// Not idiomatic
client.users.get(id, function(err, result) {
if (err) { /* callback hell */ }
});
Go:エラーの返却、インターフェース、チャネルを使用します
// Idiomatic Go
user, err := client.Users.Get(ctx, userID)
if err != nil {
return fmt.Errorf("getting user: %w", err)
}
// Not idiomatic
user := client.Users.Get(userID) // panics on error
エコシステムの慣習に合わせる
- 開発者が想定するパッケージマネージャーを使用します(npm、pip、gem、go get)
- その言語で人気のライブラリの命名規則に従います
- 人気のフレームワーク(Express、Django、Rails)と統合します
- 人気のテストパターンをサポートします
SDK の品質チェックリスト
リリース前
- すべての公開 API にドキュメントがあります
- 言語がサポートする場合、すべての公開 API に型があります
- エラーメッセージに解決手順が含まれています
- ドキュメントのコード例が自動的にテストされています
- すべての変更を反映して変更履歴が更新されています
- 破壊的変更に関する移行ガイドがあります
- 削除する機能に非推奨警告があります
優れた開発者体験のために
- クイックスタートが 5 分以内に成功します
- IDE のオートコンプリートがすべての操作で機能します
- エラーを特定の型で捕捉できます
- 再試行ロジックが一時的な障害に対応します
- ログを設定でき、役立つ情報が記録されます
- デバッグモードでリクエスト/レスポンスの詳細が表示されます
ツール
SDK の生成
- OpenAPI Generator:OpenAPI 仕様から SDK を生成します
- Swagger Codegen:代替のジェネレーターです
- Speakeasy:最新の SDK 生成プラットフォームです
- Fern:型安全な SDK 生成ツールです
テスト
- VCR/Betamax:HTTP インタラクションを記録して再生します
- WireMock:HTTP サービスをモックします
- Pact:コントラクトテストを行います
ドキュメント
- TypeDoc:TypeScript のドキュメント作成ツール
- Sphinx:Python のドキュメント作成ツール
- GoDoc:Go のドキュメント作成ツール
- YARD:Ruby のドキュメント作成ツール
関連スキル
- docs-as-marketing:SDK の機能を紹介するドキュメント
- api-onboarding:SDK を初めて利用するときの体験
- changelog-updates:SDK の変更を効果的に伝える方法
- developer-sandbox:インストールせずに SDK を試す環境
- developer-audience-context:SDK の利用者を理解する方法