OmniAICreator/Qiita-1.07M huggingface dataset:
Db2:遅いSQLを見つける方法

# Db2が遅い
Db2が遅延する原因は様々です。トランザクションが増加したのかもしれません。SQLがロック・タイムアウトしているのかもしれません。いずれにせよ調査にあたり、遅延したときにどんなSQLが実行されていたかは知りたいです。遅いSQLがデータベース遅延の引き金であれば、そのSQLに対して対策を講じるのがあるべき姿だからです。そのためには**遅いSQLを見つける必要**があります。

この記事では遅いSQLを見つける方法を紹介します。

データベースの性能を評価したい方は以下の記事もご覧ください。
[Db2:性能評価にSQL平均応答時間を用いる](https://qiita.com/tsunenorikan/items/6cf055daef790838c305 "Qiita")

# どんなやり方があるのか
現場では以下をよく使います。

- ロック・イベントモニター
- db2pd
- ステートメント・イベントモニター
- MON_GET_PKG_CACHE_STMT 表関数
- MON_CURRENT_SQL 管理ビュー

# ロック・イベントモニター

デッド・ロックやロック・タイムアウトをしていないかを調べるときに使います。

- データベース作成後、手動で常時有効に設定
- デッド・ロックやロック・タイムアウトが発生するとDb2が自動的に情報を取得
- 情報はdb2evmonfmt(Javaプログラム)でテキストファイルにフォーマット
- どのSQLがデッドロック、もしくはロック待ちになっているのかを詳細に出力

以下はIBMのウェブサイトです。
[[DB2 LUW] ロック・イベント・モニターの設定方法](https://www.ibm.com/support/pages/db2-luw-%E3%83%AD%E3%83%83%E3%82%AF%E3%83%BB%E3%82%A4%E3%83%99%E3%83%B3%E3%83%88%E3%83%BB%E3%83%A2%E3%83%8B%E3%82%BF%E3%83%BC%E3%81%AE%E8%A8%AD%E5%AE%9A%E6%96%B9%E6%B3%95 "IBM")

# db2pd
**障害がまさに発生しているときに実行**、その瞬間にメモリーにある診断情報を出力します。

- 事前設定は必要ない
- コマンドにより、診断情報を手動で出力
- ロック取得状況、実行しているSQLの経過時間など詳細な情報を出力
- 出力ファイルが大きいので見るのが大変

db2pdやロック・タイムアウトやついて知りたい方は以下の記事もご覧ください。
[勉強会:Db2問題判別 ロック タイムアウトと長時間SQL](https://qiita.com/tsunenorikan/items/b46271eaa07e4726b392 "Qiita")

# ステートメント・イベントモニター
**遅延が再現できるときやピーク時間の詳細な動きを見たいとき**に使います。

- 手動で一時的に有効化
- 有効にしている間、全てのSQLの情報を取得できる
- 詳細な情報を取得できる
- 負荷が高く、出力ファイルも大きいので実行時間は1分、長くても3分

以下はIBMのウェブサイトです。
[ステートメント・イベント・モニターによって生成されるデータ](https://www.ibm.com/docs/ja/db2/11.5?topic=monitoring-data-generated-by-statement-event-monitors "IBM")

# MON_GET_PKG_CACHE_STMT 表関数

**気軽に遅いSQLをチェックしたいとき**に使います。パッケージ・キャッシュにあるSQLを実行時間順に出力できます。

- 事前設定は必要ない
- select文の実行でパッケージ・キャッシュに残っているSQLを出力
- 実行時間を降順でorder byすることで遅いSQLを識別
- 同じSQLはまとめられ、実行時間と回数が積算される
- Where句がパラメーターマーカーではなく文字だと別のSQLと扱われる
- パッケージ・キャッシュに残っているSQLしか出力されない

以下はIBMのウェブサイトです。
[MON_GET_PKG_CACHE_STMT 表関数 - パッケージ・キャッシュ・ステートメント・メトリックの取得](https://www.ibm.com/docs/ja/db2/11.5?topic=mpf-mon-get-pkg-cache-stmt-table-function-get-package-cache-statement-metrics "IBM")


# MON_CURRENT_SQL 管理ビュー

現在実行中のSQLを表示します。**cronで定期実行、遅いSQLがあったら収集することで、後から遅かったSQLを確認することができます。**ステートメント・イベントモニターやMON_GET_PKG_CACHE_STMT 表関数がリアルタイムでの取得に向いているのとは対照的です。

- 事前設定は必要ない
- select文の実行で現在実行中のSQLを出力
- 経過時間を降順でorder byすることで遅いSQLを識別
- 同じSQLも別々に出力
- 経過時間をwhere句でフィルターしたのをcronで定期収集が吉

遅いSQLを収集したい方は以下の記事もご覧ください。
[Db2:後から遅いSQLを見つけたい](https://qiita.com/tsunenorikan/items/cd915bf9c0b9307db3e5 "Qiita")

以下はIBMのウェブサイトです。
[MON_CURRENT_SQL - 全メンバーの全アクティビティーに関する主要なメトリックの取得](https://www.ibm.com/docs/ja/db2/11.5?topic=mv-mon-current-sql-retrieve-key-metrics-all-activities-all-members "IBM")

# まとめ
各ツールを比較しました。状況によって、使い分けています。

| ツール|負荷|情報量|取得方法|
|:------------|:------------|:------------|:------------|
|ロック・イベントモニター |低い|多い|自動取得、後で確認が可能|
|db2pd|低い|多い|リアルタイムで手動取得が現実的|
|ステートメント・イベントモニター|高い|多い|リアルタイムで手動取得が現実的|
|MON_GET_PKG_CACHE_STMT 表関数 |低い|少ない|リアルタイムで手動取得が現実的|
|MON_CURRENT_SQL 管理ビュー |低い|少ない|cronで自動取得、後で確認が可能|
[py2rb] itertools.chain

# はじめに
移植やってます
# itertools.chain (Python)
```python
import itertools

for i in itertools.chain([x.end() for x in re.finditer(rule, sequence)], [None]):
```
`extend`と似ていますが、こちらは平坦化も行っています。

https://docs.python.org/ja/3.7/library/itertools.html?highlight=chain#itertools.chain
# flatten (Ruby)
```ruby
[sequence.scan(rule).map { sequence.index(_1) + _1.size } + [nil]].flatten.each do |i|
end
```
平坦化といえば`flatten`

https://docs.ruby-lang.org/ja/latest/method/Array/i/flatten.html
# メモ
+ Python の itertools.chain を学習した
+ 道のりは遠そう
いろいろな方法でajax処理を書いてみた

考えてみると「そこでajaxしてるの？」とチームメンバーに偉そうに聞くことはあるものの、実際にajaxするコードを書いたことがなかったと思い実際に複数パターン書いてみました。

## 前提

リクエストおよびデータ取得先は`JSON Placeholder`を利用
> [https://jsonplaceholder.typicode.com/](https://jsonplaceholder.typicode.com/)

以下リクエスト先から写真データの一覧を取得してみます
> https://jsonplaceholder.typicode.com/albums/1/photos

# ライブラリなしでajax処理
```jsx
var ajax = new XMLHttpRequest();
ajax.open('GET', 'https://jsonplaceholder.typicode.com/albums/1/photos');
ajax.responseType = 'json';
ajax.send(null);

ajax.onreadystatechange = function(){
	// ajaxリクエスト成功
	if(ajax.readyState === XMLHttpRequest.DONE && ajax.status === 200){
		for(var i=0; i<this.response.length; i++){
	    var data = this.response[i];
	    // 写真データのURLをログに出力
	    console.log(data.thumbnailUrl);
		}
	}
}
```

## jQueryでajax処理

```jsx
$(function(){
	$.ajax({
	  type: "GET",
	  url: "https://jsonplaceholder.typicode.com/albums/1/photos",
	  dataType : "json"
	})
	// ajaxリクエスト成功
	.done(function(response){
	  for(var i=0; i<response.length; i++){
	    var data = response[i];
	    // 写真データのURLをログに出力
	    console.log(data.thumbnailUrl);
	  }
	})
	// ajaxリクエスト失敗
	.fail(function(XMLHttpRequest, textStatus, errorThrown){
	    console.log(errorThrown);
	})
});
```

## axiosでajax処理（IEで動きません）

```jsx
axios.get('https://jsonplaceholder.typicode.com/albums/1/photos')
// ajaxリクエスト成功
.then(function (response) {
	for(var i=0; i<response.data.length; i++){
	    var data = response.data[i];
	    console.log(data.thumbnailUrl);
	}
})
// ajaxリクエスト失敗
.catch(function (error) {
	console.log(error);
})
// 最後に実行される処理
.finally(function () {
	console.log('Complete!!');
});
```

## まとめ
3通り試してみましたが、どれでもサクッと処理を書くことはできました。
比較してみたところ、axiosが一番可読性高く実装できそうな印象でした。
多段階のリクエストなど、複雑な処理が必要な場合はaxiosを利用するのがようさそうという感想です。

これからajaxを学ぶ人にとっての参考になれば幸いでございます。
macで使えるプロファイラ（Xcode13版）

mac上でビルドしたコードに対してプロファイラを使いたいとき、Linuxで標準的に使えるgprofが利用できない。clangではそもそも`-pg`オプションが無い。
そこで[以前のバージョンのmacでは`iprofiler`というコマンドを用いてプロファイルを取得することができた](https://qiita.com/yohm/items/450fbae1ee0aebe1261e)が、Xcode13では非推奨となったらしい。
（参考 : https://apple.stackexchange.com/questions/415563/repeatedly-being-asked-to-install-command-line-tools ）

2021年において最新版であるXcode13で使えるプロファイルを取るには`xcrun`, `xctrace`コマンドを利用する。

利用方法は以下の通りである。

```shell
$ xcrun xctrace record --template 'Time Profiler' --launch -- ./a.out
```

実行後に `Launch_a.out_2021-12-21...` というようなディレクトリが作られるので、これをopenコマンドで開くことによってInstruments上でプロファイルを見ることができる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28792/a25612c8-bd29-17ce-2e80-758ef237e3ff.png)

templateの引数として使えるものは'Time Profiler', 'Allocations', 'CPU Profiler' などがあり、Instrumentsで新規作成するときに出てくるダイアログ上で確認できる。
ただし、ほとんどの用途に対しては'Time Profiler'を使っておけば良いと思われる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28792/75b45c29-adff-1d60-9f68-925c0b58bdcb.png)

より詳細な使い方については以下のコマンドを実行するとヘルプが出てくる。

```shell
$ xcrun xctrace record
One of the following options is required: --all-processes, --launch -- command [arguments], --attach <pid|name>
usage: xctrace record [<options>] [--attach | --all-processes | --launch -- command ]

description:
	Perform a new recording on the specified device and target with the given template

options:
	--output <path>                        Output .trace file to the given path
	--append-run                           Appends a new run to an existing trace file
	--template <path|name>                 Record using given trace template name or path
...
```

参考
- https://qiita.com/yohm/items/450fbae1ee0aebe1261e
- https://qiita.com/yohm/items/24e7859f18b1bedcad65
JWTとは

#JWTとは
バックエンドエンジニアとして働いているのにJWTを知らなかったので勉強ついでに記事を書き書き。

JWT(Json Web Token)とは属性情報 (Claim) をJSONデータ構造で表現したトークンの仕様です。
特徴として以下があります。

- 署名 されているため改ざんをチェックできる
- URL Safe (URLに含むことができる文字のみで構成される)
- 実際のデータは JSON 文字列

# 仕組み
JWTは、以下の３つのパーツで構成されます。

- ヘッダー(Base64文字列)
- クレーム情報、つまりデータ本体(Base64文字列)
- 署名(バイナリ文字列)

例えば次のような文字列がJWTです。

```
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6IuWxseeUsCIsImV4cCI6IjIwMTkvMDQvMDEifQ.u8TT4ySJhBiMod1rNqCxiISXwCXqddVSJE5gncSCGD7RPHigHoZiDnLfwcIIGij-ARBrswe4eluMUgaQwS7FUdN8IVwKkFUY1533TQZZYhTUzobO3q_PnDyPi8cPDmkSTJHzBhT298G7fNZENUUo8fmCjOkYC9FibTMrF6Aij4w
```

ピリオド毎に

```
＜ヘッダー＞.＜クレーム部＞.＜署名部＞
```

に分かれています。

URLに含むことができない文字などの関係でjsonをBase64urlエンコードした形になります。

# ヘッダー
ヘッダーにはメタ情報を書きます。

```json
{
"alg": "RS256",
"typ": "JWT"
}
```

`alg`はJWＴのアルゴリズムを指定します（必須らしい...）
`typ`にはトークンタイプを指定します。

# クレーム
クレームの内容はアプリケーションによっては異なるため、必須とされるものは存在しませんが、相互運用性のある属性情報については予約済みパラメーターとして提供されています。

# 署名
データが改ざんされているかどうかをチェックするために署名が使われます。
ヘッダーで指定されたアルゴリズムで署名検証することにより、ID Tokenの正当性を評価できます。

# どこで使う？
認証の場面で主に利用されます。
認証の有効期限や、ユーザー情報を保持しておくことができます。セッションにぶち込むなんてことはしません。

# owari
いや～知らん技術ばっかりで勉強してもしても無限にでてきますな～～～～。
間違え等ありましたらご指摘ください。

### 参考
https://webbibouroku.com/Blog/Article/jwt

https://techblog.yahoo.co.jp/advent-calendar-2017/jwt/
[py2rb] re.finditer

# はじめに
移植やってます
# re.finditer (Python)
```python
import re

text = "He was carefully disguised but captured quickly by police."
for m in re.finditer(r"\w+ly", text):
    print('%02d-%02d: %s' % (m.start(), m.end(), m.group(0)))

# 07-16: carefully
# 40-47: quickly
```
https://docs.python.org/ja/3.7/library/re.html#re.finditer

https://qiita.com/tma15/items/b038a0ade22ba104f293

公式ドキュメントより、こちらの記事のほうが分かりやすい。
# scan (Ruby)
```ruby
text = "He was carefully disguised but captured quickly by police."

puts text.scan(/\w+ly/).map{ "#{text.index(_1).to_s.rjust(2, '0')}-#{(text.index(_1) + _1.size).to_s.rjust(2, '0')}: #{_1}" }

# 07-16: carefully
# 40-47: quickly
```
`String#scan`+`String#index`で行けそう。

https://docs.ruby-lang.org/ja/latest/method/String/i/scan.html

https://docs.ruby-lang.org/ja/latest/method/String/i/index.html
# メモ
+ Python の re.finditer を学習した
+ 道のりは遠そう
コンピュータ・システム　例外の種類

# 例外の種類

4つです。

| クラス | 原因 | 同期/非同期 | 復帰時の振る舞い |
| - | - | - | - |
| 割り込み | I/Oデバイスからのシグナル | 非同期 | 常に次の命令に戻る |
| トラップ | 意図的な例外 | 同期 | 常に次の命令に戻る |
| フォールト | 回復可能かもしれないエラー | 同期 | 現在の命令に戻る |
| アボート | 回復不可能なエラー | 同期 | 復帰することはない |

- 同期 (synchronously)
    - 現在の命令を実行した結果として、同期的に発生する。
    - この例外を起こした命令をフォールディング命令と呼ぶ
- 非同期 (asynchronously)
    - ハードウェア割り込みは特定の命令実行によっては発生しない。

## 割り込み (interrupt)

プロセッサ外にあるI/Oデバイスからのシグナルに反応して非同期に発生します。ハードウェア割り込みに対する例外ハンドラは多くの場合、割り込みハンドラ(interrupt handler)と呼ばれます。

## トラップ (trap)

命令実行の結果として発生する意図的な(intentional)例外です。割り込みハンドラと同様に、トラップハンドラは次の命令に制御を戻します。

もっとも重要な役割は、プロシージャのような形のインターフェースをユーザ・プログラムとカーネル間に提供することです。

このインターフェースを**システムコール**と呼びます。

| 種類 | モード | 命令 | アクセス |
| - | - | - | - |
| システムコール | user mode | 特権命令(privileged instructions) | カーネル定義スタック |
| 通常の関数 | kernel mode | 制限された命令 | 呼び出し元の関数と同じスタック |

## フォールト (fault)

回復の可能性があるエラーによって起きる。フォールトが起きるとプロセッサはフォールトハンドラに制御を移す。エラーが訂正できる場合、フォールディング命令に制御を戻し、再実行する。訂正できない場合はカーネル内のabortルーチンに制御を移す。abortルーチンはプログラムを強制終了させる。

## アボート (abort)

回復不可能なエラーによって起きる。アボートハンドラはabortルーチンに制御を移し、プログラムを強制終了する。

## 参考

[コンピュータ・システム](https://amzn.to/3mlYzwZ): 8章
Laravel8 Nginx 504 Gateway Timeout エラーが出た

# 目的

- Postするファイルサイズの設定修正後にテストで大きいファイルをPostしてみたところ今度は「504 Gateway Timeout」のエラーが出たので解消する方法をメモ的にまとめる

# 経緯

- 下記の作業を実施して大きいファイルをPostしたところ「504 Gateway Timeout」が出た。
    1. [Laravel8 Nginx 「413 Request Entity Too Large」のエラーが出た](https://qiita.com/miriwo/items/5655523f675e2d3020f1)
    1. [NginxのXXX.confに記載して再起動したけど「413 Request Entity Too Large」のエラーが解消しない](https://qiita.com/miriwo/items/91e7f94f203c5f7207f5)

# どうしたいか

- とにかく大きいファイルをPostできるようにしたい。（504エラーをとにかく回避したい。）

# 方法

1. `/etc/nginx/conf.d/default.conf`を修正して設定反映できるようになったので、`default.conf`に下記の内容を記載する。（一旦タイムアウトのリミットを300秒まで引き上げる）

    ```/etc/nginx/conf.d/default.conf
    # ファイルアップロードのタイムアウト対策
    fastcgi_connect_timeout 300;
    fastcgi_send_timeout 300;
    fastcgi_read_timeout 300;
    send_timeout 300;
    keepalive_timeout 300;
    ```

1. default.confファイル内は下記の様に記載されている。

    ```/etc/nginx/conf.d/default.conf
    server {
        listen 80;
        root  /var/www/html/public;
        index index.php index.html;
        # ファイルアップロードのために追記
        client_max_body_size 700M;
        # ファイルアップロードのタイムアウト対策
        fastcgi_connect_timeout 300;
        fastcgi_send_timeout 300;
        fastcgi_read_timeout 300;
        send_timeout 300;
        keepalive_timeout 300;
    
        location / {
            try_files $uri $uri/ /index.php$is_args$args;
        }
    
        location ~ \.php$ {
            fastcgi_split_path_info ^(.+\.php)(/.+)$;
            fastcgi_pass php:9000;
            fastcgi_index index.php;
            include fastcgi_params;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            fastcgi_param PATH_INFO $fastcgi_path_info;
        }
    }
    ```

1. php.iniに下記の記載を追記する。

    ```php.ini
    max_execution_time = 300
    ```

1. 念の為dockerを再ビルドしてnginxを再起動したら5分弱で容量の大きなファイルをPostする事ができた。
1. とりあえずPostできたが実用的な時間じゃないので色々試行錯誤が必要そう。

# 参考文献

- [実行時設定 ¶](https://www.php.net/manual/ja/info.configuration.php#ini.max-execution-time)
- [https://www.php.net/manual/ja/info.configuration.php#ini.max-execution-time](https://www.php.net/manual/ja/info.configuration.php#ini.max-execution-time)
- [https://brainlog.jp/server/post-2800/](https://brainlog.jp/server/post-2800/)
- [https://www.yaz.co.jp/tec-blog/web%E3%82%B5%E3%83%BC%E3%83%93%E3%82%B9/263#macOS%E3%81%A7%E3%81%AE%E7%92%B0%E5%A2%83%E6%A7%8B%E7%AF%89](https://www.yaz.co.jp/tec-blog/web%E3%82%B5%E3%83%BC%E3%83%93%E3%82%B9/263#macOS%E3%81%A7%E3%81%AE%E7%92%B0%E5%A2%83%E6%A7%8B%E7%AF%89)
Blender→Unityでつまづくこと

タイトルの通りです。

# ボーンを作ったはずなのに動かない
ボーンとメッシュがバラバラの状態です。下記の方法でウェイトをつけましょう。

# ボーンの自動ウェイトがつかない
オブジェクトモード内のコレクション内で、CTRLを押しながら**黄色**アイコンの「オブジェクト」→**黄色**の「アーマチュア」の後、右クリックで「ペアレント」→「自動のウェイトで」を押しましょう。
コレクション内でアーマチュア(親)の中にメッシュ(子)が入っていると成功です。
その後アーマチュアを選択して、左上の「ポーズモード」にしてから回転させることでくっついてるか確認できます。

# ボーンとメッシュが一緒に出力されない(どちらかがない)
出力時にコレクションで選択したオブジェクトのみの出力をする際に、**黄色**のアーマチュアと**黄色**のオブジェクトを選びましょう。
もしくはオブジェクトの選択を使わずに下のアーマチュアとメッシュからでも出力できます。
【Rails】環境変数使うならHeroku側にも設定しないと当然エラーが出る件

# はじめに

転職のためプログラミングを勉強し始めて約4ヶ月が経ちました。
現在、Ruby on Railsを使用して音声の感情を判定するポートフォリオを製作しています。
API利用で音声をpostしてレスポンスをもらうコードをHerokuに反映させたときのエラーについて記事に残したいと思います。

# 結論先に
ローカルでAPIキーを環境変数に設定した場合、
Heroku側にも設定しなければならない

  
# エラーまでの経緯
今回使用したいAPIは一日の利用回数限度が設定されていた。
ポートフォリオで使うにはもう少し上限を上げたいと思い、開発企業側にコンタクトをとってみる。
幸い上限枠の拡張を快く了承してくれ、専用のAPIキーを発行してくれた。
  
このAPIキーをGitに晒すのは良くないので、
dotenvを使用して環境変数とすることに。
  
dotenvの公式資料はこちら↓
https://github.com/bkeepers/dotenv

  
.envファイルにAPIキーを定義して

```:.env
API_KEY = '***********'
```

Railsのコントローラーで使う

```Ruby:hogehoge_controller
#~省略
key = ENV['API_KEY']
#~省略
```
Gitに晒したくないので、
.gitignoreファイルへ/.envを記載する【※重要】

```:.gitignore
/.env
```

rails sで確認、問題なし。
git pushして
herokuにもpush。

  
# heroku openでArgumenterror
APIを利用する箇所でエラーが出てしまった。
アレコレ考えているうちに、『そういやHerokuってGitの情報を元にしてるから環境変数知らんやん』
と気づきました。


# Heroku側で設定を追加する
ということで解決までの流れです。
コマンドのみで操作して解決できる方法もあるのですが、
Herokuのどの部分に書くのかな〜と見ながら進めたいと思ったので
アナログにHerokuにログインして進めました。
  
まずはHerokuにログインして、該当のアプリを開く
上部にメニューがあるので『Settings』を選択
[![Image from Gyazo](https://i.gyazo.com/57fab141c820417e79db1d89442703ad.png)](https://gyazo.com/57fab141c820417e79db1d89442703ad)
上から2番目くらいにConfig Varsという項目があるので『Reveal Config Vars』を押下
[![Image from Gyazo](https://i.gyazo.com/8e3410dc69054cd15bf7a2db5592fa63.png)](https://gyazo.com/8e3410dc69054cd15bf7a2db5592fa63)
Config Varsが表示されているはず。
左枠にKEY、右枠にValueを入れることができます。
[![Image from Gyazo](https://i.gyazo.com/c17acf32ebf164eb81da3177893097bc.png)](https://gyazo.com/c17acf32ebf164eb81da3177893097bc)
今回はこの様に記載する
[![Image from Gyazo](https://i.gyazo.com/0137f9d9dcebc4bcbcaa3df6d893108d.png)](https://gyazo.com/0137f9d9dcebc4bcbcaa3df6d893108d)
Addを押下して完了！
一応Heroku再起動のコマンドを叩きました

```
heroku restart
```
  
ちなみに、.envファイルに書いたみたいに
Value枠に'***********'←の''シングルコーテーションをつけちゃうとダメだったのでお気をつけて・・・
【VB.NET、C#】実行中のクラス名・メソッド名を取得する方法

VB.NET、C#で実行しているクラス名とメソッド名を取得する方法です。
ログファイルへの出力して、どのクラス・メソッドでエラーが出力されたのかを確認するために役立ちます。
#実行中クラス名の取得方法
実行中のクラス名を取得する方法は、Objectクラスに用意されているGetTypeメソッドを利用します。

```vb
'【VB.NET】
Me.[GetType]().Name
```
```c#
//【C#】
GetType().Name
```

#実行中メソッド名の取得方法
実行中のメソッド名を取得する方法は、MethodBaseクラスに用意されているGetCurrentMethodメソッドを利用します。

```vb
'【VB.NET】
System.Reflection.MethodBase.GetCurrentMethod.Name
```
```c#
//【C#】
System.Reflection.MethodBase.GetCurrentMethod().Name
```


#実行確認用テストフォーム
クラス名・メソッド名を取得できているか確認するためのフォームを作成しました。
![20211221_02_001.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2162017/63349395-659c-18d5-77aa-3d16007825e5.jpeg)
実行ボタンをクリックすると、テキストボックスにクラスメイトメソッド名が表示される画面です。

VB.NET、C#のソースコードは以下

```vb
'【VB.NET】
Public Class MainForm
    Private Sub btnGetRunInfo_Click(sender As Object, e As EventArgs) Handles btnGetRunInfo.Click
        Dim strClassName = Me.[GetType]().Name
        Dim strMethodName = System.Reflection.MethodBase.GetCurrentMethod.Name

        'クラス名を表示
        txtClassName.Text = strClassName
        'メソッド名を表示
        txtMethodName.Text = strMethodName

    End Sub
End Class
```
```c#
//【C#】
    public partial class MainForm : Form
    {
        public MainForm()
        {
            InitializeComponent();
        }

        private void btnGetRunInfo_Click(object sender, EventArgs e)
        {
            string strClassName = GetType().Name;
            string strMethodName = System.Reflection.MethodBase.GetCurrentMethod().Name;

            //クラス名を表示
            txtClassName.Text = strClassName;
            //メソッド名を表示
            txtMethodName.Text = strMethodName;
        }
    }
```

実行結果。
![20211221_02_002.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2162017/b803a6c7-2278-833d-c10b-ccd59f4fc644.jpeg)

#参考
https://docs.microsoft.com/ja-jp/dotnet/api/system.object.gettype?view=net-6.0

https://docs.microsoft.com/ja-jp/dotnet/api/system.reflection.methodbase.getcurrentmethod?redirectedfrom=MSDN&view=net-6.0#System_Reflection_MethodBase_GetCurrentMethod

https://stellacreate.com/entry/cs-get-run-class-method
【TypeScript】 有効な状態を表す値だけを許可する

# はじめに
この記事は、[JSL(日本システム技研) Advent Calendar 2021](https://qiita.com/advent-calendar/2021/jsl) の記事です。

- 環境
  - TypeScript v4.5.3
 
# 伝えたいこと
- 有効と無効、両方の状態を表現するタイプはエラーの元なので、注意が必要です。

### 大型旅客機エアバスA100が墜落、多くの犠牲者が…。
- 飛行機の設計に携わるエンジニアの話。

A先輩　「B君。エアバスA100の操縦システムの設計よろしく。」

　　　　 「操縦士用と副操縦士用の操縦桿が2つあって独立しているから、どっちも機能するようにしておいて。」

B君　「はい、わかりました!! 任せてください!! 」

　　　 (…とは言ったもののどうやって作るんだろ。)

```ts
interface CockpitControls {
  /** 操縦桿の角度 0 = ニュートラル */ 
  leftSideStick: number;
  rightSideStick: number;
}
```
B君　( まず右の操縦桿と左の操縦桿をモデル化させます、と。)

　　 　( 操縦桿を手前に引いたら:airplane: の高度があがって、操縦桿を奥に押すと:airplane: の高度が下がるんですよね。多分。)

```ts
function getStickSetting(controls: CockpitControls) { 
  return controls.leftSideStick;
}
```
B君　(操縦桿の状態を出力する関数はこんな感じか? とりあえず、これでいいか。)

　　 　(…あ、でも、これだと右の操縦桿が機能していないな。)

```ts

function getStickSetting(controls: CockpitControls) { 
  const {leftSideStick, rightSideStick} = controls; 
  if (leftSideStick === 0) {
    return rightSideStick; 
  }
  return leftSideStick; }
```
B君 「よし。これで。ok」

　　 　(…と思ったけど、左が0だった場合のみ右が機能するってことしか確証できないんじゃないかな…。)
　　 　(じゃあ一応、右が0の場合も考慮しておこう…。)   

```ts
function getStickSetting(controls: CockpitControls) { 
  const {leftSideStick, rightSideStick} = controls; 
  if (leftSideStick === 0) {
    return rightSideStick;
  } else if (rightSideStick === 0) {
    return leftSideStick; 
  }
}
```

B君 「よし。これでどっちの操縦桿も機能するだろう。」
　　「A先輩、実装しました。レビューお願いします。」

A先輩 「おー。お疲れ様ー。」
　　　「ok、確認するね。…ね、これ、もし操縦桿が両方ともニュートラルじゃなかったら、どうするの?」

B君 「…あ、なるほど。すみません。修正します。」


　　　(もし両方とも、0じゃなかったら、どっちの操縦桿を有効にすればいいんだろう…。)

　　「…わかった:bulb: 右と左の操縦桿の数値を足して平均値を出そう! 」


```ts
function getStickSetting(controls: CockpitControls) { 
  const {leftSideStick, rightSideStick} = controls; 
  if (leftSideStick === 0) {
    return rightSideStick;
  } else if (rightSideStick === 0) {
    return leftSideStick; 
  }
  return (controls.leftSideStick + controls.rightSideStick) / 2
```

### ある日のニュース

アナウンサー 「リオデジャネイロ発エアバスA100がセントポール群島付近の大西洋上に墜落しました。」

　　　　　　「事故の影響で、多くの犠牲者が出てている模様です。」

　　　　　　「それでは墜落直近のコックピットのレコーダーの音声をお聞きください。」

### レコーダーに録音された音声

操縦士　「 おい! 落ちるぞ!!」

　　　　「墜落しないように、高度を下げてスピードを出すんだ!! 」

　　　　「こっちと同じように、そっちの操縦桿も操作しろ!! 」

副操縦士　「はい!! わかりました!! 」

操縦士　「 スピードが下がっているぞ!! スピードを上げるんだ!! 」

副操縦士「 はい!! さっきからやっています!! でも何故かスピードが下がっています!! 」

操縦士　「お、お前、何をしている!!?? 」

副操縦士　「さっきからずっと操縦桿を引いています！! 」

操縦士　「おい! 操縦桿を引いてどうする?! 」
　　　　「機首を上げるな!! 操縦桿を押してスピードを上げろ! 」
　　　　「落ちるぞお-!! 」:airplane: :arrow_lower_right: :fire:

### 次のレビュー会にて

A先輩　「 飛行機落ちちゃったらしいじゃん。 」
　　　　 「右の操縦桿は手前に引いて、左の操縦桿は奥に押して、操作指示が相殺されたんだってね。」

B君 「はい。すみません。みたいですね…。」

A先輩 「そもそも`getStickSetting()`は必要ないんじゃないかな？」
　　　「関数で、左が0だったら○○とか、右が0だったら××とか。ごちゃごちゃ考えないでさ。型定義の時に単純にこうすればよかったんじゃない?」


```ts
interface CockpitControls {
  stickAngle: number;
}
```
B君　「…あ。なるほどです。」

## まとめ
- 型を設定する時は有効な状態を表す値だけを許可するようにしてください。
- コードは書きやすくなり、チェックも楽になります。

### 参考文献
- Effective TypeScript  
https://effectivetypescript.com/
Pandasのデータフレーム。「ある値」以下の値が存在する列のみ を抽出したい

何度も忘れ、無駄に検索を繰返してしまう処理を備忘録として記載する。
（ここで `df` は `pandas.DataFrame`）

##### １、「ある値未満の値が存在する列のみを抽出したい」場合
* 例えばある値を１００として、１００未満の値を含む列だけを抽出したい場合、
`condition = df < 100`とおいて、

```python
condition = df < 100
df.loc[:, condition.any(axis=0)]
```
(`any()`が簡便とご指摘いただき　~~`(~df[condition].isnull()).sum() != 0`~~ を削除しました。）
(※ 返り値がデータフレームとなる条件式が `.any()`でなぜ処理できるのか疑問でしたが、`.any()` は `axis` 引数を省略可能でデフォルトが `.any(axis=0)` であるとのこと。https://estuarine.jp/2017/09/extract_rows_with_nan/ ）

* 列中のすべての行が（表計算ソフトで言うところのすべてのセルが）、１００未満の列のみを抽出したい場合は以下のように書く。
~~`df.loc[:, df[condition].isnull().sum() == 0]`~~ 

```python
df.loc[:, condition.all(axis=0)]
```


##### ２、「ある値より大きい値が存在する列のみを抽出したい」場合
不等号の向きを変えて、`condition = df > 100`とします。
GitHub Enterprise で billing manager を追加・削除する手順

# GitHub の billing manager とは

billing manager は支払設定の管理するだけのユーザーで、ライセンスを消費しません。
メニュー「Billing」だけ操作可能です。

https://docs.github.com/en/enterprise-cloud@latest/organizations/managing-peoples-access-to-your-organization-with-roles/adding-a-billing-manager-to-your-organization

公式ドキュメントではOrganizationの手順になっており、Enterpriseの場合は少し違ったのでメモとして残します。

# 追加手順
Enterprise の管理者権限を持つアカウントで操作します

1. GitHub Enterprise の管理画面を開く
   - `https://github.com/enterprises/[enterprise名]`
1. メニューから People > Administrators を開く
   - `https://github.com/enterprises/[enterprise名]/admins`
1. 「Invite admin」から「Billing manager」でアカウントを招待する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628295/639efaa6-37b1-7da8-cf93-4e332db47732.png)
1. 招待したアカウントにinvitation mailが届くので、招待を受諾すればOK

# 削除手順
Enterprise の管理者権限を持つアカウントで操作します

1. GitHub Enterprise の管理画面を開く
   - `https://github.com/enterprises/[enterprise名]`
1. メニューから People > Administrators を開く
   - `https://github.com/enterprises/[enterprise名]/admins`
1. Roleが`Billing manager`となっている対象のアカウントで「Remove billing manager」を選択すればOK
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628295/c16c4553-e82d-2710-b05c-025a00cba65c.png)

# 補足

Enterpriseでのロールについては以下を参照ください。

https://github.wiki/ja/enterprise-cloud@latest/admin/user-management/managing-users-in-your-enterprise/roles-in-an-enterprise

Membersがライセンスを使う対象です。
問題解決力を向上させよう

## はじめに
どうもこんにちは@hanamichiです。

問題解決力ってよく耳にしますよね。
問題解決力がある人材が必要だ！とか、問題解決力が強みです！とかとか
職場でもバイト先でも問題に直面した際に、本当の問題は何で、何をしたら解決に向かうのかと考えることは頻繁にあると思います。
この記事では問題に直面した際にどう行動すれば良いか具体的な例を交えて話していきます。


## そもそも「問題解決力」って何だっけ？
生じている問題に対して、問題が生じた要因や原因を洗い出す。その後問題を解決できる対応可能な案を出し、解決に導く能力です。
## 問題とは？
一言で言うと理想と現実のギャップです。
例えば、「現在私の体重は100kgで来年の秋には90kgにしたいです。」みたいなことを語ってるA君がいるとします。
ここで言う現実は体重が100kgであることで、理想は来年の秋に90kgにすることです。

では問題は？

上記にある通り問題は理想と現実のギャップです。
つまり問題は「理想数値より10kg多い100kgであることです。」(めちゃくちゃ当たり前な話)

問題を解決するにはまず現状を知って、理想とのギャップを埋める。ということです。

## 解決するための5step
フレームワークではないですが、頻繁に利用されている手順です。
下記の順番でA君が痩せれるようにアドバイスをしましょう。

>1.現状の把握
>2.問題発見
>3.原因の分析
>4.解決策を出す
>5.解決策の実行


### 1.現状の把握
上記の例を用いて説明していきます。
A君は自分の体重は把握しているのでここはクリアとします。

### 2.問題発見
次の問題の発見ですが、冒頭で話した通り問題は、現実と理想とのギャップなので「理想数値より10kg多い100kgであることです。」

### 3.原因の分析
原因を探っていきましょう！
例文から原因を導くのは不可能なのでヒアリングした結果、運動は毎日しておりラーメンを毎日３食食べていると仮定します。
条件として、
・これ以上運動量は増やせない
とします。
上記のヒアリング結果的に「ラーメンを毎日３食食べている」が原因そうですね。
### 4.解決策を出す
一旦今までの流れを整理します。
>現状:体重100kg
>理想:来年の秋までに90kg
>問題:今の体重が理想より10kg多いこと
>原因:ラーメンの食べ過ぎ

こんな感じですね。
解決策は「ラーメンの食べ過ぎ」を解決するためにすれば良いことを洗い出せば良いだけです。(ここでセンスが出ますね)
・食べないようにする
・食べる回数を減らす
・食材をカロリーが低いものに変える
・とかとか

### 5.解決策の実行
あとはその解決策が実行可能かどうかを判断し選別して実行に移すだけです。(僕的にここがすごく重要)
・その解決策で来年の秋までに10kg痩せれるか？
・A君が継続可能かどうか
この辺ですかね。

例がめちゃくちゃ簡単すぎて逆にイメージしづらいかったかもしれませんが、こんな感じの流れでやっていくとよりクリティカルな解決策を導けるのではないでしょうか。
初めての正規表現

# はじめに
人生で初めて正規表現を書く機会がありましたが、想像通り難しかった＆勉強になったので共有します。

## 要件
メールアドレスの以下4つの要件を満たす正規表現を作ることになりました。

既存要件

- 「@」の入力必須

新規要件

- ローカル部分の先頭のドットを禁止
- ローカル部分で連続するドットを禁止
- ローカル部分の末尾のドットを禁止する

（※ローカル部分とはメールアドレスの@以前を指します）


つまり、以下のようなメールアドレスは弾きたいということです。

✕  .sample@example.com
✕  s..ample@example.com
✕  sample.@example.com

## まず第一歩
正規表現の知識が0だったので本当に初歩的なところから調べました。

|文字  |説明  |
|---|---|
|.  |任意の１文字 にマッチ|
|+  |直前の文字が １回以上 繰り返す場合にマッチ|
|*  |直前の文字が ０回以上 繰り返す場合にマッチ|
|?  |直前の文字が ０個か１個 の場合にマッチ|
|^  |直後の文字が行の 先頭 にある場合にマッチ|
|$  |直前の文字が行の 末尾 にある場合にマッチ|
|[...]|角括弧に含まれるいずれか１文字にマッチ|
|[^...]|角括弧に含まれる文字以外にマッチ|

（全然足りないけど・・・）
（こんなレベル感・・・）

## 最初に完成したもの
`/^(?=^(?!\.).*)(?=^(?:(?!\.\.).)*$)(?=(?!.*\.$).*$)/`

ググって見つけた表現を訳もわからず駆使して組み合わせました。
今見ても全く何を書いているのか分かりませんが、覚えたての`?=`（かつ）を使って3つの新規要件を満たそうとしている感じが伝わります。

そしてこの正規表現は「@」以前を切り取ってローカル部分のみバリデーションをかける想定の正規表現なので、「@」の入力チェックは別でJavaScriptでやる想定です。すごく面倒ですね。


https://regex101.com/
こちらのサイトで正規表現の挙動を確認できるのですが、一応3つの要件は満たされているものでした。

## 考え方が違った
どう見ても私が作った正規表現は、巷でよく見かける正規表現とはかけ離れていたため、再度考え直しました。
どうやら、考え方が全然違ったようです。

気を取り直してまずは、`ローカル部分先頭のドットを禁止`する正規表現を考えてみます。
これはつまり、`ドット以外の任意の1文字から始まる`と捉えることができるので、`/^[^.]+.*@.*/`で良さそうです。
少しずつ分解してみると、`^`（先頭）→`[^.]+`（ドット以外の文字が１回以上）→`.*`（何かしらの文字が0回以上）→`@`→`.+`（何かしらの文字が1回以上）、のようにチェックが行われています。

次に、`ローカル部分で連続するドットを禁止`する正規表現は、`ドットを入力する場合は、ドットとドット以外の任意の1文字セットで！`と考えられるので、上の正規表現に追加して、`/^[^.]+((\.[^.]+)*)@.*/`で実装することができます。
追加された`(\.[^.]+)`を分解してみると、`\.`（ドット）→`[^.]+`（ドット以外の文字が１回以上）というふうに、ドットの後に続く文字がドットではないことをチェックしています。


こうすると、ドットの後には必然的にドット以外の1文字が来るため、`ローカル部分末尾のドットを禁止する`も同時に満たすことができました。

最後に、元の仕様を踏襲するために、@以前に何も入力されていなくてもバリデーションエラーが出ないよう、@以前は全て任意とすべく調整し、完成した正規表現がこちらです。

`/^([^.]+(\.[^.]+)*)*@.*$/`


## しかし・・・
ディレクターさん「メールアドレス20文字以上入力すると画面フリーズするよ〜」



確認してみると、確かにエラー出てました。

Catastrophic backtracking has been detected and the execution of your expression has been halted. To find out more and what this is, please read the following article:
日本語訳：破壊的なバックトラッキングが検出され、式の実行が停止されました。・・・


## 破壊的なバックトラック(Catastrophic backtracking)
一部の正規表現は、実行時間が非常に長く JavaScript エンジンを"ハング"させることがあるそうです。
つまり正規表現にもパフォーマンスという概念があり（当たり前）、処理が重すぎて落ちました。
調べ始めたら沼にハマるので、興味がある方はぜひ、ご査収ください。

https://ja.javascript.info/regexp-catastrophic-backtracking


解決方法は色々あるみたいですが、私の場合`@`以前の`*`を`?`にしたら直ったので、最終的にこちらに落ち着きました。
`/^([^.]+(\.[^.]+)*)?@.*$/`


## 最後に
まだまだ初歩的な部分しか学べていないですが、簡単な正規表現であれば読めるようになったので世界が広がりました。
もっとかっこいい正規表現を書けるように頑張ります。

それでは皆様良いお年を。
効率的なビヘイビアツリーの実装

UE4やUnityのおかげで、すっかり普及した感のあるビヘイビアツリー。
基本的な実装方法や使用方法についての解説は、ネットを少し探せばたくさん見つかります。
今回は、より高速で効率的なビヘイビアツリーの実装について考えてみます。

## ビヘイビアツリーとは
基本的な仕組みについては割愛。
下記のスライドが、非常に分かりやすいと思います。
https://www.slideshare.net/sindharta/behaviour-treeingriffon/

## 静的なツリーデータ
ビヘイビアツリーは、振る舞いを表す静的なデータとして表現することができます。
必要なのは、ノードの種類、ノード自身を表す属性、そして親子関係のみとなります。
そのため、ビヘイビアツリーを実行するインスタンス間でツリーデータを共有することができれば、メモリを大幅に節約することができます。
さらに、ツリーノードの巡回は深さ優先で行われるため、各ツリーノードのメモリ配置を深さ優先で連続したメモリに配置することで、実行時のキャッシュヒット率も上げられると考えられます。

## インスタンスごとの実行時データ
ビヘイビアツリーの実行時に必要なデータは、各インスタンスごとにノード固有のデータが要求されます。
Sequenceノードであれば現在有効な子ノードのインデックス、Actionノードであれば関連するエンティティへのポインタなどです。

通常、ビヘイビアツリーを実行するインスタンスは、常にカレントの有効なノードにしか触りません。
これは、巨大なビヘイビアツリーであっても実行時に必要なデータ量というのはごく少量(数バイト～数十バイト程度)だと言うことです。
そのため、各インスタンスがカレントのノードを有効にする際に必要なメモリを確保し、ノードが結果を返すか中断されたらメモリを解放するようにすれば、実行時のメモリフットプリントを非常に小さくすることができます。
メモリの確保には小さなメモリを高速に割り当てられる bucket-based allocator などを用意すると良いでしょう。

## ツリーデータと実行時データの分離
これはおおよそ機械的に、状態を持つパラメータとそうでないものを分けることで実現できます。

```cpp
class Sequence : public Composite {
public:
    struct RuntimeData {
        uint8_t currentChild;  // 現在有効な子ノードのインデックス
    };
};
```

## 実行時データへのアクセス方法
実際にビヘイビアツリーの更新を行うためには、各ノードにおいて、インスタンスごとの実行時データ領域を取得する方法が必要になります。
1つの解決案としては、インスタンスとツリーノードにそれぞれユニークIDを持たせ、これらの値をキーとして実行時データ領域を取得できるようにすることです。

```cpp
inline uint32_t makeRuntimeDataId(uint32_t entity, uint32_t uid) {
    // https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function
    uint32_t ids[] = {entity, uid};
    return FNV(ids, sizeof(ids));
}

void BehaviorNode::execute(uint32_t behaviorTreeInstanceId) {
    uint32_t runtimeDataId = makeRuntimeDataId(behaviorTreeInstanceId, mUid);
    // mRuntimeDataManagerはノードの作成時に渡される
    // これは数百KBから数MB程度の小さなヒープを管理しており、渡されたハッシュ値をキーに実行時データのメモリ領域を管理している
    void* runtimeData = mRuntimeDataManager->find(runtimeDataId);
    if (!runtimeData) {
        runtimeData = mRuntimeDataManager->allocateRuntimeDataMemory(runtimeDataId);
        onInitialize(behaviorTreeInstanceId, runtimeData);
    }

    BehaviorStatus status = update(behaviorTreeInstanceId, runtimeData);

    if (status != BehaviorStatus::RUNNING) {
        onTerminate(behaviorTreeInstanceId, runtimeData);
        mRuntimeDataManager->deallocate(runtimeDataId);
    }
}
```

## 参考
Game AI Pro
http://www.gameaipro.com/

Game AI Pro Section 2: Architecture
6. The Behavior Tree Starter Kit, Alex Champandard, Philip Dunstan
http://www.gameaipro.com/GameAIPro/GameAIPro_Chapter06_The_Behavior_Tree_Starter_Kit.pdf

Amazon Lumberyard
Modular Behavior Tree
C++ Implementation: Runtime data
https://docs.aws.amazon.com/lumberyard/latest/userguide/ai-scripting-mbt.html
Base64 エンコーディング

# Base64 とは？
データを64種類の印字可能な英数字のみを用いて、それ以外の文字を扱うことの出来ない通信環境にてマルチバイト文字やバイナリデータを扱うためのエンコード方式である。MIMEによって規定されていて、7ビットのデータしか扱うことの出来ない電子メールにて広く利用されている。具体的には、A–Z, a–z, 0–9 までの62文字と、記号2つ (+, /)、さらにパディング（余った部分を詰める）のための記号として = が用いられる。この変換によって、データ量は4/3（約133%）になる。また、MIMEの基準では76文字ごとに改行コードが入るため、この分の2バイトを計算に入れるとデータ量は約137%となる。

Base64でエンコードされたリソースをHTML、XML、およびCSSファイルに直接埋め込みます。
<script type="text/javascript" src="data:text/javascript;base64,LyohDQogKiBqUXVlcnkgSmF2YVNjcmlwdCBM..."></script>

# 変換形式
Base64変換の手順を以下に挙げる。
1、元データを6ビットずつに分割。（6ビットに満たない分は0を追加して6ビットにする）
2、各6ビットの値を変換表を使って4文字ずつ変換。（4文字に満たない分は = 記号を追加して4文字にする）

## 変換例
元データ
(tsukaiyasui.com)
-> 
16進
(46 72 65 65 42 61 73 65 36 34 65 6e 63 6f 64 65 72)
-> 
2進
(01000110 01110010 01100101 01100101 01000010 01100001 01110011 01100101 00110110 00110100 01100101 01101110 01100011 01101111 01100100 01100101 01110010)
-> 
6ビットずつに分割
(010001 100111 001001 100101 011001 010100 001001 100001 011100 110110 010100 110110 001101 000110 010101 101110 011000 110110 111101 100100 011001 010111 0010)
->
2ビット余るので、4ビット分0を追加して6ビットにする
(010001 100111 001001 100101 011001 010100 001001 100001 011100 110110 010100 110110 001101 000110 010101 101110 011000 110110 111101 100100 011001 010111 0010<b>00</b>)
->
変換表により、4文字ずつ変換
(RnJl ZUJh c2U2 NGVu Y29k ZXI)
->
1文字余るので、1文字分 = 記号を追加して4文字にする
(RnJl ZUJh c2U2 NGVu Y29k ZXI<b>=</b>)

[オンライン実行](https://tsukaiyasui.com/base64-encoder)

## Base64でのエンコーディング
１、元文字列 ->  Base64文字列
２、ファイル ->  Base64文字列


## 参考サイト(Base64でのファイルエンコーディング可能)
https://tsukaiyasui.com/base64-encoder
（備忘録）gradleビルド接続中にエラーが発生したため…の解決法

# 記事を見つけてほしい人
- EclipseでGradleプロジェクトをインポートしようとした際に、普段なら上手くインポートできるのにたまに表題のエラー文にぶち当たる人。
- GradleプロジェクトでSpotlessを適用しようとしたけど、なぜか失敗しちゃう人。

↓こんな感じ

```
user@mypc MINGW64 ~/workspace/testProject (master)
$ ./gradlew spotlessApply

FAILURE: Build failed with an exception.

* What went wrong:
Unable to find a usable idle daemon. I have connected to 100 different daemons but I could not use any of them to run the build. BuildActionParameters were DefaultBuildActionParameters{, currentDir...（省略）

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.
```

# どうすれば良いか
`.gradle/daemon/{{version}}` フォルダ内の`registry.bin`や`.log`ファイルなどを全部削除する。以上です。
コンピュータ・システム　レジスタの種類

# レジスタ

混乱してきたので一旦整理。簡単なメモ。

> レジスタとは、マイクロプロセッサ（MPU/CPU）内部にある、演算や実行状態の保持に用いる記憶素子。最も高速な記憶装置だが、一般的なCPU製品で数個から数十個（容量に換算して数十バイト程度）と数が限られる。GPUなど特殊なプロセッサでは数万個（数百キロバイト）のレジスタを内蔵するものもある。

## プログラムカウンタ

> マイクロプロセッサ（MPU/CPU）内部でデータを保持するレジスタの一種で、次に実行すべき命令が格納されているメモリ上の番地（アドレス）を保存しているもの。また、その保存しているアドレス値。「PC」と略記されることもある。

## アキュムレータ

> 論理演算や算術演算の結果を一時的に保持しておくためのものをアキュムレータと呼ぶ。

## データレジスタ

> 演算結果を置いたり、データを一時的に記憶するレジスタである。プロセッサの内部バスにより演算装置とデータをやりとりできる。また、外部データバスとデータをやりとりできる。

## アドレスレジスタ

> メモリをアクセスする場合のアドレスを指定するときに用いるレジスタである。この内容を外部アドレスバスに出す事により、メインメモリからデータを読み出す。また、プロセッサによっては、アドレスを計算するための演算回路が付属しており、実効アドレスの計算を行なうことができるようになっていることもある。

## インデックスレジスタ

> アクセスしたいメモリ上の番地（アドレス）の、基準値からの相対的な値を格納するためのもの。汎用レジスタを転用することが多い。

## ベースレジスタ

> アクセスしたいメインメモリ上の番地（アドレス）の基準値や先頭位置を記憶しておくためのもの。

インデックスレジスタと組み合わせて使用する。

## スタックポインタ

> スタックと呼ばれるメモリ領域の現在の操作位置を保持するためのもの。

## ステータスレジスタ (フラグレジスタ)

> 演算や処理の結果により一部が書き換えられるもの。条件分岐命令などがその内容を読み取って動作に反映させる。

## 命令レジスタ

> プロセッサが命令を実行する際、プログラムカウンタ（PC：Program Counter）と呼ばれるレジスタの内容を参照し、メインメモリ上の現在の実行位置から命令を読み出す（フェッチ）。読み出された命令は命令レジスタに格納され、命令デコーダによりその内容が解析される（デコード）。解析された命令の内容に応じて必要なデータなどをレジスタやメインメモリから取り出し、処理を実行する。

## 制御レジスタ(コントロールレジスタ)

アーキテクチャによって実装のされ方が異なる。

> 制御レジスタは、CPUまたはその他のデジタルデバイスの一般的な動作を変更または制御するプロセッサレジスタです。制御レジスタによって実行される一般的なタスクには、割り込み制御、アドレッシングモードの切り替え、ページング制御、およびコプロセッサ制御が含まれます。

## 例外テーブルベースレジスタ

> システムのブート時にオペレーティング・システムは例外テーブル (exception table) とよばれるジャンプ・テーブルを確保し、初期化する。このとき、テーブルのエントリkが例外kのハンドラのアドレスを保持するよう初期化が行われる。

> 実行時(システムが、あるプログラムを実行しているとき)において、プロセッサはイベントが起きたことを検出し、対応する例外の番号kを決定する。

> プロセッサは例外を引き起こすために、間接プロシージャ呼び出しを行う。このとき呼び出されるプロシージャは、例外テーブルのエントリkを介して得られた、イベントに対応する例外ハンドラである。この例外テーブルには例外ハンドラのアドレスがまとめられている。

> 例外番号は例外テーブルのインデクスとして使われる。また、テーブルの開始アドレスはCPUの特別なレジスタによって指定される，このレジスタは，例外テーブル・ベース・レジスタ (exception table base register) とよばれる。

## 参考

[IT用語辞典 e-Words](https://e-words.jp/)
[レジスタ (コンピュータ) - Wikipedia](https://ja.wikipedia.org/wiki/%E3%83%AC%E3%82%B8%E3%82%B9%E3%82%BF_(%E3%82%B3%E3%83%B3%E3%83%94%E3%83%A5%E3%83%BC%E3%82%BF))
[コンピュータ・システム](https://amzn.to/3mlYzwZ)
[Spring]OpenFeignを使って外部API連携

# OpenFeignとは
RESTクライアントを簡単に作るためのフレームワークです
> 宣言的な REST クライアント: Feign は、JAX-RS または Spring MVC アノテーションで装飾されたインターフェースの動的実装を作成します

https://spring.pleiades.io/projects/spring-cloud-openfeign

# 使い方
## 環境
Java11
Spring 2.6.1

## OpenFeignのインストール
dependenciesに下記を追加します

```build.gradle
dependencies {
    // feign(HttpClient)
    implementation("org.springframework.cloud:spring-cloud-starter-openfeign:3.1.0")
    implementation("io.github.openfeign:feign-okhttp:11.7")
    implementation("io.github.openfeign:feign-jackson:11.7")
    implementation("io.github.openfeign:feign-slf4j:11.7")
}
```

## OpenFeignを有効にする
Mainクラスに@EnableFeignClientsを付与してClientのコンポーネントスキャンを有効にします

```SampleApplication.java
@SpringBootApplication
@EnableFeignClients
public class SampleApplication {
	public static void main(String[] args) {
		SpringApplication.run(SampleApplication.class, args);
	}
}
```

## Feign Clientインターフェースの作成
configurationを宣言することで、既存コンポーネントをオーバーライドし、独自のエラーハンドリング等を行うことができます
作成したのはインターフェースですが、実装はFeignのフレームワークが勝手に作ってくれます

```ServiceFoundationClient.java
@FeignClient(name = "serviceFoundation", url = "${service_foundation.server.url}", configuration = ServiceFoundationFeignConfiguration.class)
public interface ServiceFoundationClient {
    /**
     * サンプル
     */
    @RequestMapping(method = RequestMethod.POST, value = "sample/api")
    BaseResponseData sample(@RequestHeader(name = "Authorization") String token, @RequestHeader(name = "Content-Type") String contentType) throws AccessTokenExpiredException;
}
```

## Clientを呼ぶ

```ServiceFoundationApiRepositoryImpl.java
@Repository
@Slf4j
public class ServiceFoundationApiRepositoryImpl implements ServiceFoundationApiRepository {

    private String CONTENT_TYPE = "application/json; charset=utf-8";

    private final ServiceFoundationClient serviceFoundationClient;

    public ServiceFoundationApiRepositoryImpl(ServiceFoundationClient serviceFoundationClient) {
        this.serviceFoundationClient = serviceFoundationClient;
    }

    @Override
    public BaseResponseData sample(String token) throws AccessTokenExpiredException {

        BaseResponseData response = serviceFoundationClient.sample(token, CONTENT_TYPE);
        
        if (StringUtil.isNotEmpty(response.getErrorCode())) {
            //エラー時の処理
        }
        return response;
    }
}
```

## 最後に
ご覧いただきありがとうございました
可読性が高く、非常に使いやすいですね
何かあればお気軽にコメントください

## 参考
https://cloud.spring.io/spring-cloud-openfeign/reference/html/

https://yuukiyg.hatenablog.jp/entry/2019/11/18/203208
Watch Connectivityが突然接続できなくなる問題の解決方法

開発中のアプリで突然WatchConnectivityが接続できなる問題にたまに苦戦します。
何度か経験して今回長い時間ハマったのでとりあえず雑な知見をまとめます。

# 現象
* 特定のアプリのWatchConnectivityがまったく接続できなくなる
* 別のアプリのWatchConnectivityは接続できる
* WCSession#isReachable:trueだが、接続を試みてしばらくするとfalseになって切断されている
* iPhoneへのリクエストは到達しており、レスポンスをWatchで受け取れていない(replyHandlerは実行されている)
* Apple Watchのコントロールセンター的なところではiPhoneと接続済みのステータス

# 解決方法
* iPhone,Apple Watchを機内モードにする
* iPhone,Apple Watchを再起動する
* iPhone,Apple Watchを機内モード解除する

[参考](https://support.apple.com/en-lamr/HT205025)


## 補足
関係あるか不明だが、以下の状況のApple Watchが近くにあったのも問題だったかもしれません。
* 同じアプリがインストールされている
* 以前iPhoneとペアリングされていた


# メモ
* ipa配布したアプリか否かの因果関係は不明
* 今回はWatchアプリの開発中に配布したipaで発生した。
* またエンドユーザーからの問い合わせで、このような状況になっている可能性の高そうな問い合わせがある。
IOUで評価しよう

#IOUで評価しよう
メモがわりに書き残しておきます
##IOUって何なん

https://mathwords.net/iou

領域の共通部分/領域の和集合　らしい。
領域の重なり度合いです。
よく物体検出でiouの閾値を設定するところがあるのでそれですね。

##とりま実装

```python:iou.py
def IOU(box1,box2):
    X = box1[0]
    Y = box1[1]
    X1 = box1[2]
    Y1 = box1[3]
    _X = box2[0]
    _Y = box2[1]
    _X1 = box2[2]
    _Y1 = box2[3]

    ls = int((X1 - X) * (Y1 - Y))
    ms = int((_X1 - _X) * (_Y1 - _Y))
    lx_line = range(X,X1)
    mx_line = range(_X,_X1)
    ly_line = range(Y,Y1)
    my_line = range(_Y,_Y1)
    lmx = len(list(set(lx_line) & set(mx_line)))
    lmy = len(list(set(ly_line) & set(my_line)))
    TP= int(lmx) * int(lmy)
    Iou = TP / (ls+ms-TP)

    return Iou
```
入力は左上と右下のxy座標をリストで渡せば良い
人物画像の背景を１行のコードで差し替えるなら、SemanticImageで

#画像にバーチャル背景をつける方法

Swiftで人物の背景を別の画像にかえます。
<img width="300" src="https://user-images.githubusercontent.com/23278992/146862832-14c0f002-b4e7-43c6-92e4-8595e99e15fd.JPG">


#簡単に画像合成したい

人物画像の背景を差し替えるには、下記のステップがあるけど、一発で合成したい。

>１、人物をきれいに切り抜く
２、背景画像のサイズと位置を調整する
３、合成する

#SemanticImageならあっという間

[**SemanticImage**](https://github.com/john-rocky/SemanticImage)というライブラリを使えば、1行のコードで差し替えられる。

https://github.com/john-rocky/SemanticImage

[<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/e766dcae-378f-b470-b3b8-6d928d0f6811.png">](https://github.com/john-rocky/SemanticImage)


#手順

###１、SemanticImageをプロジェクトに追加する
SwiftPackageManagerで[**SemanticImage**](https://github.com/john-rocky/SemanticImage)を追加する。
（Xcode Projectの「ファイル」→「Add Packages」から検索欄に、"https://github.com/john-rocky/SemanticImage.git"をコピペ）
もしくは、[**SemanticImage**](https://github.com/john-rocky/SemanticImage)のSemanticImage.swiftをプロジェクトにドラッグ。

```swift
import SemanticImage
```

###２、1行で実行

```swift
let swappedImage:UIImage? = SematicImage().swapBackgroundOfPerson(personUIImage: originalUIImage, backgroundUIImage: backgroundUIImage)
```

**　　　Original　　　 +　　　　　Background　　　 = 　　　　Swapped**
<img width="200" src="https://user-images.githubusercontent.com/23278992/146860733-acf875a5-043c-4ebb-ab3c-f98e124f6a93.jpg"> <img width="200" src="https://user-images.githubusercontent.com/23278992/146864525-c787c829-bb98-4838-9dce-831932871f9d.jpeg"> <img width="200" src="https://user-images.githubusercontent.com/23278992/146862832-14c0f002-b4e7-43c6-92e4-8595e99e15fd.JPG">

🐣
****
フリーランスエンジニアです。
お仕事のご相談こちらまで
簡単な開発内容をお書き添えの上、お気軽にご連絡ください。
rockyshikoku@gmail.com

Core MLやARKitを使ったアプリを作っています。
機械学習／AR関連の情報を発信しています。

[Twitter](https://twitter.com/JackdeS11)
[Medium](https://medium.com/@rockyshikoku)
プロデルで乱数

本記事は「[日本語プログラミング言語「プロデル」 Advent Calendar 2021](https://qiita.com/advent-calendar/2021/produire)」21日目の記事です．

[18日目の記事](https://qiita.com/Mopepe51/items/0612d18db835a2334030) で一般の確率分布に従う乱数サンプリングの手法について記述しましたが，今回はより基礎的な機能として

+ シード値を固定した乱数生成
+ 正規分布に従う乱数生成

を行います．

乱数シミュレーションでは再現のためシード値固定機能が必要です．
また，正規分布は必要になる場面が多いので高速で良質な[^good]乱数が得られる[ボックス・ミュラー法](https://ja.wikipedia.org/wiki/%E3%83%9C%E3%83%83%E3%82%AF%E3%82%B9%EF%BC%9D%E3%83%9F%E3%83%A5%E3%83%A9%E3%83%BC%E6%B3%95)を実装しました．

[^good]: 提案分布に現在位置を用いるMetropolis-Hastings法などではサンプル間の相関があるため適切に処理しないと分散などの計算が正しく行えません．

## 実装

[GitHub](https://github.com/Yukishita26/Misc/tree/main/random_package_produire)

```:乱数.rdr
線形合同法とは
	ーー Park & Miller
	＋A：整数=48271
	＋B：整数＝0
	＋M：整数=2^31-1
	＋X：長整数
	はじめの手順
		X＝起動時間
		『シャッフル』を10回繰り返す
	終わり
	シャッフルする手順
		X＝（A×X+B）%M
	終わり
	乱数を求める手順
		シャッフルする
		【Y：整数】＝X
		Yを返す
	終わり
	シードを設定する手順
		X＝設定値
		シャッフルする
	終わり
終わり

ボックスミュラー法とは
	＋X：浮動小数
	＋Y：浮動小数
	フラグ：真偽値＝×
	乱数を求める手順
		もしフラグならば
			フラグ＝×
			Yを返す
		そうでなければ
			L＝（０から１までの一様乱数の自然対数×（－２））の平方根
			W＝０から１までの一様乱数×２×円周率
			X=L×cos(W)
			Y=L×sin(W)
			フラグ＝○
			Xを返す
		もし終わり
	終わり
終わり

［下限］以上で，［上限］未満の，整数一様乱数を求める手順
	下限から上限までの一様乱数を切り捨てたものを返す
終わり

［下限］から，［上限］までの，一様乱数を求める手順
	乱数生成器の乱数÷（2^31-1）×（上限－下限）＋下限を返す
終わり

中心が，［μ］で，標準偏差が，［σ］の，ガウス乱数を求める手順
	ガウス乱数生成器の乱数×σ＋μを返す
終わり

［ｘ］の，自然対数を求める手順
	ネイピア数でｘの対数を返す
終わり

［シード値］にシードをセットする手順
	乱数生成器のシードは，シード値
終わり

ネイピア数＝１の自然対数乗
乱数生成器＝線形合同法を作ったもの
ガウス乱数生成器=ボックスミュラー法を作ったもの
```

一様乱数の生成に[線形合同法](https://ja.wikipedia.org/wiki/%E7%B7%9A%E5%BD%A2%E5%90%88%E5%90%8C%E6%B3%95)，一様乱数からガウス乱数への変換に[ボックス・ミュラー法](https://ja.wikipedia.org/wiki/%E3%83%9C%E3%83%83%E3%82%AF%E3%82%B9%EF%BC%9D%E3%83%9F%E3%83%A5%E3%83%A9%E3%83%BC%E6%B3%95)を使用しています．

シード固定機能のため線形合同法を実装していますが，不要であれば`【値】の乱数`，`【開始値】から【終了値】までの乱数`で十分です．

## 使い方

```
「C:\home\rdr\乱数.rdr」を参照する

４２にシードをセットする
Ｎ＝１０

『
	０以上で１０未満の整数一様乱数を出力して改行
』をＮ回繰り返す

『
	０から１までの一様乱数を出力して改行
』をＮ回繰り返す

『
	中心が１で標準偏差が１のガウス乱数を出力して改行
』をＮ回繰り返す
```

+ 【下限】以上で【上限】未満の整数一様乱数
+ 【下限】から【上限】までの一様乱数
+ 中心が【μ】で標準偏差が【σ】のガウス乱数
+ 【シード値】にシードをセットする

日本語の意味そのままで動作します．
シードはすべての乱数で共通です[^seed]．明示的に指定しない場合はシステムの起動時間が指定されます．

[^seed]: というより他の乱数は一様乱数を変換して生成しています．
Vue.js+firebase 画像アップロード機能の実装

ECサイト作成時に画像アップロード機能の実装をしたのですが、firebaseの使い方が初心者の私には難しすぎたので記録しておきます。
うまく行った方法を書いていこうと思うのですが、必要のない作業もあるかもしれないです。。。

# Fire storeageのセットアップ

①左上の歯車マークからプロジェクト設定のページに進み、右下の赤丸をクリックしてマイアプリを作成する。

![スクリーンショット 2021-12-21 10.49.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2388688/637da7af-70b2-8750-d730-b344330c0517.png)


②以下のような画面が表示されるので、`npm install firebase`を行い。コードはすぐに使えるようにしておく。
(vue.jsを使用している場合は`npm install vuefire firebase`もしておく必要があるかもしれないです。[こちら](https://vuefire.vuejs.org/vuefire/getting-started.html#installation)を参考にしてみてください)


![スクリーンショット 2021-12-21 10.53.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2388688/a5cbb942-9e72-2c4f-7a5d-fdcffdfb8206.png)

# Fire storageに商品画像をアップロード

①Firebaseにプロジェクトを作成して、Storageを始める。
![スクリーンショット 2021-12-21 10.44.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2388688/0936e880-e7b7-4896-aec7-91ab769282e9.png)

②セキュリティルールを以下のように変更。（初期設定ではデータの追加ができないようになっている。）
![スクリーンショット 2021-12-21 10.38.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2388688/6dd36ecf-ffc6-1a50-4b57-e2447d3268a1.png)


③また、'files'というフォルダを追加しておく。（名前はなんでもいいです）
![スクリーンショット 2021-12-21 11.40.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2388688/abb2d888-eb48-51f9-d79f-a0d9a7f7af98.png)

④以下のようにコードをかく。


```typescript:

  //npm install firebaseでインストールされるパッケージに含まれる'firebase/app'のinitializeAppをインポート
  import { initializeApp } from "firebase/app";

  //アプリの設定を行う
  const firebaseConfig = {
  apiKey: process.env.VUE_APP_APIKEY,
  authDomain: process.env.VUE_APP_AUTHDOMAIN,
  storageBucket: process.env.VUE_APP_STORAGE_BUCKET,
};
  firebase.initializeApp(firebaseConfig);

  // ストレージサービスへの参照を取得し、ストレージバケットの参照を作成するために使用
  const storage = getStorage(firebaseApp);
```

⑤apiKey、authDomain、storageBucketは隠しておきたい情報なので、`.env`ファイルに以下のように書いておき、上のファイルから読み取れるようにしておく。また、[VueCLI3.x 4.xで環境変数を扱う場合は .env ファイルに VUE_APP_ の接頭語をつける](https://kic-yuuki.hatenablog.com/entry/2019/11/17/171058)ということなので`VUE_APP`も忘れずにつけておく。

```typescript:.env
VUE_APP_API_KEY = "あなたのapiKey"
VUE_APP_AUTH_DOMAIN = "あなたのauthDomain"
VUE_APP_STORAGE_BUCKET = "あなたのstorageBucket"
```

⑥gitにも上げないようにするため、`gitigonre`ファイルにも以下のように記載する。


```typescript:.gitignore
./.env.
```

⑥画像をアップロードするメソッドをかく。


```HTML:HTML
  <input type="file" @change="fileUpload" />
　　　　　<!-- アップロードされた画像が以下に表示される -->
  <img v-if="img_url" :src="img_url" />

```
```typescript
/**
   * イメージ画像をアップロード.
   */
  fileUpload(props: any) {
    //アップロードしたい画像の情報を取得。
    const file = props.target.files[0];
    //画像ファイルのURLを取得。
    this.img_url = URL.createObjectURL(file);
    //"files"は③で作成したフォルダ名
    //Firebase storageに画像ファイルを送信。
    const storageRef = ref(storage, "files/" + file.name);

    //Firebaseにデータを適切に送るために必要なコード
    uploadBytes(storageRef, file).then((snapshot) => {
      console.log("blobかfileをアップロード", snapshot);
    });
  }
```

⑦これで、　Fire storageを確認すると画像データが追加されている。
![スクリーンショット 2021-12-21 11.45.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2388688/b4e8d514-291e-c164-8cda-eec640fe7836.png)
ER図の書き方

##記事の対象##
・データベースを学び始めた初学者の方
・ER図の書き方があまり理解できていない方


###ER図が必要となる理由###
ER図とは「データベース設計（データモデリング）で使う設計手法」の一つででデータベース設計の基礎になる部分です。ER図がなくともデータベース設計はできますが、規模が大きくなるにつれ設計ミスや、システムの仕様が理解しずらくなります。その際にER図があれば設計ミスを未然に防ぐことができ、またシステムの仕様も理解しやすくなります。
ER図でデータベース構造などを整理することで、システム全体の構成を俯瞰することができ、手戻りを起こす可能性を減少させることができる為ER図が必要になります。


##基本的な用語##
###エンティティ###
データベースを構成するデータのまとまりのことです。エンティティの中にアトリビュート（属性）があります。
###アトリビュート（属性）###
エンティティの中の属性情報のことです。アトリビュートの中で「主キー」や「外部キー」も表現します。主キーとなる項目は、エンティティ上部に書きます。外部キーとなる項目は、項目名の後ろに(FK)を付けます。その他の項目は、項目名のみ記述します。
###リレーション###
エンティティ同士の関係を表現する線のことです。
　リレーションの詳細は、「カーディナリティ」という記号を使って表現します。
###カーディナリティ###
　「１対１」「１対多」「多対多」など、リレーションの詳細を表現する記号のことです。「0以上」や「0または1」といったことも表現することができます


##ER図を書く手順##
ER図はいきなり書いていくのではなく、大枠から考えて徐々に詳細に落とし込んでいきます。（概念設計→倫理設計→物理設計。
今回はこれらの説明は省くので自身で調べて見て下さい。）
今回は通販サイトを題材にしたものから手順を説明します。（説明の為簡略化して記載します。本来はもっと複雑なER図になります。）
・管理すべき情報はどのようなものが必要になるか整理する（エンティティを考える）
　（例）顧客の情報、商品の情報、注文の情報など
![a.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2155133/afa89ec0-f6cc-97d4-661b-639df712235a.png)


・整理したのものをより細かい情報へ深掘りしていく。（アトリビュートを考える）
　（例）氏名、住所、メールアドレス、電話番号など
![b.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2155133/46660a3c-e307-8ce7-8e3e-18691bf72f56.png)


・整理された情報から各情報ごとの結びつきを整理する（リレーションを考える）
・各々の結びつきに対しての詳細を整理する（カーディナリティを考える）
（例）一人の顧客に対して商品はいくつ存在するのか。逆に一つの商品に対して顧客は何人存在しているのかという感じで考えていく。
<補足>今回の場合のようにカーディナリティを考えている段階で多対多の関係にな理想な場合は中間テーブルを作成する必要があります。
![c.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2155133/749e5bfe-8ad6-b4c6-6e4b-c32c8081f57c.png)


##まとめ##
今回はER図の書き方の初歩的な部分を説明しました。どう書いていけばいいか分からず躓いている方達の助けになればと簡易的に説明しているので。正規化の説明や多対多のカーディナリティが生じた際の中間テーブルの作成の説明など省いていることもあります。まずは一度ER図を作成してみて、そこから詳細を調べて行ってもらえたらと思います。参考サイトにより詳細なER図の書き方のサイトのURLを載せていますので調べて見てください。

参考サイト
https://it-koala.com/entity-relationship-diagram-1897
https://products.sint.co.jp/ober/blog/create-er-diagram
http://itref.fc2web.com/technology/entity_relationship_diagram.html
ドメイン駆動設計 モデリング/実装ガイドを読んだ感想

## 良いモデルとは
良いモデルとはズバリ、**問題解決ができるモデル**のこと。
問題を解決できるものでなければ、それは良いモデルとは言えない。

例えば、会社のメンバーを管理するアプリケーションがあったとして、部署がセールスとCSと開発しか表現できなかったとしたら、新しくマーケティング部署ができたときに使い物にならない。
つまり、どんなにコード側で可読性や拡張性が高く、バグが出なかったとしても、高い価値を生み出さない。

コードの上流であるモデルが良くなければ、コード側で解決することが難しい。

## 良いモデルを作るために
では良いモデルを作るために大事なことは2つ。
### ドメインエキスパートと会話をする
ドメインエキスパートとは想定している業務を把握している人。
会社によっては使用する部署の人かもしれないし、PdMかもしれない。
その人たちと話し合って、開発側も同じくらい業務について理解しないといけない。
余談ですけど、エンジニアって用途の把握で業務時間の５割くらい使っている気がする。

#### 運用して得られた発見をモデルに還元する
モデルは運用開始したら完成ではなく、運用していく中でアップデートしていくもの。
結構モデルって設計したら終わりって感じがあるんですが、使っていく中で適宜アップデートしていかないといけない。
そういう意識もそうですが、アップデートしていく運用を維持しなくてはならないなと思いました。

#### どれだけそのモデルだけの情報を持っているか？を意識する
ドメインの知識を持っていないモデルは、**ドメインモデル貧血症**と呼ばれる。
ドメインモデル貧血症とは、ドメインモデルを実装するためのオブジェクト
でありながら、ドメイン知識をほぼ持たないオブジェクトのこと。

## 感想
正直、保守運用ばかりしていたせいか、いままでモデルについて考える機会があんまりありませんでした。
新しい要件が出てきたときにモデルは気にせずにコード側で頑張って汚いコードを生成していた気がします・・笑
今後はモデルも常にアップデートをする、そのために柔軟な設計をするということを念頭に置いていきたいと思います！