OmniAICreator/Qiita-1.07M huggingface dataset:
[読書感想分] SIerが「失敗の科学 失敗から学習する組織、学習できない組織」を読んでみた。

# 今回の書籍

今回の書籍は「失敗の科学 失敗から学習する組織、学習できない組織」です。

https://amzn.asia/d/027emwX

現在、私はDevOpsについていろいろ勉強しています。
その中で「失敗を恐れずに、失敗から学ぶ」ということが大事だと思っているので、この本を読んでみました。

# 本書の概要

**人の失敗から学びましょう。自分で全部経験するには、人生は短すぎます**

本書は人はなぜ失敗するのか？そして失敗を繰り返す組織とそうでない組織は何が違うのか？
という観点で多数のエピソードを描いています。
失敗をどう捉えるか、どう学ぶかを科学的に解き明かした本であり、非常に参考になりました。

一部、少々強引なエピソードもありましたが、大半のエピソードには共感し、失敗から学べる組織の凄さを感じることができました。
一見、「なぜそんなことになるんだ・・・？」と感じるような事例でも、その後になぜそのような状況に陥ったのかが詳細に書かれており、納得することができました。

# 引象に残ったキーワード

## 避けようがありませんでした。

本当はそんなことはないのだが、自分の落ち度を認められないために、このような言葉を発してしまう。

## なぜ、航空業界は奇跡的に安全なのか？

あれほど大きな機械がなぜ日々事故を起こさずに運航できるのか？
実は頻繁に事故は起きているものの、そこから徹底的に学んでいるため、安全に運航が続けられているのだ。

## クローズド・ループ現象

>失敗や欠陥にかかわる情報が放置されたり曲解されたりして、進歩につながらない現象や状態を指す。

「瀉血」（しゃっけつ）という治療法の話がわかりやすいです。

「瀉血」が効果があるか？という調査して、ある！と結論づけたのだが、
そもそも「瀉血」の後、回復しなかった人は亡くなっていてアンケートできない。
助かった人にしかアンケートしてないので効果があった！という答えしか返ってこない。
RCTとても大事！とのこと。

## RCT

https://ja.wikipedia.org/wiki/%E3%83%A9%E3%83%B3%E3%83%80%E3%83%A0%E5%8C%96%E6%AF%94%E8%BC%83%E8%A9%A6%E9%A8%93

この本ですごい推されてる分析方法です。
わかりやすくいうと、「やったグループとやってないグループで結果を比較する」です。
やった方だけで検証するのは、やったことが効果に繋がっているかはわからないということ。

## 「完璧」な集中

緊迫した状況だと、視野が狭くなり周りの声も届かなくなる。
そして、時間感覚も狂う。
故に判断ミスをするのだ。

この本で一番共感できる部分です。

## 何にでもあてはまるものは科学でない

>あらゆるものが当てはまるということは、何からも学べないことに等しい。

少し難解な章ではありましたが、
非常に重要な考え方を提示していると感じました。

ミスを「忙しいから」で済ませていたら何も学べないし、進歩もない・・・そんなところですかね。

## 考えるな間違えろ

世界は複雑なので、専門家でも正確に未来は見通すことはできない。
だから超高速で失敗と学習を繰り返すのがベストだと述べています。

やっぱアジャイルということか。

## 「物語」が人を欺く

服役囚が不良少年に刑務所暮らしの辛さを説いたら犯罪が減った！良い話！
と思ったらそうでもなかった・・・。
データに「単純で誰でも共感しやすい物語」が紛れていると、曲解されやすい。

海外でもこんな事態が起こるんですね。
卒業文集を一方的に引用したり、事件に都合の良いストーリーを作り上げてしまうのは日本だけだと思っていました。

## 成長が遅い人は失敗の理由を「知性」に求める

>固定型マインドセットの子は、いともあっさりと自分の能力を過小評価し、失敗を自分の知性のせいにしはじめた。「きっとボクはあまり頭がよくないんだ」「前から記憶力が悪かったから」「こういうのはもともと苦手なんだ」

耳が痛い・・・言葉です。
記憶力がどうのこうのと言えるほど勉強していないかも・・・。

# 自分のSIer人生に当てはめてみる

この本を読んだ上で私のこれまでSIerの仕事・・・つまり過去の担当プロジェクトはどうだったかを考えてみました。
結論から言うと、失敗を十分に活かせてないですね。

## シナリオありきの障害報告

一応、障害が起きたらそれの原因と対策を考えて、対策を少しずつ実践はしていたと思います。
ただそれは、上司や顧客に報告しなくてはならないから、という側面が強いですね。

しかも、障害発生からあまり間をおかずに報告しないといけないことが多かったので、無難で**実践できそうな対策**を立てることが多かったです。
それで効果があったかは正直検証したことはありません。

これは、失敗から学んでるとは言い難いですね・・・。

後からこの原因と対策は違ったな・・・と思っても、もう一度考えたり話あったりするのは「蒸し返す」という感じでできなかったです。

## ウォーターフォール中心の環境だと間違えることができる場所がない

ウォーターフォールのプロジェクトで、リリース作業を思い浮かべてみます。

1. 手順作成
2. 検証環境でリハーサル
3. 本番

工数的にこんなもんにせざるを得ないのですが、
リハーサル1回で失敗を洗い出せてるか・・・？と言われたらNoです。
大体本番で何か起きますよね・・・。

これを頻繁に繰り返してるならまあそのうち慣れてくるかと思いますが、
ウォータフォールだとそんなにリリース作業を頻繁にしないですよね。

たまにしかしなくて、しかも失敗が許されない作業だと、どうしても安牌を選びます。
なんか良い方法を思いついても試そうとは・・・思わないですね。

## 非公式な反省会

これは私の周りだけがおかしかったのかもしれません。

思い起こせば障害の原因と対策は大体一人で考えてました。
けど、じゃあ孤軍奮闘してたのかというとそうとも言い切れない。
飲み会の二次会で先輩たちと反省会していた時期があります。

気持ちはありがたいけど、体力的にきつかったですね。
よくよく考えたらお酒飲んで冷静な議論ができるとも思えないし、このやり方は間違っていたと思います。

反省会は、昼間、ちゃんと工数つけて開発サイクルに組みこまなければならないと思います。
お酒の場に来ない人は失敗から学ぶ機会がないというのは違うかなと思います。

# まとめ

本の最初の方の章では、話に出てくる組織に対して、なんだこのダメ組織は・・・自分のとこはさすがにここまで酷くないよ
と思って読んでましたが、
冷静に考えると自分も全然ダメだな、見習おうという内容でした。

SIerのプロジェクトってとにかく前に進めなくちゃいけないんですよね。
プロジェクト終わって次が始まったら前のプロジェクトなんて本当に振り返る暇がない。

じゃあどうすれば良いかはすぐに言えないけど考えるきっかけになる本でした。
ESP32-S3でBLE-Keyboardを使うとき

# はじめに

Arduino環境でESP32-S3をBLE-Keyboardにして使うとき、ちょっとした罠にはハマったので、メモしておく。

# 1. Arduino IDE

ボードマネージャに以下のURLを追加し`ESP32-S3ボード`を追加する。[出典](https://docs.espressif.com/projects/arduino-esp32/en/latest/installing.html)

```html
https://espressif.github.io/arduino-esp32/package_esp32_index.json
```

```diff_html
+ ↓こちらのURLでダウンロードされるjsonと内容は同じ
https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json

- ↓こちらのURLには、ESP32-S3が無い
https://dl.espressif.com/dl/package_esp32_index.json
```



# 2. ライブラリを追加

1. ESP32-BLE-Keyboard　＜主役＞
1. NimBLE-Arduino 

# 2.1 ESP32-BLE-Keyboardライブラリの追加

https://github.com/T-vK/ESP32-BLE-Keyboard

- 上のReleaseから`ESP32-BLE-Keyboard.zip`をダウンロード
- Arduino IDEの「ZIP形式のライブラリをインストール」でダウンロードしたzipファイルを指定してインストールする


# 2.2 NimBLE-Arduinoライブラリの追加

ESP32-S3でESP32-BLE-Keyboardライブラリを使う場合は、NimBLE-Arduinoライブラリが必要とのこと（USE_NIMBLE）。[出典](https://github.com/T-vK/ESP32-BLE-Keyboard/issues/239)

- Arduino IDEの「ライブラリを管理」にて`NimBLE-Arduino`を検索しインストールする


# 3. USE_NIMBLE

`#define USE_NIMBLE`をソースコードの先頭に追加する。

```cpp
#define USE_NIMBLE
#include <BleKeyboard.h>
```

# 4. USB-Keyboardと共存させる場合

USBにつながっている時は、USBキーボードとして動作し、USBにつながっていない時は、BLEキーボードとして動作させたい場合は、さらに以下の対応が必要。

## 4.1 `KeyReport`が重複

USBとBLEで`KeyReport`が重複してコンパイルエラーとなる場合は、BLE側の以下のソースを手修正する。

```diff_c:BleKeyboard.h
- } KeyReport;
+ } BLEKeyReport;

- KeyReport          _keyReport;
+ BLEKeyReport       _keyReport;

-  void sendReport(KeyReport* keys);
+  void sendReport(BLEKeyReport* keys);
```

```diff_c:BleKeyboard.cpp
- void BleKeyboard::sendReport(KeyReport* keys)
+ void BleKeyboard::sendReport(BLEKeyReport* keys)

-  this->inputKeyboard->setValue((uint8_t*)keys, sizeof(KeyReport));
+  this->inputKeyboard->setValue((uint8_t*)keys, sizeof(BLEKeyReport));
```

↓このプルリクがマスタに反映されれば不要な対応。

https://github.com/T-vK/ESP32-BLE-Keyboard/pull/197


## 4.2 `#define HID_SUBCLASS_NONE   (0)`がエラーとなる

```c
NimBLE-Arduino/src/HIDTypes.h:29:29: error: expected identifier before '(' token
 #define HID_SUBCLASS_NONE   (0)
                             ^
arduino_tinyusb/tinyusb/src/class/hid/hid.h:63:3: note: in expansion of macro 'HID_SUBCLASS_NONE'
   HID_SUBCLASS_NONE = 0, ///< No Subclass
```

`NimBLE-Arduino`の`HIDTypes.h`と、`arduino_tinyusb/tinyusb/src/class/hid/hid.h`で`HID_SUBCLASS_NONE`の定義が重複する（enumの名前が#defineに置き換るエラー）。
値は同じであるため、`NimBLE-Arduino`の方をコメントアウトする。

```diff_c:HIDTypes.h
-    #define HID_SUBCLASS_NONE   (0)
+ // #define HID_SUBCLASS_NONE   (0)
```

# 5. ペアリングした後

スマホに初めてペアリングしたとき下記のエラーが出るが、キーボードの送信は正く出来ているのでそのまま使える。また、スマホ側にはエラーは見えない。

```
BT_GATT: GATT_INSUF_AUTHENTICATION
         or
BT_GATT: GATT_INSUF_ENCRYPTION
```

# おわりに

以上で、コンパイル＆アップロード＆上手く動作するはずだ。
Spring Bootのjavax.management.InstanceNotFoundException

ログレベルをdebugにしたときに出てきたエラー、アプリを管理するための機能らしい、デフォルトではOFFになっているが、起動設定でJMXを使用可能にするがデフォルトでONになっているため発生していた。

https://spring.pleiades.io/spring-boot/docs/current/reference/html/actuator.html#actuator.jmx

青丸の箇所をOFFにすると消える

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2713217/78ffb4eb-8d6e-a4c5-cc30-ca5aa83b6790.png)

エラー抜粋
```
javax.management.InstanceNotFoundException: org.springframework.boot:type=Admin,name=SpringApplication
	at java.management/com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.getMBean(DefaultMBeanServerInterceptor.java:1088) ~[na:na]
	at java.management/com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.getAttribute(DefaultMBeanServerInterceptor.java:640) ~[na:na]
	at java.management/com.sun.jmx.mbeanserver.JmxMBeanServer.getAttribute(JmxMBeanServer.java:679) ~[na:na]
	at java.management.rmi/javax.management.remote.rmi.RMIConnectionImpl.doOperation(RMIConnectionImpl.java:1449) ~[na:na]
	at java.management.rmi/javax.management.remote.rmi.RMIConnectionImpl$PrivilegedOperation.run(RMIConnectionImpl.java:1310) ~[na:na]
	at java.management.rmi/javax.management.remote.rmi.RMIConnectionImpl.doPrivilegedOperation(RMIConnectionImpl.java:1405) ~[na:na]
	at java.management.rmi/javax.management.remote.rmi.RMIConnectionImpl.getAttribute(RMIConnectionImpl.java:639) ~[na:na]
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
	at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
	at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:360) ~[na:na]
	at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:200) ~[na:na]
	at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:197) ~[na:na]
	at java.base/java.security.AccessController.doPrivileged(AccessController.java:712) ~[na:na]
	at java.rmi/sun.rmi.transport.Transport.serviceCall(Transport.java:196) ~[na:na]
	at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:587) ~[na:na]
	at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:828) ~[na:na]
	at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:705) ~[na:na]
	at java.base/java.security.AccessController.doPrivileged(AccessController.java:399) ~[na:na]
	at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:704) ~[na:na]
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136) ~[na:na]
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) ~[na:na]
	at java.base/java.lang.Thread.run(Thread.java:833) ~[na:na]
```
WSLにMySQL 8.0を導入する手順

# WSLなら普通にLinuxだから簡単なはず！と思っていましたが・・・

MySQLバージョン、LinuxディストリビューションやWSLかどうかで意外と細かいところが変わるようで、いくつか記事を読みながら進める必要がありました。今回の記事では最終的な手順をまとめました。

- [WSLにMySQL 8.0を導入する手順](#wslにmysql-80を導入する手順)
  - [systemdを有効化](#systemdを有効化)
  - [セキュリティスクリプトを実行](#セキュリティスクリプトを実行)
- [おまけ：カジュアルトークを受け付けています！](#おまけカジュアルトークを受け付けています)

## systemdを有効化

WSL上でsystemdが有効になっていない場合、先に [WSLのsystemdを動作させる（今は設定だけでOK！）](https://qiita.com/koba-a-koba/items/8030ebe631854c6d7e98) の内容を実行しておいてください。

systemdが動いていれば後は普通に入ります。

```console
$ sudo apt update
$ sudo apt install mysql-server
$ systemctl status mysql
● mysql.service - MySQL Community Server
     Loaded: loaded
```

## セキュリティスクリプトを実行

MySQLインストール後、セキュリティスクリプト（mysql_secure_installation）を実行しようとしましたが、インストール直後は下記のとおりrootの認証Pluginがauth_socketになっているようです。
※出力は無関係な行は省いています

```console
$ sudo mysql
mysql> SELECT User, Host, Plugin FROM mysql.user;
+------------------+-----------+-----------------------+
| User             | Host      | Plugin                |
+------------------+-----------+-----------------------+
| root             | localhost | auth_socket           |
+------------------+-----------+-----------------------+
```

私の場合、このままだと下記のエラーが出てmysql_secure_installationが実行できませんでした。

```console
SET PASSWORD has no significance for user 'root'@'localhost' as the authentication method used doesn't store authentication data in the MySQL server.
```

socket_authは（MySQLサーバー上で動作しているときに）OSのユーザー名がMySQLのユーザー名と一致しているかチェックする方式ですが、この方式だとパスワードを設定することに意味がないので、エラーが返されているようです。
そのため、下記で一時的に認証プラグインを変更します。

```console
$ sudo mysql
mysql> USE mysql;
mysql> UPDATE user SET plugin='caching_sha2_password' WHERE User='root';
mysql> FLUSH PRIVILEGES;
mysql> exit;
```

その後、mysql_secure_installationを実行したら通過できました。

```console
sudo mysql_secure_installation
```

実行後の流れは下記のとおりでした。

* anonymous userを削除するか？と尋ねられます。
  プライベートの開発環境ではあるのですが特に存在する必要もないと思ったのでyesで通しました。
* 次にrootユーザーをlocalhostのみでログイン可能にするかと尋ねられます。
  これもyesで通しました。
* testデータベースを消すかと尋ねられます。
  特にいらないのでyes
* Privilegeテーブルを再読み込みするかと尋ねられます。
  これもyes

最後に下記を実行してrootの認証方式を戻しておきました。
※クライアント接続するためのユーザーは別途作成しました。

```console
mysql> UPDATE user SET plugin='auth_socket' WHERE User='root';
mysql> FLUSH PRIVILEGES;
mysql> exit;
```

なにやらいろいろ途中でこけて結構時間がかかったのですが、結果的に今まであまり理解していなかった細かいところを把握することができました。

## おまけ：カジュアルトークを受け付けています！

Musubiteというプラットフォームで、エンジニアのカジュアルトークを受け付けております。

https://musubite-job.com/recruitments/N9BLbViYgLz2

プラットフォーム自体、エンジニアの方にとってとても魅力的なものだと感じていますので、よろしければぜひのぞいてみてください！
eclipseのコンソールが途中で上書きされてしまう

地味に困ったのでメモ

コンソールで右クリック → コンソールの出力制限のチェックを外す or サイズを増やす

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2713217/749592d9-94e6-ee67-c23a-351b89123722.png)
Leetcode 121. Best Time to Buy and Sell Stock

# Problem
株価の配列があったときに、利益が最大となる買いと売りのタイミングを計算する問題です。
> You are given an array prices where prices[i] is the price of a given stock on the ith day.

InputとOutputの例は次になります。
```
Input: prices = [7,1,5,3,6,4]
Output: 5
Explanation: Buy on day 2 (price = 1) and sell on day 5 (price = 6), profit = 6-1 = 5.
Note that buying on day 2 and selling on day 1 is not allowed because you must buy before you sell.
```

利益を最大化するには、なるべく安く買ってなるべく高く売る必要があります。ただし、タイミングとしては、買った日より後に後に売らないといけません。

https://leetcode.com/problems/best-time-to-buy-and-sell-stock/description/

## Key Idea
まずは、買う日と売る日の組み合わせを総当りで調査し、最大利益になる組み合わせを見つける方法があります。(Approach #1)

ただし、それでは時間計算量がO(n^2)となっています。そこで、各日について、下記の２つの変数 `A` と `B` を追跡しておけば、各日の株価を一度だけスキャンするだけで、最大の利益を得るための最適な日を見つけることができます。(Approach #2)
`A` : その日までの最低価格: 株を買う最適な日は、その日までの最低価格の日です。なぜなら、最小の価格で買えば、それが将来的に最大の利益をもたらす可能性があるからです。
`B` : その日までの最大利益: その日の価格とこれまでの最小価格との差を計算します。この差がこれまでの最大利益を超えていれば、最大利益を更新します。

## Approach #1  Brute Force
総当りで組み合わせを考える方法は、下記の様に実装できます。
```python
class Solution:
    def maxProfit(self, prices: List[int]) -> int:

        max_profit = 0
        for i in range(len(prices)-1):
            for j in range(i+1, len(prices)):
                if prices[j] - prices[i] >  max_profit:
                    max_profit = prices[j] - prices[i]

        return max_profit
        
```
この解法では、計算量は下記の様になります。

- Time complexity: O(n^2)。二重ループを利用しています。nは、`prices`の長さです。

- Space complexity: O(1)。`max_profit` という変数しかメモリを使っていません。

## Approach #2  One pass
上述のように、その日までの最低価格と最大利益を同時に追跡していきます。
```python
class Solution:
    def maxProfit(self, prices: List[int]) -> int:

        min_price = float('inf')
        max_profit = 0

        for i in range(len(prices)):
            # 現在の価格が今までの最低価格より安い場合、更新
            if prices[i] < min_price:
                min_price = prices[i]
            
            # 現在の価格と今までの最低価格の差がこれまでの最大利益を超えている場合、更新
            if max_profit < prices[i] - min_price :
                max_profit = prices[i] - min_price
            
        return max_profit
        
```
`min_price`の初期値を無限大で設定している目的は、最初の株価がどんな値であってもそれを新たな min_price（最小価格）として更新できるようにするためです。

この解法では、計算量は下記の様になります。

- Time complexity: O(n)。一度のスキャンを通じて最安価格と最大利益を同時に追跡しています。

- Space complexity: O(1)。`min_price`と`max_profit` という変数しかメモリを使っていません。

## Reference
https://www.youtube.com/watch?v=1pkOgXD63yU
Leetcode 704. Binary Search

# Problem
与えられた整数配列から特定の数値を探し出す問題で、Binary Search（二分探索）を用いることが求められています。
> Given an array of integers nums which is sorted in ascending order, and an integer target, write a function to search target in nums. If target exists, then return its index. Otherwise, return -1.

InputとOutputの例は次になります。
```
Input: nums = [-1,0,3,5,9,12], target = 9
Output: 4
Explanation: 9 exists in nums and its index is 4
```

https://leetcode.com/problems/binary-search/description/

## What's Binary Search
Interviewにおいてよく質問される内容とその解答例を示します。
Q1 : 二分探索の原理について説明してください。
A1 : 二分探索は、ソート済みの配列に対して特定の値を効率的に探すためのアルゴリズムです。このアルゴリズムは、配列の中央の要素を比較し、目標値が中央の要素よりも大きいか小さいかによって検索範囲を半分に減らしていくことで動作します。この過程を目標値を見つけるまで、または検索範囲がなくなるまで繰り返します。

Q2 : 二分探索の時間複雑度と空間複雑度について説明してください。
A2 : 二分探索の時間複雑度は O(log n) です。これは、各ステップで検索範囲が半分になるためです。空間複雑度は O(1) です。これは、追加のメモリを使用せずに配列内を移動するだけで二分探索を実行できるためです。

Q3 : 二分探索はどのようなシチュエーションで最も効果的ですか？
A3 : 二分探索は、大きなデータセットを持つソート済みの配列に対して、特定の値を高速に探す場合に最も効果的です。データセットの大きさに対して対数的な時間複雑度を持つため、データセットが大きくなるほどその効率性が増します。

## Implementation
Pythonを使用した基本的な二分探索の実装を以下に示します。

```python
def binarySearch(nums, target):
    left, right = 0, len(nums) - 1
    while left <= right:
        mid = left + (right - left) // 2
        if nums[mid] == target:
            return mid
        elif nums[mid] < target:
            left = mid + 1
        else:
            right = mid - 1
    return -1

```
中間値を設定する際に、`mid = left + (right - left) // 2`としています。`mid = (left + right) // 2`としても基本的には問題ありません。ただし、大きな数値を扱う際には、left + rightが整数型の最大値を超えてオーバーフローを引き起こす可能性があります。

そのため、`mid = left + (right - left) // 2` のように書くと、このオーバーフローの問題を防ぐことができます。これは、right - leftが必ず0以上であり、いかなる状況でも整数型の範囲を超えることが無いからです。

この問題は、特に大きな数値を扱うことが一般的な言語（例えばJavaやC++）でより重要となります。一方で、Pythonではこの問題はそれほど顕著ではありません。なぜなら、Pythonは動的な型付けが行われ、整数型のオーバーフローが自動的に長整数型に変換されるためです。ただし、他のプログラミング言語でも適用可能なコードを書くため、またはオーバーフローに対する一般的な理解を深めるためには、`mid = left + (right - left) // 2 `の形式を使っています。

また、境界値の条件にも気をつける必要があります。例えば、`while left <= right`の `=`を忘れないようにする、 `right = mid - 1`の`-1`を忘れないようにするなどです。

## 参考 : 再帰を使った実装

Space complextityがO(n)と非効率になってしまいますが、再帰を使って書くことも可能です。

```python
class Solution:
    def search(self, nums: List[int], target: int) -> int:
        def binary_search_recursive(left, right):
            if right >= left:
                mid = left + (right - left) // 2
                if nums[mid] == target:
                    return mid
                elif nums[mid] > target:
                    return binary_search_recursive(left, mid-1)
                else:
                    return binary_search_recursive(mid+1, right)
            else:
                return -1
        return binary_search_recursive(0, len(nums) -1)
```



## Reference
https://www.youtube.com/watch?v=s4DPM8ct1pI
mac で、JDKのバージョンを切り替え -  変更が反映されない！

備忘録です。

mac でjava を使う時、環境変数の設定は windows のように設定用のGUIが見当たらないため、ターミナルで行うことになるかと思います。

## やりたいこと
まず、 https://jdk.java.net/archive/ にて任意のバージョンのopenjdkをダウンロードし、
Library/Java/JavaVirtualMachines 配下に、

・jdk-11.0.2.jdk
・jdk-20.0.1.jdk

の2つを配置。

現在のバージョンは20.0.1だったとします。

これを 11.0.2 に変更したい。

```zsh:バージョン確認
echo $JAVA_HOME
# 出力: Library/Java/JavaVirtualMachines/jdk-20.0.1.jdk/Contents/Home
```

## 問題
下記のように exportで書き換えても、
```zsh:
export JAVA_HOME="Library/Java/JavaVirtualMachines/jdk-11.0.2.jdk/Contents/Home"
```
再度ターミナルを開くと元(20.0.1)に戻ってしまったり、
ターミナルを再度開かずとも、同じターミナルで
$ java -version
で確認すると、20.0.1のままだったりした💦。

## 解決策

```zsh:zshrc を開く
open ~/.zshrc
```
で、.zshrc を開きます。
(macの場合特にこだわりがなければzshがデフォルトなので。)

```zsh:.zshrc
# JAVA_HOME="/Library/Java/JavaVirtualMachines/jdk-20.0.1.jdk/Contents/Home"
JAVA_HOME="/Library/Java/JavaVirtualMachines/jdk-11.0.2.jdk/Contents/Home"
export JAVA_HOME
PATH=$PATH:$JAVA_HOME/bin
export PATH
```
こんな感じで、エディタ上で直接　.zshrc に記載されている JAVA_HOMEを書き換えます。
そうすれば、ターミナルを再度開いた時に .zshrc が自動で参照・実行され、JAVA_HOMEが自動で設定されて、それを元に PATH にも 新しい javaのパスが追加されました。

(追記： STS4(Eclipse)のターミナルウィンドウでは、なぜか .zprofile は読み込まれず、zshrc にversionを指定しないとバージョンが切り替わらないようです。もともと、zshrcではなく.zprofileを編集する、と記事を書いていましたが、訂正しました。)

```zsh:バージョン確認
java -version
# 出力:
# java version "11.0.2" 2023-04-18
# Java(TM) SE Runtime Environment (build 20.0.1+9-29)
# Java HotSpot(TM) 64-Bit Server VM (build 20.0.1+9-29, mixed mode, sharing)
```
とても初歩的な投稿なのは承知ですが、たまにやろうとすると案外モタつくので、、
WordPressエラー：Creation of dynamic property BBP_Admin::$forums is deprecated

## 環境
ロリポップのライトプランにWordPressをインストール。プラグインbbPressおよびSimple WP Membershipをインストールし有効化。


### エラー内容
WordPressでbbPressプラグインを使用していると、管理画面の「フォーラム」画面で次のようなエラーが発生する。

`Creation of dynamic property BBP_Admin::$forums is deprecated`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307441/a9d7dc0a-8b1f-0010-863e-5f8c65a56e43.png)

### 解決？方法

調べた所、PHPのバージョンが8.2だと発生するようだ。当方のWodPressのホスティングはロリポップでPHPは確かにバージョン8.2。

実際のところ、これはエラーというよりWarningであり、無視しても問題ないようではある。以下の動画を参考。
https://youtu.be/5I-c9NZ5TiY
https://youtu.be/k94jaJ2xmJw

動画で示されているように、試しに、WordPressのプラグインファイルエディターにて"wp-content/plugins/bbpress/includes/admin/forums.php"を
次のように編集してみた。

```php
#21行目
class BBP_Forums_Admin {
```
を
```php
#21行目
#[AllowDynamicProperties]class BBP_Forums_Admin {
```
と編集し保存。

残念ながらこうしてもWarningを止めることはできなかったため、元に戻した。
ムダにいじらない方が良いと判断。


以上です。
Jetpack Compose + Map Compose

# JetpackComposeでGoogleMapを表示する
今回は、JetpackComposeで作成した画面に、GoogleMapを表示します。
次回以降、Markerの追加やPolylineの描画、地図座標-スクリーン座標の対比などを記述します。

:::note info
[JetpackCompose+MapComposeにMarkerを動的に追加する（ついでに地図座標も取得するよ）](https://qiita.com/jozuko_dev/items/b1d2b8ced3993e801959)
:::

# 環境
AndroidStudio：Flamingo | 2022.2.1 Patch 2
OS：macOS

JetpackCompose系のライブラリはこちら
```gradle:build.gradle
    implementation platform('androidx.compose:compose-bom:2022.10.00')
    implementation 'androidx.compose.ui:ui'
    implementation 'androidx.compose.ui:ui-graphics'
    implementation 'androidx.compose.ui:ui-tooling-preview'
    implementation 'androidx.compose.material3:material3'
    implementation 'androidx.navigation:navigation-compose:2.7.0-beta01'
```
GoogleMapは、Composableなライブラリが提供されていますので、そちらを使用します。
```gradle:build.gradle
    implementation 'com.google.maps.android:maps-compose:2.11.4'
    implementation 'com.google.android.gms:play-services-maps:18.1.0'
```

# Step1.GoogleCloudApiの設定
これは、JetpackComposeを使用していないときと同じように設定すれば良いだけなので、割愛します。
公式ページを見ながら設定していきます。
[Maps SDK for Android のクイックスタート(公式)](https://developers.google.com/maps/documentation/android-sdk/start?hl=ja)

# Step2.MapsComposeの表示
表示するだけであれば、本当に簡単にできますね。
```kotlin:GoogleMapsScreen.kt
package com.jozu.jetpack.compose.tutorial.screen

import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Scaffold
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import com.google.android.gms.maps.model.CameraPosition
import com.google.android.gms.maps.model.LatLng
import com.google.maps.android.compose.GoogleMap
import com.google.maps.android.compose.Marker
import com.google.maps.android.compose.MarkerState
import com.google.maps.android.compose.rememberCameraPositionState

/** 東京駅 */
val initPos = LatLng(35.6809591, 139.7673068)

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun GoogleMapsScreen() {
    val cameraPositionState = rememberCameraPositionState {
        position = CameraPosition.fromLatLngZoom(initPos, 10f)
    }

    Scaffold(
        modifier = Modifier.fillMaxSize(),
        content = { contentPadding ->
            GoogleMap(
                modifier = Modifier.padding(contentPadding),
                cameraPositionState = cameraPositionState,
            ) {
                Marker(
                    state = MarkerState(position = initPos),
                    title = "東京駅です"
                )
            }
        },
    )
}
```

# いざ実行
全画面表示で、GoogleMapが表示できました。[コード](https://github.com/jozuko/ComposeTutorial/tree/ac86e6f4dbf495d52addaf3584f2526534ddbf60)
![Screenshot_maps.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3491965/d950917a-f017-cf1a-984d-325d355c57bf.png)
IX2215のメトリクスをPrometheus+Grafanaで監視する【Docker】

こんにちは。先日購入したIX2215のメトリクスをGrafanaで確認したくなったので、やってみました。

PrometheusとGrafanaについてはDockerコンテナで動かしています。

## 事前準備

PrometheusとGrafanaの構築は事前に行っておいてください。

## 手順

今回は以下の手順を行います。

- IXのSNMPを有効化
- snmp_exporterを利用してsnmpwalkの情報をPrometheusに投げる
- Prometheusの設定
- Grafanaダッシュボードの作成

## IX2215のSNMPを有効にする

コンソールケーブルなどでIXに接続して、コンフィグモードから以下のようにコマンドを発行します。

```
RT-ix2215(config)# snmp-agent ip enable
RT-ix2215(config)# snmp-agent ip community public ro
```

一行目でsnmpとsnmptrapの両方を有効化しています。

二行目ではpublicという読み取り専用のコミュニティを設定しました。

IXで行う設定はこれだけです。

## snmp_exporterを用意する

snmp_exporterはGitHubで公開されているため、手元にクローンします。

generatorというディレクトリに移動してmibをダウンロードします。

- GitHub: [prometheus/snmp\_exporter: SNMP Exporter for Prometheus](https://github.com/prometheus/snmp_exporter)

```shell
$ git clone git@github.com:prometheus/snmp_exporter.git
$ cd generator
$ make mibs
```

> もしmakeで失敗する場合は、以下のパッケージをインストールします。
>
> ```shell
> $ sudo apt update -y
> $ sudo apt install unzip build-essential libsnmp-dev
> ```
> mibのダウンロードに失敗する場合は、makefileを編集していらないものはDLしないようにしてください。

## snmp.ymlを生成する

先ほどのディレクトリのまま、以下のコマンドでsnmp.ymlを生成します。

```shell
$ docker run -it -v "${PWD}:/opt/" prom/snmp-generator generate
```

実行するとディレクトリにsnmp.ymlが生成されていると思います。

## Docker Composeでsnmp-exporterを構築する

以下のようなdocker-compose.ymlを用意します。

先ほど作成した**snmp.ymlをコンテナ内で利用できるようにマウントしておいてください**。

今回の例ではdocker-compose.ymlと同じディレクトリに移動しておきました。

```YAML
version: '3'

services:
  prometheus:
    image: prom/prometheus
    # 省略
  snmp:
    image: prom/snmp-exporter
    container_name: snmp_exporter
    volumes:
      - './snmp.yml:/etc/snmp_exporter/snmp.yml' # snmp.ymlをマウント
    ports:
      - "9116:9116"

```

## prometheus.ymlを編集する

prometheus.ymlに以下のようなjobを追加します。

IXのIPアドレスやexporterのIPアドレスを指定するところは環境に合わせて変更してください。

前項ではPrometheusとexporterを同一のdocker-compose.ymlで起動しました。そのため、exporterのIPアドレスにcomposeのサービス名を指定します。

それ以外の場合はexporterが起動しているマシンのIPアドレスを指定しましょう。

```YAML
scrape_configs:
  - job_name: 'snmp_nec_ix'
    static_configs:
      - targets:
        - 192.168.10.254  # IXのIP
    metrics_path: /snmp
    params:
      module: [nec_ix]
    relabel_configs:
      - source_labels: [__address__]
        target_label: __param_target
      - source_labels: [__param_target]
        target_label: instance
      - target_label: __address__
        replacement: snmp:9116 # 同一composeファイルで起動する場合はサービス名を指定
```

編集後は``docker compose up -d``などで起動しておいてください。

## Grafanaのダッシュボードを編集する

Grafanaのdashboardsを検索したところ、NEC IXシリーズ向けに公開しているテンプレートはなさそうなので自分で作ります。

```
{job="snmp_nec_ix"}
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1447932/810eada6-28cb-dbdf-d363-a53e59766859.png)


こんな感じでjobを指定すれば値がたくさん表示されるので、ほしい情報を抜き取って好きなダッシュボードを作成してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1447932/eb77f392-18b3-85da-95cb-5cbe3d52e388.png)

## おわりに

NetMeisterなどで情報を確認するのも良いですが、やはり自分でカスタマイズできたほうが便利ですね。

なによりかっこいい😎
Unity 2022 Androidビルドでエラーへの対処（AndroidSDK）

Unity2022のエディタでのAndroidビルドエラーを試みた際に、ビルドが通らなかったのですが、無事解決できましたので手順を記載しておきます。

環境：
Windows10
Unity 2022.3.4f1

事象：
Build SettingからAndroidビルドを作成したところ、3件のエラーが発生。
![キャプチャ1.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3494198/9162f17b-fe94-0c5a-847e-a7c1435c989f.jpeg)
最初のエラーからAndroid SDKに問題がありそうです。
```
Starting a Gradle Daemon, 1 incompatible Daemon could not be reused, use --status for details
Exception while marshalling C:\Program Files\Unity\Hub\Editor\2022.3.4f1\Editor\Data\PlaybackEngines\AndroidPlayer\SDK\build-tools\32.0.0\package.xml. Probably the SDK is read-only
Exception while marshalling C:\Program Files\Unity\Hub\Editor\2022.3.4f1\Editor\Data\PlaybackEngines\AndroidPlayer\SDK\platform-tools\package.xml. Probably the SDK is read-only
Exception while marshalling C:\Program Files\Unity\Hub\Editor\2022.3.4f1\Editor\Data\PlaybackEngines\AndroidPlayer\SDK\platforms\android-31\package.xml. Probably the SDK is read-only
Exception while marshalling C:\Program Files\Unity\Hub\Editor\2022.3.4f1\Editor\Data\PlaybackEngines\AndroidPlayer\SDK\platforms\android-32\package.xml. Probably the SDK is read-only
Exception while marshalling C:\Program Files\Unity\Hub\Editor\2022.3.4f1\Editor\Data\PlaybackEngines\AndroidPlayer\SDK\tools\package.xml. Probably the SDK is read-only
Exception while marshalling C:\Program Files\Unity\Hub\Editor\2022.3.4f1\Editor\Data\PlaybackEngines\AndroidPlayer\SDK\build-tools\32.0.0\package.xml. Probably the SDK is read-only
Exception while marshalling C:\Program Files\Unity\Hub\Editor\2022.3.4f1\Editor\Data\PlaybackEngines\AndroidPlayer\SDK\platform-tools\package.xml. Probably the SDK is read-only
Exception while marshalling C:\Program Files\Unity\Hub\Editor\2022.3.4f1\Editor\Data\PlaybackEngines\AndroidPlayer\SDK\platforms\android-31\package.xml. Probably the SDK is read-only
Exception while marshalling C:\Program Files\Unity\Hub\Editor\2022.3.4f1\Editor\Data\PlaybackEngines\AndroidPlayer\SDK\platforms\android-32\package.xml. Probably the SDK is read-only
Exception while marshalling C:\Program Files\Unity\Hub\Editor\2022.3.4f1\Editor\Data\PlaybackEngines\AndroidPlayer\SDK\tools\package.xml. Probably the SDK is read-only
> Task :unityLibrary:preBuild UP-TO-DATE
> Task :launcher:preBuild UP-TO-DATE
> Task :unityLibrary:preReleaseBuild UP-TO-DATE
```

解決策：
Project Setting>Player>Other Settings Identification
からAPIレベルを最新のAndroid 13.0 (API level 33)を選択した上で再ビルド。
インストールが自動で入って無事ビルドが通りました。
![キャプチャ4.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3494198/02c2fbaa-539b-4f4b-af36-b18cbab7bbf9.jpeg)
![キャプチャ5.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3494198/a992f661-23d3-13f6-0e25-7d1c221543c5.jpeg)
![キャプチャ6.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3494198/535bb99a-95ab-5d3f-9f44-bd29a15ceb5c.jpeg)

最後に：
Unity2022で2023年春頃から始めた方はここでかなり引っかかるんじゃないかと思います。
3つ目のエラーからGradleのバージョンを疑いGradleの公式サイトからバージョン違いのファイルをPathへアップデートする手法も試しましたが、改善しませんでした。Androidのビルドが通らないのはAPIレベルの問題かもしれないです。Project Settingも確認してみてください。
【単体テスト入門】単体テストの考え方・使い方

CARTA HOLDINGSの成長支援制度で[単体テストの考え方/使い方](https://www.amazon.co.jp/gp/product/B0BLTG8Z9K/ref=ppx_yo_dt_b_d_asin_title_o04?ie=UTF8&psc=1)という本を買ってもらったので今日はなるほどと思ったポイントや感想を書いていこうと思います。読んだ順番で書いていくので実際の本の章立てとは順番が一致しませんが悪しからず。

単体テストや統合テストに対する基本的な方針や注意すべき点をまとめている良い本でした。

# アンチパターン

単体テストのアンチパターンはこんな感じ

- プライベートなメソッドを直接テストしたり、テストのためにプライベートなメソッドをパブリックにしたりしてはならない。あくまでテストはWhatを検証するものであり、Howに触れてはならないから。
- 同じようにプライベートな状態をテストのためにパブリックにしてはならない。テストだからといって特別なことが許されるわけではない。
- リグレッションへの保護を失うという話もあったが具体例がなくこれはよくわからなかった。
- 重要なロジックがプライベートメソッドに埋もれている場合、パブリックにする代わりに別のクラスとして切り出してテストすること。
- プライベートな振る舞いをテストで参照したくなった場合、テスト対象のコードがクライアントからどのように使われているのかを見て検証項目を考えること。
- テストのためにif文を追加するなどプロダクションコードを変更してはいけない。プロダクションコードの保守コストが高くなるから。もしどうしても必要な場合はInterfaceを導入するなどして、影響の少ない方法を取ること。
- プロダクションコードのロジックをテストにコピペしてはいけない。テストが嘘の警告を連発するようになるから。ロジックの結果導かれる期待値だけをテストに入力すること。
- 計算とデータ取得など別の責務は別のクラスに分けること。でないとテストしにくい。（これはまんまSRP）
- 現在日時をテストで使いたい時は外部から注入すること。


# 統合テスト

- コントローラに相当するコードをテストする。
- ボイラープレートなどの取るに足らないコードや、過度に複雑なコードをテストしてはいけない。取るに足らないコードは検証する価値がないし、過度に複雑なコードはまずリファクタリングすべき。

# 単体テスト

単体テストは次の3つの性質を持っている。1つでも持っていなければそれは統合テストである。

- １単位の振る舞いを検証すること
- 実行時間が短いこと
- 他のテストケースから隔離されて実行されること


- アルゴリズムやドメインロジックを検証する。
- 3Aパターンを用いる(Arrage,Act,Assert)
【ChatGPT無】私がPromptを作るやり方

:::note info
本記事は、ChatGPT（無料版）で
行なっております。GPT4での確認
はできておりません。あしからず。
:::

　どうも、カーブミラーです。

　今回は、
　　ネタ切れ、ではなくw
　　　**私がPromptを作るやり方**
　　　　です。

　ノウハウが
　　溜まってきましたので、
　　　比較的苦労なく
　　　　作成できています。
　　　　　（出力結果が
　　　　　　　想定内なだけで）

***
　ここでは、
[【ChatGPT無】和Prompt→英→結果和訳Promptだよ](https://qiita.com/kabumira/items/243b06bcf4cd8955c59c)
　　を例にしましょうか。

　1.まずは、
　　　**何をどうしたいのか**
　　　　を考えます。

　　自分の中の考えを
　　　言葉にする作業です。

　　方法はいくつかあります。

　　よくあるのが、5W3Hですね。
　　5W3H
　　　・What 何を（課題）
　　　・Why なぜ （動機）
　　　・Who 誰に（対象）
　　　・When いつ （時期、時間帯）
　　　・Where どこで （場所）
　　　・How どのように （手段）
　　　・How Many　どれくらい（規模）
　　　・How Much いくら（価格）
　　で、言葉にするのもいいです。

　　とにかく、
　　　キーワードでいいので、
　　　　メモに書き出してください。

　　今回は、質問が
　　　私の知っているパターンで
　　　　解決できそうだと
　　　　　思いました。

　　元ネタが、
　　　誰発信でどこにあるのか
　　　　検索してもわかりませんが。

　　とにかく、
　　　キーワードをメモします。

　　・日本語プロンプト
　　・英訳
　　・実行
　　・和訳


　2.キーワードから文章化。
　　　文章にします。
　　　　でも、最初の
　　　　　「日本語プロンプト」は
　　　　　　日本語であるのは
　　　　　　　当然なので
　　　　　　　「プロンプト」
　　　　　　　　とします。

　　　文章にすると
　　　　「プロンプトを英訳して、
　　　　　実行して、和訳する」
　　　　　　と簡単です。

　　　でも、
　　　　単純につなげるのでは、
　　　　　ChatGPTさんに
　　　　　　きちんと伝わらない。

　　　そこで、
　　　　**処理手順**
　　　　　という形で、
　　　　　　明確にしました。

　　　つまり、
　　　　一文で済ますのではなく、
　　　　　いくつもの処理に
　　　　　　分割していきます。

　　　以下のプロンプトを英訳する。
　　　それをプロンプトとして実行。
　　　それを日本語に和訳する。
　　　プロンプト

　　　という感じ。

　　　それから、
　　　　どういう表示を
　　　　　してもらいたいか
　　　　　　を書き入れます。

　3.結果確認
　　　このプロンプトを
　　　　ChatGPTさんに与えます。

　　　プロンプトを実行して、
　　　　結果を確認します。

　4.ふつうはここまでです。

　5.ここで、次の段階に移ります。
　　　このプロンプトでは、
　　　　一度の実行で
　　　　　終わりです。

　　　もったいない。

　　　そこで
　　　　リモートワーク研究所の
　　　　　You Tube動画
[【生産性、爆増】ChatGPTをルーティン・ワーカーとして活用する方法～「指示」と「入力」を分け、用途別チャットを作ろう](https://m.youtube.com/watch?v=Pwy_4k8F6cM)
　　　　　　で紹介された
　　　　　　　プロンプトを参考に
　　　　　　　　変更。

　　　　ルーティン・ワーカー化。

　　　　一度、プロンプトを
　　　　　実行すれば、
　　　　　　何度でも使えます。

　6.整える。
　　　マークダウン記法で
　　　　「#」を付けて、
　　　　　コメントを書き入れます。

　　　コメントとは言いますが、
　　　　ChatGPTさんは、
　　　　　そこも読んでくれます。

　　　だから、
　　　　「# 目的」とか書くと
　　　　　そこは、
　　　　　　**処理の指示ではない**
　　　　　　　とわかるわけです。

　　　で、本体を
　　　　「# 処理手順」とします。

　7.実行確認する。
　　　確実に動くことを
　　　　確認します。

　　　意図した形ではない場合、
　　　　微調整をしていきます。

　　　最終的に
　　　　NewChatして、
　　　　　この指示プロンプトが
　　　　　　動作するのを
　　　　　　　確認します。

　8.記事にして、公表する。
***
　これが、
　　私がPromptを作るやり方です。

　まぁ、
　　とにかく、
　　　**文章化するのが、
　　　　大切**ですね。

　そして、
　　**文章をわかりやすく分割する**。

　複雑な文章では、
　　人にも伝わりません。

　それと同じです。

　ChatGPTさんは、
　　プログラムですが、
　　　「頭でっかちな新人」で
　　　　「毎回、明確な指示が必要」。

　セッションが変われば、
　　また、経験のない新人に
　　　戻ります。

　まぁ、セッションごとに
　　指示に特化したプロがいる、
　　　と思えば、いいのかしら。

　もちろん、
　　これは私のやり方なので、
　　　ほかのやり方も
　　　　あると思います。

　みなさんも
　　いろいろと
　　　試してみてくださいね。

***
　上記は、
　　Promptを作成する際の
　　　私のやり方ですが、

　ほかにもあります。
　　下記も参照してくださいね。
[【ChatGPT無】私がPromptを作る際のあれこれ](https://qiita.com/kabumira/items/3613ec5c67c0860633ff)
Next.js13＋TypeScript＋Tailwindでプロジェクト作成（備忘録）

# 環境構築
前提として
備忘録として書いています。間違った表現をしている可能性もありますので、ご容赦ください🙇‍♀️

## 技術スタック
- Next.js: 13.4.7
- React: 18.2.0
- Tailwindcss: 3.3.2
- TypeScript: 5.1.6

## やりたいこと
・Next.jsのバージョンアップをしたい
・過去のプロジェクトは残しつつ、作り替える！

## Gitでバージョン管理
新しいブランチを切って、古いブランチに過去のプロジェクトを退避させつつ、mainブランチに新しいプロジェクトを作成

# Gitでの操作

1. 左メニューバーからSouce Controllを開く 
1. 以下のように[Stash（Include Untracked）]を選択する
![スクリーンショット 2023-07-02 11.02.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2499272/be82e9d4-b166-2535-f3c9-52906755195a.png)
1. oldというブランチを作成
    ```
    $ git checkout -b old
    ```
1. mainブランチからプロジェクトを移動
1. 移動したプロジェクトをoldブランチに復元（以下のように[Pop Stash...]を選択する）
    ![スクリーンショット 2023-07-02 11.09.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2499272/b29e964f-0ed3-ed33-68c9-c4888d50e05b.png)

    
1. Gitのoldブランチに保存※GitHubではないよ〜
    ```
    $ git add .
    $ git commit -m "old first commit"
    ```
1. mainブランチに戻る
   ```
    $ git checkout main
   ```   
1. mainブランチ（フォルダの中身）の`.gitフォルダ`以外のファイルとフォルダを全て削除
1. 一応、ローカルホストで起動して確認
    ```
    $ npm run dev
    ```

## 既存のフォルダ内に新しいプロジェクトを作成する
1. yarnで操作したいので、バージョンを確認する
    ```
    $ yarn -v
    ```  
    以下のエラーが出た
    ```
    zsh: command not found: yarn
    ```
    1. `yarn`がないので`npm`でインストールしようとしたけど、そもそも`npm`が最新バージョンではないかもしれない！？
    1. `npm`を最新バージョンにしよう！
    1. あっ！でも、`npm`のバージョンを管理する`node`が最新バージョンではないかもしれない！？
    1. ということで、`node`を最新にしなければ！

1. `node`をアップデートする
    ```
    $ brew update
    ```
1. `node`をアップグレードする
    ```
    $ brew upgrade
    ```
1. `nodebrew`のバージョンを確認
    ```
    $ nodebrew -v
    ```
1. 以下のコマンドをターミナルで打つ
    ```
    $ nodebrew ls-remote
    ```
    これで、`nodebrew`のインストール可能な情報を引っ張ってきた
1.  上記の中から、PCにインストールしたい（使いたい）バージョンを選ぶ
    ```
    $ nodebrew install-binary v18.14.2
    ```
1.  手元に入っているnodebrewってどんなの？
    ```
    $ nodebrew list
    ```
1.  「私は、以下のバージョンを使います！」ということで以下で選ぶ
    ```
    $ nodebrew use v18.16.1
    ```
    - brewはPC全体のことだけど、nodeは基盤になる場所
    - プロジェクトごとにnodeをきちんと選ばないとエラー出たりするから注意！
    - 「node バージョン管理」とかでググると出てくるよ！
        - node envを使って、いちいちコマンド叩かなくてもプロジェクトファイルごとでバージョンが決まるということをやるのもイイかも
        - nodebrewを使うならバージョンを意識しなけばならない！
        ※ これよくみんなやりがち。事故るから要注意！！！

1.  `yarn`のバージョン確認
    ```
    $ yarn -v
    ```
    おっと！以下のエラーが・・・
    ```
    zsh: command not found: yarn
    ```
    なぜか入っていなかったみたいなので、`yarn`をインストールすることに
1. `yarn`をインストール
    ```
    $ curl -o- -L https://yarnpkg.com/install.sh | bash
    ```
1. 2度目のチャレンジ→`yarn`のバージョン確認
    ```
    $ yarn -v  
    ```
    おっと！再び以下のエラーが・・・
    ```
    zsh: command not found: yarn
    ```
    1. `npm`でやるか〜
    1. でも、`npm`アップグレードしなきゃだよね
    
1. `npm`をアップグレード
    ```
    $  npm update -g npm 
    ```
1. 3度目の正直！→`yarn`をインストール
    ```
    $ npm install --global yarn
    ```
    やっと成功〜✨
1. `yarn`のバージョン確認
    ```
    $ yarn --version
    ```
    `1.22.19`と表示されたよー
1. 既存のフォルダ内に`TypeScript`＋`Tailwind`のプロジェクト作成
    ```
    $ yarn create next-app --typescript .  
    ```
    できた！
    
    おつかれさまでした〜🎉

### 備忘録（失敗談）
以下は間違い！
```
$ yarn create next-app --typescript with-tailwindcss .
```
tailwindを使いたかったので、`with-tailwind`をつけたけど、既存のフォルダ内に`with-tailwind`というフォルダが作られてしまった
エンジニアのための「すぐに役立つ」仕事術７選

## はじめに
都内でITエンジニアとして働いている**まさきち**といいます。

ITエンジニアとしてキャリアをスタートして一年半ほど経ちます。
これまでエンジニアとして試行錯誤しながら仕事に取り組む中で、上手くいったり失敗する事もたくさんありました。
その中で取り組んできて効果があったコトを皆さんにおすすめTipsとしてお伝えしたいと思います。

## もくじ
- この記事の対象読者
- すぐに役立つ仕事術７選
    - コミュニケーションは挨拶から
    - Todoリストで1日のタスク管理
    - 感謝の気持ちを伝える
    - アウトプット型学習法
    - 逆算して目標設定する
    - 分報のすゝめ
    - 質問は具体的かつ自分なりの考えを

## この記事の対象読者
- 研修を終えて業務に入ったばかりの方
- ITエンジニアなりたての方
- 仕事の効率アップをしたい方

## コミュニケーションは挨拶から
エンジニアはリモートワークで仕事をしている人も多く、出社に比べるとコミュニケーションの手段が限られてしまいます。
仕事を円滑に進めるためには言わずもがなメンバーとのコミュニケーションを取ることがとても大切です。
そうは言っても、特にリモートだと話しかけるタイミングとか難しいですよね。。。
そこでおすすめなのが、
### 挨拶直後のコミュニケーション
です。

始業時やメンバーとの朝会の時に最初は挨拶から入ると思いますが、そのタイミングが会話のチャンスです。
挨拶それ自体も大切ですが、その後に一言付け加えるだけでコミュニケーションが生まれます。
例えば、「おはようございます！　今日は暑いですね。朝からエアコン入れちゃいました」
など、他愛ない内容でも全然OKです。会話が生まれることに意味があります。
意外な一言で共感生まれたり、同僚の意外な一面を知れたりして距離が縮まりますよ。

## Todoリストで1日のタスク管理
作業を行うときに、行き当たりばったりで進めていませんか？？
- 作業Aから着手したけど、先に作業Bが終わっていないと完了にならなかった
- 実はCの方が優先度高くて慌てて途中でCに切り替えた

このような経験ある人多いのでは無いでしょうか。
無計画で作業を進めると、待ち時間の発生や優先度による作業の切り替えでスイッチングコストがかかってしまったりして効率が悪くなります。

まずは1日の作業をTodoリスト化して、優先度や効率の良い順番に並び替えて着手してみましょう。
その際に作業時間の見積もりをしながら進められると時間感覚が鍛えられてより良いです。

## 感謝の気持ちを伝える
新人、ジュニアエンジニアの場合は先輩に協力してもらいながらタスクを進めることがほとんどだと思います。
チケットの説明、実装の要件のすり合わせ、コードレビュー...etc
先輩に時間を割いてもらっていることを忘れずにしっかり感謝の気持ちを伝えましょう。
このときに、具体的な感謝ポイントを伝えることが出来ると良いです。
教えたり手伝ったりした方もフィードバックをもらえると嬉しいですし、「この伝え方が分かりやすかったんだな」など、今後の参考にできるからです。

もちろん、同僚に対しても感謝の気持ちを伝える事も大切です。
改善案を積極的に出して実行してくれたり、為になる情報をシェアしてくれたりした人に対してありがとうを伝えましょう。伝えられた方もモチベーションが上がって良い流れができます。

## アウトプット型学習法
本を読んだり、動画で知識を得ただけで満足してませんか？
インプットしただけだと、記憶が定着せずにほとんど身に付かずに忘れていってしまいます。
インプットをしたら手を動かしてアウトプットしていきましょう。

アウトプット型学習法には下記の方法などありますが、下記の３つは特におすすめです。
- ハンズオン教材でインプットとアウトプットを同時に行う
    - アプリや環境構築を手元で動かしながら作業を行うことで理解が深まる
- 学んだ内容をブログ等にまとめて投稿する
    - インプットしたことを自分の頭で変換して、読みやすさを意識することで理解が深まる
- スライドを作ってLT会で発表する
    - 伝わりやすさを意識しながら話すことで業務上のコミュニケーションの練習になる

## 逆算して目標設定する
以前の私は目標設定をするときは、今までの自分の状況から振り返って決めていました。
去年できてなかったから今年は出来る様にしよう！とか、周りと比べてこの部分劣っている気がするから補っていこう！という風に過去の自分に焦点を当てて目標設定してました。
この目標設定の仕方だと、モチベーションも上がらないですし、自分がどこに向かっているかも不明瞭でどこへ向かっているか分からず迷子になってしまいました。
なので、下記の手法に切り替えました。

1. 自分が達成したい事、なりたい自分を考えて目標に設定する
1. そこに到達するには何が必要でどういうアクションを取れば良いのかを洗い出す
1. 細かくタスクに切り分けてこなしていく
1. 出来たこと、出来なかったことを振り返る
1. 振り返りを元にタスクを再設定する

以上の方法にすることで、自分の目指している場所と到達するまでのアクションを見失なうことが無くなるなりました。

## 分報のすゝめ
ここでいう分報とは、自分の行動したことを細かくSlackなどのチャットツールに書き込むこと。
Twitterのツイートに近い物でもあったり。
これをする事で何がいいの？というと、自分の置かれている状況をリアルタイムで上司やメンバーに共有できるので、進捗、作業手順に誤りがないか、困り事などをわざわざ本人に確認しなくても把握できる点です。
これにより、作業手順が上司の意図したものでなければ修正してもらいやすいですし、エラーなどで詰まっている時はメンバーが助けてくれることもあります。特にリモートワークの場合はお互い状況が把握しずらいと思うのでおすすめ。

## 質問は具体的かつ自分なりの考えを
自分で考えてもどうしても分からない問題は沢山あります。
そういう時に先輩やメンバーにする質問の仕方はかなり重要です。
質問する際には以下を意識することが大切です。
　- 具体的な内容
　- 解決したいこと
　- 解決に向けて自分で取り組んだこと
　- 自分なりの解決へのアクション
　
ただ起きている現象を伝えるだけではなくて、自分が今まで解決へ向けて動いたプロセスや、どの部分がクリアになれば解決できそうなのか、しっかり自分で考えて質問することが大切です。
そうすれば答える側も問題を把握しやすいので具体的な解決方法を提案しやすいです。

## 終わりに
最後まで読んでいただきありがとうございます！
ちょっとでも参考になれば嬉しいです。
ABC 308 備忘録

## 概要
　今回はABC308（2023年7月1日21:00~22:40）のポイントと自分の実装、および感想について述べて行きたいと思う。

## A問題
https://atcoder.jp/contests/abc308/tasks/abc308_a
### ポイント
- 条件に沿って場合分けをインデックス順に行い、条件を満たさなくなった瞬間に `No` と返してプログラムを終了させる
### 自分の実装
```Python:ABC_308_A.py
S = list(map(int, input().split()))

for i in range(len(S)):
    if i != 0:
        if S[i] >= S[i-1] and S[i] >= 100 and S[i] <=675 and S[i] % 25  == 0:
            continue
        else:
            print("No")
            exit()
    elif S[i] >= 100 and S[i] <=675 and S[i] % 25  == 0:
        continue
    else:
        print("No")
        exit()

print("Yes")
```
## B問題
https://atcoder.jp/contests/abc308/tasks/abc308_b
### ポイント
- 皿の色に応じて金額を`dict`の辞書型配列で保持
- 辞書にない色の皿の場合は`P_0`を加算
### 自分の実装
```Python:ABC_308_B.py
N, M = map(int, input().split())

C = list(map(str, input().split()))

D = list(map(str, input().split()))

P = list(map(int, input().split()))

ans = 0

prices = {}

for i in range(M):
    prices[D[i]] = P[i+1]

for i in range(N):
    if C[i] in prices.keys():
        ans += prices[C[i]]
    else:
        ans += P[0]

print(ans)
```
## C問題
https://atcoder.jp/contests/abc308/tasks/abc308_c
### ポイント
- 条件通りに人の番号とその人のあたりの確率を配列に保存
- `float`型で確率を保持すると、浮動小数の誤差で　`WA`となる
- `Decimal`型で確率を`10^(-10)`未満の桁まで正確に確率を抑える
### 自分の実装
```Python:ABC_308_C.py
from decimal import Decimal, getcontext

N = int(input())
coins = []
for i in range(N):
    A, B = map(int, input().split())
    getcontext().prec = 20
    coin = [i, Decimal(str(A))/Decimal(str(A+B))]
    coins.append(coin)
    
coins = sorted(coins, reverse=True, key=lambda x:x[1])

print(*[coins[i][0]+1 for i in range(N)])
```

## 感想
　今回はC問題で詰まってしまった。浮動小数型の誤差問題については分かっていたが、`Decimal`で誤差をなくすことに関してコンテスト中には思いつかなかった。似たような問題があったら復習したい。
Railsチュートリアル　第２章まとめ

### １．Scaffold
・Scaffoldで、Web上からデータモデルにアクセスできるようになる。
・ただし、簡易的なもので学習用としては利用するがあまり実用的ではない。
### ２．モデルの継承構造
・全てのモデルは各ファイル冒頭に　Model　< ApplicationRecord があり、これによって ApplicationRecord クラスを継承している。
また、 ApplicationRecord は ActiveRecord::Base　クラスを継承しており、このクラスでは、DBにアクセスできるようになっている。よって、全てのモデルは、この ApplicationRecord を継承していることになるため、データーベースにアクセス可能となる。
### ３．コントローラーの継承構造
・全てのコントローラーは各ファイル冒頭に Controller < ApplicationController があり、これによって 
 ApplicationController クラスを継承している。
また、 ApplicationController は ActionController::Base クラスを継承しており、MVCにおいて各方面とやり取りが可能となる。また、ApplicationController　に定義したルールは、これを継承する全てのコントローラーで利用可能である。
chatGPTでマクロ開発するためのTips集

## chatGPTでマクロ開発するためのTips集
私がchatGPTでマクロ開発した際のちょっとしたノウハウを備忘録としてメモしているページです。私のような非エンジニアでもchatGPTを使えば、業務にマクロ導入することは可能だと思いますが、コツや手法を知っていると生産性も上がると思いますので、皆さんのお役に立てれば幸いです。

そもそもなぜ非エンジニアである私がマクロ開発するに至ったかは、このブログでは割愛しますが、興味がある方は以下ブログもご覧ください。

https://pokotanpapa.blogspot.com/2023/05/chatgpt.html

このブログでは、chatGPTでマクロ開発を進める上で、コツや手法等の私の経験に基づいたTipsを紹介させていただきます。

### 1. マクロ生成するとき
* マクロ化したい作業の一つ一つ言語化する。その上で、プロンプトは箇条書きにフローを示す（作業が長い場合は特に推奨）。
* 具体的に示す（列や行、作業対象となるテーブルのヘッダー、セル番地、何をするのか等）
* 作業が複雑な場合は、最初から全フローを言語化しマクロ生成するのではなく、作業ブロックに分けて生成する
* もしこんな書き方でというマクロコードのイメージがある場合は、そのコードを示した上で、そのコードのどこをカスタマイズしてほしいか示す
* 生成されたマクロの意味が分からない場合は、chatGPTに不明なマクロの詳細を説明してもらう。意図した動作になっていなければ、修正内容を指示し、マクロをモディファイしてもらう。
* マクロの関数や文法を理解したい時に、具体的な事例も交えて説明してもらう（私の場合、クラスの作成方法やクラス間で変数をやり取りする方法を教えてもらいました）。
### 2. エラー対応をするとき
* エラーが発生した場合は、エラーコメントとエラーが発生しているステートメントから修正方法を提案させる。
* 作成したマクロで発生しうるエラーを考えさせ、その対策を講じたマクロにモディファイさせる。

### 3. chatGPT以外で情報収集するとき
* フレームワークで開発コードのサンプル入手
イメージする完成形があれば、そのコードをもとにchatGPTと協働でのマクロ開発は効率化します。webサイトから探すのも良いですが、情報がまとまっているフレームワークを利用することが望ましいと思います。
[Excel VBA Framework](https://www.vector.co.jp/soft/winnt/business/se492956.html#:~:text=%E2%97%86%E3%80%8CExcel%20VBA%20Framework%E3%80%8D%E3%81%A8%E3%81%AF%3F,ExcelVBA%E3%81%A7%E9%96%8B%E7%99%BA%E3%82%92%E8%A1%8C%E3%81%86%E9%9A%9B%E3%81%AB%E3%80%81%E3%82%88%E3%81%8F%E4%BD%BF%E3%81%86%E6%A9%9F%E8%83%BD%E3%82%92%E3%83%95%E3%83%AC%E3%83%BC%E3%83%A0%E3%83%AF%E3%83%BC%E3%82%AF%E3%81%A8%E3%81%97%E3%81%A6%E3%81%BE%E3%81%A8%E3%82%81%E3%81%9F%E3%82%82%E3%81%AE%E3%81%A7%E3%81%99%E3%80%82%20%E5%A4%A7%E3%81%BE%E3%81%8B%E3%81%AB%E8%A8%80%E3%81%86%E3%81%A8%E3%80%81%20%281%29%E9%96%8B%E7%99%BA%E3%81%AE%E5%8A%B9%E7%8E%87%E5%8C%96%E3%81%A8%E3%80%81%20%282%29%E4%BF%9D%E5%AE%88%E6%80%A7%E3%83%BB%E6%8B%A1%E5%BC%B5%E6%80%A7%E3%81%AE%E5%90%91%E4%B8%8A%E3%81%8C%E3%81%93%E3%81%AE%E3%83%95%E3%83%AC%E3%83%BC%E3%83%A0%E3%83%AF%E3%83%BC%E3%82%AF%E3%81%AE%E5%A3%B2%E3%82%8A%E3%81%A7%E3%81%99%E3%80%82)
* 英語で情報収集
海外ではPythonやデータサイエンス系もそうですが、マクロに関する情報は日本語よりずっと豊富なため、分からないことが日本語で見つからなければ英語検索することをお勧めします。
* 掲示板の活用
どうしても分からないことがあれば、サクッとweb上の掲示板を利用して分からないことを教えてもらいましょう。理想像は英語版の掲示板ですが日本語サイトでも問題ないかと。注意点としては、何をしたいのか、何で困っているのか、言語化出来ないと回答の精度下がります（または回答なし）
### 4. chatGPTでマクロ開発するにあたっての心構え
* chatGPTは万能ツールでないと理解すること
相手は機械です。人間と違い、阿吽の呼吸や一を聞いて十を知るということはありません。期待する結果を得るには、過不足なく言語化することが大切ですが、現実的にはその作業は難しいと思います。大切なことは、一度のやり取りで完璧なものを求めず、chatGPTと根気よくやり取りと繰り返しながら、機能するマクロを仕上げることです。
* 業務を見直す
そもそもマクロに頼らないのがベストです。作業量を0に出来なくても、従来作業のムダやダブリを少しでも改善して、マクロに取り掛かることは、マクロ開発の効率化に繋がるだけでなく、業務そのものの生産性向上に繋がると思います。

以上
Laravel サービスプロバイダーの仕組み

# Laravelのサービスプロバイダーとは

、Laravelフレームワーク内で依存関係を解決し、便利な機能を提供する仕組みです。依存関係とは、ある機能が他の機能に依存しているということで、例えばデータベースへの接続が必要な場合やメール送信に必要な設定がある場合などです。

# サービスプロバイダーの仕組みとは


### 1 依存関係の登録: 
Laravelの開発者は、アプリケーションで使用する各機能の依存関係をサービスコンテナに登録します。例えば、データベースへの接続が必要な場合、データベースクラスの依存関係を登録します。

### 2 依存関係の解決:
アプリケーションが実行される際に、サービスコンテナは依存関係を解決します。つまり、各機能が必要な道具やリソースを自動的に提供します。例えば、データベースクラスが必要な場合、サービスコンテナは自動的にデータベース接続を提供します。

### 3 依存関係の自動注入: 
依存関係の解決後、サービスコンテナは各機能に必要な道具やリソースを自動的に注入します。つまり、開発者が明示的に道具やリソースを指定する必要がなくなります。開発者はシンプルなコードを書くだけで、依存関係の解決や注入が行われます。

これによって、開発者は依存関係を意識せずにコードを書くことができ、柔軟性と保守性を向上させることができます。また、以下のようなメリットもあります。

### 4 コードの再利用性:
サービスコンテナによって、複数の機能で同じ道具やリソースを共有することができます。これにより、コードの再利用性が高まります。

### 5 テスト容易性:
サービスコンテナを使用することで、依存関係をモックやスタブに置き換えることが容易になります。


実際にLaravelのコードでサービスプロバイダーの使い方を説明します。

```
Service
  
 MessageService

<?php

namespace App\Services;


class MessageService
{
    public function send()
    {
        echo "メッセージ表示";
    }
}
```
```
Service
 
SampleService
<?php

namespace App\Services;
class SampleService
{
    public $message;

    public function __construct(MessageService $message)
    {
        $this->message = $message;
    }

    public function run()
    {
        $this->message->send();
    }
}

```

```
Controller
app()->bind('sample', SampleService::class);
 //サービスプロバイダーにsampleという名前でSampleServiceクラスを登録

 $sample = app()->make('sample');
 //sampleという名前で取り出す

 $sample->run();
//SampleServiceのrunメソットを実行

```
#### サービスコンテナを使用しない場合
```
 // $message = new MessageService();
        // $sample = new SampleService($message);
        // $sample->run();
```

##### サービスコンテナを使用する場合と使用しない場合では上記の処理を10回した場合比較すると
###### サービスコンテナを使用しない場合は、１０回分インスタンスを作成するのでリソースが増える。
###### 逆にサービスコンテナを使用するとインスタンスが再利用されるのでリソースが比較的少なくなる.


### サービスコンテナを使用しない場合のメリットとデメリット：
#### メリット：

シンプルな依存性の注入：
サービスコンテナを使用せずに直接インスタンスを生成するため、依存関係の注入がシンプルになります。

直感的なコード理解：
サービスコンテナを使用せずに依存性を明示的にコード内に表現するため、コードを読む人が依存関係をより直感的に理解できます。
#### デメリット：

手動の依存関係管理：
サービスコンテナを使用しない場合、依存関係を手動で管理する必要があります。依存性の変更や追加がある場合、各クラスのコンストラクタやメソッド呼び出しの箇所を手動で修正する必要があります。
再利用性の低下：依存関係が直接コードに埋め込まれるため、再利用性が低下する可能性があります。クラスの再利用やモジュール化が困難になる場合があります。



### サービスコンテナを使用する場合のメリットとデメリット：
#### メリット：

依存性の自動解決：
サービスコンテナを使用すると、依存関係の解決が自動的に行われます。必要なクラスやオブジェクトをサービスコンテナに登録することで、必要な箇所で自動的に依存関係が解決されます。
依存関係の柔軟な変更：依存関係をサービスコンテナに委ねることで、依存関係の変更や追加が柔軟に行えます。クラスのコンストラクタやメソッドの引数を変更せずに、サービスコンテナ内の設定を変更するだけで依存関係を調整できます。
#### デメリット：

学習コスト：
サービスコンテナの概念や使用方法を理解するために、学習コストがかかる場合があります。


複雑性の増加：
依存関係の自動解決や柔軟な変更を実現するために、サービスコンテナに設定や登録を行う必要があります。これにより、コードの理解やメンテナンスが複雑になる場合があります。また、サービスコンテナの設定や登録に誤りがあると、正しく依存関係が解決されないなどの問題が発生する可能性があります。
サービスコンテナの使用のメリットは、依存関係の解決や柔軟な変更の容易さです。特に大規模なアプリケーションや複雑な依存関係を持つ場合に、サービスコンテナを使用することで依存性の管理を効率化できます。



以上です！ありがとうございました。
【合格体験記】Java SE 11 Programmer I (1Z0-815-JPN) 試験　（Java Silver）

# はじめに
今回はJava SE 11 Programmer I (1Z0-815-JPN) 試験を受けてきました。
聞きなじみのある言い方としてはJava Silverです。
勉強期間、方法や試験を受けてみての感想をまとめてます。
他の皆様がもしJava Silverを受ける際の参考になればと思います。

# 動機
今回試験を受けた動機について
* Javaを使った開発や講師は4、5年しているが目に見える証明として資格が欲しいなと思ったこと
* 転職して資格取得支援の制度が整っており受験しやすい環境になった

上記、2つが大きな動機です。 
それ以外に、Java Silverの上位であるJava Goldの試験を受けるにはJava Silverが必須であったため

# 結果
試験結果は**合格**でした。
結果レポートは個人情報を隠すのが難しいので控えさせていただきます。orz

# 学習期間

* 学習期間：2023年6月12日～2023年6月30日 19日間 約3週間
* 学習時間：約80時間くらい
* 試験日：2023年7月1日

# 学習方法

**利用教材**
紫本：[オラクル認定資格教科書 Javaプログラマ Silver SE11（試験番号1Z0-815）](https://www.amazon.co.jp/gp/product/4798162043)
黒本：[徹底攻略Java SE 11 Silver問題集[1Z0-815]対応](https://www.amazon.co.jp/gp/product/4295007625)

**実施内容**
黒本の問題集ベースで学習を行った。
各分野ごとに章でまとめられているので、1章分の問題を解き不明点等を紫本で補うと形で学習を進めた。

**教材の感想**
個人的な感想にはなりますが、2冊とも購入して良かったなと思っております。
理由としては、模擬試験が各教材に2回分付いていますが、
多く問題を解いて慣れたかったというのがあります。

また、1冊だけでも2回分の模擬試験がついているので十分だという方もいらっしゃると思いますが、
答えを覚えてしまい本質からずれてしまうなとも思ったためです。

Javaを利用して数年ほど開発を行っている方で、
短期集中型で勉強して試験を受けたい方は黒本のみで大丈夫だと思います。

まだ、Javaの利用経験が浅い(1、2年くらい)方は2冊とも利用し、紫本でJavaの仕様や本質を理解する。
黒本で試験での出題のされ方に慣れる。
と言った教材の利用の仕方がいいと思います。

# 感想
私事で恐縮ですが、4、5年ほどJavaを触ってきて少しはJavaについて知っているつもりでした。
ですが、改めて勉強してみたらバージョンアップしたことで
変わっていた仕様や新しい技術などがあり、キャッチアップが出来ていなかったなと反省をしてました。

また、普段の開発ではコード規約である程度コーディングの仕方が決まっております。
ただ、試験ではJavaの仕様と問う内容もあり、
そんなコーディングしないよ～と思いながら初めは四苦八苦してました。

結果として無事合格することができましたが、
やはりこれまでの経験でJavaの開発を行っていたことが大きな要因だと思います。
きっと、Javaを触りたてで勉強してたら倍は時間がかかっていたのかなと思います。

次はJava Goldを年内に受け、また合格体験記を書けるよう頑張って参ります。

# 最後に

今回、Javaを改めて勉強し、まだまだ勉強や経験が足りないなと思い知らされました。
これから試験を受ける人、勉強を始める人の手助けを今後はしていきたいと思ってます。
質問などで私が答えれることでしたら、ご協力できればと思います。

最後になりますが、最後まで読んでいただきたいありがとうございました。
設計工程

```bash
要件定義
求められる条件（要件）の内容や意味を、他と区別できるように明らかにする（定義）という意味の言葉で、システム開発の「目的」を明確にする作業

基本設計と詳細設計

基本設計では、必要な要件などを確認しながらシステムの全体像を構築していく。 

詳細設計は、基本設計において固めていたシステムの全容を、具体的な機能に落とし込んで設計する段階。詳細設計は開発者視点で求めている基本設計の要件を詳細化し、開発者がプログラミングできるレベルまで落とし込んでいくフェーズになる。

機能要件と非機能要件の違い

機能要件
要件定義の中で「実装する機能」に関する要件が機能要件。
例えば、「商品Aを購入したユーザーを検索する機能」のように、実際にクライアントが必要になる機能は機能要件として分類する。

機能要件
外部機能（目に見える機能：画面、帳票等）
内部機能（目に見えない機能：データ、I/F、バッチ、外部連携等）

非機能要件
要件定義の中で、システムの性能など「実装する機能以外」に関する要件。
例えば、「商品Aを購入したユーザーを検索する機能は、3秒以内に検索が完了すること」のような主目的以外の要望は、非機能要件として分類する。

非機能要求グレードにおける6つのカテゴリ

可用性
運用スケジュールや障害発生時の復旧などに関する要求は可用性に分類される。
バックアップ体制や障害発生時の回復方法を確立させることによって対策をする。

性能/拡張性
ピーク時の負荷や業務量増加の対応などに関する要求は性能/拡張性に分類される。ソフトウェア内部の処理を効率化したり、ネットワーク機器の配置に配慮したりして、処理速度や機器の新規設置を対策する。

運用/保守性
システム運用時の稼働率や問題発生時の対応などに関する要求は運用/保守性に分類される。正常運用のための監視の充実や、運用マニュアルの拡充によって対策する。

移行性
新システム移行に関する要求は移行性に分類される。移行までのスケジュール調整や、リハーサルの実施によって対策する。

セキュリティ
利用者の制限や不正アクセスの防止などに関する要求はセキュリティに分類される。アクセスの制限や不正利用者の監視、社員への情報セキュリティ教育によって対策する。

システム環境/エコロジー
システムの設置環境や消費エネルギー量などに関する要求はシステム環境/エコロジーに分類される。設備に適した機器の選定や、環境負荷を低減させるシステムの構成によって対策する。

```
数値のみを許可するバリデーション

## はじめに

投稿フォームにamount(量)を入力する欄を作成しました。
数値のみの入力制限に合わせて数字の上限にも制限をかけました。

## 解決方法

`数値`のみ制限をかけるバリデーションです。

```rb
numericality:
```

今回はamountに数値のみを入力を許可して数値の範囲を0~500にしました。

```rb
validates :amount, numericality: { greater_than_or_equal_to: 0, less_than_or_equal_to: 500 }
```

`greater_than_or_equal_to: 0`は
amount の値が0以上であるかを検証してくれます。
つまり、負の値は許可されません。

`less_than_or_equal_to: 500`は
amount の値が500以下であるかを検証してくれます。
つまり、500より大きい値は許可されません。