OmniAICreator/Qiita-1.07M huggingface dataset:
ユニットテスト導入のメリット・デメリットまとめ

# はじめに

株式会社ナイトレイの和田です。
普段、自社サービスの開発に取り組んでいます。
現在私が関わっているプロダクトにユニットテストを導入しました（そのプロダクトではユニットテストが省略されていました）。
その際に、改めてユニットテストのメリット・デメリットを学んだので、それをまとめたものをここに共有します。

# メリット

## ①バグによるダメージを減らせる

### 早期発見

一般的に、不具合が発生した時の改修コストは、発見が遅れるほどに上がっていく。

例えば、リリース前に見つかるのとリリース後に見つかるでは改修の影響範囲やユーザーへの対応含め大きな差がある。逆に言えばQA段階ならもっとコストが下がり、手元での動作確認時ならさらに下がり、コードレビュー段階ならさらに…

テストコードは開発段階で不具合を発見することに貢献してくれるため、改修コストが最小で済む。

### 原因特定

テストコードが書かれていれば、どこが壊れてどこが正常なのかという問題の切り分けができるので、問題箇所の特定がしやすくなる。結果的に不具合の解消を早めることができる。

### 減少

コーナーケースを明示的にテストコードに落とすことで、バグの減少に繋がる。
境界値がバグ発生率が一番高い。

## ②疎結合なシステムに開発が進む

テストを設計することで、クラスやメソッドがテストしやすい形になり、自然と機能間の結合度を下げる効果を期待できる。

コードを単体テストするためには機能（クラスやメソッド）を役割ごとに分離し、DBなど外部システムから可能な限り切り離し、外から結果を確認できるようにする必要がある。

その結果、クラスやメソッド同士に余計な依存関係が生まれず、結合度が下がる。
結合度が下がるとシステムの保守性や拡張性も向上し、バグ修正や機能追加もしやすくなるというメリットがある。

## ③リファクタリングの促進

テストがあることによって、変更後も変更前と同じ動作をするかコードベースで簡単に検証ができるので、リファクタリングというアクションを起こしやすい。

もしテストがない場合、振る舞いが変わっていないことを保証できないため、開発者は思わぬバグを恐れ手をつけなくなってしまう。

## ④****コードリーディングの効率を上げる****

テストコードがあると、実際の使用例を見ることできるので、仕様やコードの役割への理解を助け、深めてくれる。

例えば、あるメソッドはマイナス値を許容するのか、最大値・最小値は存在するのか、どのような結果が返却されるのか、テストを読むことで理解することができる。

# デメリット

## ①コストがかかる

最低でも書かない場合の2倍の工数は見積つもる必要がある。
テストを実施するにあたって、例えば以下の作業が発生する。

- **テストの準備**
    - テストに関する知識の習得
        - テストをするにも一定量の知識とスキルが必要
    - テストケースの作成
        - 前提条件
        - 手順
        - 入力値
        - 結果
    - テストDBの用意
        - 必要であれば作成する
- **テストコードを書く**
- **テストコードのメンテナンス**
    - テスト対象のコードが変更された場合、それに伴ってテストコードも修正しなければならない可能性がある

## ②テストの品質はスキル次第

テストの品質は、テスト実施者のスキルにより大きく左右する。

効果的なテストを実施するには、不具合が起こりやすい条件を想定したテストコードの作成やパラメーターの設定を行うことが重要となるが、それには一定以上のスキルが必要不可欠。

## ③費用対効果に見合わないケースがある

例えばチームやプロダクトが以下のような状態である場合、ユニットテストの効果が発揮しにくい

- **開発チームがあまりにも変動的**
    - テストコードのメンテナンスコストが高くなるため
- **プロトタイプのように寿命の少ないプロダクト**
    - ユニットテストは自動化され、何度も実行するからこそ、テストコードを書くコストが回収できる
    - 1回だけテストを行うだけならば手動テストの方が効率がよい場合もある
- **リリースが長期スパン**
    - 手動テストのコストが相対的に小さくなるため、テストを自動化するメリットが小さくなる

# 参考

**メリット**

[テストコードは必要か？（自動テスト・テスト駆動開発<TDD>について考える）](https://zenn.dev/yuulab/articles/45dc33feaada62)
[「TDD」と「テストコード」。同じ“テスト”でも全然違います〜エンジニアが語る技術愛 ＃04〜](https://mixil.mixi.co.jp/people/12608)

**デメリット**

[単体テストとは？メリット・デメリットやテスト手法を詳しく解説](https://products.sint.co.jp/obpm/blog/unit-test)
[ユニットテストにまつわる10の勘違い](https://dev.classmethod.jp/articles/10_errors_about_unit_testing/)

# 最後に

# 最後に
私たちの会社、ナイトレイでは一緒に自社開発のWebサービスを盛り上げてくれるエンジニアメンバーを募集しています！ 
基本的には直接ユーザーと接することのないポジションですが、セールス部門から
「顧客の声」を教えてもらったり、希望すればユーザーとのMTGに参加することも可能です。
モチベーションの高め方はあなた次第。

このような方は是非Wantedlyからお気軽にご連絡ください（もしくはこちらまで recruit@nightley.jp ）

 ✔︎ 自社Webサービスの開発で事業の発展に携わってみたい
 ✔︎ 自分が開発したサービスで地域活性化に貢献したい
 ✔︎ 位置情報ビッグデータに興味があり、新しい活用方法を提案したい
 ✔︎ 地理や地図が好きで仕事中も眺めていたい 

一つでも当てはまる方は是非こちらの記事をご覧ください 
「受託開発一切なし！自社WEBサービスを社長やセールスチームと一緒に開発！」 https://www.wantedly.com/projects/467606 

▼ナイトレイとは？

https://www.wantedly.com/companies/nightley
[Houdini学習6日目]別ジオメトリ内のノードのパラメーターを参照先に指定できるのか??

別ジオメトリ内のノードのパラメーターを参照先に指定できるのか??
```
◆Tree構造
obj
　・geo1
　　　└box1
　・geo2
　　　└box1
```

例えば、上記のような別々のジオメトリで作成したオブジェクトを並列で配置した際、
オブジェクト1のX軸のサイズが変化したら、オブジェクト2の配置も連動して移動してほしいということはあると思う。

ではその場合、geo2のbox1のCenterのx軸にはどんなパスを記載したらいいのだろうか？

## 疑問に思った背景
Webサイトを作るとき、
例えば下記のようなフォルダ構成で、サイト上に画像を埋め込むために
sample.htmlに
`<img src="../img/image.png">`
と記載することはよくある。
```
Aフォルダ
　└imgフォルダ
　　　└image.png
　└srcフォルダ
　　　└sample.html
```

[Houdiniの公式サイト](https://www.sidefx.com/ja/docs/houdini/expressions/ch.html)でパスの記載方法を見ても記載がなかったので試してみた。



## 実施方法
参照元パラメーターを右クリック⇒Copy Parameterでコピーし、
参照先パラメーターを右クリック⇒Paste Relative Referencesで自動的に参照パスが作られる方法で確認。

## 結果
`ch("../../geo1/box1/sizex")`

できた！

ただ、sizexというのが最下層の扱いになるのか、2つ階層をあがるパスになるのが驚きでした。
それにしても自動作成は便利！！
Falco Ruleを紹介するシリーズ - Launch Privileged Container

本シリーズでは、ランタイム脅威検知のデファクトスタンダードである<a href=https://falco.org/ target=new>Falco</a>の検知Ruleを、１つの記事で１つ簡単に紹介していきます。
ランタイムセキュリティやFalco自体の概要を知りたい方は<a href=https://sysdig.jp/blog/intro-runtime-security-falco/ target=new>こちらのブログ記事</a>をご参照ください。
今回ご紹介する検知Ruleは<b>「Launch Privileged Container」</b>です。
# Rule記述
```
- rule: Launch Privileged Container
  desc: Detect the initial process started in a privileged container. Exceptions are made for known trusted images.
  condition: >
    container_started and container
    and container.privileged=true
    and not falco_privileged_containers
    and not user_privileged_containers
    and not redhat_image
  output: Privileged container started (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline %container.info image=%container.image.repository:%container.image.tag)
  priority: INFO
  tags: [container, cis, mitre_privilege_escalation, mitre_lateral_movement]
```
# Rule概要
特権コンテナで最初のプロセスが起動したことを検知します。
セキュリティの基本原則として、「最小特権の原則」があり、コンテナに対しても本来の目的に必要な最低限の権限しか与えないようにすることが重要です。
Sysdig Japanのブログ記事の中で最も人気のある<a href=https://sysdig.jp/blog/dockerfile-best-practices-2/ target=new>「Dockerfileのベストプラクティス Top 20」</a>の一番最初の項目としても記載されています。
例外として定めていない特権コンテナが起動した場合には、このRuleを使うことで検知可能です。

# Condition（条件）
`container_started and container`
コンテナ内で最初のプロセスが起動し、

`and container.privileged=true`
特権コンテナが有効となっていて

かつ

`and not falco_privileged_containers`
Falcoが定義した特権コンテナではなく、

`and not user_privileged_containers`
ユーザが定義した特権コンテナでもなく、

`and not redhat_image`
あらかじめ定義されたRed Hatイメージでもない場合

# Output（出力）
特権コンテナが起動しました。

`%user.name`
ユーザー名

`%user.loginuid`
ユーザーのログインUID

`%proc.cmdline`
コマンドライン

`%container.info`
コンテナ情報

`%container.image.repository`
コンテナイメージリポジトリ

`%container.image.tag`
コンテナイメージタグ
vue/multi-word-component-namesのエラー解消

## はじめに
初めてVueを触ってみようと思い、下記の記事を参考にさせていただきました。
[Vue.js を vue-cli を使ってシンプルにはじめてみる](https://qiita.com/567000/items/dde495d6a8ad1c25fa43)
その際のエラー解消に時間がかかってしまったので備忘録として残しておきます。


## 遭遇したエラー

```terminal
ERROR in [eslint] 
/my-project/src/components/myheader.vue
  1:1  error  Component name "myheader" should always be multi-word  vue/multi-word-component-names

✖ 1 problem (1 error, 0 warnings)
```

## エラーメッセージの原因
コーポネント名が単一語であるためエラーで弾かれてしまったようです。

これは[スタイルガイド]の[vue/multi-word-component-names]にあるように、将来的に他の要素と競合しないよう設定されたルールのようです。一部を除き、コーポネント名は常に複数語で命名しなければいけません。

```javascript
/* ✓ GOOD */
Vue.component('todo-item', {
  // ...
})

/* ✗ BAD */
Vue.component('Todo', {
  // ...
})
```



## 対応するか否か

本来であればエラーメッセージ通りの命名規則に従っても良いのですが、このままだと不便なことが多いと思います。
今回は[vue/multi-word-component-names]のルールをオフにすることで対応することにしました。


## ESLintのルールを設定する方法
ESLintの設定を作成する方法は大きく分けて、下記の２種類あるようです。

- `package.json`内の`eslintConfig`プロパティを利用する
- プロジェクトのルートディレクトリに設定ファイルを作成する


https://eslint.org/docs/latest/user-guide/configuring/configuration-files#configuration-file-formats


### package.json内のeslintConfigプロパティを利用する

今回はプロジェクト作成時にVue3のバージョンでインストールしているので、プロジェクト直下の`package.json`内の`eslintConfig`プロパティに記述を行います。

エラー原因となった[vue/multi-word-component-names]のルールを無視する設定を行うため、下記の記述を追加しました。


```json:package.json
    "rules": {
      "vue/multi-word-component-names": "off"
    }
```

### プロジェクトのルートディレクトリーに設定ファイルを利用する

今回はこちらの方法を利用しませんでしたが、`.eslintrc.js`などのファイルをルートディレクトリに作成し、記述を追加することでESlintの設定を管理できます。

```javascript:.eslintrc.js
    'rules': {
      'vue/multi-word-component-names': 'off'
    }
```

## あとがき
今回ハマってしまった原因は、`package.json`内の設定を変更する必要があった（プロジェクトを作成する際に`.eslintrc`を参照する形にしていなかった）ことに気づくのが遅かったことです。公式ページを見ればすぐに解決する事案だっただけに悔しい...
初めて触る言語などは公式ページなどをしっかり確認しつつ進めることが大事ですね...!

[スタイルガイド]: https://jp.vuejs.org/v2/style-guide/
[vue/multi-word-component-names]: https://jp.vuejs.org/v2/style-guide/#%E8%A4%87%E6%95%B0%E5%8D%98%E8%AA%9E%E3%82%B3%E3%83%B3%E3%83%9D%E3%83%BC%E3%83%8D%E3%83%B3%E3%83%88%E5%90%8D-%E5%BF%85%E9%A0%88
【イベント】「今年こそは継続的にアウトプットすると決めた方向けに語る技術発信の取り組み方」での学びをまとめる

# はじめに
https://techplay.jp/event/866808?utm_source=eventEnquete&utm_medium=email&utm_campaign=tp_20220825

私自身、アウトプットの仕方について悩んでいたのでとても参考になるイベントでした。
スピーカーの御三方がお話しされていた内容を軽くまとめていこうと思います。
# 技術記事を書くメリット

- 他のエンジニア（コミュニティ）に記事を通して価値を提供できる
- 自分の勉強になる
    - 自分がよくわかっていなかったことが浮き彫りになる
    - 読者からのフィードバックがもらえる
- 知名度や信頼が得られる
    - twitterのフォロワーが増えた(やめ太郎さん)
- 楽しい
- 転職の際ポートフォリオとして使える
    - 技術記事からその人の人となりが見えてくる
    - 面接という短い時間では伝えきれないような、自分のいいところを「見える化」できる

# 間違った記事を書かないために

- タイプミスやリンクミスを公開前にチェックする。できれば自分だけでなく、他の人にもチェックしてもらう
- 信頼できる情報源を参考にする
- 専門用語など言葉の使い方に気を配る
- 普遍的な正しさではなく、局所的な正しさを語る
    - 「特定のバージョンでは」こう動きますみたいに、話題にしている対象を特定する(狭める)
- 「この記事は間違えている！」と勘違いされないように、記事の前提を書く
    - ex) 「良いコードの書き方」 良いコードとは何か？など

# 初心者の情報発信のやり方

- 記事の正しさにはちゃんとこだわる
- そもそも正しい、間違いみたいな議論になりにくい発信から始めるのもいい
    - 勉強会やカンファレンスに参加した感想
    - 自分なりのこだわり
    - インストール、作業ログ
- 最初は他の人の役に立てなくてもいいので、自分の成長やフィードバックを狙った記事を書く
- 防御呪文を使う
    - 「以下の内容には誤りが含まれる可能性があります」
        - 読む人も注意して読むことができる
    - 「と思います」
        - 客観的事実ではなくて、主観的な意見・推測であることを示せる

# 記事の独自性、新規性について

### 他の人がもうすでにいい記事を書いてしまっている、、、

→ 　大事なことは誰が何回書いてもいい

### 新規性のある記事を書くには

- （わかりにくい話題を噛み砕いたりして）わかりやすい記事にする
- 即効性はないが将来性のある最新情報を記事にする
- マニアックな情報を記事にする
- 英語でしか手に入らない情報を日本語に翻訳する

(この辺りの話をパネルディスカッションしていたが、子供が乱入してきて全然聞けなかった、、、、)

# 継続して技術発信するには

- 自分にとって書きやすい書き方を見つける
- 無理して書かない
    - 技術発信が辛くならないようにする
- LT駆動発信
    - LT会を探して登壇の予約をしてしまうことで、技術発信をしなければならない状態をあえて作り出す
- twitterを利用する方法（twitter駆動発信？）
    - 学びをtwitterに発信していき、ある程度溜まってきた段階で記事にする
    - 自分専用のハッシュタグをつけると、対象ツイートを探しやすいので後々まとめるときに便利

# Qiita、Zenn、自分のブログの使い分け

パネルディスカッションにて出ていた意見をまとめる。

 Zenn

- 知識系(uhyoさん)
- 真面目な技術記事を求めている人向けの記事(うさみさん)

 Qiita

- 時事ネタ(uhyoさん)
- ネタ記事(uhyo うさみさん)
- 多くの人に見てもらいたい記事(うさみさん)

ブログ

- 自分の思想(uhyoさん)

# まとめ
自分の技術ブログを作ろうかなあと思っていたので、発信媒体の棲み分けは特に参考になりました。

正しい内容の記事を書くことを大前提としつつ、楽しみながら技術記事を書いていこうと思います。

# 資料
- uhyoさん

https://speakerdeck.com/line_developers/writing-technical-articles-as-you-like

- 無職やめ太郎さん

https://qiita.com/Yametaro/items/1f096e08e7a387ae3792?utm_content=bufferdb784&utm_medium=social&utm_source=twitter.com&utm_campaign=buffer
Salesforce認定アドミニストレーター試験の公式練習問題を解説してみた-その004

こんにちは。本橋孝昭です。

Salesforce認定アドミニストレーター試験の公式練習問題があるのはご存じでしょうか。
Trailheadにフラッシュカードとして何度も解ける練習問題がございます。

今回はTrailhead
アドミニストレーター認定の準備: 構成、設定とオブジェクト
構成と設定の学習　にある練習問題4問目をご紹介します。
https://trailhead.salesforce.com/ja/content/learn/modules/administrator-certification-prep-setup-and-objects/study-up-on-org-setup

なお、こちらの内容はYouTubeでも公開しております

https://www.youtube.com/watch?v=4OzzVqmGeqo
<iframe width="560" height="315" src="https://www.youtube.com/embed/4OzzVqmGeqo" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>



練習問題4問目はこちらです

![004.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/1f0934ed-e1c5-b887-342f-a47a4f898610.png)


答えのServiceCloudユーザ有効化はユーザとなります


詳細は参考ヘルプをご確認ください
Service Cloud 機能ライセンスのユーザへの割り当て
https://help.salesforce.com/s/articleView?id=sf.console2_assign_service_feature_license.htm&type=5

今日の内容はここまでです。
皆さん楽しく元気にSalesforceを学びましょう！
【nuxtjs】middlewareからredirectするとnavigation guardに阻まれて遷移できない

## 前提
- nuxt.js(2.15.8)
  - SPAのアプリ
  - ログインページ以外は全ページに認証かけていた
## やりたかったこと
- アプリではAPIサーバとのやりとりにaxiosを使っている
- APIサーバから503が返ってきたら、メンテナンスページを表示したかった
```js
if (code === 503) {
  redirect('maintenance') // こんな感じのことをしたい
}
```

## やったこと
- maintenance.vueを作成
- axiosのpluginで応答エラー503が返ってきたらメンテナンスページにリダイレクト（上記コードのイメージ）
- **デバッグ用にapi側は全レスポンスを503返すように設定**

## 動かしてみた結果
```:chrome console
Redirected when going from "/login" to "/maintenance" via a navigation guard.
```

## 原因と解決方法
- 原因
  - 単純な話で、メンテナンスページにも認証をかけてしまっていて、ログイン済みじゃないと表示できないようになっていた
  - なので、とあるページでAPIアクセス→メンテナンスページ→ログインページ→（APIアクセス）→メンテナンスページ... みたいな感じで無限ダイレクトみたいになってたっぽい
- 解決
  - メンテナンスページで `auth: false`を設定してやる
```vue
<script lang="ts">

export default defineComponent({
  auth: false, // <-- これ
  setup() {},
})
</script>
```

## 感想
- 最初はnuxtの不具合みたいのかと思ったけど普通に設定ミスでした。。
Elasticsearchのもやもや: JVMヒープサイズを設定するか設定しないか

### はじめに

Elasticsearchを使っていて、もやもやした内容を、
メモ書きレベルで、思うがまま書いてみます。

### ElasticsearchでJVMヒープサイズを設定する?

Elasticsearchのインストール関連資料を読むと、
JVMヒープサイズ設定は要る、要らない二つの説が。
その違いや使い分けに、モヤモヤ感が。。。

### JVMヒープサイズ設定の要/不要を比較してみた

- JVMヒープサイズとは
    - Elasticsearchを起動する際、JVMサイズのオプション設定
    - OSメモリサイズの半分を割り当てるとよいらしい
    - 最小値(`-Xms`)と最大値(`-Xmx`)を同じサイズにする必要あり(二つに分けた理由は?)

- JVMヒープサイズ設定は不要との根拠
    - [Elasticsearchリファレンス](https://www.elastic.co/guide/en/elasticsearch/reference/current/advanced-configuration.html#set-jvm-heap-size)
        - Elasticsearchがノードロールやトータルメモリにより自動設定する
        - ので、本番環境では気にせずデフォルトのまま使ってね?

```
By default, Elasticsearch automatically sets the JVM heap size
based on a node’s roles and total memory.
Using the default sizing is recommended for most production environments.
```

- JVMヒープサイズ設定は必要との根拠
    - [Kibana画面が応答しない事象](https://qiita.com/mingchun_zhao/items/bf7f056f8fca0d82e0b2)の対処として、デフォルトサイズを変更
    - Elasticsearchが大量にメモリを消費し、システム全体のメモリ枯渇
    - 主に、メモリが潤沢に積まれていない開発環境で発生する模様

- 結論は出ませんが
    - システムのメモリ使用状況をモニタリングした上で
    - JVMヒープサイズを設定するか、設定値はいかに、を決めたほうがよさそうです

### おわりに

ElasticsearchのJVMヒープサイズ設定の要/不要を比較しました。
ケースバイケースなので、もやもや感は残る感じですが。。。
ルータのconfig（IPフィルター）を読んでみた

インフラ（というか機械系や設定系）には正直あまり興味が無いのですが、たまたま仕事でルータのconfigを読む機会があったので**IPフィルター**について解説してみます。
ほぼデフォルトの設定ですが。

## WANからLAN
まず、WANからLANの方向、つまりルータへ入ってくるときのIPフィルターを定義順に見ていきます。
入力フィルターとかINフィルターとも言います。

### 送信元がLAN側アドレスのパケットは破棄

```
ip filter <フィルター番号> reject <LAN側アドレス> * * * *
```

内側で使用しているネットワークが外に存在する筈が無いので、ここで落とします。
**IPスプーフィング攻撃**を防止する意図があります。

### ポート番号が135（WindowsのRPC）のパケットは破棄

```
ip filter <フィルター番号> reject * * udp,tcp 135 *
ip filter <フィルター番号> reject * * udp,tcp * 135
```

Windows系のサービスをインターネット越しに利用することは無いので、ここで落とします。

### ポート番号が137～139（NetBIOS）のパケットは破棄

```
ip filter <フィルター番号> reject * * udp,tcp netbios_ns-netbios_ssn *
ip filter <フィルター番号> reject * * udp,tcp * netbios_ns-netbios_ssn
```

Windows系のサービスをインターネット越しに利用することは無いので、ここで落とします。

### ポート番号が445（SMB）のパケットは破棄

```
ip filter <フィルター番号> reject * * udp,tcp 445 *
ip filter <フィルター番号> reject * * udp,tcp * 445
```

Windows系のサービスをインターネット越しに利用することは無いので、ここで落とします。

### ICMPパケットは通過

```
ip filter <フィルター番号> pass * <LAN側アドレス> icmp * *
```

ICMPパケットは、`ping`やWindowsの`tracert`、エラー通知等に使われます。

### メールサーバ(SMTPやPOP等)の認証用パケットは通過

```
ip filter <フィルター番号> pass * <LAN側アドレス> tcp * ident
```

通過させないと遅くなります。

### VPNパススルー（IPsec）の設定

```
ip filter <フィルター番号> pass * <自ルータのアドレス> udp * 500
ip filter <フィルター番号> pass * <自ルータのアドレス> esp
ip filter <フィルター番号> pass * <自ルータのアドレス> udp * 4500
ip filter <フィルター番号> pass * <自ルータのアドレス> udp * 1701
```

### VPNパススルー（GRE）の設定

```
ip filter <フィルター番号> pass * * tcp * 1723
ip filter <フィルター番号> pass * * gre
```

デフォルトには無いのですが、外部のPPTPサーバに接続するために僕が追加したものです。

## LANからWAN
続いて、LANからWANの方向、つまりルーターから出るときのIPフィルターを定義順に見ていきます。
出力フィルターとかOUTフィルターとも言います。

### 宛先がLAN側アドレスのパケットは破棄

```
ip filter <フィルター番号> reject <LAN側アドレス> * * * *
```

内側で使用しているネットワークが外に存在する筈が無いので、ここで落とします。
**IPスプーフィング攻撃**を防止する意図があります。

### ポート番号が135（WindowsのRPC）のパケットは破棄

INフィルターと定義は同じです。
他のWindows系のサービスも同様なので省略します。

### 回線切断中に発信されるFINパケットは破棄

```
ip filter <フィルター番号> restrict * * tcpfin * www,21,nntp
```

WWWブラウザ終了時発呼を防止する意図があります。

### 回線切断中に発信されるRSTパケットは破棄

```
ip filter <フィルター番号> restrict * * tcprst * www,21,nntp
```

WWWブラウザ終了時発呼を防止する意図があります。

### その他のすべてのパケットは通過

```
ip filter <フィルター番号> pass * * * * *
```

これが無いとDefaultによりすべて破棄されてしまいます。
人事のおじさんプログラミングを学ぶ Day7「while文を使って繰り返す」

書籍『確かな力が身につくJavaScript「超」入門 第2版』に沿って、
While文を使って繰り返してみた。
![2022-08-26 (5).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2783084/ee23b6d3-fc1b-5539-b0ab-4415b6f6ef26.png)
![2022-08-26 (4).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2783084/b38a7832-93dc-c1f5-25d3-e49ceda26f93.png)
最適化法　コロナ社　近藤次郎先生



```r

#微分項を含むの回帰模型
#コスト関数を積分値とすることで特徴量の微分を特徴量として回帰模型を構成できる。
#テイラー展開型
data("cars")

#仮のデータ
Y=c(0,cars$dist)
X=c(0,cars$speed)
t=seq(0,length(X)-1,1)
n=length(X)
data=data.frame(t,Y,X)

#最急降下法
a=1
b=1
eta=10^(-5)
h=1
ite=10^4

for(l in 1:ite){
  
da=-2*sum(X[2:(n-1)]*(Y[2:(n-1)]-a*X[2:(n-1)]-b*(X[3:n]-X[2:(n-1)])/h)*h)  
db=-2*sum((X[3:n]-X[2:(n-1)])*(Y[2:(n-1)]-a*X[2:(n-1)]-b*(X[3:n]-X[2:(n-1)])/h)) 
a=a-eta*da
b=b-eta*db
cost=sum(((Y[2:(n-1)]-a*X[2:(n-1)]-b*(X[3:n]-X[2:(n-1)])/h)^2)*h)
print(cost)  
}

pre=data.frame(t=t[2:(n-1)],Y=Y[2:(n-1)],predict=a*X[2:(n-1)]-b*(X[3:n]-X[2:(n-1)])/h)

#マトリックスによる解法
mat=matrix(c(sum(X[2:(n-1)]^2),sum(X[2:(n-1)]*(X[3:n]-X[2:(n-1)])/h),sum(X[2:(n-1)]*(X[3:n]-X[2:(n-1)])/h),sum((X[3:n]-X[2:(n-1)]/h)^2)),nrow=2)

vec=c(sum(X[2:(n-1)]*Y[2:(n-1)]),sum(Y[2:(n-1)]*(X[3:n]-X[2:(n-1)]/h)))

#係数ベクトル
solve(mat)%*%vec

```

```r

#変分問題における差分解法(ニュートン法)　p.187

h=0.05
a=0
b=1
xa=0
xb=0
n=length(seq(a,b,h))-1
tvec=seq(a,b,h)

#極値法による偏微分した式  
f=function(x){
fval=c(12*tvec[1]*h+2*(x[2]-2*x[1]+xa)/h)
for(j in 2:(n-2)){  
fval=c(fval,12*tvec[j]*h+2*(x[j+1]-2*x[j]+x[j-1])/h)
}
fval=c(fval,12*tvec[n-1]*h+2*(xb-2*x[n-1]+x[n-2])/h)
return(fval)
}


#ニュートン法
X=sample(1:9,n-1,replace=T)/10

ite=10^5
eta=10^(-4)
hh=10^(-5)

for(l in 1:ite){


dF=array(0,dim=c(length(X),length(X))) 
for(j in 1:length(X)){
Xsub=X
Xsub[j]=Xsub[j]+hh
dF[,j]=(f(Xsub)-f(X))/(hh)
}  
 
X=X-eta*solve(dF)%*%f(X)
#print(sum(f(X)))   
}  




plot(tvec[2:(length(tvec)-1)],X,xlim=c(min(tvec),max(tvec)),ylim=c(min(X),max(X)),col=2,xlab="t",ylab="x")

par(new=T)

plot(tvec[2:(length(tvec)-1)],tvec[2:(length(tvec)-1)]-tvec[2:(length(tvec)-1)]^3,xlim=c(min(tvec),max(tvec)),ylim=c(min(X),max(X)),col=3,xlab="t",ylab="x")

cbind(X,tvec[2:(length(tvec)-1)]-tvec[2:(length(tvec)-1)]^3)


```


```r

#変分問題における差分解法(ニュートン法)　p.187
#制約条件付き

h=0.05
a=0
b=1
xa=0
xb=0
n=length(seq(a,b,h))-1
tvec=seq(a,b,h)
S=0.1

#極値法により偏微分した式  
f=function(x){
lam=x[length(x)]
fval=c(12*tvec[1]*h+2*(x[2]-2*x[1]+xa)/h+lam*(2*x[1]*h))
for(j in 2:(n-2)){  
fval=c(fval,12*tvec[j]*h+2*(x[j+1]-2*x[j]+x[j-1])/h+lam*(2*x[j]*h))
}
fval=c(fval,12*tvec[n-1]*h+2*(xb-2*x[n-1]+x[n-2])/h+lam*(2*x[n-1]*h))
fval=c(fval,sum(x[1:(n-1)]^2-S))
return(fval)
}


#ニュートン法
X=sample(1:9,n,replace=T)/10

ite=10^5
eta=10^(-4)
hh=10^(-5)

for(l in 1:ite){


dF=array(0,dim=c(length(X),length(X))) 
for(j in 1:length(X)){
Xsub=X
Xsub[j]=Xsub[j]+hh
dF[,j]=(f(Xsub)-f(X))/(hh)
}  
 
X=X-eta*solve(dF)%*%f(X)
#print(sum(f(X)))   
}  




plot(tvec[2:(length(tvec)-1)],X[1:(n-1)],xlim=c(min(tvec),max(tvec)),ylim=c(min(X),max(X)),col=2,xlab="t",ylab="x")

par(new=T)

plot(tvec[2:(length(tvec)-1)],tvec[2:(length(tvec)-1)]-tvec[2:(length(tvec)-1)]^3,xlim=c(min(tvec),max(tvec)),ylim=c(min(X),max(X)),col=3,xlab="t",ylab="x")

cbind(X[1:(n-1)],tvec[2:(length(tvec)-1)]-tvec[2:(length(tvec)-1)]^3)


```
Log Analytics でテーブルの一覧を表示する

Log Analytics ワークスペースで、データがある全てのテーブルの一覧を表示する方法です。

search オペレーターにワイルドカードを指定し全テーブルから全レコードを取得します。この結果にはレコードが存在していたテーブルを表す $table 列が含まれるので、distinct オペレーターで一意のテーブルの一覧にします。

UI でテーブルを表示することもできますが、テーブルがたくさんあって大変なのと、メタデータだけでデータが存在しないテーブルも表示されてしまうので、このコマンドならデータが存在するテーブルだけを表示することができます。


```KQL
search *
| distinct $table
```

search オペレーターで複数のテーブルを検索する処理は遅いのであまり使いませんが、この組み合わせは結構便利だと思います。
Elasticsearchのもやもや: 文字列のデータ型はtextかkeywordか

### はじめに

Elasticsearchを使っていて、もやもやした内容を、
メモ書きレベルで、思うがまま書いてみます。

### Elasticsearchでtext型とkeyword型のフィールド

Elasticsearchで、文章など文字列を格納/検索する場合、
フィールドデータ型として、textまたはkeywordを使用できます。
その違いや使い分けに、モヤモヤ感が。。。

### text型とkeyword型を比較してみた

- Analyzer(解析)を使って文字列を単語分割するか
    - text: 必要、検索で転置インデックスを使用するため
    - keyword: 不要、文字列全体を一つとして扱う

- 検索方法
    - text: 文字列を分割された単語で全文検索
    - keyword: 文字列を完全一致で検索

- 使用例
    - text: `{ "description": "これはPythonプログラミングの本です。" }`
        - `これ`/`Python`/`プログラミング`/`本`のように単語分割し検索
    - keyword: `{ "email": "test@test.com" }`
        - `test@test.com`のように完全一致で検索

### 同じフィールドを、text型としてもkeyword型としても使用したい

- `マルチフィールド型(multi-fields)`を使用

※ 引用元: https://www.elastic.co/guide/en/elasticsearch/reference/current/multi-fields.html

- マルチフィールド型のマッピング定義
```
PUT index
{
  "mappings": {
    "properties": {
      "city": {
        "type": "text",
        "fields": {
          "raw": { 
            "type":  "keyword"
          }
        }
      }
    }
  }
}
```

- `city`は、keyword型とtext型二つの機能を兼ね備える
    - `city.raw`フィールドでkeyword型を表し、ソートやaggregrationに使用 
    - `city`フィールドでtext型を表し、単語単位の全文検索に使用 

### おわりに

Elasticsearchの文字列を扱うデータ型として、
textとkeywordの違いを理解しました。
【Power Shell】メール送信(Outlook/Gmail)

# Powershellでメール送信
Powershellでメール送信を行う方法を紹介致します。
私は、プログラムの実行結果の取得や特定の時間にメール送信を行いたい場合などに使用しています。

SmtpClient/Send-MailMessageを使った方法を記載しています。

※Send-MailMessageでPort指定を行えない場合は、SmtpClientを使う事があります。
上記二つではなく、現在はMailKit等でメールする方法が推奨されているようです。(職場では諸事情で使えず、、)

下記スクリプトでメールを送信できます。

## SmtpClient

```
$Address = "メールアドレス"  
$Subject = "件名"  
$Body = "本文"  

$SmtpServer = "smtp.office365.com"  Or "smtp.gmail.com"
$SmtpClient = New-Object Net.Mail.SmtpClient($SmtpServer, 587)  
$SmtpClient.EnableSsl = $true
$SmtpClient.Credentials = New-Object System.Net.NetworkCredential($Address, "パスワード")
$SmtpClient.Send($Address, $Address, $Subject, $Body) 
```

## Send-MailMessage

```
$Address = "メールアドレス"
$Subject = "件名"  
$Body = "本文"
$SmtpServer = "smtp.office365.com"  Or "smtp.gmail.com"
$Pass = ConvertTo-SecureString "パスワード"　-AsPlainText -Force
$Credential = New-Object System.Management.Automation.PSCredential $Address,$Pass

Send-MailMessage  `
    -Encoding UTF8 `
    -From $Address `
    -to $Address `
    -subject $Subject `
    -body $Body `
    -smtpServer $SmtpServer `
    -Port 587 `
    -Credential $Credential `
    -UseSsl 
```
【Heroku】 Herokuへデプロイしたアプリのproduction環境のコード内容を確認する

# はじめに
 次のようなときに使用したHeroku CLIコマンドの備忘録
 - Herokuでポートフォリオをデプロイ！
 - development環境では正しく動作しているのに、production環境では違う動作をしている
 - Herokuのproduction環境のコードを確認したい

# 目次
1. [Herokuにデプロイしたアプリを開く](#Chapter1)
2. [Herokuにデプロイしたproduction環境のコードを確認する](#Chapter2)
3. [終了する](#Chapter3) 
4. [参考文献](#reference)

<!-- 各チャプター -->
<a id="#Chapter1"></a>
# 1. Herokuにデプロイしたアプリを開く
``` 
$ heroku open
```

ターミナルからHerokuのproduction環境(https://[アプリ名].herokuapp.com/)へアクセス。
development環境とは異なる挙動をしたため、priduction環境のコードを確認することにしました。

<a id="#Chapter2"></a>
# 2. Herokuにデプロイしたproduction環境のコードを確認する

```
$heroku run bash
```

Herokuサーバー内でbashを起動する。
ローカル環境でターミナルでbashを起動すると同様の操作ができる。


[```$ heroku run```で起動されるHerokuサーバー(One-off dyno)ではシェルはbashとzshをサポートしている。](https://devcenter.heroku.com/ja/articles/heroku-cli-autocomplete#installing-autocomplete)


<a id="#Chapter2"></a>
# 3. 終了する
```
$ exit
```

<a id="#reference"></a>
# 参考文献
- [Heroku CLI のオートコンプリート | Heroku Dev Center](https://devcenter.heroku.com/ja/articles/heroku-cli-autocomplete#installing-autocomplete)
Elasticsearchのもやもや: ドキュメント登録はPOSTかPUTか

### はじめに

Elasticsearchを使っていて、もやもやした内容を、
メモ書きレベルで、思うがまま書いてみます。

### Elasticsearchのドキュメント登録

Elasticsearchの操作は、APIエンドポイントに向かって、
REST APIを用いたリクエストを発行します。

ドキュメント登録リクエストは、HTTPメソッドとして、
POSTまたはPUTを使用できるのは周知のとおりですが、
その違いや使い分けに、モヤモヤ感が。。。

### POSTメソッドとPUTメソッドを比較してみた

- 操作対象のドキュメント
    - POST: `新規`にドキュメントを作成
    - PUT: `既存`のドキュメントが存在したら更新、存在しなかったら`作成`
- ドキュメントIDの指定
    - POST: 不要(サーバーが自動採番してくれる)
    - PUT: 明示的に指定する必要がある
- 同じリクエストを5回実行したら
    - POST: 異なるドキュメントIDでドキュメントが5個作成される
        - 1回目: ドキュメントID=1
        - 2回目: ドキュメントID=2
        - 3回目: ドキュメントID=3
        - 4回目: ドキュメントID=4
        - 5回目: ドキュメントID=5
    - PUT: ドキュメントが1個しか作成されない(ドキュメントID=1)
        - ※ 2回目以降は、作成ではなく、同じドキュメントIDが更新されるのみ
        - 1回目: ドキュメントID=1を作成
        - 2回目: ドキュメントID=1を更新
        - 3回目: ドキュメントID=1を更新
        - 4回目: ドキュメントID=1を更新
        - 5回目: ドキュメントID=1を更新
- ドキュメント登録リクエストのサンプル
```
## POST
$ curl -XPOST 'http://host:port/index' -H 'Content-Type: application/json' -d '
{
    "field1": "value1",
    "field2": "value2",
    ... ...
}'

## PUT
$ curl -XPUT 'http://host:port/index/1' -H 'Content-Type: application/json' -d '
{
    "field1": "value1",
    "field2": "value2",
    ... ...
}'
```

### おわりに

Elasticsearchのドキュメント登録方法として、
POSTメソッドとPUTメソッドの違いが理解できたので、
今後は迷わず使用できそうです。
括弧内の文字列を抽出/削除する(SPSS Modeler データ加工逆引き2-11)

# 括弧内の文字列を抽出/削除(名寄せ)

![スクリーンショット 2022-08-09 10.40.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/9d747ce6-9ecc-f9cc-4adb-c32ba684cbb9.png)

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

・組織名や商品名の名寄せ
・コンタクトセンターログの分析用加工
・設備ログの分析用加工

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

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

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

![スクリーンショット 2022-08-09 10.40.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/1665e780-f0f7-64ef-89c9-4cdf77e6731b.png)

a.入力するデータは以下の通りです。
![スクリーンショット 2022-08-09 10.42.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/ae4f9d44-907b-dc08-8579-72f733f6f85b.png)

#### 括弧内の文字列を抽出する

b.[フィールド作成]ノードを編集します。substring_between(開始文字位置,終了文字位置,フィールド)でフィールドの文字列を抽出できます。locchar関数で文字の位置を示す際にはバッククォートを利用し、開始文字の場合には括弧の次にするために＋1にします。
![スクリーンショット 2022-08-09 10.43.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/2803930e-8ff9-bc19-0c62-e38f2ef86388.png)

式ビルダーの文字列関数を利用すると便利です。
![スクリーンショット 2022-08-09 10.44.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/8c81158b-5870-2ac5-7e35-cc329478468b.png)

c.[フィールド作成]ノードを編集します。substringを使っても同じことができます。
![スクリーンショット 2022-08-09 10.44.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/0abf814c-a658-794b-aaf0-aefb68103d77.png)

substringは以下の記事で扱っています。

https://qiita.com/416nishimaki/items/61cc9ab8685f8559bd3c

[プレビュー]します。
![スクリーンショット 2022-08-09 10.44.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/8a57ac72-7a35-0b11-94c5-9abca049e3bd.png)

#### 括弧を含めて該当する文字列を削除する

d.[フィールド作成]ノードを編集します。bで利用した関数を使って該当文字列特定し、replace("文字列1","文字列2",フィールド)で　空文字に置き換えています。bのノードの後続であればreplace("("><括弧内抽出1><")","", C1)でも同じことになります。
![スクリーンショット 2022-08-09 10.45.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/30607890-3582-a565-ed8a-93765572cad5.png)

[プレビュー]します。1レコード目がスペースから開始されているので除去します。
![スクリーンショット 2022-08-09 10.47.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/8e9836c8-4dd8-2eb6-3892-a8e7c9fdde92.png)

e.[置換]ノードを編集します。
![スクリーンショット 2022-08-09 10.46.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/cf53d3fc-2bce-9216-fdc1-a27b6db6b9be.png)

[プレビュー]します。
![スクリーンショット 2022-08-09 10.48.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/5f2a3126-cc63-c4e4-e145-2d0f800dfd51.png)

#### 注意事項

locchar(`` ` ``(`` ` `` ,1, C1)　ではバッククォートを利用します。

## 4.参考情報

#### よく使う文字列関数

https://qiita.com/Makimaki2020/items/35ab02a7375325e678c1

#### Modelerと正規表現

https://qiita.com/kawada2017/items/025352797a87dd85fbea

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

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

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

https://qiita.com/416nishimaki/private/4bf813e6cba84b2a1008
【Rails】Modelに定義した定数をControllerやViewで使用する方法

## はじめに
どうも、もきおです。RailsでModelに定義した定数をControllerやViewで使用する場面が実務でちょくちょく使う事があり、どうやって参照するんだっけ？と思ったので、調べたのをメモとして残しておきたいと思います。

## 結論
定数を参照するには**Model名(Rubyならクラス名)::定数名**で参照する事ができます。
```ruby:
MAIN_USERS = ["Bob", "Keny", "John", "July", "Karen"].freeze

User::MAIN_USERS
# => ["Bob", "Keny", "John", "July", "Karen"]
```
## 具体例
さて、具体例に入っていきましょう。今回はユーザー登録の際、SNSのURLを入力する欄があるとします。その際、省きたいURLを予め定数として登録しておき、実際入力され渡ってきたURLと定義していた定数が部分一致する場合、バリデーションでアラートを表示するというパターンで記述したいと思います。

まずは良く使うものをmodelに定数定義しましょう。``.freeze``メソッドで変更不可にしています。
```ruby:app/models/user.rb
SNS_URLS = ["youtube.com", "twitter.com", "instagram.com", "tiktok.com"].freeze
```

そしてcontrollerで条件分岐を書いていきます。viewでも書き方は一緒です。

```ruby:
if User::SNS_URLS.any?{ |url| params.require(:user)["url"].include?(url) }
  flash.now[:alert] = "SNSのURLを再度確認してください。"
end
```

条件分岐部分が少し複雑ですが、入力されたURL(``params.require(:user)["url"]``)を定数のURLそれぞれと一つずつ部分一致しているか確認。

``.any?``は一致したものがあった時点でtrueを返すメソッドなので部分一致するURLが見つかった時点でtrue判定になりアラートが表示されるという感じです。

ついでに分解して解説しておくと``{ |url| params.require(:user)["url"].include?(url) }``の部分をブロックで書いてますが、これはループ処理を簡略化して記述しています。

簡略化しないと以下みたいな感じ

```ruby:
# ["youtube.com", "twitter.com", "instagram.com", "tiktok.com"].each do |url| 
User::SNS_URLS.each do |url| 
  if params.require(:user)["url"].include?(url)
    flash.now[:alert] = "SNSのURLを再度確認してください。"
  end
end
```
## あとがき
意外と書き方が想像できなくて当時調べるまで参照の仕方は検討がつきませんでした笑
メモとして将来の自分の役に立つかな？笑

最後までご覧いただき本当にありがとうございました！！

Twitterでも日頃の業務で思ったことを呟いていくのでご覧いただけると幸いです。
[@mokio_50](https://twitter.com/mokio_50)
Rubyを使ってメール通知をしたいだけなのにどハマりした結果

# はじめに

新しくサーバーを構築して、自作Webアプリケーションにメール通知機能を追加したいと思い、簡単にできるだろうと考えていたらハマりました。

# 環境

Ubuntu 22.x.x
Ruby 3.0.x
Postfix 3.6.x

# ソースコード

```rb:mailtest.rb
#!/usr/bin/env ruby

require 'mail'

mail = Mail.new do
  from    "xxxx@xxxx.com"
  to      "yyyy@yyyy.com"
  subject "test mail"
  body    "this is a test mail."
end

mail.delivery_method(:smtp,
  address: "localhost",
  port:    25,
  domain:  "localdomain",
)

mail.deliver
```

# エラーメッセージ

```
$ ./mailtest.rb
/usr/lib/ruby/3.0.0/net/smtp.rb:1015:in `check_auth_response': 503 5.5.1 Error: authentication not enabled (Net::SMTPAuthenticationError)
	from /usr/lib/ruby/3.0.0/net/smtp.rb:776:in `auth_plain'
	from /usr/lib/ruby/3.0.0/net/smtp.rb:768:in `public_send'
	from /usr/lib/ruby/3.0.0/net/smtp.rb:768:in `authenticate'
	from /usr/lib/ruby/3.0.0/net/smtp.rb:604:in `do_start'
	from /usr/lib/ruby/3.0.0/net/smtp.rb:557:in `start'
	from /var/lib/gems/3.0.0/gems/mail-2.7.1/lib/mail/network/delivery_methods/smtp.rb:109:in `start_smtp_session'
	from /var/lib/gems/3.0.0/gems/mail-2.7.1/lib/mail/network/delivery_methods/smtp.rb:100:in `deliver!'
	from /var/lib/gems/3.0.0/gems/mail-2.7.1/lib/mail/message.rb:2159:in `do_delivery'
	from /var/lib/gems/3.0.0/gems/mail-2.7.1/lib/mail/message.rb:262:in `deliver'
	from ./mailtest.rb:18:in `<main>'
```

# 試したこと

以下の設定を追加するといいよと教えてもらって追記したりしました。

```rb
mail.delivery_method(:smtp,
  ...
  ssl: false,
  enable_starttls_auto: false,
  openssl_verify_mode: 'none',
)
```

...ダメでした。

# 結果

Postfixの設定を変更して解決しました。

```
/etc/postfix/main.cf
```

以下のようにTLS関連の設定をコメントアウト。

```
# TLS parameters
#smtpd_tls_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem
#smtpd_tls_key_file=/etc/ssl/private/ssl-cert-snakeoil.key
#smtpd_tls_security_level=may

#smtp_tls_CApath=/etc/ssl/certs
#smtp_tls_security_level=may
#smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
```

変更後にPostfixを再起動

```
$ sudo systemctl restart postfix
```

再度スクリプトを実行。

```
$ ./mailtest.rb
```

できた！！
機械学習環境構築


- おまじない
```:bash
sudo apt update
sudo apt upgrade
sudo apt install build-essential libbz2-dev libdb-dev \
  libreadline-dev libffi-dev libgdbm-dev liblzma-dev \
  libncursesw5-dev libsqlite3-dev libssl-dev \
  zlib1g-dev uuid-dev tk-dev
```


- Nvidia Driver Install

 https://www.nvidia.co.jp/content/DriverDownload-March2009/confirmation.php?url=/Windows/Quadro_Certified/516.94/516.94-quadro-rtx-desktop-notebook-win10-win11-64bit-international-dch-whql.exe&lang=jp&type=Quadro

- CUDA Toolkit Install
最新版

https://developer.nvidia.com/cuda-downloads

旧バージョン（Pytorch との相性をみて決めるかも）

https://developer.nvidia.com/cuda-toolkit-archive

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527627/84976f01-5e8c-d647-5c7f-785613d35597.png)

いまcuda11-6-2を選択する。

```:bash
wget https://developer.download.nvidia.com/compute/cuda/repos/wsl-ubuntu/x86_64/cuda-wsl-ubuntu.pin
sudo mv cuda-wsl-ubuntu.pin /etc/apt/preferences.d/cuda-repository-pin-600
wget https://developer.download.nvidia.com/compute/cuda/11.6.2/local_installers/cuda-repo-wsl-ubuntu-11-6-local_11.6.2-1_amd64.deb
sudo dpkg -i cuda-repo-wsl-ubuntu-11-6-local_11.6.2-1_amd64.deb
sudo apt-key add /var/cuda-repo-wsl-ubuntu-11-6-local/7fa2af80.pub
sudo apt-get update
sudo apt-get -y install cuda
```

- CUDNN Install

 https://developer.nvidia.com/rdp/cudnn-download

Ubuntuのversionを確認してきめる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527627/9073f8b0-770c-92e3-c8f6-aaee9f8a474d.png)

いま、Local Installer for Ubuntu20.04 x86_64 (Deb)を選択する。

```:bash
sudo dpkg -i  /mnt/c/Users/XXXXXX/Downloads/cudnn-local-repo-ubuntu2004-8.5.0.96_1.0-1_amd64.deb
```

- Pytorch Install

https://pytorch.org/



![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527627/90b657fd-7495-d12f-bb61-3d1f1a6164d2.png)

```:bash
pip3 install torch torchvision torchaudio --extra-index-url https://download.pytorch.org/whl/cu116
```

```:python3
import torch

torch.cuda.is_available()
print(torch.__version__)
```


- remove CUDA

```:bash
# Remove existing CuDA versions
sudo apt --purge remove "cublas*" "cuda*"
sudo apt --purge remove "nvidia*"
rm -rf /usr/local/cuda*
sudo apt-get autoremove && sudo apt-get autoclean


```
- remove torch

```
pip uninstall torch
pip install pip-autoremove

```













# 参考文献

https://zenn.dev/utahka/articles/ed881a568246f4
React testing libraryでgetByRoleのnameオプションがうまく動かない

React testing libraryのgetByRoleで同じロール[textbox]が複数存在したので、
nameで絞ろうとしたときうまく取れなかった時の話。

```hoge.test.js
test('renders react component', () => {
  render(<TestText value={"hoge"} name="fuga"/>);
  const divElement = screen.getByRole('textbox',{name: /fuga/i });
  expect(divElement).toBeInTheDocument();
});
```

```.html
<input
  name="fuga"
  value="hoge"
/>
```

以下のエラーになってしまう。
nameがhtmlにあるのにヒットしない？？
```
  ● renders react component
    TestingLibraryElementError: Unable to find an accessible element with the role "textbox" and name `/fuga/i`
    Here are the accessible roles:
```

結論としてはaria-label属性をinputにつければうまくいった。

```html
<input
  aria-label="fuga"
  value="hoge"
/>
```

公式ドキュメントに書いてました。
https://testing-library.com/docs/queries/byrole/
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653035/b254c609-2ff7-cc59-5397-76562e2b7007.png)

さらにnameについて詳しく書いてます。
https://developer.paciellogroup.com/blog/2017/04/what-is-an-accessible-name/
（メモ）nodejsのアップグレード(12から16に。RHEL環境)

nodejsのバージョンを12から16に上げました。
Red Hat Enterprise Linux の環境です。
やり方をいつも忘れるのでここにメモ。

```
sudo curl -sL https://rpm.nodesource.com/setup_16.x
sudo yum remove -y nodejs npm
sudo yum list available nodejs
sudo yum install nodejs
```

nvmなどをインストールしておきたくないので、一度リムーブして再度入れなおす、ということで対応しています。
（私の環境だとsudoをしないとインターネットアクセスができなかったのでcurlの前などもsudoをしています。）
# 備忘録・技術書を書いておくことの大切さ

Unity の学習を初めて，10日ほど経ちました。
パソコンの容量の都合，作ったファイルで時間が経過したがものは削除していたのですが

その時，自分が調べて実装できたスクリプトがあったファイルも削除していました。

自分が調べた内容を上手く整理できていなかったので，もう一度調べて書く必要がありそうです。

調べた内容を細目にまとめて保存・整理をしたいなと思います。
Basic認証アレコレ

## 割と面倒くさい

開発環境や管理画面、秘密のページに Basic 認証かけることは、結構あって、ちゃちゃっとかけたいけど、意外と面倒くさい。

## Basic 認証のかけかた基本

最近は、React.js, Next.js を取り扱うことが多い。

### React.js で Basic 認証

React をサーバに Deploy する時は、Build して Nginx で動かすことが多いと思われるので、Nginx で .htpasswd すれば良い。

> [Nginx で Basic 認証](https://qiita.com/kotarella1110/items/be76b17cdbe61ff7b5ca)

### Next.js で Basic 認証

Next.js の場合、middleware を使ってかける。middleware の取り扱いは、バージョンによって大きく異るので、ググる時は、Next.js のバージョンに気をつけて。というか、最初に公式ドキュメントを見るのが良い。

Next.js v12 の場合

> [Next.js + typescript + Prisma の API テンプレートを作る](https://qiita.com/kurab/items/6491961ea56347b48c00#basic-%E8%AA%8D%E8%A8%BC)

## AWS で CloudFront を通した場合

上記の方法で Basic 認証を書けている場合、CloudFront 通すと Basic 認証が通らなくなる。
理由は、レスポンスヘッダが足らないから。

### レスポンスヘッダを追加する

ビヘイビアを編集し、レスポンスヘッダに Authorization を追加する。キャッシュタイムを0にする。

### CloudFront Function で Basic 認証する

開発環境に CloudFront 使うのか？という話はあるけど、Production ではかけないし、Upstream にエスカレーションしていく間に機能を落としていくのもなんだかなーとも思うので、開発環境にも CloudFront 刺してる場合は、こっちの方が良い。アプリケーションでかけた Basic 認証は解除し、CloudFront Function を作成して、これまたビヘイビアで追加する。

> [CloudFront FunctionsでBasic認証のパスワードをかける](https://dev.classmethod.jp/articles/apply-basic-authentication-password-with-cloudfront-functions/)


### AWS WAF で Basic 認証する

WAF を使っても良い。

> [AWS WAF で Basic 認証をかける](https://engineers.fenrir-inc.com/entry/aws-waf-basic-auth)


開発環境への Basic 認証みたいなものは、外出しの方が良い。Basic 認証に限らず、こういう系は Solution をいくつか持っておくのが良い。

## WebView で Basic 認証

アプリ次第？だけど、基本的にできないと思っておいて良い（はず）。WebView で Basic 認証かけたいことなんてある？と思うかも知れないが、例えば Metamask と連携する Web アプリの開発環境とか。実機テストしようとすると、Basic 認証が突破できないんじゃなくて、そもそも開けない。

いずれ変わるのかも知れないけど、Basic 認証以外の制限を考えた方が良い。もしくは、WebView で表示されるのもなかなかしんどいので、Metamask は、やめとこう。とか。

## Basic 認証をやり直す

まぁそんなこんなで、何度もやり直したい時期もある。Basic 認証一回通すとキャッシュされて出てこなくなる。すぐにやり直したい場合は、ドメインの前に ```任意の文字列＠``` を付けるとログアウト？される。

https://```me@```example.com みたいなこと。


他にもありそうな気がするけど、今日はこんなところで。
ActiveRecord の update, save は Dirty じゃないとき UPDATE 文を発行しないので別のオブジェクトで同一のレコードを扱うときに注意

[ActiveRecord#update](https://api.rubyonrails.org/classes/ActiveRecord/Persistence.html#method-i-update), [ActiveRecord#save](https://api.rubyonrails.org/classes/ActiveRecord/Persistence.html#method-i-save) はDirtyな値を持たない時、実際のUPDATEを行わない。便利機能だけど、更新対象を複数の変数に受けている場合、ちょっと予想外の挙動をするので注意。


```ruby
user = User.find(42)
user.name # => 'Tarou'

current_user = User.find(42)
current_user.name # => 'Tarou'

current_user.update!(name: nil)
user.update!(name: 'Tarou') # => Dirty でないので UPDATE 文が発行されず、 DB の name は NULL のまま

current_user.reload.name # => nil
user.reload.name # => nil
```

👆こんなコードを書くことは普通はないだろうけど、バッチ処理とかでいろんなデータにいろいろやるときに書いてしまうかもしれない（書いた）。例えば採番を行う処理で;


```ruby
# [{ id: 1, number: 1, want_to_number: true  },
#  { id: 2, number: 2, want_to_number: false },
#  { id: 3, number: 3, want_to_number: true  }]
targets = User.where(want_to_number: true)

# 何らかの処理、ここで user のレコードが取得され、number がメモリに保持される
targets.each do |user|
  user.何らかの処理
end

# number カラムのクリア
# DB の値は number = null となるが、targets の各メンバーは null となる前の number を保持したまま
# DB の値と targets の間に乖離が生じる
User.all.update_all(number: nil)

# 再採番
targets.each.with_index(1) do |user, new_number|
  # このとき targets 内の id: 1 の User オブジェクトの number は 1 となっているので、
  # new_number と一致し、dirty と判定されない
  # したがって UPDATE 文も発行されない
  user.update!(number: new_number)
end

# こうあってほしいんだけど、
# [{ id: 1, number: 1, want_to_number: true },
#  { id: 3, number: 2, want_to_number: true }]
puts targets

# 実際はこうなってる
# [{ id: 1, number: nil, want_to_number: true  },
#  { id: 2, number: nil, want_to_number: false },
#  { id: 3, number:   2, want_to_number: true  }]
puts User.all

```

`update` が Dirty なものしか UPDATE しない挙動って感覚的には何となく知ってたけど、メソッドのドキュメントには書いてないっぽい([ActiveRecord#update](https://api.rubyonrails.org/classes/ActiveRecord/Persistence.html#method-i-update), [ActiveRecord#save](https://api.rubyonrails.org/classes/ActiveRecord/Persistence.html#method-i-save))。コードをたどっていくと[`ActiveRecord::AttributeMethods::Dirty._update_rows` がチェックしてるのがわかった](
https://github.com/rails/rails/blob/04972d9b9ef60796dc8f0917817b5392d61fcf09/activerecord/lib/active_record/attribute_methods/dirty.rb#L215-L219)。ちなみにこの挙動は[設定でオフることが出来る](https://railsguides.jp/configuring.html#config-active-record-partial-updates)けど、上に示したようなバグるコードはコードが悪いので設定で対処するのはやめた方が良いと思う。

```ruby
config.active_record.partial_updates = false
```
Laravelの起動時に「Your app key is missing」が発生した場合の対応方法

dockerで環境構築を行い、
最後にブラウザでlaravelのTOPページの表示を確認しようとしたのですが、
Your app key is missing
エラーが発生したので簡単にまとめます。

・エラー内容
![スクリーンショット 2022-08-26 2.05.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1096726/3033c15a-69d5-b192-3e51-d2f57e6a694f.png)

・エラー内容を解説
RuntimeException
No application encryption key has been specified.
アプリケーション暗号化キーが指定されていない。

Your app key is missing
Generate your application encryption key using php artisan key:generate.

アプリキーがないので
php artisan key:generate
コマンドを実行してアプリケーション暗号化キーを生成してください。

・laravelファイル上で、エラー内容通りコマンド実行。
![スクリーンショット 2022-08-26 2.14.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1096726/0b5ce751-2bf2-e585-1173-c7139558945b.png)

無事解決。
【Golang】Go言語のappendにおける ... (ドット３つ)の意味

## はじめに
append関数を使用する際に「...」が出てきたので、その使い方をまとめます。
※バージョン：1.18.4

## append関数
Go言語では、スライスの最後に値を追加するときに append 関数を使用します。
`func append(slice []Type, elems ... Type) []Type`([公式ドキュメント](https://pkg.go.dev/builtin#append)より)

要素ではなく、スライスを追加したい場合、次のようにスライス変数の後ろに「...」を書きます。
`slice = append(slice, anotherSlice...)`
スライス変数の後ろに「...」をつけることで可変引数の関数にスライスを展開して渡すことができます。

実際にサンプルを用いて確認します。
#### サンプル
```main.go
func main() {
	slice1 := []int{1, 2, 3}
	slice2 := []int{10, 20, 30}

	slice1 = append(slice1, slice2...)
    // slice1 = append(slice1, 10, 20, 30)
	fmt.Println(slice1) // => [1 2 3 10 20 30]
}
```
サンプルでは slice2 を展開して渡しています。
俺の正規表現集


```javascript
// https://stackoverflow.com/questions/2063213/regular-expression-for-validating-dns-label-host-name
// ホスト名 (ラベル) は、文字または数字で開始または終了できます
// ホスト名 (ラベル) は、'-' (ダッシュ) で開始または終了してはなりません
// ホスト名 (ラベル) は、すべて数値で構成されてはなりません (MUST NOT)。
// ホスト名 (ラベル) は最大 63 文字です
rfc1123: v => !v || /^(?![0-9]+$)(?!-)[a-zA-Z0-9-]{1,63}(?<!-)$/.test(v) || '先頭を英字にして、63 文字以下の英小文字、数字、ハイフンで構成します',
```

使ったものを記載していく
ボタンに関数を登録する方法


## 対象読者
+ アンドロイドアプリ開発初心者

## レイアウト画面から登録する方法

1. 対象の画面のレイアウトファイルを開く
1. （ボタンだけ適当に配置してください）

    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/442933/10110129-6d83-b58d-4982-3388a67a1519.png)

1. ボタンを選択する

    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/442933/588b292a-5ba5-3960-5666-45e241305aad.png)

1. Attributesの欄のCommon AttributeからonClickプロパティに任意の関数名を登録する。

1. アクティビティファイルを開いて関数を定義する
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/442933/951dbf47-8e71-0719-bd97-19743172ad2c.png)

1. ビルドしてボタンを押下すると、定義した関数が呼ばれる。

## コードだけでやる方法

1. ボタンを選択する
1. レイアウトでAttributesの欄からボタンにIdを振る
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/442933/13274204-9a00-a7c9-bc77-1a2cba74a612.png)
1. Codeからボタンが押されたら教えてくれるように設定する
    ~~~
    package com.example.hello
    
    import androidx.appcompat.app.AppCompatActivity
    import android.os.Bundle
    import android.view.View
    import android.widget.Button
    import android.widget.TextView
    import java.util.*
    
    class MainActivity : AppCompatActivity() {
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
    
            // ボタンをIDで特定する
            var btnCurrent = findViewById<Button>(R.id.btnCurrent)
    　　　　 // 押されたら関数が実行されるように設定する
            btnCurrent.setOnClickListener(
                object: View.OnClickListener {
                    // 実行される関数
                    override fun onClick(v: View?) {
                        // やりたいことをここでやるよ！
                    }
                }
            )
        }
    }
    ~~~
1. ボタンを押下すると登録したリスナーが反応して関数が実行される

## まとめ

実際には、下の方法で実装されることが多いため、下の方法を利用することをお勧めします。
尚、下記の方法のようにイベントに応じて実行すべき処理を記述するプログラミングモデルをイベントドリブンモデルと呼ぶそうです。
また、イベントが発生したタイミングで実行すべき処理をイベントハンドラーと言うようです。

## 参考書籍
+ TECHNICAL MASTER はじめてのAndroidアプリ開発 Kotlin編 (TECHNICAL MASTER 98) chapter2
AWS SAAの合格体験記



## はじめに
記事の内容はAWS SAA C-02の合格体験記です。
**そのため、紹介している教材はAWS SAA C-03以降に対応していないので注意してください。**

## 要旨
今年の7月に [AWS SAA SAA-02](https://aws.amazon.com/jp/certification/certified-solutions-architect-associate/)の資格を取得しました。
この記事では資格取得までの学習方法と感想について書きたいと思います。


## 前提
元々ITインフラ系のアルバイトをしていた経験があり、特にVPC, EC2, IAM, RDS周りのサービスを検証環境構築の目的で触っていました。

## 資格取得に至った経緯
今年の7月からAWS Angel Dojo という AWS 主催のハッカソン企画に参加しています。
チーム内での話し合いで、事前に資格を取得をしておいた方がより良いアーキテクチャ設計をすることができ、優勝に近づくのではないかという話になり、この資格を取得することになりました。

## 学習方法
**ここで紹介している教材はAWS SAA C-03以降に対応していないので注意してください。**


1. [AWS Hands-on for Beginners
〜 スケーラブルウェブサイト構築編 〜](https://pages.awscloud.com/event_JAPAN_Hands-on-for-Beginners-Scalable_LP.html)
2. [教科書](https://www.amazon.co.jp/%E6%A8%A1%E6%93%AC%E5%95%8F%E9%A1%8C%E4%BB%98%E3%81%8D-AWS%E8%AA%8D%E5%AE%9A-%E3%82%BD%E3%83%AA%E3%83%A5%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%82%A2%E3%83%BC%E3%82%AD%E3%83%86%E3%82%AF%E3%83%88-%E3%82%A2%E3%82%BD%E3%82%B7%E3%82%A8%E3%82%A4%E3%83%88%E6%95%99%E7%A7%91%E6%9B%B8-SAA-C02/dp/4295010650/ref=d_pd_vtp_sccl_2_2/358-5481081-8053645?pd_rd_w=lbx7h&content-id=amzn1.sym.cbb45385-7b99-44b7-a528-bff5ddaa153d&pf_rd_p=cbb45385-7b99-44b7-a528-bff5ddaa153d&pf_rd_r=1VJQE22PFE7SZWS8N5MJ&pd_rd_wg=18t3O&pd_rd_r=7306e935-ebcf-4b35-abc5-42db98604a13&pd_rd_i=4295010650&psc=1)と[問題集](https://www.amazon.co.jp/AWS%E8%AA%8D%E5%AE%9A%E3%82%BD%E3%83%AA%E3%83%A5%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%82%A2%E3%83%BC%E3%82%AD%E3%83%86%E3%82%AF%E3%83%88-%E3%82%A2%E3%82%BD%E3%82%B7%E3%82%A8%E3%82%A4%E3%83%88%E5%95%8F%E9%A1%8C%E9%9B%86-%E5%B9%B3%E5%B1%B1-%E6%AF%85/dp/486594303X/ref=pd_bxgy_img_sccl_1/358-5481081-8053645?pd_rd_w=7mMEO&content-id=amzn1.sym.918446e7-72f4-48c7-a672-af3b6ace2b19&pf_rd_p=918446e7-72f4-48c7-a672-af3b6ace2b19&pf_rd_r=WH6CY7FX1V42XVQ9B78E&pd_rd_wg=2LXOX&pd_rd_r=37e75fa3-6bbf-42da-84b7-d88486a7fff9&pd_rd_i=486594303X&psc=1)を並行して取り組む

1のハンズオンはとても参考になりました。VPC,EC2、RDS周りを触りながら学べますし、ハンズオンで構築する構成はとても基本的なもので試験問題にもよく出るようなものだからです。（そのまんまでは出ないけど。）
先にハンズオンをやることで、2の学習に取り組みやすくなりました。

## 試験の所感
ピアソンVUE形式の試験会場での受験を選択しました。
思ったよりも試験が難しく、もっと教科書と問題集を取り組んでおけばよかったなーと後悔しました。
試験時間には結構余裕があって、じっくり考えて問題を解くことができました。

## 感想
時間に余裕のない試験は苦手なので、試験時間が多めだったのは個人的に嬉しかったです。また、試験結果が受験後すぐにわかるのも嬉しかったです。
試験結果がわかるまでずっと気になって、他のことに集中しづらくなってしまう性格なので、、
学習したことをもとに引き続きハッカソンを頑張っていこうと思います。
PHP8.0からの便利な機能　～3選～

PHP8.0の新機能でよく使う機能を3つ紹介します:point_up::v:

## 1. match式
簡単な条件分岐処理はmatch式を使いましょう！
### BEFORE:frowning2:
``` php:if文
$hoge = 1;
if ($hoge === 1) {
    $fuga = 'イチだよ';
else if ($hoge === 2) {
    $fuga = 'ニだよ';
else if ($hoge === 3) {
    $fuga = 'サンだよ';
} else {
    $fuga = 'チガウヨ';
}
```
``` php:switch文
$hoge = 1;
switch ($hoge) {
    case 1:
        $fuga = 'イチだよ';
        break;
    case 2:
        $fuga = 'ニだよ';
        break;
    case 3:
        $fuga = 'サンだよ';
        break;
    default:
        $fuga = 'チガウヨ';
        break;
}
```
### AFTER:blush:
```php:match式
$hoge = 1;
$fuga = match ($hoge) {
    1 => 'イチだよ',
    2 => 'ニだよ',
    3 => 'サンだよ',
    default => 'チガウヨ'
};
```
## 2. 名前付き引数
引数が多い時は名前付き引数の書き方も検討してみましょう！
### BEFORE:frowning2:
```php:第四引数のみ指定
class Hoge
{
    public function manyArgs(
        bool $one = true,
        int $two = 2,
        string $three = 'サン',
        float $four = 4.1
    ): string {
        // 省略
    }
}

/** 
 * $fourだけ指定したい！それ以外は初期値でいい！
 * 第一引数から第三引数も書かないといけない・・・
 * /
$Hoge = new Hoge(true, 2, 'サン', 4.9);
```
### AFTER:blush:
```php:第四引数のみ指定
class Hoge
{
    public function manyArgs(
        bool $one = true,
        int $two = 2,
        string $three = 'サン',
        float $four = 4.1
    ): string {
        // 省略
    }
}

/**
 * 第四引数のみ指定できる！
 * /
$Hoge = new Hoge(four: 4.9);
```
## 3. コンストラクタのプロパティ昇格
プロパティ宣言をコンストラクタ引数でまとめてしまいましょう！

:::note warn
Laravelを想定したコードです
:::

### BEFORE:frowning2:
```php:repositoryクラスを依存注入
use xxxx\xxxx\HogeRepository;
use xxxx\xxxx\FugaRepository;
use xxxx\xxxx\PiyoRepository;

class xxxxxServiceClass
{
    // 1.ここでプロパティを宣言して・・・？
    private HogeRepository $HogeRepository;
    private FugaRepository $FugaRepository;
    private PiyoRepository $PiyoRepository;
    
    public function __construct(
        // 2.ここで注入するクラスを設定して・・・？？
        HogeRepository $HogeRepository,
        FugaRepository $FugaRepository,
        PiyoRepository $PiyoRepository
    ) {
        // 3.ここで各プロパティにインスタンスオブジェクトを設定して・・・？？？
        $this->HogeRepository = $HogeRepository;
        $this->HogeRepository = $HogeRepository;
        $this->HogeRepository = $HogeRepository;
    }
```
### AFTER:blush:
```php:repositoryクラスを依存注入
use xxxx\xxxx\HogeRepository;
use xxxx\xxxx\FugaRepository;
use xxxx\xxxx\PiyoRepository;

class xxxxxServiceClass
{
    public function __construct(
        // 1.これでプロパティ宣言もできる！
        private HogeRepository $HogeRepository,
        private FugaRepository $FugaRepository,
        private PiyoRepository $PiyoRepository
    ) {}
```
少しでも不要なコードは書かない様に意識していきたいですね:point_up:
### PHPリファレンス
[PHP8.0新機能](https://www.php.net/manual/ja/migration80.new-features.php)
Macのテキストエディットなどで英字の先頭が勝手に大文字にならないように設定

# 概要

例えばテキストエディット小文字で ```echo``` と入力したのに…
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/46f429c8-f37c-efe5-015c-f1b7c40c42f6.png)
スペース押したら ```Echo``` となってしまう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/83f1bbc1-cd81-d3fc-c8b2-b5e118b35229.png)
この **『勝手に先頭大文字』** を止めさせたい時。

# やり方

システム環境設定⇒キーボード
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/f6dbb282-95e1-643a-26de-dff99758cbcb.png)

ユーザー辞書⇒文頭を自動的に大文字にする
のチェックを外す。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/23066a51-d6c5-5bc5-c6a1-f779b5352653.png)

実はテキストエディット（ソフトウェア）の設定ではない。
システム環境設定（もっと下のレイヤー）の設定による挙動。

# 参考サイトさん

https://www.too.com/support/faq/mac/finder_os/24592.html

# バージョン

macOS Monterey バージョン12.5.1