OmniAICreator/Qiita-1.07M huggingface dataset:
FFmpegとは？概要とMac・Windowsでのインストール方法＆基本コマンドガイド

# FFmpegとは？概要とMac・Windowsでのインストール方法＆基本コマンドガイド

こんにちは！動画や音声の編集、変換に役立つ強力なツール「FFmpeg」について、ざっくりとした概要からMacやWindowsへのインストール方法、さらには基本的な使用コマンドまで、わかりやすくまとめてみました。初心者の方でも安心して始められるように、口語調で解説していきますね！

## FFmpegって何？

**FFmpeg**は、動画や音声の処理に使われるオープンソースのコマンドラインツールです。形式変換、編集、ストリーミングなど、さまざまな用途に対応しています。例えば、動画ファイルのフォーマットを変えたり、音声を抽出したりするのにとっても便利なんです。多くのメディアプレイヤーや編集ソフトも、実は内部でFFmpegを使っていることが多いんですよ。

## Macへのインストール方法

MacでFFmpegを使うには、主に**Homebrew**というパッケージマネージャーを使う方法が一般的です。以下の手順で簡単にインストールできます！

1. **Homebrewのインストール確認**
   まず、Homebrewがインストールされているか確認しましょう。ターミナルを開いて、以下のコマンドを入力します。

   ```bash
   brew --version
   ```

   バージョン情報が表示されればOK！インストールされていなければ、[Homebrew公式サイト](https://brew.sh/)の指示に従ってインストールしてください。

2. **FFmpegのインストール**
   Homebrewがインストールされている場合、次のコマンドでFFmpegをインストールできます。

   ```bash
   brew install ffmpeg
   ```

   インストールが完了すると、`ffmpeg`コマンドが使えるようになります。

3. **インストール確認**
   正しくインストールされたか確認するために、以下のコマンドを実行してみてください。

   ```bash
   ffmpeg -version
   ```

   FFmpegのバージョン情報が表示されれば成功です！

## Windowsへのインストール方法

WindowsでもFFmpegを簡単にインストールできます。以下の手順に従ってください。

1. **公式サイトからダウンロード**
   [FFmpeg公式ダウンロードページ](https://ffmpeg.org/download.html)にアクセスし、Windows用のビルドを提供しているサイト（例えば、[gyan.dev](https://www.gyan.dev/ffmpeg/builds/)）から最新の静的ビルドをダウンロードします。

2. **ZIPファイルの解凍**
   ダウンロードしたZIPファイルを適当な場所（例えば、`C:\ffmpeg`）に解凍します。

3. **環境変数の設定**
   FFmpegをどのディレクトリからでも使えるようにするため、環境変数にパスを追加します。

   - 「スタート」ボタンを右クリックして「システム」を選択。
   - 「システムの詳細設定」をクリック。
   - 「環境変数」ボタンを押す。
   - 「システム環境変数」セクションで「Path」を選択し、「編集」をクリック。
   - 「新規」を押して、FFmpegの`bin`フォルダ（例：`C:\ffmpeg\bin`）のパスを追加。
   - 「OK」で全てのウィンドウを閉じます。

4. **インストール確認**
   コマンドプロンプトを開いて、以下のコマンドを実行します。

   ```cmd
   ffmpeg -version
   ```

   FFmpegのバージョン情報が表示されればOK！

## 基本的な使用コマンド

FFmpegはコマンドラインツールなので、最初はちょっと戸惑うかもしれませんが、基本的なコマンドを覚えれば色々なことができるようになります。ここでは、よく使う基本コマンドをいくつか紹介します。

### 動画のフォーマットを変換する

例えば、`input.mp4`を`output.avi`に変換する場合：

```bash
ffmpeg -i input.mp4 output.avi
```

### 音声を抽出する

動画ファイルから音声を抽出してMP3に変換する場合：

```bash
ffmpeg -i input.mp4 -q:a 0 -map a output.mp3
```

### 動画の一部分を切り取る

例えば、最初の60秒だけを切り取って`output.mp4`に保存する場合：

```bash
ffmpeg -i input.mp4 -ss 00:00:00 -t 00:01:00 -c copy output.mp4
```

### 動画の解像度を変更する

動画の解像度を1280x720に変更する場合：

```bash
ffmpeg -i input.mp4 -vf scale=1280:720 output.mp4
```

### 動画にテキストを追加する

動画に「Hello World」と表示する場合：

```bash
ffmpeg -i input.mp4 -vf "drawtext=text='Hello World':fontcolor=white:fontsize=24:x=10:y=10" -codec:a copy output.mp4
```

## まとめ

FFmpegは、動画や音声の処理において非常に強力なツールです。コマンドラインで操作するため、最初は少し難しく感じるかもしれませんが、基本的なコマンドを覚えれば、さまざまな作業がスムーズに行えます。MacでもWindowsでも簡単にインストールできるので、ぜひ試してみてくださいね！

もしさらに詳しい使い方や応用的なコマンドを知りたい場合は、公式ドキュメントやオンラインのチュートリアルをチェックしてみてください。Happy FFmpeg-ing!
アプリのパフォーマンス低下を防げ！対「N+1問題」

# 導入

こんにちは、もんすんです。

開発を進めていく中で、アプリケーションのパフォーマンスに関わる問題に直面することがよくあります。
その中でも、データベースに関する問題は特に重要です。

アプリケーションがデータベースから情報を取得する際、効率的なデータの取得方法を選ばないと、パフォーマンスが大きく低下することがあります。

その中でもよく発生するのが「N+1問題」です。
N+1問題とは、データベースクエリを不必要に多く発行してしまう問題で、これが原因でアプリケーションが遅くなることがあります。
この問題が発生する背景を理解し、どのように解決すれば良いのかを知ることは、開発者として非常に重要です。

今回は、N+1問題の原因とその解決策を初心者向けにわかりやすく解説します。

# N+1問題
## N+1問題とは

「N+1問題」は、プログラミング初心者がデータベースを使い始めたときによく遭遇する、**パフォーマンスを悪化させる問題**です。
この問題は、データベースに無駄なクエリ(データベースへの要求)をたくさん送ることで発生します。

### 簡単な例
たとえば、ブログ投稿を表示するアプリを作っているとします。
以下のように投稿データとその著者情報を取得する場合を考えてみましょう。

1. 最初にブログ投稿を10件取得するために1つのクエリを送る。
2. その後、それぞれの投稿ごとに著者情報を取得するために10回クエリを送る。

結果として、データベースに送るクエリの数は **1(投稿一覧)+ 10(著者情報)= 11回** になります。

本来、1回のクエリで投稿と著者情報をまとめて取得できるのに、11回もクエリを送っている状態が **N+1問題** です。

## なぜN+1は問題か？

データベースへのクエリが増えると、次のような問題が発生します。

**アプリが遅くなる**  
	データベースからデータを取得するたびに時間がかかります。
	特にデータが増えるとその影響は大きくなります。
**サーバーに負荷がかかる**  
	クエリが多すぎると、データベースやサーバーの処理能力を圧迫し、他の処理が遅くなる可能性があります。

これらの問題は、ユーザー体験を大きく損ねる原因となります。

## N+1問題を解決する方法

N+1問題を避けるための基本的な方法を紹介します。
これらは初心者でも簡単に実践できるテクニックです！

### 1. データをまとめて取得する(Eager Loading)

N+1問題の原因は、データを1つずつ取得することです。
それを回避するには、「関連するデータを一緒に取得する」方法が有効です。

- **例：投稿と著者情報をまとめて取得する**
  ```sql
  SELECT posts.*, authors.*
  FROM posts
  JOIN authors ON posts.author_id = authors.id;
  ```
  これにより、1回のクエリで投稿と著者情報をまとめて取得できます。

### 2. ORMの設定を見直す

Javaでよく使われるORM(オブジェクト関係マッピング)ツール、たとえば`Hibernate`では、**遅延読み込み(Lazy Loading)** がデフォルトになっている場合があります。
遅延読み込みは便利ですが、N+1問題の原因になることがあります。

- 解決策：積極的読み込み(Eager Loading)に設定を変更する
  ```java
  @OneToMany(fetch = FetchType.EAGER)
  private List<Comment> comments;
  ```
  これにより、関連データをまとめて取得するようになります。

### 3. バッチ処理を使う

関連データが大量にある場合、一度にすべてを取得するのではなく、**バッチ**で取得することも有効です。
`Hibernate`にはバッチフェッチ機能があるので、それを活用します。

### 4. キャッシュを使う

データが頻繁に変更されない場合、**キャッシュ** を利用することでデータベースへのアクセス回数を減らせます。
Redisなどのキャッシュツールを使うのが一般的です。

## 実際のコード例(Spring Bootの場合)

以下は、Spring Bootでの例です。

### N+1問題が発生するコード
```java
// 1回目のクエリ実行
List<Post> posts = postRepository.findAll();
for (Post post : posts) {
	// N回分のクエリ実行
	String name = authorRepository.getAuthor(post.authorId).getName();
    System.out.println(name);
}
```
このコードでは、投稿一覧を取得した後、投稿ごとに著者情報を取得するためにクエリが複数回発行されます。

### N+1問題を解決するコード
```java
@Query("SELECT p FROM Post p INNER JOIN author a ON p.author_id = a.id")
List<Post> findAllWithAuthors();
```
`JOIN FETCH` を使うことで、投稿と著者情報をまとめて取得し、N+1問題を防ぎます。

# 終わりに

N+1問題は、アプリケーションのパフォーマンスを大きく低下させる問題ですが、以下のような方法で簡単に解決できます。

1. データをまとめて取得する(Eager LoadingやJOINを使う)
2. ORMの設定を適切に変更する
3. バッチ処理やキャッシュを利用する

最初は、データベースクエリを意識してコードを書くのは少し難しいかもしれません。
でも、N+1問題を理解しておけば、効率的なコードを書けるようになります。ぜひ試してみてください！
【初心者向け】小規模から大規模まで対応するアーキテクチャ戦略

# 導入
こんにちは、もんすんです。

ソフトウェアを設計するとき、アーキテクチャの選択はプロジェクトの成功を左右する重要なポイントです。
「アーキテクチャパターン」は、これまでの経験から導き出された設計のベストプラクティスで、特定の問題に対して効果的な解決策を提供します。
今回は、いくつかの代表的なアーキテクチャパターンを初心者の方でも理解できるように解説します。

# アーキテクチャパターン
## モノリシックアプリケーション：一体型のアプローチ

モノリシックアプリケーションとは、アプリ全体が一つのまとまりとして構築される方法です。
フロントエンドとバックエンドが1つのアプリケーションとして構築されます。
例えば、小さなブログサイトや簡単な業務管理システムなどはこの構造が適しています。
スタートアップ企業や個人開発で、よく採用されるアーキテクチャです。

**メリット**
- 開発や運用コストが低い
- シンプルでわかりやすく、初心者でも設計やデプロイが簡単

**課題**
- アプリが大きくなると、変更や拡張が困難
- サーバー負荷が高くなったとき、特定の部分だけを拡張するのが困難

小規模なプロジェクトには十分効果的ですが、大規模化する場合には別の選択肢を検討する必要があります。

## SOA(サービス指向アーキテクチャ)：統合のためのフレームワーク

SOAは、異なるシステム間をつなぐためのアーキテクチャです。
例えば、複数の業務システム(販売管理、在庫管理など)を連携させる場合に利用されます。
システムとしての役割ごとにシステムを分離させた構造になります。

**メリット**
- 再利用可能な「サービス」を作成でき、全体の効率が向上する
- 異なる技術スタックやプロトコル間の連携が容易である

**課題**
- 初期設計にコストと時間がかかる
- マイクロサービスに比べて構造が重たくなる場合がある

## マイクロサービス：小さく分けて独立運用

マイクロサービスは、アプリケーションを小さな機能ごとに分割し、それぞれが独立して開発・運用される方法です。
例えば、ECサイトの注文管理、在庫管理、支払い処理などを個別のサービスとして設計するケースです。

**メリット**
- サービスごとにスケーリング(性能強化)が可能。
- 異なる技術を活用でき、チームの柔軟性が高まる。
- 一部の機能を変更しても、他の部分に影響しにくい。
**課題**
- サービス同士の通信や整合性の管理が必要がある。
- 専門的な技術と運用スキルが求められる。

最近の大規模なアプリケーションで採用されているアプローチです。

## サービスメッシュ：マイクロサービスのための交通整理

マイクロサービスが増えると、サービス間の通信が複雑化します。
そこで登場するのが「サービスメッシュ」です。
これにより、通信の最適化やセキュリティの向上が図れます。

**メリット**
- 負荷分散や障害時の切り替えを自動化。
- 通信の監視やログの収集が容易。

**課題**
- 初期セットアップが複雑。
- 管理コストが増加する可能性。

Kubernetes環境で特に利用される技術で、IstioやLinkerdが有名です。

## サーバーレス：サーバーを気にしないシンプル構成

サーバーレスでは、サーバーのプロビジョニングや管理を**クラウドプロバイダーが担当**し、開発者はアプリケーションのロジックに専念できます。
つまり、アプリケーションが特定のイベントに応じて動作する形態で、サーバー自体を直接管理する必要がありません。
コードをアップロードすると、自動的にサーバーが管理され、イベントが発生したときにだけ実行されます。

**メリット**
- 開発と運用の負担を大幅に軽減
- 自動スケーリングで急な負荷増にも対応
- 実行された分だけ料金が発生し、コスト効率が高い

**課題**
- サーバーレス特有の制約に適応する必要がある。
- 長時間の実行や特定のワークロードには向いていない。

AWS LambdaやGoogle Cloud Functionsが代表例です。

## アーキテクチャ選択のポイント

ざっくりと整理すると、条件に応じてそれぞれ以下のようにアーキテクチャを選択するのがよさそうです。

- **スピード重視・軽量アプリケーション**：サーバーレスがおすすめ
- **小規模・短期的なプロジェクト**：モノリシックアプリが最適
- **大規模・多機能アプリケーション**：マイクロサービスが有利
- **マイクロサービスを効率化**：サービスメッシュを導入
- **既存システムの統合**：SOAの採用を検討

## 最後に

ソフトウェアアーキテクチャの選択は、単にシステムの設計を決定するだけでなく、その後の運用や拡張に大きな影響を与えます。
選択に迷った場合は、各アーキテクチャの特徴を理解し、具体的な課題にどう対応できるかを中心に考えることが鍵となります。

今回の記事のアーキテクチャパターンを参考に、最適なシステム設計を進めていきましょう。
ガベージコレクタとは？Javaでのメモリ管理の基礎知識

# 導入

こんにちは、もんすんです。

Javaを学んでいると「メモリ管理」という言葉を耳にすることがありますが、「具体的に何を指しているの？」と思ったことはありませんか？
今回は、Javaプログラムの中でどのようにメモリが扱われ、管理されているのかをわかりやすく解説していこうと思います。

Javaは「書いたら動く」ことで知られるプログラミング言語です。
その秘密の一つが**自動メモリ管理**です。
Javaでは、オブジェクトの生成や破棄を開発者が直接管理する必要はありません。

その仕事を担うのが**ガベージコレクタ(Garbage Collector)** です。

# ガベージコレクタの便利さ

Javaのガベージコレクタは、プログラム中で使われなくなったオブジェクトを検出し、自動的にメモリを解放してくれます。
これにより、開発者は次のようなメリットが得られます。

- 手動でメモリを解放するコードを記述する必要がない
- メモリリーク（使わなくなったメモリの解放忘れによるメモリ不足）を防ぎやすい
- より安全で安定したプログラムを開発できる

# Javaにおけるメモリ管理

## JVMのメモリ構造

Javaプログラムが動作する環境である**JVM(Java Virtual Machine)** は、メモリをいくつかの領域に分けて管理してくれています。
それぞれの領域には特定の役割が割り当てられています。

### メモリ領域

#### メソッドエリア

- JVMの起動時に作成され、クラス情報やメソッドのコードが保存される領域
- すべてのスレッド間で共有されます
- クラス名やその修飾子、スーパークラス情報などに利用されます

#### ヒープ

- オブジェクトが作成される領域で、Javaプログラムのメモリ管理の中心です
- **「new」キーワード**で作成されたすべてのオブジェクトはヒープに保存されます
- <font color="red">ガベージコレクタの対象となる領域</font>

#### スタック

- スレッドごとに割り当てられるメモリ領域で、メソッドの呼び出しに関連する情報を管理します
- ローカル変数やオブジェクトへの参照を保存します

#### ネイティブメソッドスタック

- CやC++などのJava以外の言語で書かれたコードが実行されるための領域
- JNI(Java Native Interface)によってアクセスされます

## ガベージコレクタの役割

Javaプログラムを実行していると、オブジェクトは次々と生成されます。
ただい、使い終わったオブジェクトを手動で削除する必要はありません。
**ガベージコレクタ**がその役目を担っています。

### 使われなくなったオブジェクトを片付ける仕組み

ガベージコレクタは、プログラム中で「どのオブジェクトが使われなくなったか」を検出し、それを解放します。
これにより、新たなオブジェクトを作成するためのメモリを確保します。

### ガベージコレクションの例

以下は、Javaのヒープメモリとガベージコレクションがどのように機能するかを簡潔にまとめたものになります。

1. プログラム中で変数がオブジェクトを参照する
2. 変数がスコープを抜けると、そのオブジェクトへの参照がなくなる
3. ガベージコレクタは「参照のないオブジェクト」を検出し、メモリを解放する

#### 簡単な例

```java
{
    StringBuilder sb = new StringBuilder("Hello");
    // このスコープを抜けると、sbが参照しているオブジェクトは不要になります。
}
// ガベージコレクタがこの不要なオブジェクトを削除します。
```

## 参照タイプの種類

Javaでは、オブジェクトへの参照にもいくつか種類があります。
それぞれガベージコレクタによる扱われるか方を変わってきます。

### 強い参照(Strong Reference)

- Javaのデフォルトの参照タイプ
- 参照がある限り、そのオブジェクトはガベージコレクションの対象になりません。

```java
String str = "Hello"; // 強い参照
```

### 弱い参照(Weak Reference)

- 弱い参照が付いたオブジェクトは、ガベージコレクションが実行されると収集されます。
- 一時的なキャッシュなどに適しています。

```java
WeakReference<StringBuilder> reference = new WeakReference<>(new StringBuilder("WeakRef"));
```

### ソフト参照(Soft Reference)

- メモリが不足しているときのみ収集される参照
- メモリに余裕がある場合は保持されるため、キャッシュに向いています。

```java
SoftReference<StringBuilder> reference = new SoftReference<>(new StringBuilder("SoftRef"));
```

### ファントム参照(Phantom Reference)

- ガベージコレクタがオブジェクトを収集した後の通知を受け取るために使用されます。
- 特殊な目的で使われる参照です。

```java
PhantomReference<StringBuilder> reference = new PhantomReference<>(new StringBuilder("PhantomRef"));
```


## 7メモリ管理のポイント

Javaの自動メモリ管理は便利ですが、注意を怠るとパフォーマンス問題やメモリリークを引き起こす可能性があります。
以下に、効率的なメモリ管理のためのポイントを挙げます。

1. **オブジェクトの使いすぎを避ける**
    - 不要なオブジェクトを作成しないようにする。
    - → 繰り返し処理で新しいオブジェクトを生成するのではなく、既存のオブジェクトを再利用する。
2. **コレクションに対して適切なサイズを設定する**
    - ArrayListやHashMapなどのコレクションは、初期サイズを適切に設定することで不要なメモリ消費を防ぎます。
3. **不要な参照をクリアする**
    - 長時間生存するオブジェクトが他のオブジェクトを参照していると、ガベージコレクターが解放できなくなります。
    - → コレクションから使い終わったオブジェクトを削除する。
4. **適切な参照タイプを使う**
    - ソフト参照や弱い参照を使うことで、メモリ圧迫時にオブジェクトが解放されやすくなります。

# 最後に
Javaのメモリ管理は、一見複雑に思えるかもしれません。
しかし、その多くをガベージコレクタが肩代わりしてくれるため、開発者にとって非常に強力な助けとなります。
とはいえ、「自動だから安心」と油断せず、プログラム設計の段階から効率的なメモリ使用を意識することが重要です。

ぜひ今回の記事を参考に、Javaのメモリ管理を活用してみてください！
安全第一！enumと整数値の関連付けにおける注意点

# 導入

こんにちは、もんすんです。

今回は、`enum`の`ordinal()`メソッドを使う機会があったので、それについて執筆してみました。
Javaの`enum`は便利ですが、その使い方次第でコード保守が難しくなることがあります。
今回は、`enum`と整数値を安全に関連付ける方法を解説していきます。

# `ordinal()`メソッドについて

## `ordinal()メソッドとは`

`ordinal()`メソッドは、`enum`定数の定義順序を表すインデックス値を返してくれるメソッドです。
このインデックスは`enum`の最初の定数を`0`とし、それ以降の定数は1ずつ増加させた値になります。

### サンプル

以下は`ordinal()`メソッドを使用する簡単なサンプルです。

```java
public enum Day {
    MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY
}

public class OrdinalExample {
    public static void main(String[] args) {
        for (Day day : Day.values()) {
            System.out.println(day + ": " + day.ordinal());
        }
    }
}
```

このコードの出力は、以下のようになります。

```
MONDAY: 0
TUESDAY: 1
WEDNESDAY: 2
THURSDAY: 3
FRIDAY: 4
```

### `orginal()`の使用目的

- `ordinal()`は主に、`enum`定数の相対的な位置を参照する際に役立つ
- **ソートや順序比較**が必要な場合において、インデックスとして活用できる

しかし、`ordinal()`をビジネスロジックに組み込むことは多くの場合推奨されません。

## なぜ`ordinal()`のビジネスロジックへの適用は危険なのか？

では、`ordinal()`の利用における問題について考えていきます。
ここでは、以下のコードを考えていきます。

```java
public enum Ensemble {
    SOLO, DUET, TRIO, QUARTET
}

public int numberOfMusicians() {
    return ordinal() + 1;
}
```

このコードでは、`ordinal()`を利用して、定数に人数を割り当てています。
しかし、この方法には以下のような問題が潜んでいます。

1. **定数の並び順に依存する**  
   定数の順序を変更したり、新しい定数を途中に追加すると、割り当てられる値が変わってしまいます。

1. **重複する値を持つ定数を定義できない**  
   例えば、8人編成の「OCTET」が追加されたとします。
   それと同じ人数で「DOUBLE_QUARTET」を追加したい場合、同じ値を割り当てる方法がありません。

3. **途中の値をスキップできない**  
   例えば、12人編成の「TRIPLE_QUARTET」を追加したい場合、11人編成のダミー定数を無理やり追加する必要があります。

## ではどうするか？？
### 安全な方法：インスタンスフィールドを使う

`ordinal()`を使わず、`enum`にインスタンスフィールドを持たせることで、値の安全な管理が可能になります。
以下はその例になります。

```java
public enum Ensemble {
    SOLO(1),
    DUET(2),
    TRIO(3),
    QUARTET(4),
    QUINTET(5),
    SEXTET(6),
    SEPTET(7),
    OCTET(8),
    DOUBLE_QUARTET(8),
    NONET(9),
    DECTET(10),
    TRIPLE_QUARTET(12);

    private final int numberOfMusicians;

    // コンストラクタ
    Ensemble(int size) {
        this.numberOfMusicians = size;
    }

    // 値を取得するメソッド
    public int numberOfMusicians() {
        return numberOfMusicians;
    }
}
```

#### この方法のメリット
1. **順序変更に強い**  
   定数の順序を変更しても、`numberOfMusicians`の値には影響しません。

2. **重複する値を持つ定数を定義できる**  
   例えば「OCTET」と「DOUBLE_QUARTET」に同じ値(8)を割り当てることができています。

3. **途中の値をスキップできる**  
   必要な値(例えば12)だけを直接設定でき、使わない値(例えば11)をスキップ可能です。

## `ordinal()`の正しい使い方

Javaの公式ドキュメントでは、`ordinal()`は特殊なデータ構造(`EnumSet`や`EnumMap`)で使用するために設計されているとされています。
具体的には、`enum`を配列のインデックスとして扱う場合などに適しています。
...とのことでした。

それ以外の目的で`ordinal()`を使うのは避けたほうがよさそうですね。

# 最後に

`ordinal()`メソッドは手軽で便利に見える一方で、値の関連付けに使用することは避けたほうが良いことを例を示しながら紹介しました。
代わりに、`enum`にインスタンスフィールドを追加し、値を明示的に管理する方法を採用しましょう！

ぜひ今回の内容が誰かの役に立てば、と思います！
【実践！】シンボルプロンプトで作るチャットボット開発入門


皆さん、こんにちは。最近、AIとの効率的なコミュニケーション方法について調べる機会があり、「シンボルプロンプト」という興味深い手法を見つけました。この記事では、Poe.comを使って実際にチャットボットを作る過程で得られた気づきを、自分用のメモも兼ねて残しておきます。誰かの参考になれば幸いです。

## この記事のターゲット
- 長いプロンプト作成に疲れている方
- より効率的なAIとの対話方法を探している方
- プログラミング経験がなくてもチャットボットを作ってみたい方

## 前提条件
- Poe.comのアカウント
- AIプロンプトの基礎的な理解
- 作ってみたいチャットボットのアイデア

## 目次
1. [シンボルプロンプトとは](#シンボルプロンプトとは)
2. [基本的な記号と使い方](#基本的な記号と使い方)
3. [Poe.comでの実装手順](#poecomでの実装手順)
4. [実践的な使用例](#実践的な使用例)
5. [応用とカスタマイズ](#応用とカスタマイズ)

## シンボルプロンプトとは

AIとの対話では、通常「〜について、〜のような観点で、〜を考慮しながら...」といった長文の指示を書く必要があります。シンボルプロンプトは、これを記号を使って簡潔に表現する手法です。

### 記号による表現の利点
1. トークン数の削減
2. 意図の明確な伝達
3. 構造化された指示
4. 修正・更新の容易さ

## 基本的な記号と使い方

| 記号 | 意味 | 使用例 |
|------|------|--------|
| = | 定義 | `目的 = チャットボット作成` |
| → | フロー、変換 | `入力 → 処理 → 出力` |
| + | 追加、結合 | `基本機能 + 拡張機能` |
| [] | リスト | `機能 = [認証, 検索, 通知]` |
| () | グループ化 | `処理(データ検証)` |
| ? | クエリ、確認 | `設定の確認?` |

## Poe.comでの実装手順

### 1. ボットの作成
実際に使えるボットを用意しました：
https://poe.com/SymbolPromptBot

まずはこちらにアクセスして、実際の動作を確認してみましょう。

### 2. システムプロンプトの設定
以下のようなフレンドリーな設定を使用します：

```
やあ！僕はシンボルくん。
AIとのおしゃべりがもっと楽しくなるお手伝いをするよ！

【シンボルの基本ルール】
僕は以下の記号を理解します：
= : 定義（AとBは同じ）
→ : 変換、フロー（AからBへ）
+ : 追加（AとBを組み合わせる）
[...以下省略]
```

## 実践的な使用例

### ブログ記事作成の場合
```
ユーザー：ブログ記事を書きたいんです

ボット：では、基本情報を整理しましょう！
「テーマ = 〇〇」の形で教えてください。

ユーザー：テーマ = プログラミング学習
対象 = 初心者
構成 = [導入, 基礎, 実践, まとめ]

ボット：素晴らしいですね！
各セクションの重要度を確認させてください：
重要度 → 基礎 > 実践 > 導入 > まとめ
このような優先順位で合っていますか？
```

### 注意点
- 記号の前後にはスペースを入れましょう
- 複雑な指示は階層的に分けると良いです
- 曖昧な場合は `?` を使って確認を取りましょう

## まとめ

シンボルプロンプトを使うことで、AIとのコミュニケーションがより効率的になります。特にPoe.comを利用すれば、プログラミング経験がなくても手軽にチャットボットを作成できます。

ぜひ実際に試してみて、AIとの新しいコミュニケーション方法を体験してください！

## 環境情報
- Poe.com（2024年1月時点）
- 使用モデル：Claude-instant
- 記事作成日：2024年1月8日

## 参考文献・関連リソース

### 公式ドキュメント
- Poe.com 公式ドキュメント
- Anthropic Claude プロンプトガイド
- シンボルプロンプトコミュニティガイドライン

### 関連記事・チュートリアル
- [【超時短術】AIのプロンプトは記号で書け！『シンボルプロンプト』で効率化・性能UP！](https://note.com/mbbs/n/n643266507460)  
  シンボルプロンプトの基本概念や効果について、分かりやすく解説されています。本記事の多くのアイデアは、この記事から着想を得ています。

### コミュニティリソース
- Poe.comユーザーコミュニティガイド
- AIプロンプトエンジニアリング実践ガイド
- チャットボット開発ベストプラクティス集

※ 各リソースの内容は2024年1月時点のものです。最新の情報は各サイトでご確認ください。

## 著者について
普段はAIプロンプトエンジニアリングやチャットボット開発に関する情報を発信しています。
フィードバックやご質問がありましたら、コメントでお気軽にどうぞ！
(7話_最終話) 熱波師おかん、ついにSnowPro Coreに合格！ありがとう！

こんにちは、サウナ熱波師を目指しながらSnowflakeの勉強に励んでいるアキコです！

前回、SnowProCore試験に挑戦したものの、盛大におもいっきり不合格となりましたが、その経験を糧に再挑戦を決意しました。まぁ、正直言うて、あの時はほんまに悔しかったんやけど、それを乗り越えたおかげで成長できたと感じてます。やっぱり失敗から学ぶことは多いんやなぁ、と冷静に振り返る時間を持ちました。この時間がめっちゃ大事で、次の挑戦に向けてどこを強化せなあかんかがよう分かりました。

というのは建前で、不合格からめっちゃ落ち込んでました。なんでこんなことに挑戦はじめてしまったんかと。

なにはともあれ再挑戦に向けて、自分なりに取り組んだ具体的な方法をシェアしたいと思います。これは私の個人的な経験ですが、同じように挑戦し続けている皆さんにとって少しでも参考になればええなぁと思っています。

1. 勉強計画の見直し

前回の試験での反省点を踏まえて、勉強計画をまるっと見直しました。だらだらと要点をひとつずつ理解するのではなく要点を絞る作戦です。以下の点に特に注力しました。

SNOWFLAKEサイトの精読: いわゆる公式ドキュメントというものですね、をじっくりと読み直し、細かい部分をちゃんと理解するように心掛けました。読み返してみると、「あぁ、ここがポイントやったんやな」と気づくことがたくさんありました。
でも、目次もあんまりようわからん広すぎる公式ドキュメントを一から読むのは途方にくれる作業です。
先輩合格者さんのブログがおすすめしていた問題集に、実際に出題される問題回答と、その選択肢が正解となる根拠が書かれているのでそれをしっかり読み込みました！基礎がためはほぼこれで乗り切りました。一回目の受験のときに知って起きたかったひとつです。


また、学習中には自分の弱点に対して徹底的に取り組む時間を確保しました。これが、まぁ時々「ほんましんどいわ」って感じる部分でもありましたけど、知識の穴を埋めることが合格への最短ルートやったんです。ネット上で公開されているいろんなブログ記事も参考にしました。特に、他の方が試験に向けてどうやって準備を進めたんかを知ることが、自分の計画を見直す上でめっちゃ役立ちました。

2. モチベーションの維持

不合格のショックは思った以上に大きくて、正直なところ「もう資格取得なんてええかな…」って諦めかけたんですけどね。けど、ここで諦めたらあかん！！って思って、なんとか立ち直ることにしました。モチベーションを維持するために、以下の方法を試しました。


皆さんのブログをたくさん読む: 試験に合格した方々のブログを読みまくって、「この人もこんなに頑張ったんや」って知ることで、すごく励まされました。他の方の経験談を読むことで、「自分だけがしんどいわけやないんやな」と共感できて、再挑戦する勇気をもらいました。新しい学びがあって、めっちゃ参考になりました。

特に参考にさせていただいた皆様のブログです。たくさんありすぎて、２つに絞らせてくださいすみません。

bs2024さん

https://qiita.com/bs2024/items/e22a89c00a8990b1c28b#comment-7779e1a8a1b47fe204a6

おそらく関連知識が相当に豊富な方のブログだと思います。１週間という短期間で合格できるとは、私には無縁の世界だと最初は思ったのですが、学習方法にナルホドと思いました。
何百問とある練習問題をひとつひとつ理解深くしていたらいつまでたってもおわりません。まずは考え込むの禁止して一気に通読するというやりかたは私にはなかったので勉強始めは気楽に取り組むことができました！この場を借りてありうございます。


侍DOGEさん

https://note.com/samurai_doge/n/na948464cb5a4

さらに具体的に記載してくださっているので、このブログを頼りに最後までやりきりました！私のように初心者から取り組む場合にもとても参考になると思います。
「もう少し勉強しておけばよかったなと思うこと」に記載くださっている部分については、合格だけではなくより高得点を狙う方にも大変参考になるのではないでしょうか。この場をお借りしてお礼申し上げます。

私が合格を勝ち取るのにつかった、いわゆる問題集はお二人に紹介されていたこちらです

https://note.com/data_ku/m/mb14f6943819e

データ空海研究所さんの問題集。ちょっと高いので躊躇したのは正直な気持ちです。しかし一度不合格してペケ万円を失った私は合格が第一優先度。もう一度落ちるか、いま問題集を買うかを天秤にかけ迷わず購入しました。前半に書いた通り、リンク先の公式説明へ飛べるので基礎固めも含めてこれに頼りました。結果、大正解中の大正解。いろんなブログで紹介されていることからも信頼性が伺えます。

２つ目はこちら

https://www.udemy.com/course/snowflake-snowpro-core-certification-exam-practice-sets/

VKさんの問題集。英語なのであまりすっと入ってきませんでしたが、侍DOGEさんとさんが書いてくださっているとおり、この２つの問題集が補完しているのだと思います！
bs2024さんは１つ目のみで合格されたようですので、ご経験などによるのかもしれません。私はVKさんの問題集は、アドバイスいただいたとおり1-3のみしっかり取り組み、4-6はやりませんでした！気力の関係もあります。。
一度解いた問題を２回３回と繰り返すのは気力も持つのですが、新しい問題に取り組むのはかなり元気じゃないと難しいですね。4-6は1-3の問題を並び替えただけと書いてくださっていますが、それでも新領域をいまからクリックするのは大変おっくうで諦めました！


3. 再挑戦の結果

そして迎えた再試験の日。前回不合格になったのと同じ会場。同じ手順。緊張感はんぱなかったです。でも、これまでの努力を信じて問題に取り組みました。実際に試験を受けてみると、前回よりも自信を持って回答できる部分が増えていて、特に前回苦手やった問題もちゃんと理解できていることが実感できました。

最終的な結果は… 合格 でした！

この瞬間、ほんまに言葉では表現できへんくらい嬉しかったです。不合格から合格への道のりは決して簡単やなかったですけど、その過程で学んだことはほんまに大きなものでした。努力を続けることで、必ず自分の成長に繋がるってことを改めて実感しました。
ちなみに点数は750点台！（750点が合格ラインですので、ほぼ足切り寸前）

まとめ

不合格からの再挑戦は、自分にとってほんまに大きな挑戦であり、自信を取り戻す旅でもありました。そして、成長のためには失敗を恐れずに挑戦し続けることが必要なんやなぁと強く感じました。

いやぁ、ほんまにこの１年以上、いろいろあったなぁ。試験勉強の途中、何回も「やめたろか」って思う瞬間があったけど、そのたびに「いや、ここで諦めたら悔しいやろ」って自分を奮い立たせました。結局、あの悔しさがエネルギーになったんかもしれません。

最後まで読んでくれてありがとう！これでやっと、やっとの思いで次に踏み出せます。資格取得を達成したことで現職の業務整理と引き継ぎ、そして熱波師になるために動き出します！

ほな、さようなら、またね！
Verify Signature

[Previous << Generate a Signature](https://qiita.com/flowcadence/items/85bdee18d6cc9b28cc2f)
[Next >> Snapshot Save](https://qiita.com/flowcadence/items/520a80cf91f305407954)

https://qiita.com/flowcadence/items/3073d69c6e9895e68b5a#flow-cli-と-fcl

引数のメッセージと署名作成者の公開鍵に基づいて署名の有効性を確認します。
```ruby
flow signatures verify <message> <signature> <public key>
```

<h1>Example Usage</h1>

```ruby
> flow signatures verify 
  'The quick brown fox jumps over the lazy dog' 
  b1c9eff5d829fdeaf2dad6308fc8033e3b8875bc185ef804ce5d0d980545ef5be0f98b47afc979d12272d257ce13c4b490e431bfcada485cb1d2e3f209be8d07 
  0xc92a7c72a78f8f046a79f8a5fe1ef72424258a55eb869f13e6133301d64ad025d3362d5df9e7c82289637af1431042c4025d241fd430242368ce662d39636987

Valid 			 true
Message 		 The quick brown fox jumps over the lazy dog
Signature 		 b1c9eff5d829fdeaf2...7ce13c4b490eada485cb1d2e3f209be8d07
Public Key 		 c92a7c72a78...1431042c4025d241fd430242368ce662d39636987
Hash Algorithm 		 SHA3_256
Signature Algorithm 	 ECDSA_P256
```

<h1>Arguments</h1>

<h3>Message</h3>

* Name: `message`

署名の作成に使用されたメッセージデータ

<h3>Signature</h3>

* Name: `signature`

検証されるメッセージの署名

<h3>Public Key</h3>

* Name: `public key`

署名の作成に使用された秘密鍵の公開鍵

<h1>Flags</h1>

<h3>Public Key Signature Algorithm</h3>

* Flag: `--sig-algo`
* Valid inputs: `"ECDSA_P256"`, `"ECDSA_secp256k1"`

署名に使用されたキーペアのECDSA署名アルゴリズムを指定します

Flowはsecp256k1とP-256の曲線をサポートしています。

<h3>Public Key Hash Algorithm</h3>

* Flag: `--hash-algo`
* Valid inputs: `"SHA2_256"`, `"SHA3_256"`
* Default: `"SHA3_256"`

署名に使用されたキーペアのハッシュアルゴリズムを指定します

<h3>Filter</h3>

* Flag: `--filter`
* Short Flag: `-x`
* Valid inputs: case-sensitive name of the result property.

結果から、唯一の値として取得したいプロパティの名前を指定します。

<h3>Output</h3>

* Flag: `--output`
* Short Flag: `-o`
* Valid inputs: `json`, `inline`

コマンド結果のフォーマットを指定します。

<h3>Save</h3>

* Flag: `--save`
* Short Flag: `-s`
* Valid inputs: valid filename

結果を保存したいファイル名を指定してください。

<h3>Log</h3>

* Flag: `--log`
* Short Flag: `-l`
* Valid inputs: `none`, `error`, `debug`
* Default: `info`

ログレベルを指定します。コマンド実行中に表示する出力を制御します。

<h3>Version Check</h3>

* Flag: `--skip-version-check`
* Default: `false`

低速な接続を避けて処理を高速化するために、起動時のバージョンチェックをスキップします。

*Last updated on **Nov 26, 2024** by **Giovanni Sanchez***

翻訳元

https://developers.flow.com/tools/flow-cli/utils/signature-verify

***
<b>[Previous << Generate a Signature](https://qiita.com/flowcadence/items/85bdee18d6cc9b28cc2f)
</b>

[Flow blockchain / Cadence version1.0ドキュメント](https://qiita.com/flowcadence/items/3073d69c6e9895e68b5a) (Verify Signature)

<b>[Next >> Snapshot Save](https://qiita.com/flowcadence/items/520a80cf91f305407954)</b>
テスト自動化導入！！本を片手に挑戦した日々

## 本を頼りに進める楽しさ
### 丁寧な解説に助けられる
自動化ツールに関する本には、具体的な手順や考え方が丁寧に説明されていて、初心者の私にとってはありがたいガイドとなりました。実際に手を動かしながら試すと、本で読んだ内容が次第に形になっていく感覚が楽しくて、作業に没頭しました。
夢中になって時間を忘れる

私が体験したあるあるは、テスト自動化に挑戦し始めると、いつの間にか作業に没頭していることです。
特に初心者にとっては、、気づけばあっという間に過ぎているものです。今回は、テスト自動化に取り組む中で、どのようにして時間を忘れるほど夢中になってしまうのは圧倒的な魅力だと思いました。
T-DASH感想

私は現在、大学で情報システムに関する勉強をしています。その一環として、テスト自動化ツール「T-DASH」を使う機会がありました。


T-DASHは、テスト自動化を始めるには非常に優れたツールで、自動化の奥深さを知ることができる点で、学生の私にとっても大きな学びを与えてくれるものでした。

自動化もかなり注目しているので、とても楽しい経験になったと自負をしています。
【VSCODE】便利なショートカットメモ

## まとめられている便利な記事
https://qiita.com/TakahiRoyte/items/cdab6fca64da386a690b

## Settingを開く
`Ctrl + ,`

## コマンドパレットを開く
`Ctrl + Shift + p`

## ショートカットキーのカスタマイズ
### 1. `Ctrl + k`→`Ctrl + s`でKeyboard Shortcutsを開く
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/943997/a55d25bb-882b-8fed-55a7-84ef9d7740fb.png)

### 2. 編集したいコマンドを検索
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/943997/13cf1dec-def8-dbd2-f019-e88f24f8bc5a.png)

### 3. 編集したいコマンドをダブルクリックし、編集して保存する
:::note info
編集できるのは`Keybinding`のみ
:::
https://code.visualstudio.com/api/references/when-clause-contexts

## VSCodeのリフレッシュ
コマンドパレットを開き（`Ctrl + Shift + p`）、"Reload Window"を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/943997/168e258a-e818-b245-c875-9cb73bd961e8.png)
DDJ-FLX4のPadをトグルスイッチにする

# 目標
- Elixirで作る
- PioneerDjのDDJ-FLX4を使う
- 各Padの状態を維持する

# 前提知識
PadのLEDと入力判定

https://qiita.com/t-yamanashi/items/c75022fd68132c47030b

Agentで状態を維持

https://qiita.com/Yoosuke/items/ceeb989e7c96cd9f3a63

# 仕様
- Padを押すと、オン状態で光る
- 状態は押すとオンオフ反転する

# ソース

```elixir
defmodule Button do
  @moduledoc """
  Documentation for `Button`.
  """
  use Agent
  @deck1 "97"
  @led_on "7F"
  @led_off "00"

  @pad1 "00"
  @pad2 "01"
  @pad3 "02"
  @pad4 "03"
  @pad5 "04"
  @pad6 "05"
  @pad7 "06"
  @pad8 "07"

  def pad_list, do: [@pad1, @pad2, @pad3, @pad4, @pad5, @pad6, @pad7, @pad8]
  def pad(no), do: pad_list() |> Enum.at(no)

  def start() do
    state = Enum.map(1..8, fn _ -> false end)

    Agent.start_link(fn -> state end, name: __MODULE__)

    {_, input} = PortMidi.open(:input, "DDJ-FLX4 MIDI 1")
    {_, output} = PortMidi.open(:output, "DDJ-FLX4 MIDI 1")
    PortMidi.listen(input, self())

    midi_in(input, output)

    PortMidi.close(:input, input)
    PortMidi.close(:output, output)
  end

  def midi_in(input, output) do
    receive do
      {^input, [{{144, 11, 0}, _}]} ->
        IO.inspect("end")

      {^input, [{{_, no, 127}, _}]} ->
        flg = get_button_state(no)
        set_button_state(no, !flg)

        get_state()
        |> IO.inspect()

        pad_led(output, @deck1, pad(no), led_sw(!flg))

        midi_in(input, output)

      _ ->
        midi_in(input, output)
    end
  end

  def get_button_state(index) do
    get_state()
    |> Enum.at(index)
  end

  def set_button_state(index, flg) do
    get_state()
    |> List.replace_at(index, flg)
    |> set_state()
  end

  def get_state, do: Agent.get(__MODULE__, & &1)
  def set_state(state), do: Agent.update(__MODULE__, fn _ -> state end)

  def pad_led(output, deck, pad, led_sw) do
    [deck, pad, led_sw]
    |> send_midi(output)
  end

  def hex_to_dec(hex), do: String.to_integer(hex, 16)

  def send_midi(v, output) do
    Enum.map(v, fn x -> hex_to_dec(x) end)
    |> List.to_tuple()
    |> then(&PortMidi.write(output, &1))
  end

  def led_sw(true), do: @led_on
  def led_sw(_), do: @led_off
end

```

# 動作動画

<iframe width="560" height="315" src="https://www.youtube.com/embed/ajoZqTNrIVY?si=bkSb01w5DgI5AZ8Q" 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>
システム開発の見積もりと期待値の調整

この記事は、[Lancers（ランサーズ） Advent Calendar 2024](https://qiita.com/advent-calendar/2024/lancers) の8日目の記事です。

## はじめに
こんにちは！ランサーズの若林です。
今年は社内開発と社外の顧客に向けた提案や実務など幅広い方とエンジニアリングのお話をしてきました。
その中で多くの見積もり業務に直面し、その難しさを改めて実感しました。この記事では、実践してきた見積もりと、見積もりを通したコミュニケーションについて、共有したいと思います！

## 見積もりとは
見積もりは単なる時間やコストの予測業務ではありません。目的地に到達するための道のりを予測し、潜在的なリスクや変数を考慮するプロセスです。見積もりを共有することで、タスクの難易度やリスクを第三者と共有できます。

例えば、料理のレシピを友人に説明するとき。「30分で完成」と言うだけじゃなく、「初心者には少し難しいレシピで、慣れないと1時間くらいかかるかも。事前準備と同時調理が必要だよ」と伝えます。 これが、見積もりのコミュニケーションです。単なる時間ではなく、作業の複雑さや必要な準備を相手に伝えられます。


見積もりは、顧客や社内関係者との期待値を適切に調整するコミュニケーションツールです。

非エンジニアに見積もりを通じて伝えることができること：
    * 潜在的なリスクを事前に共有する
    * 顧客と開発チーム間の認識のギャップを埋める
    * 現実的なスケジュール設定を促す

## 見積もり実践
### プロジェクト内機能開発の見積もり
社内機能開発では、フィボナッチ数列を用いた見積もりを行っています。

### フィボナッチ数列とは
フィボナッチ数列は、0と1から始まり、直前の2つの数を足して次の数を作る数列のことです。
0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89...

* 1ポイント：約1時間の軽微なタスク
* 2ポイント：半日程度の簡単な実装
* 3ポイント：1日程度の中規模タスク
* 5ポイント：2-3日の複雑なタスク
* 8ポイント：1週間程度の大規模機能
* 13ポイント：2週間程度の複雑なシステム開発

![AB.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2997391/4683fc04-1fb8-eb4e-9c86-7c30c5721d95.png)

### なぜフィボナッチ数列なのか？
この数列は、数字間の比率が徐々に拡大するため、タスクの相対的な大きさを直感的に理解しやすくなります。
ポイントで議論することで、チーム内でのコミュニケーション言語が統一されます。
「このイシューは8ポイントかかるのであれば実施の検討をした方が良いかも」「1ポイントでできるなら今週のリリースに乗せられそう」、というような会話ができます。
同じ開発資産を共有しているメンバー内では複雑さの表現が容易なフィボナッチ数列を用いた見積もりは、イシューのサイズやスケジュールに対する期待値を調整することができ、効果的に活用できています。

## 顧客向け工数見積もり
顧客向け工数見積もりでは、ファンクションポイント法を活用しました。
これは、ソフトウェアの機能的な規模を客観的に測定する手法です。要件が明確な場合、機能の数や複雑さを分析することで、かなり精度の高い見積もりができます。

要件が明確な場合、機能の数や複雑さを分析することで、かなり精度の高い見積もりが可能になります。
「この機能は処理数が3で外部連携もあるのでこのポイントになります」というような客観的にわかりやすい指標になるため、顧客に対して見積もり説明をする際にも大きなずれが生じることなくコミュニケーションを取ることができました。
また、顧客の想定している工数とのギャップがあった場合には、こちらが想定している連携処理が不足していたりとリスクやタスクがあるなど認識もれの発見にもつながりました。

実際に、この手法を用いた見積もりシートの雛形を作成することができたため今後の顧客向けの見積もりでも利用できる状態になりました。
![FP.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2997391/e93874d8-9df8-9b8b-85e9-725793140866.png)


ファンクションポイントを用いた見積もりまで精度を高めるには要件の詳細化、タスクの細分化が不可欠です。
顧客への提案初期の概算見積もりの段階では今回作成した見積もりシートの粒度まで精緻化されていないことが多いので、今後概算見積もりの精度や概算見積もりにおける期待値調整をどこまでできるかというのが課題になっていきそうです。


## 期待値調整について
非エンジニアにわかりやすく丁寧に説明し、プロジェクトの本質的な課題を共有するのは、エンジニア側の責任です。このプロセスを省くと、事業部や顧客とスケジュールの認識がずれたり、運用コストが想定以上にかかったりしかねません。
実際に、今年着手していたプロジェクトでも難易度やその工程の大切さがうまく連携できていなかったことによりスケジュールやスコープが固まらないということがありました。これは大きな改善ポイントです。

追加作業や要件の変更が発生したら、その都度コミュニケーションを取ることが大切です。
変更によって別のタスクに影響が出てスケジュールを見直すことによるリスクがちゃんと握れていたのか、など振り返ると反省をすべきポイントはたくさんあります。変更影響をエンジニアが楽観的に見積もってしまっていた可能性もあります。

見積もって終わりではなく、リスクや課題を含めてプロジェクトの関係者全員が同じ認識を持てるような、定期的なコミュニケーションの場の重要性も改めて感じました。

## おわりに
常にプロジェクトや状況は変化するため、完璧な見積もりを作ることは不可能ですが、見積もりの数値に現れるプロジェクトの複雑さや規模を元に関係者とコミュニケーションをとることが大事だと改めて感じました。
プロジェクトのゴールに向けて、見積もり数値からゴールの再定義やリソースの再構築などステークホルダーと一緒に同じ方向をむいて検討できたら良いなと思っています。
SME日記その6 Streaming SVE modeでsvcntw()とsvcntsw()を実行してみる

ようやく[ArmのScalable Matrix Extension (SME)を試す](https://zenn.dev/mod_poppo/articles/arm-scalable-matrix-extension)の`veclen.c`相当のプログラムを実行できるようになったので報告します．

SMEシリーズ

- [Apple Silicon M4はM3シリーズからScalable Matrix Extension (SME)命令などが足されている](https://qiita.com/zacky1972/items/69fd802fd41ae4d7d469)
- [SME日記その1: Apple Silicon M4に搭載されたScalable Matrix Extension(SME)のベクトル長(SVL)を取得する](https://qiita.com/zacky1972/items/231fd22a1fdef15d4108)
- [SME日記その2: Apple Silicon M4にはCVTW命令は備わっていない？](https://qiita.com/zacky1972/items/a4fc98614df085586175)
- [SME日記その3: Apple Silicon M4にどの命令が実装されているかをsysctl hwの実行結果とドキュメントから推測する](https://qiita.com/zacky1972/items/427035001554cb9768bc)
- [SME日記その4 Streaming SVE modeでCNTWを実行してみる．](https://qiita.com/zacky1972/items/3182fa1693983846205d)
- [SME日記その5 Streaming SVE modeでCNTWを実行してみる Part 2](https://qiita.com/zacky1972/items/b7b5dd456fe021b30eb2)

## プログラムコード

```c:veclen.c
#include <stdint.h>
#include <stdio.h>
#include <arm_sme.h>

void streaming_fn(void)
{
  uint64_t cntw, cntsw;
  asm volatile ("smstart sm");
  cntw = svcntw();
  cntsw = svcntsw();
  asm volatile ("smstop sm");
  printf("Streaming mode: svcntw() = %llu, svcntsw() = %llu\n", cntw, cntsw);
}

int main(void)
{
  streaming_fn();
}
```

ポイントとしては，次の点です．

* `svcntw()`と`svcntsw()`についてはエラーにならない
* `__arm_locally_streaming`と`__arm_has_sme()`はリンクエラーになる
* `CNTW`という命令は存在するが，`CNTSW`なる命令は存在しない
* `svcntsw()`でどんなアセンブリコードを生成するのかは，調べても不明

## コンパイル方法

```zsh
clang -O2 -march=armv9-a+sme -o veclen veclen.c
```

## 実行の方法と結果

```zsh
% ./veclen                                       
Streaming mode: svcntw() = 16, svcntsw() = 16
```

ここまで，長かった！
レトロPCのためのBASIC講座３　INPUT文

# 前回のおさらい
前回のプログラムは１行で
10 PRINT S1+S2
という変数に代入された値の足し算結果を表示するプログラムでした。

前回ページ
[レトロPCのためのBASIC講座２](https://qiita.com/kawamo55/items/281db3edb26eb45e4768)

変数に値を覚えさせるために＝(代入演算子)を使い、GOTO命令で実行しましたがRUNコマンドだけで変数に値を入れて実行するには？

# RUNコマンドで実行するには
INPUT命令をプログラム中にれればRUNで実行できます。
では書き換えてみます
（書き換え方はちょっとしたテクニックがあるので動画を見てください）

10 INPUT S1
20 INPUT S2
30 PRINT S1+S2

# これをRUNで実行すると
行番号１０のINPUT文が実行されると？という表示がされて入力待ちになりますので値を入れ、次に行番号２０のINPUTが実行され再び？は表示されますので値を入れます。
すると、計算結果が表示されます。
これでRUNコマンドで実行できるようになりましたが、？だけではどの変数に入力しているのかわからないので・・・

# 入力している変数名を表示するように改善する
行番号１０のINPUTを以下のように書き換えます。
INPUT "S1=",S1
これで実行してみると
最初のINPUT文が実行されるとS1=と表示されるようになります。

# 今回の動画
https://youtu.be/-puG-MTGn-o
車両のGPSデータから停留を推定する

この記事は[Hacobu Advent Calendar 2024](https://qiita.com/advent-calendar/2024/hacobu)の8日目の記事です。

株式会社Hacobuで、動態管理サービス「MOVO Fleet」のエンジニアリングマネージャーをしています。

# はじめに

今年の4月1日から改善基準告示が施行され、ドライバーの拘束時間等の制約が強化されました。この改善基準告示に合わせて、MOVO Fleetにドライバーの[稼働時間を分析する機能](https://hacobu.jp/news/10683/)をリリースしました。

稼働時間分析は、トラックに取り付けたGPS端末から取得される位置情報をもとに、運転時間や停留時間、1日の拘束時間などを可視化し、法令に則しているかチェックする機能を提供しています。

この機能では、ドライバーが適切に休憩しているかチェックするため、正確に停留（トラックが停車している）状態を取得する必要があります。Fleetチームでは、この停留状態を正確に把握するために様々な試行錯誤を重ねています。ここでは、その取り組みについて簡単にご紹介します。


# 地図メッシュごとに集計する

地図上の領域を表現するために、格子状に区切ったメッシュがよく使用されています。はじめに簡易的に停留を実装していたときは、このメッシュ内の滞在時間から停留を判定していました。

<img width="480" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3954349/b9af3e84-d163-a15e-8b82-a07e6f3a4aef.png">

この方法の最大のメリットは、実装がとても簡単であることです。メッシュは緯度経度から直接計算できるため、一定期間内の位置情報を参照してメッシュ内の経過時間を集計すれば判定できます。

デメリットは、メッシュの境界で集計単位が分かれてしまうため、停留地点がメッシュ境界付近にあると位置情報のばらつきによってメッシュが分かれ、1つの停留として判別できないことがよく起こります。

# 移動速度の変化から判定する

次に試した方法は、各ログの移動速度（移動距離）から推定する方法です。各GPSログの移動速度が落ちた時に停留と判別します。

<img width="480" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3954349/f3d54386-8d35-dea9-bb7c-2ab7fd57f21c.png">

この方法のメリットは、判定が単純であることと、デバイスから上がってくるログを逐次処理して、即時に停留の判定ができることです。

デメリットとしては異常値に弱く、取得される速度のゆらぎで意図しない停留の開始・終了が発生してしまうことです。また、停車後すぐにエンジンを切るとGPSが途切れ、速度の落ち込みを取得できないこともあります。今回のように安定して位置情報が取れないケースでは、期待通りの結果を得ることができません。

# クラスタリングの手法を使う

最後に、現在チームが実用化に向けて検討を進めている方法で、クラスタリングのアルゴリズムを使って推定する方法です。停留時はGPSの位置情報が近くに密集するため、その位置情報のクラスタリングを抽出することで停留を抜き出すことができます。

<img width="480" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3954349/77f851d8-a80f-0558-38d5-c241cfb1a30a.png">

メリットとしては、ノイズ（位置情報のゆらぎ）が多いデータに対してもロバストに判別できることです。図のように、信号待ちも含めて停車を取得できていそうです。

もちろん前述の方法よりは計算コストがかかりますが、問題になりそうなレベルではありません。実用化にはアルゴリズムをそのまま使うだけではうまくいかないところも多いですが、チーム内で試行錯誤を進めて一通り改善させることができました。


# おわりに

クラスタリングの有効性が確認でき、実用化に向けたアルゴリズムの改善も進められたので、実際にサービスに導入する準備を進めています。単純な機能実装にとどまらず、こうした研究開発要素が含まれると非常におもしろいなと感じました。今後も、今回のように一つ一つの品質にこだわりながら、チーム一丸となって取り組んでいきたいと思います。
「品質」とは？

# はじめに
本記事は、[フラー株式会社 Advent Calendar 2024](https://qiita.com/advent-calendar/2024/fuller-inc) の9日目の記事です。
8日目は [@inoriko711](https://qiita.com/inoriko711) さんで「[復職記 〜第二子〜](https://inoriko.hatenablog.com/entry/2024/12/08/113627)」でした。

# 「品質」とは？
みなさんはソフトウェアの「品質」について考えたことがあるでしょうか。
例えばスマホアプリは、何を満たしていれば「高品質」でしょうか。

- ストアでの評価が高いこと？
- バグ（欠陥）が少ないこと？　
- コードが保守しやすく、拡張性が高いこと？
- 一貫性がある、わかりやすいデザインであること？
- アクセシビリティが高いこと？
- 利用ユーザー数が多いこと？
- アプリがビジネスに貢献すること？

<a id="#Chapter1"></a>
# 品質は誰かにとっての価値である
ISO（JIS）、SQuBOK、その他様々な専門家がソフトウェアの品質を定義していますが、
今回はワインバーグ氏の「品質は誰かにとっての価値である」という定義を取り上げます。

ここでいう「誰か」とは、
ユーザー・開発者・クライアント（顧客）・その他様々なステークホルダーを指します。

クライアント（顧客）は利益につながるアプリに価値を感じるでしょうし、
特定のユーザーは、アクセシビリティ対応されていることで「高品質」と感じるでしょう。
当たり前の話ですが、立場や人によって価値観は様々です。

しかし、全員の品質基準を完璧に満たすことは難しく、
時には実装にかかる工数（予算）とのトレードオフになることも多いと思います。

工数以外にも例えば、
アクセシビリティへの配慮で画面を高コントラストにすると、
一般ユーザーにとっては目が疲れやすいデザインになってしまう懸念があります。
また、アクセシビリティやユーザビリティを優先することで、
企業のブランドカラーに沿った実装が難しくなることもあるでしょう。
<a id="#Chapter2"></a>
# 品質（価値）を最大化するには
つまるところ、品質とは誰かにとっての価値でしかなく、
その「誰か」も「誰かにとっての価値」もソフトウェアによって千差万別です。

- 自分が向き合うべき「誰か」は誰か？
- その「誰か」にとっての価値は何か？
- それぞれの価値に対して、自分の職域でどう寄り添えるか？

自分が関わるソフトウェアの価値について、あらゆる職種が真剣に考え、
「誰か」に寄り添ったモノこそが、高品質と呼べるのではないでしょうか。

…的な感じで綺麗にシメたかったんですが、
**なんと！もっと綺麗に言語化されたものをミッションに掲げている会社を見つけました！**
**「フラー株式会社」です！**

---
### ヒトに寄り添うデジタルを、みんなの手元に。 
スマホアプリのデータ分析から始まったフラーは、
分析・企画・デザイン・開発などあらゆる領域でヒトに向き合い、
デジタルの価値を考え、本当に必要なモノを創り続けてきました。

だからこそ、知っています。
デザインや技術だけが素晴らしくても、本当に必要なモノは創れないことを。
デジタルのその先にいる、ヒトに寄り添う大切さを。

ヒトに寄り添うデジタルを、みんなの手元に。
本当に必要なモノにこれからも向き合い続ける、私たちのミッションです。

---

# おわりに
ここまでお読みくださった方、ありがとうございました。

最後、考えが似てる風に会社のミッションを紹介しましたが、
事前に何の許可も取ってないので、もし解釈が違ってたら会社に消されると思います。
（あっ！僕が消されるとかじゃなく、記事の該当箇所が消されると思います！）

[フラー株式会社 Advent Calendar 2024](https://qiita.com/advent-calendar/2024/fuller-inc) はまだまだ続きます。
10日目は [@furusax](https://qiita.com/furusax) さんです。お楽しみに！
【Vite】個人メモ


## SCSSを利用できるようにする

```terminal
# .scss and .sass
#　以下どちらか。
npm add -D sass-embedded
npm add -D sass

# .less
npm add -D less

# .styl and .stylus
npm add -D stylus
```

### `npm add -D sass-embedded` 後に警告が出る
```terminal:警告内容
Deprecation [legacy-js-api]: The legacy JS API is deprecated and will be removed in Dart Sass 2.0.0.

More info: https://sass-lang.com/d/legacy-js-api
```
#### 警告の意味
Dart Sassの「旧JavaScript API (Legacy JS API)」が非推奨になったので、Dart Sassバージョン2.0.0以降で削除するとのこと。

#### Dart Sassとは
CSSプリプロセッサ**Sass**の実装の一つ。
特徴としては、Node.js環境での利用を想定してJavaScript APIを提供している。しかし、古いAPI（Legacy JS API）のメンテが非効率になってきたので、新しいAPIへの移行を進めている。

#### Legacy JS APIとは
古いNode.js API（例: require('sass').render() や renderSync()）などのこと。


### 対処方法

```diff_tsx
import { defineConfig } from "vite";

export default defineConfig({
+  css: {
+    preprocessorOptions: {
+      scss: {
+        api: "modern-compiler",
+      },
+    },
+  },
});

```

https://vitejs.dev/config/shared-options#css-preprocessoroptions

## .evnの値をフロントエンド側で取得する
```.env
APP_URL=http://localhost
VITE_BASE_URL=${APP_URL}

VITE_TEST=APPLE
```

```tsx:tsx
// http://localhost
console.log(import.meta.env.VITE_BASE_URL);

// apple
console.log(import.meta.env.VITE_TEST);
```

:::note info
viteの場合は`VITE_`から始める。
ビルドツール毎に接頭語が変わるので注意。
:::
Postmanで自動保存の機能を有効にする

# はじめに ー Postmanの設定をお好みで調整
初めてPostmanを使用する際、ユーザーがすぐに作業に取りかかれるよう、多くの機能は自動的に設定されています。しかし、お好みに合わせて、簡単にカスタマイズできます。

設定を変更するには、Webアプリの右上の歯車アイコンをクリックします。

![ss_Postman_setting.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138154/05e7e380-b646-df56-7e1c-26219bff9997.png)

次に「設定」を選択します。

![ss_Postman_setting_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138154/8788e50f-28da-28ab-62d2-70eb0cc6f7f7.png)

下の「一般」画面が表示されます。ここで、Postmanの設定をカスタマイズします。

![ss_Setting_general.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138154/be31b980-78d1-1fe6-6e41-23a06aeb1424.png)

:::note info
デスクトップアプリをご利用の場合、Macの場合は「⌘ + ,（カンマ）」、Windowsの場合は「Ctrl + ,」のショートカットキーからも設定画面にアクセスできます。
:::

尚、PostmanのUIを日本語にするには、Kuramotoさんの記事をご参考ください。

https://qiita.com/umorih-hm/items/ad742fe62c9acfc99bd0

## 自動保存の機能を有効
それでは、自動保存の機能を設定してみましょう。上記を参考に「一般」画面を表示させます。

次に、下のスクリーンショットを参考に自動保存の機能を設定してみます。

左側の「一般」が選択されていることを確認し、「アプリケーション」までスクロールします。「自動保存」をオンにすることで自動保存の設定を有効にします。

![ss_Setting_Autosave.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138154/7863f4f2-6639-c0b7-2231-b3b5f044db48.png)

## 最後に
短いですが、Postmanで自動保存の機能を有効にする手順を説明させていただきました。
【AWS】S3とCloudFrontを使用したWebサーバの構築①

この記事では、S3とCloudFrontを使用してWebサーバーの構築を実施しています。

# S3バケットの作成
1\. AWS Management Consoleにログイン
2\. S3バケットを作成
        　①S3を検索する 
 　![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3948626/1a3ede92-538e-fd69-bf48-24185edf9199.png)
　②S3の画面で「バケットの作成」をクリックする
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3948626/da804f4b-2a9f-bc9a-81e9-4b84209fcefd.png)
　③バケットの設定を行う
 　【一般的な設定】
 　　AWSリージョン：
   　　　自身が選択しているリージョンが表示されます
　　バケットタイプ：
  　　※バケット作成後にバケットタイプは変更できません
    　　　汎用　　　　→すべての機能と連携ができる。今回は、CloudFrontを使用するため
       　　　　　　　　　　こちらを選択
　　　ディレクトリ→S3 Express One Zone ストレージクラスと一部の Amazon S3 機能のみ
   　　　　　　　　　　連携ができる。低レイテンシーな通信が可能なのが魅力。
　　　バケット名：
　　　　任意のバケット名(他ユーザーが使用していな一意である必要がある)
　　　既存のバケットから設定をコピー：
　　　　今回は新規で作成するため選択しない
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3948626/2b5e79d3-1951-57bd-ef3a-2e7d23fe63dd.png)
　【オブジェクト所有者】
 　　ACL無効
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3948626/e60aaab5-988c-f059-860b-8e530f6f96f2.png)
　【このバケットのブロックパブリックアクセス設定】
　　パブリックアクセスをすべてブロック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3948626/44368c40-9656-0b50-ec58-6e303869f450.png)
　【バケットのバージョング】
　　バケットのバージョング：
　　　無効にする→ストレージ使用量が有効時に比べ増加するため、コストが抑えられる
　　　有効にする→誤った操作をした時などにデータの復旧ができるため、こちらで設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3948626/9f24ef6f-c8d8-806a-05fc-abc17ec234e9.png)
　【タグ-オプション]
 　　今回は特に設定しない
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3948626/8e2b3db8-72f2-e34c-a0c3-581cd3ea34a8.png)
　【デフォルトの暗号化】
　　暗号化タイプ：
　　　Amazon S3 マネージドキーを使用したサーバー側の暗号化 (SSE-S3)　→有効
　　　AWS Key Management Service キーを使用したサーバー側の暗号化 (SSE-KMS)
　　　AWS Key Management Service キーを使用したデュアルレイヤーサーバー側の暗号化 
   　　　(DSSE-KMS)
　　バケットキー：
　　　無効にする
　　　有効にする→設定
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3948626/53e1815e-bb45-486d-0fed-3c0b0206ad36.png)
　【詳細設定】
　　→今回は特に設定しない
上記の設定を行い、「バケットの作成」をクリックする。

今回はここまでにします
最後までお読みいただきありがとうございました
次回は、CloudFrontの設定を投稿予定です
また来週！:v:
Appleが出している機械学習ライブラリのメモ

# MLX

## 主要な特徴

**使い慣れたAPI**: MLXのPython APIはNumPyに非常に似ています。また、C++、C、SwiftのAPIも提供されており、Python APIと密接に対応しています。

**関数変換の組み合わせ**: 自動微分、自動ベクトル化、計算グラフの最適化のための関数変換を組み合わせて使用できます。

**遅延計算**: MLXでの計算は遅延評価方式です。配列は必要になるまで具体化されません。

**動的グラフ構築**: 計算グラフは動的に構築されます。関数の引数の形状を変更しても遅いコンパイルは発生せず、デバッグも簡単で直感的です。

**マルチデバイス対応**: 操作はサポートされているデバイス（現在はCPUとGPU）で実行できます。

**統合メモリモデル**: MLXの特徴的な点は統合メモリモデルです。MLXの配列は共有メモリに存在し、データ転送なしにサポートされているデバイスタイプで操作を実行できます。

## 設計思想

MLXは機械学習研究者によって、機械学習研究者のために設計されています。このフレームワークはユーザーフレンドリーでありながら、モデルのトレーニングとデプロイに効率的であることを目指しています。

## 例

MLXの例には以下のようなものがあります：

- Transformerを使用した言語モデルのトレーニング
- LLaMAを使用した大規模テキスト生成とLoRAによるファインチューニング
- Stable Diffusionを使用した画像生成
- OpenAIのWhisperを使用した音声認識

## インストール

MLXはPyPIで利用可能です。Python APIをインストールするには以下のコマンドを実行します：

```bash
pip install mlx
```

または、condaを使用する場合：

```bash
conda install -c conda-forge mlx
```

MLXは、NumPy、PyTorch、Jax、ArrayFireなどのフレームワークにインスパイアされた設計となっています。機械学習研究者が新しいアイデアを素早く探索できるよう、拡張や改善が容易になるように設計されています。

Source
GitHub - ml-explore/mlx: MLX: An array framework for Apple silicon https://github.com/ml-explore/mlx?tab=readme-ov-file

# CoreNet

## 概要

CoreNetは、研究者やエンジニアが標準的および新規の小規模から大規模なモデルを様々なタスクのためにトレーニングできるツールキットです。対象となるタスクには以下が含まれます：

- 基盤モデル（CLIPやLLMなど）
- 物体分類
- 物体検出
- セマンティックセグメンテーション

## 主な特徴

**幅広いモデルサポート**: CoreNetは、MobileNet、ResNet、ViTなど多様なモデルアーキテクチャをサポートしています。

**再現可能なトレーニングレシピ**: プロジェクトディレクトリには、公開された研究のための再現可能なトレーニングレシピ、事前トレーニング済みモデルの重み、チェックポイントが提供されています。

**MLX対応**: Apple Silicon上で効率的にCoreNetモデルを実行するためのMLX例が含まれています。

**豊富なデータセットサポート**: 音声分類、画像分類、物体検出、言語モデリング、マルチモーダル（画像-テキスト）、セグメンテーションなど、様々なタスク向けのデータセットをサポートしています。

## インストールと使用

CoreNetはGitHubで公開されており、Linux、macOS上でPython環境を使用してインストールできます。インストール手順には、Git LFSの使用やPyTorchなどの依存関係のセットアップが含まれます。

## 開発背景

CoreNetはCVNetsから進化したもので、コンピュータビジョンを超えてより広範なアプリケーションをカバーするように拡張されました。この拡張により、LLMを含む基盤モデルのトレーニングが可能になりました。

CoreNetは、機械学習研究を促進し、Appleのハードウェア（特にApple Silicon）上での効率的なモデルトレーニングと推論を可能にすることを目的としています。

Source
GitHub - apple/corenet - A library for training deep neural networks https://github.com/apple/corenet
任せる・・・心配・・・難しい

# はじめに

色々やりすぎて自分がPMなのかなんなのかよくわからなくなってくるのですが、仕事を任せるって難しいですよね。
未熟であるこのと現れなんだとは思いますがそんな経験を共有したく。

# 細かい進め方は考えてほしい・・・でもやはり進まない
 
特にある程度の経験を積んだ技術者には自立を促したいもの。
できれば「この機能いつまでに宜しく。」
と指示を出したらアウトプットが出てきて欲しいものですが現実は厳しく、アウトプットはなかなか出てこないものです。
どうなの？？と聞いても今これやってる！と返され、それは順調なの？作業のスケジュールはどう考えてる？など根掘り葉掘り聞くことになります。
これをするくらいなら・・・と作業スケジュールを組んであげて・・・工程毎に進捗聞き取りして・・・とする必要があるものです。
もちろんPMってそうゆうものなのは承知の上なのですが、工程を意識して作るところを想像して何日くらいかかりそうかな？これはそもそも収まらないんじゃないかな？など考えてほしいという趣旨です。

# インプットとインプット過多

指示を与える時、整理した要件などをインプットしなければなりませんが、口頭でインプットはあまりお勧めできません。
コミュニケーションの一環としては大変良いのですが、一方的に口頭でインプットしてもどうしてもインプット過多になってしまい、結果忘れる。根本の理解が及んでいない。となります。
要件定義書、議事録などの読み、不明な点を自分で疑問を持ちインプットを求めさせる。これが理想ですが、なかなかインプットを求めさせるは要求が高いことが多いです。

# プロジェクト規模が小さければなんとかしようがあるが

例えば30人に対してすべての人に十分なケアを与え続けるのは難しいでしょう。
このくらいの規模になるとチーム分けして細かいケアをリーダーに託すというのが普通でしょう。
プロジェクト規模が小さい5人程度である場合はパワープレイでのリカバリは可能ですが、年間の計画の中で一部にパワーを充てすぎると他のプロジェクトでパワー不足(充てられる人がいないとか残業できないとか)に陥ります。
このあたり難しいですよね。

# なんだかんだで個の力は重要

PMの力はチーム力に大きく影響する。
これは事実だと思いますが、個の力はやはり重要だと思います。
開発力そのものはある程度の努力でなんとかなりますが、非技術的な部分の課題解決ができるか、他の人と連携できるか、やばいことほど報告できるかなど開発力以外の能力は開発そのもの能力と同等、個人的にはそれ以上の重要性があると思います。

# 結局は人に合わせるしかないかと悟る

人それぞれ自分のキャリアプランは少なからずあるのだと思います。
* 将来的に管理職を目指す人
* 管理職を目指したいわけではないが、自分が牽引する立場になるのだと自覚を持っている人
* 役職はできればもらいたくない人
* 転職する気満々であまり現職でどうこうというつもりのない人
* 特になにも考えたくない人

後ろの方の腹づもりは判断しかねますが、前の方は仕事に臨む態度である程度は雰囲気が伝わるものです。
上昇志向がある人には多くを求め、そうでない人には作業の指示を与える。
現在の「働き方」とはこうゆうことでしょうか。
正直日本が心配になりますが、大きな流れには逆らえません。
できることをせざるを得ないというところなのでしょう。

# 終わりに

なんだか勝手に悟りを開きました。
社会人になっていろいろな人を見てきましたが、任せられる人は早々に任せられるようになりますし、そうでない人はなかなか到達できないものです。
人の特性・成長はそれぞれですので、人に合わせるしかないのでしょう。

ただ、やはり社会人の最初は重要だと思います。
大きな企業では同期と相互に助け合い、競い合える関係など構築できるものですが、中小企業においてはそもそも同期がいなく先輩に助けてもらうだけの関係で成長してしまうこともあるでしょう。
年次の近しい人がフォローできるのであればよいのですが、近い先輩がそもそも10近く離れていると世代が全く異なりますので、互いにとはいかないでしょう。
なるべく近しい関係でフォローしあえる人と作業指示を与える人は別にいたほうが新社会人にとっては良いのではないでしょうか。
【Ruby】 今日書いたコードの振り返り#2



# はじめに
こんにちは！アメリカの大学で語学を学びながら、独学でソフトウェアエンジニアを目指している者です。

現在、Rubyの `Time` や `Date` クラスについて学習しており、練習問題に取り組む中で、以下のようなミスをしてしまいました。今回は、「よくあるミス」ではなく、私が実際に犯した誤りを振り返り、同じ過ちを繰り返さないための学びを共有したいと思います。

## やりたかったこと
UNIXの `ls -t` コマンドのように、ファイルを更新日時が新しい順に表示するRubyスクリプトを作成しようとしていました。

`ls -t` は「ファイル名」と「更新日時」を基に並べ替えるため、Rubyでも同様にファイル一覧の取得、更新日時の取得、並び替え、表示というステップを踏む必要があります。

## 間違ったコード
以下が、私が書いた間違ったコードです：

```ruby
hash = Hash.new(0)

def ls_t(path)
  Dir.glob(["#{path}/**/*","#{path}/**/.*"]) do |name|
    unless File.directory?(name)
      hash[name] = File.mtime(name)
    end
  end
  
  hash.values.sort.each do |c|
    printf("%s \n", hash[c])
  end
end
```

## このコードの問題点

### 1. 変数スコープの問題
`hash` を `ls_t` メソッド外で定義しているため、`ls_t`内で呼び出すことができません。

### 2. `hash.values.sort` 後の不適切な参照
`hash.values.sort` は更新日時 (`Time` オブジェクト) のみを抽出した配列を返します。しかし、その後の処理で：

```ruby
hash.values.sort.each do |c|
  printf("%s \n", hash[c])
end
```

このコードでは、`c` は更新日時であり、`hash` のキーはファイル名なので、`hash[c]` でファイル名を取得することはできません。

### 3. 並べ替えロジック不足
`ls -t` のような機能を再現するには、ファイル名と更新日時のペアを維持しながら並べ替える必要があります。値だけ抜き出して並べ替えてしまうと、どの更新日時がどのファイル名に対応するのかがわからなくなります。

### 4. `Hash.new(0)` ではなく `{}` で初期化すべき理由
`Hash.new(0)` は「存在しないキーにアクセスしたとき、デフォルトで0を返す」ハッシュを生成します。しかし、このケースではキーは必ずファイル名として存在する前提なので、そんなデフォルト値は不要です。`{}` で初期化する通常のハッシュを使えば、存在しないキーにアクセスすると `nil` が返るため、不適切なアクセスに気づきやすくなります。また、`Hash.new(0)` だと「キーが無いのに0が返る」ことでデバッグが難しくなる場合があります。

## 問題を解決したコード
以下が修正後のコードです：

```ruby
def ls_t(path)
  hash = {}

  # ファイルの更新日時を取得して hash に格納
  Dir.glob(["#{path}/**/*", "#{path}/**/.*"]) do |name|
    unless File.directory?(name)
      hash[name] = File.mtime(name)
    end
  end

  # 更新日時で並べ替えて新しいファイルから表示
  sorted = hash.sort_by { |_, mtime| mtime }.reverse
  sorted.each do |filename, _|
    puts filename
  end
end
```

### 修正ポイント

1. `hash` をメソッド内で `{}` で初期化し、毎回クリーンな状態で処理を開始できるようにしました。

2. `sort_by { |_, mtime| mtime }` の `|_, mtime|` はブロック引数のパターンマッチで、「キー（ファイル名）は使わない（変数 `_` で受ける）」という意味です。`_` は変数名として無視を表す慣用的記法で、`mtime` だけを利用して並べ替えます。

3. 並べ替え後の `each do |filename, _|` では、逆にファイル名だけが必要で、更新日時は使わないため `filename, _` と書いて `_` で更新日時を受け取っています。これも「更新日時は使わない」という意図を明示するためです。

## (追記) Pathnameクラスを使用した場合のコード
コメントで補足いただきましたが、今回のケースのような`path`を扱う場合は`Pathname`クラスを用いることでかなり簡単にコードが書けるようです。
`Pathname`を使用する場合は`require "pathname"`を記述する必要があります

```ruby

require 'pathname'

def ls_t(path)
  dir = Pathname.new(path)

  # ファイルと更新日時を取得し、並べ替えて新しい順に表示
  dir.glob("**/{*,.*}")
     .reject(&:directory?)
     .sort_by(&:mtime)
     .reverse
     .each { |file| puts file }
end

```


## まとめ
今回の振り返りで得られたポイントは以下の通りです。

1. **スコープ管理**：`hash` や他の変数はメソッド内で初期化することで、呼び出しごとの状態管理が容易になります。

2. **関連情報を保持したまま並べ替え**：ファイル名と更新日時を保持したハッシュを `(キー, 値)` のまま `sort_by` してから `reverse` を行うことで、`ls -t` のような挙動を実現できます。

3. **不要なデフォルト値を避ける**：`Hash.new(0)` のようなデフォルト値つきハッシュは、このケースでは不要です。`{}` にしておけば、存在しないキーへのアクセスが明確に `nil` になり、問題発生時に気づきやすくなります。

4. **`|_, mtime|` や `|filename, _|` について**：これはブロック引数のパターンマッチ（分割代入）で、2要素の配列 `[キー, 値]` を `(キー, 値)` という形で受け取るとき、一方を使わないことを明示できます。`_` は使わない変数であることを示す慣習的な記号で、コードの可読性と意図の明示に役立ちます。

この学びを活かして、次回からはより意図通りに動作するコードを書けるようにしていきたいと思います！
SQLパズル　p186　44　商品のペア　解法１の学習メモ

# 概要
SQLパズル　p186　44　商品のペア　解法１の学習メモです。



# 要件
要素が２つの順列を組み合わせに変換したい。

順列：順序を考慮する
組み合わせ：順序を考慮しない

![alt text](image.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/25747250-be81-afb8-ad35-29c17b3371f8.png)


# SQL

## DDL
```sql
DROP TABLE IF EXISTS SalesSlips CASCADE;
CREATE TABLE SalesSlips
(item_a INTEGER NOT NULL,
 item_b INTEGER NOT NULL,
    PRIMARY KEY(item_a, item_b),
 pair_tally INTEGER NOT NULL);

INSERT INTO SalesSlips VALUES(12345, 12345, 12);
INSERT INTO SalesSlips VALUES(12345, 67890,  9);
INSERT INTO SalesSlips VALUES(67890, 12345,  5);

```

## 答えのSQL

```sql
-- 44　商品のペア　１
-- CASE式を使って順列→組み合わせに変換
SELECT s1, s2, SUM(pair_tally)
FROM (SELECT CASE WHEN item_a <= item_b
				  THEN item_a
				  ELSE item_b END,
			 CASE WHEN item_a <= item_b
				  THEN item_b
				  ELSE item_a END,
			 pair_tally
		FROM SalesSlips) AS Report (s1,s2,pair_tally)
GROUP BY s1,s2;

-- item_a > item_bの場合 item_aとitem_bを交換する。
--全てのレコードに対してs1 <= s2がなるので、s1,s2で部分集合を取ったときの件数が組み合わせの数になる。 
SELECT *
FROM (SELECT item_a,item_b,
			 CASE WHEN item_a <= item_b
				  THEN item_a
				  ELSE item_b END,
			 CASE WHEN item_a <= item_b
				  THEN item_b
				  ELSE item_a END,
			 pair_tally
		FROM SalesSlips) AS Report (item_a,item_b,s1,s2,pair_tally)
;

```


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/17359ac9-25ea-a801-35a2-09e0a044d236.png)


# 参考

SQLパズル　p186

SQLパズル　サポートページ
https://mickindex.sakura.ne.jp/database/db_support_sqlpuzzle.html#LocalLink-p44

達人に学ぶSQL徹底指南書第２版 p47 順列　組み合わせ　非等値結合

https://github.com/RYA234/SQL_Puzzle_Learning/commit/1329a9374cbe13a1b3b790cf258ee468011d61cb
チャットコミュニケーションの利点・不利点

# はじめに

前回「コミュニケーションが苦手なメンバーとの上手な連携方法]()という記事の中で チャットによるコミュニケーションでトラブルを引き起こす可能性があるという記載がございましたが これまであったトラブルについて共有したいと思います。
本記事、チャットを否定するものではありません。 チャットツールがなくなるのは業務影響が大きく、じゃあやらない方がいい! やはり全て書面・口頭が一番! というのは飛躍しすぎと思いますのでその点ご留意ください。

# 冷たく感じさせる

文字というのは普段私たちが行っているコミュニケーションにおいてかけている部分があり、 感情を込めることが難しいです。
「お願いいたします。」
これ一点取っても「やっておけよ」と取ってしまう方もいらっしゃいますし、文字を書いている側は頭を下げているつもりでもこれは通じません。
日常生活などでは絵文字やスタンプなどを使用することにより、これらを表現しますがビジネスにおいては使用できるケースはかなり限られるでしょう。 
少なくとも客先に対してはよほどの関係性であっても使用することはないでしょうし、相手方を不快にさせる可能性をはらんでいるという点があります。

これはチャットツールにだけ言える事ではなく、メールでも一緒ですが、短く言いたいことを表現することが多いチャットではより顕著であるというところでしょう。

# 共有してもらえない可能性

組織間の問題でもあるでしょうが、メールであればCCに相手方に知ってほしい人も入れたりできます。
個人間のチャットだとこれができない為、相手方の関係者に行き届いていないなどもよくあります。
グループチャットなどであればこれは解決できる問題であると考えますが、「広場」への投稿は 見過ごされる可能性は高いものとも思われます。

# 組織によってはあまりいい印象を与えない

新しい組織であればあまりないかもしれませんが、多くの上司というものは適切なコミュニケーションの上仕事を進めてほしいでしょう。
相談に向かう姿、時にはメンバーと談笑する姿はコミュニケーションを積極的にとっているというように見えるものです。(程度によりますが)

もとよりリモートを主体としてきた組織はこの印象点は存在しないかもしれませんが、コロナ満によりリモートを推し進めてきた組織については、評価方法の見直しが必要となり、評価する側は戸惑いを覚えるでしょう。(これも人によりますが)

いずれ経営者も上司も人間ですので、ある程度その人の尺度がありますので、場合によっては自分が期待している評価基準ではないという点は組織に属している以上は認識せざるを得ないでしょう。

# 終わりに

わたしも歳をとったもので、若い世代と異なる考え方なんだろうなと思います。
人それぞれ得手不得手があるとは思いますが、仕事を遂行するだけの目的のコミュニケーションだけではなく、 仕事を円滑に進めるためのコミュニケーションも大事にしてほしいなという次第です。
先にも書きましたが、チャット自体は私も使いますし、仕事上重要なツールです。
場合によってコミュニケーションの取り方を使い分けるという仕事術も重要なファクターだと思います。
終身雇用という考え方は薄れ、いずれ関係性はなくなると思いながら仕事をされている方も中にはいるかもしれません。
それでも今を全力で!と考えてしまうのは中年になった証拠でしょう。 この記事を通じて少しでもこのギャップが埋まるようになればなと思います。