OmniAICreator/Qiita-1.07M huggingface dataset:
AWS GlueのCrawlerのCSV/JSON/Parquetにおける挙動の違いを確かめた手順

S3上のCSVファイルのスキーマが変更された際に、Athenaのクエリが変な動きをしているることがわかりました。

どうも、AWS GlueのCrawlerではCSVのスキーマの変更を上手く扱えないように見えました。
今までJSONやParquetなら大丈夫だったので、その辺り含めて検証した方法のメモです。


# CSV/JSON/Parquetのファイルを生成

以下のようにPythonスクリプトで生成してみました。Google Colabなどで動かすとPC上の環境無しでも動かせます。

PC上で動かす場合は、pipでpyarrowのインストールが必要です。

```python
import csv
import json
import pandas as pd
import pyarrow as pa
import pyarrow.parquet as pq

cases = [  
         ("c0", {"a":1,"b":2,"c":3,"d":4}), 
         ("c1", {"a":1,"b":2,"c":3,"c1":99,"d":4}), 
         ("c2", {"a":1,"b":2,"c":3,"d":4,"d1":99}), 
         ("c3", {"a":1,"b":2,"d":4,"d1":99}), 
         ]

for c in cases:
  case = c[0]
  data = c[1]

  # CSV出力
  with open(f"{case}.csv","w") as f:
    w = csv.DictWriter(f,fieldnames=list(data.keys()))
    w.writeheader()
    w.writerow(data)

  # JSON出力
  with open(f"{case}.json","w") as f:
    json.dump(data,f)

  # Parquet出力
  pq.write_table(pa.Table.from_pandas(pd.DataFrame({k:pd.Series(v) for k,v in data.items()})),f"{case}.parquet")
```

ケース毎のCSV/JSON/Parquetファイルができました。

```sh
$ ls -1
c0.csv
c0.json
c0.parquet
c1.csv
c1.json
c1.parquet
c2.csv
c2.json
c2.parquet
c3.csv
c3.json
c3.parquet
```


# S3にアップロードしてGlue Crawlerでクローリング
S3に以下のようにアップロードします。

```sh
BUCKET=bucket-name
aws s3 mb s3://${BUCKET}
for c in $(seq 0 3);
do
  aws s3 cp c${c}.csv s3://${BUCKET}/csv/case=${c}/
  aws s3 cp c${c}.json s3://${BUCKET}/json/case=${c}/
  aws s3 cp c${c}.parquet s3://${BUCKET}/parquet/case=${c}/
done
```

以下のようにすると、csv/json/parquetというテーブルがcaseパーティション付きで作成されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116068/9c3a9a5a-8b4e-8272-0b63-49cb354d3053.png)



# Athenaで検索してみる
CSVとJSONとParquetをクエリしてみると、CSVだけ値がズレてしまっているのがわかります。

元々はこの挙動を確認するための手順でしたが、後々使えそうなので残しておきます。

```sql
SELECT * FROM "testdb"."csv" ORDER BY "case";
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116068/a47aaa39-97e6-1442-448a-9267648cad6d.png)

```sql
SELECT * FROM "testdb"."json" ORDER BY "case";
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116068/be0b7b9c-b61e-c8ec-faa8-dd50e135e02f.png)

```sql
SELECT * FROM "testdb"."parquet" ORDER BY "case";
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116068/7014e6a3-a495-bd81-b774-889cd0a81b9d.png)
KVM で qcow2 イメージの中に含まれる root のパスワードを変更したい

これで行けるらしいです。root のパスワードを root に変更しています。

```
[root@kvm VM]# virt-customize -a CentOS-7-x86_64-GenericCloud.qcow2 --root-password password:root
[   0.0] Examining the guest ...
[  27.7] Setting a random seed
[  27.7] Setting passwords
[  29.3] Finishing off
```
小道具：テーブル生成用書式出力

一覧の可読性を向上させるための小道具。

```python:Python
def format_list(data, *, width=16, prefix='',
                datafmt='%s', msgfmt='%#s', separator=',', space=1, suffix='\n'):
    space = ' ' * space
    fmtdata = [datafmt % d for d in data]
    msgfmt = msgfmt.replace('#', str(max(len(s) for s in fmtdata)))
    msglist = [(msgfmt % d) + separator for d in fmtdata]
    return ''.join((prefix + space.join(msglist[i:i+width]) + suffix)
                   for i in range(0, len(msglist), width))
```

```python:Python
print(format_list(range(44)))
print(format_list(range(44), msgfmt='%-#s', space=2, prefix=(' ' * 4)))
print(format_list(range(44), datafmt='%#04x', width=8))
```

```console:結果
 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43,

    0 ,  1 ,  2 ,  3 ,  4 ,  5 ,  6 ,  7 ,  8 ,  9 ,  10,  11,  12,  13,  14,  15,
    16,  17,  18,  19,  20,  21,  22,  23,  24,  25,  26,  27,  28,  29,  30,  31,
    32,  33,  34,  35,  36,  37,  38,  39,  40,  41,  42,  43,

0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
0x28, 0x29, 0x2a, 0x2b,
```
STM32L010で来年(2022)のカレンダーをシリアルに表示する。2(例題の為の例題)(ダメな例)



目的
例題の為の例題(ダメな例)

簡単な説明
二重ループで月ループ、日ループ31で
月が全て31なのは、不正解だけど一歩前進
この段階では、海の様な広い心が必要　「絶対!!」に必要なすステップ

いろいろが今回長い　まー　分かっていると思うげど　お約束

Apache Log4jで制作者をたたきまくっているけど
叩いている方が悪い　(立場上)

1.お金を出す
2.デバッグに協力する
3.開発に参加する
4.サポートに参加する
5.使わない

いろいろあったみたいだが　「協力しないで」「使っていて」「叩く」のは
おかしい　立場上「絶対に認められない」「一生絶対に忘れない」
「一生絶対に許さない」(怒る教授)

開発のこみにてーを見ていて思ったのだが

アメリカで大規模無料ソフトが存在するのは、寄付の文化があり
みんなが1ドルから気軽な寄付をしている。
1ドルの寄付でレポート用紙6枚の要求書を出す人もいるが例外だった
60万ドル出していても名前を協力者リストに出してくれれば
いいと言う人もいた。
ほとんどは、1ドルの投げ銭
ボランティアが日本でいうボランティアではない。


![o_con165.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/6b936758-6294-7caf-782a-41645b3c08e3.jpeg)




```c++




#include "mbed.h"

RawSerial pc(PA_2, PA_3); //010

int main()
{

    // ループ 月
    for( int ii = 1 ; ii <= 12 ; ii++  ) {
    
    //月の出力
    pc.printf( "\r\n%d\r\n",  ii  );
    pc.printf( "\r\n"  );

    // ループ 日
        for( int jj = 1 ; jj <= 31 ; jj++  ) {

            //文字列出力
            pc.printf( "%d ",  jj  );
            
        } //for jj 日

    } //for ii 月

    //無限ループ マイコン的停止処理
    while(1) {};

} //main

//容量削減
void error(const char* format, ...) {}




```
Power Query SPOリストでハマった話

## 初めてのPower BI
SharePoint Onlineリストを使ったPower BIレポートを作りました。Power BI Desktop(以降Desktop)をダウンロードしてPower QueryでデータをコネコネしてWeb Serviceに発行しました。（大事なことが抜けている！？）


## DesktopとWeb serviceの値が違う
上司より数字がおかしいと連絡あり。確かに値が変わってます。ただDesktopで見たところ、特に問題なし。なので再度Webに発行。ただまたおかしくなります。発行直後は問題なし、スケジュールの更新で更新するとおかしくなることがわかりました。
いつも特定の値がおかしくなります。
   　　　   　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　
## Microsoftサポートに聞く
レポートを簡易化し要因を特定することをお勧めされました。項目を減らす、リレーションを取る、参照するデータベースを減らす、、　　　　　　　　　　　　　　　　　　　　　　　   　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　
見つけました！フィルターに使ってるbooleanの項目を取ると値が変わりません。

## 原因
SharePoint Onlineリスト上のboolean項目True/Falseをフィルターに使っていましたが、Power Query上にはAny型に変換され誤った値が表示されました。
私の場合、DesktopではAny型であっても正しく処理されていましたが、Webではだめでした。
DesktopとWebで値が変わることがあるなんて思いもしませんでした。
解決まで**2か月**かかりました。。
[MS Power Query Docs](https://docs.microsoft.com/ja-jp/power-query/connectors/sharepointlist "Qiita Home")
>SharePoint リスト コネクタを使用する場合、ブール値は、Power BI Desktop および Power BI サービス環境では TRUE/FALSE または 1/0 として一貫性を持たなくなります。 これにより、間違ったデータ、不適切なフィルター、空のビジュアルが発生する可能性があります。


## 型変更は必ず実施しましょう
やらないと正しい結果がでないことがあります。
私自身も正しく型を変更するよう何度も聞いていました。ただ項目が200以上あるようなテーブルでめんどくさい気持ちからやっていませんでした。

石川さんも書かれてました。
[Power BI Advent Calendar 20216日目 正しいデータの型を](
https://qiita.com/ishiayaya/items/5647c7b481603e9c5c14#%E6%AD%A3%E3%81%97%E3%81%84%E3%83%87%E3%83%BC%E3%82%BF%E3%81%AE%E5%9E%8B%E3%82%92"Qiita Home")
Spring Boot 2.5 -> 2.6 に上げるときに Mockito のバージョンアップで困った話

本記事は [NECソリューションイノベータ　Advent Calendar 2021](https://qiita.com/advent-calendar/2021/nec_solution_innovators) の 12/20 の記事です。

こんにちは。

先日 Spring Boot を 2.5.3 から 2.6.1 にバージョンアップする機会があったのですが、単体テストが通らなくなって困った話をします。

## テストが通らねぇ・・・

Spring Bootをバージョンアップして `mvn clean test` とすると・・・。

むむむ・・・。

```bash
java.lang.NoSuchMethodError: org.mockito.Answers.get()Lorg/mockito/stubbing/Answer;
	at org.powermock.api.extension.listener.AnnotationEnabler.standardInject(AnnotationEnabler.java:85)
	at org.powermock.api.extension.listener.AnnotationEnabler.beforeTestMethod(AnnotationEnabler.java:55)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
```

これは謎・・・。

## ぐーぐる先生に聞いてみよう

ぐーぐる先生に頼ります。
私は結構（いやかなり）横着なので、エラー内容をそのままコピペして検索しちゃいますｗ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/157029/7feaa00b-9d5e-55a5-4598-1475a8d0a079.png)

ふむふむ・・・✧φ(ロ-ロ๑)

GitHub に [Issue](https://github.com/powermock/powermock/issues/1109) が上がってました。

https://github.com/powermock/powermock/issues/1109


Mockito のバージョンが上がったことで PowerMock との互換性がなくなったみたいですね。
バージョンダウンもワークアラウンドとしてあるようですが、これまで PowerMock に頼っていた静的メソッドのモッキングがMockitoでもできるようになったということで、せっかくなのでこれを試してみようと思います。

## いざ実践

これを・・・

```java
@RunWith(PowerMockRunner.class)
@PrepareForTest({ ClassA.class })
public class staticTest {

  @Test
  public void test() {
    PowerMockito.mockStatic(ClassA.class);
    when(ClassA.methodStatic()).thenReturn("OK!!");
    // 以下略
  }

}
```

こう書き換えます。

```java
public class staticTest {

  @Test
  public void test() {
    try (MockStatic<ClassA> mocked = Mockito.mockStatic(ClassA.class)) {
      mocked.when(() -> ClassA.methodStatic()).thenReturn("OK!!");
      // 以下略
    }
  }
}
```

`try` で囲まずに最後にモックをクローズ（この例でいうと `mocked.close()` ）する記法もあるのですが、 `try` で囲むとスコープが限定されてわかりやすいですし、クローズ漏れもなくなるのでこの記法を採用しました。

で、再テスト。

```
[INFO] Results:
[INFO]
[INFO] Tests run: 171, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 01:04 min
[INFO] Finished at: 2021-12-xxTHH:mm:ss+09:00
[INFO] ------------------------------------------------------------------------
```

テストをパスしました！

## まとめ

Spring Bootってマイナー以上のバージョンを上げるとき、テストフレームワーク起因の非互換が発生することがちょいちょいあるんですよね。
これからもバージョンを上げるときは覚悟して挑みたいと思います（笑）

## 参考

- [powermock-api-mockito2 does not work with Mockito 4 due to using deprecated API(s) - GitHub](https://github.com/powermock/powermock/issues/1109)
PySdie、PyQtをpytestする際に、pytest-qtを使う

:::note info
こちらは、以前（2021.01.01）に別サービスで展開した内容を Qiita に移行したものです。
:::


# はじめに

以前、 「[PySide & Pytest での テスト駆動開発 スタートアップ](https://qiita.com/takavfx/items/98e6633af4f1fae1576a)」にて、PySide + pytestする方法をまとめたが、以下のようなものをやっていた。

まずconftest.pyで、fixtureとして次を登録し、

```python:conftest.py
@pytest.fixture
def base_window():
    app = QApplication()
    mainWindow = QMainWindow()
    mainWindow.show()
    return mainWindow
```

テストで、それを利用して、ウィジェットのスモークテストを行う

```python:test_widget.py
def test_addWidget(base_widget):
    from MyCustomPySideLib,QCustomWidgets import QMyWidget
    tagWidget = QMyWidget()
    base_widget.setCentralWidget(tagWidget)
```

ということをしていたが、どうやら別の方法を提供している人もいるらしいという事で調べてみた。

# pytest-qtの導入

[pytest-qt](https://pytest-qt.readthedocs.io/en/latest/index.html)で、こういったところをシミュレートできる。
pytest-qtは、[pytestのプラグイン](https://docs.pytest.org/en/latest/plugins.html)として扱われる。

インストールは、pipで行える。

```shell
pip install pytest-qt
```

# pytest-qtを使って書く

pytest-qtを使ってはじめのテストコードを書き直すとこうなる。

## Widgetの追加テスト

```python:test_widget.py
def test_addWidget(qtbot):
    from MyCustomPySideLib,QCustomWidgets import QMyWidget
    myWidget = QMyWidget()
    qtbot.addWidget(myWidget)
```

ここで引数として使用されている`qtbot`が、pytest-qtをインストールすることによって使用できる用になるfixtureとなる。
この`qtbot`は、人の操作によるテストに加えて、Qt側のもろもろのテストとエラーに対するキャプチャ機能を備えている。

例えば、エラーをキャプチャする際にはこんなかんじ。

```python
with qtbot.capture_exceptions() as exceptions:
    qtbot.click(button)
```

## シグナル待ちを含めたテスト

長時間処理を行う場合でのシグナル待ちや別スレッド処理中のシグナル待ちなどを含めたテストを書くこともできる。

```python
def test_long_computation(qtbot):
    app = Application()

    with qtbot.waitSignal(app.worker.finished, timeout=10000) as blocker:
        blocker.connect(app.worker.failed)
        app.worker.start()
	
    assert_application_results(app)
```

## 特定の状態待ちテスト

例えば、「ウィンドウのステータステキストが『Please input a number』になってなっているか」といったテストを書きたい場合、次のように書ける。

```python
def test_validate(qtbot):
    window = MyWindow()
    window.edit.setText("not a number")
    window.edit.setFocus()

    def check_label():
        assert window.status.text() == "Please input a number"

    qtbot.waitUntil(check_label)
```

出力はこんな感じ

```shell
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    def check_label():
>       assert window.status.text() == "Please input a number"
E       AssertionError: assert 'OK' == 'Please input a number'
E         - OK
E         + Please input a number
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
>       qtbot.waitUntil(check_label)
E       pytestqt.exceptions.TimeoutError: waitUntil timed out in 1000 miliseconds
```


# まとめ

PySideのふるまいに関して、それぞれまじめにテストを書くという手もあるが、エラーキャプチャ周りや、スレッド分けしたものを追っていく、またはその方法を作るのは大変なので、このプラグインを使用することによって、その手間を省いてくれるのはありがたい。
ドキュメントを読んでいくと、まだまだ機能がある様なので、いろいろ試してみての恩恵具合を見てみたいところ。
JupyterLabでオートコンプリート(Kite)を導入する

:::note info
こちらは、以前（2021.02.06）に別サービスで展開した内容を Qiita に移行したものです。
:::

# はじめに

本来はこちらの記事は「ドキュメントを読めばいい」で済むが、インストールする過程でエラーが発生したのと、一応のそれへの対処のメモとして残しておく。

https://twitter.com/auratus/status/1356982450556080132

## 開発環境

> Windows 10
> Python 3.7.8
> jupyterlab 3.0.7
> jupyterlab-kite 2.0.2
> jupyterlab-server 2.1.3

# インストール方法

1. Jupyter Labのインストール
	```shell
	pip install jupyterlab
	```
2. Kiteのインストール
	[インストーラーを使用](https://www.kite.com)してインストール。
4. NodeJSのインストール
	[インストーラーを使用](https://nodejs.org/ja/)してインストール。
	テーマパッケージのビルドにwebpackなどを使用していたり、TypeScriptで書かれているケースもあり、npmビルドが必要になるため。
	因みに、僕は通常のインストーラーでバージョン管理ができなくなるのが嫌いなので、[nvm-windows](https://github.com/coreybutler/nvm-windows)でインストールしている。
6. JupyterLab KiteとJupyterエクステンションのインストール
	```shell
	pip install "jupyterlab-kite>=2.0.2"
	jupyter labextension install "@kiteco/jupyterlab-kite"
	```
	こちらJupyterLabのバージョンに応じて、バージョン指定があることもあるので、[インストールドキュメント](https://github.com/kiteco/jupyterlab-kite)も参照すること。

:::note alert
ドキュメント的には、`pip install "jupyterlab-kite>=2.0.2"`のみですべてインストールされるように書かれているが、個人環境だとエクステンションまでのインストールはしてくれなかったので、追加で拡張機能のインストールコマンドを実行した。
:::

# 実行

通常通りにJupyter Labを実行する。

```shell
jupyter lab
```

![we5v3rkfm7zcd4oa1vunkpwovtx6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51857/6ff1247e-7065-e11f-196a-a2912c2bcaff.png)


# トラブルシュート

## CP949 encoding error

　次の様なエラーメッセージが発生する。

```shell
File "f:\develop\.venv\lib\site-packages\jupyterlab_server\config.py", line 37, in get_federated_extensions
    pkgdata = json.load(fid)
File "C:\Users\takanori\AppData\Local\Programs\Python\Python37\lib\json\__init__.py", line 293, in load
    return loads(fp.read(),
UnicodeDecodeError: 'cp932' codec can't decode byte 0x82 in position 523: illegal multibyte sequence
```

### 原因

`jupyter-server` モジュールのJSONリードするためのファイルの開き方が、JSONがマルチバイトの文字を読めないにも関わらず生の状態で開かれてしまっている。

### 解決方法

#### 方法1

ソースを書き換える。

`<Lib Root>\site-packages\jupyterlab_server\config.py`

を、以下の様に書き換える。

```python
def get_federated_extensions(labextensions_path):
    ~~~
            with open(ext_path, encoding="utf-8") as fid:
                pkgdata = json.load(fid)
    ~~~
```

#### 方法2

こちらの問題、本家のレポジトリにIssue/PRを出して、Approve/Merge済み。

https://github.com/jupyterlab/jupyterlab_server/issues/155

https://github.com/jupyterlab/jupyterlab_server/pull/158

`jupyterlab-server==2.1.5` で適応されているので、jupyterlab-serverをアップデートする。

```shell
pip install -u jupyter-server==2.1.5
```


# 最後に

とりあえず、そこまで問題なく導入ができた。
コンプリート機能も結構いい感じに補完してくれるKiteさんなので、これからも付き合っていきたいところ。
gitサーバを構築して開発するときのssh接続について

gitサーバを家に建てたくなったのでついでにsshで公開鍵認証onlyでアクセスするようにしてみたときの雑記
(単純にあとからやり直そうとした際に忘れそうなので書きます)

# 構築の流れ

- サーバ側にgitをインストール
- adduser git(正直個人的にはrootでもいいと思ってる) && su git
- サーバの容量の大きいディスクをマウント，gitユーザのhome配下の適当な場所にバインド
- バインドしたフォルダの任意の場所でgit init --bare --share=true
- groupadd {グループ名} で任意のグループを作成(これがリポジトリ開発者のグループ)
- gpasswd -a {ユーザ名} {グループ名}でグループにリポジトリ開発者を追加
- リポジトリの所有権限を作成したグループにしておく
- 公開鍵をサーバに登録
    - ssh-copy-id -i ~/.ssh/id_rsa.pub [リモートユーザー]@[リモートサーバーのホスト名] ←linux to linuxならこれが早い
    - windowsの場合は物理で頑張るなり，一時的にsshへのパスワード認証許可だったりで公開鍵を渡す
- クライアント側でも.ssh/configを作成してアクセスを簡単にする

```
host ${hostname}
user ${remote user id}
hostname ${server ip or domain}
port ${sshのポートを変えてなければ22}
IdentityFile ${秘密鍵へのパス}
```

configを作成しておくとsshでgit cloneする際にgit clone ssh://hostname/サーバのリポジトリまでのパス
で済むので便利
海外との多拠点開発の話 - 開発のための通翻訳チームの挑戦を振り返る

[海外との多拠点開発の話 - 東京で開発のための通翻訳チームを立ち上げたことを振り返る - Qiita](https://qiita.com/e99h2121/items/24f7beb0ee847332331e) の続き。
具体的にチャレンジした内容を書いてみます。

## 様々な試み...

### 1. 通翻訳者と寺子屋を開催する

- 毎日 9:00-10:00。講師: 通訳、翻訳各位。
- 寺子屋なので、基本は自学自習。出入り自由、スポット利用歓迎。
- 場所: 開発フロア フリースペース(翻訳チーム座席横) 。
- ルール: 各自、解決したい課題を持ってくる。時間内、先生に個別レクチャーしてもらえる場とする。
- 朝方生活を推奨する。

#### シチュエーション例

- 海外事業所メンバーに自己紹介したく考えてみたがこれでナチュラルに表現出来ているだろうか？
- 締切りの調整等の微妙なニュアンスを伝えたい文章を書いたが適切に表現できているだろうか？
- 自分のレベルでお勧めの本とか勉強法を教えてほしい etc

What is Terakoya?:https://en.wikipedia.org/wiki/Terakoya

### 2. 「日本語」を直す

- 論理的なドキュメント、読みやすいドキュメントを書く。
- 口語をドキュメントに使わない。
- お客様名を正しくお客様名と分かるようにする。(E.g. ○○さん, ○○ -> ○○コーポレーション様 etc)
- 人名、社員名を正しく人名と分かるようにする。議事録でニックネームを使わない。
- 機能名を極力機能名と分かるようにする。略さない。
- その場の「文脈がわかる人」にしか分からないような口語をドキュメントで使わない。
- 主語を明確にする。
- 「、」を適切な位置で行う。

これらができるだけでも「Google翻訳」が使いやすくなるという試み。


### 3. 業界用語・社内用語辞書を整備する。

#### 業界用語

[不思議の国のSE用語 - Qiita](https://qiita.com/t_nakayama0714/items/478a8ed3a9ae143ad854) に準じ、以下など。

- 上げる -> Version upgrade
- 叩く -> 実行する
- 蹴る -> 実行する
- 回す -> 実行する
- 落ちる -> エラーになる、中止される
- 落とす -> 止める、ダウンロードする
- (プロセスを) 切る -> 止める
- (チケットを) 切る -> 発行する
- 引く -> 検索する、取得してくる
- 持ち方 -> データのでき方
- 走る -> 実行される (run)
- 発火する -> 起動する (invoke)
- 飛ぶ -> データが消える
- 串ざし -> いくつかのレコードを指定条件で検索し束ねて取得すること

#### 社内用語辞書

- 以下の解決を目論む。
    - 用語の標準がないため、言葉を好きなように翻訳してしまう。
    - 結果コミュニケーションミスが発生する。
    - 各用語が再利用できておらず、各チームが時間とコストを浪費している。
    - 各用語の質に矛盾、不統一があり、それがドキュメントやプロダクトの信頼性に影響している。
- 日英中の対訳だけでなく、日日・英英…で用語の定義を管理できる。
- 各プロジェクトにて別の意味を持つ用語をそれぞれのプロジェクト毎に管理できる。
- アカウントを作成できる。
- 検索にはログイン不要。ログインすると「boo!」ボタンを操作でき、Upvote、Downvoteができる。

 

### 4. 「技術翻訳のチェックポイント」をチェックする。

- [実践テクニカルライティング - 開発者が「外国語」を使うときの言語技術達3つ - Qiita](https://qiita.com/e99h2121/items/aa87cddd0ff57ff98e5b)
- [すぐに身につく、技術翻訳のチェックポイント：日立インフォメーションエンジニアリング](https://www.hitachi-ife.co.jp/solution/translation/column/index.html)

(引用) 以下に気をつけよというようなこと。

> 1. 冠詞(a/an/the)の不適切な使用
2. 用語が不明瞭、不正確、または不適切
3. 単数、複数間違い
4. 文法間違い
5. 誤訳のために事実と違っている英語
6. 不正確、不必要、または不自然な前置詞
7. 不自然な英語
8. 句読法間違い
9. 明瞭な動詞構文が必要
10. 綴りエラー
11. 修飾語句の対象が不明瞭または間違っている
12. 用語が推奨翻訳辞書と矛盾している
13. 不明瞭、または不可解な文
14. スタイルガイドに相反
15. 不統一な用語や句
16. 不明瞭:語順が読み手を混乱させる
17. 受動態:不必要な受動態の使用
18. 不明瞭:指示語(it, they)が不明瞭、または不正確
19. 主語と動詞の不一致
20. 不統一:並列でない構文
21. 類語反復または不必要な繰り返しを含む文
22. 不明瞭:動作主または主体が不明瞭
23. 事実に反するエラーまたは矛盾
24. 用語の修飾語句が多すぎる
25. 用語または略語が未定義
26. 不明瞭:動作の目的語が不明瞭
27. 不明瞭:文が長すぎて難解

## 結果

実務的には [アプリをローカライズする時の見積もり - 翻訳外注 - Qiita](https://qiita.com/e99h2121/items/2d23ef33dfaa2797c363)。
色々やりました。意図はどれもこれも悪くはないと思っている。

が！**これだけでは、** 劇的な改善はなかった！
というのが冷静な振り返りである。次記事でその闇を深堀る... 。
シェルスクリプト case文

case $var in #$varはチェックする変数
　パターン1) #$varがパターン1に該当する場合に実行される
　　プログラム1;;
　パターン2) #$varがパターン2に該当する場合に実行される
　　プログラム2;;
　*) #$varがパターン1にもパターン2にも該当しない場合に実行される
　　プログラム3;;
esac

パターンの記載方法
[a-z]:a-zまでの場合
[A-Z]:A-Zまでの場合
[0-9]:0-9までの場合
microk8sが入っているVMを再起動するとkubernetesのcertsが毎回切れる件

# 現象:microk8sが入ったVMを再起動するとkubectlコマンドが使えなくなる
```
taka@microk8s-vm:~$ microk8s kubectl get all
Unable to connect to the server: x509: certificate has expired or is not yet valid: current time 2020-05-03T23:53:06Z is after 2021-12-16T16:38:01Z
```

```
taka@microk8s-vm~$ sudo microk8s.refresh-certs -c
The CA certificate will expire in 365 days.
```

証明書は生きているのになぜ....

```
taka@microk8s-vm~$ sudo microk8s.refresh-certs -i
```

すると

```
Backing up certificates under /var/snap/microk8s/1385/var/log/ca-backup/
Creating new certificates
Signature ok
subject=/C=GB/ST=Canonical/L=Canonical/O=Canonical/OU=Canonical/CN=127.0.0.1
Getting CA Private Key
Signature ok
subject=/CN=front-proxy-client
Getting CA Private Key
1
Creating new kubeconfig file
Stopped.
Started.

The CA certificates have been replaced. Kubernetes will restart the pods of your workloads.
Any worker nodes you may have in your cluster need to be removed and re-joined to become aware of the new CA.
```
証明書が更新されます．

# しかし.....
この挙動は再起動すると再現してしまいます．．．

```
taka@microk8s-vm:~$ microk8s kubectl get all
Unable to connect to the server: x509: certificate has expired or is not yet valid: current time 2020-05-03T23:53:06Z is after 2021-12-16T16:39:01Z
```


```
taka@microk8s-vm~$ sudo microk8s.refresh-certs -c
The CA certificate will expire in 730 days.
```
あれっ?更新期限伸びてね?????? && 状態治ってなくない???
テストようならこんな感じでよいかもしれない....

```
kubectl --insecure-skip-tls-verify cluster-info dump
```
追加の調査必要そう...
【React】fetchを使ってapiからjsonデータを取得する（GETメソッド）

今回は簡単にReactでfetchを使って、apiからjsonデータを取得する方法を教える。つまり、GETメソッドの方法。

## 手順
1\.　React appを作成

2\.　Fetch.jsにコード入力

3\.　App.jsにコード入力

4\.　結果


## React appを作成
```
$ npx create-react-app my-app
＄ cd my-app
＄ yarn build
$ yarn start
```
* もし、npmの場合は

```
$ npx create-react-app my-app
＄ cd my-app
＄ npm run build
$ npm start
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2312213/0d1f22cc-f039-a60f-b2d9-815d15bcddd6.png)
これで簡単にReact appが成功できた。

## Fetch.jsにコード入力
次はsrcの中のFetch.jsファイルを作成し、以下のコードを追加する。
（今回は関数コンポーネントを使っています。）

```
import React, {useState, useEffect} from 'react'

const Fetch = () => {

    const [posts, setPosts] = useState([])

    useEffect(() => {
        fetch('https://jsonplaceholder.typicode.com/posts', {method: 'GET'})
        .then(res => res.json())
        .then(data => {
            setPosts(data)
        })
    },[])

    return (
        <div>
            <ul>
                {
                    posts.map(post => 
                    <li key={post.id}>{post.title}</li>
                    )
                }
            </ul>
            
        </div>
    )
}

export default Fetch;
```
fetch('　')の文字列の部分に、叩きたいAPIのURLを記述する。
今回はdummyとして、（ https://jsonplaceholder.typicode.com/posts ）を使っている。

→ もしlocalhostのAPIの場合、例えば
( http://localhost:3000/posts )の時、package.jsonファイルの中に
"proxy": "http://localhost:3000", を追加し、fetch('/posts')をする必要がある。

fetchメソッドを使う場合、メソッドの指定は{}を使う。今回はGETメソッドなので{method: 'GET'}としておく。
.thenでレスポンスを取得する。

##App.jsにコード入力
最後にsrcの中のApp.jsにコードを追加する。

```
import logo from './logo.svg';
import './App.css';
import Fetch from './components/Fetch';　　　　　　　　　　　//　⇦ ここを追加した

function App() {
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <Fetch /> 　　　　　　　　　　　　　　　　　　　　　　//　⇦ ここを追加した
        <p>
          Edit <code>src/App.js</code> and save to reload.
        </p>
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>
      </header>
    </div>
  );
}

export default App;
```
表示したくないもののコードは削除しても構わない。

## 結果
以下のように実行したら、成功。🎉

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2312213/06ad2a3c-5583-31de-9aeb-557a754a9ac5.png)
Chrome拡張のUnchecked runtime.lastError: Could not establish connection. Receiving end does not exist.というエラーを解決する。。。終点

<ul>
<li><h3>事の発端</h3></li>
<p> Chrome拡張機能を開発している時に、拡張機能が実行されたら開いているページの<br>URLを取得してそれに対して非同期処理実行する必要がありました。
<br>
<br>
URLの取得自体は、popup.jsの中にchrome.tabs.queryで取得できるのですが、<br>
非同期処理はbackground.jsに宣言したため<br>
background.jsとpopup.jsで通信する必要がありました。<br>
<br>
しかし、popup.jsでchrome.runtime.sendMessageを使って
background.jsに送信し、<br>background.jsでchrome.runtime.onMessage.addListener
を使って受信し、<br>sendResponseで送り返しているはずなのですが、時々<br>
Unchecked runtime.lastError: Could not establish connection. Receiving end does not exist.<br>というエラーが表示されていました。

</p>
<li><h3>解決方法</h3></li>
<p>私の場合、マニフェストファイルの以下の部分を<br>
 <strong> "content_scripts": [<br>
    {<br>
      "matches": ["http://*/*", "https://*/*"],<br>
      "js": ["js/background.js"]<br>
    }<br></strong>
以下のように変更することで解決できました！<br>
   <strong>"content_scripts": [<br>
    {<br>
      "matches": ["http://*/*", "https://*/*"],<br>
      "run_at":"document_start",<br>
      "js": ["js/background.js"]<br>
    }<br></strong>
</p>

<li><h3>追加情報</h3></li>

上記の方法で解決できない場合は以下の方法も試してみてください<br><br>
・特定のChrome拡張機能をOFFにするとエラーが消える事を検証している動画
<a href="https://www.youtube.com/watch?v=DsKYuBn7YpQ">Unchecked runtime.lastError: Could not establish connection. Receiving end does not exist.(YouTube)</a>
<br><br>
・chrome.runtime.onMessage.addListener()のfunctionの中の一番最後にreturn trueを記述していない
<a href="http://www.nononagainfo.com/2019/08/chromeunchecked-runtimelasterror-could.html">Chrome拡張のUnchecked runtime.lastError: Could not establish connection. Receiving end does not exist.というエラーを解決する - nonoNagaInfo</a>
<br><br>
・回答の一例でのsetTimeoutの話を参考にさせてもらった
<a href="https://stackoverflow.com/questions/54181734/chrome-extension-message-passing-unchecked-runtime-lasterror-could-not-establi">Chrome Extension message passing: Unchecked runtime.lastError: Could not establish connection. Receiving end does not exist - Stack Overflow</a>

<li><h3>御礼</h3></li>
<p>初めての投稿ですので私はこの記事を書くにあたって以下の記事を参考にさせて頂きました。<br>お礼申し上げます。
<br>
<a href="http://www.nononagainfo.com/2019/08/chromeunchecked-runtimelasterror-could.html">Chrome拡張のUnchecked runtime.lastError: Could not establish connection. Receiving end does not exist.というエラーを解決する</a></p>

</ul>
Powerpointでベクター画像の文字ズレを防ぐ方法

texで論文を作成する際にベクター画像を作成したいときがある．そのような場合に個人的にはPowerpointを利用している．最も簡単な方法は[このWeb page](http://tecsingularity.com/%E3%81%9D%E3%81%AE%E4%BB%96/vector/)にあるように図形を選択し，それをSVGとして貼り付け，そのSVGを何らかの方法でPDFに変換するという手順で行うことができる．一方でこの方法を利用するときに文字ズレがしばしば問題となったので対処方法を備忘録として残しておく．

対処方法は至って簡単で，図形内に文字を直接書かない，これだけである．つまり，図形と文字列は分離して別々の図形として扱うことで位置情報がズレなくなることを狙っている．
【Git】git revertとgit resetの違い

## はじめに
　本記事は、プログラミングの学習を始めて1ヶ月の初学者が、学習を進めていて疑問に思った点について調べた結果を備忘録も兼ねてまとめたものです。
　そのため、記事の内容に誤りが含まれている可能性があります。ご容赦ください。
　間違いを見つけた方は、お手数ですが、ご指摘いただけますと幸いです。

## 今回の疑問点
　今回の疑問点は、

　　_`git revert` と`git reset`の違いについて_
　
　です。　


## 疑問点についての解説

### 結論

`git revert`：指定したコミットの内容を打ち消すコミットを作成

`git reset`：指定したコミットを削除


### git revert
`git revert`は指定したコミットの内容を打ち消すコミットを作成します。そのため、指定したコミットがログから消えることはありません。また、`git revert`を実行した後には、`push`をする必要があります。

```

 git revert [打ち消したいコミットコード]　　#指定したコミットを削除

 git revert -m [1か2] [打ち消したいコミットコード]　--no-edit #指定したマージコミットを削除

　
```

```
git log

commit a9857cfa0d63caef134k7ea07061370ffd0fe3dc
Merge: xxxxxxx  yyyyyyy
Author: xxxxxxxxxxxxxxxxxxxxxxxxxx
Date:   xxxxxxxxxxxxxxxxxxxx
 
    xxxxxxxxxxxxxxxxxxxxxxxx
 
    xxxxxxxxxxxxxxxxxx

```

打ち消したいコミットとは`git log`で出力された上記のcommitの横に記載されているコードです。左から7桁分入力することで指定できます。GithubのNetwork graphからも確認することができます。
また、`git revert -m [1か2] [打ち消したいコミットコード]`の`[1か2]`には、`git log`で出力された上記の`merge`の右に記載されている２つのコードのうちどちらを残すのか指定します。右側が1、左側が2です。
最後の`--no-edit`を記述しない場合、コマンド実行後にエディタが開き、コミットメッセージの入力を求められます。

### git reset
`git reset`は、指定したコミットを削除します。ログも消えます。

```

git reset [削除したいコミットコード]  # 現在のブランチを指定したコミットに戻す
 
git reset [option] [削除したいコミットコード]  # オプションを指定 [--soft | --hard] [HEAD | HEAD^]
　
```

上記処理後、普通にpushができない場合には、`git push -f`を実行しましょう。

`[option]`について→https://www.r-staffing.co.jp/engineer/entry/20191129_1

## まとめ
最後にポイントをまとめます。

- `git revert`：指定したコミットの内容を打ち消すコミットを作成。ログは消えない。実行した後にはpushする必要がある
- `git reset`：指定したコミットを削除。ログも消える。
Global変数をmodule間やmainとmoduleの間で共有する方法



# Python関連小ネタ
これは、 Python Advent Calendar 2021 https://qiita.com/advent-calendar/2021/python  の16日目の記事です
どうやら、Pythonを使った解析とかPythonを使って作ったアプリとかの投稿が多いようであるが、PythonのAdvent calendarということで、純粋にpythonについて学んだ（そうなるとは思っていたが、まさか本当にそうなるとは思った）ことを共有しておこうと思う。

## Global変数をmodule間やmainとmoduleの間で共有する 
あまり意識したことがない人も多いかもしれないが、実はPythonではimportしたmodule側とmain側ではglobal変数の名前空間が異なる。こうなっていないと、main側で、module側にある変数と同じ名前を変数を作ってしまった時に大惨事になってしまうので、当たり前といえば当たり前の仕様である。　　
一方で、「module側のglobal変数をmain側から参照することはできても、main側のglobal変数をmodule側から参照することができない！！」といった問題に直面することがある。　「え、そんな問題に直面することあるか？」と思われるかもしれないが、少なくとも筆者にはあったのだ。そして、優しいpython公式さんはちゃんと解決策を提示してくれていた。

https://docs.python.org/3/faq/programming.html#how-do-i-share-global-variables-across-modules

ということで、module間やmodule側からmainの変数を参照したければ、公式ドキュメントに書いてあるようにお互いに共有する変数を保持するための共通のmoduleファイルを別に用意してあげればいい。**ドキュメントは素晴らしい！。みんなQiitaじゃなくて公式ドキュメントをちゃんと読もう！**となってしまうと、Qiitaの意味がなくなってしまうので、この記事では、この問題に対する別解（多分、あんまり好まれない）を紹介したい。

さて、先の公式ドキュメントを読んだときに、筆者はあることを思った。

「なるほどぉ。でも、ちょっと面倒だなぁ。うーーーーーーん。(N時間経過)。そうだ！こんな面倒なことしなくてもmain側のglobal変数の名前空間を直接渡せるんじゃね？」

さて、どうゆうことか。そもそも、pythonにはdefaultでglobals()という関数が用意されている。これはglobal空間にある、変数やメソッドを返してくれる関数だ。例えば、インタプリタでもNotebookでもなんでもいいんだが、

```
a=1
print(globals())
```

と実行すると、

```
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, 'a': 1}
```

みたいになる。「それぐらいは知ってるわ」という人も多いと思うが、実はこんなこともできる。

```
hoge = globals()
hoge["b"] = 1
print(b)
```

「うん?、何やってんの？bはhogeにkeyとして加えただけで変数としては未定義でしょ？」、って思われるかもしれないが、結果は

```
1
```

となる。そう、globals()の返り値である辞書に新しいkeyを追加すると、global変数として追加されるのだ。。(この仕様、いつか変わっちゃうんだろうなぁと思っていたのだが、どうやらpython2のときから同じ仕様になっているようなので、多分変わることはないと思いたい。)

ってことは、このglobalsの返り値はモジュール側の変数に代入したり、関数の引数にしたって、main側のglobal空間にアクセスできる辞書として機能するはずである。



**実際にやってみた。**

まず、importする用のファイルとしてhoge.pyを作成。

```python:hoge.py
namespace_main = None
```


そして、hoge.pyの`namespace_main`に対して、main側の`globals()`をエイっと代入。main側でグローバル変数を`fuga`から直接編集してみる。

```python:main.py
import hoge
hoge.namespace_main = globals()
fuga = 100

#mainのglobal変数hogeにmy_funcからアクセス
print(hoge.namespace_main["fuga"])
hoge.namespace_main["fuga"]=200

print(fuga)
```

で、できてしまった。。。筆者が書くのもなんだが、実に気持ちが悪い動作である。。。



## で何に使えるの？

さて、「こういう気持ちが悪い動作ができるのはわかったけど、これ何に使えるの？」と思われたかもしれない。

正直、私にもあまり使い道はわからない。しかし、例えば、こんなことができてしまう。

```python:hoge.py
def add(x, y, z, namespace):
	namespace[z]=namespace[x]+namespace[y]
  print("グローバル変数{}とグローバル変数{}の和は{}です。".format(namespace[x],namespace[y],namespace[z]))
  print("計算結果はグローバル変数{}に代入されました".format(namespace[z]))
```

```
>>> import hoge
>>> a = 10
>>> b = 20
>>> hoge.add("a", "b", "c", globals())
グローバル変数aとグローバル変数bの和は30です。
計算結果はグローバル変数cに代入されました。
>>> c
30
```

何ができたか、お分かりいただけただろうか。**なんとmodule側から、main側のどのglobal変数が操作されたかと、どのglobal変数に代入が起こったのか**を追跡できているのだ。 「それって、そんなにすごいか？」ってなりそうだが、これを他の方法で実現しようとすると意外と難しい、、、？気がする。

とにかく、上記の手法を応用すればmain側での書き方を工夫する必要は出てくるものの、mainでの動作をユーザが定義した変数名も含めて追跡、記録することもできるはずである。 しかし、自分で作っておいてなんだが、どこにも`c =  ` 書いていないの`c`が勝手に作られて、`a+b`の計算結果まで代入されているのは非常に気持ちがわるいなぁ。。。

というように、Pythonを使い始めて結構時間が経つのですが、まだまだ知らないことがたくさんあるなぁ、と思わされた1年でありました。
p5.jsの関数まとめ part.11 push(), pop()

この記事は Qiita p5js アドベントカレンダー16日目の記事です。

## これはなに
p5.jsが用意している関数について理解を深める記事です。
今回はpush()とpop()について。

## pushとpop
shapeなどの設定を保存するために`push`を利用し、`pop`で元に戻す。
そんな使い方をします。


### リファレンスより

> push()関数は、現在の描画スタイル設定と変換を保存し、pop()関数はこれらの設定を復元する。これらの関数は常に一緒に使用されることに注意してください。これらの関数により、スタイルと変換の設定を変更し、後で元の設定に戻すことができます。push()で新しい状態が開始されると、現在のスタイルとトランスフォームの情報を基に構築されます。push()とpop()関数を埋め込むことで、より多くの制御を行うことができます。(デモは2番目の例を参照してください)。
> 
> push() には、現在の変形状態や、以下の関数で制御されるスタイル設定に関する情報を格納する。fill(), noFill(), noStroke(), stroke(), tint(), noTint(), strokeWeight(), strokeCap(), strokeJoin(), imageMode(), rectMode(), ellipseMode(), colorMode(), など。textAlign(), textFont(), textSize(), textLeading(), applyMatrix(), resetMatrix(), rotate(), scale(), shearX(), shearY(), translate(), noiseSeed() の各項目。
> 
>WEBGL モードでは、追加のスタイル設定が保存されます。これらは、次の関数で制御されます：setCamera(), ambientLight(), directionalLight(), pointLight(), texture(), specularMaterial(), shininess(), normalMaterial() および shader().

push()とpop()で保存、呼び出し可能な情報は上記の関数に限られているようです。
shapeのスタイルに関すること、またWEBGLモードでは3Dオブジェクト用の関数が追加されています。

### Type
```typescript
push(): void;
pop(): void;
```
設定の保存、呼び出しだけなので渡す引数もなく、返り値もありません。


### どんな時に使えそうか
> 現在の描画スタイル設定と変換を保存し、pop()関数はこれらの設定を復元する

という挙動を私は少し勘違いしていたようなのでまとめます。
（てっきり、push()以降の情報を保存するものと思っていました）

次のようなコードを書いて、ドットを３つ出してみましょう。

```javascript
function setup(){
  createCanvas(200, 200);
  background(100);
  noStroke();
}

function draw() {
  stroke('red')
  strokeWeight(10)
  point(10, 10)
  // これまでの設定（赤色でストローク幅10）を保存
  push()
  stroke('blue')
  strokeWeight(20)
  point(30, 30)
  // 保存していた設定が蘇る
  pop()
  point(50, 50)
}
```

![スクリーンショット 2021-12-14 23.30.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358229/b3045f84-2686-bdcd-f241-6acc6aea4329.png)

一つ目の丸は`stroke('red')`が効いているので赤色に染まっています。

その後`push()`と`pop()`の間に上書きしたい情報を書きます。
`pop()`以降は`stroke('red')`と`strokeWeight(10)`が再度有効になるため、一つ目と三つ目の丸は同じものになりました。

このようにある部分だけを例外にして、その他は同じスタイルを使いたい時に使えます。
ちなみにネストもできて、2回push()をした場合は2回pop()することで元にもどるようです。

## 参考
[p5.js reference | push()](https://p5js.org/reference/#/p5/push)
[p5.js reference | pop()](https://p5js.org/reference/#/p5/pop)
[メモ] Terraform 1.1 リリース

これは「[「はじめに」の Advent Calendar 2021](https://adventar.org/calendars/7037)」15日目の記事です。

## Terraform 1.1リリース

2021/12/08に1.1がリリースされています。
(投稿日はちょうど1週間後)

CHANGELOG

https://github.com/hashicorp/terraform/blob/v1.1.0/CHANGELOG.md

リリースブログ

https://www.hashicorp.com/blog/terraform-1-1-improves-refactoring-and-the-cloud-cli-experience


## 新機能・変更点

地味な差分ですが、紹介していきます。
なお、 `v1.0 Compatibility Promise` は維持しているようです。

https://www.terraform.io/docs/language/v1-compatibility-promises.html

### macOS 10.13 (High Sierra)未満は非サポートに

- 10.13未満はサポートされません。
- 4年前なので、まだ現役でアップグレードしていないMac多そう・・・

## `moved` ブロックが追加。

`terraform state mv` リソース名の変更、特にmoduleのリファクタリングなどを安全に行うための仕組みらしいが・・・
ドキュメントが見当たらないので、どうやって使うのか不明・・・

コレが多分目玉機能だと思うのだけれども。

## `terraform plan` `terraform apply`

リソースの削除があった場合、追加で情報を出力するようになるとのこと。

### Azure AD Graphが非推奨に
MicrosoftがAzure AD GraphからMicrosoft Graphへの移行を進めていることに合わせて、Terraformも対応を始めたようです。
`backend "azurerm"`に`use_microsoft_graph = true`を設定して`terraform init -reconfigure`を実行すればMicrosoft Graphに移行できるようです。
(※筆者にAzure環境がないので、挙動を確かめられません)

また、Terraformv1.2から、`use_microsoft_graph = true`がdeafultになるそうです。

### terraform graphコマンドの変更

内部実装を公開しなくなったことに合わせて、以下のオプションが廃止のようです。

`-type=validate`
`-type=eval`

ドキュメントには `validate` があり、 `type=plan` と同じ結果を返すようです。

https://www.terraform.io/docs/cli/commands/graph.html

### `terraform state mv` のコマンドの厳密化

`-backup` `-backup-out` を `-state` なしで実行した場合、エラーになるように変更。
`-backup` `-backup-out`はレガシーオプションという扱い。
ダイアログにURLを持たせたい！


## やりたいこと
🎅　ダイアログコンポーネントに一意のURLを持たせ、そのURLにアクセスした時にダイアログを自動で開きたい
🎅　ダイアログページをURL共有できるようにしたい
🎅　ブラウザをリロードしてもダイアログが開いた状態を保ちたい
例えば
`http://myurl?id=123`へアクセス
→ IDが123のデータをAPIリクエストし、その結果を載せたダイアログコンポーネントを開く

（ダイアログを使わない方が楽にできる気がしますが、
アプリケーション内の操作方法を統一したいなどの諸事情により今回はこのような実装にしました）

## 環境
- Angular 13
- Angular Material


## 早速つくっていきます
### 1. ダイアログの親コンポーネントのngOnInitのタイミングでダイアログを開く

```ts
@Component({
  selector: 'app-my-table',
  templateUrl: './my-table.component.html',
  styleUrls: ['./my-table.component.sass'],
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class MyTableComponent implements OnInit {
  constructor(
    private route: ActivatedRoute,
    private router: Router,
    public dialog: MatDialog,
    private http: HttpClient
  ) {}

  ngOnInit(): void {
    this.route.queryParams
      .pipe(
// 🎅クエリパラメータに特定のパラメータ（今回はid）が含まれるときのみダイアログを開く
        filter(({ id }) => id),
// 🎅クエリパラメータから取得したIDでデータを取得、ダイアログコンポーネントに渡す
        switchMap(({ id }) => this.http.get<MyData>(`${myURL}/${id}`)),
        switchMap((myData) => {
          return this.dialog
            .open(MyDialogComponent, {
// 🎅今回はダイアログを普通のページっぽく見せたいのでheight, widthを100％にして、背景を見えないようにする
              data: myData,
              height: '100%',
              width: '100%',
              disableClose: true,
            })
// 🎅ダイアログを閉じた後は任意のページに遷移させる
            .afterClosed()
            .pipe(
              tap(() => {
                this.router.navigate(['/myURL']);
              })
            );
        })
      )
      .subscribe();
  }
}

```

### 2. ダイアログが開くまでの間スピナーを表示する
ダイアログに表示するデータが返ってくるまでに時間がかかる場合、overlay+spinnerを使ってユーザの操作を制限

```ts
@Component({
  selector: 'app-my-table',
  templateUrl: './my-table.component.html',
  styleUrls: ['./my-table.component.sass'],
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class MyTableComponent implements OnInit {
  // 🎅追加
  overlayRef = this.overlay.create({
    hasBackdrop: true,
    positionStrategy: this.overlay.position().global()![Something went wrong]()
.centerHorizontally().centerVertically(),
  });

  constructor(
    private route: ActivatedRoute,
    private router: Router,
    public dialog: MatDialog,
    private overlay: Overlay, // 🎅追加
    private http: HttpClient
  ) {}

  ngOnInit(): void {
    this.route.queryParams
      .pipe(
        filter(({ id }) => id),
        switchMap(({ id }) => {
// 🎅APIからのリスポンスが返ってくるまでの間スピナーを表示
          this.overlayRef.attach(new ComponentPortal(MatSpinner));
          return this.http.get<MyData>(`${myURL}/${id}`);
        }),
        switchMap((myData) => {
// 🎅スピナーを非表示にしてダイアログを開く
          this.overlayRef.detach();
          return this.dialog.open()
          ...

        })
      )
      .subscribe();
  }
}

```

### 最終結果
URLに`?id=123`を追加すると、ダイアログコンポーネントが開いてくれました！
（※URL部分がわかりやすいように一部を切り取っているためスピナーの位置がずれています）
![ezgif.com-gif-maker (2).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/908779/039d75ef-14be-7c8a-5c22-194bb98f5660.gif)
re:Invent 2021 私的HPCまとめ

2019年は自分のプレゼンと仕事で忙しすぎて忘れてた、2020年はコロナで現地にいないのでまとめる気にならなかったけど。３年ぶりにre:Invent 私的HPCまとめをしてみたいと思います。

HPC Tech ShortsというYoutubeチャネルでまとめをやってくれるんだろうなー、と思って待ってたら12/15に出てきた。
https://www.youtube.com/c/HPCTechShorts

 - FSx on OpenZFS : https://aws.amazon.com/about-aws/whats-new/2021/11/amazon-fsx-openzfs/
    - ZFSって触ったことないのでよくわからんのですが、結構パフォーマンスでるならLustreから乗り換えるのもありかも。
 - Im4gn and Is4gen powered by Graviton2 : https://aws.amazon.com/about-aws/whats-new/2021/11/amazon-ec2-im4gn-is4gen-aws-graviton2/
    - Nitro x Gravitonの組み合わせでサーバサイドのコストとパフォーマンス最適化がどんどんすすむ
 - C7g - Graviton3 : https://aws.amazon.com/ec2/instance-types/c7g/
    - 大本命。すぐにベンチマーク取りたい。
 - HPC Connector for NICE EngineFrame : https://aws.amazon.com/blogs/hpc/introducing-aws-hpc-connector/
    - オンプレからバーストするのって最高にかっこいい。ユーザがクラウドかオンプレなのか気にする必要ないってのが理想だし。でも自分オンプレにクラスター持ってないっす。
 

HPC Tech Shortsで触れられていない、かつ個人的な興味を引いたreleaseがこちら。

- AWS Batch - Step Function : https://aws.amazon.com/blogs/hpc/using-aws-batch-console-support-for-step-functions/
    - AWS Batchからのピタゴラスイッチが捗るのは非常に夢が広がる。
- AWS Batch fareshare scheduling : https://aws.amazon.com/blogs/hpc/introducing-fair-share-scheduling-for-aws-batch/
    - クラウドの潤沢なリソースを使えばあまりfareshareスケジューリングって、あまり使う機会がないのかなと思っていたのですが、実装されたということはリクエストが多かったという意味。Batchユーザが増えてきたんだなと感じる。
- Slurm API : https://aws.amazon.com/blogs/hpc/using-the-slurm-rest-api-to-integrate-with-distributed-architectures-on-aws/
    - Jobのサブミットの方法が色々準備されてると、用途は広がる可能性があると思う。
- HPC-optimized EC2 Hpc6a instance : https://aws.amazon.com/blogs/hpc/coming-soon-dedicated-hpc-instances-and-hybrid-functionality/
    - EC2インスタンスがたくさん出てきていて、Nitroの凄さを感じる。
- 3.2M vCPU : https://aws.amazon.com/blogs/hpc/running-a-3-2m-vcpu-hpc-workload-on-aws-with-yellowdog/
    - 1M vCPUを経験した身としては、3.2M vCPUを33分でフル稼働させたスケジューラーすごすぎる
単純な処理で思わぬ性能問題が出た話

Listに重複がある場合に出力するという、Java初心者練習用のようなプログラム。

```
import java.util.*;

public class Main {
    public static void main(String[] args) throws Exception {
        List list = Arrays.asList("yamada", "nakamura", "aoki", "yamada", "shimizu", "nakamura");
        
        Iterator it = list.iterator();
        List list2 = new ArrayList<String>();
        while(it.hasNext())
        {
            String name = (String)it.next();
            if( list2.contains(name)){
                System.out.println(name);
            } else {
                list2.add(name);
            }
        }
    }
}
```

実行結果
```yamada
nakamura
```

だが、これと同様のプログラム構造のバッチ処理の性能試験にて、Listの件数が10万件、20万件・・・となった際に、処理速度が指数関数的（比例ではない）に遅くなるという問題が起きた。
なぜ、指数関数的に遅くなる・・・？

当初、ヒープの枯渇によるGC連発を疑ったが、そうではなかった。

list2.contains(name)の部分の処理が、list2の件数に比例して遅くなるのが原因だった。
まあそりゃそうか、内部的には全件なめるんだろうしな・・・。
なので、ループの回数と、list2.contains(name)の1回あたりの処理が両方件数に比例するので、比例×比例で二乗になっていた。

賢明な皆さんは一瞬で気づいたかもしれないが、小一時間悩んでしまった。orz
denops.vimを使ってdein.vimでインストールしているプラグインのリポジトリにstarをつける

# denops.vimを使ってdein.vimでインストールしているプラグインのリポジトリにstarをつける

これは[vim advent calendar 2021](https://qiita.com/advent-calendar/2021/vim)の16日目の記事としての投稿です。

## はじめに

Vimを使っているといろいろなプラグインをインストールすると思います。
私はなんかかっこいいという雑な理由で[dein.vim](https://github.com/Shougo/dein.vim)を使ってプラグインをインストールしています。

https://github.com/Shougo/dein.vim

インストールしているプラグインのリポジトリにコマンドでスターがつけられると便利だなあと思ったのでdenops.vimを使って実験的なプラグインを作ってみました。


## [denops.vim](https://github.com/vim-denops/denops.vim)

https://github.com/vim-denops/denops.vim

denops.vimはTypescriptのランタイムであるDenoを使ってvim/neovimのプラグインを書くフレームワークです。
APIの乖離が進むVim/neovimの両方に対応することができるほか、重い処理をDenoに負担させることで高速なプラグインを書くことができるようです。（個人的にはそこまで大きいプラグインを作ったことが無いので速度の恩恵はあまり受けれてないです）

## 出来上がったもの

https://github.com/Omochice/dps-dein-star.vim

実験なのでまだヘルプ等はありません。ごめんなさい。

## 中身

[githubのREST APIのドキュメント](https://docs.github.com/en/rest/reference/activity#star-a-repository-for-the-authenticated-user)を見てみると。以下のアクセスポイントに`PUT`するとスターがつけられるとあります。


```
https://api.github.com/user/starred/${owner}/${repo}
```

また、このAPIを叩くために`repo:public_repo`の権限がついたパーソナルトークンを発行しておく必要があります。

これをDenoで実行できるようにしてみるとこんな感じ

```ts
export async function star(owner: string, repo: string, token: string) {
  const url = `https://api.github.com/user/starred/${owner}/${repo}`;
  const res = await fetch(
    url,
    {
      headers: new Headers({
        Authorization: `Bearer ${token}`,
        Accept: "application/vnd.github.v3+json",
      }),
      method: "PUT",
    },
  );
  if (res.status != 204) {
    throw new Error(`${res.status} ${res.statusText} ${url}`);
  }
}
```

これをvimから実行できるようにしたのが前述のプラグインです。

（明らかにアクセスするのが推奨されてなさそうな`g:dein#_plugins`にアクセスしているのでいつ動かなくなってもおかしくありません)
2021-12-18追記
`g:dein#_plugins`ではなく、`dein#get()`でも同様の情報が取得できました。

簡単なドキュメントを以下に書いておきます。

- コマンド
    - `deinStar`

        deinを使ってインストールしているプラグイン全てにスターをつけます

- 変数
    - `g:dps_dein_star_token`

        先述したREST APIを実行するためのトークン

    - `g:dps_dein_star_ignore_users`

        スターをつけたくないプラグインのowner(自分など)をリストとして指定

## できなかったこと

- REST APIでスターをつけてるため、バックグラウンドで処理しているとはいえそこそこ時間がかかる
    - GraphQLを使えばいい感じになるかも 
- denopsを使わなくてもできそう
    - Vitalを使えばDenoに頼らずにWebAPIを叩けそう

## 参考

- [https://github.com/google/go-github/blob/master/github/activity_star.go](https://github.com/google/go-github/blob/master/github/activity_star.go)

- [https://docs.github.com/en/rest/reference/activity#star-a-repository-for-the-authenticated-user](https://docs.github.com/en/rest/reference/activity#star-a-repository-for-the-authenticated-user)


## さいごに

みなさんも年末年始でよいVim活を！！
複数バージョンのXcodeを手動で併存する方法

## XcodeをAppStoreからインストールするといろいろ問題が・・・。

iPhoneアプリ個人開発者のつねたです。こんにちわ。

Xcode13.2が不具合多すぎて苦しんでる人、多いですね。
他にも、「AppStoreでのXcodeバージョンアップが進まない。固まる。」などで苦しんでいる人も多いですね。

AppStoreからXcodeをインストールすると

* インストール実施時・バージョンアップ実施時の進捗がわからない
* 複数バージョン併存できない (=13.2みたいなウ◯コなバージョンになると死ぬ）

のでオススメできません。

ではどうすればいいのか？
について書いていこうと思います。


## 概要

Xcodeには2通りのインストール方法があります。

* AppStoreからXcodeをインストール
* developerサイトからXcodeのセキュリティアーカイブファイル(xipファイル)をダウンロードしてインストール

お手軽なのはAppStoreからXcodeをインストールする方法です。
ちょっとプログラミングやiPhoneアプリ開発を試してみたい、という目的ならこちらでいいかと思います。


ですが、iPhoneアプリをAppStoreに公開するようなレベルの方には
「developerサイトからXcodeのセキュリティアーカイブファイル(xipファイル)をダウンロードしてインストール」
がオススメです！

この方法だと、

* 過去のバージョンのXcodeを遡って利用する
* 複数のXcodeを併存させて並行して利用する

ということができるので、過去バージョンのメンテナンスなどを行うような人は確実にこちらの方法を選択したほうが良いです。

## developerサイトからダウンロードしてインストールする手順

#### ①インストールしたいバージョンのXcodeのxipファイルをダウンロードする。

https://developer.apple.com/develop/

にアクセスして「Downloads」をクリックします。

サインインを求められるかと思いますので、developerアカウントでサインインしましょう。


#### ②xipファイルをダウンロードする。

右上に「More」というリンクがあるのでそれをクリックします。
こちらの画面からインストールしたいバージョンのXcodeをダウンロードします。
最近のXcodeは10GBくらいあるので、ダウンロード完了までしばし待ちましょう。
ここでは Xcode_13.2.xip をダウンロードした場合の例として進めます。

#### ③xipファイルを展開する。

ダウンロードした Xcode_XX.X.xip というファイルダブルクリックして展開します。
アーカイブユーティリティが起動して、ダウンロードの進捗がわかるのですが、かなり時間がかかります。
特に、CPUが遅いマシン(Intel Macbook AirのCPU2コアモデルなど)だとものすごく時間がかかります！
気長に待ちましょう。

（AppStoreでバージョンアップした際に時間かかる理由も、この作業に時間がかかってるものと思われます。）



#### ④展開して出てきた Xcode.app ファイルをバージョンがわかる名前にリネームする。

Xcodeを併存可能にするために、展開してXcode.appのファイル名を変更しましょう。
ここでは Xcode_13.2.app という名前にリネームしたとして進めます。


#### ⑤Xcode_13.2.app を Applicationフォルダに移動する。

ドラッグ&ドロップで /Application に移動しましょう。
Finderの左にある  「アプリケーション」にドラッグ&ドロップすればOKです。


#### ⑥新しくインストールした Xcode を一度起動する。

初回の起動時には管理者パスワードを求められることになると思います。
新しくインストールしたXcodeをLaunchpadなどから起動してみて、管理者パスワードを入力しておきましょう。


#### ⑦(必須ではないがやったほうがいい)コマンドラインツールバージョンの設定変更

最近のXcodeは、インストール時にコマンドラインツールもインストールされます。
ですが、Xcodeをインストールするだけでは、使用されるコマンドラインツールのバージョンは変わりません。

Xcodeを起動し、上部のメニューから
 Xcode → Preferences
を選択してプリファレンス画面を表示しましょう。

プリファレンス画面内の「Locations」ボタンをクリックし、
 Command Line Tools:
のプルダウンから、コマンドラインで使用したいバージョンを選択します。


以上で、ダウンロードしたファイルからの手動インストール方法は完了です。
この方法なら安心して新しいバージョンのXcodeを試すことができます。
ダメだったらすぐに古いバージョンに戻れます！


それでは、楽しいXcodeライフを！
個人的にスクラムマスターの資格勉強したときが他人（開発者）との関わり方が明確に変わったのでおすすめしたい

こちらの記事はアドベントカレンダー[開発者体験:DXをめちゃくちゃ改善した話 Advent Calendar 2021](https://qiita.com/advent-calendar/2021/dx-improvement)　の16日目の記事です。


> 個人的にスクラムマスターの資格勉強したときが他人（開発者）との関わり方が明確に変わったのでおすすめしたい。

というタイトルにさせてもらったのですが、この一言でいうとその通りで、他に言うことないです。

`開発者体験` という意味だとゴールを持つことがとても重要で、そこに向かって開発者として何故何をどうやって開発するのか、そういうのをとても意識できるようになった体験でした。2021年の年末にぜひ挑戦してほしいなと思っております。

来年度もみなさんが、最高の開発者体験でありますように。



* ※※※こちらポエム && 主観 && 駄文（推敲せずに30分くらいで書いている） です※※※
* 題名とおりです。勉強したら他の開発者との関わり方とか変わって、仕事しやすくなりました
* [PSM](https://www.scrum.org/professional-scrum-master-i-certification)のプロフェッショナルスクラムマスターを勉強するのをおすすめします


# スクラムマスターの資格取得について

## 外部リンク
色々参考情報を調べましたが、個人的に参考にした外部リンクこちら2つです

- [スクラムマスター資格psmに合格した私の勉強法](https://shiftasia.com/ja/column/%E3%82%B9%E3%82%AF%E3%83%A9%E3%83%A0%E3%83%9E%E3%82%B9%E3%82%BF%E3%83%BC%E8%B3%87%E6%A0%BCpsm%E3%81%AB%E5%90%88%E6%A0%BC%E3%81%97%E3%81%9F%E7%A7%81%E3%81%AE%E5%8B%89%E5%BC%B7%E6%B3%95/)
- [スクラムマスターにおすすめの資格は3つだけ【コスパ良し】](https://proengineer.internous.co.jp/content/columnfeature/17096)

## 私が今回勉強した資格

スクラムマスターの資格はたくさんありますが、今回はPSMの資格をおすすめします。

* 認定スクラムマスター（Certified ScrumMaster®：CSM®）
* PSM（Professional Scrum Master™）
* LSM（Licensed Scrum Master）

他とくらべると

- 安い！$150!
    - （1/10以下）
    - 認定スクラムマスターは資格に30万円とかかかるので会社の補助とかないと難しいと思います
- 合格最低点数が高いので真剣に勉強が必要、理論がしっかり身につく


## 勉強方法

* 0. スクラムの入門書籍を読む
    * スクラムっぽいもの、アジャイルを経験したことない人は読み物からがおすすめ
    * [SCRUM BOOT CAMP THE BOOK](https://www.amazon.co.jp/dp/4798129712)を読む
* 1. スクラムガイドを読む
    * PDF版が読みにくかったので以下、Web版をQiitaに公開してます
        * [【Web版】スクラムガイド™ 2020](https://qiita.com/ykhirao/items/ed320eaecb876bfd189e)
        * [【Web版】スクラムガイド™ 2017](https://qiita.com/ykhirao/items/421dd8681671ada1f55a)
* 2. Scrum.orgの公式問題30問解く
    * https://www.classmarker.com/online-test/start/?quiz=3qg5fac7589c0416
    * 正直わからないものばかりだと思います
    * このorgのテストを受けるのとGoogle翻訳アドオンの使用は許可されているので試しにうけてみる
* 3. Udemyで問題集を解く
    * UdemyのProfessional Scrum Master certification Practice Tests PSM1 [リンク](https://www.udemy.com/course/professional-scrum-master-certification-practice-tests-psm1/) をやると一気に理解度が深まる
    * 定価2400円くらいで割引使うととても安い
    * こういう場合はスクラムはこう使うんだ〜とかの理解が深まった
    * Google翻訳使いながら、説いていくとよいが、スクラムガイドの原文・英文を読まないと翻訳の問題とかで変な日本語になります
        * アーティファクトとか
* 4. Scrum.orgのテストを受ける
    * 150$
    * 受けなくても

## 効果

ポエムで主観で定量的ではないですが以下のような効果あったなと振り返ってます

* 仕事するときに誰の責務かはっきりすることで勉強になった
* 外注のコントロールにスクラムの概念（漸進的なインクリメンタルな開発・報告をお願いするとか）をちゃんと導入してうまくいくようになった
* 周りの開発者とのかかわりがかわった
* しっかり学んだことで、スクラムの概念を崩して使ったりできるようになった
    * （これは基本的には非推奨、 `スクラムはシンプルである。まずはそのままの状態で試してほしい。` と明確にかかれている ）
* 上手くいってないプロジェクトのファシリテーションを任せるって言われて急に投入されてもうまく回せた


## 最後に

スクラムの本質の一つはゴール・目標に向かって漸進していく開発だということです

* プロダクトゴール（スクラムの⻑期的な目標）をプロダクトオーナーが決め、プロダクトバックログとして管理します
* スプリントゴール（スプリントの目標）をプロダクトオーナーが決め、その中で開発者が何をするか自分の意志で決めます
* デイリースクラムで、日々何をやるかを開発者が宣言して、また昨日の予実を振り返ります

長期的な目標に向かって、日々振り返り、毎週振り借り、少しずつでも進んでいく、そんな姿勢がスクラムです。
プロダクトゴールは2020年度のスクラムガイドから導入されましたが、目標に向かって自分自身・自分たちのチームのことを定期的に振り返る、きれいなサイクルがイベントとして設定されています。

スクラムでやりたかったことが少しだけわかると誰かに広めたくなって、この記事をかかせていただきました。


少しでも誰かの興味に残ってもらえるとうれしいです。


最後まで読んでいただきありがとうございました。
VScodeのTerminalでyarnすると怒られた

# 現象
 Windows10にyarnをインストールして、Visual Studio Code（以下VScode）でTerminalを開き、yarnのバージョンを確認するために以下を入力するとエラーメッセージが出た。

```
> yarn -v
yarn : このシステムではスクリプトの実行が無効になっているため、ファイル C:\Users\{PC名}\AppData\Roaming\npm\yarn.ps1 を読み込むことができません。詳細については、「about_Ex 
ecution_Policies」(https://go.microsoft.com/fwlink/?LinkID=135170) を参照してください。   
発生場所 行:1 文字:1
+ yarn -v
+ ~~~~
    + CategoryInfo          : セキュリティ エラー: (: ) []、PSSecurityException
    + FullyQualifiedErrorId : UnauthorizedAccess
```

コマンドプロンプト（以下CMD）では、バージョンが表示された。

```
> yarn -v
1.22.17
```

# 
VScodeでTerminalを開くとデフォルトでPowerShellが開いていることが判明。
そして、PowerShellには実行ポリシーというものが設定されていて、実行できるコマンドに制約がある模様。

参考：https://qiita.com/tomoko523/items/df8e384d32a377381ef9

ポリシーを変更するにはPowerShellを管理者として開く必要があるため、VScodeのTerminalからではなく、PowerShellを検索して右クリックして管理者として実行する必要がある。（面倒）
yarn.ps1は署名が付いていないみたいなので、ポリシーはRemoteSignedに変更してみる。

```
> Set-ExecutionPolicy RemoteSigned
実行ポリシーの変更
実行ポリシーは、信頼されていないスクリプトからの保護に役立ちます。実行ポリシーを変更すると、about_Execution_Policies
のヘルプ トピック (https://go.microsoft.com/fwlink/?LinkID=135170)
で説明されているセキュリティ上の危険にさらされる可能性があります。実行ポリシーを変更しますか?
[Y] はい(Y)  [A] すべて続行(A)  [N] いいえ(N)  [L] すべて無視(L)  [S] 中断(S)  [?] ヘルプ (既定値は "N"): y
```

コマンドを打った後、[Y]を選択するとポリシーが変更される。
以下のコマンドでポリシーが確認できる。

```
> Get-ExecutionPolicy -List
        Scope ExecutionPolicy
        ----- ---------------
MachinePolicy       Undefined
   UserPolicy       Undefined
      Process       Undefined
  CurrentUser       Undefined
 LocalMachine    RemoteSigned
```

VScodeに戻ってTerminal上でyarn -vと打ってみると無事にバージョンが表示された。