OmniAICreator/Qiita-1.07M huggingface dataset:
オブジェクト指向言語におけるクラスの基礎知識Part2~インスタンス化~

## はじめに
この記事ではオブジェクト指向言語におけるクラスのインスタンス化について解説します。

説明するのは以下の2点です。

・オブジェクト指向言語におけるクラスのインスタンス化の役割
・どのようにクラスのインスタンス化を実行するか

※この記事は「オブジェクト指向言語におけるクラスの基礎知識Part1」の続きの記事となっています。
クラスに関する役割と、クラスがどのようなデータを持つかについてを記載しています。
[オブジェクト指向言語におけるクラスの基礎知識Part1](https://qiita.com/Ichi_begin/items/522541a56223aa1f4eba)


## オブジェクト指向言語におけるクラスのインスタンス化の役割

まずインスタンスとは、一言でいえばクラスの実体を指します。
プログラム上では、クラスそのものを操作するのではなく、そのクラスを実体化したデータを操作することになります。
そして、インスタンス化とはクラスの実体を持つデータを生成する処理のことを指します。

前回の記事に記載した通り、クラスは目的を持った型枠のようなものです。定義されたクラスそのものを操作することはできませんが、
インスタンス化を行うことで、そのクラスの**インスタンス:実体**が生成され、プログラム上にてクラスの所持するメンバ変数やメソッドなどに対する操作が行えるようになります。これが、インスタンス化の役割です。

## どのようにクラスのインスタンス化を実行するか

Javaでは、以下のように記述することでインスタンスが生成できます。

**データ型 変数 = new クラス名(引数);**

これを見ただけでは理解が深まらないので、以下に具体例としてJavaのソースコードと
出力結果を記しました。

コードについて簡単に説明します。
name,birthplace,ageというメンバ変数を持つクラスPersonがあります。
これらのメンバ変数をコンストラクタを利用し初期化します。
その後、PersonExampleクラス内のmainメソッドで、Personクラスのインスタンス化を行います。
インスタンス化することで、具体的な値がメンバ変数に代入されていることが確認できるかと思います。

今回の例では、Personクラスをインスタンス化したことにより、Personの属性を持つデータの出力が可能となりました。

また、結果からコンストラクタに渡したデータによって、生成されたインスタンス毎に同名のメンバ変数でも異なる値を持っていることが
確認できると思います。

具体的には、p1,p2ともにPersonクラスのインスタンスですが、メンバ変数のnameが持っている値が、p1は「Satou」が、p2には「Suzuki」が格納されていることがわかると思います。

つまり、同じ属性を持つクラス型のデータでも、インスタンス生成時に渡されるデータなどによって、それぞれ個性を持ったインスタンスが生成されるということがわかったかと思います。

## ソースコード(Java)

```java
class Person {

    //メンバ変数
    String name;
    String birthplace;
    int age ;

    //コンストラクタ
    Person(String const_name,String const_birthplace,int const_age){

        name = const_name;
        birthplace = const_birthplace;
        age = const_age;

    }   

}

class PersonExample{

    public static void main(String args[]) {

        //インスタンス化
        Person p1 = new Person("Satou","Tokyo",11); 
        Person p2 = new Person("Suzuki","Osaka",20);

        //データの出力
        System.out.println("氏名:" + p1.name + " " + "出身:" + p1.birthplace + " " +"年齢:" + p1.age);
        System.out.println("氏名:" + p2.name + " " + "出身:" + p2.birthplace + " " +"年齢:" + p2.age);
    }

}
```

## 出力結果
```
氏名:Satou 出身:Tokyo 年齢:11
氏名:Suzuki 出身:Osaka 年齢:20
```

## まとめ
この記事では
・オブジェクト指向言語におけるクラスのインスタンス化の役割
・どのようにクラスのインスタンス化を実行するか
について解説しました。

プログラムの実例を確認することで、インスタンス化の必要性を
学んでいただけたら幸いです。
stimulusでselect2変更時のchange actionを定義したい

## 問題：select2のchangeイベントが呼ばれない
stimulusを使っているアプリケーション内でselect2を導入しようとした時の話です。
以下のように、都道府県のselect2の値が変更された時に市区町村を取得してくるような処理を書いていたのですが、なぜかfetchCitiesが呼ばれない。

```hoge.html.slim
= f.select :prefecture_id,
            Prefecture.all.map { |p| [p.name, p.id] },
            { required: true },
            data: { 'hoge-target': 'prefectureSelectBox', action: "change->hoge#fetchCities" }
```

```javascript:hoge_controller.js
import { Controller } from "@hotwired/stimulus"

export default class extends Controller {
  static targets = ['prefectureSelectBox']

  connect () {
    $(this.prefectureSelectBoxTarget).select2
  }

  fetchCities (e) {
    // 市区町村を取得する処理
  }
}
```

## 解決策：select2の変更時にchangeイベントを発火させる

そこで参考にしたのが以下の記事。
select2はネイティブイベントではなく独自のイベントを発火させているため、**select2の独自イベントをキャプチャしてネイティブイベントを発火させるようにすれば良い**とのことでした。なるほど。

> 問題は、Select2が'ネイティブ'イベントを使わないことだ。独自のイベントフレームワークを持っているのです。そのため、Select2イベントをキャプチャして、ネイティブイベントを再送信する必要があります。それがわかれば簡単だ！


https://psmy.medium.com/rails-6-stimulus-and-select2-de4a4d2b59e4

上記を踏まえて修正したコードが以下になります。
select2変更時にネイティブのchangeイベントも発火されるようになるため、stimulusに設定したアクションが呼ばれ`fetchCities`が実行されるようになりました。

```javascript:hoge_controller.js
import { Controller } from "@hotwired/stimulus"

export default class extends Controller {
  static targets = ['prefectureSelectBox']

  connect () {
    $(this.prefectureSelectBoxTarget).select2
    // select2の独自イベントをキャプチャしてネイティブchangeイベントを発火
    $(this.prefectureSelectBoxTarget).on('select2:select', function () {
      const event = new Event('change', { bubbles: true })
      this.dispatchEvent(event)
    })
  }

  fetchCities (e) {
    // 市区町村を取得する処理
  }
}
```

https://select2.org/programmatic-control/events
インターンシップから学ぶ「開発手法」

## この記事の位置づけ
先日まで行っていたインターン中に触れた事項について復習しながらまとめる記事となっています。自分の感じたことを残しておくという意味で書いている側面もあるので、誤りも多々あると思いますがご容赦ください。これら気が向いたらご指摘いただけると幸いです。

今回はインターンで触れられた「ウォーターフォール」と「アジャイル」の２つについて述べていきます。

## ウォーターフォール
要求分析→基本設計→詳細設計→実装→テスト（単体テスト→結合テスト）→運用・保守の順で流れる開発モデルになります。
%(画像挿入）
作業を順番に進めていく開発する手法であり、大規模なプロジェクトを大人数で開発することに適しています。
##### 要求分析
ユーザの話を基にソフトウェアで実現するべき機能をまとめる作業。要求仕様書として記述をまとめます。要求される内容は機能仕様と非機能仕様の２つに分けられます。（要件定義は要求工学として一つの分野になるような内容なのでここでは詳細は割愛します）

#### 基本設計・詳細設計
ソフトウェアの要件を満たすようなソフトウェアの機能などを考えます。詳細設計だと処理記述書を書くこともあるのかな?（詳細設計だとほぼコード書いてるのと同じみたいなこともあるので書かないこともあるとか）

#### テスト
品質管理の際にプログラムに欠陥が残っているかを確認します。後述のV字モデルとかだと設計・PGとテストが対応していたりします。テストについては別記事でまとめようと思うのでここでは割愛します。

#### メリット
* 開発の進捗管理が容易
    * 作業を順番に行うので開発がどこまで進んでいるかすぐにわかります。
* 作業分担が行いやすい
* 信頼性の高いソフトウェアを作りやすい。
    * 各種ドキュメントの制作を行いながら開発を行うことができ、テストをしっかりと行うことができるので、ソフトウェアの信頼性を高めやすいです。

#### デメリット
* 上流工程での遅れが下流工程に大きく影響
    * 作業が順番に流れるので、要求定義などのドキュメント作成が遅れるとそのままその後の作業が起これることになります。実際には要求定義が完結せずに次の段階に移らないといけない状況があることも。
* 作業を順番通りに行うことが難しい
* 作業後半で仕様と設計の相違を見つけた場合に前の段階に戻るのは難しい



### V字モデル
ウォーターフォールの発展形としてV字モデルがあります。このモデルではドキュメント作成や開発作業とテストを対応させることにより、テストをより合理的に実施することが可能なモデルとなっています。


## アジャイル
１つのプロジェクトの中で特定のサイクル（スプリント）を複数回繰り返すことによってソフトウェアの開発を行う方式です。スプリントは1~4週間区切りで行われます。
#### プロジェクト立ち上げ時に行うこと
プロジェクトを立ち上げた後に行うこととしては以下があります。以下の各項目はスプリントでは繰り替えしません。
* インセプションデッキ
インセプションデッキはプロジェクトの概要に当たるものです。チームの中でプロジェクトに対しての共通理解を得るために行われます。
* ワーキングアグリーメント
アジャイル開発を行う際のルール作成です。この中で各スプリントで行われるデイリースクラムの時間の使い方などの様々なルールが決められます。
* ユーザストーリーマップ
プロジェクトの中で必要な機能などを割り出します。実現したい事項を時系列順に並べます。そのうえで、より詳細な機能を各事項毎に記述していきます。（これらは紙などの上に付箋で張られる事が多いです。）この上で、各機能をいつまでに実装するかを区分します。（前述の付箋を貼った紙の領域を線で区切ります。）

#### 各スプリントで行うこと
以下に記述することは各スプリントの中で行うこととなります。ただし、それをどの程度の頻度で行うのかには差異があります。
* スプリントプランニング（スプリント開始時のみ）
    ここでは、プロダクトバックログ（プロジェクトの中で行う必要がある作業）からスプリントバックログ（スプリントの中で行う作業）を抜き出して決定します。重要度や作業の重さを基にしてスプリントの中で行う作業を決定します。
* デイリースクラム（毎日）
    チームの中で作業の進捗やその日に行う作業などを確認します。（IPAの資料だと15分でやるとか、立ったままやるとか、朝やるとか書いてありましたが、人数・チームメンバーの勤務地・スケジュールなどによって変化します。実際、私の担当をしていただいた方は16:30からしてましたし、勤務地がばらばらなのでオンラインでやってました...）
* バックログリファインメント（適宜）
    スプリントプランニングで決定したスプリントバックログの内容を作業状況に合わせて見直します。進捗が早いから次のスプリントで行うであろう作業を今のスプリントに入れたり、逆に抜いたりという作業が行われます。この項で述べている各スプリントで行うことの中で唯一、行うタイミングがきまっていない作業になります。
* スプリントレビュー（スプリント終了時）
スプリントの成果をステークスホルダ―に発表します。成果物のデモなどを行うことがあります。ステークスホルダ―のフィードバックは次のスプリントプランニングなどに活かされます。
* スプリントレトロスペクティブ（スプリント終了時）
    スプリントの振り返りを行います。スプリントの成果や反省点などを振り返ることでつぎのスプリントにつなげます。KPT分析などが行われます。


## 案件として見るウォーターフォールとアジャイルの違い
ここからは開発する側はあまり意識することのない金銭とか契約的な話の違いを見ていきます。
ウォーターフォール型は開発期間及び開発の予算となる資金は契約の際に確定することになります。このため、作業を効率よく進めて費用を浮かせれば利益が増える半面、工数が伸びて経費が増えると案件としての利益は減少します。また、瑕疵責任があります。
アジャイル開発は準委任契約という形で契約が行われます。このため、金額や工数などがウォーターフォール開発ほどしっかり確定していません。ウォーターフォール開発よりも案件として柔軟に開発することができます。

## 参考
https://www.ipa.go.jp/jinzai/skill-standard/plus-it-ui/itssplus/ps6vr70000001i7c-att/000065606.pdf
cronを自由にカスタム可能にする

## 背景
cron使ったら時間間隔やコマンドを書いておくと定期実行をやってくれるが、深夜は実行頻度下げてそれ以外の時間はいつも通りにしたいが、cronに書くやり方だけだと分からなかった。

あるかもしれないが、今後自由にカスタマイズできたほうが便利だと思うので作ってみることになった。

そういうGUIアプリあるが、自分用に便利なツールを作る

## やり方
ざっくりいうと、Node.jsプログラムでcronファイルを作成する。

実行内容、実行間隔などを変数にして、cronファイルとして書き込んでしまえばいい。

cronファイルにcronファイルを作成するnode.jsプログラムを1分ごとに実行するコマンドを仕込んでおく。

# プログラム
以下のようなコマンドのリストとなる配列を作成する。
「createExecTime」メソッドで、自由に定期実行間隔を作成しちゃえばいい。例えば実行するたびに時間を見て、深夜だったら定期実行時間を下げる数値をreturnしたらいい

あとは、上書きではなく追記である必要があるので「append」で書き込む。
※fsモジュールのappendをPromise使ったバージョンとかにしたメソッド作って呼び出す

```typescript:anime-suko.ts
    const crontabCmdList = [
        "# 何かコメント",
        `*/${await createExecTime("機能名")} * * * *  コマンド`,
        // ・・・(以下省略)
    ]

    for (let i = 0; i < crontabCmdList.length; i++) {
        // 自作のファイル上書きメソッド
        await appendPromise(cronTabFilePath, crontabCmdList[i] + "\n")
    }

```


すると、きれいにcronファイルが作成できた。

今は1つのファイルにしているので、扱いやすくしたいならコマンド一覧をjsonにして外部ファイルにするのもありだと思う。

あと、createExecTime()メソッドに機能名のような引数を追加したら、機能ごとの時間が取得できるようになる。

機能ごとの時間とか、業務での開発だったら設定ファイルとかでまとめたほうが適切だとは思うが個人開発なので僕は直接配列にぶっこんでます。

世の中にあるGUIアプリによる定期実行もあるが、自分用のプログラムのほうがなんでも自由にカスタマイズできるので作ってよかった。
Windowsの外付けUS配列キーボードでMacのかな/英数変換を実現する

## 前置き
元々Mac+外付けUS配列キーボードを使用していたのですが、使用ソフトの関係でどうしてもWindowsを使用することになりました。。。
でも、同じキーボードを使用したいし、使用感を変えたくない。
一番困った、使いにくかったのはかなと英数の切り替え。
これをこれまでの使用感に戻します！

いろんな人がいろんなやり方を載せているけれど、それぞれ好みもあるせいか書いていることがそれぞれで、なかなかに調査に時間を取られたので自分でもまとめ。

## 環境
- Windows OSのノートPC（JIS配列キーボード）
- US配列の外付けキーボード

## やりたいこと
US配列のスペースキー両隣にあるCommandキー（私の場合。Altキーの場合もあるかも）で、右を押したらかな入力、左を押したら英数字入力にする。
（つまりMacのJISキーボードの配列に寄せたい）

## 設定手順
1. JIS配列キーボードの変換、無変換キーをIMFオン、オフにする
設定 > 時刻と言語 > 言語と地域 >　日本語 > 言語のオプション
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3490854/185467b8-73de-3235-78f1-664688c0f793.png)

Microsoft IME > キーボードオプション > キーとタッチのカスタマイズ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3490854/06e92c56-cec5-d891-7817-a316c452661a.png)

キーの割り当てをオンにして、無変換キーを`IME-オフ`、変換キーを`IME-オン`にする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3490854/f5646998-78e7-efe8-e558-c2a9e220d8a5.png)

2. Powertoysのインストール
https://apps.microsoft.com/store/detail/XP89DCGQ3K6VLD?ocid=pdpshare

3. PowerToysのKeyboard Managerで左右のCommandキーに変換/無変換キーを割り当てる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3490854/436e7f73-8f98-2bf5-29af-2ef52dc343b3.png)

※ちなみに私はなくなったCommandキー（Winキー）を小さなCtrlキーに退避させ、CapsLockをCtrlに変えています。

## 注意点
はじめはPCに認識させるキーボードをどれにすれば良いのか迷いました。
この方法を使うのであれば、US配列を認識させて構いません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3490854/3b0cb6d6-d017-0361-3d00-4154341b32b5.png)
ちなみに私は接続キーボードを認識させています。（外付けなしでJISキーボード使うこともあるかもなので）

## 完了
これでこれまでの使用感にかなり近づき、日本語がさらさらさらーっと打てるようになりました！
誰かのお役に立てれば幸いです。
インターンから学ぶ「MVC」

## この記事の位置づけ
先日まで行っていたインターン中に触れた事項について復習しながらまとめる記事となっています。自分の感じたことを残しておくという意味で書いている側面もあるので、誤りも多々あると思いますがご容赦ください。これら気が向いたらご指摘いただけると幸いです。

この記事ではMVCモデルについて記述を行います。ASP.NETを用いたプロジェクトの体験を行った経験を基に記述していきます。

## MVCモデルとは
MVCモデルはデータ・ユーザインタフェース・アプリケーションロジックをModel, View, Controllerの3つに分割して記述するモデルを指します。モデルの考え方に基づいてコードを作成することによってファイル構造などを整えることができ、開発作業や保守作業を効率的に行うことができます。
（Microsoft（参考1）などはMVCをデザインパターンとしてMVCパターンとしています。ただ、MVCをデザインパターンの１種としては扱わない記事などが多々見られたので、ここでは参考程度に記述するにとどめておきます。）

### Model
Modelはデータを扱うために利用されます。ViewのUI上で入力されたデータをModelに入れて、それを基にデータベースとやり取りして、またViewでデータを表示するなど、データベースとデータをやり取りするうえで利用するものです。
プロジェクトで「~Model」というクラスのインスタンス変数にデータを入れて、コントローラーやロジックで処理していたので、やり取りに利用するための複数のデータを保持しておくものというイメージを個人的には持っています。（このイメージだとDTOになってしまう...）

Modelにはビジネスロジックを含むようです。
（インターンだと、～Modelはデータを格納しておくクラスで、Logicは処理を記述する別ファイルで、Controllerで呼び出されるという形だったので、モデル=DTOみたいなイメージがついてしまったので違和感が多少あります。本来Logicのファイルに記載するべき要素が一部Controllerのファイルに残っていることもあって、Controllerとロジックの関連が強い印象が残っているせいだと思います。ただ、Controllerにロジックを書くな的な話もあるので、当てはまる場所としてはModelしかないですかね。）
（データベースとのやり取りを行うDAOはデータの処理だからModelに含まれるのですかね。ただ、ビジネスロジックとデータアクセスは別物という話もあるので、もうわかんないなぁ...）

### View
Viewはアプリケーションのユーザインタフェース（UI）に当たるものです。画面表示を担当します。Modelが持つデータを参照してデータの表示を行います。また、データの入力を受け付けてmodelにデータを入れるのもViewの担当のイメージです。
（ControllerでGetViewという名前のメソッドを使って表示が行われていた印象が強いです。）(インターンだとRazorを利用してページを生成していました）

### Controller
ModelとViewの制御・仲介を行うものです。Viewを呼び出してのUIを生成や、ModelのLogicやDB操作などの呼び出しを行います。操作や処理の流れに応じてViewやLogicを呼び出す役割です。
Logicなどは処理の順序的にはControllerにも書くことができますが、ファイルに記述される処理が膨大となり、役割から外れるので、書かないようにした方が良いです。



## インターン中に学んだ事項
### ファイルに記述する内容
~Model：Modelで扱うデータを入れるクラスを定義します。別ファイルのクラスを継承する場合もあります。
~Controller：コントローラーの処理を記述します。このファイルでは~Modelで定義したクラスのデータなどを引数として~Logicの関数を呼び出してモデルのデータの制御などを行います。また、Viewの取得もControllerの関数で行います。
~Logic：~Controllerのファイルに記載されているメソッドから呼び出されます。入力値の条件チェックや、データベース操作を行うための~Daoのメソッド呼び出しを行います。Daoの操作が行えるようにデータを別のクラスに入れて渡すこともあります。
~Dao：DB操作を行います。引数として与えられたデータを基にSQL文を実行します
ここでは別ファイルのSQLを読み込み、引数として与えたデータを基にしてSQLの内容を置換することで動的にSQLを生成して実行することもあります。

### 意識する事
各ファイルにはそれぞれ機能として想定する役割があります。このため、各ファイルの役割を逸脱しないように処理の記述を行いましょう。特に、Controllerは本来Logicに分けるべき内容を記述して膨大になってしまうことがあるので注意しましょう。

## 参考
Microsoft, 「ASP.NET MVC パターン」, https://dotnet.microsoft.com/ja-jp/apps/aspnet/mvc
Geekly Media, 「MVCモデルとは！概念やそのメリットをわかりやすく解説！」, 
https://www.geekly.co.jp/column/cat-technology/1911_040/#View
@s_emoto, 「MVCモデルについて」, https://qiita.com/s_emoto/items/975cc38a3e0de462966a
@kunrenyouAcount,  「MVCモデルについて」, https://qiita.com/kunrenyouAcount/items/bcb040dc42708d0844ce
@os1ma,  「『ビジネスロジック』とは何か、どう実装するのか」, https://qiita.com/os1ma/items/25725edfe3c2af93d735
@RINYU_DRVO,  「DTO(Data Transfer Object)」, https://qiita.com/RINYU_DRVO/items/112957b84ec8c2a4711a
クチの利きかた気ィ付けろ、えーおい

Qiita のターゲット層というのはエンジニアが大半であることを前提に。
「クチの利きかたに気を付けろ」ということを提言したい。

のっけから大上段に構えて偉そうにカマしてみましたが、僕は TypeScript 書きの vincent. と申します。普段は React とか React とかを書いています。以後、お見知りおきを。

さて、タイトルなんですが、別段、ケンカを売っている訳ではなく、「レビュワー、レビューイの人、分かってる？　ちょっともう」ということなんです。

「あの人、ものっそ細かいトコで指摘してくんのよ。。ぜってえモテねえタイプだぜ。やぁ、そうに違いない。。」などと嘆く前に、「あーたのクチの利きかたがなってないんじゃなーの？」と。自戒も込めて、今一度振り返ってほしいのです。

皆さん普段は余り意識しておられませんが、大抵のプログラムというものは「言語」です。
そう、もうお分かりですね？　「言葉遣いが悪いとエラーを吐く」。

「ああ、僕の言葉遣いがなっちゃねーからコードちゃん、言うこと利いてくれねえんだ。。」と、プログラムと情緒的な対話を楽しんでみては、という提言でもあります。先のレビュワーはそれを指摘しているのだ、と。

どちらが上でどちらが下か、的な **ヒエラルキーが失墜した昨今** では素通りされてしまう観点かも知れませんが、「レビューをお願いいたします」と PR を飛ばしたのならば、雰囲気、こちらが神妙になって正座して待っていても良い気がします。ねぇ？　一応お伺い立てとる訳やしｗ

そして、「指摘があるのはうれしいことだ」と。箸にも棒にも、本当にどうしようもない人には何も投げ掛けてくれないのが我々の棲息している常世です。真性かまってちゃんは本懐を遂げられないのが自然の摂理、宇宙の法則なのですｗ

「ここ直したほうがいいぜ。そしたらきっと君はハッピーになれるはずさ」的な白い歯きらりスマイルとか浴びされようもんなら「己、こわっぱ。。ワシがさんざ苦労して書いたソースを愚弄しくさってからに。。目にもの見せてくれようぞ。。」といった呪いのアングリーエニグマはマリアナ海溝より深く海底の底の底のどん底に沈めて、、「ハイ、僕頑張ります！　ご指摘ありがとうございました！」と、そんな **大人なエンジニア** になれたら、きっとモテるはずですね。ですよね？　ですよね。。

余りにもポエムが過ぎるのでこの辺で。。☆

「おう。クチの利きかた気ィ付けろ、えーおい」←

そんな感じで♪
【図解あり】IPアドレスとポート番号の違い

前回IPアドレスについて記事を書きました。今回はポート番号とは何か、IPアドレスと何が違うのかという視点でまとめてみました。

# ポート番号とは？
ポート番号とは、TCP/IP通信において、 コンピュータが通信に使用するプログラムを識別するための番号です。 ポート番号は16ビットの整数であるため、2^16=65535　つまり、0番～65535番まであります。

# IPアドレスとポート番号の違い
## webサイトが読み込まれるまでのフロー
1. PC(自分のIPアドレス)
2. 送信先のIPアドレスを調べる
2. PCのポート番号から出発
2. 送信先のサーバに到着
2. サーバのポート番号から入る 

## IPアドレス
IPアドレスは、インターネット上の住所のようなもの。下記のように、どこのPCからどのサーバーに送るのかIPアドレスを指定することで、送受信を行えます。
![Group 32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1049661/8b9925e4-bc41-964d-6719-8e2ffda6084e.png)
※PCのポート番号は、そのとき空いているポート番号が割り当てられます。そのためPCのポート番号は都度変化します。(ダイナミック/プライベートポート番号にて記載)

## ポート番号
一方、ポート番号はプログラムの識別を行なっている。１つのコンピューターでできることはさまざまなプログラムが行なっており、例えば、「メールを送受信する」「Webページを閲覧する」といったものである。これをポート番号が識別を行っています。
![Group 31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1049661/f00957c5-1930-609a-da26-ec189fed2e26.png)


# ポート番号の種類
ポート番号は、範囲ごとに3つの名前があります。
1つ目は、「ウェルノウンポート番号：0～1023」です。
2つ目は、「登録済みポート番号：1024～49151」です。
3つ目は、「ダイナミック/プライベートポート番号：49152～65535」です。

## ウェルノウンポート(Well-Known Port)番号とは？
一般的に特定のサービスやプロトコルに割り当てるために予約されている0番~1023番のことです。広く知られているため「ウェルノウンポート」と呼ばれています。特に有名なのはHTTP、FTP、AMTP、POP、DNSのポート番号です。


| ポート番号	|TCP/UDP	|用途|
|---|---|---|
|20|	TCP,UDP	|ftp　データ転送ポート
|21	|TCP,UDP	|ftp　コントロールポート
|22	|TCP|ssh, scp, sftp
|23	|TCP|	telnet
|25	|TCP|	smtp
|53	|TCP,UDP|	dns
|80	|TCP	|http
|88	|TCP	|kerberos
|110 |	TCP	|pop3
|111 |	TCP,UDP	|sunrpc
|123 |	TCP,UDP	|ntp
|137 |	TCP,UDP	|NetBIOS Name Service
|138 |	TCP,UDP	|NetBIOS Datagram Service
|139 |	TCP,UDP	|NetBIOS Session Service
|177 |	TCP	|X Display Manager Control Protocol (XDMCP)
|220 |	TCP	|imap3
|389 |	TCP	|ldap
|443 |	TCP	|https
|445 |	TCP,UDP	|MS ファイル共有/プリンタ共有
|465 |	TCP	|smtps

## レジスタードポート(登録済みポート)番号
1024番から49151番までが「レジスタードポート」「登録済みポート」（registered ports）あるいは「ユーザーポート」（user ports）と呼ばれ、インターネット資源の管理団体であるIANA（Internet Assigned Numbers Authority）が用途の受付・登録を行っています。

| ポート番号	|TCP/UDP	|用途|
|---|---|---|
|1433 |	TCP	|SQL Server
|1434 |	UDP	|SQL Server Browserサービス
|1521 |	TCP	|Oracle
|3306 |	TCP	|MySQL、MariaDB
|3389 |	TCP	|リモートデスクトップ
|5432 |	TCP	|PostgreSQL
|10050 |	TCP|	Zabbixエージェント
|10051 |	TCP	|Zabbixサーバ

## ダイナミック/プライベートポート番号
ダイナミック/プライベートポート番号は、エフェメラルポートとも呼ばれており、用途の決まっていないポート番号群です。サーバー側と通信する上でクライアント側が一時的に設定する番号となります。こちらは固定された番号ではありませんが、49152～65535番の範囲で使用することをIANAは推奨しています。
パワーシェル、プロンプト変更方法

```
PS C:\WINDOWS\system32> New-Item $profile -force -type file


    ディレクトリ: C:\Users\(ユーザ名)\Documents\WindowsPowerShell


Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a----        2023/09/08     10:07              0 Microsoft.PowerShell_profile.ps1

PS C:\WINDOWS\system32> notepad $PROFILE
```

```Microsoft.PowerShell_profile.ps1

function prompt { 
    $user = $env:USERNAME 
    $computer = $env:COMPUTERNAME 
    $location = (Get-Location).Path 
    $date = Get-Date -Format "yyyy-MM-dd HH:mm:ss" 
    Write-Host ("PS $user@$computer"+":"+"$location - $date >" )
    }
```
```
[System.Security.Principal.WindowsIdentity]::GetCurrent().Name
```
これは、カレントユーザ名（現在のユーザを表す）

```
PS C:\WINDOWS\system32> . $PROFILE
PS (ユーザ名)@（PC名）:C:\WINDOWS\system32 - 2023-09-08 11:14:51 >
```

パワーシェル再起動
```
PS (ユーザ名)@（PC名）:C:\WINDOWS\system32 - 2023-09-08 11:18:33 >
PS>
```

となることを確認
NetAppのデータをFSx for NetApp ONTAPへデータ移行してみた②

どうも、GOKUSANです。
前回のNetAppのデータをFSx for NetApp ONTAPへデータ移行してみた①の続きになります。

↓前回

https://qiita.com/gokusan/items/9f74859475ea876507a8


そうそう。
お伝えし忘れていたのですが、FSx側への移行の前段階として、

**移行前提を満たすための準備**　← 今はここ
↓
バージョンアップに向けた下準備
↓
バージョンアップ
↓
FSxとの同期

という順でお送りしたいと思います。


## DP形式をXDP形式に
前回の記事で、オンプレミス側のNetApp間のSnapMirrorをバージョンアップ後も維持するため、**DP形式なんてやめちまえ**というお話しをしました。

↓のキャプチャでいうと、「SourcePath」がIKA:vol2 というのが、type列の値が「DP」になっていますね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3552050/6fcd23cd-f645-7680-f427-2ff491bc2d52.png)


さて、現状DP形式で取得されているSnapMirrorをXDP形式に変換するには

① DP形式のsnapmirrorを停止する
② 停止したsnapmirrorの関係を解除する
③ snapmirrorを削除する
④ 再びsnapmirrorを作成する
⑤ snapmirrorによる同期を再開する

という手順をたどります。

要するに、**１回消してもう１回SnapMirror作り直せ**ということですね。

作り直すためのコマンドをパパっと！書いてしまいましょう！
ここでは、
【ソース側】
　SVM名 = IKA
　ボリューム名 = vol2

【デスティネーション側】
　SVM名 = GOKUSAN
　ボリューム名 = vol2
としますね。

``` :① 停止コマンド
snapmirror quience -destination-path GOKUSAN:vol2
```

``` :② 関係解除コマンド
snapmirror break -destination-path GOKUSAN:vol2
```

``` :③ 削除コマンド
snapmirror delete -destination-path GOKUSAN:vol2
```

``` :④ 作成コマンド
snapmirror create -source-path IKA:vol2 -destination-path GOKUSAN:vol2 -type XDP
```

これだけでsnapmirrorはXDP形式で作り直せます。
大事なのは、-type XDP の部分ですね。古いONTAPだとここを明示的に指定しないとDP形式になってしまいます。

### ん？最初から同期し直しにならないよね？
この作り直しに際して、私は一つ疑問が湧きました。
**作り直したら、ボリュームの同期は一からやり直しになったりしない？**
という点です。

結論から言うと**なりません**。
ただ、注意しないといけない点もあります。

:::note warn
**注意！**
・DPからXDPの変換を行うと、必ず一度「同期」をかけなければいけない
:::
というのも、作り直した直後の状態は「broken-off」された状態

↓のキャプチャでいうと「Mirror State」列にご注目
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3552050/829b110a-a2f4-2903-d4ea-419bddac2d83.png)

これは、snapmirror break コマンドを行った直後（関係解除）の状態です。
なので、breakと対になる**関係再開**のコマンドを打たなければなりません。

breakコマンドと対となるコマンドは**resync**です。

snapmirror breakコマンドで関係解除された場合は、
snapmirror resyncコマンドで関係が再開できます。


``` :⑤ 関係再開コマンド
snapmirror resync -destination-path GOKUSAN:vol2
```
ただ、この関係再開コマンドは、実行するとその時点で**強制的にsnapmirrorによる同期処理が走って**しまいます。
なのでこのコマンドを実行する前に、２つ目の注意点です。

:::note warn
**注意！**
・DPからXDPの変換にはそれなりに時間がかかる
:::
今回のお客様はNetAppで払い出せるボリュームの最大値である「60TB」のボリュームをお持ちで、
かつ、95%以上のデータを使用されておられました。

環境に依存するところはあると思いますが、変換には**1週間近く**の時間を要しました。
正直、「そんなにかかるの！？」という感じでしたが、それなりに時間がかかるケースがあることも想定しておいてください。

なお、変換中におけるユーザー利用への影響はありませんが、変換処理中にソース側とデスティネーション側の通信が切れてしまうと、変換処理は失敗します。

なお、実際の作業では、変換処理中にソース側をお客様都合で再起動せざるを得ない状況となり、一時失敗状態となりましたが、**もう一度resyncを叩けば処理は失敗時点からちゃんと再開**されました。

## まとめ
今回は、FSxへのデータ移行の前準備として、オンプレミス側のSnapMirror関係に手を入れました。

:::note info
**まとめ**
・DPからXDPの変換にはSnapMirrorの作り直しが必要だよ！
・DPからXDPの変換やると必ず1回は同期処理をしないといけないよ！
・DPからXDPの変換にはそれなりに時間がかかるんだよ！
:::

次回は、バージョンアップのための下準備についてお話ししまーす。
ではでは。
zshでgitのブランチ名を表示する


## 設定方法

ツールを追加するディレクトリを作成する。

```zsh
$ mkdir ~/.zsh
$ cd ~/.zsh
```

補完に必要なツールを取得する。

```zsh
# 補完用ツール
$ curl -L -O https://raw.github.com/git/git/master/contrib/completion/git-completion.bash
# zsh用に補完用ツールを読み込むシェル、ファイル名を_gitに変更する
$ curl -L -o _git https://raw.github.com/git/git/master/contrib/completion/git-completion.zsh
# __git_ps1を提供するシェル
$ curl -L -O https://raw.github.com/git/git/master/contrib/completion/git-prompt.sh
```

下記を記載する。

```zsh
$ vi ~/.zshrc
```

```.zshrc
fpath=(~/.zsh $fpath)

if [ -f ${HOME}/.zsh/git-completion.bash ]; then
        zstyle ':completion:*:*:git:*' script ~/.zsh/git-completion.bash
fi
 
if [ -f ${HOME}/.zsh/git-prompt.sh ]; then
        source ${HOME}/.zsh/git-prompt.sh
fi
 
GIT_PS1_SHOWDIRTYSTATE=true
GIT_PS1_SHOWUNTRACKEDFILES=true
GIT_PS1_SHOWSTASHSTATE=true
GIT_PS1_SHOWUPSTREAM=auto
 
setopt PROMPT_SUBST ; PS1='[%n@%m %c$(__git_ps1 " (%s)")]\$ '
```

```zsh
$ source ~/.zshrc
```

## 確認

ブランチのディレクトリを表示する

```zsh
repository_name (issues/1_branch_name *%=)]$
```
【docker compose】ログをすべて消すコマンド

備忘録

## 動作確認環境
Windows11
WSL2(Ubuntu-22.04)
jq コマンドのインストールが必要(`sudo apt -y install jq`) ※適宜`apt update`

## コマンド
ワンライナー
```sh
sudo sh -c 'for id in $(docker compose ps -q); do log_path=$(docker inspect $id | jq -r ".[0].LogPath"); echo "" > "$log_path"; done'
```

整形したもの
```sh
sudo sh -c '
  for id in $(docker compose ps -q); do
    log_path=$(docker inspect $id | jq -r ".[0].LogPath")
    echo "" > "$log_path"
  done
'
```

これでスッキリ
UserAgentって対応してないって…ってコト！？


# 愚痴記事です

あしからず

画面周りを作ってる最中に起きたことでふと思い立った。

> あ、userAgentって廃止するんだっけなぁ。

なんだかんだで、文字列正規表現で判定してるプロジェクトも多いし、概要くらいは知ってたけどブラウザの対応状況とかも一律にならないから今までのやりかたしかやってなかった。

まぁもう2023年だしそろそろuserAgentで実装するよりuserAgentDataで実装した方がいいなーと思って当初のチェックはしてなかった。

:::note info
参考としてuserAgentの実装とuserAgentDataの実装方法

* userAgentの実装方法
```js
const isMatch = navigator.userAgent.match(/iPhone|Android.+Mobile/);
const isMobile = isMatch != null;
```

* userAgentDataの実装方法
```js
// 環境によりけりですが、こんな感じのデータが取れます。
{
  brands: [
    {
      brand: 'Not/A)Brand',
      version: '99'
    },
    {
      brand: 'Google Chrome',
      version: '115'
    },
    {
      brand: 'Chromium',
      version: '115'
    }
  ],
  mobile: false,
  platform: 'Windows',
}

const isMobile = navigator.userAgentData.mobile;
```
:::

楽！！！それって最高じゃん！！
ってウキウキで実装したところconsole上でエラーが発生。

どうやらiPhone（Chrome）でもuserAgentDataがnullで取得されておる。なんだこれ？

どうやらPCはスケジュール通りに移行作業が行われてるようですが、SPブラウザはそれとは別のタイムラインで計画されている？
（どなたか詳しい方がいれば教えてください。）

なので最終的にこんな実装に落ち着きました。

```js
const isMobile = () => {
  const { userAgent, userAgentData } = navigator;

  if (userAgentData == null) {
    return userAgent.match(/iPhone|Android.+Mobile/) != null;
  }
  return userAgentData.mobile;
}
```

余計面倒じゃん！！！！！！！！
喜びがない～・・・・

個人的な感想としては
新しくプロパティ追加したのであれば影響も僅かだろうし一気にやってほしいよなぁと思いながらも移行できない大人の事情があるのか。ブラウザの実装者も大変やなぁと現実を見て泣きそうになるあーみーでした。

中身がうっすい記事ですが、今回はここまでとなります。
コントロールしながら安全かつ高速にAIの取り組みを拡大

今日、デジタル環境はめまぐるしく変化しています。その中で、世界中の企業が、競争力を獲得するために、アナリティクスとAIの進化、最近は特に生成AI、に期待しています。AIの可能性は魅力にあふれており、より良いお客様体験、社員の生産性向上、イノベーションの加速等を実現できる可能性があります。しかし、AI導入のプロジェクトを成功するための道のりには課題が山積しています。IT部門は、アナリティクスとAIの取り組みの際、効果を出すことに苦労することが多々あるでしょう。

IT部門が直面する困難な課題の一例としては、スピード、コントロール、コスト最適化のバランスが挙げられます。IT部門は、組織が強固なガバナンス、セキュリティ、レジリエンス対策を維持し、コストを管理します。その一方で、チームが実験と変革ができる自律性を認めるという、微妙なバランスを取らなければなりません。データとAIの民主化は、さまざまなチームがデータドリブンな洞察を利用できるようにするためには、極めて重要です。データの完全性とコンプライアンスを損なうことなく実現するのは、難しいといえます。DataikuがIT部門を支援するための洞察と方法は、次の[インフォグラフィック](https://content.dataiku.com/it-leaders-infographic)をご覧ください。
![GM3330-DAC IT Persona Campaign Infographic (1).jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1196881/a4e337f4-ae40-4895-6e00-205538f263bd.jpeg)
# Dataikuがお手伝いできること
上のビジュアルにあるように、アナリティクスとAIを拡張する際に、IT部門が直面する主な問題に対処できる、包括的なソリューションをDataikuは提供しています。

### 1. スケーラブルで柔軟なアーキテクチャを低コストで構築
Dataikuは、企業の進化するニーズに対応できる、拡張性と柔軟性を備えたアーキテクチャを提供します。Dataikuを利用することで、IT部門は過剰なコストをかけることなく、AIプロジェクトの急成長を支える強固なプラットフォームを構築できます。このプラットフォームでは、パフォーマンスと効率性を損なうことなく、大容量データのアナリティクスを処理できます。


### 2. エンド・ツー・エンド環境で価値実現までの時間を短縮
Dataikuは、データ準備、モデルのトレーニングからデプロイ、モニタリングに至るまで、AI開発のライフサイクル全体を効率化します。エンドツーエンドの環境を提供することで、IT部門は、アナリティクスとAIプロジェクトを早く開発してデプロイできるようになり、パイロットから本番稼動までの時間を短縮できます。この高速化により、企業は最先端のAIソリューションで競争に勝ち残り、競争上の優位性を獲得できます。


### 3. 強固なガバナンス機能による監視でAIを安全に拡張
Dataikuは、IT部門がイノベーションを阻害することなく、AIプロジェクトの監視とガバナンスを維持できるよう支援します。堅牢なガバナンス機能により、組織はデータセキュリティ、コンプライアンス、倫理的な確認を実施できます。また、責任を持ってデータを扱え、潜在的なリスクから保護できることを保証します。Dataikuを利用することで、組織はコントロールとセキュリティに妥協することなく、自信を持ってAIの取り組みを拡大できます。

### 4. データとAIの民主化
Dataikuは、適切なデータセットを探せるようにし、アクセスできるようにすることで、データとAIの民主化を実現します。[データ製品](https://blog.dataiku.com/from-data-to-delight-unleashing-the-power-of-exceptional-data-products)（データセット、ダッシュボード、BIによる分析などのデータ製品、もしくはモデル、アプリケーションなどのAIデータ製品）は、目当てのデータを特定でき、可視化でき、アクセスできる必要があります。データ製品の目的は、求める部門が、データ、アナリティクス、AIソリューションを使用できることです。データ製品の共有は、データとAIの民主化戦略に組み込まれるべき重要なポイントでです。


# まとめ
多くの組織は、AIとアナリティクスの拡大に取り組んでいます。しかし、IT部門は成功を妨げるかもしれない重大な課題に直面しています。データとAIを民主化しながら、スピード、コントロール、コストの最適化のバランスを取るには、堅牢なソリューションが必要です。Dataikuは、IT部門がこれらのハードルを克服できるよう支援する、包括的なプラットフォームを提供します。さらに、コントロールとガバナンスを維持しながらAIを素早く拡張できるようにします。Dataikuは、ROIと時間短縮への効果が実証されています。Dataikuは、IT部門がアナリティクスとAIの取り組みの可能性を最大限に引き出すことを支援し、イノベーション、効率性、お客様満足の新時代を切り開くために必要な戦略的パートナーとなります。

# さらに先へ： Dataikuの経済的インパクト
フォレスター・コンサルティングがDataikuに協力を依頼し実施した本レポートでは、Dataikuの導入により、複合組織で3年間で1,289万ドル、ROIで423%の効果が得られたとしています。

<font color="#00B2A9">＞＞Dataiku導入でどのようにROIを上げたのか、詳しくは[**こちらのEbook**](https://pages.dataiku.com/dataiku-forrester-tei-report)をダウンロード</font>

原文：[Safely Scale AI at Speed Without Losing Control](https://blog.dataiku.com/safely-scale-ai-at-speed-without-losing-control)
Homebrew で dart-lang/homebrew-dart failed! が出たときの対処法

ひさしぶりにHomebrewを入れ直そうとして、

```zsh
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
```

や

```zsh
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
```

を試みると以下のエラーが出た。

```zsh
fatal: couldn't find remote ref refs/heads/master
Error: Fetching /usr/local/Homebrew/Library/Taps/dart-lang/homebrew-dart failed!
Installing from the API is now the default behaviour!
You can save space and time by running:
  brew untap homebrew/core
  brew untap homebrew/cask
Error: Some taps failed to update!
The following taps can not read their remote branches:
  dart-lang/dart
This is happening because the remote branch was renamed or deleted.
Reset taps to point to the correct remote branches by running `brew tap --repair`
Failed during: /usr/local/bin/brew update --force --quiet
```

以下のように躓いた部分を手動で入れてやり直すとエラーが出なくなった。

```zsh
cd /usr/local/Homebrew/Library/Taps/dart-lang/
rm -rf homebrew-dart
git clone git@github.com:dart-lang/homebrew-dart.git
```
High-Resolution Image Synthesis with Latent Diffusion Models

:::note info
インフォメーション
母語が日本語じゃないので、変な日本語で論文をまとめる予定です。
:::

# モチベーション
計算資源の節約：
1.Diffusion Models(DMs)を訓練するために、数百GPU日が必要。
生成するために、50kサンプル　大体5日間A100GPUが必要。
→ピクセル空間の代わりに、潜在空間を利用する。

2.条件付き（text or bounding boxes）生成：
By introducing cross-attention layers into the model architecture.
※実はDiffusion Modelを訓練するために膨大なデータが必要です。これについて、本論文が特に注目してないようです。
# Method
![スクリーンショット 2023-09-07 16.51.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1277696/16d01ce7-330d-861d-2041-23e58d66425c.png)
一見怖いかもしれないが、少しずつ見ていこう。
1.まずは画像xをEncoder εに入れ、潜在空間Z（Latent space）に転換する。

*ここのEncoder、DecoderがGANの思想で作ったものです（GANの生成部分）。
だたし、損失関数がトリックです。
考慮すべき項目として、元画像がちゃんと復元したのか（MSE（元の画像,生成したの画像）論文でLrecと書いている項）、
潜在空間がnormal distributionに近づいたのか（KL（Latent,normal distribution）論文でLregと書いている項）、
識別器の性能（logDψ（x）,-log[Dψ（D(ε（x）)）]論文でLadvと書いている項）からなる。*

2.次に、Latent Spaceで表現した画像xの行列を普通に訓練する（DM）。
3.Decoderに入れて、Pixel Spaceに戻す。
4.条件付きがcross attentionで実現した。注意すべきな部分をDMに伝達する。

英語大丈夫あれば、[ここの動画](https://www.youtube.com/watch?v=rC34475rEnw)をおすすめ！
Paiza練習問題「長テーブルのうなぎ屋」kotlinで解きました。

## はじめに
Paizaの練習問題のひとつに、「長テーブルのうなぎ屋」という設問があります。
Paizaの練習問題はスキルチェックとは違い解答を含む投稿が認められており、qiitaにも投稿している方が何名かおられます。
執筆日現在、Kotlinで解いた内容を投稿している方がおらず、Paiza公式の模範解答にKotlinでの解答が含まれていません。
そこで、この記事ではKotlinで「長テーブルのうなぎ屋」を解いた際の解答例のひとつとして私の解答を記載します。

なお、私はいわゆる競技プログラミングをしておらず、比較的通常業務に近いコードの書き方をしていることをご了承ください。

## 回答例
```kotlin
private var seats: MutableList<Boolean> = mutableListOf() //true:着席済 false:空席

fun main() {
    val (numberOfSeats, numberOfGroups) = inputPair()
    seats = MutableList(numberOfSeats) { false }
    (1..numberOfGroups).map {
        visit()
    }
    export()
}

private fun visit() {
    val (numberOfPeople, seatStartRaw) = inputPair()

    val rangeStart = seatStartRaw - 1 //リストの添字は0から始まるため1ひく
    val rangeEnd = rangeStart + numberOfPeople - 1 //リストの添字は0から始まるため1ひく

    val isBooked = getIsRangeBooked(rangeStart, rangeEnd)
    if (!isBooked) {
        bookRange(rangeStart, rangeEnd)
    }
}

private fun getIsRangeBooked(rangeStart: Int, rangeEnd: Int): Boolean {
    return (rangeStart..rangeEnd).any { i -> getIsSeatBooked(i) }
}

private fun getIsSeatBooked(seat: Int): Boolean {
    if (seat >= seats.count()) {
        return getIsSeatBooked(seat - seats.count())
    }
    return seats[seat]

}

private fun bookRange(seatStart: Int, seatEnd: Int) {
    (seatStart..(seatEnd)).map { i -> bookSeat(i) }
}

private fun bookSeat(seat: Int) {
    if (seat >= seats.count()) {
        bookSeat(seat - seats.count())
        return
    }
    seats[seat] = true
}

private fun export() {
    println(seats.count { s -> s })
}

private fun inputPair(): Pair<Int, Int> {
    val input = readln().split("\\s".toRegex())
    val firstVal = input[0].toInt()
    val secondVal = input[1].toInt()
    return Pair(firstVal, secondVal)
}
```

感想・ご指摘などあれば後学のためにお寄せいただけますと幸いです。
これからのデータ主権の話をしよう　～データ主権とは一体何なのか～

# はじめに
「データ主権」という言葉、一度は耳にしたことがある方もいるのではないでしょうか。

初めて聞いたという方も、言葉を見れば何となくの意味は想像できるかも知れません。
ただ、何となくは想像できるのですが、じゃあ具体的にどんなことなのかと言われると説明が難しい言葉だなと思います。

本エントリーでは出来るだけわかりやすく「データ主権」についてを説明しながら
「データ主権」に関して色々考えを巡らせてみようと思います。

# データ主権とは
単純に「主権」という言葉で用いられる場合、それは国を統治する権力すなわち、以下を意味するそうです。

```
そもそも「主権」とは、「国を統治する権力」のことです。「国を統治する権力」と
いうのは、社会秩序を維持するために法律を定め（立法権）、定められた法律を執行し
（行政権）、法に基づいて争いごとを解決する（司法権）といった権力のことです。
```
(引用元) https://www.soumu.go.jp/main_content/000689710.pdf

これを元に「データ主権」を考えると自身が所有するデータを統治する権力を有すること、となりそうです。
『データを統治する権力』というのはどういうことなのかちょっとわかりにくいですね。

私は自分のデータを自分自身で管理し、データに対する操作なども制御できる権利状態、くらいの意味で捉えています。
これはあくまで個人で所有するデータの話で、国としてデータ主権を～と言った場合は、各国の法を踏まえながら自国のデータに対する権力を主張する必要があります。

でもよく考えてみてください。
「このデータは僕が主権をもっているんだよ」
と言うのは簡単ですが、それをどうやって証明するのでしょうか。

# データ主権の確保の難しさ
ここにネットワークに繋がっていないパソコンがあったとします。
そのパソコン上で作成しローカルのディスクに保存した文書データは自分で管理することができる状態にある事は明らかです。

しかしインターネットが普及した今の時代では、パソコンは当然のようにインターネットを経由して様々なモノと繋がっています。

パソコンで保存したデータが意識しないうちにクラウドストレージに保存されていた、という経験が誰しもあるのではないでしょうか。でもそのクラウドストレージの実体がどこにあるのかを気にする方は少ないと思います。

もしかすると知らない間に海外のサーバにあなたのデータが保存されているかも知れません。
もしくは、使用しているクラウドストレージサービスから別のクラウドストレージサービスにコピーされているかも知れません。

自分のデータが保存されていて使いたいときに使える、という状態は当然維持されると思いますが、
そのデータ、本当に自分だけが管理している状態と言えるのでしょうか。クラウドストレージサービスの管理者があなたのデータに対してアクセスし、そのデータを自分のモノだと主張したらあなたの権利はどうなるのでしょうか。

ここに今の時代におけるデータ主権の確保の難しさがあります。
そして昨今、データ主権について議論され始めた理由もここにあると考えています。

# データ主権を確保するために
データ主権を確保するという命題に対して色々なソリューション検討や取り組み行われています。

- ソブリンクラウド
クラウドサービス側でデータ主権を担保することを保証する考え方です。
このクラウドを利用することにより、ユーザは必然的にデータ主権を確保できることになります。

```
情報セキュリティーや法令順守（コンプライアンス）の担保に加え、
単一の国・地域内でのみ提供するなどして、他の国・地域の法令の影響を排除しデータ主権を担保した
クラウドサービスを指す。「主権クラウド」や「データ主権クラウド」などと訳される。
```
(引用元) https://active.nikkeibp.co.jp/atcl/act/19/00146/122200103/

- 「自己主権型アイデンティティ(SSI)」や「分散型アイデンティティ(DID)」
現在主流となっている中央でIDを管理するようなサービスを介さずとも、自分自身のIDの保管・制御を可能にする仕組みが「自己主権型アイデンティティ(SSI)」や「分散型アイデンティティ(DID)」です。ブロックチェーンなどの暗号応用技術が用いて実装されています。
この仕組みを使用することで、データ主権を事業者任せにすることなく、それぞれがデータに対する権利を主張できるようになることを想定しています。

https://www.nri.com/-/media/Corporate/jp/Files/PDF/service/ips/technology_1.pdf

- GAIA-X
GAIA-Xは、ドイツの連邦経済産業省が2019年10月に立ち上げた、欧州のクラウド／データ基盤構築プロジェクトで
セキュリティとデータ主権を保護しつつ、データ流通を支援するためのインフラ構想です。

```
GAIA-Xはプラットフォーマ―に対するアンチテーゼとして構想された。
欧州は基本的に、プラットフォーマ―がデータを独占するのは独占禁止法違反に相当し、
データ主権はデータの発生源にあるというGDPR(General Data Protection Regulation：一般データ保護規則)の考え方を踏襲している。
このため、GAIA-XはGAFAのようにデータとコンピュータ資源、アプリケーションを統合的に提供するのではなく、
3つの機能を一旦分解し、データについてはデータの発生源がデータ主権を保有しつつ保持、自律分散の連邦型の構造により企業間でデータ連携を図る仕組みである。
```
(引用元) https://www.nri.com/jp/knowledge/blog/lst/2022/iis/fujino/0727_1

ちなみにGAIA-Xの動向を受け日本でもデータ連携基盤の整備に向けた動きが活発化しています。

https://monoist.itmedia.co.jp/mn/articles/2307/11/news021.html

https://www.cas.go.jp/jp/seisaku/digital_denen/dai4/siryou8.pdf

# まとめ
執筆時点(2023年9月)では、データ主権を確保するために色々な取り組みが行われ試行錯誤されている状況だと私は認識しています。
また、どのような状態であればデータ主権を確保されていると言えるのかについてもそれぞれの解釈や求める主権レベル次第なのではと考えています。

データ主権が完全に確保された先には、こうやって書いている記事にも主権が伴い、引用する場合なども主権者の承認を得る必要があるなど厳格にデータの権利が管理された世の中になるかも知れません。

なのでデータ主権は生活が便利になるような類のものではなく、個人や法人が発生源となるデータについて、本来守られるべき権利を確実に守ることができるものという認識の方が正しいと私は理解しています。
Modeler FlowでDB関数を使う

Watson Studio on CP4DaaSのModeler FlowでDB関数をつかってみます。

* テスト環境
    * CP4DaaS (2023/9/8)
    * Db2 Warehoues on Cloud
    * Dallas


以下のように、「フィールド作成ノード」で、Db2の関数「SYSIBM.REGEXP_INSTR(地域,'東')」を入力して実行しますと、正しく結果が返りました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/a41bc802-b7a3-b03f-0cb1-e18f20fcb4b0.png)

実行履歴を確認すると以下のようにSQLプッシュバックされていることがわかります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/07843e1f-5865-eb4d-25e8-f7242653e22f.png)

ただし、関数のリストにはでてきません。また、「検証」ボタンをクリックしても、「AEQMJ0329E:関数'SYSIBM.REGEXP_INSTR'が定義されていません」というエラーになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/4f1170eb-0045-c6de-9fc6-788cb3b60aef.png)

なお、UDFも同様に動きました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/df975115-f86b-f73e-c243-1c522fd9f575.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/816e8179-46dc-a126-8602-2ba03f6b4099.png)

使ったUDFは以下です。

```sql:UDF
CREATE FUNCTION UDF_TAN (X DOUBLE)
  RETURNS DOUBLE
  LANGUAGE SQL
  CONTAINS SQL
  NO EXTERNAL ACTION
  DETERMINISTIC
  RETURN SIN(X)/COS(X)
```


#### 参考:データベース関数
https://dataplatform.cloud.ibm.com/docs/content/wsd/nodes/clem_reference/expressionbuild_database_functions.html?locale=ja&audience=wdp&context=cpdaas

データベース関数を含む SPSS Modeler デスクトップ・ストリーム・ファイル (.str) を実行できます。 ただし、データベース関数は、式ビルダーのユーザー・インターフェースでは使用できません。また、編集することもできません。

#### 参考:REGEXP_INSTR スカラー関数
https://www.ibm.com/docs/ja/db2/11.5?topic=functions-regexp-instr

#### 参考:CREATE FUNCTION (SQL スカラー、表、行) ステートメント
https://www.ibm.com/docs/ja/db2/11.5?topic=statements-create-function-sql-scalar-table-row
デバイスIDからシリアルポート（COM）番号取得

# 概要
通常シリアルポート番号はPCにデバイスが接続された時点で自動で割り付けされます。
シリアル通信を行う場合"COM**"とポート番号を指定しますが、PCが変更になった
場合には変わってしまいます。
ポート番号一覧を表示して選択しても良いのですが、Bluetoothシリアル通信では
送信用、受信用で同一のデバイス名で表示されるため違いが分かりません。
![2023-09-08 085153.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2611426/f5c75f13-a67f-89f9-1378-ad7d8b67034c.png)


色々調べた結果、USBデバイスのユニークIDが取得できるとのことで、このIDとCOMポート
番号を紐づけすることができました。

# デバイスのユニークIDについて
　デバイスマネージャーを起動し、'詳細タブ'から'デバイス インスタンス パス'を選択すると
　表示されます。このIDをあらかじめ調べておく必要があります。
![2023-09-08 073700.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2611426/ad32aaea-fd20-9bfb-3d66-7cd466f910c7.png)

# 作成したプログラムについて
プログラムを起動するとForm1が表示されます。
テキストボックスにデバイスマネージャーで調べておいたデバイスインスタンスパスを入力後、
COM番号取得ボタンを押すと隣のテキストボックスに表示されます。

![2023-09-08 083926.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2611426/6eecc2c1-992f-8f43-9ec4-25abfe0a00b9.png)


また、別のPCに接続してもCOM番号を取得できました。

![2023-09-08 090152.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2611426/ead6ee7a-2abd-ed16-a1ce-88fd2bb17f02.png)

# 環境
　VisualStudio C# .NET6.0
　※NuGetで「System.Management」をインストール。
![2023-09-08 073403.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2611426/c6ad034c-8770-cc4b-41f3-da58432f8cf2.png)



# コード
``` cs

using static System.Windows.Forms.VisualStyles.VisualStyleElement.StartPanel;
using System.Management;

namespace _comPort_get
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }

        private void button1_Click(object sender, EventArgs e)
        {
            // インスタンス作成
            ManagementClass device = new ManagementClass("Win32_PnPEntity");

            // 接続されたデバイスを取得
            foreach (ManagementObject port in device.GetInstances())
            {
                // デバイスインスタンスパス取得
                string dev_uqid = (string)port.GetPropertyValue("PNPDeviceID");

                //　デバイス名取得
                string name = (string)port.GetPropertyValue("Name");

                // デバイスインスタンスパスに一致するか確認
                if (dev_uqid.Contains(textBox1.Text))
                {
                    // "(COM" に一致するインデックス取得
                    int index = name.IndexOf("(COM");

                    // com番号取得
                    string comPort = name.Substring(index + 1).Replace(")", "");

                    // 表示
                    textBox2.Text = comPort;

                }

            }
        }
    }
}
```

# 参考サイト
https://www.84kure.com/blog/2015/02/18/c-%E3%82%B7%E3%83%AA%E3%82%A2%E3%83%AB%E3%83%9D%E3%83%BC%E3%83%88%E3%81%AE%E5%90%8D%E5%89%8D%E3%81%A8%E3%83%87%E3%83%90%E3%82%A4%E3%82%B9%E5%90%8D%E3%82%92%E5%88%97%E6%8C%99%E3%81%99%E3%82%8B/

https://guminote.hatenablog.jp/entry/2015/08/13/193216

https://www.runexy-dlp.com/devicelock/column/devicelockcolumu08.html
MinikubeをDockerで立てたNginxコンテナで公開する

# はじめに

長い間、勉強用に立てたKubernetes環境内のServiceをどうやって公開しようか悩んでいました。
今回、ルートテーブルを学んでNginxコンテナを立ててMinikube内のPODにアクセスできるようにしたので記事を書くことにしました。

# 構築した構成

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1474054/58f987f7-f2c0-0ab8-cc7c-f909e839eb2e.png)

Dockerを使ってMinikubeを動かしています。
Minikube外部にNginxコンテナを立てています。このNginxをロードバランサーに見立てて外部からアクセスできるようにしています。
以下に作成したTerraformファイルを公開しています。良ければ見てみてください。
https://github.com/kohei39san/mystudy-handson/tree/main/k8s-manifests/make-jmeter-scenario
（上記のファイルではJMeterを使うためのものなのでその他インストールコマンドを実行しています）

※参考ですが、Minikubeを公開する方法としては他に以下のものがあります。

* ノードポートでの公開
Serviceにてノードポートを指定します。ノードに対して、30000~32767内のポートのいずれかで公開できます。しかし、ポート番号を覚えておく必要があります。また、Minikubeをコンテナで動かしている場合、コンテナのポートの公開になるのでEC2外からアクセスするには別途用意が必要になります。
* Minikubeのtunnel機能での公開
EC2から内部のk8sネットワークにアクセスできるようになります。
参考：https://qiita.com/inajob/items/4025a1d1aa83721c453d

# NginxコンテナからServiceへの通信方法

Minikubeを起動すると、「minikube」というDockerネットワークが出来上がります。そこにNginxコンテナを動かします。

そうすると、Minikubeの本体のコンテナ（「minikube」というコンテナ）とNginxコンテナが通信可能になります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1474054/dda4ef06-9571-f69e-fa77-47088b77428b.png)

Minikubeコンテナでは、内部にKubernetesのService用のネットワークを持っており、Minikubeコンテナ内からServiceにアクセスできるようになっています。

そこで、NginxコンテナからMinikubeコンテナを経由したPODへのルーティングを設定します。これはMinikubeのトンネルと同じことをやっています。以下のようにNginxコンテナにルートを追加します。

```bash
route add -net 10.96.0.0 netmask 255.240.0.0 gw 192.168.49.2 eth0
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1474054/c0cc5c3a-9062-1763-6fdd-aead55698d98.png)

ここで、k8sネットワークのDNSの機能を持っているのはCoreDNS（kube-dnsサービス）です。
NginxコンテナのDNSサーバーにCoreDNSを指定することで、k8s内の名前解決ができるようになります。（Nginxコンテナから、service.namespace.svc.cluster.localの形式のレコードにアクセスできます）

※参考
https://qiita.com/inajob/items/4025a1d1aa83721c453d

# Ingressを使うと転送先のServiceを変えられます

Nginxコンテナにてパススルーすると、k8s内で通信経路を決めやすいかもしれません。
例として、NginxのIngress Controllerを使うとk8s内部にNginx PODが立ち上がり、Ingressで通信経路を制御できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1474054/e083aaef-0af3-8f62-07c6-93c6c54197ec.png)

※参考
https://kubernetes.io/ja/docs/concepts/services-networking/ingress/

# NginxコンテナはEC2のポートにバインドすることで公開できます

EC2外部から、Nginxコンテナにアクセスする方法の一つとして、ポートのバインドがあります。
https://docs.docker.jp/engine/userguide/networking/default_network/binding.html

例えば、Nginxコンテナの80,443ポートをバインドすれば、EC2の80,443ポートからk8s内部にアクセスできるようになります。
公開するポート番号を比較的自由に決められて、通信経路制御もk8s内部で決められるのが利点だと思っています。

# おわりに

改めてネットワークの勉強になりました。奥が深いですね。
これからも勉強します。
weak selfについて

強参照と弱参照は意識して使い分けてる？と言われ、ドキッとした。

2回目言われると心臓が止まってしまうので理解が曖昧な今
深夜テンションで雑にまとめる！！！

# weak selfがないと何が起こるのか
「循環参照してメモリリークする」です。　なんのこっちゃ？

## そのまえにARCとは
swiftではARC(Auto Reference Counting)という仕組みを用いて、自動でメモリの管理を行なってくれています。そのお陰で、私でも脳死でコードを書くことが出来たんですね。

このARCはランタイム時に自動で参照をカウントする仕組みで、
例えば、

```swift
class Hoge {
    init() {
        print("init")
    }
    deinit {
        print("deinit")
    }
}
```
こういうクラスがあったとしましょう。

```swift
var ref1: Hoge? = Hoge()
var ref2: Hoge? = ref1
var ref3: Hoge? = ref1
```

この時、Hoge()は
- ref1
- ref2
- ref3
の3つから参照されています。(参照カウンター = 3)

Hogeが解放される時にdeinitが呼ばれます。
deinitを呼び出すにはどうすれば良いでしょうか。

キルするには参照している箇所をなくせば良いですね。

![スクリーンショット 2023-09-07 0.03.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517291/ca3dd220-9ee0-521c-efc5-aea325a609f5.png)

ref1にnilを入れてみてもdeinitは呼ばれていません。

![スクリーンショット 2023-09-07 0.03.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517291/d3c1f35e-52f7-eee2-f408-41158e2ed1aa.png)

ref1とref2にnilを入れてみてもdeinitは呼ばれていません。

![スクリーンショット 2023-09-07 0.04.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517291/1c4077c7-3463-e7c7-16e9-e2371f9d6243.png)

ref1,ref2,ref3にnilを入れて初めて参照されている箇所がなくなり、Hogeをキルすることが出来ました。


これがざっくりとした参照カウントという概念
(説明が面倒なので、他のわかりやすい記事を見てね)


これはインターンのメンターさんに教えていただいた

```swift
class HogeViewController: UIViewController {
    let hogeView: HogeView = .init()

    var counter: Int = 0

    // 強参照
    hogeView.state = { _ in
        self.counter += 1
    }
}

class HogeView: UIView {
    var state: (() -> Void)?

    // ボタンが押された時、ここが呼ばれるとする
    func button() {
        state?()
    }
}
```

hogeViewのbuttonが呼ばれた時、

```swift
hogeView.state = { _ in
    self.counter += 1
}
```

が動く。
この時のselfはHomeViewControllerのことですな。

hogeView.state内のHomeViewControllerのcounterを強参照しています。(参照カウンターが増える)

この時、HomeViewControllerが解放されようとしますが、参照カウンター(HomeViewControllerが無くなると困るよ〜って言ってる箇所)が0にならずメモリ解放ができません。これによりメモリリーク(使ってないのにメモリが確保されている状態)に陥る。


# weak selfを使うとどうなるのか
参照カウンターが増えません。
つまり、HomeViewControllerと運命を共にするさだめの、参照箇所は参照カウンターが増える必要はないですね。


```swift
class HogeViewController: UIViewController {
    let hogeView: HogeView = .init()

    var counter: Int = 0

    // 弱参照
    hogeView.state = { [weak self] in
        self?.counter += 1
    }
}
```

ここで、IBOutlet について、なぜweak selfがついているのか疑問に思いました。

```swift
@IBOutlet weak var myView: UIView!
```

UIKitを使ってるとこんなコードをよく見ますね

下記の記事を参考にしてください 
 https://qiita.com/chocovayashi/items/a96adc1356b7c45524b7

参考記事の結論がわかりやすかったので引用
> IBOutletのViewをremoveする予定がなければ、適当でOK
> IBOutletのViewをremoveし、その後は使わなければ、`@IBOutlet weak var hogehoge: HogeView!`
> IBOutletのViewをremoveし、その後また使うなら`@IBOutlet var hogehoge: HogeView!`
> なにも予想できない場合は、`@IBOutlet weak var hogehoge: HogeView?`

参考
https://zenn.dev/mhackit/articles/a0b1c6e780c3c6aabe45
https://qiita.com/reo0612/items/b0d1ee00ebf3a0e7c857
Vueでコンポーネントに渡したPropsが正しく読み込まれずエラーになる

# はじめに

Vueの挙動がうまく行かないときに思ってもいなかったところ(なんとなくで意識せずにやっていたこと)で躓いたのでまとめていきます

# 問題

以下のコンポーネントを作成しました

```vue:component.vue
<template>
  <div>
    {{message}}
  </div>
</template>

<script lang="ts">
import Vue from 'vue'
import { Prop } from 'vue-property-decorator'

export default class SampleComponent extends Vue {
  @Prop({ required: true, default: 'no message'})
  readonly message: string
}
</script>
```

そして別の場所からコンポーネントを利用します

```vue
<SmapleComponent :message="Hello"/>
```

しかし実際の画面をみるとメッセージは渡せていませんでした

# 解決方法

`@Component({})`を書いていないことが原因でした
これがないとPropsを読み取れないようです。外部のコンポーネントを利用するときに使うものだと思っていました

コンポーネントとしては描画されるのでわかりづらかったです

```vue:component.vue
<template>
  <div>
    {{message}}
  </div>
</template>

<script lang="ts">
import Vue from 'vue'
import { Prop } from 'vue-property-decorator'
import { Component} from 'vue-property-decorator'

@Component({})
export default class SampleComponent extends Vue {
  @Prop({ required: true, default: 'no message'})
  readonly message: string
}
</script>
```

# おわりに

あまりVueをしっかり書いたことがなかったのでわからないなりに手探りで実装している感があり不安定になりがちでした
今回は新たな学びがありました。
EclipseでgutterにGitの差分を表示する方法

Eclipseでは差分のある行にgutter（行番号があるエリア） が色付きで表示されるようになっています。
![Eclipseのgutterの表示](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2585392/46f1a328-b527-4907-8df9-76d50904ad58.png)
この差分はデフォルトでは**保存状態との差分**が表示されるようになっています。
つまり、編集中は差分が表示されますが、ファイルを保存した時点で差分の表示が消えてしまいます。

この記事では、**保存状態との差分**の代わりに**Gitの差分**を表示する方法を紹介します。

## 手順：gutterにGitの差分を表示する方法

1. Eclipseのメニューから `Window` → `Preferences` を開きます。
    ![Preferencesを開く](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2585392/8027550f-f397-4a51-91bd-596d855597db.png)
1. `Preferences` ウィンドウの左上の検索欄から `Quick Diff` と検索します。
    出てきた `Quick Diff` を開き、 `Use this reference source` で `A Git Revision`を選択します。
    ![A Git Revisionをせんｔ](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2585392/2f0d4699-1fcd-4a97-8ada-906b6b3ad3e8.png)
1. `Apply and Close` ボタンを押して設定を保存します。
1. 設定を反映させるためにEclipseを再起動します。
1. これでgutterにGitの差分が表示されるようになります。
    試しに行を追加してファイルを保存しても、gutterの差分が消えずに表示されたままになることを確認します。

:::note warn
EclipseでプロジェクトがGitリポジトリとして認識されていない場合は、gutterにGitの差分が表示されません。
その場合は、以下の手順でGitリポジトリとして開きます。
:::

1. プロジェクトを右クリックして `Team` → `Share Project...` を開きます。
    ![image_04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2585392/a503ca8e-3e64-49d0-b841-47a6d814b687.png)
1. 正しいリポジトリが選択されていることを確認して `Finish` ボタンを押します。
    ![image_05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2585392/de5eef06-5984-404d-aa19-7c085e748f52.png)
1. これでgutterにGitの差分が表示されるようになります。

## 【おまけ】手順：gutterに追加の情報を表示する方法

さらに設定を行うことで以下のようにgutterに追加の情報（hashやauthor）を表示できるようになります。
![gutterにhashとauthorを表示](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2585392/064de419-06d8-4304-879e-abf3423666a0.png)
以下、その設定方法を紹介します。

1. gutterを右クリックして `Show Revision Information` を選択します。
    ![how Revision Informationを選択](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2585392/60e1c8e0-eab8-4ff8-9d65-c2e7130ed251.png)
1. このじてんで差分のある行だけでなく、すべての行に対してGitの情報が色付きで表示されるようになります。
    ![すべての行に対してGitの情報が色付きで表示](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2585392/e946c5e9-71f5-4fc8-98c8-327edb5cb780.png)
1. さらにgutterを右クリックして `Revision` を選択すると、表示される情報を変更できます。
    ![表示される情報を変更する](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2585392/ee392737-ddbb-491c-8ed4-97c31714779a.png)
1. 例えば、`Show Author`を選択すると、gutterにauthorが表示されるようになります。
    ![gutterにauthorを表示](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2585392/96cb137e-c25e-47df-bac9-b4b5405238b8.png)
1. 同様に `Show Id` を選択するとgutterにhashが表示されるようになります。
1. 表示をもとに戻したい場合は `Hide Revision Information` を選択します。
Vue.jsのライフサイクルフックについて

# なぜこの記事を書こうと思ったか
・今の現場の開発観点の一つに、ライフサイクルの観点を意識して実装することが挙げられたため。
・以前、自分自身もライフサイクル関連でハマった事があったので改めて理解を深めるため。

# この記事を読んでわかること
onMounted、onUpdated、およびonUnmountedが呼ばれるタイミング
 
# そもそもライフサイクルとは？
インスタンスの生成からコンポーネントが破棄されるまでの間に実行される関数のこと。
例えば、コンポーネントの作成、更新、破棄などのタイミングで実行される関数があります。

公式ドキュメントにて、より詳しく説明してあります。
https://ja.vuejs.org/guide/essentials/lifecycle.html#lifecycle-diagram

今回は、onMounted、onUpdated、およびonUnmountedに絞って解説します。
# 前提
　・Vue.js v3^ (CompositionAPI)
# 結論
**・onMounted**
 　コンポーネントがマウントされた後に呼び出されます。
**・onUpdated**
　そのコンポーネントがもつリアクティブなデータが更新され、
　コンポーネントのDOM更新後に呼び出されます。
※データの値が変わらない限り、onUpdatedは実行されないので注意！
**・onUnmounted**
　コンポーネントがアンマウントされた後に呼び出されます。
# console.log()で確かめる
それでは先ほど説明したonMounted,onUpdated, onUnmountedがいつ呼ばれるのかについて
検証していきます。
今回は、以下のような画面を作成しました。
赤枠の部分が子コンポーネントになっており、親コンポーネントのボタンで表示、非表示を切り替えることができます。
![](https://storage.googleapis.com/zenn-user-upload/27bd0577829a-20230624.png)
## サンプルコード
**・親コンポーネント**
```vue:Index.vue
<script setup>
import ChildComponent from '@/Components/ChildComponent.vue';
import { ref } from 'vue';

const isShow = ref(false)
// 子コンポーネントの表示切り替え
const toggle = () => {
    isShow.value = !isShow.value;
}
</script>
<template>
　　　　　　　　<button type="button" @click="toggle">表示/非表示</button>
    <div v-if="isShow">
        <ChildComponent />
    </div>
</template>
```
**・子コンポーネント**
```vue:ChildComponent.vue
<script setup>
import { ref, onMounted, onUpdated, onUnmounted } from 'vue';
const text = ref('')

onMounted(() => {
    console.log('onMounted')
})

onUpdated(() => {
    console.log('onUpdated: ' + text.value)
})

onUnmounted(() => {
    console.log('onUnmounted')
})
</script>
<template>
    <label for="default-input">入力してください</label>
    <input type="text" id="default-input" v-model="text">
</template>
```
子コンポーネント内にonMounted、onUpdated、onUnmounted　を登録し、どのタイミングで実行されるのか、コンソールを見て確かめたいと思います。
## 初期表示
コンソールには何も出力されていません。
![](https://storage.googleapis.com/zenn-user-upload/3618f9a10a57-20230624.png)
## onMounted発動！
ボタンを押すと、子コンポーネントが表示され、onMountedが実行されます。
ボタンを切り替えたことにより子コンポーネントのインスタンスが生成され、DOMツリーがレンダリングされたためです。
![](https://storage.googleapis.com/zenn-user-upload/f7cd46276460-20230624.png)

## onUpdated発動！
文字を入力すると、onUpdatedが実行されます。
子コンポーネントが持っているデータ「text」が更新され、DOMツリーに反映されたためです。
![](https://storage.googleapis.com/zenn-user-upload/45ba20093e07-20230624.png)

## onUnmounted発動！
再びボタンを押して子コンポーネントを非表示にすると、onUnmountedが実行されます。
子コンポーネントのインスタンスが削除されたためです。
![](https://storage.googleapis.com/zenn-user-upload/7b753606892e-20230624.png)

# 補足

v-ifの部分をv-showにしたらどうなるでしょうか。
```vue:Index.vue
<template>
　　　　　　　　<button type="button" @click="toggle">表示/非表示</button>
    <div v-show="isShow">
        <ChildComponent />
    </div>
</template>
```
結論から言うと、以下の挙動に変わります。
onMounted: 初期表示の段階で実行される
onUnmounted: 非表示にしても実行されない
理由は、v-showはcssの切り替えによって表示、非表示を切り替えているためです。
よって、画面がレンダリングされるタイミングで子コンポーネントのインスタンスが生成されます。
また、非表示にするボタンを押しても子コンポーネントのインスタンスが削除されることはありません。

■参考URL
https://ja.vuejs.org/api/composition-api-lifecycle.html