OmniAICreator/Qiita-1.07M huggingface dataset:
【VSCode】スニペット機能を使って作業を効率化する方法

## まえがき
`VSCode`には**スニペット機能**という、作業を**効率化**できる機能が備わっています。
本日はこの機能に関する説明や設定方法を紹介します。

## スニペット機能による恩恵
そもそも**スニペット機能**とはなんでしょうか。
答えは、**予め書いておいたコードをすぐに呼び出せる**という機能です。
例えば、`C++`でforループを書く時は以下のような構文を使います。
```c++
for (int i=0; i<n; i++) {
    //process
}
```
これを毎回書くのは、ほんの少しだけ面倒ですね。ですがスニペット機能を用いれば、以下のようにして簡単に書くことができるようになります。
1. forin(予め設定しておいたコード呼び出し)と入力
![スクリーンショット 2024-12-22 142744.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3858134/2749a4a3-b4e6-8177-d96f-80574fff6673.png)

2. 表示されたスニペットを呼び出す
![スクリーンショット 2024-12-22 145225.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3858134/720e4dc0-ac93-3c29-cd33-c8eed076152c.png)


こんな感じですぐに書きたいコードを呼び出すことが出来ました！
今回出した例のような短いコードでも十分恩恵はありますが、さらに**長いコード**や**複雑なコード**を呼び出したいときは大幅な**時間短縮**となり作業の**効率化**に大きく寄与するので、是非設定してみてはいかがでしょうか。

## スニペット機能の設定方法
さて、スニペット機能の内容や効能を知っていただけたかと思います。ということで、実際に設定していきましょう。

### スニペットファイルの作成
まずは、`VSCode`の画面左下にある歯車マークから`スニペット`という項目を探してください。
![スクリーンショット 2024-12-22 141922.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3858134/f1f45724-ef59-03fe-cd20-e29bd64ba4bb.png)

押下すると、以下のような検索欄が画面上部に表示されるので、スニペット機能を使用したい言語を選択しましょう。

![スクリーンショット 2024-12-22 144103.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3858134/3b995709-2793-d4ef-4bcd-b74b9f71de6a.png)

選択すると、`cpp.json`のような選択した言語名の`json`ファイルが生成されます。

### スニペットファイルの設定
さて、スニペットを書き込むスニペットファイルが作成できたので、この中に登録したいコードを書いていきましょう。初めて作成した場合サンプルコードが書かれているかと思いますが、全て消してしまって大丈夫です。

スニペットは以下のような形式で登録することが出来ます。
```c++
{
	"スニペットの名前": {
	  "prefix": "呼び出す際に入力するコード",
	  "body":[
		"出力するコード1行目", 
		"出力するコード2行目", 
		"出力するコード3行目", 
	],
    "description": "スニペットの説明(なくても良い)"
	},
}
```

また、複数のスニペットを登録したい場合は、一番最後のカンマに続けて同じようにスニペットの登録を書けばOKです。
<details><summary>複数のスニペットを登録したい場合</summary>

```c++
{
	"スニペットの名前": {
	  "prefix": "入力するコード",
	  "body":[
		"出力するコード1行目", 
		"出力するコード2行目", 
		"出力するコード3行目", 
	],
   "description": "スニペットの説明"
	},
 
	"スニペットの名前": {
	  "prefix": "入力するコード",
	  "body":[
		"出力するコード1行目", 
		"出力するコード2行目", 
		"出力するコード3行目", 
	],
   "description": "スニペットの説明"
	},
}
```
</details>

#### スニペットファイルの設定例
分かりやすいように、スニペットファイルの設定例を見てみましょう。
冒頭で紹介したforループのスニペットは以下のような感じになります。
```c++
{
	"forin": {
	  "prefix": "forin",
	  "body":[
		"for(ll i=0; i<n; i++) {", 
		"\t$1", 
		"}", 
   ],
   "description": "i=0~n-1でループ"
	},
}
```
上のコードをよく見ると、`"body"`の部分に`\t`や`$1`という記号があると思います。この記号を使うことにより、スニペット機能を更に便利にすることができるので紹介しましょう。

#### 「\t」の利用方法
`\t`とはタブ文字のことで、文字列中でタブを表す文字です。
改行文字の`\n`が改行を表すのと同じです。
スニペットのコード中でインデントが含まれる場合はこのタブ文字`\t`を利用してインデントを示しましょう。

:::note warn
実際にタブを入力してインデントを書いてしまうとエラーが出てしまいます。
:::

#### 「$」の利用方法
`$`とは、スニペットを呼び出したあとの入力箇所を指定する文字です。
例えばスニペットのコード中に`$1`と書いておけば、呼び出し直後に`$1`の場所からコードを書き始めることができるようになります。デフォルトのままだとスニペットの最後にカーソルが自動で移動されるので、`$`を利用することでさらに効率化することができますね。
また、`$1,$2,...,$n`とスニペットのコード中に書くことにより、複数の入力箇所を指定することができます。

スニペット呼び出し直後は`$1`にカーソルが移動し、`Tab`を押すと`$2`に移動、再度`Tab`を押すと`$3`に移動、・・・、再度`Tab`を押すと`$n`に移動

といった具合です。

## あとがき
`VSCode`でのコーディングを効率化するスニペット機能の紹介をしました。
スニペットの登録はやや面倒に感じるかもしれませんが、一度登録してしまえば今後の作業がグッと楽になること間違いなしなので、是非試してみてください。
【UiPath】JSON配列をデータテーブルに変換してCSVで出力する

UiPathにて、要素数・深さが一定のJSON文字列を取込み、各種Json変数を通してデータテーブルに変換し、CSVとして出力するワークフローを作成する。

## 事前準備

「JSON 配列を逆シリアル化」アクティビティやJArray変数などを使うため、`UiPath.WebAPI.Activities`パッケージが必要になる。標準ではインストールされていないので、「パッケージを管理」から探してインストールしよう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/578020/6de95712-7c3b-275b-aee2-2f66c922c53b.png)

また、今回は以下のJSON配列のテキストファイルをインプットとして使用した。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/578020/cfad0739-7d16-0ecd-b5b8-569ecf28f119.png)

## 実装
こちらが今回のワークフロー全体。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/578020/4696809e-a9bb-2b1c-bcbf-d1633030fd73.png)

以下でポイントについて解説していく。

### ① 「JSON 配列を逆シリアル化」
`UiPath.WebAPI.Activities`に含まれるアクティビティ。
設定はシンプルで、「入力」にJSONフォーマットへ沿った文字列（`String`型変数）を渡すと、`JArray`型変数に変換してくれる。


### ② 「繰り返し (コレクションの各要素)」：currentJProperty
```次のコレクション内の各要素：jsonAry(0).Children(Of JProperty)()```

ここではJSONの要素に対応してデータテーブルの列名を定義するため、「JSON 配列を逆シリアル化」が出力した`JArray`型変数のうち1行目のみを取得し、プロパティの名前を読み取って空のデータテーブルに列追加している。

### ③ 「繰り返し (コレクションの各要素)」currentJToken

ここからはデータテーブルに行を追加していく。繰り返しが2重になっており、外側のループはJSON配列、内側のループはJSONの各要素に対応している。
はじめにDataTableの`NewRow`メソッドを使って空の行変数を作成。次に列名を定義した時と同様にJSONのプロパティで繰り返しをかけ、プロパティ名と同じ列名（`rowTemp(currentJProperty.Name)`）にプロパティの値（`currentJProperty.Value`）を追加していく。最後に、行変数をデータテーブルに追加。これをJSON配列ごとに繰り返す。

### 出力結果
こちらが出力したCSVの内容。無事にJSONをCSVとして変換できている。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/578020/983af281-e6bd-f9f4-dd6b-bb492ae0347a.png)

## 参考
https://forum.uipath.com/t/json-csv/263937

## 動作環境
UiPath.WebAPI.Activity v1.21.1
UiPath.System.Activity v24.10.7
cscの作法 その546

# 概要
cscの作法、調べてみた。
練習問題やってみた。

# 練習問題
sqliteをselectして、csv出力せよ。

# サンプルコード

```


using System;
using System.Text;
using System.IO;
using System.Data;
using System.Data.Common;
using System.Transactions;
using System.Data.SQLite;

namespace App
{
	public class Program {
		public static void Main(string[] args) {
			SQLiteConnectionStringBuilder ConnectionStr = new SQLiteConnectionStringBuilder();
			ConnectionStr.DataSource = "db0.sqlite";
			using (SQLiteConnection Connection = new SQLiteConnection(ConnectionStr.ToString()))
			{
				Connection.Open();
				SQLiteCommand command7 = Connection.CreateCommand();
				command7.CommandText = "SELECT * FROM wari";
				SQLiteDataAdapter dataAdapter7 = new SQLiteDataAdapter(command7);
				DataTable dt7 = new DataTable();
				dataAdapter7.Fill(dt7);
				var filePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "wari.csv");
				Encoding enc = Encoding.GetEncoding("Shift_JIS");
				using (StreamWriter sr = new StreamWriter(filePath, true, enc))
				{
					foreach (DataRow row in dt7.Rows)
					{
						sr.WriteLine(string.Join(",", row.ItemArray));
					}
				}
			}
			Console.WriteLine("ok0");
		}
	}
}




```

以上。
Secrets Managerを使用してAppRunnerに安全に環境変数を設定する方法

## はじめに
本記事では、AWS AppRunnerを使用してアプリケーションをデプロイする際に、AWS Secrets Managerを活用して機密情報を安全に管理する方法について解説します。

## シークレットの作成

1. **シークレットのタイプ選択**
    - 「その他のシークレットタイプ」を選択します。
    - 「キー」と「値」のペアを追加します。

2. **暗号化キーの選択**
    - デフォルトの `aws/secretsmanager` を選択します。これにより、KMSの設定を行わずにAWSが暗号化を管理してくれます。

3. **名前とタグの設定**
    - シークレットに分かりやすい名前を付けます。
    - 必要に応じてタグを追加します。リソースのアクセス許可は後述しますので、この段階では設定しなくて構いません。

4. **シークレットの作成**
    - すべての設定を確認し、「シークレットの作成」をクリックします。

## ポリシーにて、カスタムポリシーを作成
AWS IAMでAppRunnerがSecrets Managerにアクセスできるように、カスタムポリシーを作成します。

1. `IAMコンソール`に移動し、`ポリシー` > `ポリシーの追加`を選択します。
2. `JSON`タブを選択し、以下のポリシーをポリシーエディタに貼り付けます。
3. 次の画面でポリシー名を`apprunner-secret-custom-key`と指定し、ポリシーを作成します。

![カスタムポリシー作成画面](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984024/21a42791-cfb9-f84b-5c91-bdff5d7c1a13.png)

**ポリシーの内容：**
```json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "secretsmanager:GetSecretValue",
      "Resource": "arn:aws:secretsmanager:ap-northeast-1:851725429673:secret:roten-app-secret-MYSQL-HOST-mgA22t"
    }
  ]
}
```

## IAMロールを作成

以下の記事を参考にAppRunnerがSecretManagerにアクセスするためのIAMロールを作成しました。

https://dev.classmethod.jp/articles/app-runner-secrets-ssm-parameter/

1. IAMコンソールのロールを開き、IAMロールを作成していきます。

2. `ユースケース`に`EC2`を選択

![スクリーンショット 2024-12-21 17.43.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984024/88744ac9-6431-9521-d988-f42850a36a11.png)
<br/>
3. `次へ`をおして許可ポリシーに`IAMFullAccess`, `SecretsManagerReadWrite`, `apprunner-secret-custom-key`（先ほど作成したカスタムポリシーの名前）を選択します。
 (参考：https://docs.aws.amazon.com/ja_jp/secretsmanager/latest/userguide/auth-and-access.html#auth-and-access_admin)
 <br/>
4. `次へ`を押して、ロール名を入力し、カスタム信頼ポリシーを以下のように設定します。

**カスタム信頼ポリシーの内容：**
```
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "tasks.apprunner.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
```

## AppRunnerで環境変数とセキュリティの追加

1. `サービスの設定` > `環境変数`で必要な環境変数を追加します。
![スクリーンショット 2024-12-21 18.08.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984024/89c19aaa-2f0a-7bf2-7061-bf18a2e5dcc3.png)

2. `セキュリティ` > `アクセス許可`で先ほど作成したIAMロールを指定します。これにより、AppRunnerがSecrets Managerからシークレットを取得する権限を持つようになります。

## 最後に
本記事では、AWS AppRunnerを使用してアプリケーションをデプロイする際に、AWS Secrets Managerを活用して機密情報を安全に管理する方法について解説しました。カスタムポリシーやIAMロールなど、複雑な概念が多く登場し、最初は苦労しましたが、様々な参考記事を活用しながら一つずつ手順を進めることで、目標を達成できました。この調子で、セキュリティにも強い開発ができるエンジニアを目指して頑張っていきたいと思います。
kenichi884/M5StackToioを使うときはNimBLE-Arduinoのバージョンを1.4.3に固定してください(令和6年末時点)

　タイトルが言いたいことのすべてです。

# 以下細かい話

　M5Stack(まあ、M5製品に限らずESP32/ESP32-S3系ボードでArduino使うぶんには使えるんですが)でtoio core cubeを動かしたりセンサーの情報をよみとったりできるライブラリ [kenichi884/M5StackToio](https://github.com/kenichi884/M5StackToio)ですが、依存ライブラリの[NimBLE-Arduino](https://github.com/h2zero/NimBLE-Arduino)がver.1.4.xからver.2.0.x、ver.2.1.xへバージョンアップし、APIの互換性がなくなりました。

なんか2.0.0のリリースでミスったっぽい

https://github.com/h2zero/NimBLE-Arduino/issues/784

そして2.1.0リリーズ
"Reduced the code size by over 40KB." とあるのが魅力的ですが、1.4.x系とAPI互換性がありません。

https://github.com/h2zero/NimBLE-Arduino/releases/tag/2.1.0

今は2.1.2が最新のようです。

https://github.com/h2zero/NimBLE-Arduino/releases/tag/2.1.2

　このため、現時点(2024年12月)ではNimBLE-Arduinoのバージョンをver.1.4.3に固定してビルドしないと、[kenichi884/M5StackToio](https://github.com/kenichi884/M5StackToio)を使ったプロジェクトをビルドすることができず、ビルドエラーになります。

 # Arduino IDEの場合

 ライブラリマネージャで、M5StackToioのバージョン選択で「1.4.3」を選択してください。なんも考えずにアップデートしていると最新の2.1.2(2024年12月末時点)になってしまってビルドできなくなります。
 
 ![スクリーンショット 2024-12-22 113954.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/431649/f1664be6-9432-6dfc-1050-d7e1a8210c1e.png)

この状態にしてください。
![スクリーンショット 2024-12-22 114016.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/431649/d47fc714-a8b9-6c12-2456-0256d19f0a50.png)

　Arduino IDE 2.3.4、ボードマネージャ esp32 3.1.0 または M5Stack 2.1.3 でビルドできることを確認。

# PlatformIOの場合

 platformio.iniファイルのlib_depsで「NimBLE-Arduino@1.4.3」としてバージョンを固定してください。[kenichi884/M5StackToio](https://github.com/kenichi884/M5StackToio)のREADME.mdでは「NimBLE-Arduino@^1.4.1」と書いてしまっていたので、このままだと「1.4.1以上」ということになり2.1.2が選択されてしまします。

platformio.iniの例
```
platform = espressif32 @ 6.9.0 
board = m5stack-core2
framework = arduino
monitor_speed = 115200
lib_deps = m5stack/M5Unified
    https://github.com/stack-chan/m5stack-avatar
    kenichi884/M5StackToio
    h2zero/NimBLE-Arduino@1.4.3
```

# 現状の動作状況

　M5Stackシリーズでないと動かないということはなく、NimBLE-Arduinoの対応MCU(ESP32、ESP32-S3、ESP32-C3)であれば動きます。(M5UnifiedなどのM5専用ライブラリは外した状態で)XIAO ESP32-S3での動作は確認しました。
 
　ESP32-C6は未対応です。なのでM5 nano C6では動きません。
　ToioCore.hで // #define USE_NIMBLE 1 としてNiMBLEの使用をやめてarduino-esp32のBluetooth APIを使うようにするとC6でも動くかも。(Arduino IDEのほうが新しめのarduino-esp32に対応しているっぽいのでそっちだと可能性ありそうです。)

　NimBLEを使った場合、PSRAMのある機種ではWiFiとの同時使用が可能(arduino-esp32のBluetooth APIだとヒープメモリが足りずに動かない)ですが、それでもメモリが足りず、大体以下のような感じになっています。

WiFi使わない→PSRAMなし機種でもOK
WiFi(http/https)→PSRAM必須　radiko視聴などはいける
WiFi使う＆OpenAIなどによるいわゆるAIｽﾀｯｸﾁｬﾝ PSRAMがあってもメモリ不足で動作せず。

動作したものについては以下に置いてあります。

https://github.com/kenichi884/Stack-chan-Ez-with-toio

# 将来

　[kenichi884/M5StackToio](https://github.com/kenichi884/M5StackToio)のほうでNimBLE-Arduino 2.1.x対応しないといけないなーとは思っています。ただ、APIが違うので NimBLE-Arduino 2.1.x 専用になっちゃうかなと。( NimBLE-Arduino 1.4.xはarduino-esp32のBluetooth APIと互換なwrapperがあったのでarduino-esp32のBluetooth APIで書いておけば切り替えが容易だったのです。)

 あとnrF52というかAdafruit_nRF52_Arduino対応してみたいなーという気がしなくもないです。
Windows VBS

Windowsでメーカー、機種、製造番号を取得してテキストに保存する。

###PCのメーカー、機種、製造番号を取得

```メーカー、機種、製造番号を取得.vbs
Set objWMIService = GetObject("winmgmts:\\.\root\cimv2")
Set colItems = objWMIService.ExecQuery("Select * from Win32_ComputerSystemProduct",,48)

dim fso
dim myc
dim f

set fso = CreateObject("Scripting.FileSystemObject")

myc = fso.getParentFolderName(WScript.ScriptFullName)

set f = fso.OpenTextFile(myc & "\メーカ・機種・製造番号.txt", 8, True)

For Each objItem in colItems
 f.WriteLine("メーカー  :" & objItem.Vendor & vbCrLf)
 f.WriteLine("機種名   :"   & objItem.Name & vbCrLf)
 f.WriteLine("製造番号:" & objItem.IdentifyingNumber)
Next

f.Close
```
MDM を有効的に活用するための４つのポイント

# MDMを有効的に活用する方法
## マスターデータはデータマネージメントの「土台」
マスターデータはDIKWモデルのピラミット構造にも定義されているように、企業全体のデータ構造の全体像の土台として、社内の各業務横断的に共通で使用されるデータとなります。例えば、「取引先マスタ」、「製品マスタ」、「顧客マスタ」など一つの事業部のみで使用するのではなく、事業部横断的に使用するケースが多いのが特徴です。更にマスターデータを構成する要素として、「Reference Data=参照データ」も重要なマスターデータの位置づけです。

![スクリーンショット 2024-12-22 13.15.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3947834/1b59ef63-08f1-7fef-f5d8-d2ebdd8a53d5.png)

マスターデータが汚れていると、日々のトランザクションデータも、更にはその分析データもどんどん汚れていくことに繋がります。そうなると、日々の業務に悪影響をきたしたり、会社として誤った経営判断をすることにも繋がっていきます。それらを避けるために様々な企業は日々「データマネージメント」の施策を行っていますが、その「土台」となるのがマスターデータと言えるわけです。

## マスターデータによくある課題３選
### **その１：データの粒度がバラバラ**
データ活用を行う際にもっとも多くの課題として挙がるのが、データの粒度が揃っていないことのデータ分析軸を揃えることが困難だったり、データが重複していることで集計結果が合わなかったりすることです。
「誰が、いつ、どこで、何を、いくらで買ったのか」を分析するにも、「顧客軸」、「地域軸」、「製品軸」などが揃っていないと正確な分析はできません。加えてデータが重複しているような場合は、間違った集計結果を生んでしまいます。

### **その２：データの精度と鮮度が低い**
例えば、顧客の住所・電話番号・メールアドレスなど、連絡先の精度や鮮度が低いと、正常に取引が行われなかったり、顧客からのクレームに発展するリスクも高まってしまいます。業務上重要なマスターデータについては、常に精度と鮮度が高い状態を維持することが必要となります。

### **その３：マスターデータの所在がバラバラ**
同じ一つの会社であっても、各事業部ごとや業務ごとにシステムが個別最適化されていることで、マスターデータも各システムごとに個別に作られるケースは少なくありません。しかしながら、似て非なるマスターデータを各システムごとに作ってしまうことで、データを横断的に活用していくことや、企業全体最適の観点では非常に使いにくい状態になってしまいます。

## MDMを有効的に活用するために必要なこと
マスターデータ管理の必要性は分かっていても、どのようにしてMDMを有効的に活用していけばよいかが分からないという声もよく聞きます。
## MDMを有効的に活用するための４つのポイント
### ***その１：マスターを整備する「目的」を明確に掲げる***
自社もしくは事業部として「どのような目標を達成したいのか」、「どのような課題を解消したいのか」などを徹底的に議論をおこない「目的」を明確にします。これは直近の目標や課題に限らず、将来を見据えたものでも良いと思います。目的を見失うと、途中で何故マスターデータを整備する必要があるのかと自問自答したくなる場合があります。その時、当初の「目的」に立ち戻って考えることが必要です。ですので、必ず「目的」は明確かつ、誰にでも説明できる状態を作り上げることが必要不可欠です。
### **その２：業務視点で考える**
企業におけるマスターデータの整備は、整備することがゴールではありません。あくまで、業務に対して効果を出すことがゴールになります。企業によっては業務自体が多岐に渡るケースも多く、どの業務に対して、どのような効果をもたらすのかを考えることが重要です。例えば販売業務であれば「売上アップ」や「顧客満足度向上」などもありますし、製造業務であれば「生産性向上」や「品質向上」などもあります。それぞれの業務視点で、抱えている課題やMDMがもたらす効果を考えることが重要となります。
### **その３：MDMを運用するための「体制」づくり**
MDMを継続的な取り組みとして企業に根付かせるためには、継続的な取り組みができるような「体制」が必要です。MDMの整備で得られる効果はIT部門や業務部門だけでなく、経営層にまで広がります。そのため、その効果をより高めて持続させるためにも、「当事者」を横串でまとめた「体制」づくりが必要となります。ある企業では、物理的に「組織」として作っているケースもありますが、それが難しい場合は、一体化して動くバーチャルな「体制」でも問題ないかと思います。
### **その４：マスターデータの「運用マニュアル」の整備**
マスターデータは企業内のデータの「１丁目１番地」といっても過言ではないと思っています。そのため、その時の思いつきや、特定の事業部だけの発言で、都度都度作り変える訳にはいきません。そこで必要になってくるのがマスターデータのルールブック、いわゆる「運用マニュアル」です。部門ごとに言葉の定義や、使用しているシステム、アプリケーションが異なることが多いため、長年運用するためのMDMの「運用マニュアル」を整備することを推奨します。ここでは、「共通言語化のルール」や、「集配信の方法」、「コードの読み替え方法」、「データのオーナー」などをマニュアル化しておきます。そうすることで、新しいメンバーが加わったり、組織が変更されたとしても後任者が「運用マニュアル」に従って、長期的にMDMの維持・運用ができるようになります。
## 最後に
MDMの活用範囲を最初から大きくする必要はありません。「小さく始めて大きく育てる」ことが、MDMを有効的に活用するためには必要なポイントとなります。従って、上述した「目的」や「利用範囲」についても、まずは小さい範囲で十分かと思います。そこで得られた成功体験をもとに、中長期的に「大きく」育てていき、多くの事業部や企業全体に効果をもたらすことが何よりも重要だと思います。
VBS Windowsでファイル一覧を取得する

Windowsでファイルの一覧を取得したい場合のスクリプト
カレントディレクトリのリストを読み取り、テキストファイルに保存します。

```ファイル一覧取得.vbs
'ファイル一覧を取得して、テキストに保存します。

Option Explicit
 
Dim objFileSys
Dim objFolder
Dim objFile
Dim objOutputTextStream
Dim fso

'カレントディレクトリ取得
Set fso= createObject("Scripting.FileSystemObject")

'ファイルシステムを扱うオブジェクトを作成
Set objFileSys = CreateObject("Scripting.FileSystemObject")
 
'ログ出力用 TextStream オブジェクトを作成
'第2引数は 1 ：読み取り、2 ：上書き、3 ：追記。
Set objOutputTextStream = objFileSys.OpenTextFile("ファイル一覧.txt", 2, True)

'フォルダのオブジェクトを取得
Set objFolder = objFileSys.GetFolder(fso.getParentFolderName(WScript.ScriptFullName))

'FolderオブジェクトのFilesプロパティからFileオブジェクトを取得
For Each objFile In objFolder.Files
    'ファイル名を取得し、ログファイルに出力
    objOutputTextStream.WriteLine objFile.Name
Next
 
'TextStream は Close を忘れずに
objOutputTextStream.Close

Set objOutputTextStream = Nothing
Set objFolder  = Nothing
Set objFileSys = Nothing 

```
伝わる技術解説 ~聞き手を迷子にしない~

# はじめに

皆さんは、プレゼンやブログなどで技術解説をすることはありますか？
この記事では、知ってほしいことを聞き手、読み手に理解してもらうための解説の仕方を考えてみます。

「技術解説」でなくてもほとんど共通する部分があると思いますが、あえて今回は技術解説をする場合とします。

# 聞き手を迷子にしないこと

プレゼンやブログで、途中から頭に「？」マークを浮かべてしまう場面に遭遇したことはないでしょうか。専門用語や前提知識、あるいはその人が言いたいことや目的が共有されていないまま話を進めると、聞き手は一度迷子になった後、なかなか軌道修正できません。

技術的な話題を理解するためには、 **始めの段階で“土台”をしっかり固めること** が大切です。本記事では、この“土台”つまり「前提」に時間をかけて丁寧に説明することのメリットと、実際にどのように解説すればよいのかを解説します。


# “前提”の重要性

伝えたい内容に注力してしまうあまりに、前提となる知識をすっ飛ばしてしまうケースは珍しくありません。
一方で、聞き手が「これ、どういう意味だっけ？」と疑問を感じても、その場で質問しづらい雰囲気だったり、ブログ記事ならそのまま読み飛ばしてしまうこともあります。
論理の辻褄が合わないなどの疑問については質問しやすいのですが、話が理解できないとなってしまうとそもそも質問も思い浮かびません。一度理解が止まると、その先の内容は全く頭に入らないということも良くあります。

反対に、しっかり前提を説明することで、聞き手は 「なるほど、なるほど」と納得しながらから次のステップに進むことができます。

結果として、多少本題の内容の時間を短く駆け足で触れたとしても、前提がわかっていれば大枠で理解できるため、聞き手の理解度は格段に上がります。

## 特にプレゼンにおける“前提”の重要性

ブログなど文書での解説の場合、多少前提を端折っても、文章全体での論理に破綻がなく、最低限必要なことが書かれていれば、読む気のある読者であれば、別の資料を探し、時間をかけて読解し、理解に繋げることができます。

一方で、口頭でのプレゼンの場合、聞き手はリアルタイムで情報を受け取ることになります。いくら聞き手に興味があっても、理解ができていないまま、その場で足りない知識を補うために他の資料を探したり、調べ直すことはほぼ不可能です。

さらに、プレゼンでは一度話が進んでしまうと、理解が追いつかない聞き手は簡単に“迷子”になってしまいます。文書であれば「途中で別の資料を先に読む」「あとから読み返す」といった対処が可能ですが、口頭発表中に戻ってもう一度確認する、というのは困難です。

だからこそ、「前提知識を丁寧に共有する」ことは、口頭でのプレゼンにおいて特に重要になります。要所要所で用語や背景を少し時間をかけて説明するだけで、聞き手の理解度が大幅に変わるのです。

このように、口頭でのプレゼンでこそ、前提を飛ばさずに手厚くする必要があります。

結果として、聞き手が迷子になりにくくなり、プレゼンの後半で扱う専門性の高い内容や細かい理論についてもスムーズに理解してもらえるようになります。


# “前提”を丁寧に説明するとはどういうことか

## 聞き手の理解レベルを考え、より広く想定する

プレゼン前や記事を書く前に、想定読者はどの程度の専門知識を持っているのかを確認または推定しましょう。
そして、確認または想定したレベルより **さらに理解度が低めの聞き手を想定** して話すことが重要です。

ブログ記事の場合は、読者対象を明確にする一文を最初に入れるのがおすすめです。

対面のプレゼンなら、質問や表情から反応を見て微調整できます。丁寧に話す準備をしておけば、聞き手が十分理解できてそうであればその場で省略することができます。

## 概念や目的を明確にし、ゴールまでの道筋を示す

解説する技術の属する分野そのものや、解説する技術が目的とすることをしっかりと話しましょう。

その技術が解決しようとする課題を聞き手が知っている、理解しているとは考えられません。何のためにその分野が存在し、どのような課題があって解決されるか、それを最初に伝えておく必要があります。

「何を知ってほしいのか」「どんな成果物を得られるのか」を最初に示し、全体の道筋を聞き手に提示します。そうすることで、聞き手が「今、どこを走っているのか」を把握しながら話を聞けます。

## 話が長くなる場合

解説の内容が濃く、最初の段階では最後のゴールまでの道筋を聞き手に伝えることが困難な場合もあります。
その場合も、暗闇の中を走るのではなく、常に少し先の中間地点を示しながら解説することが大事です。


# 例えば

例として、「Dockerコンテナでパケット処理を行うソフトウェア」(架空の内容です) を解説するとします。
このプレゼンの本質は、今までアプリケーションを扱うことが多かったDockerコンテナでIPやトンネリングといったパケット処理を行うという点を解説することになります。

この場合、丁寧に説明すべき“前提”となるのは次の2点です

* Dockerなどのコンテナ実行環境の存在意義とそのメリット
* 今回コンテナ化しようと思っているパケット処理それ自体

私が聞き手を想定するのであれば、「目的となるパケット処理は理解しているがコンテナについて知らない」「コンテナについては理解しているが、普段パケット処理のようなネットワークプログラミングをしていない」「両方理解は深くないが、何となく雰囲気はわかる」ぐらいの聞き手を想定すると思われます。

裏を返せば、「コンテナのことも知っている、パケット処理も理解している、ただしDocker上ではやったことがない」と言ったようなピンポイントな聞き手だけを想定することはしないということです。

自分が思う以上にそのような聞き手は存在しません。

全体を一度理解した人から見ると、Dockerそのものの説明や、通常のパケット処理の説明を丁寧にすることは時間の無駄のようにも思ってしまいますが、この前提の共有こそがプレゼンの重要度の8割以上を占めます。

この前提さえ理解できれば、実際にどうやったらできるのか、ということは極端に言うと資料に書いてさえあればいいのです。



# まとめ: まずは迷子を出さない解説を目指そう

解説、ひいては理解の核となる「前提」を端折ると、途中で聞き手が追いつけなくなり、最終的に高度な内容まで届かないという問題が起こります。反対に、前提にしっかり時間を使うことで、少し高度な部分はざっくり説明しても理解の土台があるため、聞き手は“なるほど”と納得しやすくなります。

ブログやプレゼンを通して技術を共有したいときこそ、まずは迷子を出さない丁寧な前提共有を意識してみてください。そうすることで、聞き手に「わかりやすかった」「もっと知りたい」というポジティブな感情を持ってもらえるはずです。

今後の技術解説の場面で、ぜひ実践してみてください。
2024年に開催された「メイカー系展示イベント」

この記事は、「[ProtoPedia Advent Calendar 2024](https://qiita.com/advent-calendar/2024/protopedia)」の15日目の記事です。

ProtoPediaの次回でいつも紹介しているが、「あれ？いつだっけ？」となるので、一覧にまとめてみた。
2024年はとてもイベントの多い年だった気がする。

https://protopedia.net/event/111

何を対象とするか…迷ったければ、日本国内で、ProtoPediaに登録してくれるとうれしいなぁと思う作品が展示されているイベントという括りにしてみた。
なので、アートよりなイベントもちょっと含まれてる。
今年は「HOMEWORKS 2024」が最後のイベントかな？


実は2025年もまとめているので、こっちもよろしく。
「この日にこのイベントあるよ」なんて情報あったら、XのProtoPediaアカウント（@ProtoPedianet）に連絡いただければ追加します。

https://protopedia.net/event/113
ghコマンドでGitHub Container RegistryにDockerイメージをプッシュできるようにする

:::note info
3行まとめ
1. `gh auth login -s write:packages` で `write:packages` スコープ付きでログイン
2. `docker login ghcr.io -u <ユーザー名> -p $(gh auth token)` でGHCRにログイン
3. `docker push ghcr.io/<ユーザー名>/<リポジトリ名>:latest` でイメージをプッシュ
:::


本稿ではGitHub CLI (ghコマンド)を使って、GitHub Container Registry (GHCR) にDockerイメージをプッシュする際の設定方法をご紹介します。

`gh`コマンドを使っている人は、もうGitHubのWebページからpersonal access tokenをいちいち取りに行かなくて済むので便利ですよ。

## 背景

GitHub Packagesの一部であるGitHub Container Registry (GHCR) を使うと、GitHub上でコンテナイメージを簡単にホスト・管理できます。

ただし、Dockerでプッシュする際にはトークンにwrite:packagesスコープが必要です。

GitHub CLI (gh) では、リポジトリ操作だけでなく、発行されるトークンのスコープを柔軟に指定できるため、Dockerイメージのプッシュもスムーズに行えます。

## 手順

### 1. すでにログインしている場合はログアウトする

GHCRへのプッシュに必要なトークンスコープを新たに付与したい場合、まず既存の認証状態からログアウトします。

```bash
gh auth logout
```

### 2. write:packages スコープ付きのトークンを取得する

GitHub CLIを使ってログインします。このとき、-s write:packages のオプションを指定することで、パーソナルアクセストークンにwrite:packagesスコープが追加されます。

```bash
gh auth login -s write:packages
```

ログインが完了すると、gh auth tokenコマンドでトークンを取得できます。

```bash
gh auth token
```

このコマンドで表示されたトークンは、GHCRにログインする際やDockerでプッシュする際に使用します。

ちなみに、このトークンは「OAuth Access Token」です。基本的に有効期限がないものになります。

https://qiita.com/suin/items/1ce9e11bd1c203fb1167

### 3. GHCRにログインする

取得したトークンを使ってDockerでGHCRにログインします。
ghcr.io はGitHubのコンテナレジストリのドメインです。

```bash
docker login ghcr.io -u <GitHubユーザー名> -p $(gh auth token)
```

-u にGitHubのユーザー名を指定し、パスワードとして gh auth token の出力を渡します。

### 4. Dockerイメージをビルドしてプッシュする

ログインが完了したら、あとは通常のDockerプッシュと同じ手順です。
以下のようにイメージをビルドし、GHCRにプッシュしてください。

```bash
# イメージをビルド (例: REPO という名前のイメージを作成)
docker build -t ghcr.io/<GitHubユーザー名>/<リポジトリ名>:latest .

# プッシュ
docker push ghcr.io/<GitHubユーザー名>/<リポジトリ名>:latest
```

`<GitHubユーザー名>` と `<リポジトリ名>` の部分は適宜変更してください。

## まとめ

- gh auth logout で一度ログアウトしたうえで gh auth login -s write:packages する。
- gh auth token で取得したトークンを使って docker login ghcr.io。
- あとは通常のDockerイメージのプッシュと同じ手順で docker push ghcr.io/USERNAME/REPO:tag すればOK。

GitHub CLIを活用することで、コマンドラインから一貫してGitHubの各種サービスにアクセスできるのが便利ですね。

これで、GitHub CLIでwrite:packagesスコープを取得し、GHCRにDockerイメージをプッシュする方法の説明は以上です。ご参考になれば幸いです😌
【Web】Cookie とキャッシュの違いについて


# はじめに
こんにちは、アメリカで独学でエンジニアを目指しているものです。本記事では、Cookie とキャッシュの違いについて解説していきたいと思います。

Cookie とキャッシュはいずれも、クライアントとサーバーが通信する際に「**記録を活用して、再度の通信をスムーズにする**」という広義の役割を持ちます。しかし、それぞれの目的や仕組みは大きく異なります。ここでは、それらの特徴や用途を整理し、どのように使い分けるべきかを見ていきましょう。

---

## 1. Cookieとは？

Cookie は、Web ブラウザと Web サーバー間でやり取りされる**小さなデータファイル**です。
主にユーザー情報やセッション状態を保存するために利用されます。

#### Cookieの特徴

- **保存場所**: クライアント側（ブラウザ）
- **サイズ制限**: 通常 1 つの Cookie は 4KB まで
- **利用目的**:
  - ユーザーのログイン状態を保持
  - サイトの設定（言語やテーマなど）を記憶
  - 広告ターゲティングのためのトラッキング
- **有効期限**:
  - セッションCookie: ブラウザを閉じると削除される
  - 永続Cookie: 開発者が指定した有効期限まで保存される

#### Cookieの仕組み

1. ユーザーが Web ページを訪問すると、Webサーバーが Cookie を生成してブラウザに送信します。
2. ブラウザは Cookie を保存し、次回以降に同じ Web サイトへアクセスする際、この Cookie をサーバーへ送信します。


### 2. キャッシュとは？

キャッシュは、Web ページの**静的リソース（HTML、CSS、画像など）**を保存して再利用する仕組みです。
目的は、次回アクセス時の読み込み速度を向上させ、サーバー負荷を軽減することにあります。

#### キャッシュの特徴

- **保存場所**:
  - クライアント側（ブラウザキャッシュ）
  - 中間キャッシュ（CDN やプロキシサーバー）
  - サーバー側（キャッシュサーバー）
- **保存内容**:
  - HTML、CSS、JavaScript、画像、動画などの静的コンテンツ
- **利用目的**:
  - ページの読み込み時間を短縮
  - サーバーへのリクエスト回数を削減
- **有効期限**:
  - Web サーバーがレスポンスヘッダー（Cache-Control など）で管理

#### キャッシュの仕組み

1. ユーザーが Web ページを初めて訪問すると、ブラウザは各リソースをキャッシュに保存します。
2. 次回以降、同じリソースが必要になった際、キャッシュされたリソースが利用されるため、サーバーへのリクエストをスキップしたり削減したりできます。


---

### 3. Cookieとキャッシュの違い

| **項目**        | **Cookie**                           | **キャッシュ**                                     |
| ---------------- | ------------------------------------- | -------------------------------------------------- |
| **目的**        | ユーザー情報やセッション管理           | 静的リソースの再利用                               |
| **保存内容**    | ユーザーID、セッションID、設定情報など | HTML、CSS、画像、動画などの静的コンテンツ           |
| **保存場所**    | クライアント側（ブラウザのCookieストア） | クライアント、プロキシサーバー、キャッシュサーバー |
| **サイズ制限**  | 約4KB（ブラウザや仕様による）          | 基本的に上限はなし（リソースの種類に依存）          |
| **有効期限の管理** | 開発者が Cookie 自体に設定             | サーバー側が HTTP ヘッダーで設定                    |
| **送信頻度**    | 毎回のリクエストでサーバーに送信される   | 必要に応じてサーバーと通信（キャッシュを利用）      |

---

### 4. Cookieとキャッシュの活用方法

#### Cookieの活用例

1. **ログイン状態の保持**
   - ログインしたユーザーのセッションを維持し、再ログインの手間を省いたりできます。

2. **ユーザー設定の記憶**
   - 言語設定やテーマ設定を Cookie に保存し、次回訪問時にすぐ適用します。

3. **トラッキング**
   - 広告配信やアクセス解析のために、ユーザーの行動履歴を保存します。先ほど見ていたサイトのほしいと思っていたものが広告に流れてくるのはトラッキングによるものです。

#### キャッシュの活用例

1. **ページの高速化**
   - 頻繁にアクセスされる静的リソースをブラウザキャッシュに保存し、読み込みを高速化する。

2. **サーバー負荷の軽減**
   - CDN やプロキシサーバーを利用し、キャッシュからリソースを配信してサーバーへのリクエストを削減。

3. **オフライン対応**
   - PWA（Progressive Web App）でキャッシュを活用し、オフラインでも一部機能を利用できるようにする。

---

# まとめ
Cookie はユーザー情報やセッション情報を管理し、キャッシュは静的リソース（HTML、CSS、JavaScript、画像、動画など）の再利用を通じて高速化や負荷軽減を実現する仕組みです。
引き続きWebについても記事を出しますので間違いや補足があればコメントいただけるとありがたいです。
Google Workspace Administrator 学習メモ：その4

# 学習メモ

1. Google Cloud Directory Sync (GDCS)
    - Microsoft Active DirectoryなどのLDAPサーバーのデータ（ユーザー、グループ、連絡先など）を自動的に同期するためのツール
    - 同期元サーバーにインストールして使用する
    - 基本的に同期元LDAPディレクトリとGoogle Workspaceのアカウントは1対1での同期となる
    - 複数の同期元LDAPディレクトリとGoogle Workspaceのアカウントの同期をおこなう際は、「除外ルール」を使用してそれぞれのLDAPディレクトリに存在しないデータが削除されないようにする
        - 例えば、以下の2つのディレクトリが存在する場合、
            - ディレクトリA：ユーザーA、ユーザーB、ユーザーC
            - ディレクトリB：ユーザーA、ユーザーC、ユーザーD
        - 先にディレクトリAをGoogle Workspaceに同期する。このとき、ユーザーA、ユーザーB、ユーザーCが存在する状態となる
        - 次にディレクトリBをGoogle Workspaceに同期する。このとき、ユーザーA、ユーザーC、が存在する状態となる
          ※ディレクトリBのデータで上書きされ、ユーザーBが削除され、ユーザーDが追加される
        - このような状況を「除外ルール」を設定することで回避できる
:::note info
参考
[Google Cloud Directory Sync](https://support.google.com/a/topic/2679497?sjid=3319585546126494874-AP)
:::

1. Password Sync
    - Active Directoryのディレクトリ情報（パスワード）をGoogle Workspaceに同期するツール
    - 同期の仕組みとしてはDirectory APIを使用している

:::note info
参考
[Password Sync の仕組み](https://support.google.com/a/answer/2920764?hl=ja&ref_topic=2611858&sjid=3319585546126494874-AP)
[Directory API の概要](https://developers.google.com/admin-sdk/directory/v1/guides?hl=ja)
:::

1. Data Loss Prevention（DLP）
    - Google ドライブ上のファイルに対して、中身の内容を検査し、自動的にラベル付けする機能
    - 定義したルールに基づいてラベル付けして、機密情報を外部にもらさないようにブロックすることが可能になる
    - ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616519/5b99e53e-59fe-f21b-68f8-e1abd4f9cb9d.png)
:::note info
参考
[DLP で機密情報を保護する](https://support.google.com/a/topic/7556687?hl=ja&ref_topic=7558840&sjid=3319585546126494874-AP)
:::
バックエンドエンジニア1年目が受講してよかったGo講座、AI講座

# イントロダクション
こんにちは。今回はバックエンドエンジニア1年目の私が実際に受講してよかったと感じたGoおよびAI関連の講座についてご紹介します。どちらもUdemyで受講できる講座で、実践的な内容が多く、非常に勉強になりました。

# Go講座
1. [現役シリコンバレーエンジニアの15時間のGo講座 〜 シリコンバレーで流行り出したGoを入門から習得し、応用で次世代Fintechアプリを開発する。Bitcoin以外の株やFXにも使えるシステムトレーディング分析方法を教授](https://www.udemy.com/course/go-fintech/?couponCode=KEEPLEARNING)

この講座はGo言語の基礎から応用までを幅広くカバーしています。特に良かった点は以下の通りです。
- ​詳細な説明​：基礎から始まり、実際に手を動かしながら学べるため、理解が深まりました。また他の講座と比べ並列処理やポインターについても解説してるので書籍ではわからなかった部分も補完できました。標準パッケージのみでAPIを実装し、フロントエンドとの繋ぎ込みまでこれ一本でマスターできます

2.[Working with Microservices in Go (Golang)](https://www.udemy.com/course/working-with-microservices-in-go/)
この講座は、マイクロサービスアーキテクチャに焦点を当てています。
- ​マイクロサービスの実装​：Goを使ってマイクロサービスを構築・管理する方法を学ぶことができました。その他にもgRPCや異なるアプリ間の連携も学べると思います。今後マイクロサービスアーキテクチャは主流になっていくと思うのでやって損はないです

# AI講座
1.[ 米国データサイエンティストが教える統計学超入門講座【Pythonで実践】](https://www.udemy.com/course/python-stats/)
- ​基本概念の理解​：内容はあくまで基本的なことに絞られており、お値段もちょっと気になるかもしれないです。しかし、数学的なこともかなりわかりやすく説明してくれるのでこれだけでAIに必要な基礎的な統計学は完結できてしまうと思います。余談ですが統計検定2級を取得する際にもお世話になりました

2.米国データサイエンティストがやさしく教える機械学習超入門【Pythonで実践】[【前編】](https://www.udemy.com/course/mlpython-1/)[【後編】](https://www.udemy.com/course/mlpython-2/)
- ​応用；統計検定準一級レベルで出題されるような代表的な機械学習について学びました。例として、ロジスティック回帰、PCA、クラスタリング、線形・非線形回帰、正規方程式などです。これらの知識無くしてアンサンブル学習などを理解するのは非常に困難だと思います。ぜひ【本番編！！】を受講まえにやっておくことをおすすめします

3.[【本番編!!】米国データサイエンティストがやさしく教える機械学習超入門【Pythonで実践】](https://www.udemy.com/course/mlpython-3/)
- 実践的な手法：今はディープラーニングなどが主流だと思いますが、一定の条件下においては後輩ブースティング決定木アルゴリズムは使用されると思っています。理論を学ぶだけでなくアルゴリズムをスクラッチ実装していくので知識の習得につながりました。また機械学習では前処理が重要です。この講座では前処理について3時間も割り振られています。ぜひ前処理の部分だけでも受講してみてください

これらの講座を通じて、私は以下のことを学びました。
- ​Go言語の基礎と応用​：サーバーサイド開発に必要なスキルを習得しました
- ​マイクロサービスアーキテクチャ​：スケーラブルなシステムの設計方法を理解しました。また講座においてアプリ構成はクリーンアーキテクチャで作られているのでそこもgoodです
- ​AIの基礎理解​：機械学習の基本概念、代表的な手法を学びました
- ​実践的なアプリケーション開発​：手を動かしながら実装することで、理論だけでなく実践的なスキルが身につきました

# 来年受講したい講座
## フロントエンド
1. [Working with Microservices in Go (Golang)](https://www.udemy.com/course/working-with-microservices-in-go)
- 先輩エンジニアが口揃えておすすめする講座がこれです。React,TyoeScript, micro sercviceについてより深く学ぶことができます。最近ではフロントの実装を見ることも増えてきたのでぜひ受講したいです。

まとめ
これからGoやAIの学習を始めようとしている方には、上述のUdemy講座を強くお勧めします。受講したことで、実務に
直結する知識とスキルを身につけることができました。
ABC385回答メモ

# 0.はじめに
　ABCにクリスマスが冠されるこの頃に参戦。
　Cにてこずりつつ、何とか3問クリアしDに取り組むも、試験終了5分後にACと
　惜しくも間に合わず、3問止まりでした。
　レートは+12と微増でした。


# 1. 	A - Equally
　いい感じの工夫をすればスタイリッシュにかけそうでしたが
　時間優先で思いつくケースすべてを列挙して
　条件文を書きYesとNoに振り分けました。

　https://atcoder.jp/contests/abc385/submissions/60943779


# 2.B - Santa Claus 1
　Bとは思えない複雑な問題・・・
　とはいえ、コーディングが面倒なだけで
　数学的工夫とか競プロテクニックがいるわけではない感じでした。
　
　単純に、指定通りの方角へ移動させていき、壁以外だったら移動
　家だったら、家の場所辞書をみて、登録されていればそのまま
　登録されていなければ、登録しつつ回答用変数に1加算と
　そのまま実装しACとなりました。

　https://atcoder.jp/contests/abc385/submissions/60954976


# 3.C - Illuminate Buildings
　上限3000ということで強引に全パターン行けるかなーとも思いましたが
　まぁ、無駄に時間をロスするだけかなと思い考えて実装。

　【考え方】
　　・ビルの高さ毎に、位置ののソート済みリストを用意
　　・ビルの高さ毎のリストを先頭から見ていき、一番長い等差数列を求め最後に出力

　意外とてこずりましたが、まぁどこかで見たロジックの組み合わせで行けました。

　https://atcoder.jp/contests/abc385/submissions/60970275


# 4.D - Santa Claus 2
　Bと同様、一度通った家はカウントしないという部分がポイントになる感じでした。

　【考え方】
　　列と行ごとに、その行列内の家の場所を持ったソート済リストを整備
　　移動ごとに、移動する行列内の移動範囲内にある家の場所をカウントしリスト化
　　回答項目に家のカウントを加算したあと、家の場所を行列の
　　ソート済みリストから削除する
　　上記を繰り返し、最後にサンタの位置と家のカウントを出力して終了

　方針はすぐ決まりましたが、上手くカウントし、削除するのにてこずり
　いつの間にか、時間を過ぎてました。

　https://atcoder.jp/contests/abc385/submissions/60993322


以上
コミットメッセージはAIに作ってもらおう

# はじめに
プログラミング学習中の[@kat_log](https://twitter.com/kat__log "Twitter")と申します。

コミットメッセージをAI（VSCodeのCopilot）に作成してもらう機能の共有記事です

![image.png](https://soco-st.com/wp-content/themes/socost/upload/11813_color.svg)

# 結論
VSCodeにCopilotをインストールすると１クリックです！

# 設定

1. VSCodeにCopilotをインストールする
    1. 無料で使えるようになったのでぜひ導入しましょう〜🙌
    1. [CopilotをVSCodeにインストール](https://code.visualstudio.com/docs/copilot/overview "GitHub Copilot")
        ![Screenshot 2024-12-22 at 14.25.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1455073/4f05dfec-2be5-eb10-e7b4-79fb53239f9d.png)
1. コミット時に✨️をクリック
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1455073/8bd7793c-1e38-acb8-2c8e-1ee69f6d6da4.png)
    ![Screenshot 2024-12-22 at 14.29.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1455073/f570d0f8-3d85-732e-c81b-707e6df4fa0c.png)
1. AIがコミットメッセージを作ってくれます！
    ![Screenshot 2024-12-22 at 14.31.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1455073/1d0deda8-0de3-4eee-a5b5-baa9a364b3a5.png)
    今回試しにCSSを削除したところ以下のように作成してくれました
    `refactor: remove unused CSS styles from App.css`・・・すごい！
1. 以上です！

# おわりに
お読みいただきありがとうございました。
どなたかの参考になれば嬉しいです！
行処理と並列処理

## 並行処理 (Concurrency)

並行処理は、複数のタスクを同時に進行させる技術。タスクが同時に実行されるわけではない
。システムがそれらのタスクをスイッチしながら処理する。

### 特徴

- **タスクの進行管理**: タスクは実際には一度に1つしか実行されていないが、タスクを切り替えることで、あたかも同時に処理されているかのように見える。
- **リソースの共有**: 複数のタスクがリソースを共有しながら進行する。
- **CPUの時間を分けて使用**: マルチタスクを実現するために、CPUがタスク間を切り替えながら処理を進める。

### 例

- シングルコアプロセッサの上で、複数のタスクが時間を分け合って処理される場合。
- 非同期プログラミング（例えば、I/O待機などでタスクを待機させ、他のタスクを実行する）。

### 利点

- リソースの効率的な利用。
- 複数のタスクが同時に進行するため、全体的な応答性が向上する。

### 使用例

- サーバーが複数のクライアントリクエストを扱う。
- アプリケーションが複数のファイルの読み書きを並行して処理。

---

## 並列処理 (Parallelism)

並列処理は、複数のタスクを同時に実行する技術。これにより、計算を同時に並行して行い、全体の処理速度を高速化する。

### 特徴

- **タスクの同時実行**: 複数のタスクが並列に実行され、計算リソースをフルに活用する。
- **ハードウェアの利用**: マルチコアCPUや複数のCPUを活用し、タスクを物理的に同時に実行する。
- **リソース分割**: 処理を複数のプロセスやスレッドに分け、各プロセッサがそれぞれのタスクを並行して処理する。

### 例

- 複数のCPUコアを使って、複数のデータを同時に処理する場合。
- 大規模なデータ分析やシミュレーションなどで、タスクを複数のスレッドやプロセスに分割して同時実行。

### 利点

- 処理時間を短縮できる（特に計算負荷が高い場合）。
- 複数のリソースを活用することで、パフォーマンスの向上。

### 使用例

- 大規模なデータセットに対して行われるマップリデュース処理。
- 画像処理や科学的計算で、タスクを複数のスレッドやコアに分けて同時に処理。

---

## 並行処理と並列処理の違い

|項目|並行処理 (Concurrency)|並列処理 (Parallelism)|
|---|---|---|
|実行方法|複数のタスクを時間的に切り替えて実行|複数のタスクを物理的に同時に実行|
|使用するリソース|単一のプロセッサ、シングルコアのCPUなど|マルチコアCPU、複数のプロセッサ、GPUなど|
|効率性|リソースを効率よく使う、I/O待機を活用|計算速度が向上、時間短縮を目指す|
|目的|複数のタスクを並行して進行させる|複数のタスクを高速で同時に処理|

---

## まとめ

- **並行処理**は、リソースを効率的に使うためにタスクを時間的にスイッチしながら進行させる方法。
- **並列処理**は、複数のタスクを物理的に同時に実行し、計算負荷の高い処理を高速化する方法。


## 次回への展望
最近マジダル。さっさと切り替えて来年の備えで勉強しないと全然成長できてない。
スケジュールトリガーフローでのコールアウト時のエラー



デバックでは問題ないけど、エラーになりますね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/50c78bcb-4b58-0fbd-0a4c-b8ab22a7c618.png)


:::note alert
Info
エラーが発生しました:

呼び出し可能なアクション JobcanSearch.申請一欄 のコールアウトが失敗しました。フローの再開時や Apex キュー可能内ではコールアウトを実行できません。フローの一時停止や Apex キュー可能のスケジュールを行う前にコールアウトを external service の呼び出し可能なアクションに配置してください。詳細は、Salesforce システム管理者にお問い合わせください。
:::


+ [Guidance on Callout to External Service From Flow](https://trailhead.salesforce.com/trailblazer-community/feed/0D5KX000000n74v0AA)

# 待機要素？

+ [スケジュールトリガーフローに関する考慮事項](https://help.salesforce.com/s/articleView?id=sf.flow_considerations_trigger_schedule.htm&type=5)

>スケジュールトリガーフローは、待機要素を実行した後にのみコールアウトを実行できます。たとえば、待機要素がないと、フローは外部オブジェクトにアクセスできず、コールアウトを実行する Apex アクションを実行したり、外部サービス登録から生成されたアクションを実行したりできません。

ヒントを読んでも具体的な設定方法が分からんなぁ。

:::note
ヒント 
少しの間だけフローを一時停止する待機要素を挿入できます。時間取得元として特定の時間を使用して、指定の時間まで一時停止するように再開イベントを設定します。基準時刻には、$Flow.CurrentDateTime グローバル変数を指定します。次に、オフセットを 0 時間に設定します。通常、次のように設定された待機要素ではフローが 1 分未満に一時停止します。
:::

+ [スケジュールされたフローでの HTTP コールアウト ベータ版](https://trailhead.salesforce.com/trailblazer-community/feed/0D54S00000JgVNVSA3)

+ [フロー要素:待機](https://help.salesforce.com/s/articleView?id=sf.flow_ref_elements_pause.htm&type=5)
  + [フロー要素:一定期間待機](https://help.salesforce.com/s/articleView?id=sf.flow_ref_elements_wait_for_amount_of_time.htm&type=5) 

一定時間だけ待機してからフローインタビューを再開します

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/1da4f7e7-c394-c7d1-7a9f-0a280b26825f.png)

これかな？

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/1cc206ef-e280-02f5-0753-bc6558f56e60.png)

上記の一定時期待機を追加することでエラーはなになりましたが、何故か複数件メールが届きます。

# デバックしてみても、メールは１件しか来ないんだけど

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/8dc16013-45fe-02db-9d20-95c131a15e87.png)

スケジュール起動だと３件同じメールが来ます。

似たような現象？

+ [アクションは複数の電子メールを送信しているようですが、これはレコードの取得要素で取得されたレコードの数に等しいようです (つまり、2 つ取得すると電子メールが 2 倍になり、3 つ取得すると 3 つの電子メールが届きます)。](https://trailhead.salesforce.com/trailblazer-community/feed/0D54S00000FWuBFSA1)

:::note
私がやったことは、戻って開始要素から基準を削除し、オブジェクトを外して、スケジュールだけを入れることでした。  

テストしたところ、メールは以前のように重複しなくなりました。なぜ修正されたのかはわかりませんが、私の場合はうまくいったようです。
:::
グローバルQAチームの日常

今日は、エッセイです。
いくつか、グローバルチームは体験しましたが、そのなかでも比較的最近の事例を
ご紹介します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/156898/3c1b1fe0-35e7-ec6d-5844-5c3ef9a99e00.png)


## 構成
活動の対象の製品は日本人向けでありました。文化・習慣の違いを心配しましたが、製品がシンプルなこともあり、この時に限っては、結局無用の心配となりました。

- 日本： 日本語メイン
- ベトナム： 両方対応可
- インド： 英語メイン

こんな状態で、どうやってコミュニケーションを行っていったかの話です。

## お互いを知る

### LT
週に１回、フリーテーマで自己紹介や、お国のお祭り、食べ物などの紹介をお願いしました。お互いに質問したり、わいわい話すことで、距離が縮まったと思います。


### トレーニング
１か月に２～３回、テスト技法などのトレーニングをしました。また、仕事の割り振りも、それぞれのメンバーの良いところを伸ばすように割り振っていきました。


## 得意分野を明確にする
それぞれの拠点ごとに強みがあり、言語的な問題のほかには、大まかに以下のスキルの違いがありました。

- 日本： マニュアルテスト
- ベトナム： マニュアルテスト
- インド： マニュアルテスト ＆ ＡＰＩテスト ＆ リグレッションツール

### スキル棚卸
スキルのヒートマップを作って、それぞれのスキルを可視化し、課題を明確にしていきました。これによって、チームの強みと弱みが明確になったので、トレーニングの参考にしていきました。

## グローバルチームのメリット

- 英語に対応しやすい
- 比較的安価
- こちらもコミュニケーションの勉強になる

## グローバルチームのデメリット

- 原則、英語は必須
- 管理体制の維持
- 意思の疎通が難しい場合があるのは避けられず、オーダーの仕方に細心の注意は必要

上記の内容から、それぞれの拠点に、パフォーマンスに責任を持つリーダーは必要となるでしょう。

## まとめ
個人的には、きちんとお互いへのリスペクトを表現できれば、身は離れていても、仲の良いチームを作ることは可能であると実感しました。思えばグローバルチームでは何度か働いてきましたが、それぞれスキルの高い人々と仕事できたのは、とても幸運だったと思います。
YouTube (Music) のプレイリスト管理を楽にするウェブアプリを Next.js で作った

# はじめに
こんにちは。[鈴木](https://github.com/suzuki3jp)です。
個人開発で YouTube、YouTube Music のプレイリストの管理を簡単にするウェブアプリケーション **Playlist Manager For YouTube** (https://pmfy.suzuki3.jp) を開発しました。
リポジトリはこちらです。

https://github.com/suzuki3jp/YouTubePlaylistManager

:::note warn
この記事の内容は v1.0.0 時点での情報です。現在のバージョンはサイトのフッターから確認することができます。
:::

# 何ができる？
YouTube, YouTube Music のプレイリストを管理できます。
- プレイリストをコピー
- プレイリストのアイテムをシャッフル
- プレイリスト同士を結合
- プレイリストを削除
- プレイリストのアイテムを検索

![playlistmanager.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984751/a8d155a8-84af-e959-4698-18486cbea9b8.png)
![playlistitemsbrowser.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984751/091d7b68-51c6-23b5-a78a-9a4f5532d7d1.png)


# 開発の背景
## プレイリスト同士をマージしたい
普段から YouTube Music を使っていて、K-POP, 洋楽などジャンル別のプレイリストを作成しています。
それらのジャンルの曲を含んだ "すべて" のようなプレイリストを作成したかったのですが、当時すでに K-POP プレイリストは150曲ほど、洋楽プレイリストは100曲ほど入っていたので手作業で追加するには大変な量でした。
## プレイリストのアイテムをシャッフルしたい
YouTube Music のシャッフル再生はプレイリストから毎回ランダムに曲が選ばれるのではなく、何曲スキップするかを毎回ランダムに決めている（多分）ので "すべて" のようなプレイリストを作成すると、ジャンルそれぞれが固まっているのでランダム再生をしても同じジャンルが続きます。
そのため、真にランダムな再生をするため、プレイリストそもそもをシャッフルするという需要がありました。

# 使用技術
|  |  |
| ---- | ---- |
| Vercel | デプロイ先 Next.jsと相性がいい |
| Next.js | フレームワーク |
| TypeScript | 型最高！ |
| Material UI | コンポーネントライブラリ 今のデザインに満足していないので他のライブラリに乗り換えるかも |
| NextAuth | Google OAuth、永続化が簡単 |
| YouTube Data API v3 | NextAuth で取得したアクセストークンを使用して、APIにリクエスト |

# 工夫したこと
## 認証について
Google 認証周りは NextAuth の GoogleProvider がよしなにやってくれました。
ユーザーの機密情報をサーバーに保存したくなかったので、Cookie に JWT 形式で保存する方法を採用しました。
詳しくは以下の記事で紹介しています。

https://zenn.dev/suzuki3jp/articles/nextauth-approuter-google-20241025

##  Next.js Server Actions はなるべく小さい粒度で作成する
当初プレイリストの コピー・シャッフル・マージ・削除 の操作を行う Server Action をそれぞれ作成していました。
しかしコピーなどは処理完了までに長い時間が予想されるので、進捗を表示するために state を変更するようなイベントハンドラを Server Actions に渡そうと思ったところ、Server Actions はクライアントサイドで定義された関数を渡せないようで、進捗の表示に行き詰まっていました。

そこで Server Actions を プレイリストを作成する・プレイリストにアイテムを追加する・プレイリストアイテムのポジションを変更する のようになるべく小さな粒度で作成します。
そしてそれらを コピー・シャッフル・マージ の固有のロジックを含んだ純粋な関数から呼び、その関数にクライアントサイドで定義したイベントハンドラを渡すことで進捗の表示を実装しました。

## i18n について
今回のアプリケーションでは YouTube Data API を使用しており、Google の OAuth も併せて使用しています。そのため Google の OAuth 関係の審査のために少なくとも英語に対応する必要がありました。
せっかくなので、多言語対応しようと思い、i18n を実装しました。
クライアントサイドとサーバーサイド両方で翻訳を利用できるようにするのに大分詰まりました。
詳しくは以下の記事で紹介しています。

https://zenn.dev/suzuki3jp/articles/nextjs-i18n-20241115

# 課題と展望
## デザイン
当初自分用のツールとして開発をスタートし、localhostで使用することを想定していたため、デザインを凝ることよりも開発速度を優先しました。
そのため、お世辞にもおしゃれとは言えないデザインになっています。
ホストするならもう少しデザインを凝るのも勉強になっていいなと思っています。

## エラーハンドリング
これも当初はlocalhostでの使用を想定したことに関係するのですが、Github にソースコードを公開するだけの場合、非エンジニアが利用することは考えずらかったため、現在は YouTube Data API からエラーコードが変えてきた場合やその他エラーが発生した場合など、エラーコードを表示するのみで処理を中断しています。
これをもう少しユーザーフレンドリーな形にアップデートする必要があると感じています。

## 追加予定の機能
- プレイリストのアイテムを曲名やアーティスト名でソートする
- プレイリストからアーティスト名で曲を抽出する
- プレイリストから手選択でアイテムを抽出する
- 操作で出力されるプレイリストを指定可能にする
  - 現在は毎回新しいプレイリストを作成している
  - これを指定可能にすることで API quota の節約にもなる
  - ユースケースによってはより便利になる

# さいごに
今後も継続してメンテナンスを続けていくつもりです。
よければ Github リポジトリにスターをお願いします！

https://github.com/suzuki3jp/YouTubePlaylistManager
Roo-ClineでMCPサーバーを自動設定した話 🚀【exa-mcp-server編】

## はじめに

Roo-Clineの便利な機能の1つに、プロンプト1つでGitHubからMCPサーバーをダウンロードして設定までを自動で行える機能があります。今回は実際にexa-mcp-serverを導入した際の体験を共有したいと思います。

<blockquote class="twitter-tweet" data-media-max-width="800"><p lang="ja" dir="ltr">ExaのMCPサーバーをRoo-clineに入れてみた！<br>＊導入自体もRoo-clineにやって貰いました！<br>---<br>プロンプトは「<a href="https://t.co/qNZvy9DrPr">https://t.co/qNZvy9DrPr</a> のMCPサーバーを導入して」 <a href="https://t.co/gDpksMhr8N">https://t.co/gDpksMhr8N</a> <a href="https://t.co/VATcFhjMo7">pic.twitter.com/VATcFhjMo7</a></p>&mdash; Maki@Sunwood AI Labs. (@hAru_mAki_ch) <a href="https://twitter.com/hAru_mAki_ch/status/1870696839231750267?ref_src=twsrc%5Etfw">December 22, 2024</a></blockquote> 

## 実行環境

- OS: Windows
- Roo-Cline: 最新版
- VSCode: 最新版

## プロンプトと実行結果

### 入力したプロンプト
```plaintext
https://github.com/exa-labs/exa-mcp-server.git のMCPサーバーを導入して
```

### Roo-Clineの応答と実行プロセス

1. まず、Roo-Clineはタスクを分析し、以下のように計画を立てました：
```plaintext
必要なステップ:
- リポジトリのクローン
- 依存関係のインストール
- ビルド
- MCP設定ファイルへの追加
```

2. リポジトリのクローン実行：
```bash
cd C:\Prj\MCP && git clone https://github.com/exa-labs/exa-mcp-server.git
```

3. 依存関係のインストールとビルド：
```bash
cd C:\Prj\MCP\exa-mcp-server && npm install && npm run build
```

4. 設定ファイルの更新：
- MCP設定ファイル（`cline_mcp_settings.json`）の読み取り
- exa-mcp-serverの設定を既存の設定と同じフォーマットで追加
- 変更の保存

## コスト分析

実行にかかったコストの内訳：

- トークン使用量：
  - 初期プロンプト: 20トークン
  - 全体の処理: 1.6kトークン
- キャッシュ使用量：
  - 追加: +44.8kトークン
  - 合計: 58.3kトークン
- API総コスト: $0.2093

## Roo-Clineの優れた点

1. **自動タスク分析**
   - 必要な手順を自動で特定
   - 依存関係の把握と順序付け

2. **エラーハンドリング**
   - 各ステップでの実行確認
   - 問題発生時の適切な対応

3. **設定ファイルの自動管理**
   - 既存設定の読み取り
   - フォーマットに沿った設定追加

## まとめ

たった1行のプロンプトで、Roo-Clineは：
- GitHubからのクローン
- 依存関係のインストール
- ビルドプロセスの実行
- 設定ファイルの更新
を自動で完了させました。

コストは約$0.21と、手動での設定時間を考えると非常に効率的な投資だと言えます。

## Tips

- VSCodeの再起動で新しい設定が反映されます
- 設定ファイルは自動的にバックアップされます
- エラー発生時は自動でロールバックされます

## 参考リンク

- [exa-mcp-server GitHub](https://github.com/exa-labs/exa-mcp-server)
- [Roo-Clineドキュメント](https://github.com/RooVetGit/Roo-Cline)

<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
Reactで作ったアプリをNext.jsで書き換えてわかった、それぞれのパフォーマンス差

## はじめに
ReactとNext.jsの2つのフロントエンド技術を用いて同一内容のアプリを開発し、それらを比較しました。Reactのみを使用したもの（以下「ピュアReact」）とNext.jsを採用したものの両方を対象に、パフォーマンスとSEOの観点から検証を行いました。  
今回の検証は、特に**初学者**や**個人開発者**の方々がアプリ開発を進める際の選択肢として役立つことを目的としています。シンプルなアプリを題材にしているため、同じような規模のプロジェクトを進める際の参考になるはずです。ReactとNext.jsの違いを理解する手助けができれば幸いです。

## 前提 + 概要
２つのアプリの主な違いは下記です。それぞれのアプリのデプロイ先が違うので、少なからずパフォーマンスに影響していることが考えられます。

### ① ピュアReact
- フロント・バックエンド：App Runner
- シンプルなSPA（Single Page Application）

### ② Next.js
- フロントエンド：Vercel + Cloudflare(Proxy)
- バックエンド：App Runner
- Next.jsはデフォルトでページごとにデータ分割される

### 検証に使用したページ
- トップページ(`/`): 簡単な内容を表示するだけのページ
- マイページ(`/mypage`): 
  - トークンをバックエンドに送信して認証
  - ユーザーの過去データを取得して表示

### パフォーマンス計測に使用したツール（共通）
- WebPageTest
https://www.webpagetest.org/
- Lighthouse（下記設定で使用）
  - Throttling：devtools
  - Mode：Navigation
  - Device：Desktop

コードは極力同じにしました。また、今回は複雑なアプリではなく、かなりシンプルな構成で検証を行いました。

## 検証1. Page Performance Metrics
トップページにおけるページパフォーマンスを計測しました。

### ピュアReact（CSR）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3967051/5c2262d9-bef6-f922-bacc-bf02a76a2b42.png)
- **Time to First Byte (TTFB):** 0.79秒  
  サーバーが最初のデータを返すまでの時間を計測したものです。サーバーの応答速度が影響します。
  
- **Largest Contentful Paint (LCP):** 2.84秒  
  ユーザーが見るページ内で、最も大きなコンテンツ（画像やテキスト）が表示されるまでの時間を示します。ユーザー体験に直結する重要な指標です。
  
- **Page Weight:** 639kb


### Next.js（SSG）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3967051/2830df04-25a0-2a99-6560-c3b6580f2963.png)
- **Time to First Byte (TTFB):** 0.26秒  
- **Largest Contentful Paint (LCP):** 0.65秒  
- **Page Weight:** 109kb



**比較結果：パフォーマンスに大きな差が出た**  
Reactはページ全体をデフォルトでインストールするので初速が遅い。一方、Next.jsはページごとにデータ分割されているかつSSGということもあり高速で表示を実現しています。

## 検証2. マイページ内でSEOとパフォーマンスを計測

### ① ピュアReact（CSR）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3967051/a583a1b8-aaf9-196f-d1cf-fc45d8f77635.png)
- **Performance:** 96  
  その他の指標はすべて最高スコア



### ② Next.js（SSR）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3967051/fd9a7ad1-7063-c840-5c19-27867e3ec662.png)
- **Performance:** 95  
  その他の指標はすべて最高スコア

  



SEOは両方とも最高スコア。Next.jsはSEOの高いスコアを期待して導入されるケースが多いと思いますが、予想に反して差がなかったという結果となりました。むしろ、ピュアReactでも十分なスコアが出ることが分かりました。

Googleは現在、**JavaScriptをほぼ完全にレンダリングできる**ため、Lighthouseのスコアが高いのであれば、Google検索エンジンにおいては大きなSEOの問題は発生しない可能性が高いです。また、ピュアReactは**robots.txt**というGoogleのクローラーが適切に巡回・評価するためのファイルをSEO用に設定する必要がありますが、簡単に作成できるので大きなコストとは言えません。Next.jsでは特に設定は不要です。

パフォーマンスにおいても差はありませんでした。最初にダウンロードしてしまえば、後は高速に処理されるというピュアReact(SPA)の特性上、トップページを経由してアクセスされるマイページは高パフォーマンスを発揮しました。

## 結論

### 初期ダウンロードにおいてはNext.jsが非常に高速
デフォルトでページごとにデータ分割され、サーバーサイドでレンダリングされるNext.jsは、初期表示が高速で、UXも高いです。一方、デフォルトで全てのページを読み込んでしまうSPAのピュアReactは、最初の表示に時間がかかります。改善策を講じることでパフォーマンスを向上させることが可能です。

### SEOには差が出なかった
SEO観点での差を知りたくて始めた検証でしたが、予想に反して両者に大きな差はありませんでした。しかし、Google以外の検索エンジンはJavaScriptを完全に読み込めない場合があるため（例：Bingなど）、SSRやSSGが有利であると言えます。また、今回は小規模なアプリで検証しましたが、多数のページを持つ大規模なアプリではSEOに差が出てくる可能性があります。

---

今回使用したアプリ
AI食生活診断（Next.js）
https://www.healthchecker.app/
ソースコード
https://github.com/Kay-pht/Health-Checker-App-NextjsVer
Miroを使ってディスカッションをオンラインで

# はじめに
先日，就職活動の一環でM社のインターンシップに参加してきました．「製造現場をDXで改革しよう（意訳）」という感じで，製品を作る現場にどのようなICT技術を取り入れられるのかをグループでディスカッションするテーマでした．
特徴的なだったのは，インターン全日程を通してオンラインだったことです．本拠地が東京ということで，対面で参加するにはキツイ距離ではあります．しかし，オンラインですべて完結させるというのは，それはそれで不安が残ります．特に，**各々が調べた資料や作成した文章を逐一共有したい**わけですが，どうすればよいのでしょうか．
そんなときに活躍したのが[Miro](https://miro.com/ja/)というツールです．本稿ではディスカッションをオンラインで行うことができる本ツールを軽く紹介する記事になります．

### Miroはこんな人におススメ
* 研究を複数人で行っている人
* 先生や先輩に自分の思考プロセスを共有したい人
* サーベイした文献や資料の関係を視覚的にまとめて残しておきたい人

# Miroとは
Miroとは，ミロ・ジャパン合同会社が提供するイノベーションワークスペースです．一言でいえば，**複数人がオンラインでアクセスできる巨大なホワイトボード**です．通常，企業向けにビジネスプラン（有料）が提供されていますが，個人で少し利用するぐらいでしたら，フリープラン（無料）で事足りると思います．SlackやGoogleアカウントでログインすれば利用でき，Slackのチームメンバーを招待してボードを共有することができます．次章では，実際にMiroを利用する流れを説明します．

# 大体のつかいかた

### ボードを作る
０からホワイトボードを作成してみましょう．まずは上のリンクからMiroの公式ホームページにアクセス→「無料で登録する」をクリック．
![Miro1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3959689/80ba25f0-246f-83cc-42a5-45713e2dcd2f.png)

今回はSlackのアカウントでログインしてみます．
![Miro2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3959689/e2830c91-0a42-2e0e-89d7-757fdcd0f704.png)

Slackのワークスペースを選択してMiroをスタートします．空白のボードを新規作成すると，以下のような画面になります．
![Miro5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3959689/e6507834-a82a-c562-27bf-d8e6a9315a79.png)

これがホワイトボードの画面になります．この上に好きなように文章を書いたり，図表を作成したり，コンテンツ同士を繋いで関係性を視覚的にわかりやすくしたりできます．左のタブから追加したいコンテンツを選べばOK.

:::note info
スクロールで拡大・縮小．クリック＆ドラッグで場所を移動できますが，この状態だとコンテンツを編集できません．左タブのカーソルのアイコンをクリックすることでコンテンツに触れることができます．逆にカーソルがオンになっているときは場所の移動ができません．
:::

### 実際に触ってみる
![Miro8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3959689/3c6b2917-35da-6507-6bcc-31f246aea8c0.png)

イメージはこんな感じ．フレーム単位でプレゼンテーションを行うことも可能です．
![Miro9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3959689/b09cf205-ff9d-2165-d709-5847de94f0a1.png)

コンテンツを作成するときは左タブ中にあらかじめ用意されているテンプレートを利用することもできます．
![Miro6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3959689/284f9a77-6d60-b7e8-0f5d-6828b91ea0d4.png)

結構種類があって使いこなすのは大変．
![Miro7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3959689/31e03f06-71ef-49eb-2d78-afa06884f207.png)

右上の共有から同じワークスペースにいる人を招待したり，ボードのURLを共有することができます．（今回はやらないです）

他にもMiroAIを利用して適切なテンプレートを作成したり，簡易的な画面共有ができたり，その機能は多岐にわたります．

# まとめ
本稿ではMiroというツールについてさわりの部分をご紹介しました．備忘録として日々の研究の成果を残しておきたい人，複数人で使えるホワイトボードが欲しい人など，興味があれば触ってみると面白いかもしれません．
“現行踏襲”リプレイスで炎上しないためには、精度の高いデータが重要である


## 概要
本記事では、10年以上前に開発された既存システムをリプレイスする際に、私自身が直面した「課題」、「課題に対するアクション」、「結果」について紹介します
また、自身のリプレイススキルを証明する一つの材料として執筆しております

:::note warn
本記事は下記のサービスにて公開しております。公開日時：2024年12月15日
複数のプラットフォームで発信することで、多くの方にご覧いただき、少しでも参考になれば幸いです。
- Zenn
- Qiita
- Twitter
- linkedin
- Findy
- Forkwell
- LAPRAS
- 職務経歴書のレジュメ
- etc
:::

## 結論
***10年以上前に開発された古いシステムをリプレイスする際、特に“現行踏襲”要件が盛り込まれている場合は、精度の高いデータが重要です。***

具体的には、下記のようなケースが該当します。
- 旧システムの1つのテーブルに100カラムを超える非正規化されたDB設計群を、リプレース後も引き継ぐ場合
- 旧システムにおける数千～1万行を超える巨大なビジネスロジックや複雑なSQLを、リプレース後も維持する場合

といったケースである。

このような現行踏襲開発するケースでは、開発初期段階で「精度の高いデータ」早期に入手することが重要です。逆に「精度の高いデータ」を確保できないと、不具合多発や納期遅延などのリスクが高まります。

## 結論の背景
### 前提
|項目|詳細|
|:--|:--|
|開発分野|Web|
|概要|10年以上前に開発された業務Webシステムのリプレイス && 新機能開発|
|Webシステムの画面数|100画面以上|
|DBのテーブル数|100テーブル以上|

### 発生した課題
初期ローンチ直前なのに1番大事な機能が未完成であるという課題が発生した。
10年以上前に開発されたリプレイス前のシステムには、ユーザ自身の売上を詳細に確認できる機能が備わっており、新システムでも現行踏襲する要件となっていたが、初期ローンチ直前にも関わらず、この機能群は未完成状態であった。
仮にこの状態を自身の生活に置き換えると、自身の給料明細をWebで確認する際に、そこに記載されている数字がデタラメである状況と同義である。

### 課題が発生した経緯・原因
下記要因が複合的に重なった結果、本課題が発生した。
#### 要因1
現行踏襲機能開発における制約をクリアにできなかった。

主に2つ制約がありました。
1つ目の制約は、現行踏襲機能の実装方針が基本的にリライトするという制約があった。
つまり、10年以上前に開発された旧システムの非正規化されたDB設計を、リプレイス後も継承し、旧システム同様に、アプリ側で複雑なSQL(ORM)とビジネスロジックをリライトする必要があるという制約があった。
本来であれば、DBを正規化したい所ですが、商流や外部システム連携との兼ね合いがあったため、現行踏襲機能のDB正規化は不可能だった。

2つ目の制約は、現行踏襲機能開発に必須である「精度の高いデータ」を共有して貰えないという制約があった。
つまり、現行踏襲機能の実装過程でダミーデータを作成する際は、各実装者が10年以上前の旧ソースコード、旧DDL、旧テーブル定義書を参考に各テーブルのデータ構造を主観的な予想でダミーデータを作成することになります。
旧システムの非正規化されたDB設計は、1つのテーブルのカラム数が多く、場合によっては100カラム超えるテーブルが存在します。
精度の高いデータが無いとモノリス度が高いリライトほど不具合が多発するリスクがある。

精度の高いデータ共有NG理由は、個人情報保護の観点からローンチ直前までNG状態でした。
上位商流企業に対して、データ共有の要請を数回行ったが、本番データには、個人の売上など重要な個人情報が含まれている為、NG状態でした。

#### 要因2
バックエンド力とリライト力が得意な私のリソースが現行踏襲機能開発以外にリソースが持ってかれた。具体的には、新機能開発>結合試験>受入試験対応>追加要望といったところで私のリソースが持ってかれてしまい、現行踏襲機能開発に十分な集中ができなかった。

#### 要因3
上位商流企業に対する交渉が足りなかった。
納品完了が初期リリース+合意のある納品遅れという結果だった。

この納品遅れを改善する為には、開発初期フェーズの段階で、上述べした現行踏襲機能開発に必須である「精度の高いデータ」を死守することが必要条件である。「精度の高いデータ」死守するためにも、私個人もしくはチーム全体で、上位商流企業に対してもっと深い交渉をするべきであったと反省している。
「精度の高いデータ」NG理由が個人情報を懸念しているという理由であることから、例えば、万が一個人情報が流出しても安全であるように、徹底したマスキングを提案するなど、より具体的且つ深い提案を行うべきだった。

### 課題に対するアクションと結果
```
■課題に対するアクション
現行踏襲機能開発に必須である「精度の高いデータ」共有要請を交渉した。

■アクションの結果
- 「精度の高いデータ」を一部共有して貰うことに成功した。
- 以前から提案していてテスト手法である画面比較法が浸透したことで、現行踏襲機能の受入試験が円滑に進行した
```

```
■課題に対するアクション
業務時間外で下記キャッチアップを行った
- リプレイス前の旧ソースコードをソースリーディング
- リプレイス後の他担当者がリライトしたソースコードのソースリーディング

■アクションの結果
実装不備を自ら手を動かして修正完了した
```

```
■課題に対するアクション
PMに対して課題に関する懸念と提案を定期的に実施した。

■アクションの結果
上位商流に対して本課題に対する調整が行われた
Realm databaseがおすすめできなくなった件

# Realmの開発はメンテナンスモードとなり、以後コミュティベースでの開発になるとのこと

いろいろな処理系をサポートし、SQLiteより読み書きが速いRealmをAndroidアプリで使用していました。

mongoDBに買収されてからも積極的な開発が続いていると思っていたのですが、2024年9月にアナウンスがあり、`We announced the deprecation of Atlas Device Sync + Realm SDKs in September 2024`とのことです。

クライアント側とサーバー側のデータを自動で同期してくれる、Device Sync機能が1年後に廃止とのことで、これに依存していたアプリには大ダメージです。

Device Sync機能を取り除いたバージョンの開発が、以後communityブランチで行われることになりました。

## Realm Kotlinの現状

Realm Kotlinも2024年前半までは積極的にバージョンアップしていたのですが、9月になってぴたりととまりました。

https://github.com/realm/realm-kotlin/issues/1852#issuecomment-2456592109

現時点で一番問題なのがKotlin2.1.0に対応していない点。

一つ前のKotlin2.0の場合でも、Realm 2.x + protobufの組み合わせでコンパイル時にstackOverflowErrorが出る致命的な問題があります。これはおそらくKotlin側の問題ですが、おかげでライブラリすべてをkotlin1.9用にとどめておく必要があり頭が痛い。

少なくともコミュニティベースでの開発が軌道に乗らない限り、Realmの利用はお勧めできません。

SQLiteにしとけばよかった...