OmniAICreator/Qiita-1.07M huggingface dataset:
【Go】XORMでOracle Databaseに接続する

## 概要
GolangのO/Rマッパーで、Oracle Databaseへの接続できるものがないか探してみたところ、[XORM](https://xorm.io/)というライブラリに行き着きました。[こちら](https://gobook.io/read/gitea.com/xorm/manual-en-US/)のドキュメントにある通り、Oracleのドライバー対応は2022年4月現在はexperimentの状態ですが、使えなくもないだろうということで少し試してみました。

## 前提
[mattn/go-oci8](https://github.com/mattn/go-oci8)のセッティングを事前に行なってください。[【Oracle】Mac環境でmattn/go-oci8のライブラリをインストール時「oci.h: No such file or directory」が発生](https://qiita.com/someone7140/items/47bc754040374e2c5c8f)の記事も、参考になるかと思います。

## 実装サンプル（接続部分）
DBの接続部分（エンジン生成）について、実装のサンプルを記載します。
CRUD操作については、[【Go】Xormの使い方 その①(CRUD)](https://zenn.dev/a_ichi1/articles/5d9fbf3fbfea38)の記事を参照ください。

```go
import (
	"log"

	_ "github.com/mattn/go-oci8"
	"xorm.io/xorm"
)

func GetOracleDbEngine() (*xorm.Engine, error) {
	engine, err := xorm.NewEngine("oci8", "sample_user/password@localhost:1521/ORCLPDB1")
	if err != nil {
		log.Fatal(err)
	}
	return engine, err
}
```
備忘録）nodistからVoltaに移行する【Windows10】

# はじめに
前回はMACの移行が済んだので、今回はwindows10の方を
現状使っているnodistからvoltaへ移行しようと思いメモ

https://qiita.com/idler/items/a170d3aecfd5d32ba669

【実行環境】
Windows 10 Home
21H2

# 概要
今まで使ってたnode.js、nodist、yarnを削除し、
新たにvoltaをインストールし、node.jsを使う
今回はWSLの設定した状態でMACと同じようにインストールします

# 削除する
今回はchocolateyなどのパッケージ管理ソフトを使ってインストールなどもしていないので、コントロールパネルから直接アンインストールします
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/702325/aea735ba-577a-4f90-d6ae-ac93acc596e5.png)

::: note warn
ただ、これだけだと削除されていないものがあるので、
個々にNodeやnpm及びyarn関連で下記階層ファイルを削除しました
※chache類は先にコマンドから削除しといたら楽かも

【node.js関連】
C:\Users\user\.node_repl_history
C:\Users\user\.config\configstore\nodemon.json
【yarn関連】
C:\Users\user\.yarnrc
C:\Users\user\AppData\Local\Yarn\Cache\v6
【npm関連】
C:\Users\user\AppData\Roaming\npm-cache
:::

:::note alert
Nodistに関してもグローバルインストールされているものは
残ったままみたいなので下記も削除
C:\Program Files\Nodist
:::

これで削除完了！

今回環境変数のNode用pathが何故か見当たらなかったので削除しなかったが、
システムのプロパティにある環境変数の編集から確認してnodeのpathがあれば削除する

# Voltaをインストールする
今回はWSLのUbuntuを設定した状態でMAC同様にインストールしました
WSLの設定に関しては割愛します（詳しく知りたい場合は下記から）

https://docs.microsoft.com/ja-jp/windows/wsl/


```:Ubuntu
//インストール
curl https://get.volta.sh | bash
//Ubuntu再起動後
volta -v
→1.0.6
```
後はMAC同様の操作で完了

:::note warn
今回ubuntuからインストールしたため、コントロールパネルのプログラムと機能からはアンインストールできなさそうだったため場所を確認した
:::
```:ubuntu
//パスで確認したがこの階層に見当たらなかった
which volta
→Users/user/.volta

//調べたら次の場所にあった
\\wsl$\Ubuntu\home\user\.volta
または
C:\Users\user\AppData\Local\Packages\CanonicalGroupLimited.Ubuntu_79rhkp1fndgsc\LocalState\rootfs\home\user
```
:::note 
メモ
今回練習も兼ねてwslからインストールしたけれど、
windowsは余り使用頻度も少なく、何よりGUI操作のほうが直感的にできるので、パッケージインストールの検討も頭の片隅で考えておく
:::

# 追記
Voltaをwin版パッケージでインストールして使用を始めました。
パッケージでインストールした方がコマンドプロンプトで呼び出せて
個人的には使い勝手が良いと気づき今はパッケージ版を使ってます


# 参考
https://zenn.dev/ymasaoka/articles/note-uninstall-nodish-windows
Power Automate Desktopでメール本文取得しExcelに書き込む練習

# 空白を削除

練習用に、以下記載のメールを、Power Automate Desktopで取得しExcelに書き込む処理を設定しました。
メール本文には余分な空白が入ってます。
Excelには、1ワードを1行ごと（タテに）、および列に（ヨコに）配置させます。

~~~
作品情報
映画賞
映画 レビュー
試 写会
注目映 画特集
インタビュー
新作映画評 論 
~~~

メール本文を取得した状態から記載します。
空白を削除します（置換します）。
「%' '%」を「%''%」に置き換えます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/07bc0bd3-3169-50cf-12f3-1a9f40280fc2.png)

# 空白行を削除

1行空きで取得されることがあります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/d15e3fa9-7806-358a-8b4e-46592f2e8064.png)

先頭が空白でない行のみ検索、取得します（残すようにします）。
「\S」は「すべての非空白文字」という指定です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/1ca79fc0-8050-6dac-dc5f-0103f1c25d9a.png)

上記処理後の結果です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/f597ce0e-3e49-24a5-8ef8-d3a186984ab8.png)

# Excelに書き込み

Excelへの書き込みは、セルの位置を指定しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/87bc9f42-efc0-2c41-781b-1ce301a74e23.png)

上記処理で行ごとに書き込めます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/c840cc02-ebd6-2247-6507-f50f7d49c5e6.png)

# 横並びに書き込む

横並びに書き込む場合、以下のようにしました。
もっと効率にいい方法があるかもしれませんが、今回は「LOOP」で取得した本文リストの行数分だけループさせました。
本文リストは「0」からカウントするので、「%Matches.Count - 1%」をLOOPの終了値としました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/a25c1b29-890d-7d70-d755-c519286f5d8c.png)

リストに縦に並んだワードを、列方向に並べる指定をしてExcelに書き込みます。
「%Matches[LoopIndex]%」と指定することで、リスト（Matches）の1行目、2行目・・・（LoopIndex）と順に書き込むことができます。
書き込む方向は「列」に「%LoopIndex + 1%」と指定することで、1列目、2列目・・・と記載箇所が移るように設定しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/c71e1b51-e449-44f1-d294-f554c86db873.png)

上記処理の結果です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/34971f79-2e73-52a4-a64d-1413a916fc76.png)

1通のメールをピックアップする場合は上記のフローでできました。
複数メールを取得する場合、別の方法を考えることになります。
今度試す予定です。

**了**
【Flutter × Firebase】 Firebase authで発生するエラーをキャッチする方法（エラーハンドリング）

# はじめに
Flutterで`Firebase`の`authentication`を使ってログインや新規登録の処理をしていた時に、
参考にした記事等が少し古いこともあり、ログインや新規登録のエラー処理に少し苦戦しました。
その後、自分が実装したい範囲まではできたので共有したいと思います。

# 今回使う、例外処理の基本
```
　　　　try{
  　　　　ログインする
　　　　}
　　　　catch(e){
  　　　　print(e); //エラー内容が出力
  　　　　//出力例）　パスワードが間違っています
　　　　}
```
Dartにおける例外処理の基本が上記の`try-catch文`です。
`try`で実行された処理にエラーが発生した際に、`catch`で指定した処理が実行されます。
引数の`e`で`try`が失敗したときのエラーを受け取ることができます。

# FirebaseAuthからのエラーをキャッチする
```
   onPressed: () async {
     try {
       await _auth.createUserWithEmailAndPassword(
            email: email, password: password); //ユーザーの新規登録を行う処理
     } 
     on FirebaseAuthException catch (e) { //FirebaseAuthExceptionからのエラーをeに格納する
       print(e);
     }
   }
```
上のコードは`FirebaseAuthException`つまり`firebase_auth`で出るエラーだけをキャッチします。
# 具体的にはどんな処理を書けばいいのか
```dart:新規登録.dart
   onPressed: () async {
     try {
       final newUser = await _auth.createUserWithEmailAndPassword(
            email: email, password: password); //ユーザーを新規登録する処理
     } on FirebaseAuthException catch (e) {
       if (e.code == 'email-already-in-use') {
         print('指定したメールアドレスは登録済みです');
       } else if (e.code == 'invalid-email') {
         print('メールアドレスのフォーマットが正しくありません');
       } else if (e.code == 'operation-not-allowed') {
         print('指定したメールアドレス・パスワードは現在使用できません');
       } else if (e.code == 'weak-password') {
         print('パスワードは６文字以上にしてください');
       }
     }
   }
```
`on FirebaseAuthException`を指定しておけば`e.code`で発生したエラーコード（エラーの中身）を取得できて、
エラー別に実行する処理を指定できます。
`FirebaseAuthException`によって起こる可能性があるエラーコードはfirebase_authのドキュメントから確認できます。
上記のコードはメールアドレスとパスワードを使って`新規登録`する際の例になります。[こちら](https://pub.dev/documentation/firebase_auth/latest/firebase_auth/FirebaseAuth/createUserWithEmailAndPassword.html)を参考にしました。

```dart:ログイン.dart
   onPressed: () async {
     try {
       final newUser = await _auth.createUserWithEmailAndPassword(
            email: email, password: password); //ユーザーを新規登録する処理
     } on FirebaseAuthException catch (e) {
       if (e.code == 'user-disabled') {
         print('そのメールアドレスは利用できません');
       } else if (e.code == 'invalid-email') {
         print('メールアドレスのフォーマットが正しくありません');
       } else if (e.code == 'user-not-found') {
         print('ユーザーが見つかりません');
       } else if (e.code == 'wrong-password') {
         print('パスワードが違います');
       }
     }
   }
```

上記はメールアドレスとパスワードを使って`ログイン`の処理を書く場合の例になります。[こちら](https://pub.dev/documentation/firebase_auth/latest/firebase_auth/FirebaseAuth/signInWithEmailAndPassword.html)を参考にしました。
# 最後に
もし参考になったらいいねしてくれたら嬉しいです！
今回参考にしたサイト等
https://flutternyumon.com/how-to-use-exception/
https://pub.dev/documentation/firebase_auth/latest/firebase_auth/FirebaseAuth/createUserWithEmailAndPassword.html
https://pub.dev/documentation/firebase_auth/latest/firebase_auth/FirebaseAuth/signInWithEmailAndPassword.html
SchemaSpyでER図をパパッと自動生成する



ER図(Entity Relationship Diagram)はDBテーブルを関連性と属性を使って表す図のことです。
プロジェクトにジョインする時とか、ER図を書きながらテーブル構成を把握すると捗りますよね!

とはいえ、テーブル数が数百を超えると手書きは時間がかかるし、機能的に重要でないテーブルとかもあり効率が悪くなってきます。
(ツールを使ってもいいですが、テーブルの追加があった時にわざわざメンテするの忘れがちになってしまいますしね)

エンジニアらしく効率的に作れないかな🤔と思っていたら、ER図を自動生成する**SchemaSpy**というツールがあったので、使い方と共に紹介します。

### SchemaSpyについて

https://github.com/schemaspy/schemaspy

↓ER図サンプル
https://schemaspy.org/sample/index.html

オープンソースのER図自動生成ツールで、
dockerベースとjarベース(Java製アプリケーション)の2種類で使うことができます。

使えるRDBMS主だったところ(Mysql,Postgresql,Oracle,SQLServer)なら問題なく使えます。

使用してみたわかったこと・感想は、以下の通り。
・300テーブルくらいのER図を約5m半で作成 (テーブルのレコード数とかも出力するので、DBの状態によって前後するかも)
・各レコードの統計も出力
・基本は外部キー制約設定を元にリレーション分析するが、**オプション(`-rails`)で暗黙のリレーションもチェック**してER図を作成してくれる


**暗黙のリレーション**とは、`products`にINT型`category_id`があり`categories`というテーブルがあったら、
`products.category_id`を`categories.id`でリレーションがあると判断する感じのやつのことです。

サクッとできるので、さっそくやってみましょうー🏃‍♀️

### 手順
前提として、今回は`docker`ベースで、`Mysql5.6`でER図を作成する方法でやってます。

#### ダウンロード

githubリポジトリのReleasesから最新版をDLしていきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/420171/2663ef15-a424-1c49-b37b-fd74b6795471.png)

CodeからDLしようかなーとも思ったんですが、[公式ドキュメントのInstallation](https://schemaspy.readthedocs.io/en/latest/installation.html#schemaspy)のリンクから飛んだ先がReleasesなので、それに従いましょう。

続いて、Releaseページの最新版のうち、`zip`か`tar`をDL。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/420171/687bd10a-48a9-e16b-1e47-27391fef6553.png)

#### コマンド実行
DLしたら解凍し、解凍したディレクトリ内に移動してdockerコマンドを実行します。

参考までに、私が開発環境でER図を作成した時のコマンドを記載します。

```
docker run -v "$PWD/schema:/output" --net="host" schemaspy/schemaspy:snapshot \
 -t <DBの種類(mysql postgresqlなど)> -host <ホスト:ポート [例localhost:3306]> -db <スキーマ名> -u <ユーザ名> -p <パスワード> -connprops useSSL\\=false -s <スキーマ名>
```

他の方の投稿されている記事のコマンドとほぼ同じですが、
私の場合は`rg.schemaspy.model.InvalidConfigurationException: Schema (-s/-schemas) was not provided and unable to deduce schema, schema is sometimes referred to as user/owner/database`というエラーが出て、`-s`オプションを追加することで解消しました。
-dbと-s両方でスキーマ名指定しているので、どちらか一方だけの指定だけで大丈夫な方法があるかも。

公式で[オプションの説明](https://schemaspy.readthedocs.io/en/latest/started.html)が色々記載されてますが、おおよそ使いそうなのを下記にまとめました。
導入の際には色々試してもらえればと思います。

| オプション | 意味 | 必須|
|:-:|:-:|:-:|
| -t | RDBMSタイプ(`mysql` `pgsql`,`sqlite`, `ora`など。デフォルトは`ora`) | ○ |
| -db | DBスキーマ名 | ○ |
| -u | 接続ユーザ名  |○ |
| -p | 接続ユーザのパスワード  | ○ |
| -host | 接続先ホストとポート番号 | ○ |
| -connprops useSSL\=false  | [MySQL 5.5.45+, 5.6.26+ and 5.7.6+環境の場合、SSLを省略](https://schemaspy.readthedocs.io/en/latest/advanced_usage.html?highlight=connprops#supply-connection-properties)して接続するためのオプション  | △　|
| -s | スキーマ指定。ユーザ名とスキーマ名が同じ時は省略可能 | △ |
| -rails  | railsベースの論理リレーションを探索するオプション | |
| -o | ファイルの出力先(デフォルトはカレントディレクトリ) | |
| -debug | 実行中にデバッグログを出力 | |



### 参考資料
https://qiita.com/ap8322/items/b93dfb2ff29b026ffa72

https://qiita.com/maika_kamada/items/c23c2a3717168c3b8e7a
Herokuデプロイ時のエラー（fatal: repository 'app_url' not found）の解消方法

こんにちは、かずやです。

この記事を読んでいるあなたは、以下のエラーが出てお困りかと思います。

```
$ heroku create
Creating app... done, ⬢ xxxxx-xxxxxxx-70383
https://xxxxx-xxxxxxx-70383.herokuapp.com/ | https://git.heroku.com/xxxxx-xxxxxxx-70383.git
$ git push heroku master
remote: !       No such app as yyyyyy-yyyyy-25498.
fatal: repository 'https://git.heroku.com/yyyyyy-yyyyy-25498.git/' not found
※「x」「y」は仮文字です。
```
この記事を最後まで読めば、上記のエラーが解消できるだけではなく、無事にherokuへのデプロイを完了させられるでしょう。

# エラーの解消方法
以下の2ステップで簡単にエラーを解消できます。

## ①gitのリモートURLを変更する
まずはgitのリモートURLをデプロイしたいURLに変更しましょう。

コマンドは以下のとおりです。

```
$ git remote set-url heroku https://git.heroku.com/xxxxx-xxxxxxx-70383.git
```
これでURLが変更されました。

## ②再度herokuへデプロイする
gitのリモートURL変更が完了したら再びherokuへデプロイをしてみましょう。
```
$ git push heroku master
```
これで無事にherokuへデプロイできました！

# 終わりに
本記事があなたの学習の助けになれば幸いです。

一緒にこれからも頑張りましょう！
vscode rails環境構築時のエラー bundle install

```
**********@mbp jisaku_app % bundle install
Fetching gem metadata from https://rubygems.org/..........
Resolving dependencies...
Bundler found conflicting requirements for the Ruby version:
  In Gemfile:
    Ruby (~> 3.1.1.0)

    listen (= 3.1.5) was resolved to 3.1.5, which depends on
      Ruby (>= 2.2.3, ~> 2.2)

Bundler could not find compatible versions for gem "minitest":
  In Gemfile:
    minitest (= 5.11.3)

    rails (= 7.0.2.3) was resolved to 7.0.2.3, which depends on
      activesupport (= 7.0.2.3) was resolved to 7.0.2.3, which depends on
        minitest (>= 5.1)

    minitest-reporters (= 1.3.8) was resolved to 1.3.8, which depends on
      minitest (>= 5.0)
```
```
*******@mbp jisaku_app % gem install sqlite3
Building native extensions. This could take a while...
Successfully installed sqlite3-1.4.2
Parsing documentation for sqlite3-1.4.2
Done installing documentation for sqlite3 after 0 seconds
1 gem installed
```
gem sqlite3のバージョンを変更
```
*******@mbp jisaku_app % bundle install
Fetching gem metadata from https://rubygems.org/..........
Resolving dependencies...
Bundler found conflicting requirements for the Ruby version:
  In Gemfile:
    Ruby (~> 3.1.1.0)

    listen (= 3.1.5) was resolved to 3.1.5, which depends on
      Ruby (>= 2.2.3, ~> 2.2)
*******@mbp jisaku_app % gem install listen 
Successfully installed listen-3.7.1
Parsing documentation for listen-3.7.1
Done installing documentation for listen after 0 seconds
1 gem installed
```
gem listenのバージョンを変更。

```
*******@mbp jisaku_app % bundle install
Fetching gem metadata from https://rubygems.org/..........
Resolving dependencies....
.
.
.
Bundle complete! 32 Gemfile dependencies, 113 gems now installed.
Use `bundle info [gemname]` to see where a bundled gem is installed.
```
```Use `bundle info [gemname]` to see where a bundled gem is installed.```
と書いてある。意味はわからなかったが入力。
```
***********@mbp jisaku_app % bundle info listen   
  * listen (3.7.1)
        Summary: Listen to file modifications
        Homepage: 
        Documentation:
        Source Code: 
        Changelog: 
        Bug Tracker: 
        Path: /Users/**************:/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/listen-3.7.1
        Reverse Dependencies: 
                guard (2.16.2) depends on listen (>= 2.7, < 4.0)
                spring-watcher-listen (2.0.1) depends on listen (>= 2.7, < 4.0)
```
多分gemの諸情報が書かれているのだと思う。
「マイクロサービスパターン」の復習 2章 サービス分割

## 概要

Java読書会でせっかく勉強したのにつぎつぎと忘れていくので、印象に残ったところを記録していく

http://www.javareading.com/bof/

## 2章 サービスへの分割

- アーキテクチャとはなにか？
- どうやってサービスに分割するか？


## アーキテクチャとは？

- アーキテクチャとは、ソフトウェア要素とその関係性
- 4 + 1ビューモデル
    - 論理ビュー：クラス構成、パッケージ構成とそれらの依存関係
    - 実装ビュー：jarやwarの配置と、それらの依存関係
    - プロセスビュー：プロセスとプロセス間通信
    - デプロイビュー：マシンとネットワーク
- アーキテクチャが重要なのは、品質属性に関わるから
    - 特にマイクロサービスはメンテナンス性やデプロイ容易性に影響する
- アーキテクチャスタイル
    - 建築様式
    - 寺院を建てるのにもXXX様式が複数ある
- 論理ビューについてのアーキテクチャスタイル
    - 階層アーキテクチャ
        - お馴染みの3層アーキテクチャなど分かりやすいやつ
        - 実際のところ本当に上位層が下位層に依存しているかと言えば、DIなどがあるのでかならずしもそうではないし、上位が下位に依存するばかりだとテストもしづらい
    - ヘキサゴナルアーキテクチャ
        - ビジネスロジックを中心に考え、他の要素はビジネスロジックに依存するが、ビジネスロジックは他の要素に依存しないようにする
        - ビジネスロジックから永続層や外部サービスを呼び出す場合は、ビジネスロジック層の方にインタフェース定義を置く（アウトバウンドポートと呼んでいる）
        - 永続層や外部サービスを呼び出すための実装は、ポートの実装を用意する（アウトバウンドアダプタ）
        - こうすることで依存関係の向きを、呼び出しの向きとは逆にする。あとはDIで注入するなりする
        - 本書では論理ビューとしては、こちらを推している
- 実装ビューに関するアーキテクチャスタイル
    - Monolithic architectureパターン
        - お馴染みの一枚岩
    - Microservice architectureパターン
        - 本書のテーマとなっている個別デプロイ可能なサービスの集合体


## マイクロサービスアーキテクチャ

- マイクロサービスアーキテクチャを定義するための3ステップ
    - システム操作の洗い出し
    - サービスの洗い出し
    - 各サービスのAPIの定義と連携方法の定義

- システム操作の洗い出し
    - とりあえずユーザーシナリオはあるとする
    - いわゆるオブジェクト指向分析的な方法でドメインモデルを作る（例えば名詞抽出法など）。この段階では荒いもので良い
    - システム操作を抽出する
  
- サービスの洗い出し
    - Decompose by business capabilityパターン
        - 業務を細分化していって、手頃な粒度になったらそれをサービスとする
    - Decompose by sub-domainパターン
        - DDD由来の方法。
        - DDDでは、ドメイン全体を単一のモデルにするのではなく、サブドメインの集合体としてモデリングする
        - サブドメインとサービスを一対一に対応させる
        - サブドメインに分割する方法は本書では述べられていない代わりに、分割後のサブドメインの概要が書いてある
        - FTGOではOrderという概念が中心になるが、受注サブドメインと、配達サブドメインと、キッチンサブドメインでは持つべき情報も異なるし、呼び方も異なるかもしれない。配達サブドメインではDeliverであり、キッチンサブドメインではTicketであるが、単一モデルだとOrderに集約されてしまう
        - 上記のように一つの概念が別々に見える場合はサブドメインとして分かれる。一方でサブドメイン内では概念についての共通認識が持てる。

- サービスAPIの定義
    - まずクライアントからのエントリポイントとなるサービスを見つける
    - 複数サービスの連携が必要ならそれぞれAPIを定義する

## まとめ

- アーキテクチャに関しては、ヘキサゴナルアーキテクチャが重要な考え方と思われる
    - アプリケーションの中心はあくまでビジネスロジックであり、ここの部分を他の要素に依存させないことで再利用性やテスタビリティを高める
- 後半に関しては、Decompose by sub-domainパターンが大事
    - サブドメインとは概念の境界なので、ここを超えると同じ概念と思っていたものが別のものとなる（実際は呼び方が同じだけで別概念）
    - 概念の不一致は、ソフトウェアが発展する過程で、不具合の要因になったり、God Classのを生み出すもとになる
    - 最初の段階できっちり概念境界を明確にするDecompose by sub-domainの方が、単に業務を細分化しただけのDecompose by business capabilityよりはより良い方法と言えるでしょう
    - ただし、分析の難易度としては、Decompose by sub-domainの方が圧倒的に上でしょう。
    - このあたりは本書よりもDDD本の領域なので詳しくは述べられてはいない。
    - DDDに少し興味を持った
[Joke-RFC] RFC1776 アドレスはメッセージである

# はじめに

* この文書は [RFC1776](https://www.rfc-editor.org/rfc/rfc1776.txt) を勉強と好奇心のため適当に訳したものです。
* 翻訳の正確さは全く保証しません。
* 誤字誤訳等の指摘はいつでも大歓迎です。

# The Address is the Message（アドレスはメッセージである）

* Network Working Group
* Request for Comments: 1776
* Category: Informational

- S. Crocker
- CyberCash, Inc.
- 1 April 1995

## Status of this Memo（このメモの位置づけ）

> This memo provides information for the Internet community.
> This memo does not specify an Internet standard of any kind.
> Distribution of this memo is unlimited.

このメモは、インターネットコミュニティーのための情報を提供するものである。
このメモは、いかなる種類のインターネット標準も規定するものではない。
このメモの配布は無制限である。

## Discussion（議論）

> Declaring that the address is the message, the IPng WG has selected a packet format which includes 1696 bytes of address space.
> This length is a multiple of 53 and is completely compatible with ATM architecture.
> Observing that it's not what you know but who you know, the IPng focused on choosing an addressing scheme that makes it possible to talk to everyone while dispensing with the irrelevant overhead of actually having to say anything.

IPng WG [^1]  では、アドレスはメッセージであると宣言し、1696バイトのアドレス空間を含むパケット形式を採択した [^2]。
この長さは53の倍数であり、ATMアーキテクチャと完全に互換性がある。
IPng は、重要なのはあなたが何を知っているかではなく誰を知っているかであることに気づき、実際に何かを言わなければならないという無関係なオーバーヘッドを省きつつ、誰とでも話ができるアドレス体系を選択することに重点をおいた。

> Security experts hailed this as a major breakthrough.
> With no content left in the packets, all questions of confidentiality and integrity are moot.
> Intelligence and law enforcement agencies immediately refocused their efforts to detect who's talking to whom, and are silently thankful they can avoid divisive public debate about key escrow, export control and related matters.

セキュリティの専門家は、これを大きなブレークスルーとして歓迎している。
パケットにコンテンツが残らないので、機密性や完全性の問題はすべて無意味になる。
諜報機関や法執行機関は、誰が誰と話しているかを検知するための取り組みに直ちに注力しつつ、鍵預託や流出管理などの監視ごとに関する世間を二分する議論を避けられることに、密かに感謝している。

> Although the IPng WG declared there should be more than enough address space for everyone, service providers immediately began vying for reserved portions of the address space.

IPng WGは十分すぎるほどのアドレス空間を確保すると宣言したが、サービスプロバイダはすぐにアドレス空間の予約部分の奪い合い始めた。

## Security Considerations（セキュリティに関する考察）

> Security issues are not discussed in this memo.

セキュリティ上の問題については、このメモでは触れない。

## Author's Address

```
   Steve Crocker
   CyberCash, Inc.
   2086 Hunters Crest Way
   Vienna, VA 22181

   Phone: +1 703 620 1222
   EMail: crocker@cybercash.com
```

[^1]:訳注：次世代のIPを策定するワーキンググループ。IPv4アドレス枯渇の対策のため、アドレス空間を広げるなどの対策を検討した。ここで策定されたものが、のちのIPv6。

[^2]:例えばイーサネットのMTUは通常1500バイト。アドレスが1696バイトもあれば、データ本体もアドレス部に含められるため、データ本体が不要になるというジョークと思われる。
簡単なChrome Extension： 日本株の4桁証券コードから各株式情報サイトへ遷移

##### これは何

株式投資をされる方は、
「バフェットコード」や「四季報オンライン」などの株式情報サイトを読んだり、
「TradingView」でチャートを見たり、GoogleSpreadsheetでデータを整理したりなど、
いくつかのサイトやサービスをまたいで、WEBブラウザ上で多くの作業をされることが多いことと思います。

そこで、「ブラウザで表示しているページのどこかにある4桁証券コードから、別の株式情報サイトの個別銘柄ページに遷移できる」
機能をChrome Extensionで実装してみました。

https://github.com/westcide/chrome-extension-tickerlink

##### 使い方

ストアには登録はしてないのですが、
https://support.google.com/chrome/a/answer/2714278?hl=ja の「手順 2: アプリや拡張機能をテストする」
を参考にExtensionをブラウザに登録することで使えるようになります。

Extensionを追加すると、
ブラウザ文書表示中の右クリックコンテキストメニューに「株式銘柄情報サイトへのリンク」というメニューが追加されるので、
ブラウザで表示している文書中の、4桁の数値テキストをカーソルで選択したうえで、
メニューから任意のサイトの個別銘柄ページに遷移できます。

機能はこれだけですが、SpreadSheetで作った銘柄一覧表を見てるときに別のサイトに移動して詳しく調べたい、といったことが結構あるかと思うので、
とてもシンプルな割には役に立つのではないかと思っています。
（遷移先がログインが必要なサイトの場合は、事前にログインしておいたりは必要になりますが）

##### プログラムについて

background.jsがメインのプログラムで、
ここの右クリックコンテキストメニューのイベントリスナーに登録(chrome.contextMenus.onClicked.addListener)した関数で、
遷移先各サイトのURLを、カーソルで選択中の文字列で個別銘柄ページのURLに置換して、新たなタブで開く、といったことをやっているだけです。
一部サイトのURLは単純な置換だけでは対応できなかったので、条件分岐で個別対応のコードを入れています。

遷移先サイトのリストは site.js のconstに列挙しているので、追加したいサイトが有る場合はここで追加できます。

設定用のポップアップも作ってみました（option.htmlとoption.js）
サイトリストの表示のON/OFFをここで切り替えることができます。
（設定内容はlocalStorageに保存されます）

当初はManifest V2用に作っていたのですが、
Manifest V3に対応するにあたって manifest.jsonを何箇所か直しました。
* background.scriptsをbackground.service_workerに変更。
background.scriptsには複数のスクリプトを登録してましたが、service_workerには1つしか登録できないようなので、
登録したスクリプトの中で別のスクリプトをimportScriptsするようにした
（具体的には、background.jsの最初に importScripts('sites.js'); を入れた
* browser_actionをactionに変更
【解決】Cloud Firestoreのエミュレーターがタイムアウトする

# 現象
Firestoreのエミューレーターがタイムアウトする

```
$ yarn add --dev firebase-tools
$ yarn firebase init
? Which Firebase features do you want to set up for this directory? Press Space to select features, then Enter to confirm your choices. (Press <space> to select, <
a> to toggle all, <i> to invert selection, and <enter> to proceed)
❯◉ Emulators: Set up local emulators for Firebase products
# エミュレーターを設定
...
=== Emulators Setup
? Which Firebase emulators do you want to set up? Press Space to select emulators, then Enter to confirm your choices. (Press <space> to select, <a> to toggle all,
 <i> to invert selection, and <enter> to proceed)
❯◉ Firestore Emulator
# Firestoreのエミューレーターを設定
...

$ yarn firebase emulators:start
⚠  emulators: Support for Java version <= 10 will be dropped soon in firebase-tools@11. Please upgrade to Java version 11 or above to continue using the emulators.
i  emulators: Starting emulators: firestore, hosting
i  firestore: Firestore Emulator logging to firestore-debug.log
i  emulators: Shutting down emulators.
i  firestore: Stopping Firestore Emulator
i  hub: Stopping emulator hub

Error: TIMEOUT: Port 8080 on localhost was not active within 60000ms
```

## 期待する結果
ググって出てくる他の人を参考にするとこんな感じになってほしい

```
$ yarn firebase emulators:start
...
┌───────────┬────────────────┬─────────────────────────────────┐
│ Emulator  │ Host:Port      │ View in Emulator UI             │
├───────────┼────────────────┼─────────────────────────────────┤
│ Firestore │ localhost:8080 │ http://localhost:4000/firestore │
└───────────┴────────────────┴─────────────────────────────────┘
```

# 解決方法
`"host": "127.0.0.1"`を`firebase.json`設定に追加

``` firebase.json
{
  "firestore": {
    "rules": "firestore.rules",
    "indexes": "firestore.indexes.json"
  },
  "emulators": {
    "firestore": {
      "port": 8080,
      "host": "127.0.0.1"
    },
    "ui": {
      "enabled": true
    }
  }
}
```

```
$ yarn firebase emulators:start
⚠  emulators: Support for Java version <= 10 will be dropped soon in firebase-tools@11. Please upgrade to Java version 11 or above to continue using the emulators.
i  emulators: Starting emulators: firestore, hosting
i  firestore: Firestore Emulator logging to firestore-debug.log
i  hosting: Serving hosting files from: public
✔  hosting: Local server: http://localhost:5000
i  ui: Emulator UI logging to ui-debug.log

┌─────────────────────────────────────────────────────────────┐
│ ✔  All emulators ready! It is now safe to connect your app. │
│ i  View Emulator UI at http://localhost:4000                │
└─────────────────────────────────────────────────────────────┘

┌───────────┬────────────────┬─────────────────────────────────┐
│ Emulator  │ Host:Port      │ View in Emulator UI             │
├───────────┼────────────────┼─────────────────────────────────┤
│ Firestore │ 127.0.0.1:8080 │ http://localhost:4000/firestore │
├───────────┼────────────────┼─────────────────────────────────┤
  Emulator Hub running at localhost:4400
  Other reserved ports: 4500
```


# 環境
OS: macOS Monterey
Intel CPU

```
$ node -v
v17.2.0
$ yarn -v
1.22.17
$ firebase --version
10.6.0
```
基本情報技術者試験対策　25日目

基本情報技術者試験勉強　25日目
-
この記事の目的
-
今年の5月に基本情報技術者試験を合格するために、過去問で間違えた箇所をただまとめる自分のための記事

プロフィール
-
・文系大学の３年生
・ITパスポートは保有
・ウェブアプリやサイト作成を個人で行ったことがある程度
・猫好き

今日の目標
-
午前問題を50問解き、間違いを10問以内に抑える。また、午後問題を2,３問はとく

間違った箇所
-
1、RPC(Remote Procedure Call)
サーバにあるプログラムを、サーバのIPアドレスを意識することなく、プログラム名の指定だけで呼び出すようにする

2、Address Resolution Protocol
IPアドレスから対応する機器のMACアドレスを取得するプロトコル

3、Routing Information Protocol
ゲートウェイ間のホップ数によって経路を制御するルーティングプロトコル
ホップ数とは、軽有するルータの数
RIPv1とRIPv2がある

4,ルーティング
ルータが受信したパケットの宛先を見て次の転送先を決めること

5、ルーティングテーブル
どのネットワークに届けるにはどの隣接ルータに転送すべきかをまとめたもの

6、EGP
大規模なネットワークの中での各組織が保有、運用するネットワーク（AS）同士の経路情報を交換する

7、BGP
AS内の経路情報を交換する

8、MHS（Message Handling System)
ITU-T X.400シリーズで勧告された電子メールについての標準を定めたメッセージ通信処理システム

9、スラッシング
仮想記憶システムにおいて主記憶の空きが少ない状態で多くのプログラムを実行すると、ページング処理が多発しシステムのオーバヘッドが増加し、CPUの使用率が低下すること

10、ADSL
既存の電話回線(ツイストペア線)を利用して，上り下りの速度が異なる高速データ伝送を行う

11、NPV(Net Present Value，正味現在価値)
現金流入の現在価値から、現金流出の現在価値を差し引いたもの

12、リグレッションテスト(退行テスト)
プログラムの修正または変更によって他の機能が意図しない影響を受けていないことを確認


振り返り
-
間違えた箇所が10問以内に抑えられなかったことと以前間違えた箇所をまた間違えてしまったことが残念だった。また、午後問題を取り組んだが、記事にまとめることが難しい。そもそも午前問題を理解できていない部分があるので、次回も午前問題を解きつつ、各午後問題の一通りの流れを覚える。

>引用

基本情報技術者試験ドットコム
https://www.fe-siken.com
Eclipseの設定のメモ

# Eclipseの設定
### インストール済みのJRE
[ウインドウ] → [設定] → [Java] → [インストール済みのJRE]
JREではなくJDKを指定する

### メモリの状況の表示
[ウインドウ] → [設定] → [一般] → [ヒープ・ステイタスを表示]にチェック
私の環境（Pleiades2019）ではデフォルトでチェックがついていました。

画面の右下のメモリの表示にマウスカーソルを近づけると
起動時のメモリ量(Xms)と最大のメモリ量(Xmx)を確認できる。
100日でSQLの達人になる@LeetCode! Day62 <復習問題：DENS_RANKで順位を付ける>

## 178. Rank Scores （問題レベル: Medium）無課金

今日もリハビリで`LeetCode Curated SQL 70`とは違う問題。

今日の問題はこれ。
ばらばらに並んでいるスコアのリストを降順に並べて、順位を付けるというシンプルな問題。
順位は同じ順位なら同順を付けて、順位はスキップしない。
つまり、1位、1位、3位ではなくて1位、1位、2位と付けるという方法。

ポイントは[Day44](https://qiita.com/Nono3/items/0a55db034095085b1a43)で学習した`DENSE_RANK`を使うだった。

提出したのはこちら。
```:SQL Server
SELECT score, DENSE_RANK() OVER(ORDER BY score DESC) AS rank
  FROM scores
```

`Discuss`を覗いて見るとMySQLでは、`AS rank`がだめなようで
```:MySQL
SELECT Score, DENSE_RANK() OVER(ORDER BY score DESC) `rank`
  FROM scores
```
と記載する必要があるということ。`rank`が予約語だからかな？

* [LeetCode](https://leetcode.com/)の問題は、`MS SQL Server`で解いています。
Rustの無限イテレータ

# 無限イテレータ
HaskellやClojureでは、遅延評価する無限リストから出発し、途中で打ち切ることで別のリストを作り出すというパターンがあったと思うが、Rustでも同じようなものがないかと思っていたら、あった。


```rust
0..
```
https://doc.rust-lang.org/std/ops/struct.RangeFrom.html

使い方の例
`v = vec![a_1, a_2, ..., a_n]`に対し、`a_1, a_n, a_2, ...`というvecを返す関数。`(0..)`と`map_while`(Someが出る間mapを続け、ついでにunwrapするメソッド)を組み合わせる。

```rust
use std::collections::VecDeque;
fn head_tail<T>(v: Vec<T>) -> Vec<T> {
    let mut vd = VecDeque::from(v);
    (0..)
        .map_while(|i| {
            if i % 2 == 0 {
                vd.pop_front()
            } else {
                vd.pop_back()
            }
        })
        .collect()
}
```

もちろんたとえば次のように書けば無限イテレータも、そもそもイテレータ(に対するメソッド)も要らないのだが、変数がすくなくて済むのがなんとなく好き。


```rust
fn head_tail<T: Copy>(v: Vec<T>) -> Vec<T> {
    let mut a = 0;
    let mut b = v.len() - 1;
    let mut w = Vec::with_capacity(v.len());
    for i in 0..v.len() {
        if i % 2 == 0 {
            w.push(v[a]);
            a += 1;
        } else {
            w.push(v[b]);
            b -= 1;
        }
    }
    w
}
```

計算時間やメモリ的にはどうだろう。そこまで無駄はない(collect先のvecの大きさがわからないので再配置が生じうる点を除けば)と思うが、検証はまたいつか。

補足
さらに以下のようにシンプルに書けると気づいた。
```rust
fn head_tail<T>(v: Vec<T>) -> Vec<T> {
    let mut vd = VecDeque::from(v);
    (0..)
        .flat_map(|_| [vd.pop_front(), vd.pop_back()])
        .map_while(std::convert::identity)  // map_while(|x| x) と同じ
        .collect()
}
```
ただ、いずれの書き方でも、この関数であればイテレータの最大長はあらかじめ`vd.len()`とわかっているので、`(0..vd.len())`と書けばよく、無限イテレータは不要であり、事前に長さのヒントがあった方が、`collect`するときにvecの再配置がなくて早いような気もする。(要検証)

# 他の無限イテレータ
## std::iter::repeat
おなじ値を無限に繰り返す。`take`などと組み合わせて使う。
```rust
let i = std::iter::repeat(4).take(4) // vec![4; 4].iter()と同じ
i.eq(vec![4;4]) // => true
```
https://doc.rust-lang.org/stable/std/iter/fn.repeat.html


## std::iter::repeat_with
同じ関数の結果を無限に繰り返す。

https://doc.rust-lang.org/stable/std/iter/fn.repeat_with.html

## cycle
cloneできるイテレータを無限に繰り返す。
```rust
[1, 2, 3].iter().cycle().take(7).collect::<Vec<_>>() // => [1,2,3,1,2,3,1]
```
https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html#method.cycle
ラジオボタンが選択されていない時にバリデーションエラーを出す

今更ながらですが、簡単なフォームならjQueryでバリデーションして、フォームにエラーを出したりしたいですよね。
その時にラジオボタンがどれも選択されていない状態だったらバリデーションエラーにしたい、つまりユーザーが必ず意思を持ってラジオボタンを選択して欲しい、ということがあります。

そんな時、どのように書きますか？
以下のようなHTMLがあります。

```html
<label><input type="radio" name="payment" value="銀行振込"> 銀行振込</label>
<label><input type="radio" name="payment" value="クレジットカード"> クレジットカード</label>
<label><input type="radio" name="payment" value="PayPay払い">PayPay払い</label>
```

これを選択されてなかったらバリデーションエラーにしたいわけです。
では、jQueryで書いてみましょう。

### 方法1

```javascript
// チェックされている要素の個数を取る
const payment = $('[name="payment"]:checked').length;

if (payment === 0) {
    // エラーを表示する・メッセージを変数に入れる等々の処理
}
```

ラジオボタンなので、`$('[name="payment"]:checked').length` は選択されていれば必ず1が返ります。
選択されていなければ0が返ります。

### 方法2

```javascript
// チェックされている要素のvalue属性を取得する。チェックされていないと取得できないのでundefinedが返る
const payment = $('[name="payment"]:checked').val();

if (!payment) { // undefinedは否定するとtrueになる。文字が入っていれば否定するとfalseになる
    // エラーを表示する・メッセージを変数に入れる等々の処理
}
```

`undefined` の扱い方が胆。 `!undefined` が `true` になることを覚えておくといいですね。


簡単なことなんだけど初心者には気づきづらいのかも。
Python Socket通信

# 概要
pythonで Socket通信に関して学んだので、その実際にSocket通信（TCP）するPG作ってみました。

# 前提
* Python 3.9.7

# 目次

Ⅰ. Socket Server
Ⅱ. Socket Client

## Ⅰ.Socket Server

元々、socket自体は入っているので、インストール不要。なので、そのまま、importを行う。

```
import　socket
```

まず、Serverを作成していきます。

```
import socket

# with構文使用することで、close不要になるため使用します。
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
  s.bind((socket.gethostname(), 50000))  # IPとポート指定
  s.listen(10)                           # サーバなので、Listen状態にします。10は、キューに貯める数。

  # 何度もレスポンスを返せるように、ここで無限ループにします。
  while True:
    conn, address = s.accept() # 接続受信
    print('Connection is established by {}'.format(address))
    
    # ここで、接続開きます。
    with conn:
      data = conn.recv(2048) # 格納できるバッファー指定 
      conn.sendall(data)     # 受け取ったデータをここで返します。
```

※ AF_INET：Ipv4
※ SOCK_STREAM：TCP通信


## Ⅱ.Socket Client

次に、client作成していきます。

```
import socket

# with構文使用することで、close不要になるため使用します。
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
  
  # サーバへ接続
  s.connect((socket.gethostname(), 50000))

  # データ送信 
  s.sendall(b'Connect to Socket Server')

  # レスポンスで受け取ったデータを取得して表示
  data = s.recv(2048)
  print(repr(data))
```
Javascript HTMLを書き換える

## はじめに
Javascriptの使い方を学ぶ
### 参考書
https://www.sbcr.jp/product/4815601577/
## 目的
HTML内の要素を書き換える
## 実行内容
```html:要素を書く
<p id = "choice">この要素を書き換える</p>
```
```js:choice要素を時刻に置き換える
<script>
 'use script'
 document.getElementById('choice').textContent = new Date();
</script>
```
このように表示される。
![スクリーンショット 2022-04-05 22.32.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2606223/febb7261-2dc0-6f0c-3caa-7eca8889073e.png)
【備忘録】Homebrewについて

## はじめに
こんばんは、だいごです。
今回は、プログライング学習を進める中で多々目にするbrewコマンドについて学んだのでまとめてみたいと思います。
よかったらご覧ください。

## 予備知識
- <b>パッケージ</b>
プログラムや処理をひとまとめにしたもの。
ライブラリとも言えるが、パッケージは複数のライブラリをまとめていることもある。

- <b>パッケージ管理</b>
パッケージやパッケージが持つライブラリなどの依存関係を考慮してインストールやバージョンアップを行う管理のこと。
１つのパッケージを利用したいとき、そのパッケージと依存関係にある複数のパッケージも合わせてインストールしてくれる。

- <b>依存関係</b>
あるファイルやライブラリが正常に動作するために、別のファイルやライブラリによる処理と結果が必要になる状態の関係。

## Homebrewとは
macOSのパッケージ管理ツールのこと。
Homebrewを使うとで、依存関係のあるパッケージが正しく動作するよう、複数のパッケージのバージョンをコントロールしてインストールすることが可能になる。

## Homebrewのインストール
Homebrewのインストールにはターミナルにて以下のコマンドを実行する。

```sh
% ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
```

## brewコマンド
基本的なbrewコマンドをいくつかまとめていきます。

```sh
# Homebrewのバージョン表示
% brew -v

# パッケージのインストール
% brew install パッケージ名

# パッケージのアンインストール
% brew uninstall パッケージ名

# インストールしたパッケージの表示
% brew list

# インストール可能なパッケージの表示
% brew search

# インストールしたパッケージを最新へ更新
% brew update
```
ちなみに「brew」というのは「醸造する」という意味で、Homebrewはパッケージ管理を醸造に見立てて作られているみたいです。

## 終わりに
今回はHomebrewについてまとめてみました。
まとめる中で今までの疑問が少しだけ晴れた気持ちになれました。
いろんなパッケージもあるので今後使いながら理解を深めていきたいです。
間違いや付け加え等ありましたら、コメントお願いします。
ありがとうございました。
backlog.com に登録した課題を Azure DevOps に転記するコードを書いた

backlog.com の登録課題を Webhook で Azure Functions で捌いて Azure DevOps に連携するコードを書きました。

![header.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110482/efce617d-4793-3d58-7ad7-554e4ef4ec65.png)

あまり見せられるコードでもないですが、ここに置いておきます。

https://github.com/nnashiki/bklg2devops-func

# 開発のモチベーション

[LIGHTz](https://www.wantedly.com/companies/company_7845665) では SaaS プロダクトを展開する予定です。
CS チームは CS に適した backlog.com を使って管理したいし、開発チームは Azure DevOps を使いたいです。
開発チームは問い合わせに対して機敏に対応したいが、なるべく Azure DevOps でチームのアサイン状況を管理したいという気持ちです。
そこでジレンマ解消のために、試しに backlog.com に登録した課題を Azure DevOps に転記することにしました。
運用はまだこれからですが、上手く回っていくことを祈っています。

# 開発のポイント

backlog.com の 課題登録 hook の request body に対応したモデルを pydantic で生成しました。
json を食わせたら良い感じに pydantic モデルを作成してくれました。
https://pydantic-docs.helpmanual.io/datamodel_code_generator/

スキーマだけ PyPI に別に publish して、bklg2devops-func で使っています。
https://pypi.org/project/backlog-schema/

# 最後に
Azure を活用した Ops 知見をもっと見たいな!
別アセンブリの非公開クラスのメソッドをリフレクションで実行する方法

## 0. はじめに

やたら情報量が多いタイトルになってしまった🙄

公開(アクセシビリティがpublic)されているクラスの非公開メソッドを直接実行したい場合は、リフレクションで実行すればOKかと思います。

:::note warn
あくまでテストのためですよ？テスト以外ではそんなことになってしまう設計がダメですね😇
:::

しかし、

**別アセンブリ　かつ　非公開(アクセシビリティがinternal)**

のメソッドを実行する必要があったので、そのときやった方法を備忘録として残しておきたいと思います。

:::note warn
あくまでテストのためですよ？(略)
:::

## 1. やったこと

```Csharp
// Type.GetType("名前空間.クラス名, アセンブリ名")を指定し、非公開クラスを取得します。
var hogeType = Type.GetType("Hoge.Logger, LoggerLib");

// ↑で取得したクラスのインスタンスを生成します。
// コンストラクタ引数がある場合は、例みたいにCreateInstance()の第2引数にパラメータを指定します。
// コンストラクタ引数がない場合は、指定不要です。
var hogeImpl = Activator.CreateInstance(hogeType, xxx);

// リフレクションで対象のメソッドを指定します。
// オーバーロードがある場合は、例みたいにGetMethod()の第2引数にパラメータを指定します。
// コンストラクタ引数がない場合は、指定不要です。
var writeMethod = loggerImpl.GetType().GetMethod("Write", new[] { typeof(string), typeof(string) });

// 実行します。
writeMethod.Invoke(hogeImpl, new object[] { title, message });
```

## 2. おわりに
ベストプラクティスじゃなかったらごめんなさい。
Sigfox Breakout Board（BRKWS01）を使ってみた。

![IMG20220411230343.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1339052/d3f3ef41-9523-14a5-91b8-8709da2bbfb6.jpeg)

今回はSigfoxのBRKWS01のモジュールを使ってみたので
レポートをあげます。

# ハードウェア設定
ハードウェアの構成とプログラムは以下のサイトを参考にしました。
https://www.kccs.co.jp/sigfox/blog/technical/2019/0213/
なお上記サイトのArduinoのプログラムには、一部誤りがあったので修正プログラム以下に記載しておきます。

``` c
#include <SoftwareSerial.h>
SoftwareSerial mySerial(10, 11); // RX, TX

void setup() {
  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }

  // set the data rate for the SoftwareSerial port
  mySerial.begin(9600);
  Serial.println("Connect to the Sigfox Breakout board...");
  Serial.println("AT$I=10 : get Device ID");
  Serial.println("AT$I=11 : get PAC");
  Serial.println("AT$T? : get Temperature");
  Serial.println("AT$V? : get Voltages");
  Serial.println("AT$P=unit : set Power mode (unit = 0:software reset 1:sleep 2:deep_sleep)");
  Serial.println("AT$TR=unit : set Transmit repeat (unit = 0..2)");
  Serial.println("AT$WR : save config");
  Serial.println("AT$SF=[payload] : SEND SIGFOX MESSAGE");
  Serial.print("Device ID : ");
  mySerial.print("AT$I=10\r");
}

void loop() { // run over and over
  if (mySerial.available()) {
    Serial.write(mySerial.read());
  }
  if (Serial.available()) {
    mySerial.write(Serial.read());
  }
}
```

# 無償回線登録
以下のサイトから登録処理を行います。（事前にユーザー登録している場合を記載します）
https://buy.sigfox.com/activate/devkit/JP

### 1、DevKitの登録
![スクリーンショット 2022-04-05 23.18.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1339052/9fbe7c2c-2d00-2c61-b339-55f64875ac5a.png)

### 2、登録完了画面
![スクリーンショット 2022-04-05 23.19.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1339052/3e5f4bb0-a814-e4f5-1204-4002b90fab22.png)

### 3、デバイス一覧に登録されているか確認
以下のサイトから正常に登録されたか確認してください。
https://backend.sigfox.com/device/list


## ちなみにSigfoxモジュール自作してみました
自分でも防水用のSigfoxモジュール自作してみました。
よかったら販売していますので使ってみてください。
https://qiita.com/Kurogara/items/49e5350c0e859b5a8380
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1339052/ede34e36-87e2-7efd-5e0f-50b0f704fd71.png)
DDNS について

## 勉強前イメージ

ダイレクトとかダイナミック的なDNS？
ダイレクトだったら内部的な？ダイナミックだったら動的に勝手にしてくれるの？DNSが？

## 調査

### DDNS とは

Dynamic Domain Name System の略で
動的に変更されるグローバルIPアドレスに対して固定でホスト名を割り当て
IPアドレスが変わってもホスト名で繋いでくれるものです。
アドレスが変更されるとDNS情報も変更するというシステムになります。

ルーターのGIPは電源を入れ直したときや、一定期間通信がなかった際に変更になります。
その為、GIP配下にあったシステムに接続する際にアクセスができなくなりますが
DDNSを使用することでIPアドレスが変更されてもホスト名で接続することができるので
引き続き使用することができます。

ユースケースとしては、家のネットワーク内に監視カメラを確認するwebサービスを立ち上げたとします。
それを外出先からホスト名を指定して確認することができます。

主にプロバイダやルーター製品の設定、サービスとして契約することができます。

## 勉強後イメージ

あんまり新しい記事が出てこなかったんだけど、今はあんまり使われてなかったりする？
それとも当たり前すぎて新しい記事がなかったのかな....

## 参考

- [SkyKinkDDNSとは](https://www.clear-net.jp/about)
- [DDNS 【Dynamic DNS】 ダイナミックDNS / 動的DNS](https://e-words.jp/w/DDNS.html)
最速！ CodePipeline の結果を Chatbot 経由で Slack に通知設定する

# はじめに
最速でcodepipelineの結果をslackに通知する方法について説明します。
他の記事ですと、通知用に SNS を作成する方法がありましたが、chatbotを作成すると、自動で作成されます。

![スクリーンショット 2022-04-06 21.44.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/988747/f94cc6b7-6c0d-444d-ca3b-ed6836dd6f4d.png)

# 事前構築
- codepipelineを作成

https://qiita.com/holdout0521/items/3aeeb9c9f9e663778ed7


# CodePipelineの通知作成
codepipelineの`通知`から`通知ルールの作成`をクリックします。


![スクリーンショット 2022-04-06 21.50.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/988747/4674d5f2-b938-895e-82b2-2cddf859c906.png)

- 通知をトリガーするイベント
    - `Succeeded`(各ステージが完了ごとに通知する)
    - `Failed`(ステージが失敗すると通知する)

`ターゲットを作成`をクリックします。
![スクリーンショット 2022-04-06 21.51.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/988747/27cdf67d-17c1-a5c0-d483-6c460c2ab5b1.png)

`Chatbotで設定する`をクリックします。
![スクリーンショット 2022-04-06 21.54.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/988747/ac137b9a-aabf-f5ad-ad13-834a3183eed9.png)

`新しいクライアントを設定`をクリックします。
![スクリーンショット 2022-04-06 21.54.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/988747/a9918d4f-3c48-05b7-0aec-9f3d316ff26e.png)

Slackを選択し、`設定`をクリックします。
![スクリーンショット 2022-04-06 21.55.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/988747/32ae88f3-1f0a-3fbe-2c64-231688f4183c.png)

Chatbotをslackを連携するため、`許可をする`クリックします。
![スクリーンショット 2022-04-06 21.55.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/988747/a216ef73-00d5-7d72-cd17-196e471ed7aa.png)


承認されました。`新しいチャネルを設定`をクリックします。
![スクリーンショット 2022-04-06 21.57.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/988747/799352c6-a6e4-4758-8190-4e713b103310.png)

# Slackチャネルを設定


- Slackチャンネル
    - チャンネルタイプ：`パブリック`
    - チャンネル名：`codepipelineの通知をしたいslackのチャンネル名を選択します。`
-  アクセス許可
    -  ロール名：`適当に`
    -  ポリシーテンプレート：`デフォルトのまま`
    -  チャネルガードレールポリシー：`AWSAccountManagementFullAccess`
![スクリーンショット 2022-04-06 22.04.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/988747/30b54f8e-f3ed-7f3e-c3a6-331f6bb2617d.png)
- 通知オプション
    - SNSトピックのリージョン：`記載しない`

下記のようになるかと思います。
![スクリーンショット 2022-04-06 22.00.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/988747/9e75cfd5-4576-8c15-a54e-3f97cd9f3843.png)

設定をクリックすると、chatbotとslackの連携が完了します。
![スクリーンショット 2022-04-06 22.06.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/988747/82f290b2-7fac-fb91-3a92-07fb2c9e506f.png)



# CodePipelineの通知作成続き
先程のCodePipelineの通知作成の画面に戻りましょう。
ターゲットタイプを`Chatbot(Slack)`にすると、先程作成した`test`が選択できるようになっています。
選択して、`Submit`をクリックすると、通知の設定が完了です。
![スクリーンショット 2022-04-06 22.07.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/988747/90a83be7-30b4-dee5-57a1-590087cece70.png)

CodePipelineが起動すると、Slackに通知されました。

![スクリーンショット 2022-04-06 22.12.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/988747/4f1ba72e-4fac-e2ae-ed06-f75536c1e837.png)
findで見つけた複数ファイルの最終行を削除する

# 問題
- これをしたい。
```
$ cat sample.txt
hoge1
hoge2
hoge3
（空白）
（空白）
↓
$ cat sample.txt
hoge1
hoge2
hoge3
（空白）
```
- ディレクトリ配下に複数の`sample_*.txt`があるような状況を考え、その全てに上記の処理をしたい。

# ダメだった例
- 以下の方法でできるかと思ったがなぜかダメだった。
    - 理由わかる方、ぜひコメントで教えてください！
```bash
find ${TGT_DIR} -maxdepth 1 -name "*.txt" | xargs -I {} bash -c "sed -i -e '$d' '{}'"

```

# うまくいった例
- `while`で回す方法だと、期待通りの動作となった。
```bash
find ${TGT_DIR} -maxdepth 1 -name "*.txt" | while read file; do
    echo ${file}
    sed -i -e '$d' ${file}
done
```
Docker for Windows 環境で Linuxコンテナ版 Azure Cosmos DB emulator 起動


公式ドキュメントでは、以下のようになっているのですが、できればWindowsコンテナじゃなくて、Linuxコンテナ版をWindows 10とか、11のDocker for Windowsで起動したいよねって事で、この記事です。

https://docs.microsoft.com/ja-jp/azure/cosmos-db/local-emulator-on-docker-windows?tabs=cli

https://docs.microsoft.com/ja-jp/azure/cosmos-db/linux-emulator?tabs=ssl-netstd21

# イメージのPullと実行

```dosbatch:イメージのPull
docker pull mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator
```

```dosbatch:イメージのRun
$ docker run -p 8081:8081 -p 10251:10251 -p 10252:10252 -p 10253:10253 -p 10254:10254  -m 3g --cpus=2.0 --name=test-linux-emulator -e AZURE_COSMOS_EMULATOR_PARTITION_COUNT=10 -e AZURE_COSMOS_EMULATOR_ENABLE_DATA_PERSISTENCE=true -it mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator
```
管理画面に8081を使います、もし競合する場合は、ポートを変えてください。

# エミュレーター用の証明書の取得

起動したら、以下にブラウザからアクセス（証明書の取得）
https://localhost:8081/_explorer/emulator.pem

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24782/9776f1c5-cd23-3986-a319-6a7405695715.png)

証明書が表示されたら、ブラウザを右クリックしてemulator.crtという名前で保存してください。


あとは、emulator.crtをダブルクリックして開き、証明書をインストールします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24782/e52055a4-5171-1059-ac1f-725488c2dd37.png)

その後、ブラウザで以下にもアクセスしてください（ローカル管理画面）
https://localhost:8081/_explorer/index.html

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24782/7e1329b4-f8a9-ade5-6a28-f9534b297203.png)
ripgrepはgrepよりも早い　sql文で検索する

## 用途
sql文で検索したい文字列を指定することで、指定した文字列が入っているテキストファイルが返ってくる。
現在grepを使っている方は多いと思いますが、断然にripgrepの方が早いです。

## 使用方法
```sql:コマンド
rg "検索したい文字列" 
```
"検索したい文字列" に入力した文字列が入っているテキストファイルが返ってくる。
※rgはripgrepの略で使用する際は、rgと入力する
　
　
そんなコマンドは無いよと言われた人は下記のコマンドを実行して、Homebrewでripgrepをインストールしてから再度試してみてください
```sql:コマンド
brew install ripgrep
```
　
　
`brew`コマンドを使ったことがない方は下記の公式サイトから `Homebrew` をインストールしてみてください。
[https://brew.sh/index_ja](https://brew.sh/index_ja)

## なぜ早いのか

ripgrepは、検索する必要がなさそうなファイル（隠しファイルやバイナリファイルなど）を無視するようになっている。
※バイナリファイルとは、簡単にいうとテキストファイル以外（画像、音声、動画などのファイルなど）のファイルのこと。
外部キー制約のついたカラムを削除する方法

ここではgenreテーブルからmovie_idカラムを削除します。

まず ```$ rails generate migration remove_カラム名_from_テーブル名``` を実行して、外部キー制約のかかったカラムを削除するためのマイグレーションファイルを作成します。


```
# rails g migration remove_movie_from_genre movie:references
Running via Spring preloader in process 414
      invoke  active_record
      create    db/migrate/20220406054902_remove_movie_from_genre.rb
```

削除用のマイグレーションファイルを確認します。
```20220406054902_remove_movie_from_genre.rb
class RemoveMovieFromGenre < ActiveRecord::Migration[6.0]
  def change
    remove_reference :genres, :movie, null: false, foreign_key: true
  end
end
```

特に問題ないので、手を加えることなく```rails db:migrate```を実行します。
```
# rails db:migrate
== 20220406054902 RemoveMovieFromGenre: migrating =============================
-- remove_reference(:genres, :movie, {:null=>false, :foreign_key=>true})
   -> 0.1231s
== 20220406054902 RemoveMovieFromGenre: migrated (0.1268s) ====================
```

以上でカラムの削除ができました。

何か間違いや不足などあればご指摘いただけると幸いです。

開発環境
mac OS バージョン11.6
エディタ
VScode

参考：https://qiita.com/himatani/items/38445aafa1312390d418
Flutterをアップグレードしたときのメモ

Flutterをバージョンアップしたら以下のように怒られた。

```

class RTCDataChannelNative extends RTCDataChannel { ^^^^^^^^^^^^^^^^^^^^ ../../../Downloads/flutter/.pub-cache/hosted/pub.dartlang.org/webrtc_interface-1.0.3/lib/src/rtc_data_channel.dart:79:12: Context: 'RTCDataChannel.bufferedAmount' is defined here. int? get bufferedAmount; ^^^^^^^^^^^^^^ ../../../Downloads/flutter/.pub-cache/hosted/pub.dartlang.org/webrtc_interface-1.0.3/lib/src/rtc_data_channel.dart:74:12: Context: 'RTCDataChannel.id' is defined here. int? get id; ^^

```

Flutterのバージョンとプラグインのバージョンが互換性がないよってことらしいです。（忘れると結構ハマる）

以下のコマンドを実施する。

```
flutter pub upgrade
```

以下参考

https://stackoverflow.com/questions/70473202/the-non-abstract-class-internalselectablemathstate-is-missing-implementations

また、このエラーに引っかかりがちな人は初学者だと思うのでFlutterのバージョンを複数管理する仕組みとしてFVMの導入も合わせて検討ください。

https://zenn.dev/welchi/articles/d8f120adeebc7a85ed17
Oracle Autonomous Databaseのクライアント資格証明(ウォレット)をダウンロードしよう

# 前提
１．OCI ADBインスタンス作成済み（参考ブログ↓）

https://qiita.com/heanzza/items/5232ab4b9f4092de7563
# 手順
１．ADBインスタンス詳細画面へアクセス
２．クライアント資格証明(ウォレット)をダウンロード
## １．ADBインスタンス詳細画面へアクセス
以下のブログの「３．SQL文を書かずに、DBユーザを作成しよう」の①~②を参照

https://qiita.com/heanzza/items/42e5f38f4358b21b7a34
## ２．クライアント資格証明(ウォレット)をダウンロード
① 「DB接続」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562390/dad77539-b199-a057-d988-5f07a082692d.png)
② 「ウォレットのダウンロード」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562390/4dd76907-04ac-5145-4914-15f586a6eda4.png)
③ 
パスワード：Welcome12345#
パスワードの確認：Welcome12345#
「ダウンロード」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562390/68944acf-791f-f5ff-04c6-8b79a67c02cb.png)
以上
WP REST APIのApplication Passwordsを使う

# 概要

- WP REST API を使った自動化みたいなことを考えているので使えるようになりたい
- 本番で検証するのは掃除や事故が怖いのでDockerで検証しました
- Application Passwordsは過去はPluginとして利用でしたが、あるバージョンからは組み込まれているっぽい
- また、SSLが必須（定義でどうにかなるらしいが探しきれなかった）なので、SSL化するdocker-compose.ymlを用意した


# 環境

```bash
$ sw_vers
ProductName:	macOS
ProductVersion:	12.3
BuildVersion:	21E230
```

WordPressのバージョンは `5.9.1` でした

# Docker使って環境を用意する

https://github.com/Aipakazuma/wordpress-ssl

↑のリポジトリに従って起動・手続きするだけ

# WordPressの初期設定

これは世にありふれているので割愛します

# Application Passwordsの設定

WordPressにログインし、左メニューから`Users`→`All Users`→`自分のユーザー名`→ユーザー編集ページの下部にある`New Application Password Name`にパスワード名を入力

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101690/581bc451-e42d-5128-ab5f-8d3d7e681a1f.png)

適当に `aipa1192` 
作ろう鎌倉幕府
　　と入力し、 `Add New Application Password` ボタンを押します

そしたら、パスワードが表示されるので、メモしておいてください（再表示はできないらしい）


# リクエストしてみる


```bash
$ curl --user "${wpログインユーザー名}:${メモしたパスワード}" \
  -X POST \
  'https://localhost/?rest_route=/wp/v2/posts' \
  -H "Content-Type: application/json" \
  -d '{"title": "MyTitle", "content": "MyBody", "status": "publish"}' | jq .
```

特にエラーコードなく、結果が返ってきたらおｋです。投稿されているか確認してみてください


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101690/33e87bdf-e274-da97-38c3-8a82fb32adc4.png)




ぼくのページ勝手にブクマしないでください！！！＞＜


大丈夫そうですね。以上です。

# 次

- JWT Authentication for WP REST API
- WordPress REST API – OAuth 1.0a Server
sbt-launcherのDLに失敗する時

Versionが上がるときに毎回忘れる。
```
failed to download launcher jar: https://repo1.maven.org/maven2/org/scala-sbt/sbt-launch/1.5.5/sbt-launch-1.5.5.jar (shasum mismatch)
```

https://stackoverflow.com/questions/68754878/sbt-failed-to-download-launcher

セキュリティツールとかの影響でDLできないことがあるんだよねえ。

解決策はこれ。キャッシュディレクトリにsbt-launcherを直接配置する。そうするとsbtだけで動作する。

```
cd  ~/.cache/sbt/boot/sbt-launch/1.5.5/
 wget https://repo1.maven.org/maven2/org/scala-sbt/sbt-launch/1.5.5/sbt-launch-1.5.5.jar
```
【Git】1つのコミットを2つに分割したい

## 今の状況
4つのファイルがある。
```
$ ls
a b c d
```
a→ｂ→ｃ→dの順にファイルを作成してコミットした。
本来は4回のコミットに分けるべきだったが、3回にしてしまった。
2回目のコミットを2つに分けたい。

```
$ git log
commit b7d7a993f7bce58701fac5b9526db21afc04ccbb (HEAD -> main) // (三回目)
Author: yuu 
Date:   Wed Apr 6 20:44:46 2022 +0900

    add d

commit b3889b0a5b71cfc3cf2412a25518d74d6823a235 // (二回目)
Author: yuu 
Date:   Wed Apr 6 20:44:16 2022 +0900

    add b, c

commit 336eebd502046ebbe4bd8068661d07d5c6c61b7e // (一回目)
Author: yuu 
Date:   Wed Apr 6 20:41:17 2022 +0900

    add a
```

## git resetを使う
`git reset --soft commit_ID`で任意のcommitまで戻ることができる。ただ、変更済みのファイルは手元に残る。


```
// 一回目のIDを指定。一回目のコミットまで戻る。が、二回目と三回目で加えた変更は手元に残っている。
$ git reset --soft 336eebd502046ebbe4bd8068661d07d5c6c61b7e

// 二回目と三回目のコミットがなくなっている
$ git log
commit 336eebd502046ebbe4bd8068661d07d5c6c61b7e (HEAD -> main)
Author: yuu
Date:   Wed Apr 6 20:41:17 2022 +0900
    add a

// コミットは消えたが変更したファイルは残る
$ ls
a b c d

$ git status
On branch main
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
	new file:   b
	new file:   c
	new file:   d
```

手元にはa,b,c,dの4つのファイルがあり、aの追加だけがコミット済みである。
ここからファイル名を指定して`git add`をして、一回ずつコミットしていけばいい。

```
$ git add b
$ git commit -m "add b"

$ git add c
$ git commit -m "add c"

$ git add d
$ git commit -m "add d"
```

### できました〜！！
コミットの履歴が綺麗だとコードレビューをがしやすいので、レビュー依頼を出す前に綺麗にしたいですね。
```
$ git log
commit 36fd1b2cb82d3810ad64b6c5f40890b97df904de (HEAD -> main)
Author: yuu
Date:   Wed Apr 6 21:09:21 2022 +0900

    add d

commit 68a195940a5c444c885d8b0bce714f2a4a56f25d
Author: yuu
Date:   Wed Apr 6 21:09:06 2022 +0900

    add c

commit 9e80cb253401d315e978147bfbf8701ab9acc7d0
Author: yuu
Date:   Wed Apr 6 21:07:28 2022 +0900

    add b

commit 336eebd502046ebbe4bd8068661d07d5c6c61b7e
Author: yuu
Date:   Wed Apr 6 20:41:17 2022 +0900

    add a
```