OmniAICreator/Qiita-1.07M huggingface dataset:
【仮想環境なし】ゼロから始めるk3s構築【Kubernetesわかんない人向け】

弊社でKubernetesをメインとして使っていますがよくわからなかったので自分で構築してみることにします。
学習のために本番と近しい環境にしたいので今回はあえて仮想環境を使わずに構築します。


---

### ここからは不要な方は飛ばしてもOK

## 基礎情報 Kubernetesとは何か
Kubernetes(通称「k8s」)
デプロイとかスケーリング、管理を自動化するためのオープンソースのプラットフォームです。
Dockerはコンテナごとに1つの機能しか動かせませんが、
Kubernetesを使えば、複数のコンテナをまとめて管理したり、一緒に動かすことができます！

## 基礎情報 Kubernetesの基本構成
- クラスター
ノードを1つのクラスターとしてまとめて管理します。

- マスターノード
Kubernetes自体を制御、管理します。

- ノード
アプリケーションなどを実際に実行します。クラスターの中に複数のノードが存在します。

- ポッド
コンテナをまとめた最小単位です。通常、1つのポッドの中には最低1つまたは複数のコンテナが入っていて、同じネットワークやストレージを共有しています。

- コンテナ
Dockerコンテナのことをさします。

図にするとこんな感じ。
<img width="550" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3982231/a9dab5c8-330c-48fd-ad73-38a6b9b81969.jpeg">


### 早速やっていく

今回はk3sを使用していきます。
本物のKubernetesにめちゃくちゃちゃ近いminikubeなんかもありますが学習コストが高いので今回は使用しません。

k3sを簡単に解説すると...

`軽量なKubernetes。インストールが簡単で、メモリ使用量は半分、100MB未満のバイナリにすべてが収まります。`


https://docs.k3s.io/ja/



---
### ここから手順になります

## 使うもの
- 初期化しても大丈夫なPC
- USB（8GB以上メモリ）

以上。

また、精密な作業なので意識のあるうちにやること(眠い時は禁物)


Windows11を使用しています。


# 1.バックアップを取る（必要な人）

スタートボタン → 設定 → 検索窓で「バックアップ」を検索 → Windowsバックアップをみて設定に漏れがないか確認する。


# 2.Ubuntuをダウンロード

今回は`Ubuntu Desktop 24.04.2 LTS`を使用。

https://jp.ubuntu.com/download

# 3.Rufusをダウンロード
窓の杜にてダウンロード。
今回は`v4.7`を使用。
https://forest.watch.impress.co.jp/library/software/rufus/

# 4.Rufusを使ってUSBにUbuntuを焼く

以下の通りに設定する。

デバイス → `USBの名前`
ブートの種類 → `先ほどダウンロードしたububtuファイル`
パーティション構成 → `GPT`
ファイルシステム → `FAT32v`
クラスターサイズ → `16キロバイト`

設定したら書き込み開始。10分くらいかかる。


# 5.k3sをいれる

`F12`を押しながら起動すると、セーフモードに入る。
（機種によって違うので、確かめること）

一番上の`Try or install Ubuntu`を選択して中に入る。

**ここで早速問題発生。** 
タッチパッドが動きませんでした。
今回使用したのはdynabookのS73だったがよくよく調べてみたらlenovoでも同じ現象が起きているらしい...。
どうやらSynaptics社のタッチパッドが原因とのこと。有効化の方法があるらしいので調べてやってみてください。
私はUSB接続のマウスを使用して一旦凌ぎました。

最初の設定を終わらせて

`Ctrl + Alt + T`してターミナルを開く。

**curlをインストール**
```
$ sudo apt install curl
```
**K3sをインストール**（クラスターの構築）
```
$ curl -sfL https://get.k3s.io | sudo sh -
```
**ステータス確認**
```
# サービス起動状態の確認 (k3sサービスが起動中か、ログにエラーが出ていないかが確認できる)
$ sudo systemctl status k3s
```
**k3sのバージョン確認**
```
# ちなみにこのときは`v1.32.3`
$ k3s --version
```

## nginxを立ち上げてみる！


**起動**
```
# 必ずk3sに --snapshotter=fuse-overlayfsを明示して起動させる
sudo curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC="--snapshotter=fuse-overlayfs" sh -
```
**起動後の確認**（ノードの確認）
```
# ubuntuがReadyになっていればok
sudo kubectl get nodes
```
**nginx デプロイ**（ポッドの作成）
```
sudo kubectl create deployment nginx --image=nginx
```
**起動後の確認**（ポッドの確認）
```
sudo kubectl get pods
```
**外部公開**
```
# nginxのPodがRunningになっていればok
sudo kubectl expose deployment nginx --port=80 --type=NodePort
```
**ポート確認**
```
sudo kubectl get svc
```
## アクセスする！

**ローカルIPの確認**
```
hostname -I
```
**ブラウザのアドレスバーに入力**
```
http://ローカルIP:NodePort番号
```


## 🎉 画面に「いつものアレ」が表示されれば成功！

![IMG_1825 (2).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3982231/53f21940-3b0b-4e33-ad68-7280ecd22a26.jpeg)

---

とりあえず構築してみたことでなんとなくな流れは掴めたような気がする。
ちなみにUbuntu入ってるUSBはめちゃくちゃ繊細なので扱いにはくれぐれも気をつけてください。

---


## 参考にした記事

https://qiita.com/tadashiro_ninomiya/items/6e6fea807b2a16732b5b
【EC2】RHEL9以降パスワード認証でSSH接続がいつものようにできなくなっていた件



Qiita 初投稿です！

今日は AWS EC2 上で RHEL 9 をパスワード認証でssh接続するために自分の知っている方法で設定して接続をしてみるも「接続できない!?」という事象にハマりましたので、その原因と解決策を記事にしました！


---

## ハマったこと

新しく作成したユーザーでパスワード認証ログインしようとして、下記の設定をしても、なぜか繋がらない…

 `/etc/ssh/sshd_config` を編集

```text
#Banner none
# override default of no subsystems
Subsystem       sftp    /usr/libexec/openssh/sftp-server
# Example of overriding settings on a per-user basis
#Match User anoncvs
#       X11Forwarding no
#       AllowTcpForwarding no
#       PermitTTY no
#       ForceCommand cvs server
PasswordAuthentication no
```

`PasswordAuthentication no` を `yes` にして、サービスを再起動

```bash
systemctl restart sshd.service
```
teratermでパスワード認証によるssh接続を試しましたが失敗しました、、


![投稿用.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4077172/89396db5-1239-4c7b-867e-302604e3fbff.png)



## 原因はこれでした

`/etc/ssh/sshd_config.d`の配下に怪しいファイルがありました。

```bash
 ll /etc/ssh/sshd_config.d*
total 8
-rw-------. 1 root root  26 May  2 15:43 50-cloud-init.conf
-rw-------. 1 root root 719 Jan  5  2024 50-redhat.conf
```

`50-cloud-init.conf` の中身を確認してみると`PasswordAuthentication no`がありました。
これをyesに編集すれば解決しそうですね！

```bash
# cat /etc/ssh/sshd_config.d/50-cloud-init.conf
PasswordAuthentication no
```
---
## 対処方法

以下の手順で問題を解決しました！

`50-cloud-init.conf` の内容を `yes` に変更しサービスを再起動。

```bash
vi /etc/ssh/sshd_config.d/50-cloud-init.conf
```

```diff
PasswordAuthentication yes
```


その結果、無事にパスワード認証で SSH 接続できるようになりました。

![タイトルなし.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4077172/07261f1e-617d-4f88-bc7d-9061e9ab1e52.png)


---

## まとめ

RHEL 9 の AMI では、`/etc/ssh/sshd_config.d/50-cloud-init.conf` が `cloud-init` により自動生成されており、こちらの設定が優先されます。

本事象は RHEL 9 系の AMI を利用する際に発生する可能性があるため、参考になれば幸いです。

---

以上、SSH パスワード認証が無効だった原因と対処方法の紹介でした。
[poem]IQテストの落とし穴

IQテストに次のような問題が出たとします。どうします？

問：数列の中の□を埋めよ。

3  6  9  □  39  78

一見、規則性がなくて戸惑うかも知れません。あるいは、□の中に12と入れる人がいるかも知れません。

しかし、これ、ある数式で表せます。

f(x)=(x-1)(x-2)(x-3)+3x

(x-n)は0になり、乗算の部分が0で、3xが足されるので、答は18です。

一般にn番目の数をr(n)とし、あとは不規則でいいなら、

f(x)=g(x)(x-n)+r(x)

と置けます。

よって、こんな数列もできます。

f(x)=(x-1)(x-2)(x-3)(x-5)+3x

3   6   9   6   15   78  ...

数式を出されるまでわかりませんが、規則性のある部分を抽出して、(x-m)で置き換え、後を計算するという手法でできます。

IQテストの結果を自慢しているやつがいたら、この問題を出してあげたら、相当頭が良くなければ、まず解けないでしょう。僕は解けませんでした。

終わり
【GitHub】誤った情報をcommitした場合の対応

# 記事概要
誤った情報をcommitした際の対応方法について、記述する。

# 事象
1. 誤った情報をcommitする

# 解消方法
1. 「Commit to master(main)」の下にある「Undo」をクリックする
1. commitを行う前の画面に戻る
【GitHub】誤った情報をpushした場合の対応

# 記事概要
誤った情報をpushした際の対応方法について、記述する。

# 事象
1. 誤った情報をcommitする
1. 上記をpushする

# 解消方法
1. GitHubDesktopの「History」タブをクリックする
1. 誤ったcommitを選択し、右クリックする
1. 「Revert Changes in Commit」をクリックする
1. 「Push origin」をクリックする
【GitHub】コンフリクトが発生した場合の対応

# 記事概要
コンフリクトが発生した際の対応方法について、記述する。

# 事象
1. ブランチAをマスターにマージする
1. ブランチBをマスターにマージしようとしたが、コンフリクトが発生した
    [![Image from Gyazo](https://i.gyazo.com/a409592a413d74d7677fb7174cc0d9af.png)](https://gyazo.com/a409592a413d74d7677fb7174cc0d9af)

# 原因
2つのブランチで同じファイルを作業したため

# 解消方法
1. 「Resolve conflicts」をクリックする
1. 本来あるべきコードに編集し、コンフリクトの解消を行う
1. 「Mark as resolved」をクリックする
1. 「Commit merge」をクリックする
【GitHub】誤ったブランチでコード編集を行った場合の対応

# 記事概要
ブランチの作成を忘れた場合や、別のブランチにコードを記入した場合の対応方法について、記述する。

# 事象
トピックブランチではなく、mainブランチにコード修正が適用されている

# 原因
トピックブランチの作成を忘れ、mainブランチで作業を進めてしまったため

# 解消方法
1. 新しいブランチを作成する
1. `Bring my changes to 新しいブランチ名`を選択する
    |表記|意味|
    |-|-|
    |Leave my changes on master (main)|元のブランチで書いていたコードを保留にして、新しいブランチで0からコードを書く選択です。|
    |Bring my changes to 新しいブランチ名|元のブランチで書いていたコードを新しいブランチに引き継ぐ選択です。|
1. mainブランチの修正コードが新しいブランチに移動する
【Playwright MCP】月次パッチを自動でダウンロードする

## はじめに

オフラインで運用している Windows PC は、インターネットから自動的にパッチをダウンロードできない📥
パッチとは、マイクロソフトが定期的に発出している更新プログラムのことだ🛠️

オフラインで運用しているPCとはいえ、脆弱性を放置してはおけない⚠️
定期的にパッチをあてるべきだ🔄

毎月毎月、マイクロソフトが提供してくれるパッチをダウンロードして📅
各パソコンにパッチをインストールする必要がある💻

パッチの自動配布については、[藤原竜也ソフトウェア](https://www.skyseaclientview.net/function/ale/ale03.html)を使うこともできよう🖥️

## この記事は

オフラインで配布するためのパッチを自動でインターネットから取得する🌐
もちろん、人が手でせっせこダウンロードするのではなく、AIにやらせる🤖

具体的には、Github Copilotに指示をして、PlaywrightでWEBをクローニングさせる🕸️
私はあいまいな指示だけをして、必要なパッチをダウンロードさせる📂

前提として、管理対象のパソコンは Windows サーバの2016～2022に限定されれるものとする🖥️

## 命令、プロンプト

```markdown:prompt.md
## 作業内容

1. [Microsoft Update カタログ](https://www.catalog.update.microsoft.com)をブラウザで開いて
2. [今月の配信リスト](#今月の配信リスト)の項目を検索して。その際、yyyy-mmは先月の日付にして。
4. 検索結果のURLを[リンク先一覧](#リンク先一覧)に追記して

## 今月の配信リスト

- yyyy-mm Cumulative Update for Microsoft server operating system version 21H2 for x64-based Systems
- yyyy-mm Cumulative Update for Windows 11 Version 23H2 for x64-based Systems 

## リンク先一覧
```

## Github Copilotに作業をさせた結果

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272511/d5d43b12-3dc9-4a9e-835f-9233791e9609.png)

### 取得したリンク

- [2025-04 Cumulative Update for Microsoft server operating system version 21H2 for x64-based Systems](https://www.catalog.update.microsoft.com/Search.aspx?q=2025-04%20Cumulative%20Update%20for%20Microsoft%20server%20operating%20system%20version%2021H2%20for%20x64-based%20Systems)
- [2025-04 Cumulative Update for Windows 11 Version 23H2 for x64-based Systems](https://www.catalog.update.microsoft.com/Search.aspx?q=2025-04%20Cumulative%20Update%20for%20Windows%2011%20Version%2023H2%20for%20x64-based%20Systems)

## おわりに

いちいちKB番号をもとに検索する手間が減った

ちなみに最初のほうで各行末に絵文字が挿入されているのも、Copilotにやらせた

## 参考

- [Playwright MCP を使ってAIにブラウザ操作をさせてみる（GitHub Copilot / Cline 環境構築手順付）](https://qiita.com/t-kurasawa/items/fc47a9133dd6cfe1ae7b)
- [Github Copilotでブラウザを制御しテストスクリプトを生成する。](https://qiita.com/shigeshigeshige/items/179e4a8165ecffef18c9)
vscode 1.99から古いLinuxに接続する

vscodeを1.99以降にアップデートすると古いLinuxにRemote SSHやRemote Containerでアクセス出来なくなってしまいました。

https://aka.ms/vscode-remote/faq/old-linux

回避策も書いてあるのですがどうも分かりにくい。
どうやら仕組みとしては下記のようです。

- Remote SSHやRemote Containerは接続先のマシンにvscode serverを起動させる
- 1.99以降はvscode serverがglibc 2.28など新しいライブラリを要求するようになった
- glibcは動的リンクされるので、接続先マシンにglibcの新しいバージョンが入っている必要がある
- 通常、動的リンクはシステムの固定のパスからライブラリを探すため、古いLinuxでは必要なバージョンが見つけられずエラーになる

上記の公式ページに書いてある回避策は、

- VSCODE_SERVER_PATCHELF_PATH という環境変数で patchelfというツールのパスを指定する
- patchelf は動的リンクする際のライブラリを探すパスを実行ファイルを書き換えることで変更する機能を持ってる
- 事前に crosstool-ngというツールを使ってvscode serverが必要とする新しいglibcなどをビルドして用意しておく
- patchelfがvscode serverを書き換えて新しいglibcを探しに行くようにしてくれるので動作できる

仕組みは理解したが、色々面倒なので、vscode 1.99 から接続できる Ubuntu 16と18のDocker imageを作りました。


https://github.com/naitaku/old-linux-vscode/pkgs/container/old-linux-vscode

ghcr.io/naitaku/old-linux-vscode:ubuntu-16.04
という名前でdockerやDockerfileから参照できるので、これをベースにイメージを作ればvscodeから接続できるイメージが作れます。
Azure Functions で McpToolTrigger を使ったらビルドできなかった話（SDK 2.0.2 に上げればOK）

以下を参考に Azure Functions の McpToolTrigger を試そうとして個人的にハマったので備忘録としてまとめておきます。

https://techcommunity.microsoft.com/blog/appsonazureblog/build-ai-agent-tools-using-remote-mcp-with-azure-functions/4401059

## 環境

Windows 11
Visual Studio 2022 Version 17.13.6

## 問題: McpToolTrigger の Function を定義すると何故かビルドエラーになった

初めて MCP を使ってみたので、公式ドキュメントの内容をほぼコピペで進めていました。
プロジェクトは .NET 9 の「分離プロセス Worker」テンプレートを使用し、Microsoft.Azure.Functions.Extensions.Mcp の 1.0.0-preview.2 を参照に追加。ここまではビルド成功。

ところが、McpToolTrigger を定義した途端、以下のようなエラーでビルドが失敗：

> 1>C:\r\trash\FunctionApp2\FunctionApp1\obj\Debug\net9.0\WorkerExtensions\WorkerExtensions.csproj : error NU1202: Package Microsoft.Azure.Functions.Extensions.Mcp 1.0.0-preview.2 is not compatible with net6.0 (.NETCoreApp,Version=v6.0). Package Microsoft.Azure.Functions.Extensions.Mcp 1.0.0-preview.2 supports: net8.0 (.NETCoreApp,Version=v8.0)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180121/af65c6da-aec8-4706-a7dc-d5d37c1cd4c7.png)

.NET 9 プロジェクトにも関わらず、McpToolTrigger を定義したことでビルド時に生成される WorkerExtensions.csproj のターゲットフレームワークが net6.0 になっていました。

そのため、.NET 9 専用の Microsoft.Azure.Functions.Extensions.Mcp パッケージがビルドに失敗していたという原因のようです。

## 解決策 : Microsoft.Azure.Functions.Worker.Sdk を 2.0.2 以上にする

テンプレートでは Microsoft.Azure.Functions.Worker.Sdk の 2.0.0 が使われていましたが、このバージョンでは WorkerExtensions.csproj が net6.0 固定。

https://github.com/Azure/azure-functions-dotnet-worker/issues/2924

WorkerExtensions.csproj の ターゲットフレームワークを .NET 8 にあげる修正が `2.0.2` にて取り込まれたようなので、それを指定することでビルドが通るようになりました。

> <PackageReference Include="Microsoft.Azure.Functions.Worker.Sdk" Version="2.0.2" />

## まとめ

* Microsoft.Azure.Functions.Worker.Sdk が 2.0.0 だと .NET 6 ターゲットになり、ビルド失敗
* 2.0.2 以上に更新すれば .NET 8 ターゲットでビルド成功
【Node.js】exceljsを使って自動でExcelに記録する

## はじめに
KG-7thの後藤です。

自動で仮想通貨を売買するアプリを作ったのですが、
為替の推移と購入・売却時の価格を記録しておかないとフィードバックができず。。
アプリ内で自動でエクセルに記載させて楽しようと思います。

ちなみに現在までの成果は1000円ほど損してます。笑ってください。

### 関連記事

CoinCheckのWebAPIの使い方については以下でご紹介しています。

https://qiita.com/KG-7th/items/e3246c65af2172f291fa

## 基本仕様

- 開発言語：Node.js + TypeScript
- ライブラリ：exceljs

## 目的

以下のようなエクセルを用意しました。
（お金ないのでLibreOfficeで作成しましたが、拡張子は.xlsxにしてます）

選択範囲であるB3・C3以下に自動で値を入れていくのが目的です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4042336/992d30a7-d57b-4bbd-8ee9-4f42f6d79b86.png)

## コード解説

### ワークブック・ワークシートの指定

Excelファイルのパスとワークシートの名前を使います

```ts
  private EXCEL_FILE_PATH = './result.xlsx';

  // ワークブックを読み込み
  protected workbook = new ExcelJS.Workbook();
  // ワークシートを取得
  protected worksheet: Worksheet | undefined;

  /** 
   * ワークブックの取得に同期処理が必要なため、asyncを使用して初期化
   * @param worksheetName ワークシート名
   * @returns {Promise<void>} ワークブックの初期化
   * @throws {Error} ワークブックの初期化に失敗した場合
   */
  async initialize(worksheetName: "PRICE" | "BO-SELL" | "BO-BUY" | "MA-SELL" | "MA-BUY" | "RSI-SELL" | "RSI-BUY"): Promise<void> {
    try {
      // ワークブックを読み込み
      await this.workbook.xlsx.readFile(this.EXCEL_FILE_PATH);
      // ワークシートを取得
      this.worksheet = this.workbook.getWorksheet(worksheetName);
    } catch (error) {
      // エラー処理
      console.error('Error initializing Excel worksheet:', error);
    }
  }
```

### 最後の行を取得する

B3、B4、B5・・のようにどんどん値が入っていくので、
最新の一番下の行を取得する関数を作成しました。

B1は空白セルなので、startRowNumberを引数に入れることで
空白セルを飛ばして行のチェックをするようにしています。

```ts
  /**
   * 対象列の最終行を取得する
   * @param columnNumber 
   * @param startRowNumber 
   */
  getLastRowNumber(columnNumber: number, startRowNumber: number): number {
    if (!this.worksheet) {
      throw new Error('Worksheet is not initialized');
    }
    // 最終行を取得
    let lastRowNumber = 0;
    this.worksheet.eachRow((row, rowNumber) => {
      if (rowNumber < startRowNumber) {
        // 指定行より上の行はスキップ
        return;
      }
      // 指定列の値が空でない場合、最終行とする
      const cell = row.getCell(columnNumber); 
      if (cell.value !== null && cell.value !== undefined && cell.value !== '') {
        lastRowNumber = rowNumber;
      }
    });

    return lastRowNumber;
  }
```

### テキストの入力

getCell(セルを指定).valueだけで値が設定できるらしいです。

```ts
  /**
   * テキストの入力
   * @param columnAlphabet 
   * @param rowNumber 
   * @param cellValue 
   */
  async appendCellValue(columnAlphabet: string, rowNumber: number, cellValue: number | string): Promise<void> {
    if (!this.worksheet) {
      throw new Error('Worksheet is not initialized');
    }
    // セルに値を追加
    this.worksheet.getCell(`${columnAlphabet}${rowNumber}`).value = cellValue;
    // ファイルを保存
    await this.workbook.xlsx.writeFile(this.EXCEL_FILE_PATH);
  }
```

## 終わりに

以下のリポジトリで使用しています。
もしかしたらmainブランチにはマージされてないかもです。

**ExcelWorksheetAdapter.ts**

https://github.com/undo-works/AutoCrypto-Node
良いコード／悪いコードで学ぶ設計入門 第１２章

# 第12章 メソッド（関数） ―良きクラスには良きメソッドあり

この章では、メソッドの設計がクラス設計の質に大きく関わること、そしてその逆もまた然りであるという原則から始まる。メソッドは単なる処理の集まりではなく、オブジェクト指向における振る舞いを担う重要な構成要素であり、良いクラスには必ず良いメソッド設計があるという前提に立って、様々な観点から設計指針が述べられている。

---

## 12.1 必ず自身のクラスのインスタンス変数を使うこと

原則として、メソッドは自身のクラスのインスタンス変数を使って動作すべきである。他クラスの状態を変更するような構造は低凝集を招くため避けるべきだ。

実際の開発でも、他のクラスのフィールドを無理に操作しようとして設計が崩れることはよくある。インスタンス変数の操作は、その変数を保持するクラスに委ねる方が責任の所在が明確になり、安全性も向上する。

---

## 12.2 不変をベースに予期せぬ動作を防ぐ関数にすること

メソッドが可変な状態を変更すると、その影響範囲が予想しづらくなり、バグの温床になる。不変な設計にすることで堅牢性が増し、保守性が格段に向上する。

予期しない副作用によって挙動が崩れる体験は誰しも経験があるだろう。後からその理由をコード中に探すのは非常に骨が折れる作業である。不変性を前提にした設計を心がけたい。

---

## 12.3 尋ねるな、命じろ

「尋ねるな、命じろ（Tell, Don’t Ask）」という設計原則が紹介されている。他クラスの状態を取得し、その結果に応じて処理を変える構造は、凝集度が低くなる傾向がある。

この章では特に getter / setter に対する警鐘が鳴らされており、データを自由に操作できる構造は危険だとされている。代わりにカプセル化を徹底し、必要な操作だけをメソッドとして公開すべきである。個人的にも、ビジネスロジックが外に漏れる設計は極力避けたいと常々感じている。

---

## 12.4 コマンド・クエリ分離

CQS（Command Query Separation）は、メソッドは「状態を変更する」か「状態を返す」かのいずれか一方に限定するという設計原則。コマンドとクエリを同時に行う「モディファイア」は避けるべきとされる。

副作用があるのかどうかが曖昧なメソッドは読み手を混乱させ、テストや保守の負担も増える。コードを読む際にも「このメソッド、値を返してるけど副作用あるのかな…？」と警戒することが多いため、こうした原則は実務において非常に重要である。

---

## 12.5 引数の扱い

引数に関する設計の注意点が丁寧に述べられている。以下がポイントだ。

- 引数は不変にすること  
- フラグ引数は使わない  
- null を渡さない  
- 出力引数を使わない  
- 引数は可能な限り少なく

null やフラグ引数は実装者の意図がコードから読み取れず、メソッド内部を開いて確認する必要が出てしまう。ストラテジパターンなどの活用で機能の切り替えを明示することが推奨されている。

日頃から引数に `null` を使ってしまう場面はあるが、意味を持った状態として設計し直す努力が必要だとあらためて感じた。特にPHPのように `null` が簡単に使える言語では、安易な選択肢として流れてしまいがちなので意識して避けたい。

---

## 12.6 戻り値の設計

戻り値にも多くの設計配慮が求められる。主な原則は以下の通り。

- プリミティブ型ではなく、型で意図を明示する  
- null を返さない  
- エラーは戻り値ではなく例外でスローする

エラーを戻り値で表すと、ダブルミーニング（二重の意味を持つ）状態となり、呼び出し元がそれを知っていないと誤動作を招く可能性がある。これにより分岐処理があちこちに散らばり、複雑さが増す。

私自身も、値の戻し方を簡単に済ませたくて null を返したり、状態コードを戻した経験がある。しかし後から見返すと、解釈が難しくバグの温床になっていたことを痛感している。

---

## メソッド名の設計

「動詞＋目的語」の命名は、一見わかりやすいようでいて、責務を超えるロジックを抱えがちである。理想は、動詞1語で完結するようにクラスとメソッドの設計を合わせること。

この視点は実際に設計を考える上で非常に参考になる。メソッド名が長くなるときは、そもそもその処理が1メソッドに収まるべきなのかを見直すきっかけになる。

---

## static メソッドの扱いに注意

static メソッドは、凝集度が下がるため使用には注意が必要であり、限定的な用途（ファクトリメソッドやユーティリティなど）に留めるべきである。

便利だからと多用してしまうと、オブジェクト指向の利点が活かせなくなり、疎結合な設計が崩れてしまう。適材適所で使いたい。

---

## まとめ

メソッドの設計は、単に動くコードを書くこととはまったく次元の異なる行為である。クラスとメソッドの責務を明確に分け、不変性を保ち、状態やデータの扱いを慎重に考えることで、コードは驚くほど保守しやすく読みやすくなる。

引数や戻り値の扱い方、命名の仕方、設計上の原則など、どれも実務での悩みどころを的確に突いており、改めてメソッド設計に向き合う良いきっかけとなった。
【CLI】HomebrewでCaskを説明付きで検索する方法

HomebrewでCaskを説明付きで検索するには以下のコマンドを使用します。

```terminal
brew search --casks --desc cask名
```

```terminal
$ brew search --casks --desc ''
==> Casks
0-ad: (0 A.D.) Real-time strategy game
010-editor: (010 Editor) Text editor
115: (115, 115桌面版) Client for the 115 cloud storage service
115browser: (115Browser, 115浏览器) Web browser
1clipboard: (1Clipboard) Clipboard managing app
1kc-razer: (Razer macOS) Open source colour effects manager for Razer devices
1password: (1Password) Password manager that keeps all passwords secure behind one password
1password-cli: (1Password CLI) Command-line interface for 1Password
1password-cli@1: (1Password CLI) Command-line helper for the 1Password password manager
```
【React】学習記録アプリを改良した話

# はじめに
[前回作成した学習記録アプリ](https://qiita.com/higa1234q/items/73c7d09df2fd58a1cf1c)に機能を追加したり、Supabaseを利用してデータをDB管理したり、改良を加えました。さらに、作成したアプリをGithub Actionsで自動デプロイしたり、Jestでテストを書いたりしました。

▼前回の記事

https://qiita.com/higa1234q/items/73c7d09df2fd58a1cf1c

# アプリの機能
1\. 登録ボタン押下→学習内容と学習時間を記録
2\. 学習内容と学習時間を一覧で表示
3\. 学習内容と学習時間が入力されていない状態で登録ボタン押下→エラー
4\. 記録した学習時間の累計表示
5\. **追加**：各学習内容と時間に削除ボタン配置→押下で当該行削除

![プレゼンテーション1 (2).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4048214/0afe7606-40b7-485a-9313-fe574c78da2c.gif)

# さらにやったこと
* 登録した学習内容と時間をDBに保存
* Firebaseにホスティング
* GitHub Actionsでテスト→ビルド→デプロイを自動実施

# やってみて…
### Supabase
* バックエンドはSupabaseを利用。
* Supabaseは初めて使用。RDBっぽく操作できたので使いやすかった。
* Reactアプリでどのようにモジュールを書いていけばいいか、非同期処理の扱いで結構時間かかった。

### Firebase
* 初めて使用。
* 設定などはこのページを参照しながら結構慎重に実施。（https://ralacode.com/blog/post/register-firebase/）

### GitHub Actions
* ここらへんも初めて実施。
* CI/CDは、情報処理系の試験などで名前は知っていた程度だった。実際に実装してみてものすごく理解が深まった。ビルド、テスト、デプロイの一連の動作を自動でできるのはすごく便利。

### Jest
* 考え方含めて、今回一番時間を使った箇所。テストケースが全く書けない。公式ドキュメントを読んでもさっぱり。先人が残したQiita記事やChatGPTを駆使してようやく書けた。
* 今回のアプリでは、DBを操作するモジュールがあり、最終的にそのモックを作成しテストできたのはよかったか。

# その他（課題や今後の展望など…)
* どれも初めて触る技術、サービスばかりだったが、課題を終わらせる、先に進むという意識が強すぎて1つ1つの理解がまだ十分でないと感じる。公式ドキュメントなどももっと読み込んでいきたいと思う。
* とりあえず動けばOKみたいな感じで進めていたので、次はベストプラクティスなど調べて、スマート、安全なコードや実装を心掛けたい。

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

https://projisou.jp
Rails7:フォーム送信後のエラーメッセージの表示ができない(Error: Form responses must redirect to another location)

環境
Ruby:3.2.2
Rails:7.1.5

期待していた動作
・フォーム送信時にエラーメッセージを伴ってフォームを再び表示させる

症状
・エラーが表示されない
・コンソールに以下のメッセージが出力されていた
```
”Error: Form responses must redirect to another location”
```
推察
・フォームの送信結果は送信の成否にかかわらず他のページへリダイレクトする必要があるのではないか？

調査
https://qiita.com/wa-chan222/items/01f86da80d0d59e966d8
https://stackoverflow.com/questions/70400958/error-form-responses-must-redirect-to-another-location

調査の要約
・Turboはフォーム送信後のレスポンスで所定のステータスコードを期待している。（成功時は303,失敗時は422）。これらのステータスコードでないとTurboはうまく動作しない。

解決策
・Railsではレスポンス時に明示的にステータスコードを指定できる
・結果としてうまくエラーメッセージが表示され、期待通りの結果となった。

```
  def create
    @task = Task.new(task_params)
    if @task.save
      #303を返す
      redirect_to @task,notice: "タスク#{@task.name}が新規作成されました",status: 303
    else
    　#422を返す
      render :new,status: 422
    end
  end
```


# ステータスコードについて
・Rails はデフォルトではrenderで200,redirectで302のステータスコードを返す。そこでTurboが正常に動作するようにステータスコードを設定する必要があった。ステータスコードの意味は以下のようになっている。

302：リダイレクト。「コンテンツが一時的に移動しているのでメソッドはそのままにしてほかのURLにリクエストを送ってくれ」という指示。
303：リダイレクト。「送信結果はほかのページで表示するための場所を用意しているのでメソッドをgetリクエストにしてそちらを訪ねてくれ」という指示。
422:クライアントエラー。「400と違い、構文・リクエストのメタデータ的には問題ないがnullやバリデーションエラーなどカラムの値的・意味的な問題がある」という指示。


参考文献
・[webを支える技術](https://www.amazon.co.jp/Web%E3%82%92%E6%94%AF%E3%81%88%E3%82%8B%E6%8A%80%E8%A1%93-HTTP%E3%80%81URI%E3%80%81HTML%E3%80%81%E3%81%9D%E3%81%97%E3%81%A6REST-WEB-PRESS-plus/dp/4774142042/ref=sr_1_1?adgrpid=102912038115&dib=eyJ2IjoiMSJ9.keVxzcS97Fi6xZQxNB-wHo7-ciGSZcdOl_EaquddPglqrcgo4_UH8U1Ipo2v_rNyr3DCzbGhwNmfYuxlJDcR9PkNFODi5nepISRHtxj4y0jtpekZ_t_oRTFjQHRhkKhTGYRIpuhieA3MjLZiErfmsir3e9RBYSMXwkYuJbnty0gT8x7Ooik6qUUP4BJc3daKs4BHtvoMzr1ADCt57X-xaIyaoiVUJ76gh3mOVCd7uls8OSijPZ8g5RzKoT-qoE05_AJ46xtYxvRl-LlCG5T68oG8sTAXW9uu9fIdaajNX4k.Swsl9gEU_fqKFTSazGm4TexH21Hzkew3zQI39BIusQE&dib_tag=se&hvadid=651192011668&hvdev=c&hvlocphy=9198588&hvnetw=g&hvqmt=e&hvrand=424611683802800021&hvtargid=kwd-394859824714&hydadcr=21894_13456357&jp-ad-ap=0&keywords=web+%E3%82%92+%E6%94%AF%E3%81%88%E3%82%8B+%E6%8A%80%E8%A1%93&mcid=65819bc0be4b36919a8d51e1f78c74f9&qid=1746197081&sr=8-1,"webを支える技術")
・プロになるためのweb技術入門
mermaid-cliで出力されるSVGをWebブラウザ以外でも正常に読めるようにする

[対処方法へのショートカット](#対処方法)

フローチャート等の様々なダイアグラムを定義するマークアップ言語の[Mermaid](https://mermaid.js.org)。以下のような記法。

```text:カレーの作り方.mmd
flowchart TD
    A[材料を準備する] --> B[玉ねぎを炒める]
    B --> C[肉を加えて炒める]
    C --> D[野菜を加える（にんじん・じゃがいも）]
    D --> E[水を加えて煮込む]
    E --> F[アクを取る]
    F --> G[材料が柔らかくなるまで煮る]
    G --> H[火を止めてルーを入れる]
    H --> I[ルーを溶かす]
    I --> J[再び火をつけて煮込む]
    J --> K[完成！盛り付ける]
```

Mermaid記法で記述されたテキストからダイアグラム画像を出力するコマンドラインツールの[mermaid-cli](https://github.com/mermaid-js/mermaid-cli)を使えばお手軽に画像化できて便利。上記のテキストは以下のように画像化できる。
![curry.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4069698/fae26c5b-2d29-4462-96ce-050b54dcd8db.jpeg)
PNGだけでなくベクター画像のSVGやPDFの出力もできる。

しかしながら、mermaid-cliで出力されるSVGをWebブラウザ以外で読もうとしても正常に読み込まない。例えば、Inkscapeで読み込むと、
![curry_inkscape.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4069698/8ff93300-eea9-4b2f-8c0b-b936da7a5505.jpeg)

PDFで出力して、pdf2svgでSVGを生成すれば正常に読めるが、これだとテキストがパスデータになっていたりして不便。何とか直接生成されるSVGを読めるようにしたい。

# 原因
mermaid-cliで出力されるSVGには一部の環境でサポートされないCSSが含まれるかららしい。
[参考](https://github.com/mermaid-js/mermaid/issues/2102#issuecomment-1242763775)
[Mermaid Live Editor](https://mermaid.live/)でも同じ症状なので、おそらく公式の実装の仕様。

# 対処方法

[mermaid-js公式のissueで紹介されている方法](https://github.com/mermaid-js/mermaid/issues/2102#issuecomment-2314514579)を参考に以下の手順で修正。
1. 設定ファイルを書く。
```json:config.json
{ "flowchart": { "htmlLabels": "false" } }
```
3. mmdcを実行する時に↑の設定ファイルを適用する。
```bash
$ mmdc -c config.json -i [Mermaidテキストファイル名] -o [SVGファイル名]
```
5. 出来上がったSVGに対し、以下のように書き換え。
```bash
$ cat [元のSVGファイル名] | sed 's/root{--mermaid-font-family/root{mermaid-font-family/' > [変更後のSVGファイル名]
```

Inkscapeで読み込んでみる。
![curry_converted.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4069698/6ce19728-ecc1-49f8-a634-9e9c0244ec97.jpeg)

👍
さくらのVPSのDebianをVNCコンソールで日本語配列キーボードを使う

# 事象
日本語配列キーボードを使って、Debian on さくらのVPSで「VNCコンソール」から操作しようとしたときに、記号等において意図した入力とならなかった。「シリアルコンソール」からであれば問題なく操作できることは確認できていたが、なんとなく対応してみた。
* さくらのVPSでVNCコンソール
* Debian 12(bookwarm) amd64
* 日本語配列キーボード

# さくらのVPSの設定
「VNCコンソールキー配列」を「ja」にする。
![sakura1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538068/e6b5cf48-3e83-46f2-ae45-5dc2a63541ca.png)


# Debianの設定
次の通り設定する。
```
$ sudo apt install -y console-data console-setup
$ localectl set-keymap --no-convert jp106
$ sudo loadkeys jp106
```

ここらに反映されている模様。
```
$ cat /etc/default/keyboard
XKBMODEL="a4techKB21"
XKBLAYOUT="jp"
XKBOPTIONS="terminate:ctrl_alt_bksp"
BACKSPACE="guess"
XKBVARIANT="

$ cat /etc/vconsole.conf
KEYMAP=jp106
```

これで設定は終わり。あとはアットマーク@や、コロン:がキーボード配列どおりに入力できるかを確認する。

# 参考
 - [Debian keyboard](https://wiki.debian.org/Keyboard)
 - [さくらのVPS OSセットアップ情報 » Debian 12](https://manual.sakura.ad.jp/vps/os-packages/debian-12.html)
 - [さくらのVPS サーバー » コンソール](https://manual.sakura.ad.jp/vps/server/console.html#vnc-setting)
 - [XServer VPS コンソール接続時のキーボード配列設定日本語化](https://vps.xserver.ne.jp/support/manual/man_server_console_keyboard_setting.php)
Databricksのチュートリアルをやってみた(Day1.データをクエリして可視化)

## 前提
・利用環境：Databricks

https://www.databricks.com/jp/try-databricks?scid=7018Y000001Fi15QAC&utm_medium=paid+search&utm_source=google&utm_campaign=17377047998&utm_adgroup=138148229998&utm_content=trial&utm_offer=try-databricks&utm_ad=732035937815&utm_term=databricks%20%E3%83%88%E3%83%A9%E3%82%A4%E3%82%A2%E3%83%AB&gad_source=1&gclid=CjwKCAiA8Lu9BhA8EiwAag16b8b3zbkIb3V7gp-8VUwKukXnhtVZRQ-1RY8SbETmGVgNT4bQramYmRoCX5wQAvD_BwE#account

## 参考ドキュメント
https://docs.databricks.com/gcp/ja/getting-started/quick-start

## 操作手順（動画）

<iframe width="100%" height="315" src="https://www.youtube.com/embed/4hFuGV8I2eM?si=ED3_aWWkE9auKHBn" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>

## 手順
#### 1.新しいノートブックを作成する
①「新規」→「ノートブック」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562390/5dcb0f69-147c-4ea8-8de4-04a506a631b0.png)
#### 2.テーブルのクエリを実行する
①次のコードをコピーして、新しい空のノートブックセルに貼り付ける
`SELECT * FROM samples.nyctaxi.trips`
②Shift+Enterを押してセルを実行もしくは、実行ボタンをクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562390/e25ae3fb-e02c-40b9-a1e3-a98decad63a6.png)
#### 3.データを表示する
①テーブル タブの横にある「+」をクリックし、「可視化」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562390/242ad4be-eba6-448c-8c8b-3f5e4b931528.png)
②以下を参考に設定し、保存
Visualization type：Bar
X column：fare_amount
Y columns：trip_distance
集計タイプ：Average
Group by：pickup_zip
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562390/316c6bd7-430d-437f-8571-a2fae1ce2099.png)
以上
GitHub Copilot Agent機能を使ってオセロゲームを作成してみた

### やってみたこと
最近、（とは言っても2025/2）GitHub Copilot AgentがVS Code Insidersで利用できる様になったので、どういったことができるのか、試してみた。実際の動作は参考サイトに掲載しているGitHub公式サイトのリンクに動画が埋め込まれているので、そちらを参照頂きたい。
具体的にやってみたことは以下となる。
- GitHub Copilotエージェントモードを使ったHTMLのプログラム作成（→成功）
- javaのプログラム作成（→失敗）

### 感想
今までは、コードを生成AIで作成させ、出来上がったコードをローカル環境で実行して試してみる、という流れであったのが、ローカル環境へのプログラムファイル作成、テスト、ドキュメント作成、実行までエージェントとの会話だけで成立した。

環境面におけるエラーの対応については、まだ人の介入が必要そうな印象であるが、大体のぷろぐらむｈ仕様さえ決めてしまえば待つだけで成果物ができる様になっていきそうだという印象を持った。

### エージェントモード実行の流れ

Copilot Editの機能を利用時、「Agent」を選択。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/305763/d50e0c9d-6e17-45d1-a121-ac8f7413fd38.png)
プロンプトを入力し、実行ボタンを押す。
![image (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/305763/5b9c127a-ee5d-45bc-866f-37fb9d2c6c7d.png)

#### プロンプト
```plaintext
htmlでオセロゲームを作成してください。 
アプリの実行手順や環境構築の方法はREADME.mdとして保存してください。
テストを実行し、エラーが発生すればそれらを修正しながら進めてください。 
発生したエラーとその解決方法についてもREADME.mdに含める様にして下さい。
では、宜しくお願いします。
```

### プログラム作成の結果
#### 作成されたファイル
![image (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/305763/22adcba4-11f1-4bb4-b55d-112fc14ede93.png)

#### 結果のイメージ
→以下のメッセージが出来上がるとともに、実際のローカル環境上にファイルが作成されていく
![image (3).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/305763/042d59b4-8af9-4325-8368-ced2c693b59e.png)
![image (4).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/305763/733be603-761f-4f57-97c1-64c47c5c5ba2.png)

#### README
→READMEも作成してくれる
```markdown
# オセロゲーム

シンプルなHTML/CSS/JavaScriptで作成したオセロ（リバーシ）ゲームです。

## 実行方法

1. このリポジトリをクローンまたはダウンロードします
2. `index.html` をブラウザで開くだけで実行できます

## 開発環境

- HTML5
- CSS3
- JavaScript (ES6+)

## ゲームの遊び方

1. 黒石が先手、白石が後手です
2. 盤面の空いているマスのうち、相手の石を挟めるところに石を置くことができます
3. 相手の石を1つ以上挟めるところにのみ石を置けます
4. 両者とも石を置けなくなったらゲーム終了です
5. より多くの石を獲得した方が勝利となります

## エラー対応履歴

現時点ではエラーは発生していません。エラーが発生した場合は、ここに追記していきます。
```

### プログラム実行の結果
#### 追加プロンプト
→プログラム完成後に、ゲーム実行までを指示
![image (5).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/305763/3ab20c0c-18c2-47f2-93b1-c00762814c66.png)

#### 結果のイメージ
→ターミナル上でコマンドが実行され、ブラウザを立ちあげることができる
![image (6).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/305763/bfe54c95-f15f-4d0d-afe0-f86f6d5b4968.png)

#### ゲーム画面
→ブラウザでHMTLファイルを開き、ゲームができる
![image (7).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/305763/6c3ecc38-2830-4fb0-b76c-b2ce2d79ca4b.png)

### 補足（失敗例）
#### プロンプト
```plaintext
javaでパックマンを作成してください。
アプリの実行手順や環境構築の方法はREADME.mdとして保存してください。
テストを実行し、エラーが発生すればそれらを修正しながら進めてください。
発生したエラーとその解決方法についてもREADME.mdに含める様にして下さい。
では、宜しくお願いします。
```
#### エラー画面
→gradleラッパーを作成してjavaプログラムを実行する様にコマンド実行されるも、以下のエラーにより動かず。
Copilotエージェントにエラー解決の指示をするも、環境面ではなくプログラムの修正を行い続けることで、最終的な解決に至らなかった。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/305763/2d70066c-4a6c-4350-b188-2f39f70e048b.png)

### 参考サイト
https://github.blog/jp/2025-02-07-github-copilot-the-agent-awakens/
【GET?POST?】LLMの応答をSSEする際のHTTPメソッド

## POST？GET？
バックエンド開発ぼく「LLMの生成をリアルタイム送信したいな...」

バックエンド開発ぼく「仕様的には受信するだけで1方向、双方向のWebSocketはオーバースペックだ」

インフラ開発ぼく「そうだね。WebSocketは水平スケールに弱いし、起動しっぱなしになりがちでコストが増えるね」

バックエンド開発ぼく「やはりこういう時は **server-sent events（SSE）** に限る」

フロントエンド開発ぼく「SSEするときは**GETで実装してくれない？**」

バックエンド開発ぼく「なんで？？？？」

フロントエンド開発ぼく「**EventSource**を使うと受信がラクだからだよ」

バックエンド開発ぼく「ほえ～～～」


（複数人格が頭に住んでいますが心療内科には通っています。大丈夫です。）
## EventSourceはGETしか使えない

`EventSource`はSSEで送信されるデータを扱いやすくするためのAPIです。
SSEはサーバーが自由にテキストを送信できますが、その形式は
```js
`data: ${content}\n\n`
```
のような、
```
イベント名: データ\n\n
```
で表されるデータが標準です。
`EventSource`はこのデータのパースを行ってくれるすごいやつです。


```js
const sse = new EventSource("/api/v1/sse");

/*
 * これは以下のようなイベントのみを待ち受けします。
 *
 * event: notice
 * data: useful data
 * id: someid
 */
sse.addEventListener("notice", (e) => {
  console.log(e.data);
});

/*
 * 同様に、これは `event: update` というフィールドを持つ
 * イベントを待ち受けます。
 */
sse.addEventListener("update", (e) => {
  console.log(e.data);
});

/*
 * "message" というイベントは特別なケースで、
 * イベントフィールドを持たないイベントや、特定の型である
 * `event: message` を持つイベントを捕捉します。それは、
 * 他のイベント型では発生しません。
 */
sse.addEventListener("message", (e) => {
  console.log(e.data);
});
```

https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events

実際には`data`はシリアライズしたJSONを使用することが多いかと思います。

便利ですが、これは**GETメソッドにしか対応していません。**

## HTTPメソッドの葛藤
バックエンド開発ぼく「あれ？でもLLMのチャット生成結果はDBに保存するから、生成開始リクエストはPOSTが正しいのかも...?」

バックエンド開発ぼく「いや、同じリクエストなら初回の生成結果が返されるようにすれば取得操作...つまりGETで良い？どっちなんだ...？」

GPT-4o「技術的にはどちらも成立します。でも目的が“結果を受け取ること”なら、GETでいいんです。副作用はサーバー側でうまく隠してしまえばいいんですよ。」

バックエンド開発ぼく「！！！！」

GPT-4o「実際、OpenAIのSSEレスポンスだって裏でログや課金情報書いてます。」

GPT-4o「なので、**副作用あるけどUI的には読み取りっぽいもの**はGETでやっちゃって大丈夫。」

GPT-4o「ただ、設計が気持ち悪いと感じるなら、POSTで状態を作ってからGETの2ステップ方式にするとRESTっぽさは守れます。」

バックエンド開発ぼく「なるほど！！！」

## たどり着いた結論
どちらでも大きく不自然ではない

### POSTを使うパターン
- 目的が「生成とデータの登録」
- 生成のためのパラメータをJSONで送信したい

EventSourceは使えないが [MSのfetchラッパー](https://github.com/Azure/fetch-event-source)等ライブラリはある。

### GETを使うパターン
- 目的が「取得寄りの生成」
- `EventSource`で楽したい
- クエリパラメータで生成条件指定が完結する（生成タスクID指定のみで済むなど）
- 取得結果がどこでキャッシュされても支障がない
Studioでかーでぃらぼのサイトを作ってみた

こんばんは、かーでぃです。

突然ですが、副業の個人事業主の屋号として「**かーでぃらぼ**」を使っています。
事業としては、以下になります。

 * Web記事 / ブログの執筆
 * 技術同人誌 / 技術書の執筆
 * コミュニティ運営 / 支援

ということで、個人用名刺も作ったので、宣伝用のサイトがあってもいいかなぁー
と思いまして、チャレンジしてみることにしました。

インターネット黎明期（30年前？！）にHTMLやCSS、レガシーなJavaScriptは学びましたので、基礎は知ってる（つもり）。
ですが、最近のいわゆる「モダンサイト」はさっぱりわかりません！！

実は、数年前にStudioを知り、1度サイト作りにチャレンジしたことはあったのです。
が、結局は挫折。
「なんか作れたら……」程度の動機では、なかなか前に進むことができずに、諦めてしまいました。

しかし！
今回の動機が「**自サイトを持ちたい！**」と明確になれば、話は別です。

かくして、再度Studioにログインをしたのが、まだ寒い1月の中旬ごろだったと思います。

## 何していいのかわからん

なんか触りながら、こんな感じで……とノープランでログインしたので、何していいのかわからんのですよね。
なので、一旦プランを作るところから始めました。

 * 画像が横スクロールして切り替わるやつ（カルーセルというらしい）を使う
 * アニメーションするようにする
 * note記事やYoutube動画に飛べるにする。

などなど、目的/アイデア出しをした上で、改めてStudioにログインしまして…

なんやかんやで出来上がったのが、先日。
実に**1枚のHP作成に、3か月**かかりました💦

## 完成品
https://kardylabo.studio.site/

HTMLの知識がゼロではないとは言え、ノーコードでこれだけのサイトが作れる**Studio**、すごい！👏

## 完成までの経緯はこちら

https://note.com/kerdy/n/n6b5231e9138a?magazine_key=meb93f6b7a119

Studioに関して言えば、ヘルプやコミュニティサイトがしっかりしてる上に、勉強会やセミナーが結構頻繁に開催されているので、「わからなくなってもなんとなる」のは素晴らしい取り組みだと感じました。
【React】Jestでモック化しても読み込まれないエラーの解決方法について

# はじめに
Jestでモック化をしていてiconメソッドが見つからないというエラーが表示され、こちらの解決方法について記事にします。

:::note warn
TypeError: Cannot read properties of undefined (reading 'icon')
const greenIcon = L.icon({
:::

<br>
【修正前のコード】

```.tsx
jest.mock('leaflet', () => ({
  icon: jest.fn()
}));

```



# 解決方法
Jestの公式に書いてありました。

～以下公式内容～

:::note
デフォルトのエクスポートのES6モジュールで factory パラメータを使用する場合、 __esModule: true プロパティを指定する必要があります。
通常、このプロパティは Babel / TypeScript によって生成されますが、ここでは手動で設定する必要があります。 
デフォルトエクスポートをインポートする場合、エクスポートオブジェクトから default という名前のプロパティをインポートします。
:::

leafletのLオブジェクトはデフォルトエクスポートしていました。

```
import L from 'leaflet';
```
```.tsx

jest.mock('leaflet', () => ({
  __esModule: true,
  default: {
    icon: jest.fn()
  }
}));

```

# 参考
https://jestjs.io/ja/docs/jest-object

https://ja.javascript.info/modules-intro

ファクトリーパラメータとは第２引数の () => ({})　のこと（ファクトリーメソッドとは違います）


# おわりに
用語１つ１つの意味もついでに調べていくと理解が深まります

<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)
Unity6（6000系）でVRM 1.0を表示して非矩形ウィンドウする

# はじめに
Unityで背景透過をしたい。
デスクトップマスコットを作りたい。
Unity触るの初めてだけどさ。まぁ何とかなるっしょｗ

ってわけでやってみることにする

# UnityHubから最新版Unityの導入とプロジェクトの作成
とりあえずインストールして
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30037/34103fc2-26e1-435e-bf2e-1a0da6a4548d.png)
プロジェクト作って
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30037/edba7e7c-e12f-43bd-afda-27114467f90d.png)
Universal3Dプロジェクトを開く（Universal Render Pipelineを使う3Dプロジェクト）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30037/26221d06-18db-40c3-87d2-33ad238de45f.png)

# 非矩形ウィンドウ対応
VRMのロード処理は良しなに書くとして、VRMのロードが完了しているとします。
んで、透過非矩形ウィンドウを実現するためにこのあたりのライブラリを使っていく。
いや本当にありがとうございます

https://github.com/kirurobo/UniWindowController

本題はここから。

# VRMを表示する（一部透過できていない）
![スクリーンショット 2025-04-30 122028.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30037/a5d9ebd8-15fd-451f-a9de-cb93e18a5bec.png)

背景の黒い丸はUnity上の黒い丸じゃなくて、VRMが読み込まれると同時に出てきます。
こんな風に場所を変えても黒くなります。

![スクリーンショット 2025-04-30 151804.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30037/a4723c93-3539-412b-b456-5b2e5088c47f.png)

てことで、原因をとりあえずIssuesから調べてみた。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30037/0ee8f55f-c44f-4889-8af0-040c54f8032c.png)

完全にこれだった。

https://github.com/kirurobo/UniWindowController/issues/42

ってことで、設定項目を書いておきます。まぁVRM表示させるくらいじゃHDR無効化してもさしたる影響はない。
むしろ背景が透過できない方が問題なのでね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30037/4b3cde9b-5fbc-4bcf-986f-34011bf8540f.png)

メニューバー
`Edit > Project Settings...`

画像の真ん中のウィンドウ（Project Settings）が開くので
`Graphics > Default Render Pipeline`の矢印がポイントしている設定された値の部分をダブルクリックする。

今使っているDefault Render PipelineのInspector（デフォルトの場合はPC_RPAsset(Universal Render Pipeline Asset)）が開くので、HDRの項目から"チェックを外す"ことと、Alpha Processingに"チェックを入れる"ことでいい感じに透過が走る

開発ビルドなので左下にめっちゃNullReferenceExceptionのログ出てるけどVRM部分は透過できたのでﾖｼｯ！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30037/e0a2fe62-d0ed-48d1-9ca2-878f429af780.png)

ちゃんとクリックも、透明部分は貫通するしよかったよかった！

おわり。
AWS資格に効いた！ChatGPTを最強の家庭教師にする方法



## 1. ChatGPTとは？エンジニア目線での概要

最近、エンジニア界隈だけでなく一般層にも広く知られるようになった「ChatGPT」。
すでに触ったことがあるという方も多いのではないでしょうか。

ChatGPTは、OpenAI社が開発した対話型AIで、大量のテキストを学習した「大規模言語モデル（LLM）」をベースにしています。
単なるチャットボットとは異なり、文脈を理解しながら自然な対話ができるのが特徴です。

では、実際にどんな使い方ができるのでしょうか？
ChatGPTは例えば以下のような用途で活用できます：

* プログラミングの相談（コードレビュー、バグ調査など）
* 技術要点の整理やドキュメントの要約
* 設計や方針の壁打ち
* 英文メールの翻訳・添削
* 学習の効率化や調べもの支援

まさに“技術系なんでも相談所”といえる存在ですが、今回はその中でも「資格試験」、特に**AWS認定資格の学習**に絞って、実際に役立った活用方法を具体例とともに紹介していきます。

---

## 2. AWS資格勉強とChatGPTの相性とは？

AWS認定試験は、出題範囲が広く、初学者にはとっつきにくい内容も多いです。
特に、「選択肢の正誤」や「設問の意図」を自力で理解するのは難しく、独学に限界を感じることもあります。

そこで私が最も価値を感じたのが、**ChatGPTを1on1の家庭教師のように使う方法**でした。

### ChatGPTを家庭教師として使うメリット

* 自分の**苦手分野を分析**・特定してくれる
* 間違えた問題の**意図や背景を深掘り**してくれる
* 質問のレベルに合わせて**説明スタイルを柔軟に変えてくれる**
* 何度でも**聞き返せる**ので理解が定着しやすい

Udemyや市販の教材はカリキュラムに沿って進むため、個別対応は難しいですが、ChatGPTなら\*\*「今、知りたいこと」\*\*にピンポイントで応えてくれます。

---

## 3. 質問例と効果的なやり取り（プロンプト実例）

ChatGPTの効果を最大限に引き出すには、**プロンプト（質問の仕方）の工夫**が重要です。
以下に、実際に学習中に使って効果を感じたプロンプト例を紹介します。

### プロンプト例①：「なぜこの選択肢が正しいのか教えて」

```text
次の問題で、なぜBが正解なのか、他の選択肢と比較して理由を教えてください。
Q: S3バケットに対するアクセス制御に関する設問（中略）
A: A. ACL、B. バケットポリシー、C. IAMポリシー、D. SCP
```

→ 正解の理由と他選択肢の誤りを論理的に比較しながら解説してくれます。

---

### プロンプト例②：「自分の苦手分野を分析して」

```text
今までのやり取りから、私が理解できていないAWSサービスのカテゴリを教えて。
試験対策として、どこを重点的に復習すべきかアドバイスしてください。
```

→ 自分でも気づいていなかった**弱点領域を可視化**してくれます。

---

### プロンプト例③：「全体構成から詳細手順まで一気通貫で理解」

```text
外部ネットワークにアクセスするためのセキュアなソリューションを複数列挙し、
それぞれの構成方法、サービスの組み合わせ、具体的な手順や画面操作方法まで例を交えて詳しく教えて。
```

→ アーキテクチャの全体像から具体的設定手順まで**一貫した理解**が得られました。
教材では得られない深い実践知が身につきます。

---

## 4. ChatGPTを使って良かったこと・注意点

### ✅ 良かったこと

* **自分専用の学習パートナー**になる
* **質問の意図に応じて**説明スタイルを変えてくれる
* **検索よりも速く・深い答え**が得られる
* 構成の背景や意図まで含めた**本質的な理解**が進む

### ⚠ 注意点・コツ

* **情報の正確性は必ず確認する**（公式ドキュメントも併用）
* **プロンプトの質が回答の質を決める**（慣れが必要）
* あくまで\*\*「補助ツール」として主体的に使う\*\*意識が大切

---

## 5. まとめ：効率的に資格勉強を進めるために

ChatGPTは、使い方次第で**学習の最強パートナー**になります。

とくにAWS認定資格のように範囲が広く、理解が問われる試験では、

* 苦手分析
* 問題解説
* 設計支援
* 手順説明

といった多角的な学習支援をしてくれます。

「検索」や「動画視聴」では得られない、**会話を通じた理解の深まり**が最大の魅力です。

---

## 📌 こんな人におすすめ

* AWS資格の独学に不安がある
* 書籍や動画では理解が進まなかった
* 学習をもっと効率的に進めたい
* ChatGPTを「検索以上」に活用してみたい
フィッシングサイトかも？というときに警告を表示するブラウザ拡張機能を作りました。

Google Chrome 用: [フィッシングアラート - Chrome ウェブストア](https://chromewebstore.google.com/detail/%E3%83%95%E3%82%A3%E3%83%83%E3%82%B7%E3%83%B3%E3%82%B0%E3%82%A2%E3%83%A9%E3%83%BC%E3%83%88/kegljohlmicgajfgfpkolnfmbcelkbca?authuser=0&hl=ja)
Firefox 用: [フィッシングアラート – 🦊 Firefox (ja) 向け拡張機能を入手](https://addons.mozilla.org/ja/firefox/addon/phishing-alerts/)

![フィッシングアラート](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/205989/62b297e5-5e20-4942-960b-eab66c0271ae.png)

# これは何？

**ブラウザの履歴にないドメインにアクセスしてパスワードを入力しようとした際に、確認メッセージを表示する**ブラウザ拡張機能です。

フィッシングサイトは今までアクセスしたことがないドメインになっているはずなので、履歴にないのにパスワードを求めてくるならフィッシングサイトでは？という考えで作りました。

# よくありそうな質問と回答

**Q. 新規登録の際にも表示されてしまうのでは？**
**A. はい。**
ただ、その場合はメッセージにある「過去にアクセスしたはず」という条件に該当しないので、無視して大丈夫です。
（新規登録はそんなに頻繁に行うことはないので、割り切っています）


**Q. スマートフォンには対応していますか？**
**A. 残念ながら、対応していません。**
Google Chrome / Safari は拡張機能を入れられないためです。
また、Android 版 Firefox は拡張機能を入れられるのですが、動作に必要な [History API がサポートされていない](https://extensionworkshop.com/documentation/develop/differences-between-desktop-and-android-extensions/) ため対応できませんでした。
【Git】過去のコミットを修正する方法

## 📓 このブログを書く目的

自分のため（アウトプットの練習）

## 📝 このブログから学べること

Pushしてしまった過去のコミットを安全に修正する手順

## 📌 手順
### 1️⃣ 特定コミットの修正
- `git rebase -i` コマンドで、特定のコミットを「edit」モードで編集

```bash
# 修正したいコミットの1つ前を指定
git rebase -i XXXXXXXXXXX^
```
```bash
# エディタが開いたら、修正したいコミットの行の「pick」を「edit」に変更
edit XXXXXXXXXXX [feature]コミットメッセージなんちゃらかんちゃら
# 以下の行はそのまま
pick 2XXXXXXXXXX [fix]コミットメッセージなんちゃらかんちゃら
pick 3XXXXXXXXXX [update]コミットメッセージなんちゃらかんちゃら
```
### 2️⃣ リベースプロセス一時停止後、過去にコミットしたファイルを修正する
- 👩‍💻＜ｼｭｳｾｲ！
### 3️⃣ リベースプロセス一時停止をおわる
```bash
# ファイルを編集後
git add .
git commit --amend --no-edit # コメントそのままで
git rebase --continue        # 一時停止おわりにします
```
### 4️⃣ 変更の反映
- 強制プッシュ（`--force-with-lease`オプション付き）で変更を反映
```bash
git push --force-with-lease origin feature/XXXXXXXXXXXXXXXXXXXX
```
## 🌟 ポイント解説
### 「edit」モードとは？
リベース中の「edit」は「このコミットで一時停止して編集させて」という指示です。
これにより、コミット内容だけを変更し、メッセージはそのままにできます。
### 「--force-with-lease」の安全性
通常の `--force` はドキドキですが、`--force-with-lease` は「他の人が同時に変更していないことを確認してから強制プッシュする」という安全装置付きです。
チーム開発では常にこちらを使うのが得策に感じます。
### リベースによる履歴の書き換え
リベースはコミット履歴を「書き換える」操作です
これにより以下が発生します
- コミットハッシュが変わります（同じ内容でも新しいハッシュに）
- マージコミットが解消され、直線的な履歴になります
- コミットの順序が整理されます
## 🕊️ より安全に作業をするために
ポイント解説にも記載しましたが、**リベースはコミットハッシュが変わります**。
「--force-with-lease」を利用しても、以下の問題は解決できません。

**＜問題＞**
- **参照切れ**: JIRAなどでコミットハッシュを参照している場合、リンクが切れます
- **レビュー影響**: PRのレビューコメントが「古い変更」として扱われる可能性があります
- **チーム混乱**: 「バグは#abc123で修正した」といった会話が通じなくなります

問題が関係ありそうな場合は、以下のような対策をとったほうがいいかもです。

**＜対策＞**
1. **適用範囲を限定**: 個人ブランチや未マージのPRでのみリベースする
2. **事前通知**: チームメンバーに変更を事前に伝える
3. **タグの活用**: 重要な参照点にはコミットハッシュでなくタグを使う

リベースは強力なツールですが、チーム開発では注意して使いましょう！

## 🙄 ..（そのまま修正して再プッシュすれば？）

💡 もちろん！それもありだとおもいます。

が、わたしは、チーム開発でレビューをしてもらう立場でした。
なので、自身の立場を踏まえ、以下を意識していました。

**＜意識していたこと＞**
- コミット履歴はなるべく綺麗に（軽微な修正とコミットを繰り返さない）
- レビューの指摘対応は指摘ごとにコミットする
- このコミットでは、こんな修正してます！ということが分かりやすくなるようにする

**✨️参考にしてる考え方**

https://qiita.com/chihiro/items/04482caebc702e75e84d

そんなこんなで、リベースにたどり着いたのでした。

## 💡 まとめ
Gitは過去のコミットは、`rebase -i` と `--force-with-lease` の組み合わせで修正できます。
履歴をクリーンに保ちながら安全に作業するためにとっても便利です😄

いじょう！
だれかのお役にたてればさいわいです
（つぎは、リベース中にコンフリクトが発生した場合の対処法についても書こうかな🤔）
【振り返り】2025/04/28 〜 2025/05/02

## ご挨拶
お久しぶりです。
@HayatoHanaoka です。
投稿が滞っていましたが、これからしばらくの間は投稿を継続していこうと思います。

内容としては、 **よりアジャイル開発に適した行動ができるよう、個人の1週間を振り返ってアクションを出す**　です。
なぜこのようなことをするかというと、
今所属している組織ではアジャイル開発を採用しているのに、自分はまだまだ思想の定着や行動の適応が間に合っていないと感じたためです。

毎週金曜に1時間程度の時間を使っての振り返って投稿を行うので、内容的には少し雑になってしまう部分もあると思いますが、よろしくお願いいたします。

## 今週の行動
### 良かった
- ペアプロの際に、ドライバーをたくさん奪うことができた
- ペアで共有できれば良い話題が全体共有で話されそうになった時、
「ペアに分かれてからの共有にしませんか？」と提案することができた
- ユニットテストを書く時、自分の思う良い設計を相手に伝えることができた
### 伸び代
- CIが停滞してリリースが滞っている状況で取り組めそうなストーリーを選ぶ際、
どのストーリーの優先度が高いかの認識が正しくできていなかった
- ペアプロでペアをチェンジしたタイミングで、引き継いだ設計や既存の実装をそのまま受け取り、取り組んでしまった
- ペアで誰かに質問をする時、ペアの相手が主導で聞きに行き、自分はついていくだけのような場面があった

### 伸び代から感じる課題
- （事象）引き継いだ設計や既存の実装をそのまま受け取ってしまう
    - （問題）なぜその設計や実装なのか？を知る機会を損失する
    - （問題）よりシンプルで良い設計や実装は何かを考えるきっかけが生まれないため、成長できなくなる
- （事象）チーム外に質問を主導して聞きにいけない
    - （問題）自分が質問を言語化できないため、チームとして強くなれなくなる
    - （問題）分からないことが分からない状況が発生しやすくなる

## アクション
来週のチームとしてのアクションが「ペアチェンジを多めに行う」のようなモノなので、以下のことをアクションにします。

**よりシンプルで良い設計や実装が何かを考えるきっかけを失わないために、ペアチェンジの際に引き継いだ内容の背景や経緯について質問をする。**
# AWS SSM Parameter Storeで環境変数を管理して、Lambdaで利用する方法

# はじめに
AWS SSM Parameter Storeを利用して、Lambda関数で環境変数を管理する方法について説明します。
AWS SSM Parameter Storeは、AWSが提供するサービスで、アプリケーションの設定情報やシークレット情報を安全に保存し、管理することができます。これにより、環境変数をコードにハードコーディングすることなく、Lambda関数で利用することができます。

今回はHonoで作成したWebAPIから環境変数を取得する手順について記録します。
TypescriptやJavascriptで動くフレームワークなら同様にできるはずです。

# AWSコンソールで環境変数を作成

1. AWSコンソールにログインし、SSM Parameter Storeのページに移動します。
2. 「パラメータの作成」ボタンをクリックします。
3. 以下画像のように階層構造的に名前を入力し、パラメータの作成をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4042336/f54e2164-3ca8-4004-8466-b1bb348cae11.png)

## 実装

### AWSWrapper.ts

AWS関連クラスの継承元となる、ラッパーを作成して使っています。
環境変数に以下を定義しています
- リージョン
- アクセスキー
- シークレットキー

これらの認証情報は「AmazonSSMReadOnlyAccess」ポリシーが設定されたIAMの
セキュリティ認証情報　＞　アクセスキーを作成　から作成できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4042336/d3e9167c-62e7-4654-8a8e-57110b8b6ef7.png)

ちなみに紐づいているLambdaのIAMにも同様のポリシーが設定できている場合、環境変数は不要だったりします。

```ts
import * as AWS from "aws-sdk";
import 'dotenv/config'

export default class AWSWrapper {

  /**
   * AWS SDKのインスタンス
   */
  protected aws = AWS;

  constructor() {
    this.aws.config.update({
      region: process.env.AWS_SSM_REGION,
      accessKeyId: process.env.AWS_SSM_ACCESS_KEY,
      secretAccessKey: process.env.AWS_SSM_PRIVATE_KEY,
    });
  }
}

```

### SsmParameter.ts

パラメタの名前を引数とする関数を作成しました。
AWSのコンソールで入力した階層構造の名前を入れると環境変数の値が取得できます。

```ts
import AWSWrapper from "./AWSWrapper";
require("dotenv").config();

export class SsmParameter extends AWSWrapper {
  /**
   * AWS SSMのインスタンス
   */
  ssm = new this.aws.SSM();

  /**
   * SSMパラメータから環境変数を取得
   * @param parameterName - パラメタ名
   * @returns The value of the parameter as a string.
   */
  public async getSsmParameter(parameterName: string): Promise<string> {
    try {
      const result = await this.ssm
        .getParameter({
          Name: parameterName,
          WithDecryption: true,
        })
        .promise();

      if (!result.Parameter || !result.Parameter.Value) {
        throw new Error(
          `Parameter ${parameterName} not found or has no value.`
        );
      }

      return result.Parameter.Value ?? "";
    } catch (error) {
      console.error(`Error retrieving parameter ${parameterName}:`, error);
      throw error;
    }
  }
}
```

## 終わりに

以下のリポジトリで使ってます。

https://github.com/undo-works/SnsAutomate-Hono
asdfでuvをinstallする方法


# 【メモ】asdfでuvをインストールする手順まとめ

Pythonパッケージマネージャ`uv`を `asdf` 経由でインストールする方法についてまとめました。

`asdf` や `uv` に関する日本語情報が少なかったため、備忘録も件ねて残しておきます。

---

## ✅ インストール手順

### 1. `uv` プラグインを追加

```bash
asdf plugin add uv
```

### 2. 利用可能なバージョンを確認

```bash
asdf list all uv
```

### 3. 最新バージョンをインストール

```bash
asdf install uv latest
```

### 4. グローバルにバージョンを設定

```bash
asdf set --home uv latest
```

※ asdfのvertionが上がってからglobalコマンドが使用できなくなった為、set --homeコマンドを使用 

### 5. インストール確認

```bash
uv -V
```

バージョンが表示されればOKです。

---

## 📌 補誤

* `asdf` によってインストールされる `uv` は、プロジェクトごとのバージョン管理ができるため、開発環境の整備に便利です。
* `asdf` 自体のインストールについては、[公式ドキュメント](https://asdf-vm.com/)を参考にしてください。

---

## 🙌 おわりに

`asdf` で `uv` を扱う例はまだ多くないので、同じように環境を整えようとしている方の参考になれば幸いです。
初心者がUnityプロジェクトをGitHub連携した…その後

※ずっと使える自分用の作業メモ

※初心者が見て120％同じことができるように仕上げてる

## ✅ 手順まとめ（全体の流れ）

1. GitHubにログイン
2. フォルダ移動からのクローン
3. ブランチを作成する
4. Unityで作業
5. GitHubにアップロード（push）する
6. 作業内容をmainにマージする
7. 感想

## ✅ 1. GitHubにログイン

▶ [GitHubダッシュボード](https://github.com/dashboard) にアクセス

- 左側の `Top repositories` から `MyUnityProject` を選択

- 「<> Code ▼」→ `HTTPS` のURLをコピー

```
https://github.com/yourname/MyUnityProject.git
```

## ✅ 2. フォルダ移動からのクローン

1行目 → フォルダ移動
2行目 → プロジェクトをクローン
3行目 → プロジェクトに移動

> `git clone` = GitHub上のプロジェクトを自分のPCにコピーしてくるコマンド

「このURL先にあるプロジェクト、丸ごと持ってきて作業できるようにして」って意味

コマンドをそのままコピペでOk

```
cd %USERPROFILE%\Desktop\UnityProjects
git clone https://github.com/yourname/MyUnityProject.git
cd MyUnityProject
```

この一発で、フォルダ構成も中身も全部そのまま再現される

いちいち手動でダウンロード → 解凍 → 設定し直し…って手間がなくなる

## ✅ 3. ブランチを作成する

> `git checkout -b` = 新しいブランチを作ってそこに切り替えるコマンド

「feature/○○」みたいに名前をつけておくと、あとから見ても作業内容がわかりやすい

```
git checkout -b feature/作業内容
```

### 🔸 ブランチ名のカテゴリ一覧（独自ルール）
- **feature/機能名**：新しい構造・機能の追加  
- **fix/修正名**：バグ・挙動不正の修正  
- **adjust/調整名**：表示・位置・サイズなどの微調整  
- **add/追加名**：フォント・Prefab・マテリアルなどの導入  
- **remove/削除名**：不要なアセットやスクリプトの削除  
- **rename/改名**：命名統一・ファイル名の変更など  
- **restructure/構成名**：階層構造・Transformの整理など  
- **refactor/リファクタ名**：内部コードの整理・最適化

## ✅ 4. Unityで作業

ここはちょっと内緒にしておきたい部分なので詳細は省略

見た目の調整とか、思ったより試行錯誤したけどなんとか形にはなった

また別の機会にちゃんとまとめるかも

## ✅ 5. GitHubにアップロード（push）する

Unityのエラー（赤ログ）や見た目崩れがないかを先にチェック

※変更内容を記録する手順（`git add` / `commit`）は

[初心者がUnityプロジェクトをGitHub連携してみた](https://qiita.com/tar-app/items/f31c253c82a5abbeb97e) を参照

```
git add .  
git commit -m "実装：メッセージ"
```

作業ブランチをGitHubにアップロードする

> `git push origin feature/○○` = 作業した内容をGitHubのリポジトリにアップロードするコマンド


作った作業用ブランチがローカル（自分のPC）だけだと、GitHub上では見えないので、ここで反映させておく

```
git push origin feature/作業内容
```

## ✅ 6. 作業内容をmainにマージする

まず、作業の結果をmainブランチに反映させるには  
「mainに切り替えて → 作業ブランチの内容を取り込む」流れになる

### 🔸 ① mainブランチに切り替える

> `git checkout main` = mainブランチに切り替えるコマンド

自分のPCの作業ブランチから、mainブランチに切り替える

※マージはmain側で行うため、まずここで切り替えておく

```
git checkout main
```

### 🔸 ② GitHub上の最新状態に合わせる（保険）

> git pull origin main = GitHubの main ブランチの最新状態を自分のPCに取り込むコマンド

変更点がないか念のため、GitHub上のmainブランチの最新状態を取得しておく

```
git pull origin main
```

今回は1人作業やから不要やけど、癖づける

### 🔸 ③ 作業ブランチの内容を取り込む

> git merge = 他のブランチでやってた作業を今いるブランチに反映するコマンド

今は main にいる状態やから、「さっきの feature/作業内容 の中身を main 側に合体させる」っていう操作

つまり、作業の成果をメインラインに反映させる一番重要なステップ

```
git merge feature/作業内容
```

mainの中に、さっき作業してたブランチの変更を取り込む

この時点で変更がmainに統合される

### 🔸 ④ mainをGitHubにアップロードする

```
git push origin main
```

ローカルで変更されたmainを、GitHubのmainにも反映して完了

⚠ 本来はPull Requestを使うのが推奨

共同開発や確認フローが必要な場合は

**push → GitHubでPull Request（PR） → 内容レビューしてマージ** の方が安全で管理もしやすい

今回はひとり作業なので、直接マージでもOK

## ✅ 7. 感想


全然覚えられへんかっても大丈夫

何回も見返して繰り返してたら体で覚える

これたぶん実務でもだいぶ使えると思う