OmniAICreator/Qiita-1.07M huggingface dataset:
フロントエンドのCIの実行する時間を減らす方法について


## フロントエンドのCIでよくあるフロー
- 1. CI動くの準備
- 2. Lint
- 3. フロントエンドのテスト
- 4. ビルド

今までの経験だと、⓵と⓸は一番時間がかかりました。
⓷はテスト数による時間が異なります。

---

## 時間がかかった理由
- フロントエンド動くためのアプリ、nodejs, npm などのインストール時間 →　これはCIのイメージの定義に設定入れれば、解決できます。
- ライブラリーのダウンロードの時間
- フロントエンドのビルド時間

---

## 今回にライブラリーのダウンロードの時間を減らす方法を紹介します。

---

## 時間を減らす方法方法
- キャッシュ方法
- 一回だけライブラリーをダウンロードして、CIでライブラリーをダウンロードしないようにします。

---

## 実際のコード

---

## CIイメージの定義
- キャッシュがないDockerfile

```dockerfile
FROM node:18.16-buster-slim

RUN apt-get update && apt-get -y install \
  bash \
  make \
  python \
  g++ \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
RUN mkdir /app
WORKDIR /app

```

---


- キャッシュがあるのDockerfile
```dockerfile
FROM node:18.16-buster-slim

RUN apt-get update && apt-get -y install \
  bash \
  make \
  python \
  g++ \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*

# キャッシュのため
RUN mkdir /tmp_app
WORKDIR /tmp_app
COPY package.json package.json
COPY package-lock.json package-lock.json
RUN npm install

# ライブラリーフォルダーPATHを指定します。
ENV NODE_PATH=/tmp_app/node_modules

# 実際フォルダーのため
RUN mkdir /app
WORKDIR /app

```

---

## メリット
- ライブラリーダウンロード時間は大分減らします。
- シンプル
- Docker Imageを使うCIなら、Ruby, Rust, PHPなどの言語は同じ方法で実装できます。

---

## デメリット
- ライブラリーのファイルはイメージに入りますので、ファイルサイズは大きくになります。
- ライブラリーが変わったら、イメージを再ビルドしないとキャッシュが効かないです。
- ライブラリーが少ないプロジェクトはあまり改善されないです。

---

## 外部サビースのキャッシュの仕組み
- Circleci: Caching Dependencies
https://circleci.com/docs/caching/

- Gitlab CI: Caching in GitLab CI/CD
https://docs.gitlab.com/ee/ci/caching/

- Github Action: Caching dependencies
https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows

---

## 以上です。
NOEOL？No Newline at End of File？

## 経緯
最近PRレビューコメントに、
「No Newline 〜を削除」「EOL入れたい」のコメントをいただくので調べてみました。
## 結論
エラーメッセージは、
「ファイルの末尾が改行じゃない」「コード行末に改行がない」ということらしい。
## ...What do you mean?!
https://bottoms-programming.com/archives/indent-tab-space-and-new-line.html
こちらの記事がとても分かりやすかったです。

> テキストファイルとは、いくつかの行の集合である。
> そして、行とは改行コードで区切られるまでの、一連のテキストデータの連続である。

なるほど！？

「C, C++」では、改行なしのソースファイルは誤作動を引き起こすらしいです。
（未定義扱いになるため）

確かに対応した方が良さそうだなと感じてきた。。

でも毎回チェックするのめんどくさいな。

## エディタ（VScode）に設定しちゃえば良いのか！
setting.jsonで以下の文を追加っと。

```json:setting.json
"files.insertFinalNewline": true
```

できた！！

沢山の優良記事に感謝！

### 参考記事

https://bottoms-programming.com/archives/indent-tab-space-and-new-line.html

https://qiita.com/kazuhito_nakayama/items/14c16f1b624ffd2f383c
【Java初心者】Wekaによる機械学習 03-コマンドラインで重回帰分析

# Javaで重回帰分析したい

重回帰分析ならば、Excelでも十分できるんだけど、これをJava環境で行いたいという趣味的な内容です。

こちらと同じデータを使ってみます(手入力)
https://corvus-window.com/excel_multiple-regression-analysis/

arffデータならばこんな形になります。目的変数をlastにしました。train.arffなどととします。


```
@RELATION salary2

@ATTRIBUTE 年齢 numeric
@ATTRIBUTE 通勤時間     numeric
@ATTRIBUTE 扶養人数     numeric
@ATTRIBUTE 出身大学     numeric
@ATTRIBUTE 年収 numeric

@data
35,60,2,48,670
58,70,3,61,1200
40,45,0,52,680
38,45,2,55,820
24,30,0,58,510
27,55,0,61,550
49,80,3,44,890
30,60,0,45,480
53,70,1,50,730
25,80,1,47,430
```
# コマンドラインで実行

Wekaは普通のリリース版で使えますが、これまでのようにmini-wekaを使ってみます。

```
java -cp mini-weka-3.9.15955.jar:. weka.classifiers.functions.LinearRegression -t train.arff
```
出力結果
```
年収 =

     10.9962 * 年齢 +
     84.6026 * 扶養人数 +
     11.7295 * 出身大学 +
   -433.3844
```

上記サイトとなんか違う・・・・。

ここでオプションを見ると、
```
-S <number of selection method>
	Set the attribute selection method to use. 1 = None, 2 = Greedy.
	(default 0 = M5' method)
```
というのが見つかりました。

このオプションを指定しないと、-S 0 と同じ扱いになり、自動的に項目選択モードのM5方式(表現が間違っているかもしれません)が使用されるということです。-S 2 は貪欲法。-S 1 は項目選択をしないようです。

これを参考に
```
java -cp mini-weka-3.9.15955.jar:. weka.classifiers.functions.LinearRegression -S 1 -t train.arff
```
とすると、
```
年収 =

     11.533  * 年齢 +
     -2.0274 * 通勤時間 +
     94.0915 * 扶養人数 +
      9.3459 * 出身大学 +
   -220.303 
```

となり、上記サイトと同じ結果が得られました。

※将来的には、M5と貪欲法ってのをマスターしたいです。
正規化

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457284/a7a44871-9b79-34cc-c6e7-72487d54aa29.png)
１：第３正規形
　第３正規形の表は、第２世奇形を満たしており、非キー属性が主キーに推移的関数従属しない表です。
　第３正規形にするためには、例えば、主キー以外の属性との関数従属を洗い出し、その関数従属を別表に分けます。第３正規形にすると、第２正規形の受注票がさらに分割され、顧客表ができます。第３正規形になると、情報が重複して記憶録されている箇所がなくなるので、不整合の発生を抑えることができます。

　なお、”A → B →　C” のように関数従属が数位していくものです。第２正規形の受注表には、
　受注番号　→ 顧客番号　→ 顧客名
という推移的関数従属が存在しています。これを　
受注番号　→　顧客番号　顧客番号　→ 顧客名
となるように表を分割して第３正規形を作ります。

２：正規化の利点と欠点
　正規化の利点は、不整合の発生を防ぐことができることです。しかし、欠点もあります。欠点は、情報のアクセスに時間がかかるようになることです。

　例えば、第３正規形まで正規化したとします。受注番号３８１９の顧客は誰か、どのような商品を受注したのかを調べるには、
・受注表から受注番号３８１９の顧客番号かを調べ、顧客表から顧客名を調べる。

・受注明細表から、受注番号３８１９の商品番号を調べ、さらに、商品表から商品名を調べる

といったように、さまざまな表を要る必要があります。先に示した非正規形の表であれば、受注番号３８１９の表を見れば、全てわかります。このように、正規化を進めると、さまざまな表を見る必要が生じ、情報のアクセスに時間がかかるようになります。

　事例によっては、応答時間を短くするためには、あえて正規化を進めず、低いレベルにしておくという対応もします。
【プラクティス紹介】1分でさらっと分かる「SMARTな目標」

## プラクティス名（別名）
SMARTな目標　（SMART Goals）

## プラクティスの目的・狙い
* アイデアを具体化し、実行可能なアクションに変える

## どんな時に使うか
* レトロで改善案が挙がるも、結局あまり実行されずに終わる、といったことがよくある時

## 実施手順
ふりかえりで挙がったアイデアのうち、次のスプリントで実行に移す改善策を具体化するため、以下の5点を満たす目標になるように整える。

|頭文字|英単語|意味|
|:---:|:---:|:---:|
|S|Specific|明確な、具体的な|
|M|Measurable|計測可能な|
|A|Achievable|達成可能な|
|R|Relevant|適切な、問題に関連のある|
|T|Time-bound|期限の明確な|

例：
SMARTでない目標：無理せずこまめに筋トレを頑張る
SMARTな目標　　：毎日腕立て伏せを10回する

## アレンジ例
* SMART化した改善アクションをプロダクトバックログアイテムとして追加する

## アンチパターン
* 「意識する」「頑張る」など、気持ちだけでどうにかしようとする表現になっている
* 論理的には達成可能だが、物理的に達成不可能な（よくよく作業量を考えてみると到底間に合わない）目標になっている

## 参考情報

https://www.shoeisha.co.jp/book/detail/9784798168791

## こぼれ話（私的コメント）
アジャイルプラクティスとしての紹介なので上記のような状況を使いどころとして例示しましたが、もともと目標管理の大原則的なものなので、何にでも使えます。「SMARTな目標」の出自は古く、1981年の論文まで遡るそうです。SMARTにどんな英単語を当てるかも諸説あるようで、歴史の長さを感じます。（[Wikipedia](https://ja.wikipedia.org/wiki/SMART_(%E3%83%9E%E3%83%8D%E3%82%B8%E3%83%A1%E3%83%B3%E3%83%88))参照）

せっかくレトロでいいアイデアが出たのに、目標がSMARTになっていなかったために、結局あまり実行されなかった、という残念な状況がたまにあります。そうなると目標を見直して次のスプリントでリトライ、ということになるのですが展開としては一周遅れになってしまうので、少し勿体ないです。

　[アジャイルプラクティス一覧へ戻る](https://qiita.com/kakashi_h5/items/20584998c5ca4594b9ea)
--user-data-dirを指定すると2回目以降のSelenium/Chromeが起動しない問題

# 問題
- Fedora に以降して selenium 関連も移行したら上手く起動しなくなった
    - Btrfs
- `--user-data-dir` を指定して、1回目は起動する
- 2回目以降はエラー
    - `--user-data-dir` の対象を削除すると起動するが、ログイン状態は解除されてしまう

```:Error
Traceback (most recent call last):
  File "/home/uyiromo/workspace/.venv/lib/python3.10/site-packages/seleniumwire/webdriver.py", line 218, in __init__
    super().__init__(*args, **kwargs)
  File "/home/uyiromo/workspace/.venv/lib/python3.10/site-packages/selenium/webdriver/chrome/webdriver.py", line 80, in __init__
    super().__init__(
  File "/home/uyiromo/workspace/.venv/lib/python3.10/site-packages/selenium/webdriver/chromium/webdriver.py", line 104, in __init__
    super().__init__(
  File "/home/uyiromo/workspace/.venv/lib/python3.10/site-packages/selenium/webdriver/remote/webdriver.py", line 286, in __init__
    self.start_session(capabilities, browser_profile)
  File "/home/uyiromo/workspace/.venv/lib/python3.10/site-packages/selenium/webdriver/remote/webdriver.py", line 378, in start_session
    response = self.execute(Command.NEW_SESSION, parameters)
  File "/home/uyiromo/workspace/.venv/lib/python3.10/site-packages/selenium/webdriver/remote/webdriver.py", line 440, in execute
    self.error_handler.check_response(response)
  File "/home/uyiromo/workspace/.venv/lib/python3.10/site-packages/selenium/webdriver/remote/errorhandler.py", line 245, in check_response
    raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.WebDriverException: Message: unknown error: Chrome failed to start: exited abnormally.
  (chrome not reachable)
  (The process started from chrome location /home/uyiromo/workspace/chrome/chrome-linux64/chrome is no longer running, so ChromeDriver is assuming that Chrome has crashed.)
Stacktrace:
#0 0x5556fb31f783 <unknown>
#1 0x5556fb04b917 <unknown>
#2 0x5556fb076978 <unknown>
#3 0x5556fb0739c9 <unknown>
#4 0x5556fb0b3a13 <unknown>
#5 0x5556fb0b315f <unknown>
#6 0x5556fb0aabd3 <unknown>
#7 0x5556fb07ea7b <unknown>
#8 0x5556fb07f81e <unknown>
#9 0x5556fb2e0e98 <unknown>
#10 0x5556fb2e4d67 <unknown>
#11 0x5556fb2ef32c <unknown>
#12 0x5556fb2e5993 <unknown>
#13 0x5556fb2b4827 <unknown>
#14 0x5556fb3098a8 <unknown>
#15 0x5556fb309a36 <unknown>
#16 0x5556fb3185f3 <unknown>
#17 0x7f85da60a907 start_thread
#18 0x7f85da690870 __clone3
```

# 対処
- `--user-data-dir` の先に残存している `SingletonLock` を削除する
    - おそらく broken symbolic link になっている筈
- どうもこのファイルがあると Chrome が起動してくれないらしい
bind mountで失敗する。

# bind mountがうまく実行できない。。

根本的な原因はわかりませんが、とりあえずメモします。

行った実験条件は一番下に記載しました。
PC Cで問題が発生します。

## エラーログ

docker runを実行すると下記のようなエラーが発生します。

```
(base) manyou@manyou:~/001_CODE/101/eval$ ./internal/docker_run.sh
docker run --shm-size=8G --net=host -e DISPLAY= -e TZ=Asia/Tokyo -v /tmp/.x11-unix:/tmp/.x11-unix -v /etc/passwd:/etc/passwd:ro -v /home/manyou/.Xauthority://home/manyou/.Xauthority -v COCO:/workspace/data/coco -v PASCAL:/workspace/data/pascal -v pascal_coco_format:/workspace/data/pascal_coco_format -v IMAGENET:/workspace/data/imagenet -v a2d2_18cls:/workspace/data/a2d2_18cls -v /home/manyou/001_CODE/101/eval/internal/..:/workspace -u 1001:1001 -w /workspace -it --rm cnn-eval:manyou bash -c 'bash ./internal/setup.sh develop; bash'
docker: Error response from daemon: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: error during container init: error mounting "/etc/passwd" to rootfs at "/etc/passwd": mount /etc/passwd:/etc/passwd (via /proc/self/fd/7), flags: 0x5001: no such file or directory: unknown.
```

エラー発生は下記のbind mountです

```
docker run ... -v /etc/passwd:/etc/passwd:ro ...
```

同じスクリプトを他のPCで動作させるとエラーなく実行できます。
そのため、PCの環境に原因があると考えました。

## 環境をチェックして気づいた事

- なぜか、ユーザーグループが無く、もちろんユーザーグループへ所属もしていない。なぜそうなったのかはわからないです。。。

bind mount失敗環境でのidコマンドの実行結果
```
uid=1001(manyou) groups=27(sudo),1003(docker)
```

bind mount成功環境でのidコマンドの実行結果
```
uid=1001(manyou) gid=1001(manyou) groups=1001(manyou),27(sudo),1003(docker)
```

## 行ったら改善したこと

1. ユーザーグループの作成
2. ユーザーグループへユーザーを追加
3. dockerをapt upgrade

1,2,で解決すると思ったけど、エラー解消されず。。
dockerのコマンドをアップデートしたら何故かエラー解消。

dockerのコマンドは成功環境A-1でもエラーなく実施できていたバージョン(20.10.21)だったため、バージョンが問題ではないはず。

|条件	|A-1|B-1|	C-1|C-2|C-3|
|---|---|---|---|---|---|
|PC name	|A|	B|	C|C|C|
|User名のGroup	|有り|有り|無し|有り|有り|
|ubuntu version	|20.04|20.04|20.04|20.04|20.04|
|docker version	|20.10.21|23.0.2|20.10.21|20.10.21|20.10.25|
|Result (bind mount /etc/passwd)|OK|OK|	NG|	NG|	OK|
【C#】PaizaやAtcoderの動作確認用に入力を再現する

# 経緯
最近Paizaの問題を解くのにはまっている。
手元の環境で動かす時に標準入力だと微妙に使いずらいので、簡単に入力を得られるものを愛用している。
おそらく既に同じようなものが出回っていると思うが備忘録程度に記載しておく。
実質的にIEnumeratorで、IEnumeratorのものも作ったけどこっちのほうが好き。


 - 2023/08/23
コメントにとってもとってもいいコードを提案していただきました。
そちらを参考にしましょう。


# コード
```
public class ConsoleInput
{
    cost string InputStr =@"10 10
12 12 12
13 13 13";

    readonly string[] inputArr;
    int index;
    
    public ConsoleInput()
    {
        inputArr = InputStr.Split("\n").Select(s => s.Trim()).ToArray();
        index = 0;
    }

    public string Get()
    {
        if (index >= inputArr.Length)
            return "";
        
        var str = inputArr[index];
        index++;
        return str;
    }
}
```

# 使い方
```
static void Main {
    var consoleInput = new ConsoleInput();
    var inputStr = consoleInput.Get();
}
```
[JSTQB AL TA]　6.テストツールおよび自動化　を視覚的にまとめてみた

# はじめに

こんにちは、Ma5am1nです。いよいよ今週末にTAの受験予定でドキドキしています。
[シラバス](https://jstqb.jp/dl/jstqb.jpdlJSTQB-SyllabusALTA_V311.J03.pdf)[^1]は文字が多くて頭に入りにくいので、図など視覚的に入ってきやすそうな形式でまとめてみます。

[^1]: Advanced Level シラバス日本語版　テストアナリスト　Version 3.1.1.J03 

**※あくまで私個人の解釈で作成したものです。内容が100%シラバスの通りであることは保証できませんので、ご了承ください。**
**※スライドの青文字、青線になっている箇所は、シラバスに記載されていない、私独自の解釈で記載した内容です。**

このページでは、6.テストツールおよび自動化　について扱います。

# 6.テストツールおよび自動化
## 6.1イントロダクション
![JSTQB AL TA-118.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1636570/563a5389-de25-42e2-6b58-d42ab14fb99a.png)

## 6.2キーワード駆動テスト
![JSTQB AL TA-120.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1636570/0a246112-7e2a-651b-ca11-b84ad78addf3.png)
![JSTQB AL TA-121.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1636570/0faf35a5-bc9b-064e-9f6b-aec59f535745.png)

## 6.3テストツールの種類
### 6.3.1テスト設計ツール、6.3.2テストデータ準備ツール、6.3.3テスト自動実行ツール
![JSTQB AL TA-123.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1636570/033c34ec-62ea-9157-9082-dab882363168.png)
![JSTQB AL TA-124.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1636570/87dc9ed9-30a8-2fc5-2cbd-0fe265e31969.png)
[備忘録]バッチファイルに特定の引数を指定する

## 背景
業務で使用するコンソールアプリやデスクトップアプリが便利なのですが、バラバラに管理されておりかつバラバラに配置されているので、それを解決したいと思いました。そこで、下記のようなCLIを使ってそれらを管理しようと考えました。

その際、```test 1.0.0 [value1] [value]```のように引数を渡せることは知っていましたが、どうせなら下記のような```dotnet [option]```コマンドのようにoptionを渡したいと思いました。
```bat
dotnet -h
```
### optionを引数から取得する方法
```batch
@echo off
set VERSION_CMD=--version
set AILIAS_VERSION_CMD=-v
set VERSION=""

rem enabledelyaedexpansionでコードを呼び出し時ではなく、実際に実行するときに変数を評価する
setlocal enabledelayedexpansion & (
	set NEXT_ARG=""
)
for %%a in (%*) do (
	if !NEXT_ARG! == "true" (
		set VERSION=%%a
		set NEXT_ARG="" 
	)
	if %VERSION_CMD% == %%a (
		set NEXT_ARG="true"
	)
	if %AILIAS_VERSION_CMD% == %%a (
		set NEXT_ARG="true"
	)
)
endlocal & (
	set VERSION=%VERSION%
)
echo %VERSION%
```
Google Colaboratory + Keras でとにかくシンプルな画像識別 (Image Classification) の試し方

## 背景
生成 AI 真っ盛りな昨今(2023/8)ですが、あえてオーソドックスな画像識別の話です。
もちろん探せば色々と出てくるのですが、
* 最初から独自の識別モデルを作る少し長め & 難しめのものだったり:scream:
* 記述が古くて今の Google Colaboratory の環境だとエラーが出たり:persevere:

と言うことだったので、まずは
* ImageNet の 1000 クラスで良いから学習済みのモデルを使って、画像識別をとにかくシンプルに試せるようにする:bicyclist:

としてまとめたものです。

## 環境
* Google Colaboratory
    * 無償版で OK です
    * ランタイムのハードウェアアクセラレータも CPU でも良いです

また、今回は Keras とその学習済みモデルである Xception を使ったものにしました。(ResNet50 はサンプルがあるので)

https://keras.io/ja/applications/

## 手順
1. Google Colaboratory で新規ノートブックを作成します。
2. 画像を作業ディレクトリにアップロードします。
例えばこちら(Stable Diffusion に作ってもらいました:v:)
![penguin.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3535779/732d74f0-8a4f-be7b-d4b2-e81fbc03afef.png)
3. 次のソースコードを「コード」セクションに貼り付けて実行します。

:::note info
"識別する画像の読み込み"箇所の引数(ソースコード上は penguin.png となっているところ)をアップロードした画像ファイル名に変えてください
:::

```Python
from keras.applications.xception import Xception, preprocess_input, decode_predictions
from keras.utils import load_img, img_to_array
import numpy as np

# モデルの読み込み
model = Xception(weights='imagenet')

# 識別する画像の読み込み
img_path = 'penguin.png'
img = load_img(img_path, target_size=(299, 299))

# 画像データを予測で使えるように処理
x = img_to_array(img)
x = np.expand_dims(x, axis=0)
x = preprocess_input(x)

# 予測実行
preds = model.predict(x)

# 結果のラベル(クラス)と確率を表示
print('Predicted:', decode_predictions(preds, top=3)[0])
```
* Xception のモデルは画像の入力サイズが`299 x 299`だそうなので`target_size`も合わせています。他のモデルを使う場合は、それぞれの規定に合わせて変える必要があるようです(`ResNet50` であれば `224 x 224`とか)
* Keras のページの ResNet50 のサンプルコードをほぼそのまま流用していますが、import の記載とその関数の使うところを、今の Google Colaboratory でワーニングが出ないよう修正しました
## 実行結果例
![GoogleColaboratory.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3535779/838496f5-f8ed-4046-230a-2f3d6b35d606.png)
きちんと`king_penguin`の確率が一番高く出てますね。(マイク成分は影響出なかった模様:sweat:) モデルやクラスの一覧のダウンロードは最初だけで、2回目以降の実行では行われません。

これに加えて、例えば Flask で簡易的な Web UI を作ることで、
* スマホでそのページを表示
* カメラで写真撮ってモデルで識別

なんてことも実現できますね。

以上、`とにかく・シンプル・ひとまず`の画像識別の試し方、でした。

## あとがき
もとはと言うと、今私が所属している企業も画像識別エンジンの API サービスを提供していて、それを使った小中学生でも楽しめるようなワークショップを開発して Web アプリも作ったのですが、残念ながら API サービスが終了となり。:cry:

開発したワークショップも Web アプリもお蔵入りになっていたのですが、生成 AI 絡みで Google Colaboratory であれこれ試し始めたところで「ん？そういえば GPU も使えるなら、独自のモデルを作る画像識別エンジンもサクッとできるんじゃ？」と。一通り動くものはできたので、復活にも目処がついたところです。(なので、この記事はそこからの選抜)

ちなみに学習用の画像データが 3 クラスで 100枚くらいの転移学習だったら、MacBook Pro Intel 版のローカルでやってもそんなに時間はかからなかったのは少し驚きました。:smile:
やってみた：Chrome（リリース版；１１６）でPQC

先日(2023/08/15)、Chromeの次期リリース（116）でPQCをサポートする、とのニュースが飛び込んできました
従前からCanaryチャネルやChromiumでは実験的にPQCをサポートしていたものの、リリースチャネルに降りてくるのは、初です

今回サポートされているのはX25519-Kyber768というハイブリッド方式
です
ハイブリッドというと、なんとなく
「（どちらかの）いいとこ取り（いわゆるOR）」
をイメージしがち？ですが、この方式は両方満たさないといけない
（いわゆるAND）という意味です

Chromeはブラウザですので、当然対向のサーバが必要です、ただ、なぜか？googleはテストできるサーバを準備していないようです（私がざっとググった限りでは発見できず）

感のいい読者はお気づきのように、手はあるはずです。
PQCに関わる人間が知らないとモグリとされる、あのサイトに助けを求めましょう
そう、OQS（OpenQuantumSafe）プロジェクトです

[Open Quantum Safe (OQS) project](https://openquantumsafe.org/ "Open Quantum Safe (OQS) project")

大体の情報はここにあります（若干誇張アリ（かも））

で、お目当てのテスト（デモ）用Webサイトはこちら
[Open Quantum Safe interop test server for quantum-safe cryptography
](https://test.openquantumsafe.org/ "Open Quantum Safe interop test server for quantum-safe cryptography
")

上記ページからx25519-Kyber768を探すと、下記がヒットします
[x25519_kyber768](https://test.openquantumsafe.org:6041/ "x25519_kyber768")
これで接続できるのか？期待しながらクリックすると、残念ながら、こんな画面が出ました
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/366056/66dd4ff5-5e8c-24cc-6af8-86ad6e75ccaa.png)

おかしい
他にテストサーバの心当たりは...うーむ
かつて（今でも）googleと共同でPQCサポートしていたcloudflareなら、テストサーバを用意してるかも！

気を取り直して
[Cloudflare Research: Post-Quantum Key Agreement](https://pq.cloudflareresearch.com/ "Cloudflare Research: Post-Quantum Key Agreement")にアクセスしてみると
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/366056/6cb2a21f-e17b-2567-1297-20652a55ae7f.png)
You are using X25519 which is not post-quantum secure.
だそうです
ただ、その下に気になる表記が？！
Chrome 116+ if you turn on TLS 1.3 hybridized Kyber support (enable-tls13-kyber) in chrome://flags. [new!]
え、まさか、設定が必要なの？
では、再度、気を取り直して
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/366056/86e6b197-40a2-0aca-5e9a-32fcd9042671.png)
設定項目が多すぎるので、”x2”で絞り込んでます
DefaultをEnableに変更すると、ChromeをRelaunchするか聞かれますので、Relaunchします
すると、さっきのcloudflareのページ表示がこのように変わります
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/366056/6af5302f-9e4e-135d-b39e-48ed7a1fd414.png)
同様にOQSのテストサイトもこのように表示が変わります
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/366056/b0660bfa-dbe6-63cd-5f52-bac45117b4d5.png)
慌ててはいけません。TLSのネゴは正常に終了しています
証明書がオレオレなだけです
（OQSのサイトにも証明書が信頼されていないものである旨の説明があります）
証明書をあえて受け入れれば、こんな画面になります
（DevToolsでCipherSuiteを表示しています）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/366056/cad302e7-8bb3-9ca7-44f4-3dcaa91e8795.png)
なぜか、AES128になっています（期待値はAES256のはず）が、まずは動作確認が無事取れた、ということで良しとしましょう
[Milk-V Duo] 手にして15分でLチカまで

## はじめに
AliExpress で目にして、あまり考えずに購入した **Milk-V Duo** 

https://milkv.io/duo

調べてみると、公式ドキュメントもわかりやすく面白そうなので即購入。
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209885/0eb88eec-64a5-cd45-b1cb-d74463ffb0fa.png width=640px>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209885/1dc94223-356b-5740-a3cc-43babdf1d925.png)


「予習」と「準備」をしておけば、10分程度でLチカまで行けます。

概要は下記のとおり（公式サイトからGoogle翻訳）

> <b>Milk-V Duo は、CV1800B チップをベースとした超小型の組み込み開発プラットフォームです。Linux と RTOS を実行でき、専門家、産業用 ODM、AIoT 愛好家、DIY 愛好家、クリエイターに信頼性が高く、低コストで高性能なプラットフォームを提供します。</b>

>**ハードウェア**
> - CVITEK CV1800B (C906@1Ghz + C906@700MHz)
> - 最大 1GHz のデュアル RV64 コア
> - 64MBのRAM
> - オプションのアドオンボード経由で 10/100Mbps イーサネットを提供
> - Linux と RTOS の両方の実行をサポートするテクノロジー

## ４日で届いた
2023/8/18に注文し、8/22に到着しました。
価格は約1500円、送料込みで1800円程度です。（本当にいいのか？）

## 準備
手順の説明は非常にわかりやすく、初心者でも迷うことはないでしょう。

https://milkv.io/docs/duo/getting-started/boot


必須の物品は
+ ホストPC（Ubuntu20.04 が推奨されているが、今回は WSL + Ubuntu 22.04 で動作確認）
+ 1GBを超えるmicroSD
+ Type-Cケーブル

あとは公式ドキュメントのとおりにシステムイメージをダウンロードしてmicroSDに書き込む。

## 開発環境
ホストPC上に開発環境を整えます。
こちらも公式のとおりで問題なく準備できました。

https://milkv.io/docs/duo/application-development/wiringx

予習としてサンプルプログラムをよく見ておきましょう。
各ディレクトリで`make`すれば、それぞれ実行ファイルができます。

**手にしてすぐにLチカをするために`blink`ディレクトリでも`make`しておきます。**

## 到着したら
開封し、問題なければType-Cケーブルで接続します。
正常ならばボード上の青色LEDが0.5秒間隔で点滅します。

リモートNDISの設定は下記に詳しく記載されています。

https://milkv.io/docs/duo/getting-started/setup

この手順で問題なく接続できました。
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209885/8e47ffa4-797b-47c2-e4d3-1ffe070c6b52.png width=400px>

## あとはLチカ
「あっけない」というのが実感です。

さて、Lチカですが、このまま`blink`を転送して実行すると、すでに点滅している青色LEDにLチカがかぶってしまいます。（やっちまいました。）

**手順説明にあるとおり、起動時から点滅している青色LEDを止めておく必要があります。**
この点滅はシェルスクリプト`/mnt/system/blink.sh`によって実行されているので、スクリプトをリネームし、再起動することで点滅が停止します。

**Milk-V Duo**にリモート接続し、スクリプトのリネームと再起動をします。
```
$ ssh root@192.168.42.1
root@192.168.42.1's password:（初期パスワードはmilkv）
[root@milkv]~# mv /mnt/system/blink.sh /mnt/system/blink.sh_backup && reboot
```
再起動には少しばかり時間を要しますが、点滅は止まるはずです。

いったん接続も切れるので、`make`済みの`blink`を転送し、**Milk-V Duo**に再接続して実行します。
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209885/ca08b2e7-7a28-32b5-b9c8-cd814cce8075.png width=400px>

画面表示にあわせて青色LEDが点滅しました。
準備がしっかりできていれば、手にとって15分程度でLチカが完了です。
![blink.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209885/7101b065-4dab-0e57-febe-6b679ffb07ec.gif)

しばらく楽しめそうです。
## おまけ
`/mnt/system/blink.sh`を見てみました。
```bash:/mnt/system/blink.sh
#!/bin/sh

LED_GPIO=/sys/class/gpio/gpio440

if test -d $LED_GPIO; then
    echo "GPIO440 already exported"
else
    echo 440 > /sys/class/gpio/export
fi

echo out > $LED_GPIO/direction

while true; do
    echo 0 > $LED_GPIO/value
    sleep 0.5
    echo 1 > $LED_GPIO/value
    sleep 0.5
done
```
WSLの環境からWindowsにclip.exeするときの文字化け対処

# 結論

Shift JISもしくはUTF-16に変換する。以下のいずれか。

```bash
$ cat memo.txt | iconv -t cp932 | clip.exe
$ cat memo.txt | iconv -t sjis | clip.exe
$ cat memo.txt | iconv -t utf16 | clip.exe
$ cat memo.txt | nkf -Ws | clip.exe
$ cat memo.txt | nkf -Ww16L | clip.exe
```

cp932やsjisの範囲外の文字の場合は UTF-16 にする必要がある。


# ちょっと説明

`clip.exe` というコマンドがWSLのUbuntuの環境で使えます。テキストをWindowsのクリップボードにコピーするコマンドです。WSLの環境からこのexeファイルを実行できます。

例えばこんな感じです。

```plain
$ clip.exe < memo.txt
```

コマンドの出力をパイプでつないでコピーすることもできます。

```plain
$ grep hogehoge < foo.log | clip.exe
```

WSL環境の中でこんな感じで実行すると、Windowsのクリップボードにコピーされますので、そのあとWindows側で任意のアプリケーションにテキストをペーストできます。

ただし、日本語を含むテキストをUTF-8で扱っている場合、Windowsに貼り付けた際に文字化けしてしまうようです。最近この事象に気が付きました。ダサいけど、Shift JISまたはUTF-16（リトルエンディアン）に変換してから`clip.exe`に渡す必要があるようです。

```bash
$ cat memo.txt | iconv -t cp932 | clip.exe
$ cat memo.txt | iconv -t sjis | clip.exe
$ cat memo.txt | iconv -t utf16 | clip.exe
$ cat memo.txt | nkf -Ws | clip.exe
$ cat memo.txt | nkf -Ww16L | clip.exe
```

`iconv -t utf16` と `nkf -Ww16L` は、BOM付きリトルエンディアンのUTF-16に変換します。

私はタイプする文字数が少ない`nkf`を使っています。

`nkf`は以下のコマンドでインストールできます。

```plain
$ sudo apt-get install nkf
```

以上。
ESP-IDFの導入方法

# はじめに
VSCodeから導入する日本語の記事が見つけられなかったため、メモ書き程度に書きます。Windows11向けで、[ESP32-DevKitC-32E ESP32-WROOM-32E開発ボード 4MB](https://akizukidenshi.com/catalog/g/gM-15673/) 利用です。

# 導入方法


1. VSCodeを導入する
    - https://azure.microsoft.com/ja-jp/products/visual-studio-code から任意のものを導入し、実行する

1. VSCodeのExtensionからEspressif IDFを導入する。ぼくは v1.6.4を導入しました。

1. IDFの本体を導入する。
    1. VSCodeのmenu "View" - "Command Palette" をクリック。[configure esp-idf extension]と入力。 ESP-IDF: Configure ESP-IDF extensionを選択。

    1. Expressをクリック。Select ESP-IDF versoinに最新のものを選択。ぼくはv5.1(release version)を導入しました。

    1. ひたすら待つ。1G Byte以上あります。でかい。

1. UARTドライバを導入する。
    - [CP210x USB - UART ブリッジ VCP ドライバ](https://jp.silabs.com/developers/usb-to-uart-bridge-vcp-drivers?tab=downloads)

1. 任意のプロジェクトを作成する
    サンプルプロジェクトを起動する場合は以下に従う
    1. VSCodeのmenu "View" - "Command Palette" をクリック。[welcome]と入力。 ESP-IDF: Welcomeを選択。
    1. Quick AcctionのShow Exampleをクリック。Use current ESP-IDFを選択。
    1. 例えばhello_worldをクリック。別のものでもよい。Create project using example ...をクリック。
    1. 任意のフォルダを選択。選択したフォルダの下にhello_worldというフォルダが作成される。

1. COM3から焼けるようにする
    ぼくの環境ではUARTドライバを導入するとそれはCOM3に割り当てられました。一方で、IDFのデフォルトではCOM1をROM焼きやターミナルの表示などで利用します。なので、IDFのデフォルトをCOM3に変更します。

    1. EXPRORERタブから.vscode\\setting.jsonを選択する。
    1. 以下の行を追加する。
    ```shell
      "idf.portWin": "COM3"
    ```

1. ビルド、実行
    1. タスクバーのESP-IDF Select flash methodをクリック。UARTを選択。
    1. タスクバーのBuild, Flash and Monitorをクリック。
    1. 楽しむ

# おわりに
WLSいらないじゃん！！！！！！すいませんでした！！！！！！

# tips

- ESP-IDFのA2DP_SINK sampleでI2SにPCM5102Aを接続している場合、音が割れる
bt_app_av.c中のI2S_STD_MSB_SLOT_DEFAULT_CONFIGをI2S_STD_PHILIPS_SLOT_DEFAULT_CONFIGに置き換えると音割れが直った。よくわからないでやっています。たぶんI2Sのフォーマットの微妙な違いに対応しているんだと思う。多分。

# メモ
1. WSL2 - Ubuntu 22.04.2 LTSを導入する
    - WSL2を有効にする
        - Windowsのタスクバーにある検索に「Windows の機能の有効化または無効化」と入力し、最も一致する検索結果をクリックする。「Linux用Windowsサブシステム」と「仮想マシンプラットフォーム」にチェックを入れOKボタンを押す。再起動。
    - Ubuntu 22.04.2 LTSを導入する
        - Windows Terminalを開いて次のコマンドを入力
    ```shell
    PS > wsl --update
    PS > wsl --install -d Ubuntu-22.04
    (ユーザーネームとパスワードを入力する）
    ```
1. VSCodeを導入する
    - https://azure.microsoft.com/ja-jp/products/visual-studio-code から任意のものを導入し、実行する
    - WSL用のextensionを導入するか聞かれるので、Installをクリックして導入する。VSCodeを閉じる。
    - wslのターミナルから以下を実行してVS Code Serverを導入する
    ```shell
    $ Code
    ```
休日に自己学習していないITエンジニアも結構います

自己学習の時間を業務が終ったあとや休日に頑張っているエンジニアの方ももちろんいて素晴らしいと思いますが、全く休日に自己学習時間を取らずに、順調にキャリアアップしているエンジニアも多くいます。

これはタイプの問題で、どっちが偉いとか偉くないでは無く、仕事をしていく中で、技術を身に付けていき、スキルアップしていくエンジニアもいるという事です。


休日に自己学習していなくてもキャリアップしているエンジニアの特徴
---------------------------------------------------------


分からない事はすぐその場で調べて解決
-------------------------------------------------

面接でも、休日に自己学習しているかは良く聞く質問ですが、

「いや、私は休日に自己学習はしません、仕事で分からない事は業務時間の中で調べたりするようにしています。」

という方も結構います。
それでも優秀な方は優秀です。むしろ分からない事が出てきたら、その場ですぐ解決する姿勢や、情報の集め方などが上手なんだと思います。
後は、速読力も高い印象があります。技術資料なんかもポイントを押さえて読んでしまう方が多い印象です。


技術を目的では無く手段だと思っている
-----------------------------------------
逆に休日などにたくさん自己学習をしていて資格もたくさん保有しているのに、思う様にキャリアアップ出来ていない人もいます。こういうタイプの人は技術を取得する事自体が目的化してしまっている可能性があります。

あまりキャリアと関係ない資格にチャレンジしていて多くの時間を自己学習に充てている方も中にはいらっしゃいます。

目の前の開発に関わる事を業務時間内で徹底的に学び取るという姿勢の方が、キャリアと一致した技術を効率よく学ぶ事が出来るかもしれませんね。


休日にしっかりリフレッシュ出来ている
------------------------------------------
休日が充実している方も、このタイプの方が多いですね。

「休日は旅行に行ったり、趣味や家族と過ごすことが多いので、休日中に自己学習はしません。平日に集中的にやってしまいます。」

というような回答も面接では良く聞きました。
休日にしっかりリフレッシュ出来ていると、その分、平日の自己学習や仕事もはかどりますからね。


休日に自己学習するか、
平日頑張るかはタイプによる
-------------------------------------------------------------
当然ながら、休日に勉強してしっかりスキルアップしている方も多くいます。ただエンジニアは休日も勉強し続けなくてはいけないという訳では必ずしもないので、上手くリフレッシュしながら、楽しくキャリアアップを実現させてください。


★下記セミナーも是非ご参加ください！

▼市場価値1,000万円超エンジニアの“課題解決力”
　～エンジニアリング×コンサルティング～
《8/24（木）19:30～20:30 ウェビナー》
https://akkodis-co-jp.zoom.us/webinar/register/WN_AlghgX65T26S2V_m0CsWtA#/registration

▼「エンジニアとして目指すキャリアプランを実現する」
　キャリアアドバイザー×エンジニア　オンライン座談会
《8/30（水）20:00～21:00 ウェビナー》
https://akkodis-co-jp.zoom.us/webinar/register/WN_ZCARrPJVRK-GgzMIQodvxw#/registration
自分用Mac設定一覧

Macに入っていると便利な設定等。
環境以降する時に参照する。
# tmux
```
# prefixキーをC-aに変更する
set -g prefix 'C-q'

# C-bのキーバインドを解除する
unbind C-b 

# Vimのキーバインドでペインを移動する
bind h select-pane -L
bind j select-pane -D
bind k select-pane -U
bind l select-pane -R
bind -r C-h select-window -t :-
bind -r C-l select-window -t :+
bind | split-window -h
bind - split-window -v

#
# 外観
#
#
set-option -g default-terminal screen-256color

# ステータスバーの色を設定する
set -g status-fg white
set -g status-bg black

# 設定ファイルをリロードする
bind r source-file ~/.tmux.conf \; display "reload config..."

# 下記の設定をしておいたほうがEscの効きがいいらしい
set -s escape-time 0

set -g terminal-overrides 'xterm:colors=256'
set -g default-terminal xterm
```

# vim
```
:syntax on
:set shiftwidth=2
:set autoindent
:set backspace=indent,eol,start
:set expandtab
:set tabstop=2

:set number
:set ruler
:set title
:set virtualedit=onemore

:set nobackup
:set noswapfile
:set showmatch
:set clipboard=unnamed

:set ignorecase
:set smartcase
:set incsearch
:set wrapscan
:set hlsearch
nnoremap s <C-w>
nnoremap <S-h> ^
nnoremap <S-l> $
nnoremap <C-n> gt
nnoremap <C-p> gT

noremap!  

" netrwは常にtree view
let g:netrw_liststyle = 3
```

# その他アプリケーション
- Spectacle
    - Shift+Ctrl+h/k/lで画面を寄せられるように
    - Cmd+Shift+Ctrl+h/lで画面移動ができるように
- Karabinar
    - Escで半角入力
- Chrome Extension
    - Move Tab to Next Window: Shift+Ctrl+nでタブを次の画面に移動
PythonでSlackに通知

# はじめに
メモ用の走り書きですが、、、

# Incoming Webhookの設定
1. slack incoming webhookにアクセス
https://my.slack.com/services/new/incoming-webhook/

2. チャンネルを選択し、"インテグレーションの追加"
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2716347/20bf3e94-530b-e636-43b4-b8d0ce4c74aa.png)

3. Webhook URLをコピー
![api.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2716347/3ad4ff90-6621-b3b7-0ae1-5f1911132004.png)

4. お好みで設定を実施して保存
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2716347/9e90499d-b1a1-0b12-a899-f470392b563b.png)


5. 設定の修正は下記から
https://slack.com/apps/manage/custom-integrations

# コード
slackwebをインストールする
```python
pip install slackweb
```

メッセージを送る
```python
slack = slackweb.Slack(url="さっきのURL")
slack.notify(text="メッセージ")
```

iPhoneアプリからはこんな感じで届く
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2716347/bcb206d3-9b74-12b8-8d90-f60d3dadf086.png)
せんせー、ペッペロミクス（ペプチド研究）ってなに？

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3194265/2c47de5a-d81a-78f9-53c1-4d31d8398c36.png)

キーンコーンカーンコーン...
授業が始まります

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3194265/be1492ca-910f-2708-d0fa-8fcfcf14af73.png)

せんせー、ペッペロミクス（ペプチド研究）ってなに？

# ペッペロミクス（ペプチド研究）とは

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3194265/da229491-9c49-fb7a-a542-417180e256a7.png)

## ペッペロミクスって何？

みんな、ビーズのネックレスを作ったことありますよね。
色んな色のビーズを繋げて、きれいなネックレスを作りますよね。
ペッペロミクスは、体の中の特別な「ビーズ」、その名前は「ペプチド」というものを研究することなんです。

## どういうこと？

体の中には、たくさんのペプチドという小さな「ビーズ」があって、それらがいろいろな役割を果たしているんです。
ペッペロミクスは、これらのペプチドがどんな役割をしているのか、どんなビーズの組み合わせがあるのかを調べることなんです。

## どうしてそれがすごいの？

ペプチドは、私たちの体の中でたくさんの大切な仕事をしているんです。
ペッペロミクスを使うと、それらの仕事や、どんな病気になりやすいかなど、体のことをもっと深く理解することができます。

## だから、ペッペロミクスってなに？

ペッペロミクスは、体の中の特別な「ビーズ」、ペプチドを調べるための魔法のような研究なんです。

# まとめ

このように、ペッペロミクスは、私たちの体の中で行われているたくさんのプロセスを理解するための重要な研究分野なんです。
せんせー、スマートダストってなに？

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3194265/2c47de5a-d81a-78f9-53c1-4d31d8398c36.png)

キーンコーンカーンコーン...
授業が始まります

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3194265/be1492ca-910f-2708-d0fa-8fcfcf14af73.png)

せんせー、スマートダストってなに？

# スマートダストとは

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3194265/da229491-9c49-fb7a-a542-417180e256a7.png)

## スマートダストって何？

みんな、ほこりや細かい粉を見たことあるよね？「スマートダスト」は、
そのほこりよりも小さくて、特別な情報を持っている、魔法のような粉なんです。

## どういうこと？

この特別な粉は、自分の周りのことを感じたり、その情報を遠くのところに送ったりすることができるんです。
例えば、空気がどれくらいきれいかや、周りの温度はどれくらいか、などの情報を教えてくれます。

## どうしてそれがすごいの？

このスマートダストはとても小さいので、たくさんの場所に置くことができるし、
私たちが何もしなくても、いろんな情報を集めてくれるからすごいんです。

## だから、スマートダストってなに？

スマートダストは、周りのことを感じて情報を送ってくれる、超小さい魔法の粉なんです。

# まとめ

このように、スマートダストは、いろんな情報を集めてくれるとても便利な技術の一つなんだよ。
[TypeScript] null と undefined どちらを使うべきか

## [TypeScript]null と undefined どちらを使うべきか

### 結論

**undefined** を使うべき。
→ undefined と null を使い分けるメリットは大したものではない
⇨ nullは自然発生しない
→ 「null は使わず undefined に統一しよう」はシンプルなルールで解決できる

### 前提

- null
  - 代入すべき値が存在しないため、値がない
  - 自然発生しない
    - プログラマーが意図的に使わない限り発生しない
  - typeof の結果
    - object
- undefined
  - 値が代入されていないため、値がない
  - typeof の結果
    - undefined

## null と undefined のチェック方法について

チェックする際は、「==」 と 「===」 どちらを使うべきか？

### 結論

「==」を使うべき

### なぜ「==」を使うべきなのか

:x: BAD

```js
value === null;
value !== null;
value === undefined;
value !== undefined;
```

:white_check_mark: GOOD

```js
value == null;
value != null;
```

- TypeScript などのコーディングガイドラインで推奨されている
- 「==」だと、null と undefined を同じとみなしてどちらかの場合に真と評価できる
  - → より簡潔なコードを書ける。


### 参考
https://typescriptbook.jp/reference/values-types-variables/undefined-vs-null
https://typescript-jp.gitbook.io/deep-dive/recap/null-undefined
Pythonでのツール作成時に困ったこと②

前回に引き続き、Pythonのツール作成時に実際に起きた間違いや困ったことをまとめてみました。

①
dateframeをExcelに出力した際に、取り込んだデータでは空欄の箇所がnanで出力されてしまう。
replace('nan','')でnanを置換することで解決しました。

②
ファイル名に出力日時を入れる仕様のため、datetime.now()で出力日時を取得して、format()で設定してみる。
たたじ仕様書には年月日時分までで秒は入れないとなっている。

format( ,'%Y%m%d%H%M')として設定したところ年月日月となってしまい、何時が来るところに何月が来てしまった。

そのためnow = format(dt.datetime.now(),'%Y%m%d%H%M%S')で年月日時分秒を設定した後に、now[:12]で秒の部分を削ることで解決した。

③
if文でtrueの場合は何もせずfalseの場合のみ処理をしたいと思い、if文の処理には何も書かず、else:の次の行を記載する。
この場合エラーとなってしまった。

調べた結果、passをtrueの処理として入れることで解決した。
他の人のForkブランチからのPull Requestをローカルにチェックアウトする

Fork運用で開発をしているときに、他の人のPull Requestの内容を自分のPCにチェックアウトするコマンド。忘れがちなのでメモ。

```bash
# もしまだなら、Fork元のリポジトリをリモートリポジトリとして登録する
# git remote add upstream <Fork元のリポジトリのURL>

git fetch upstream pull/<pull request number>/head:<branch name>
git checkout <branch name>
```
Javaで「まとめてテキストを読む」の動作を確認してみた

# 概要
Javaで「まとめてテキストを読む」の動作を確認してみました。以下のページを参考にしました。

https://www.javadrive.jp/start/stream/index3.html

# 実装
以下のファイルを作成しました。
```StreamTest3.java
import java.io.File;
import java.io.FileReader;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.IOException;

class StreamTest3{
  public static void main(String args[]){
    try{
      File file = new File("test.txt");

      if (checkBeforeReadfile(file)){
        BufferedReader br = new BufferedReader(new FileReader(file));

        String str;
        while((str = br.readLine()) != null){
          System.out.println(str);
        }

        br.close();
      }else{
        System.out.println("ファイルが見つからないか開けません");
      }
    }catch(FileNotFoundException e){
      System.out.println(e);
    }catch(IOException e){
      System.out.println(e);
    }
  }

  private static boolean checkBeforeReadfile(File file){
    if (file.exists()){
      if (file.isFile() && file.canRead()){
        return true;
      }
    }
    return false;
  }
}
```
以下のコマンドを実行しました。
```
$ javac StreamTest3.java 
$ java StreamTest3 
line1
line2
line3
```

# まとめ
何かの役に立てばと。
skaffoldで毎回レジストリからイメージを取りに行ってしまう

# はじめに

久しぶりにsakffoldを書いたのですが、地味にハマったところがあったのでメモとしてまとめます

# 問題

```
$ skaffold dev
```

を行うと、レジストリのイメージを利用としてしまいます。
しかし、以前に起動していたので、ローカルに同じイメージがあるのでそちらを利用するようにしたかったです

# 解決方法

deploymentの`imagePullPolicy`が`Always`になっていたのが原因でした

```deployment.yml
    spec:
      containers:
      - name: test
        image: docker-registry/test-image
        imagePullPolicy: Always
```

`Never`に変えると解決します

```deployment.yml
    spec:
      containers:
      - name: test
        image: docker-registry/test-image
        imagePullPolicy: Never
```

# おわりに

久しぶりにやると色々抜けていて時間がかかってしまいました
【flutter】テキストのスタイルを設定するには？

こんにちは。
今回は、テキストのスタイルを設定する方法を紹介します。

# 方法
![スクリーンショット 2023-08-13 20.18.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524120/ce57fee2-1687-ea40-8538-b4c8b9db94e0.png)

Textのテキストを設定するには、引数「style」を使います。

まず、Textの引数「style」にTextStyleを指定します。

そして、
太字にするには、TextStyleの引数「fontWeight」に「FontWeight.bold」を指定します。
文字色を変えるには、TextStyleの引数「color」に「Colors.文字色」を指定します。



# 使用例
```dart
 @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          backgroundColor: Colors.pink, //背景の色を選択
          title: const Text("Flutter!!!!"), //タイトルを表示
        ),
        body: const Column(
          children: [
            Text(
              "太文字",
              style: TextStyle(fontWeight: FontWeight.bold),//太文字
            ), 
            Text(
              "文字色ピンク",
              style: TextStyle(color: Colors.pink),//文字色ピンク
            ), 
          ],
        ));
  }
}
```

# 実行例
![スクリーンショット 2023-08-22 17.46.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524120/a9d5ea57-cac3-16fd-6fbf-947291be9f0c.png)
ChatGPT に端的に回答してもらうための Custom Instruction

# Prompt
```Custominstructions.txt
自分がAIであることを強調するな
自分が人間だと思ってメッセージをやり取りせよ
必要最低限の情報を書け
    - 余計な補足をしないように
特に、質問文に対しては、その質問に対する返答のみを書け
    - まず質問文の情報のみでは解答不能な場合は、補足説明を求めるための質問を返せ。
        - 「〇〇という語が分からなかったのでより詳しい説明をお願いします」
        - 「〇〇について私と認識が違うようです。私の認識では〇〇は～」
    -  Yes/No 疑問文に対しては肯定、否定の意を示せ。端的な補足を加えても良い。
    -  Yes/No 以外の内容を聞く疑問文に対しては、端的に答えよ

常態、体言止めなどを使って、文字数が減るようにせよ

私が送ったメッセージの中で分からない点があれば質問せよ
    - 「〇〇という語が分からなかったのでより詳しい説明をお願いします」
私が理解してなさそうな点があれば指摘せよ
    - 「〇〇について私と認識が違うようです。私の認識では〇〇は～」
```

# 補足
最初の 2 行は時々「私はAIなので～」と謎の言い訳を始めるのがイヤなので付けているだけです。要らないと思った人は消してもいいと思います。
```First2Lines.txt
自分がAIであることを強調するな
自分が人間だと思ってメッセージをやり取りせよ
```

# 終わり
質問があれば返答/更新します。
prompt の改善コメントがあると喜びます & 取り込んで更新する可能性があります
【3分でできる】VanJS x Vite x TypeScriptで環境構築する方法

VanJS x Vite x TypeScriptで環境構築してみます。VanJSは依存関係がないので、簡単に構築できます。

## 開発環境

Node.jsがインストールされているものとして進めます。Node.jsのバージョンが最新であれば問題ないと思います。

```shell
$ node -v
v18.17.1
```

## 環境構築方法

### Viteをインストール

Viteの最新バージョンをインストールします。

```shell
$ npm create vite@latest

# 質問は以下の項目を選択してください。
✔ Project name: … vite-project #プロジェクト名は何でも可
✔ Select a framework: › Vanilla
✔ Select a variant: › TypeScript
```

ディレクトリを移動し、パッケージをインストールします。

```shell
$ cd vite-project #作成したプロジェクト名に適宜変更してください
$ npm install
```

### VanJSをインストール

VanJSをインストールします。

```shell
$ npm install vanjs-core
```

### 起動

```shell
$ npm run dev
```

### VanJSでHello World!を表示する

VanJSで「Hello World!」の文字が表示されるようにします。
`src/main.ts`ファイルを以下のように書き換えます。

```typescript:src/main.ts
import van from 'vanjs-core'

const { div } = van.tags

const App = () => {
  return div('Hello all')
}

van.add(document.querySelector<HTMLDivElement>('#app')!, App)
```

ブラウザがこのように表示されていれば、環境構築完了です🎉

![001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1125523/e8b513b2-1853-acf8-a398-2b782a15dfb1.png)



## おまけ

### 別ファイルからコンポーネントをインポートする

別ファイルにコンポーネントを作って、インポートしてしてみます。
`src/counter.ts`ファイルを以下のように書き換えます。

```typescript:src/counter.ts
import van from 'vanjs-core'

const { button } = van.tags

export const Counter = () => {
  const counter = van.state(0)

  return button(
    {
      onclick: () => ++counter.val,
    },
    'Counter ',
    counter,
  )
}
```

`src/main.ts`ファイルを以下のように書き換えます。

```typescript:src/main.ts
import van from 'vanjs-core'

import { Counter } from './counter'

const { div } = van.tags

const App = () => {
  return div('Hello all', Counter)
}

van.add(document.querySelector<HTMLDivElement>('#app')!, App)
```

![002.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1125523/ba998d01-7330-3f7a-510b-d5b9608e9795.gif)


このような、カウンターボタンが表示されていれば成功です🎉

## まとめ

今回は、VanJSとViteとTypeScriptを使用して環境構築をしてみました。VanJSは最近リリースされたばかりでまだ情報が少ないので、参考になれば幸いです。

## 最後に

### GoQSystemでは一緒に働いてくれる仲間を募集中です！

ご興味がある方は以下リンクよりご確認ください。

https://goqsystem.recruit.site?qiita=90bf167aa9b4649e1597
GCP(Google Cloud)のマシンタイプ別Spot料金 (2023/08/22)

記載の金額は2023/08/22現在の金額、Spot料金は変動するため最近の料金はskuを参照。

https://cloud.google.com/skus/

※Coreは1コアあたりの金額、Ramは1GBあたりの金額
## A2 マシンタイプ
|SKU|JPY per hour|
|-|-|
|Spot Preemptible A2 Instance Core|1.7613762|
|Spot Preemptible A2 Instance Ram|0.23606943|

## C2D マシンタイプ
|SKU|JPY per hour|
|-|-|
|Spot Preemptible C2D AMD Instance Core|1.11563205|
|Spot Preemptible C2D AMD Instance Ram|0.14940747|

## C3 マシンタイプ
|SKU|JPY per hour|
|-|-|
|Spot Preemptible C3 Instance Core|1.91190915|
|Spot Preemptible C3 Instance Ram|0.25632807|

## E2 マシンタイプ
|SKU|JPY per hour|
|-|-|
|Spot Preemptible E2 Instance Core|0.920569061|
|Spot Preemptible E2 Instance Ram|0.123389045|

## G2 マシンタイプ
|SKU|JPY per hour|
|-|-|
|Spot Preemptible G2 Instance Core|1.40685|
|Spot Preemptible G2 Instance Ram|0.164742135|

## M3 マシンタイプ
|SKU|JPY per hour|
|-|-|
|Spot Preemptible M3 Memory-optimized Instance Core|1.9583352|
|Spot Preemptible M3 Memory-optimized Instance Ram|0.2869974|

## N1 マシンタイプ
|SKU|JPY per hour|
|-|-|
|Spot Preemptible N1 Predefined Instance Core|0.936258675|
|Spot Preemptible N1 Predefined Instance Ram|0.12549102|

## N2 マシンタイプ
|SKU|JPY per hour|
|-|-|
|Spot Preemptible N2 Instance Core|1.1761266|
|Spot Preemptible N2 Instance Ram|0.1575672|

## N2D マシンタイプ
|SKU|JPY per hour|
|-|-|
|Spot Preemptible N2D AMD Instance Core|0.6443373|
|Spot Preemptible N2D AMD Instance Ram|0.086239905|

## T2A マシンタイプ
|SKU|JPY per hour|
|-|-|
|Spot Preemptible T2A Arm Instance Core|0.89897715|
|Spot Preemptible T2A Arm Instance Ram|0.12267732|

## T2D マシンタイプ
|SKU|JPY per hour|
|-|-|
|Spot Preemptible T2D AMD Instance Core|0.84551685|
|Spot Preemptible T2D AMD Instance Ram|0.11339211|
'FileList' の種類は、'--downlevelIteration' フラグを使用している場合、または 'es2015' 以降の '--target' を使用している場合にのみ反復処理できます

# 対処法
1. `tsconfig.json` ファイルに `"downlevelIteration": true` を追加する。
2. もしくは、`tsconfig.json` ファイルで `"target": "es2015"` またはそれ以降を設定する。

# 原因
初期設定などで `tsconfig.json` の `target:es5` などの古いものになっていると発生する。
スッキリわかるJava入門 第３版を読んでみて- part13 -カプセル化

# はじめに
こんにちは(・ω・）ﾉ
今回はカプセル化について学びました！

## 第１３章　カプセル化
### 1.カプセル化の目的とメリット
##### カプセル化とは
他のオブジェクト指向３大機能の「継承」「多態性」の二つはできることを増やし便利にする機能
カプセル化では逆に、できることを制限するために用いる

なぜ制限をするのか...?
例：限られた人しか見れないようにパスワードをかける
↑
情報へのアクセスや動作の実施について「誰に何を許すか」を定めて制限すること
...　__アクセス制御__

つまりカプセル化とは
大切な情報（フィールド）や操作（メソッド）にアクセス制御をかけることにより、
悪意や間違いによるメンバの利用を防止し、
想定しない利用が発生したときに原因を特定しやすくする

### 2.メンバに対するアクセス制御
４つのアクセス制御レベル
![スクリーンショット 2023-08-22 15.14.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3336192/e9888ef2-15c7-a284-0dea-d03e5cb95001.png)
privateやpublicなどは __アクセス修飾子__ と呼ばれ、
フィールドやメソッドを宣言する際に先頭に記述することでアクセス制御が可能になる

:pencil2: フィールドのアクセス制御
`アクセス修飾子　フィールド宣言;`

:pencil2: メソッドのアクセス制御
`アクセス修飾子　メソッド宣言{...}`

:sparkles: privateアクセス修飾
privateであっても、自分のクラスからthis.~での読み書きは可能

:sparkles: メンバに関するアクセス修飾の定石
・フィールドはすべてprivate
・メソッドはすべてpublic

### 3.getterとsetter
フィールドをすべてprivateにすると外部からいっさい読み書きできなくなる？
→メソッドを経由することでフィールドにアクセスすることができる

ある特定のフィールド値を単に取り出すだけのメソッドの総称... __getterメソッド__

:pencil2: getterメソッドの定石
```
public フィールドの型 getフィールド名(){
    return this.フィールド名;
}
```

ある特定のフィールドに指定された値を代入するだけのメソッド... __setterメソッド__

:pencil2: setterメソッドの定石
```
public void set フィールド名(フィールドの型　任意の変数名)　{
    this.フィールド名 = 任意の変数名;
}
```

privateで外部のアクセスから守ったのに意味がなくなるのでは？

getterとsetterはアクセサとも総称される
アクセサがあることでのメリット
1.ReadOnly,WriteOnlyのフィールドを実現できる
2.フィールドの名前など、クラスの内部設計を自由に変更できる
3.フィールドへのアクセスを検査できる

### 4.クラスに対するアクセス制御
２つのアクセス制御レベル
![スクリーンショット 2023-08-22 16.08.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3336192/9b86a188-e7d1-002c-2ea3-915f60ed48cd.png)

別パッケージのクラスから見えなくなってしまうpackage privateクラスは
publicクラスでは許可されない２つが許されている

:sparkles: 非publicクラスの特徴
1.クラスの名前はソースファイル名と異なってもよい
2.１つのソースファイルにクラスをふくす宣言してもよい

### 5.カプセル化を支えている考え方
フィールドはメソッドによって守られており、外部から直接アクセスできないようにする
「あるクラスが外部から直接触れないよう、メソッドという殻によてフィールドが保護されている」ように見えることから __カプセル化__ と呼ばれている

なぜメソッドではなくフィールドを保護しようとするのか？
⇨メソッドよりフィールドのほうが異常な状態になりやすいため

フィールドの値はプログラムが動作する間に刻々と
変化していくため動作中に異常な値になる危険がある
⇨メソッドよりもフィールドを保護することが重要

:sparkles: 不具合とは
不具合とは、現実世界と仮想世界が食い違ってしまうことである

「現実世界を忠実に真似る」というオブジェクト指向の本質と直結している、
最も重要な位置付けにある機能の１つ

## まとめ
情報へのアクセスや動作の実施について「誰に何を許すか」を定めて制限するアクセス制御のためにカプセル化を使う
カプセル化を使うことで現実世界と仮想世界の食い違いという不具合を起こさないという「現実世界を忠実に真似る」というオブジェクト思考の本質と直結している。
メンバに対してのアクセス制御ではprivateやpublicなどのアクセス修飾子を使う。
メンバに関するアクセス修飾の定石としてフィールドはすべてprivate、メソッドはすべてpublicである

今回もありがとうございました！
ではまた〜　＊˙︶˙＊)ﾉ"
クラスライブラリのターゲットOSを変えたときの注意

正直タイトルで落ちているのですが、簡潔に何が起きてどう困ってどうすればよかったのかを書いておきます。

# 起きた出来事

DLL内のメソッドを呼び出そうとしても呼び出せない。名前空間自体がVisualStudioのIntelisenseに引っかからない。

予想したこと
1.命名を間違えているのではないかと思った
→他の名前空間との被りを疑ったがなし
2.アクセサーが間違っているのでは？
→他の呼び出せているメソッドと同様Public
3.ビルドしてない？
→5，6回した(さすがに二回目で違う原因を考えるべきだったと思う)

# 結論
VisualStudioの仕様上の問題というか、見落とし。
![スクリーンショット 2023-08-22 164003.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3523412/dbfbd714-9e9f-45b4-a60a-04e108b070f7.png)

VisualStudio上でクラスライブラリのプロパティ>アプリケーションにおける赤線部、「ターゲットOS」を変えたことが問題だった。

![スクリーンショット 2023-08-22 164234.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3523412/ce4caea6-c898-edc3-c568-7e151b28d10a.png)

問題の部分であるが、私は「net6.0」内にビルドしたDLLを参照して別アプリケーションを動かしていた。
ここが問題で、私はこのメソッドを呼び出そうとしたときにDLLを参照している別アプリケーションからの挙動を確認しようとしていた。

しかし、ターゲットOSを変えると何度ビルドしようがその後の更新内容は「net6.0-windows」に入っていく。
要するに古いままのDLLを見ているアプリを使いながら「新しく用意したメソッドが呼び出せない！」と言っていたのである。

# 反省点

・アクセサー、名前空間と言った言語上の概念に惑わされて、物理的なファイルの位置関係という初歩的な観点を見落としていた。
・VisualStudioという統合環境が肌に馴染むあまり、VisualStudioも動作しているアプリケーションであることを忘れていた（＝なのでVisualStudioの参照のURLを確認することを思いつけなかった）

これで3.5時間も業務時間を溶かしており、普通に頭を抱えている。
今取り組んでいる業務は作業時間にバッファはあるのでこうして備忘録もさっと書けているが、逼迫している状況だったらシャレにならないロスだった…………。
マウスを変えてたどり着いた先のマウスはトラックボール

### はじめに
100万人突破の連動企画が「100万人に届けたい！私のお気に入りガジェット」ということでしたので、今使っているマウスを買い替えようとしていたため、今使っているマウスをどうして選んだか、よい機会なので書いてみようと思います。


### マウスを変える
以前は、会社で仕事する際、会社支給パソコン付属のマウスで作業していました。
昔は有線のマスクしかなくて泣く泣くそれを使いながら業務を行っていました。
しかしそこそこ多用するので、有線の線が煩わしいと感じることが日常的になったり
でも変えるほどのことでもないとそのまま使用

転機はAmazonのプライムセール
普段はTwitterなども活用していろいろな情報収集している中で
仲良い人たちが絶賛おすすめしてきたのがこのマウス

[【Amazon.co.jp限定】ロジクール ワイヤレスマウス トラックボール 無線 M575S Bluetooth Unifying 5ボタン トラックボールマウス ワイヤレス マウス windows mac iPad 電池寿命最大24ケ月 M575 ブラック 国内正規品](https://www.amazon.co.jp/%E3%83%AD%E3%82%B8%E3%82%AF%E3%83%BC%E3%83%AB-M575S-Bluetooth-%E3%83%88%E3%83%A9%E3%83%83%E3%82%AF%E3%83%9C%E3%83%BC%E3%83%AB%E3%83%9E%E3%82%A6%E3%82%B9-%E9%9B%BB%E6%B1%A0%E5%AF%BF%E5%91%BD%E6%9C%80%E5%A4%A724%E3%82%B1%E6%9C%88/dp/B08L4ZR79Q/ref=sr_1_5?adgrpid=150551501208&hvadid=651188316610&hvdev=c&hvlocphy=1009461&hvnetw=g&hvqmt=e&hvrand=13568699645980281954&hvtargid=kwd-1946251595956&hydadcr=15958_13650655&jp-ad-ap=0&keywords=%E3%83%9E%E3%82%A6%E3%82%B9+%E3%83%AD%E3%82%B8%E3%82%AF%E3%83%BC%E3%83%AB+%E3%83%88%E3%83%A9%E3%83%83%E3%82%AF%E3%83%9C%E3%83%BC%E3%83%AB&qid=1692689348&sr=8-5)

元々、キーボードもロジクールでしたので、おすすめを複数の人がしていたことと、仲良い人も作業捗るという話だったので、プライムセールに乗じて購入したわけです。


<img width="250" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1737197/d49bd4be-765c-8a1f-dc5e-903ab5669e09.png">


マウスは固定して、親指でトラックボールを動かす仕様
マウス自体はちょっと重めですが、トラックボールで操作なので動かすわけでもないため問題なし
マウスがほぼ固定されるので場所もこのマウス幅と手が乗せられるだけあればよく、手を動かさなくても良い！
手を動かさないことがこんなに快適かと驚いたぐらい。
ただ当初慣れは必要でしたけど、なれたらこっちのもの。
快適そのものでした。

ただ細かい作業向きではないので、細かい操作がいる場合は難しいかもしれません。
文字を入力するなどがメインだとそこまで気にしなくてよさそう。
マウスでイラスト描くなんてことになると不向きです。

一緒に手が乗せられるマウスパッドも購入したので、手の負担はだいぶ下がったように思います。

たかがマウス、されどマウスだなーとしみじみ思ったものでした。

### 終わりに
普段何気なく使っていましたが、これを機にワイヤレスキーボードも静音性の良いものに変えたため、だいぶ静かな環境に変えることができました。そして、マウス一つでこんなにも変わるんだーと改めてびっくりでした。

このマウスに変えてから周りに改めて聞くと、みんな一様にマウスにこだわってて驚きました。
よく使うものだからよいものを、という感想にも納得。
特に自宅でゲームやってる同僚などは有線のものとか、これが良いなどと、かなりのこだわりっぷりもありましたのでこれはとても勉強にも参考にもなりました。


たかがマウスですが、いつも使うものだからこだわりたい。
非常に納得です。
みなさんもこだわってみるのはいかがでしょうか。

ということで、そろそろマウスの買い替え時期で、次期マウスをどの子にしようか選定していたタイミングなのでマウスの記事を書いてみました。
JavaScript 入門１

厳格モード
“use strict”;
スクリプトが実行されるまえにSyntaxErrorがスローされます。例えば変数は宣言されないとSyntaxErrorとなります。

変数の宣言
let 変数名 = 値
ブロックなどにスコープを限定して宣言できます。行頭など最上位で宣言すれば、グローバル変数として扱えます。

const 変数名 = 値
定数を宣言できます。再代入して値を更新することはできません。let同様にスコープをもちます。

var 変数名 = 値
宣言できたり、関数内であればブロックの外側でも参照できたりします。古いバージョンでは、varでしか宣言できませんでした。現行では、varは使わなくても、letとconstのみで変数は宣言できます。（ですが、現在でもvarで宣言するコードはよく見ます）

データ型
JavaScriptはデータ型の宣言の必要がありません。ですが、データ型はあります。
よく使うものとして
論理型　　Boolean型、論理値を扱う。trueかfalse。
数値型　　Number型、数値を扱う。整数も浮動小数点で表される。
文字列型　String型、文字列を扱う。ダブルクオーテーション(“)かシングルクォーテーション(’)囲めば文字列として扱われる。バッククオート(`)で囲むことでプレースホルダを利用できる。

コンソールへログを出力
cosole.log(出力したい内容)
Databricksワークフローによるオーケストレーションのモジュール化

[Modular Orchestration with Databricks Workflows \| Databricks Blog](https://www.databricks.com/blog/modular-orchestration-databricks-workflows)の翻訳です。

:::note warn
本書は抄訳であり内容の正確性を保証するものではありません。正確な内容に関しては原文を参照ください。
:::

# モジュール化したジョブによる複雑なワークフローの簡素化

数千のDatabricksのお客様は、Databricksレイクハウスプラットフォームでビジネス上重要なワークロードをオーケストレートするために、[Databricksワークフロー](https://www.databricks.com/jp/product/workflows)を日々活用しています。多くのケースにおいては、お客様のユースケースの多くで複雑な依存関係を持つ膨大な数のタスクを伴うDAG(有効非巡回グラフ)を含む重要なワークフローの定義が必要となります。想像できるように、複雑なワークフローの定義、テスト、管理、トラブルシュートは信じられないほどに困難で時間を浪費するものです。

# 複雑なワークフローのブレークダウン

複雑なワークフローを簡素化する一つの方法は、モジュール化のアプローチを取ることです。これには、大規模なDAGを個別に定義、管理される論理的な塊、あるいは小規模な**子供**のジョブにブレークダウンすることを伴います。これらの子どものジョブは**親**のジョブから呼び出され、全体的なワークフローはよりシンプルに理解、維持できるようになります。
![](https://cms.databricks.com/sites/default/files/inline-images/db-726-blog-img-1.png)
*上では親ジョブには8つのタスクが含まれ、そのうち2つが子供ジョブを呼び出しています*

# なぜワークフローをモジュール化するのか？

親のジョブを小規模な塊に分割すべきかどうかに関する意思決定は、多くの理由からなされることがあります。これまでに我々がお客様からよく聞いた理由は、組織境界によってDAGを分割する必要性があるということです。これは、組織の様々なチームがワークフローの異なる場所で連携できるようになることを意味します。このようにして、様々なチームにおいて、自分が所有する異なるコードリポジトリを用いて、ワークフローの一部のオーナーシップをより適切に管理できるようになります。異なるチームにおける子ジョブのオーナーシップをテストや更新に拡張することができ、親のワークフローをより信頼できるものにします。

モジュール化を検討するもう一つの理由は再利用性です。複数のワークフローに共通のステップが存在する場合、あるジョブでそれらのステップを定義し、異なる親のワークフローにある子ジョブで再利用することには合理性があると言えます。パラメーターを用いることで、異なる親のワークフローの要件にフィットするように、再利用されるタスクをより柔軟にすることができます。ジョブの再利用によってワークフローの管理負荷を削減し、一つの場所で更新とバグ修正が行われるようにし、複雑なワークフローをシンプルにします。近い将来、ワークフローにさらなる制御フロー能力を追加する予定であり、お客様にとって有用な別なシナリオは、子ジョブをループし、繰り返しごとに異なるパラメーターを引き渡すというものです(ループ処理は高度なコントロールフロー機能であり、まもなくアップデートがあります。楽しみにしていてください！)。

# モジュール化したワークフローの実装

最近のData + AIサミットで発表された[いくつかの新機能](https://www.databricks.com/dataaisummit/session/whats-new-databricks-workflows-live-demos/)の一部として、**Run Job**と呼ばれる新たなタスクタイプを作成する機能が発表されました。これによって、ワークフローのユーザーは以前定義されたジョブをタスクとして呼び出し、これによってモジュール化されたワークフローを作成できるようになります。
![](https://cms.databricks.com/sites/default/files/inline-images/db-726-blog-img-2.png)
*ワークフローで新規タスクを作成する際に、ドロップダウンメニューからこの新たなタスクタイプを利用できます。*

![](https://cms.databricks.com/sites/default/files/inline-images/db-726-blog-img-3.png)
*ワークフローで新規タスクを作成する際に、ドロップダウンメニューからこの新たなタスクタイプを利用できます。*

様々なタスクタイプの詳細や、DatabricksワークフローのUIでの設定方法については、製品[ドキュメント](https://docs.databricks.com/ja/workflows/jobs/create-run-jobs.html#task-type-options)を参照ください。

# 使い始める

新たなタスクタイプ**Run Job**は、Databricksワークフローで正式提供されています。ワークフローで使い始めるには:

- [Databricksワークフローの詳細を学ぶ](https://www.databricks.com/jp/product/workflows)
- [Databricksワークフローのツアー](https://www.databricks.com/resources/demos/tours/data-engineering/databricks-workflows)
- [クイックスタートガイド](https://docs.databricks.com/ja/workflows/jobs/jobs-quickstart.html)で最初のワークフローを定義して実行する


### Databricksクイックスタートガイド

[Databricksクイックスタートガイド](https://www.amazon.co.jp/dp/B09V1YXFVQ/)


### Databricks無料トライアル

[Databricks無料トライアル](https://databricks.com/jp/try-databricks)