OmniAICreator/Qiita-1.07M huggingface dataset:
BlobコンテナーのVHDからAzure VM をつくる

こんにちは、駆け出しアーキテクトのやまぱんです。

ストレージ アカウント(Blobコンテナー)にある VHD からAzure VM (仮想マシン)を作ることがあると思います。

そういった人向けにAzure Portal を使った手順を簡単に案内します。


## 前提
Blobコンテナーに VHD がすでにある状態。
今回は **movedVHD1.vhd** からAzure VM を作成します。
![2023-12-19_00h51_46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982508/58a5d017-c611-9dee-e67c-3fdc199239af.png)

# 手順
## マネージドディスクの作成
ディスク → 作成 からマネージドディスクを作成します。
![2023-12-18_23h40_09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982508/93320936-fe90-358b-1788-ed7fa752d989.png)


先ほどのblob コンテナー を選択し、**[参照]** から該当の VHD を選択します。
今回はOSディスクなので以下のように設定します。(環境やソースのディスクの OS や世代 に合わせて変更してください)
もし、OSディスクなのに、**[なし(データディスク)]** を選択されると、作成されたディスクからAzure VM の作成ができません。

![2023-12-19_00h53_19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982508/81d348f0-3f3b-0b77-4724-d24bf494a24f.png)


今回は一分程度で完了！

![2023-12-19_00h57_23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982508/44848cf5-6af0-4f3d-9c5b-dbc00576ad67.png)


## Azure VM の作成
作成したディスクに移動し、対象のディスクからVMの作成を行う。
![2023-12-19_00h58_40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982508/6689111f-b531-80d2-10e8-0d6c4d9a4015.png)

こんな感じでイメージの項目に作成したマネージドディスクが選択されているのを確認し、あとはよしなに環境や要件に合わせてパラメータを設定する。
![2023-12-19_00h59_56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982508/15e937aa-7772-3383-9b16-636c0bfd75dc.png)

今回は
２分程度で完了

無事にAzure VM ができました。
![2023-12-19_01h03_26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982508/3e4f197f-5ae4-fc46-b809-f1d1c087a3a5.png)
DockerfileのENTRYPOINTとCMDの違いは何でしょうか。

Docker では、ENTRYPOINT と CMD が Dockerfile内で使用され、両方ともコンテナー内で実行するコマンドを定義します。 コンテナ起動の際に指定したコマンドがコンテナ内で実行されることになります。

どちらも同じ用途で使われてるようですが、それぞれの違いは何だろうかこちら記事で明確にしようと思います。

## ENTRYPOINT

ENTRYPOINTは、コンテナが起動されるときに実行されるコマンドを指定します。このコマンドは、docker runで--entrypointフラグを使用しない限り、実行時に上書きすることはできません。
ENTRYPOINTのベストな使い方は、イメージにおけるメインコマンドの設定することです。

```dockerfile
# Dockerfile
FROM ubuntu
ENTRYPOINT ["echo", "Hello"]
```
このイメージからコンテナを実行すると、`echo Hello`コマンドが実行されます。
```shell
$ docker build . -t test_image
$ docker run test_image

# Output: 

Hello
```

## CMD

一方、CMDはコンテナのデフォルトのコマンドまたはパラメータを設定します。ENTRYPOINTとは異なり、CMDが定義するコマンドは引数として`docker run`に渡すことで上書きすることができます。

```dockerfile
# Dockerfile
FROM ubuntu
CMD ["echo", "World"]
```

こちらで、CMDしか利用されない場合、CMDが指定したコマンドはデフォルトコマンドとして実行されます。逆に、docker runに引数を渡すなら、このコマンドが上書きされる。

```shell
$ docker build . -t test_image
$ docker run test_image

# Output: 

World

$ docker run test_image echo Universe

# Output: 

Universe
```

ENTRYPOINTとCMDが結合される際に、CMDが指定しているものがENTRYPOINTのコマンドのデフォルト引数となります。

下記の定義はコンテナが起動されると、echo Hello Worldが実行されます。

ENTRYPOINTとCMDの組み合わせ:

```dockerfile
# Dockerfile
FROM ubuntu
ENTRYPOINT ["echo", "Hello"]
CMD ["World"]
```

```shell
$ docker build . -t test_image
$ docker run test_image

# Output: 

Hello World
```
こちらの場面で、このイメージからコンテナを実行し（docker run）、Goodbyeのような引数を指定すると、コマンドはecho Hello Goodbyeになります。

```shell
$ docker build . -t test_image
$ docker run test_image Goodbye

# Output: 

Hello Goodbye
```

## 問題になるのは

ENTRYPOINTとCMDが結合される際に、CMDが指定しているコマンドを独自のコマンドとして実行したいときに、どうすれば良いでしょうか。

例えば、こちらのDockerfileのCMDにコマンドを定義したいですが、docker runを実行すると、ENTRYPOINTが指定しているEchoコマンドの引数になってしまいます。

ENTRYPOINTとCMDの組み合わせ:

```dockerfile
# Dockerfile
FROM ubuntu
ENTRYPOINT ["echo", "Hello"]
CMD ["echo", "World"]
```

コンテナを起動するとき、`echo Hello echo World`コマンドが実行されてしまいます。
```shell
$ docker build . -t test_image
$ docker run test_image

# Output: 

Hello echo World
```

### 対策

CMDが指定するコマンドがENTRYPOINTのコマンドの引数に追加されることになっている前提で、
もし、ENTRYPOINTが指定するコマンドは引数部分を子コマンドのように実行できれば解決できます。

カスタマイズなbashファイルを作成。ENTRYPOINTのコマンドに入れる。

-  entrypoint.sh file
```sh
#!/bin/sh

echo "Hello"

exec "$@" #　何かのコマンドをBashシェルスクリプトの最後で実行したいとき、execを利用する。
```
- Dockerfile
```dockerfile
From ubuntu
COPY . .
RUN chmod +x entrypoint.sh # 実行権限を付与
ENTRYPOINT ["./entrypoint.sh"]
CMD ["echo", "World"]
```

```bash
$ docker build . -t test_image
$ docker run test_image

# Output: 

Hello
World
```
なぜか、こちらの結果が出てくるか調べてみます。

ENTRYPOINTとCMDの結合により、上記にDockerfileでイメージを`docker run`を実行すると、`./entrypoint.sh echo World`のコマンドが実行されます。

そちらのコマンドの引数はentrypoint.shのスクリプト内で読み込める変数はこちら表となります。

```
$0 : entrypoint.sh
$1 : echo
$2 : World
$@ : echo World
```
なので、entrypoint.shのフィアルの最後に実行する`exec "$@"`は`echo World`コマンドとなります。
echo "Hello"とecho "World"と合わせて、"Hello World"の結果を出力しました。

こちらで、Dockerfile内のENTRYPOINTとCMDの違いについて、ある程度理解できたとおもいます。ご質問やご不明な点がございましたら、お気軽にコメントください。
sshで遠隔の端末にコマンドを投げまくる

## あらすじ

- `ssh`で遠隔の端末にコマンドを投げたい事がある
- 対象台数が１台２台の場合もあるが、時には１０台〜２０台が対象である場合しばしばもある
- 手動だとやってられないので一撃でコマンドを投げたい事がある

## `ssh`について

> https://ja.wikipedia.org/wiki/Secure_Shell
> Secure Shell（セキュア シェル、SSH）は、暗号や認証技術を利用して、安全にリモートコンピュータと通信するためのプロトコル。パスワードなどの認証を含むすべてのネットワーク上の通信が暗号化される。

## パスワード（`user/password`を使う場合）

※どちらかというと後述の公開鍵認証を利用した通信の方が良さそうだが備忘メモ的に記載する

```shell
USER="xxx"               # アクセス先のユーザ名
IPADDR="xxx.xxx.xxx.xxx" # アクセス先のIPアドレス
COMMAND="ls && pwd"      # 実行したいコマンド（先は一例）

# コマンドを投げる
# `key_password`ファイルにpasswordを記載しておく
sshpass -v -f ./key_password ssh ${USER}@${IPADDR} bash -c "${COMMAND}"
```

## 公開鍵認証を利用した通信をする場合

事前に公開鍵認証を利用するための設定をしておく
以下の`クライアントPCからリモートサーバーへ公開鍵を転送して登録する`の部分を設定しておく

> [SSH公開鍵認証で接続するまで](https://qiita.com/kazokmr/items/754169cfa996b24fcbf5)

```shell
# 事前にSSH公開鍵通信のための設定をしておく

USER="xxx"                 # アクセス先のユーザ名
IPADDR="xxx.xxx.xxx.xxx"   # アクセス先のIPアドレス
COMMAND="ls && pwd"        # 実行したいコマンド（先は一例）
KEY_FILE_PATH="~/.ssh/xxx" # 鍵ファイルのパス

# コマンドを投げる
ssh -i ${KEY_FILE_PATH} -p ${PORTNO} ${USER}@${IPADDR} bash -c "${COMMAND}"
```


# 参考

https://qiita.com/kazokmr/items/754169cfa996b24fcbf5

https://ja.wikipedia.org/wiki/Secure_Shell
re:Invent2023でJAMに挑んだらぼこぼこにされた話

こんにちは。
Japan AWS Jr. Champion兼アジアクエスト株式会社でクラウドエンジニアをしている宮島です。
この記事はJapan AWS Jr. Champion Advent Calendarの18日の記事です。
先に懺悔しますが、タイトルは誇張表現です。

## AWS JAMとは？
簡単に言えばチームで複数の課題に取り組みにチャレンジし、他のチームと得点を競い合うイベントです。
事前にメンバーを集めて参加することも、その場でソロ参加の人同士で集まって即席チームを組むことも可能です。

オンラインでのイベントもありますが、醍醐味はオフラインで一斉に同じ課題に取り組み、順位が出ることではないかと思います。チーム間で得点を競い合うことは普段の業務やエンジニアリングでは得難い経験です。

## 今回参加したJAM
今回私は初日に行われた、「Generative AI」をテーマにしたJAMに参加しました。

![1000001900.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556386/4c55b3fa-3a6b-89d2-4b9c-aeb861b4b1c4.jpeg)
会場の様子

JAMのような実際に現地で手を動かすようなセッションはGamified Learningといったジャンルに分類されていますが、このジャンルのセッションはあっという間に埋まってしまっており、唯一滑り込めたのがここだった、という感じです。
テーマとしては参加者の多そうな本セッションが空いていた理由としては、会場が初日のマンダレイベイというところでベネチアン（re:Inventの主会場）から遠いから、ということなのかなと思っています。
ともあれ自分は無事参加出来たのでありがたい限りです。

## チーム結成
私はre:Invent初参加でAWS Summit TokyoもJr. Champions表彰で行ったのが初めてでした。
そのため、事前にチームを組んでいくといったことは一切頭にありませんでした。
JAMは一人では参加できません。即席のチームを組むことになります。途方にくれていると、後ろに居た長身の男性が声をかけてくれました。仮にJasonとします。

Jason「Hey! Where are you from?」
ぼく「... ! Japan!! Tokyo!」
Jason「Nice! Lets do this!」

いい人でした。
ありがたいことに他に後ろの二人にも声をかけて、一瞬で即席のチームが完成しました。
私が最もアメリカを感じた瞬間でした。
メンバーはこんな感じです。ちなみに全員仮名です。

Jason: 長身のアメリカ人男性。ベテランっぽい雰囲気
Tasel: 中華系アメリカ人男性。一番声かけてくれた。
Orey: 北欧地域から来たって言ってた。一緒に同じ課題に取り組んだ結果一番迷惑かけた。

ありがたい反面、私はこの後の課題の難易度よりもいかに円滑にコミュニケーションを取るかで頭が一杯でした。
なので以降写真が一枚もありません。（余裕が無いので）

## 戦えるのか？
気になるのは、Jr. Championsが行ってどれくらい戦えるのか？というところかなと思うのですが、結論から言うと表題に記載の通り、全く歯が立ちませんでした。
Cloud9とCodeWhispererを利用して開発を進めていくイベントだったのですが、まずJasonが全員に確認します。

「君たちCodeWhisperer使ったことある？」
「「「ほとんど無い」」」
「俺もだ！！HAHA！！」

終わったと思いました。

ところが、蓋を開けてみると意外と取り組めます。
というのも、CodeWhispererの導入はJAM内で丁寧に案内があるし、なによりCloud9を利用することで環境構築に慌てる必要がありません。
難易度別にLevel 1-3程度まで用意してあり、Level2くらいまでなら初見でもソロで取り組めます。

ちなみに最後に自分が放ったセリフは「Try it myself」でした。
つまり、最終的にコミュニケーションを諦めてソロで課題を達成する方針で進めました。

## 結果順位
計何チーム参加していたのか定かではありませんが、全体で見るとギリ上位半数に入れないくらいでした。
誰も対象の経験の無い状態でこの順位はまあまあ頑張ったんじゃないかと思います。
とはいえ、自分は英語での課題のキャッチアップ、メンバーとのコミュニケーションもコストがかかるため、他三人の足を引っ張ってしまった感覚は否めません。
全体で10-12問くらいあるうちのLevel1 2問、Level2 1問取り組んだところでタイムアップになりました。

## それでもJAMに参加するべき理由
何よりも、今いる組織の外のスキル感やトレンドを感じることが出来ました。
特にJr. Championsに選ばれるまでの自分にとっては自社内のエンジニアが全てだったため、外のエンジニアと接することで得られるものは少なくありませんでした。

オンラインでもJAMに参加することは出来ます。しかし、私は絶対にオフラインでの参加をお勧めします。自分の横で同じ課題に取り組むエンジニアがどういったアプローチをするのか、リアルタイムで見ることのできる機会はさほど多くありません。

今年もAWS Summit Tokyoがあるかと思いますが、これまでグループで参加した人はソロでの参加を検討してみてください。
これまで一度も参加したことが無い人は、是非誰かと一緒にでも構わないので参加してみてください。きっと素敵な経験になると思います。誰もいないという方は、私に声をかけてください。一緒に一位目指しましょう。

## 宣伝
私の企画したCONNPASSイベント、全資格取得者座談会が12月19日(火)に開催されます。

https://asiaquest.connpass.com/event/304520/

登壇者はJAWS-UG ストレージ支部で運営を実施している澤さん、弊社全冠達成者の渡邊さん、司会兼何も知らない役の私、の計三名でお送りします。
【TIPS】データの回転

この記事は、[Elixir Advent Calendar 2023 シリーズ11](https://qiita.com/advent-calendar/2023/elixir) の18日目です

---

【本コラムは、5分で読め、4分で試せます】

[piacere](https://twitter.com/piacere_ex) です、ご覧いただいてありがとございます :bow:

たとえば、

```elixir
%{
  a: [nil, 2.0, 3.0],
  b: [0.9, nil, 3.3]
}
```

というデータを、

```elixir
[
  %{a: nil, b: 0.9}, 
  %{a: 2.0, b: nil}, 
  %{a: 3.0, b: 3.3}
]
```

という感じに回転させたいとき、ありませんか？

そういうシーンで困らないようにTIPSとしてまとめておきました … Elixirの様々な書き方のトレーニングにもなると思います

# リスト内リストを回転

```elixir
[
  [nil, 2.0, 3.0],
  [0.9, nil, 3.3]
]
|> Enum.zip 
|> Enum.map(& Tuple.to_list(&1))
```

```elixir:結果
[
  [nil, 0.9], 
  [2.0, nil], 
  [3.0, 3.3]
]
```

# マップのリスト値をリスト内マップに回転

`then` を挟むことで、入力データを、「マップのリスト値の回転」と「マップキーのzip」の両方に `&1` で渡せるようにしている点がテクニックです

```elixir
%{
  a: [nil, 2.0, 3.0],
  b: [0.9, nil, 3.3]
}
|> then(& 
    Enum.map(
      Map.values(&1) |> Enum.zip, 
      fn row -> Enum.into(List.zip([Map.keys(&1), row]), %{}) end))
```

```elixir:結果
[
  %{a: nil, b: 0.9}, 
  %{a: 2.0, b: nil}, 
  %{a: 3.0, b: 3.3}
]
```

# リスト内マップからマップのリスト値に回転

```elixir
[
  %{a: nil, b: 0.9}, 
  %{a: 2.0, b: nil}, 
  %{a: 3.0, b: 3.3}
]
|> Enum.reduce(%{}, & 
  Enum.reduce(&1, &2, fn {k, v}, acc -> 
    Map.update(acc, k, [v], fn n -> n ++ [v] end) end))
```

```elixir:結果
%{
  a: [nil, 2.0, 3.0],
  b: [0.9, nil, 3.3]
}
```

# Nxテンソルを回転
```elixir
[
  [1, 2, 3],
  [9, 8, 7]
]
|> Nx.tensor
|> Nx.transpose
```

```elixir:結果
#Nx.Tensor<
  s64[3][2]
  EXLA.Backend<host:0, 0.1373024662.28180512.24755>
  [
    [1, 9],
    [2, 8],
    [3, 7]
  ]
>
```
特徴画像のサイズを計算する

畳み込みとプーリングを2回ずつ行った際の、特徴画像の一辺の長さを計算する関数です。

~~~Python
def calc_character_size(image_node, padding, kernel_size, stride):
    
    x = ((image_node + 2*padding - kernel_size) // stride) + 1
    x = x // 2
    x = ((x + 2*padding - kernel_size) // stride) + 1
    x = x // 2

    return int(x)

#MNISTの場合、一辺が28ピクセルの正方形
#padding=0, kernel_size=3, stride=1として計算
character_size = calc_character_size(28, 0, 3, 1)
print(character_size)
#5
#特徴画像の一辺は5ピクセル
~~~

PyTorch以外のライブラリ（KerasとかTensorflowとか）だと、畳み込みで小さくなった画像サイズを自動でpaddingして補完してくれる関数（same関数？）があったりするらしいです。PyTorchにはないみたいで、残念です。
MySQLをアップデートしたらINSERT INTO ... ON DUPLICATE KEY UPDATEでデッドロックした話

この記事は[MySQL Advent Calendar 2023](https://qiita.com/advent-calendar/2023/mysql) 23日目の記事です。

# はじめに

MySQLのバージョンアップをした際に、今までデッドロックが起きなかったクエリでデッドロックが頻発するようになり、調べてみたところ下記のバグ報告（ページはバグ報告のものですがこの挙動自体はバグではなくて意図通りのものと説明されています）を見つけ記載されている回避策を試してみたところデッドロックの解消も出来たので日本語での情報としてだいぶ簡潔ではありますがまとめさせていただきます。

（そのため詳しい情報や正確な情報を知りたい際には下記のリンク先を確認していただければと思います）

https://bugs.mysql.com/bug.php?id=98324

また、英語も得意ではないのとMySQLの実装も理解しているわけではないので間違っていることを書いていたらコメントなどで指摘していただけると助かります :bow:



# デッドロックが起きる例

下記のようにAUTO INCREMENTのPRIMARY KEYとUNIQUE KEYを持つテーブルがあるとします。

```sql
CREATE TABLE `user` (
    `id` int AUTO_INCREMENT,
    `user_id` int,
    `value` int,
    PRIMARY KEY (`id`),
    UNIQUE KEY (`user_id`)
)
```

このテーブルに対して、下記のような`ON DUPLICATE KEY UPDATE`によるクエリや

```sql
INSERT INTO `user` (`user_id`, `value`) VALUES (?, ?), (?, ?) 
ON DUPLICATE KEY UPDATE `value` = VALUES (`value`)
```

下記のような`REPLACE INTO`クエリを実行するとクエリの実行頻度などによってはPKでデッドロックが発生しました。

```sql
REPLACE INTO `user` SET id = NULL, user_id = ?, value = ?;
```

ちなみに、このときにデッドロックが起きる条件として新規INSERTの場合や同じUNIQUE KEYに対して更新しようとしているみたいな条件はなく、

| id | user_id | value |
| :-- | :-- | :-- |
| 1 | 1001 | 1 |
| 2 | 1002 | 2 |
| 3 | 1003 | 3 |
| 4 | 1004 | 4 |

上記のようなレコードが存在する状態で下記のようなクエリを別々のトランザクションから発行された際にもデッドロックが起きる可能性があります。

```sql
-- トランザクション1
INSERT INTO `user` (`user_id`, `value`) VALUES (1001, 10), (1002, 20) 
ON DUPLICATE KEY UPDATE `value` = VALUES (`value`)

-- トランザクション2
INSERT INTO `user` (`user_id`, `value`) VALUES (1003, 30), (1004, 40) 
ON DUPLICATE KEY UPDATE `value` = VALUES (`value`)
```

# 回避策

https://bugs.mysql.com/bug.php?id=98324#c504319

こちらも上記のバグ報告のスレッドに記載されている一部の方法ですが、下記のような方法を試すことで改善する場合があります。
（下記の2つの方法は実際に試してみて改善したところまで確認済みです）

1. `ON DUPLICATE KEY UPDATE`や`REPLACE INTO`をやめて複数クエリでの実行に変更する
    1.1. `ON DUPLICATE KEY UPDATE`の場合は、UNIQUE KEYでSELECTしてみてレコードが見つかればUPDATE, 見つからなければINSRTする
    1.2. `REPLACE INTO`の場合は、UNIQUE KEYでレコードを削除してからINSERTする
1. `id`カラムをドロップしてUNIEQUE KEYをPKに変更する


# なぜデッドロックが起きるのか

（ここから先は自分でもあまり理解できていない&間違っていることを書いているかもしれないのであまり参考にはしないで何となく読んでいただければと思います）

競合するレコードが存在する状態で`INSERT INTO .. ON DUPLICATE KEY UPDATE`クエリを実行した際には、内部実装的には下記のように処理されているらしいです。

1. テーブルにインテンション排他ロックを取る
1. 最初にレコードのINSERTを試みる
    1.1. ここではUNIEUQ KEYが一致するレコードがあったとしても無視してINSERTされる
    1.2. このタイミングでPKに対して挿入意図ロックも取られる
1. INSERTしたレコードのUNIQUE KEYが重複するものがあるのかチェックする
1. 重複したものがあったらINSERTしたレコードを削除する
    4.1. その際に削除したレコードのPKの範囲をロックする
    4.2. そのためPKがsupremum pseudo-recordまでギャップロックされる
1. 競合するレコードに対してUPDATEを実行する

そのため、1トランザクション内で2レコード以上処理するクエリが複数トランザクションで発行されると、タイミングによってはデッドロックが発生するという認識です。

1. 各トランザクションで1レコード目を同時に処理し、その結果PKにsupremum pseudo-recordまでのギャップロックが2つのトランザクションから取られる。
1. 各トランザクションが2レコード目を同時に処理しようとした際に、PKがsupremum pseudo-recordまでギャップロックを取られているので、どちらのトランザクションもPKの挿入意図ロックを取ろうとするが待ちになりデッドロックになる。

# なぜMySQLをアップデートしたら起きるようになったのか

MySQL 5.7.26と8.0.16で下記の修正が入っており、こちらはざっくりいうと多分内部処理の説明をした際の4.1~4.2のPKのギャップロックを取るようにした修正らしいです。

https://github.com/mysql/mysql-server/commit/066b6fdd433aa6673622341f1a2f0a3a20018043

それまではPKのギャップロックを取っていなかったことにより、十分なロックが取られておらず直列化可能性(serializability)が保証出来ていないという重大な問題があったとのことです。
そのため、この挙動はMySQLのバグではなくて意図した挙動とのことです。
2023/12/4にリリースされた『My BizRobo!』とは

就業先では、RPAツールのBizRobo!を使用しています。BizRobo!開発で悩み、BizRobo!ナレッジベースで日々検索しています。

RPAテクノロジーズ株式会社は、2023年12月4日に「My BizRobo!」をリリースしたと発表しました。
既にBizRobo! PORTALやBizRobo! LAND Communityなど様々なBizRobo!ユーザー向けサポートコンテンツがあります。今回新しくリリースされた「My BizRobo!」がどういうコンテンツなのかわからない人も多いでしょう。
今回は、23年12月4日にリリースした「My BizRobo!」がどんなものか調査いたしました。

※時間が経過して変わってしまった箇所や間違っている箇所、不適切な表現があるかもしれませんが、その時は都度修正いたしますので、ご指摘いただけると幸いです。


## My BizRobo!とは
既に様々なBizRobo!ユーザー向けサポートコンテンツがあります。
・[BizRobo! PORTAL](https://rpa-technologies.com/news/information/1779/)（「BizRobo!」関連の情報を一つに纏めたポータルサイト）
・[BizRobo! LAND Community](https://rpa-technologies.com/bizrobo-land-community/)（日本全国BizRobo!開発者様の専用コミュニティサイト）
・[BizRobo!ナレッジベース](https://knowledge.bizrobo.com/hc/ja)（10年間積み重ねてきたBizRobo!に関する豊富なナレッジを検索できるサイト）
・[BizRobo! PORTAL](https://qiita.com/TBO/items/06122d910d44019b1896)（BizRobo!の概要や開発方法、各種アプリの操作、運用管理などを、オンラインで受講できる学習サイト）
上記コンテンツを集約させ、初心者から熟練者まで必要な情報を手軽に利用できる環境を整備することで、利便性を向上させるサイトです。

下記URLをクリックすると、下記ログイン画面がでてきます。
[My BizRobo!](https://my.bizrobo.com/login/)
<img width="75%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2955689/a0c0ac9a-a75e-4ee9-0ef5-ea6a917c67a2.png">

「My BizRobo!」の詳細な画面は、RPAテクノロジーズ株式会社公式HPの下記ニュースをご参考ください。
[BizRobo!ユーザー向けサポートコンテンツを集約し、利便性を向上した「My BizRobo!」を12/4（月）に公開](https://rpa-technologies.com/news/information/9974/)


## BizRobo! PORTALとの違いは何か
正直、始めはBizRobo! PORTALとの違いが判りませんでした。
Qiitaに記載するため、今回のニュースと過去の下記ニュースを見比べました。
[RPAテクノロジーズ、BizRobo!ユーザー向けの新たなポータルサイト「BizRobo! PORTAL」6月25日(火)より提供開始](https://rpa-technologies.com/news/information/1779/)

「My BizRobo!」は様々なコンテンツを統合・集約させています。BizRobo! PORTALも統合対象になっているため、BizRobo! PORTALで閲覧できることは「My BizRobo!」でも閲覧できます。

別々のサイトだったBizRobo!ナレッジベースやBizRobo! eラーニング、BizRobo! LAND Communityを統合しているため、別々のサイトを開く必要がなくなりました。


## BizRobo! LAND Communityはどうなるのか
「My BizRobo!」がリリースされたことで、BizRobo! LAND  Communityは稼働停止になってしまいました。現在、新規投稿およびコメントができないようになっています。
その代わりに、「My BizRobo!」にある『「聞く」トップ』から投稿することができます。

BizRobo! LAND  CommunityはFacebookのようなインターフェースでしたが、「My BizRobo!」はteratailやStack Overflowに近いインターフェースになりました。
私はBizRobo! LAND  Communityのようなインターフェースの方が好きでした。「My BizRobo!」の色合いがオレンジと白の2色しかないため、見にくく感じます。私の目の問題なので関係ないと思いますが、目が疲れるので、個人的にあまり見る気にはなれません。


## 最後に
「My BizRobo!」について解説いたしました。

RPAでわからないことに出くわしたときは、RPAテクノロジーズ株式会社の各サイトをよく使用していますが、「My BizRobo!」内にまとまったことで探しやすくなったかなと思います。
しかし、サイトをみるとちかちかしてしまうため、もう少し何とかならないかなと感じています。

私が過去に書いた下記記事が古くなってしまったので、お気を付けください。
[BizRobo!学習するには～BizRobo e-learingがオススメ～](https://qiita.com/TBO/items/06122d910d44019b1896)
[『BizRobo! LAND Community』を活用してみた](https://qiita.com/TBO/items/d713cbbb3ae864767682)

今回の記事が、RPA開発で悩んでいる人の為になれば幸いです。
JQueryの簡易ローディング

色々小細工しなくたって、これでいいよね。

``` html

  <header class="">
    ナニガシカノナビゲーション
  </header>

  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
  <script>
    $(document).ready(function () {
      $('#form').on('submit', function(e) {
        $('#loading-screen').show();
        $('main').hide();
      });
    });
  </script>
  <div class="text-center py-3" id="loading-screen" style="display: none;">
    <button class="btn btn-primary btn-lg" type="button" disabled>
      <span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>
      登録中
    </button>
  </div>

  <main>
  　　イロイロカキタイコト
   <form action="{{ route('upload') }}" method="POST" enctype="multipart/form-data" id="form">
   @csrf
     <div class="mb-5">
      <div>
        <label for="file" class="form-label">データをアップロード</label>
        <input class="form-control" id="file" type="file" name="file">
      </div>
    </div>
    <div class="text-center">
      <button type="submit" class="btn btn-primary btn-lg" id="submit">アップロード</button>
    </div>
   </form>
  </main>
  
```
未来のボクへの贈り物をシェアします。
Djangoの初心者学習

## 目的
Spring経験者が、Djangoを学習するので、Springとの違いを考えながら、少しづつ学習した内容をまとめる。

### 学習書籍
https://amzn.asia/d/247NZ1Z

### アーキテクチャ
+ Webサーバとアプリケーションの間にWSGIサーバがある。
+ URLディスパッチャ：URLに対して、どのビューを呼び出すかを決める役割を担う。

~~~
本ではControllerに該当するとのことだが、どちらかというとHandlerに該当するように思えた。
読み続けていくと分かるかもしれないので、メモ
~~~

+ ミドルウェア：前処理と後処理を行う。
~~~
ControllerAdviceに似てそうだが、共通的な定義じゃなければ似て非なるもの。
読み進めていけばわかるかもなので、メモ
~~~

+ ビュー：Springのビューと似ているが異なる。Djangoではビューを二つに分けていて、テンプレート(データの見せ方)と「ビュー(データの選び方)」となっている。

### プロジェクト構成
+ プロジェクト：プロジェクト固有のモジュールとアプリケーションを持つ。
+ アプリケーション：固有のモジュールを持つ
Mavenプロジェクトと似てるかなと思ったが、全く違った。
アプリケーションは入れ替え可能なように作成するのが良いとのことなので、親子関係や依存関係のあるjarというよりは、自分たちのサードパーティのライブラリを作ってるようなイメージに近そう。

### URLディスパッチャとURLconf
+ URLconfを読み込んでURLディスパッチャがどのビューを実行するかを決定している。URLconfの書き方は、パスコンバータを使った書き方、正規表現を使ったURLパターンがある。
 
+ エラーハンドリングはURLディスパッチャで行ってくれ、例外系のハンドリングもしてくれる。

+ URLパターンの設定をルートのURL.confのみに追加していくと、ルートのURL.confが肥大化してくので、アプリケーションディレクトリごとに1つずつurls.confを配置するのがベストプラクティス。
NumWorks の MicroPython (その後)

# はじめに

AdventCalendar 2018の記事で[NumWorks の MicroPython](https://qiita.com/inachi/items/40c683f65aede5df7697)をとりあげました。本記事では、その後の変化について書きます。

# ハードウェアのバージョンアップ

私が所持しているハードウェアのバージョンは N0100 ですが、その後に N0110, N0120 と進化しています。違いは MCU の強化、メモリ増強、外部フラッシュによるストレージ増強です。

|    | N0100 | N0110 | N0120 |
|----|-------|-------|-------|
| リリース年 | 2017 | 2019 | 2022 |
| MCU | STM32F412<br>(Cortex-M4) | STM32F730<br>(Cortex-M7) | STM32H725<br>(Cortex-M7) |
| Clock | 100 MHz | 216 MHz | 550 MHz |
| RAM | 256 KB | 256 KB | 564 KB |
| 内蔵フラッシュ | 1 MB | 64 KB | 512 KB |
| 外部フラッシュ |  | 8 MB | 8MB |

# MicroPython のグラフィック強化

当初は、ピクセルとラインぐらいしかサポートされていなかった MicroPython のグラフィック機能ですが、その後 `matplotlib.pyplot` モジュールでグラフを描くのが容易になったり、 `turtle` モジュールでタートルグラフィックができるようになりました。

# オープン路線はやや後退

NumWorks といえば、ハードウェアもソフトウェアも情報公開していることが特徴です。そのため、 [Omega](https://getomega.dev/)のような機能拡張したものや、[ファミコンのエミュレータ](https://zardam.github.io/webnofrendo/)が登場したり、Raspberry Pi Zero を合体させるなど、ユーザやコミュニティによる拡張が行われてきました。

ところが、ソフトウェアのバージョン 16 からフラッシュにロックをかけて、ユーザやコミュニティによるソフトウェア更新をできなくしてしましました。

これに反発したコミュニティは脱獄ツール [Phi](https://phi.getomega.dev/)を開発しました。NumWorks ではその後もロックを強化していて、Phi とイタチゴッコが続いています。

# Omega について

[Omega](https://getomega.dev/)は、NumWorks が公開しているソフトウェアのソースコードを元に、機能拡張やリソース削減を施したものです。

NumWorks からの拡張で、特に特徴的なものは以下でしょう。

* シンボリックコンピューテーション（Symbolic Computation）
* 逆ポーランド計算
* 外部アプリ
* デュアルブート
* Nintendo 3DS で動作するエミュレータ

かつては、MicroPython でのキースキャンも Omega 特徴的な機能でしたが、今では NumWorks でも可能です。

# おわりに

すみません、MicroPython についてはほとんど書いてませんでした。そのうち、 `matplotlib.pyplot` モジュールについて書いてみます。

N0100 だと、リソースの都合で使えない機能も増えてきたので、そろそろ N0120 に買い換えようかなと思いつつ、本記事を終わります。
チーム開発・コーディング初心者がハッカソンに出た話

## はじめに
フロント歴３ヶ月の僕が、技育CAMP名古屋キャラバンでGoに手を出して苦戦した話です。

今回の記事は「事前準備」→「キックオフ当日」→「開発期間」→「ハッカソン当日」の順で書きたいと思います。

大したことは書いてありませんが、初心者の失敗談を赤裸々に語っていますので温かい目で見ていただけるとありがたいです。

## この記事の対象者
* プログラミング初心者
* ハッカソンに参加したいと思ってる人
* チーム開発してみたいと思ってる人
* 失敗談を聞きたい人

## 事前準備
まず事前準備として以下のものを学習しました

* Go言語
* MySQL
* Docker Desktop

友達との参加だったので「Go使ってDB叩ければなんでもいいよね」ぐらいのノリで技術選定しました。この甘い考えが後の僕たちを苦しめることになります、、、

主に、ネットの記事を見ながら学習しました。

## キックオフ当日
約１か月ほど経過して、いよいよキックオフ当日です。

僕たちのチームでは、フロントとバックで分けて開発する方法にしました。
僕はフロントとバックの中継ぎを担当しました。

ここで問題発生。なんとバックエンド担当と学習していたサイトが違いました。

開発環境も大きく違い、僕の浅い知識ではほとんどわかりませんでした。

一気に雲行きが怪しくなりました、、、

## 開発期間

頼りになるチームメイトに環境構築は任せて、自分はせこせこと中継ぎ準備を進めます。

フロントでたたく準備ができたところでバック担当から連絡が。ローカルサーバからたたけるとのこと。

早速エラーが出ました

![スクリーンショット 2023-11-18 075730.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3624662/ea07c99d-8a19-e716-5970-b6489cb9f56c.png)

![スクリーンショット 2023-11-18 075650.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3624662/e02d5fcd-f4f8-2cc4-8fe5-44cf052b2a55.png)

どちらのエラーもリクエストを拒絶するエラーでした。

原因はバック側で生成したトークンがリクエストヘッダーに設定されてないからです。

「じゃあコメントアウトしよっ」

やってしまいました。バック側のトークン認証をコメントアウトしてしまいました。

「なんか動いたわ！」

認証が必要なくなったので動きます。しかしデプロイした環境ではそうはいきません。
幸いバック担当が異変に気付き、デプロイ前にコメントアウトを元に戻してくれていました。

いざ本番環境でたたくと最初のエラーが再び発生します。

そんなこんなであっという間にハッカソン当日になりました。

## ハッカソン当日
当日のことを書くと長くなってしまうので箇条書きにします。

* トークン認証が必要だということを知る
* Cookieを使ってヘッダーを設定する方法を知る
* ヘッダーを設定しても受付ないリクエスト
* なぜかひとつ前のトークンを保存するCookie
* リクエスト送りすぎてサーバサイドから弾かれる(再起動で直った)

などなど今までのツケが回ってきたような量のエラーが降りかかりました。

結局エラーの解決も間に合わず不完全燃焼のままハッカソンは幕を閉じました。

## 反省点

今回の反省点は以下の通りです。

### 連絡はこまめに
どれだけ意識していても億劫になりがちな性格なので、今回のハッカソンで大切さを再認識しました。特に開発期間が短いハッカソンにおいては、積極的に取っていかないと最終調整でとても苦労することがわかりました。

### 自分の力を過信しないこと
僕の場合ですが「大抵のことは何とかなるやろ」の精神で生きています。しかし頭脳労働の場合、それは成立しないことがわかりました。なれないことは、見切り発車せず計画的に行いたいと思います。

### なんかできたで片づけない
今思えばあり得ませんが、チーム開発でなんかできたは絶対にタブーですよね、、、
自分のコードは論理的に説明できるように、しっかりと学習します。本当に反省しています。

技術面の反省は山の様にあるので今後学習してく中で解決していきます。

## あとがき

今回のハッカソンで、多くの失敗を体験して多くのことを学べました。この経験を糧に次の挑戦につなげたいと思います。

初心者の失敗談を最後まで読んでいただきありがとうございます。
【Rails】大量にメール送信してしまった話

# はじめに
以前、とあるシステムの開発でメール一括送信機能を開発する機会がありました。開発終了後本番環境でメール一括送信機能を使ってメール送信されたのですが、なぜが同じ人に対して大量にメール送信されたり、ある人に対してはメール送信されていなかったりしました...今後同じような事態が発生しないように、何が問題だったのか、どう解決したのかまとめていこうと思います。

# 問題点
メール一括送信機能はrailsのdelayed_jobを用いて実装していました。具体的には、「メール一括送信job」の中で全ての対象者全員に対してメール送信する処理を実装していました。

メール一括送信機能を実行すると、実装したdelayed_jobが実行され、一人目二人目とユーザに対してメール送信されるのですが、何らかの理由でn人目のユーザに対してメール送信失敗し、再度delayed_jobがリトライし、また一人目二人目からメール送信が始まりn人目でメール送信失敗し、再度delayed_jobがリトライされるの繰返しが発生していました。

dalayed_jobに関して調査してみると、**delayed_jobの設定ファイルに失敗した時のリトライ数を記載しない場合、デフォルトで25回リトライされる設定になる**ことが分かりました。
すぐさま設定ファイルを確認すると、リトライ数は記載しておらず、**デフォルトの25回リトライされる設定になっていたことが原因**で、同じ人に対して大量にメール送信されていました。

また、**メール送信失敗した時の処理を考慮せずに、「メール一括送信job」の中で全ての対象者全員に対してメール送信する処理を実装していた**ことが原因で、上記で記載したようにメール送信に失敗した場合は、最初のユーザへのメール送信に戻るため失敗したユーザ以降のユーザにメール送信できなくなっていました。

# 解決策1
delayed_jobの設定ファイルに**失敗した時はリトライさせない**ように下記の設定を記載することで、メール送信失敗時に同じ人に対して大量にメールされる事象を解決しました。
~~~ruby:失敗した時はリトライさせない
Delayed::Worker.max_attempts = 0
~~~
しかし、この解決策1のみだと、n人目のユーザにメール送信失敗した場合、n+1人目以降のユーザにメール送信できない事象は解決できません。

# 解決策2
そのため、メール一括送信機能のdelayed_jobの構造を「メール一括送信job」のみの構造から、**「メール送信job」と「対象者分のメール送信jobを作成するjob」の二つを用いる構造**に変更しました。その結果、メール送信に失敗したユーザがいた場合でも、jobの構造上対象者全員にメール送信されるため、失敗したユーザ以降のユーザにメール送信できない事象は発生しないようになりました。

# おわりに
不具合が生じた際に影響が大きい機能に関しては特に失敗した時の動きを想定して処理を作りこむことが大切だと身をもって感じました。今後同じような過ちを繰り返さないようにdelayed_jobの設定や構造は気を付けていきます。

# 参考
https://tech.actindi.net/2015/12/25/3659991970
開発チームをワンチームから分割するときにめちゃくちゃ悩んだ話

去年の12月から今日までに7名のエンジニアが新たにジョインして開発チームはついに13名体制となりました。

開発チームの適切な人数を考える際、「ピザ2枚の法則」が有名です。
ピザ2枚でお腹いっぱいになる以上のメンバーがいると多すぎるという意味です。
ちなみに、ピザ2枚という表現だと人によって人数にばらつきが出そうですが4〜8名くらいらしいです。

開発チームはこの記事を執筆時点で13名ですが、10名を超えたあたりから下記の課題が出てきたのでチーム分割の検討を始めました。

* デイリースクラムでのツッコミコメントが減り、ただ発表する場となり形骸化してきた
* 1on1や目標・評価などマネジメントコストが高くなってきた
* チーム内で密に連携をとる人が限られてきたため、全員が全員の状況を日次で把握する必要がなくなってきた
* システムが成長し、全員がシステム全体を把握するのが難しくなってきた

# チーム分割の検討

チーム分割を検討を始めましたが、タイトルの通りめちゃくちゃ悩みました。
悩みつつ、メンバーとも相談して検討を重ねて最終形に落ち着きました。

なお、開発しているプロダクトはWebプロダクトであり、フロントエンドはReact、バックエンドはRailsで作られており、リポジトリ含めて疎結合になっています。

## 案1 職能チーム

チームを分割する際、私が必ず守ろうと考えていた法則があります。
それが「コンウェイの法則」です。

コンウェイの法則に従うと、現状システムはフロントエンド / バックエンドで綺麗に分割できているので、そこで分けるのが良さそうです。
実際に1チームのときから内部的にはバックエンドを主に担当するメンバーとフロントエンドを主に担当するメンバーで暗に分かれていました。

ただし、この体制の場合は1つのチーム内で機能開発が完結しないという課題があります。

ほとんどの場合、機能開発をするとバックエンドとフロントエンド両方の対応が必要になります。
そのため、バックエンドとフロントエンドでチームを分けた場合、チーム間での密なコミュニケーションが必要になることを意味します。

チームを分けるときに達成したいことの一つとして「チーム間の適切なサイロ化」があります。
高頻度で連携が必要になる場合、チーム分割するメリットが薄れてしまいます。

そこで次の案を考えました。

## 案2 職能横断チーム

職能横断チームとは各チームにフロントエンドとバックエンドの役割を持ったメンバーを混在させたチームのことです。

チーム内に全ての職能が揃っているので、機能開発をチーム内のメンバーだけで完結させることができるようになり、チーム間の密な連携は減りますが、一方で2つのチームで同じシステムを触ることになります。
2つのチームで1つのシステムを触る場合、チーム間でコンフリクトしたり、共通部分のオーナーシップが不在になるなどの懸念ありました。
コンウェイの法則好きエンジニアの私としては1つのシステムを**無策で**触る状態を許容することはできないので、この案は不採用にしました。

## 案3 システムのドメインで分割

案2に似ているのですが、案2の場合はドメイン考慮せずに均等に分けたのに対して、案3ではプロダクトのドメインを考慮して分割を試みました。

ドメインで分ける場合、ドメインに対する開発がどれくらいあるか？によってチームの開発量が変わります。そのため、活発に開発されるドメインで分ける必要があります。

幸い、来期のロードマップを加味すると明確な注力領域が1つ見つかりました。
また、そのドメインは高い専門性が要求されることもわかりました。

そこでみんな大好き(?)チームトポロジーを参考に、この注力＆専門性が高いドメインを「コンプリケイテッド・サブシステムチーム」として切り出すことにしました。

チーム1: 専門性が高いドメインを担当(コンプリケイテッド・サブシステムチーム)
チーム2: 上記以外のドメインを担当

この案でも2つのチームで1つのシステムを触ることになるのですが、ドメインが明確に分かれていることでコンフリクトの懸念はかなり抑えられると判断しました。
また、しばらくこの体制で開発を進めてドメイン分割の妥当性が見えてきた段階で、システム自体の分割もありだと考えています(逆コンウェイ戦略)。

# まとめ

チームトポロジーの受け売りですが、プロダクトやサービスの成長に合わせてチームの最適な形も変わっていくものです。
今回のチーム分割はただの通過点です。
今後、まだまだプロダクトも開発チームも成長させていくので、常に最適な形を模索し続けて、そのときそのときにあった形に変化させていきたいと思います。
Z世代取扱説明書

# はじめに
久しぶりにアドベントカレンダーを書いていこうと思いましたがすでに、遅刻してしまいました…16日目担当です。

https://qiita.com/advent-calendar/2023/udontech

何描こうかなと思ったのですが、社会人2年目から見た世の中のお話を偏見を踏まえてお話しできればと思います。あくまで個人的な意見が多いので、聞き流す感じで見ていただけると幸いです。

# 軽く自己紹介
現在、社会人2年目のエンジニアで香川県出身かつ、いつか香川に戻って働きたいと考えている人です。2023年は、The本厄というような1年でした...というのも、今年の10月にiPhone11→iPhone15に買い換えたのですが、買い替え理由が、iPhone11を洗濯機に入れてしまうという失態...メルカリに出す予定だったのに...というようなことが立て続けに起こり散々な1年でした。
来年は、コロナも開けたことから正月にイギリスへ旅行に行く予定です！2024年は、後厄ですが気を引き締めて生活したいです...と軽く自己紹介でした。

# なぜこのお題なのか？
最近、Z世代という言葉に対して向けられるのは「主体性がない」や「無気力」などマイナスなイメージが多いように感じたからです。反対に、バブル期を経験した世代からすると変わった世代なのだろうと感じます。このギャップはどこから来ているのかについて考えたくなり、書き起こそうとおもいました。

# Z世代は不運なのか？
私が生まれたのは2000年ぐらい、世間はバブルが崩壊して失われた30年の片足をつけた頃です。物心ついた時に初めて使った電子機器は、iPod touch。もうすでに世の中にはYouTubeやTwitter、Instagramなど現代では欠かせないアプリケーションが出回ってる時代でした。その当時から世の中は不況だと思う日々で、リーマンショックによる年越し派遣村や東日本大震災による原発事故、少子高齢化など暗いニュースが多かったように思います。
言い換えると、日本が元気だった頃を知らないから上の世代の「あの頃はよかった」という言葉がよく分からない。バイトをすれば、最低限度の生活は保証され生きていくことに不自由はしない。人一人が頑張ったとしても景気が良くなるわけでもない。という澱んだ空気感がずっと漂っている環境で成長してきました。
一方で、この世代に生きていて良かったと思うことも多々あります。個人的には、暇つぶしには困らないことと案外自由に生きられることが大きいですね。
まず「暇つぶしに困らない」とは、YoutubeやInstagramなどの溢れんばかりのコンテンツの数々、全国各地で開催されるイベントやライブなど公共交通機関が充実しているおかげで気楽に各地へ行けることです。また「案外自由に生きられる」は、本気で嫌になれば転職したり起業したりなど行動がしやすい環境になってきていることが挙げられると思います。
と言うように個人的にZ世代は、不況というトンネルに長く入っている分、世の中に対して大した期待もしていない一方、自由な生き方をしている人が多いことが特徴と言えるでしょう。
# 上の世代に望むこと
ここまでZ世代の特徴について語ってきましたが、個人的に上の世代の人に何を期待しているかを言及したいと思います。
それは、ワクワク感かな？と思います。特に年功序列という枠組みの中にいると、「安定」という環境にいるとどうしても「このままでいいのかな？」など漠然とした不安に駆られることがあります。その時に、ワクワクするような仕事があると時間を忘れて邁進できると思います。これは仕事をただ単に振ればいいと言う話ではなく、上司が楽しそうに夢物語を語っていることが非常に重要だと思います。個人的に、Z世代は不安に駆られることが多いため、なるべく根拠のない自信をもっている上司の方がいいように感じます。

# さいごに
これまでZ世代に関して語ってきましたがこれはあくまで個人的な偏見が散りばめられた文章です。意味もなければ、参考にもして欲しくないぐらいです。個人的な視点からはこんな感じが取扱説明書かな？と思いますので壊れない程度にZ世代を使っていただけるとありがたいです。以上社会人２年目エンジニアからでした。
SingularityのWSL2への構築

SingularityコンテナをWSL2上に構築しました。構築環境はSingularityの公式サイトの記述に基づき、Ubuntu 22.04上とします。
参考となるドキュメントは https://docs.sylabs.io/guides/latest/admin-guide/installation.html#installation-on-windows-or-mac に存在します。このドキュメントに従えば、Singularity 4.0.0がインストールされます。

手順としては以下の通りになります。
```bash
wget https://github.com/sylabs/singularity/releases/download/v4.0.0/singularity-ce_4.0.0-jammy_amd64.deb
sudo apt install ./singularity-ce_4.0.0-jammy_amd64.deb
```

まず、Singularity 4.0.0のUbuntu 22.04用のdebファイルを取得します。しかる後に、debファイルをaptコマンドでインストールします。当方で実行したときにはいくつか気になるメッセージが出力されていましたがインストール自体は行われているようです。以下のメッセージの表示理由等は未解明です。

N: Download is performed unsandboxed as root as file '/home/gorn/singularity-ce_4.0.0-jammy_amd64.deb' couldn't be accessed by user '_apt'. - pkgAcquire::Run (13: Permission denied)

さて、Singularityがインストールできたので確認してみます。

以下のファイルをex001.defとして作成します。

```singularity
Bootstrap: docker
From: ubuntu:22.04

%post
    apt-get -y update
    apt-get -y upgrade

%runscript
    echo "Hello, Ubuntu"
```

以下のコマンドでビルドします。
```bash
singularity build ubuntu.sif ex001.def
```

Ubuntu 22.04のイメージとなります。

Shellでコンテナの中に入ってみます。

```bash
singularity shell ubuntu.sif
```

とりあえず、動きは確認できました。
C#の始め方🔰

## はじめに
[Progaku Advent Calendar 2023](https://qiita.com/advent-calendar/2023/progaku) 18日目を担当する@inakuuunです。
C#歴約2年半ですが、C#のロードマップ的なものが少ないように感じます。今回は自分なりにC#入門ロードマップなるものを作ってみました。
※全て無料の教材で構成しています。

#### 対象者
- C#学習してみたいけど、そもそもどう学習すれば良いかわからない。。
- 現場でC#を使うんだけど、何から学べば良い？？

## C#とは？？
- C#について詳しく書かれている記事があったので以下の記事を参照ください

https://x-hours.com/articles/2144

## C#ロードマップ
#### 1.paizaラーニングを使ってC#の基本文法を学び、概要を理解する
Paizaは無料でプログラミングを学べる学習サイト。
- 会員登録は以下の公式サイトから

https://paiza.jp/sign_up/services

- C#体験編
  - 身に着けられること
    「Hello World」のように任意の文字列を標準出力に出力するところから、「プログラミングにおいてよくあるミス」「コメント」「四則演算」「変数」「標準入力」「標準出力」「条件分岐」「比較演算子」「ループ処理」などを理解し、paizaランクD相当の問題に挑戦できるようになる
  - 対象者
    どのプログラミング言語を学習すべきかお悩みの方、別のプログラミング言語を学習済みで新たにC#について触れてみたい方、paizaスキルチェックやレベルアップ問題集にチャレンジしたい方など

https://paiza.jp/works/cs/trial

学習の入り口としては打ってつけだと思います。

#### 2.Visual Studioの環境構築をして、Paizaの内容をVisual Studioで解いてみる
仕事でC#の開発を行う時に、ほとんどVisual StudioというIDE(統合開発環境)を使うかと思います。実践に近い環境で早めに触っておくと良いかもです。
- Visual Studioとは。。
C#のデバッグ機能やビルド、パッケージのインストールなど開発における便利な機能が標準で備わっています。VSCodeとは別なので気を付けてください。現状はC#を開発する上で良く使われている開発環境という認識で大丈夫です

https://learn.microsoft.com/ja-jp/visualstudio/get-started/visual-studio-ide?view=vs-2022

Paizaのチャプター5、6ぐらいまで完了したら、Visual Studioの環境構築をしてPaizaの問題をVisual Studio上で解くといった方針でも良いかなと思います。
- C#環境構築

https://qiita.com/grinpeaceman/items/b5a6082f94c9e4891613

https://learn.microsoft.com/ja-jp/visualstudio/get-started/csharp/tutorial-console?view=vs-2022

#### 3.Visual Studio のキーボード ショートカットを知る

https://learn.microsoft.com/ja-jp/visualstudio/ide/default-keyboard-shortcuts-in-visual-studio?view=vs-2022

- 個人的に良く使うが割とマイナーなショートカットキー
  - [F12] => 定義へ移動(関数やプロパティの呼び出し元に移動)
  - [Ctrl + -] => 後ろに移動する(ファイルをまたぐため定義へ移動して、元の場所に戻りたい時とかによく使う)
  - [Ctrl + Shift + -] => 次に移動する
  - [Shift + F12] => すべての参照の検索(関数やプロパティの参照先を全て表示)
  - [Ctrl + R + R] => 参照している箇所を置換(コメントは含めない)

#### 現場で使うような技術を学ぶ
内容を見た感じだと、配列、アクセス修飾子、継承や抽象クラス、インタフェースなど開発現場で一生使う内容だったので、とても良い教材だと思いました。

- 業務で使うような汎用的な知識を叩き込む

https://csharp.sevendays-study.com/index.html

- 業務で使うような汎用的な知識のテンプレート

https://www.tohoho-web.com/ex/c-sharp.html

#### 深く学びたい方向け
- .NETについて知る
C#は.NETというプラットフォーム上で動くため、いずれ学ぶことにはなると思います。

https://learn.microsoft.com/ja-jp/dotnet/core/introduction

#### お世話になっているC#に関するドキュメント

https://learn.microsoft.com/ja-jp/dotnet/csharp/

## さいごに
約2年半C#を使った現場で仕事をしていますが、Microsoft社が作った言語ということもあって情報は多いです。そして、.NETには色んなプラットフォームやフレームワークがあり、ドキュメントにはC#だけじゃなくC++やVisual Basicなど色んな言語が混在しているため、特定の情報を見つけづらいという問題があるのも事実です。
なので今回は、C#を学び続ける土台を作るというのをテーマに記事を書かせていただきました。この記事をご覧になられた方が良いC#人生を歩めることを心から願っています。
この記事が良ければいいねなどをしていただけるととても励みになります。
MisskeyでAiScript Appを作るならページを使いこなそう。

:::note warn
もし、前の記事を見ていない場合はこちらを確認した方がわかりやすいかもしれません。
:::
https://qiita.com/the_quick_fox/items/17d03f2bfc5a56cf73f9

# 主張
今回の主張は「**外部の情報を参照するPlayやAiScript Appを作るのならば、ページ機能を活用すると良い**」といった内容のものです。
今回のポイントは**外部の情報を参照する**という点です。
これは外部との情報をページを通して取得するという試みです。

# 用語整理
## AiScript App
ウェジェットの一種です。

https://misskey-hub.net/docs/features/widgets.html

## ページ
Misskeyの機能の一つです。

https://misskey-hub.net/docs/features/pages.html

## 前提確認
一般的には一度公開したAiScript App用のソースコードは、他人の手に渡ると書き換えができません。また、データの更新のたびにユーザーにソースコードの更新をお願いするのもあまり親切ではありません。そうすると、**データの更新をソースコードの変更で達成するべきではない**ことがわかります。そこで、データをソースコードに書き込まずに、ソースコードの外に置くことを考えます。
また、外部のサービスのデータを取り込む場合にもデータをページに置くことで、ソースコードを書き換えずに変更を反映することができます。

その上にあげた二つの目標

* ソースコードを変更せずにデータの更新を反映する
* 外部のデータを利用する

を達成する構成を考えていきます。

## 構成
![図形.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3574887/1b87919d-3561-8629-dbdf-425750dac4f2.png)

### botの役割
botは主になんらかのデータを受け取り、その結果をMisskeyのページに反映させる機能を持つものとします。その上でbotはこのような流れで動作するでしょう。

0. ソースとなるサーバーにリクエストを飛ばす
0. レスポンスを受け取る
0. レスポンスで得たデータを整形する
0. 整形したデータをページのコンテントに埋め込み、`"pages/update"`を使ってページに反映させる

# 例
具体的な例として、今回はMYCOEに追加された音声直近15件を表示するようなAiScript Appのウェジェットを作成することを考えます。

botはMYCOEのページにアクセスして、配布リストから最近取得された音声を取得します。そして、そのデータを扱いやすい形式(JSONなど)にしてMisskeyのページのコンテントとして埋め込み、ページを更新します。これで情報の更新は完了です。
AiScript Appはページにアクセスして、コンテンツに含まれたJSON形式などのデータを取得します。そしてそれを使って、それぞれ振る舞いを変えます。
スマートホームの革新とゲーミフィケーション

スマートホーム技術は日常生活に革命をもたらしました。自動化された照明、温度調節、さらには音声で制御される家電など、私たちの住まいはかつてないほど便利で快適なものになっています。

しかし、このような技術的進歩にも関わらず、家庭内の日常作業は依然として退屈で単調なものが多いという現状があります。

ここで注目されるのが「ゲーミフィケーション」です。ゲームの要素を非ゲームの文脈に取り入れるこの手法は、単純な作業も楽しい体験へと変える力を持っています。

- エネルギーの節約を家族みんなで競うゲーム
- 健康管理を促進するフィットネスチャレンジ
- 子供の学習活動に報酬を設けるシステム

など、ゲーミフィケーションは家庭のあり方を変え、日常をもっと楽しいものにする可能性を秘めています。

# 家庭活動の変革
スマートホームのゲーミフィケーションは、家庭内のさまざまな活動を変革します。

例えば、エネルギー使用量を可視化し、家族間での節約競争を促進するシステムは、環境保護意識を高めると同時に、節約行動を楽しいものに変えることができます。

政府が省エネチャレンジを推進している国々も存在します。国民の意識を高めてホームからグローバルへ省エネチャレンジを展開しようとしています。

### アメリカ

アメリカでは、政府や民間企業が共同で、省エネチャレンジを実施する取り組みを行っています。例えば、アメリカ環境保護庁（EPA）は、2030年までに米国全体のエネルギー消費量を2005年比で30%削減するという目標を掲げており、そのための取り組みの一つとして、省エネチャレンジを推進しています。

EPAが実施している省エネチャレンジは、主に家庭向けの取り組みです。参加者は、省エネに取り組んだことで得られた節電量をEPAに報告することで、ポイントや景品などの特典を獲得することができます。

### イギリス

イギリスでは、政府が「エネルギー効率化目標（Energy Efficiency Strategy）」を策定し、省エネの推進に取り組んでいます。この目標の一環として、政府は、家庭向けの省エネチャレンジを実施しています。

イギリス政府が実施している省エネチャレンジは、主に、照明の省エネ化や、家電製品の省エネモードの活用など、比較的簡単に実践できる取り組みを対象にしています。参加者は、省エネに取り組んだことで得られた節電量を政府に報告することで、ポイントや景品などの特典を獲得することができます。

### 中国

中国では、政府が「エネルギー消費総量制約と脱炭素」を掲げ、省エネの推進に取り組んでいます。この目標の一環として、政府は、家庭向けの省エネチャレンジを実施しています。

中国政府が実施している省エネチャレンジは、主に、照明の省エネ化や、エアコンの設定温度の適正化など、家庭で簡単に実践できる取り組みを対象にしています。参加者は、省エネに取り組んだことで得られた節電量を政府に報告することで、ポイントや景品などの特典を獲得することができます。

## 健康管理の面（MyFitnessPal）

MyFitnessPalは、食事や運動の記録、栄養価の計算ができるアプリです。世界中で1億人以上が利用しており、健康管理アプリの代表格として知られています。

MyFitnessPalでは、以下のゲーミフィケーションの要素が活用されています。

#### 目標や達成感の提供
MyFitnessPalでは、ユーザーが健康に関する目標を設定することができます。目標を達成することで、達成感やモチベーションを高めることができます。

例えば、体重を減らすことを目標に設定した場合、目標体重を達成すると、バッジやトロフィーなどの報酬を獲得することができます。

#### ゲームやクイズなどの要素
MyFitnessPalでは、ゲームやクイズなどの要素を取り入れることで、健康管理を楽しみながら続けられるように工夫されています。

例えば、食事や運動の記録をゲーム感覚で行うことができる機能や、健康に関するクイズで知識を身につけることができる機能などが提供されています。

#### ソーシャルメディアとの連携
MyFitnessPalでは、ソーシャルメディアと連携することで、他のユーザーと競争したり、励まし合ったりしながら健康管理を継続できるようになります。

例えば、他のユーザーと目標を共有したり、運動の成果をシェアしたりできる機能などが提供されています。

これらのゲーミフィケーションの要素により、MyFitnessPalは、ユーザーの健康管理を支援する効果的なツールとして高い評価を得ています。

MyFitnessPalのゲーミフィケーションの要素は、今後もさらに進化していくことが予想されます。例えば、AIや機械学習を活用したゲーミフィケーションの要素の導入が考えられます。AIや機械学習により、ユーザーの行動を分析し、一人ひとりに最適な目標やアドバイスを提供したり、ゲームやクイズなどのコンテンツをよりリアルに体験できるようにしたりすることで、ユーザーの健康管理をさらに効果的にサポートすることが可能になると考えられます。

## 子供たちの学習活動

ゲーミフィケーションを取り入れることで、教育的な側面を強化できます。例えば、数学や科学の問題を解くごとにポイントを獲得し、一定数集めると特定の報酬が得られるようなシステムです。

教育に関しては先の記事で書きましたのでこちらをどうぞ
https://qiita.com/aoinakanishi/items/b37d52dea1da209035dd

# 心理的・教育的な効果

スマートホームのゲーミフィケーションがもたらす最も注目すべき効果の一つは、心理的および教育的な面にあります。ゲームの要素を取り入れることで、家族間の相互作用や学習過程がよりポジティブなものとなり、子供たちの教育にも大きな影響を与える可能性があります。

## 目標達成と成功体験

ゲーミフィケーションを通じて子供たちは目標達成のための自己管理能力や、チームワークの重要性を学びます。

また、家庭内の小さな成功体験は、子供たちの自己肯定感を高め、学習へのモチベーションを向上させることができます。

さらに、ゲーミフィケーションは家庭内のストレスを軽減し、家族間の関係を強化することも可能です。共通の目標に向かって協力することで、家族間の絆が深まり、より健全なコミュニケーションが促進されます。

# スマートホームとゲーミフィケーションの融合
ゲーミフィケーションを通じて、スマートホームは単なるテクノロジーの集合体から、家族全員が共有し、楽しむことのできる活動の場へと進化しています。

家庭内の日常的な作業から、教育や健康管理に至るまで、ゲームの要素を取り入れることによって、これらの活動がもっと魅力的で意味のあるものに変わります。

今後、スマートホーム技術の進化とともに、ゲーミフィケーションはさらに多様な形で家庭生活に取り入れられることでしょう。家族が共に楽しむ新しい活動や、生活を充実させる革新的なアイデアが期待されます。これは、私たちの生活をより楽しく、有意義なものへと変えていく大きな一歩です。
【Next.js】ロード中にエラーが発生した際にエラー画面を表示する方法

## ページを作成する

`page.tsx`を以下のように作成します。

```tsx:page.tsx
async function getData() {
  const res = await fetch('https://api.example.com/...')
 
  if (!res.ok) {
    throw new Error('エラーが発生しました。')
  }
 
  return res.json()
}
 
export default async function Page() {
  const data = await getData()
 
  return <main></main>
}
```

## エラー画面を作成する

`pages.tsx`と同じ階層に`error.tsx`を作成します。

```tsx:error.tsx
'use client'
 
import { useEffect } from 'react'
 
export default function Error({
  error,
  reset,
}: {
  error: Error & { digest?: string }
  reset: () => void
}) {
  useEffect(() => {
    console.error(error)
  }, [error])
 
  return (
    <div>
      <h2>{error.message}</h2>
      <button onClick={() => reset()}>
        Try again
      </button>
    </div>
  )
}
```

上記のように記述すると`page.tsx`の`throw new Error('エラーが発生しました。')`が実行された際に`エラーが発生しました。`というメッセージと再実行するためのボタンが表示されます。


:::note warn
`error.tsx`の`error.message`は本番環境では`An error occurred in the Server Components render. The specific message is omitted in production builds to avoid leaking sensitive details. A digest property is included on this error instance which may provide additional details about the nature of the error.`というメッセージになります。
:::

:::note warn
`error.tsx`と同じ階層に`not-found.tsx`が存在しない場合に`page.tsx`で`notFound()`を実行すると`not-found.tsx`が表示されるのではなく、`error.tsx`の`error.message`に`NEXT_NOT_FOUND`が渡されて表示されます。
:::
個人開発でチャットができるサイトを作ってみた

# はじめに
この記事は[Systemiアドベンドカレンダー](https://qiita.com/advent-calendar/2023/systemi23)19日目です。
ゲーム系の専門学校を卒業しシステムアイに入社後の6月までの研修期間中に学んだことを使って個人開発で作ったものとその振り返りについて書いていきます。

# 作ったものの説明
簡単なチャットができるサイトを作成しました。

![chatroom.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417080/3bf2405a-a3a0-3c2c-4752-6788772c9e5e.png)

画像は発表の際に同期に実際に使ってもらっていた様子です。
この画像には写していませんが、画像やgifが張られていたりhtmlタグが生きていたりなどいろいろと予想外の使い方をしていて面白かったです。


制作期間は5月16日(環境構築開始)～6月30日(発表)でした。

始めての挑戦が多く前半の5月中にしたことのほとんどが無駄になり、発表の日に取りあえず完成したということもありできることは少ないですが、チャットが行え、簡単にですがハンドル名の登録が行えたりという必要最低限はできたと思います。

# 技術スタック
- フロントエンド:TypeScript React
- バックエンド: Java SpringBoot
- DB:Azure cosmosDB for MongoDB
- インフラ:Azure(App Service)

以下でそれぞれについて振り返ってみます。

### 1.フロントエンド
フロントエンドはバックエンドにそこまでの時間がかかる予定ではなくここに時間を使えるだろうと考えていたのですが、見た目にこだわれるほどの時間がなかったのでchatscopeを使用し最低限の見た目を整えたといった形になりました。
Reactの状態遷移には苦戦し、受け取ったデータの持ち方やページ遷移後の処理等いろいろと悩まされました。
それ以外にも、CORSエラーはなぜ出てくるのかが全然わからずに対処に時間がかかりよくわからないまま終わったような気がします。

### 2.バックエンド
バックエンドはSpringBootを使用することで簡潔にコードを書くことができ、コーディングは時間がかからなかったです。
ただ、開発の当初はDBをPostgreSQLにし、buildツールにDockerを使用していたのですが、DockerのbuildがPostgreSQLで躓くようになり、Dockerでのbuildを完全にGitHub Actionを使用したbuildとデプロイに切り替えDBもAzure cosmosDB for MongoDBに切り替えたということもあり、ここで大きなロスになりフロントエンドに影響がでました。

### 3.DB & インフラ
DBは学んだものを使用するということもありpostgressにする予定でしたが、バックエンドでの問題もあり、sqlよりもNoSqlの方がやりやすかったこともあり、Mongoを採用しました。
インフラ周りは研修ではAWSを使用していたのですが、その時によくわからなかったということもありますが、逆張りオタクなのでどうせなら1番ではないものでやりたいと思いAzureを採用しました。

# 振り返り
時間が足りずタイムゾーンのバグの修正ができずに終わったり、画面が簡素な見た目になってしまったことなどの反省点も多いものの、締め切りまでに完成させるための過程で、機能の実現のために考え続けることが楽しく、非常に充実した経験でした。

今はTwitterを真似したサイトを作成中なのですが(XではなくTwitter)、ここでも新しいことに挑戦して楽しんでやっていきたいです。
語源学習の招待

# はじめに
これは「imtakalab Advent Calendar 2023」の 19 日目の記事です🎄

https://adventar.org/calendars/9285

こんにちは！B2 の理系大学生です。
今回は英単語の語源について書いてみたいと思います🎉
（絶対 Qiita で書くような内容ではない・・・）

# なぜ語源？
みなさんは語源と言われるとどのような印象を持たれるでしょうか。

語源といえば某大学受験塾の英単語帳なんかが有名だったりしますが、意識的に取り入れようとした経験がある方はそれほど多くないのではないでしょうか？

語源を知ることは単語を覚えやすくなるという恩恵もありますが、背景に持つ意味を知ることができてとても面白いのです。

そこで、語源を知ることの愉しさを感じてもらうために記事にしてみました。

# e-sport って sport なの？
「e-sport ってやってるのはゲームだし、スポーツっていうのは変じゃない？」と思ったことはありませんか？

最初に紹介するのは sport の語源です。
sport という単語は disport からの変形で生まれました。disport を分解すると、dis（離れる）+ port（運ぶ）です。
そう、もともと sport は **「仕事から離れて足を運ぶ」**、つまり「余暇」の意味だったのです。お手元の辞書で sport を引いてみると「楽しみ」や「娯楽」といった意味も出てくるはずです。ここまでくれば、e-sport という単語もしっくりくるでしょう。

sport の語源はわかったけど、せっかく dis と port の意味も知れたわけなので、同系統の語も見てみましょう。

まずは dis からです。例えば、discover なんてどうでしょう。これはイメージしやすいと思いますが、覆いかぶさっていたもの（cover）を離す（dis）わけですから「発見する」といった意味が出てきます。あとは displace, distribution, discriminate ... などなど挙げたらキリがないほどたくさんあります。

次は port です。例えば、export, import がありますね。export は ex（外に） + port（運ぶ）で「輸出する」、import は im（中に）+ port（運ぶ）で「輸入する」となります。ここで ex や im[in] を語源に持つ単語を調べれば芋づる式ですね。他にも report, transport, airport, support ... などたくさんあります。

# 知を愛する
哲学は英語で philosophy といいます。この語源はギリシャ語の philosophia です。 **philo は「愛する」、shohia は「知識、知恵」の意味** です。

philoshopy を（希）哲学と訳したのは西周（にし あまね）ですが、philosophy の **原義は「知を愛すること」（＝愛智）** を指し、広義的に「知りたいという探求心」を表しています。よって、philosophy は学問全般を表し、学問博士を（Doctor of Philosophy；Ph.D）というのも納得がいくでしょう。

ちなみに、philharmonic は「harmony（ハーモニー）を愛する」から「交響楽団の、音楽愛好の」、philology は「log（言葉）を愛する」から「言語学、文献学」（log についても調べてみると面白いです）、philter は「愛するもの」から「惚れ薬」、philanthropy は「anthrop（人類）を愛する」から「人類愛、博愛」へと拡がっていきます。

ここで紹介したのは一部にすぎません。例えば、アメリカの都市フィラデルフィア（Philadelphia）など philophia を語源に持つ単語は他にもたくさんあります。

# 教養ってなに？
少し教養について考えてから語源の話に移りたいと思います。

教養という言葉を英語では liberal education とか liberal arts といいます。直訳すると、「自由な教育」となるわけですが、ここでの「自由」とは **「自由人を作る」** という意味が込められています。教養教育を受けることによって人が初めて **隷属状態から自由な状態へと変身できる** ということです。

大抵、なにか必要があって勉強しているという人が多いと思いますが、そういった必要性から離れて、必要がないからこそ意義のある学びが教養なのです。

ですから、なにもクイズの問題に多く答えるといったようなことだけが教養ではないのです。

では最後に、liberal の語源の紹介します。
語源はラテン語で「自由な」、「束縛されない」と言う意味の liber からです。先ほどの話とつながりますね。
同系統の語としては、liberate（解放する）、liberation（解放）、liberty（自由）、liberalism（自由主義）、liberalize（自由主義化する）があります。
他には、deliver なんかもそうです。「自由にする」→「手放す」から「配達する」という意味になりました。

# 参考資料
- 『教養の語源英単語』
- 『言葉がひらく哲学の扉』
- 語源英和辞典

# さいごに
いかがでしたでしょうか。

私は語源を知ることは言葉に生命を吹き込むことに等しいと思っています。いままで無機質に暗記したものが、イミを知ると突如として活き活きとしはじめ、いろいろなものが有機的に結びつくのです。私は語源を知ることにこんな嬉しさがあると思います。

記事は以上となります。ありがとうございました～
双方向変換ってなに？

# この記事は Abstract
授業や研究で『双方向変換 : Bidirectional Transformation』を学習する必要に迫られた人類（筆者含む）に向けて、10分弱で読めて具体例と一緒に雰囲気だけでも掴める記事になればと…
説明の正確さは保証できませんが…

# 双方向変換 Bidirectional Transformation : BX
### 概略
双方向変換をかなり簡単化していうなら、『ある情報源から情報の一部をとったり、その情報源を更新する操作』です。ただしこれだけが双方向変換なのではなく、あくまでも双方向変換のメジャーな一種です。以降本記事ではこれについて説明します。その点では先述の説明は不適切ですが今は正確性を捨てます。
### 変換（？）
双方向**変換**とは、$s$ をある情報源とし、そこから一部をとってきたものを $v$ として（それぞれ Source、View の頭文字）、 $s$ や $v$ の間で変換する技術です。
また**双方向**変換は、『情報をとってくる操作 ($\textit{get}$) 』と『情報源を更新する操作 ($\textit{put}$) 』という関数で構成されます。（具体例はあとで挙げます。）
$\textit{get}$ は 情報源 ($s$) を引数に取り、あるビュー ($v$) を返す関数です。
$\textit{put}$ は **更新したい情報源 ($s$) と**更新情報を含んだビュー ($v$) 引数に取り、更新された情報源 ($s'$) を返す関数です。引数は**二つ**です。

数学や関数型言語について知ってる人に向けて書くならば、
```math
\begin{align}
    \textit{get} &: S \to V\\
    \textit{put} &: S \times V \to S
\end{align}
```
となります。なお、$s\in S$ と $v\in V$ です。

ちなみにこの二つの関数の組を**レンズ** (**Lens**) と呼ぶことが多いです。というか双方向変換よりレンズの方がメジャーかも？

### 具体例1. DB
とはいえ私も最初は抽象的な説明だと理解できなかったので具体例を挙げてみます。（具体例を挙げている論文が少なすぎるんじゃ）
情報源 $s_1$ を以下の表とします。\[国名、首都、フラッグキャリア\]の組です。
今回は $S=\[\text{Nation}, \text{Capital}, \text{Flag Carrier}\]$ という型になります。
|Nation |Capital   |Flag Carrier       |
|:-:|:-:|:-:|
|Japan  |Tokyo     |All Nippon Airways |
|Italy  |Rome      |ITA Airways        |
|Egypt  |Cairo     |EgyptAir           |

#### get の例
このとき、国名と首都の情報だけ欲しいとします。この『情報をとってくる操作』は $\textit{get}(s_1)=v_1$ と書きビュー $v_1$ は以下の表になります。
ビューの型は $V=\[\text{Nation}, \text{Capital}\]$ です。
| Nation | Capital |
|:-:|:-:|
|Japan  |Tokyo     |All Nippon Airways |
|Italy  |Rome      |ITA Airways        |
|Egypt  |Cairo     |EgyptAir           |

#### put の例
仮に日本がバグって仙台に遷都したとします。このとき、この更新情報を元の情報源 $s$ に反映しなければなりません。今回の例程度の表のサイズなら「直接 $s_1$ に反映しろよ」という話ですが、一般論として小さい表を更新した上でそれが元の大きい表に反映できれば便利だよね、という体で話を進めます。
まずビュー $v_1$ （小さい表）を更新して新しいビュー $v_2$ を作成します。
| Nation | Capital |
|:-:|:-:|
|Japan  |**Sendai**|All Nippon Airways |
|Italy  |Rome      |ITA Airways        |
|Egypt  |Cairo     |EgyptAir           |

これに基づいて、元の情報源 $s_1$ を更新して新しい情報（源） $s_2$ を作成します。 
この『情報源を更新する操作』は $\textit{put}(s_1, v_2)=s_2$ となります。
自然な感じに更新して以下のような表 $s_2$ を得ます。
|Nation |Capital   |Flag Carrier       |
|:-:|:-:|:-:|
|Japan  |**Sendai**|All Nippon Airways |
|Italy  |Rome      |ITA Airways        |
|Egypt  |Cairo     |EgyptAir           |

以上が双方向変換の（おそらく最も容易に想像がつきやすい）具体例です。
この辺は SQL で書けると思います。筆者は長らく SQL を書いていないので忘れましたが…

### 具体例2. 代数
論文とかのより抽象的な議論が求められるものでは、先ほどの表のような具体例を挙げるのではなく、代数的な例で議論することが多々あります。
例えば
```math
\begin{align}
&S=V=\mathbb{Z}\\
&get(s)=2s\\
&put(s, v) = s + v
\end{align}
```
とか。ここでは $\mathbb{Z}$ を整数全体の集合とします。
例えば $get(3)=6$、$put(-2, 7)=5$ などとなります。このような代数を用いた双方向変換はその性質の証明や反例をあげるのに使われることが多そうです。

# まとめ Concluding Remarks
もちろんこれだけが双方向変換なのではなく、むしろ双方向変換の 1% も説明してません。ただ教科書的なのがなさそうな分野なので大変ですがこれ以上の双方向変換を学ぶには解説論文なりを読みましょう。

最後にもう一度、**この記事の正しさは保証しません and/or できません。**
間違ってたらそっと教えてください。


<!--
    M511, R**C, K*t*hir* Campus, T*h*k* University の研究室の人ならおそらく誰が書いたか特定できると思いますが内容について不具合を見つけたらそっと教えてください。
    アドベントカレンダー向けに書いたものなので内容の雑さは流してください。
-->
QAの成果物もレビューが大切。それも早い段階で。

# はじめに

こんにちは、HRBrainでQAエンジニアをしているhh（@hh_hrb）です。
今回は「レビューってやっぱ大事」「レビューは早ければ早いほどいい」って改めて思ったお話です。


本記事は、HRBrain Advent Calendar 2023　20日目の記事となります。

https://qiita.com/advent-calendar/2023/hrbrain

# QA成果物のレビューの必要性とタイミング
テスト段階でも、テスト設計書、ケース等々、レビューが必要な成果物がたくさんあります。
QAが出した観点やケースが、今回の改修範囲と齟齬がないか、過不足がないかを確認するためにも、その成果物に対してQAエンジニア内だけでなく、開発エンジニアにもレビューしていただくことが非常に大事だと思っています。
そして、そのタイミングも早ければ早いほど開発全体の速度も上がるはずなのでは？と考えています。
今回は現状を交えて、どういった状態が理想なのかのお話です。


# 現状
新機能や大きめの改修は、中盤あたりからQAエンジニアも仕様把握やテスト見積に入れていることが多いですが、日々の細かい修正確認についてはざっくり以下流れになっているのが現状です。


![Untitled (9).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032267/b7a29ad4-b604-c9c3-ff83-9a847bb68cb4.png)



このままでもやれないことはないですが、デメリットの方が多い気がしますしスピード感にも影響が...

![Untitled (8).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032267/ec67b085-f00f-d080-5d6a-b244e7e7e648.png)



おそらく弊社だけではなく、一人QAや組織内で開発とテスト工程が分断されている、開発スピードが早い場合などは割とこういう状況が多いのかなと思います。


# 現状の打開と理想

最終の理想は要件要求定義からの参画ですが、まず第一段階の理想（現状の打開から）とすると、以下になるかと考えています。
- 早い段階からテスト設計を開始することで、実装完了と同時にテスト実施ができる
- レビューを挟むことで、テスト実施段階の手戻りを減らす

これを達成し継続していくためには、QAの着手を早めることに加えて**QAの成果物もレビューをする文化**を浸透させていくことが重要となりそうです。

![Untitled (11).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032267/c5c3096e-1c5c-07c4-9806-d2712faaf1f7.png)

### 打開していくために
> QAの初動を早める

実装段階で、必要情報の収集・テスト観点出し（設計）を行い、ある程度テスト工程を実装と並行することで、レビュータイミングを早めると同時に全体の期間の短縮が見込めると考えています。
とはいえ、リソースの問題で初動をすぐに早めていくことは難しい..

「まずはできることから!」と言うことで、最近は少し小さめの規模のものでも実装終盤あたりにエンジニアに仕様共有の場を呼びかけています。
その場では、仕様（実装内容）共有を第一の目的としているのですが、我々QAエンジニア視点からの仕様確認、疑問、影響範囲の確認を行うことで、テスト設計に入る前に考慮/実装漏れやユーザー視点の懸念事項が１つでも減らせる機会となっています。
（※もちろんテキストに残すことは大事）

実際にその場で浮かんだ疑問（入力内容の一部がxxxなので、出力されるこの機能でも影響がありそう？みたいな）が、実装の変更に至ったことも度々ありました。


> 成果物をQAチームメンバーと開発エンジニアにレビューしてもらう

テスト範囲が適切か、過不足がないかを双方で確認できることで適切なテストが実施でき、また実装漏れ等があった場合、QA観点のレビューにより開発エンジニア側も事前に漏れを検知できるようになると思っています。

レビューにもいろいろありますが、（JSTQBのシラバスを見ても「形式的レビュー」「非形式的レビュー」「インスペクション」「ウォークスルー」等々）細かいこと気にし出すと時間がかかってしまうので今回はあんまり気にしません。笑
大事なのは、QAと開発エンジニアに齟齬なくかつ、手戻りが少ない最適なテストができている状態を目指すことです。
と、ここで気になるのがレビューの範囲とポイントですよね。。
QAチーム（QAエンジニア内）がみるポイントと、開発エンジニアに見てほしいポイントは少し違う気がしてます。
個人的な見解ですが、それぞれ以下になるかと思います。

■QAエンジニア
範囲：成果物全て（テスト設計（観点）、テストケース等）
ポイント：非機能要件等、テスト観点としての漏れがないか、ケースに抜け漏れがないか、手順に問題がないか等

→仕様書や変更内容に書いてあることが含まれているかもみますが、どっちかと言うとテストすべき観点を中心にレビュー

■開発エンジニア
範囲：テスト設計（観点）
ポイント：実装範囲とテスト範囲に齟齬がないか、実装時に影響がある範囲についても拾えているか（もしくは過分がないか）
　
→基本的には実装内容とずれてないか、みてほしいポイントが含まれているかを中心にレビュー
※QAの成果物粒度によりますが、基本的には「何をどこまでテストするか」のテスト観点ベースでのレビューで十分だと思っています。

あくまで個人の見解ですが、QA成果物のレビュー機会がないと、どこを見て良いのかわからないこともあるかと思うので気持ち参考にしてもらえてばと思います。
（レビューを出すQAエンジニア側からは特にみてほしいポイントをお伝えできるとベストですね！）

こちらも部分的にですが、心配な時は他のQAメンバーに観点みてもらったり、エンジニアに事前に観点共有したり範囲が広い時はどこまで確認するかの認識合わせを行なっています。
今後は、レビューをしっかりと通せる体制を徐々に作っていけたらと思っています。




# やっぱりQAもレビューって大事。
まずは小さいものでも、少しでも早い段階でQAテスト観点を見てもらう、確認する、共有していく、そしてフィードバックをもらうことが大事です。
これから徐々にQA成果物のレビュー文化を根付かせて、開発エンジニアもQAエンジニアも、もっというとチーム全体としても手戻りを減らして、より最適なサイクルを回していければと思っています。


# 終わりに
レビューフローも大事だけど、そもそもQAの観点表を用意するとかもっと別の対策も必要では？って声が聞こえそうです笑

確かにその通りでそれもやる必要はあると思うのですが、今回はまず第一歩としてのお話をさせていただきました。
レビュー、少し面倒に思ってもやっぱり大事なのでお互い助け合っていきましょう。


HRBrainでは、一緒に働く仲間を募集しております（もちろんQAも！）
ご興味ある方はぜひ、以下リンク先まで↓

https://www.hrbrain.co.jp/recruit