OmniAICreator/Qiita-1.07M huggingface dataset:
テスト駆動開発（TDD）について

## はじめに
ここ最近案件でテストを書くことが非常に増えたため、テスト駆動開発というワードを知った。
テストを書くメリットが想像以上に多いことを知り、個人開発や小さいサービスにおいてもテストの必要性を今まで以上に感じたので、
今回テスト駆動開発についての説明とメリットについてまとめていく。

## テスト駆動開発とは
テスト駆動開発（TDD）とは、ソフトウェア開発の手法の一つであり、テストを中心に開発を進めることによって品質の高いコードを生み出すことを目的とする。
TDDの項目ごとに説明していく。

### 1. TDDの流れ
TDDは、以下のような流れで開発を進めていく。

①テストを書く
②テストを実行し、失敗することを確認する
③コードを書き、テストを通過することを確認する
④リファクタリングを行う

この流れを「赤→緑→リファクタリング」と呼ばれ、繰り返し行うことで、コードの品質を高めていく。

### 2. TDDのメリット
TDDを行うことによって、以下のようなメリットがある。

#### バグを早期に発見しやすくなる
TDDでは、最初にテストを書き、そのテストを通過するようなコードを作成することが求められる。
このため、テストを書くことでコードの欠陥やエラーが早期に発見され、修正することができる。

#### コードの品質が向上する
TDDでは、コードを書く前にテストを書くため、テストケースに基づいたコードを作成することになる。
このため、要件を満たし、かつテストの結果が正しいことを保証するコードを作成することができる。
また、テストを通過するために、冗長なコードや重複したコードを排除することができ、コードの可読性や保守性を高めることが可能。

#### テストがあることでリファクタリングがしやすくなる
TDDでは、テストを中心にコードを書くことが求められるため、コードの変更によってテストが通らなくなることがある。
しかし、テストがあることで、リファクタリングを行った後にテストを再度実行し、コードが正常に動作していることを確認することができる。
このため、テストがあることでリファクタリングを行いやすくなる。

#### コードが読みやすくなる
TDDでは、コードの品質を高めることが求められるため、コードの可読性が向上する。
また、小さな単位でテストを行うため、コードが分割され、モジュール化されるため、コードの理解や保守がしやすくなる。

### 3. テストの書き方
TDDでテストを書くときは、以下のような点に注意が必要。

#### テストは小さく単純に
TDDでは、小さな単位でテストを行うことが求められる。
これは、コードの機能を小さな単位に分割し、それぞれの単位に対してテストを行うことで、コードの品質を高める。
また、小さな単位でテストを行うことで、バグの発見や修正が容易になる。したがって、テストは小さく、単純に書くことが重要。

#### テストは自動化する
TDDでは、テストを自動化することが求められる。
テストを自動化することで、テストを繰り返し行うことができ、手作業によるミスを防ぐことができる。
また、テストを自動化することで、テストの実行時間を短縮し、開発者が迅速にフィードバックを受けることができる。

#### テストは正常系と異常系を網羅する
TDDでは、テストを正常系と異常系の両方を網羅するように作成することが求められる。
正常系のテストは、コードが期待どおりに動作することを確認するために必要。
異常系のテストは、エラーや例外が発生した場合に適切に処理されることを確認するために必要。

#### テストは意図的に失敗するように作成する
TDDでは、最初にテストを書く際に、テストが必ず失敗するように作成することが求められる。
このようにして、テストが正しく動作していることを確認することができる。
そして、その後、テストが通るようにコードを修正することで、要件に基づいた正しいコードを作成することができる。

#### テストは繰り返し実行する
TDDでは、テストを繰り返し実行することが求められる。
これにより、コードの変更によってテストが通らなくなった場合に、すぐに気づくことができる。
また、テストを繰り返し実行することで、コードの品質を保つことができる。

#### テストは可読性が高く、意図が明確である必要がある
TDDでは、テストコードは可読性が高く、意図が明確であることが求められる。
テストコードが読みにくかったり、意図が分かりにくい場合、コードの品質が低下する恐れがある。
したがって、テストコードを書く際には、意図が明確で、テスト結果が分かりやすくなるような記述方法を選ぶことが重要。

#### テストはリファクタリングの際にも実行する
TDDでは、コードの品質を高めるために、リファクタリングを行うことが求められる。
リファクタリングを行う際には、テストを実行し、変更したコードが期待どおりに動作することを確認する必要がある。
また、リファクタリングの際に、テストコードも同時にリファクタリングすることが推奨されている。

### 4. リファクタリング
TDDでは、コードを書いた後に必ずリファクタリングを行う。
リファクタリングとは、既存のコードを改善することで、可読性や保守性を高めることを目的とする。

リファクタリングを行う際には、以下のような点に注意する必要がある。

①テストを通過することを確認する
②変更箇所が明確になるようにする
③コードが正しく動作するようにする

### 5. TDDの実践方法
TDDを実践する際には、以下のような方法がある。

①小さなテストから始める
②テストが失敗した場合は、テストケースを修正する
③コードを書く前にテストを書く
④テストを自動実行する仕組みを用意する

## まとめ
以上が、TDDの項目ごととなる。
TDDは、テストを中心に開発を進めることによって品質の高いコードを生み出すことを目的としているため、開発者にとって非常に有益な手法。
TDDを実践することで、バグを早期に発見しやすくなるだけでなく、コードの品質や保守性が向上し、開発プロセス全体を改善することができる。

以上

## 参考
https://www.qbook.jp/column/20181009_713.html
https://service.shiftinc.jp/column/4654/
https://blog.aiqveone.co.jp/tdd/
こういうテストはNG！ソースコードを変更させないテスト

はいさい！オースティンやいびーん！

# 概要

単体テストで、ソースコードの変更を許さないようなテストを書かないように気をつけましょう。

# ソースコードの変更を許さないテストとはどのようなテストか

この前、筆者はGoogleのTesting Blogで以下の記事を読みましたが、とても共感するところがありました。

https://testing.googleblog.com/2015/01/testing-on-toilet-change-detector-tests.html

この記事の趣旨は、ソースコードの変更に合わせて**機械的に修正しなければならないようなテストがあると、開発効率が下がる**という話です。

例えば以下のようなソースコードがあるとします。

```typescript
class AuthHandler {
  private loggedIn = false;

  async login(password: string) {
    const isAlreadyLoggedIn =　this.loggedIn || this.isAlreadyLoggedIn();
    if (isAlreadyLoggedIn) return;
    // 非同期処理
    this.loggedIn = true
  }

  isAlreadyLoggedIn() {
     if (someGlobalVariable) throw Error(); // なんでエラーが起きるかもわからず...
     return this.loggedIn
  }
}
```

ありえないくらい変なソースコードですが、気づかないで何年もバグる日までソースコードの奥底で深い眠りに入っているこのようなコードを、読者も発見したことがあるでしょう。

そしてこれに対して以下のようなテストコードがあるとします。

```typescript
describe('test auth', () => {
   const spyOnIsAlreadyLoggedIn = ...

   it('isAlreadyloggedInが呼ばれる', () => {...});

   it('isAlreadyloggedInが呼ばれない', () => {...});

   it('loggedInがtrueの場合、isAlreadyloggedInがtrueを返す', () => {...});

   it('loggedInがfalseの場合、isAlreadyloggedInがfalseを返す', () => {...});
});
```

ここで**isAlreadyLoggedInを削除すればいいね**と楽観的に思って削除したら、今度は単体テストが無意味にもこけます。

- 動作も変わらないのにこけるテスト
- 実装の詳細にこだわったテスト
- 仕様と関係もないテスト

これらが**ソースコードの変更を許さないテストです**。

# なぜこういうテストが存在するのか

以下の理由が考えられます。

- テストを書けば何かと安心するところがあるから
- 内容関係なしにテストを書いておけば、コードレビューが進みやすい場合があるから
- 変更に対して自信が持てないから
- 仕様がはっきりしないから
- 仕様を守る、機能衰退テストが必要だったが、機能がなくなったのにテストが残ったから
- チームでテストの基準が定かでないから

さまざまな理由は考えられますが、最後の**チームでテストの基準が定かでないから**が最も大きいと思います。

# 無意味なテストのコスト

ソースコードの変更を許さないテストは、**無意味なテストです**。

これらのテストを削除することも、**簡単ではありません**。なぜかというと、テストが一旦入ってしまうと、入れるより三倍ほどの労力で仕様を確認して削除してもいい証拠を集める作業が発生するからです。

この`isLoggedIn`のメソッド自体に対してのテストが入ってくると、仕様と関係があって重要だからテストがある、という誤解を与えてしまいます。

テストを削除することは勇気も要るし、調査も必要です。

そのようなテストが大量にあると、**作業効率が著しく低下します**。

テストはソースコードと同じように保守するコストもかかってくるので、増えれば増えるほど技術負債になりえます。

# どのようなテストを書けばいいだろう？

まず、テストを作る時に、以下の質問を自問自答しましょう。

- テストで何の目的を果たしたいのか
- このテストは仕様に基づいているテストか
- このテストが評価している機能はすぐに変わる予定があるのか

ログアウトしたら`isLoggedIn`が`false`を返すようなテストではないく、**ログアウトしたらリダイレクトされる**というふうに、実際の動作を保証するテストを書くといいです。

テストを書かない判断を時としてするべきことがあります。テストはたくさんあればいいわけではなく、きちんと確認するべきことを確認しているテストが助けてくれます。

冪等性を確認するテストもありますが、これはテストをするべきでないと思います。`2 + 2 === 4`のようなテストを書くと同じくらい無意味なのです。

また、第三者ライブラリ、ブラウザAPI等、自分たちの書いたことでないものに対してテストを書くべきではありません。なぜかというと、それは自分らが保証するべきコードでないからです。

# まとめ

テスト作成は非常に難しいことです。

筆者自身も非常に悩みますし、無意味なテストをたくさん書いてきています。

また、テストが不要だと主張することもなかなか受け入れられない話だから、勇気が要ります。

「テストを書けと言われたから、とりあえずテストを書いた」という状況もあるかと思います。

自信を持つことです。ちばら！
LINE WORKS の監査ログを毎月自動保存して通知してくれるBot

## ついつい忘れてしまう監査ログの保存を自動化

LINE WORKSは監査を目的としたトーク履歴等の保存が可能ですが、
閲覧期間は180日までとなっています。

CSVデータとしてローカルにDLする事も可能ですが、
手動だとついつい忘れてしまいがちです。

そこで毎月１日に監査ログAPIを定期実行し、CSVファイルをGoogle Driveへ自動保存
およびBotでCSVファイルをお届けしてくれるツール(GAS)をつくりました。

LINE WORKSの監査ログAPIは、過去最大31日間までのログを取得可能です。
そのため 前月1日00:00:00 ~ 前月最終日の23:59:59までのログを毎月１日に取得する実装にしました。


#### 実行イメージ

毎月１日になると、Botがログファイルと保存先パスを届けてくれる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2727469/122ffdc8-5c71-3f2e-1ae9-121cfd758cce.png)

保存先パスは以下のような感じ
※カスタマイズによりLINE WORKSのDriveや共有フォルダへ置くことも可能ですが
ひとまず今回はGoogle Driveの指定フォルダへ自動保存にしました
<img width="500" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2727469/ecfb1f8c-197b-b720-1010-dbde21aa6430.png">

## 必要なもの
* Googleアカウント（無償でもOK）
* LINE WORKS Developers Consoleへのアクセス権限を持つID
* [LINE WORKS 便利ツール](https://qiita.com/nonattonolife/items/16181d666b8246e3f28d)


## 事前準備

### 1. LINE WORKS便利ツールの準備

以下の手順に従い、便利ツールの事前準備をします

https://qiita.com/nonattonolife/items/16181d666b8246e3f28d


便利ツールの準備ができたら、シートの「**Audit**」を開き、必要事項を入力します

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2727469/be8abb33-d2b8-4f3a-efe9-75100a080124.png)


### 2. トリガーの設定

毎月１日にプログラムが定期実行されるように、
GASのトリガーを設定していきます。


Googleシートの「**拡張機能**」メニューから「**Apps Script**」を開きます
<img width="400" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2727469/ae5ac3f9-5eec-9d02-f692-7e8ba9da254c.png">


左側のメニューアイコンから、トリガーを選択します

<img width="400" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2727469/91921beb-2292-d8f4-0e23-0fcc4253bbe2.png">


画面右下のほうにある「＋トリガーを追加」をクリックします
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2727469/687a4bfe-ae45-f5fb-2bf3-bb5ea30c5c4e.png)

以下のとおりトリガーを設定します

　実行する関数を選択：**getAudit**
　実行するデプロイを選択：**Head**
　イベントのソースを選択：**時間主導型**
　時間ベースのトリガータイプを選択：**月ベースのタイマー**
　日を選択：**１日**
　時刻を選択：**午前０時～１時**
　エラー通知：**任意**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2727469/ea2795cc-8931-37ae-1f69-65b02b292a8a.png)

以上で設定完了です。


## 動作テスト

毎月１日にならないとログは取得できないですが、
ここまで設定がちゃんとできたか検証だけしてみましょう。

「**Apps Script**」へ戻ります
<img width="400" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2727469/ae5ac3f9-5eec-9d02-f692-7e8ba9da254c.png">

ファイル：**audit.gs** を選択して、**getAudit** を **実行**してみてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2727469/f1c14454-57d3-0576-cba5-527b2639bbb1.png)

Botからメッセージが届いたら成功です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2727469/9a66322e-12b6-9f7b-cae9-bd32f69b20d5.png)

ファイルを開くと、データはありません。
前月の１日～本日までの期間が指定されてしまっているのでエラーになっていますが、動作テストはこれでOKです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2727469/4796945f-824f-ae11-b9c0-60a8e9ba0b2a.png)
トリガーの設定を誤っていなければ、１日になったらちゃんとデータが入ったログが届くはずなので、気長に待ちましょう。


## 参考にさせていただいた記事


いつもお世話になっている @kunihiros さんのコチラの記事のおかげで、徹夜を免れました。
https://qiita.com/kunihiros/items/0a8ecc855fe721912d5f
[Flutter]関数の呼び出しのあれこれ

　
　

こんにちは。いせきです。もうすぐ新生活の時期ですね。どんな生活になるのかがとても楽しみと感じながらコードを書いています。疲れすぎない毎日を送りたいものですね。


今回は、関数の呼び出しについて記事を書いていきます。



# はじめに

自作のWidgetが`onTap`などのコールバックを受け取ることがあると思います。具体例としてはこちらです。

```dart
class SampleApp extends Stateless {
  const SampleApp({
    Key? key,
    this.onPressed,
  }) : super(key: key);

  final void Function()? onPressed;

...
}
```

このような関数を作成したときに、２つほど書き方があります。


```dart
return ElevatedButton(
//１つ目の書き方
 onPressed: () => onPressed?.call(),
//２つ目の書き方
 onPressed: () {
   if(onPressed != null) {
     onPressed!();
   }
  },
  child: Text('Tap'),
),
```

# 解説

一つ目の書き方について説明します。

```dart
onPressed: () => onPressed?.call(),
```

`onPressed?`のあとに`call`をつけることで<b>`onPressed`がnullの場合は何もしないようにし、nullでなければ関数を呼び出す</b>という仕組みがたった１行で書けるとても便利な書き方となっております。

とてもスッキリしていておすすめだと感じました！！


二つ目の書き方について説明します。

```dart
 onPressed: () {
   if(onPressed != null) {
     onPressed!();
   }
  },
```

二つ目の書き方は、`onPressed`の処理を呼び出す前にnullかどうかのチェックを行い、nullではない時に、処理を呼び出すやり方です。



個人的な意見としてはどちらも結果としては同じなのですが、一つ目の方が１行でかけてとてもスッキリしているためおすすめします。僕はこのことを最近まで知らなかったので、反省しております。。。
人工知能による自然言語処理を用いた対話アシスタントシステムの開発について

# 人工知能による自然言語処理を用いた対話アシスタントシステムの開発について

近年、パワハラやセクハラなどの問題が取り上げられるようになってきた。これらの問題が起こる原因は、言葉の伝え方が良くないことが大きな原因である。しかし、その背景には、言葉の伝え方を改善するための支援システムが不十分であることもある。そこで、AIによる自然言語処理を用いた対話アシスタントシステムの開発が求められている。

## 自然言語処理による解決案

人工知能による自然言語処理を用いることで、以下の解決案を提案する。

### 1. 不適切な発言の検知
人工知能により、パワハラやセクハラなど不適切な発言があれば検知して、警告を出す機能を実装する。これにより、相手を傷つけるような言葉遣いを避けることができ、より円滑なコミュニケーションを実現することができる。

例えば、会話の内容をリアルタイムで解析し、敬語が不十分だったり、不適切な表現を使うといった場合、対話アシスタントシステムはそれらの発言を検知し、注意喚起メッセージを表示する。これにより、相手の気持ちを意識して話をすることができるようになる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/486826/6cd1edf4-fef8-322a-153b-5be323bd0e9c.png)


### 2. 文章作成支援
人工知能により、伝えたいことをもとに文章を作成する機能を実装する。これにより、文章の表現方法に悩むことなく、スピーディに文章作成ができるようになり、より効率的なコミュニケーションが実現する。

例えば、自分が伝えたいことを人工知能に伝えると、対話アシスタントシステムがそれを分析し、文章を作成する。これにより、時間を節約しながら、適切な表現で相手に伝えることができる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/486826/51dab88f-1690-317a-558c-2bb315b87af2.png)


### 3. 要約機能
人工知能により、受け取った内容を要約する機能を実装する。長文の文章を読むのが苦手な人でも、要約することで簡潔な情報を得ることができるようになり、よりスムーズなコミュニケーションが実現する。

例えば、長い文章を読むことが苦手な人は、対話アシスタントシステムに要約してもらうことができる。これにより、簡潔な情報だけで済むため、相手の負担も減り、コミュニケーションがスムーズに進む。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/486826/b12fbcce-8960-205f-3f3f-dc6f65bf383b.png)

## 結論
以上、人工知能による自然言語処理を用いた対話アシスタントシステムの開発について述べた。これらの機能を実装することで、パワハラやセクハラなどの問題を解決するだけでなく、円滑なコミュニケーションが実現する。今後、より優秀な対話アシスタントシステムの開発が進められることを期待したい。
MySQLの接続・切断方法

# ターミナルでの接続方法
以下の様に記述する
```
mysql -u root
```
ターミナルで接続すると長い文章の後に`mysql>`が出てくる。
```
mysql>
```
# ターミナルでMySQLを切断する方法
`exit`を打つ
```
mysql>exit
```
Rails、PostgreSQLで ActiveRecord::StatementInvalid: PG::InsufficientPrivilege: ERROR:  must be owner of database my_app_test と怒られる

## 困ったこと

RSpec流そうとしたら怒られました。

```terminal
$ be rspec                           
rails aborted!
ActiveRecord::StatementInvalid: PG::InsufficientPrivilege: ERROR:  must be owner of database my_app_test
```

## 解決

databaseの設定でuserをチェックします。

```yaml:config/database.yml
default: &default
  username: <%= ENV.fetch("DBUSER") { "postgres" } %>

test:
  <<: *default
  database: my_app_test
  host: localhost
```

`rails db`でDBに入り、`\l`でデータベースのリストを表示。
Ownerの欄を見ると、postgresではない人がいる。
`ALTER DATABASE <DB名> OWNER TO <ユーザー名>;`でオーナーを変更。

```terminal
$ rails db
psql (13.10)
Type "help" for help.

my_app_development=# \l
                                             List of databases
               Name                |    Owner    | Encoding | Collate | Ctype |      Access privileges      
-----------------------------------+-------------+----------+---------+-------+-----------------------------
 my_app_test                       | kakudaisuke | UTF8     | C       | C     | 


my_app_development=# ALTER DATABASE my_app_test OWNER TO postgres;
ALTER DATABASE
my_app_development=# \l
                                             List of databases
               Name                |    Owner    | Encoding | Collate | Ctype |      Access privileges      
-----------------------------------+-------------+----------+---------+-------+-----------------------------
 my_app_test                       | postgres    | UTF8     | C       | C     | 


my_app_development=# exit
```

これで解決しました。

参考
https://stackoverflow.com/questions/7210563/rake-aborted-error-must-be-owner-of-database
Oracle JSON型を試してみたのでメモ

# 目的
OracleでJSON型が使用できるようになったとのことなので、使うかどうかわからないが試してみたメモ

:::note info
「ネイティブ・バイナリ形式OSONを使用したJSONデータ」というらしい
https://docs.oracle.com/cd/F32587_01/adjsn/json-in-oracle-database.html#GUID-F6282E67-CBDF-442E-946F-5F781BC14F33
『JSONデータ型(他のSQLデータ型との変換)』参照
:::

# 環境
Oracle 21c

# SQL*PlusでのDB操作
## テーブル作成
```
SQL> create table test_tbl(json_fld json);
```
## レコード登録
```
insert into test_tbl
values('{"user_id": "U000000001","fld1": "str1","fld2": "2","fld3": "2023/3/15"}');
```

## select

:::note warn
クライアントが21cの場合は、`select * from test_tbl`でJSONが表示されるが、12cの場合は、正常に表示されない。
12cでもフィールド毎にselectすることはできる。
:::
### fld1を文字列型としてselectする場合
```
SQL> select t.json_fld.fld1.string() from test_tbl t;
```
:::note warn
json_fldの前にt_alias(この例の場合はt)が必要。
t_aliasではなくtest_tbl.json_fldと記述するとエラーになる。
文字列として取得する場合はstring()が必要。
※t_aliasは以下の表記に基づいた
https://docs.oracle.com/cd/E57425_01/121/SQLRF/statements_10002.htm
:::

### fld2を数値型としてselectする場合
```
SQL> select t.json_fld.fld2.number() from test_tbl t;
```

### fld3を日付型としてselectする場合
fld3.date()では表示されない。
```
SQL> select to_date(t.json_fld.fld3.string(), 'YYYY/MM/DD') from test_tbl t
```

## 検索条件とする場合
`where t.json_fld.fld1.string()='str1'`のように指定する。
他のテーブルとの結合条件としても使用できる。
・・・が、検索条件、結合条件にするならば、別途フィールドを設けたほうが効率がよいのではないかと思う。

# 参考
https://docs.oracle.com/cd/F32587_01/adjsn/json-in-oracle-database.html#GUID-F6282E67-CBDF-442E-946F-5F781BC14F33
wordpressブログでユーザーに見やすい目次表の作り方

## 読者に見やすい目次表
wordpressブログに目次表を導入すると、読者の見やすさが改善されます。
たとえば下図は自身ブログで用いている目次表の一例です。
![目次表.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2699006/8f1138bd-27f2-016b-167e-3c315f4fa7bd.png)
ブログの導入部分に目次表があることで、そのコンテンツの概要が掴めるからです。
今日はそんな目次表のhtml/cssでの作り方を記事にしてみました。
## 目次表作成のためのhtml/cssコード
自身が使っている目次表は、下記の例示の要領でコードで利用しています。
``` html
<div style="display: inline-block; background: #008000; padding: 5px 10px; color: #ffffff;"><strong>目次</strong></div>
<div style="background: #ffffff; padding: 10px; border: 5px solid #008000;"><a href="#a">◇ h1など見出しタグと目次併用の効果</a> <br />
　○ <a href="#a1">wordpressブログ見栄え改善には目次を利用する</a><br />
　○ <a href="#a2">ワードプレスブログでの目次の使い方</a><br />
　○ <a href="#a3">目次とh1など見出しとのレイアウト</a><br />
<a href="#b">◇ 目次からh1やh2、h3見出しリンクでSEO対策</a><br />
　○ <a href="#b1">ブログ記事の目次と見出しを紐付ける</a><br />
　○ <a href="#b2">ワードプレス記事目次リンクのビジュアルエディタでの作り方</a><br />
　○ <a href="#b3">wordpress目次リンクhtmlでの作り方</a><br />
<a href="#c">◇ ブログの印象は目次で決まる</a><br />
　○ <a href="#c1">来訪者は目次で読み続けるか否かを判断する</a><br />
　○ <a href="#c2">wordpress目次作成にはhtmlとプラグインがある</a></div>
```
それぞれ文字列部分を記事内容に応じて変更すれば、目次表のテンプレートとして使うことが出来ます。

また、目次表の#a1などとアンカー機能を使うことで、文字列部分から見出しとリンクして飛ばす方法も可能です。
## 目次表と見出しリンクの作り方
目次表と見出しをリンクさせるには、該当する見出しの段落をクリックしてアクティブ状態にします。
![目次表と見出しリンク.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2699006/3bff2d72-43df-19a5-4541-e67e512f3b78.png)
たとえば上図では見出し『wordpressブログ見栄え改善には目次を利用する』の段落頭をクリックして、右上のアンカーアイコンをクリックします。

そして先ほど目次表で登録しておいた#a1とリンクさせるために、ここではアンカーボックスへ『a1』と入力します。

こうすることで目次表の『wordpressブログ見栄え改善には目次を利用する』をクリックすれば、ページ内にある見出し『wordpressブログ見栄え改善には目次を利用する』へジャンプすることが可能となり、読者が見たい部分へすぐ移動することが可能となります。
"EntityBean内のabstractメソッド_ebean_intercept()をオーバーライドしません"の原因と対処

EbeanのEntityクラスで以下のコンパイルエラーが発生しました｡

> <クラス名>はabstractでなく、com.avaje.ebean.bean.EntityBean内のabstractメソッド_ebean_intercept()をオーバーライドしません

何がなんだかわからなかったのですが､結論として､sbtのクラスファイルのキャッシュが悪さをしていたようです｡

```
sbt clean
```

してから再ビルドすることで解決（コンパイルエラーが消えた)しました｡
Pythonのクラス変数はコンストラクタで初期化しなさいなって話

コメントにてご指摘いただきました。
筆者の勘違いから理解までの流れをお楽しみください。

# 事象
listをクラス変数として初期化していると、
インスタンスの```sample_1```と```sample_2```で```list```が共有されちゃいます。
```python:Sampleクラス
class Sample:
    int_x:int = 0
    list_y:list = []
        
    def set_int(self, val):
        self.int_x = val
    
    def list_add(self, val):
        self.list_y.append(val)
```
インスタンス生成後、当然両方とも初期値です。
```python:インスタンス生成後
sample_1 = Sample()
sample_2 = Sample()
# 1_int:0
# 1_list:[]
# 2_int:0
# 2_list:[]
```
```sample_1```の```int```を変更しても```sample_2```の```int```には影響ないですね。
```python:intを変更
sample_1.set_int(3)
# 1_int:3
# 1_list:[]
# 2_int:0
# 2_list:[]
```
ただし```sample_1```の```list```を変更すると```sample_2```の```list```も変更されています！
~~クラス変数でもlistはシャロ―コピーされるっぽいですね、、、~~
全然違いました。
[こちら](https://qiita.com/ShqnD/items/75865612e4794d134586#comment-7bc221ac0c007881cc38)の素晴らしくわかりやすいコメントをご参照ください。
```python:listを変更
sample_1.list_add('TEST')
# 1_int:3
# 1_list:['TEST']
# 2_int:0
# 2_list:['TEST']
```
# 解決方法
タイトル通りsampleクラスをこんな感じで変更して、
コンストラクタ内でlistを初期化すると想定通りの動きになります。
```python:修正後Sampleクラス
class Sample:
    int_x:int = 0
    list_y:list
    
    def __init__(self):
        self.list_y = []
        
    def set_int(self, val):
        self.int_x = val
    
    def list_add(self, val):
        self.list_y.append(val)
```
インスタンス生成後、```int```は前回と同じ動きになります。
```python:インスタンス生成後
sample_1 = Sample()
sample_2 = Sample()
# 1_int:0
# 1_list:[]
# 2_int:0
# 2_list:[]

sample_1.set_int(3)
# 1_int:3
# 1_list:[]
# 2_int:0
# 2_list:[]
```
```Sampleクラス```を修正したことで、想定通り```sample_2```の```list```は影響なく済みました！
```python:listを変更
sample_1.list_add('TEST')
# 1_int:3
# 1_list:['TEST']
# 2_int:0
# 2_list:[]
```

Python結構長いこと使っていましたが全然知りませんでした、、、
みんな気を付けてくれよな！
Pub/SubなしでCloud Functionsを定期実行【cron】

ググるとPub/Subをサンドイッチする記事ばかりでした。Pub/Subを管理するのはめんどいので直接実行しましょう

`OIDCトークを追加`を選択することでPub/Subなしで定期実行可能です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3127414/59453477-b9e7-52eb-7449-986998d62aa8.png)
classの継承

***Powershell***でクラスの継承のプログラムを実装しました。

```Powershell
# Powershell class Test4
# 新規作成 2023/3/15

class TestClass4{
    [int] $ID
    [String] $Name
    
    
    #コンストラクタ
    Disp([int] $ID,[String] $Name) {
        $this.Id = $Id
        $this.Name = $Name
    
    }
    #ToStringメソッド
    [String] ToString() {
        return "Id=" + $this.Id + ",Name=" + $this.Name
    }
    #ToNameメソッド
    [String] ToName() {
        return "私の名前は" + $this.Name + "です。"
    }
    


}

# TestClass4を継承して、testClass5を作成する。
class TestClass5 : TestClass4{
    [String] Livein(){
        $Data = ([Testclass4]$this).ToName()
        $Data += "出身は立川市です"
        return $Data
    }
}

$T1 = New-Object TestClass4
$T1.Disp(1,"白石麻衣")
$T1.ToString()
$T1.ToName()

$T2 = New-Object TestClass5
$T2.Disp(2,"山下美月")
$T2.ToString()
$T2.ToName()
$T2.Livein()
```
Emmet(エメット)入門 CSS編

## Emmet（エメット）とは
Emmet（エメット）は、HTMLやCSSのコーディングを効率化するための機能です。
VScodeでは、デフォルトで対応しているため、すぐに使用することができます。

## Emmetの基本的な使い方

### margin
```css
/* m */
margin: ;

/* m10 */
margin: 10px;

/* m10-10 */
margin: 10px 10px;
```

### padding
```css
/* p */
padding: ;

/* p10 */
padding: 10px;

/* p10-10 */
padding: 10px 10px;
```

### color
```css
/* c#FFF */
color: #fff;
```

### width
```css
/* w */
width: ;
    
/* w10 */
width: 10px;
```


### font-size
```css
/* fz */
font-size: ;

/* fz10 */
font-size: 10px;

/* fz1r */
font-size: 1rem;
```

### display
```css
/* db */
display: block;
/* df */
display: flex;
/* di */
display: inline;
```
【Unity】VFX GraphでSkinned Meshからサンプリングする

UnityのVFX Graph 11.0(Unity 2021.1.9f1+)からVFX Graph内でSkinned Meshからサンプリングできるようになったので使い方を解説します。

この記事は以下のバージョンで検証しています。

- **Unity:** 2021.3.18f1
- **Visual Effect Graph:** 12.1.1.0


以前のバージョンでも以下のパッケージを使用すればSkinned Meshからサンプリングできましたが、VFX Graph公式が対応してくれたことで利用しやすくなりました。(このパッケージも公式が対応したことで、公式実装の利用サンプルに内容が変わっているようです。)
[GitHub \- keijiro/Smrvfx: Skinned mesh sampling with VFX Graph](https://github.com/keijiro/Smrvfx/tree/master)


## 準備

VFX GraphでSkinned Meshをサンプリングするために、使用するSkinned MeshのImport Settingsで`Read/Write`にチェックを入れておく必要があります。
![Prepare2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61569/cba2529a-f62a-6db8-d82a-64b031f8bc18.png)

## Set Position (Skinned Mesh) Blockを使用する方法

`Set Position (Skinnend Mesh)` Blockを使用することでSkinned Meshから位置をサンプリングしてパーティクルの位置に設定することができます。
[Set Position \(Mesh\) \| Visual Effect Graph \| 12\.0\.0](https://docs.unity3d.com/Packages/com.unity.visualeffectgraph@12.0/manual/Block-SetPosition(Mesh).html)

![SkinnedMeshSample01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61569/593bf022-4974-5c09-b2fa-ea0e70d51c01.png)
![VfxSkinnedMeshSample.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61569/ada23a47-308d-1d21-3e9a-802842d49a4e.gif)

`Skinned Mesh Renderer`をプロパティとして設定する必要がありますが、ここはシーン内にあるものを指定したいのでグラフ自体に`Skinned Mesh Renderer`プロパティを追加して、それを利用するようにします。このBlockでサンプリングできる位置はオブジェクトスペースなので、ボーンルートのTransformを適用して位置を再設定します。Transformを適用するには`Transform Binder`コンポーネントを使用するのが簡単です。
![HierarchyAndInspector.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61569/cf985602-0d26-9541-4f34-49f1adba8cad.png)


## Sample Skinned Mesh Operatorを使用する方法

`Set Position (Skinnend Mesh)` Blockは位置を設定するだけでしたが、`Sample Skinned Mesh` Operatorを使用すると、より複雑なネットワークを作ることができます(ただし、以下のサンプルでは`Set Position(Skinned Mesh)` Blockを使用したサンプルと同じ挙動になるようにしています)。
[Sample Mesh \| Visual Effect Graph \| 12\.0\.0](https://docs.unity3d.com/Packages/com.unity.visualeffectgraph@12.0/manual/Operator-SampleMesh.html)
![SkinnedMeshSample02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61569/2243f36a-ac48-435f-2498-f062dc879b54.png)

`Sample Skinned Mesh` Operatorで`Placement Mode`を`Surface`、`Surface Coordinates`を`Uniform`にした場合、どの三角形プリミティブ(`Triangle`プロパティ)のどの位置(`Square`プロパティ)からサンプリングするかを指定する必要があります。メッシュを構成する三角形プリミティブの数は`Skinned Mesh Index Count` Operatorで取得できるインデックス数を3で割ることで求まるので、上のグラフではその値をもとに設定しています。
[Mesh Index Count \| Visual Effect Graph \| 11\.0\.0](https://docs.unity3d.com/Packages/com.unity.visualeffectgraph@11.0/manual/Operator-MeshIndexCount.html)

`Sample Skinned Mesh` Operatorから取得できる値は`Position`だけでなく、`Color`や`TexCoord0`、`Normal`なども取得することができ、`Sample Skinned Mesh` Operatorのインスペクターから設定することができます。
![SampleSkinnedMesh2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61569/da37d952-20c5-2bd3-c2f2-0d003656b7e4.png)


## 参考

- [Visual Effect Graphの新機能で広がる表現 – Unity for Pro](https://forpro.unity3d.jp/unity_pro_tips/2021/12/22/3207/)
- [VFX Graph追加されたSkinned Mesh Sampleブロックを使ってみる](https://zenn.dev/drumath2237/scraps/be3b25041c3838)
福利厚生としてChatGPT Plusを一人一つ契約します【GPT-4】

https://www.itmedia.co.jp/news/articles/2303/16/news182.html

https://prtimes.jp/main/html/rd/p/000000300.000055900.html

https://digital-shift.jp/flash_news/FN230317_6

https://prtimes.jp/main/html/rd/p/000000095.000033025.html

https://news.yahoo.co.jp/articles/40ff6c2e0d8aacd30d3eacb2870b8311b1c7d4da

https://secretplace.co.jp/employeebenefit-aisubsidyprogram/

https://www.excite.co.jp/news/article/AMP_323856/

https://prtimes.jp/main/html/rd/p/000000051.000061060.html

GPTの可能性を模索するため、みんなにGPTネイティブな人材になってほしいと願っています。GPT-4を使い倒しましょう
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3127414/0ed81adc-73ea-3ec6-85f1-4226a058166d.png)
VBAでSleep関数 Application.waitメソッド　ではない 待つ 方法

<h2>別解</h2>
諸々割愛

```vba:wait procedure
Sub wait(int_msec)
    tim_cur = Timer
    Do Until Timer > tim_cur + (int_msec / 1000)
    Loop
End Sub
```

```vba:call side
Sub sample()
    Debug.Print "Executing"
    Call wait(6000)
    Debug.Print "Done"
End Sub
```
で対応しました。


<h2>どう失敗したか</h2>

【Sleep関数】
　ESC連打が効かない。
　32Bit 64Bitを毎回考える。
　モジュール前にPrivate？Declare？PtrSafe？ちょっと疲弊気味。
　
【Application.Waitメソッド】
　Application.Wait Now() + 6000 / 86400000
　等やっていたがやはり　ESC連打が効かない

【DoEvents関数】
　応答無しが多い

【OnTimeメソッド】
　記述の冗長

<h2>懸念</h2>
実行端末の自動時刻補正が効いた瞬間にこのプロシージャ実行していた時の検証をやってない。

雲つかむみたいな瞬間だな・・・。
Now()とかではなくTimerだから大丈夫か・・・
時刻っていつ補正されてるのか・・・。常時？
敵対的生成ネットワークGANに入門してみる

# 1. はじめに

敵対的生成ネットワーク(Generative Adversarial Network:GAN)について勉強しました。
備忘録として残します。

# 2.どういう手順で学習させるのか？

アルゴリズム
- step 1. 識別器の学習（贋作と本物を識別する人を育成します。）
- step 2. GANの学習（贋作を作る人が本物に近づくように育成します。）
- step 3. step 1.に戻る

## 2.1. 識別器の学習

識別器の学習では、贋作と本物を識別する人を育成します。

- step 1. 画像のデータベースからランダムに抽出した画像に、教師ラベル1を割り当てます。
- step 2. 画像データ生成器で生成した画像に、教師ラベル0を割り当てます。
- step 3. 訓練画像のデータベースに、教師ラベルと画像を格納します。
- step 4. 訓練画像のデータベースの教師ラベルと判定結果が、一致するように識別器を学習します。

![GANの識別器の学習.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139678/979a2bb4-874c-b0c2-7344-aedf38ef3d77.jpeg)

## 2.2. GANの学習

GANの学習では、贋作を作る人が本物に近づくように育成します。

- step 1. 識別器のパラメータ更新をオフにします。
- step 2. 画像データ生成器と識別器の合成関数GANを定義します。
- step 3. GANの判定結果と教師ラベルが一致するように、GANを学習します。間接的に、画像データ生成器が学習されます。

![GANの生成器の学習.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139678/27e0ae2c-6a7b-ce1a-5256-b7f8d8dfcb0d.jpeg)

# 参考文献

- [今さら聞けないGAN](https://qiita.com/triwave33/items/1890ccc71fab6cbca87e)
- [kerasでGAN(mnist)動かしてみた](https://qiita.com/ozora/items/28b9ae219492ffb62812)
- [今さら聞けないGANの目的関数](https://qiita.com/typecprint/items/035478748a811dd29721)
BizRobo!演習問題解いてみた～Excelと二重ループ～

就業先でRPAツールのBizRobo!を使用しています。日々BizRobo!開発で悩み、BizRobo!ナレッジベースで検索しています。

BizRobo!を提供しているRPA テクノロジーズ株式会社が演習問題を用意しています。BizRobo!の演習問題（Excelと二重ループに関するロボット開発）を解いてみましたので、紹介いたします。

※間違っている箇所や不適切な表現があるかもしれませんが、その時は都度修正いたしますので、ご指摘いただけると幸いです。


## BizRobo!の演習問題とは
BizRobo!の演習問題は、BizRobo! LAND COMMUNITYの中にあります。
BizRobo! LAND COMMUNITYとは、BizRobo!開発者同士で情報共有や悩み相談、ユーザー同士の交流ができるSNSです。BizRobo! LAND COMMUNITY内のスタディというコンテンツの中に演習問題が用意されています。

演習問題は、全部で10題あります。演習問題には、演習に必要なインプットファイルや回答となるサンプルロボットがついています。自分が1から開発したロボットが合っているかどうか確認できるのはいいですね。

ただ、最終更新日付は2020年のため、現在は更新されていません。これ以上演習問題が増えないのは残念です。また、BizRobo!バージョンはv10.3.0.7になります。最新版でないため、注意してください。

eラーニングで学んだ後は、ロボットを自分で開発し経験を積むのはとても大事なことです。BizRobo!の技術力向上のために、演習問題を解くのをオススメします。

BizRobo! LAND COMMUNITYに入るには、BizRobo! Portalに登録する必要があります。BizRobo! PortalやBizRobo! LAND COMMUNITYについては、下記のURLも参考にして下さい。
[BizRobo!学習するには～BizRobo e-learingがオススメ～](https://qiita.com/TBO/items/06122d910d44019b1896)



## 演習問題と解いてみた
今回解いた演習問題は、「 Excelのデータを別Excelの各シートに振り分けるロボットを開発する」ことでした。
詳細はBizRobo! LAND COMMUNITYをみてほしいので、ここでは例え話を用いて、今回解いた演習問題の中身を説明します。

:::note
Excelには、株式会社TBOの全社員情報が格納されています。そのExcelには、氏名や所属部署、メールアドレスなどのデータが用意されています。
あなたは、そのExcelを参考に、社員を所属部署ごとに振り分けたいと考えています。

別ExcelにA部署、B部署、C部署、D部署と各部署ごとのシートを用意し、Excelから別Excelに振り分けようと考えました。

しかし、自分でやるのは大変であり、ミスも出る可能性があります。そのため、BizRobo!で自動化しようと考え、ロボットを開発することにしました。
:::

上記が演習問題でやりたいことになります。イメージはつきましたでしょうか。

どこの会社でも起こりうる業務だと思います。実際の業務でありそうな内容を扱ってくれているのがありがたいですね。

また、BizRobo!の実践経験が多い人にとっては簡単な内容ですが、eラーニングで学んだばかりの人が1人で開発するにはいい難易度で解きがいのある問題でした。といいますのも、躓く箇所があるが、BizRobo!ナレッジで調べたらわかる程度の開発だったからです。ぜひ演習問題に取り組んでみてください。


#### ポイント
演習問題ごとに学ぶポイントが書かれています。今回は、下記の通りでした。
>項目によって追記するシートが変わるので注意して、最終行に追記する方法を学ぼう
>条件分岐／値判定／行挿入

しかし、私がこの演習問題を解いて感じたポイントは違いましたので、3つにまとめて、紹介いたします。


###### Excel
まずExcelファイルを開いて中身を確認できなければ、先に進みません。Excelファイルを開くには、ブラウザで開くと変数で開くの2種類があります。この開き方の使い分けがキーになりました。
[「ファイル読込(Load File)」ステップ](https://knowledge.bizrobo.com/hc/ja/articles/360042358671)

###### 二重ループ
二重ループとは、繰り返しの中に繰り返しが入っている構造を指します。
プログラミングでは初心者がつまづきやすいポイントであり、かつロボット開発で非常によく使われる構造です。BizRobo!でどうやって作るのかを学ぶいい機会となりました。

###### グローバル変数
二重ループによりたくさんのデータをExcelに転記します。しかし、変数の設定を間違えると、二重ループしても全くデータが転記されず、空のExcelファイルができてしまう事態に陥ります。グローバル変数を適切に設定しなければいけませんでした。
グローバル変数について、下記でも解説しているので、参考にしてください。
[BizRobo!の変数～初心者あるある～](https://qiita.com/TBO/items/90cb7a0f5e23e8508911)


## 自分の回答
自分が開発したロボットを載せようかと思いましたが、演習問題を解く楽しみがなくなってしまうため、辞めました。その代わりに、各ステップの流れを簡単にまとめます。

```
(1) 2種類のExcelファイルを先に開いておく
(2) 2種類のループ実行
　  (2-1) Excelデータ（社員情報一覧）の先頭データからループ
　  (2-2) 別Excel（各部署ごとの社員情報一覧）の各シートをループ
　　  　　(2-2-1) 該当シートにデータを格納
(3) 別Excelを保存
```

演習問題についていたサンプルロボットには、下記以外の流れのロボットがありました。どんなロボットか気になる方は、BizRobo! LAND COMMUNITYの演習問題を実際に解いてみてください。


## 最後に
BizRobo!演習問題について、解説いたしました。BizRobo!のeラーニングでDSにおける開発について学びましたが、今回の演習問題で1からロボットを開発することで、eラーニングで学んだことを活かすことができました。

今回の演習問題はRPA テクノロジーズ株式会社が用意してくれた問題です。実際に自分で1からロボットを開発することで、実際の現場に役立つと思います。今回の記事を読んで、BizRobo!の技術力向上につながったら幸いです。

また、今後もBizRobo!開発に役立つような記事を書いていきます。
Windows11 に Node.js インストール, JavaScript実行, React 環境構築

Windows11 に Node.js インストールして JavaScript 実行、React環境構築をやってみる
やることは大雑把にこんあところ

- Node.jsインストール
- Node.js で JavaScript実行(簡単なHTTPサーバたてる)
- React環境構築


# Node.js インストール（node:v18.15.0, npm:v9.5.0）

1. Node.js インストーラー取得(LTSの方を選択)
    https://nodejs.org/
1. インストーラ実行
    画面に従い進める、許可などは確認して同意、はいを選択
    途中でコマンドプロンプト、PowerShell 上がってくるのも画面に従いキー入力
    Warning とか出ても気にしないでOK
1. インストール確認
    コマンドプロンプト or Powrshell で以下を入力してバージョン確認
    ```Powershell
    # Node
    node --version
    # Node Package Manager
    npm --version
    ```

# Node.js で JavaScript実行(HTTPサーバ)

1. 適当なフォルダを作る
    `C:\nodework`
1. フォルダの中に JavaScript `index.js` を作る
    `C:\nodework\index.js`
1. `index.js` に以下のコードを入力
    ```JavaScript:index.js
    // モジュールインポート
    const http = require("http");

    // HTTPサーバ設定
    http.createServer((request, response) => {
        switch (request.url) {
            case '/json':
                response.writeHead(200, { "content-type": "application/json", "charset": "utf-8" });
                response.write("{ text : Hello World }");
                response.end();
                break;
            case '/html':
                response.writeHead(200, { "content-type": "text/html", "charset": "utf-8" });
                response.write("<!doctype html><html><body><h1>Hello World</h1></body></html>");
                response.end();
                break;
            default:
                response.writeHead(200, { "content-type": "text/plain" });
                response.write("Hello World");
                response.end();
        }
    }).listen(8888);
    ```
1. コマンドプロンプト or Powrshell で作ったフォルダに移動
    ```Powershell
    cd C:\nodework
    ```
1. コマンドプロンプト or Powrshell で Node 使って JavaScript 実行
    以下のコマンド実行で Node から JavaScript が実行される
    ```Powershell
    node index.js
    # 実行すると Windows セキュリティの警告が出るときは気にせずキャンセルでOK
    # 他のPCとかデバイスから接続させたいときはアクセス許可するようにする
    ```
1. 実行したやつにアクセス
    以下にブラウザからアクセスで `Hello World` が表示されればOK
    http://localhost:8888/
    http://localhost:8888/json
    http://localhost:8888/html

# React環境構築(create-react-app:v5.0.1)

公式の [Create a New React App](https://ja.reactjs.org/docs/create-a-new-react-app.html) を参考にやってみる 

1. 適当なフォルダを作る
    `C:\reactwork`
1. コマンドプロンプト or Powrshell で作ったフォルダに移動
    ```Powershell
    cd C:\reactwork
    ```
1. `create-react-app` よりプロジェクト名を指定して作成
    ```Powershell
    npx create-react-app my-app
    # my-app のフォルダが作られて開発するプロジェクトになる
    # create-react-app のインストールするか聞かれたら y で続ける
    ```
1. 作ったプロジェクトに移動
    ```Powershell
    cd my-app
    ```
1. 作ったプロジェクトを実行
    ```Powershell
    npm start
    ```
1. ブラウザで以下が上がってくればOK
    http://localhost:3000/
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51758/76e68754-e096-7aed-c917-7bed96574bd5.png)
モデルをカテゴリで出し分ける(SPSS Modeler データ加工逆引き9-10)

# モデルをカテゴリで出し分ける

![スクリーンショット 2023-03-08 13.57.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/ad118f83-a2bd-95a8-b3b8-c3f632fe7136.png)


## 1.想定される利用目的

・47都道府県別の予測モデルを作る際に、ストリームを何度も複製したり、スクリプトでループ処理したりすることなくデータ型ノードで出し分ける

## 2.サンプルストリームのダウンロード

https://github.com/yoichiro0903n/blue/blob/main/multi_modeling.str?raw=true

## 3.サンプルストリームの説明

### データ型の[分割]で出し分ける
＊数値予測、判別予測、時系列予測共通

![スクリーンショット 2023-03-08 15.32.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/547f1384-6e23-3024-5011-194329afd3e3.png)

a.入力するデータは以下の通りです。日と店舗の組み合わせになっています。
![スクリーンショット 2023-03-08 16.02.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/2d03be5a-dd70-cc91-1746-4ccc6a3ea880.png)

b.[データ型]ノードを編集します。[店舗]のフィールドを[分割]とすることで内部的には３つの店舗のモデルを作り分けます。
![スクリーンショット 2023-03-08 16.04.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/843c33a5-cc4b-a7bc-5975-a9daf5693a45.png)

c.[時系列]ノードを編集します。7日先の時系列を作成して予測をさせるモードです。
![スクリーンショット 2023-03-08 16.06.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/8fc7d7de-9f87-4dc3-f9d4-3f398378528c.png)

d.[時系列]モデルナゲットを編集します。見た目はシングルモデルですが内部では店舗別に作り分けられているのがわかります。
![スクリーンショット 2023-03-08 16.10.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/619b2804-a793-40c4-99d8-29e76d6efd9b.png)

e.[散布図]ノードを実行します。1/1から11/22までの実績を学習して7日先の予測モデルを3店舗分だし分けられています。
![スクリーンショット 2023-03-08 16.10.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/de0c19c6-50f3-bae7-b1ff-23f746a6f8e7.png)

### カテゴリを横持ちしてモデルに投入する
＊時系列予測のみ

カテゴリをフィールドで配置した場合にはモデル作成で同時に処理が可能です。

![スクリーンショット 2023-03-08 16.17.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/38d8e72b-f4f4-5b09-e37f-59f497b78714.png)

![スクリーンショット 2023-03-08 16.18.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/81e71c29-d7fe-662f-cf73-65e9c459adbd.png)


#### 注意事項

250種類以上のカテゴリを同時に扱う場合には以下を参考にしてください。

https://qiita.com/416nishimaki/items/0522f72e897fcb222a61#%E5%B0%BA%E5%BA%A6%E4%B8%8D%E6%98%8E%E3%82%92%E5%90%8D%E7%BE%A9%E5%9E%8B%E3%81%AB%E3%81%99%E3%82%8B

## 4.参考情報

#### モデル出し分けについて解説した記事

https://www.ibm.com/blogs/solutions/jp-ja/modeler-tips-18/

#### SPSS Modeler ノードリファレンス目次

https://qiita.com/416nishimaki/private/503037195081d3323eee

#### SPSS Modeler 逆引きストリーム集（データ加工）

https://qiita.com/416nishimaki/private/4bf813e6cba84b2a1008
ArgumentError in NotesController#create　エラー解消法


エラー内容について解消法を備忘しておきます。



**ArgumentError in NotesController#create**
**wrong number of arguments (given 4, expected 1..2)**
```ruby:エラー文
 extend ActiveHash::Associations::ActiveRecordExtensions
  belongs_to :weather, :usage_type, :taking_medicine, :bathing #この箇所でエラー色に


```

## 解説
このエラーは、ActiveHashとActiveRecordを組み合わせて使用しているときに発生するエラーです。
エラーメッセージによると、引数に4つの値が渡されたため、予想されている1〜2つの引数の範囲を超えているよと注意されている模様。

:::note info
詳細解説：
今回の場合、belongs_toメソッドは、通常、1つまたは2つの引数を受け取ります。最初の引数は関連するモデルの名前であり、2番目の引数はオプションであり、関連付けの設定を構成するために使用できます。しかし、このエラーの場合、4つの引数が渡されたため、belongs_toメソッドが期待する引数の範囲を超えてしまっています。

つまり、エラーメッセージは、ActiveHashのbelongs_toメソッドが、引数に対して受け入れ可能な範囲よりも多くの値が渡されたことを示しています。そのため、予想されている1〜2つの引数の範囲を超えているというエラーメッセージが表示されます。
:::


綺麗にまとめたいと思いこの記述をしたものの、
:belongs_toを使用する際には、引数は一つだけである必要となりうっかりしていました。
よって下記のように修正。

```ruby:エラー文
ActiveHash::Associations::ActiveRecordExtensions
belongs_to :weather
belongs_to :usage_type
belongs_to :taking_medicine
belongs_to :bathing

```

上記で
無事に解決しました。
DirectXの頂点シェーダで出力する座標について



## 目的

DirectXでビューワーを作っていて久々にハマったので個人的記録。記憶違いと知識不足が原因で、次の二点に気づかずに苦労しました。

1. 頂点シェーダで射影行列(projection matrix)を作用後の座標値は、スクリーン(ウィンドウ)のサイズ[-1.0, 1.0]で正規化されていない。wの値で割ることで[-1.0, 1.0]に正規化される。
1. 頂点シェーダでSV_POSITIONセマンティクスを付けた変数へ出力したものを、ピクセルシェーダで受け取った時には、値が変わっている。SV_POSITIONセマンティクスを付けた変数はラスタライザで利用しやすいように加工されてから、ピクセルシェーダに受け渡される。DirectX(10以降？)ではx,y座標に関してはスクリーン(ウィンドウ)のピクセル座標に変換されている。

参考：[https://shikihuiku.github.io/post/projection_matrix/](https://shikihuiku.github.io/post/projection_matrix/)

以下は、DirectX11を前提に記述します。一部はOpenGLでも通じる概念かもしれません。

## 1. 頂点シェーダで射影行列を作用後の座標値

一般的に頂点シェーダでは、入力となる頂点ベクトルに、ワールド変換行列、ビュー行列、射影行列の順に作用して、SV_POSITIONセマンティクスを付けた変数として出力すると思います。
```hlsl
//example 頂点シェーダ
struct VS_INPUT
 {
  float3 pos : POSITION;
  ...
};

struct PS_INPUT
 {
  float4 pos : SV_POSITION;
  ...
};

PS_INPUT main(VS_INPUT input)
{
  PS_INPUT output;
  float4 vpos = float4(input.pos, 1.0f);
  vpos = mul(vpos, world);
  vpos = mul(vpos, view);
  output.pos = mul(vpos, projection);
  ...

  return output;
}
```

これでスクリーンに二次元射影された座標になっていそうです。スクリーン座標はスクリーン(ウィンドウ)の中心を(0,0)として、左端を$x=-1$、右端を$x=1$、下端を$y=-1$、上端を$y=1$とします。変換後の頂点が、$(x,y) \in [-1,1]\times[-1,1]$の範囲に入れば画面に描画されると説明されます。つまり画面幅で規格化されています。

一方で、上記のような頂点シェーダから出力される`output.pos`の座標は、規格化されておらず、`output.pos.xy`には、もっと大きな値や小さな値が入っています。スクリーン座標$(x,y)$と結びつけるには、第四成分の`output.pos.w`で割ってやる必要があります。

つまり、
```hlsl
x = output.pos.x / output.pos.w;
y = output.pos.y / output.pos.w;
```
として初めてスクリーン座標になります。

これはマウスクリックなどでスクリーン座標を得てから、オブジェクトのあるワールド座標へ逆変換する際にも気を付ける点ですね。

（私は、記憶違いでwでの除算を忘れていてハマりました。）

## 2. 頂点シェーダ出力したSV_POSITIONの値は、ピクセルシェーダで受け取るときには変わっている

これも厄介です。上記のように、頂点シェーダで出力した座標`output.pos`は、wでの除算をしてやればスクリーン座標になるはずです。しかし、ピクセルシェーダの入力として受け取った際には、値が変わってしまっているのです。

例えば、上記の頂点シェーダと組み合わせて使うピクセルシェーダとして次のようなものを書くでしょう
```hlsl
//example ピクセルシェーダ
struct PS_INPUT
 {
  float4 pos : SV_POSITION;
  ...
};

float4 main(PS_INPUT input) : SV_TARGET
{
  float2 uv = float2(input.pos.x / input.pos.w * 0.5f + 0.5f,
                     input.pos.y / input.pos.w * 0.5f + 0.5f);
  float val = texture.Sample(sampler, uv);
  ...
  ...
  return color;
}
```

ここでは、画面全体を覆う一枚のテクスチャから、色を取得しようとしています。テクスチャ座標の`uv`に、`input.pos`の座標を利用しようとしてます。ｗで割れば規格化されるので、0.5で書けて、0.5シフトすれば、uvは[0,1]の範囲に収まりそうです。ただ、このコードは意図した動きになりません。

というのは、ピクセルシェーダの入力として渡される`input.pos`の値は、頂点シェーダで出力されたものとは変わってしまっているためです。その原因は、`input.pos`に`SV_POSITION`セマンティクスが指定されているためです。これが指定された座標情報は、ピクセルシェーダに渡る前に、システムに都合の良い値に書き換えられてしまうそうです。

webで調べた限りでは断片的な情報しか見つけられませんでしたが、良くあるのはラスタライザに都合よく変換されるようで、私の環境ではスクリーンの左上を[0,0]としたピクセル座標に変換されていました。なので、上記のピクセルシェーダを動くようにするには、例えば次のように書きなおします。
```hlsl
float4 main(PS_INPUT input) : SV_TARGET
{
  float2 uv = float2(input.pos.x / screen_w, input.pos.y / screen_h);
  float val = texture.Sample(sampler, uv);
  ...
  ...
  return color;
}
```
ここで、`screen_w`や`screen_h`にはスクリーンのピクセル幅が入っているとします。これで`uv`は[0,1]の範囲に収まり、意図通りにテクスチャの値を取得できます。

ただ、`SV_POSITION`の変換動作がこれに限るのかどうかが良く分かりません。利用するシェーダや組み合わせ、また、ハードウェアにもよるのかもしれないなどの情報もあるので、気を付ける必要がありそうです。

## おわりに

DirectXは昔から苦労していますが、私の場合は必要に応じて時々機能を追加するというスタイルなので、どうにも記憶違いが多く、毎回何かにハマります。

同じようにハマった方の参考になれば幸いです。
フリップフロップ回路

# メモリセル
メモリセルとは、```半導体メモリにおいて情報を記憶、読み書きする最小単位となる回路構成```のこと。メモリチップは半導体基板上に微細な大量のメモリセルと配線を敷き詰めた構造となっている。
# 出典
https://e-words.jp/w/%E3%83%A1%E3%83%A2%E3%83%AA%E3%82%BB%E3%83%AB.html#:~:text=%E3%83%A1%E3%83%A2%E3%83%AA%E3%82%BB%E3%83%AB%E3%81%A8%E3%81%AF%E3%80%81%E5%8D%8A%E5%B0%8E%E4%BD%93%E3%83%A1%E3%83%A2%E3%83%AA%E3%81%AB%E3%81%8A%E3%81%84%E3%81%A6%E6%83%85%E5%A0%B1%E3%82%92%E8%A8%98%E6%86%B6%E3%80%81%E8%AA%AD%E3%81%BF%E6%9B%B8%E3%81%8D%E3%81%99%E3%82%8B%E6%9C%80%E5%B0%8F%E5%8D%98%E4%BD%8D%E3%81%A8%E3%81%AA%E3%82%8B%E5%9B%9E%E8%B7%AF%E6%A7%8B%E6%88%90%E3%81%AE%E3%81%93%E3%81%A8%E3%80%82%E3%83%A1%E3%83%A2%E3%83%AA%E3%83%81%E3%83%83%E3%83%97%E3%81%AF%E5%8D%8A%E5%B0%8E%E4%BD%93%E5%9F%BA%E6%9D%BF%E4%B8%8A%E3%81%AB%E5%BE%AE%E7%B4%B0%E3%81%AA%E5%A4%A7%E9%87%8F%E3%81%AE%E3%83%A1%E3%83%A2%E3%83%AA%E3%82%BB%E3%83%AB%E3%81%A8%E9%85%8D%E7%B7%9A%E3%82%92%E6%95%B7%E3%81%8D%E8%A9%B0%E3%82%81%E3%81%9F%E6%A7%8B%E9%80%A0%E3%81%A8%E3%81%AA%E3%81%A3%E3%81%A6%E3%81%84%E3%82%8B%E3%80%82

# フリップフロップ回路
* 現在の入力と、過去の入力（保持されている値)の両方によって出力が決定する回路。
    レジスタ、SRAMなどに使われる。
# 出典
https://gihyo.jp/book/2022/978-4-297-12375-8

* １ビットの情報を記憶し、時間の推移に伴って二つの安定状態を持つ順序回路です。
    キャッシュメモリやレジスタなどに使われています。

# 出典
https://gihyo.jp/book/2022/978-4-297-13178-4

# 図
https://www.renesas.com/jp/ja/support/engineer-school/digital-circuits-03-sequential-logic

#
ChatGPT：GPT-4がリリースしたため使ってみた

# GPT-4がリリースしました
有料版（ChatGPT Plusユーザ）限定で「GPT-4」が利用できるようになったため、使ってみました(๑╹ω╹๑ )

# 利用する前に
有料版はクレジットで登録ができるため、初めに登録をお願いします٩( 'ω' )و
月20$で仕事の生産性が改善されるChatGPTというのを考えると、激安だと思います！！
![スクリーンショット 2023-03-15 11.26.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/263017/ee8987d9-e3ac-2207-cba7-1973f3407705.png)

# 利用方法
プルダウンで、「GPT-4」が利用できるため、選択するだけです！
![スクリーンショット 2023-03-15 11.28.34 1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/263017/3ce6c520-fa1d-c8fb-be92-3d6e01da94ae.png)

# 使ってみた
## Default (GPT-3.5)
返信スピードが早いのが特徴的でした。
![スクリーンショット 2023-03-15 11.34.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/263017/5c2028e1-e936-8895-3da5-3d3df0fab244.png)
![スクリーンショット 2023-03-15 11.35.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/263017/e341a98d-4714-2706-647d-e2da9872c6b4.png)
![スクリーンショット 2023-03-15 11.41.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/263017/91a3b1b5-f87c-091f-d3fe-84b872b8815b.png)


## GPT-4
「GPT-3.5」より、返信スピードは少し遅いですが、特別気にならないスピードです。
簡潔にまとまってるように見えましたが、まだ比べ足りないところもあるため、今後使っていきたいと思います！
![スクリーンショット 2023-03-15 11.36.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/263017/4e173824-9b02-856a-fca5-24828bd8f06f.png)

# 最後に
仕事でChatGPTを使い始めて、生産性の向上やスキルアップにつながりました！
ChatGPTと検索を併用することで、技術スキルの獲得も早くなるため、有効活用してください(☝︎ ՞ਊ ՞)☝︎
Spring Framework 5.3.14 更新内容

Spring Framework 5.3.14 は、2022年3月にリリースされました。主な更新内容は以下の通りです。

JDK 17.0.2 への対応
Spring Framework 5.3.14 は、JDK 17.0.2 に対応しています。

Jackson ライブラリの更新
Jackson ライブラリが 2.13.0 に更新されました。これにより、新しい JSON バージョン 3.0 のサポートが追加されました。

コンポーネントのアップグレード
以下のコンポーネントがアップグレードされました。

Reactor 3.4.14
Kotlin 1.6.10
Netty 4.1.70
その他の改善点
その他、細かなバグ修正や改善点が含まれています。具体的には、以下のようなものがあります。

Spring Data MongoDB 2.3.7 に対するサポートが向上しました。
WebFlux の CORS サポートが改善されました。
JPA のバッチ操作が、PostgreSQL でのシーケンス生成戦略をサポートするようになりました。
Spring Framework 5.3.14 では、Apache Cassandra 4.13.0 がサポートされます。
以上が、Spring Framework 5.3.14 の主な更新内容です。
Springboot バージョンアップ　２.4から２.5

Spring Boot 2.6 において、特に重大な脆弱性が報告されているわけではありません。ただし、2.5 から 2.6 へのアップグレードにより、いくつかの潜在的な問題が発生する可能性があるため、注意が必要です。

具体的には、以下のような問題が報告されています。

ライブラリの更新による互換性の問題
Spring Boot 2.6 では、依存しているライブラリのバージョンが更新されています。このため、アップグレードによって互換性の問題が生じる可能性があります。特に、以下のライブラリの更新に注意が必要です。

Spring Framework 5.3.14 への更新
Tomcat 9.0.56 への更新
Jetty 9.4.46 への更新
自動構成の変更による影響
Spring Boot 2.6 では、自動構成に関する変更があります。例えば、次のような変更があります。

デフォルトで @ControllerAdvice アノテーションを持つ Bean が自動検出されなくなりました。
デフォルトで @TransactionalEventListener アノテーションを持つ Bean が自動検出されなくなりました。
デフォルトで、ServerProperties に定義されたプロパティ値を使用するように Tomcat が構成されるようになりました。
これらの変更により、アップグレード後にアプリケーションが正常に動作しなくなる可能性があります。したがって、アップグレード前に変更点を確認し、必要に応じて修正を行うことが重要です。



Spring Boot 2.6 では、以下の機能が推奨されなくなりました。

Spring Boot の Maven プラグインによるアプリケーションのパッケージング
これまで、Spring Boot では、Maven プラグインを使用してアプリケーションをパッケージングしていました。しかし、Spring Boot 2.6 からは、この方法が推奨されなくなりました。代わりに、Gradle もしくは Maven Wrapper を使用してビルドすることが推奨されます。

非同期リクエスト処理における Tomcat の旧型スレッドプールの使用
Spring Boot 2.6 では、Tomcat の旧型スレッドプールによる非同期リクエスト処理が推奨されなくなりました。代わりに、Tomcat の NIO 2 モードのスレッドプールを使用することが推奨されます。

Apache CXF による Web サービスのサポート
Spring Boot 2.6 では、Apache CXF による Web サービスのサポートが推奨されなくなりました。代わりに、Spring Web Services または Spring Cloud Contract を使用することが推奨されます。

これらの機能は、今後のバージョンで削除される可能性があるため、できるだけ早く代替手段に移行することが望ましいです。
【Linux】composerインストール手順

# composerインストール手順

## 背景
* 公式ページからインストールを試みたが```Installer corrupt```とエラーが発生しインストールできなかったため。

## 結論
* aptを最新にしたらいけた。


## 手順
### aptのアップデート
```sh
sudo apt update -y
```

### インストーラーのダウンロード
* [公式HP](https://getcomposer.org/download/ "composer公式HP")
```sh
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
```

### インストーラの確認
```sh
php -r "if (hash_file('sha384', 'composer-setup.php') === '55ce33d7678c5a611085589f1f3ddf8b3c52d662cd01d4ba75c0ee0459970c2200a51f492d557530c71c15d8dba01eae') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup. php'); } echo PHP_EOL;"
```
:::note warn
ここで```Installer corrupt```となればOK。```Installer corrupt```となりハマったがapt updateをしたら解決した。
:::

### インストーラーの削除
```sh
php -r "unlink('composer-setup.php');"
```

### composerコマンドを使用できるようにする
```sh
sudo mv composer.phar /usr/local/bin/composer
```

### composerに実行権限をつける
```sh
sudo chmod +x /usr/local/bin/composer
```

### コマンドが使用できるかバージョン確認
```sh
composer --version
```
スプーリング

# スプーリング
プリンタなどの低速の装置に出力する場合、いったん```磁気ディスク装置などの高速補助記憶装置にデータを書き込んでおき後でCPU処理と並列して入出力処理```を行う。
一時的な出力領域を```スプール(SPOOL)```といい、スプールを使った入出力を```スプーリング```という。

これにより```CPUを早く解放することが可能になり、複数のジョブから要求に効率よく応えられる```。

# 出典
https://gihyo.jp/book/2022/978-4-297-12375-8
自分的TypeScript型定義まとめ

# 関数
**◎戻り値が無い関数の型定義にはvoidを用いる。**
**◎voidはundefinedの上位型として扱われる。**

```
function hoge(): void { 

 ~処理~

}
```

戻り値がない関数の場合、関数から戻る値はundefinedになる。


例)
ボタンをクリックしてクラスの付け外しをする処理や、アコーディオンの処理などの関数に戻り値は無いので、基本的に「**:void**」をつけてvoid型を定義する。



# セレクタへの型定義

**◎変数宣言時、「**HTMLElement | null**」で一度変数を初期化する。**
**◎HTMLコードの解析までは出来ない**

```
const a = document.querySelector('a') 
// => HTMLAnchorElement | null 型

const div = document.querySelector('div')
// => HTMLDivElement | null 型

const input = document.querySelector('input')
// => HTMLInputElement | null型

もっと上位の大枠の型
const hoge = document.querySelector(‘.’p-hoge)
// => HTMLElement | null型
```

# 型キャスト
**◎「**as HTMLElement**」など「**as**」で型を指定する。**
**◎「**＜HTMLElement＞**」などを前に付ける。**



```
const hoge = <HTMLInputElement>document.getElementById(‘hoge’);
もしくは
const hoge = document.getElementById(‘hoge’) as HTMLInputElement;

hoge.value = ‘こんにちは’; 　//hogeでvalueプロパティが利用可能
```

 例) 
idで取得したセレクターのvalueを使用しようとすると、「プロパティ 'value' は型 'HTMLElement' に存在しません。」というエラーが発生してしまう。

解決法)
hoge変数を「＜HTMLInputElement＞」もしくは「as HTMLInputElement」で型キャストして、hoge変数は「.value」プロパティが使える変数だよ、ということを宣言してあげる必要がある。


# undefinedとnullの違い
**◎nullは初期化時などに宣言しない限り、自然発生しない。
◎基本的にundefinedを利用する。
◎変数の初期化時にnullを利用するのはその限りではない。**
Springboot バージョンアップ　２.4から２.5

一般的に、Spring Boot の新しいバージョンにアップグレードする場合、脆弱性の問題が発生する可能性があります。しかし、Spring Boot 2.4 から 2.5 にアップグレードする場合、重大な脆弱性の問題は報告されていません。

ただし、Spring Boot 2.5 には、新しい機能や改善点が多数含まれています。そのため、アップグレードを検討する場合は、以下の点に留意することが重要です。

Spring Boot 2.5 では、Java 16 をサポートしています。Java 16 に移行する場合、Java 16 での動作を確認する必要があります。

Spring Boot 2.5 には、Spring Framework 5.3.8 が含まれています。Spring Framework 5.3.8 には、Spring Framework の重大な脆弱性が修正されています。したがって、Spring Framework のバージョンアップグレードも検討することが推奨されます。

Spring Boot 2.5 には、推奨されなくなった機能が含まれています。これらの機能を使用している場合、アップグレードすることが推奨されます。

アップグレードに伴って、既存のアプリケーションで互換性の問題が発生する可能性があります。そのため、アップグレード前に十分なテストを実施することが重要です。

以上の点に留意し、アップグレードを検討することをお勧めします。


Spring Framework 5.3.8 は、2021年5月にリリースされた Spring Framework のメンテナンスリリースです。主な修正点は以下のとおりです。

Security の改善
Security の OAuth 2.0 クライアントサポートにおいて、PKCE の改善が行われました。
Security の OAuth 2.0 クライアントサポートにおいて、Spring Security との統合が改善されました。
WebFlux の改善
WebFlux において、リクエストの前処理と後処理に関する機能が改善されました。
WebFlux において、HTTP サーバーのタイムアウトに関する機能が改善されました。
Data Access の改善
Spring Data の MongoDB サポートにおいて、MongoDB のバージョン 4.4 に対応しました。
JDBC のバッチ更新に関する機能が改善されました。
その他の改善
Spring Core において、Kotlin のサポートが改善されました。
Spring の Web サポートにおいて、静的ファイルの配信に関する機能が改善されました。
以上が、Spring Framework 5.3.8 の主な修正点です。このリリースでは、主にセキュリティと WebFlux に関する機能が改善されています。


Spring Framework 5.3.8 では、いくつかの重大な脆弱性が修正されています。具体的には、以下の2つの脆弱性が修正されています。

CVE-2021-22122: Spring Framework のログレベルの調整ができる場合、攻撃者がログインファイルに機密情報を書き込むことができる脆弱性
この脆弱性は、Spring Framework のログレベルを調整できる場合に発生します。攻撃者は、ログインファイルに機密情報を書き込むことができます。Spring Framework 5.3.8 では、ログレベルの調整に関する機能が改善され、この脆弱性が修正されました。

CVE-2021-22121: Spring Framework のリクエストパラメーターに対する DoS 攻撃が可能な脆弱性
この脆弱性は、Spring Framework のリクエストパラメーターに対して行われる DoS 攻撃によって発生します。攻撃者は、リクエストパラメーターを多数送信することで、アプリケーションを停止させることができます。Spring Framework 5.3.8 では、リクエストパラメーターの処理に関する機能が改善され、この脆弱性が修正されました。

これらの脆弱性は、Spring Framework を使用しているアプリケーションにとって重大な脅威となり得ます。したがって、可能な限り早急に Spring Framework 5.3.8 へのアップグレードが推奨されます。


Spring Boot 2.5 では、以下のような推奨されない機能があります。

非推奨の機能
Spring Boot 2.5 では、以下の非推奨の機能が除去されました。

EmbeddedServletContainerFactory インターフェース
EmbeddedServletContainerCustomizer インターフェース
EmbeddedWebApplicationContext クラス
EmbeddedWebServer クラス
EmbeddedWebApplicationContext クラス
EmbeddedWebServerFactoryCustomizerBeanPostProcessor クラス
これらの機能は、代わりに WebServerFactoryCustomizer インターフェースを使用することが推奨されています。

アプリケーション起動時の挙動の変更
Spring Boot 2.5 では、以下のようなアプリケーション起動時の挙動の変更があります。

アプリケーション起動時に、@SpringBootApplication アノテーションが付与されたクラスがあるパッケージの外にあるコンポーネントを自動的に検出するようになりました。
アプリケーション起動時に、@ConfigurationProperties アノテーションが付与されたクラスのバリデーションが行われるようになりました。
これらの変更によって、アプリケーションの起動やコンポーネントの検出に影響を与える可能性があります。したがって、アップグレード前に変更点を確認し、必要に応じて修正を行うことが重要です。
BigQueryのviewでは期間指定関数が使えない

## BiqQueryのviewとは
viewはSQLクエリによって定義される仮想テーブル
クエリを記述することで元となるテーブルから必要なデータだけを取り出した
「テーブルのようなもの＝ビュー」

## viewを使うメリット
作成したクエリ結果をコンソール上で簡単に保存可能
保存したviewはテーブルと同じように扱えるためクエリ労力が減る
データの定義変更する際、テーブルはデータの置き換えが必要だが、viewの定義はもととなるクエリを書き換えるだけで変更可能

※毎日、毎月定期実行するようものをビューとして保存して使うのが一般的

## テーブルでは出来てviewでは出来ない期間指定関数
日付を跨いだ期間指定が出来ない
例えばviewが日付ごとに分かれていたとした場合
`test-yy.views_000000.events_20230101`
`test-yy.views_000000.events_20230102`
`test-yy.views_000000.events_20230103`
これら3日間の合計ユーザー数を知りたい場合は
```
_TABLE_SUFFIX BETWEEN "20230101" AND "20230103"
```
を指定して集計すれば問題ないが、

viewでは
```
_TABLE_SUFFIX BETWEEN "YYYYMMDD" AND "YYYYMMDD"
```
が使用できない


:::note info
3日間のユーザー数を集計する方法は2通り
・viewをテーブル化する（テーブル作成権限がある場合に限る）
・UNION ALLで3日間分のデータを繋げる
:::

## 結論
viewデータでしか権限を貰えていない場合は何故テーブルで貰えないかを確認した方が良い
参照権を与えたくないカラムがある為のみであれば（個人情報を閲覧させたくない等）

:::note warn
検討案1：マスク処理したテーブルを新しく作る
マスク処理したテーブルを別途作りマスク済みのカラムを閲覧。
ロードしたテーブルとは別に個人情報ををマスクした値を適用したテーブルを作る。
この方法だとポリシータグと併用はでき、データ基盤でデータレイクの役割は担える一方で、テーブルの実体が増えるので管理が煩雑に。
:::
:::note warn
検討案2：元テーブルにマスク済みのカラムを新しく追加する
元のデータは残したままテーブルにマスクしたカラムを追加する案です。元データは残し、カラムレベルのアクセス制御を行った状態のまま利用者にマスクしたカラムを閲覧。
:::


## どうしてもviewでしか参照権を貰えない
スケジュールクエリ等でviewをテーブル化することが賢明

```
DECLARE yesterday INT64;
SET yesterday = (SELECT CAST(FORMAT_DATE("%Y%m%d",CURRENT_DATE() -1) as INT64));

EXECUTE IMMEDIATE format("""

  CREATE OR REPLACE TABLE
    `myproject_name.mydataset_name.copy_from_view_%d` AS (

    SELECT
      *
    FROM
      `tenzin_project_name.tenzin_dataset_name.events_%d`
    )

""", yesterday,yesterday);
```