OmniAICreator/Qiita-1.07M huggingface dataset:
【Notion】チェックリストはデータベースでも作れる

レイアウト=`リスト`
表示する属性に`ステータス`追加
ステータスの表示方法を`チェックボックス`に設定


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237839/9597ac21-a372-4172-b734-0071a382214f.png)

下記のような感じにできる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237839/82dfb936-03a4-4862-9771-60387928b976.png)

リストで表示されたチェックボックスを、`alt+クリック`すると細かく更新したいステータスの選択ができる

---

その他にも、開始ボタンなどを作ってステータス変更をトリガすることもできる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237839/f904246d-d627-4a08-8186-0a2b429b62f0.png)

ボタンで設定できるアクションの種類には謎が多い、、わら
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237839/9d12d447-b46e-4652-ada5-fc464dff3f5c.png)
【初心者向け】CPU のベンチマーク【５分で読める】

# CPU のベンチマーク

理解のために小咄形式でまとめました。

:::note info
システムパフォーマンス関連記事の目次
- [【初心者向け】システムパフォーマンス関連まとめ【それぞれ５分で読める】](https://qiita.com/nouernet/items/d3efe67e0f52a92e061d)
:::

**登場人物**
- **太郎（後輩）**：入社1年目の若手エンジニア。
- **花子（先輩）**：システムエンジニア歴3年の先輩。

**場面：社内の開発ルーム**
*太郎が CPU のパフォーマンステストについて調べている。花子に質問をする。*

**太郎**：「花子先輩、`CPU のベンチマーク測定や、パフォーマンステスト` ってどうやるんでしょうか？ `普段の監視ツールと何が違う` のか、いまいち分からなくて。」

**花子**：「いい質問ね！ `CPU のパフォーマンスを評価する方法` には、大きく `監視ツール` と `実験ツール` の 2 つのアプローチがあるの。」

---

### **CPU のベンチマーク**
**花子**：「`CPU のパフォーマンスを積極的にテストする方法` は、大きく 2 つあるわ。」

1. **アドホックテスト**
2. **SysBench を使った CPU ベンチマーク**

---

### **1. アドホックテスト**
**花子**：「`アドホックテスト` っていうのは、 `簡単なスクリプト` で CPU の負荷を意図的に作り出して、 `システムの監視ツールが正しく動作しているか確認する方法` よ。」

- **例として、以下のコマンドを実行する**
  ```sh
  while :; do :; done &
  ```
- **このコマンドは、 `無限ループ` を作り出し、`CPU を 1 つのスレッドで 100% 使用` させる**
- **`top` や `mpstat` を見れば、この負荷がどのように CPU に影響するか確認できる**

「これは `負荷を意図的に発生させて、監視ツールの精度を確かめる手法` よ。」

**太郎**：「ってことは、 `監視ツールが期待通りに CPU の負荷を表示できるか` を確かめるんですね！」

---

### **2. SysBench を使った CPU ベンチマーク**
**花子**：「`SysBench` は、 `CPU の計算能力を評価するためのベンチマークツール` よ。」

- **例として、以下のコマンドを実行する**
  ```sh
  sysbench --num-threads=8 --test=cpu --cpu-max-prime=100000 run
  ```
- **このコマンドは `CPU に素数を計算させる負荷をかける`**
- **`スレッド数を増やすことで、マルチスレッドのパフォーマンスを測定` できる**
- **結果として、`CPU の処理速度やスケジューリングの影響` を評価可能**

「これは `CPU にとって実際の負荷がどれくらいの影響を与えるか` を測る `本格的なベンチマーク` ね。」

**太郎**：「なるほど！ `アドホックテストは監視ツールの確認`、 `SysBench は CPU のパフォーマンス計測` に使うんですね！」

---

**花子**：「これを `車の性能評価` に例えると、こんな感じね。」

1. **アドホックテスト → アイドリングテスト**
   - `エンジンをかけっぱなしにして、計器類（監視ツール）が正しく動いているかを確認する`
   - `問題があれば、計器の調整や修理を行う`

2. **SysBench → 実際の走行テスト**
   - `高速道路で最高速度テストを行い、どこまで加速できるか測る`
   - `坂道を登らせて、負荷がかかった時の性能を測る`

**太郎**：「めちゃくちゃ分かりやすいです！ `監視ツールの確認と、CPU の本格的なベンチマークを使い分ける` のが重要なんですね！」

---

### **まとめ**
**花子**：「`CPU の実験的なテスト` は、 `可観測性ツールの検証` と `CPU の本格的なベンチマーク` の 2 つの目的で行うのよ。」

**太郎**：「ありがとうございます！ `まずはアドホックテストで監視ツールを確認し、それから SysBench で CPU の本格的な測定を試してみます！」 

# 参考リンク

システムパフォーマンス関連記事の目次

- [【初心者向け】システムパフォーマンス関連まとめ【それぞれ５分で読める】](https://qiita.com/nouernet/items/d3efe67e0f52a92e061d)

システムパフォーマンス関連記事は、以下の書籍を参考に記述しています。

- [［改訂新版］プロのためのLinuxシステム構築・運用技術](https://www.amazon.co.jp/dp/B01LZURAPK)
- [改訂2版 ネットワークエンジニアの教科書](https://www.amazon.co.jp/dp/B07NXQ4TDV)
- [絵で見てわかるシステムパフォーマンスの仕組み](https://www.amazon.co.jp/dp/B00LHFOTF4)
- [詳解 システム・パフォーマンス 第2版](https://www.oreilly.co.jp/books/9784814400072/)
- [入門 モダンLinux](https://www.oreilly.co.jp/books/9784814400218/)
- [Linuxシステム管理](https://www.oreilly.co.jp/books/9784873113463/)
MacのGrapherを回路設計の補助に使う

# 背景
回路設計で使う遅延回路ですが、お手軽に遅延時間を設定するにはCRを使った時定数が便利です。
時間`t`と電圧`V`の関係は、数式を知っていれば簡単で、
```math
\displaylines{
V=E(1-e^{-\frac{1}{CR}t})\\
E:電源電圧
}
```
で表されます。
経験豊富(?)なエンジニアは、おおよそ電源電圧の0.63倍とか、0.36倍という数字で当たりをつけると思います。

マージンも考慮してこの程度の計算でカバーできるなら、これでOKですね。

しかし詳細な解析となると、ちゃんと計算をしなきゃいけないこともあります。
そんな時、Macに標準で入っている`Grapher`というアプリケーションがとても頼りになりますよ！

# 時定数をグラフ化してみる
例えば82KΩ、22uFの組み合わせでの回路の動作をGrapherで見てみます。
この時の時定数は
```math
(82\times10^3)\times(22\times10^{-6})=1.804[sec]
```
で、使用する電源の電圧が29.2Vの場合、充電回路の数式は
```math
\displaylines{
V=29.2(1-e^{-\frac{1}{1.804}t})\\
}
```
となります。
この数式をGrapherに入力し、グラフを書かせてみます。
わかりやすくするため、グラフの色は青に変えました。

![スクリーンショット 2025-02-20 9.10.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202602/8cd06d47-33b6-45e6-a4f5-94438e3ca77a.png)

実際の回路の振る舞いをそのまま表せています。

# お手軽に経過時間と電圧を知る方法
## カーソルを動かして調べる
とりあえず、大まかに20Vに達する時間はどのくらいか...
これはグラフをクリック・ドラッグしてみればいいです。
その際、`アクション`をカーソルにしておきます。
青いグラフをクリックしてなぞって(ドラッグ)いくと、X軸とY軸の破線がカーソルに合わせて動きます。
それと同時に、ウィンドウの下にその時のXとYの値が表示されます。
![スクリーンショット 2025-02-20 9.14.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202602/ad247d57-5504-4b2b-b6d3-1ec29a953630.png)

Yがおよそ20の時、Xは2なので、**電圧が20Vに達する時間はおよそ2秒**ということがわかります。
## 時間を数値で指定して電圧を調べる
入力した数式の`x`の値を入れて`y`の値を求めることもできます。
メニューバーの`方程式`から`評価`を選びます。

![スクリーンショット 2025-02-20 9.22.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202602/54f40697-5768-4c2f-9364-d438c6327bb7.png)

xの値を探りながら入れて、実際は2.1秒くらいなんだろうな...ということがわかります。

# 正確に時間を知るには
これはちゃんと計算するしかありません。
時定数の式は電圧を求める式なので、逆に時間を求める式に変換します。
懐かしいですね...学生時代を思い出す方もいらっしゃるかと(笑)
```math
t=-1.804ln(1-\frac{V}{E})
```
グラフを書かせると、こんな感じになります。
![スクリーンショット 2025-02-20 9.29.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202602/ef5d8d5f-13fa-4bbe-8d64-7200e45248d1.png)

このグラフで`方程式`の`評価`をすればいいですね。
![スクリーンショット 2025-02-20 9.30.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202602/f8a49ba5-3fe6-447f-b362-cd446ad773e2.png)
**充電電圧が20Vになるのは2.0836秒**と正確に求められます。

# Grapherの使いこなし
## 範囲指定のグラフ
この機能はGrapherのバグでクラッシュしてしまうことがありますが、とても便利です。
```math
0<x<100
```
という範囲でグラフを書きたい...ということはありますよね。
その場合は条件を指定する数式を使います。

![スクリーンショット 2025-02-20 9.35.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202602/4e90a8bb-3890-427f-b3a7-f4d2ffef6d0c.png)

条件の数は「2」にしてみました。
![スクリーンショット 2025-02-20 9.40.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202602/485840f8-f3a1-45e4-b62b-7c47fe5de2d0.png)
上の書き方では、
- xが0未満は0
- xが5未満はグラフを描画

という意味です。
また、条件の書き方では`&`でAND条件が書けます。
![スクリーンショット 2025-02-20 9.44.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202602/16bdd648-0e33-433d-af67-b2435b2a1eb9.png)
上記の例では二次関数を`2<x<5`の範囲で書きます。
Grapherの条件の数を2にしましたが、1もできるんじゃなかと思うのですが...
バグなのか仕様なのか、うまくいきませんね...

# 最後に
回路設計では指数関数、対数関数などを扱うことが多いです。
大抵は関数電卓で済んでしまうのですが、不具合の解析などで回路の動きを追うときには、やはりグラフ化して確認するのが視覚的にわかっていいです。
お客様に説明するときにも、大抵すぐに理解してもらえます。

Grapherのバグが直ることを期待しつつ、回路設計に従事している方は使ってみてはいかがでしょうか？

とても使いやすいですよ、これ！
【初心者向け】CPU のパフォーマンス可視化（ビジュアライゼーション）【５分で読める】

# CPU のパフォーマンス可視化（ビジュアライゼーション）

理解のために小咄形式でまとめました。

:::note info
システムパフォーマンス関連記事の目次
- [【初心者向け】システムパフォーマンス関連まとめ【それぞれ５分で読める】](https://qiita.com/nouernet/items/d3efe67e0f52a92e061d)
:::

**登場人物**
- **太郎（後輩）**：入社1年目の若手エンジニア。
- **花子（先輩）**：システムエンジニア歴3年の先輩。

**場面：オフィスの開発ルーム**
*太郎が `CPU のパフォーマンス可視化` に関する資料を見ながら、花子に質問する。*

**太郎**：「花子先輩、`CPU の使用状況を可視化` する方法って色々あるみたいですが、 `どの手法がどう役立つのか` いまいち分からなくて…。」

**花子**：「そうね、 `データを視覚的に分析すること` で、 `システムのボトルネックを直感的に理解` できるのよ。 `主要な可視化手法` を説明するわね。」

---

### **CPU のパフォーマンス可視化（ビジュアライゼーション）**
**花子**：「CPU の `パフォーマンスを可視化する手法` には、 `4 つの主要な方法` があるの。」

1. **使用率ヒートマップ**
2. **秒未満オフセットヒートマップ**
3. **フレームグラフ**
4. **FlameScope**

---

### **1. 使用率ヒートマップ**
**花子**：「`使用率ヒートマップ` は、 `複数の CPU コアの使用率を時系列で表示するグラフ` よ。」

- **横軸** → `時間（秒単位）`
- **縦軸** → `CPU コア`
- **色の濃淡** → `CPU 使用率の高さを示す`

**花子**：「例えば `htop` では、 `各 CPU の使用率` をリアルタイムで確認できるけど、 `時系列の傾向` までは分からないわよね。」

**太郎**：「たしかに！ `ヒートマップなら、 CPU の負荷が時間とともにどう変化するか` が直感的に分かりそうですね！」

---

### **2. 秒未満オフセットヒートマップ**
**花子**：「`秒未満オフセットヒートマップ` は、 `ミリ秒レベルの CPU 負荷の変動` を視覚化する手法よ。」

- **横軸** → `時間（秒単位）`
- **縦軸** → `秒未満のオフセット`
- **色の濃淡** → `CPU の負荷や I/O レイテンシの変化を示す`

**花子**：「例えば `CPU のスパイク` が `特定のタイミングで発生` している場合、 `秒未満レベルの精度` で可視化することで、 `何が原因かを特定しやすくなる` のよ。」

**太郎**：「なるほど！ `ミリ秒単位での負荷変動` を知りたいときに使えるんですね！」

---

### **3. フレームグラフ**
**花子**：「`フレームグラフ` は、 `CPU のスタックトレースを可視化する手法` よ。」

- **縦軸** → `関数のスタックの深さ`
- **横軸** → `CPU 時間`
- **幅の広さ** → `関数の実行時間が長いほど太くなる`

**花子**：「例えば `perf` で `スタックトレースを収集` して、それを `フレームグラフに変換する` と、 `どの関数が CPU を多く消費しているか一目で分かる` のよ。」

**太郎**：「ってことは、 `プログラムのどこがボトルネックになっているかを探る` のに最適なんですね！」

---

### **4. FlameScope**
**花子**：「`FlameScope` は、 `CPU の負荷のパターンをズームインして調査できるツール` よ。」

- **全体的な負荷のパターンを確認**
- **特定のピーク部分を拡大**
- **異常な CPU 使用パターンを素早く発見できる**

**花子**：「例えば `短時間の CPU スパイク` の原因を探したいとき、 `FlameScope ならピンポイントでズームインして調査できる` のよ。」

**太郎**：「なるほど！ `FlameScope を使えば、CPU スパイクの発生要因を詳細に分析できる` んですね！」

---

**花子**：「これらの `可視化手法` を `交通分析` に例えると、こんな感じね。」

1. **使用率ヒートマップ** → `渋滞マップ`
   - `どの道路がどの時間帯に混雑しているかを一目で把握。`
  
2. **秒未満オフセットヒートマップ** → `信号の変化パターン`
   - `細かいタイミングのズレを確認し、スムーズな流れを作る。`
  
3. **フレームグラフ** → `交差点の監視カメラ`
   - `どの車がどのルートを通っているかを記録し、混雑の原因を特定。`
  
4. **FlameScope** → `特定の渋滞ポイントを拡大して分析`
   - `ピンポイントで混雑の原因を探し、解決策を考える。`

**太郎**：「すごく分かりやすいです！ `ビジュアライゼーションを活用すれば、システムのボトルネックを発見しやすくなる` んですね！」

---

### **まとめ**
**花子**：「`CPU のパフォーマンス可視化` には、 `データを視覚的に分析することで、負荷の傾向やボトルネックを直感的に把握できる` メリットがあるわ。」

**太郎**：「ありがとうございます！ `まずはヒートマップとフレームグラフを試してみます！」

# 参考リンク

システムパフォーマンス関連記事の目次

- [【初心者向け】システムパフォーマンス関連まとめ【それぞれ５分で読める】](https://qiita.com/nouernet/items/d3efe67e0f52a92e061d)

システムパフォーマンス関連記事は、以下の書籍を参考に記述しています。

- [［改訂新版］プロのためのLinuxシステム構築・運用技術](https://www.amazon.co.jp/dp/B01LZURAPK)
- [改訂2版 ネットワークエンジニアの教科書](https://www.amazon.co.jp/dp/B07NXQ4TDV)
- [絵で見てわかるシステムパフォーマンスの仕組み](https://www.amazon.co.jp/dp/B00LHFOTF4)
- [詳解 システム・パフォーマンス 第2版](https://www.oreilly.co.jp/books/9784814400072/)
- [入門 モダンLinux](https://www.oreilly.co.jp/books/9784814400218/)
- [Linuxシステム管理](https://www.oreilly.co.jp/books/9784873113463/)
SnowflakeのQuery Historyで<redacted>になっているSQL TEXTが表示されるようにする方法


# 状況

![CleanShot 2025-02-20 at 09.24.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102123/27fc4feb-47ba-4beb-a15f-3c0c7dcd875b.png)

# 対応

```sql
ALTER USER <user_name> SET ENABLE_UNREDACTED_QUERY_SYNTAX_ERROR = TRUE;
```

# 参考

- [Snowflake Documentation / Reference / General Reference / Parameters / ENABLE_UNREDACTED_QUERY_SYNTAX_ERROR](https://docs.snowflake.com/en/sql-reference/parameters#enable-unredacted-query-syntax-error)
- [Snowflake Documentation / Guides / Organizations & Accounts / Accounts / Paramter management / Altering parameters for your account](https://docs.snowflake.com/en/user-guide/admin-account-management#altering-parameters-for-your-account)
【ブラウザArc】素早くピン留めのURLをリセットしたり、ピークのウィンドウを全画面にしたいなど


- `ctrl + w`：タブを閉じれば、ピン留めがリセット
- `ctrl + o`：ピークウィンドウが全画面に変換
- `ctrl + ⌥(option) + ↑/↓`：上下のタブに切り替え
- `ctrl + ⌥(option) + ←/→`：左右のスペースに切り替え
- `shift + リンククリック`：ピークで開く
Databricksのカタログエクスプローラでファイルのプレビューがサポートされました！

これも心待ちにしていた & 地味に嬉しい機能です。

![Screenshot 2025-02-20 at 9.03.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/32227cba-4330-4d48-8a53-a1f90d2789e0.png)

**ボリュームにおけるファイルのプレビュー**

> カタログエクスプローラのボリュームページのモーダルで直接ファイルをプレビューできるようになりました。サポートされるファイルタイプは、画像、テキスト、ログ、マークダウン、JSON、yml、yaml、csvです。

このようにVol.のファイルを一覧している状態で、サポートされているファイルをクリックします。

![Screenshot 2025-02-20 at 9.04.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/62c85511-be5c-4f67-b6aa-e859e8226648.png)

内容が表示されました！

![Screenshot 2025-02-20 at 9.04.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/8cfdfc3f-c33a-45d3-addb-5b33c1b19181.png)

画像の中身も確認できます。

![Screenshot 2025-02-20 at 9.06.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/0e08f9fd-b817-4f68-99b1-d7e200a86494.png)

ご活用ください

### はじめてのDatabricks

[はじめてのDatabricks](https://qiita.com/taka_yayoi/items/8dc72d083edb879a5e5d)

### Databricks無料トライアル

[Databricks無料トライアル](https://databricks.com/jp/try-databricks)
テストが無いならリクエストテストから作ろう

「テストが無いコードはレガシーコードだ」と言われます。十分なカバレッジのユニットテストや E2E テストが用意されていて、それが常時 CI/CD で回っているというのは今時当たり前のことであって、とりたてて特別な環境ということもないでしょう。

しかし、テストが無い、もしくは不十分なコードに出会うことは多々あります。時間が無くてテストコードを書けなかったりとか、前任者から引き継いだらびっくりコードだったりとか、いろいろありますね。

そんなレガシーコードに出会ったとき、まず最初にどこから取り掛かろうかというのがこの記事です。どちらかというと、泥縄的、間に合わせ的なお話ですので、「正しいテストコードの在り方とは」といった話からは乖離しているでしょう。そういう記事をお求めの方は離脱していただくのが幸せかと思います。

なお、私自身がウェブ系の開発者なのでウェブ系を前提に記事を書いてますが、他の分野でも通じる話だと思います。

## 正しいけれど時間のかかり問題がある方法

テストフレームワークを導入して、手近なコードからユニットテストや E2E テストを書いていく方法です。もちろん CI/CD にも組み込みますから、仕組みとしては一気にモダンになります。

仕組みを用意できました。あとはテストコードです。時間があるときにみんなで少しずつテストコードを書いていきましょうとなります。よくある光景だと思います。

これ、手法としては正しいんですけれど、問題はテストが充実するまでの時間です。テストコードが充実して、テストによって障害を事前に防げるのって何年後の話でしょうか。テストコードが充実するまでの数年間、事実上テストなしの状態が継続してしまう問題はどうしましょう。

## 正しくないけどとりあえず役に立つ泥縄的方法

前述の正しいけれど時間のかかる方法に対し、正しくないし泥縄的だけどとりあえず役に立つ方法としてリクエストテストというものが考えられます。ウェブ系開発を前提にしているのでリクエストとレスポンスでテストする想定ですが、これは要するに統合テストのことです。

例えば Qiita の本番環境を対象にリクエストテストを書くとしたら以下のようになるでしょう。

```bash
#!/bin/bash

urls=(
  "https://qiita.com/"
  "https://qiita.com/question-feed"
  "https://qiita.com/official-events"
  "https://qiita.com/official-columns/"
  "https://qiita.com/organizations"
)

for url in "${urls[@]}"; do
  result=$(curl -s -I $url)
  if [[ ! "$result" =~ "HTTP/2 200" ]]; then
    echo "NG: $url"
    echo "======"
    echo "$result"
    echo "======"
  fi
  sleep 0.1
done
```

サービスの主要なページに対して HTTP リクエストを送り、レスポンスのコードが 200 であるかどうかの検証だけを行っているテストです。

こんなテストであれば1時間もあれば用意できますよね。つまり、1時間後にはテストコードが無かったプロダクトにテストコードが出来上がるのです。何年も掛かってしまう正しい方法に比べると、圧倒的に速いですよね。

1時間程度で用意できるテストなのに、テスト対象のページに何か障害があってコケてしまう場合には検出が出来るようになるのです。これって便利ではないですかね。

もちろんリクエストテストには欠点もあります。

* 統合テストなので、テストがこけても障害個所の特定に手間がかかる。
* 簡単に書けるリクエストテストといえど、サービスの全機能を網羅するのは大変。
* ログイン機能や記事投稿機能など、複数ページに渡る挙動はテストしにくい。
* curl コマンドによるテストのため、フロントエンドの動作はテストできない。

欠点はあるのですが、とりあえずテストが無い状態を脱するということは実現できます。そこに価値はあるのではないかと思うのですが、いかがでしょうか。

## まとめ

ということで、正しいけれど時間のかかる方法に対して、正しくないけれど即座に効果を表すリクエストテストという方法の提案でした。

リクエストテストはあくまでも応急処置であって、ユニットテストなどを書かなくていい言い訳ではありません。リクエストテストでとりあえず出血を止めている間に、きちんとしたテストコードを整備していくというのが適切なアプローチではないかと思います。
型 'string | undefined' の引数を型 'SetStateAction' のパラメーターに割り当てることはできません。の解決方法について

# はじめに
下記のようなエラーが表示されました。

:::note warn
型 'string | undefined' の引数を型 'SetStateAction<string | null>' のパラメーターに割り当てることはできません。
  型 'undefined' を型 'SetStateAction<string | null>' に割り当てることはできません。ts(2345)
"Qiita": Unknown word.cSpell
const matchedQiita: string | undefined
:::
下記のように記述していました。
```.ts
export class Users {
 public github_id?: string;
```
```.tsx
 const [userGithub, setUserGithub] = useState<string | null>("");

setUserGithub(matchedGithub); // ユーザーのGithub管理ｽﾃｰﾄにその説明をｾｯﾄ
```

# 解決方法
nullをundefinedに変更
```.tsx
 const [userGithub, setUserGithub] = useState<string | undefined>("");

setUserGithub(matchedGithub); // ユーザーのGithub管理ｽﾃｰﾄにその説明をｾｯﾄ
```


何気なく、stateにnullを記述していましたが、下記の資料を参考にnullとundefinedについて調べることにしました。

# 参考

https://typescriptbook.jp/reference/values-types-variables/undefined-vs-null

# おわりに
undefinedとnullも奥が深いですね。

<br>

[<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3707255/8bfacf61-7d8d-6d27-cb07-98d1f8f27fcd.png"  width=100%>](https://projisou.jp)
VSCodeにESLintとPrettierを入れたときにおこるインデントのエラー解決方法

こんにちは。
駆け出し素人プログラマーのHirotoです。

今回はVSCodeにESLintとPrettierを同時に入れたときに起こったインデントのエラーについてまとめてみました。

まず、私の環境では両方の拡張機能を入れると以下のようにインデントのエラーが表示されるようになってしまいました。。。

![スクリーンショット 2025-02-20 065928.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4015962/b6c8c591-592f-4d0b-9baa-7df943f97a2c.png)

VSCodeのsettings.json（VSCodeのSettingから右上の以下のボタンを押すとでてくるやつ）

![スクリーンショット 2025-02-20 074211.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4015962/23f3c7d4-40e4-477f-9e3f-932d6e6c66bb.png)

は以下です。
```setting.json
{
    "security.workspace.trust.untrustedFiles": "open",
    "python.createEnvironment.trigger": "off",
    "[html]": {
        "editor.defaultFormatter": "vscode.html-language-features"
    },
    "python.defaultInterpreterPath": "C:\\Users\\marks\\scoop\\apps\\python\\3.12.4\\python.exe",
    "editor.formatOnSave": true,
    "editor.tabSize": 2,
    "editor.insertSpaces": true,
    "editor.defaultFormatter": "vscode.html-language-features",
    "editor.formatOnPaste": true,
    "[javascript]": {
        "editor.defaultFormatter": "esbenp.prettier-vscode"
    },
      "eslint.probe": [
    "javascript",
    "javascriptreact",
    "typescript",
    "typescriptreact",
    "vue"
  ],
    "genieai.enableConversationHistory": true,
    "genieai.openai.model": "o1-preview-2024-09-12",
    "genieai.promptPrefix.customPrompt1-enabled": true,
    "genieai.openai.temperature": 1
}
```

注目箇所は以下

```
"[javascript]": {
        "editor.defaultFormatter": "esbenp.prettier-vscode"
    },
```

JavaScriptのフォーマッターをこのようにprettierにしたときにエラーが起こったんですよね。。。

## 解決法
結果的には問題が起こったファイルと同じディレクトリにある.eslintrc.jsというファイルに以下のコードを付け加えることでエラーが出なくなりました。

```.eslintrc.js
  indent: [
    "error",
    4,
    { SwitchCase: 1, ignoredNodes: ["ConditionalExpression *"] },
  ],
```

## 解説（ChatGPTより）
これは ESLint のインデントルールの設定で、以下のような意味があります。

"error"
ルール違反がある場合、エラーとして扱うという意味です。つまり、コードのインデントが指定通りでないとエラーが発生します。

4
基本のインデント幅を 4 スペースに設定しています。すべてのブロックやコード構造は、4 スペースを基準としてインデントされる必要があります。

オプション { SwitchCase: 1, ignoredNodes: ["ConditionalExpression *"] }

SwitchCase: 1
switch 文内の case 句（および default 句）を、switch 本体より 1 レベル深くインデントする設定です。つまり、switch ブロックの内部で、case の開始位置は 4 スペース（1レベル分）ずらされます。

*ignoredNodes: ["ConditionalExpression "]
条件演算子（?:）などの一部のノードに対しては、このインデントルールのチェックを無視する設定です。これにより、条件式内の複雑な構造が ESLint のインデントチェックに引っかからないようになります。

まとめると、この設定は「すべてのコードでインデントは 4 スペースを基本とし、switch 文の case 句は 1 レベル分インデント、ただし条件演算子に関連する部分はインデントチェックの対象外とする」というルールを定めています。

らしいです😁

複雑ですね。。。
Web APIシリーズその2(全5回)：REST APIの弱点

## RESTはきれいだが、設計に苦悩することがあるのも確か！

----
## 正直、今回の話は正解がわかりません。

----
## どれが正解？ - エンティティの部分更新
- 例えばユーザ名のみ変更するAPIは？

```
PUT https://example.com/user/1/
{ "name": "jabara" }
※実装たいへん！
```

```
PATCH https://example.com/user/1/
{ "name": "jabara" }
※実装たいへん！
```

```
PUT https://example.com/user/1/name
"jabara"
```

----
## どれが正解？ - エンティティのリストの同時更新

- 多数のユーザの情報を同時に更新

```
PUT https://example.com/user/1
{ ... }
PUT https://example.com/user/2
{ ... }
PUT https://example.com/user/3
{ ... }
※明らかに非効率！
※トランザクションが分離してしまう！
```

```
PUT https://example.com/user/1,2,3
{
  "user": [
    "id": 1,
    "name": ...
  ],
  ...
}
※メソッドどれにするか迷う
※URL中のID値とボディがずれたらどうする？
```

```
POST https://example.com/user/
{
  "user": [
    "id": 1,
    "name": ...
  ],
  ...
}
※メソッドどれにするか迷う
※UPSERTな動きになるだろう
※この辺が落としどころな気がする
```

----
## どれが正解？ - 特殊な操作

- 既読処理

```
PUT https://example.com/blog/1/article/1
{ "read": true }
```

```
PUT https://example.com/blog/1/article/1/read
※ボディはなし？だとすると未読に戻すには？
```

----
## RESTの弱点

- 何を「リソース」とみなすか、という問題
- 「既読」をリソースとするならば、未読にする操作は以下のように表現できる
```
DELETE https://example.com/blog/1/article/1/read
```

・・・ちょっと非直感的。この表現力の低さがRESTの弱点と言える。

----
## もう１つの弱点 - 複数リソースや複数回の操作の扱い

- 複数のリソースを**トランザクショナル**に更新したい
- 複数回の操作を**トランザクショナル**に実施したい
- RESTではこれを素直に表現できない


----
## もう１つの弱点 - 複数リソースや複数回の操作の扱い

- RESTはシンプルで分かりやすいが、業務的に要件を満たすには不足することがある
- 非汎用的な、特定の画面に特化した仕様にせざるを得ない
  ここは割り切り！


----
## 最後に

- RESTはきれいだがときには現実との折り合いを付ける必要がある
- そうだ、GraphQLにしよう！
【SwiftUI】.onTapGestureでシングルタップ・ダブルタップを共存させる

# はじめに
SwiftUIの`.onTapGesture` を使ったタップ処理の実装について学習したので、備忘録として残します。

---
## 環境
【Xcode】16.2
【iOS】18.2
【macOS】Sequoia 15.3.1

---
## ポイント
- `.onTapGesture` で **シングルタップ** や **ダブルタップ**、またはそれ以上のタップを判定して処理を実行することができる。
- **複数のジェスチャ**（シングルタップとダブルタップなど）を組み合わせることで、1つのボタンに対して複数のタップ処理を実装できる。
- ⚠️ **先に回数の多いジェスチャを記述する必要あり。**

---

## `.onTapGesture` でタップを認識する

```swift
.onTapGesture {
    color = .blue
}
```

で、あらかじめ変数で指定していた **赤色が青色に変わる**。

![スクリーンショット 2025-02-20 7.12.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4004493/67512cbc-6820-4892-9826-faba09c2aa53.png)

---

## ダブルタップを認識する

```swift
.onTapGesture(count: 2) {
    color = .green
}
```

.onTapGesture に (count: 2)で、引数として **2を渡すだけでダブルタップを認識** できる。
3回以上のタップも可能。

![スクリーンショット 2025-02-20 7.17.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4004493/667f29dd-cb75-4b22-8933-9c0155d37f7e.png)

---

## 複数のジェスチャを組み合わせる

```swift
.onTapGesture(count: 2) {
    color = .green
}
.onTapGesture {
    color = .blue
}
```

`.onTapGesture` モディファイアを **2つ適用するだけ** で、シングルタップとダブルタップをそれぞれ認識できる。
ただし...

⚠️ **先に回数の多い `.onTapGesture` を記述する。**
ビューに対して **先に適用されたモディファイアが判定される** ため、
先にシングルタップを記述すると、1回タップされた時点で処理が実行され、ダブルタップの処理が実行されなくなる。

![スクリーンショット 2025-02-20 7.23.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4004493/d48b3b98-34fb-4887-8ef8-be1acd6d8832.png)
PHPで「演算子の優先順位」の動作を確認してみた。

# 概要

PHPで「演算子の優先順位」の動作を確認してみました。
以下のページを参考にしました。

https://www.javadrive.jp/php/num/index3.html

# 実装

以下のファイルを作成しました。

```sample.php
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>PHPテスト</title>
</head>
<body>

<p>PHPのテストです。</p>

<p>
<?php
echo "5 + 3 * 4 = ", 5 + 3 * 4, '<br />';
echo "(5 + 3) * 4 = ", (5 + 3) * 4;
?>
</p>

</body>
</html>
```

以下のコマンドを実行しました。

```
$ php sample.php 
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>PHPテスト</title>
</head>
<body>

<p>PHPのテストです。</p>

<p>
5 + 3 * 4 = 17<br />(5 + 3) * 4 = 32</p>

</body>
</html>
```

# まとめ

何かの役に立てばと。
ライブラリ管理



+ [ファイル ＞ ライブラリ に移動し、新規フォルダを作成し、公開グループに「閲覧者」（参照のみ）権限を割り当てようとしたところ、「ライブラリ管理者」の権限しか選択できません。 ](https://trailhead.salesforce.com/trailblazer-community/feed/0D5KX00000KDips)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/c254fcb1-5b27-4127-acf9-16fa1dd962a2.png)

:::note
以下を確認してみてください。 

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/800cd6dd-dee3-406c-a9b4-65d9d29d2a9d.png)

https://atsudayo.com/library/
:::
偏差値で遊ぶ。(NanoC6 アナステックの0点カットの予定)


参考
----

![o_coq821.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/f29783e9-53cc-44b5-a5b0-5254be70f679.jpeg)

![o_coq822.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/5a78990b-dc11-4975-bb13-5c8262b91158.jpeg)

![o_coq823.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/6bd4ccbb-eda4-4761-be12-c7edd7a91a5e.jpeg)


https://www.seisekiup.net/column/study/2034/


注意
----

- 過去ログをみょ???
- 平方根は、後で考えて倍精度浮動小数点を使ってしまおう。
- 整数演算のため、誤差は、考えない
- M5NanoC6での予定は、未定

その他、もろもろ
----

いろいろ
昨日の夜(20250219)、(元絶滅メディア博物館高円寺)に行ってきたよ!!
スタックチャンを展示して来たよ。
今週(20250220)、来週は、ペースを落として、軽めのをするよ!!!
因みに、昨日(20250219)のアナログジョイスティック無線電送は、4、5時間かかって、
非常にやばかった、原因不明だが、熱とノイズと電力不安定でやられた。
熱ぽいのは、速めに気づいたが、無線が大暴れするとは、思わなかった。(ADCが不安定)
後で有線系のプログラムは、アップするが、有線は、静かな湖面の様に
ピクリともノイズが出なかった。
平坦化は、意味あり。(ある意味、ローパスフィルター)
(アナログジョイスティックの話だよ)

(↓は、ガジェットメイドカフェ　(20250219))

![o_coq825.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/f6e21294-a770-4ca3-8f3c-2f91252bf6e5.jpeg)


目的
----


アナログジョイスティックのゼロ点付近でのカットを行う


図


![o_coq820.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/6b55f3a0-b1c8-405f-a38a-8d1d9541bd6a.jpeg)


工業的な例の図　リベットを打つ時の穴の大きさを知る時に
偏差値を使う、大きすぎると、ぶかぶかになり、
小さすぎると入らない
(リベットとは、裏からハンマーでたたくのだよ!!)
(ねじとは、違うねじの一種、永久的に部材を固定する)

![o_coq819.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/a61be6a4-ae91-46c5-b504-d733eba2df1f.jpeg)


プログラム(風呂グラム?)
----


オンラインコンパイラ


```c++


#include <math.h>

#include <iostream>
using namespace std;
int main(void){
    // Your code here!
    printf("START\n");
    
    int al;
    int sum;
    int ave;
    int die;
    int n;
    int y[] = {NULL,70,40,60,100,40,50};
    
    n = 6;
    sum = 0;
    for(int i = 1;i<=n;i++ ){
        sum = sum + y[i];
    }
    printf("sum = %d\n",sum);
    ave = sum / n;
    printf("ave = %d\n",ave);
    
    die = 0;
    for(int i = 1;i<=n;i++ ){
        al = (y[i] - ave);
        al = al * al;
        die  = die + al;
    }
    die = die / n;
    die = sqrt( die );
    printf("die = %d\n",die);
    printf("...\n",die);
    
    for(int i = 1;i<=n;i++ ){
        al = 10 * (y[i] - ave);
        al = al / die;
        al = al + 50;
        printf("[%d] die = %d\n",i,al);
    }
}



```



```

START
sum = 360
ave = 60
die = 20
...
[1] die = 55
[2] die = 40
[3] die = 50
[4] die = 70
[5] die = 40
[6] die = 45


```
ゼロから始めるセキュリティ生活

# あいさつと注意

:::note 
この先書いていることはゼロから始める方向けの学習ロードマップで技術的な話はないです。
そのためセキュリティ界隈でご活躍されている方にはあまり意味のない記事となっております！
:::

初めまして！
株式会社ギグーのtkmiiiです。

私自身まだまだ未熟で偉大な先人たちの背中を追いかけている身ではありますが
ＩＴ業界における人材不足が大きな話題になる中で、
　・エンジニアとしてのキャリアをスタートされた方
　・異業種からエンジニアになろうかな？と考えてる方
に向け、少しでもセキュリティを身近に感じてもらえたらと思い、今この記事を書いています。

まず、興味を持つことが大事だと思うので音楽学校出身の自分がどうやって興味を持ったかなどを思い出しながら、ゼロから始めるときに学ぶべき基礎的な知識について、極力難しい話はせず、堅苦しくならないように書いていこうと思います。

このシリーズでは二章まで読み終わった後に皆さんがセキュリティマネジメント試験に合格できるようになることを目標に頑張ります！
物語にする需要なければ普通にゴリゴリ書いていきます笑

:::note warn
警告
筆者オタクにつき世界観強めになります。
苦手な方は最後のまとめだけ読むこと推奨
:::


# 序章 
あなたは、とある企業の駆け出しITエンジニア。日々、苦労しながらシステムの安定運用に尽力していますが、最近、サイバー攻撃のニュースを頻繁に目にするようになり、漠然とした不安を抱え始めていました。

そんなある日、とうとう勤務先が大規模なサイバー攻撃を受け、顧客情報が大量に流出するというとんでもない事件が発生。
社会的信用が失墜し、目の前が真っ暗になったあなたは気づくとセキュリティの知識＝強さのRPGの世界に迷い込んでいました。

# 第1章：知識の迷宮に入ったら２秒でやられた件　
この章ではお金を稼ぐためにたまたま入ったダンジョン「知識の迷宮」で飛び交う専門用語の嵐にぶちのめされこのままではお金もまともに稼げないことに気づいたあなたは、まず基礎知識を固めることにします。


### サイバーセキュリティの基礎知識
用語の意味、攻撃の種類、情報セキュリティの原則などを学び、セキュリティの全体像を把握します。
### ネットワークの基礎知識
 TCP/IPモデル、ルーティング、DNSなどの仕組みを理解し、ネットワークの基礎を築きます。
### Linuxコマンド
 Linux環境での作業は必須。基本的なコマンドを習得し、自由自在にLinuxを操れるようにします。

# 第2章：初めてのボス
基礎知識を身につけたあなたは、いよいよフロアボス『セキュマネ』に挑み本格的な旅に出るための準備を始めます。

### ネットワークセキュリティ
 ファイアウォール、VPN、IDS/IPSなどの設定・運用方法を学び、ネットワークの守りを固めます。

### アプリケーションセキュリティ
 OWASP Top 10、脆弱性診断、ペネトレーションテストなどの知識を習得し、Webアプリケーションの弱点を突き止め、対策を講じます。

### 暗号技術
共通鍵暗号方式、公開鍵暗号方式、ハッシュ関数などの仕組みを理解し、情報を暗号化して守ります。

# 第3章：さらなる高みへ 
あなたは、日々の冒険や仲間との鍛錬を通じて、セキュリティに関する経験を積んでいきます。

### セキュリティ運用
 インシデントレスポンス、ログ分析、脆弱性管理などの知識を習得し、セキュリティ対策を継続的に改善します。
### 最新動向のキャッチアップ
 セキュリティ関連のニュースやブログを定期的にチェックし、最新の攻撃手法や対策を学びます。
### 資格取得
 情報処理安全確保支援士試験、CompTIA Security+などの資格取得を目指し、自身のスキルを証明します。
 
# エピローグ：そして、英雄へ
サイバーセキュリティの知識と経験を活かし、会社や社会のセキュリティ強化に貢献。
セキュリティ戦士として、サイバー空間の平和を守る英雄として活躍します。


# まとめ
経験談ですが
自分がゴリゴリの文系出身者なのもあってエンジニアになった当初技術書はあまり受け付けませんでした！
なので、苦手克服のための手段として自身で擬人化したことを思い出して物語風にしました。
もちろんこれが万人受けする方法だとは思っておりません。

まずは皆さん自分に合う学習方法があるはずなのでそれを見つけましょう。



さて、それぞれのステップにおいて学習するべき知識について簡単にまとめてみました。

■基礎知識編（ごく一般的な知識）

・サイバーセキュリティの基礎知識
用語の意味、攻撃の種類、情報セキュリティの原則などを学び、セキュリティの全体像を把握。
・ネットワークの基礎知識
 TCP/IPモデル、ルーティング、DNSなどの仕組みを理解し、ネットワーク知識の基礎を築く。
・Linuxコマンド
 Linux環境での作業は必須。基本的なコマンドを習得し、自由自在にLinuxを操れるようにします。

■基本知識編（少し進んだ知識）
・ネットワークセキュリティ
 ファイアウォール、VPN、IDS/IPSなどの設定・運用方法を学び、守備力を上げる。

・アプリケーションセキュリティ
 OWASP Top 10、脆弱性診断、ペネトレーションテストなどの知識を習得し、Webアプリケーションの弱点を突き止め、対策を講じる知識を養う。

・暗号技術
共通鍵暗号方式、公開鍵暗号方式、ハッシュ関数などの仕組みを理解し、情報を暗号化して守る力をつける。


■高み編（そのほか役立つ知識）
・セキュリティ運用
 インシデントレスポンス、ログ分析、脆弱性管理などの知識を習得し、セキュリティ対策を継続的に改善していける人材になる。
・最新動向のキャッチアップ
 セキュリティ関連のニュースやブログを定期的にチェックし、最新の攻撃手法や対策を学び応用する力をつける。
・資格取得
 情報処理安全確保支援士試験、CompTIA Security+などの資格取得を目指し、自身のスキルを証明する。

以上、がとりあえずどこでも通用する知識かと思います

こうして長々と書いてきましたが
一番大事なのはどれだけ自分が興味を持てる方法で勉強ができるかどうかです

自分だけの方法を編み出して現実世界でも俺だけレベルアップしちゃいましょう!
ChatGPT o3 mini-highとFirebaseとStripeを使って月額課金制ゲームをつくる（１）

はじめまして。

最近ChatGPTを使ってインディーズゲーム制作に目覚めたHirotoと申します。

今回はChatGPT o3 mini-highとFirebase,Stripeを使って、サーバーを自分でレンタルまたは購入することなく月額課金制オンラインRPGを作った話をしようと思います。

できたゲームは以下
https://codequest-e825e.web.app/
（まだ課金はテスト中なのとゲーム内容はかすっかす）

今回から躓いた点などをQiitaで共有していきたいと思います。

## ・躓いた点１
・Firebaseのメール認証機能がうまく動作しない

基本的にChatGPTにすべてを聞きながらFirebaseのデフォルト設定でログイン画面を追加したのですが、どうもうまくいきませんでした。

英語の文献を探しまくった結果、どうも以下の「メール列挙保護（推奨）」のチェック項目を外すといいそうです。

![スクリーンショット 2025-02-20 061738.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4015962/24662a26-27a2-4038-b18e-817bb974cb80.png)

これで普通のログインができるようになりました！

でも、推奨って書いてあるけど大丈夫？って話ですが、メール列挙保護って何？って方は以下の説明を読んでください。

メール列挙保護とは（以下ChatGPT）
>「メール列挙保護」とは、ウェブサイトやオンラインサービスにおいて、攻撃者がシステム内の有効なメールアドレスを自動的または体系的に抽出（列挙）するのを防ぐためのセキュリティ対策のことです。
>
>主なポイント
メールアドレスの保護:
ユーザーのメールアドレスが悪意のある第三者に大量に収集されると、スパムメールの送信やフィッシング詐欺などのリスクが高まります。メール列挙保護は、こうしたリスクを低減するための重要な手法です。
>
>自動化ツール対策:
ボットやスクリプトによる自動化されたアクセスから、メールアドレスを抽出されるのを防止するため、CAPTCHA（画像認証）やレートリミッティング（一定期間内のアクセス回数制限）などの技術が使用されることが一般的です。
>
>エラーメッセージの工夫:
例えば、ユーザー登録やパスワード再設定時に、「入力されたメールアドレスは存在しません」と明確に返答するのではなく、常に同じ曖昧なメッセージを返すことで、攻撃者が有効なメールアドレスを推測できないようにする方法も取られます。
>
>このように、メール列挙保護は、個人情報の漏洩を防ぎ、ユーザーのプライバシーとセキュリティを確保するための重要な対策となっています。

つまりはログイン時のエラーメッセージを元にして有効なメールアドレスを推測されるのを防ごうってわけですね！

でも、現状うまく機能していないのでOFFにしてOKです。（しらんけど）


## ・躓いた点２
### Firebase側とStripeの連携が難しい！！

２日かけてChatGPTと戦いましたが、FirebaseのFunctions機能を使うとき、バージョン１を使わないとうまくいかないことがありました。

具体的にはもう忘れましたがよくわからんエラーが出るときは以下のコードでFirebaseのV1を使うようにするとうまくいくことがあります。

```javascript:index.js
// functions/index.js
const functions = require("firebase-functions/v1");
```


## まとめ

・Firebaseのメール列挙保護を切る
・Functionsを使ってよくわからんエラーが出るときはV1を使う


他にも色々躓きましたがだいたいはChatGPT先生がうまくやってくれました。

それではクソゲーをお楽しみください。
[【古き良きテキストベースRPG　コードクエスト】](https://codequest-e825e.web.app/)
JSDoc標準を用いたGASのコメント記法

## 経験者向け

GASはECMAScript標準に基づいており、広義のJavaScriptファミリーに属する一種のJavaScriptであるため、当然JSDocも利用可能です。私個人はGASを用いて、主にシンプルで定例的なGoogle Sheetsの処理を行っているため、この程度のニーズであれば、TypeScriptやTSDocを導入する必要はないと感じています。もし、チームや企業で大規模な要件に対応するためにGASを利用されている方がいれば、TSの導入も興味深いところですが、私の現在のニーズでは、JSDocの方が軽量で十分です。

また、私は基本的に自分一人で開発を行っており、チームでGASを共同開発した経験がないため、現時点ではJSDocツールを使ってAPIドキュメントを生成する必要はなく、主に自分自身のためのコメントとして利用しています。特に多くのヘルパー関数に対して有効です。

例えば：

```js
/**
 * カラム番号を対応するカラム文字に変換します。
 *
 * @param {number} columnNumber - 変換するカラム番号（1始まりのインデックス）。
 * @return {string} - 対応するカラム文字（例：1 → "A", 27 → "AA"）。
 */
function getColumnLetter(columnNumber) {
  let letter = "";
  while (columnNumber > 0) {
    let remainder = (columnNumber - 1) % 26;
    letter = String.fromCharCode(65 + remainder) + letter;
    columnNumber = Math.floor((columnNumber - 1) / 26);
  }
  return letter;
}
```

もちろん、現代のgenAI時代において、私はgenAIで生成したJSDocを元に自分で調整を行っています。最近、リファクタリングや新たな機能追加の際に古いコードを再利用する必要が生じたとき、以前のコードを再度読み返す手間を大幅に省いてくれています。

## JSDocを知らない方へ

もしあなたが開発者でありながらJSDocを知らない場合、それは既にTypeScriptを使用しているためかもしれません。JSDocによる型注釈は冗長な面があり、TypeScriptほど強力ではないため、TypeScript公式ではTSDocが推奨されています。もしあなたが開発者でなく、私と同様に何らかのコードを扱う必要があるのであれば、以下に簡単な説明を記します。

JSDocはJavaScriptのコメント標準であり、先述のTSDocのように公式の標準サポートはありません（私の知る限り、TSDocはMicrosoftが主導するコミュニティによって推進されている準標準です）が、JSDocツールを利用してAPIドキュメントを自動生成するため、基本的には大きな差異は生じません。（例えば、Airbnbのスタイルガイドは説明と変数の間に空行を強制しない一方、ESLintのデフォルト設定では空行が必須となっています。）

「/\*\*」という記法は、JSDocツールがこのコメントがJSDocであると認識するための重要なフォーマットです。この標準により、共同開発者やAPI利用者は、関数の機能、引数の型、返り値の型を迅速に理解することが可能となります。

JSDocの公式ドキュメントを通じて文法をさらに詳しく学ぶこともできますし、もしあなたがロウコード開発者であれば、文法を詳細に理解する手間を省き、直接genAIにJSDoc標準に従ったコメントの付与を依頼するのも効率的な方法です。

JSDocの出力ツールとしては、公式のもの（<https://jsdoc.app/>）のほかに、ESDoc、Documentation.js、Docmaなどがあり、チーム全体の好みに合わせて選択することができます。
JavaScriptのメカニズム(実行環境)

# 参考
[【JS】ガチで学びたい人のためのJavaScriptメカニズム](https://www.udemy.com/course/javascript-essence)

# あらすじ
現場でrailsを触ってlaravelを触って今はtypescriptとreact-routerで実装することが多くなってきたが、今までJavascriptをがっつり勉強してなかったので復習も兼ねて上記講座を受けてみようと思った。

とある先輩から「エンジニアじゃない人間が聞いてもわかる程度の説明にしろ」という言葉をいただいたので、できるだけ頑張る。

# ブラウザとJavaScriptの関係
ブラウザには以下の要素がある
- UserInterfaceーuserに見える部分
- DataStorageーデータを保存する場所
- RenderingEnginーレンダリング（画面生成）の処理
- JavaScriptEnginーJavaScriptが動く部分

JavaScriptEnginでJSが動く。ChromeはV8というエンジン。
エンジンの中でJavaScriptやWebAPIsが動く。V8はオープンソースなのでどの環境でも使える。これを**UniversalJavaScript**という。
ちなみにfirefox等ブラウザごとに個体差があるので注意。

# JavaScriptコードが実行されるまで
JavaScriptはJavaScriptエンジン内で処理が行われる。
具体的にはエンジンの中、実行前に３つ要素が準備されている。
- 開発コード（自分で作ったコード）
- グローバルオブジェクト（Windowオブジェクト、中にWebAPIsが含まれる）
- this

thisに関して、thisはオブジェクトの参照を意味するもの。コンテキスト（コードの実行場所）によって取得できる値が変わる。初期値はWindowオブジェクト。

グローバルオブジェクトはJSエンジンによって生成される**コード内のどこからでもアクセスできるオブジェクト**

大事なのは**ブラウザのグローバルオブジェクトはWindowオブジェクトとなる**こと

# 実行コンテキストについて
プログラミングに関して、コンテキストとは**コードを実行する際の文脈、状況**である。
前述の開発コード、グローバルオブジェクト、thisをまとめたものが実行コンテキストと呼ばれる。
現在は主に以下のコンテキストがある
- グローバルコンテキスト
- 関数コンテキスト
（moduleコンテキストもあるが今はこの２つを覚えておく。evalコンテキストはパス）

# グローバルコンテキストの中身
- 実行中（宣言した）のコンテキスト内の変数、関数
- グローバルオブジェクト
- this

以下のような状況がグローバルコンテキストを使用してると言える
```javascript
const a = 0;
function b(){}

console.log(a);
b();
```

# 関数コンテキストの中身
- 実行中（宣言した）のコンテキスト内の変数、関数
- arguments
- (super)
- this
- 外部変数

以下のような状況が関数コンテキスト内の宣言
```javascript
const a = 0;
function b(){
    console.log(this, arguments, a)
}

b();

// 出力結果
// window //グローバルオブジェクト
// argumets //arguments
// 0 //外部変数
```

# コールスタックについて
コールスタックとは、実行中のコードが辿ってきたコンテキストの積み重ね
```javascript
function a(){
}

function b(){
    a();
}

function c(){
    b();
}

c();
```

chromeの開発者ツールでsourceにアクセスし、ブレイクポイントを決めてリロードすると動きが見られる。c()の時点で最初にCallStack内でanonymousが出るがこれはグローバルコンテキストの意味。進めていくとc->b->aとなり、aから消えていく。これを**後入れ先だし**という。

# ホイスティング（hoisting）とは
コンテキスト内で宣言した変数や関数の定義をコード実行前にメモリーへ配置すること。

```javascript
function a(){
    console.log('a is called');
}

a();
```

このコードは
```javascript
a();

function a(){
    console.log('a is called');
}
```
でも動く。関数や変数は実行前にメモリへ保存されるため、コード上は後ろに書いても関数が存在している扱いになる。

# 各変数はどのような扱いになるか
### varの場合
```javascript
console.log(b);
var b = 0;

//出力結果
// undefined
```
実はこれでも動く。ただし出力結果はundefinedになる。
なぜこうなるかというと内部的にはこのような形になっている。
```javascript
var = b
console.log(b);
b = 0
```
`var`という値をメモリに確保して、undefinedをセットしてるからundefinedが出る仕組み。そういうふうになっている。

### let、constの場合
```javascript
console.log(b);
let b = 0; //またはconst

//出力結果
// ReferenceError
```
`let`や`const`はundefinedによる初期値のセットが行われない

### 発展系
```javascript
a();

function a(){
    d();
    function d(){
        console.log('d is called')
    }
}

// 出力結果
// d is called
// a is called
```
関数に関してはすでにメモリに確保されているので前に宣言していても呼べる

# 関数式
```javascript
a();

const a = function a(){
    d();
    function d(){
        console.log('d is called')
    }
}

// 出力結果
// ReferenceError
```
`const`宣言で関数を定義できる。それを**関数式**という。この場合`const`扱いになるのでエラーになる。

基本は巻き上げ実装がよろしくないと思うので変数、関数はconstで実装しようって印象です。
kintoneのプラグインの新しい開発方式を試してみる

# はじめに
いつからか、kintoneの開発中の新機能として「プラグインの新しい開発方式」が追加されています。
実運用に乗ってくるのがいつかは完全に不明ですが、（パートナー企業等には、もしかしたら告知等あるのかもしれませんが）乗り遅れないように触ってみようと思います。

# 0. 「プラグインの新しい開発方式」とは
従来のプラグインだと、プラグインの処理もkintone本体と同じ環境上で動作していたものを、プラグインごとにiframe上で動作させることで、独立した環境を持たせることができるようです。

以下のようなメリットが挙げられています。
参考：[プラグインの新しい開発方式](https://cybozu.dev/ja/kintone/docs/api-lab/new-plugin)
> ・プラグインの実行環境分離により、他プラグインやカスタマイズJSの影響を受けなくなり、安定して動作するプラグインの開発・提供が可能
・プラグインの利用者が権限を確認できるので、より安全なプラグインの導入が可能

確かに、サードパーティ製のプラグインはコードが確認できないためセキュリティの不安点や、現状の処理との競合もあり、運用中のアプリに乗せることへの抵抗感もありましたので、良いことのように思えます。

# 1. サンプルプラグインで新しい開発方式を試す
下記ページを参考に実際に新しい開発方式でのプラグインを試してみました。
実施内容は、参考先に記載されておりますので、ここでは省略します。
参考：[サンプルプラグインで新しい開発方式を試す](https://cybozu.dev/ja/kintone/docs/api-lab/new-plugin/sample-plugin)

参考ページ内に、気になる一文がありました。
> 新しい開発方式のプラグインを適用したアプリでは、従来のプラグインは動作しません。また、新しい開発方式のプラグインをアプリに適用すると、 [フロントエンド基盤の刷新](https://kintone.cybozu.co.jp/update/main/2022-08.html) の取組の一環として、開発中の新しいレコード一覧画面に切り替わります。

同じアプリに、従来のプラグインとの併用ができないような記載に読めます。それだと、正直かなり不便だと思うので、以下のcybozuが公開しているサンプルプラグインを同じアプリに適用して確認してみました。
* 併用：[自動採番プラグイン](https://cybozu.dev/ja/id/3f929d76d0c5d73928c0412a/)
レコード登録のタイミングで、自動採番を行うプラグイン。
動作を確認したが、問題なく自動採番が行われることを確認できました。
* 併用：[いいねプラグイン](https://cybozu.dev/ja/kintone/tips/development/plugins/sample-plugin/like-plugin/)
一覧画面で、レコードに対して「いいね」をつけられるようになるプラグイン。
動作を確認したが、一覧画面での「いいね」機能がなくなっていました。
原因が、
  * 上記引用の「新しい開発方式のプラグインを適用したアプリでは、従来のプラグインは動作しません。」というのが理由なのか、
  * 新しい開発方式のサンプルプラグインを適用すると、一覧画面のデザインが変わったので、それが影響しているのか

  は分からないので、実際に、新しい開発方式でサンプルプラグインを作成し、挙動の調査を行います。
# 2.新しい開発方式でプラグインを作成する
下記ページを参考に実際に新しい開発方式でのプラグイン作成を試してみました。
参考：[新しい開発方式でプラグインを作成する](https://cybozu.dev/ja/id/f9c32a713f202dfe0774750a/)
細かいmanifest.jsonの設定が、既存のプラグインの作成方法とは異なるくらいだったため、今までプラグインを作成したことがあれば、すんなり作成できると思います。
今までの参考ページや、[リファレンス](https://cybozu.dev/ja/id/a242646912ccb2302b14552d/)を確認していたところ、
* 一覧画面にiframeが追加されそこに独立した環境の画面が作れる
* 通常のJSや今までのプラグインのように、kintoneイベントに対して処理を追加するようなことはできないのかな？

という印象だったため、**既存のプラグインの用途とは大きく異なる**ものになると思います。
また、[1. サンプルプラグインで新しい開発方式を試す](#1-サンプルプラグインで新しい開発方式を試す)で気になった、「従来のプラグインとの併用ができない」という内容だが、おそらくは一覧画面のDOMが大きく変わっていたため、一覧画面に関するものは併用ができないということかと思います。（予想の範疇を出ないが、、、）
# まとめ
kintoneの「プラグインの新しい開発方式」を触ってみたが、まだ**少し早かった**かなという印象です。
参考ページにも、
> このページで説明している新方式は開発検討中の実験的な機能です。随時、機能の追加を予定しています。また今後、大きな仕様変更や機能自体を削除する可能性もあります。

と書かれていますので、もう少し確度の高そうなアナウンスがcybozuから出てから触ってみるので良いかと思います。

また、新しいプラグインを適応した際の一覧画面のUIが大きく異なる点を見ると、ずっと言われている「kintoneはUIがいまいち、、」という点を直そうとしていると思うので、そこは期待しつつ、ただ、サードパーティのプラグインが増えすぎていて、そこへの影響を考慮しつつと、なかなか動きにくそうだなと思いつつ、今後のkintoneの進展に期待し締めさせていただきます。
個人的備忘録：ECS環境で.envが読み込めない？GO_ENV=prodを設定したら案外いけた件

## はじめに

ECS環境で `.env` ファイルの読み込みエラーが発生し、アプリケーションの動作に支障が出ていました。

本記事では、その原因と `GO_ENV=prod` を追加することでエラーを解消する方法について説明します。

## 変更の背景

ECS環境で `.env` ファイルが読み込めず、以下のエラーが発生していました。

```
.envファイルが読み込めません: open .env: no such file or directory
```

この問題の原因は、ECS環境で `GO_ENV` の設定が未定義または `dev` のままだったことです。

本来、`GO_ENV=prod` にすることで `.env` の読み込みを回避し、環境変数を適切に適用する必要があります。そのため、ECSのタスク定義 (`aws_ecs_task_definition.main`) に `GO_ENV=prod` を追加しました。

## 変更前のECSタスク定義

```json
"environment": [
  {
    "name": "MYSQL_USER",
    "value": "myuser"
  },
  {
    "name": "MYSQL_PW",
    "value": "${jsondecode(data.aws_secretsmanager_secret_version.rds_password_v5.secret_string)[\"password\"]}"
  },
  {
    "name": "MYSQL_HOST",
    "value": "${aws_db_instance.rds_instance.endpoint}"
  },
  {
    "name": "MYSQL_PORT",
    "value": "3306"
  },
  {
    "name": "MYSQL_DB",
    "value": "mydatabase"
  }
]
```

この状態では `GO_ENV` が設定されておらず、アプリケーションが `.env` の読み込みを試みてエラーになっていました。

## 変更後のECSタスク定義

`GO_ENV=prod` を追加し、環境変数の適用を強制しました。

```json
"environment": [
  {
    "name": "GO_ENV",
    "value": "prod"
  },
  {
    "name": "MYSQL_USER",
    "value": "myuser"
  },
  {
    "name": "MYSQL_PW",
    "value": "${jsondecode(data.aws_secretsmanager_secret_version.rds_password_v5.secret_string)[\"password\"]}"
  },
  {
    "name": "MYSQL_HOST",
    "value": "${aws_db_instance.rds_instance.endpoint}"
  },
  {
    "name": "MYSQL_PORT",
    "value": "3306"
  },
  {
    "name": "MYSQL_DB",
    "value": "mydatabase"
  }
]
```

これにより、ECS環境で `GO_ENV=prod` が適用され、`.env` の読み込みが不要になります。

## 適用方法

### 1. Terraformの変更を適用

Terraformの設定を変更した後、以下のコマンドを実行して適用します。

```sh
terraform init
terraform apply -auto-approve
```

### 2. ECSのタスクを再デプロイ

Terraformの適用後、ECSのサービスを強制的に再デプロイし、新しい環境変数が適用されるようにします。

```sh
aws ecs update-service --cluster my-ecs-cluster --service my-ecs-service --force-new-deployment
```

## 変更後の影響

- **ECS環境で `.env` が不要になり、エラーが解消**
- **アプリケーションが正しく環境変数を使用するようになる**
- **デプロイ時の安定性向上（開発環境と本番環境の分離が明確になる）**

## まとめ

ECS環境で `.env` ファイルが読み込めないエラーの原因は、環境変数 `GO_ENV` が未定義だったことでした。タスク定義に `GO_ENV=prod` を追加することで `.env` の依存をなくし、環境変数のみで動作するように修正しました。


Terraformの適用とECSの再デプロイを行うことで、安定したデプロイ環境を実現できます。
個人的備忘録：ECSデプロイ時の.env問題とRDS接続エラーを解決した話のポイントをまとめてみた

## はじめに
本記事では、ECS環境で発生した `.env` ファイルの読み込みエラーと、RDSのホスト名が解決できないエラーの原因と解決策について解説します。

現在発生しているエラーは以下の2つです。

## 1. `.env` ファイルが読み込めない

```
2025/02/19 03:10:40 .envファイルが読み込めません: open .env: no such file or directory
```

### 原因
- `db.go` の `NewDB()` 内で `.env` を読み込もうとしている。
- ECS環境では `.env` ファイルが存在しないため、エラーになる。

### 修正方法
#### `db.go` で `.env` の読み込み処理を削除
```go
if os.Getenv("GO_ENV") == "dev" {
    err := godotenv.Load()
    if err != nil {
        log.Fatal(err)
    }
}
```
⬇ **この部分を削除**

```go
// `GO_ENV` に関係なく `.env` を読み込まないように修正
```

---

## 2. RDSのホスト名が解決できない

```
dial tcp: lookup terraform-2025021903052566110000000b.crq4wsi04dj7.ap-northeast-1.rds.amazonaws.com:3306:3306: no such host
```

### 原因
- RDSのエンドポイントが誤っている、またはRDSが作成されていない。
- ECSタスクがRDSのDNSを解決できない。
- RDSのセキュリティグループでECSのアクセスが許可されていない。

### 修正方法
#### **1. RDSのエンドポイントを確認**
ECSから **RDSのエンドポイントが正しいか確認** します。

```sh
aws rds describe-db-instances --region ap-northeast-1 --query 'DBInstances[*].[DBInstanceIdentifier,DBInstanceStatus,Endpoint.Address]'
```
- **ステータスが `available` ならOK**
- **エンドポイントの値を `MYSQL_HOST` に設定しているか確認**

もしエンドポイントが異なっていたら、ECSタスク定義で `MYSQL_HOST` を修正して再デプロイ。

#### **2. ECSのDNS設定を確認**
ECSコンテナから **DNSが正しく解決できるか確認** します。

```sh
aws ecs execute-command --cluster my-ecs-cluster --task タスクID --container my-app-repo --command "/bin/sh" --interactive
```
その後、コンテナ内で以下を実行：

```sh
nslookup terraform-2025021903052566110000000b.crq4wsi04dj7.ap-northeast-1.rds.amazonaws.com
```

- **エラーになる場合 → VPCのDNS設定が無効になっている可能性**
  
  VPCの `EnableDnsHostnames` と `EnableDnsSupport` を確認：
  ```sh
  aws ec2 describe-vpcs --region ap-northeast-1 --query 'Vpcs[*].[VpcId,EnableDnsHostnames,EnableDnsSupport]'
  ```
  
  - **`false` なら修正**
  ```hcl
  resource "aws_vpc" "main" {
    enable_dns_support   = true
    enable_dns_hostnames = true
  }
  ```

#### **3. RDSのセキュリティグループを修正**
ECSがRDSにアクセスできるように、RDSのセキュリティグループ (`rds_sg`) にECSのセキュリティグループ (`ecs_sg`) を許可する。

```hcl
resource "aws_security_group_rule" "allow_ecs_to_rds" {
  type                     = "ingress"
  from_port                = 3306
  to_port                  = 3306
  protocol                 = "tcp"
  security_group_id        = aws_security_group.rds_sg.id
  source_security_group_id = aws_security_group.ecs_sg.id
}
```
Terraformを適用：

```sh
terraform apply -auto-approve
```

---

## 最終的な修正ポイント

| エラー | 修正方法 |
|------|------|
| `.env` ファイルがないエラー | `db.go` から `.env` の読み込み処理を削除 |
| RDSのホストが解決できない | RDSのエンドポイントを確認 & `MYSQL_HOST` を更新 |
| ECSがRDSに接続できない | DNS設定 (`EnableDnsHostnames` / `EnableDnsSupport`) を有効化 |
| RDSのセキュリティグループ設定ミス | ECSのセキュリティグループを許可 (`aws_security_group_rule`) |

## まとめ
ECS環境で `.env` ファイルの読み込みエラーと、RDSのホスト名解決エラーが発生しました。それぞれの原因を分析し、`.env` の読み込み処理の削除、RDSのエンドポイント確認、DNS設定の有効化、セキュリティグループの調整を行うことで解決できます。

### 事象解決のために、実施したこと
1. **`db.go` から `.env` の読み込み処理を削除**
2. **ECSタスクの `MYSQL_HOST` に正しいRDSエンドポイントを設定**
3. **ECSコンテナから `nslookup` でRDSのホスト名が解決できるか確認**
4. **RDSのセキュリティグループにECSを許可**
5. **Terraformを適用し、ECSを強制再デプロイ**

```sh
terraform apply -auto-approve
aws ecs update-service --cluster my-ecs-cluster --service my-ecs-service --force-new-deployment
```
個人的備忘録：Goアプリで発生した「db.NewDB() (no value) used as value」エラーの原因と解決方法

## **はじめに**  
Go で開発を進めていると、関数の戻り値に関するエラーに遭遇することがあります。その中でも、`(no value) used as value` というエラーは、**関数の戻り値を期待しているのに実際には何も返していない場合** に発生します。  

本記事では、**ECS 環境で Go アプリをデプロイした際に発生した `db.NewDB()` に関するエラー** について、原因と解決策を整理しました。 

## エラー内容

Goのプログラムをビルドまたは実行すると、以下のようなエラーが発生することがあります。

```
router/router.go:19:8: db.NewDB() (no value) used as value
```

このエラーは、Goの関数 `db.NewDB()` の戻り値がないのに、戻り値を使おうとした場合に発生します。

## エラーの発生原因

エラーの原因は、`NewDB()` 関数の定義と、それを呼び出す側 (`router.go` など) のコードの不整合です。

### 誤ったコード

#### `db.go`
```go
package db

import (
	"fmt"
	"log"
	"os"

	"gorm.io/driver/mysql"
	"gorm.io/gorm"
)

var DB *gorm.DB // グローバルな DB 変数

func NewDB() {  // ← 戻り値がない
	url := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&parseTime=True",
		os.Getenv("MYSQL_USER"),
		os.Getenv("MYSQL_PW"),
		os.Getenv("MYSQL_HOST"),
		os.Getenv("MYSQL_PORT"),
		os.Getenv("MYSQL_DB"))

	var err error
	DB, err = gorm.Open(mysql.Open(url), &gorm.Config{})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("Connected")
}
```

#### `router.go`
```go
package router

import (
	"skill-typing-back/db"
)

func SetupRouter() {
	dbInstance := db.NewDB() // エラー発生！ NewDB() に戻り値がないのに受け取っている
}
```

このように、`NewDB()` は `*gorm.DB` を返さないのに、`dbInstance := db.NewDB()` で戻り値を受け取ろうとするとエラーになります。

## 解決方法

### 方法 1: `router.go` の呼び出しを修正

最も簡単な修正方法は、`NewDB()` の戻り値を受け取らないようにすることです。

#### 修正後の `router.go`
```go
package router

import (
	"skill-typing-back/db"
)

func SetupRouter() {
	db.NewDB() // 戻り値を受け取らずに実行
}
```

これで、戻り値を期待しない形になるため、エラーが解消されます。

### 方法 2: `NewDB()` に戻り値を追加

もし `NewDB()` の戻り値を使いたい場合は、関数の定義を修正して戻り値 `*gorm.DB` を追加する方法もあります。

#### 修正後の `db.go`
```go
func NewDB() *gorm.DB {  // 戻り値を追加
	url := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&parseTime=True",
		os.Getenv("MYSQL_USER"),
		os.Getenv("MYSQL_PW"),
		os.Getenv("MYSQL_HOST"),
		os.Getenv("MYSQL_PORT"),
		os.Getenv("MYSQL_DB"))

	db, err := gorm.Open(mysql.Open(url), &gorm.Config{})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("Connected")
	return db  // DB インスタンスを返す
}
```

#### 修正後の `router.go`
```go
package router

import (
	"skill-typing-back/db"
)

func SetupRouter() *echo.Echo {

	e := echo.New()

	// DBコネクション作成（戻り値を受け取らずに実行）
	db.NewDB()
	// DBリポジトリ初期化（db.GetDB() を使う）
	repo := repository.New(db.GetDB())
    ・・・
    ・・・
}
```

この方法を使えば、`NewDB()` の戻り値を DBコネクションとして利用できるようになります。

## どちらの方法を選ぶべきか？

| 方法 | 適用ケース | メリット |
|------|------|------|
| 方法 1: `NewDB()` の戻り値を受け取らない | グローバル変数 `DB` を利用する | 修正が簡単・コードがシンプル |
| 方法 2: `NewDB()` に戻り値を追加する | DBコネクションを明示的に取得・管理したい | 柔軟なDB管理が可能 |

基本的には、方法 1 の修正（戻り値を受け取らない）で十分ですが、`NewDB()` の戻り値を明示的に使いたい場合は 方法 2 を選ぶとよいでしょう。

## まとめ

- `"(no value) used as value"` エラーは、関数の戻り値がないのに受け取ろうとすると発生する。
- 最も簡単な修正方法は、`db.NewDB()` の戻り値を受け取らないようにすること。
- より柔軟にするなら、`NewDB()` に `*gorm.DB` の戻り値を追加する方法もある。

このエラーに遭遇したら、「関数の戻り値があるかどうか」を確認し、適切な方法で修正してみてください。
開発者向けのAI検索エンジン、Phindの進化が最高すぎた件。


## 背景

個人的にプチバズした、開発者向けのAI検索エンジン[Phind](https://www.phind.com/)についての記事。
（皆様いいねやストックありがとうございます）

https://qiita.com/miu-P/items/078dd0f90952110ecbc8

さて、この記事を書いていた当初はすごくPhindを頼りにしていたのですが、それ以降はChatGPTを使っていたり、最近ではClaudeをメインで使うようになりました。
そして、[DeepSeek](https://chat.deepseek.com/)や[Qwen](https://chat.qwenlm.ai/)など次々にすごいモデルも出てきているため、正直全くと言っていいほどPhindを触ることがありませんでした。

つい先日偶然思い立ち、Phindって何かアップデートがされてるのかな〜と軽い気持ちで最新状況を調べたところ、直近（2025年2月）で**Phind 2**がリリースされているとわかりました。

https://gigazine.net/news/20250214-phind-2/

とりあえず触ってみると、そのアップデートによる進化が最高だったので早速シェアしたいと思います。

## アップデート内容

それでは早速アップデート内容についてですが、

* 視覚的な回答機能
* マルチステップでの推論機能

がこれまでとの主な違いとなりそうです。

言葉で説明するより次のスクショなどをみていただけたらその凄さは一目瞭然だと思います。そして、ぜひすぐに触ってみてください。

### 視覚的な回答機能

概念図やフロー図、シーケンス図など視覚的な回答を適宜生成してくれます。
色分けがされていたり、視覚的に関係性が整理されているのでめちゃくちゃいいですね。

> MCPについて聞いたときの回答

![スクリーンショット 2025-02-20 1.24.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2259490/19f702bd-ecfc-4dcd-bc7e-2bdc301666f1.png)

> kubectlについて聞いたときの回答

![スクリーンショット 2025-02-20 1.26.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2259490/1c39bc5e-8a2a-4f1a-9337-8f25c162c827.png)


### マルチステップでの推論機能

以下のような感じでいくつか推論もしてくれます。
ユーザー視点で欲しそうな情報が何か考えてくれているようです。

![スクリーンショット 2025-02-20 1.26.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2259490/7b79c55a-306c-43fa-815e-cd52164cab11.png)


### その他

全体的にUIがブラッシュアップされていましたが、個人的に刺さったのはこのモーダルでurlの参照先が見られる機能です。
ホバーすれば出てくるので、タブの移動もなくなりありがたいです。

![スクリーンショット 2025-02-20 1.18.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2259490/58ad524d-17dc-4c4c-ba11-b430b49cd39f.png)


## まとめ

視覚的にわかりやすい回答を生成してくれるので、**新しい技術や概念についてキャッチアップする際の頭の整理**にとても良さそうだと思いました。

また、全体的に推論による検索結果の質の向上がすごいと感じました。
これだけわかりやすく組み立てて教えてくれると先生いらずですね。

それでは、最後までお読みいただきありがとうございました！
個人的備忘録：ローカル環境とECSデプロイのつまずきから、godotenv.Load() について本気で調べてまとめた

## はじめに

Go 言語で環境変数を管理する際、`.env` ファイルを使うことがあります。その `.env` を読み込むための便利なライブラリが `github.com/joho/godotenv` です。

:::note info
**しかし、適切に設定しないと「`.env` ファイルが読み込めません」というエラーが発生することがあります。**
:::

本記事では、`godotenv.Load()` の基本的な使い方と、実際に発生したエラーの原因と解決方法について解説します。

## godotenv.Load() の基本的な使い方

### インストール
まず、`godotenv` を Go モジュールに追加します。

```sh
go get github.com/joho/godotenv
```

### `.env` ファイルの作成
`.env` ファイルに環境変数を定義します。

```
MYSQL_USER=myuser
MYSQL_PW=mypassword
MYSQL_HOST=localhost
MYSQL_PORT=3306
MYSQL_DB=mydatabase
```

### Go コードで `godotenv.Load()` を使用
Go アプリケーションのコード内で `.env` ファイルを読み込みます。

```go
package main

import (
	"fmt"
	"log"
	"os"

	"github.com/joho/godotenv"
)

func main() {
	// .env ファイルを読み込む
	err := godotenv.Load()
	if err != nil {
		log.Fatal(".env ファイルを読み込めませんでした", err)
	}

	// 環境変数を取得
	mysqlUser := os.Getenv("MYSQL_USER")
	mysqlPw := os.Getenv("MYSQL_PW")

	fmt.Println("MYSQL_USER:", mysqlUser)
	fmt.Println("MYSQL_PW:", mysqlPw)
}
```

## 起きていたエラー

Go のアプリケーションを実行した際、以下のエラーが発生しました。

```
2025/02/19 02:11:07 .envファイルが読み込めません: open .env: no such file or directory
```

このエラーの原因は、アプリケーションが `.env` ファイルを読み込もうとしているが、ファイルが存在しない、または適切にロードされていないためです。

## エラーの原因と解決策

### 1. `.env` ファイルが存在しない

`.env` ファイルがプロジェクトのルートディレクトリにない場合、エラーが発生します。

#### **解決策**

`.env` ファイルを作成し、プロジェクトのルートディレクトリに配置してください。

```sh
echo "MYSQL_USER=myuser" > .env
echo "MYSQL_PW=mypassword" >> .env
```


### 2. `.env` ファイルのパスを指定していない

デフォルトでは `godotenv.Load()` はカレントディレクトリの `.env` を読み込みますが、異なるディレクトリにある場合は正しいパスを指定する必要があります。

#### **解決策**

`.env` のパスを明示的に指定してロードする。

```go
err := godotenv.Load("/path/to/.env")
if err != nil {
    log.Fatal(".env ファイルを読み込めませんでした", err)
}
```


### 3. `GO_ENV=prod` の場合でも `.env` をロードしている

本番環境（`GO_ENV=prod`）では `.env` を使用しないのが一般的です。しかし、開発環境と本番環境の区別がないまま `.env` をロードしようとすると、ファイルが存在せずエラーになります。

#### **解決策**

本番環境では `.env` を読み込まないように修正します。

```go
if os.Getenv("GO_ENV") != "prod" {
    err := godotenv.Load()
    if err != nil {
        log.Fatal(".env ファイルを読み込めませんでした", err)
    }
}
```

このコードでは、`GO_ENV` が `prod` の場合には `.env` を読み込まないようにしています。

## まとめ

- `godotenv.Load()` は `.env` ファイルを Go の環境変数としてロードするために使用する。
- `.env` ファイルが存在しない場合、エラーが発生する。
- `.env` のパスを正しく指定することで解決できる。
- `GO_ENV=prod` の場合は `.env` をロードしないようにするのがベストプラクティス。

これらのポイントを押さえることで、Go アプリケーションでの環境変数管理を適切に行うことができます。