OmniAICreator/Qiita-1.07M huggingface dataset:
Amplifyで画像(Webp)が表示されない【備忘録】

## 結論

- リダイレクトルールを次のように変更

**変更前**

```
</^[^.]+$|\.(?!(css|gif|ico|jpg|js|png|txt|svg|woff|ttf|map|json)$)([^.]+$)/>
```

**変更後**

```
</^[^.]+$|\.(?!(css|gif|ico|jpg|js|png|txt|svg|woff|ttf|map|json|webp)$)([^.]+$)/>
```

変更場所のスクリーンショット

![スクリーンショット 2024-12-21 181217.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119135/c994befe-105f-3f45-1cca-efbaabbd43fa.png)



## 背景

Astro.jsを使ってWebサイトを公開するにあたり、Amplifyのホスティングを使用することにしました。

Astro組み込みコンポーネント ```<Image>``` を使用すると、WebP形式に変換して、タグも最適化させることが可能になります。

ローカルでビルドした際は問題ありませんでしたが、ホスティングにアップロードした際、画像が表示されないエラーとなりました。

## 解決策

Googleで検索したところ、AmplifyはWebPに対応していないと出てきたのですが、2023年以降は対応しているという情報もありました。

下記サイトにドンピシャな質問が出ていたので、リダイレクトルールと気づきました。

[AWS Amplify Failing to Load .webp pictures](https://repost.aws/ja/questions/QUvLmv6JXsQOm3LFO-eezQKA/aws-amplify-failing-to-load-webp-pictures)

リダイレクトルールでは、特定の拡張子（css, gif, icoなど）を許可し、それ以外はルートディレクトリにリダイレクトする設定をしています。この中にWebP形式が含まれていなかったため、エラーが発生しました。

他の形式（例: AVIF, HEIFなど）を追加する場合も、同様にリダイレクトルールに含める必要があります。また、ルールを変更した際は、再度デプロイが必要になります。デプロイ後、正しく動作することを確認してください。

### その他

久しぶりのQiita記事ですが、かなり短くなってしまいましたが、同様の問題を抱えている方の参考になれば幸いです。
ChatGPT先生。変わりましたか。すごすぎます。(2024-12-21)


みなさまの情報をお待ちしております。
ChatGPTのバージョンの確認方法がわかりませんでした。

#### 実行例の抜粋

具体的な数値の計算をsympyのソースコードで、結果も教えて下さい。

①**実行ボタンがありました。**
②必要であればさらに詳細な解析や図示も可能です。 ​​
③途中、チャット何とか。でてたような。


**すごすぎます。エラー発生しない？ソースコードです。(2024-12-21)**
??? もしかして気分よって、対応が違うかも。

#### 以前。私の記憶
・sympyの実行結果を教えてもらえなかった。自分でやって。
・ここまで気のきいた回答が記憶にありません。

#### 実行例

https://qiita.com/mrrclb48z/items/5628539287e6cc7ebe68#chatgpt%E5%85%88%E7%94%9F%E3%81%B8%E5%86%8D


# ＞みなさまの情報
これかも。ありがとうございました。
DAY 4：「Canvas」機能が無料ユーザーでも使えるように！

https://qiita.com/daigo1130/items/37706c2a631c477c484c#day-4canvas%E6%A9%9F%E8%83%BD%E3%81%8C%E7%84%A1%E6%96%99%E3%83%A6%E3%83%BC%E3%82%B6%E3%83%BC%E3%81%A7%E3%82%82%E4%BD%BF%E3%81%88%E3%82%8B%E3%82%88%E3%81%86%E3%81%AB

＞Zenn内

https://zenn.dev/link/comments/958dd1e2f8e4cc
[ODC]Client Actionから複数のサーバー処理を呼ぶと出る警告の対策

Reactive Web App・Mobile AppのClient Actionからサーバーサイドの処理を呼ぶ場合、1つ1つの呼び出しが通信経由で（実行形態としてはWeb APIとして）実行される。

通信のオーバーヘッドを避けるため、1つのClient Actionから呼び出すサーバー処理は1つに絞るのがベストプラクティス。

これに反すると、ODC Studio上で警告も出るし、AI Mentor Systemの指摘事項にもあがってくる。

よって、レビューやテスト時点では解消されているはずだが、結構残っており、修正が大変なので直せない、と言われることがある。が、新しいServer Actionを作り、複数のサーバー処理の呼び出しを全部そこに移動するだけなので、基本的には対処は簡単。

# 環境情報
ODC Studio(Version 1.5.0)

# 問題が発生するサンプル実装
Buttonをクリックしたときに起動するClient Actionを以下の様に実装してみると、問題の発生を確認できる。中間のAssignは1つ目の呼び出し結果を一時保存するのにおいているだけなので、省いても問題は再現する。
![スクリーンショット 2024-12-19 22.04.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/0e8323bc-3bf7-d803-0191-4b9f2bce6674.png)


# ODC Studioの警告
ODC Studio左下に、「Performance Warning」として以下の内容が表示される。

> The 'serverAction____OnClick' Client Action calls several Server Actions. To avoid performance issues, group them all in a single Server Action and call it instead.

# AI Mentor Systemのパターン
AI Mentor Systemは、OutSystemsが事前に定めたルールに基づいて静的解析をしてくれる機能。
基本機能については以下を参照。

https://qiita.com/jyunji_watanabe/items/56906821c9bb321306c4

パターンというのは、AIMSが指摘してくる指摘事項の種類のこと。以前、（当時の）パターン一覧について順番に見て行った時の記録は以下の記事にまとめた。

https://qiita.com/jyunji_watanabe/items/340913e160e7e1f933c1

このパターンの中に、「[Multiple server requests (Aggregates or Actions) inside Client Actions - ODC Documentation](https://success.outsystems.com/documentation/outsystems_developer_cloud/monitoring_and_troubleshooting_apps/manage_technical_debt_in_odc/performance_findings/multiple_server_requests_aggregates_or_actions_inside_client_actions/)」というものがあり、この問題に対して指摘を挙げてくれる。

## AI Mentor SystemのUI上で指摘を確認する

![スクリーンショット 2024-12-19 21.52.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/bc740d72-2891-a36c-0e1a-0d609013534e.png)

![スクリーンショット 2024-12-19 22.03.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/ab821526-6cce-b9a9-4f64-6866c87de5c8.png)

# 対策
1. Server Actionを1つ作成する
1. Client Actionから呼び出しているServer Actionを↑で作ったServer Actionに移動する
1. 移動したAction呼び出しに必要な値をInput Parameterに、呼び出し結果から取得が必要な値をOutput Parameterに作成する
1. Client Actionから新設したServer Actionを呼び出し、Input/Output Parameterを設定する

実装例
新設するServer Action
I/F定義（呼び出したServer ActionのOutput Parameterを画面で使っていたため、ActionにもOutput Parameterを追加した）
![スクリーンショット 2024-12-21 18.11.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/05c27eef-68d4-3915-2650-d6aaad0cfa59.png)

フロー
![スクリーンショット 2024-12-21 18.12.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/8962d4c0-f7a8-4ea1-88d7-2cc6f6bcdc47.png)

Client Actionのフロー変更
![スクリーンショット 2024-12-21 18.13.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/a1809055-fa50-8911-6395-7e7ef2e11002.png)
【自習】AWS S3 ②

PMする上で必要になってきたのでおさらい

https://docs.aws.amazon.com/s3/?icmpid=docs_homepage_featuredsvcs

https://firebase.google.com/docs/storage?hl=ja

## AWS S3 と Firebase Storage の比較

### **基本的な概要**

| 特徴                | **AWS S3**                                     | **Firebase Storage**                                 |
|---------------------|-----------------------------------------------|---------------------------------------------------|
| **主な用途**         | 静的ファイル保存、バックアップ、大量データ管理   | モバイル/ウェブアプリ向けのファイル保存・共有      |
| **スケーラビリティ**  | 高い（無制限スケール）                          | アプリケーション開発向けに最適化                  |
| **APIの柔軟性**      | REST API、SDK、CLI、IAMで高度な制御が可能        | Firebase SDKを使って簡単にアプリと統合可能        |
| **セキュリティ管理** | IAMポリシーやバケットポリシーで細かく制御可能    | Firebase Authenticationと連携し簡単に制御可能    |

---

### **AWS S3 の特徴**
#### **メリット**
1. **大規模なスケール**  
   - 無制限のデータ保存と、ペタバイトクラスのデータ管理が可能。
2. **ストレージクラスの選択肢**  
   - アクセス頻度や保存期間に応じて、Standard、Intelligent-Tiering、Glacierなどのクラスを選べる。
3. **柔軟なセキュリティ設定**  
   - IAMポリシーやバケットポリシーで詳細にアクセス管理が可能。
4. **汎用性が高い**  
   - バックアップ、ログ保存、静的Webサイトホスティング、大量データの分析基盤など多用途。

#### **デメリット**
1. **設定が複雑**  
   - 初心者にとってIAMやバケットポリシーの設定が難しい。
2. **アプリ連携の開発が手間**  
   - アプリに直接統合するには追加のコードや構成が必要。

---

### **Firebase Storage の特徴**
#### **メリット**
1. **モバイル/ウェブアプリに最適**  
   - Firebase SDKを利用して、簡単にアプリ内でファイルのアップロードや取得を実装可能。
2. **Firebase Authenticationとの連携**  
   - ユーザーごとのアクセス権限を簡単に設定可能。
3. **簡単に始められる**  
   - 初心者でも直感的に使いやすく、設定がシンプル。
4. **無料枠の提供**  
   - 初期段階では無料枠（1GBストレージ、50,000リクエスト/月）を活用できる。

#### **デメリット**
1. **スケールに制限**  
   - S3ほど大規模なデータ保存には向かない。
2. **用途が限定的**  
   - 主にアプリケーションのファイル保存や共有に特化。

---

### **具体的な比較ポイント**

#### **1. ユースケースの違い**
- **AWS S3**:
  - 大量のデータ保存（例: バックアップ、ログデータ）。
  - 静的Webサイトホスティング。
  - データ解析基盤やデータレイクとしての利用。
- **Firebase Storage**:
  - モバイルアプリの画像アップロード機能。
  - ユーザーごとにアクセス制御が必要なアプリ。
  - アプリケーション内でファイルを保存・共有する場合。

#### **2. セキュリティとアクセス管理**
- **AWS S3**:
  - IAMポリシー、バケットポリシーで細かく設定可能。
  - CloudFrontとの連携で追加のセキュリティレイヤーを実現。
- **Firebase Storage**:
  - Firebase Authenticationでユーザー単位のアクセス制御が簡単。
  - セキュリティルールが直感的で使いやすい。

#### **3. 料金体系**
- **AWS S3**（従量課金制）:
  - **ストレージ料金**: $0.023/GB（S3 Standard）。
  - **リクエスト料金**: GETリクエスト10,000回あたり $0.0004。
  - **データ転送料金**: 1GBまで無料、以降は $0.09/GB。
- **Firebase Storage**（従量課金制）:
  - **無料枠**: 1GBのストレージ、50,000リクエスト/月。
  - **ストレージ料金**: Google Cloud Storageと同じ料金体系（$0.026/GB）。
  - **データ転送料金**: Firebaseの無料枠を超えた場合、Google Cloud料金に基づく。

#### **4. APIと開発環境**
- **AWS S3**:
  - REST APIやSDKを通じて柔軟に制御可能。
  - データ分析や大規模システムと連携するのに最適。
- **Firebase Storage**:
  - Firebase SDKを使うとアプリ内で簡単に統合可能。
  - 他のFirebaseサービス（Realtime Database, Firestore）とシームレスに連携。

---

### **どちらを選ぶべきか？**
#### **AWS S3が向いているケース**
- **大量データを管理**:
  - 例: バックアップ、アーカイブ、データ分析。
- **静的Webサイトをホスティング**:
  - HTML/CSS/JavaScriptファイルの配信。
- **エンタープライズ用途**:
  - 高度なセキュリティや大規模システムに対応。

#### **Firebase Storageが向いているケース**
- **モバイル/ウェブアプリの開発**:
  - 画像や動画のアップロード機能が必要。
- **小規模なプロジェクト**:
  - 無料枠を活用して、コストを抑えたい場合。
- **Firebase環境を利用**:
  - 他のFirebaseサービスと統合して効率的に開発したい場合。

---

## 感想
従量課金のサービスを個人開発で使う場合にセキュリティーをおろそかにして使ってしまうとすごい料金請求されそうで怖いというハードルをどうにかしたい。
SAMLを用いたシングルログアウト(SLO)の流れ

# はじめに
シングルサインオン(SSO)に関する説明は割りと世の中に多いですが、SAMLを用いたシングルログアウト(SLO)の流れや挙動を確認したいときに参考にできそうなものは比較的少ないという印象があります。SAMLを用いたSLOの理解に時間がかかってしまったので備忘の意味も込めて自分なりに整理したいと思います(特にセッションを終了するタイミングに関して)。

:::note warn
一般的な流れをまとめたつもりですが、IdPやSPの実装の違いにより若干の仕様の差が生じることもあるのでご留意ください
:::

# SLOの流れ
SLOの流れについて、種類ごとに分けて説明します。
ここではユーザーがSSOを用いて複数のSPにログインしている状態からSLOを開始する場面を想定します。
またブラウザ上でリダイレクトなどの処理を繰り返すことでSLOを行う、「フロントチャネル方式」を想定します。

### IdP-Initiated
ユーザーがIdP側で「ログアウト」ボタンを押して開始するようなSLOです。
処理の流れは下図のようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3841947/c23a87d0-16e2-f088-708e-cc73fc8a6cb6.png)

IdPがSPにログアウト処理を要求 → SPでセッション終了 (→ 繰り返し ) → IdP側でセッションを終了
という流れになります。
ここでログアウトの要求のために「**LogoutRequest**」というSAMLが用いられ、SPがログアウトしたことをIdPに通知するために「**LogoutResponse**」というSAMLが用いられます。

IdPは全てのSPに対してLogoutRequestを発行し、それらからLogoutResponseを受け取った時点でセッションを終了させます。

### SP-Initiated (全てのSPのセッションを終了)
ユーザーがSP側で「ログアウト」ボタンを押して開始するようなSLOです。
処理の流れは下図のようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3841947/89a8bce2-732c-b942-0948-c5f97fcbe759.png)

SP側でセッションを終了 → IdPにログアウト処理を要求 → 他SPでもセッション終了 → IdP側でセッションを終了
という流れになります。
ここで、SLOを開始するSPでは、**IdPにログアウトを要求する時点で**セッションが終了することに注意が必要です。
またIdP-Initiatedの場合と異なり、LogoutRequestは**SLOを開始するSPとIdP**から、LogoutResponseは**IdPとその他のSPから**送信されることになります。

### SP-Initiated (SLO開始元のSPのセッションのみを終了)
先ほどと同様、ユーザーがSP側で「ログアウト」ボタンを押して開始するようなSLOですが、セッションを終了するSPはSLO開始元のSPに限られます。
IdPの種類によりセッションの終了の方式は異なるようで、OktaなどのIdPではこのように他のSPに影響を与えないようなSLOの処理が進行します。
処理の流れは下図のようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3841947/294d1adb-904b-c307-33d1-40521a6db68c.png)

SP側でセッションを終了 → IdPにログアウト処理を要求 → IdP側でセッションを終了
という流れになります。

# 終わりに
SSOやSLOについては一度きちんと処理の流れを確認することで、コードの理解がスムーズにできるようになりました。実装から機能を確認するケースもあると思いますが、粗い理解から始めて徐々にコードの理解に進んでいくということについても意識していきたいです。
文章の順番を入れ替えたラブレター（後編の1）｜文章題で身に付くプログラミング思考入門️（16/25）

## はじめに

今回は、文章の順番を入れ替えたラブレターシリーズの最終回です。

- [前編](https://qiita.com/yuki_thewaggle/items/221bf14462fc5c4170ac)
- [中編](https://qiita.com/yuki_thewaggle/items/611149af390eaea6ee06)

『文章題で身に付くプログラミング思考入門️』は、日常や文章問題からプログラミング思考を身に付けていく、簡単で身近で、あなたをちょっと輝かせてくれるシリーズです。

今回は、前回のラブレターから無駄を省いたり、合わせたりして、シンプルにしてみましょう。

## これまでのまとめ

https://qiita.com/advent-calendar/2024/thewaggle

## 対象者
- プログラミングの考え方を学びたい人
- プログラミングに挫折したことのある人
- 論理的思考を鍛えたい人
- 文系の人
- エンジニアの思考を理解したい人

## 概要
前回のラブレターは、ゴールに照らし合わせても、起承転結で分解してみても、良い文章だなという結論になりましたね。

今回は、**とは言え、文章が長いので、もっと簡潔にできませんか？** という観点でブラッシュアップしていきましょう。

### なぜ簡潔さが大事か？

**結局、シンプルなものが一番強いです。**
適応範囲が広く、周りに影響されにくい構造になるからです。

手順の最適化の過程でも、シンプルにすることはどこかで必要になります。

例えば、鉄棒で逆上がりをした経験はありますか？
逆上がりが上手な人は、とても簡単そうに回りますよね。
これは、その人の中で体の動かし方が最適化されて無駄が省かれ、シンプルになったから簡単そうに見えるんですね。
一流職人の職人技なども、とてもスマートで美しい所作で、簡単そうで真似できそうなのに、実際やってみるととても真似できない。

シンプルとは、強みです。
シンプルにできれば自動化にも繋げられます。
あなたの日常や仕事を、とても助けてくれる考え方です。

### シンプルにするために重要な、3つの方法と2つの観点

ではどうやったらシンプルにできるかというと、3つの方法があります。
- 無駄をなくす
- 順番を整理する、入れ替える
- まとめる（合わせる）

プログラミングでも、業務改善でも、毎日のルーティンでも一緒です。

そして、大事なのは、以下の2つの観点です。
- どうやったら労力をかけずに継続できるか？
- どのようにしたら問題を発生させない仕組みになるか？

理論が長すぎても何なので、ラブレターを例にやっていきましょう。

### ラブレターをシンプルにしてみる

では文章を見ていきましょう。

```
ふと振り返ると、私たちは本当にたくさんの時間を共に過ごしてきましたね。
楽しいことも、つらいことも、すべてを一緒に乗り越えてきたことが、私たちの絆を深めてくれたと思います。
甘い思い出もたくさんあります。
初めて手をつないだあの日、笑い合った何気ない瞬間、そして特別な記念日たち。
けれど、それ以上に、苦しい時にあなたがそばにいてくれたことが、私にとって何よりも大きな支えでした。

辛いことがあったときも、迷いがあったときも、あなたはいつも優しく励ましてくれましたね。
「大丈夫、一緒に乗り越えよう」という言葉に、どれほど救われたことでしょう。
あなたとだからこそ、どんな逆風も耐えてこれたんだと思います。

これから先も、甘い瞬間だけではなく、時には試練が訪れるかもしれません。
でも、今の私には確信があります。
私たちなら、どんな困難も乗り越えられる。
なぜなら、あなたといることで、私はどんなときも力強く前を向けるから。

これまで本当にありがとう。
そして、これからもよろしくね。
あなたと一緒に歩む未来が、私の何よりの幸せです。
心からの愛と感謝を込めて。
（466文字）
```

割とボリュームありますね。
うん、何だかとても良さそうなんですが、すごく大切にしている相手からの手紙じゃないと心を込めて読めません。
日々時間に追われている忙しい私たちには、もっとシンプルで力強い文章が必要です。


#### 無駄をなくす

ではまず、無駄なものを減らしていきましょう。
すると、そもそも何が無駄なのか？を考える必要がありますね。

**これは定義やルール、コンテクストによります。**
要は、このラブレターを送る人と受け取る人の関係値の中で、何を大事にしているのか、どんな決まりがあるのか、どんなことを経験してきたのか、が大事ということですね。

正直、そこはわからないです。仮想のラブレターなので仕方ありません。

ということで、別軸から無駄を減らしていきます。
**無くても伝わるものをなくしましょう。**
目標は20%削減です。

```
振り返ると、たくさんの時間を共に過ごしてきましたね。
楽しいことも、つらいことも、すべてを一緒に乗り越えてきたことが、私たちの絆を深めてくれたと思います。
初めて手をつないだあの日、笑い合った何気ない瞬間、そして特別な記念日たち。
けれど、それ以上に、苦しい時にあなたがそばにいてくれたことが、私にとって何よりも大きな支えでした。

あなたはいつも優しく励ましてくれましたね。
「大丈夫、一緒に乗り越えよう」という言葉に、どれほど救われたことでしょう。
あなたとだからこそ、どんな逆風も耐えてこれたんだと思います。

これから先も、どんな困難も乗り越えられる。
なぜなら、あなたといることで、私はどんなときも力強く前を向けるから。

これまで本当にありがとう。
そして、これからもよろしくね。
あなたと一緒に歩む未来が、私の何よりの幸せです。
心からの愛と感謝を込めて。
（370文字）
```

ちょうど20%強の削減ができましたね。
上々です。

でも記事が長くなってしまったので、続きは次回に任せましょう。

次回は、順番を整理したり入れ替えてみます。

## まとめ

順番の入れ替えに必要なこと
1. まず初めに、ゴールは何なのかを明確にする（前々回）
1. 俯瞰的に見直す（前々回）
    1. いかに柔軟な目線で縦横無尽に検証できるか（前回）
1. シンプルにする
    1. 無駄をなくす


## 最後に
ここまで読んでくださってありがとうございます！
少しでも役に立ったら「いいね」をください。続ける励みになります！
色んなエディタ使ってるチームで、Spotlessでフォーマットを統一してみた

## はじめに  

私が所属しているチームはJavaで開発を行ってるのですが、メンバーそれぞれ別のエディタを使っています。基本的にあまり困ることはないのですが、ある一つの課題に直面しました。
コードフォーマットです。

開発で余計なことを考えずに済むように、フォーマットルールは統一したい。でも各人のエディタのフォーマット設定を手作業で一致させるのは面倒くさすぎる...

コードフォーマットを統一する方法を模索した結果、Spotlessというライブラリを見つけました。
Spotlessは、コードフォーマットやスタイルの一貫性を保つためのライブラリで、これを利用することで、各人が異なるエディタを使う環境でもフォーマットルールを統一することができました。

本記事では、Spotlessを使ったフォーマット統一の具体的な方法と、その効果について解説します。同じような課題を抱える開発チームの一助になれば幸いです。  


## Spotlessとは  

Spotlessは、MavenやGradleのプラグインとして利用できる、コードフォーマットやスタイルの一貫性を保つためのオープンソースツールです。
Java以外の言語にも使用できますが、今回はJavaのフォーマットルールを設定するために利用しました。

https://github.com/diffplug/spotless


## SpotlessでのJavaフォーマット設定  

Spotlessを使うには、`build.gradle`に設定を追加します。
今回はGoogle Java Formatをベースに、インポート順の整理・不要なインポートの削除などいくつかのルールを設定しました。

[build.gradle]
```groovy
plugins {
    id 'com.diffplug.spotless' version '6.21.0'
}
apply plugin: "com.diffplug.spotless"

spotless {
    java {
        googleJavaFormat() // Google Java Format を使用
        importOrder() // インポート順の整理
        removeUnusedImports() // 未使用インポートの削除
        trimTrailingWhitespace() // 行末の空白削除
        endWithNewline() // ファイル末尾に改行を追加
    }
}
```


[フォーマットチェック]
```bash
./gradlew spotlessCheck
```

[フォーマット適用]
  ```bash
  ./gradlew spotlessApply
  ```


## Spotless実行適用設定
これで一応Spotlessのフォーマット適用が行えるようになりましたが、いちいちコマンドを打つのは面倒です。
私たちのチームは開発中必ずユニットテストを触るので、今回はJUnitテスト実行時にSpotless applyが実行されるようにしました。 

[build.gradle]
```groovy
tasks.named('test') {
    dependsOn 'spotlessApply'
}
```



## 課題：VSCodeはテスト実行にgradleを使用しない

ここで、一つ課題が出てきました。
VSCodeはテスト実行時にgradleを使わないらしく、前項で設定したテスト実行時のspotless実行が動きませんでした。
そのため今回は、VSCodeの「Run On Save」拡張機能を使用して、ファイル保存時に `spotlessApply`が実行されるようにしました。

1．`Run On Save`拡張機能をインストール
2．`tasks.json`設定追加

Spotlessのフォーマット適用タスクがVSCodeから実行できるようにします。

[tasks.json]
```json
{
    "version": "2.0.0",
    "tasks": [
        {
            "label": "spotlessApply",
            "type": "shell",
            "command": "./gradlew spotlessApply",
            "group": {
                "kind": "build",
                "isDefault": true
            },
            "problemMatcher": []
        }
    ]
}
```

3．`settings.json`設定追加  
ファイル保存時にtasks.jsonに追加したタスクを実行するようにします。

[settings.json]
```json
{
    "editor.formatOnSave": false, // VSCodeのデフォルトのフォーマッタ機能を無効化
    "runOnSave.commands": [
        {
            "match": ".*\\.java$",
            "command": "workbench.action.tasks.runTask",
            "args": "spotlessApply"
        }
    ]
}
```
これで、ファイル保存時にspotlessApplyが実行されるようになりました。

## まとめ  

Spotlessを導入する前は、エディタごとにフォーマットルールが異なるために、差分が大量に発生することを恐れてフォーマットを手動で行ったり、フォーマットが統一されていない状態でコードをコミットすることがあり、ストレスでした。
しかし、Spotlessを導入したことでフォーマットルールが強制的に適用され、フォーマットに意識を割く必要がほとんどなくなりました。
 

Spotlessには他にも機能や使い道があるので、今後はこんなこともやっていきたいなあと思っています。
- CIでのフォーマットチェック
テスト実行時（VSCodeはファイル保存時）にフォーマットが適用されるのでルール違反が起こることはほとんどないはずですが、CI実行時にチェックが入るとより安心
- Java以外の言語でのフォーマット統一
Javascriptやsqlなど他の言語でもフォーマットを統一したい。（これらの言語パッケージはnpmを使用した環境設定が必要なのが少しネック...）
TerraformでNLB構築・応用編 Terraformでfor文を使おう!(for_each)

# はじめに

本記事はTerraformを使ったNLB構築第二弾となります。
前回作成した、NLB用のセキュリティグループに大量のインバウンドルールの
構築・管理をTerraformで簡単に行う手法を紹介いたします。

# 想定状況
前回構築したNLBにオンプレのサーバーからのアクセスだけを許可したい場面を想定します。
オンプレのサーバーは静的なIPアドレスを持っています。
許可したいIPアドレスからのインバウンドルールをセキュリティグループに追加する必要があります。
指定したいサーバーの数(IPアドレスの数)が100台とか200台だった場合、
これをマネジメントコンソールから実装するのはとても大変でしょう。
Terrformで書くにしても100個、200個の`resource`ブロックを記述するのは大変です。
そこでTerraformには`for_each`という便利な構文があります。

# `for_each`文
`for_each`は`resouce`や`module`ブロックを繰り返し文として使えるようにできます。
たとえば下記のようなリソースは、
```
resource "aws_s3_bucket" "bucket1" {
  bucket = "bucket1"
}

resource "aws_s3_bucket" "bucket2" {
  bucket = "bucket2"
}

resource "aws_s3_bucket" "bucket3" {
  bucket = "bucket3"
}
```
下記のように1つにまとめて記述できます。
```
resource "aws_s3_bucket" "buckets" {
  for_each = toset(["bucket1", "bucket2", "bucket3"])
  bucket   = each.key
}
```
# `for_each`を使ってインバウンドルールを構築

第一弾の基礎編のソースコードに追記・編集していく形で紹介します。
まだ、読んでない方は是非[こちら](https://qiita.com/thiroi04db/items/598eff28eb84dd1be16f)からご一読お願いいたします。

今回は話を簡単にするため5個のIPアドレスからの443ポートのインバウンドルールを追加します。
また、特に疎通確認などもするつもりもないので、IPアドレスはVPC内のプライベートIPで代用します。(実践では許可したいグローバルIPアドレスを指定してください。)
最終的なtfファイルが以下になります。

・security_group.tf
```
#許可したいIPアドレスリスト(今回はVPC内のプライベートIPを書いてます。)
locals {
  ip_list = [
    "172.31.0.11",
    "172.31.0.12",
    "172.31.0.13",
    "172.31.0.14",
    "172.31.0.15"
  ]
}

#セキュリティグループ本体
resource "aws_security_group" "sg_nlb" {
  vpc_id = <VPCのID>"
  name   = "nlb-alpha-sg"
}

#インバウンドルール1
resource "aws_vpc_security_group_ingress_rule" "allow_http" {
  from_port         = 80
  to_port           = 80
  ip_protocol       = "tcp"
  cidr_ipv4         = "172.31.0.11/32"　#適当に許可したいIPアドレス
  security_group_id = aws_security_group.sg_nlb.id
}

#インバウンドルール2(for_eachで記述)
resource "aws_vpc_security_group_ingress_rule" "allow_https" {
　for_each = toset(local.ip_list)
  from_port         = 443
  to_port           = 443
  ip_protocol       = "tcp"
  cidr_ipv4         = "${each.value}/32"　#静的IPアドレスのリストを代入
  security_group_id = aws_security_group.sg_nlb.id
}

#アウトバウンドルール1
resource "aws_vpc_security_group_egress_rule" "allow_all" {
  ip_protocol       = "-1"
  cidr_ipv4         = "0.0.0.0/0"
  security_group_id = aws_security_group.sg_nlb.id
}
```
# NLB
NLB.tfのコードは前回と同じなので割愛。

# 構築されたリソース
リストで指定したIPアドレスからのインバウンドルールが構築できています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3966995/d7d6dad9-24cb-aa6e-7238-6a957183a7a3.png)



# おわりに
今回は`for_each`を使ってリスト化したIPアドレスからのインバウンドルールを構築する手法を紹介いたしました。
大量のIPアドレスからの許可ルールを作成しなければいけない際などに役立つかと思います。
今後もawsやTerraformに関する記事を投稿していく予定です。
また機会があれば認定資格の学習法などのtipsも公開できればと思います。
それではまた。
Reactコンポーネントで作られた配信レイアウトをforkして再利用する

この記事は TSKaigi Advent Calendar 2024 の記事です。

https://qiita.com/advent-calendar/2024/tskaigi

## こんにちは

こんにちは、先日京都で行われたTSKaigi Kansai 2024にて配信チームをしていたmagchoです。

https://kansai.tskaigi.org/

当日の会場の映像周りとリアルタイムの配信を行なっていました。

## 配信の様子

当日の配信のレイアウトとしては配信スライドと登壇者のカメラ映像に加えて、トーク中のセッション名や登壇者情報・スポンサー様のロゴなどを掲載していました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99375/65ae9397-de5d-db66-b842-32db281afe02.png)

TSKaigi 2024に参加いただいた方にはピンとくるかもしれませんが、このレイアウトは2024年5月に東京 中野で開催したものをforkして利用しています。その時の技術面の解説記事を当時[ken7253](https://x.com/ken7253_)さんがブログにまとめていただいているので興味のある方はそちらもご覧ください。

https://zenn.dev/ken7253/articles/tskaigi-streaming-layout

TSKaigi 2024のレイアウトがReactコンポーネントとして実装されており 1920 x 1080pxのDIV要素が描画できるようになっています。

今回はそのレイアウトをforkし、Kansai2024版にいくつか作り替えた上で利用しています。

前回のTSKaigi2024ではこのレイアウトをNodeCGというブラウザベースの描画を伴うOSSを利用してレイアウトの描画を行っていました。これには描画用のPCを必要とする構成になります。Kansaiでは事前の準備時間が短いなど前提が異なっているため別のアプローチを実施しました。

## 利用機材の内容

TSkaigi 2024では準備時間が十分あり、当日は字幕・翻訳などリアルタイム性の高い要件があったためリアルタイムにReactコンポーネントを描画するためのPCを専用に用意していました。Kansai2024では準備時間と配信要件から専用のPCを設置しない方向で調整をしています。

メインスイッチャーにはRoland社の VR-6HDを利用しそれぞれinput/outputを設定しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99375/69e7b2eb-e381-0e0e-aea3-51eb3132f516.png)

レイアウト描画用PCを幕間CM再生PCと兼任させることでPCの台数を減らしています。

## 配信レイアウトの構造

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99375/41d133b9-783d-a209-ed4f-42a2fd055129.png)

レイアウトは３つのパーツに分かれていて枠・スライド・カメラ映像を現地のVR-6HDで合成します。以前はこの合成を行うためにPinPを利用していましたが、Kansaiでは素材については事前に動画としてレンダリングをしてRoland社からリリースされているGraphics Presenterを利用し当日はDSKレイヤーとして利用する方針をとりました。

https://proav.roland.com/jp/products/graphics_presenter/

## Reactコンポーネントから配信枠動画を生成する

Reactコンポーネントを利用して動画ファイルを生成するフレームワークとして[remotion](https://www.remotion.dev/)を採用しました。

remotionにはStorybookのようなカタログ機能と、レンダリングの操作をGUIから行えるstudio機能がついています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99375/3ef37d5d-f076-74e8-fc66-4dd4cef4dd9a.png)

Root.tsxにてフレームワークが提供する`<Composition>`コンポーネントでwrapする形にReactコンポーネントを記述するとStudioの中央に描画されます。

フレームワークの特性でCSSアニメーションやsetTimeoutを用いるような操作は想定とは異なった挙動をします。そのため、時間経過を元にするアニメーションを作成するにはremotionが持つカスタムフックである`useCurrentFrame`から今再生中のフレーム数が取得できるのでその数値からアニメーションの計算・描画を行います。これはcanvas要素でアニメーションを作る際はrequestAnimatonFrameを元にフレーム数を計算しアニメーションを行うアプローチが取られることがありますがそれに近い概念です。

DSKレイヤーであれば配信のスライドとカメラ映像の部分を穴あきにしておきたいのですが、remotionでは出力の動画を透過させることができません。幸い今回の要件では透過はopacity0% or 100%のどちらかでありグラデーションが存在しないためremotonで透過部分をgreenで出力し、後処理としてgreen部分を透過させます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99375/92b019de-d769-5855-ac7f-13d03c874e36.png)

Graphics Presenterはwebm形式であれば透過を含む動画を読み込む事ができます。

## まとめ

以上の構成で当日のオペレートはGraphics Presenterとビデオスイッチャーの操作のみに集約でき、準備時間の圧縮をする事ができました。

簡単な配置をするだけのレイアウトではあるもののセッション名やスポンサー様のロゴなどパターン数が多いようなテックカンファレンスにおいて宣言的に配信のレイアウトを生成できるようにしておくのは便利です。今回はReactコンポーネントをベースとしたことで異なったアプローチでも流用ができるためおすすめです。
「自分の成長」から「共に成長」「創発」へと変化　2024年の取り組みを共有したい

## はじめに

2024年、私の価値観や行動が大きく変わりました。「**創発**」というあまり馴染みのない言葉が自分の中にしっかりと根付いた一年でした。

この記事では、この1年で私に起きた変化をお伝えします。

## 先に結論

- アウトプットやコミュニティ活動を始めた
- 「自分の成長」を中心に考えていたが、「**共に成長**」を重視するようになった
- 「共に成長」を意識して行動した結果、**創発**的な行動が増え、成果が良くなった

## 2024年前半の取り組み

### アウトプットを始める

2024年3月、アウトプットを始めました。Qiitaで習慣的に投稿するようになりました。

次の記事は多くの反応をいただきました。

https://qiita.com/mkt_hanada/items/923bbf9a9e51d6aa16b3

2024年4月には月間Contributor賞もいただきました。

![スクリーンショット 2024-12-21 17.04.24.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/616496/2aa193b7-d865-bca9-73ae-ad53a887e909.jpeg)

その後も、投稿マラソン(38記事を毎日投稿)を完走しました。

![スクリーンショット 2024-12-21 17.05.26.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/616496/568fb09b-302a-2596-95fb-b63f68a72a57.jpeg)

アウトプットを通じて、自分の基礎知識を磨くことができ、さらに周囲の役に立っている実感を得られました。

例えば、次の記事を投稿した後、「記事を読んだよ」と社内で多くの方から声を掛けて頂きました。

https://qiita.com/mkt_hanada/items/44c20c4db78db9d6c024

### コミュニティ

同時期に社外のコミュニティにも参加するようになりました。

アウトプットした記事の反応をいただいたり、共に勉強したりと刺激がありました。

2024年4月にIPAの「情報処理安全確保支援士」を取得しましたが、「共に勉強しながら資格を取得した」という感覚でした。

https://qiita.com/mkt_hanada/items/f9b1fae7d74c40d1df1e

https://qiita.com/mkt_hanada/items/f30a856f5db35b000b23

## 自己理解の深耕

社外のコミュニティに参加し、フィードバックを受けたり、他者と比較する中で、自分の強みや価値観をより深く理解できるようになりました。

2024年11月に「人生でやりたいこと100個」を挙げてみました。その結果、自分のやりたいことや興味が浮き彫りになりました。

## 価値観の変化「共に成長」「創発」

2024年の活動や「人生でやりたいこと100個」から、「自分の成長」よりも「**共に成長**」を重視していることに気づきました。

アウトプットやコミュニティでの活動を通じて、これまでになかった自分の価値観が引き出されました。

そして、それは「**創発**」という言葉がピッタリ当てはまりました。

[「VISION DRIVEN INNOVATION ひとりの妄想で未来は変わる」](https://amzn.asia/d/eAq8zBA)より引用します。

> 創発とは、複雑系の理論で使われる用語で、”1+1 > 2”のように、多様な要素が集まることでそれ以上の結果を生むことを指す

創発によって、相手とともに成長し、社会にさらなる価値を届けられることに強い関心を抱いています。

これからの私の人生のキーワードは「**創発**」です。

## 価値観の変化の結果

価値観の変化に気づいたことで、創発的な行動が増えました。

社内でも発信するようになったり、個人間の連携やチーム連携を強化したりしました。

その結果、良い成果が出るようになっただけでなく、嬉しい言葉をかけてもらえることが多くなりました。

より上位職の方からは「周りをエンパワーメントする力がある」「あなたの周りの人は生き生きと働いている」など、私と一緒に働いてくれる協力会社の方からは「スキルを引き上げてくれる」など、これまでなかった言葉でした。

自分の強みに気づくことができました。

## おわりに

この記事では、私の1年間の変化を紹介しました。

この内容が、キャリアや成長戦略を考える際の参考になれば幸いです。

それでは。
Db2へのJDBC接続の簡単なテスト方法

# 概要
Db2に対してJDBC接続を行う際、ネットワークが疎通できているか、接続パラメータが正しいかをテストしたいことがあります。Db2のJDBCドライバ（db2jcc.jar/db2jcc4.jar）には接続テスト用のプログラムが同梱されており、JDBCドライバとJavaの実行環境があれば、JDBC接続を1コマンドで簡単にテストすることができます。

# 手順
以下のコマンドでDb2へのJDBC接続をテストできます。

```shell
# コマンド
java -cp <JDBCドライバ(db2jcc.jar/db2jcc4.jar)のパス> com.ibm.db2.jcc.DB2Jcc -url <JDBC URL> -user <DBユーザ> -password <DBパスワード>

# コマンド実行例
java -cp /jdbc/driver/db2jcc4.jar com.ibm.db2.jcc.DB2Jcc -url jdbc:db2://mydb.example.com:50000/MYDB -user db2user -password db2password
```
PHPでMavenリポジトリを無理やりつくってる話

# はじめに
Mavenリポジトリを作成するならば、本来はNexus RepositoryやJFrog artifactoryを使うらしいのですが、当時はMavenリポジトリの作り方を調べようとしました。ただ、それっぽいのが出てこず諦めてしまい、PHP使って無理やりMavenリポジトリつくってしまえばいいのではと思ったわけです。

Javaを使っているとやっぱりライブラリ公開する必要っておそらく出てくると思うんですよ（どうなんでしょう？）

私はGitHub PagesでMavenリポジトリを設置したいなと思って...

本当はもっといい方法があるんでしょうけど、深追いせずに済ませている感じです。

### 簡単にまとめると
- GitHub Pages上でMavenリポジトリを公開するためにPHP (ローカル側、XAMPP) でMavenリポジトリ生成ツール(？)をつくった

### なぜPHPで？
「で、なんでPHPを使ったのか？」というとその当時はPHPが好きだったんですよ。
それとWebベースでjarやらpomやらをアップロードしてGitに自動プッシュできたらいいなーと思っていました。

### 何のために？
Minecraft のMod開発のためです。

- https://maven.pitan76.net/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1015774/f46cf11f-42ff-9b07-4f38-fe39f81a410e.png)

MCPitanLib というライブラリ(前提mod)などの公開に使ってます。

### リポジトリ管理ソフトウェアに移行しないのか？
きちんと勉強すべきなんでしょうけどそのリポジトリ管理ソフトウェアについてよくわかってないんですよね。
今更それに移行するのもなあと思ってて、、、
時間があれば「Nexus Repository」や「JFrog artifactory」への移植も試みてもいいかなと思ってます。

# 自作した「Maven Repository Generator」
以下のGitHubのページで公開してます（需要ないだろうけど）

https://github.com/Pitan76/maven/releases/tag/v1.1

## maven.php
```php
<?php
// Maven Repository Generator v1.1
// License: MIT
// Author: Pitan

define('DEFAULT_GROUP_ID', "net.pitan76");
define('DEFAULT_VERSION', "1.0.0");
define('GENERATE_INDEX_HTML', true);
define('AUTO_PUSH', true);
define('NODISPLAY_FILE', array('index.html', 'maven.php', 'CNAME'));
define('NODISPLAY_DIR', array('v'));

$DEFAULT_GROUP_ID = DEFAULT_GROUP_ID;
$DEFAULT_VERSION = DEFAULT_VERSION;
```

| 定数名 | 備考 |
| ----- | ---- |
| DEFAULT_GROUP_ID | デフォルトのGroup ID (パッケージ名) |
| DEFAULT_VERSION | デフォルトのバージョン |
| GENERATE_INDEX_HTML | index.html (ファイル一覧) の生成の有効/無効 |
| AUTO_PUSH | 自動でGitプッシュするかどうか |
| NODISPLAY_FILE | index.htmlで一覧に載せないファイル |
| NODISPLAY_DIR | index.htmlで一覧に載せないディレクトリ |

XAMPPとか使ってサーバー立ててmaven.phpにアクセスするとこんな感じです。
まあ自分用なので見た目に関してはめちゃくちゃテキトーです。

Createボタン押すとmavenリポジトリ構築します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1015774/29aa8791-9fcc-1332-3a99-c40cc136a89b.png)

### 生成の流れ
1. group id、artifact id、versionを入力
2. ファイル(複数)を選択してPOST送信 (操作)
3. `git pull`
4. POSTで受け取ったデータからフォルダを生成し、POSTされたファイルをリポジトリ先に移動、生成
5. maven-metadata.xmlとハッシュのファイルを作成
6. ファイル、ディレクトリ一覧のindex.htmlを生成
7. `git add *`
8. `git commit -m "auto push ([artifact id]-[version])"`
9. `git push`

とかなり無理やりやってます。

# ビュワー「Maven Repo Viewer」も作った
Mavenリポジトリの閲覧用により見やすくした感じです。こっちはJavaScriptで書いた奴です。

- http://localhost/maven/v/#net/pitan76/itemalchemy/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1015774/8394e3c1-f227-0940-33af-31a7282017f7.png)

必要ないと思いますが、載せときます。
- ソース: https://github.com/Pitan76/maven/blob/main/v/index.html

# 最後に
GitHub Pages使ってMavenリポジトリ管理してると以前はpullする処理入れてなかったのでgit pullし忘れてたまに他のパソコンから作業したらコンフリ起こしてたんですよね...

Javaライブラリのパッケージ管理にPHP使うってどないこっちゃって感じですが（笑）
まあ合理的ではない方法ですが、ロマンだと思っていただけたらです。(何が正しい方法なのかもよくわかってない)

初めて書いたと思い込んでたら僕過去に同じような記事書いてたっぽい...w

GitHub Pagesを利用してMavenリポジトリをつくる

https://wikichree.com/pitablog/?GitHub+Pages%E3%82%92%E5%88%A9%E7%94%A8%E3%81%97%E3%81%A6Maven%E3%83%AA%E3%83%9D%E3%82%B8%E3%83%88%E3%83%AA%E3%82%92%E3%81%A4%E3%81%8F%E3%82%8B
firecrawlをWSL2＋Docker（Desktop）環境にインストールする

# 手順
WSL2のプロンプトより、リポジトリをクローンします
```bash
git clone https://github.com/mendableai/firecrawl.git
```

apps/apiの中の「.env.example」を「.env」にコピーして下記を設定します。
```vim
USE_DB_AUTHENTICATION＝false
TEST_API_KEY= test
```
こちらの設定は、テスト用のため、実際には`USE_DB_AUTHENTICATION＝true`と設定して認証を利用するようにしましょう。

`TEST_API_KEY= test`は外部サービスやプログラムよりAPIを利用するときに使用するAPIキーです。

プロジェクトのルートディレクトリに戻り、以下のコマンドでDockerコンテナをビルドし、バックグラウンドで起動します。

```bash
cd ../..
docker compose up -d --build
```

起動後にテストを実行します。
```bash
curl -X GET http://localhost:3002/test
Hello, world!
```

# 参考
- [Dify+Firecrawlでお手軽にRAGを構築](https://note.com/fujii_ritsuo/n/n8020ea0284a5)
- ChatGPT
Excelでマニュアル作成等のためにマーカーを使う方法

Excelの標準機能にはWordのようなマーカー機能はありません。

しかし、マニュアル作成等のために、スクリーンショット画像の特定部分をマーカーで目立つようにしたい、ということがあります。

Excel以外のペイントツールでスクリーンショット画像の目立たせたい部分にマーカーをつける方法もありますが、その場合には画像貼り付け後にExcel上でマーカーを削除したり位置を変更したりする編集が難しくなります。

そこで、代替手段として、透明度を上げた四角い図形を挿入して、スクリーンショット画像の上に重ねる方法があります。

![マーカー画像.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3479442/6611e265-c699-08a3-06c1-6882ec6d5e85.png)

ただ、図形の透明度を設定したりするのは面倒なので、VBAでマーカー代替物となる半透明の四角図形をアクティブセルの位置に挿入すると便利です。


```vb:ExcelVBA
Sub sbマーカー代替図形挿入_青マーカー()
    Call sbマーカー代替図形挿入(RGB(0, 176, 240))   '青マーカー
End Sub

Sub sbマーカー代替図形挿入_緑マーカー()
    Call sbマーカー代替図形挿入(RGB(0, 240, 176))   '緑マーカー
End Sub

Sub sbマーカー代替図形挿入_赤マーカー()
    Call sbマーカー代替図形挿入(RGB(240, 0, 0))     '赤マーカー
End Sub

Sub sbマーカー代替図形挿入(a_markerColor As Long)
    Dim shp As Shape
    Dim markerColor As Long
    Dim transparencyLevel As Single
    Dim lineWeight As Single

    ' 定数設定
    transparencyLevel = 0.6       ' 透明度

    With ActiveCell
        ' 図形（長方形）を作成
        Set shp = ActiveSheet.Shapes.AddShape( _
                    Type:=msoShapeRectangle, _
                    left:=.left, Top:=.Top, Width:=200, Height:=20)
    End With

    With shp
        ' 塗りつぶしの設定
        With .Fill
            .Visible = msoTrue
            .ForeColor.RGB = a_markerColor     ' 塗りつぶし色
            .Transparency = transparencyLevel ' 透明度
        End With

        ' 枠線の設定
        .line.Visible = msoFalse '枠線なし

    End With
End Sub
```

作成した好みの色は、個人マクロブック等に保存した上で、リボンにマクロを登録し、どのブックでも呼び出せるようにします。

![スクリーンショット 2024-12-21 203240.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3479442/72d33f3c-3d4d-fdbb-5a8d-9eca5b4286ad.png)

色を変更したい場合には、RGB値を変更して好みの色に変更してください。
テスト戦略の話

## テスト戦略を立てるための、ポイントを確認する
ここまでのテスト文脈の話のなかで、テストストラテジーマップの話を何度かしましたが、目標とする品質を実現するために必要なアクティビティを整理して、リスクをコントロールしながら打ち手を講じていく話をしてきました。

- #### 必要なアクティビティを整理する話　[[自分のテストフレームワークを作ろう！]](https://qiita.com/EgaSaQA/items/1eb643ebda0cceafa4bb)

- #### 必要とする目標を打ち立てる話　[[クライテリアコントロールの話]](https://qiita.com/EgaSaQA/items/03317ee6b649ee59b757)

目指す品質を実現するために、ポイントを押さえたうえで戦略を持っていると、自分たちの活動が、どこに向かっているのかを把握しながら、品質保証活動ができます。できてない箇所の影響範囲を確認しながら、説明ができるようになります。逆に、個々の品質を下げるかわりに、顧客がもっと喜ぶ機能を開発しよう、という判断もできるようになります。今回は、この戦略を立てる話です。


## テストストラテジーマップ
では、マップ上のそれぞれのパートで、何を保証しようとしているかをご説明します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/156898/d53bf964-1f5a-6125-13c2-1882638bc185.png)


### 1. テスト設計　Test Plan in Organization
先に、必要な品質を担保するにはどのくらいのアクティビティが必要かを見積もります。

### 2. テスト計画 Test Plan
見積もったテストアクティビティから、現実的なリソースでどのくらいの活動ができるかを計画に落とします。

### 3. リソース確認 Decide criteria
計画を立てる上で、どのくらいの人員・期間などが活動に充てられるかを確認します。

### 4. テスト実行 Test Run
作成されたテストを実行していきます。

#### 4-1. 基本のテスト Single Condition
単純に機能が１つ１つ動くかを確認していきます。なかには、これだけでテスト終了とするチームもあります。

#### 4-2. 応用のテスト Multiple Condition
複合的な条件で行われるテストを実行していきます。最初からQAのテストがここだけを行うチームもあります。

### 5. 結果ふりかえり Closing
発見された不具合などを分析し、傾向と対策を確認したうえで、次回の品質活動につなげます。


## まとめ
最後に、振り返り活動が入ることで、テストアクティビティ自体のカイゼンサイクルを回していくことができます。こうして、マップ自体を時々見直したり、新しい手法を試しながら、ブラッシュアップしていくと、テスト戦略そのものを育てていけるでしょう。
AIデータセンターでのEthernetのNICを調べてみた

# はじめに

この記事は、[Ethernet Advent Calendar 2024](https://qiita.com/advent-calendar/2024/ethernet)の23日目の記事です。

私は、EthernetといえばPC用の100BASE-Tで、NICは通称カニさんチップで頭の中が止まっています。

先日発表されたブロードコムの決算から、ブロードコムの株価が急上昇しており、AI関連ネットワークチップが好調とのことで、改めてAIデータセンター用のEthernetについて調べてみました。
AIの恩恵はNVIDIAだけじゃないんだと興味を持った次第です。

https://shikiho.toyokeizai.net/news/0/846351

>AI関連の売上高は､AIプロセッサーとネットワーク部品の需要に後押しされ､通期で220％増加したとタン氏は説明した。

# ブロードコム

>![スクリーンショット 2024-12-21 16.30.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1032713/312a46b9-2b19-b363-ec3d-bda52de265e7.png)

400Gbまで出ている様子。

https://jp.broadcom.com/products/ethernet-connectivity/network-adapters/p1400g

> 特徴
> ラインレート、全二重スループットを備えた標準準拠の 400/200/100/50/40/25G QSFP112-DD PCIe NIC
> シングルポート 400/200/100/50/25G

# NVIDIA

NICまでNVIDIAが作っていたのか・・。
イーロンマスクのxAIのデータセンターを紹介する下記ビデオの中で、スーパーマイクロのサーバに組み込まれたNICが、NVIDIA製だと知りました。

https://www.youtube.com/watch?v=Jf8EPSBZU7Y&t=390s

https://www.nvidia.com/ja-jp/networking/products/data-processing-unit/


https://resources.nvidia.com/en-us-accelerated-networking-resource-library/datasheet-nvidia-bluefield

>NVIDIA BlueField-3 DPU は、ソフトウェアデファインドのネットワーク、ストレージ、サイバーセキュリティをラインレートで処理する毎秒 400 Gb インフラストラクチャ コンピューティング プラットフォームです。

# 終わりに

400Gになっていて驚きでした。5nmプロセスとか最先端のプロセス技術を採用したチップになっている。
ビデオにもありましたが、ストレージへはネットワーク経由でアクセスするため、大量の学習データをGPUサーバに転送するための帯域が重要だということがわかりました。

以上、AIデータセンターでのEthernetのNICを調べてみたでした。
OpenFOAMのrigidBodyMotionによる二重振り子

# rigidBodyMotion
　OpenFOAMのrigidBodyMotionでは、複雑な物体の動きを表現することができます。

　例えば、OpenFOAMのチュートリアル
`$FOAM_TUTORIALS/multiphase/overInterDyMFoam/rigidBodyHull`では、船体と一緒に動くプロペラの回転をrigidBodyMotionで模擬しています。

　この機能を使用して、二重振り子の計算を行ってみました。

![doublePendulum.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3948655/2f2f4a27-fd9c-a039-244a-10b7ecbee62b.gif)

# ケースファイル
　[こちら](https://github.com/jmu-26/OF_doublePendulum)にOpenFOAM v2212で動作確認をしたケースファイルが置いてあります。

# dynamicMeshDictの設定
　物体は上の動画の赤い物体「box1」と青い物体「box2」の２つが定義されています。「box1」は絶対座標系で$(0, 0, 1)$の位置に紐でつながっていて、「box2」は「box1」に紐でつながっています。（もちろん、紐と言っても剛体を想定しています。）
　まず、「box1」の設定から見てみましょう。

## box1の設定
```
box1
{
    type cuboid;
    parent root;

    mass 5;
    L (0.1 0.1 0.1);
    centerOfMass (-1.0 0.0 0.0);
    joint
    {
        type Ry;
    }
    transform (1 0 0 0 1 0 0 0 1) (0.0 0.0 1.0);

    patches (box1);
    innerDistance 100;
    outerDistance 200;
}
```

　物体は、「cuboid」というタイプで定義されていて、`mass`で物体の質量、`L`で直方体の各方向の長さを定義します。これらの設定を使って、慣性モーメントの値は自動的に計算されます。

　`transform`は、この物体の運動についての原点の位置の設定です。`parent`が`root`に指定されているので、絶対座標系に対してこの値を定義します。設定の最初のカッコが回転移動を表すテンソル、次のカッコが並進移動を表すベクトルになっています。「box1」は$(0, 0, 1)$の位置で固定された紐につながっているので、`transform`の2つ目のカッコの設定が`(0.0 0.0 1.0)`になっています。

　`centerOfMass`は重心位置の設定です。この物体の運動の原点位置$(0, 0, 1)$からの相対座標値で設定します。「box1」の初期位置は、振り子の中心位置から$x$方向に$-1$離れた点ですので、`(-1.0 0.0 0.0)`に設定しています。

## box2の設定
```
box2
{
    type cuboid;
    parent box1;

    mass 5;
    L (0.1 0.1 0.1);
    centreOfMass (-1.0 0.0 0.0);
    joint
    {
        type Ry;
    }
    transform (1 0 0 0 1 0 0 0 1) (-1.0 0.0 0.0);

    patches (box2);
    innerDistance 100;
    outerDistance 200;
}
```

　「box2」は、「box1」と紐でつながっています。つまり、「box2」は移動する「box1」まわりに回転するように定義する必要があるので、`parent`は`box1`に設定します。

　`transform`で設定する「box2」の運動の原点は「box1」のある位置です。`parent`が`box1`に設定されているので、`transform`は「box1」の運動の原点位置に対する相対座標値で設定します。「box1」の初期位置は「box1」の運動の原点に対して$x$方向に-1離れた点ですので、`transform`の2つ目のカッコの設定は`(-1.0 0.0 0.0)`にします。

　`centerOfMass`は「box1」と同じように、この物体の運動の原点位置からの相対座標値で設定するので、`(-1.0 0.0 0.0)`にします。
【Go】カリカリなMutexを作る

## はじめに

こちらはCA26卒内定者がお届けする、[CyberAgent 26th Fresh Engineer's Advent Calendar 2024](https://qiita.com/advent-calendar/2024/ca-26th)の20日目の記事になります。

サボり記事で申し訳ないのですが、せっかく枠が空いていたので、今回は内定者バイト期間中のチーム内勉強会で発表したGoのMutexに関する資料を貼っておきたいと思います。

## スライド

<iframe src="https://docs.google.com/presentation/d/e/2PACX-1vQIIPC0riOxNHEWSzxhF2wEI9rW4HEIiRY73XTtsqM8FanORwTCHwHj09_TVC-smHYZNDLnbWEl-W54/embed?start=false&loop=false&delayms=3000" frameborder="0" width="960" height="569" allowfullscreen="true" mozallowfullscreen="true" webkitallowfullscreen="true"></iframe>
Green's theorem「グリーンの定理をsympyのソースコードで説明して下さい。」をAI先生に教えてもらう。


・タイトル名を変更予定です。　
・以下、正しいのか、私の力で判断できませんでした。申し訳ありません。

**グリーンの定理をsympyのソースコードで説明して下さい。**

# ChatGPT先生へ

>(回答抜粋)
```python
from sympy import symbols, Function, diff, integrate

# 変数を定義
x, y = symbols('x y')
P = Function('P')(x, y)  # スカラー場 P(x, y)
Q = Function('Q')(x, y)  # スカラー場 Q(x, y)

# 面積分（右辺）
area_integral = integrate(diff(Q, x) - diff(P, y), (x, 0, 1), (y, 0, 1))  # 領域は例として [0, 1] × [0, 1]

# 線積分（左辺）
# 曲線をパラメータ化（例: 単位正方形の境界）
t = symbols('t')
x_curve = [t, 1, 1-t, 0]
y_curve = [0, t, 1, 1-t]
line_integral = 0

for i in range(4):
    dx = diff(x_curve[i], t)
    dy = diff(y_curve[i], t)
    line_integral += integrate(P.subs({x: x_curve[i], y: y_curve[i]}) * dx +
                               Q.subs({x: x_curve[i], y: y_curve[i]}) * dy, (t, 0, 1))

# 結果を表示
print("面積分:", area_integral)
print("線積分:", line_integral)
```

グリーンの定理の一般的な形を、mathjaxのコードを教えて下さい。

>(回答抜粋)
```math
\oint_C \left( P \, dx + Q \, dy \right) = \iint_R \left( \frac{\partial Q}{\partial x} - \frac{\partial P}{\partial y} \right) \, dx \, dy
```

# Gemini先生へ
>(回答抜粋)
```python
from sympy import *

# 変数の定義
x, y = symbols('x y')

# ベクトル場の定義 (例: P = x*y, Q = x^2)
P = x*y
Q = x**2

# 偏微分の計算
dQdx = diff(Q, x)
dPdy = diff(P, y)

# 二重積分の計算 (例: D は x=0 から x=1, y=0 から y=1 の正方形)
# この例では、線積分を計算するための具体的なパラメータ表示がないため、二重積分のみ計算しています。
# より複雑な例では、線積分もSymPyで計算できます。
integral = integrate(integrate(dQdx - dPdy, (y, 0, 1)), (x, 0, 1))

# 結果の出力
print("∂Q/∂x:", dQdx)
print("∂P/∂y:", dPdy)
print("∬(∂Q/∂x - ∂P/∂y) dA:", integral)

# 線積分を計算する例 (C は x=t, y=t^2, 0<=t<=1 でパラメータ表示された曲線)
t = symbols('t')
x_t = t
y_t = t**2
dx_dt = diff(x_t, t)
dy_dt = diff(y_t, t)

line_integral = integrate(P.subs({x: x_t, y: y_t})*dx_dt + Q.subs({x: x_t, y: y_t})*dy_dt, (t, 0, 1))
print("∮(P dx + Q dy):", line_integral)
```

グリーンの定理の一般的な形を、mathjaxのコードを教えて下さい。

```math
\oint_C (P \, dx + Q \, dy) = \iint_D \left( \frac{\partial Q}{\partial x} - \frac{\partial P}{\partial y} \right) dA
```

# copilot先生へ


# いつもの? sympyの実行環境と 参考のおすすめです。
[(テンプレート)](https://qiita.com/mrrclb48z/items/00dd08b0317069be9342)

# いつもと違うおすすめです。
#### wikipedia

https://en.wikipedia.org/wiki/Exterior_derivative

https://en.wikipedia.org/wiki/Green%27s_theorem

https://ja.wikipedia.org/wiki/%E3%82%B0%E3%83%AA%E3%83%BC%E3%83%B3%E3%81%AE%E5%AE%9A%E7%90%86


#### 過去問

https://qiita.com/mrrclb48z/items/bc48712d383d1d020a1b
Salesforceの組織情報から環境の有効期限を確認する方法

## はじめに
Salesforce環境の有効期限を確認することは、システム管理者にとって重要なタスクの一つです。この記事では、組織情報から環境の有効期限を確認する手順を詳しく解説します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2648069/08070dfd-5805-47a2-2dd1-c9d4185a3c34.png)


## 前提条件
- Salesforce組織の管理者権限を持っていること
- システム管理者プロファイルまたは「組織の参照」権限を持っていること

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2648069/c67ecbbe-10cc-6e64-f457-06e3430ea63f.png)

## 確認手順

### 1. 設定画面へのアクセス
1. 画面右上の歯車アイコン⚙️をクリック
2. 左側のクイック検索ボックスに「会社情報」と入力
3. 「会社情報」をクリック

### 2. ライセンス情報の確認
組織情報のページで以下の項目を確認できます：

- 組織の有効期限
- Salesforceライセンスの有効期限
- 各種アドオンライセンスの有効期限

### 3. 重要な確認ポイント
- **組織の有効期限**: これは環境全体の有効期限を示します
- **ユーザーライセンス**: 各種ライセンスの数と有効期限
- **機能ライセンス**: アドオン機能の有効期限

## 有効期限が近づいた場合の対応

### 1. 更新が必要な場合
- アカウントエグゼクティブに連絡
- 更新手続きの開始（通常1-2週間程度必要）

### 2. 注意点
- 有効期限の3ヶ月前から更新手続きを開始することを推奨
- 有効期限切れ後はデータにアクセスできなくなる可能性があるため、期限切れには要注意

## トラブルシューティング

### よくある問題と解決方法
1. **有効期限が表示されない場合**
   - プロファイルの権限を確認
   - システム管理者に確認

2. **更新後も有効期限が更新されない場合**
   - キャッシュのクリア
   - 24時間待って再確認
   - Salesforceサポートへの問い合わせ

## まとめ
定期的な有効期限の確認は、システムの安定運用に不可欠です。本記事の手順に従うことで、簡単に環境の有効期限を確認することができます。

## 参考情報
- [Salesforce ライセンスガイド](https://help.salesforce.com/articleView?id=users_licenses_overview.htm)


<iframe width="560" height="315" src="https://www.youtube.com/embed/zAj-Ov-ErXc?si=g-IXuWnkbv3IUcUo" 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>
TiDB関連イベント1月分

アドベントカレンダーのトリとして、恒例のイベント案内1月分です！

PingCAP主催のもの、コミュニティイベントに参加するものの両方を記載しています。
WebinarについてはJSTで6:00-24:00に開催されるイベントを記載しています。

また、ここに記載がなくとも、イベント/社内勉強会でTiDBについて話してほしいというリクエストはお気軽に @bohnen ([X/@bohnen](https://twitter.com/bohnen)) までお気軽にご連絡ください。

## 【お知らせ】TiDB Advent calendarにご参加ください!!

https://qiita.com/advent-calendar/2024/tidb

俺達のアドカレはこれからだ！駆け込み需要にも対応しています。

## ウェビナー: MySQL互換の分散型データベース 8.5 LTS新機能の紹介

https://pingcap.co.jp/event/20250116-webinar/

先日リリースされたばかりの [v8.5.0](https://docs.pingcap.com/tidb/stable/release-8.5.0) の新機能について紹介するウェビナーです。講師はおなじみPingCAP本田さんです。

## ウェビナー（英語）: Introduction to TiDB

https://www.pingcap.com/event/scale-out-like-nosql-enforce-data-integrity-like-sql-all-without-manual-sharding-apac-timezone/

英語のウェビナーですが、APAC向けに日本時間の午後に実施されるものです。TiDBの概要を事例を交えて紹介します。

## オープンソースカンファレンス 2025 Osaka

https://event.ospn.jp/osc2025-osaka/

オープンソースカンファレンスにブースを出します！オープンソースTiDBユーザーの皆様ぜひご参加ください。
2月のOSC東京ではセッションも持つ予定ですが、1月はブースのみです。

## 2月28日（金） TiDB User Group 一周年記念 Meetup （仮）

TiDB User Groupも一周年！記念ミートアップを東京で開催予定です。
Save the date!

## おわりに

今年もTiDBを応援してくださりありがとうございました。
それでは、良いお年を！
LeetCodeを1日1題解いてみる (day47)

47日目に取り組んだ問題はこちら！

# 596. Classes More Than 5 Students

https://leetcode.com/problems/classes-more-than-5-students/description/?lang=pythondata

## 問題文
Table: `Courses`
```
+-------------+---------+
| Column Name | Type    |
+-------------+---------+
| student     | varchar |
| class       | varchar |
+-------------+---------+
```
(student, class) is the primary key (combination of columns with unique values) for this table.
Each row of this table indicates the name of a student and the class in which they are enrolled.

Write a solution to find all the classes that have at least five students.

Return the result table in any order.

## 僕の回答
```py
import pandas as pd

def find_classes(courses: pd.DataFrame) -> pd.DataFrame:
    count = courses["class"].value_counts()
    filtered = count[count.values >= 5]
    return pd.DataFrame({"class": filtered.index})
```

## より効率の良い回答例

```py
import pandas as pd

def find_classes(courses: pd.DataFrame) -> pd.DataFrame:
    courses = courses.groupby(['class']).count().reset_index()
    return(courses[courses['student']>=5][['class']])
```

## 学んだこと
- `courses.groupby(['class'])`: `courses`の`class`列の値ごとにグループを作る
- `.count()`: 各グループごとに`student`列の非欠損値の数を数える
- `.reset_index()`: インデックスをリセットしてデータフレームに戻す
- `.value_counts()`: 指定した列のユニークな値ごとの出現回数を返す
返り値はSeries型で、インデックスに元の列のユニークな値、値に出現回数をもつ

## コメント
今回の使用しているメソッドは理解が難しかった。

## 次の問題はこちら!
https://qiita.com/h_y_s_d/items/f353197a3fa84d12ac5e
GraphQLを1から勉強しなおしてみた ~ リゾルバ ~

# はじめに
先日に引き続きGraphQLを一から勉強し直していきます。

前回はこちら。

https://qiita.com/mattsu_mocha/items/072ba882eff0ea30da48

# リゾルバ
スキーマで定義された型に基づいてデータを取得するための関数。クエリが実行されると、各フィールドに対応するリゾルバが呼び出され、データベースや他のAPIから必要なデータを取得して返す。

## フィールドリゾルバ
フィールドの型がスカラーの場合実行は完了するが、オブジェクト型の場合はそのオブジェクトに属するフィールドがスカラー型または列挙型になるまで実行を繰り返す。

```graphql:graphql
type Query {
  human(id: ID!): Human
}
 
type Human {
  name: String
  appearsIn: [Episode]
  starships: [Starship]
}
 
enum Episode {
  NEWHOPE
  EMPIRE
  JEDI
}
 
type Starship {
  name: String
}
```

```graphql:request
query {
  human(id: 1002) {
    name
    appearsIn
    starships {
      name
    }
  }
}
```

```json:response
{
  "data": {
    "human": {
      "name": "Han Solo",
      "appearsIn": [
        "NEWHOPE",
        "EMPIRE",
        "JEDI"
      ],
      "starships": [
        {
          "name": "Millenium Falcon"
        },
        {
          "name": "Imperial shuttle"
        }
      ]
    }
  }
}
```

具体的にどのようにresponseを返すのかを見ていく。（以降はJavaScriptの例）

### ルートフィールドとリゾルバ
- `obj`: 直前のオブジェクト（ルート・クエリ型のフィールドの場合、この引数は使用されないことが多い）
- `args`: GraphQL操作でフィールドに提供される引数
- `context`: すべてのリゾルバに提供される値で、現在ログインしているユーザーやデータベースへのアクセスのような重要なコンテキスト情報を保持している可能性がある
- `info`: 一般的に高度な使用例でのみ使用され、スキーマの詳細と同様に現在の操作に関連するフィールド固有の情報を保持する値（https://graphql.org/graphql-js/type/#graphqlobjecttype）

```javascript
function Query_human(obj, args, context, info) {
  return context.db.loadHumanByID(args.id).then(
    userData => new Human(userData)
  )
}
```

### 非同期リゾルバ
`context`はデータベースからデータを取得するが、データ取得は非同期操作でPromiseを返す。リゾルバ関数はPromiseを扱うがクエリ自体はその詳細を気にしないため、Promiseが完了するのを待ち、最適な並行性で処理を続ける。

### 簡単なリゾルバ
通常はオブジェクトのプロパティをそのまま返す。

多くのGraphQLライブラリではこのようなリゾルバを省略できる。つまり、以下を明示的に定義しなくてもGraphQLライブラリが自動的に処理してくれる。

```javascript
function Human_name(obj, args, context, info) {
  return obj.name
}
```

### スカラー強制
GraphQLがリゾルバから返された値をスキーマで定義された型に自動的に変換するプロセス。

### リストリゾルバ
GraphQLフィールドがリスト（配列）を返す場合に使用されるリゾルバ関数。

各リスト要素に対して個別にデータを取得し、非同期処理を行う。GraphQLはPromiseがすべて解決されるのを待ち、並行して処理を続ける。

# 参考

https://graphql.org/learn/execution/#producing-the-result
GNU gforth 超初心者が説明を試みる 〜実行環境、参照先〜

# はじめに
GNU gforth 超初心者です。右も左も分かりませんが GNU gforth とはどんなものか、 また古典的な FORTH から何が拡張され何が変わってないのか、 そんな感じでいきたいと思います。

# 実行環境
プログラミング言語の利点の一つは実際に手元で動かして試してみれることです。
なにはともあれ手元に動くブツが無いといけません。 

## Docker版
現在、 割と新し目のをもっともお手軽に動かせそうなのがDocker版です。
2024年12月20日時点では Gforth 0.7.9_20241009 で、 最新より2ヶ月遅れぐらい？

Docker版についてはこちらをご覧下さい。
https://kuma35-memo.readthedocs.io/ja/latest/gforth-docs-ja/bit-try.html

## ディストリビューション版
Ubuntu Linux 等でもパッケージャでインストールすることで GNU gforth を使うことができます。
が、 しかし、 結構古いです。 Ubuntu Linux 24.04LTS では gforth 0.7.3 となっています。

## 開発版をビルド
手元では swing (GUI)絡みのビルドに失敗しましたが、それ以外の機能は動いています。
(同時にできる vmgen というのは gforth エンジン用のVM(仮想マシン)を生成するためのプログラムで、まだ未対応のアーキテクチャ等に対応するために使うものです)

````bash
git clone https://git.savannah.gnu.org/git/gforth.git
````

# 参考文献など

詳しい説明などは以下を参考にしてください。

- GNU gforth マニュアル オレオレ翻訳 https://kuma35.github.io/gforth-docs-ja/
- FORTH入門 レオ・ブロディ著 原 道宏 訳 工学社 1984年。 ターゲットマシンがTRS80とかなので、今から見ると古臭いですけども、古典的なFORTHの仕組みを知るには良い本です(国立国会図書館デジタルコレクションで閲覧できるようです(要登録) https://dl.ndl.go.jp/pid/12632206 )
- Starting FORTH FORTH入門の原著です。 FORTH.Inc で無料公開されています。 但し、Webで見れる版は Swift FORTH 用に書き換えられてるそうです。 原著そのままが読みたい場合は PDF版をダウンロードしてください。 https://www.forth.com/starting-forth/
- Thinking FORTH アメリカでは Starting FORTH と対になると言われたらしい、 FORTHのプログラムはどのようにして書くか、どう書くのが望ましいか、方法論まで踏み込んだ本(らしい。書籍版は読んだことない)。 フリー版(?)は https://thinking-forth.sourceforge.net/  
- FORTH思考 上記 Thinking FORTH のオレオレ翻訳版です。 https://thinking-forth-ja.readthedocs.io/ja/latest/

今回はここまで。次回から、あちこちつまみ食い気味に解説していきます。
エンジニアリングマネジメントトライアングルを用いてチームを可視化し進むべき方向を考える！

# はじめに
クイックのエンジニアリングマネージャー桃原（とうばる）です。

弊社は 「プロダクトチーム」と「職種」の掛け合わせでマトリクス型組織を運営しており、
私はエンジニアリングチームのマネージャー（以下、EMとする）として、日々業務を行っています。


本記事は[Engineering Manager Advent Calendar 2024 シリーズ2 14日目](https://qiita.com/advent-calendar/2024/em)の記事です。

# 悩みながらもエンジニア組織を漸進する
EMとして「エンジニアリングチームの成果最大化」を目指し推進しています。

その中で悩むことがあります。
- 進むべき方向は誤っていないか？
- 過不足なく取り組めているか？

私のように悩みながら組織開発を担っているEMは多いのではと思います。
（システム開発は多く経験してきたが、組織開発の経験は現職が初めて）
EMが関わる範囲は組織によって異なります。
だからこそ答えはどこにもなく、一歩一歩前に進みながら答えを定義するしかありません。
私たちがどのように取り組み、課題解決を行っているか一つのケースとして書きました。

# 進むべき方向や目的のために過不足なく動けているか？
「すべて計画通りで問題ない。」と言いきれますでしょうか？

私自身は、組織運営の中で日々発生する緊急度の高い対応に追われることで、
目的や事業計画に対して俯瞰して組織内の課題発見や解決へのアクションが少なくなり、
気づけば一部の偏った領域にフォーカスがあたり、小さな推進に留まる事があります。

進めている事を可視化し俯瞰する事で、今後取り組む方向性を本記事で共有します。


# エンジニアリングマネジメントトライアングルとは？
一言でいうと、プロダクトマネジメントトライアングルのエンジニアリング版です。

https://github.com/engineering-manager-meetup/engineering-management-triangle

こちらをもとに考えましたが、カケハシ社の記事にあるような「エンジニアリングチーム」を中心に置き、頂点を事業・ピープル・技術とした考えの方が、私たちのエンジニアリングチームに近くベースとして利用しました。

https://kakehashi-dev.hatenablog.com/entry/2023/12/27/113000

さて、いざマッピング！

# 事業 - ピープル / ピープル - 技術の領域
私+数名のEMで担う範囲

![私 + 数名のEMで担う範囲.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/40546/37d7ff6f-5cc0-0856-07da-a9aa91094c4c.jpeg)
エンジニア組織開発推進を専任とする私と、プロダクトチームと兼務のEMが複数名でこれらの領域を推進しています。

HR部署と連携しながら、新卒採用、中途採用、ビジネスパートナー様参画に向けた取り組みなど、エンジニアの採用市場は非常に難易度が高くなっています。

「ピープル - 技術」の領域においては、エンジニアリングチームの中で少人数制のユニットを設け、EMが複数名のエンジニアを率い、目標設定、チームビルディング、メンタリング、定期的な1on1実施を行っています。
育成については、EMの強みに応じた推進範囲を決めてエンジニアリングチーム独自の技術研修、社内イベントを実施しています。

# 技術 - 事業 / 技術 - ピープルの領域
技術統括が担う範囲
![技術統括が担う範囲.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/40546/4b5ed00d-6893-b217-553c-0e9a746b2c70.jpeg)

横断的な技術課題解決や社内開発基盤の構築を行う@miki-yojiが、技術統括としてこの領域を爆進しています。技術統括が担う範囲は非常に広く関わるプロダクトや事業も多いため、より力を入れていく領域です。

# 事業 - 技術の領域
プロダクト開発チーム、テックリードが担う範囲
![プロダクトチームやテックリードが担う範囲.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/40546/190323ec-cdb8-8588-8517-f9290ab99062.jpeg)
事業計画に紐づくプロダクト開発においては、プロダクトチームのプロダクトオーナーやテックリードにより意思決定と推進が行われています。

「事業 - 技術」の領域については、セキュリティ、インフラ、情シス/コーポレートITなど、プロダクト開発以外で対応すべき範囲が広く、プロダクト開発チームが開発に集中できるよう、先述した技術統括が技術横断、検証、開発者体験向上、開発生産性向上の仕組み作りを担っています。
その上で事業ドメインに即したシステム開発、プロセス設計はプロダクト開発チームが推進しています。

# 可視化まとめ
事業・ピープル・技術の軸に推進している項目を並べて担う範囲をマッピングした事で、網羅的に取り組めている状況は把握できました。
![領域が網羅されたイメージ.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/40546/a7420579-664f-c9b4-3c42-2290cec945b8.jpeg)

一方で、マッピングする中で「ピープル - 技術」の領域におけるアクションが少ない事に再認識できました。（推進はしているが、今後はより多くの力を注ぎたい）
今回の記事で具体的なアクションについては割愛しますが、認識できれば特定領域に対してより力を注ぐために優先順位を決めて計画を進めていくのみです。

# まとめ
私たちが取り組んでいる動きをエンジニアリングマネジメントトライアングルにマッピングする事で、エンジニアリングチームを中心とした領域毎のカバー範囲、網羅性、今後力を入れたい領域について（MECEではありませんが）可視化が行えました。

わかった事は、いざ可視化してみると各領域にかける力に偏りがあり、

「過不足なく取り組めているか？」
　→　「否！」となりました。

同じような悩みを持つEMが、チームを可視化する事でエンジニアリングチームを漸進するきっかけなれたら嬉しいです。

よきEMライフを！
環境構築チートシート(備忘録)

随時更新予定
## VsCode
1\. ターミナルでcodeが認識されない
確認コマンド
　`code --version`
結果
　`zsh: command not found: code`
原因：パスが設定できていない
対策
Command Paletteで`Shell Command: Install 'code' command in PATH`を実行