mcpField
D
domain-language-types

domain-language-types

github.com/marius-townhouse開発645 回インストール39 週間前に更新
リポジトリ

domain-language-types について

問題領域の概念に基づいて型に名前を付ける、TypeScript 開発向けのスキルです。ドメインエキスパートにも意味が伝わる型の作成やレビューに役立ちます。

主な機能

  1. 01ドメイン用語で型を命名
  2. 02構造を示す名前を意味ある名前に変更
  3. 03ハンガリアン記法の接頭辞や冗長な接尾辞を回避
  4. 04ドメインで共有される用語を採用

活用シーン

  1. 01新機能の型命名
  2. 02不明瞭な型名のリファクタリング
  3. 03ドメインエキスパートとの API レビュー

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/marius-townhouse/effective-typescript-skills --skill domain-language-types

インストール後、Claude Code で/domain-language-typesを入力して読み込まれたか確認します。

詳細

問題領域の言葉を使って型に名前を付ける

概要

型名は構造ではなく、意味を伝えるべきです。

INodeNameValueData という名前の型からは何も分かりません。一方、APIResponse や CustomerOrder という名前の型からは、すべてが分かります。データ構造の言葉ではなく、ビジネスドメインの言葉を使いましょう。

このスキルを使う場面

  • 新しい型に名前を付けるとき
  • 分かりにくい型名をリファクタリングするとき
  • ドメインエキスパートとコードをレビューするとき
  • 公開 API を設計するとき

絶対的なルール

Type names should be meaningful to domain experts.
If a non-programmer can't understand it, rename it.

覚えておきましょう:

  • 技術用語よりビジネス用語
  • 構造より意味
  • 名前はドキュメント
  • ドメインエキスパートが型を理解できること

判別:構造を表す名前

// Bad: describes structure, not meaning
interface IEntityWithIdAndName {
  id: string;
  name: string;
}

interface IStringPairList {
  items: [string, string][];
}

interface IDataRecord {
  data: Record<string, unknown>;
}

IEntityWithIdAndName とは何でしょうか? ユーザーでしょうか? 商品でしょうか? カテゴリーでしょうか?

より良い例:ドメインを表す名前

// Good: describes what it IS
interface User {
  id: string;
  name: string;
}

interface TranslationPairs {
  items: [sourcePhrase: string, targetPhrase: string][];
}

interface CustomerProfile {
  data: Record<string, unknown>;
}

実例:E コマース

// Bad: generic/structural names
interface IData {
  id: string;
  props: Record<string, unknown>;
}

interface IEntity extends IData {
  type: string;
}

interface ICollection {
  items: IEntity[];
  total: number;
}

と、

// Good: domain language
interface Product {
  sku: string;
  name: string;
  price: Money;
  inventory: number;
}

interface Order {
  orderNumber: string;
  customer: Customer;
  items: OrderItem[];
  total: Money;
}

interface ProductCatalog {
  products: Product[];
  totalCount: number;
}

避けるべきパターン

ハンガリアン記法のプレフィックス
// Bad: I prefix for interfaces
interface IUser { }
interface IProduct { }

// Good: just the name
interface User { }
interface Product { }
型を表すサフィックス
// Bad: redundant suffixes
interface UserType { }
interface ProductInterface { }
interface OrderObject { }

// Good: clean names
interface User { }
interface Product { }
interface Order { }
汎用的な技術用語
// Bad: generic
interface DataModel { }
interface EntityRecord { }
interface ItemContainer { }

// Good: specific
interface Invoice { }
interface ShippingAddress { }
interface ShoppingCart { }

プロパティ名も同様です

// Bad: technical property names
interface User {
  dataString: string;
  valueNumber: number;
  itemsArray: Product[];
}

// Good: domain property names
interface User {
  email: string;
  age: number;
  purchases: Product[];
}

コンテキストが重要です

構造が同じでも、ドメインが違えば名前も異なります。

// Healthcare domain
interface Patient {
  mrn: string;          // Medical Record Number
  admissionDate: Date;
  diagnosis: string[];
}

// Education domain  
interface Student {
  studentId: string;
  enrollmentDate: Date;
  courses: string[];
}

構造は似ていますが、名前は異なる意味を伝えています。

技術的な名前が許容される場合

標準的な技術概念
// OK: widely understood technical terms
interface HttpRequest { }
interface DatabaseConnection { }
interface CacheEntry { }
汎用ユーティリティ
// OK: truly generic utilities
type Nullable<T> = T | null;
type AsyncResult<T> = Promise<T>;
内部実装
// OK for internal implementation details
interface InternalCacheNode<T> { }
interface TreeNodeImpl<T> { }

ユビキタス言語

ドメイン駆動設計では、開発者とドメインエキスパートの双方が共有する「ユビキタス言語」を使います。

// If domain experts say "fulfillment", use that:
interface OrderFulfillment { }

// Not:
interface OrderProcessingData { }
interface IOrderExecutionEntity { }

圧力に負けないためのプロトコル

1. 「技術的な詳細にすぎません」

圧力:「ユーザーはこの型名を見ません」

回答: 開発者は見ます。未来の自分も見ます。意味のある名前にしましょう。

アクション: 構造ではなく、何を表すのかに基づいて名前を付けましょう。

2. 「命名規則があります」

圧力:「スタイルガイドでは I を付けることになっています」

回答: 規則は明確さを損なうのではなく、明確さを支えるべきです。

アクション: 明確さを損なう規則には異議を唱えましょう。IUser には何も付け加えるものがありません。

危険信号 — 作業を止めて再考しましょう

  • I、T で始まる型名、または Type/Interface/Object で終わる型名
  • 構造を説明する名前(StringArray、NumberMap)
  • ドメインエキスパートが理解できない名前
  • どれも「Data」と呼べてしまう複数の型

よくある正当化(すべて無効)

言い訳実態
「バックエンドと一致しています」バックエンドの名前も適切とは限りません
「内部でしか使いません」内部コードにも明確さが必要です
「これが規則です」悪い規則は変えるべきです

クイックリファレンス

// DON'T: Structural/technical names
interface IDataEntity { }
interface StringValuePair { }
interface ItemsCollection<T> { }

// DO: Domain language names
interface Customer { }
interface PriceRange { }  // [min: Money, max: Money]
interface ProductCatalog { }

// DON'T: Redundant suffixes
interface UserType { }
interface ProductInterface { }

// DO: Clean names
interface User { }
interface Product { }

要点

構造ではなく、意味に基づいて型に名前を付けましょう。

ドメインエキスパートが型名を読んで、それが何を表すのか理解できるようにしましょう。Invoice は IFinancialDataRecord より多くのことを伝えます。問題領域の言葉を使いましょう。

参考文献

Dan Vanderkam 著『Effective TypeScript』の項目 41「問題領域の言葉を使って型に名前を付ける」に基づいています。

コメント