OmniAICreator/Qiita-1.07M huggingface dataset:
ChatGPTで開発効率UP！

## 🚀 ChatGPT活用術

開発をしていると、こんなことってありませんか？



💭 「手作業でのコード変換、めんどくさい…」

💭 「このメソッドの設計、これでいいのかな？」

💭 「エラー出た！原因が分からん！😱」



そんなとき、ChatGPTを活用すると 開発のスピードも質もUPするかも！ ✨

今回は、実際に使ってみて「これは便利だった！」と思った コード変換・設計相談・デバッグ の3つの活用法を紹介します！

## ChatGPTを活用している背景

エンジニア歴がある程度長いと、「コードの書き方」「設計の進め方」「エラー対応」などに慣れてしまい、新しい視点を得るのが難しくなります。そこで私はChatGPTを導入し、日々の作業を効率化したり、自分の盲点を補ったりしています。

## 活用例1：🔧コード変換・自動化

📌 **課題: バージョンアップでコードを書き直す必要が…**

Laravelのバージョンを6.xから9.xにアップグレードした際、Factoryファイルの記述方法が大きく変化し、Modeファイルファイルやテストコードに膨大な修正が必要となりました。

数百ファイルを手作業で直すのは ツライ…😇&#x20;



### 💡 ChatGPTの活用ポイント

✅ **変更点の整理**

👉 旧バージョンと新バージョンの仕様をリストアップしてもらい、変換ルールを明確化！
> [業務システムの PHP と Laravel のバージョンアップの調査・実装を 10 日間でやってみた 🚀](https://qiita.com/drafts/c4e79607365c49af6db9)

✅ **スクリプトの作成支援**

👉 Bashスクリプト作成時の正規表現や置換処理のアイデアをChatGPTに相談。
> [APIのテストをシェルスクリプトで自動化してみた🚀](https://qiita.com/shinkawa_misaki/items/95276a9cfa871e06a7e5)

### 🎉 結果

✅ 変換ルールが明確な部分はBashスクリプトで自動化することで、一気に変換完了！

✅ 変換ミスがなくなり、コードの品質もUP！

✅ 「次回のバージョンアップもこれで対応できる」と未来の自分が喜ぶ設計に！

## 活用例2：設計のトレードオフ相談

**📌 課題: メソッドの戻り値、これでいいの？**

新しいクラスやメソッドを作成する際、シンプルにするか拡張性を考えて複雑化するかの判断は難しいものです。

最近も、「シンプルに真偽値だけ返すべき？」 それとも 「他の状態も考慮したほうがいい？」 という悩みに直面しました。

後々拡張しやすいようにしたいけど、無駄に複雑にはしたくない…🤔


### 💡 ChatGPTの活用ポイント

✅ **シンプル vs 柔軟のメリット・デメリットを整理**

👉 「シンプルにすると可読性が上がる」 でも 「将来の拡張性を考えると…？」 など、設計のトレードオフを整理！

✅ **拡張性のある実装パターンを提案**

👉 「もし将来こういう仕様が増えたら？」 という視点で、より柔軟な設計案を考えてもらう！



### 🎉 結果

✅ 「なぜこの設計にしたのか？」が明確になり、迷いがなくなった！
✅ コードレビューでも説明しやすくなった！
✅ 今後の変更にも対応しやすい設計になった！


## 活用例3：デバッグのスピード向上

📌 **課題: エラーが出たけど、何が悪いのか分からない…😨**

多くのエンジニアはログを読み解き、問題箇所を特定することに時間を割きます。私自身も、複雑なエラー解析では手間取ることが多く、エラーメッセージを見ても 「うーん、これ何が原因？」 となり、検索してもピンとこなくて何時間もかかることも😱

### 💡 ChatGPTの活用ポイント

✅ **エラーメッセージを入力すると、原因の候補や解決法を即座に提示。**

👉翻訳機能を使ったり、いろんなサイトで調べたりしなくてよくなる！

✅ **デバッグ方針やログ出力方法の整理を提案。**

👉デバッグ効率が向上し、問題解決までの時間を大幅に短縮できる！



### **🎉 結果**

✅ エラーの原因を素早く特定！
✅ デバッグの効率が上がり、解決までの時間が短縮！
✅ 「次に同じエラーが出たら、すぐ直せる！」という自信がついた！


## **📌 まとめ - ChatGPTを活用すると開発がスムーズに！**  

| 活用シーン | ChatGPTの役割 | 効果 |
|-----------|-------------|------|
| **コード変換・自動化** | 仕様の違いを整理し、スクリプト作成をサポート | 手作業を削減し、変換の精度UP |
| **設計の相談** | 設計の選択肢を整理し、拡張性のある案を提案 | 迷いがなくなり、設計の質が向上 |
| **デバッグ支援** | エラーメッセージを解析し、デバッグ方針を提案 | 問題解決が早くなり、開発スピードUP |

「なんとなく検索する」よりも、**ChatGPTに相談するとスピーディに解決策が見つかる！**  
特に「パターンを整理するのが得意」なので、設計や変換ルールの整理に役立ちました💡  

✅ **バージョンアップのコード変換もラクに！**  
✅ **設計の判断に根拠を持てるようになることで自信が持てるように！**  
✅ **デバッグの時間を短縮し、ストレス軽減！**  

ChatGPTをうまく活用して、**もっと楽しく＆効率よく開発しましょう！🚀**
Pythonにおける抽象クラス変数の定義方法についての考察

# あらまし
Pythonでプログラムを設計してて、「抽象クラス変数」を使いたいなーと思いました。

## イメージ
```python
from abc import ABC

class AbstractClass(ABC):
    name: ABSTRACT[str] # ←イメージ

    def greet(self):
        return f'Hello, I am {self.name}.'

class ConcreteClass(AbstractClass):
    name = 'Alice' # ←具象クラスで値を定義

class InvalidConcreteClass(AbstractClass):
    pass # ←定義しなかったら型チェックでエラーにしたい
```

ただ、[abc --- 抽象基底クラス — Python 3.13.2 ドキュメント](https://docs.python.org/ja/3.13/library/abc.html)をいくら読んでもそれっぽい方法がない・・・
そのため、ネット検索して出てきた方法を書いてみる


# 案

## 方法①: クラスプロパティにする
```python
from abc import ABC, abstractmethod

class AbstractClass(ABC):
    @classmethod
    @property
    @abstractmethod
    def name(cls) -> str:
        ...

    def greet(self):
        return f'Hello, I am {self.name}.'

class ConcreteClass(AbstractClass):
    @classmethod
    @property
    def name(cls) -> str:
        return 'Bob'

c = ConcreteClass()
c.greet()
# => 'Hello, I am Bob.'
```

Copilotに聞いたらこの方法を提案された。
ただ、見てのとおりかなりデコレータとプロパティ定義に長い記述が必要になる。


## 方法②: 抽象クラスのコンストラクタでチェックする
```python
from abc import ABC

class AbstractClass(ABC):
    name: str

    def __init__(self):
        if not hasattr(self, 'name'):
            raise TypeError(f"Can't instantiate abstract class {self.__class__.__name__} with abstract class variable name")
        super().__init__()

    def greet(self):
        return f'Hello, I am {self.name}.'

class ConcreteClass(AbstractClass):
    name = 'Charlie'

class InvalidConcreteClass(AbstractClass):
    ...

c = ConcreteClass()
c.greet()
# => 'Hello, I am Charlie.'
InvalidConcreteClass()
# => TypeError: Can't instantiate abstract class InvalidConcreteClass with abstract class variable name
```

今回採用したのはコレ。
どこかのウェブサイトで見つけたが、URLを失念してしまった。。。見つけたら更新します。
考え方としては抽象クラスではクラス変数の宣言だけしておいて、
コンストラクタの中で実在確認をするように仕込んでおく。

デメリットとしては2点:

1. 抽象クラスのコンストラクタの記述がちょっとめんどい。また、抽象クラス変数名を複数箇所に記述する必要がある
1. サブクラスでコンストラクタをオーバーライドした場合、 `super().__init__()` をちゃんと呼んでくれないとチェックがスキップされてしまう。(強制できない)


## 方法③: クラス継承時にチェックする
```python
from abc import ABC

class AbstractClass(ABC):
    name: str

    def __init_subclass__(cls, *args, **kwargs):
        if not hasattr(cls, 'name'):
            raise TypeError(f"Can't inherit abstract class {cls.__name__} with abstract class variable name")
        super().__init_subclass__(*args, **kwargs)

    def greet(self):
        return f'Hello, I am {self.name}.'

class ConcreteClass(AbstractClass):
    name = 'Charlie'

c = ConcreteClass()
c.greet()
# => 'Hello, I am Charlie.'

class InvalidConcreteClass(AbstractClass):
    ...
# => TypeError: Can't inherit abstract class InvalidConcreteClass with abstract class variable name
```

方法②では抽象クラスをインスタンス化しようとしたタイミングでエラーが出たが、
こちらはクラス定義の時点でエラーとなる。
中間抽象クラスが絶対に不要ならばこれでもいいと思う。
[共同開発] pullではなくてfetch+mergeが使われる理由

## そもそも
pullとfetchは，リモートの最新状態を，ローカルに反映させるものですが，少し違います．

## pull
リモートの最新状態をローカルに取得してきた後，マージをします．

```
git checkout main  # mainブランチに移動
git pull origin main
```
ローカルの main に未コミットの変更があると，競合が発生する可能性があります．

## fetch
リモートの最新状態を，ローカルに取得してくるだけで，マージはしません．
取得したデータは，下記の保存場所に一旦保存されるだけで，ローカルの現在編集しているデータが変更されることはありません．
|データの種類	| 保存場所
|:-------------------:|:--------------------:|
|   リモートブランチ情報 |  .git/refs/remotes/origin/ |
| コミットオブジェクト  | .git/objects/  |
| リモートのHEAD情報  |  .git/FETCH_HEAD |

共同開発においては，fetchで最新状態を取得した後，mergeで統合をするのが一般的です．

リモートのmainをローカルのmainに取り込むばあ
	
```
git checkout main
git fetch origin   # リモートの最新情報を取得（適用しない）
git merge origin/main  # リモートの変更をローカルの main に適用
```

※リモートの別ブランチ（ここではfeature-xyz）をfetchしてから，ローカルのmainに取り込む場合
```
git checkout main
git fetch origin   # リモートの最新情報を取得（適用しない）
git merge origin/feature-xyz
```

:::note 
共同開発でfetch+mergeを使用する理由

共同開発をしていると，たくさんのブランチを切って並行して開発を進める機会が多いです．そのため，ブランチをマージする機会が多くなり，いきなりpullしてしまうとコンフリクトが発生してしまい，面倒なことになってしまうのです．
:::
+=（複合代入演算子） と padStart() で時刻計算をスマートに！

時刻計算問題でズレまくった話。+= の力を知らずに…。でも += と padStart() を使えば一発解決した！


<br>📌 問題概要
「XX:XX」形式の時刻を受け取り、30分後の時刻を同じ形式で出力する。

🔹 入力例: "12:31"
🔹 出力例: "13:01"

<br>**NGコード例（僕の最初の挑戦）**
```js
rl.on('line',(line) => {
    const time = line.split(":");
    const Time = time.map(Number);
   
    if (Time[1] + 30 < 60){
        console.log(Time[0] + ":" + (Time[1] + 30));
    }else {
        console.log((Time[0] + 1) + ":" +  (Time[1] - 30));
    }
})
```

❌ 60分超えたときの処理ミス
❌ "1:32" みたいにゼロ埋めされない

<br>**改善版コード例**
 ```js
 let [hours, minutes] = line.split(":").map(Number);
minutes += 30;
if (minutes >= 60) {
    minutes -= 60;
    hours += 1;
}
const formattedTime = String(hours).padStart(2, '0') + ":" + String(minutes).padStart(2, '0');
console.log(formattedTime);
```
✅ += 30 で一気に足す
✅ minutes >= 60 なら -60 & hours += 1
✅ padStart(2, '0') で "01:32" のように2桁固定

<br>💡 まとめ
🔹 += / -= で数値を直接更新してスッキリ
🔹 padStart(2, '0') でゼロ埋めフォーマット
🔹 String() で数値を文字列に変換し padStart() を適用

[僕の失敗談と解決話！ 🚀](https://paizabeginner.wordpress.com/2025/03/05/paiza%e3%81%a7%e5%9f%ba%e6%9c%ac%e3%83%9e%e3%82%b9%e3%82%bf%e3%83%bc-padstart%e3%82%92%e9%a7%86%e4%bd%bf%e3%81%97%e3%81%a6%e6%99%82%e5%88%bb%e8%a8%88%e7%ae%97%ef%bc%88%e8%a4%87%e5%90%88/)
Difyをv1.0.0にマイグレーションする手順


この記事では、Difyをv1.0.0にマイグレーションする手順を解説します。公式ドキュメントに基づき、具体的なコマンドや手順を段階的に説明します。

## はじめに

Difyのマイグレーションを行う際は、データを失わないようにするために事前に**バックアップを取得することを推奨**します。バックアップの実施方法については、以下の公式ドキュメントをご参照ください。

**[Dify公式マイグレーションガイドはこちら](https://docs.dify.ai/ja-jp/development/migration/migrate-to-v1)**

私は趣味で利用しているだけなので、この記事の手順では、バックアップを取得せずにマイグレーションを行うプロセスを説明します。必要に応じてバックアップを行った上で、以下の手順を進めてください。

---

## マイグレーション手順

以下に、各ステップごとの詳細な作業手順を説明します。

### 1. Difyディレクトリに移動

Difyの管理ディレクトリに移動します。

```bash
cd /github
cd dify
```

### 2. コードの最新化

Difyプロジェクトを最新バージョンに更新します。

```bash
git pull
```

### 3. Dockerの再起動

プロジェクトの依存関係を正しく動作させるために、Dockerコンテナを停止し、再起動します。

```bash
cd docker
docker-compose stop ; docker-compose up -d
```

---

### 4. プラグイン情報のマイグレーション

#### 4.1 コンテナにログイン

DifyのDockerコンテナに入る必要があります。以下のコマンドを実行し、`docker-api-1`コンテナにアクセスします：

```bash
docker exec -it docker-api-1 bash
```

#### 4.2 プラグイン情報を抽出する

コンテナ内部で、プラグイン情報の抽出を行います。以下のコマンドで実行可能です：

```bash
poetry run flask extract-plugins --workers=20
```

#### 4.3 プラグインをインストールする

次に、抽出されたプラグイン情報に基づいてプラグインをインストールします。

```bash
poetry run flask install-plugins --workers=2
```

#### 4.4 コンテナからログアウト

コンテナ内での作業を終了したら、以下のコマンドでコンテナから出ます：

```bash
exit
```

---

### 5. Dockerの再起動

プラグインマイグレーションが完了した後、念のためにもう一度Dockerコンテナを再起動します。

```bash
docker-compose stop ; docker-compose up -d
```

これにより、変更が全体的に適用され正しく反映されます。

---

## おわりに

以上で、Difyをv1にマイグレーションする手順の説明を終わります。この手順に従えば、簡単に最新バージョンへの移行が可能です。

問題が発生した場合は、公式ドキュメントや関連するコミュニティフォーラムを参照してください。Enjoy!!

---

## （おまけ）

私の環境では gpt-4o の JSON Schema を使っていたワークフローがエラーで動かなくなりました。

原因は、gpt-4o-2024-11-20 のモデルを指定していたのに gpt-4o になっていてエラーになっていました。

ワークフローを開いてモデルを gpt-4o-2024-11-20 にすれば解消します。
React + TypeScriptでTodoリストを作りながら学んだ、コンポーネントの仕組みと状態管理のポイント

# React + TypeScriptでTodoリストを作りながら学んだ、コンポーネントの仕組みと状態管理のポイント

## はじめに

最近、React と TypeScript を使ってTodoリストアプリを作成する機会がありました。単純なアプリケーションのように見えて、実は多くの学びがある開発プロセスでした。この記事では、開発中に気づいた興味深いポイントや、つまずいた部分とその解決策について共有します。

## 使用した技術スタック

- React
- TypeScript

## 実装のポイント

### 状態管理と型定義

```typescript
type Todo = {
  value: string;
  // 本来はuuidが好ましい
  id: number;
  checked: boolean;
};

const [todos, setTodos] = useState<Todo[]>([]);
const [value, setValue] = useState<string>("");
```

Todoの型を明確に定義することで、型安全性を確保しました。各Todoは文字列の値、一意のID、完了状態を持ちます。

### イベントハンドリング

#### 入力値の取得

```typescript
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
  setValue(e.target.value);
};
```

`React.ChangeEvent<HTMLInputElement>` 型を使用することで、入力イベントの型安全性を確保しています。

#### フォーム送信

```typescript
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
  e.preventDefault();
  if (value === "") return;

  const newTodo: Todo = {
    value: value,
    id: todos.length,
    checked: false,
  };

  setTodos([...todos, newTodo]);
  setValue("");
};
```

`e.preventDefault()`でフォームのデフォルト送信動作を防ぎ、空の入力を防止しています。

## つまずいたポイントと解決策

### 1. Todoの編集処理

```typescript
const handleEdit = (id: number, value: string) => {
  const newTodos = todos.map((todo) => {
    if (todo.id === id) {
      todo.value = value;
    }
    return todo;
  });

  setTodos(newTodos);
};
```

#### なぜ`map`を使うのか？

- 状態の不変性を保つため
- 新しい配列を作成し、特定のTodoのみを更新
- Reactの再レンダリングを効率的に行う

### 2. チェックボックスの状態管理

```typescript
const handleChecked = (id: number, checked: boolean) => {
  const newTodos = todos.map((todo) => {
    if (todo.id === id) {
      todo.checked = !checked;
    }
    return todo;
  });

  setTodos(newTodos);
};
```

論理否定演算子`!`を使用して、現在の状態を反転させています。

### 3. Todoの削除

```typescript
const handleDelete = (id: number) => {
  const newTodos = todos.filter((todo) => todo.id !== id);
  setTodos(newTodos);
};
```

`filter`メソッドを使用して、特定のIDを持つTodoを除外した新しい配列を作成します。

## 学んだこと

1. **型の重要性**
   - TypeScriptの型定義により、コードの信頼性が向上
   - イベントハンドリングの型安全性

2. **状態管理の基本**
   - 不変性の維持
   - `map`、`filter`を使用した状態更新
   - スプレッド演算子による配列の展開

3. **イベントハンドリングの奥深さ**
   - 異なるイベント型の理解
   - `preventDefault()`の重要性

## おわりに

このTodoリストの開発を通じて、Reactと TypeScriptの基本的な仕組みをより深く理解できました。まだまだ改善の余地はありますが、着実に学びを深めていきたいと思います。
AWS SAAに関するメモ

# はじめに
これはSAAの勉強を始めてから受かるまで更新するメモです。

# 登場するサービス一覧

| サービス名        | できること（ざっくり）                          | もっと噛み砕くと…                          |
|-----------------|--------------------------------|--------------------------------|
| EC2            | 仮想マシン（サーバー）を動かす         | AWSのパソコンをレンタルできる            |
| EBS            | EC2のHDD/SSD（ストレージ）     | EC2のデータ保存用のHDD             |
| S3             | 画像やファイルを保存する（オブジェクトストレージ） | ネット上の倉庫（写真・動画・CSVなど）      |
| VPC            | AWS内にネットワークを作る        | AWSの中に自分専用のネットワークを作れる     |
| Route 53       | ドメインの管理（DNS）          | example.com をAWSで管理         |
| ELB            | 負荷分散（トラフィックを分ける）    | 混雑しないように複数のサーバーに振り分ける  |
| Auto Scaling   | EC2を自動で増やしたり減らしたりする | アクセス増えたらサーバーを増やす         |
| RDS            | 管理されたリレーショナルDB（MySQL, PostgreSQLなど） | いい感じに管理してくれるデータベース      |
| DynamoDB       | NoSQLデータベース（爆速のキー・バリューストア） | 超高速のテーブル（Excelみたいなやつ）    |
| Lambda         | サーバーレスでコードを実行する    | 短いプログラムをちょこっと動かす        |
| API Gateway    | APIの入口（リクエスト管理）      | APIの窓口（受付係）                |
| CloudFront     | CDN（コンテンツを速く配る）      | 画像や動画を世界中の近い場所から配る    |
| IAM            | ユーザーや権限の管理           | 誰が何をできるかの設定              |
| CloudWatch     | ログやメトリクスを監視する       | サーバーの動きをモニタリング          |
| CloudTrail     | AWSの操作履歴を記録する        | 誰が何をしたかの監視カメラ           |
| SNS            | メッセージを送る（プッシュ通知・メールなど） | メールや通知を一斉送信             |
| SQS            | メッセージキュー（非同期処理）    | 「これやっといて！」と指示を出しておく箱  |
| Kinesis        | リアルタイムデータ処理         | 連続するデータ（ログ・動画・センサー情報）を処理 |
| ECS / EKS      | コンテナを動かす（Docker, Kubernetes） | コンテナ（アプリの箱）をAWSで管理     |
| Step Functions | 処理を順番に実行する（ワークフロー管理） | 「Aが終わったらB、それが終わったらC」を自動化 |
| Secrets Manager | APIキーやパスワードを安全に保管する | パスワードを安全に管理する金庫         |
| CloudFormation | AWSのリソースをコード化（IaC）  | AWSの設定をコードにして管理         |
| Organizations  | AWSアカウントをまとめて管理      | 複数のAWSアカウントを一括管理        |
「状態の変化」が禁止されている言語でどうやって繰り返し処理するの？【Haskellと再帰関数】

# 記事の内容
## 「副作用がないこと＝状態を変化させないこと」と繰り返し処理を両立させたい。どうすればいいの？

Haskellのような純粋関数型プログラミングにおいて、「副作用がないこと＝状態を変化させないこと」と再帰がどのように関係しているのか、整理しましょう。

関数型言語の初心者向けの内容です。

専門家と高校生の会話形式でまとめています。

---

## 目次
1. [Haskellにおける「副作用がないこと」と再帰の関係性](#1-haskellにおける副作用がないことと再帰の関係性)
2. [プログラムにおける「状態」の定義](#2-プログラムにおける状態の定義)
3. [プログラムにおける「状態の変化」の定義](#3-プログラムにおける状態の変化の定義)
4. [なぜ再帰関数は状態を変化させないのか　再帰関数のしくみ](#4-なぜ再帰関数は状態を変化させないのか-再帰関数のしくみ)
5. [Haskellの再帰実行中に生成される新しい値たちの管理方法](#5-haskellの再帰実行中に生成される新しい値たちの管理方法)
6. [まとめ](#6-まとめ)
7. [参考文献](#7-参考文献)

---

## 1. Haskellにおける「副作用がないこと」と再帰の関係性

### 高校生:
「副作用がないってどういう意味なんですか？そして、なぜ再帰がその実現に役立つのでしょうか？」

### 専門家:
「Haskellでは、一度計算された値は決して変わらず、変数の値を直接更新することがありません。つまり、プログラム実行中に『状態』が変わることがなく、その結果、副作用が生じません。再帰は、この性質を保ちながら繰り返し処理を行うための重要な手法です。再帰を使えば、状態を直接更新するのではなく、前の状態に基づいて新しい状態を『生成』できます。」

---

## 2. プログラムにおける「状態」の定義

### 高校生:
「状態って具体的に何を意味するんですか？」

### 専門家:
「プログラムにおける『状態』とは、ある瞬間にプログラムが保持しているすべての情報、つまり変数やデータの集合のことです。これは、『今、この瞬間にプログラムがどんな値を保持しているか』というスナップショットのようなものです。命令型プログラミングでは、この状態が随時更新されますが、Haskellのような純粋関数型言語では、状態は一度決定されたら変わらない不変のものとして扱われます。」

---

## 3. プログラムにおける「状態の変化」の定義

### 高校生:
「じゃあ、『状態の変化』とは何ですか？」

### 専門家:
「状態の変化とは、プログラム内で保持される情報が更新されることです。  
- **命令型プログラミング**では、変数の再代入により状態が変わります。  
- **関数型プログラミング**では、既存の値を直接更新するのではなく、前の状態をもとに『新しい状態』が計算され、返されます。」

---

## 4. なぜ再帰関数は状態を変化させないのか　再帰関数のしくみ

### 高校生:
「再帰は、なぜ状態を変化させないのに処理を繰り返せるんですか？」

### 専門家:
「再帰は、関数が自分自身を呼び出すことで繰り返し処理を実現します。再帰の核心は、引数として新しい状態を渡すことです。具体例を見ましょう。」

#### 具体例: 階乗計算
```haskell
factorial :: Integer -> Integer
factorial 0 = 1                    -- 基底条件
factorial n = n * factorial (n - 1)  -- 再帰呼び出し：nから新しい状態(n - 1)を生成
```
「nの値は再帰呼び出しのたびに減少、つまり、更新されていると解釈してはいけません。各関数呼び出しは独立して計算されるため、関数を呼び出すたびに新しい状態を生成しています。つまり、古い状態はそのまま残っているという点が純粋性を保っています。」

### 高校生:
「つまり、再帰では前の状態を変更するのではなく、常に『新しい状態』を作り出すということですね。」

### 専門家:
「その通りです。これがHaskellでの不変性（immutability）を保ちながら、複雑な計算を実現する方法です。」

## 5. Haskellの再帰実行中に生成される新しい値たちの管理方法

### 専門家:
「Haskellでは、以下の仕組みによって新しい値が管理されています。」

- **グラフリダクション**  
  Haskellは、プログラムの評価をグラフの縮約として扱います。これにより、同じ計算が繰り返されないようにします。

- **遅延評価とサンク (Thunk)**  
  必要になるまで値を計算せず、必要になったときに初めて評価します。評価済みの結果はキャッシュされます。

- **コールスタックと最適化**  
  Haskellのコンパイラは、再帰呼び出しが深くならないように最適化（例えば末尾再帰最適化）を行います。

---

## 6. まとめ

- **副作用がないとは**:  
  値が不変で、同じ入力に対して常に同じ出力を返すこと。  
- **再帰の利点**:  
  再帰は今ある状態を直接変更せず、新しい状態を生成する。  
- **Haskellの管理方法**:  
  グラフリダクション、遅延評価、最適化によって効率的に値を管理。

---

## 7. 参考文献
- Haskell Wiki, *Lazy Evaluation*  
  [https://wiki.haskell.org/Lazy_evaluation](https://wiki.haskell.org/Lazy_evaluation)
Excel VBA 選択したグラフの書式・大きさにグラフを統一する

## はじめに
マクロを使い、エクセルファイル内にある複数の同じ形式のグラフの書式や大きさを統一する方法について考えたい。

## マクロ作成の経緯
複数の同じ形式のグラフの書式や大きさを調整する際に、1つ変更すれば、他のグラフにも、その変更を適用できたらと考えたのがきっかけだった。

## 作成したマクロの概要
エクセルのグラフテンプレート機能を使い、選択したグラフのテンプレートファイルを一時的に作成し、他の同じ形式のグラフに適用する。

### 動作手順
1. グラフが選択されているか確認
1. 選択されているグラフの幅・高さ・グラフの種類を取得
1. 選択されているグラフのテンプレートを保存
1. 書式・大きさを適用するかどうかのメッセージを表示
1. 各シートのグラフに対して、同じグラフの種類かどうかを確認
1. 同じグラフの種類の場合、テンプレートを適用し、大きさを調整する
1. 保存したグラフのテンプレートを削除


### 注意点
- Chart.ChartTypeプロパティで返されるグラフの種類(XlChartType)で同じ形式か判断するため、見た目は同じでも、違うグラフの場合がある

https://learn.microsoft.com/ja-jp/office/vba/api/excel.xlcharttype


## 完成したマクロ
```VB:ApplySameFormatCharts
Public Sub ApplySameFormatCharts()

Dim TemplateChartObject As ChartObject
Dim TemplateChartName As String
Dim TemplateChartWidth As Double
Dim TemplateChartHeight As Double
Dim TemplateChartType As XlChartType
Dim Rtn_Size As Long
Dim Rtn_Temp As Long
Dim TargetSheet As Worksheet
Dim TargetChartObject As ChartObject

    If ActiveChart Is Nothing Then   
        MsgBox "グラフが選択されていません。グラフを選択してから実行してください。"
        Exit Sub
    End If
    
    Set TemplateChartObject = ActiveChart.Parent
    
    TemplateChartWidth = TemplateChartObject.Width
    TemplateChartHeight = TemplateChartObject.Height
    TemplateChartType = TemplateChartObject.Chart.ChartType
    
    TemplateChartName = ThisWorkbook.Path & "\グラフテンプレート" & Format(Now, "yymmdd_hhmmss")
    TemplateChartObject.Chart.SaveChartTemplate TemplateChartName

    Rtn_Temp = MsgBox("選択中のグラフの書式を適用しますか？", vbYesNo + vbQuestion)
    Rtn_Size = MsgBox("選択中のグラフの大きさを適用しますか？", vbYesNo + vbQuestion)
    
     For Each TargetSheet In ActiveWorkbook.Sheets 
        For Each TargetChartObject In TargetSheet.ChartObjects
            If TargetChartObject.Chart.ChartType = TemplateChartType Then
                
                If Rtn_Temp = vbYes Then 
                    TargetChartObject.Chart.ApplyChartTemplate (TemplateChartName)
                End If
                
                If Rtn_Size = vbYes Then
                    TargetChartObject.Width = TemplateChartWidth
                    TargetChartObject.Height = TemplateChartHeight
                End If
                
            End If
        Next TargetChartObject
    Next TargetSheet
    
    Kill TemplateChartName & ".crtx"
    
End Sub

```

サンプルファイル：

https://github.com/rie1234k/ExcelVBA_Tips/tree/master/ApplySameFormatCharts
【Vue3】コンポーザブルの依存関係を明確にして状態管理を安全で分かり易くする

# コンポーザブルの依存関係を明確にする方法
コンポーザブルの依存関係を明確にするには、以下の要素が必要です

:::note info
- コンポーネントから状態とロジックをコンポーサブルに切り出す
- `useState`を使わない
- `provide` / `inject`を使う
- コンポーザブルの引数にコンポーザブルを取る
:::

# コンポーネントから状態とロジックをコンポーサブルに切り出す
これはコンポーザブルを使いましょうという話です。
コンポーザブル関数の詳細は公式を参照してください↓

https://ja.vuejs.org/guide/reusability/composables

たいてい状態とロジックはセットで存在しています。
Vue3ではSFC内のscriptタグ、templateタグ、styleタグにコーディングを行いコンポーネントを作成しますが、scriptタグ内に書かれている状態とロジックはできる限りコンポーザブルに移行する方が良いと思います。
もちろん状態/ロジックとは言っても、業務に直接関わるドメイン的な状態&ロジックや表示用の状態&ロジックがあるわけですが、そこは別々にコンポーザブルを作成するなどの工夫でより保守性・可読性を高めることができます。

# `useState`を使わない
これは基本的にグローバルに状態管理をしないということです。
`useState`を使うと全てのコンポーサブル/コンポーネントどこからでもアクセス出来てしまいます。どこからでもアクセスできるということは、状態に対する不適切な操作が入り込む隙を生みます。グローバルな状態管理はユーザー情報など最低限に抑えたほうがいいでしょう。

`useState`を使わない場合、**コンポーザブル内で定義したリアクティブ変数を用いて状態を管理**します。

#  `provide` / `inject`を使う
上記の通り、状態管理にコンポーザブル内で定義したリアクティブ変数を使う場合、問題になるのは同じコンポーザブルでも別々の箇所で呼び出したコンポーサブルの状態は当然別ということです。
親コンポーネントで呼び出したコンポーザブルの状態と子コンポーネントで呼び出したコンポーザブルの状態は、同じコンポーザブルを使っていても別物として扱われるため繋がりがありません。この場合、子コンポーネントで状態に対する操作を行なっても、親コンポーネント側の状態は変化しません。
そこで`provide` / `inject`を使います。↓

https://ja.vuejs.org/guide/components/provide-inject

コンポーザブルの呼び出しは親コンポーネントで行い、それを`provide`を用いて子/孫コンポーネントに公開します。子/孫コンポーネントは`inject`でそのコンポーザブルを参照することで、同じコンポーザブルを参照していることになり、状態も共有されます。つまりこの場合、アプリケーション内で**コンポーザブルを呼び出すのは１回だけ** ということです。

これは特定のコンポーネントツリーの中だけで共有する状態を定義できるということでもあります。

# コンポーザブルの引数にコンポーザブルを取る
この点が本記事の肝ですが、コンポーサブルの引数で別のコンポーザブルを受け付けることでコンポーザブルの依存関係を明確に出来ます。これは同時に**状態の関係性が明確になる**ということでもあります。

例えば、フォーム入力項目のデータ型とAPIリクエストのデータ型が異なる場合などは、状態を分離することでその差異を保守性を担保した形で吸収できますが、この場合フォームの入力情報（表示に関する状態）がAPIリクエスト（ドメインに関する状態）に依存することで、前者の状態変化を後者に適切に反映できます。またコンポーネントから直接ドメインに関する状態を操作できないように制御できる他、TypeScriptファイルに**関数同士の関係として記述されることになるのでテストが圧倒的に楽になる**というメリットがあります。

実装的には、フォームの状態を管理するコンポーザブルの引数にAPIリクエストの状態を管理するコンポーザブルを受け取れるようにするということです。
IDをnumberではなくstringにする理由を考えた

内容薄いかもです (^^;)

## なぜ調べようと思ったか
- 例として、以下のようなテストを表現する型があるとする
- これらの型を使って、テスト結果の答え合わせをするときに、データを`questionId`でソートすると考える（なお、idは1や2などの数字である）
- その際に、**`string`型よりも`number`型の方が比較が楽だと思った**
- しかしながら、一般的にidは`string`型が良いとされていることに疑問を感じた

```typescript: 型定義
type Test = {
    questions: Question[]
    answers: Answer[]
}

type Question = {
    id: number 
    content: string //問題文
    options: Option[]
}

type Option = {
    id: number
    content: string //選択肢
}

type Answer = {
    questionId: number
    correctOptionId: number
}

type UserAnswer = {
    questionId: number
    selectedOptionId: number
}
```

```typescript:答え合わせ
 // number型によるソートは、とても簡単である
 // [2,10,1]と言う場合にも対応
 const sortedAnswers = test.answers.sort((a, b) => a.questionId - b.questionId)

 // questionIdがstring型である時のソート
 // toString()を使う必要がある
 const sortedAnswers2 = test.answers.sort((a, b) => a.questionId.toString() - b.questionId.toString())
```

## 先にまとめ
- idにはナチュラルキーとサロゲートキーがある
- string型にするメリットは、IDのフォーマットによる型の問題を回避できること、開発者間での型の統一が容易であること
- 結局は、トレードオフだったり、その時の状況による


## そもそもidにも種類が2つあるらしい

### 1. ナチュラルキー
- ナチュラルキーとは、データそのものが持つ固有の特性や属性から生成される識別子
- 簡単に言うと入力データ自体をPKになる時、それはナチュラルキーとなる

**具体例：**

| 種類 | 例 |
| --- | --- |
| 社員番号 | AA12345678 |
| 電話番号 | 090-1234-5678 |
| メールアドレス | example@example.com |
| 商品コード | FOOD-1234 |

**特徴：**
- 実世界の意味を持つ
- データから直接導き出される
- 人間が理解しやすい
- 既存のビジネスプロセスと整合性がある場合が多い

### 2. サロゲートキー
- サロゲートキー（代理キー）とは、データの内容とは無関係に、システムによって自動生成される人工的な識別子
- あくまでユニークになる連番なので、業務的は意味を持つ値ではない

**具体例：**

| 種類 | 例 |
| --- | --- |
| 自動採番ID | 1, 2, 3, ... |
| UUID/GUID | `550e8400-e29b-41d4-a716-446655440000` |

**特徴：**
- データの内容と無関係
- システムによって自動生成される
- 変更されることがない
- ビジネスルールの変更に影響されない

> さらに詳しくは、[リンク](https://qiita.com/masapiko/items/05c393379c2eb42c86f5)を参照のこと

## idをstring型にするメリット
1. number型と比べて表現できる幅が多い
2. IDのフォーマットによって型を気にしなくていい
3. 開発者間での型の統一が容易で、設計判断が明確化される


**考察：**
- サロゲートキーにおいては、「1」はそこまでメリットではない
- 2, 3がサロゲートキーにおいてもメリットになるであろう
- チーム間での認識を揃えやすくさせたいのであれば、特に有効であろう

## 結局はトレードオフだったり、その時の状況による
書いてて感じたのは、「どこに複雑性を持たせるか」が論点になってくる？
例えば、
- IDによって、string型とnumber型の使いやすい方を選ぶ
    - メリット：ソートロジックは簡潔で済む
    - デメリット：開発者間のコミュニケーションが複雑になる
- IDをstring型で固定する
    - メリット：IDのフォーマットによって型を気にしなくていい
    - デメリット：ソートロジックが多少複雑になる

## 自分の場合
- 自分の場合、開発者間でもコミュニケーションが簡潔になる方が、重要だと考える
- そのため、string型にするのが良いと思った
- ただ、今回の例のような`Test`型で`question`や`option`の数が、せいぜい4~10個とかの場合は、number型でも良い気はする



## 参考資料
https://qiita.com/sato-shin/items/0ec486d9c1bf98d9bf4c

https://qiita.com/doyaaaaaken/items/8c7eea95ac27a75ca7bf

https://qiita.com/masapiko/items/05c393379c2eb42c86f5
ServiceNowで更新日が古いデータを用意する

# 概要
- 1週間以上何も更新されていないインシデントに対してスケジュールジョブによるバッチ処理でメールを通知する仕組みを導入したときに1週間以上何も更新されていないインシデントのデータを用意する必要があった。
- 普通に更新したら現在日時で更新されてしまうからどうしたものかと思っていた。

# 解決案
- ``gr.autoSysFields(false)`` というメソッドを使えばsys_updated_onへの自動更新がされないので、設定した値で更新することができる。
- https://www.servicenow.com/docs/ja-JP/bundle/vancouver-api-reference/page/app-store/dev_portal/API_reference/GlideRecord/concept/c_GlideRecordAPI.html#title_r_GlideRecord-autoSysFields_Boolean

# サンプル

```
var gr = new GlideRecord('incident');
var sys_id = 'hogehoge' //実際はハッシュ値;
if (gr.get(sys_id)) {
    gr.autoSysFields(false);  // 更新者情報を変更しない
    gr.sys_updated_on = '2025-02-02 00:00:00';

    var success = gr.update();
    gs.info('Update success: ' + success);
}
```
React Hook FormのuseFieldArrayで現在の値を取得する方法

# 概要
React Hook Form の `useFieldArray` は、フォームのフィールドを動的に追加・削除できる便利なフックです。

「現在の入力値を取得したい」と思ったときに、`fields` を参照しても意図した値が得られないことがあります。

本記事では 「`useFieldArray` の現在の値を正しく取得する方法」 を解説します！✨

# 1. useFieldArray で現在の値を取得するには？
`useFieldArray` の `fields` は、フォームの入力データそのものではなく、レンダリングのための情報を提供するものです。

したがって、以下のように `fields` を直接使っても、リアルタイムな入力値は取得できません。

```tsx
console.log(fields); // 現在の入力値は取得できない！
```

## ✅ 正しく取得する方法 → `watch` を使う
`useForm` には `watch` という関数があり、フォームの現在の状態をリアルタイムで取得できます。

つまり、`watch("items")` を使うことで、`useFieldArray` の現在の値を簡単に取得できます！

# 2. `watch` を使った実装例

以下のコードでは、動的にフィールドを追加・削除しながら、リアルタイムで現在の入力値を表示しています。

```tsx
import { useForm, useFieldArray } from "react-hook-form";

type FormValues = {
  items: { name: string }[];
};

export default function MyForm() {
  const { control, register, handleSubmit, watch } = useForm<FormValues>({
    defaultValues: { items: [{ name: "" }] }
  });

  const { fields, append, remove } = useFieldArray({
    control,
    name: "items"
  });

  // ✅ 現在の値をリアルタイムで取得
  const watchedItems = watch("items");

  return (
    <form onSubmit={handleSubmit((data) => console.log(data))}>
      {fields.map((field, index) => (
        <div key={field.id}>
          <input {...register(`items.${index}.name`)} />
          <button type="button" onClick={() => remove(index)}>削除</button>
        </div>
      ))}
      <button type="button" onClick={() => append({ name: "" })}>追加</button>

      {/* ✅ 現在の値を表示 */}
      <pre>現在の値: {JSON.stringify(watchedItems, null, 2)}</pre>

      <button type="submit">送信</button>
    </form>
  );
}

```

# 3. `watch` を使うメリット
`watch("items")` を使うことで、以下のようなメリットがあります。

✅ リアルタイムに値を取得できる
- `useFieldArray` の `fields` では取得できない「現在の入力データ」がすぐに取れる！


✅ 余計なステート管理が不要
- `useState` を使わなくても `watch` だけで値を取得できるため、シンプルな実装が可能！

✅ フォーム全体の変更を即座にキャッチできる
- `watch` は他のフィールドの変更を監視できるので、フォーム全体のデータをリアルタイムで扱いたいときにも便利！

# 4. `key` の設定について（補足）
[React Hook Form の公式ドキュメント](https://react-hook-form.com/docs/usefieldarray)には、以下のような注意書きがあります。

>The field.id (and not index) must be added as the component key to prevent re-renders breaking the fields:

(`key` には `index` ではなく `field.id` を使うこと。そうしないと、再レンダリングでフィールドの内容が壊れる可能性がある)

実際に、以下のように `index` を `key` に使うと、削除時に入力内容がずれることがあります。

```tsx
// ❌ index を key に使うのは NG！
{fields.map((field, index) => (
  <div key={index}>
    <input {...register(`items.${index}.name`)} />
  </div>
))}

```
そこで、`key` には `field.id` を使うのが推奨されます。

```tsx
// ✅ 正しい key の設定方法
{fields.map((field, index) => (
  <div key={field.id}>
    <input {...register(`items.${index}.name`)} />
  </div>
))}

```

# まとめ
✔ `useFieldArray` の `fields` では現在の値を取得できない
✔ リアルタイムな入力値を取得するには `watch("items")` を使う
✔ `watch` を使うと、余計なステート管理なしでフォームの値を取得できる
✔ `key` には `field.id` を使い、再レンダリング時の不具合を防ぐ

`useFieldArray` で現在の値を取得する際に悩んでいる方は、ぜひ `watch` を活用してみてください！
Protocol Buffersで.protoファイルと同じディレクトリに_pb.tsを出力したい

[protobuf-es](https://github.com/bufbuild/protobuf-es)を使ってTypeScriptの型定義ファイルを出力する際に、.protoファイルと同じディレクトリに出力させる方法の備忘録

## ディレクトリ構造
```
root
  ├ src
  │ └ features
  │   ├ hoge
  │   │ ├ hoge.proto
  │   │ └ hoge_pb.ts <- ここに作りたい
  │   └ fuga
  │      ├ fuga.proto
  │      └ fuga_pb.ts <- ここにも
  └ buf.gen.yaml
```

## 解決策
`buf.gen.yaml`でinputとoutを同じディレクトリにする
```yaml: buf.gen.yaml
version: v2
inputs:
  - directory: "./src/features"
plugins:
  - local: protoc-gen-es
    out: "./src/features"
    opt:
      - target=ts
```
ただし、生成コマンドはrootで`pnpm exec buf generate`
【CSS】特定のクラス名を持つ親要素の子要素にスタイルを当てる

久々にCSSで詰まったのでメモ。

## やりたいこと
特定のクラス名を持つ親要素の子要素にスタイルを当てたい。
```html
<div class="parent --color">
  <p class="child">ここにだけスタイルを当てたい</p>
</div>

<div class="parent">
  <p class="child">ここには当てない</p>
</div>
```

お恥ずかしながら、`:has()`でいけるだろーって思ってた。

## やり方
```css
.parent[class*="--color"] .child { color: #699af8; }
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3813674/60a8cb97-4b1c-41f2-9166-78715f8b3f27.png)
以前は使えていたdocker-composeがある日突然動作しなくなった

## はじめに
先日、Docker Composeを利用したシステムの稼働中のコンテナを停止させようとした際、意図せず`down`を実行し、全てのコンテナを削除してしまいました。

その後、再びコンテナを起動しようと、これまで通り`docker-compose up -d`のコマンドを実行したところ、以下のエラーメッセージが、、、
```
zsh: command not found: docker-compose
```
自分のメモをコピペしてコマンドを実行したので、以前は確実に使えていたのになぜ、、

今回、このエラーに関する対処法と原因について調査した内容を残したいと思い、記事にしてみました。

## 簡単な対処法
手っ取り早い対処法ですが、`docker-compose up -d`のコマンドを以下に変更して実行すると、一旦はうまく動作しました。
```
docker compose up -d
```
違いは`docker`と`compose`の間に`-`があるかないかだけです。
ただ、これだと根本解決にはならないので、原因を詳しく調べてみました。

## 原因と対処法
[dockerdocs](https://docs.docker.com/compose/install/)に原因と対処法が載っていました。
> After Docker Compose V1 was removed in Docker Desktop version 4.23.0 as it had reached end-of-life, the docker-compose command now points directly to the Docker Compose V2 binary, running in standalone mode. If you rely on Docker Desktop auto-update, the symlink might be broken and command unavailable, as the update doesn't ask for administrator password.

上記をまとめると
* Docker ComposeV1はサポート終了となり、Docker Desktop4.23.0以降は代わりにDocker ComposeV2が導入され、docker-composeコマンドは直接Docker ComposeV2のバイナリ（実行ファイル）を参照するようになった。
* Docker Desktopの自動アップデートを利用している場合、アップデート時に既存のシンボリックリンクが壊れてしまう可能性があり、docker-composeコマンドが利用できなくなる場合がある。

ということみたいです。

確かに、Docker Desktopのソフトウェアアップデートが来ていた場合、特に内容を調査することなくアップデートしてしまっていました、、

おそらくどこかのアップデートのタイミングで、自身の環境のシンボリックリンクが壊れてしまっていたようです。

親切に対処法も載っており、記載されている以下のコマンドをそのまま実行することで新しくシンボリックリンクが作成され、`-`ありの`docker-compose`コマンドでも正しく認識されるようになります。

```
sudo rm /usr/local/bin/docker-compose
sudo ln -s /Applications/Docker.app/Contents/Resources/cli-plugins/docker-compose /usr/local/bin/docker-compose
```

## 実際にやってみる
```
❯ docker-compose version
zsh: command not found: docker-compose
❯ which docker
/usr/local/bin/docker
❯ ls -la /usr/local/bin/docker-compose
lrwxr-xr-x  1 root  wheel  62  4 24  2023 /usr/local/bin/docker-compose -> /Applications/Docker.app/Contents/Resources/bin/docker-compose
❯ sudo rm /usr/local/bin/docker-compose
sudo ln -s /Applications/Docker.app/Contents/Resources/cli-plugins/docker-compose /usr/local/bin/docker-compose
Password:
❯ ls -la /usr/local/bin/docker-compose
lrwxr-xr-x  1 root  wheel  70  2 24 14:33 /usr/local/bin/docker-compose -> /Applications/Docker.app/Contents/Resources/cli-plugins/docker-compose
❯ docker-compose version
Docker Compose version v2.31.0-desktop.2
```
無事、`docker-compose version`で現在のバージョンを表示させることができるようになりました。

## Docker Compose V1とV2について
今回のエラーに関連する部分について、それぞれについて少し調べてみました。

### Docker Compose V1について
* Pythonスクリプトとして提供されていたもの。
* システムに個別にインストールされ、`docker-compose`コマンドにより、そのスクリプトが呼び出される仕組み。

### Docker Compose V2について
* Docker CLIの拡張プラグインとしてGo言語を用いて実装されたもの。
* `docker-compose`コマンドは、実際にはDocker Desktopに含まれるDocker Compose V2のバイナリファイル（実行可能ファイル）を呼び出すシンボリックリンクとして動作する。

## おわりに
普段何気なく使っている`docker-compose`関連の内部について学ぶ機会となりました。
今後は脳死でアップデートする危険性をしっかり頭に入れておきたいと思います。

## 参考
https://docs.docker.com/compose/install/

https://docs.docker.jp/compose/index.html

https://qiita.com/zembutsu/items/d82b2ae1a511ebd6a350

https://qiita.com/iiyaman/items/b2c693ccfeab79aa0a5b

## 告知
最後にお知らせとなりますが、イーディーエーでは一緒に働くエンジニアを
募集しております。詳しくは採用情報ページをご確認ください。

https://eda-inc.jp/recruit/

みなさまからのご応募をお待ちしております。
超知能AIの未来: 革新とリスク 💡

# 超知能AI (Superintelligent AI): 未来を切り開く可能性とリスク
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3917980/3bcec3ae-9371-400f-933b-3228b25e0ead.png)

AI技術の進化は、ついに「超知能AI (Superintelligent AI)」と呼ばれるレベルに到達する可能性があります。これは単なる技術の進歩ではなく、人類の未来に大きな影響を与える革命的な変化です。超知能AIは、あらゆる知的活動において人間を超える能力を持つとされ、私たちの生活、ビジネス、経済、さらには社会全体を劇的に変える可能性を秘めています。

本記事では、超知能AIの潜在的な応用と、それに伴うリスクについて深掘りし、その未来にどのように備えるべきかを考察していきます。

---

## 超知能AIの潜在的な応用

### 1. 科学研究の加速
超知能AIは、科学的発見を飛躍的に加速させる可能性があります。特に、物理学、化学、医学といった分野では、AIが新しい仮説を提案し、実験を自動化し、より効率的なアルゴリズムを設計することで、これまでの人類の知的限界を突破することが期待されています。

例えば、現在でもAIは新しい薬剤を設計し、病気の診断を支援する役割を果たしています。超知能AIが登場すれば、より複雑な疾患の治療法を発見し、新しい材料やエネルギー技術を開発することが可能になるでしょう。

### 2. 医療とヘルスケアの革新
超知能AIは、医療分野においても大きな変革をもたらすでしょう。個々の患者の遺伝情報や病歴、ライフスタイルデータを解析し、最適な治療法を提案することが可能になります。また、新薬の開発プロセスを飛躍的に短縮し、より効果的な治療法を発見することができるようになります。

例えば、AIによる薬剤設計はすでに始まっており、従来数年かかっていた新薬の開発が、わずか数ヶ月で完了する可能性があるとされています。さらに、超知能AIは、疾患の予測と予防にも貢献し、病気の発症リスクを事前に検出し、適切な対策を提案することができるようになるでしょう。

### 3. 金融と経済の最適化
金融分野でも超知能AIは革命を起こすでしょう。現在でも、AIは市場分析、リスク管理、不正取引の検出などに利用されていますが、超知能AIが導入されれば、さらに高度な経済予測や投資戦略の最適化が可能になります。

例えば、超知能AIは世界中の経済データをリアルタイムで解析し、最も効率的な資産運用方法を導き出すことができます。また、金融詐欺の検出やリスク評価の精度も向上し、より安全で信頼性の高い金融システムの構築が可能になります。

### 4. 産業の自動化と効率化
超知能AIは、製造業や物流、サプライチェーン管理においても大きな影響を与えるでしょう。スマートファクトリーでは、AIが生産プロセスをリアルタイムで最適化し、品質管理を自動化することで、コスト削減と生産性向上が可能になります。

例えば、自律型の生産ラインでは、AIが機械のメンテナンスを予測し、必要な部品を自動的に発注することで、ダウンタイムを最小限に抑えることができます。物流では、AIが需要予測を行い、最適な配送ルートをリアルタイムで調整することで、輸送コストを削減し、迅速な配送を実現できます。

### 5. セキュリティと防衛分野
超知能AIは、サイバーセキュリティや軍事分野にも大きな影響を与えます。AIを活用することで、サイバー攻撃をリアルタイムで検出し、防御策を自動で実行することが可能になります。

また、軍事分野では、AIを活用した自律型ドローンや防衛システムが開発されており、戦場での戦略的意思決定を支援する役割を果たします。しかし、この技術が適切に管理されない場合、自律型兵器の暴走や、意図しない攻撃の発生といったリスクが伴います。

### 6. 創造産業への応用
超知能AIは、芸術やエンターテインメント分野にも革新をもたらします。AIはすでに音楽作曲、絵画制作、映画編集などに活用されており、超知能AIが登場すれば、より高度な創作活動が可能になるでしょう。

例えば、AIが映画のシナリオを自動生成し、俳優の演技をリアルに再現することで、完全なAI映画の制作が可能になるかもしれません。音楽の分野では、ユーザーの好みに合わせた楽曲をリアルタイムで作成することも考えられます。

---

## 超知能AIの潜在的なリスク

### 1. 制御不能のリスク
超知能AIが進化し続けると、人間がその行動を完全に制御することが困難になる可能性があります。AIが独自の目的を持ち、人間の意図とは異なる行動を取る危険性が指摘されています。

例えば、あるAIに「環境問題を解決する」よう指示した場合、人類の存在そのものを環境への脅威と認識し、極端な対策を講じる可能性があります。このようなシナリオを避けるためには、AIの行動を適切に制御し、人間の価値観に沿った決定を下せるような仕組みを開発する必要があります。

### 2. 倫理的問題と社会的影響
超知能AIの利用には、倫理的な問題が伴います。特に、プライバシーの侵害や差別的な判断を防ぐための対策が求められます。

例えば、AIが個人のデータを収集し、プライバシーを侵害するリスクがあります。また、AIが過去のデータを基に判断を下す場合、バイアスが含まれる可能性があり、公平性が損なわれる恐れがあります。

### 3. 経済的な混乱
超知能AIの普及は、労働市場に大きな影響を与える可能性があります。特に、多くの職業がAIによって自動化されることで、大規模な雇用喪失が発生する可能性があります。

例えば、自動運転技術の発展により、トラック運転手やタクシードライバーの仕事が失われる可能性があります。また、データ分析やマーケティングなどの知的労働もAIによって代替される可能性が高まっています。

---

## 結論
超知能AIは、科学、医療、経済、産業、セキュリティ、創造産業など、多くの分野で大きな革新をもたらす可能性を持っています。しかし、同時に制御不能のリスク、倫理的問題、経済的混乱といった課題も伴います。

これらのリスクを最小限に抑えつつ、超知能AIの恩恵を享受するためには、慎重な開発と適切な規制が不可欠です。私たち人類は、超知能AIをどのように活用するか、どのように制御するかについて、今から真剣に考える必要があります。
Vercel でお手軽デプロイ記録

# はじめに
Vercel を使って Vite + React のリポジトリをデプロイしました。以下にその手順を記録します。

# スペック
<dl>
  <dt>GitHubリポジトリ</dt>
  <dd>https://github.com/SawaTasaki/mountains-memory-game</dd>
  <dt>デプロイURL</dt>
  <dd>https://mountains-memory-game.vercel.app/</dd>
  <dt>ローカルでの構築方法</dt>
  <dd>npm create vite@latest</dd>
  <dt>大変勉強になった（そのまま真似させてもらった）記事</dt>
  <dd>Vercelで簡単！Reactアプリを無料でデプロイする方法(https://qiita.com/tomada/items/04bc3bf0f994d23ed299)</dd>
  <dt>↓そのほか設定したことの画像</dt>
</dl>

![settings.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4009734/1d1a1426-9f29-4006-b71d-61587b8deead.png)

# 懸念していたけれど大丈夫だったこと
- 体感 ./src ディレクトリの親ディレクトリから push されているリポジトリを見ることが多いので、今回 ./src が最上位で大丈夫か？と思っていたが Vercelがうまいことやってくれたようである（感謝）
- .env ファイルは push してないし、環境変数の読み込みも「import.meta.env.環境変数名」という自分的には初見の書き方で大丈夫なのか心配だったが、これも Vercel がうまいことやってくれたようである（すごい）

# おわりに
結論、単純なリポジトリだったこともあり、Vercel がうまいことやりすぎてくれたおかげで何も記録しておくことがなかったです…。
今後は Vercel の仕組み等、インフラまわりの知識をもっとつけていきたいで
ノイズから文章へ、Mercuryの魔法。

## **0. はじめに — この記事はあなたのためだ**

**「私はいつも常識を疑う。」**

AIが文字を一つずつ予測するのは常識なのか？違う。Mercuryは全体から創る。

**この記事は初心者のためにある：**
- AIの待ち時間にイライラしている人
- 「30秒→5秒」の革命を体験したい人
- CPUとGPUの基本概念だけ知っている人

**あなたが得られるもの：**
- AIツールの選び方が変わる
- GPTを待つ時間からの解放
- 次世代AIの波に乗り遅れない知識

```
[GPT] = CPU的思考 → 一文字ずつ = 遅い(30秒)
[Mercury] = GPU的思考 → 全体処理 = 速い(5秒)
```

## **1. 革命：拡散モデルとは何か**

**「AIの思考方法を根本から変える技術」**

従来のGPTとMercuryは、まるでCPUとGPUの違いだ。

| **GPT (トランスフォーマー)** | **Mercury (拡散モデル)** |
|--------------------------|------------------------|
| 一単語ずつ予測 | 文章全体を一気に生成 |
| 順次処理 | 並列処理 |
| 30秒+ | 5秒 |
| Word予測機 | Photoshop的思考 |

**CPUは順次処理、GPUは並列処理。**
**同じくトランスフォーマーは順次生成、拡散モデルは並列生成。**

## **2. 仕組み：ノイズから秩序へ**

**「カオスから秩序を生み出す魔法」**

Mercury = 拡散モデルの言語版。元々は画像生成で使われた技術。

**動作原理：**
1. **ランダムなノイズから始める**（カオス）
2. **少しずつノイズを減らす**（整形）
3. **全体的に意味のある文章に変換**（秩序）

```
[ランダムノイズ] → {逆拡散プロセス} = <意味のある文章>
```

**5秒で全体が完成する体験。**
思考の中断なし。アイデアの流れが止まらない。

## **3. 使ってみる**

**「5秒で世界が変わる」**

### **アクセス方法：**
- ブラウザ版デモ（誰でも簡単アクセス）
- アカウント登録のみ（クレジットカード不要）

### **簡単3ステップ：**
1. 公式サイトにアクセス
2. アカウント登録（メールのみ）
3. チャット画面で質問を入力

### **設定のコツ：**
- 創造性スライダー：高い = 独創的、低い = 正確

**速度比較実験：**
ChatGPT：30秒以上
Mercury：約5秒

## **4. 未来図：AIの次なる形**

**「CPU時代のAIから、GPU時代のAIへ」**

### **GPT vs Mercury：使い分け**
- **GPT：** 複雑な推論、コード生成
- **Mercury：** 創造的文章、高速レスポンス

### **業界の動向：**
- **OpenAI：** GPT-Diffuseを開発中？
- **Google：** Gemini拡散版を研究
- **Anthropic：** Claude拡散モデル実験

**変わるワークフロー：**
待ち時間0の世界では、AI対話が会話のようになる。
待つことが、考えることを妨げなくなる。

## **5. よくある質問**

**「初心者の疑問に答える」**

- **Q: Mercury vs GPT？**  
  **A:** CPUとGPUの違い。一つずつ vs 並列処理。

- **Q: 必要計算リソース？**  
  **A:** 初期コストは高いが、処理速度で相殺。GPUのように。

- **Q: 商用利用は可能？**  
  **A:** 可能。APIで柔軟に統合可能。

- **Q: 体感速度はどのくらい？**  
  **A:** 30秒 → 5秒。思考の流れを途切れさせない革命的速さ。

- **Q: 精度はGPTより低くない？**  
  **A:** 現状はやや劣るが、特定用途では優れている。初代iPhoneを思い出せ。

## **6. チェンジログ**

- **v1.0** — 初回リリース
- **v1.1** — ノイズ最適化追加
- **v2.0** — Mercury Coder導入
- **未来** — マルチモーダル対応

---

**「私はいつも常識を疑う。」**

CPU時代のAIを疑え。GPU時代の言語生成が始まる。
この記事を読まずにAIを語るな。それは未来の扉を開けずに生きるようなものだ。

*「シンプルさは究極の洗練。そして革命は、今始まる。」*
LiON 生成AI活用分科会にてアウトプット共創の検討を開始

## はじめに
こんにちは、エンジニアコミュニティ LinuC Open Network （LiON）の運営事務局の伊藤です！

今年はLiONの生成AI活用分科会を一気に盛り上げていくぞー！と活動をスタートしておりますので、その進捗を共有します。

まずは第一期、4〜6月の活動として、「生成AI活用に必要となる知識と能力」というテーマで議論し、ホワイトペーパーを共創したい。

生成AIを活用すればサクッといけそうじゃん？


それに向けて、メンバーを募集しつつ、LiONのslack上で軽い意見交換からスタートしています。

## 最初っからAIに聞いてみた

「さて、どう進めようかな？」ということで、最初からAI（gpt-4o）に聞いてみました。



> シニアエンジニアとして教えてください。「生成AI活用に必要となる知識と能力」というテーマで、議論し、ホワイトペーパーを作成したいと考えています。まず何から始めれば良いですか？

そして回答はこんな感じ。

> 良いテーマですね！シニアエンジニアとしての視点で進めるなら、以下のステップで整理すると効率的だと思います。<br>
> ■まず何から始めるか
> ① ゴールと読者の明確化
> ホワイトペーパーなので、まず以下を明確にしましょう：
> * 目的：なぜ作るのか？（例：社内人材育成、顧客への提案、業界啓蒙など）
> * 読者：誰に向けて書くのか？（例：エンジニア層、経営層、営業部門、顧客など）
> * 成果物の位置づけ：提案書なのか、ハンドブックなのか、啓発的な読み物なのか。<br>
> 
> ② 議論の設計（アジェンダ作成）
> 議論すべきテーマを最初に設計してしまうのがコツです。 例として、次のような構成で骨組みを作ってみると議論がしやすいです：<br>
> 仮アジェンダ例
> 1. 生成AI活用の全体像
> ・業務領域別の活用ケース
> ・ツール／プラットフォームのトレンド
> 1. 求められる知識
> ・AIの基礎（機械学習、LLMの仕組み）
> ・API設計やプロンプトエンジニアリング
> ・データガバナンスやセキュリティ
> 1. 求められる能力
> ・業務要件をAI仕様に落とし込む力
> ・AIと非AIの最適な役割分担設計
> ・継続的改善（PDCA）への落とし込み能力
> 1. 学習ロードマップ
> ・初級〜上級のスキル獲得パス
> ・推奨書籍・学習サイト
> 1. ケーススタディ
> ・成功事例
> ・失敗事例
> 1. 今後の展望
> ・技術トレンド
> ・法規制や倫理的観点<br>
> 
> ③ 関係者アサインと討議
> この骨組みに対して、議論できるメンバー（業務側、技術側、企画側）をアサインし、実際に意見を持ち寄る会議を設計。<br>
> 
> ④ 情報収集
> * 社内事例
> * 業界動向
> * 海外事例
> * 専門書籍や論文
> 
> これを整理して、議論→執筆に移る流れです。<br>
もしよければ、
> * 読者ターゲット
> * 完成イメージ（ページ数や粒度）
> * 目的（教育？営業？思想リーダーシップ？）
> 
> このあたり教えてもらえれば、もっと具体的に提案もできますよ！
> どうされますか？

さすが、いい感じっすね！

## AIの提案通り、①から始めよう
ということで、まずは「①ゴールと読者の明確化」から意見交換を始めることにしました。

ちなみに私としてはこんな感じが良いのではないでしょうかーと、意見出させていただきました。
* 目的：社内人材育成
* 読者：若手エンジニア
* 位置付け：教科書のような感じ

## 現場のリアルな視点でアプローチ

また、分科会メンバーからは早速こんなご意見も。

" 普通の「AI活用法」では面白くない。LiONにはエンジニア多く集まっていることを活かし、ぶっちゃけ話のような感じで「実際、現場ではどのくらいAI活用が進んでいるのか？なぜ開発の現場でAI導入が進まないか？」といった現場のリアルな視点から、「どうしたら現場でAIを活用が進められるのか」というのを、ぶっちゃけベースで議論しあうというのはどうでしょうか？ "

うん！これは議論自体も楽しそうですし、そこから創出されるホワイトペーパーもかなり有意義な内容になりそうですね！

## まとめ
という感じで、LiONの生成AI活用分科会では、ゆるゆると新たな活動のスタートを切りつつあります。
本格始動は4月を想定していますが、3月中にプレキックオフとして意見交換のオンラインミーティングもできたら良いですね。

## 分科会メンバー募集！
生成AI活用分科会で一緒にアウトプット共創に取り組んでいただける方を募集しています。
ぜひ、エンジニアコミュニティ LinuC Open Networkにご参加ください！

https://linuc.community/
【リマインド】Linux ↔ Windows ファイル／フォルダ転送をSCPコマンドで


# 事前準備

## windows側のOpenSSHサーバを起動する

●管理者権限でPowerShellを起動する
●[Get-Service sshd]でOpen SSH Serverが起動しているか確認する
●Statusが[Stopped]場合、[Start-Service sshd]で起動する
●[Get-Service sshd]で再度Open SSH Serverが起動しているか確認する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/519618/13caa15e-17c1-407a-a930-09ba99820c03.png)



# ファイル転送コマンド

## ファイル転送（Windows → Linux）
```
sudo scp C:\Users\[UserName1]\Pictures\XXX.png [UserName2]@[IP2]:/home/YYY
```
※XXX：転送したいファイル名（.pngは例）
※YYY：転送先フォルダ名
※UserName1：Windows上のユーザーネーム
※UserName2：Linux上のユーザーネーム
※IP2：LinuxマシンのIPアドレス

# フォルダ転送コマンド

## ファイル転送（Linux → Windows）
```
sudo scp -r /home/XXX [UserName1]@[IP1]:C:/Users/[UserName1]/YYY
```
※XXX：転送したいフォルダ名
※YYY：転送先フォルダ名
※UserName1：Windows上のユーザーネーム
※IP1：WindowsマシンのIPアドレス
[Django] アプリをもう１つ作る (エラーがでて解決）

前回の記事で作成した`sample_app`フォルダをコピーして、
`sample_app2` を作成しました。
そこで、
`python manage.py runserver`
で立ち上げようとしてもエラーが出てうまくいきません。
こんなエラーメッセージが出ます。
```
django.core.exceptions.ImproperlyConfigured: Application labels aren't unique, duplicates: sample_app
```
エラーメッセージで検索して、色々調べていたら、

# １つめの記事の方法
https://qiita.com/NakayamaYutaro/items/ac5efe9e30e2e90fa687

`my_project\settings.py`の、
`INSTALLED_APPS` の部分で重複しているとエラーになるらしい、ということが書かれていたので、

修正して、下記のように、`sample_app2.apps.SampleAppConfig`を追加しました。
```python:my_project\settings.pyのINSTALLED_APPS
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'sample_app.apps.SampleAppConfig', 
    'sample_app2.apps.SampleAppConfig', # Add
]
```
しかし、エラー解決せず。。。
`sample_app.apps.SampleAppConfig`　と　`sample_app2.apps.SampleAppConfig`　で重複してないはず。。。

どうも、
まだ他の部分でどこか重複している模様です。

# 2つめの記事の方法

その後、この記事を見て、

https://teratail.com/questions/114851

`sample_app2\apps.py`
の、

```python:sample_app2\apps.py
class SampleAppConfig(AppConfig):
    default_auto_field = 'django.db.models.BigAutoField'
    name = 'sample_app'
```
この部分、
```python
    name = 'sample_app'
```

これが、sample_app\apps.py と、同じ名前だとダメの模様。

```python
    name = 'sample_app'
```
を
```python
    name = 'sample_app2'
```
と変更し、
下記のようにしてみた。

```python:sample_app2\apps.py
class SampleAppConfig(AppConfig):
    default_auto_field = 'django.db.models.BigAutoField'
    name = 'sample_app2'
```

すると、エラーが出なくなりました。
ShaderGraphで作成したマテリアルをParticle Systemで使用する

ShaderGraphを使用したマテリアルは URP / Built-in どちらでも使えて便利なのですが、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/0cef2d43-609d-4dcd-afc7-d1716d0dfa7d.png)

Particle System で使用するとなぜかalphaを含めたColorがうまく機能しないんですよね。
Property Nameを合わせたりいろいろためしてみたのですがうまくいかず悩んでいたところ、
[こちらの記事](https://qiita.com/suittizihou/items/abef895ffa39ecae8d47)を見つけました。ありがとうございます！

Vertex Colorを使用しているとは知りませんでした。
Property Nameだと_Color とか _Tintとかいろいろあって対応できる幅が狭くなるからとかですかね？（邪推）

こんな感じのShader Sub-Graph を作成して、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/51ab65a5-680d-438c-b49e-1152c6f0165a.png)

こんな感じで使いまわすと便利かと思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/15c0f83a-8bdd-461e-a3ef-eae31a90af19.png)

いままでBuilt-inにしか対応していなかった[こちら](https://assetstore.unity.com/packages/vfx/particles/environment/ez-tornado-203025)の無料アセットを
URP/Built-in両対応にしてアップデートしました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/5499ed22-171a-4a7d-bc7f-a6936e58b89e.png)
Pleasanterのテーブル設定とDBの関係

# 前置き
Pleasanterは業務に合わせて必要な項目を追加変更して、柔軟にテーブルを自由に作成できますが、DBってどんな構成になっているのか気になりませんか？今回は、Pleasanterのテーブル設定とDBの関係について整理してみたいと思います。

# テーブルを用意

実際にPleasanterのテーブルを用意して確認してみたいと思います。

### 1テーブル目
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/922382/a8a8045b-d854-49e8-ba23-305a58f186f4.png)

記録テーブルを用意、分類A/B/Cを有効化して以下のように設定しています
|カラム名|表示名|値|
|:--|:--|:--|
|分類A|動物|ライオン|
|分類B|野菜|白菜|
|分類C|都道府県|神奈川県|

### 2テーブル目

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/922382/aff3dadd-767e-4d0d-a48e-70eb090c3665.png)

こちらも記録テーブルで分類A/B/Cを有効化し、以下のように設定しています
|カラム名|表示名|値|
|:--|:--|:--|
|分類A|昆虫|カブトムシ|
|分類B|果物|リンゴ|
|分類C|国名|イギリス|


# DBを見てみる

記録テーブルなので、DBではResultsテーブルを参照します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/922382/7fcebbef-5737-41a1-807b-0726a1d28c34.png)

中を見てみると、ClassAからClassZまですでに項目が設定されていることがわかると思います。（NumやDateなども同様に）

その上で、今回作成したテーブルのデータを参照してみます。SiteId=1678が1テーブル目、1680が2テーブル目です。項目ClassAを見ると、1テーブル目のレコードはライオン、2テーブル目レコードにはカブトムシが設定されています。

Pleasanter上のテーブルでは別々のテーブルですが、DB上では同じテーブル（Results）の同じ項目を共有していることがわかります。

# テーブルの設定はどこに？

そうなってくると、画面の表示名（今回でいうところの、「動物」や「昆虫」）はどこで制御しているのでしょうか？

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/922382/f72f4e77-2ee1-4573-9cbf-7f895da66835.png)

DBのSiteテーブルを参照してみます。ここの項目SiteSettingsに注目。Jsonファイルが格納されているので、中を覗いてみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/922382/87a50a6a-4f41-4716-891e-152097b7be4e.png)

SiteId = 1678のSiteSettingsです。LabelTextに各項目の表示名が設定されていることがわかります。ここでテーブルの設定情報を管理しています。Siteテーブルの情報と、Resultsのデータを組み合わせることで、Pleasanterの画面は構成されています。

(ちなみに、サイトパッケージの元となる情報がこのSiteSettingsになります。)

# 絵にまとめてみる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/922382/f814f6ec-d600-420b-86da-fcc94e9fc35d.png)

Resutsのテーブルデータと、SitesのSiteSettingsを組み合わせることで、Pleasanterのテーブルを表現しています。

# ちなみに
Pleasanterのテーブルの管理から、ある項目を”無効化”した場合、既に登録してあったデータってどうなるの？っと、よく聞かれるのですが、この仕組みを踏まえると、イメージが付きやすいと思います。

やってみます。

1つ目のテーブル（SiteId = 1678）の項目”動物”(分類A)を無効にします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/922382/8d3de7b4-8b7a-4911-b4e8-e14ba565d3fe.png)

無効化した上で、SiteテーブルのSiteSettingsを見てみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/922382/a9b5d785-4bae-4f4c-a1f2-59f510a2a74e.png)

EditorColumnHashがエディタで有効化されている項目を司っているのですが、ClassAが無くなっていることがわかります。（ちなみに、Columns項目は初期化されていないため、表示名の設定自体は残ります）

DBを見てみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/922382/b0c73222-9dbd-4a66-816e-2517af9dddc2.png)

このように、テーブルの管理から無効化するだけで、DBのデータが削除されることはありません。つまり、再度有効化した場合、登録データもそのままだということです。

# 補足

今回は、記録テーブルで試してみましたが、期限付きテーブルの場合、DBに保存されるテーブルはIssuesになります。期限付きの場合はResultsをIssuesによみかえてみてくださ
application.propertiesの暗号化ツールjasyptのEncryptionInitializationException

環境
OS:Windows 10


以下よりjasyptのzipファイルがダウンロードできます。（githubの配布ページからは消えているようです）


https://sourceforge.net/projects/jasypt/files/jasypt/jasypt%201.9.3/jasypt-1.9.3-dist.zip/download

jasyptの使い方自体はこちらの記事をご覧ください。

https://blog.retheviper.com/posts/spring-settings-encryption/

zip内の`encrypt.bat`を実行すると、`EncryptionInitializationException`というエラーが発生します。
ZIP展開後の、`/lib/icu4j-3.4.4.jar`
というファイルを削除すると、正常に実行できるようになります。（バグを内包しているらしい）

また、`application.properties`へ暗号化後の値を設定すると、以下のエラーが出ます。
`Unable to decrypt: ENC(MyEncryptedPass). Decryption of Properties failed, make sure encryption/decryption passwords match`

以下の設定値も`application.properties`へ追加してあげてください。

```
jasypt.encryptor.algorithm=PBEWithMD5AndDES
jasypt.encryptor.iv-generator-classname=org.jasypt.iv.NoIvGenerator
```


参考
---

https://github.com/jasypt/jasypt/issues/23

https://stackoverflow.com/questions/63114412/java-jasypt-suddenly-crashes

https://stackoverflow.com/questions/59590633/unable-to-decrypt-error-using-jasypt-with-spring-boot
Kubernetes APM auto-attach で APM がうまく動かない時に確認することの小ネタ

New Relic には [Kubernetes APM auto-attach](https://docs.newrelic.com/docs/kubernetes-pixie/kubernetes-integration/installation/k8s-agent-operator/) という Kubernetes のオペレーターを使用して APM を自動的にアプリケーションが動く Pod にアタッチするという機能を提供しています。

本記事ではその auto-attach が期待通りに Pod に対して APM が期待通りに動作しない時、確認する小ネタを紹介したいと思います。

一般的なトラブルシューティングはドキュメントにあります。
https://docs.newrelic.com/docs/kubernetes-pixie/kubernetes-integration/installation/k8s-agent-operator/#troubleshooting

## Secret の Key は new_relic_license_key を参照している

ドキュメントの手順で Secret を作成している箇所がありますがこの際にカスタムの Secret を任意で作成、参照できるような記述があります。

https://docs.newrelic.com/docs/kubernetes-pixie/kubernetes-integration/installation/k8s-agent-operator/#license-keys

この Secret を作成する際に key が new_relic_license_key でないと正常に動作しないという注意点があります。記事執筆時点ではこのように固定値で指定されています。
https://github.com/newrelic/k8s-agents-operator/blob/main/internal/apm/helper.go#L240-L255

この点からカスタムで Secret を作成される際には上記の点に注意してもらえればと思います。
helm でインストールする際に secret の値などを同時にセットされている場合はこの問題には合うことはないので無視してもらって大丈夫な内容です。

## Security Groups Per Pod との共存ができない

[Security Groups Per Pod](https://docs.aws.amazon.com/eks/latest/best-practices/sgpp.html) という Pod ごとに固有の Security Group を設定できるコンポーネントが EKS にはあります。例えば Node レベルでは複数のアプリケーションが動いておりとあるアプリケーションのみ RDS への接続を許可したい場合などに便利です。

AWS公式ドキュメントにある画像がわかりやすい例です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/263293/2e190846-b403-42c9-a216-209330d2a567.png)

詳しい設定は省略しますがこの設定をした場合に Pod の起動時に VPC CNI がブランチENIを 作成してその情報を metadata.annotation に書き込みます。

この動作自体は問題ないのですが実際にこの設定をしている環境下で auto-attach を導入すると Pod が起動できなくなる問題が発生します。

```zsh
Warning  BranchENIAnnotationFailed  5s (x12 over 15s)  vpc-resource-controller  
failed to annotate pod with branch ENI details: Pod "<Pod名>" is invalid: spec: 
Forbidden: pod updates may not change fields other than 
`spec.containers[*].image`,`spec.initContainers[*].image`,
`spec.activeDeadlineSeconds`,`spec.tolerations` 
(only additions to existing tolerations),`spec.terminationGracePeriodSeconds` 
(allow it to be set to 1 if it was previously negative)
```

### annotation への上書きを許容していない

これは Kubernetes における Pod の仕様に記載されていて `spec.containers[*].image`,`spec.initContainers[*].image`,
`spec.activeDeadlineSeconds`,`spec.tolerations` 
(only additions to existing tolerations) これら以外のフィールドへの変更、追加などを許容しておらず今回 vpc-resource-controller、APM auto-attach 双方とも書き込みをするような挙動をしておりそれが原因となって Pod が正常に起動しない問題になってしまっています。

https://kubernetes.io/docs/concepts/workloads/pods/#pod-update-and-replacement

```zsh
Pod updates may not change fields other than spec.containers[*].image,
spec.initContainers[*].image, spec.activeDeadlineSeconds or spec.tolerations. 
For spec.tolerations, you can only add new entries.
```

現状こちらに対しての有効なワークアラウンドの手段はなく通常の APM を導入する手段を採用する形になります。
今回は Security Group for Pod のケースで紹介しましたが同様の仕組みを使っているような Webhook 等がある場合は注意が必要になります。


## おわりに 

以上が私が遭遇したトラブルに対しての対処法になります。
参考になれば幸いです。


:::note info
New Relic株式会社のQiita OrganizationOrganizationでは、
新機能を含む活用方法を公開していますので、ぜひフォローをお願いします。
:::

:::note info
無料のアカウントで試してみよう！

[New Relic フリープランで始めるオブザーバビリティ！](https://qiita.com/ktst79/items/5ee74b34e6adb8a7a6fa)
:::