OmniAICreator/Qiita-1.07M huggingface dataset:
JavaScriptにおけるテスト戦略：単体テストと統合テストの設計的な住み分け


## 概要

テストは単なる「確認作業」ではない。  
それは**“ソフトウェアが意図通りに動き続けるための設計支援ツール”**である。

JavaScriptにおいて、単体テストと統合テストをどう設計し、どう住み分けるかは、  
- モジュール構造  
- 責務の分離  
- 副作用の制御  
と密接に関係する。

本稿では、**テスト戦略を設計レベルで分解し、単体/統合テストの役割・設計・判断基準を明確に**していく。

---

## 1. 単体テストの目的と設計指針

```ts
// math.ts
export const sum = (a, b) => a + b;
```

```ts
// math.test.ts
test('sum of 1 and 2 is 3', () => {
  expect(sum(1, 2)).toBe(3);
});
```

- ✅ 関数単位で**入力 → 出力が決まっているもの**に適用
- ✅ 副作用なし、外部依存なしの**純粋な処理に対して有効**
- ✅ リファクタリングの安全性を担保する

---

## 2. 統合テストの目的と設計指針

```ts
// API連携 + ストア更新 + UI描画の一連の動作を検証
test('user login flow', async () => {
  render(<Login />);
  userEvent.type(screen.getByLabelText('Email'), 'test@example.com');
  userEvent.click(screen.getByText('Login'));

  await waitFor(() => {
    expect(screen.getByText('Welcome')).toBeInTheDocument();
  });
});
```

- ✅ 複数のモジュールを**現実的な形で連結して検証**
- ✅ 副作用（API、ストレージ、ルーティング）を含めて確認
- ✅ バグの**再現性とシナリオレベルの担保**に向いている

---

## 3. それぞれの役割と設計的な境界

| 項目             | 単体テスト                          | 統合テスト                          |
|------------------|--------------------------------------|--------------------------------------|
| 対象             | 関数・クラス・モジュール単位         | 機能全体・ページ・画面遷移           |
| 副作用の有無     | 原則なし（MockやStubで分離）         | 原則あり（実API or MSW/DB連携）     |
| 検証粒度         | 小さい・ピンポイント                 | 大きい・ユースケースベース           |
| 実装変更への耐性 | 高い（テスタブルな設計が前提）       | 中程度（構造変更に影響を受けやすい）|
| バグ検知力       | ロジック・境界値・例外に強い         | 繋がりの不整合・想定外フローに強い   |

---

## 4. 単体と統合を接続する設計：責務分離と依存制御

```ts
// usecase.ts
export function registerUser(apiClient, validator, userData) {
  if (!validator(userData)) throw new Error('Invalid');
  return apiClient.post('/register', userData);
}
```

- ✅ 単体テスト：validator と apiClient を Mock に差し替えて検証  
- ✅ 統合テスト：DIで依存を差し替えず、**実ロジックの流れを通す**

---

## 5. テストの優先度とカバレッジ設計

```text
- 重要なロジック・計算 → 単体テストで網羅
- ユーザーの操作フロー → 統合テストでシナリオ検証
- インフラとの接続部分 → モック or 実接続でエッジテスト
```

- ✅ 「すべてをテストする」のではなく、**目的に応じた最小構成で安定を担保**
- ✅ テストしやすさを基準に設計を見直すことが、**テストコストと品質の両立**につながる

---

## 設計判断フロー

```text
① 関数の出力は入力に依存しているか？ → 単体テスト

② モジュール間の接続部分に不安があるか？ → 統合テスト

③ 外部依存は明示的か？ → Mock可能なら単体、不可なら統合

④ ユーザー操作からのエンドツーエンド確認が必要か？ → 統合テスト

⑤ 実装変更に強いテストが必要か？ → 単体テストを重視
```

---

## よくあるミスと対策

### ❌ 統合テストだけ書いて「落ちた原因が特定できない」

→ ✅ **統合 → 単体へと掘り下げて書く**。階層別に分離して整備。

---

### ❌ 単体テストでMockを使いすぎて本番挙動と乖離

→ ✅ **Mockは「契約が安定している依存」に限定**する

---

### ❌ テストが通ってもバグが混入する

→ ✅ **「確認したい事実」に対してテストが明示的か確認する**

---

## 結語

テストを書くことはゴールではない。  
それは**“設計を洗練させ、変更に強く、意図を保証できるシステムを育てるための構造戦略”**である。

- 単体テストは、設計を明示し、モジュールを独立させる  
- 統合テストは、現実のフローを通して一貫性を確認する  
- どちらをいつ使うかは「テストしやすさ」ではなく「設計目的」で判断する

**JavaScriptにおけるテスト戦略とは、  
“確認のためではなく、進化するソフトウェアを支える設計基盤である。”**
JavaScriptにおけるユーティリティ関数設計：汎用性と責務分離の美学


## 概要

ユーティリティ関数は、**共通処理を抽象化・再利用するための最小単位**である。  
しかし一方で、それが「ただの便利関数集」になると、  
- スコープの不明瞭さ  
- 副作用の混入  
- 汎用性の破壊  
といった問題を引き起こす。

本稿では、**ユーティリティ関数を「アプリケーションを構造的に支える基盤」として設計するための原則と戦略**を解説する。

---

## 1. ユーティリティ関数の定義と分類

```ts
// 計算系
const clamp = (value, min, max) => Math.max(min, Math.min(max, value));

// 判定系
const isNullish = (val) => val === null || val === undefined;

// 変換系
const toSnakeCase = (str) => str.replace(/[A-Z]/g, (c) => `_${c.toLowerCase()}`);
```

- ✅ **純粋であること（副作用を持たない）**
- ✅ **小さく、明確な責務を持つ**
- ✅ **入力と出力が完全に制御可能**

---

## 2. 共通処理として抽出すべき基準

| 判断基準                           | 例                                  |
|------------------------------------|-------------------------------------|
| 同じ処理が3回以上現れる            | 日付フォーマット、数値変換         |
| 条件分岐で頻繁に使うロジック       | null判定、型判定                    |
| テストの独立単位にできる           | 計算処理、正規化処理                |
| 複数の層（UI/ドメイン）で利用される | ID生成、トークン付加、形式変換     |

---

## 3. 責務分離と汎用性のトレードオフ

```ts
// ❌ 責務が混在した関数
function formatUser(user) {
  if (!user) return 'N/A';
  return `${user.firstName} ${user.lastName}`;
}
```

```ts
// ✅ 単一責務に分割
const formatName = (first, last) => `${first} ${last}`;
const isUserValid = (user) => user && user.firstName && user.lastName;

function safeFormatUser(user) {
  if (!isUserValid(user)) return 'N/A';
  return formatName(user.firstName, user.lastName);
}
```

- ✅ 汎用性を保つには「粒度の分離」が鍵  
- ✅ **ユーティリティ関数は低レイヤに位置付け、特定文脈に依存しないこと**

---

## 4. 命名と責務の可視化

| 命名指針          | 意図                      |
|-------------------|---------------------------|
| `isXxx`           | 判定関数（boolean返却）   |
| `toXxx`           | 変換関数（形式変更）      |
| `createXxx`       | 新しい構造の生成          |
| `formatXxx`       | 出力用の表現調整          |
| `getXxxFromYyy`   | 特定構造からの抽出        |

- ✅ 命名は**責務そのものを示すもの**に統一  
- ✅ 関数の型だけで**使い方が想起できる設計**にする

---

## 5. テストと再利用を前提とした構造

```ts
// dateUtils.ts
export const toISODate = (d: Date) => d.toISOString().split('T')[0];
export const isWeekend = (d: Date) => [0, 6].includes(d.getDay());
```

- ✅ **モジュール単位で目的別に分類**（e.g. `stringUtils`, `arrayUtils`, `dateUtils`）  
- ✅ 関数ごとの**単体テストが簡単に書ける**ように副作用は排除  
- ✅ 共通処理は**ドメイン層ではなく基盤層**に配置する

---

## 設計判断フロー

```text
① この処理は1つの目的だけに特化しているか？ → YES → ユーティリティ候補

② 他の文脈（UI/サーバー）でも使えるか？ → YES → 抽出すべき

③ 依存する状態や副作用はないか？ → NO → 安全にメモ化・テスト可能

④ 再利用前提の命名になっているか？ → YES → 読みやすさ・維持性が向上

⑤ モジュールごとに責務が整理されているか？ → YES → スケーラビリティ確保
```

---

## よくあるミスと対策

### ❌ 一度しか使わないロジックを「とりあえずutils.ts」へ放り込む

→ ✅ **再利用性が見込めないなら、ローカル関数で閉じるべき**

---

### ❌ 複数の責務を1つのユーティリティ関数でまとめている

→ ✅ **構成単位ごとに分離し、責務を明示する**

---

### ❌ 副作用のある処理（console.logやDOM操作）を含む

→ ✅ **ユーティリティ関数は必ず「純粋関数」で設計する**

---

## 結語

ユーティリティ関数とは「小さな便利関数」ではない。  
それは**“アプリケーションのあらゆる層を横断して支える、責務と再利用の設計単位”**である。

- 再利用性と責務の分離は両立可能  
- 命名、構造、スコープを戦略的に整えることで、**コード全体の保守性が跳ね上がる**  
- 純粋で、予測可能で、明示的な「部品」が、堅牢なシステムを構成する

**JavaScriptにおけるユーティリティ設計とは、  
“小さくて強い機能を明確に分離し、全体構造に美しさを宿す戦略である。”**
JavaScriptにおけるAPI設計戦略：戻り値の構造とエラー伝達の整合性設計


## 概要

フロントエンド/バックエンドを問わず、**APIの戻り値設計は通信だけでなくアーキテクチャ全体の信頼性に直結する。**  
その「形」と「一貫性」は、  
- データの扱いやすさ  
- エラー処理の予測性  
- UI側の実装負担  
すべてに影響する。

本稿では、**JavaScriptで設計するAPIの戻り値とエラー構造の設計原則**、  
さらには**成功/失敗の表現形式、パターン統一、呼び出し元の最適化**について解説する。

---

## 1. 戻り値は「構造」と「意味」を分けて設計する

```ts
// ❌ データかどうかが戻り値の中身を見ないとわからない
fetch('/api/user')
  .then((res) => res.json())
  .then((data) => {
    if (data.error) {
      // エラー処理
    } else {
      // 成功処理
    }
  });
```

```ts
// ✅ 明示的なステータスと構造を設計
{
  status: 'ok', // or 'error'
  data: { name: 'Taro' }
}
```

- ✅ `status` フラグにより**成功/失敗の判断が即座に可能**
- ✅ `data` / `error` などのフィールドが**役割単位で分離**

---

## 2. 成功/失敗を構造的に返すパターン（Either風）

```ts
type ApiResponse<T> =
  | { ok: true; data: T }
  | { ok: false; error: string };

async function fetchUser(): Promise<ApiResponse<User>> {
  try {
    const res = await fetch('/api/user');
    if (!res.ok) throw new Error('Network error');
    const json = await res.json();
    return { ok: true, data: json };
  } catch (e) {
    return { ok: false, error: e.message };
  }
}
```

- ✅ 戻り値を構造化することで、呼び出し側で**型安全に判断可能**
- ✅ `try-catch` による制御が不要になるパターンも構築可能

---

## 3. エラーはメッセージではなく「構造」で返す

```ts
// ❌ 単なる文字列だけでは処理不能
{ ok: false, error: "Invalid parameter" }

// ✅ フィールドベースで構造化
{
  ok: false,
  error: {
    code: 'INVALID_PARAMETER',
    message: 'User ID must be a number.',
    field: 'userId'
  }
}
```

- ✅ フロントエンド側で**フィールド単位のエラーハンドリングが可能**
- ✅ i18n化・UIバリデーション連携も容易になる

---

## 4. API呼び出し側の最適化：分岐の一元化

```ts
const res = await fetchUser();

if (!res.ok) {
  showError(res.error);
  return;
}

renderUser(res.data);
```

- ✅ 成功/失敗の制御が明確・簡潔  
- ✅ 複数パターンに拡張する場合も**判定条件が安定する**

---

## 5. REST/GraphQL問わず設計に共通する指針

| 要素         | 設計方針                                |
|--------------|-----------------------------------------|
| 成功応答     | 明示的な `status: 'ok'` / `ok: true`   |
| 失敗応答     | エラー構造 `{ code, message, field }`  |
| 戻り値の型   | Union型で成功/失敗を分離                |
| 例外の扱い   | 可能な限り `throw` より `Result型` を優先 |
| 呼び出し側   | `if (!res.ok)` による**フラットな分岐構造**

---

## 設計判断フロー

```text
① APIの成功/失敗をどう判断する？ → 明示的にステータス or okフラグで表現

② エラーはどこで使われるか？ → UI連携 or ログ出力なら構造化すべき

③ 呼び出し側でtry-catchが多発していないか？ → 戻り値ベースの設計を導入

④ 型安全に処理したいか？ → Union型による成功/失敗モデルへ移行

⑤ 今後の拡張（複数エラー、バリデーション）に備える？ → エラー構造を定義
```

---

## よくあるミスと対策

### ❌ APIエラーを `throw` に任せすぎて制御が複雑化

→ ✅ **「失敗もレスポンス」として扱い、構造的に処理**

---

### ❌ 成功時と失敗時の戻り値の構造が不一致で呼び出し側がバグる

→ ✅ **必ず `status` / `ok` を軸に共通構造を設計**

---

### ❌ フロントでエラーメッセージの内容を分岐処理してしまう

→ ✅ **エラーコードを導入し、UI処理を安定化させる**

---

## 結語

API設計において最も重要なのは「通信」ではない。  
それは**“データと失敗を同じ構造で安全に管理し、UI・ロジック・保守性を整合的に設計すること”**である。

- 成功と失敗を明確に分離した構造で返す  
- 例外ではなく構造的レスポンスで制御する  
- フロントエンドとの接続面において、予測可能性と統一感を保証する

**JavaScriptにおけるAPI設計とは、  
“返すデータだけでなく、それをどう扱わせるかまでをデザインする構造戦略である。”**
【Power Automate】SharePointの情報をExcelへ自動入力する機能実装につまずいた話

今回は、Excel Online(Business)コネクタの「行の更新」アクション後、SharePointコネクタの「ファイルのプロパティの更新」アクションを利用した際に発生したエラーについて、エラー原因と対策を記載します。

## 目次

・実装イメージ
・エラー内容
・エラー原因
・エラー回避の検討 
・対策
・まとめ
・さいごに

## 実装イメージ

以下の画像のように、Power Automateを利用して、SharePoint OnlineドキュメントライブラリにアップロードしたExcelファイルのプロパティ情報を同じExcelファイルシート上に定義されているテーブルに自動で書き込む機能を実装します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3987442/74765c09-8a5d-48c2-8f3c-d40a36f72066.png)

また申請用のワークフローを開発するため、SharePointのカスタムフォーム(Power Apps)を利用していました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3987442/cdafa085-4c0c-49fd-8135-ec81eb2db4ec.png)

## エラー内容

今回の機能実装時には、Power AutomateとSharePointのカスタムフォーム(Power Apps)にてエラーが発生しました。

#### ●Power Automate
エラー文：アクション 'ファイルのプロパティの更新' に失敗しました: ファイル "https:// sharepoint.com/sites/blog_demo/sample/フローテスト.xlsx" は、共有するために<Microsoft365　アカウント>によってロックされています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3987442/0e211932-9c19-490c-b220-359599374479.png)

#### ●SharePointのカスタムフォーム(Power Apps)
　エラー文：Patch関数の使用中にネットワーク エラーが発生しました:要求された操作は無効です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3987442/0d3bc038-802e-4546-9c1c-b5d510974eb7.png)

## エラー原因

Power Automateの「行の更新」アクションのようにExcelファイルを対象にしたアクションを利用する場合、内部的にファイルロックをかける仕様となっています。
そのため、ファイルロック中はSharePointドキュメントライブラリのプロパティを編集することはできず、エラーが発生します。

## エラー回避の検討

Excel Online(Business)コネクタの「スクリプトの実行」アクションとOffice Scriptを組み合わせた、同様の機能の実装も検証しました。
結果として、「行の更新」アクションを利用した時と同じエラーが発生しました。「スクリプトの実行」アクションではファイルロックを回避することはできないようです。

以下の画像のように、SharePoint Onlineの情報を取得し、Office Scriptの引数とすることで、同様の機能が実装可能です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3987442/16fa278d-b3f7-4f4f-b696-e98263d72094.png)

検証のために利用したOffice Scriptは以下の通りです。

```TypeScript:サンプルコード

    function main(workbook: ExcelScript.Workbook,txtSample: string) {
    // Sheet1を取得する
    let applicationSheet = workbook.getWorksheet("Sheet1");
    // A1セルを取得する
    let clA1 = applicationSheet.getRange("A1");
    // 選択したシート内のセルにSPOの列の値を入力する
    if (txtSample == "") {
        clA1.setValue("");
    }
    else {
        clA1.setValue(txtSample);
    }
}

```

## 対策

ファイルロックは別アクションの処理などで意図的に解除することはできないため、「待ち時間」アクションを追加することでエラーを回避しました。
具体的な待機時間は各環境にて検証が必要ですが、目安として私の環境では6～7分ほどの待機時間が必要でした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3987442/07b18b2c-7fb4-41bd-9418-8e3a838e8e3f.png)

## まとめ

今回は、「行の更新」アクションの後にSharePointコネクタの「ファイルのプロパティの更新」アクションを利用した際に発生したエラーについて、エラー原因と対策を記載しました。
同様のエラーが発生した際のご参考になれば幸いです。

## さいごに

テンダでは、「こんなプロジェクトに挑戦したい」「こんなチームで働きたい」「理想のチームを創りたい」と願う仲間を求めています。 カジュアル面談も随時受付中です。ぜひ一度お話ししましょう。

[募集職種一覧](https://hrmos.co/pages/tenda/jobs)
[カジュアル面談の申込](https://hrmos.co/pages/tenda/jobs/031002/apply)
[テンダで働く人や社風について](https://note.com/tenda_recruit)
[テンダのMicrosoftサービス](https://mssp.tenda.co.jp/)
JavaScriptにおけるメモ化戦略：計算コストと副作用を最適化するための記憶技法


## 概要

**「同じ入力なら同じ結果を返す」処理において、再計算を省略できる手法**——それがメモ化（memoization）である。  
とくに**計算コストが高い処理、データの変換、純粋関数**などでは、  
この戦略がパフォーマンスと安定性の両立に大きく寄与する。

JavaScriptは動的で柔軟な反面、無駄な再評価が発生しやすい。  
本稿では、**メモ化の原則、関数・React・副作用における実装例、キャッシュ設計の判断基準**を示し、  
実用的かつ制御可能なメモ化戦略の構築方法を解説する。

---

## 1. メモ化とは何か

```ts
function memoize(fn) {
  const cache = new Map();
  return function (arg) {
    if (cache.has(arg)) return cache.get(arg);
    const result = fn(arg);
    cache.set(arg, result);
    return result;
  };
}
```

```ts
const slowDouble = (n) => {
  console.log('calculating...');
  return n * 2;
};

const fastDouble = memoize(slowDouble);
fastDouble(5); // 計算される
fastDouble(5); // キャッシュされているため再計算されない
```

- ✅ 入力と出力のペアを記憶し、**再評価を回避**
- ✅ 関数が**純粋である（副作用を持たない）ことが前提**

---

## 2. Reactにおける `useMemo`

```tsx
const total = useMemo(() => {
  return calculateExpensiveValue(data);
}, [data]);
```

- ✅ `data` が変わらない限り、**再評価されない**
- ✅ `useMemo` は **レンダリングコスト最適化**において重要

---

## 3. useCallbackによる関数メモ化

```tsx
const handleClick = useCallback(() => {
  doSomething();
}, [dependency]);
```

- ✅ **子コンポーネントへの props 渡しで無駄な再レンダリングを防止**
- ✅ 関数そのものの**参照が変わらないこと**を保証

---

## 4. 値の同一性とキャッシュキー設計

```ts
const memoizeJSON = (fn) => {
  const cache = new Map();
  return (obj) => {
    const key = JSON.stringify(obj);
    if (cache.has(key)) return cache.get(key);
    const result = fn(obj);
    cache.set(key, result);
    return result;
  };
};
```

- ✅ **プリミティブ以外（配列やオブジェクト）**は `JSON.stringify` 等をキーに使う必要がある
- ❌ 循環参照や巨大データに注意（コストと整合性）

---

## 5. キャッシュ戦略の設計判断

| パターン                      | 戦略                             |
|------------------------------|----------------------------------|
| 同じ値での再計算が多い       | memoize（入力値をキーに）        |
| コンポーネント描画が重い     | useMemo（計算コスト削減）        |
| 関数を子に渡す（再レンダ発生）| useCallback（参照の安定化）      |
| 大量データを変換・集計       | 外部キャッシュ（IndexedMap等）で保持 |

---

## 設計判断フロー

```text
① この関数は同じ入力なら同じ出力か？ → メモ化の候補

② 計算コストが高いか？ → キャッシュによる最適化を検討

③ 再レンダリングで毎回再評価されていないか？ → useMemo / useCallback の適用

④ 入力がオブジェクトか？ → stringify or hash でキーを設計

⑤ キャッシュのスコープは？ → ローカル / アプリケーションスコープで設計
```

---

## よくあるミスと対策

### ❌ 毎回新しいオブジェクト/関数を渡し、メモ化が意味をなさない

→ ✅ **依存配列やキャッシュキーの同一性を保証**

---

### ❌ メモ化しすぎて逆にオーバーヘッド（メモリリーク）

→ ✅ **不要になったキャッシュは明示的に削除 or スコープで限定**

---

### ❌ 副作用を持つ関数をメモ化し、意図しない挙動に

→ ✅ **メモ化の対象は純粋関数に限定すること**

---

## 結語

メモ化は「高速化の魔法」ではない。  
それは**“同じ計算を繰り返さないために、状態と責務を戦略的に保持する設計技法”**である。

- 計算コストと値の安定性を見極め、メモ化を選定する  
- useMemo / useCallback に頼りすぎず、構造的にキャッシュ設計する  
- 常に副作用とスコープを意識し、**「何を記憶するか」**を明確に設計する

**JavaScriptにおけるメモ化戦略とは、  
“コストと正確性のバランスを制御し、システムの応答性を設計として最適化するための知的キャッシュ戦略である。”**
JavaScriptにおけるグローバル状態の設計戦略：依存性・スコープ・構造の明示化


## 概要

グローバル状態は、**コードの見通しを曇らせる最大の要因の一つ**である。  
便利だが制御しにくく、依存関係を不透明にし、テストや再利用性を著しく下げる。

しかし、完全に排除することは現実的ではない。  
だからこそ重要なのは、**グローバル状態を「管理する設計」**である。

本稿では、**グローバル状態の構造的取り扱い、スコープ制御、依存性注入（DI）、状態の局所化による戦略的な状態設計**について掘り下げる。

---

## 1. グローバル状態が持つリスク

```ts
let currentUser = null;

function login(name) {
  currentUser = { name };
}

function greet() {
  return `Hello, ${currentUser?.name ?? 'Guest'}`;
}
```

- ❌ 状態がどこで変更されたか分かりづらい
- ❌ **テスト・拡張が難しく、複数のモジュールに影響**
- ❌ モジュールの結合度が高まり、依存の方向が不明瞭に

---

## 2. スコープを絞った状態管理（クロージャ戦略）

```ts
function createUserStore() {
  let user = null;

  return {
    login(name) {
      user = { name };
    },
    getUser() {
      return user;
    }
  };
}

const userStore = createUserStore();
```

- ✅ 外部からの直接操作を防ぎ、**インターフェース越しにアクセス**
- ✅ 閉包によるスコープ制御で**安全性とテスト容易性が向上**

---

## 3. 依存性注入によるグローバル回避

```ts
function greet(userStore) {
  const user = userStore.getUser();
  return `Hello, ${user?.name ?? 'Guest'}`;
}
```

- ✅ 依存関係を**引数として受け渡す**
- ✅ **モジュールの独立性**が保たれ、モックの注入も容易

---

## 4. モジュールスコープでの状態保持

```ts
// userStore.js
let user = null;

export function login(name) {
  user = { name };
}

export function getUser() {
  return user;
}
```

- ✅ 共有状態は **モジュールの中で閉じ込める**
- ✅ **名前付きエクスポートで明示的に責務を表現**

---

## 5. UIレイヤにおける状態管理（React/Vue等）

```tsx
const [user, setUser] = useState(null);
```

- ✅ グローバルでなく、**ローカルな状態を必要な単位で管理**
- ✅ グローバルが必要な場合でも **Context API / Store構成**で管理レイヤを定義

---

## 設計判断フロー

```text
① その状態は複数箇所からアクセスされるか？ → ストアとして分離

② 外部から直接操作できてしまうか？ → クロージャまたはモジュールで制御

③ テストで状態を差し替えたいか？ → DI設計に変更

④ 状態が不透明に変更されていないか？ → getter/setter型のインターフェース導入

⑤ 将来的に非同期 or 永続化される可能性は？ → ストア層で切り出しておく
```

---

## よくあるミスと対策

### ❌ 直接 `window.X = ...` でグローバル注入し、デバッグが困難に

→ ✅ **モジュール or ファクトリを用いて明示的に設計**

---

### ❌ 状態の変更箇所が散乱してトラブルシュート困難

→ ✅ **`setX`, `getX` のインターフェース越しに管理統一**

---

### ❌ グローバル状態を変更する関数が無制限に増殖

→ ✅ **状態のスコープと依存性を制御する責務分割を導入**

---

## 結語

グローバル状態は「悪」ではない。  
だが、それが**制御されないまま野放しになることが危険**なのだ。

- スコープを限定し、インターフェース越しに制御する
- 状態の変更経路を明示し、**依存性の方向を単純化**
- 必要なときだけ、必要な形で、安全にアクセスする

**JavaScriptにおける状態設計とは、  
“変更と依存を予測可能にし、構造の中で責務を分離することで、保守性と拡張性を保証する戦略である。”**
JavaScriptにおけるイベント設計戦略：カスタムイベントとコールバックの使い分け


## 概要

JavaScriptにおいて、ユーザーアクションや非同期処理の完了通知には **イベント** や **コールバック** が使われる。  
どちらも「通知」の手段だが、設計の観点から見ると**結合度・柔軟性・スケーラビリティ**に大きな違いがある。

本稿では、**コールバックとカスタムイベントの使い分け、イベントドリブン設計の指針、疎結合化のためのイベントアーキテクチャ戦略**を解説する。

---

## 1. コールバックの基本と責務

```ts
function fetchData(callback) {
  setTimeout(() => {
    const result = { message: 'done' };
    callback(result);
  }, 1000);
}

fetchData((res) => {
  console.log('Result:', res.message);
});
```

- ✅ 呼び出し元が「何をすべきか」を直接渡す  
- ✅ **高凝集・明示的な1対1の通信**に向いている  
- ❌ コールバック地獄、拡張性の乏しさ、汎用化困難

---

## 2. カスタムイベントの基本と拡張性

```ts
const event = new CustomEvent('user:created', {
  detail: { name: 'Taro' }
});
document.dispatchEvent(event);

document.addEventListener('user:created', (e) => {
  console.log('Created user:', e.detail.name);
});
```

- ✅ イベント発火元とリスナーが疎結合 → **柔軟な通知設計**
- ✅ イベント名・detailにより拡張可能  
- ✅ **1対多通信**や**将来的な変更**に強い

---

## 3. 使い分け戦略：明示 vs 汎用

| 条件                           | 推奨形式         |
|--------------------------------|------------------|
| 単一箇所でのみ使用される通知     | コールバック       |
| 汎用イベント（ログイン・エラー通知など） | カスタムイベント   |
| 外部ライブラリ連携             | コールバック       |
| UI構成間通信（モジュール間通信） | カスタムイベント   |

---

## 4. カスタムイベントの拡張設計

```ts
class EventBus extends EventTarget {
  emit(name, detail) {
    this.dispatchEvent(new CustomEvent(name, { detail }));
  }

  on(name, handler) {
    this.addEventListener(name, handler);
  }

  off(name, handler) {
    this.removeEventListener(name, handler);
  }
}

const bus = new EventBus();

bus.on('login', (e) => {
  console.log('User login:', e.detail.username);
});

bus.emit('login', { username: 'admin' });
```

- ✅ 独自の **イベントバス（PubSub）** 実装で再利用性とテスト性を両立  
- ✅ アプリケーション全体に **分離された通知ライン** を持てる

---

## 5. 結合度と拡張性の設計基準

| 観点           | コールバック                  | カスタムイベント                     |
|----------------|-------------------------------|--------------------------------------|
| 結合度         | 高（呼び出し側と処理が密結合） | 低（発火元と受信先が分離）           |
| 拡張性         | 低（1対1構造）                | 高（1対多、将来の追加に強い）        |
| テスト性       | 高（関数単位）                | 中（リスナ登録のテストが必要）       |
| 保守性         | 低（処理の移植が難しい）      | 高（通知が宣言的）                   |

---

## 設計判断フロー

```text
① 通知の対象は一箇所か？ → コールバックでシンプルに

② 複数のリスナーに通知したいか？ → カスタムイベント

③ モジュール間を疎結合にしたいか？ → イベントバスを導入

④ イベントの種類は将来的に増えるか？ → カスタムイベントを前提に設計

⑤ イベントにペイロードを持たせたいか？ → detail を活用して設計する
```

---

## よくあるミスと対策

### ❌ コールバックを多重にネストし、制御不能なコールバック地獄に

→ ✅ **Promise / async に置き換える or 責務ごとに分離**

---

### ❌ カスタムイベントを乱用し、どこで何が発火しているかわからない

→ ✅ **EventBusを設け、名前・スコープ・責務を明示**

---

### ❌ リスナーを登録したまま削除忘れでメモリリーク

→ ✅ `off` を徹底 or `once` フラグで自動解除する仕組みを導入

---

## 結語

イベント設計は、単なる「通知のしかた」ではない。  
それは**“情報伝達の責任と結合度を設計し、モジュール間の流れと柔軟性を統御するための戦略”**である。

- コールバック：シンプル・直接的。責務が明確  
- カスタムイベント：柔軟・宣言的。責務を分離し、拡張に強い  
- 設計段階で「今後の変化」にどこまで耐えるかを見据えて選択する

**JavaScriptにおけるイベント設計とは、  
“モジュール間の通信を設計構造として表現し、責務分離と拡張性を最大化する技術戦略である。”**
JavaScriptにおけるクラス vs 関数ベースの設計戦略：状態・継承・柔軟性のトレードオフ分析



## 概要

JavaScriptはクラスベースのOOPも、関数による構成的設計も許容する言語である。  
だからこそ重要になるのが、**「どちらをいつ選ぶか」**という戦略的判断だ。

クラスは**状態管理と継承構造**を持ちやすく、関数は**テスト容易性と柔軟性**に優れる。  
本稿では、**クラスと関数の設計トレードオフ、選定基準、状態・継承・副作用への適応戦略**を整理し、設計の観点から体系的に比較する。

---

## 1. クラスベース設計の特徴

```ts
class User {
  constructor(name) {
    this.name = name;
  }

  greet() {
    return `Hello, ${this.name}`;
  }
}

const user = new User('Taro');
user.greet();
```

- ✅ **状態を持つインスタンスの生成**に適する
- ✅ 継承・ポリモーフィズムを使いたいときに明示的
- ❌ **継承のツリーが複雑化しやすく、柔軟性に欠ける**

---

## 2. 関数ベース設計の特徴

```ts
function createUser(name) {
  return {
    greet: () => `Hello, ${name}`
  };
}

const user = createUser('Taro');
user.greet();
```

- ✅ **閉包による状態管理が可能**
- ✅ 柔軟・軽量・依存が明示的 → **テスタブルな構造**
- ❌ 明示的な型/継承階層を設計するには工夫が必要

---

## 3. 継承 vs コンポジションの選択基準

```ts
// 継承（OOP）
class Animal {
  speak() {
    return '...';
  }
}

class Dog extends Animal {
  speak() {
    return 'ワン！';
  }
}

// コンポジション（関数構成）
function speakDog() {
  return { speak: () => 'ワン！' };
}

function createDog() {
  return {
    ...speakDog(),
    name: 'Pochi'
  };
}
```

| 戦略         | 特徴                                     |
|--------------|------------------------------------------|
| 継承         | 型階層が明確、IDE支援が効く               |
| コンポジション | 責務ごとの構成、柔軟性・再利用性が高い   |

- ✅ 単純な型差異だけなら継承、  
- ✅ 複数の機能合成や差し替えが必要ならコンポジションが適する

---

## 4. 状態と副作用に対する設計視点

### クラス：状態を内部に閉じ込めやすい

```ts
class Counter {
  #count = 0;
  increment() {
    this.#count++;
    return this.#count;
  }
}
```

### 関数：状態を引数で受け渡し、副作用を分離可能

```ts
function increment(count) {
  return count + 1;
}
```

- ✅ **関数ベースは状態の責任を明示的に制御できる**
- ✅ クラスは**状態と振る舞いが一体化するため隠蔽性に優れる**

---

## 5. 実装の適用指針

| 観点         | クラス設計が有利な場面                     | 関数設計が有利な場面                         |
|--------------|--------------------------------------------|----------------------------------------------|
| 状態管理     | 複数のプロパティをまとめて保持したい     | 状態は外部管理、関数の引数で制御したい     |
| 継承構造     | 型ごとにメソッドを上書きしたい             | ツリー構造を避け、構成で差し替えたい       |
| テスト性     | モック可能な外部依存を注入しづらい         | 関数単位で依存を切り替えやすい             |
| 柔軟性       | 型と振る舞いを密接に設計したい場合         | ユースケース単位で自由に構成したい場合     |

---

## 設計判断フロー

```text
① 継承関係が必要か？ → ないならコンポジションを優先

② 状態を内部に持たせたいか？ → 必要ならクラスで一元化

③ 単体テストしやすいか？ → 関数分離で依存を注入可能に

④ 振る舞いの差し替えはどこで必要か？ → コンポジションで責務分離

⑤ 柔軟性と保守性のバランスを取りたいか？ → 関数型 + DI戦略を導入
```

---

## よくあるミスと対策

### ❌ 継承ツリーが深くなり、どこでオーバーライドされたか不明

→ ✅ **委譲（コンポジション）で構成し、責務ごとに分割する**

---

### ❌ 関数ベースで状態をもたせすぎて密結合に

→ ✅ **外部状態に依存する部分は外へ出し、副作用を注入形式にする**

---

### ❌ クラスに大量のユーティリティ関数を持たせて単一責務が崩壊

→ ✅ **責務ごとにクラス or ファクトリを分離**

---

## 結語

クラスと関数、どちらを選ぶかは「好み」ではない。  
それは**“状態・振る舞い・責任の所在をどう構造化し、どこまで柔軟性を持たせるか”という設計の選択**である。

- クラス：状態と振る舞いの一体化、明確な型設計  
- 関数：柔軟性とテスト性、責務の明示と切り替え可能性  
- 両者を使い分け、アーキテクチャに応じた設計戦略を選択することが鍵

**JavaScriptにおける構造設計とは、  
“構文ではなく責務と変化耐性を設計することで、進化に耐えるコードを作る戦略である。”**
JavaScriptにおけるデフォルト値設計：安全な初期化とパターンベースのフォールバック戦略

## 概要

JavaScriptでは `undefined` が多くの不具合の起点になる。  
特に入力値、外部APIのレスポンス、オプショナルな設定など、  
**「値があることを前提に書かれたコード」はしばしば脆弱**である。

そこで重要になるのが、**「デフォルト値の戦略的設計」**である。  
これは単なる `||` や `??` の話ではなく、**フォールバック戦略としての初期値設計、パターンベースの型安全化**の話である。

本稿では、**デフォルト値設計のパターン、初期化戦略、undefined耐性のある記法と設計判断**を解説する。

---

## 1. デフォルト値の基本パターン

```ts
function greet(name) {
  const user = name || 'Guest';
  console.log(`Hello, ${user}`);
}
```

- ✅ `||` は「**falsy値**」にフォールバック → `''`, `0`, `false` も対象になるため注意
- ✅ より明示的には `??`（Nullish Coalescing）を使う

```ts
const user = name ?? 'Guest'; // ← null または undefined のみを補完
```

---

## 2. 関数引数のデフォルト値

```ts
function createUser(name = 'Anonymous', age = 0) {
  return { name, age };
}
```

- ✅ 呼び出し元で省略された場合の安全な初期化
- ✅ `undefined` だけを対象にするため、**引数の意図が明確になる**

---

## 3. オブジェクトの分割代入における初期値

```ts
function initConfig({ timeout = 1000, retries = 3 } = {}) {
  return { timeout, retries };
}
```

- ✅ オプショナルなプロパティでも安全に読み取れる
- ✅ 全体が `undefined` の場合にも安全 → `{}` をデフォルトとする設計

---

## 4. 初期化関数による構造化デフォルト

```ts
function getDefaultUser() {
  return { name: 'Guest', age: null, loggedIn: false };
}

const user = inputUser ?? getDefaultUser();
```

- ✅ 複雑なデフォルト構造は関数として切り出す
- ✅ **動的構成・依存性注入**を持つ構造にも対応可能

---

## 5. フォールバック関数パターン

```ts
function getDisplayName(user) {
  return user?.name ?? getAnonymousLabel();
}
```

- ✅ `??` に関数を渡すことで、**必要なときだけ評価される**
- ✅ 重い処理の回避 + フォールバックの柔軟性を両立

---

## 設計判断フロー

```text
① falsyな値も許容するか？ → `??` を使う（`||` は避ける）

② 引数がundefinedの可能性があるか？ → デフォルト値で初期化

③ 入力オブジェクトは不完全かもしれないか？ → 分割代入 + 初期値設計

④ 複雑な構造の初期値が必要か？ → getDefault関数を導入

⑤ フォールバックが動的か？ → 関数 + `??` で遅延評価
```

---

## よくあるミスと対策

### ❌ `||` によって `false` や `0` が意図せず上書きされる

→ ✅ **「null or undefined のみ」を対象にするなら `??` を使う**

---

### ❌ 関数内で都度 `if (!value) value = default` を繰り返す

→ ✅ **関数引数 or 分割代入の初期値に移行**

---

### ❌ default 値が他モジュールや依存に結合し、テスト困難に

→ ✅ **初期値関数を抽出し、モック差し替え可能な構造へ**

---

## 結語

デフォルト値の設計は、単なる保険ではない。  
それは**“コードの前提条件を明示し、異常系に耐える構造を設計するための防衛的戦略”**である。

- `||` と `??` の使い分けは明確に
- 関数の引数と分割代入で初期値を設計的に扱う
- 動的なフォールバックは関数化し、依存と責務を切り離す

**JavaScriptにおけるデフォルト値設計とは、  
“コードの健全性を保証し、入力不備に対して安全な構造を維持するための設計技術である。”**
JavaScriptにおける条件分岐の最適化戦略：if, switch, オブジェクトリテラルによる選択制御


## 概要

条件分岐はコード内で最も多く使われる制御構造だが、  
**乱用すると分岐がスパゲッティ化し、ロジックが不透明化**する。

JavaScriptでは `if-else`, `switch`, `三項演算子`, `オブジェクトリテラル`, `関数ディスパッチ` など、  
条件制御の手法が豊富にある。重要なのは、**分岐そのものより「分岐の責務と配置」**である。

本稿では、**条件分岐の使い分け、分岐の抽象化、選択の最適戦略、設計判断の基準**を整理して提示する。

---

## 1. 基本：`if / else` の役割

```ts
if (status === 'active') {
  activate();
} else if (status === 'disabled') {
  disable();
} else {
  fallback();
}
```

- ✅ 2〜3条件までなら直感的で読みやすい
- ❌ 条件が多くなると**ネスト・重複・可読性の低下**が発生

---

## 2. `switch` による明示的分岐

```ts
switch (type) {
  case 'circle':
    drawCircle(); break;
  case 'square':
    drawSquare(); break;
  default:
    drawUnknown(); break;
}
```

- ✅ **同一キーに対する分岐**では switch が効果的
- ❌ コード量が増えやすく、**式として扱えない（戻り値がない）**

---

## 3. オブジェクトリテラルによるディスパッチ制御

```ts
const drawStrategies = {
  circle: () => drawCircle(),
  square: () => drawSquare(),
  default: () => drawUnknown()
};

const draw = (type) => (drawStrategies[type] || drawStrategies.default)();
```

- ✅ 条件をデータとして扱える → **マップベースの分離**
- ✅ 関数の切り替えが**構造的・スケーラブル**に記述可能

---

## 4. 関数型分離による選択制御

```ts
function draw(type) {
  const strategyMap = new Map([
    ['circle', drawCircle],
    ['square', drawSquare]
  ]);

  const fn = strategyMap.get(type) ?? drawUnknown;
  fn();
}
```

- ✅ 関数を値として扱うことで、**ロジックの切り替えを柔軟に管理**
- ✅ `Map` によって**ランタイム構築・条件追加が容易**

---

## 5. 戦略的に選択する条件分岐構造

| 条件の数 | 状況                         | 推奨構文             |
|-----------|------------------------------|----------------------|
| 1〜3個    | 単純条件分岐                 | `if / else`         |
| 複数定数  | 同一キーに対する処理切り替え | `switch` または オブジェクトリテラル |
| 動的登録  | ランタイムに関数を登録       | `Map + 関数ディスパッチ` |
| スタイル/クラス切り替え | UI構造の動的変更 | オブジェクトリテラル or 条件式展開 |

---

## 設計判断フロー

```text
① 条件の数は？ → 多いならデータ構造で管理すべき

② 条件は静的か動的か？ → 動的ならMapなどを活用

③ 条件に副作用が含まれるか？ → 関数として分離

④ 処理が複雑になっていないか？ → 戦略パターンの導入を検討

⑤ switch や if が肥大化していないか？ → 構造を見直し
```

---

## よくあるミスと対策

### ❌ if が10段以上続いて読解不能に

→ ✅ **マップベースの制御に書き換える（オブジェクト or Map）**

---

### ❌ switch 文で break を忘れて fall-through バグ発生

→ ✅ **各caseで必ずbreak or return する構造に**

---

### ❌ UIのクラス切り替えで if を大量に書く

→ ✅ **classNamesユーティリティやオブジェクト展開で解決**

---

## 結語

条件分岐の最適化とは、**「どの構文を使うか」より「どう整理するか」**である。  
それは**“分岐の責任とスコープを設計し、スケーラブルかつ可読性の高い制御構造を実現するための戦略”**である。

- 少ない分岐 → if / switch  
- 多い分岐 or 関数の切り替え → オブジェクト or Map  
- 分岐の意味を構造に持たせることで、**責務が可視化される**

**JavaScriptにおける条件分岐最適化とは、  
“条件の意図と責任を構造的に分離し、メンテナブルで明快な制御を構築する設計技術である。”**
ChatGPTで作る「問いリスト」で1人業務改善

# 時短勤務ワーママの私、先週なにやったのか覚えてない問題

時短勤務になって、「やべえ！」って言いながらお迎え時間ギリギリまで仕事をし、
終わらなかったタスク・返信していないSlackなど全部放りだして迎えに行く生活。

今のところ、重要なヌケモレは発生していない。（気づいていないだけ？）
しかし、濁流に飲み込まれもがくような働き方をしているので、先週なにやったのか全く覚えていない。

先生ッ・・・振り返りがしたいですッ・・・（雑）

## ChatGPTに頼む

１人で振り返るのも難しいので、ChatGPTを活用してみる。

:::note info
業務改善につながるような、自己レビュー用の質問を10個ください
:::

## 出してもらったリスト
実際のリストがこちら。

:::note info
業務改善につながる問いリスト 10選

1. 今週、最も時間を使った業務は何だったか？その時間配分は妥当だったか？
2. 一番スムーズに進んだ作業は何か？なぜうまくいったのか？
3. 逆に、思ったより時間がかかった・手間取った作業は何か？その原因は？
4. 「これ、毎回やってるけど必要？」と思った作業はあったか？
5. 他の人に聞かれたり、確認したりしたことで「仕組み化できそう」と思ったものは？
6. 手動でやっていた作業の中で「自動化できそう」「テンプレ化できそう」と感じたものは？
7. 今週のやりとりの中で「伝えづらかった」「伝わらなかった」と感じた場面は？どう改善できる？
8. 「これ、やっておけばよかった」と思ったことは何か？それは次回どうカバーできる？
9. 自分の作業が誰の役に立っているか・どう貢献しているかを実感した瞬間は？
10. 来週に向けて、1つだけ改善できるとしたら何を変えたい？
:::

## 書いてみた感想

- Googleカレンダーを見ながらやるとやりやすい
（弊社はスケジュールがGoogleカレンダーに全部入力されているので）
- 思っていたよりも考える時間を設けないと出てこないことが多かった
- なんとなくわかっている事も、改めて改善方法を考えられるので良かった
- 改善方法が思いつかない場合は**その場でChatGPTに聞ける**のがなかなか良かった
- **精神的に少し疲れる瞬間**もあった（※ネガティブへの感度が高い自分は注意が必要かも）

## 発展させるなら
- 週末に書いて、週明けに読み返すのが良さそう
- 振り返りと一緒に「タスク洗い出し」もすると◎
- 問いのアレンジしてチームメンバーと共有しても使えるかも
- **なんならプロジェクト振り返りも各自ChatGPTと壁打ちした後にメンバーでMTGのがいいのでは？**

## しばらく続けてみます！

以上、1人業務改善でした。
しばらく続けてみて、改善点とかあったらまたまとめます。
Pythonでわかる線形時不変システム（LTIシステム）における畳み込みの仕組み


##  はじめに
本記事では、線形時不変システム（LTIシステム）における畳み込みの仕組みを視覚的に理解するための、Pythonによるアニメーションコードを解説します。
入力信号とインパルス応答の関係がどのように出力を生み出すのかを、段階的に確認できるよう工夫されています。

Colab上で実行・再生・ダウンロードが可能なコードも紹介していますので、ぜひ手を動かしながら学んでみてください。


##  参考リンクまとめ

https://x.com/linear_tec/status/1906712934367338756

##  Pythonコード


```python
# --- ffmpegをインストール（必要な場合のみ）---
!apt-get -y install ffmpeg

# --- ライブラリのインポート ---
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
from google.colab import files
from IPython.display import HTML

# === 時間軸設定 ===
t = np.linspace(0, 100, 1000)
dt = t[1] - t[0]

# === インパルス応答 h(t) ===
h = np.exp(-0.1 * t)

# === 入力信号 x(t) ===
x = np.zeros_like(t)
x[(t >= 10) & (t < 30)] = 1
x[(t >= 50) & (t < 70)] = 1

# === 出力格納配列 ===
y = np.zeros_like(t)

# === プロットの準備 ===
fig, axs = plt.subplots(4, 1, figsize=(10, 10), sharex=True)
lines = []

# 1. Impulse response
lines.append(axs[0].plot(t, h, color='orange')[0])
axs[0].set_title("Impulse Response: h(t)")
axs[0].set_ylim(-5, 5)
axs[0].grid()

# 2. Input signal
input_line, = axs[1].plot(t, x, color='blue')
point_dot, = axs[1].plot([], [], 'ro')
lines.append(input_line)
lines.append(point_dot)
axs[1].set_title("Input Signal: x(t)")
axs[1].set_ylim(-5, 5)
axs[1].grid()

# 3. Area: x(u) * h(t-u)
area_line, = axs[2].plot([], [], 'red')
axs[2].set_ylim(-5, 5)
axs[2].set_title('Area: x(u) * h(t - u)  ("u" is the delay)')
axs[2].grid()

# 4. Output signal
output_line, = axs[3].plot([], [], color='blue')
axs[3].set_title(r'Output: $y(t) = \int x(u) h(t - u) du$')
axs[3].set_ylim(0, 25)
axs[3].grid()

# === アニメーション関数 ===
def update(frame):
    t_now = t[frame]
    h_shifted = np.zeros_like(t)
    if frame > 0:
        h_shifted[:frame] = h[frame - 1::-1]
        area = x * h_shifted
        y[frame] = np.sum(area * dt)
        area_line.set_data(t, area)
        point_dot.set_data([t_now], [x[frame]])
        output_line.set_data(t[:frame], y[:frame])
    return lines + [area_line, point_dot, output_line]

# === アニメーション作成 ===
ani = FuncAnimation(fig, update, frames=len(t), interval=15, blit=True)

# === MP4ファイルとして保存 ===
ani.save("convolution.mp4", writer="ffmpeg", fps=30)

# === ダウンロードリンクを表示 ===
files.download("convolution.mp4")


```

# 結果 

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4046871/1077c655-ed63-468d-ab15-5be83b55cff2.png)
#0092（2025/04/04）高速パッケージマネージャ uvのススメ

# 高速パッケージマネージャ uvのススメ

仮想環境に `venv` や `conda` を使い、パッケージ管理は主に `pip` を利用しているかと思います。この記事では、新たな選択肢として注目されている高速パッケージマネージャ **uv** を紹介します。

## uvとは？

[uv](https://github.com/astral-sh/uv) は、Rustで書かれた高速かつ安全なPython向けパッケージマネージャで、従来の `pip` や `virtualenv` を置き換えることを目的として作られています。

uvの特長は以下の通りです。

- **高速な依存関係の解決**（Rust製でスピードが段違い）
- キャッシュを効率的に使うことで、パッケージインストールを大幅に高速化
- PEP582対応で、プロジェクト内にパッケージを管理することも可能

## uvと既存技術（venv, pip）の違い

| 項目 | venv + pip | uv |
|------|------------|----|
| 仮想環境の作成 | `python -m venv` | `uv venv` |
| パッケージ管理 | `pip install` | `uv pip install` |
| 依存関係管理 | `requirements.txt` | `pyproject.toml` + `requirements.lock` |
| 速度 | 通常速度 | 非常に高速 |
| キャッシュ機構 | 一般的 | 強力（再インストールが高速化）|

uvは従来のワークフローをほぼそのまま維持しつつ、スピードと信頼性を向上させたツールです。

## uvは誰が作ったのか？

uvはPython開発ツールのエコシステムで注目されている [astral.sh](https://astral.sh/) によって作られています。astral.sh は他にも高速Pythonリンターとして有名な **Ruff** や、モダンなPython開発環境の **PDM** を開発しているチームです。

## uvの使い方の例

実際の使用例を見てみましょう。

### 仮想環境を作る

```bash
uv venv
source .venv/bin/activate
```

### パッケージをインストール

```bash
uv pip install numpy pandas
```

### インストールしたパッケージを確認

```bash
uv pip list
```

### インストールしたパッケージをrequirements.txtに書き出す

```bash
uv pip freeze > requirements.txt
```

### pyproject.tomlを使った依存関係の管理（応用編）

以下のようなシンプルな `pyproject.toml` を作成しておけば、

```toml
[project]
name = "myproject"
version = "0.1.0"
dependencies = [
  "numpy",
  "pandas"
]
```

uvで簡単に依存関係を同期できます。

```bash
uv sync
```

## 良く使うuvのコマンドまとめ

| コマンド | 説明 |
|----------|------|
| `uv venv` | 仮想環境を作成 |
| `uv pip install <pkg>` | パッケージをインストール |
| `uv pip uninstall <pkg>` | パッケージをアンインストール |
| `uv pip list` | パッケージの一覧表示 |
| `uv pip freeze` | requirements.txt 形式で出力 |
| `uv sync` | pyproject.toml に従ってパッケージを同期 |
| `uv cache clear` | キャッシュをクリア |

## まとめ

uvを使えば、普段のPython開発の速度を劇的に向上させられます。`venv` や `pip` に慣れているエンジニアこそ、その恩恵を感じやすいはずです。ぜひuvを試して、その快適さを実感してみてください！
windows11で、sketchup6 その47

# 概要
windows11に、sketchup6を入れてみた。
rubyで、3Dを書く。
プラグインのサンプル見つけたので、やってみた。

# サンプルコード

```


require 'sketchup.rb'

module Examples
	module CustomTool
		class LineTool
			def activate
				@mouse_ip = Sketchup::InputPoint.new
				@picked_first_ip = Sketchup::InputPoint.new
				update_ui
			end
			def deactivate(view)
				view.invalidate
			end
			def resume(view)
				update_ui
				view.invalidate
			end
			def suspend(view)
				view.invalidate
			end
			def onCancel(reason, view)
				reset_tool
				view.invalidate
			end
			def onMouseMove(flags, x, y, view)
				if picked_first_point?
					@mouse_ip.pick(view, x, y, @picked_first_ip)
				else
					@mouse_ip.pick(view, x, y)
				end
				view.tooltip = @mouse_ip.tooltip if @mouse_ip.valid?
				view.invalidate
			end
			def onLButtonDown(flags, x, y, view)
				if picked_first_point? && create_edge > 0
					reset_tool
				else
					@picked_first_ip.copy!(@mouse_ip)
				end
				update_ui
				view.invalidate
			end
			CURSOR_PENCIL = 632
			def onSetCursor
				UI.set_cursor(CURSOR_PENCIL)
			end
			def draw(view)
				draw_preview(view)
				@mouse_ip.draw(view) if @mouse_ip.display?
			end
			def getExtents
				bounds = Geom::BoundingBox.new
				bounds.add(picked_points)
				bounds
			end
			private
			def update_ui
				if picked_first_point?
					Sketchup.status_text = 'Select end point.'
				else
					Sketchup.status_text = 'Select start point.'
				end
			end
			def reset_tool
				@picked_first_ip.clear
				update_ui
			end
			def picked_first_point?
				@picked_first_ip.valid?
			end
			def picked_points
				points = []
				points << @picked_first_ip.position if picked_first_point?
				points << @mouse_ip.position if @mouse_ip.valid?
				points
			end
			def draw_preview(view)
				points = picked_points
				return unless points.size == 2
				view.set_color_from_line(*points)
				view.line_width = 1
				view.line_stipple = ''
				view.draw(GL_LINES, points)
			end
			def create_edge
				model = Sketchup.active_model
				model.start_operation('Edge', true)
				edge = model.active_entities.add_line(picked_points)
				num_faces = edge.find_faces || 0
				model.commit_operation
				num_faces
			end
		end
		def self.activate_line_tool
			UI.messagebox "ok"
			Sketchup.active_model.select_tool(LineTool.new)
		end
		unless file_loaded?(__FILE__)
			menu = UI.menu('Plugins')
			menu.add_item('Line Tool') {
				self.activate_line_tool
			}
			file_loaded(__FILE__)
		end
	end
end





```

以上。
! [rejected]        main -> main (non-fast-forward) エラーの解消方法

# はじめに
Gitの操作に慣れていないため、同じミスを繰り返さないように記録として残します。
# 問題
pushをしようとしたら以下のエラーが発生しました。
```
 ! [rejected]        main -> main (non-fast-forward)
error: failed to push some refs to 'github.com:ユーザー名/リポジトリ名.git'
```

# 解決方法
以下のコマンドを実行したところpushできました。
```
git pull --rebase origin main
git push origin main
```
git pull --rebase origin mainコマンドは、リモートの変更（README.md）をまず取得し、その上にローカルの変更を再適用（リベース）します。これにより履歴の不一致が解消され、その後のgit pushが成功するようになりました。

# 原因
GitHubで新しくリポジトリ作成時に「Add a README file」オプションを選択したことで、リモートリポジトリにはREADME.mdファイルが既に存在していました。しかし、このファイルをローカルリポジトリに反映する前にローカルリポジトリのファイルをコミット・プッシュしようとしたため、履歴の不一致が生じてエラーが発生しました。

# おわりに
GitHubで新しくリポジトリ作成時に「Add a README file」を選択した場合、リモートリポジトリには既にファイルが存在している状態になります。そのため、ローカルリポジトリからプッシュする前にリモートの変更を取り込むようにする。


# 参考
https://docs.github.com/ja/get-started/using-git/dealing-with-non-fast-forward-errors
AWSでBIG-IPからEC2(RHEL9)へのSNMPトラップ送信を構築・検証

# はじめに
AWS上に構築した F5 BIG-IP ロードバランサー から、RHEL9 EC2インスタンスに対して SNMPトラップ転送 を行う設定手順を紹介します。

SNMPトラップを受け取ることで、BIG-IPで発生したイベント（ログイン失敗など）を別サーバで監視・記録できます。

# 検証環境
| 種別 | 構成 |
| ---- | ---- |
| SNMPクライアント | F5 BIG-IP Virtual Edition - GOOD (PAYG, 25Mbps) |
| SNMP受信サーバ | Red Hat Enterprise Linux 9 |
| ネットワーク | 同一VPC内でUDP 162ポートを開放（Security Group） |

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3092281/e415a295-6183-4e18-8120-eb068dca8b05.png" width="80%">


# 構築手順
## SNMP受信サーバ構築（RHEL9）
### SNMP関連パッケージのインストール
```
# dnf install -y net-snmp net-snmp-utils
```

### SNMPデーモン設定
```
vi /etc/snmp/snmptrapd.conf

★★★ 以下を追記する ★★★
disableAuthorization yes
authCommunity log,execute,net public
#　authCommunity により、コミュニティ名 "public" でのトラップを受信・ログ出力します。
```
### snmptrapd.serviceの起動オプション変更
デフォルトではログ出力がされないため、/lib/systemd/system/snmptrapd.service を編集します。
```
vi /lib/systemd/system/snmptrapd.service

★★★ ExecStart設定値を変更する ★★★
ExecStart=/usr/sbin/snmptrapd -Lf /var/log/snmptrapd.log -f
# -Lf はログファイル出力、-f はフォアグラウンド実行です。
```

### サービス再起動・永続化
```
systemctl daemon-reload
systemctl enable --now snmptrapd
systemctl restart snmptrapd
```

## SNMPクライアント構築（BIG-IP）
### SNMPトラップ送信の有効化（Web UI）
１．WebUIにログインする。
２．左メニューから[System] - [SNMP] - [Traps] - [Configuration]を選択する。
３．以下の項目を Enabled にする。
・Agent Start/Stop
・Device

![Bigip3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3092281/a8fb8095-c7a3-4df8-86b1-1b7cfb0739d5.png)

### トラップ送信先の設定
１．左メニューから[System] - [SNMP] - [Traps] - [Destination]を選択する。
２．以下のように設定する。

| 項目 | 設定値 |
| ---- | ---- |
| Version | v2c |
| Community | public |
| Destination | 172.31.40.7（SNMP受信サーバのIP） |
| Port | 162 |
| Network | Management |

![Bigip4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3092281/2eddab91-cc90-4f66-a798-7630fca8d5a3.png)

## SNMPトラップ送信テスト
### 自動トラップ送信例
BIG-IPでは、Web UIログイン失敗時 などに自動でSNMPトラップが送信されます。
実際にログイン失敗を発生させると、SNMP受信サーバ構築（RHEL9）の/var/log/snmptrapd.log に以下のようなログが出力されます。
```
DISMAN-EVENT-MIB::sysUpTimeInstance = Timeticks: (164636) 0:27:26.36
SNMPv2-MIB::snmpTrapOID.0 = OID: SNMPv2-SMI::enterprises.3375.2.4.0.27
SNMPv2-SMI::enterprises.3375.2.4.1.1 = STRING: "[auth_pam:error] [pid 13354] [client xxx.xxx.xxx.xx:60019] 
AUTHCACHE PAM: user 'admin' (fallback: false) - not authenticated: Authentication failure,
referer: https://xxx.xxx.xxx.xx:8443/tmui/login.jsp" SNMPv2-MIB::snmpTrapEnterprise.0 = OID: SNMPv2-SMI::enterprises.3375.2.4
```

## おわりに

本記事では、AWS上のBIG-IPからRHEL9へのSNMPトラップ転送設定について解説しました。
SNMPトラップによって、重要なシステムイベントを外部へ通知し、運用監視の自動化や可視化に役立てることができます。
go-test-traceでテストのパフォーマンスを確認する

# Run jaeger

```
docker run -d --name jaeger -p 16686:16686 -p 4317:4317 -e COLLECTOR_OTLP_ENABLED=true jaegertracing/all-in-one:latest
```

# Run [go-test-trace](https://github.com/rakyll/go-test-trace)

Install

```
go install github.com/rakyll/go-test-trace@latest
```

Run

```
go-test-trace -traceparent=00-0af7651916cd43dd8448eb211c80319b-b7ad6b7169203331-01 -endpoint 127.0.0.1:4317 ./... -count=1
```

Open Jaeger UI with the root span id:

http://localhost:16686/trace/0af7651916cd43dd8448eb211c80319b

# Ref

- https://zenn.dev/canary_techblog/articles/2c11335be49f84
- (https://github.com/rakyll/go-test-trace
Javaにも「uv」みたいな便利ツールが欲しい！→ JBangにたどり着いた話

# はじめに

最近、独自のMCPサーバの開発を趣味としてます。

[MCPの公式ドキュメント](https://modelcontextprotocol.io/quickstart/server
)を読んだときに知った「uv」が便利でjavaにもあったらな。。。と思っていたところ、JBangというのをあるのを知ったため、そちらの紹介となります。

# JBangとは？

こちらは公式から引用させていただきますが、以下のことができます。

- 使用するライブラリをソース上に直接記載できる

```
// DEPS org.slf4j:slf4j-simple:1.7.25
// DEPS org.kohsuke:github-api:1.116
import org.kohsuke.github.*;
```

公式サイトのコメント
> Embedded Dependencies
> Automatic fetching of any dependency using //DEPS group:artifact:version > or @Grab annotations directly from the source code.


- イントールが簡単
各種以下の方法でイントールできます

```
# sdk使ってインストール可能
$ sdk install jbang

# macで定番のbrewでもインストール可能
$ brew install jbangenv/tap/jbang

# Windowsにもインストール可能
C:/> choco install jbang
```

公式サイトのコメント
> Install & Run Anywhere
> JBang installs and run on Windows, Linux, macOS, Docker and Github Actions as well as usable from Maven and Gradle plugins

- JDKがインストールされていなくても実行可能（勝手にインストールされる）

```
Downloading JBang...
Installing JBang...
Downloading JDK 11. Be Patient ...
```

公式サイトのコメント
> No Java ? No Problem!
> Java will automatically be downloaded when needed.

# さっそく使ってみよう

定番の「Hello World」やってみます。

まずは普通に実行：

```
$ jbang init hello.java --template=cli
[jbang] File initialized. You can now run it with 'jbang hello.java' or edit it using 'jbang edit --open=[editor] hello.java' where [editor] is your editor or IDE, e.g. 'codium'. If your IDE supports JBang, you can edit the directory instead: 'jbang edit . hello.java'. See https://jbang.dev/ide
$ jbang hello.java
[jbang] Building jar for hello.java...
Hello World
```

ちなみにソースはこんな感じです

```
$ cat hello.java 
///usr/bin/env jbang "$0" "$@" ; exit $?


import static java.lang.System.*;

public class hello {

    public static void main(String... args) {
        out.println("Hello World");
    }
}
```

# GitHubのファイルを即実行

ネット上にあるファイルもこんな感じで実行可能です

```
$ jbang https://raw.githubusercontent.com/jbangdev/jbang-examples/refs/heads/main/examples/helloworld.java
Hello World!
```

# まとめ
- Pythonの uv や npx って便利だなと思った！
- でもJavaにも JBang という選択肢がある！

# 参考リンク
- [公式サイト](https://www.jbang.dev/)
- [GitHubリポジトリ](https://github.com/jbangdev/jbang)
- [Qiitaタグ: JBang](https://qiita.com/search?q=jbang)
【Rails】ローカルサーバーの起動

# 記事概要
ローカルサーバーを起動する方法について、まとめる

# 前提
- Ruby on Railsでアプリケーションを作成している
- 開発環境で下記変更を行なった場合、必ずローカルサーバーの再起動が必要[^1]
    - Rubyバージョンの変更
    - テーブル・カラム情報の変更
    - Gemの導入状況の変更

# 手順(起動)
1. rails sコマンドでローカルサーバーを起動する
    ```
    # アプリのディレクトリに移動
    % cd ~/[アプリ名]
    
    # ローカルサーバーを起動
    % rails s
    ```
1. 下記が表示されると、サーバーが起動している
    ```
    => Booting Puma
    => Rails 7.1.4.3 application starting in development 
    => Run `bin/rails server --help` for more startup options
    Puma starting in single mode...
    * Puma version: 5.6.5 (ruby 3.2.0-p0) ("Birdie's Version")
    *  Min threads: 5
    *  Max threads: 5
    *  Environment: development
    *          PID: 41905
    * Listening on http://127.0.0.1:3000
    * Listening on http://[::1]:3000
    * Listening on http://127.51.68.120:3000
    Use Ctrl-C to stop
    ```
1. ブラウザで[http://localhost:3000](http://localhost:3000)にアクセスすると、サーバーに接続できる
    [![Image from Gyazo](https://i.gyazo.com/dd90df49767ab6c6dac6a28e71710b4a.png)](https://gyazo.com/dd90df49767ab6c6dac6a28e71710b4a)

# 手順(停止)
1. ターミナル.appで`control + C`を同時に押す
1. サーバーが停止できたことを確認する

# Ruby on Railsまとめ
https://qiita.com/likapantrip/items/46b43c9d1309b6633f0a

[^1]: ローカルサーバーの起動時に、1度だけ読み込まれるため
【Vue.js】フォームに入力した文字列から自動で空白を取り除く

## はじめに

Vue.jsの公式ガイドを読んでいたところ、便利な機能を初めて知ったので紹介します。

## trim修飾子

`v-model`に`.trim`をつけるだけで、フォームに入力した文字列から自動で空白を取り除いてくれます。

```vuejs
<script setup>
import { ref } from 'vue'

const message = ref('')
const t_message = ref('')
</script>

<template>
  <p>Message is: {{ message }}</p>
	<input v-model="message" placeholder="edit me" />
  <p>Trimmed message is: {{ t_message }}</p>
	<input v-model.trim="t_message" placeholder="edit me" />
</template>
```

`message`の方は頭の空白がそのままですが、`t_message`の方は空白を取り除いて表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/911578/4a6fc578-acd4-49a4-a67b-5f5c8b502651.png)

上の画像では後者の入力欄には空白が表示されていますが、Enterを押した瞬間に入力欄の空白も自動で除去されます。

## おわりに

今まで別途バリデーションしていたのですが、今後はこちらを使いたいと思います。

## 参考

https://ja.vuejs.org/guide/essentials/forms.html#trim
【Rails】DBについて

# 記事概要
Ruby on RailsのDBについて、まとめる

# 前提
- Ruby on Railsでアプリケーションを作成している

# 手順(環境設定)
1. [database.yml](https://qiita.com/likapantrip/items/0337383a5b0b368bf586)を編集する

# 手順(DB作成)
1. rails db:createコマンドでDBを作成する
    ```
    # アプリのディレクトリに移動
    % cd ~/[アプリ名]
    
    # DBを作成
    % rails db:create
    ```
1. 下記が表示されることを確認する
    ```
    Created database '[アプリ名]_development'
    Created database '[アプリ名]_test'
    ```
1. [Sequel Ace](https://qiita.com/likapantrip/items/4c363d844847825d2dca)でDBを可視化する

# Ruby on Railsまとめ
https://qiita.com/likapantrip/items/46b43c9d1309b6633f0a
【Rails】アプリケーションの新規作成

# 記事概要
フレームワークRuby on RailsでRubyのアプリケーションを新規作成する方法について、まとめる

# 前提
- Ruby on RailsをPCにインストールしている

# 手順
1. rails newコマンドで雛形を作成する
    ```
    # 新規アプリを作成するディレクトリに移動
    % cd ~/[新規アプリ作成ディレクトリ]
    
    # Railsの新規アプリを作成
    % rails new [アプリ名]
    ```
1. VSCodeで新しいアプリのフォルダを開き、さまざまなディレクトリやファイルが作成されていることを確認する

# rails newコマンド
## バージョン指定
Railsのバージョンを指定できる

```
# Railsのバージョン7.0.0を指定してアプリを作成
% rails _7.0.0_ new [アプリ名]
```

## -dオプション
データベースの種類を指定できる

```
% rails new [アプリ名] -d データベース名

# MySQLを指定
% rails new [アプリ名] -d mysql
```

## --apiオプション
API作成に特化した状態(「常にデータを返却する仕様」に特化した状態)でアプリケーションを作成できる

`html.erb`などのビューファイルが自動で作成されないなど、APIとして作っていくにあたって最適な状態でアプリケーションの作成をスタートできる

```
% rails new [アプリ名] --api
```

# Ruby on Railsまとめ
https://qiita.com/likapantrip/items/46b43c9d1309b6633f0a

# 備考
- バージョン指定でエラーが発生した場合、[こちら](https://qiita.com/likapantrip/items/b7afe47e6a537eeb628b)を参照
【Rails】Rubyアプリの作成方法

# 記事概要
フレームワークRuby on RailsでRubyのアプリケーションを作成する方法について、まとめる

# 前提
- Ruby on RailsをPCにインストールしている

# railsコマンド
Railsに関する動作を行うには、ターミナルにて`rails`コマンドを使用する

```
# railsの後にコマンドを記述する
% rails コマンド名
```

## rails gコマンド
ファイルなどを生成するために使用するコマンド

```
# ファイルを生成する
% rails g ファイルの種類 生成するファイル名
```

## rails dコマンド
`rails g`コマンドで生成したファイル一式をすべて削除するコマンド

```
# rails gコマンドで生成したファイル一式を、rails dコマンドで削除する
% rails d ファイルの種類 削除するファイル名
```

## bundle execコマンド
Gemの依存関係を整理してくれるコマンド

# アプリケーションの新規作成
基本的には、上から順番に作業を行う

## アプリケーション
https://qiita.com/likapantrip/items/b346dd251e8e689dddb3

## データベース(DB)
https://qiita.com/likapantrip/items/9323f4abbec7f58b123a

## ローカルサーバー
https://qiita.com/likapantrip/items/dc23cc74ed2c1c9d7278

## ルーティング
https://qiita.com/likapantrip/items/dbac4af68ade060decac

## コントローラー
https://qiita.com/likapantrip/items/66a30e887ffe20ad08a4

## ビュー
https://qiita.com/likapantrip/items/7773987cdd641ea3aad9

## 画像ファイルの格納
https://qiita.com/likapantrip/items/f2660ad350db508b1c5b

## モデル
https://qiita.com/likapantrip/items/8cd3ac1a970b1764b7ee

## テーブル
https://qiita.com/likapantrip/items/6e94b32d8ea9ad266964

## ライブラリ
https://qiita.com/likapantrip/items/d7317b9ece36b58dffd6

## JavaScript
https://qiita.com/likapantrip/items/1d140b2d5746e58028fc

# 備考
- Ruby on Railsのインストール方法は、[こちら](https://qiita.com/likapantrip/items/ac9b3c9262316213d259)を参照
VyOSを使用してVPCルートサーバの動作を確認

# 内容

先日リリースされたVPC ルートサーバーについて、VyOSを作成して動作を確認しました。

具体的な設定手順などはモブさんの[【ハンズオン】入門チュートリアルをもとにVPC ルート サーバーを触ってみよう！！](https://qiita.com/mob_engineer/items/fe921021a0dcbf377004)の記事に設定方法の記載がありました。本記事はVPCルートサーバーの設定が完了している前提で、VyOSを2台作成しBGPセッションを開始。片方のVyOSを停止してVPCのルートテーブルの宛先切り替わりまでを確認します。

https://aws.amazon.com/jp/about-aws/whats-new/2025/04/amazon-vpc-route-server/

# 環境

ルートサーバをASN64515で作成しVPCに関連付けを行います。ルートサーバエンドポイントの作成、ルートサーバの伝播、ルートサーバピアの作成を行います。VyOSのIPアドレス、ASN、ENIは下記の設定とします。両方のVyOSから192.0.0.0/24の経路を広報します。MED値はVyOS01が0、VyOS02が100です。VPCのルートテーブルには192.168.0.0/24の経路はVyOS01のENIが設定されています。

![スライド1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/8fc1e078-70f3-4225-af27-55788ab4cf51.png)


その後、VyOS01を停止すると、VPCのルートテーブルの192.168.0.0/24の宛先が自動的にVyOS02のENIに変更されるかを確認します。

![スライド2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/36c145d8-bec1-497f-81b7-8f240a9677a7.png)

# 検証


下記がVyOS01の設定の一部です。RM-EXPORTという名前のルートマップを作成。自分のASN64516を指定。neighborはエンドポイントのIPアドレス（10.0.0.13）とルートサーバのASN（64515）を指定してBGPを有効にします。VyOS02の方もIPアドレスやASNなどは異なりますがほぼ同様の設定となります。

```shell
set policy prefix-list PL-EXPORT rule 10 action 'permit'
set policy prefix-list PL-EXPORT rule 10 prefix '192.0.0.0/24'
set policy route-map RM-EXPORT rule 10 action 'permit'
set policy route-map RM-EXPORT rule 10 match ip address prefix-list 'PL-EXPORT'
set policy route-map RM-EXPORT rule 10 set metric '0'
set protocols bgp 64516 address-family ipv4-unicast network 192.0.0.0/24 route-map 'RM-EXPORT'
set protocols bgp 64516 neighbor 10.0.0.13 capability
set protocols bgp 64516 neighbor 10.0.0.13 remote-as '64515'
set protocols bgp 64516 parameters router-id '10.0.0.30'
```

BGPが有効になりました。

```shell
show ip bgp summary

IPv4 Unicast Summary:
BGP router identifier 10.0.0.30, local AS number 64516 vrf-id 0
BGP table version 1
RIB entries 1, using 192 bytes of memory
Peers 1, using 21 KiB of memory

Neighbor        V         AS   MsgRcvd   MsgSent   TblVer  InQ OutQ  Up/Down State/PfxRcd   PfxSnt
10.0.0.13       4      64515        17        18        0    0    0 00:01:17            0        1
```

ルートサーバピアのBGPステータスがUPになっていることを確認出来ます。

![ccc.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/bb404105-759f-4fc1-b8f9-3390cb9d6afe.png)

また、VPCのルートテーブルには動的に192.0.0.0/24：VyOS01のENIの経路が追加されていることを確認出来ます。

![aaa.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/44444900-1086-441c-af6c-381c0abecd4c.png)

この状態でVyOS01をシャットダウンします。

![スライド2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/36c145d8-bec1-497f-81b7-8f240a9677a7.png)

ルートサーバピアのBGPステータスがDOWNになっていることを確認出来ます。

![dddd.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/27553064-da34-47d9-9dbb-768c2e087133.png)

その後、VPCのルートテーブルの経路も動的にVyOS02のENIに変更されました。

![bbb.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/58985827-6697-4d2d-8b33-367ac9a19035.png)