OmniAICreator/Qiita-1.07M huggingface dataset:
【超簡単】「MCPサーバーって何？」をHTTPと図でざっくり解説してみた

「MCPサーバーは“大規模言語モデル（LLM）がデータソースや外部ツールとやり取りするための新しいプロトコル”でUSBのようなもの」と言われても、`MCP`って何なのかよくわからないですよね。

この記事では、`MCPサーバー`をHTTPと比較したり図解を用いて、できるだけわかりやすく説明していきます。

## ざっくり解説
MCPサーバーとは、`AI（LLM）`と`外部データ・ツール`をつなぐための仕組みです。
MCPサーバーを建てると、AIがGoogle DriveやSlackなど、いろんな外部サービスにアクセスして、効率的にタスクをこなせるようになります。

#### イメージ： GoogleDriveとAIを繋いで資料を探す時
```
 AI（クライアント） 
    │
    │ 「Google Driveから最新のPDF探して！」
    ▼
 MCPサーバーのwebAPIがGoogle Driveからデータを探す
    │
    │ データをAIに返す
    ▼
 AI「じゃあこの内容を要約するね〜」
```
このように、MCPサーバーとが外部の情報とAI(LLM)の仲介役となります。

### HTTPとMCPを比べると
| 項目           | HTTP                           | MCP（Model Context Protocol）               |
|----------------|----------------------------------------|---------------------------------------------|
| **使い道**      | WebページやAPIとのやり取り              | AIと外部データ・ツールとのやり取り            |
| **クライアント** | Webブラウザやアプリ                     | AI（例：Claudeなど）                         |
| **サーバー**    | Webサーバー（Apache, nginxなど）        | MCPサーバー（Google Drive, Slack等と連携）   |

まずはうっすら理解することの手助けになれば幸いです。
気になった方は、ぜひ公式ドキュメントも読んでみてください。

#### 参考文献
https://qiita.com/syukan3/items/f74b30240eaf31cb2686
https://zenn.dev/zaki_yama/articles/mcp-server-getting-started
https://qiita.com/syukan3/items/5c3c9321d713bc1d8ecf
AWS試験の日程変更に失敗した話

# AWSの日程変更にご用心
こんにちは！ocarin-aと申します！
皆さんはAWS試験の日程変更をしたことがありますか？
私は日程変更をした...つもりでした...

# AWSの罠
結論を言うと、変更完了の通知メールが来るまでが変更手続きです。
画面上で変更が完了しようと、メールが来ないのであれば変更は完了していません。

# 私の場合
1週間後に試験を予約し、数日後に変更手続きをして別日程を押さえ直したつもりでした。
しかし、変更完了のメールはこの時点で来ていません。

私は元々試験を受ける予定の日からその次の日にずらしたつもりでした。
なので、変更前の日は別の予定を入れてエンジョイしておりました。
予定を終えて駆け込みで脳みそに知識を詰め込んでいたところ、
ふと「明日何時だっけ？」と気になりAWSへログインしました。
しかし、明日受けるはずの試験の予定が表示されません。

ここで私はパニックになりました。
「え、試験の変更を間違えた？」
結果的に変更手続きは完了しておらず、私はそれをきちんと確認できていませんでした。
変更した表示や変更完了のメールがない限り、変更hできていないのです。

色々調べて変更手続きができていないことを悟った後、
私は缶チューハイを開け一気飲みしました。アヒャホゥ！
さらば、1万5千円...
私はクラウドの将来にささやかな薪をくべたのだ...

# まとめ
AWS試験の変更には気をつけよう！
同じ誤りをした人がいたら僕と握手！(無念)
Win:ExecutionPolicy

# Windowsの実行権限
windowsのPowerShellでwgetを実行する際にExecutionPolicyの制限に触れた。デジタル署名がある場合も実行が不可能であった。ExecutionPolicyを確認する手法と、変更する方法、変更先について述べる。

## ExecutionPolicyを確認する方法
PowerShellの実行権限を確認するコマンド
```Shell
$Get-ExecutionPolicy
```

### デフォルトの場合
`Restricted`と表示される。このままの場合、基本的にシェルスクリプトの実行は不可能である。
公式（）文書を確認すると次のように記述されている。
* 個々のコマンドは許可されますが、スクリプトは許可されません
* 書式設定と構成ファイル (.ps1xml)、モジュール スクリプト ファイル (.psm1)、PowerShell プロファイル (.ps1) など、すべてのスクリプト ファイルの実行を防止します

## どの設定に変えるべきか
`RemoteSigned`に変更する事で、次の場合にシェルスクリプトの実行が許可される。

* Windows コンピューターの既定の実行ポリシー
* スクリプトは実行できます
* メールやインスタント メッセージ プログラムを含むインターネットからダウンロードされるスクリプトや構成ファイルには、信頼できる発行者からのデジタル署名が必要です
* インターネットからダウンロードされたものではなく、ローカル コンピューターに書かれたスクリプトにはデジタル署名は必要ありません
* Unblock-File コマンドレットを使用するなどしてスクリプトのブロックが解除された場合、インターネットからダウンロードされた符号なしのスクリプトを実行します
* インターネット以外からの符号なしのスクリプトや、悪意のある可能性がある符号のあるスクリプトを実行するリスク

## 設定の変更方法

まず管理者としてPowerShellを実行し、次のコマンドを使用する。

```PowerShell
Set-ExecutionPolicy
   [-ExecutionPolicy] ExecutionPolicy
   [[-Scope] ExecutionPolicyScope]
   [-Force]
   [-WhatIf]
   [-Confirm]
   [CommonParameters]
```

複数のコマンドがあるが、実行権限を`RemoteSigned`に変更する方法は
```PowerShell
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned
```
で良い。

## コメント
PowerShellでは、デフォルトでの実行権限を与えていないため堅牢に感じた。一方で、初見でスクリプトを実行出来ない点に難易度の高さを感じた。
Microsoft Fabric における Lakehouse と Warehouse と Eventhouse 比較について


Microsoft Fabric では、目的やユースケースに応じて選べる 3 つの主要なストレージアーキテクチャが提供されています。この記事では、Microsoft が公開したドキュメントを参考にしてそれぞれの違いと選定ポイントを比較表形式で記載しました。

## アーキテクチャ別の比較表
| 項目 | Lakehouse | Warehouse | Eventhouse |
|------|-----------|-----------|------------|
| **データ容量** | 無制限 | 無制限 | 無制限 |
| **対応データ形式** | 非構造化、半構造化、構造化 | 構造化、半構造化（JSON） | 非構造化、半構造化、構造化 |
| **主な開発スキル** | Spark (PySpark, Spark SQL, Scala, R) | SQL | KQL, SQL, ノーコード |
| **データ構造** | フォルダ、ファイル、DB、テーブル | スキーマ、DB、テーブル | スキーマ、DB、テーブル |
| **読み取り操作** | Spark, T-SQL | T-SQL, Spark* | KQL, T-SQL, Spark |
| **書き込み操作** | Spark (Scala, PySpark など) | T-SQL | KQL, Spark, コネクタ経由 |
| **複数テーブルトランザクション** | ❌ | ✅ | ✅（インジェスト時） |
| **開発インターフェース** | Sparkノートブック、Sparkジョブ | SQLスクリプト | KQLクエリセット、KQL DB |
| **セキュリティ** | RLS, テーブルレベル(T-SQL), CLS** | オブジェクト レベル(table, view, function, stored procedure), RLS, CLS, DDL/DML, 動的データ・マスキング | RLS |
| **ショートカットアクセス** | ✅ | ✅（SQL分析エンドポイント経由） | ✅ |
| **ショートカットのソース** | ✅（ファイルとテーブル） | ✅（テーブル） | ✅ |
| **クエリ横断** | ✅ | ✅ | ✅ |
| **高度な分析** | 並列処理、フォールトトレランス | 同左 | 時系列、ジオ空間、全文検索など |
| **対応フォーマット** | PARQUET, CSV, JSON, AVRO, Hive形式 | 同左 | JSONや全文対応のインデックス機能 |
| **取り込み遅延** | 即時クエリ可能 | 即時クエリ可能 | キューイング・ストリーミング数秒レイテンシ |

 \* Spark では、ショートカットを使用したテーブルからの読み取りがサポートされています。ビュー、ストアド プロシージャ、関数などのアクセスはまだサポートされていません。
 ** T-SQL を使用して、SQL 分析エンドポイントを介して Lakehouse で利用できる列レベルのセキュリティ。

 ## ユースケース別の選定ガイド
* Lakehouse：データサイエンス、機械学習、様々な形式のデータを統合分析したいとき
* Warehouse：高パフォーマンスなBI、業務データ分析、トランザクション重視
* Eventhouse：リアルタイムデータ、ログ分析、アプリケーションからのストリーミング処理向き

## 🔗 参考リンク（Microsoft 公式ドキュメント）

- 🧭 [Microsoft Fabric の意思決定ガイド: ウェアハウスと Lakehouse の選択](https://learn.microsoft.com/ja-jp/fabric/fundamentals/decision-guide-lakehouse-warehouse)
- 🧠 [Microsoft Fabric 意思決定ガイド: データ ストアを選択する](https://learn.microsoft.com/ja-jp/fabric/fundamentals/decision-guide-data-store)
- 🏞️ [Microsoft Fabric のレイクハウスとは](https://learn.microsoft.com/ja-jp/fabric/data-engineering/lakehouse-overview)
- 🏢 [Microsoft Fabric のデータ ウェアハウスとは](https://learn.microsoft.com/ja-jp/fabric/data-warehouse/data-warehousing)
【TypeScript】tsconfig.jsonで「設定 "composite": true が必要です」と「生成を無効にできません」が出てきた時の対処法

## 発生した事象
以下のように`tsconfig.json`ファイルを記述したところ、referencesの2つのpathにエラーが発生していました。
```typescript:tsconfig.json
{
  "files": [],
  "references": [
    { "path": "./tsconfig.app.json" },
    { "path": "./tsconfig.node.json" },
    // tsconfig.app.jsonとtsconfig.node.jsonはルート直下に入っている前提
  ],

  "compilerOptions": {
    "target": "ESNext",
    "useDefineForClassFields": true,
    "lib": ["DOM", "DOM.Iterable", "ESNext"],
    "allowJs": false,
    "skipLibCheck": true,
    "esModuleInterop": false,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "module": "ESNext",
    "moduleResolution": "Node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react-jsx",
    "types": ["node", "jest", "@testing-library/jest-dom"]
  },
  "include": ["src"],
}
```

エラーの内容は次の通りでした。
* 「参照されているプロジェクト '(jsonが格納されたフォルダ)/tsconfig.app.json' には、設定 "composite": true が必要です。」
* 「参照されたプロジェクト '(jsonが格納されたフォルダ)/tsconfig.node.json' は、生成を無効にできません。」

## 「設定 "composite": true が必要です。」エラーの対処法
エラーが出ているjsonファイルに`"composite": true,`の記述を追加します。compilerOptionsの内側であれば場所はどこでもOKです。

```diff:tsconfig.app.json
{
  "compilerOptions": {
+ 　"composite": true,
 }
}
```

## 「生成を無効にできません。」エラーの対処法
該当するjsonファイルに含まれている`"noEmit": true,`の記述を削除します。
```diff:tsconfig.app.json
{
  "compilerOptions": {
- 　 "noEmit": true,
 }
}
```

## 最後に
上記の2つの処理を行うことでpath周りのエラーは解消されました。
同じような現象で困っている方の参考になれば幸いです。

## 参考資料

https://zenn.dev/katsumanarisawa/articles/58103deb4f12b4

https://zenn.dev/hayato94087/articles/d05b3eb7de1fcf
📦 Amazon Ember ~ Amazon 自社ブランド専用フォント ~ 

## はじめに

実務にてフロントアプリで利用中のフォントが `AmazonEmber_Rg.ttf` と指定があり、Amazon? なんだこれっと気になったのでざっくり調べてみました。

## 目次

1. [Amazon Emberって何？](#-amazon-emberって何)
2. [.ttf って何？](#-ttf-って何)
3. [使用方法](#-使用方法)
4. [まとめ](#-まとめ)
5. [参考文献](#-参考文献)

## 🔤 Amazon Emberって何？
`Amazon Ember` は、**Amazon が自社のブランドに合わせて開発した 専用フォント。**
 Web、モバイルアプリ、Kindle デバイスなど、あらゆる製品やサービスに使われています。
 
* 読みやすさ重視：長文や小さなサイズでも視認性が高い
* ブランド性：Amazon らしさ（シンプルで親しみやすい感じ）を出すためのデザインバリエーション
* 豊富：Light, Regular, Bold, Italic などスタイルが複数ある

## 📁 .ttf って何？
`.ttf` は `TrueType Font` の略で、広く使われているフォント形式の一つ。
 Web やアプリ、OS に組み込みやすい形式です。

## ✨ 使用方法
`~assets` は **Nuxt の Webpack で解釈されるエイリアス** です。
URL ではアクセスできないけど、CSS 内で使うなら以下の記述で読み込める。

* `@font-face`：フォントの読み込み
* `~assets`：Webpack で解釈されるエイリアス
```scss:/nuxt/assets/variables.scss
@font-face {
  font-family: 'AmazonFont';
  src: url('~assets/font/AmazonEmber_Rg.ttf') format("truetype");
}
```
💡 `AmazonEmber_Rg.ttf` は、Amazon のコーポレートフォントの一つ
💡 `Amazon Ember` の「Regular（標準）」ウェイトの `TrueType` フォントファイル



## 🎉 まとめ
* `Amazon Ember` は Amazon が自社のブランドに合わせて開発した専用フォント
* `assets` でURL指定することで `AmazonEmber_Rg.ttf` をcssで使用可能

Amazon Ember を使いたいなら、Amazon が提供している正式な方法（例えば Kindle 開発など）に従う必要があります。
代替フォントとしては `RobotoOpen SansHelvetica` など、読みやすくてシンプルな Web フォントも多数あります。

## 💫 参考文献
* [Amzon Ember](https://developer.amazon.com/ja-JP/alexa/branding/echo-guidelines/identity-guidelines/typography)
【事例で学ぶ】APT攻撃への備えが会社の運命を分けた話

APT（Advanced Persistent Threat）攻撃は、今や大企業だけでなく中小企業も標的になるサイバー攻撃です。  
今回は、**セキュリティ対策を講じていた「会社A」と、無対策だった「会社B」** が同じAPT攻撃に遭遇したときの違いを、ストーリー仕立てで解説します。

---

## 🏢 登場企業

### ✅ 会社A：セキュリティ重視の精密機器メーカー
- SOC（セキュリティオペレーションセンター）設置
- 多層防御（EDR、SIEM、MFA、WAF）を導入済み
- 社員へのセキュリティ教育も徹底

### ❌ 会社B：急成長中のITベンチャー
- セキュリティ専門部署なし
- ウイルス対策ソフトのみ導入
- セキュリティ研修未実施

---

## 🕵️‍♂️ APT攻撃の始まり：月曜日の朝

### 会社Aの場合：
社員がスピアフィッシングメールを受信。しかし不審に思いSOCに報告。  
EDRが添付ファイルを検出・隔離し、SIEMにより異常を即時検知。  
SOCが封じ込め対応し、被害はゼロ。

> 🛡️ **未遂対応で防御成功。信頼性アップ。**

---

### 会社Bの場合：
社員が業務メールと信じて添付ファイルを開封。  
マルウェアが侵入、バックドアが設置されるも誰も気づかず。  
攻撃者は静かに内部ネットワークを探索開始。

> 🚨 **初動の遅れで内部侵害が進行。**

---

## ⏳ 数週間後：攻撃の深化

### 会社A：
SIEMとEDRに異常なし。定期監視でネットワーク健全を確認。

### 会社B：
攻撃者が権限昇格を達成し、社内の機密ファイル・ソースコードにアクセス。  
顧客データ含む重要情報が外部に転送され続ける。

---

## 🔥 結末の違い

### 会社A：
未遂事例として社内に共有され、意識がさらに向上。  
顧客からの信頼も揺るがず、事業は順調。

### 会社B：
1ヶ月後、外部セキュリティベンダーからの通報で発覚。  
「100万人分の顧客データ流出」と報道され、株価急落・契約打ち切り多発。  
最終的には他社に吸収合併される。

---

## ✅ 比較まとめ

| 項目         | 会社A（対策あり）       | 会社B（対策なし）             |
|--------------|--------------------------|-------------------------------|
| 初期対応     | SOCが即時検知＆封じ込め | 社員がマルウェア実行         |
| 被害規模     | なし                     | 顧客情報100万人分流出         |
| 社会的評価   | 「しっかり守った企業」   | 「信用できない企業」         |
| ビジネス影響 | 信頼維持、成長継続       | 信頼失墜、吸収合併            |

---

## 💡 この事例からの学び

- **APT攻撃は防げなくても、被害を最小限に抑えることはできる。**
- **セキュリティ対策は「費用」ではなく「投資」。**
- **SOCやSIEMのような仕組みは、早期発見・迅速対応のカギ。**
- **社員教育も最前線のセキュリティ対策の一つ。**

---

## 🔐 最後に

APT攻撃のような高度な脅威に備えるには、「技術」と「人」の両面の対策が不可欠です。  
「うちは狙われるような会社じゃないから…」ではなく、**「備えていたから助かった」**という状況を作れるよう、セキュリティ体制を見直していきましょう。
ChatworkにPythonから通知を送る方法

# ChatworkにPythonから通知を送る方法（業務自動化にも便利！）

こんにちは！今回は、**PythonからChatworkにメッセージ通知を送る方法**をご紹介します。

業務の自動化や、処理完了の確認、エラー通知などに活用できる便利なスクリプトです。

---

## 🔧 事前準備

Chatwork APIを使うために、以下の準備が必要です。

### ✅ Chatwork APIトークン
- Chatworkにログインし、右上のアイコン → [API設定] から取得できます。

環境変数や `.env` ファイルに設定しておくと安全です：
```env
CHAT_WORKS_API=your_chatwork_api_token
```

### ✅ ルームID
- 通知を送りたいチャットルームのIDを確認しておきましょう。
- **ルームIDはChatworkでチャットルームを開いたときのURLに含まれています。**
  例えば、以下のようなURLの場合：
  
  ```
  https://www.chatwork.com/#!rid123456789
  ```
  
  → この `123456789` がルームIDです。

---

## 🐍 Pythonコード

以下がChatworkにメッセージを送信するPython関数です。

```python
import os
import requests
from datetime import datetime
from dotenv import load_dotenv

load_dotenv()

CHAT_WORKS_API = os.getenv('CHAT_WORKS_API')

def chat_works(message, room_id):
    URL = 'https://api.chatwork.com/v2'
    current_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
    str_out = message + "\n"
    str_out += f"現在時刻: {current_time}\n\n"

    url = URL + '/rooms/' + room_id + '/messages'
    headers = {
        'X-ChatWorkToken': CHAT_WORKS_API,
        'Content-Type': 'application/x-www-form-urlencoded'
    }
    data = {'body': str_out}

    resp = requests.post(url, headers=headers, data=data)
    if resp.status_code == 200:
        print(resp.content)
        print('\nChatworkへ通知しました\n')
    else:
        print(f"エラー: {resp.status_code}")
```

---

## 📦 使用例

例えば、kintoneのレコード更新後や、定期バッチ処理の完了通知にこう使います：

```python
chat_works("kintoneのデータが更新されました", "123456789")
```

---

## ✅ まとめ
- Chatwork APIを使えば、Pythonから簡単にメッセージを送信可能！
- 処理の完了通知や障害の早期発見に役立ちます。
- チーム内でのリアルタイムな共有にも便利です。

---

## 💬 最後に
Chatwork通知は、ちょっとした工夫でチームの情報共有をよりスムーズにします。
業務効率化やアラート通知の仕組みにぜひ取り入れてみてください！

記事が役に立ったら「いいね」やコメントで教えてもらえると嬉しいです！ 🙌
Pythonで作る簡易Qiita投稿MCPサーバーの解析と実装解説

# Pythonで作る簡易Qiita投稿サーバーの解析と実装解説

## はじめに
これもコードの解析から自動投稿された記事となります。

今回は、PythonでQiitaへの記事投稿を自動化するシンプルなサーバーの実装コードを解析します。このコードはFastMCPというフレームワークを使用してツール関数を定義し、Qiita APIを通じて投稿を行うものです。

## コードの全体像

提供されたコードは以下の機能を持つPythonスクリプトです：

1. 必要なライブラリのインポートとインストール
2. 環境変数からQiitaのAPIトークンを取得
3. FastMCPを使用したサーバーの初期化
4. Qiita投稿用の関数定義
5. サーバー起動のエントリーポイント

## 主要コンポーネントの解説

### 必要なライブラリの自動インストール

```python
# requests が無ければ自動インストール
try:
    import requests
except ModuleNotFoundError:
    subprocess.check_call([sys.executable, "-m", "pip", "install", "--upgrade", "requests"])
    import requests
```

このコードブロックでは、`requests`ライブラリがインストールされていない場合に自動的にインストールする機能が実装されています。これにより、スクリプトの実行環境への依存関係のセットアップを簡略化しています。

### 環境変数の設定

```python
from dotenv import load_dotenv
load_dotenv()
QIITA_TOKEN = os.getenv("QIITA_TOKEN")
```

`.env`ファイルから環境変数を読み込み、Qiita APIのアクセストークンを取得しています。これはセキュリティのためにコード内にトークンを直接書かないための良い実践です。

### FastMCPサーバーの初期化

```python
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("Qiita投稿MCPサーバー")
```

FastMCPというフレームワークを使用してサーバーインスタンスを初期化しています。このフレームワークを使うことで、ツール関数を簡単に定義・提供できるようになります。

### Qiita投稿ツール関数

```python
@mcp.tool()
def post_qiita_article(article_json: str | dict) -> dict:
    """
    記事データファイルのパス（str）または記事データ本体（dict）を受け取り、Qiitaに投稿します。
    """
```

この関数は以下のような処理を行います：

1. 入力として記事データのファイルパス（文字列）または記事データ（辞書型）を受け取る
2. QiitaのAPIトークンの存在確認
3. ファイルパスが与えられた場合はJSONファイルを読み込む
4. 辞書型データの場合はそのまま使用
5. Qiita APIにPOSTリクエストを送信
6. レスポンスをJSON形式で返す

特に柔軟な入力形式を受け付ける設計になっており、ファイルパスまたは直接データを受け取れるようになっています。

### エラーハンドリング

コード内では以下のようなエラーハンドリングが実装されています：

1. APIトークンが設定されていない場合
2. 指定されたファイルが存在しない場合
3. 入力パラメータの型が正しくない場合
4. API応答のJSONパースに失敗した場合

これらのエラーには適切なエラーメッセージが返されるようになっています。

## Qiita APIの利用方法

Qiita APIを使用する際の基本的なパターンがシンプルに実装されています：

```python
headers = {
    "Authorization": f"Bearer {QIITA_TOKEN}",
    "Content-Type": "application/json"
}

resp = requests.post(
    "https://qiita.com/api/v2/items",
    headers=headers,
    json=data
)
```

この部分では、認証ヘッダーを設定し、投稿データをJSON形式でAPIエンドポイントに送信しています。

## まとめ

このコードは以下の点で優れたPythonプログラミングの例を示しています：

1. **依存関係の自動管理**: 必要なライブラリを自動インストール
2. **セキュリティ対策**: API認証情報を環境変数から取得
3. **柔軟な入力処理**: 複数の入力形式（ファイルパスまたは直接データ）に対応
4. **適切なエラーハンドリング**: 様々なエラーケースに対処
5. **モジュール設計**: FastMCPフレームワークを使用した整理された構造

このような設計パターンは、APIを活用した自動化ツールを開発する際の参考になるでしょう。

## 実装のポイント

1. `.env`ファイルに`QIITA_TOKEN=あなたのQiitaトークン`を設定する必要があります
2. 記事データはQiita APIの仕様に従ったJSON形式である必要があります
3. FastMCPフレームワークのインストールが必要です（`pip install fastmcp`など）

このコードを応用することで、Qiitaへの投稿を自動化するだけでなく、他のAPIサービスとの連携も同様のパターンで実装できるでしょう。
Next.js(App Router) cookieの扱い方

## はじめに
web系を中心に開発している、エンジニアの [yh1110]("https://qiita.com/yh1110") です。

個人開発として進めているwebアプリにて、cookieの扱い方で行き詰まった部分があったので備忘録として書き残しておきます。

サーバーアクションまわりでの扱い方で少し苦戦したので誰かの助けになれば幸いです。

## 概要
- server actionsでのcookieの扱い方
- client, server componentでの扱い方

## 前提
@next/headersのcookiesについての扱い方を主に書いていきます。

## 本題

そもそもとしてNext.jsのApp Routerでは、cookiesの.set()や.delete()が使えるのは **サーバーアクション**か**ルートハンドラー**でしか使用できません。(document.cookieは問題ないですが、今回の趣旨とはずれるので割愛)


基本的にサーバーコンポーネントやクライアントコンポーネントではcookieの値の操作は取得のみとなります。

参考↓

https://nextjs.org/docs/app/api-reference/functions/cookies

### :grey_question: なぜサーバーアクション or ルートハンドラーのみか

**ざっくりした解説**

cookieとはブラウザにkeyとvalueにて保存されます。

headerにcookieの値をくっつけてブラウザにリクエスト → 無事ブラウザのcookieに保存されます。

例えば下記のようなクッキーをセットするだけのサーバーアクションが実行されると

``` ts
"use server";

import { cookies } from "next/headers";

export async function setCookies() {
  const cookieStore = await cookies();
  const cookie = cookieStore.set("key", "value");
}

```

サーバーアクションの実行をトリガーとして、このようなヘッダーをブラウザに投げます。

```
Set-Cookie: key=value; Path=/
```

このような処理の流れとなるので、ブラウザに対してcookieをどう送るかがカギとなります。
ルートハンドラも同様です。

:::note warn

cookie情報を含んだヘッダーはブラウザに対して投げないと、セットできないためエラーとなります。
:::


### :grey_question: サーバーコンポーネントもSSRでリクエスト送ってるからcookieのセット出来るんじゃないのか


SSRはレスポンスを返す処理ではないので出来ません。
あくまでもサーバーでReactをレンダリングしているにすぎないので、レスポンス自体にはアクセスできません。
また、Next.jsの設計の思想上、レスポンスを書き換える副作用の処理なので、制限されています。(宣言的UIの原則に反する)

### :grey_question: クライアントコンポーネントはさすがに出来ますよね

cookieをセットすることは出来ますが、```document.cookie```でしか出来ないです。
そもそもnext/headersがnode.jsランタイム上で動いているため、エラーとなります。
セキュアな値でなければ```document.cookie```でも問題ないし、テーマとかのUI関連ならむしろそっちを使うべきだと思っています。

### :no_entry_sign: 実行コンテキスト制限
これは私がハマったとこなのですが、下記のようにcookieをセットする関数を作成し、サーバーアクション内で呼び出すとエラーとなります。


```ts
// actions/setCookiesAction.ts
"use server";

import { cookies } from "next/headers";
import { setCookie } from "@/utils/setCookie";

export async function setCookiesAction() {
  await setCookie();
}


// utils/setCookie.ts
"use server"

export async function setCookie() {
  const cookieStore = await cookies();
  const cookie = cookieStore.set("key", "value");
}

```

**ざっくりした解説**

```cookie().set()```を読んだコードがサーバーアクションのコンテキスト内でなければエラーとなります。
```cookies().set()```は副作用を発生させる(レスポンスヘッダーを書き換える)ため、Next.jsが完全に責任を持って実行・追跡出来ないからです。
そのためcookieのセットなどの副作用APIはサーバーアクションのトップレベルで使用する必要があるということになります。

### :grey_question: じゃあ取得はなんでサーバーコンポーネントでもOKなのか

リクエストに含まれてるヘッダー情報を読み取る処理だからです。
```.set()```の場合はレスポンスを書き換えるような「副作用」を持っていますが、取得に関しては純粋な読み取りなので、問題ないです。

## まとめ
cookieに関してはoAuth等で使用することはありますが、特に気にも留めずに (エンジニアとして良くない) 実装することが大半だったので、エラーを通じてcookieの仕様を「完全に理解」しました。
cookieのセットに関しての制約が意外とありますが、それと同時にNext.jsの設計思想を強く感じました。
ここまで読んでいただきありがとうございました！
「Dotnet new console」を実行したらNU1302エラーが発生

### 背景
コンソールアプリケーションをコマンドをたたいて作成しようしたら下記のエラーが表示されプロジェクトファイルの作成に失敗した。

### エラーの内容
``` text:書き方
error NU1302: 'HTTP' ソースを使用して 'restore' 操作を実行しています:
http://******.com/nuget。NuGet には HTTPS ソースが必要です。
HTTP ソースを使用するには、NuGet.Config ファイルで'allowInsecureConnections' を [true] に
明示的に設定する必要があります。詳細については、https://aka.ms/nuget-https-everywhere を
参照してください。
```
### 原因
どうやらパッケージのURLでHTTPを使用されていることが原因でした。
.NET ドキュメントを確認したところ「SDK 分析レベルの値 9.0.100未満の場合、HTTP ソースを使用すると警告がトリガーされます」とのことで…
現在の環境が.NETSDKのバージョンが7.0を使用していたため設定ではじかれていました。

### 解決方法
解決方法は２つあるようですが、公式パッケージのためHTTP接続の許可をする方法をとりました。
具体的な方法としては、Nugetのパッケージ管理ファイルとなる「Nuget.Config」にて指定のパッケージのURLにてHTTPの接続許可を行います。
**"allowInsecureConnections="true"** を指定します。
下記は例となります。

```XML:Nuget.Config
<configuration>
  <packageSources>
    <add key="SecureSource" value="https://example.com/nuget/"allowInsecureConnections="true"/>
  </packageSources>
</configuration>
```

このエラーに半日ハマるという…
実装よりも環境設定が難しいと感じる日々です。

詳しくは下記を参照してください。
**「NuGet エラー NU1302」**
https://learn.microsoft.com/ja-jp/nuget/reference/errors-and-warnings/nu1302
GitLab CI/CDかJenkinsかー実際に悩んでみて

# GitLab CI/CDをベースにJenkinsも導入へ - ログ解析を通じたCI/CDツール選定

## 1. はじめに

CI/CDの導入は、開発プロセスの自動化・効率化を進める上で不可欠です。本稿では、代表的なCI/CDツールである **GitLab CI/CD** と **Jenkins** の特性と、実運用での使い分けについて、具体的なユースケースを交えて整理してみました。

## 2. GitLab CI/CDとJenkinsの概要

| 項目 | GitLab CI/CD | Jenkins |
|------|----------------|---------|
| 開発元 | GitLab社 | OSS（コミュニティ主導） |
| インストール要否 | GitLabに統合（SaaS/オンプレ） | 自前でサーバ構築が必要 |
| ジョブ定義 | `.gitlab-ci.yml`（YAML） | Jenkinsfile または GUI設定 |
| プラグイン | 少なめ（標準機能が充実） | 豊富なプラグイン群 |
| VCS連携 | GitLabに特化 | 多様なVCSに対応（GitHub, Bitbucketなど） |

## 3. メリット・デメリット比較

### GitLab CI/CD

**メリット**
- GitLabに統合されており、導入しやすい
- YAMLベースでCI設定が明確で、バージョン管理しやすい
- GitLabの権限管理と連携可能
- Web UIからパイプラインの状況が視覚的に把握できる

**デメリット**
- GitLab以外のリポジトリとの連携に不向き
- UIや通知設定などの柔軟性に乏しい
- 外部ファイルや複雑な条件付き処理には不向き

### Jenkins

**メリット**
- 高いカスタマイズ性（プラグインで自由に拡張可能）
- あらゆるVCSやビルドツールと連携可能
- スケジュール実行や外部イベント連携などにも柔軟に対応

**デメリット**
- 自前運用が必要（セキュリティやメンテナンスの手間がかかる）
- 初学者には学習コストがやや高い
- プラグイン依存によるトラブルの可能性がある

## 4. 使い分けの判断ポイント

| 判断軸 | GitLab CI/CDが向いている | Jenkinsが向いている |
|--------|---------------------------|------------------------|
| Gitとの連携 | GitLab利用時 | GitHub, Bitbucketなどと併用している場合 |
| 導入コスト | 低く抑えたい | 環境構築・カスタマイズ重視の場合 |
| ワークフロー | シンプルでGitベース | 複雑な条件分岐や外部連携、非Gitトリガ対応 |
| 運用規模 | 小〜中規模チーム | 大規模、複数プロジェクト管理時 |
| IN/OUTファイル | コミット必要(構成管理対象のファイル) | コミット不要(構成管理対象だけでなく一時ファイルも解析できる) |


## 5. 実際の活用例とユースケースでの使い分け

### Jenkinsでログ解析を自動化したユースケース

当初はGitLab CI/CDで構築していたが、以下の課題に直面：

- ログをインプットとするにはリポジトリにコミットが必要
- 一時的なファイルをGit管理するのは非効率（履歴不要）
- ストレージの無駄遣いやCIの無駄なトリガ増加
- 大容量ファイルがリポジトリを肥大化させる

このため、**GitLabでCI/CDを運用していたが、課題に直面し、後からJenkinsの導入を検討・実装**しました。

CAN通信ログに含まれるCPU使用率ログをPythonで解析し、Jenkins上で以下のフローを構築：

1. Jenkins Web UIからファイルをアップロード
2. スクリプトを実行して解析処理を実施
3. 結果をレポートとして出力

→ JenkinsはGitに依存せず、柔軟にファイルを取り扱えるため、ログ解析などの一時的な処理に最適

また、Jenkins上で解析スクリプトを柔軟に差し替えられるため、ログ形式の変更やフィルタ条件の追加などにも素早く対応できる。

### GitLab CI/CDが効果的だったユースケース

- コードのビルド・ユニットテスト・静的解析など、コミット単位で確実に実行
- マージリクエストに連動して自動でCIが動作し、レビューの効率化に貢献
- Markdownベースのドキュメント（設計資料など）をPandocでPDFに自動変換し、成果物として出力

→ コードとドキュメントの変更・レビュー・CIを1つのUIで完結できる点が大きな強み

## 6. まとめと得られた気づき

- GitLab CI/CDとJenkinsは、それぞれに強みと弱みがある
- "最初から完璧な選定"は難しく、**実際に運用してみて分かることも多い**
- ツールを使い分けるという柔軟な発想が、現場に最適なCI/CDを育てていく

## 7. 補足：ハイブリッド運用の可能性

- GitLabでコード管理＋レビュー用CI、Jenkinsで夜間バッチや外部データ連携を実行
- 役割を分けることで、CI/CDツールを無理に一本化せず効率的な運用が可能
データのクリーニング【PHP】

## ユーザーの投稿データは汚い

なんて書くと、ユーザーから「なんだと！　傲慢な開発者め！」と言われそう。
だが、これは事実である。

ユーザーの投稿するデータはすべて汚れているという前提に立つのがセキュリティの基本であると言える。
よって、このデータをキレイキレイにしなければならない。

## 汚れたデータからクリーンなデータを抽出する

汚れているデータからクリーンなデータを抽出するには、バリデーションとサニタイズの両方をやる必要がある。
まずバリデーションでデータを検証し、不正なデータならエラーにする。
その後、データをサニタイズで無害化し、クリーンなデータとして扱う。

```php:
// dirty_int は汚れている
$dirty_int = $_POST['dirty_int'];

// バリデーション
// $dirty_int が不正な整数だったら false が返る
$int = filter_var($drity_int, FILTER_VALIDATE_INT);
if ($int === false) {
    throw new \Exception('validation error');
}

// サニタイズ
// 値を範囲内にする
if ($int > 100) {
    $int = 100;
} else if ($int < -100) {
    $int = -100;
}

// クリーンデータとして管理
$clean_int = $int;
```

問題はデータが単数でなく複数の場合である。
$_POSTには配列もデータとして受け取ることができる。
よって、この配列からクリーンデータを抽出しないといけない。

```php:
// クリーンデータの格納先
$clean_data = [];

// dirty_data は汚れている
$dirty_data = $_POST['dirty_data'];

$number = filter_var($dirty_data['number'], FILTER_VALIDATE_INT);
if ($number === false) {
    throw new \Exception('invalid data number');
}
if ($number > 100) {
    $number = 100;
} else if ($number < -100) {
    $number = -100;
}

// number はキレイ！
$clean_data['number'] = $number;
```

## バリデーションとサニタイズは両方やったほうがいいの？

サニタイズだけしてデータを無害化し、バリデーションは行わないという選択肢もある。
だがこれだと不正データの投稿を検出できない。
バリデーションで不正データの投稿を検出し、エラーにしてログを残すことで、アタッカーの痕跡を残すことができる。
アタッカーの攻撃の痕跡を知るのはセキュリティ上、非常に重要なので、バリデーションによってこれを検出した方がいいだろう。
ChatGPT への口頭試問（シェルスクリプトのオプション解析コードの生成）

こんにちは。
シェルスクリプトの使用方法の記述からオプション解析コードを生成するという課題で、ChatGPT へ口頭試問を行い[^1]、概ね優れた回答をもらいました。

[^1]: これは「[ChatGPT への口頭試問（docopts）](https://qiita.com/kkdd/items/d19a2366981e5e2eeeca)」の続編です。

### ChatGPT への質問
次の使用方法の記述から、シェルスクリプトのオプション解析コードを作ってください。なお POSIX 準拠、かつ getopt や getopts は使用しないでください。

```
  Name: $PROGNAME - parse arguments$LF
  Usage: $PROGNAME [options] [__argument__...]$LF
  Options:
    -h|--help       Print this usage and exit.
    -d|--debug      Set debug mode.
    -n|--number __number__  Set non-negative integer (default: $number_var)
    -m|--mammal __name__    Set mammal name.
```

### ChatGPT からの回答
了解しました！以下は POSIX 準拠 かつ getopt や getopts を使わずに、純粋に shift と case を使って手動でオプションを解析するシェルスクリプトです。

```
#!/bin/sh

PROGNAME=$(basename "$0")
LF='
'

# デフォルト値
debug=0
number_var=0
mammal_name=""
positional_args=""

print_usage() {
  cat <<EOF
Name: $PROGNAME - parse arguments$LF
Usage: $PROGNAME [options] [__argument__...]$LF
Options:
  -h|--help            Print this usage and exit.
  -d|--debug           Set debug mode.
  -n|--number __number__   Set non-negative integer (default: $number_var)
  -m|--mammal __name__     Set mammal name.
EOF
}

# オプション解析開始
while [ "$#" -gt 0 ]; do
  case "$1" in
    -h|--help)
      print_usage
      exit 0
      ;;
    -d|--debug)
      debug=1
      shift
      ;;
    -n|--number)
      shift
      if [ -z "$1" ] || ! echo "$1" | grep -Eq '^[0-9]+$'; then
        echo "Error: --number requires a non-negative integer." >&2
        exit 1
      fi
      number_var=$1
      shift
      ;;
    -m|--mammal)
      shift
      if [ -z "$1" ]; then
        echo "Error: --mammal requires a name." >&2
        exit 1
      fi
      mammal_name=$1
      shift
      ;;
    --) # 明示的な区切りがあった場合
      shift
      break
      ;;
    -*) # 不正なオプション
      echo "Unknown option: $1" >&2
      exit 1
      ;;
    *)  # オプション以外（位置引数）
      break
      ;;
  esac
done

# 残りは位置引数
positional_args="$@"

# デバッグ表示
if [ "$debug" -eq 1 ]; then
  echo "Debug mode: $debug"
  echo "Number: $number_var"
  echo "Mammal: $mammal_name"
  echo "Positional arguments: $positional_args"
fi
```
【統計】平均、偏差、分散、標準偏差、偏差値の数式

統計等でよく出てくる **平均**、**偏差**、**分散**、**標準偏差**、**偏差値**について、数式で整理してみました。なお、**母集団** と **標本** という概念もあるため、それぞれ分けてまとめてみました。

# 1. 平均（Mean）
### 1.1. 母集団平均（Population Mean）

$$
\mu=\frac{1}{N}\sum_{i=1}^{N}x_i
$$
+ $\mu$：母集団の平均
+ $N$：母集団のデータ数
+ $x_i$：母集団の各データ点

### 1.2. 標本平均（Sample Mean）
$$
\bar{x}=\frac{1}{n}\sum_{i=1}^{n}x_i
$$
+ $\bar{x}$：標本の平均
+ $n$：標本のデータ数
+ $x_i$：標本の各データ点

# 2. 偏差（Deviation）
### 2.1. 母集団偏差（Population Deviation）
$$
d_i=x_i-\mu
$$
+ $d_i$：母集団の偏差
+ $x_i$：母集団の各データ点
+ $\mu$：母集団の平均
 
### 2.2. 標本偏差（Sample Deviation）
$$
d_i=x_i-\bar{x}
$$
+ $d_i$：標本の偏差
+ $x_i$：標本の各データ点
+ $\bar{x}$：標本の平均

# 3. 分散（Variance）
### 3.1. 母集団分散（Population Variance）
$$
\sigma^2=\frac{1}{N}\sum_{i=1}^{N}(x_i-\mu)^2
$$
+ $\sigma^2$：母集団の分散
+ $N$：母集団のデータ数
+ $x_i$：母集団の各データ点
+ $\mu$：母集団の平均

### 3.2. 標本分散（Sample Variance）
$$
s^2=\frac{1}{n-1}\sum_{i=1}^{n}(x_i-\bar{x})^2
$$
+ $s^2$：標本の分散
+ $n$：標本のデータ数
+ $x_i$：標本の各データ点
+ $\bar{x}$：標本の平均

# 4. 標準偏差（Standard Deviation）
### 4.1. 母集団標準偏差（Population Standard Deviation）
$$
\sigma=\sqrt{\sigma^2}=\sqrt{\frac{1}{N}\sum_{i=1}^{N}(x_i-\mu)^2}
$$
+ $\sigma$：母集団の標準偏差
+ $\sigma^2$：母集団の分散
+ $N$：母集団のデータ数
+ $x_i$：母集団の各データ点
+ $\mu$：母集団の平均

### 4.2. 標本標準偏差（Sample Standard Deviation）
$$
s=\sqrt{s^2}=\sqrt{\frac{1}{n-1}\sum_{i=1}^{n}(x_i-\bar{x})^2}
$$
+ $s$：標本の標準偏差
+ $s^2$：標本の分散
+ $n$：標本のデータ数
+ $x_i$：標本の各データ点
+ $\bar{x}$：標本の平均

:::note info
分母が $n−1$ になるのは「不偏分散」として偏りを補正するためらしいです。
:::


# 5. 偏差値（Standard Score）
### 5.1. 母集団に対する偏差値の式
$$
T=50+10\cdot\frac{x-\mu}{σ}
$$
+ $T$：偏差値
+ $x$：1つのデータ
+ $\mu$：母集団の平均
+ $\sigma$：母集団の標準偏差

### 5.2. 標本に対する偏差値の式
$$
T=50+10\cdot\frac{x-\bar{x}}{s}
$$
+ $T$：偏差値
+ $x$：1つのデータ
+ $\bar{x}$：標本の平均
+ $s$：標本の標準偏差

:::note info
偏差値は基本的に「標本」に対して使うものらしいです。全体（母集団）を推定するための指標として使われるらしいです。
:::

---
以上
CSS/Tailwind CSS で text-overflow:ellipsis/truncate による 3点リーダーが効かないのはなぜ？

Tailwind CSSでスタイリングしているページのレイアウト改善をしていた際に、コンテンツのタイトルが長い場合などは3点リーダー(「...」)で省略するために`truncate`をタグのクラスにとりあえず追加していたのですが、思うように効かないことがあったため対処法をまとめます。

## 適用するタグをブロック要素もしくはインラインブロック要素にする

Tailwindの`truncate`クラスは、CSSで言う下記のクラスに当たります。
[TextOverflow-TailwindCSS](https://v3.tailwindcss.com/docs/text-overflow#truncate)

```
overflow:hidden;
text-overflow:ellipsis;
white-space:nowrap;
```

そして`text-overflow`は、MDNのドキュメントによるとブロックコンテナー要素が適用対象になります。
[text-overflow-CSS:カスケーディングスタイルシート|MDN](https://developer.mozilla.org/ja/docs/Web/CSS/text-overflow)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2207701/f246e064-4c39-4b4e-816a-77679b89afaf.png)


そのため、たとえばspanタグなどのインライン要素内の文字に`truncate`を適用しようとして`<span class="truncate>文字</span>`としても効きません。この場合は、`block`もしくは`inline-block`を指定してspanタグをブロック要素もしくはインラインブロック要素にすることで反映されます。

## 適用するタグに一番近い親にflexを指定する

`flex`を指定すると直接の子要素はブロック要素のようなものになるらしく、`truncate`の適用対象になります。これはAIに聞いてやっとわかりました。以下がAIの回答です。

```
flexコンテナの直接の子要素（flexitems）は自動的にブロック化されます。つまり：
1. divがflexコンテナになることで
2. その直接の子要素であるspanはflexitemとなり
3. flexitemは自動的にブロックフォーマッティングコンテキスト（BFC）を確立する
4. BFCが確立されることでtext-overflow:ellipsisが有効になる

- display:flexは子要素のレンダリングコンテキストを変更する
- インライン要素でも、flexアイテムになるとブロック的な振る舞いをする
- テキスト切り捨てを確実に機能させるには、要素がブロックコンテキストを持つ必要がある
- これがサンプル3でblockやinline-blockを明示的に指定しなくてもtruncateが機能する理由
```

## 挙動をコードで見てみる

tailwindPLAYというサイトでコードを書いて挙動を試してみました。
https://play.tailwindcss.com/CNu1C7kesS

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2207701/4da75061-db4c-4138-928a-30d3287c977f.png)

```html
<h1 class="text-2xl">🙅‍♂️ サンプル1</h1>
<div class="w-2/4 border border-black p-2 text-xl font-bold">
  <div>
    <span class="truncate"> ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890 </span>
  </div>
</div>

<div class="h-10"></div>

<h1 class="text-2xl">🙆‍♂️ サンプル2</h1>
<div class="w-2/4 border border-black p-2 text-xl font-bold">
  <div>
    <span class="block truncate"> ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890 </span>
  </div>
</div>

<div class="h-10"></div>

<h1 class="text-2xl">🙆‍♂️ サンプル3</h1>
<div class="w-2/4 border border-black p-2 text-xl font-bold">
  <div class="flex">
    <span class="truncate"> ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890 </span>
  </div>
</div>

<div class="h-10"></div>

<h1 class="text-2xl">🙆‍♂️ サンプル4</h1>
<div class="w-2/4 border border-black p-2 text-xl font-bold">
  <h2 class="truncate"> ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890 </span>
</div>
```

- サンプル1は、spanタグがインライン要素のままなので`truncate`が適用されず、親のdivから文字がはみ出してしまっています。
- サンプル2は、spanタグをブロック要素にしているので`truncate`がきちんと適用されています。
- サンプル3は、親のdivに`flex`を指定しており、その直下の子要素であるspanがすでにブロック要素(のようなもの)になっているため、`block`もしくは`inline-block`を指定しなくても`truncate`が適用されます。
- サンプル4は、h2タグがブロック要素のタグであるため、`block`もしくは`inline`を指定しなくても`truncate`の指定のみで適用されます。
Next.jsプロジェクトの開発環境の構築（備忘録）

## 初めに
新しいプロジェクト立ち上げの際の手順書になるように備忘録として記述する。

## Next.js プロジェクト立ち上げ時の設定
```
npx create-next-app
```
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3779623/c62fb055-894e-4a71-b6b3-7610a126d963.png)

Nextjs v15からTurbopack Devが安定化したとのことなので使ってみることにする。
ただ現時点では、本番環境へのbuildには含めないほうがいいらしい。

https://nextjs.org/blog/turbopack-for-development-stable

## 静的解析ツール
### ESLINT
プロジェクト立ち上げ時の設定を特に変更せずに使用する。

### Prettier
``` .prettierrc
{
  "singleQuote": true,
  "trailingComma": "es5",
  "printWidth": 100,
  "tabWidth": 2,
  "useTabs": false,
  "plugins": ["prettier-plugin-tailwindcss"],
  "tailwindConfig": "./tailwind.config.ts"
}
```

## パッケージマネージャー
npmを使用。

各パッケージツールに関する記事は以下に良くまとめられていたので参考に読ませていただいた。

https://zenn.dev/bizlink/articles/14a65815472bcd

## モックサーバー
mswを使用
Next.jsでのmswを利用する方法については以下の記事にまとめた。

https://qiita.com/K_KN/items/9d3d18761d139f8dde21

## UIカタログ
storybookを使用
https://storybook.js.org/

Next.js ドキュメント
https://storybook.js.org/docs/get-started/frameworks/nextjs?renderer=react

私はコンポーネント駆動開発のほうがやりやすいと感じたので、とても重宝するツールである。
ドキュメント生成を自動でしてくれたり、storybook内でテストができたりと素晴らしいツールである。

以下の記事に環境構築方法をまとめてある
https://qiita.com/K_KN/items/bf49791c2e4c01b7b503

## 状態管理ツール
簡単に状態管理をしたい場合は、Zustand
https://zustand-demo.pmnd.rs/

複雑な状態管理を必要とする場合は、Redux　かな。
https://redux.js.org/

## その他
動的なCSSクラスに利用するツール
``` typeScript
import { type ClassValue, clsx } from "clsx"
import { twMerge } from "tailwind-merge"

export const cn = (...inputs: ClassValue[]) => {
  return twMerge(clsx(inputs))
}

```


prettier-plugin-tailwindcss
https://www.npmjs.com/package/prettier-plugin-tailwindcss/v/0.0.0-insiders.d539a72?activeTab=readme
Geminiでハーモニカを使う魔法少女を描いてみた。

# 概要

Geminiでハーモニカを使う魔法少女を描いてみました。

# 実装

プロンプトと実行結果は以下の通りでした。

```
闇のハーモニカを使う魔法少女を描いてください。
```

![闇のハーモニカを使う魔法少女_20250424.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3192024/48dc9819-6e19-4c5e-b11f-12e323f85623.png)


```
聖なるハーモニカを使う魔法少女を描いてください。
```

![聖なるハーモニカを使う魔法少女_20250424.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3192024/0aa70712-2342-484a-be26-cf97ac182827.png)



```
心のハーモニカを使う魔法少女を描いてください。
```

![心のハーモニカを使う魔法少女_20250424.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3192024/0f1f8293-5d3f-4a4e-90a3-c99f9d935736.png)

# まとめ

心の子が可愛い。何かの役に立てばと。
金欠3DプリンターものづくりTips 1


## はじめに
**みなさん、慢性鼻炎がつらい日々ですねぇ()**
ということで、PCでの作業中でもいつでも鼻をかめてかつ場所を取らないティッシュケースを作りたいと思い、机の裏に設置するミニティッシュケースを作ろうと思った次第です。
この記事は、そんなティッシュケースを作りながら、日々自分が3Dプリンターで物を作るときに工夫しているところをまとめようと思います。

## やりたいことを決める

今回やりたいこと↓
**PCでの作業中でもいつでも鼻をかめてかつ場所を取らないティッシュケースを作る！！**

これを達成するための要件がこんな感じになりました

- デスク裏に設置する (デスク上の場所は取らないし取りやすい)
- 小型化する (デスク裏とはいえ普通の大きさだと邪魔)
- 交換を簡単にする (交換が面倒だと自分の性格上置物になる)

あとは自分がなにか作るときに入っている暗黙の要件があって

**なるべく安くかっこよく！！**


ここで問題になってくるのが **小さくて入手性のいいティッシュがない！！** ということ

最初は献血でもらったポケットティッシュを使おうかと思ってたけど、普通に血がなくなって死んじゃいます。

そんな時に、ふらっと訪れたダイソーにこんなものが


https://jp.daisonet.com/products/4550480305547


ダイソーを出ることには右手に持ってました。
ということでこのティッシュ用のティッシュボックスを書いていこうと思います。

## とりあえず形にする

とりあえずFusion360で設計します。
今回はそこまで複雑なものでもないので、ティッシュケースというふわっとした考えのまま、とりあえず手を動かします。

とここで、**謎の貧乏性発動**
愚直に、こんな感じの箱に取り出し口をつけるのだけでもいいけど、

![Fusionの画像1](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618548/fe67a230-af17-e579-1d29-5c3012715111.png)

いかんせんフィラメントの消費が痛い(156g)。あと印刷時間も長い(18時間26分)。

![Curaの画像1](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618548/110317c4-0743-5e63-6184-8721f388a2ac.png)

印刷成功するかもわからないのにこんなにコストかけるのあまりにもギャンブルすぎる。
これは、暗黙の要件の **なるべく安くかっこよく！！** に反してしまいます。

そこで自分がよくやるのが、骨組みはあるいはジョイントは3Dプリンタで作りそれ以外はダイソー木材でという手法。

今回はジョイントだけ3Dプリンターで作ってそれ以外はーというのは無理そうだから、骨組みと取り出し面だけ作って、側面はMDFでいきます。

そして今回は初めて見つけた2.5mmMDFを使います。めっちゃ加工しやすそう。~~それでも木材の加工めんどくせぇ~~

https://jp.daisonet.com/products/4550480291239

次回はダイソーMDFを使った設計していきます。
新卒エンジニアの学習記録＃２ ~SQLの基本とSELECT文の実践~

こんにちは。新卒未経験エンジニアのDeepBlend45です。

📘 今日の学習記録：SQLの基本とSELECT文の実践
---

今日はSQLの学習を深めた一日でした。前半は、SQLの4つの基本操作である SELECT、INSERT、UPDATE、DELETE について、それぞれの役割と使い方を学習しました。

後半は特に SELECT 文に注目して、実際に仮想のデータベースを作成し、情報の抽出を試してみました。WHERE や GROUP BY、HAVING なども使って、より見やすく・意味のある表を作る体験ができ、Excelでの集計に似ている感覚があってとても楽しかったです。

特に難しかったのは、複数のテーブルを結合する部分でした。共通のID的なカラムを基に JOIN を行う必要があるのですが、まだしっかりとは理解しきれていない感覚があります。

個人的には、ExcelもJavaと連携するようになれば、SQLの出番が減るのでは？なんて未来のことを考えてみたりしました。現場でSQLが使われている理由に少しだけ触れられた気がして、少し視野が広がった気がします。

⚡️明日に向けて
---

今後はもう少し複雑なクエリや、データベース設計の基本も触れていきたいと思っています。読んでくださってありがとうございました！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4069042/b414bdc7-a073-4472-a16f-ad25e44b2820.png)
どのがdenoを使う

React、Vue、Next...  
フロントエンドの技術は進化が早くて、正直追いかけるのがしんどいです。  
バックエンド寄りの自分にとっては、これが大きな壁でした。

個人開発ではフロントにもこだわりたいと思っていたけれど、  
「どのフレームワークを選ぶべきか」「今から学ぶ価値があるのか」に迷って、なかなか手を出せずにいました。

そんなときに出会ったのが、DenoとそのWebフレームワークのFreshでした。  
「これから伸びそう」「学び始めるにはちょうどいい」そんな直感があり、  
どのはDenoを勉強することにしました。

## なぜDenoとFreshを選んだのか
まず、現在フロントの技術としてはReactやNextといったNode.js系の技術が主流だと思います。
私自身も少し触ってみたことはあるのですが、むずかしかったです。
調べれば調べるほど情報が出てきて、
Next.js 13のApp Router、Preactの導入、TailwindやEmotionなどのCSSライブラリ…
自分はもともとバックエンドエンジニア寄りで、APIやDBのほうが得意です。  
そのため、フロントの技術トレンドを毎回キャッチアップするのは、とても大変で、正直面倒だと感じました。

### Denoに出会う
そんな中でも、個人開発ではフロントにもこだわりたいという思いがあり、いろいろと調べていました。  
そこで出会ったのが、Denoという新しいJavaScriptランタイムです。
DenoはNode.jsの作者が、Node.jsの課題を解決するために新たに開発したランタイムで、以下のような特徴があります。
- 最初からTypeScriptに対応
- 権限ベースの実行でセキュリティが高い
- モジュールがURLで管理される（npm installが不要）

Node.jsの開発者が自ら作り直した、という背景も知り、「先にDenoを勉強しておけば、キャッチアップの手間なくなるじゃん」と思い、勉強を始めました。
また、日本語の情報も少ない分、逆に「一次情報（公式ドキュメントなど）を見ながら学ぶ力を鍛えられる」とも思い勉強を始めました。

### Freshというフレームワーク
そんなDenoには、FreshというWebフレームワークが存在します。
Freshの主な特徴は
- islandアーキテクチャの採用
- JSX + Preactで書ける
- バンドル不要で超高速なSSRが可能
など…
です。
「Deno版Next.js」とも言われている記事も見て、今後の主流これになるじゃん！と思い、Freshの学習も始めました。

## 使ってみて
Nextをちょっと勉強したときにReactにも触れたので、すぐFreshの環境に慣れて自分にとってはとても使いやすくて好感触でした。
Freshにはroutes/api/**.tsのようにAPIルートを作れる仕組みがあるので、
ちょっとしたバックエンド処理もフロントと同じ構成内で書けるのが便利です。

### デプロイが簡単
Deno公式の「Deno Deploy」は、GitHubと連携すればほぼ設定なしでデプロイが完了します。
個人開発ならこれで十分すぎるレベルです。

### 簡易DBとして使える「Deno KV」
Deno KVというKey-Valueストレージもあり、ちょっとしたデータの永続化ならこれだけで済みます。
SupabaseなどDBを使うほどでもない場合にぴったりで、試作アプリにはとても向いています。

## おわりに
結論としては、「今後も何か個人開発をするときは、まずFresh + Denoで始めてみる」というのが自分のスタイルになりそうです。
セットアップもシンプルで、DB,API,フロントも1つの構成で完結でき、デプロイまで簡単。  
「とりあえず試してみたい」というときにこそ、Fresh + Denoは最高の環境だと思います。
【AWS用語解説】SSE-S3、SSE-KMS、SSE-Cの違いとは？S3のサーバーサイド暗号化を整理してみた

## はじめに

Amazon S3では、保存するデータを「サーバーサイド暗号化（SSE）」によって保護することができます。  
ただ、一口にSSEといっても方式が複数あり、それぞれで仕組みや使い方が異なるため、混乱しやすいポイントで、僕も実際に問題を解く中で何度も間違えました。

この記事では、S3で利用できる3つの暗号化方式について、違いと適した使い方をわかりやすく整理してみました。

- **SSE-S3（S3が鍵を管理）**
- **SSE-KMS（AWS KMSが鍵を管理）**
- **SSE-C（ユーザーが鍵を提供）**

---

## サーバーサイド暗号化（SSE）とは？

サーバーサイド暗号化とは、  
S3にアップロードされたオブジェクトをAWS側で自動的に暗号化・復号する仕組みです。

ファイルはアップロード時に暗号化され、ダウンロード時に自動で復号されるため、  
アプリケーション側で特別な処理を加える必要はなく、普段通りの使い方でセキュアに利用できます。

---

## 3つの方式の比較

| 項目             | SSE-S3           | SSE-KMS                     | SSE-C                       |
|------------------|------------------|-----------------------------|-----------------------------|
| 鍵の管理         | S3が自動で管理   | AWS KMSで集中管理          | 利用者が鍵を提供            |
| 暗号化キーの生成 | 自動生成・自動管理 | KMSのCMK（カスタマー管理キー） | ユーザーが毎回リクエストで提供 |
| 認可管理         | S3のアクセス制御のみ | IAMポリシー＋KMSポリシー     | 毎回鍵を送る必要あり         |
| 導入の手軽さ     | ◎（一番簡単）    | ○（KMSとの連携が必要）      | △（運用手間あり）           |
| コスト           | 無料             | KMS利用に応じて課金あり     | 無料（ただし自己管理）       |

---

## 使い分けのヒント

### ✔ SSE-S3

- **とにかく簡単に暗号化したいとき**
- 鍵の管理はすべてAWSに任せたいとき
- 「S3のデフォルト暗号化」でよく登場する方式

### ✔ SSE-KMS

- **アクセス制御や鍵の操作履歴を厳密に管理したいケース**
- セキュリティ要件が厳しい業務システムや企業ユース
- CloudTrailによる操作の記録も行いたい場合に向いています

### ✔ SSE-C

- **自社ポリシーで暗号鍵を完全にコントロールしたいとき**
- 他のAWSサービスとは連携せずに暗号化を独立して運用したいとき
- 毎回鍵を送信する必要があるため、運用の工夫が求められます

---

## 試験対策のポイント

- **SSE-S3：** 設定がシンプル、復号も自動。とりあえず暗号化したいときに。
- **SSE-KMS：** IAMとKMSの連携が必要で、一段階高度な管理ができる。
- **SSE-C：** 毎回鍵を提供する手間があり、運用ハードルが高い。特徴的なので逆に問われやすい。

選択肢として提示されたときは、「誰が鍵を管理するか」と運用負荷で判断すると選びやすくなります。

---

## まとめ

- S3のサーバーサイド暗号化には3つの方式があり、それぞれ「鍵の管理者」が異なる。
- 簡単さを重視するならSSE-S3、制御性を求めるならSSE-KMS、自主管理重視ならSSE-C。
- 試験では利用シーンに応じた選択が問われることが多いため、シナリオ判断の練習がおすすめです。

---

## あわせて知っておきたい用語

- AWS KMS（Key Management Service）： 鍵をセキュアに管理・運用するサービス
- バージョニング： オブジェクトの世代管理機能。暗号化との併用可
- クライアントサイド暗号化（CSE）： アプリ側で暗号化してからアップロードする方式

---

📘この記事はAWS認定SAP試験の勉強メモとしてまとめたものです。  
内容に誤りや補足点があれば、ぜひコメントで教えてください！
Iteratorに見る“流れ”の設計哲学



> _"繰り返しとは単なる操作ではない。それは、データに通じる意味の流れである。"_  

Rustにおける `Iterator` は、ただの繰り返し構文ではない。  
それは「**データの流れを記述する言語**であり、**抽象と最適化、意味と構文の交差点**である。

この章では、Rustにおける `Iterator` がいかにして**制御構造を美学と効率に還元した構文**なのか、  
そしてその背後にある「流れ」という概念が、**なぜRustの設計哲学において重要なのか**を探る。

---

## イテレータは「構文の形式」ではなく「設計の意思表明」である

C言語では `for` ループは構文的構成物だった。  
Pythonではそれが高階型に置き換わり、Goでは `range` に進化した。  
しかしRustの `Iterator` はそのどれでもない。

```rust
let nums = vec![1, 2, 3, 4];
let doubled: Vec<_> = nums.iter().map(|x| x * 2).collect();
```

この1行は、単なる繰り返しではない。  
**「このデータは、順に流れ、写像され、収束する」**という**流れの構造を文法で語っている**。

これは **「データをどう処理するか」ではなく、「どのような構造で流すか」を定義する設計構文**である。

---

## `.iter()`：所有から参照への設計転換

Rustでは `.iter()` の存在が意味を決定づける。

```rust
nums.iter() // 参照の流れ
nums.into_iter() // 所有権の流れ
nums.iter_mut() // 可変参照の流れ
```

この違いは、**設計上の意思を構文で示す**というRustの原則に忠実だ。

- 借用（&）のまま流すのか  
- データの所有を委譲して流すのか  
- 値を変更しながら流すのか

これらの「データの流れ方」は、**実装者ではなく構文によって可視化される。**

---

## `.map()`：変換ではなく“意味の移動”

```rust
.iter().map(|x| x * 2)
```

この構文の本質は「変換」ではない。  
それは、「**この段階で、データに意味の変換がある**」という**流れ上の転換点**である。

`.map()` は関数型プログラミングにおける関手（Functor）と同義であり、  
「写像可能な構造に対して意味の変換を定義する構文的契機」となる。

---

## `.filter()`：意図的な構造の選別

```rust
.iter().filter(|x| *x % 2 == 0)
```

これは、「**この流れには条件が必要だ**」という選別の表明である。

- `.map()`：意味を移動する  
- `.filter()`：存在の可否を決定する  
- `.fold()`：意味の集約点を与える

これらはすべて、ループではなく“意味の流れを整流する構文”である。

---

## `.collect()`：流れの帰結としての構文的終止符

```rust
.collect::<Vec<_>>()
```

この `.collect()` は、「**この抽象的な流れを具体的な容器へ変換する**」という構造的宣言である。

つまり、`Iterator` とは **“未確定な意味の流れ”** であり、`.collect()` はそれを **“確定された構造へ収束させる操作”** なのだ。

ここには次のような哲学がある：

- 途中までは抽象で動かす  
- 必要なタイミングで具体化する  
- すべてを強制せず、選択的に意味を落とし込む

---

## zero-cost abstractionの具現化としてのIterator

Rustの `Iterator` は、**「高階抽象は最適化と矛盾しない」**という哲学の証明である。

- `.map()` や `.filter()` は中間イテレータを返すだけ  
- `.collect()` まで実行されない（遅延評価）  
- LLVMがそれらをすべてインライン最適化する

つまり、**抽象を維持しながらも、オーバーヘッドを限りなく0に近づける構造的達成**がここにある。

---

## イテレータ＝構文的DSL（ドメイン特化言語）

Rustの `Iterator` チェーンは、**「流れ」という意味空間におけるDSL** として機能する。

```rust
let summary = items
    .iter()
    .filter(|x| x.is_valid())
    .map(|x| x.value())
    .take(10)
    .collect::<Vec<_>>();
```

このコードは、**「データ処理の意図」だけを構文的に表現している**。  
ループ変数もインデックスも制御構造もない。  
あるのは、**“何が起きるべきか”という意味だけだ。**

---

## 結語：イテレータは“意味の順序”を記述する構文である

Rustにおける `Iterator` は、繰り返しではない。  
それは、「どのようにデータが意味を変えながら流れるか」を構文で記述する装置であり、  
**その流れの中で抽象と最適化が一致する構造的詩法**である。

- `.iter()` は入口  
- `.map()` は変化  
- `.filter()` は選別  
- `.collect()` は終止符  

これらすべてが、「**意味の経路を構文で定義するという、静かで強固な設計言語**」として機能する。

> _"RustのIteratorはループではない。それは、意味が構文の中を流れるための設計構造である。"_
Miriと検証の未来：未定義動作を静かに殺す



> _"破滅は音を立ててやってこない。静かに忍び寄り、設計の盲点を貫く。"_  

未定義動作（Undefined Behavior）。  
この言葉は、CやC++の世界で聞き慣れた警告だが、Rustにおいても油断は許されない。  
なぜなら、**Rustの安全は“unsafeを使わない限り安全”という契約に依存している**からだ。

しかし逆に言えば、`unsafe` を使った瞬間、**そのコードは“自己責任”の領域へと放り込まれる。**  
Rustは、その自由に対して「では、責任は構文で取れ」とは言わない。  
代わりに、「**実行時に検証しよう、正しさが破られていないかを**」と語る。

この哲学の実装が **Miri** である。  
本稿では、Miriというツールがなぜ特別なのか、そしてそれが開く「構文では見えない正しさ」の未来を解き明かす。

---

## Miriとは何か？：Rustのメタ実行機械

Miri は、Rustコンパイラの一部として動作する **インタプリタベースの実行検証エンジン** である。  
名前の由来は「Mir interpreter」──Rustの中間表現 MIR を評価する仮想的な実行器だ。

Rustコードを「**抽象構文木からコンパイル直前の中間形に変換」し、それを“解釈”する形で実行する。  
このアプローチにより：

- 通常のバイナリでは検出不能な未定義動作を検出  
- ポインタの二重可変借用、解放後アクセス、未初期化メモリの読み取りなど  
- コンパイル後だが、**構文より深く、実行より静かに**動作する検証器

---

## 未定義動作とは「型では捕まえられない崩壊」

Rustは型と借用チェッカーで非常に多くの誤りを排除できる。  
しかし `unsafe` を使うと、その外側へ踏み出せる：

```rust
unsafe {
    let mut x = 10;
    let r1 = &mut x;
    let r2 = &mut x; // UB：同時に2つの可変参照
}
```

コンパイラはこれを許す。なぜなら構文上は正しいから。  
だがこれは、**実行時には「何が起きるか分からない」世界＝未定義動作**を生み出す。

Miriはこのような「**型では制御できない時間的構造の破綻**」を検出する。

---

## “構文では見えない構造”を、仮想的に実行して照らす

Miriのすごさは、**Rustのコードをそのまま仮想的に“逐語的に解釈”する**という点にある。

- メモリの初期化状態をすべて追跡  
- ポインタごとの借用状態を記憶し続ける  
- スタック上の寿命・ライフタイムを型情報よりも精密にトレース

これはもはや単なるテストではない。  
**“意味を構文から切り離し、実行の文脈で再検証する”動的静的検証**なのだ。

---

## Miriを使うとは、“責任を確認する行為”である

使い方は簡単だ：

```bash
cargo +nightly miri test
```

これは、「`#[test]` に書かれた全ての関数を、未定義動作がないか仮想実行しよう」という命令である。

実際に破綻があれば、次のような明確なエラーメッセージが出る：

```
error: Undefined Behavior: multiple mutable references exist
   --> src/lib.rs:10:5
```

これは、構文ではなく、**“構造そのものが崩壊していた”という証明**だ。

---

## unsafeコードが開く“闇”を、Miriが照らす

Rustは `unsafe` によって次のような力を開発者に与える：

- 生ポインタの操作  
- グローバル変数の変更  
- メモリの手動割当・解放

しかしその代償として、「**このコードはコンパイラの保証対象外である**」。  
Miriはこの領域に対して、「**では、実行時の意味として正しいか？」**を問い直す。

これはまさに、**設計の自由に対する、実行時保証の再配置**である。

---

## Miriの限界と未来：完全検証への欲望

Miriは強力だが万能ではない：

- 実行時間が遅い（インタプリタ方式）  
- 一部のライブラリ呼び出しに非対応  
- グローバルに副作用のあるコードは制限される

だがそれでも、**Miriの存在はRustに“言語では拾いきれない破綻を拾う文化”を根付かせた**。

そして将来的には、以下が期待されている：

- コンパイラ統合による逐次検証  
- IDEへの統合支援（保存時チェック）  
- `unsafe` ブロックの定期スキャン

---

## 結語：Miriは“意味の継続検査装置”である

Rustは型で安全を担保する。  
だが型では扱えない「**時間の中で起こる崩壊**」がある。  
Miriは、その崩壊を構文ではなく**仮想的構造の実行によって可視化する検証器**である。

それは単なる静的解析ではない。  
また単なる実行でもない。  
それは、**設計された意味の内側を、構造として照らす倫理的な装置**である。

> _"意味の崩壊は構文では止められない。だが、その崩壊を見つめ、言語の未来へ還元することはできる。Miriは、そのための眼だ。"_
プロパティベーステストとquickcheckの設計的美



> _"すべての例を挙げることはできない。だが、正しさの性質を記述することはできる。"_  

多くのテストは具体例に依存する。  
与えられた入力と出力のペアが正しいかどうかを検証する――それは基本的な戦略であり、同時に限界を持つ。

Rustにおけるプロパティベーステスト（PBT）は、この限界に対する応答である。  
それは「**例を挙げるのではなく、性質を語ることで設計を検証する**」という、**より抽象度の高い検証手法**だ。

この章では、`quickcheck` クレートを中心に、PBTの美学とその設計的意義を読み解く。

---

## テストの“例外性”からの脱却

従来の単体テストは、具体例に基づく。

```rust
#[test]
fn adds_two() {
    assert_eq!(add(2, 2), 4);
}
```

だがこのテストが保証しているのは、「`2 + 2` は `4`」である、という**点の正しさ**でしかない。

この点に対して、プロパティベーステストはこう考える：

- 「任意の a と b に対して、`add(a, b)` は `b + a` に等しいべきでは？」
- 「境界値や予期せぬデータで壊れない保証はあるか？」

つまり、**特定の入力ではなく、入力空間全体に対する性質そのものを構文で記述する**のがPBTの思想である。

---

## quickcheck：性質の表現言語

Rustには、Haskell由来の `quickcheck` クレートが存在する。

```rust
use quickcheck::quickcheck;

fn reverse_reverse_is_identity(xs: Vec<u32>) -> bool {
    let reversed = xs.clone().into_iter().rev().collect::<Vec<_>>();
    reversed.into_iter().rev().collect::<Vec<_>>() == xs
}

quickcheck! {
    fn test_reverse_reverse(xs: Vec<u32>) -> bool {
        reverse_reverse_is_identity(xs)
    }
}
```

この構文は、以下を意味する：

- `Vec<u32>` 型のあらゆる入力をランダムに生成し  
- 関数が満たすべき「性質」をブール値で記述し  
- その性質が崩れる最小の入力を探索する

これは**「性質の記述＝設計の検証」**という文法的契約である。

---

## 設計とは“性質の集合”である

設計とは、本質的に「**この関数はこう振る舞うべきだ**」という**性質の集積**である。  
例ではなく、性質こそが関数の定義に近い。

たとえば：

- `len(a + b) == len(a) + len(b)`：結合における長さの保存  
- `sort(sort(x)) == sort(x)`：安定性の検証  
- `parse(serialize(x)) == x`：シリアライズの同一性保証

これらはすべて、**構文で書ける保証の形**である。  
そして `quickcheck` は、その性質を**コードとして自動実行可能な保証装置に変える**。

---

## “無限のテスト”を“構文で抑える”という逆説

PBTでは、すべてのケースを網羅することはできない。  
だが、**テストケースを自動生成することで、“想定外”を想定内に引き込む構造**を構築できる。

これは、次のような特性を持つ：

- 多様な入力パターンに対して高い信頼性  
- 複雑な境界ケースでの自動検出  
- 構造的バグの最小入力としての“縮小（shrink）”

つまり、**“入力の無限性を構文の有限性で取り囲む”**という構造化手法である。

---

## 性質を書くという行為は、設計に責任を持つということ

関数の仕様が曖昧なとき、PBTは成立しない。  
逆に言えば、**PBTを書くためには、関数がどう振る舞うべきかを設計者が自覚していなければならない。**

これは設計倫理の問題だ：

- “この関数はどのような性質を守るべきか？”  
- “それは常に成り立つものか？”  
- “例外はあるのか？ ならばなぜ？”  

性質を書くことは、**設計者がコードの意味と限界を構文で引き受ける行為**に他ならない。

---

## プロパティベーステストの文化的意義

Rustは、ただ安全な言語ではない。  
それは**設計を言語化し、構文として共有可能にする文化**を持っている。

- `#[test]`：命題の断片  
- `quickcheck!`：命題の普遍化  
- `assert!` → `forall`: 特定から汎化へ

この進化は、**コードが「ロジック」ではなく「理論」として語られる世界への遷移**を意味している。

---

## 結語：性質こそが、設計の語彙である

プロパティベーステストとは、**設計を論理式に分解し、それを構文として検証する構造的試み**である。  
`quickcheck` のようなツールは、その文脈をRustに持ち込み、**例を超えた信頼性の設計**を可能にする。

具体例で語れるのはコードの断片だけだ。  
性質で語ることで、**設計の本質を構文化する**ことができる。

> _"すべてをテストすることはできない。だが、設計の正しさを語る言葉なら、構文にできる。"_
#[test]属性は保証の形式である



> _"設計に対する信頼は、コードが動くことではなく、構文として明文化されるべきだ。"_  

ソフトウェア開発における“テスト”とは、結果としての成功/失敗ではなく、**設計そのものの信頼性に対する構造的証明行為**である。  
Rustにおける `#[test]` 属性は、その構造をもっとも直接的に明示する装置だ。

この章では、`#[test]` が単なる注釈にとどまらず、**「この関数はテストであり、信頼の根拠としてコンパイル時に保証されるべきものである」**という設計的表明であることを掘り下げる。

---

## #[test]：属性としての“設計契約”

```rust
#[test]
fn should_add_correctly() {
    assert_eq!(sum(1, 2), 3);
}
```

この `#[test]` は、関数の振る舞いを変えるものではない。  
それは、**この関数が「検証のために存在している」**という意図をコンパイラに伝える**構文上の契約**である。

つまり `#[test]` は、「この関数は本番用途ではなく、設計の正しさを示すものである」という**語りの形式**なのだ。

---

## テストコードは設計者による「実行されるドキュメント」

ドキュメントは書かれても読まれない。  
だが `#[test]` によって書かれたコードは、**機械によって定期的に評価され、失敗すれば即座に通知される**。

これは、次のような構造をもつ：

- ドキュメントよりも正確  
- 実装よりも抽象的  
- 使用よりも未来志向

Rustのテストは、**“設計者の設計意思がコンパイル時から実行時まで一貫して保証される構文的意思表明”**である。

---

## `cargo test` の実行は「構造の検証」である

`cargo test` を走らせるという行為は、次のことを意味している：

- コンパイラが `[cfg(test)]` を含む構文をビルドし  
- `#[test]` の付いた関数を自動で収集し  
- それぞれを独立した検証単位として実行する

この自動化こそが、**「設計者の意思を形式化して反復可能にする」**というRust流の品質保証哲学である。

Rustは、**テスト実行すら設計に組み込むことを言語の構文設計の一部にしている**。

---

## テストとは、「壊れない」のではなく、「壊れたら分かる」構造である

Rustの `#[test]` は、完全性ではなく、**明示的失敗の設計**を支援する。

```rust
#[test]
fn fails_when_negative() {
    let result = parse_positive("−42");
    assert!(result.is_err());
}
```

このようなテストは、「**この入力には失敗するのが正しい**」という構文的保証を意味している。

つまり `#[test]` は、「**正しい失敗すらも、構文の中で意味づけることができる**」保証の枠組みでもある。

---

## テストの粒度は“設計の語彙力”に比例する

良いテストとは、以下のような性質を持つ：

- テスト名が「何を検証しているか」を説明できる  
- `assert` 文が仕様の一部を映している  
- テスト群として「設計の輪郭」を再構成できる

Rustでは、`#[test]` 関数はひとつの命題であり、**その命題の集合が設計全体の意味構造を裏打ちする**。

---

## #[test]は“構文的構成主義”の核である

Rustは、設計を構文で語る言語である。  
`#[test]` はその最前線にあり、以下の機能を担う：

- 開発者に検証の責任を要求する  
- 設計者に仕様の定義を強制する  
- コンパイラにその保証を負わせる

Rustの哲学は、「**動くコードより、壊れたときに意味がある構造**」を重視する。  
そして `#[test]` は、**その構造が本当に意味を持つかを照らす反射光**である。

---

## 結語：#[test]は構文の中の倫理である

Rustにおける `#[test]` は、単なるテスト関数の指定ではない。  
それは、「**この設計には、検証可能な正しさがあるべきだ**」という構造的倫理の宣言である。

テストコードは設計の語りであり、`#[test]` はそれを**構文として形式化する構造的信頼の道具**である。  
だからこそRustは、あらゆる関数にこの属性を与える自由を許しつつ、  
**その使用を設計的義務として、開発者に課している。**

> _"信頼される設計とは、テストによって検証された設計ではない。検証されるべき設計を構文として書けることである。"_
Rustにおける単体テストの倫理



> _"テストはコードを検査する行為ではない。それは、設計が信頼に足るかどうかを問う対話である。"_  

ソフトウェアの品質は、テストによって保証される。  
それは誰もが知る常識でありながら、**そのテストが設計にどれだけ踏み込めているか**を問い直す場面は少ない。  
Rustは、テストにすら**言語的構文による設計思想の適用を求める**。

この章では、Rustにおける単体テストがなぜ特別なのか、  
それが**「コードの正しさ」ではなく「構造の信頼性」**を保証するための倫理装置として機能する理由を解き明かしていく。

---

## テストは「コードの外部にある構文」である

Rustのテストは、関数の前に `#[test]` 属性をつけるだけで始まる。

```rust
#[test]
fn it_adds_two() {
    assert_eq!(2 + 2, 4);
}
```

この構文は、テストを「**特別な責務を持つ関数**」として明確に切り出している。  
そしてこの関数は、プロダクションコードとは**分離された宇宙に存在する**。

つまりRustは、「テストはコードの一部ではなく、**構造への外的評価である**」という立場をとっている。

---

## `cargo test`：コンパイルされた信頼の実行

テスト関数は通常の `main()` とは異なるバイナリにリンクされ、`cargo test` によって実行される。  
ここでRustがしているのは、**「テスト対象そのものとは別の文脈でコードを評価する構造」**の生成である。

このアプローチは以下を可能にする：

- 本番ロジックとテストを明確に分離  
- テスト用の依存関係（`dev-dependencies`）の切り出し  
- テストの存在そのものがコードベースに組み込まれている状態を防ぐ

Rustは、**テストを“実行ではなく設計の検証”として再定義**している。

---

## `assert_eq!`, `should_panic`, `#[ignore]`：構文で設計意図を語る

Rustのテストでは、ただの真偽判定ではなく、**構文で意図を語る**。

```rust
#[test]
#[should_panic(expected = "division by zero")]
fn it_panics() {
    let _ = 1 / 0;
}
```

これは単なる「クラッシュの確認」ではなく、**「この構造はこの条件で壊れてよい」という明示的な設計」**である。  
設計者が「壊れてよいポイント」を構文で語れる、数少ない言語的機構だ。

また `#[ignore]` は、**「このテストは一時的に除外すべき理由がある」**ことを、明示的に設計に残す。

---

## テストモジュールは“設計の内部可視化領域”

Rustでは、テストは `#[cfg(test)]` を使ってモジュール内に埋め込むことができる。

```rust
#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn it_works() {
        assert_eq!(sum(2, 3), 5);
    }
}
```

これは「**内部構造へのアクセスを許された、設計者の試験場**」という位置づけである。

- 内部関数やモジュールの直接テストが可能  
- `use super::*` により、そのモジュールを直視できる  
- 本番環境には影響を与えない（cfg属性による分離）

この構文分離が、**「本質を壊さずに内部を問い直す構造的試験」を可能にする**。

---

## テスト関数は関数ではなく、“証明”である

Rustの `#[test]` 関数は、返り値を持たない（`fn foo() {}`）にもかかわらず、  
失敗すればそれが `Err` のように扱われ、テスト全体を落とす。

この構造は、**テスト関数＝命題の証明**という意味を持つ。

- `assert!` は仮定の論理式  
- `panic!` は否定の証明  
- `#[should_panic]` は逆説の受容

Rustでは、「テストを書く」とは「**この構造がこの条件で保証されるべきであるという倫理宣言**」なのだ。

---

## Rustのテストは「未来のコードの保護装置」である

単体テストは、今のコードに対する検査ではない。  
それは未来の自分、未来の設計者に対して：

- 「ここに意図がある」  
- 「この振る舞いが仕様である」  
- 「この制約を壊すなら意図が必要だ」

という**設計的境界線を構文で残すための装置**である。

テストとは信頼の記録であり、変更に対する防波堤だ。

---

## 結語：テストは責任を残す構文である

Rustにおける単体テストは、構文が持つ意味を最大限に活かして、  
**「設計は検証されるべきである」「検証は構文で透明化されるべきである」**という態度を明確に示している。

- `#[test]` は検査の開始点  
- `assert!` は信頼の定式化  
- `#[should_panic]` は例外を含めた仕様の言語化  
- `#[cfg(test)]` は構造的可視性の範囲指定

Rustは、**テストさえも“構文で構造を語る場”として扱う数少ない言語**である。

> _"設計とは信頼の記録であり、テストとはその記録を構文で遺す倫理的形式である。"_