SkillAgentSearch skills...

domain-driven-design

Re-Stock アプリでは、以下の基本原則に従ってドメイン駆動設計を適用します: - 値オブジェクトとエンティティを区別する

Install / Use

npx skills add noriaki/re-stock-app

Installs into whichever agent you are using.

About this skill
🔧

.clinerules

Cline rules

Quality Score

63/100

Supported Platforms

Cline

Our assessment of domain-driven-design

domain-driven-design scores 63/100 on our quality scale, 3956th of 4,594 Development & Engineering skills we index.

Its .clinerules is 5.7 KB long, well organised into 12 sections with 7 code examples: a solid amount of guidance for an agent.

It has no GitHub stars yet, so there is no community track record; judge it on its content.

Substance
26/30
Structure
20/20
Description
12/15
Adoption
0/20
Freshness
5/15

Maintenance, license and trust

  • We could not determine when the repository was last updated.
  • Our last check on 2026-09-20 found the source still online.
  • No license is declared. By default that means all rights are reserved: you can read it, but reusing or redistributing it is not clearly permitted. Ask the author before building on it commercially.
  • Its trust signals score 68/100, with 3 cautions from licensing, adoption, age or documentation. These come from repository metadata, not a code audit — read the skill file before letting an agent act on it.

Safety scan

No issues found

Our scan of the whole file found no instruction hijacking, hidden characters, credential access, data exfiltration or destructive commands.

Automated pattern scan on 2026-10-14. It catches known dangerous patterns, not every risk — read a skill before letting an agent act on it.

domain-driven-design compared with similar skills

All 4 of these similar skills score higher than domain-driven-design; compare them before choosing.

SkillScoreStarsUpdatedFormat
domain-driven-design (this skill)by noriaki630—.clinerules
taste-skillby Leonxlnx10095.7ktodayCLAUDE.md
ai-job-searchby MadsLorentzen10046.7k5d agoCLAUDE.md
claude-howtoby luongnv8910041.9k3d agoCLAUDE.md
algorithmic-artby anthropics100177.9k21d agoSKILL.md

Frequently asked questions

How do I install domain-driven-design?
Run npx skills add noriaki/re-stock-app. The install tabs above show the steps for each supported agent.
Which AI agents does domain-driven-design work with?
It is written for Cline, as a .clinerules file. Other agents that read the same format can often use it too.
Is domain-driven-design safe to use?
Our scan of the whole file found no instruction hijacking, hidden characters, credential access, data exfiltration or destructive commands. It declares no license and scores 68/100 on trust signals. Skills are instructions an agent will follow, so read the file before installing it and do not approve commands you do not understand.
Is domain-driven-design still maintained?
We could not determine when the repository was last updated.

Re-Stock アプリのドメイン駆動設計 (DDD)

基本原則

Re-Stock アプリでは、以下の基本原則に従ってドメイン駆動設計を適用します:

  • 値オブジェクトとエンティティを区別する
  • 集約を通じて一貫性を確保する
  • リポジトリでデータアクセスを抽象化する
  • 境界づけられたコンテキストを意識する

ドメインモデル

値オブジェクト

値オブジェクトは以下の特性を持ちます:

  • 不変
  • 値に基づく同一性
  • 自己検証
  • ドメイン操作を含む
// 値オブジェクトの例
type ItemId = Branded<string, 'ItemId'>;

function createItemId(value: string): Result<ItemId, Error> {
  if (!value || value.trim() === '') {
    return err(new Error('ItemIdは空にできません'));
  }
  return ok(value as ItemId);
}

type ItemName = Branded<string, 'ItemName'>;

function createItemName(value: string): Result<ItemName, Error> {
  if (!value || value.trim() === '') {
    return err(new Error('アイテム名は空にできません'));
  }
  if (value.length > 100) {
    return err(new Error('アイテム名は100文字以内にしてください'));
  }
  return ok(value as ItemName);
}

エンティティ

エンティティは以下の特性を持ちます:

  • IDに基づく同一性
  • 制御された更新
  • 一貫性ルール
// エンティティの例
type Item = {
  id: ItemId;
  name: ItemName;
  category: Category;
  brand: BrandName;
  unopenedCount: number;
  openedCount: number;
  threshold: number;
  purchaseUrl: URL | null;
};

function createItem(params: {
  id: ItemId;
  name: ItemName;
  category: Category;
  brand: BrandName;
  unopenedCount: number;
  openedCount: number;
  threshold: number;
  purchaseUrl?: string;
}): Result<Item, Error> {
  // バリデーション
  if (params.unopenedCount < 0) {
    return err(new Error('未開封数は0以上である必要があります'));
  }
  if (params.openedCount < 0) {
    return err(new Error('開封済み数は0以上である必要があります'));
  }
  if (params.threshold < 0) {
    return err(new Error('閾値は0以上である必要があります'));
  }

  // URLの検証
  let purchaseUrl: URL | null = null;
  if (params.purchaseUrl) {
    try {
      purchaseUrl = new URL(params.purchaseUrl);
    } catch {
      return err(new Error('購入URLの形式が正しくありません'));
    }
  }

  return ok({
    id: params.id,
    name: params.name,
    category: params.category,
    brand: params.brand,
    unopenedCount: params.unopenedCount,
    openedCount: params.openedCount,
    threshold: params.threshold,
    purchaseUrl,
  });
}

ドメインサービス

ドメインサービスは、単一のエンティティや値オブジェクトに属さない操作を提供します:

// ドメインサービスの例
function isItemLowStock(item: Item): boolean {
  const totalCount = item.unopenedCount + item.openedCount;
  return totalCount <= item.threshold;
}

function getLowStockItems(items: Item[]): Item[] {
  return items.filter(isItemLowStock);
}

リポジトリ

リポジトリはデータアクセスを抽象化します:

// リポジトリインターフェース
interface ItemRepository {
  findAll(): Promise<Result<Item[], Error>>;
  findById(id: ItemId): Promise<Result<Item | null, Error>>;
  save(item: Item): Promise<Result<void, Error>>;
  delete(id: ItemId): Promise<Result<void, Error>>;
}

// インメモリ実装(テスト用)
class InMemoryItemRepository implements ItemRepository {
  private items: Map<string, Item> = new Map();

  async findAll(): Promise<Result<Item[], Error>> {
    return ok(Array.from(this.items.values()));
  }

  async findById(id: ItemId): Promise<Result<Item | null, Error>> {
    const item = this.items.get(id);
    return ok(item || null);
  }

  async save(item: Item): Promise<Result<void, Error>> {
    this.items.set(item.id, { ...item });
    return ok(undefined);
  }

  async delete(id: ItemId): Promise<Result<void, Error>> {
    this.items.delete(id);
    return ok(undefined);
  }
}

// localStorage実装
class LocalStorageItemRepository implements ItemRepository {
  private readonly storageKey = 'items';

  async findAll(): Promise<Result<Item[], Error>> {
    try {
      const data = localStorage.getItem(this.storageKey);
      if (!data) {
        return ok([]);
      }
      return ok(JSON.parse(data));
    } catch (error) {
      return err(new Error('アイテムの取得に失敗しました'));
    }
  }

  // 他のメソッドも同様に実装
}

アプリケーションサービス

アプリケーションサービスはユースケースを実装します:

// アプリケーションサービスの例
class ItemService {
  constructor(private readonly itemRepository: ItemRepository) {}

  async addItem(params: {
    name: string;
    category: string;
    brand: string;
    unopenedCount: number;
    openedCount: number;
    threshold: number;
    purchaseUrl?: string;
  }): Promise<Result<Item, Error>> {
    // IDの生成
    const idResult = createItemId(crypto.randomUUID());
    if (!idResult.ok) return idResult;

    // 名前の検証
    const nameResult = createItemName(params.name);
    if (!nameResult.ok) return nameResult;

    // カテゴリの検証
    const categoryResult = createCategory(params.category);
    if (!categoryResult.ok) return categoryResult;

    // ブランド名の検証
    const brandResult = createBrandName(params.brand);
    if (!brandResult.ok) return brandResult;

    // アイテムの作成
    const itemResult = createItem({
      id: idResult.value,
      name: nameResult.value,
      category: categoryResult.value,
      brand: brandResult.value,
      unopenedCount: params.unopenedCount,
      openedCount: params.openedCount,
      threshold: params.threshold,
      purchaseUrl: params.purchaseUrl,
    });
    if (!itemResult.ok) return itemResult;

    // 保存
    const saveResult = await this.itemRepository.save(itemResult.value);
    if (!saveResult.ok) return saveResult;

    return ok(itemResult.value);
  }

  // 他のユースケースも同様に実装
}

型安全性

ブランド型

型安全性を確保するためにブランド型を使用します:

type Branded<T, B> = T & { _brand: B };

type ItemId = Branded<string, 'ItemId'>;
type ItemName = Branded<string, 'ItemName'>;
type BrandName = Branded<string, 'BrandName'>;

Result型

操作の成功/失敗を明示的に表現するためにResult型を使用します:

type Result<T, E> = { ok: true; value: T } | { ok: false; error: E };

function ok<T, E>(value: T): Result<T, E> {
  return { ok: true, value };
}

function err<T, E>(error: E): Result<T, E> {
  return { ok: false, error };
}

実装アプローチ

  1. まず型と、それを処理する関数のインターフェースを考える
  2. ドメインの言語を型で表現する
  3. 外部依存のない純粋関数から実装する
  4. テストを先に書く
  5. IO操作は関数の境界に押し出す
  6. 外部サービスやDBへのアクセスを抽象化する

Related Skills

View on GitHub
GitHub Stars0
CategoryDevelopment
UpdatedNaNy ago
Forks0

Trust signals

68/100

From repository metadata: license, adoption, age and documentation. Not a code audit — see the Safety scan above for what the skill file itself contains.

2 medium1 low