OmniAICreator/Qiita-1.07M huggingface dataset:
[Git] Wikiの概要と特徴




## In a nutshell
GitにおけるWikiは，プロジェクトのドキュメントを時系列で管理・共有できる仕組みである．READMEでは記述しきれない詳細情報を分けて整理でき，WebからもGit操作でも編集が可能．ソースコードとは別に，設計方針や手順書などの知識を蓄積・活用するのに適している．

## はじめに
GitHubには，Wikiのタブが存在する．これについて，README等のドキュメントとは適切に使い分けたいと考えた．そこで，Wikiとその特徴や使い道について，調べて以下に纏めた．



## 予想される読み手
 - GitHubについて，初学者である
 - GitHubについて実務で利用している，する予定がある．


## 概要  
GitにおけるWikiは，ソフトウェアプロジェクトやドキュメントを記述するための仕組みの一つ．主に，GitHubやGitLabなどのGitホスティングサービスで提供されている．WikiはGitのバージョン管理機能と組み合わされ，プロジェクトの技術的・運用的な情報を時系列で管理・編集することが可能である．Wikiはリポジトリごとに個別に用意される専用のGitリポジトリとして存在し，Markdown形式のファイルによってページが構成される．開発者やチームメンバーは，ウェブインターフェースからの編集はもちろん，ローカルにクローンして通常のGit操作でページを編集・管理することも可能である．



## なぜWikiを利用するのか？  
### プロジェクトのドキュメントを整理・共有するため  
Wikiは，READMEファイルに記述しきれないような詳細な情報を分けて記述するのに適している．たとえば，以下のような情報を明確に整理できる．

- プロジェクトの目的や設計思想
- 開発・ビルド・テスト手順
- 各モジュールの仕様や使用例
- チームでの運用ルールや開発方針

### 履歴管理・共同編集が可能  
WikiもGitによって管理される為，変更履歴が残る．よって内容の追跡・差分確認が容易であり，複数人での共同編集が安全に行える．

### Webインターフェースとコマンドラインの両方に対応  
WikiはGitHubのブラウザ上と，コマンドラインからの通常のGit操作での編集の両方が可能．


## ソースコード内のドキュメントとの違い  
多くのプロジェクトでは，ソースコードのコメントやREADME.mdなどにドキュメントを記述する．しかし，Wikiはこれらとは明確に異なる目的と役割を担う．ソースコードに近いコメントやREADMEは必須であるが，それだけでは全体像や運用フローを網羅できない．Wikiはその補完として，開発と運用の橋渡しとなるような情報を整理するのに向いている．

| 比較項目 | ソースコード内のドキュメント | Wiki |
|----------|-----------------------------|------|
| 主な目的 | 関数・クラスなどの仕様を直接説明 | プロジェクト全体の仕様・手順などの整理 |
| 管理単位 | ソースファイルごと | ページ単位(独立した構成) |
| 編集者 | 主に開発者 | 開発者に限らず，ドキュメント担当者や他職種も可能 |
| 内容の粒度 | 細かい実装に密接 | 高レベルな設計や方針，全体構成 |




## どのようなときにWikiを使うべきか

Wikiの導入は必須ではないが，以下のような状況において特に有効である．

- READMEが肥大化し，情報の整理が難しくなってきたとき
- 複数人で情報を記録・編集する必要があるとき
- 非開発者(例:マネージャー，ドキュメント担当)も情報を記載・共有したいとき
- 時系列で仕様やルールが変更されるプロジェクト
- 開発者が入れ替わる可能性があり，引き継ぎ情報を残したいとき


## Wiki活用のベストプラクティス  
### 情報の階層化とページ構成の整理  
Wikiには階層的な構造がないため，リンクによるページ間の接続や，インデックスページ(目次)を自作することで可読性を高める．

### 命名規則の統一  
ページ名やファイル名に明確なルール(例:命名にプレフィックスを使う，日付順，トピック別)を設けると，チームでの運用が容易になる．

### 編集履歴の活用  
変更履歴はトラブルシューティングや情報の追跡に有用である．大きな変更を加える際は，変更理由や背景も記述しておくとよい．

### タグやカテゴリの工夫(GitLabの場合)  
GitLabでは，Wikiにカテゴリ機能があるため，情報を整理するために活用できる．GitHubでは，ページタイトルや見出しを工夫して代用する．


## Wiki利用上の注意点
- 階層構造がない:大量のページを作成する場合は，リンク・インデックスページによる工夫が必要．
- ブランチ運用に制限:Wikiには通常，mainブランチしか存在せず，細かい分岐管理には不向き．
- 非公開Wikiの制限:パブリックリポジトリではWikiも自動的に公開される点に注意(GitHubの場合)．


## Wikiの導入方法  
GitHubを例に，Wikiの導入手順を示す．

### Web上での導入  
対象のリポジトリを開く．上部メニューの「Wiki」タブをクリック．初回の場合，「Create the first page」と表示されるので，ページタイトルと内容を入力し，「Save Page」で作成完了．

### ローカル環境での編集  
Wikiは `.wiki.git` という名前の独立したリポジトリとして管理されているため，以下のようにクローン可能．
クローン後は，Markdownファイルを追加・編集し，通常のGit操作で更新する．

```bash
git clone https://github.com/<ユーザー名>/<リポジトリ名>.wiki.git
```



## Summary
- WikiはGitHubやGitLab上で使えるGit管理されたドキュメント機能である．  
- READMEに入りきらない詳細な情報の整理・共有に向いている．  
- 編集履歴が残り，共同編集にも対応している．  
- ソースコード内のコメントとは異なり，プロジェクト全体の情報を扱う．  
- Webとローカル両方から編集でき，Markdown形式で記述可能．  
- 情報の整理や命名ルールを明確にすると，チーム運用がスムーズになる．


## References
 - [GitHub Docs - Building communities/Using wikis/About wikis](https://docs.github.com/en/communities/documenting-your-project-with-wikis/about-wikis)
エンジニアに必要なスキルとは？

# エンジニアに必要なスキルとは？

エンジニアとして活躍するためには、さまざまなスキルが求められます。以下は、その一部です。

## 必要なスキル

### 1. プログラミングスキル

エンジニアの基本となるスキルです。言語の選択やフレームワークの理解はもちろん、アルゴリズムやデータ構造の知識も重要です。実際の開発現場では、コードの可読性や保守性を意識した設計も求められます。

### 2. コミュニケーションスキル

チームで開発を進める際、適切な情報共有や意思疎通が欠かせません。特に、仕様変更や技術的な課題に対して、適切に伝える能力がプロジェクトの成功に直結します。

### 3. マネジメントスキル

個人開発とは異なり、チーム開発ではプロジェクトの進捗管理が非常に重要です。どれだけベテランのエンジニアが集まっても、管理が適切に行われなければ開発は滞ってしまいます。そのため、誰かがリーダーとしてマネジメントを行うことが求められます。

### 4. 優先事項の見極め

案件を進めるうえで重要なのは、タスクの優先順位を適切に判断することです。開発には限られた時間やリソースがあるため、全てのタスクを同時にこなすことは困難です。そのため、影響度が大きいものや緊急性の高いものから着手し、重要度の低いタスクは後回しにする判断力が求められます。

---

## プロジェクトとは？

プロジェクトとは、特定の目的を達成するために期限やリソースを設定し、計画的に進められる作業の集合体です。開発においては、要件定義から設計・実装・テスト・リリースまでの流れを適切に管理し、目標を達成することが求められます。

プロジェクトを成功させるためには、適切なフレームワークや手法を活用することが重要です。ここでは、代表的な2つの手法を紹介します。

---

## SCAMPER（スキャンパー）

SCAMPERは、アイデアを生み出すための発想法の一つで、以下の7つの視点から既存のものを改良・発展させる方法です。

1. **Substitute（代用する）** - 他のものと置き換えられないか？
2. **Combine（結合する）** - 別のアイデアと組み合わせられないか？
3. **Adapt（応用する）** - 他の用途や環境に適用できないか？
4. **Modify（変更する）** - 形状や色、大きさを変更できないか？
5. **Put to another use（他の用途に使う）** - 別の使い方ができないか？
6. **Eliminate（削除する）** - 不要な部分を取り除けないか？
7. **Reverse（逆転する）** - 逆の発想ができないか？

この手法を活用することで、新しいサービスや機能のアイデアを生み出しやすくなります。

---

## KPT（ケプト）

KPTは、振り返りの手法としてよく使われるフレームワークで、開発の改善に役立ちます。

- **Keep（継続すること）** - うまくいったこと、今後も続けるべきこと。
- **Problem（問題点）** - 課題や改善が必要な点。
- **Try（試すこと）** - 次回試したいこと、改善策。

KPTを定期的に行うことで、プロジェクトの課題を早期に発見し、改善サイクルを回すことができます。

---

## まとめ

エンジニアには、プログラミングスキルだけでなく、コミュニケーションやマネジメントのスキルも必要です。また、SCAMPERやKPTのようなフレームワークを活用することで、開発の効率を向上させることができます。チームでの開発においては、技術力と共に適切なプロジェクト管理を意識することが、成功の鍵となるでしょう。
【React Native】map関数使用時のキー重複エラー

## エラー内容
卒業制作の実装で下記エラーが発生しました。
```
Warning: Encountered two children with the same key, `5`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — the behavior is unsupported and could change in a future version.
```

## エラーが起きた箇所
```react:mapSample.tsx

<View style={styles.radioItemGrid}>
    {options.map((option) => (
        <RadioButton.Item 
            key={option.optionId} // ここでエラー
            label={option.optionName}
            value={String(option.optionId)}
        />
    ))}
</View>
```

## 原因
keyの値にindexが必要だった。
現状の実装だとkey指定のoptionIdが重複してしまう場合があるため、
map関数の引数にindexを追加してキーをUniqueにすることで解消されました。

## 修正後のソース
```react:mapSample.tsx
<View style={styles.radioItemGrid}>
    {options.map((option, index) => (
        <RadioButton.Item 
            // ここにindexを追加して、キーをUniqueにする
            key={`${option.optionId}-${index}`} 
            label={option.optionName}
            value={String(option.optionId)}
        />
    ))}
</View>
```

参考にした記事は下記です

https://qiita.com/yoshiwo/items/2d73f10fd1011b3a6b8a

## indexを追加する場合の注意点
indexをキーとして使用するのは、以下の条件を満たす場合に限ります。
【画面表示後】
- リストの順序が変わらない（ソートなどで順序が変更されない）
- リストの内容が動的に変更されない（リストの追加・削除が行えない）

## 対応後に気づいたこと
indexで対応してエラーは無くなったのですが、
改めて見直すと、別画面でキー自体が重複して登録されてしまうのが問題だとわかり、
今回の修正後のソース対応はせずに修正前のソースに戻しました。

どちらかというと、改めてmap関数についての気づきと
エラー調査の履歴を残す目的でこちらの記事を書かせていただきました。
気付いたこと、改めて勉強になったな！と思ったことは
どんどんOUTPUTして行こうと思います。
【SQL】ユーザー権限の設定(GRANT)

## ユーザーに設定出来る権限

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/387980/eccb33e9-334f-430b-a2be-f18af8378bda.png)


```SQL:システム権限を設定する
GRANT [権限] TO [ユーザー名];
```

```SQL:オブジェクト権限を設定する
GRANT [権限] ON [オブジェクト名] TO [ユーザー名];
```

## 主な権限（Oracleの場合）
### システム権限
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/387980/acf17fd0-aaf9-43ba-9c55-7cda90ec5593.png)

### オブジェクト権限
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/387980/b8852935-1062-4e21-a772-0799ba565143.png)


## おわりに
ここまで読んでいただきありがとうございます！

## 参考文献
・図解 SQL これからはじめる基本の知識 (知りたい！テクノロジー) 単行本（ソフトカバー） – 2010/12/11
島田 裕二 (著)
p.70-71
GraphRAGとエージェントアーキテクチャー入門 - Neo4jのプロトタイプ環境NeoConverseから学ぶ

## はじめに

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2648069/ad073a15-b4bd-40d7-8649-7a1a3840ec90.png)

Neo4jのブログ記事「[A Practical Experimentation of GraphRAG and Agentic Architecture With NeoConverse](https://neo4j.com/blog/developer/graphrag-and-agentic-architecture-with-neoconverse/)」を参考に、GraphRAGとエージェントアーキテクチャーの基本概念についてまとめます。

「NeoConverse」はNeo4j社の実験的なGenAIアプリケーションで、GraphRAGとエージェントアーキテクチャーを組み合わせたプロトタイプ環境です。次世代AI技術の可能性を探るための実証環境として開発されています。詳細は記事末尾の参考リンクをご覧ください。

## RAGとGraphRAGの違い

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2648069/804e4bc1-efbb-40fe-9e2d-d2bdeb513d3b.png)

### 従来のRAG（Retrieval-Augmented Generation）

従来のRAGは、ドキュメントを小さなチャンクに分割し、ベクトル化して検索する手法です。

**主な課題**:
- **関係性の理解が弱い** - 単語の類似性ベースの検索で、エンティティ間の関係性の推論が難しい
- **断片化されたコンテキスト** - 文書は孤立したチャンクとして扱われ、全体的な関係性が見えにくい

### GraphRAG

GraphRAGはナレッジグラフを活用し、エンティティと関係性を中心に据えたアプローチです。

**主な利点**:
- **関係性を活かした検索** - グラフ構造を探索して、必要なノードと関係を正確に特定
- **マルチホップクエリ** - 複数のエンティティをまたいだ関係性（例：「A社→B製品→C業界」）を1クエリで取得
- **説明可能な推論** - 回答の導出プロセスをグラフ上で追跡可能

## エージェントアーキテクチャーとは

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2648069/bf9810c3-b652-492d-9481-cf654826f2a0.png)

エージェントアーキテクチャーは、タスクを専門コンポーネント（エージェントやツール）に委任するアプローチです。

- **ツール**: データベース検索や計算機などの特定機能
- **エージェント**: 1つ以上のツールを調整する意思決定者

### 主なタイプ

1. **シングルエージェント**: LLMが直接ツールを使用（ChatGPTプラグインなど）
2. **マルチエージェント**: 複数の専門エージェントが協力（LangGraphなど）
3. **オーケストレーション**: 中央LLMがエージェントネットワークを統括（Bedrock Agentsなど）

### 利点

- **精度向上**: 個別のエージェントを専門家が調整可能
- **複雑なワークフロー対応**: 複数ツールの連携が可能
- **拡張性**: 新しいAIサービスを随時追加可能

## NeoConverseの仕組み

NeoConverseのシンプルな動作フロー:

1. ユーザーが自然言語で質問
2. LLMが意図を解析し適切なツールを選択
3. 専門ツールが利用可能なら実行、なければText2Cypher（自然言語からNeo4jのCypherクエリを自動生成し、データベースに直接問い合わせる機能）にフォールバック
4. 取得したコンテキストを基にLLMが回答を生成
5. ユーザーに根拠のある回答を提供

## 実験例: GraphRAG vs 従来のRAG

「Palantirの顧客について」という質問での比較:

**従来のRAG**: 
- 関連性の低いドキュメントも取得
- 別企業（WeWork）の顧客情報と混同
- 不正確な回答を生成

**GraphRAG**: 
- Palantirノードを中心に関連情報を検索
- エンティティ間の関係を正確に把握
- 正確な顧客リストを提供

### エージェントアーキテクチャの対応プロセス

エージェントアーキテクチャは以下のように効率的に対応します：

1. **分析フェーズ**：システムが質問を分析し、必要な情報を識別
   
2. **ツール選択**：それぞれの情報に最適なツールを自動選択
   - データベースクエリツール：メディア報道数の多い企業を特定
   - 企業情報ツール：選ばれた企業の詳細情報を取得
   - 株価情報ツール：リアルタイムの株価データを取得

3. **情報収集**：システムが各ツールを効率的に起動
   - まず「Accenture」が最も報道されている企業と特定
   - Accentureに関する企業情報を取得
   - Accentureの株価情報（ティッカー：ACN）を取得

4. **情報統合**：複数のソースからの情報を統合して完全な回答を生成

## まとめ
![summary-diagram (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2648069/b408afad-cb8f-45c3-88e8-579dcd69803f.png)

GraphRAGは関係性重視の検索を可能にし、エージェントアーキテクチャはタスクの効率的な分担と実行を実現します。両者を組み合わせることで、より正確で文脈を理解した回答が可能になります。

NeoConverseは、これらのコンセプトを実験的に実装したオープンソースプロジェクトです。

## 参考情報

https://github.com/neo4j-labs/neoconverse
OADPでバックアップ先を切り替え

# はじめに

本記事では、OpenShift API for Data Protection (OADP) を利用している環境において、新しいオブジェクトストレージへ移行する場合など、バックアップ先のバケットを切り替える必要が生じた場合の切り替え手順を示します。

# 目次

1. [検証環境](#検証環境)
1. [バックアップ先の切り替え手順](#バックアップ先の切り替え手順)
1. [まとめ](#まとめ)
1. [参考文献](#参考文献)

# 検証環境

- OADP version: 1.3, 1.4 
- Object Storage: MinIO
- Data Mover: kopia

# バックアップ先の切り替え手順

既存のBackupRepositoryの定義を念のためバックアップしておきます。
```shell-session
# oc get backuprepository -n openshift-adp <repostiory_name> -o yaml > <repository name>.yaml
```

BackupRepositoryを削除します。削除する理由は、BackupRepositoryの定義が残ったままだと、バックアップ先切り替え設定後も古いバケット内のデータを参照しようとして、バックアップが失敗してしまうためです。
```shell-session
# oc delete backuprepository -n openshfit-adp <repository_name>
```

Data Protection ApplicationのbucketLocations部分の定義を新しいバックアップ先の情報に変更します。(credentialも必要に応じて更新します)

```yaml: dpa.yaml の例 (backupLocations部分抜粋)
  backupLocations:
    - name: default
      velero:
        provider: aws
        default: true
        objectStorage:
          bucket: backup-new
          prefix: velero
        config:
          region: minio
          s3Url: http://192.168.0.1:8080
          s3ForcePathStyle: "true"
          insecureSkipTLSVerify: "true"
          profile: "backupStorage"
        credential:
          key: cloud
          name: cloud-credentials
```

既存のData Protection Applicationを一旦削除します。
```shell-session
# oc delete -f dpa.yaml
```

変更したyamlファイルを適用して、新しいバックアップ先を有効化します。
```shell-session
# oc apply -f dpa.yaml
```

新しいバックアップ先にバックアップが取れるか確認するためのyamlを用意します。
```shell-session
# cat << EOF > backup.yaml
apiVersion: velero.io/v1
kind: Backup
metadata:
  name: backup-test-1
  namespace: openshift-adp
spec:
  storageLocation: default
  includedNamespaces:
  - test1
EOF
```

バックアップを実行します。
```shell-session
# oc apply -f backup.yaml
backup.velero.io/backup-test-1 created
```

対象namespaceの全PVについて、datauploadsのSTATUSがCompletedになっていれば、バックアップが成功しています。
```shell-session
# oc get datauploads -A
NAMESPACE       NAME                             STATUS      STARTED   BYTES DONE    TOTAL BYTES   STORAGE LOCATION   AGE     NODE
openshift-adp   backup-test-1-xd4gp              Completed   4s        3485696       3485696       default            114s    worker1.example.com
```

# まとめ

新しいオブジェクトストレージへの移行などに伴うOADPのバックアップ先の切り替え手順を検証しました。BackupRepositoryを削除せずに、Data Protection Applicationの設定を変更するだけだと、古いバケットのデータを参照しにいこうとしてバックアップに失敗するので、その点注意する必要があります。

# 参考文献
- [OADP Application backup and restore](https://docs.redhat.com/en/documentation/openshift_container_platform/4.14/html/backup_and_restore/oadp-application-backup-and-restore#new-features-1-4-2_oadp-1-4-release-notes)
Tableau使いがPowerBIに入門した時の苦労メモ

# はじめに
8年以上Tableauを使っていて脳みそがTableauと同期しているため、PowerBIに慣れるのには苦労しました。せっかくあんおで苦労したポイントを殴り書きして残しておきます。TableauユーザーがPowerBIに入門する時の助けになれば幸いです。

# 戸惑ったところ

## 列とメジャーの違い(行単位計算と集計計算の違い)
Tableauだと行単位計算と集計計算の2種類は計算式の書き方で使い分けるが、PowerBIではそもそもフィールドの種類が違う。行単位計算をするなら「列」を追加する。集計計算をするなら「メジャー」を追加する。

## Ｍ言語とDAX関数
PowerBIはデータソース、セマンティックモデル、ワークブックの3層構造を持っている。
セマンティックモデルはPowerQueryで前処理を行うレイヤーでここではＭ言語を使う。ワークブックで列やメジャーを追加する際はDAX関数を使う。（どうやらテーブルも作れるらしいが、今のところよくわかっていない）。

PowerBIでの実現方法を検索するとき、セマンティックモデルで操作をしたいならM言語を探す必要があるし、ワークブックで操作をしたいならDAX関数を探す必要がある。これを間違えると使えない関数を入れようとしてうまくいかない、なんてことになってしまう。（なった）

## 各チャート間のフィルター設定
TableauでいうダッシュボードアクションについてはPowerBIでは相互作用と呼ぶ。書式設定から相互作用を表示をONにすれば、あるグラフをクリックしたときにどのグラフにフィルターを書けるか選ぶことができる。ただしチャート内の特定のディメンションのみフィルターに利用するといった細かな設定はできなさそう。

## 書式設定周り
Tableauとは異なり。Power BIではチャートタイプごとに設定できる書式設定が異なります。Tableauのように色、サイズ、ラベルですべてのチャートタイプをコントロールしているのに比べると少し難しく感じました。

## 要素の並び替えにひと手間必要
アルファベット順か数値に基づく並び替えしか基本的にできない模様。好きな順番に変更したい場合は並び替え用の列を追加する必要がある。Tableauだとグラフ上でドラッグアンドドロップで変更出来たり、デフォルトの並び順を設定できるのであれは便利だったなと実感

## グループ機能がない
Tableauだとグルーピング機能があるので、特定の要素を一つの要素にまとめることができる。例えば愛知、三重、岐阜を東海地方にグルーピングするイメージ。おそらくPower BIだと計算式で作るしかないのでは？

# PowerBIいいなと思ったところ

## 色がキレイ
デフォルトの色がモダン。

## スライサーのボタン表示がいい
これはTableauにもほしい機能。プレースホルダーで作れるっちゃ作れるけど面倒ではある。

## パワポっぽくレイアウトが作れるのはいい
パワポに慣れてる人には使いやすい気がする。Tableauに慣れてる身としてはTableauのレイアウトコンテナが恋しくなる。均等配置をつくるならレイアウトコンテナの方が楽。

## 角丸デザインがある
細かいけどデザインがモダンにみえる良い機能。

## Teams連携がいい
Teamsからそのまま見に行けるのがいい。ダッシュボードは見られてなんぼなのでみんなが毎日使うTeamsから簡単にアクセスできるのはいい。この点は[Tableauも強化を図っている](https://www.tableau.com/blog/introducing-tableau-app-microsoft-teams)ので今後に期待。

# おわりに
今後も気づいたことがあれば追記していこうと思っています。ほかにもここが困るよという要素があれば教えてもらえたら嬉しいです。
node.js？npm？Nuxt？な自分のためのメモ

## node.jsとは？
- javascript実行環境のこと
- JavaScriptはChromeやFirefoxといった「ブラウザ上」で動作するプログラミング言語
- ブラウザ上で動作するJavaScriptはOSの機能にアクセスできない
- Node.jsではJavaScriptで「OSの機能にアクセスする」プログラムを組むことができる

https://qiita.com/non_cal/items/a8fee0b7ad96e67713eb

## npmとは？
- node.jsのパッケージ管理システム
- パッケージの依存関係、パッケージの競合関係を解決

https://zenn.dev/antez/articles/a9d9d12178b7b2

## npmはじめの一歩
- npm init
  - 「このディレクトリ下は 我々npmが 管理下に置く！」宣言
  - package.jsonが作成される
- npm install
  - npmリポジトリからライブラリ（正確にはパッケージと呼びます）をダウンロードしてくる
- npm run
  - package.json内に書かれたシェルスクリプト(scripts)を実行する

https://qiita.com/hashrock/items/15f4a4961183cfbb2658

## vue.jsとは？

## nuxt.jsとは？
- Vue.jsをより使いやすくしたフレームワーク

https://www.webstaff.jp/guide/trend/webit/nuxtjs/

## nuxt.jsの前に必要な前提技術

https://qiita.com/newt0/items/763b0c228a8451c68865
AWSのLambdaとは

# そもそもAWSのLambdaとは？

サーバーのプロビジョニング、管理なしにコードを実行できるAWSが提供するサーバーレスコンピューティングサービス。
基本的にどのようなタイプのアプリケーションのコードも実行できる。
ちなみにサーバーレスというのはこちらがサーバーを用意する必要がなく、実行基盤はAWS側で管理されるということでサーバー自体が必要ないということではないです。

プロビジョニング
→必要なものを準備・提供すること、またはその作業工程、リソースのこと

# Lambdaの特徴

### その1 LambdaはFaaS（Function as a Service）の一つ
FaaSとは
・FaaSは「Function-as-a-Service」の略で、サーバーレスアーキテクチャの一形態

・オートスケーリング
　→　作成したプログラムに合わせて自動的にサーバーを拡大、縮小（オートスケーリング）する機能。
 
・イベントドリブン方式
　→ 基本的にイベントごとに実行させるコードを書く方式
 なんらかのイベントが発生した時に、初めて処理が実行される。
 コードの実行に必要なリソースのみを割り当て、使用されない時にはリソースを割り当てられないのが特徴

### その2 DB,S3連携
S3やDynamoDBのデータ更新をトリガーにLambdaを起動することができる

# Lambdaのメリット

### メリット
コスト効率
・未使用時はコストがかからず、実行時間と使用リソース量に基づいてのみ料金が発生する料金形態

自動スケーリング
・関数はイベントの量に合わせ自動的にスケールアップ、ダウンする

開発者の運用が楽に
・サーバーレスのため、サーバーの管理、スケーリングなどを気にせず開発に集中できる。

# まとめ
・AWSのLambdaはサーバーなどのインフラを管理する必要なく、運用負荷を減らし、簡単にDBに対してのコード実行などのバックエンドしょrが可能になり、より開発に集中できるようになる。
【制作記録】学習記録アプリの制作

## 作ったもの
学習内容・時間を記録出来るものを作成しました。  
Reactの習得も兼ねており、useStateを中心に理解を深められたと思います。

また、使いやすさを考え以下を工夫しました。
- 記録がない場合は`記録がありません`と表示分け
- 初期値で学習時間に0と入れていましたが、0を削除し入力する手間が発生していたため空欄に変更しました。

![Videotogif.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/683820/c2c74c69-8a22-418e-8876-a6a5ff04fbad.gif)


## 今回の学び(詰まったところ)
- JSX特有の書き方
    - CSSの書き方
- 入力値の取得方法
- reduceの使い方


#### JSX特有の書き方
割り当てるCSSも多くない予定だったため、今回直接CSSを書くことにしました。

```
//正
<h3 style={{ "margin-top": "40px" }}>学習履歴</h3>

//誤
<h3 style={{ margin-top: 40px }}>学習履歴</h3>
```
CSSは「""」で囲む必要があります。`margin`の際は不要ですが`margin-top`の場合は囲む必要があります。  
今回はVSCodeの拡張機能にエラーを吐いてもらうことで即解決しましたが、後日忘れてまたやらかしそうなので備忘録としてここに残します。

#### 入力値の取得方法
`event.target.value`が咄嗟に出てこず、「どうやって取得するんだっけな」となっていました。
```
<input
  type="number"
  value={time}
  placeholder="学習時間を記入してください"
  onChange={(event) => setTime(event.target.value)}
/>
```

### reduce
今回一番の学びで、一番詰まった所かもしれません。  
reduceとは配列の値を順に「pre(前回の値) + current(今回の値)」と足していく処理ですが、初回はpreに初期値を設定する必要があります。
初期値を設定出来ることを理解しておらず、初回だけエラーを吐くので処理の条件分けを行おうとしてました。
```
setTotal(
 records.reduce((pre, current) => {
 return pre + current.time;
 }, parseInt(time)) // parseInt(time)が初期値
);
```

## まとめ
コードの可読性を保つのは難しいなと痛感しました。
割り当てるCSSはちょっとだけと直接CSSを当てましたが、結局それなりに割り当てていて読みにくくなってしまったので。

# JISOUのメンバー募集中！
プログラミングコーチングJISOUでは、新たなメンバーを募集しています。
日本一のアウトプットコミュニティでキャリアアップしませんか？
興味のある方は、ぜひホームページをのぞいてみてください！
▼▼▼

https://projisou.jp
Vue.jsの基本

# Vue.jsとは

Vue.jsは、ウェブページに動きを加えるためのJavaScriptフレームワークです。
軽量で高速且つ、書き方がシンプルです。小さな部品（コンポーネント）で画面を構築可能です。

### 公式ページ

https://ja.vuejs.org/guide/introduction.html

# 使い方
### 1. CDNによる簡易利用（学習・お試し向け）
CDN（Content Delivery Network）を使ってHTMLファイルから直接読み込むことで、すぐに使い始めることができます。
``` html
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>Hello Vue</title>
  <!-- CDNからVue.jsを読み込む -->
  <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
</head>
<body>
  <div id="app">
    <h1>{{ message }}</h1>
  </div>
  <script>
    // アプリケーションの作成とマウント
    const { createApp } = Vue;

    createApp({
      data() {
        return {
          message: 'こんにちは、Vue.js！'
        };
      }
    }).mount('#app');
  </script>
</body>
</html>
```

### 2. ViteやVue CLIによる本格的な開発
```
npm create vite@latest my-vue-app -- --template vue
cd my-vue-app
npm install
npm run dev
```
※ npmのインストールが必要

# 基本的な構成
## data()
アプリケーションで使用するデータ（状態）を定義する場所
``` js
data() {
  return {
    message: 'Hello World!!'
  }
}
```

## {{ }}
data() で定義したデータを HTML に表示
```html
<h1>{{ message }}</h1>
```

## 属性バインディング
HTML 属性にデータを動的に挿入するには、v-bind を使用
```html
<img v-bind:src="imageUrl" alt="画像" />
<!-- 省略する場合 -->
<img :src="imageUrl" alt="画像" />
```

## メソッド
methods
イベントに応じて呼び出される関数群を定義
```js
methods: {
  greet() {
    alert('こんにちは！');
  }
}
```

## イベントバインディング
イベントを Vue のメソッドに結びつける
```html
<button v-on:click="greet">あいさつする</button>
<!-- こちらも同じ -->
<button @click="greet">あいさつする</button>
```

## 条件分岐
要素の表示・非表示を制御
v-if / v-else-if / v-else
```html
<p v-if="isLoggedIn">ようこそ！</p>
<p v-else>ログインしてください。</p>
```
```js
data() {
  return {
    isLoggedIn: true
  }
}
```

## 繰り返し
v-for
```html
<ul>
  <li v-for="(item, index) in items" :key="index">{{ item }}</li>
</ul>
```
```js
data() {
  return {
    items: ['リンゴ', 'バナナ', 'ぶどう']
  }
}
```

## フォームバインディング
v-model

```html
<input v-model="name" placeholder="名前を入力" />
<p>こんにちは、{{ name }}さん！</p>
```
```js
data() {
  return {
    name: ''
  }
}
```
## 算出プロパティ
computed
依存関係に基づいて動的に値を計算するプロパティ

```js
data() {
  return {
    lastName: '福沢',
    firstName: '諭吉'
  };
},
computed: {
  fullName() {
    return `${this.lastName} ${this.firstName}`;
  }
}
```
"Mozilla ThunderBird" でWindows起動時からリアルタイム通知が来るようにする方法 / How to make "Mozilla ThunderBird" get real-time notifications from Windows startup.【2025】

※This text is supported in Japanese only. Please translate and read in your browser.
## 内容構成

- 目標
- ダメだった方法
- できた方法
- 仕組み
- 注意点
- あとがき

## 目標
Mozilla ThunderBirdをWindows起動時に常駐させ、メールにリアルタイム通知を出させる

## ダメだった方法
- Traybirdを用いる -> 配布終了
- Shell:StartUpにショートカットを置き、 -minimize -tray の引数をつける -> ウィンドウが開いてしまう
- Shell:StartUpにショートカットを置き、 ショートカットのプロパティから最小化起動に設定 -> 上に同じ
- Shell:StartUpに.bat、.vbs、,ps1などを置き、最小化で.exeを起動させる ->上に同じ

## できた方法
拡張機能「Simple Startup Minimizer」をインストールし、
設定￥一般￥システム統合￥最小化したThunderbirdをタスクトレイにしまう 
を有効化した上で、Shell:StartUpに.exeへのショートカットを置く

## 仕組み
Windows起動時にShell:StartUpの内容が実行される。
Thunderbirdはあらゆる最小化起動オプションを無視して起動するが、拡張機能の「起動時にタスクトレイに移動する」機能によりウィンドウが消える。

## 注意点
- xまたはタスクを終了した場合通知が出てこなくなる -> 通知を押してウィンドウを開いた後は、最小化を押すとトレイに戻る
- Windows起動時に一瞬だけウィンドウがみえる -> あきらめる
- Windowsの設定によっては、タスクバーの「/\」みたいなやつに隠れていることがある -> 取り出して見えるとこに置く

## あとがき
Mozillaは実装してくれないかな、Windowsの起動時からリアルタイム通知する機能
電波法を説明します➂[特定小電力]➁

前回の続きで特定小電力です。

「特小は便利」な理由として「場所の規定がない」こところまで説明しました。今回は時間について説明します。
時間と書かれていても何のことわからないと思います。電波法では以下の規定があります。

➀送信する前にキャリアセンスする時間
➁送信する電波が連続的に発射できる時間
➂送信後に送信を休止しなければならない時間
➃1時間あたりに送信できる時間の総和

ちょっとわかりづらいですね。簡単に言えば、他の無線との干渉を避けつつ、かつ、共存させるためのマナーです。
例えば、コンサートで演者が喋っている声や歌は誰もが聞きたいと思っていますが、夜中に道路工事されて騒音で眠れないようなことがあったら、誰しも怒りますね。その場合、工事は日中に行い、皆の安眠を妨害しないようにします。無線も同じで、誰か一人だけが使えるのでなく、ある条件でマナー化して共存します。
➀のキャリアセンスとは、喋っている人がいないかを確認するためのものです。この時、あるレベル以上の場合は送信を行いません。レストランの隣のテーブルとは離れているので、自分が喋っても問題ありませんが、同じグループ内で同時に喋ったら会話になりません。そのため、事前に喋っている人を確認する作業のことを指します。
②は、独演会ならいざ知らず、独りよがりを避けるため、喋っていい時間を規定します。
➂は、一旦喋り終わってから、次の喋りまでの休憩時間です。
④は、グループごとの発表で、他のグループが発表している間は休憩している状態です。
こんな風に例えるとわかりやすいですね。

具体的な例として、920MHz帯のアクティブタグでは以下のようになっています。

A)キャリアセンス時間　128us以上の場合
　送信する電波が連続的に発射できる時間      　　　　　　最大400ms    
　送信後に送信を休止しなければならない時間  　　　　送信時間の10倍
　1時間あたりに送信できる時間の総和　　　　　　　　360秒

B)キャリアセンス時間　5ms以上の場合
　送信する電波が連続的に発射できる時間      　　　　　　最大4s    
　送信後に送信を休止しなければならない時間  　　　　50ms
　1時間あたりに送信できる時間の総和　　　　　　　　規定なし

Aは1/10デューティと呼ばれ、一回送信したら10倍休むものです。
Bはその規定がない代りにキャリアセンス時間が長くなっています。
Bの方が使いやすそう、と思いますが、そこは色々とあります。これ以外にの、「キャリアセンス不要」の条件もありますが、条件はこれらより、厳しくなります。
なお、免許局は免許があるため、特小より制限が少ないか、全くないものもあります。

話が長くなったので、時間についてはパート2でもう少し話します。
Cognitoでユーザー登録時の、LimitExceededExceptionのエラー

# エラー内容
Cognitoでユーザー登録をしたときに、メール送信が1日に送信できる上限を超えたという内容のエラーが発生した

```
LimitExceededException: Exceeded daily email limit for the operation or the account. If a higher limit is required, please configure your user pool to use your own Amazon SES configuration for sending email.
```

# 前提
- AdminCreateUser APIを使用している
- user_verifiedをtrueにして登録しているので認証メールは飛ばないようになっている
- 何もメール送信したくない


# わかったこと
- AdminCreateUser API を使用してユーザーを手動で作成すると、招待メールがデフォルトで送信されてしまう
- それがカウントされて、１日の上限に引っかかっていた
- 上限は1日50件

# 対応
オプションを追加して、招待メールも送信されないようにしたら、エラーがなくなった

```js
const {
  CognitoIdentityProviderClient,
  AdminCreateUserCommand
} = require('@aws-sdk/client-cognito-identity-provider');

const cognitoIdentityProviderClient = new CognitoIdentityProviderClient({});

const params = {
UserPoolId: userPoolId,
Username: username,
UserAttributes: attributes,
MessageAction: 'SUPPRESS' // これを追加。メール送信されなくなる
};

await cognitoIdentityProviderClient.send(new AdminCreateUserCommand(params));
```
データ基盤のデータレイク・データウェアハウス・データマートのイメージ

データ分析のステップと、そこで活躍するインフラに関する用語・ベストプラクティスをまとめてみようと思いました。
「ベストプラクティス」なので、世間一般で使われる、（やや？）枯れた技術のまとめです。

# データ分析のステップ

データ分析はいくつかステップがあります。
区切り方は諸説ありますが、大まかには以下のステップかなと思います。

1. Ask：目的を明確化し、問い・仮説を立てる
1. Prepare：データを準備する
1. Process：分析しやすいようにデータを整理・処理する
1. Analyze：実際にデータを分析する
1. Share：分析結果を共有する
1. Act：分析結果から行動を起こす

# データ分析を支えるインフラ

上記ステップのうち、ビッグデータに対して、Prepare~Process~Analyze~Shareを手間を掛けず、効率的・自動的に処理できるようにするインフラがデータ基盤です。
データ基盤は、その機能で大まかに、データレイク・データウェアハウス・データマートに分かれます。

こちらの図が個人的イメージと近いです。
https://medium.com/@david.alvares.62/datalake-datawarehouse-datamart-with-bigquery-32f6c3735a9d

## データレイク Data Lake

データの**湖**です。**非常に大きい湖**のイメージです。
データ基盤では上流に位置し、装置などから送られてくるデータが、まずここに入ってきます。
データレイクでは、**多種多様な生データ**を貯めています。

生データのため、そのまま使いやすいものもあれば、加工が必要なものも入っています。
（一般的に、使いやすいデータ＝表形式のデータを「構造化データ」と呼びます。）
そのため、ここがデータ分析に直接使われることは少ないです。

生データを貯めるため、ファイルシステムやAmazon S3などの比較的単純な**ストレージ**で構成されていることが多いです。

前述の分析ステップでは、Prepare~Processの段階で登場するかなと思います。

## データウェアハウス Data Warehouse

データの**倉庫**です。Amazonの**巨大物流倉庫**のようなイメージで、**多種多様なデータを扱いますが、整理整頓され使いやすい状態**で保持されています。
データ基盤では中流に位置し、データレイクのデータを加工処理[^1]して倉庫に貯めています。

データ分析では、このデータウェアハウスを用いて分析するはまあまああります。
ただし、「巨大物流倉庫」のため、「どこに何があるか」や「どうすれば効率的に扱えるか」といった、データを触る前の「コツ」があり、初心者には扱いにくいです。

データウェアハウスでは、**データベース**を使います。
小規模・単一データであれば表計算ソフトを利用する人が多いですが、データベースを用いると、大規模・複数のデータを一箇所で整合性が高い状態で管理できます。
データを取り出したいときも、計算処理や複数データを組み合わせた上で、所望の部分のみ抽出することができます。

前述の分析ステップでは、Process~Analyzeで登場するかなと思います。データサイエンティストであれば、結果をそのままShareすることもあるかなと思います。

[^1]: この、「データを使いやすい状態になるような加工処理」を「ETL処理」と呼ぶことがあります。Extract（ファイル抽出）、Transform（変換・加工）、Load（データベースに読み出し）の頭文字を取っています。
ETL処理により、不要な部分の削除、データの集約、簡易的な計算など、データの前処理を行います。

## データマート Data Mart

データの**店舗**です。小売店のイメージです。
データウェアハウスから必要なものを取り出し、特定用途に特化したデータを扱っています。

データウェアハウスは多種多様なデータを扱っているため初心者には扱いにくいですが、
データマートは特定の用途に絞っているため、高度な分析は難しいが、扱いやすいという特徴があります。
例えば、データウェアハウスには「全ての決済の詳細な情報」が入っている場合、それを集約した「日ごとの売上」がデータマートのイメージです。

データマートでもデータベースが使われることが多いです。
データマートの中身は比較的単純・軽量なデータであることが多いため、ストレージに書き出して扱うことも可能ですが、
ストレージにファイルを書き出す方式だとフォーマット変更などが容易で、データ整合性が保ちにくいため、
データベースを使うのがベストプラクティスかと思います。 

前述のデータ分析ステップでは、Analyze~Shareで主に登場するかなと思います。
ssh接続がバグったとき

# ssh接続が上手くいかないとき

### `C://user/ユーザ名/.ssh/` の `known_hosts` がSSHの履歴らしい
`known_hosts`ファイルがSSHの履歴らしいので、それを削除して接続し直すと治ることもあるそうです！！

![スクリーンショット 2025-04-01 194704.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3957418/7db6abb3-a27f-496a-a12a-1022c94fb122.png)
Next.js+TypeScript+Docker+Prismaのテーブル生成まで

Next.js+TypeScript+DockerでPrismaのセットアップをする手順を備忘録として以下に記載します。


## インストールと下準備
```
docker compose run --rm frontend sh
npm install @prisma/client
npm install prisma --save-dev
```
```
docker compose run --rm frontend sh
npx prisma init
```
Dockerfileに以下を追記してビルドします。
```dockerfile
RUN npx prisma generate
```
```f:prisma/schema.prisma
generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}
```
以下のようにoutputが記載されたままだと
generator client {
  provider = "prisma-client-js"
  output = "../generated/prisma"
}
以下のようなエラーが出る場合があります。
:::note warn
 ⨯ Error: @prisma/client did not initialize yet. Please run "prisma generate" and try to import it again.
:::

postgresのIPを固定します。
```f:docker-compose.yml
  frontend:
  ・
  ・
  ・  
  postgres:
  ・
  ・
  ・
    networks:
      fixed_compose_network:
```

## テーブルの生成
先にpostgresのコンテナだけを起動しmigrateをしてテーブルを生成します。
```
docker compose up postgres
docker compose run --rm frontend sh
npx prisma migrate dev --name init
```

なお、特定のコンテナだけを止めるときは以下のコマンドです。
```
docker-compose rm -fsv サービス名
```

## 参考
https://www.prisma.io/docs/optimize/getting-started

https://www.prisma.io/docs/getting-started/quickstart-sqlite
JavaScriptにおけるテスト設計戦略：ユニット / 結合 / E2E の分離、モック戦略、UIとロジックのテスト方針


## 概要

テストとは「書くもの」ではなく「設計を証明するもの」である。  
それは単なるチェックリストではなく、**設計が意図どおりであることを保証する、もう一つのインターフェース**である。

本稿では、JavaScriptにおけるテストを「単なるツール」から「設計構造の一部」へと昇華させるために必要な戦略を解説する。

---

## 1. テスト三層構造の理解と責務分離

| レイヤー     | 主な対象              | 特徴                        |
|--------------|-----------------------|-----------------------------|
| Unit Test    | 関数 / クラス         | 高速、ピュア、責務明確     |
| Integration  | モジュール / サービス | 実際の依存間の整合性検証   |
| E2E Test     | UI + サーバ           | ユーザー視点での振る舞い保証 |

→ ✅ それぞれ**何を守るためのテストか**を明確に設計する

---

## 2. ユニットテスト：純粋な構造の保証

```js
function add(a, b) {
  return a + b;
}
```

```js
test('加算関数', () => {
  expect(add(1, 2)).toBe(3);
});
```

- ✅ 入力と出力のみで定義される関数は**最小の保証対象**
- ✅ 副作用なし・依存なしが前提

---

## 3. 結合テスト：依存間の接続保証

```js
import { fetchUser } from './api';
import { renderUser } from './ui';

test('ユーザー情報の取得と表示', async () => {
  const user = await fetchUser();
  const ui = renderUser(user);
  expect(ui).toContain(user.name);
});
```

- ✅ 外部呼び出し（API / DBなど）は**mock/stubで制御**
- ✅ 依存先の“契約”を守るテスト → **インターフェース保証**

---

## 4. モック戦略：何を偽装し、何を残すか

```js
jest.mock('./api', () => ({
  fetchUser: jest.fn().mockResolvedValue({ id: 1, name: 'Toto' }),
}));
```

- ✅ モックは**副作用の排除 or テスト高速化**のための構造
- ✅ モックが乱立するとテストの意味が失われる → **構造の一部として設計すべき**

---

## 5. E2Eテスト：動作の保証ではなく、流れの保証

```js
// e.g. with Playwright
test('ログインしてダッシュボードが表示される', async ({ page }) => {
  await page.goto('/login');
  await page.fill('#email', 'user@example.com');
  await page.fill('#password', 'securepassword');
  await page.click('button[type=submit]');
  await expect(page).toHaveURL('/dashboard');
});
```

- ✅ E2Eは**振る舞いの確認 + 回帰テストの最後の砦**
- ❌ 頻度は少なめでよい → **回帰用に絞って設計**

---

## 6. テスト容易性を前提にした構造設計

- 関数は**副作用と切り離して設計**
- グローバル依存を減らし、**DI / hook / context などで外部注入**
- データ構造は**関数引数で与える**

```js
function createUserStore(apiClient) {
  return {
    fetch: () => apiClient.get('/user'),
  };
}
```

→ ✅ モック可能な構造にすることで**テストしやすさ = 設計品質**となる

---

## 7. CI / カバレッジとの統合戦略

- ✅ 全てのテストをCI上で実行し、**“守られている”構造を保つ**
- ✅ カバレッジはあくまで補助指標 → **低くても「テストすべき場所」がカバーされているならOK**
- ✅ 重要なのは**“設計の意図がテストで守られているか”**

---

## 設計判断フロー

```text
① テストがUI中心に偏っていないか？ → ロジック単位の分離を検討

② モックが意味をなしているか？ → 副作用・契約・境界で切る

③ ロジックとDOMが分離されているか？ → ユニットとE2Eの分離設計へ

④ テストが壊れたとき“なぜ”かがわかるか？ → 名前 / 構造を明示的に

⑤ テスト対象が関数でなければテスト不能では？ → 設計見直し
```

---

## よくあるミスと対策

### ❌ UIの見た目ばかりをsnapshotでテストし、内部ロジックが壊れても気づかない

→ ✅ **テストの粒度をUI / ロジックに明示的に分離**

---

### ❌ モックだらけでテストが意味を成していない

→ ✅ モックの対象を**「制御不能な外部」だけに限定**

---

### ❌ E2Eで全てを保証しようとして時間がかかりすぎる

→ ✅ E2Eは**ユーザーフロー + 致命的回帰の監視用**に絞る

---

## 結語

テストとは「安心を得るため」ではない。  
それは**“設計を守るための防波堤”**であり、  
**未来の開発者への契約文書**でもある。

- 責務単位で分離し  
- モックは構造的に設計し  
- 振る舞いではなく“意図”を検証する

**JavaScriptにおけるテスト設計とは、  
“壊れても壊れた理由が分かり、すぐに直せる構造”をつくる戦略である。**
JavaScriptにおけるセキュリティ設計：XSS / CSRF 対策、エスケープ戦略、トークン制御、クライアント保護の原則


## 概要

フロントエンドにおけるセキュリティとは、  
「攻撃を防ぐこと」ではなく、**「壊れない構造を設計すること」である。**

XSS、CSRF、セッションハイジャック、トークン漏洩、悪意ある入力…  
JavaScriptがユーザーのインターフェースを担う今、**クライアント側の設計品質がそのまま防御力となる。**

本稿では、JavaScriptにおける代表的な脅威とその対策、  
およびUI/UXを壊さずにセキュリティを担保する**構造的アプローチ**を紹介する。

---

## 1. XSS（クロスサイトスクリプティング）対策

```js
// ❌ 危険なパターン：innerHTMLに直接出力
element.innerHTML = userInput;
```

### ✅ 解決策：

- innerText / textContent を使う
- DOM生成を**明示的に構築**

```js
const text = document.createTextNode(userInput);
element.appendChild(text);
```

- HTMLテンプレートエンジンでは、**サニタイズ処理の有無を常に確認**

---

## 2. CSRF（クロスサイトリクエストフォージェリ）対策

- GETでは副作用のある操作を**絶対に許可しない**
- Cookieベースの認証には**SameSite=Strict or Lax** を設定
- 非Cookieベースの認証では**CSRFトークンを埋め込み + サーバーで検証**

```html
<input type="hidden" name="csrf_token" value="xxxx">
```

- フロントエンドから送信：

```js
fetch('/api/update', {
  method: 'POST',
  headers: {
    'X-CSRF-Token': csrfToken,
  },
});
```

---

## 3. トークン管理：localStorage / sessionStorage / Cookie の選択戦略

| 保管場所       | 特性                               |
|----------------|------------------------------------|
| localStorage   | 永続。XSSに弱い                    |
| sessionStorage | タブごと。XSSに弱い                |
| Cookie         | Secure / HttpOnly / SameSite 可。CSRF対策必須 |

### ✅ 原則：

- **XSS対策が万全でなければ Cookie + HttpOnly が最も安全**
- SPAでアクセストークンを扱う場合は、**期限 + scope + リフレッシュ設計**が必要

---

## 4. エスケープと検証の境界戦略

### ✅ サーバーサイド → サニタイズ済みを前提にしない  
### ✅ クライアント側 → 出力前に**escapeHTML**

```js
function escapeHTML(str) {
  return str
    .replace(/&/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;')
    .replace(/'/g, '&#39;');
}
```

→ ✅ UI層で必ず**「この値は表示される」ことを想定して防御**する

---

## 5. ユーザー入力を介するイベントの設計

- イベント名 / クラス名 / data属性 に**ユーザー入力を直接使用しない**

```js
// ❌ 危険な例
const el = document.querySelector(`[data-user="${input}"]`);
```

→ ✅ `Map` や `id-index` で**セーフな検索手段に分離**

---

## 6. エラーとロギング：セキュリティ情報の漏洩防止

- ✅ APIの失敗時に**スタックトレース・内部構造を出力しない**
- ✅ ログに**アクセストークンや個人情報を含めない**

```js
console.error('ユーザー取得に失敗しました'); // ✅ OK
console.error(error.stack); // ❌ 内部構造が露出
```

---

## 設計判断フロー

```text
① 出力箇所にinnerHTMLを使っていないか？ → textContentを選択

② トークンがlocalStorageにあり、XSSに晒されていないか？ → Cookie + HttpOnlyを検討

③ イベント/属性でユーザー入力を扱っていないか？ → DOM設計を再構成

④ トークンや個人情報をconsole.logで出力していないか？ → ロギングポリシー設計へ

⑤ CSRF保護が不完全なままCookieを使っていないか？ → SameSite/Tokenの導入
```

---

## よくあるミスと対策

### ❌ すべての出力にinnerHTMLを使い、XSS攻撃を許容

→ ✅ **表示は textContent、構造は DOM構築で対応**

---

### ❌ アクセストークンをlocalStorageに永続化し、別ページでも利用可能に

→ ✅ トークンは**必要なタイミングでメモリ保持 + 期限管理 or HttpOnly Cookie**

---

### ❌ fetch時にCSRFトークンを含め忘れ、保護バイパスが可能に

→ ✅ API設計時に**トークン含有をデフォルト設計**

---

## 結語

セキュリティとは「攻撃をブロックする」ことではない。  
それは**「攻撃される前提で設計する」こと**である。

- 表示前に必ず疑い  
- イベント前に経路を遮断し  
- 情報が漏れることを想定して制御する

**JavaScriptにおけるセキュリティ設計とは、  
“フロントエンドが最後の砦であることを理解した構造の構築”である。**
JavaScriptにおける状態管理設計：ローカル vs グローバル、再レンダリング最小化、ステートの正規化戦略

## 概要

状態管理とは「値を保存する」ことではない。  
それは**「UIとデータを最小コストで同期させ続ける構造設計」**である。

状態が肥大化すればロジックは壊れ、  
共有しすぎればコンポーネントは鈍重になり、  
非正規化された構造は**バグの温床**となる。

本稿では、以下の観点から**モダンJavaScriptアプリケーションにおける状態管理設計戦略**を提示する：

- ローカル vs グローバルの責務定義
- 再レンダリング最小化の構造
- ステートの正規化と派生設計
- 非同期状態と一貫性の保証
- 永続化・ストレージとの橋渡し

---

## 1. ローカル vs グローバル状態の原則

### ✅ ローカル状態（UIスコープ）

- ボタンの押下状態
- モーダルの開閉
- 現在のページ番号

```js
const [isOpen, setIsOpen] = useState(false);
```

### ✅ グローバル状態（アプリ全体に影響）

- ログインユーザー情報
- カート内容
- アプリ設定

```js
import { userStore } from '@/stores/user';
```

→ ✅ **「誰が管理し、誰が使うか」**で切り分けるのが本質

---

## 2. ステート正規化：配列をマップで持つ構造

```js
// ❌ 非正規化
const users = [
  { id: 'u01', name: 'Toto' },
  { id: 'u02', name: 'Mir' },
];

// ✅ 正規化
const userById = {
  u01: { id: 'u01', name: 'Toto' },
  u02: { id: 'u02', name: 'Mir' },
};
const userIds = ['u01', 'u02'];
```

- ✅ 再取得・更新が**O(1)**
- ✅ 重複を回避し、一貫性を保てる
- ✅ Redux Toolkitなどの**正規化支援ライブラリ**も有効

---

## 3. 派生状態（Derived State）の戦略

```js
const totalPrice = cartItems.reduce((sum, item) => sum + item.price, 0);
```

- ✅ 派生値は**状態に含めない**
- ✅ **関数で導出することで信頼性を担保**
- ✅ memo化・selector設計が重要（Recoil, Zustand など）

---

## 4. 再レンダリングを最小化する構造

```js
// ❌ すべての状態を1つにまとめると全部が再描画
const [state, setState] = useState({ a, b, c });

// ✅ 状態を粒度ごとに分割
const [count, setCount] = useState(0);
const [input, setInput] = useState('');
```

- ✅ **粒度を分けることでパフォーマンスが安定**
- ✅ グローバルステートでも**購読単位を最小に**

---

## 5. 状態と永続化ストレージの接続設計

```js
useEffect(() => {
  const stored = localStorage.getItem('theme');
  if (stored) setTheme(stored);
}, []);
```

- ✅ ステートとストレージを**直接結ばず、Adapterを設計**
- ✅ JSON.parse / stringify の一元化
- ✅ SSR対応時は**hydrationタイミングの制御**が必要

---

## 設計判断フロー

```text
① この状態はどこで必要？ → ローカル/グローバル切り分け

② 同一データを複数場所で参照していないか？ → 正規化へ

③ 状態に「結果」ではなく「原因」を保存しているか？ → 派生は関数に分離

④ 状態が肥大化していないか？ → 粒度分割 + 再レンダリング最適化

⑤ ストレージと直結していないか？ → Adapter or hook経由に構造化
```

---

## よくあるミスと対策

### ❌ すべての状態をグローバルに持たせてUIが鈍重化

→ ✅ **“必要なところにだけ届ける”**という設計の逆算を行う

---

### ❌ データの冗長表現が複数存在し、片方だけ更新されバグに

→ ✅ **正規化 + セレクターによる導出**に切り替える

---

### ❌ 状態が深くネストされて操作が難解に

→ ✅ 構造をフラットに、**参照・更新の経路を明示的に**

---

## 結語

状態管理とは「データを保管する」ことではない。  
それは**UIの整合性とアプリ全体の一貫性を保証する、構造の中核設計**である。

- スコープで役割を分け  
- 粒度で責任を分離し  
- 計算と保存を区別する

**JavaScriptにおける状態管理設計とは、  
“壊れず、重くならず、説明可能な構造をつくる”ための戦略である。**
JavaScriptにおけるモジュール設計戦略：ESModules vs CommonJS、分割・再利用・依存制御の設計論


## 概要

モジュールとは「処理の塊」ではない。  
それは**責務の単位であり、他との依存関係をコントロールする構造上の境界線**である。

本稿では、JavaScriptにおけるモジュール設計を以下の視点から体系化する：

- ESModules vs CommonJS の根本的違い
- export/import構文の設計ルール
- 分割と責務の境界定義
- 依存関係の明示的設計
- ルートエントリと内部構造の整理

---

## 1. ESModules vs CommonJS：構文と動作の差異

| 特性             | ESModules (ESM)                    | CommonJS (CJS)            |
|------------------|------------------------------------|---------------------------|
| 構文             | `import` / `export`                | `require()` / `module.exports` |
| 実行タイミング   | **静的**（パース時に解決）        | **動的**（実行時に解決） |
| 拡張子           | `.mjs` / `.js`（type:module）     | `.cjs` / `.js`（type:commonjs） |
| top-level await | ✅ 可能                            | ❌ 不可                   |

### ✅ ESMが主流だが、Node.jsとの互換性ではCJSが未だ根強い  
→ プロジェクト開始時点で**ESM / CJSどちらを使うかを明示**すべき

---

## 2. モジュールの構成原則：意味単位での分割

```text
project/
├─ modules/
│   ├─ user/
│   │   ├─ index.ts
│   │   ├─ service.ts
│   │   └─ validator.ts
│   ├─ auth/
│   │   ├─ index.ts
│   │   └─ session.ts
```

- ✅ モジュールは**機能（feature）単位**で分割
- ❌ utils や common のような**横断的な名目だけでまとめない**

---

## 3. export戦略：構造を公開するか抽象化するか

```js
// user/index.ts
export { getUser, updateUser } from './service';
export { validateUser } from './validator';
```

- ✅ `index.ts` で公開APIを整理することで**外部依存をコントロール**
- ✅ 内部構造を隠蔽し、**意図されたエントリポイントのみ公開**

---

## 4. 依存関係の設計と制御

- ✅ モジュール → サブモジュールの**一方向依存**を維持
- ❌ 循環依存（A→B→A）は構造崩壊の原因
- ✅ 共通依存（例：logger / config）は**DI（依存注入） or Adapter層**に隔離する

```js
// NG
userService → config → userService

// OK
userService → configAdapter → config
```

---

## 5. ESM特有の import/export パターン

```js
// 名前付きエクスポート
export function hello() {}

// デフォルトエクスポート
export default function () {}
```

```js
// インポート側
import { hello } from './module';
import main from './module';
```

→ ✅ 名前付きで意図を明示、defaultは**1モジュール = 1主要機能**がある場合のみ使用

---

## 6. top-level await と構造化非同期

```js
// ESMのみで使える構文
const data = await fetchData();
```

- ✅ 非同期初期化ロジックを**mainエントリで直書き可能**
- ✅ setup用モジュールとして `.bootstrap.ts` のような命名を採用する例も多い

---

## 設計判断フロー

```text
① 実行環境はNode.jsかブラウザか？ → ESM/CJSの選択

② 機能単位で責務が切れているか？ → modules/ を構造で分割

③ エクスポートする構造は抽象化されているか？ → index.tsの活用

④ 依存関係に循環はないか？ → 一方向 & Adapter層を設計

⑤ 非同期初期化はどこに書く？ → top-level await または明示的setup関数に分離
```

---

## よくあるミスと対策

### ❌ util.js に全処理をまとめて import で吸い上げ

→ ✅ 意味単位のモジュールに分割し、**単一責務の原則**を適用

---

### ❌ デフォルトエクスポートが多用され、関数の意図が読めない

→ ✅ 名前付きエクスポートで**意図を構文で明示**

---

### ❌ 内部構造まで全部exportし、外部モジュールからの依存が崩壊

→ ✅ `index.ts`で**公開するインターフェースを制限・統制**する

---

## 結語

モジュールとは、再利用ではなく、**“意味の境界線を設計する”ための構造**である。

- 責務ごとに構造を切り  
- エクスポートは意図を明示し  
- 依存を一方向に制御する

**JavaScriptにおけるモジュール設計とは、  
「プロジェクトの破綻を防ぐための、構造と言語による契約」である。**
JavaScriptにおける非同期設計戦略：Promise / async/await / 並列処理とエラーフロー設計


## 概要

非同期とは「後で起こる」ではなく、  
**「制御の流れが分断される構造」そのものである。**

現代のJavaScriptアプリケーションにおいて、非同期処理は通信・IO・遅延処理など、**あらゆるUXのコア**として存在する。  
しかし、設計を誤ればそれは**バグの温床・読みづらさ・失敗時の不安定な状態**を生む。

本稿では、**非同期制御の戦略的設計：Promise / async/await の原則、並列 vs 逐次制御、タイムアウト・キャンセル・エラーフローの構造化**を包括的に整理する。

---

## 1. Promiseの原則と構造

```js
const fetchUser = () =>
  new Promise((resolve, reject) => {
    setTimeout(() => resolve({ name: 'Toto' }), 1000);
  });
```

- ✅ resolve / reject は**一度だけ**
- ✅ 状態：pending → fulfilled / rejected
- ✅ `.then().catch().finally()` でチェーン制御

---

## 2. async/await構文：非同期を同期的に書く

```js
async function loadUser() {
  try {
    const user = await fetchUser();
    console.log(user.name);
  } catch (e) {
    console.error('取得失敗:', e);
  }
}
```

- ✅ `await` は**Promiseを待つ**
- ✅ `try/catch` により**同期的なエラーフロー**設計が可能
- ❌ `await` の連発は**逐次処理による性能劣化**に注意

---

## 3. 並列処理 vs 逐次処理の設計判断

### ❌ 逐次処理：時間がかかる

```js
const a = await fetchA();
const b = await fetchB();
```

### ✅ 並列処理：同時に開始

```js
const [a, b] = await Promise.all([fetchA(), fetchB()]);
```

→ ✅ **依存がなければ並列に、依存があるなら逐次に**切り分けて設計

---

## 4. タイムアウト・キャンセル設計

```js
function withTimeout(promise, ms) {
  const timeout = new Promise((_, reject) =>
    setTimeout(() => reject(new Error('Timeout')), ms)
  );
  return Promise.race([promise, timeout]);
}
```

- ✅ ネットワーク遅延・API停止時の**UIロック防止**
- ✅ AbortController との併用で**実際の通信も中断可能**

---

## 5. エラーフローの一貫性とUI統合戦略

```js
async function submit() {
  try {
    showLoading();
    const res = await sendData();
    showSuccess();
  } catch (e) {
    showError('送信に失敗しました');
  } finally {
    hideLoading();
  }
}
```

- ✅ ロジックとUIを**イベント的に接続**
- ✅ `finally` で**共通終了処理**を保証

---

## 6. 複数Promiseの制御構造

```js
const results = await Promise.allSettled([
  fetchA(),
  fetchB(),
  fetchC(),
]);
```

- ✅ `Promise.all` → いずれか失敗で即reject
- ✅ `Promise.allSettled` → **全ての成功/失敗を把握可能**
- ✅ `Promise.any` → 最初に成功したものを返す（他は無視）

→ ✅ 目的に応じて制御構造を設計的に選択する

---

## 設計判断フロー

```text
① Promiseとasync/awaitを混在していないか？ → await優先で構造統一

② 処理が依存してるか？ → 逐次か並列かで設計を明確化

③ 失敗時のUI制御はどうなっているか？ → try/catch/finallyを必ず設計

④ API遅延に備えているか？ → withTimeout / AbortControllerを検討

⑤ 複数非同期の制御方針はあるか？ → all / allSettled / any の選定を戦略的に
```

---

## よくあるミスと対策

### ❌ 複数 `await` を連続で書き、パフォーマンスが悪化

→ ✅ **依存がなければ Promise.all() で並列化**

---

### ❌ API失敗時に何も表示されない

→ ✅ catchブロック内で**UIに対して明示的通知を設計**

---

### ❌ async関数内でエラーを無視してクラッシュ

→ ✅ `try/catch`は**常にロジックの中で明示的に設計する**

---

## 結語

非同期とは「ただ待つ」ことではない。  
それは**“制御の流れが見えない世界”を“構造的に可視化する”ための設計行為**である。

- 流れを明確にし  
- 失敗を想定し  
- 同時性を設計し  
- UIとの整合を保証する

**JavaScriptにおける非同期設計とは、  
「後で何が起こるか」を未来の自分に説明できる構造である。**
JavaScriptにおけるイベント設計戦略：委譲・スコープ制御・一過性イベント・カスタムイベント構造



## 概要

イベントとは、“操作への反応”ではなく“構造の変化を伝播させるトリガー”である。  
UIはイベントによって動的に変化し、**イベントの設計はそのままインタラクションの設計である。**

本稿では、**DOMイベントの基本構造から委譲設計、スコープ制御、カスタムイベントの抽象化、イベント駆動設計の原則**までを体系的に解説する。

---

## 1. イベントリスナーの基本構造と落とし穴

```js
button.addEventListener('click', () => {
  console.log('Clicked');
});
```

- ✅ `addEventListener` は**関数オブジェクトを渡すことが原則**
- ❌ `onclick = function...` では後から上書きされうる

---

## 2. イベント委譲：親に任せる設計

```js
document.querySelector('#list').addEventListener('click', (e) => {
  if (e.target.matches('.item')) {
    console.log('Clicked item:', e.target.textContent);
  }
});
```

- ✅ **動的に生成される要素でも対応可**
- ✅ リスナーを1箇所に集約でき、**性能・構造ともに明瞭**
- ❌ `stopPropagation()` の多用は委譲を阻害する

---

## 3. スコープと伝播制御

### ✅ イベントバブリングの理解

```js
parent.addEventListener('click', () => console.log('parent'));
child.addEventListener('click', (e) => {
  e.stopPropagation();
  console.log('child');
});
```

- ✅ `stopPropagation()` → バブリング停止
- ✅ `stopImmediatePropagation()` → 他の同階層リスナーも阻止
- ✅ `capture: true` → **キャプチャフェーズで実行**

---

## 4. 一過性イベントとクリーンアップ戦略

```js
function bindOnce(el, type, callback) {
  const handler = function (e) {
    el.removeEventListener(type, handler);
    callback(e);
  };
  el.addEventListener(type, handler);
}
```

- ✅ 一度きりの処理（例：初回クリック、初期化、同意）を**自己削除型リスナー**で設計
- ✅ 不要イベントの残留防止

---

## 5. カスタムイベントの発火と監視

```js
const event = new CustomEvent('user:login', {
  detail: { userId: 'u01' },
});
document.dispatchEvent(event);
```

```js
document.addEventListener('user:login', (e) => {
  console.log('ログイン検知', e.detail.userId);
});
```

- ✅ 名前空間付きイベントで**意図の明確化**
- ✅ `detail`に**任意の構造体**を含められる
- ✅ UIだけでなく**状態通知にも使える**

---

## 6. イベント駆動のドメイン設計と契約

- ✅ 「何が発火されるか」を**コード外部から見える設計**にする
- ✅ 複数イベントのマッピングを用意（例：イベントバス、PubSub）

```js
export const EventBus = new EventTarget();
```

```js
EventBus.dispatchEvent(new CustomEvent('cart:updated'));
EventBus.addEventListener('cart:updated', updateCartIcon);
```

→ ✅ イベント設計が**ドメイン知識の構造化**になる

---

## 設計判断フロー

```text
① 要素が動的に生成される？ → 委譲で親に任せる

② 複数箇所で使われる？ → 共通のイベント名で抽象化

③ 状態変化を検知したい？ → カスタムイベント + EventBus構造

④ 一度きりのイベント？ → 自己削除型リスナー

⑤ 他のイベントに影響を与える？ → stopPropagationを慎重に
```

---

## よくあるミスと対策

### ❌ 同じ要素に何度もaddEventListenerし、メモリリーク

→ ✅ **明示的にremoveEventListenerを設計に組み込む**

---

### ❌ DOM構造とイベントの責務が混在し、変更に弱い構造に

→ ✅ **UIとイベントの接点を分離**し、コントローラ層を用意する

---

### ❌ カスタムイベントの命名がバラバラで意図不明

→ ✅ 名前空間（例：`user:login`, `modal:close`）で**意味と粒度を明確に**

---

## 結語

イベントとは「起こること」ではなく、  
**「構造の中で何を伝え、どう変化させるか」を設計する信号である。**

- 委譲によって構造を軽くし  
- カスタムイベントで意味を可視化し  
- バブリング・伝播を設計に取り込む

**JavaScriptにおけるイベント設計とは、  
“UIとロジックを接続する設計上のインターフェース”である。**
JavaScriptにおけるフォームバリデーション設計：構造化・再利用性・UI統合・バリデーション戦略の分離

## 概要

バリデーションとは「値のチェック」ではなく、  
**「正しさの定義」と「設計的責任」の明示である。**

UIに紐づいたアドホックなバリデーションは、  
保守不能なフォーム構造を生む。

本稿では、**バリデーションロジックの抽象化、入力UIとの分離、エラーメッセージの戦略的設計、同期/非同期チェックの構造化、再利用のための分離原則**を軸に、**信頼できるフォーム構造の構築法**を提示する。

---

## 1. バリデーションを「責務」で分離する

```js
function validateEmail(email) {
  if (!email) return '必須項目です';
  if (!/^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(email)) return 'メール形式が不正です';
  return null;
}
```

- ✅ 入力のチェックロジックは**UIとは切り離して**構築
- ✅ 戻り値は `"エラーメッセージ"` or `null` で統一 → **分岐コストを減らす**

---

## 2. フィールド単位でルールを宣言する

```js
const validators = {
  email: [isRequired, isEmail],
  password: [isRequired, minLength(8)],
};
```

```js
function runValidations(value, rules) {
  for (const rule of rules) {
    const error = rule(value);
    if (error) return error;
  }
  return null;
}
```

- ✅ 複数ルールを**ループ評価**
- ✅ 入力フィールドにバリデーションルールを“宣言”できる構造に

---

## 3. UIとの接着部分は別レイヤーで制御

```js
const emailInput = document.querySelector('#email');
const errorLabel = document.querySelector('#email-error');

emailInput.addEventListener('blur', () => {
  const msg = runValidations(emailInput.value, validators.email);
  errorLabel.textContent = msg || '';
});
```

→ ✅ バリデーションロジックと**DOM操作のレイヤーを明確に分離**

---

## 4. 非同期バリデーションの組み込み

```js
async function checkEmailDuplication(email) {
  const res = await fetch(`/api/email-check?email=${email}`);
  const isTaken = await res.json();
  return isTaken ? '既に登録されています' : null;
}
```

```js
async function validateFieldAsync(value, rules) {
  for (const rule of rules) {
    const result = await rule(value);
    if (result) return result;
  }
  return null;
}
```

- ✅ 同期と非同期のルールを分離設計 → `validateSync()` / `validateAsync()` 両立設計へ

---

## 5. 全体バリデーションの設計構造

```js
async function validateForm(values, validators) {
  const errors = {};
  for (const key in validators) {
    const rules = validators[key];
    const value = values[key];
    const error = await validateFieldAsync(value, rules);
    if (error) errors[key] = error;
  }
  return errors;
}
```

→ ✅ “全体として正しいか”をチェックするAPI用の検証構造を統合設計

---

## 6. メッセージの国際化・汎用化構造

```js
const messages = {
  required: '必須項目です',
  invalidEmail: 'メール形式が不正です',
};

function isRequired(value) {
  return !value ? messages.required : null;
}
```

- ✅ ロジックと文言を分離
- ✅ i18nとの統合が容易な構造に

---

## 設計判断フロー

```text
① ロジックがUI内に埋もれていないか？ → 関数分離

② 同期/非同期チェックが混在してないか？ → 分離して統合設計

③ ルールが再利用可能になっているか？ → フィールド単位の宣言型に

④ 文言がロジックにハードコードされていないか？ → メッセージ分離

⑤ DOMとの接着部分がテスト不能になっていないか？ → UIとロジック分離
```

---

## よくあるミスと対策

### ❌ UIイベント内で直接 `if (!value) { showError(...) }` を繰り返す

→ ✅ ルールごとの関数を定義し、**宣言的に登録**する構造へ

---

### ❌ 非同期チェックを `onSubmit` に直書きして処理が複雑化

→ ✅ 非同期ルールを**同期ルールと同様の形式で処理できる構造**に

---

### ❌ エラー文言がHTMLにハードコードされていて再利用不能

→ ✅ メッセージは**定義モジュールから取得**する形式に統一

---

## 結語

フォームバリデーションとは、“正しいか”を判定する行為ではない。  
それは**“何を許可し、どこで止め、どう伝えるか”という、設計上の責任の表明**である。

- UIとロジックを分離し  
- 責務を関数に還元し  
- メッセージを柔軟に制御する

**JavaScriptにおけるバリデーション設計とは、  
“意図された操作だけを許容する、安全なインターフェースの設計である”。**
JavaScriptにおける日付処理設計：標準API vs ライブラリ、国際化、フォーマット・比較・操作の一貫性

## 概要

日付処理とは、“見た目”ではなく“意味”を整える設計行為である。  
JavaScriptの `Date` は**グローバルな仕様にしては脆弱すぎる**。  
だからこそ、**標準APIの理解と、ライブラリの選定・運用ポリシーを含めた戦略設計が必要不可欠**になる。

本稿では、日付を“壊れず・迷わず・読める形で使い続ける”ための構造設計を整理する。

---

## 1. JavaScript標準Dateの限界と強み

```js
const d = new Date('2023-12-01T12:00:00+09:00');
```

### ✅ 利点

- ブラウザ/Node.js共通
- ISO文字列で扱いやすい
- `toISOString`, `getTime()`などで精度あり

### ❌ 欠点

- `Date`のコンストラクタが曖昧な挙動をする（非標準文字列がパースされる）
- タイムゾーンが内部ではUTC固定 → **“表示用”のズレ**
- 月（0始まり）、日付比較の煩雑さ

---

## 2. ライブラリ導入の判断軸

| 処理の内容                     | 推奨手段       |
|------------------------------|----------------|
| フォーマット・差分・加減算     | ✅ `date-fns`   |
| タイムゾーン操作が多い         | ✅ `Luxon` or `Intl` API |
| 単純な日付表示・変換           | `Date.toLocaleDateString()` で済ませる
| ビジネスロジックに関わる計算   | 自作 or date-fns で構造化

---

## 3. date-fnsで構造化する日付処理

```js
import { format, parseISO, addDays, isBefore } from 'date-fns';

const d = parseISO('2023-12-01');
const label = format(d, 'yyyy年MM月dd日');
const tomorrow = addDays(d, 1);
```

- ✅ 関数型で**1処理1関数**
- ✅ 型の変化が明確、**不変**
- ✅ 一貫した処理構造が構築可能

---

## 4. Luxonでのタイムゾーン管理

```js
import { DateTime } from 'luxon';

const dt = DateTime.fromISO('2023-12-01T12:00:00', { zone: 'Asia/Tokyo' });
dt.toFormat('yyyy/MM/dd HH:mm'); // "2023/12/01 12:00"
```

- ✅ `zone`による明示的タイムゾーン指定
- ✅ ISO ⇄ ローカル ⇄ UTCの切り替えが簡潔
- ✅ `toUTC()`, `toLocal()`, `toISO()` で表現形式を制御可能

---

## 5. 表示 vs ロジックの構造的分離

```js
// ロジック（計算）
const isExpired = isBefore(parseISO(dueDate), new Date());

// 表示
const label = format(parseISO(dueDate), 'yyyy/MM/dd');
```

→ ✅ 日付そのものの“意味”と“表現”を常に**別レイヤーで設計する**

---

## 6. 国際化（i18n）とフォーマット戦略

```js
const date = new Date('2024-03-31');

date.toLocaleDateString('ja-JP', {
  year: 'numeric',
  month: 'long',
  day: 'numeric',
}); // → "2024年3月31日"
```

- ✅ `toLocaleDateString()`で言語ローカライズ
- ✅ ただし細かいレイアウト制御には不向き（→ ライブラリ使用）

---

## 7. 設計判断フロー

```text
① 単純な表示 or ログ？ → Date + toLocaleDateString()

② 表示形式が複数？ → format()系関数でテンプレート化

③ 日付加算・差分？ → date-fnsで構造化

④ タイムゾーン変換が必要？ → Luxonなどで明示的設計

⑤ UI表示とロジックが混在？ → レイヤーを明確に分離
```

---

## よくあるミスと対策

### ❌ 月の計算で off-by-one エラー（0始まり）

→ ✅ `getMonth() + 1` ではなく `format(date, 'MM')` を利用

---

### ❌ UTC / ローカル変換で意図しないズレが発生

→ ✅ `Date`の内部は常にUTC → 明示的に `toLocaleString()` or `toISOString()` を使い分け

---

### ❌ `new Date()` に文字列を直接渡す

→ ✅ `parseISO()` や `fromFormat()` などを明示的に使う

---

## 結語

日付とは「いつか」ではなく、**「どう扱うか」が本質である。**

- 表示と意味を分離し  
- 加減算と比較を明示的にし  
- タイムゾーンを設計に組み込む

**JavaScriptにおける日付処理設計とは、  
“曖昧な時間”を“壊れない構造”に変換する技術戦略である。**