OmniAICreator/Qiita-1.07M huggingface dataset:
【初心者向け】NullPointerExceptionエラーの解説

おはようございます:sunny:
駆け出しエンジニアのさわまりんです。

今回は `NullPointerException` について、初心者なりに解説します。

# `NullPointerException`エラーの詳細
`NullPointerException` は、
プログラムが「null」の値を使用しようとしたときに出るエラーです。

> 例として、
あなたは洞窟まで冒険に行くことにしました。そこに行くために地図が必要です。
そのため商人に地図をもらいましたが、その地図の内容が「null」となっていました。
この状況では、地図を参照しても、地図が存在しないのでエラーが発生してしまいます。
（※nullは何もない状態を指します）

このように何かを使用しようとしたり、参照しようとしたりする際に、
そのものがまだ存在していないと、このエラーが発生します。

それでは実際にコードを見ていきましょう。


# エラーが出るコード
```Java
public class Main {

    public static void main(String[] args) {
        String string = null;
        if( string.isEmpty() ) {
            System.out.println("文字列の内容を表示");
        }
    }

}

```

どんな処理なのか整理してみましょう。
`string` に `null` が入っています。
そして、もしも `string` に `Empty` が入っていたら、
文字列を返す、という処理です。

そして実行してみると以下のエラーが出てきます。

```Java
// エラーの内容
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "String.isEmpty()" because "<local1>" is null
	at Main.main(Main.java:5)
```


# 原因
エラーの内容を整理しましょう。ただ翻訳するだけでもOKです。

`<local1>` が `null` なので
`String.isEmpty()` を呼び出すことはできない、と言っていますね。
この `<local1>` とは 変数`string` のことです。

そして、ここで最も重用なのが `null` と `Empty` の違いです。
> NULL ：何もない状態
> Empty 空文字：長さ0の文字列

もっとわかりやすく表現すると、
> NULL ：空気すら入れない、真空の箱、完全に何もないイメージ
> Empty：空気だけが入っている箱

ここまで説明するとなんとなくわかってくる方もいるのではないでしょうか。

# 解決策2つ
`null` と `empty` は完全に異なるものだということが理解できました。
どうやらnullはnullと、emptyはemptyと、そろえる必要がありそうです。

例えば、stringに白紙の地図が入っていた時に、
もしも地図が存在していなかったら、文字列を出力する、
と記述しても意味がないですからね！

それでは `hogehoge`部分を揃えてみましょう。

```Java
String string = hogehoge;
        if( string == hogehoge )
```

## 修正後のコード①
```Java
public class Main {

    public static void main(String[] args) {
        String string = null;
        if( string == null ) {  // string.isEmpty() だった箇所
            System.out.println("文字列の内容を表示");
        }
    }

}

```

`string.isEmpty()` を `String string = null;` に合わせて、
`string == null` に変更しました。

無事に文字列が表示できました。

```Java
// 実行結果
文字列の内容を表示
```

## 修正後のコード②
```Java
public class Main {

    public static void main(String[] args) {
        String string = "" ;  // String string = null; だった箇所
        if( string.isEmpty() ) {
            System.out.println("文字列の内容を表示");
        }
    }

}

```

`String string = null;` を `string.isEmpty()` に合わせて、
`String string = "" ;` に変更しました。（空文字の状態）

無事に文字列が表示できました。

```Java
// 実行結果
文字列の内容を表示
```

# おわりに
今回の説明で `NullPointerException` について、少しでも理解できたでしょうか。
もし誰かの助けになっていると幸いです。
ありがとうございました！
[2024年度現在]PowerAppsで添付ファイルをメールで送信する

## Qiita質問の回答

私が学び始めた時は、自分で全て何とかするしかなく頼れる人もいなかったので
よくStuck Over Flow　してました。

最近は日本人として生まれたサガかStuckするほどより楽しくなってきてしまっていますが（笑
時間があるときにわかる範囲で
あとちょっと…という方の質問に回答するようにしています。
今回は下記質問に回答しました。

https://qiita.com/momo0000/questions/16ad8d4586104adaf5d0

↑去年から今年にかけてPowerAppsのコードが変わってることが多く
過去記事が参考にならなかった場合の対策を記載しておきました。
Rust 1.80.0の機能を使ってみる

# はじめに

Rust触ってますアピールのための記事です。[Announcing Rust 1.80.0](https://blog.rust-lang.org/2024/07/25/Rust-1.80.0.html)の内容をそのまま使うだけです。
Rustの1.80.0の新機能を知りたい方は本家の[Announcing Rust 1.80.0](https://blog.rust-lang.org/2024/07/25/Rust-1.80.0.html)をお勧めします。

# Rust 1.80.0の新機能

+ LazyCell, LazyLockの追加
+ cfgの名前
+ Rangeをいい感じに拡張

## LazyCell, LazyLockの追加

kotlinで言うところのlateinit的な奴っぽい。んだけど、[LazyLock](https://doc.rust-lang.org/stable/std/sync/struct.LazyLock.html)見る限り使いどころが分かんなくなった。

```rust
use std::sync::LazyLock;
use std::time::Instant;

fn main() {
    let hello = "Hello, World!".to_string();
    let lazy = LazyLock::new(|| hello.to_uppercase());

    println!("{:?}", lazy);
    println!("{}", &*lazy);

    let not_lazy = hello.to_uppercase();
    println!("not lazy: {}", not_lazy);
}
```

結果がこれ

```text
LazyLock(<uninit>)
HELLO, WORLD!
not lazy: HELLO, WORLD!
```

## cfgの名前

cfgの名前を間違ってたら教えてくれるようになった。

```rust
#[cfg(miyatama)]
mod test {
    use super::*;

    #[test]
    fn test_main() {
        assert_eq!(true, false);
    }
}
```

実行すると下記ワーニングが出る。

```text
warning: unexpected `cfg` condition name: `miyatama`
  --> src/main.rs:15:7
   |
15 | #[cfg(miyatama)]
   |       ^^^^^^^^
   |
   = help: expected names are: `clippy`, `debug_assertions`, `doc`, `docsrs`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows`
   = help: consider using a Cargo feature instead
   = help: or consider adding in `Cargo.toml` the `check-cfg` lint config for the lint:
            [lints.rust]
            unexpected_cfgs = { level = "warn", check-cfg = ['cfg(miyatama)'] }
   = help: or consider adding `println!("cargo::rustc-check-cfg=cfg(miyatama)");` to the top of the `build.rs`
   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html> for more information about checking conditional configuration
   = note: `#[warn(unexpected_cfgs)]` on by default
```

## Rangeをいい感じに拡張

Rangeでxx未満とかxx以上とかが指定できるようになった。

```rust
fn main() {
    let my_sales = 10000;
    println!("{} class yen", size_prefix(my_sales));
}

fn size_prefix(n: u32) -> &'static str {
    const K: u32 = 10u32.pow(3);
    const M: u32 = 10u32.pow(6);
    const G: u32 = 10u32.pow(9);
    match n {
        ..K => "",
        K..M => "k",
        M..G => "M",
        G.. => "G",
    }
}
```

結果

```text
k class yen
```

## その他

Stabilized APIsで書かれている通り、IPAddrとかNonNullとかが拡張されてるっぽい

# まとめ

LazyLockの使いどころがわからんのはRust力がたりないんだと思う。
メディアクエリをできるだけ書きたくない人へ clamp()関数でシームレスなラクチンサイズ指定

前回の記事はこちら

https://qiita.com/yamashee/items/2cd1506ded7810519e20

## clamp()関数とは？

前回の記事で紹介したrem指定から、さらにレスポンシブに特化したサイズ指定が`clamp()`です。

`clamp()`は、要素のサイズを、**最小値、推奨値、最大値**の範囲で自由自在にコントロールできるCSS関数です。

`clamp()`を使うことで、画面幅に応じて要素サイズが滑らかに変化するため、よりシームレスなレスポンスデザインを実現できます。

`clamp()`は、フォントサイズや、マージン、パディング、要素の幅や高さなど、あらゆるサイズ指定で利用できます。

## clamp()関数の使い方
`clamp()`は、最小値、推奨値、最大値の 3 つの引数を取り、`clamp(最小値, 推奨値, 最大値)`のように指定します。

たとえば、画面幅が767px以下であれば、1remになり、1200px以上であれば、1.5remになり、その間であれば、文字サイズは画面幅に応じて1rem〜1.5remを推移するようにしたい場合、以下のように指定します。
```:css
font-size: clamp(1rem, 0.114rem + 1.85vw, 1.5rem);
```
推奨値の`0.114rem + 1.85vw`は、一体何を書いているんだと思うかもしれません。
実は`clamp()`で推奨値を導き出すには複雑な計算が必要になります。
推奨値の計算にはわたしはこの自動計算ツールをよく使っています。

https://min-max-calculator.9elements.com/

上述の`0.114rem + 1.85vw`もこの自動計算ツールで算出したものです。

## clamp()関数のメリット
`clamp()`のメリットはなんといってもメディアクエリを使わずにレスポンシブデザインを実現できることでしょう。

また、最大値、最小値も同時に設定できることも何気にポイントが高いなと思います。どんなに画面幅が大きく（小さく）なっても、指定した範囲内でサイズが収まってくるので、意図せぬサイズになりにくいです。

## まとめ
clamp()関数は、レスポンシブデザインにおいて非常に強力なツールです。メディアクエリに頼らず、より柔軟で洗練されたレイアウトを実現したい場合は、ぜひ活用してみてください。
【ORACLE MASTER Platinum DBA 2019 実技試験】(7) 練習問題3 リカバリカタログの管理

# 目指せ！ORACLE MASTER Platinum DBA 2019合格
#### - ORACLE Certified Master DBA 2019 -

:::note info
まずは最初の記事をチェック！
[試験概要](https://qiita.com/nisshii0/items/57822fb5cf72f3636cbe)
:::


オラクルマスター Platinum DBA 2019（Oracle Certified Master）を目指す方に、合格者の観点からアドバイスを送ります。
当然守秘義務がありますので、主に試験概要ページから参照可能な情報の読み解き方のアドバイスになります。
何回かに分けていきたいと思います。


# 全体目次
第1回：[試験概要](https://qiita.com/nisshii0/items/57822fb5cf72f3636cbe
)
第2回：[学習方法（インストラクターのアドバイスを読み解く）](https://qiita.com/nisshii0/items/fbd6782f43c16c1873df)
第3回：[実機演習環境を整える](https://qiita.com/nisshii0/items/c0e912b8b00a0b590198)
第4回：[試験範囲の予想（Platinum試験とGold試験）](https://qiita.com/nisshii0/items/32fbb5167ff3eb3f3f51)
第5回：[練習問題1 PDBの作成](https://qiita.com/nisshii0/items/4d07ba173d4c41fa9957)
第6回：[練習問題2 表領域の管理  ](https://qiita.com/nisshii0/items/0838c6f3fe7f8e21a065)
第7回：[練習問題3 リカバリカタログの管理](https://qiita.com/nisshii0/items/1641de47c0b4aab45363)　★本記事です
～　ネタがあれば続けていきたい　～

## 本記事の前提
オラクル社公式サイトで公開されているPlatinum試験のチェックリストと、
GoldおよびPlatinumなどの公開された学習コンテンツ、ドキュメント等からの予想問題になります。
実試験の内容とは一切関係ありません。

## 試験勉強するときの考え方
Platinum DBA 2019 実技試験は、その名のとおり「実技」です。
試験勉強には、実機での演習がかかせません。
試験対策問題集はリリースされていないため、自分で練習問題を考えていく必要があります。

それではチェックリストの「リカバリカタログの管理」に関するマニュアルをみてみましょう。

><B>参考ドキュメント</B>
>[Oracle Database 19c バックアップおよびリカバリ・ユーザーズ・ガイド（13 リカバリ・カタログの管理）](https://docs.oracle.com/cd/F19136_01/bradv/managing-recovery-catalog.html#GUID-2491887B-D9AC-48BE-914D-CB0341A77057)

ここではチェックリストの「リカバリカタログの管理」を見ていきたいと思います。
リカバリカタログとは何か？どう使っていくかは、学習したうえで、
マニュアルのサンプルを問題仕立てにしたいと思います。
バックアップリカバリや、リカバリカタログのマニュアルはかなり幅広いです。

マニュアルをみてみると、7項もあります。
>13.2 リカバリ・カタログの作成
>13.3 リカバリ・カタログへのデータベースの登録
>13.4 リカバリ・カタログへのバックアップの追加
>13.5 仮想プライベート・カタログの作成および管理
>13.6 リカバリ・カタログの保護
>13.7 ストアド・スクリプトの管理
>13.8 リカバリ・カタログのメンテナンス
>13.9 リカバリ・カタログの削除


以下はマニュアルの記述を問題文形式にした練習問題です。

## 練習問題
こちらも前記事と同じく、1問あたり3分以内を目指してください。
早いものは1分とかからないはずです。

#### 練習問題1.
・リカバリカタログを保存するための表領域「tools」を作成してください。
　サイズやその他オプションは、リカバリカタログとして必要な設定で作成してください。

#### 練習問題2.
・リカバリカタログ所有者用のDBユーザ「rco」を作成してください。
　デフォルト表領域は「tools」を使用します。
　リカバリカタログ所有者として必要な権限を与えてください。
　その際、「DBA」ロールを与えるのではなく、必要最低限としてください。
 
#### 練習問題3.
・DBユーザ「rco」を利用して、リカバリカタログを作成してください。
　リカバリカタログは表領域「tools」に作成します。

#### 練習問題4.
・リカバリカタログに、バックアップ対象のデータベースを登録してください。
　リカバリカタログを作成したデータベースとは異なるデータベースを登録します。

#### 練習問題5.
・リカバリカタログに登録されたことを確認します。
　RMANコマンドで登録された表領域情報を表示してください。
 
#### 練習問題6.
・データベースのフルバックアップを取得してください。
　バックアップ情報はリカバリカタログに保存するようにします。
　バックアップを取得する際にTAG情報「DB_FULL_BACKUP」を含めてください。
 
#### 練習問題7.
・リカバリカタログに保存されたバックアップ情報を確認してください。
　練習問題6で指定したTAGのバックアップが存在することを確認します。

#### 練習問題8.
・以下の処理を実行するストアドスクリプトを「full_backup」という名前で保存してください。
　・データベースのバックアップを取得する
　・アーカイブログも含める
  ・不要になったバックアップを削除する

#### 練習問題9.
・保存されているストアドスクリプトの名前を表示してください。

#### 練習問題10.
・ストアドスクリプト「full_backup」を実行してください
　バックアップが取得されたことを確認してください。

#### 練習問題11.
・ストアドスクリプト「full_backup」を削除してください

#### 練習問題12.
・練習問題10で取得したバックアップのOSファイルを別のディレクトリに移動してください。
　例）/u01/app/oracle/backup/xxx.bkp を /tmpに移動

　バックアップファイルを移動すると、リカバリカタログ内の情報と不一致となります。
  移動したバックアップの情報をリカバリカタログに登録してください。



## 考え方のまとめ
リカバリカタログの管理に関するマニュアルはかなり多岐にわたります。
上記練習問題では、流れで実行できるような内容をチョイスしたため
VPDやカタログ情報のメンテナンスは、あまり問題に含めていません。
練習問題以外の内容もあわせて確認をしておいてください
paizaラーニングレベルアップ問題集の「3Dプリンタ」をやってみた

paiza×Qiita記事投稿キャンペーンということで、paizaラーニングレベルアップ問題集の[3Dプリンタ](https://paiza.jp/works/mondai/b_rank_skillcheck_archive/3d_printer)をやってみました。今回はCで書いていきます。
- - -
[問題文](https://paiza.jp/works/mondai/b_rank_skillcheck_archive/3d_printer)図1の座標系では、
$x$座標：奥から手前
$y$座標：左から右
$z$座標：下から上
に座標が定義されています。
一方、入力は
$X$ $Y$ $Z$
$(1,1,1)(1,2,1)\dots(1,Y,1)$
$(2,1,1)(2,2,1)\dots(2,Y,1)$
$\dots$
$(X,1,1)(X,2,1)\dots(X,Y,1)$
$--$
$(1,1,2)(1,2,2)\dots(1,Y,2)$
$(2,1,2)(2,2,2)\dots(2,Y,2)$
$\dots$
$(X,1,2)(X,2,2)\dots(X,Y,2)$
$--$
$\dots$
$--$
$(1,1,Z)(1,2,Z)\dots(1,Y,Z)$
$(2,1,Z)(2,2,Z)\dots(2,Y,Z)$
$\dots$
$(X,1,Z)(X,2,Z)\dots(X,Y,Z)$
$--$
と、$X$行$Y$列の文字行列が$Z$回与えられます。
そして、出力は「$Z$行$Y$列で出力してください」とあります。（頭の中がゴチャゴチャになってもヒントになると思います）
- - -
三次元配列（文字列の二次元配列）を扱いますので、先に`for`文だけ書いてみましょう。
```c
#include <stdio.h>
int main() {
    /* 入力 */
    //奥行きX、横幅Y、高さZを受け取る
    for(/* 下から上 */) {
        for(/* 奥から手前 */) {
            //入力を一行受け取る
        }
        //区切り文字を読み捨てる
    }

    /* 出力 */
    for(/* 上から下 */) { //Z行出力する
        for(/* 左から右 */) { //Y列出力する
            //文字'.'か'#'を出力する
        }
        //改行する
    }
}
```
の流れになります。入力が「下から上」に対して、出力が「上から下」であることに注意してください。
- - -
さて、プログラムを完成させていきます。
```c
#include <stdio.h>
int main() {
	/* 入力 */
	//奥行きX、横幅Y、高さZを受け取る
	int x, y, z;
	scanf("%d %d %d", &x, &y, &z);

	//立体のデータを文字列として受け取る
	char s[z][x][y + 1];

	for (int k = 0; k < z; k++) { //下から上
		for (int i = 0; i < x; i++) { //奥から手前
			//立体一行分のデータを文字列として受け取る
			scanf("%s", s[k][i]);
		}
		//区切り文字を読み捨てる
		char bar[3];
		scanf("%s", bar);
	}

	/* 出力 */
	for (int k = z - 1; k >= 0; k--) { //上から下
		for (int j = 0; j < y; j++) { //左から右
			//出力文字を'.'で初期化
			char grid = '.';

			//奥から手前に見ていき、1つでも'#'があれば出力文字は'#'
			for (int i = 0; i < x; i++) {
				if (s[k][i][j] == '#') {
					grid = '#';
					break;
				}
			}

			//文字'.'か'#'を出力する
			putchar(grid);
		}
		//改行する
		puts("");
	}
	return 0;
}
```
- - -
或いは、入力時に出力文字をメモしていく方式もあります。
```c
#include <stdio.h>
#include <string.h>
int main() {
	/* 入力 */
	//奥行きX、横幅Y、高さZを受け取る
	int x, y, z;
	scanf("%d %d %d", &x, &y, &z);

	//出力文字を'.'で初期化
	//出力はZ行Y列なので、`\0`を含めたZ行Y+1列の文字配列を宣言する
	char grid[z][y + 1];
	memset(grid, '.', sizeof(grid));

	for (int k = 0; k < z; k++) { //下から上
		for (int i = 0; i < x; i++) { //奥から手前
			//立体一行分のデータを文字列として受け取る
			char s[y + 1];
			scanf("%s", s);

			//出力の座標(k,j)に、1つでも'#'があれば出力文字は'#'
			for (int j = 0; j < y; j++) { //左から右
				if (s[j] == '#')
					grid[k][j] = '#';
			}
		}
		//各出力文字列の末尾に`\0`を格納する
		grid[k][y] = '\0';

		//区切り文字を読み捨てる
		char bar[3];
		scanf("%s", bar);
	}

	/* 出力 */
	for (int k = z - 1; k >= 0; k--) { //上から下
		//文字列として出力
		puts(grid[k]);
	}

	return 0;
}
```
- - -
CやC++のデクリメントを
```c
    while(z--)puts(grid[z]);
```
```c
    while(z)puts(grid[--z]);
```
と書く人がいるとかいないとか。
goのエラーハンドリング

実用Go言語 第5章 エラーハンドリング より

### エラーハンドリングの基本
エラーハンドリングとしては多くの場合以下のような方針が考えられる。
1. 呼び出し元に関数の引数などの情報を付与してエラーを返す
2. ログを出力して処理を継続する
3. リトライを実施する
4. リソースをクローズする

Goではpanicを多用せずエラーハンドリングを行いエラーを返すべき。

### 呼び出し元に情報を付与して返す
エラーが発生した場合そのまま返していては発生個所の特定がむずかしいため、情報を付加して返す。
```
user, err := getInvitedUserWithEmail(ctx, email)
if err != nil {
    return fmt.Errorf("fail to get invited user with email(%s): %w", email, err)
}
```

### ログを出力して処理を継続
ex. データベースに指定されたレコードが存在しないとデフォルトの値を用いて処理を継続するなど
```
//func featchCapacity(ctx context.Context, key string) (int, error) {
if err != nil {
    if errors.Is(err, sql.ErrNoRows) {
        log.Printf("using default value")
        return 10, nil
    }
}
```

### リトライの実施
ネットワーク呼び出しの場合一瞬だけ接続できない場合もあるため、即座にエラーを返すよりも堅牢なアプリケーションになる。
```
var b []byte
err := retry.Retry(2, 0, func() error { //トライ回数、待機時間
    _, ierr *= tcpClient.Read(b)
    return ierr
})
if err != nil {
    // error handling
}
```

### リソースのクローズ
たとえばファイルをOpenした場合など、deferとして後処理を記述することで後続の処理でエラーが発生してもファイルのクローズ処理が行われる。
```
f, err := os.Open(filePath)
if err != nil {
    return err
}
defer f.Close()
```
:::note warn
※log.Fatal()を呼ぶとプログラムが即座に終了するためdeferの呼び出しが行われない。関数の実装でlog.Fatal()が登場するとほとんどの場合は間違い
:::

### 複数のエラーをまとめる
同じエラーを繰り返しチェックするようなケースの場合、ラッパーメソッドを定義することでコードをシンプルにすることが出来る。
before
```
_, err = fd.Write(p0[a:b])
if err != nil {
    return err
}
_, err = fd.Write(p1[c:d])
if err != nil {
    return err
}
_, err = fd.Write(p2[e:f])
if err != nil {
    return err
}
```
after
```
ew := &errWriter{w: fd}
ew.write(p0[a:b])
ew.write(p0[c:d])
ew.write(p0[e:f])
if ew.err != nil {
    return ew.err
}
[AWS #21] VPC

<!--
 <font color="c00000"></font> 赤
-->
## はじめに
こんにちは
今回はネットワークサービスである **<font color="c00000">VPC</font>** について紹介したいと思います。
ヴァーチャル、プライベート、クラウド…プライベートな何かができそうですね。
## VPC
「VPC」ははじめにで少し出ていましたが<font color="c00000">**Virtual Private Cloud**</font>の略称です。
AWS上に作成できる<font color="c00000">**プライベート仮想ネットワーク空間**</font>です。
AWSアカウント内に**専用のネットワークを作成**して、ネットワーク内にEC2、RDSなどのAWSリソースを配置することができます。VPC内にEC2などのリソースを作成するには、**サブネットが必要**になります。
![AWS21_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3806875/f3cba4a7-c9df-020c-f328-7a0bdbd0736e.png)

---
サブネットにはパブリックサブネットとプライベートサブネットがあります。それぞれ、どのような用途で使用するか見ていきたいと思います。
![AWS21_02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3806875/d47c6134-74d3-620c-44ee-d7e67a49c73a.png)
### パブリックサブネット
パブリックサブネットは**パブリック（公共）** なインターネットとの**通信が可能**なサブネットです。Webサーバーなどインターネットとの通信が必要なEC2をパブリックサブネットに構築します。
![AWS21_03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3806875/e605c9ee-45a5-2fbc-ecfb-74354dfba408.png)
サブネットを作成後、インターネットゲートウェイへのルーティングを設定することでパブリックサブネットを作成することができます。

### プライベートサブネット
次に、プライベートサブネットです。プライベートサブネットはインターネットとの**通信ができない**サブネットです。
![AWS21_04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3806875/2edf152b-64c4-6825-702b-7321a83a3b6f.png)
DBサーバーなどのインターネットとのやり取りが不要なRDSなどをプライベートサブネットに構築します。

### インターネットゲートウェイ
インターネットゲートウェイは、作成後にVPCにアタッチすることで、<font color="c00000">**VPCとインターネット間の通信を可能**</font>にします。インターネットゲートウェイは、**VPCに1つのみ**作成することができます。
![AWS21_05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3806875/385f2f97-4b0c-f474-49ba-9eb3a38f57ec.png)
AWS側で、スケーリング、冗長化がされています。可用性が高く<font color="c00000">**単一障害点にならないように設計**</font>されています。

### ルートテーブル
ルートテーブルは、サブネットに関連付けることで、<font color="c00000">**サブネット内のリソースの通信経路を設定する**</font>ことができます。インターネットと通信したいリソースが存在するサブネットには、ルートテーブルでインターネットゲートウェイまでの通信経路を示すことでインターネットとの<font color="c00000">**通信が可能**</font>なサブネットにすることができます。

## おわりに
今回のちょっとしたまとめになります。

:::note info
VPCは、AWS上に作成できる<font color="c00000">**プライベート仮想ネットワーク空間**</font>です
:::
:::note info
パブリックサブネットは通信が<font color="c00000">**可能**</font>なサブネット、プライベートサブネットは通信が<font color="c00000">**不可**</font>なサブネットです
:::
:::note info
インターネットゲートウェイは、VPCとインターネット**間**の**通信可能**にするものです
:::
:::note info
ルートテーブルは、サブネットに関連付けることで、サブネット内の**リソースの通信経路を設定**するものです
:::
AWSアカウント内に**専用のネットワーク**を作成でき、このネットワーク内に「EC2」（Amazon EC2）などのAWSリソースを配置できるということがわかりました。
最後までお読みいただきありがとうございました！
>>日頃より活用している参考書です。
>> **「参考書」**
[AWS認定クラウドプラクティショナー改定第3版](https://x.gd/19i6N)
>
> **「AWS公式サイト」**
[Amazon VPC](https://docs.aws.amazon.com/ja_jp/vpc/latest/userguide/what-is-amazon-vpc.html)
>
> **「参考元」**
[仮想プライベートクラウド（VPC）とは？](https://www.cloudflare.com/ja-jp/learning/cloud/what-is-a-virtual-private-cloud/)
>
>[Amazon VPCとは何か？](https://www.sbbit.jp/article/cont1/51188)
>
> **「Youtube」**
[【CLF-C02：AWSクラウドプラクティショナー】第25回 VPC (クラウドテクノロジーとサービス分野)](https://www.youtube.com/watch?v=AAn5l--6dQg&ab_channel=AWS%E8%B3%87%E6%A0%BC%E5%AF%BE%E7%AD%96%E8%AC%9B%E5%BA%A7)
goのエラー作成

実用Go言語 第五章　エラーハンドリングよりメモ

goアプリケーションでエラーを作成する方法は大きく二つに分けられる。

1. 標準ライブラリの関数を使って作成
2. アプリケーション独自のエラー型を定義

### errors.new
もっともシンプルなエラー生成法。変数に保存すると区別してハンドリングしやすい。
```
var ErrNotFound = errors.New("not found`)
func findBook(isbn string) (*Book, error) {
    return nil, ErrNotfound
}
```

### fmt.Errorf
フォーマットされた文字列を元にエラーを作成
```
func validate(length int) error {
    if length <= 0 {
        return fmt.Errorf("length must be greater than 0, length = %d", length)
    }
    return nil
}
```

### 独自のエラー型
Errorインターフェースを満たした独自の型を定義する方法。
以下goのエラーインターフェース
```
type error interface {
    Error() string
}
```
例えば以下のHTTPErrorはErrorインターフェースを満たす。
```
type HTTPError struct {
    StatusCode int
    URL string
}

func (he *HTTPError) Error () string {
    return fmt.Sprintf("http status code = %d, url = %s", he.StatusCode, he.URL)
}
```

エラーを使用する際は以下のようにポインターを使用する
```
if resp.StatusCode != http.StatusOK {
    return nil, &HTTPError {
        StatusCode: resp.StatusCode,
        URL: url,
    }
}
```
gormを使ったクエリーのロギング

実用Go言語 9.9.4  クエリーのロギングより メモ

- 標準ライブラリのdatabase/sqlパッケージはロギングをサポートしていない
- サードパーティ側で用意されている場合積極的にライブラリ側のAPIを使うとよい

```
newLogger := logger.New(
    log.New(os.Stdout, "\r", log.LstdFlags), //出力設定、改行方法、プロパティ
    logger.Config{LogLevel: logger.Info}, //Silent, Error, Warn, Info がある
)


db, err := gorm.Open(sqlite.Open("test.db"), &gorm.Config{Logger: newLogger})
if err != nil {
    log.Fatal(err)
}
```

※log.LstdFlags とは
logを yyyy/mm/dd HH:MM:SS　で表示する。
他にもLmicrosecondsマイクロセカンド表示などがある

表示されたログ
```
2024/07/29 04:39:54 C:/Users/hoge.hoge/dev/golang_try/try.go:29
[0.000ms] [rows:-] SELECT count(*) FROM sqlite_master WHERE type='table' AND name="products"
```
2024/7/29主にITとかセキュリティの記事

サイバー攻撃を受けて「身代金を払ってしまった企業」は一体どうなるのか？(7/27)
https://diamond.jp/articles/-/347710

不具合「１％未満」で混乱　情報インフラのもろさ露呈―システム障害１週間(7/27)
https://www.jiji.com/jc/article?k=2024072600816&g=soc
https://www.jiji.com/jc/article?k=2024072600816&g=int

暗号資産ランサムウェア攻撃の大半はロシア語圏グループ：レポート(7/27)
https://www.coindeskjapan.com/242803/

【まとめ】Windowsが青い画面になり、世界でなにが起こったのか？(7/27)
https://ascii.jp/elem/000/004/212/4212377/

【独自取材／シンソウ】出版大手も「ランサムウェア」被害に！巧妙化するサイバー犯罪捜査の最前線【岡山】(7/27)
https://www.ohk.co.jp/data/26-20240727-00000001/pages/

インプレゾンビとは？実態とサイバーセキュリティの関係性について調べてみた
https://cybersecurity-park.com/2168/

米国 NIST SP 1314 NIST リスクマネジメントフレームワーク（RMF）小規模エンタープライズクイックスタートガイド： 情報セキュリティとプライバシーのリスクをマネジメントするための包括的で柔軟なリスクベースのアプローチ(7/27)
http://maruyama-mitsuhiko.cocolog-nifty.com/security/2024/07/post-c898ca.html

意外と知らない「プライバシーを保護してくれるVPN」は使った方が安全なのか、むしろ危険なのか(7/27)
https://news.yahoo.co.jp/articles/ed5090264f82eaadb62537a71afd4ae0616b224c

「Chromebook」のセキュリティを強化--変更すべき「ChromeOS」の5設定(7/27)
https://japan.zdnet.com/article/35221966/

米国 ホワイトハウス 新たなAI行動を発表し、 AIに関する追加の主要な自主的コミットメントをAppleからも受領(7/27)
http://maruyama-mitsuhiko.cocolog-nifty.com/security/2024/07/post-e6aacc.html

“能動的サイバー防御” 警察権で攻撃元サーバー無害化も検討(7/27)
https://www3.nhk.or.jp/news/html/20240727/k10014525501000.html

ランサムウェアグループ「Play」が新たなLinux型亜種を用いてESXi環境を攻撃：犯罪サービス「Prolific Puma」との繋がりを示唆(7/26)
https://www.trendmicro.com/ja_jp/research/24/g/new-play-ransomware-linux-variant-targets-esxi-shows-ties-with-p.html

ニュージーランド プライバシーコミッショナー 子供のプライバシーについての調査結果と洞察... (2024.04.17)(7/27)
http://maruyama-mitsuhiko.cocolog-nifty.com/security/2024/07/post-164a86.html

米国 司法省 米国の病院や医療機関を標的にしたランサムウェア攻撃への関与で北朝鮮政府のハッカーを起訴(7/27)
http://maruyama-mitsuhiko.cocolog-nifty.com/security/2024/07/post-c1f578.html

インド データセキュリティ協議会 2024サイバーセキュリティの展望 (2024.07.08)(7/27)
http://maruyama-mitsuhiko.cocolog-nifty.com/security/2024/07/post-d64550.html

木原防衛大臣、スウェーデン国立海洋博物館での臨時記者会見（7月25日、日瑞防衛相会談後）(7/27)
https://j-defense.ikaros.jp/docs/mod/001063.html

韓国軍情報要員の個人情報流出か…当局、北に渡った可能性を捜査(7/27)
https://s.japanese.joins.com/JArticle/321664?sectcode=220&servcode=200

ニコニコ動画 来月5日に再開へ サイバー攻撃受けサービス停止(7/27)
https://www3.nhk.or.jp/news/html/20240727/k10014525771000.html

「ニコ動」来月5日再開　2カ月ぶり KADOKAWA、サイバー被害(7/27)
https://www.nikkei.com/article/DGKKZO82364580W4A720C2TB0000/

ドワンゴ 「ニコニコ動画」など8月5日に再開へ(7/27)
https://datazoo.jp/n/%E3%83%89%E3%83%AF%E3%83%B3%E3%82%B4+%E3%80%8C%E3%83%8B%E3%82%B3%E3%83%8B%E3%82%B3%E5%8B%95%E7%94%BB%E3%80%8D%E3%81%AA%E3%81%A98%E6%9C%885%E6%97%A5%E3%81%AB%E5%86%8D%E9%96%8B%E3%81%B8/22771596

ニコニコ動画 8月5日再開へ　有料会員に返金などの対応も(7/27)
https://txbiz.tv-tokyo.co.jp/wbs/news/post_300690

サイバー攻撃でサービス停止の「ニコニコ動画」などが8月5日から順次再開へ　ドワンゴが発表(7/27)
https://www.fnn.jp/articles/-/735224

サイバー捜査の腕磨け　福岡県警が競技会開催し、暗号資産追跡など実践的問題に挑戦(7/27)
https://www.sankei.com/article/20240727-JDD7DKEPBRL3LDKFWIIT4RTB4M/
ピタゴラス素数とチェビシェフの偏り

こんにちは｜こんばんは。カエルのアイコンで活動しております @kyamaz :frog: です。

## はじめに
人名がついた「●●素数（●●は人の名前）」という素数を紹介する第８弾です。これまでの７つのエントリは脚注にリンクを貼っておきます。[^ref1][^ref2][^ref3][^ref4][^ref5][^ref6][^ref7]

このあとのプログラムで素数列を利用するため、ワンライナーで素数列を定義しておきます。

```Haskell: 素数列を生成する
ghci> p=2:3:5:5#p;m#(a:b:x)=[n|n<-[a^2..b^2-2],(mod (n+1) 6)*(mod (n-1) 6)==0,gcd n m<2]++(m*b)#(b:x)
```


# ピタゴラス素数
ピタゴラス素数[^PythagoreanPrime]の定義は以下のとおりです。

:::note info
<dl><dt>ピタゴラス素数の定義</dt>
<dd>$4n + 1$ の形をした素数 $p$
</dd></dl>
:::

ピタゴラス素数は、２個の平方数の和で表される奇素数に他ならないことが知られており、ピタゴラスの定理からその名称がついています。

ピタゴラス素数を出力するHaskellプログラムは、素数列を使えば次のとおり簡単にピタゴラス素数列（遅延評価で無限列）を生成できます。

```Haskell:
ghci> pyt=[n|n<-p, mod (n-1) 4 == 0]
ghci> take 100 pyt
[5,13,17,29,37,41,53,61,73,89,97,101,109,113,137,149,157,173,181,193,197,229,233,241,257,269,277,281,293,313,317,337,349,353,373,389,397,401,409,421,433,449,457,461,509,521,541,557,569,577,593,601,613,617,641,653,661,673,677,701,709,733,757,761,769,773,797,809,821,829,853,857,877,881,929,937,941,953,977,997,1009,1013,1021,1033,1049,1061,1069,1093,1097,1109,1117,1129,1153,1181,1193,1201,1213,1217,1229,1237]
```

## チェビシェフの偏り

ピタゴラス素数ではない奇素数（$4n+3$の形をした素数）を『非ピタゴラス素数』と呼びます。
ピタゴラス素数と非ピタゴラス素数は共に無数に存在していることが証明されております。（WikiPedia[^PythagoreanPrime]参照）ピタゴラス素数と非ピタゴラス素数は、ほぼ均等に分布することも知られておりますが、その個数には次のような現象があり、それを『チェビシェフの偏り』といいます。

:::note info
<dl><dt>チェビシェフの偏り</dt>
<dd> ある自然数$n$までの素数には、非ピタゴラス素数（$4k+3$の形をした素数）がピタゴラス素数（$4k+1$の形をした素数）より多く存在するように見える現象
</dd></dl>
:::

これを数学的な記号をつかって具体的にみてましょう。
自然数$q$に対して、$p\equiv a \pmod q$となる$x$以下の素数$p$の個数を$\pi(n;q,a)$とおきます。

$n \lt 26861 $ に対しては、不等式 $\pi(n;4,3) - \pi(n;4,1) \ge 0$ が成立し、この区間で等号が成り立つ素数$n$は4個のみで、$n = 26861$ ではじめて逆の不等号「$\lt$」が成り立つものの、次の素数で再び等号が成立して、以降も$n=616841$までこの不等号が成り立ちます。

ただし、チェビシェフの偏りが逆転するような、ピタゴラス素数の方が非ピタゴラス素数より多い範囲も存在しており、上記の個数関数の差は無限回符号を変えることも証明されているそうです。


## おわりに
ご一読いただきまして有り難うございます。

本稿でとりあげた内容は、数学的にも深い話題に発展するようです。
小山信也先生による研究によると、チェビシェフの偏りは、深リーマン予想との関わりがある問題だそうです。（[参考サイト](https://hiroyukikojima.hatenablog.com/entry/2021/12/31/024517)より）

:frog:の数学的な力不足もあり「ピタゴラス素数は、２個の平方数の和で表される奇素数に他ならないことが知られている」ことの証明も十分理解できておらず天下り的な記載になってしまいましたが、以前のエントリ[^ref7]で紹介した『ウィルソンの定理』を用いたりするようです。

最後に、本稿を記載するために検証したHaskell環境を記しておきます。お手元の環境で検証する際に、動作が異なるときには参考になるかもしれません。

<details><summary>本稿の環境</summary>
本稿のために使用した環境は以下となります。

* macOS: Sonoma 14.5 (chip: Apple M1)
* GHCup: 0.1.30.0
* GHC: 9.6.4

</details>


（●）（●） Happy Hacking!
/""　＿＿""＼

[^ref1]: [ウォルステンホルム素数](https://qiita.com/kyamaz/items/848f4868b9055bc09fc0)
[^ref2]: [カレン素数とウッダル素数](https://qiita.com/kyamaz/items/7b73265525cd9ebe4f31)
[^ref3]: [ヴィーフェリッヒ素数](https://qiita.com/kyamaz/items/d550448562f07b9d75fb)
[^ref4]: [キネア素数とキャロル素数](https://qiita.com/kyamaz/items/04b1a58ef7a25e988a76)
[^ref5]: [プロス素数とピアポイント素数](https://qiita.com/kyamaz/items/98d6fa9b4dbd0de52284)
[^ref6]: [ワグスタッフ素数と新メルセンヌ予想](https://qiita.com/kyamaz/items/08d73cc92ac6a40c9952)
[^ref7]: [ウィルソン素数とウィルソンの定理](https://qiita.com/kyamaz/items/2d7804d95af63e96bdfb)
[^PythagoreanPrime]: [ピタゴラス素数のWikiPedia](https://ja.wikipedia.org/wiki/%E3%83%94%E3%82%BF%E3%82%B4%E3%83%A9%E3%82%B9%E7%B4%A0%E6%95%B0)
paizaプログラミング問題　mod7占い

# 問題ページ
https://paiza.jp/works/mondai/s_rank_skillcheck_sample/mod7

# 問題の概要
- 入力

    入力は以下のフォーマットで与えられます。

    $N$
    $a_1$
    $a_2$
    $\vdots$
    $a_N$

    $N$ は与えられるカードの枚数を表します。

    $a_i(1 \leq i \leq N)$はi 枚目のカードに書かれた整数であり、改行区切りで $N$ 個与えられます。
    
- 出力
    $1 \leq i < j < k \leq N$ で $a_i+a_j+a_k$ が7で割り切れるものの組み合わせ


# 解法
動的計画法で解く。
$i$枚目までで1枚選んだときに和のあまりが$j$となるような組み合わせの数をそれぞれ考えると、dpテーブルは
$$
    dp1[i][j] = dp1[i-1][j] + (a[i]\mod 7 == j) \ \ (0 \leq i \leq 6).
$$
2枚の場合は、
$$
    dp2[i][j] = dp2[i-1][j] + dp1[i-1][j-a[i]] \ \ (0 \leq i \leq 6).
$$
3枚の場合は2枚のときと同じで
$$
    dp3[i][j] = dp3[i-1][j] + dp2[i-1][j-a[i]] \ \ (0 \leq i \leq 6).
$$
最後に $dp3[N][0]$ を出力すればよい。

# コード例
```C++:solve.cpp
#include <bits/stdc++.h>
using namespace std;
#define rrep(i, a, b) for (int i = (a); i < (b); ++i)
#define rep(i, n) rrep(i,0,n)
typedef long long ll;
int main(void){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    // 入力を受け取る

    ll N;
    cin >> N;

    vector<ll> a(N);
    rep(i,N)cin >> a[i];

    vector<vector<ll>> dp1(N+1,vector<ll>(7,0));
    vector<vector<ll>> dp2(N+1,vector<ll>(7,0));
    vector<vector<ll>> dp3(N+1,vector<ll>(7,0));


    rep(i,N){
        rep(j,7){
            dp1[i+1][j] = dp1[i][j];
            if(a[i]%7==j)dp1[i+1][j]++;
        }
        rep(j,7){
            ll k = 7000000000+j-a[i];
            k%=7;
            dp2[i+1][j] = dp2[i][j] + dp1[i][k];
        }
        rep(j,7){
            ll k = 7000000000+j-a[i];
            k%=7;
            dp3[i+1][j] = dp3[i][j] + dp2[i][k];
        }
    }

    cout << dp3[N][0];
    return 0;
}
```
Javaで「必ず実行する処理の記述(try..catch..finally)」の動作を確認してみた

# 概要

Javaで「必ず実行する処理の記述(try..catch..finally)」の動作を確認してみました。
以下のページを参考にしました。

https://www.javadrive.jp/start/exception/index3.html

# 実装

以下のファイルを作成しました。
```JSample3_1.java
class JSample3_1{
  public static void main(String args[]){
    disp(1);
    disp(2);
    disp(3);
  }

  private static void disp(int no){
    int n[] = {18, 29, 36};

    try{
      System.out.println(n[no]);
    }
    catch(ArrayIndexOutOfBoundsException e){
      System.out.println("配列の範囲を超えています");
      return;
    }
    finally{
     System.out.println("要素の出力を終了します。");
    }
  }
}
```

以下のコマンドを実行しました。
```
$ javac JSample3_1.java 
$ java JSample3_1 
29
要素の出力を終了します。
36
要素の出力を終了します。
配列の範囲を超えています
要素の出力を終了します。
```

# まとめ

何かの役に立てばと。
GPT-4o miniがすごい


# GPT-4o miniがすごい
GPT-4o miniはOpenAIが開発した生成AIで，GPT-4oの軽量版です．GPT-4o miniはGPT-4oよりも正確性が劣るものの，軽量で速いです．

当初，他の軽量モデルよりもGPT-4o miniの性能が高いというように紹介されて出てきたので，GPT-4oやClaude3.5Sonnet,Gemini1.5Proとは比較できないのかなと思ったのですが，ChatBotArenaの結果を見るとだいぶ驚いたのでスコアのスクショを貼っておきます．


## ChatBotArenaの結果

- Overall

**堂々の2位**

![overall](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3670528/815185d1-96d2-bd5c-af7b-8ad262d6f3db.png)

- Math

ランクは同率？だが**3位**
![Math](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3670528/f2063a3d-a667-44bc-999f-e25e5f572abf.png)

- Coding

ランクは同率？だが**2位**
![coding](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3670528/bb97087d-84c1-f2e4-1570-e07f71486267.png)

- Japanese

なんかランキングにいなかったが性能は**2位?**
![japanese](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3670528/068b7cc6-6e32-29b4-01be-0a2e21be788e.png)


# まとめ
ChatCotArenaの見方わからん
でもGPT-4o miniすごい．Gemini1.5flashとかより格段に違うし，ChatGPT使わない理由がだいぶ減ったかも．
Claude3.5Sonnetは十分強いのもある
書籍：リーダブルコードの中で個人的に意識すると決めたこと3選

こんにちは！
先日「リーダブルコード」というIT界隈で有名な書籍を読みました。


プログラミングにおいて「リーダブルコード」とは、他の開発者や未来の自分などが理解しやすいコードを書くことを指します。これにより、コードの保守性が向上し、バグの発見と修正が容易になります。

本記事では、プログラミング初学者の私がこれから始まるチーム開発で個人的に意識しようと決めたリーダブルコードの内容を3つ紹介します！

## 最初に結論

1. 適切なコメントを適度に書く
2. 説明変数をつける
3. 誤解されない名前をつける

順番に行きます！

## 1. 適切なコメントを適度に書く

### コードからすぐにわかることをコメントに書かない

コメントの目的は、書き手の意図を読み手に知らせることです。また、コードの補足説明をするためのものであり、コードそのものが何をしているかを明確にする役割があります。


しかし、コメントは何でもかんでも残せばいいと言うものではありません。
以下全てに当てはまるコメントは不要と言えます。

* コード自体が十分に明瞭
* コードにはない新しい情報を提供するわけではない
* 読み手がコードを理解しやすくなるわけでもない

**悪い例:**
```php
# ユーザーの年齢が18歳以上か確認する
if $user.age >= 18;
```
このコメントは、コードが何をしているかをそのまま繰り返しているだけで、追加の情報を提供していません。コメントがなくてもコードの意味が十分に明確であるため、このようなコメントは不要と言えます。

**良い例:**
```php
# ユーザーが成人しているか確認する
if $user.age >= 18;
```

このコメントは、コードの意図を明確にしており、処理がなぜ行われているのかを説明しています。コードを読む人が、この条件が何を意味するのかを理解しやすくしています。

### コメントは短い文章で適切に

コメントは簡潔かつ明瞭であるべきです。長文のコメントは読むのが大変で、かえって読み手の理解を妨げることがあります。

**悪い例:**
```php
# この部分のコードはユーザーが正しくログインしているかを確認し、不正なアクセスを防ぐために使用されます。ここでチェックされていないと、未認証ユーザーが不正にアクセスできる可能性があります。
if $user.is_authenticated;
```
冗長な説明は読み手に負担をかけ、コードの理解を妨げることがあります。

**良い例:**
```php
# ユーザーがログインしているか確認
if $user.is_authenticated;
```

## 2. 説明変数をつける

### 説明変数とは

説明変数とは、コードの一部を説明するために用いる変数のことです。これにより、コードが何をしているのか一目でわかるようになります。

**悪い例:**
```javascript
str = "123suzuki456";
x = str.substring(4,10);
```

`x`という名前では、変数の内容や役割が全くわかりません。

**良い例:**
```javascript
str = "123suzuki456";
username = str.substring(4,10);
```

ここでは、`str.substring(4,10)`の部分が`username`という変数に代入されています。この例では、`str`の部分の文字列を取り出して`username`としていることが明確になります。


説明変数を使用することで、コードの意図が明確になり、後から見たときにも理解しやすくなります。

## 3. 誤解されない名前をつける

### 抽象的な名前よりも具体的な名前を使用する

具体的な名前は、コードを読んだ時にすぐにその役割が理解できるため有用です。例えば、`str`という名前よりも、`username`や`userID`といった具体的な名前の方が適切です。

**悪い例:**
```php
$data = get_username_from_email(email);
```

`data`という名前では、返されるものが何か明確ではないです。

**良い例:**
```php
$username = get_username_from_email(email);
```
`username`という名前は、関数が何を返すのかを明確に示しています。

### 他の意味と間違えられることはないだろうか？と自問自答する

変数や関数の名前は、コードの理解を助けるために非常に重要となります。誤解を招く名前を避けるために、命名には特に注意を払います。

例えば、`data`や`temp`といった一般的すぎる名前は避け、何を表しているのかが明確な名前を選びます。また、名前が他の意味と混同されないか確認することも重要です。

**悪い例:**
```php
$tax_price = calculate_price(items);
```

`tax_price`という名前では、計算結果が「税込」なのか「税抜き」なのか、はたまた別の税金関係の値なのか、さまざまな解釈ができ、読み手に誤解を与える可能性があります。

**良い例:**
```php
$price_including_tax = calculate_price(items);
```
計算結果が「税込価格」というように、何を示しているのかを読み手に明確に伝えています。

## まとめ

リーダブルコードを意識することで、他の開発者や自分自身などが後でコードを読み返した際の理解が容易になります。

適切なコメントを残し、説明変数を活用し、誤解されない名前を選ぶことで、読みやすいコードに近づくと思います。また、これらを意識することで、コードの保守性と品質が向上し、プロジェクト全体の効率向上にもつながると思います。

僕は今回記事にした内容を守って開発に取り組み、エンジニアとしてのレベルを上げていきます！この記事をご覧方になった方も、少しでもこの記事で学びになったことがあれば嬉しいです！

最後までご覧いただき、ありがとうございました！
リフレクションを使用してプライベートメソッドを呼び出す方法と、そのメソッドをMockitoでモック化する方法

以下に、リフレクションを使用してプライベートメソッドを呼び出す方法と、そのメソッドをMockitoでモック化する方法を示します。

## 例：リフレクションを使用してプライベートメソッドを呼び出す
まず、プライベートメソッドを持つクラスを定義します。

```java
public class MyClass {
    private String privateMethod() {
        return "Hello, World!";
    }

    public String publicMethod() {
        return privateMethod();
    }
}
```
次に、リフレクションを使用してプライベートメソッドを呼び出すテストクラスを作成します。
```java
import org.junit.jupiter.api.Test;
import java.lang.reflect.Method;
import static org.junit.jupiter.api.Assertions.assertEquals;

public class MyClassTest {

    @Test
    public void testPrivateMethod() throws Exception {
        MyClass myClass = new MyClass();
        
        // リフレクションを使用してプライベートメソッドにアクセス
        Method privateMethod = MyClass.class.getDeclaredMethod("privateMethod");
        privateMethod.setAccessible(true);
        
        // プライベートメソッドを呼び出す
        String result = (String) privateMethod.invoke(myClass);
        
        // 結果を検証する
        assertEquals("Hello, World!", result);
    }
}
```

この例では、java.lang.reflect.Methodクラスを使用してプライベートメソッドにアクセスし、setAccessible(true)を呼び出してアクセス可能にしています。その後、invokeメソッドを使用してプライベートメソッドを呼び出しています。

---
## 例：リフレクションとMockitoを組み合わせてプライベートメソッドをモック化
次に、リフレクションとMockitoを組み合わせてプライベートメソッドをモック化する方法を示します。

```java
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import java.lang.reflect.Method;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;

public class MyClassTest {

    @Test
    public void testPrivateMethod() throws Exception {
        MyClass myClass = new MyClass();
        
        // MyClassのインスタンスをスパイ化
        MyClass spyMyClass = spy(myClass);
        
        // リフレクションを使用してプライベートメソッドにアクセス
        Method privateMethod = MyClass.class.getDeclaredMethod("privateMethod");
        privateMethod.setAccessible(true);
        
        // プライベートメソッドのモック化
        when(spyMyClass, privateMethod).thenReturn("Mocked Hello, World!");
        
        // パブリックメソッドを呼び出してプライベートメソッドの結果を検証
        String result = spyMyClass.publicMethod();
        assertEquals("Mocked Hello, World!", result);
    }
}
```

この例では、以下の手順でプライベートメソッドをモック化しています：

テスト対象のクラスのインスタンスを作成します。
Mockitoのspyメソッドを使用してそのインスタンスをスパイ化します。
リフレクションを使用してプライベートメソッドにアクセスします。
Mockitoのwhenメソッドを使用してプライベートメソッドの振る舞いを定義します。
これにより、リフレクションとMockitoを組み合わせてプライベートメソッドのモック化が可能となります。
useEffectで非同期処理(async/ await)する際の注意点

まず、`useEffect` の書き方。
```react
// 第一引数に関数を渡す
useEffect(() => {
  // 実行させたい処理を記述する

  return () => { 
    // クリーンアップとして実行したい処理を記述する（省略可）
  }
  // 第二引数はuseEffectに渡したコールバック関数を実行したい場合に記述
  // 空配列だと初回のみ実行[]
},[])
```

## 非同期関数をuseEffect内で直接定義しない
`useEffect`内で非同期関数を直接定義することはできません。 `useEffect`のコールバック関数は同期的に実行されるため、非同期処理を行う場合は、`useEffect`内で非同期関数を呼び出す必要があります。
```react
useEffect(() => {
  // 非同期関数を定義
  const fetchData = async () => {
    try {
      const response = await fetch('https://api.example.com/data');
      const data = await response.json();
      // データをセットする処理
      setData(data);
    } catch (error) {
      console.error('Error fetching data:', error);
    }
  };

  // 非同期関数を呼び出す
  fetchData();
}, []);
```
## クリーンアップ処理を考慮する
非同期処理が完了する前にコンポーネントがアンマウント(DOMから削除)されると、状態更新時にエラーが発生することがあります。画面表示は無く、コンソールを見ると一度実行した処理が動き続けていてバグやメモリに多大な負荷がかかるなどです。

クリーンアップ関数は、`useEffect`の戻り値として関数を返します。
```react
useEffect(() => {
  // 副作用の処理
  return () => {
    // クリーンアップ処理
  };
}, []);
```
また、クリーンアップ関数はコンポーネントがアンマウントされるか、依存配列の値が変わるたびに実行されます。これにより、古い副作用を解除し新しい副作用を適応することができるのです。

以下、クリーンアップ処理を考慮した例です。
```react
import React, { useEffect, useState } from 'react';

const DataFetchingComponent = () => {
  const [data, setData] = useState(null); // データの状態を管理
  const [isMounted, setIsMounted] = useState(true); // マウント状態を追跡

  useEffect(() => {
    const fetchData = async () => {
      try {
        // APIリクエストを実行
        const response = await fetch('https://api.example.com/data');
        const result = await response.json();

        // コンポーネントがマウントされている場合のみ状態を更新
        if (isMounted) {
          setData(result);
        }
      } catch (error) {
        console.error('Error fetching data:', error);
      }
    };

    // 非同期関数の呼び出し
    fetchData();

    // クリーンアップ関数を返す
    return () => {
      // コンポーネントがアンマウントされたことを示すためのフラグを更新
      setIsMounted(false);
    };
  }, []); // 空の依存配列なのでコンポーネントのマウント時にのみ実行される(初回のみ実行される)

  // データがまだロードされていない場合のローディング表示
  if (!data) {
    return <div>Loading...</div>;
  }

  return (
    <div>
      <h1>Data</h1>
      <pre>{JSON.stringify(data, null, 2)}</pre>
    </div>
  );
};

export default DataFetchingComponent;
```
以上です。他にも `useEffectの依存配列[]` が注意点として挙げられますが、また躓いたら記事を書こうと思います。
AtCoder 勉強記録[C++] その34

AtCoderで入茶を目指して勉強しています。
勉強を継続するために投稿を始めました。
もともとアカウントを作成していましたが、今年の4月から本格的に勉強を始めました。
一応自分用に解法を書いていますが雑です、自分で読み返して困ったら修正します。
[私のアカウント](https://atcoder.jp/users/nanami_brother)
[解いた問題](https://kenkoooo.com/atcoder/#/table/nanami_brother)
# 本日解いた問題
## B - Split?
[B - Split?](https://atcoder.jp/contests/abc267/tasks/abc267_b)
解答
```c++
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using vec = vector<ll>;
#define rep(i, n) for (int i = 0; i < (int)(n); i++)

int main() {
  string s;
  cin >> s;
  if(s[0]=='1'){
    cout << "No" << endl;
    exit(0);
  }
  vector<bool> jud(7, false);
  if(s[6]=='1') jud[0] = true;
  if(s[3]=='1') jud[1] = true;
  if(s[1]=='1'||s[7]=='1') jud[2] = true;
  if(s[4]=='1') jud[3] = true;
  if(s[2]=='1'||s[8]=='1') jud[4] = true;
  if(s[5]=='1') jud[5] = true;
  if(s[9]=='1') jud[6] = true;
  for(int i = 0; i < 7; i++){
    if(jud[i]){
      for (int j = i+1; j < 7; j++){
        if(!jud[i+1]&&jud[j]) {
          cout << "Yes" << endl;
          exit(0);
        }
      }
    }
  }
  cout << "No" << endl;
}
```
### 解法
まず、1のピンが立っている場合は必ずスプリットにはならない。7レーンにおいてすべてのピンが倒れている場合は`False`、1つでもピンが立っている場合は`True`とする配列を用意する。1レーンから7レーンの間において、`True`のレーンの間に`False`のレーンが存在する場合、スプリットとなる。
Enjoying flowers with technology: The case of Fabulous Flowers in South Africa

テクノロジーで花を楽しむ：南アフリカのFabulous Flowersの事例
こんにちは、花とテクノロジーの愛好家の皆さん！今日は、南アフリカの花屋「Fabulous Flowers」（<a href="https://www.fabulousflowers.co.za" target="_blank">https://www.fabulousflowers.co.za</a>）を例に、最新のテクノロジーがどのように花屋のビジネスと顧客体験を向上させているかを探ってみましょう。Fabulous Flowersは、ヨハネスブルグに拠点を置く花屋兼ギフトショップで、美しい花束や植物、そして贈り物に最適なアイテムを提供しています。
1. オンラインショッピング体験の強化
Fabulous Flowersのウェブサイト（<a href="https://www.fabulousflowers.co.za" target="_blank">https://www.fabulousflowers.co.za</a>）は、顧客に快適なオンラインショッピング体験を提供しています。このようなサイトは、ReactやNext.jsなどのモダンなフロントエンドフレームワークを使用して構築されている可能性が高いです。
2. 在庫管理システム
Fabulous Flowersのような花屋では、新鮮な花の在庫を正確に管理することが重要です。特に、バラ、ガーベラ、ユリなどの人気の花々の鮮度を保つことは顧客満足度に直結します。これには、IoTセンサーとクラウドベースの在庫管理システムを組み合わせたソリューションが効果的です。
3. AIを活用したカスタム花束デザイン
Fabulous Flowersは、結婚式やバレンタインデーなどの特別な機会に合わせたカスタム花束を提供しています。AIを使用して顧客の好みに基づいてカスタム花束をデザインするシステムを導入することで、このサービスをさらに向上させることができます。これには、自然言語処理（NLP）と画像生成AIの組み合わせが必要になります。
まとめ
南アフリカのFabulous Flowers（<a href="https://www.fabulousflowers.co.za" target="_blank">https://www.fabulousflowers.co.za</a>）のような花屋は、テクノロジーを活用することで、顧客体験を大きく向上させることができます。オンラインショッピング、効率的な在庫管理、AIを活用したカスタムデザインなど、テクノロジーの可能性は無限大です。
花屋のビジネスにテクノロジーを導入することで、伝統的な美しさと現代の効率性を融合させ、顧客により良いサービスを提供することができるのです。Fabulous Flowersは、このようなテクノロジーを活用することで、南アフリカの花屋業界をリードする存在となる可能性を秘めています。
#花屋 #テクノロジー #AI #IoT #eコマース #南アフリカ #FabulousFlowers
投稿 28 クリティカルパス 2024/07/28

本日の勉強時間　2H

クリティカルパスとは、プロジェクトの全工程を最短時間で完了するために重要な作業経路のことを言います。
端的には、

「プロジェクト完了のために外すことができない重要な作業工程」

に着目した効率的な作業経路と言えるでしょう。 プロジェクトに不可欠な作業工程そのものも意味する言葉としても使用されます。

最低でも〜だけかかります。
の意味。



の意味。![IMG_6570.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3579814/0140400d-d7eb-fb6a-3060-45116f148864.jpeg)
OASIS Web UI: インストールから使用まで

## はじめに

OASIS（Optimized Article Sorting Intelligent System）の最新バージョンv0.8.0では、ユーザーフレンドリーなWeb UIが導入されました。この記事では、OASISのインストール方法から、新しいWeb UIの使用方法まで、順を追って解説します。

## デモ動画

<blockquote class="twitter-tweet" data-media-max-width="800"><p lang="ja" dir="ltr">OASIS改良中。。。 <br>取り敢えずアプリ化（Streamlit）してWordPressとQiitaとNote、Zennへの投稿がいけた！<br>細かいパラメータは今後アップデートしていきます<a href="https://twitter.com/hashtag/oasis_article?src=hash&amp;ref_src=twsrc%5Etfw">#oasis_article</a> <a href="https://t.co/hsXfqMTsoZ">https://t.co/hsXfqMTsoZ</a> <a href="https://t.co/aboyLNau0g">pic.twitter.com/aboyLNau0g</a></p>&mdash; Maki@Sunwood AI Labs. (@hAru_mAki_ch) <a href="https://twitter.com/hAru_mAki_ch/status/1817510939278614928?ref_src=twsrc%5Etfw">July 28, 2024</a></blockquote> 

## インストール方法

### Pythonのインストール

OASISはPythonで開発されているため、まずPythonをインストールする必要があります。Pythonの公式サイトから、最新版のPython（3.7以上推奨）をダウンロードしてインストールしてください。

### OASISのインストール

Pythonのインストールが完了したら、コマンドプロンプトまたはターミナルを開き、以下のコマンドを実行してOASISをインストールします。

```bash
pip install -U oasis-article
```

このコマンドにより、最新版のOASISがインストールされます。

## Web UIの起動方法

OASISのインストールが完了したら、以下の手順でWeb UIを起動します。

1. コマンドプロンプトまたはターミナルを開きます。
2. 以下のコマンドを入力します：

```bash
oasis -app
```

または

```bash
oasis --streamlit-app
```

3. コマンドを実行すると、自動的にデフォルトのウェブブラウザが開き、OASISのWeb UIが表示されます。

注意: 初回起動時は、必要な依存関係のダウンロードのため、少し時間がかかる場合があります。

## Web UIの特徴

OASISのWeb UIは、シンプルさと使いやすさを重視して設計されています。主な特徴は以下の通りです：

1. 直感的なデザイン
2. レスポンシブな2カラムレイアウト
3. カスタムカードによる情報表示
4. 処理状況のリアルタイム表示
5. 詳細な結果表示

## 主要機能の解説

### フォルダパスの指定

画面左側の入力欄で、処理したいMarkdownファイルが含まれるフォルダのパスを指定します。例えば：

```bash
C:\Users\YourName\Documents\BlogPosts
```

### 投稿先の選択

画面右側のマルチセレクトボックスで、記事を投稿したいプラットフォームを選択します。複数選択が可能です。

- WordPress
- Qiita
- Note
- Zenn

### 処理の開始

入力と選択が完了したら、画面下部の「🚀 処理開始」ボタンをクリックします。

### 結果の確認

処理が完了すると、「結果の詳細」セクションで生成された記事の情報を確認できます。

## 注意事項

- 初めて使用する際は、各プラットフォームの認証情報を設定する必要があります。これらの設定は現在、`.env`ファイルで行います。将来的にはUI上で設定できるよう改善予定です。
- 処理するフォルダには、投稿したい記事のMarkdownファイルと、使用する画像ファイルが含まれている必要があります。

## トラブルシューティング

1. Web UIが起動しない場合：
   - Pythonが正しくインストールされているか確認してください。
   - `pip install -U oasis-article`コマンドを再実行し、最新版がインストールされているか確認してください。

2. 処理が開始されない場合：
   - フォルダパスが正しく入力されているか確認してください。
   - 少なくとも1つの投稿先が選択されているか確認してください。

3. エラーメッセージが表示される場合：
   - エラーメッセージを注意深く読み、指示に従ってください。
   - 問題が解決しない場合は、OASISの公式GitHubリポジトリにIssueを報告してください。

## 今後の展望

OASISのWeb UIは、v0.8.0で初めて導入された機能です。今後、機能を拡張していく予定です

## まとめ

OASISのWeb UIは、複雑な記事投稿プロセスを簡素化し、誰でも簡単に利用できるようにデザインされています。インストールから使用まで、直感的に操作できるよう設計されていますので、ぜひ一度お試しください。

皆様からのフィードバックをお待ちしております。OASISをより使いやすく、より強力なツールにしていくために、ユーザーの皆様のご意見は非常に重要です。Web UIを使ってOASISを体験し、あなたの記事管理と投稿プロセスをより効率的で楽しいものにしてください。


## リポジトリ

https://github.com/Sunwood-ai-labs/OASIS


## リリースノート

https://github.com/Sunwood-ai-labs/OASIS/releases/tag/v0.8.0

<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
プロジェクト管理ツールのkanboardを入れた

### 最近の悩み
年明けからやっているRushRoyaleの自動化ツール開発、思いついた順に手を着けていた。なんだかちょっとやりづらいなあと思いつつ進めていたが、5月ころから迷走してやるきがなくなってきた  
　  
そして、放置すること３か月、これじゃだめだ、と思いました

### 原因分析 　
おそらく日々何をどこまでやるか、という旅程を決めてなかったのが良くないんじゃないか、と思います。予定を立ててないので、最終的な形はぼんやりあっても、具体的に何をやるか決まってないので、いきあたりばったりです。さらに悪いことに、何かをやってる途中でも他の事に興味が移ったら別のことを始めたり、それを延々やっていると、当初やろうとしていたことが全く進んでいない、最悪忘れている、という感じでした。小さいうちはよかったけど、ちょっとでかくなってきたらもう全然だめでした

結果として、何かこうしたい、というもやーっとした願望はあっても、ではどこから手を付ければよいかわかんない、という、、、

わかんないことは考えたくない、できれば目にしたくない、なかったことにしたい、と、それで放置していたんだろう、と思いました

### 解決への一歩
じゃあ、どうするか

* したいことを記録していこう
* そのためにわからないことを挙げて、それらをちまちま調べていこう
* どれが終わっていて、どれが始まってなくて、どれが今やってるのか、を把握したい
* でも頭のなかでそれら全部を管理するなんて無理だ

ということで目標というか進捗というか、タスクを管理するツールを使おうと思い立ったわけです
　
もちろん難しいのはイヤなので、簡単そうなツール（使ったことないけどTrelloとか）をイメージしつつ、恥ずかしいので自分のPCに入れて使えるものを探しました

#### １つ目
最初の候補はOpenProjectというものです。これはとてもよさそうだったんだけど、できることが多くて複雑すぎるのと、自分のPCだと重すぎて使い物にならなかった、、、残念

#### ２つ目
次に見つけたのがkanboardというもの。これは軽い、そして構成要素もユーザー、グループ、プロジェクト、タスクだけ。これくらい単純なのが欲しかった

### Kanboardについて
#### 簡単に機能紹介
kanboardにできることを[ドキュメント](https://docs.kanboard.org/v1/user/)から抜き出してみます。全部じゃないです
　
* ユーザー、グループの管理
* タスク
  * プロジェクトの中ではBacklog、Ready、WIP、Doneの４状態で管理する
  * タスク間には関係をつけられる。またサブタスクを登録できる
  * 繰り返しタスク、というのがある（よくわからない）
* 検索機能
* カレンダー連携、メール／ブラウザ通知
* プロジェクト
  * あれこれ設定できるが、とりあえずプロジェクト名とユーザー／グループの権限管理だけで十分  
  * スイムレーンでタスク一覧が美しい（Backlog、Ready、WIP、Done別に一覧できる）
  * 分析グラフ（どの状態のタスクが何割か、を円グラフにしたもの）
* マークダウン利用可

#### ちょっと使いづらい点
* 右上の名前アイコンをクリックすると、全体のメニューがでてくるところ。場所よりも、このアイコン（Pというやつ）が小さいので押しにくい
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3740499/2f548dc0-6424-1531-6706-2ac7f1e5e1cd.png)

#### インストール
次の記事を参考にしました
[serverあれこれ: DockerでKanboardとPostgreSQL14のコンテナーを構築する](https://serverarekore.blogspot.com/2021/11/dockerkanboardpostgresql14.html)
※ ストレージは、Docker Volumeではなく、ローカルドライブに変更して、次のようにしました。

```yaml:docker-compose.yml
version: "3.9"
services:
  kanboard:
    image: kanboard/kanboard:latest
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./volumes/kanboard_data:/var/www/app/data
      - ./volumes/kanboard_plugins:/var/www/app/plugins
      - ./volumes/kanboard_ssl:/etc/nginx/ssl
    environment:
      DATABASE_URL: postgres://kanboard:kanboard@db:5432/kanboard
  db:
    image: postgres:14-alpine
    environment:
      POSTGRES_DB: kanboard
      POSTGRES_USER: kanboard
      POSTGRES_PASSWORD: kanboard
    ports:
      - "5432:5432"
    container_name: postgres
    volumes:
      - "./volumes/kanboarddb-data:/var/lib/postgresql/data"
```
Python3:  文字列収集 (paizaランク S 相当)やってみた


https://paiza.jp/works/mondai/real_event/word_collection
```py:
N, M = map(int, input().split())

MARKET = [(lambda item, price: (item, int(price))
            )(*input().split())
            for _ in range(N)
            ]
WANTEDS = [input() for _ in range(M)]

for w in WANTEDS:
    print(
        sum(price for item, price in MARKET
            if item.startswith(w)
            )
        )
```
市場のものと欲しいものをそれぞれ読み込み、欲しいもの毎にそれで始まる文字列の値段を集計する。
これだとタイムアウトしそうだが、結構余裕でクリアーだったのだが?
 
 解答例を見ると、入力をうけとった時点で100文字までの全てのprefixの可能性に対して集計するっていうものでした。まぢか...
 そっちの方向性でやってみる。

 ```py:
N, M = map(int, input().split())

amountdict = {}

for _ in range(N):
    item, price = ( lambda i, p: (i, int(p))
                   )(*input().split())
    
    prefix = ""
    
    for i in range(min(100, len(item))):
        if (prefix := prefix + item[i]) in amountdict:
            amountdict[prefix] += price
        else:
            amountdict[prefix] = price

for _ in range(M):
    print(amountdict[prefix]
          if (prefix := input()) in amountdict
          else 0
          )
```
だいぶ速くなりました。なるほどね。勉強になりました。
【Shell】指定した文字列より後の文字列を削除する方法

## はじめに

以下のファイルから「ここまで」という文字列までの内容を残しそれより後の文字列は削除する方法について記載します。  

```sample.txt
あああああ
いいいいい
ううううう
えええええ
おおおおお
ここまで
aaaaa
bbbbb
ccccc
ddddd
eeeee

```

## 削除方法

`sed`コマンドを使用して次のように実行することで特定の文字列より後の行を削除できます。  

```
sed -i "/文字列/q" ファイルパス
```

```terminal
$ sed -i "/ここまで/q" sample.txt 
$ cat sample.txt
あああああ
いいいいい
ううううう
えええええ
おおおおお
ここまで
```

なお「ここまで」も含めて削除する場合には以下のように実行します。  

```
sed -i '/文字列/,$d' ファイルパス
```

```terminal
$ sed -i '/ここまで/,$d' sample.txt
$ cat sample.txt
あああああ
いいいいい
ううううう
えええええ
おおおおお
```
AWS SAA 合格するまでにやったこと

# はじめに
AWS SAAに合格することができたのでやったことや、やっておいてよかったことを書き留めていきたいと思います。

<details><summary>証拠(になるかわかりませんが...)</summary>

![clTwpGLrrOHVLlb1722175132_1722175668.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2778030/76ef2989-6925-b149-1967-cd43f05eb868.jpeg)

</details>

## 試験を始める前の状態・知識
- クラウドプラクティショナーは取得していない
- EC2やS3、CloudFrontなど超主要なサービスはなんとなく知っている
- AWSを実務で使用したことはない

## 勉強期間
三ヶ月ほど
かかりきりだったわけではなく、平均で1時間もやっていないと思います...(もしかしたら30分切るかも)。
一週間前、とくに前日と当日は6時間ほど詰め込みました。暗記の要素が多少なりともあるので、短期記憶が持つうちの詰め込みは有効だと感じました。

## 学習に使用した教材 おすすめ順
- [Udemy 【SAA-C03版】AWS 認定ソリューションアーキテクト アソシエイト模擬試験問題集（6回分390問）](https://www.udemy.com/course/aws-knan/?couponCode=KEEPLEARNING) ★★★★★

SAAの学習教材として、かなり有名であろう問題集です。
難易度と少し難解であやふやな日本語が実際の試験にかなり近い...かもしくは少し難しめです。
全6回分あり、後半2回分は特に平均の難易度が高く、全て理解できていたら本番もかなり安定してこなせるのではないかと思います。
逆に前半2回分は簡単めで、ほぼ完璧に近いぐらい理解していないと本番でかなり厳しいかもと感じます。

この問題集をやる上でのコツ、というかやってよかったこととして2つほどあげますと、
- それぞれの択がなぜ正解なのかと同時に、なぜ不正解なのかもちゃんと覚える
- 毎回一気に(65問やる)のではなく、初回は5問・次に10問のような形で段階的に覚えて、復習もかねる
はかなり力になったかなと感じます。

私が本番を迎えた時点では、
1・２回が8~9割ほど
3・4回が4~5割ほど
5・6回は2~3割ほどの正解率だったと思います...(全然勉強が足りてない)

あと、Udemyはスマホアプリのクオリティーが低く、PCでの学習を強くおすすめします...

- [PingT 最強WEB問題集](https://mondai.ping-t.com/g/question_subjects#content-large_category_2) ★★★★☆

今回の試験で始めて存在を知りましたが、とてもいいサイトです！
本当にUI/UXが優れているサイトで、PC/スマホ問わずUdemyより気軽に取り組めます。

難易度はもっとも難しい部類の問題で本番の簡単な問題と同等レベルかと思います。
ですが、問題数、カバーしている範囲・サービスが多く、基礎を固める上でかなりおすすめです。
サイトの使いやすさも相まって、隙間時間にちょうどよいです。

- [AWS認定資格試験テキスト AWS認定ソリューションアーキテクト - アソシエイト改訂第2版](https://www.amazon.co.jp/AWS%E8%AA%8D%E5%AE%9A%E8%B3%87%E6%A0%BC%E8%A9%A6%E9%A8%93%E3%83%86%E3%82%AD%E3%82%B9%E3%83%88-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-NRI%E3%83%8D%E3%83%83%E3%83%88%E3%82%B3%E3%83%A0%E6%A0%AA%E5%BC%8F%E4%BC%9A%E7%A4%BE/dp/479739739X) ★★☆☆☆

こちらは書籍です。私は最初にこの書籍から学習をはじめました。
資格試験にいわれがちなことかもしれませんが、書籍に時間を使いすぎるのはあまり良い選択肢とは言えないな、という感想です。
一周さらっと読んでどんなサービスがあるのか、サービスの特徴、基本的なオプションの機能あたりをなんとなく覚えるだけでよいと思います。章末の問題もあまりきにしなくて良いです。
AWS全くがわからないよ！っていう状態なら書籍での学習をはじめの一歩とするのは良いかもしれません。
すでにCPを取得している方ならこの書籍を買う意味は薄いのかなと思います。

## もっとやっておけばよかったと思うこと
- 各サービスの名前と概要を一通り覚える

試験を受ける上で一番キツかったのは、選択肢に出てくるサービスがそもそも聞いたことない、という問題です。
サービス自体がわからなければもはや思考の意味がなくなってしまうので、一つのサービスを深く掘るよりもどんなサービスがあるのか、名前と機能の概要をひととおり覚えておくのがかなり大事だと思います。

- Udemyにもっと時間を使う

書籍での学習に時間を使いすぎました。
正直、上に挙げた本を完全完璧に理解しても合格は多分無理です。早いとこPingT(かUdemy)に切り替えて学習すれば、もう少し余裕のある合格ができるのではないかなと思います。

- あと一個ぐらいレベルの高めな学習教材をやっておきたかった
上にあげた三つをやっていても、本番では見たことない問題ばかりでした。難易度高めでもう少しニッチなところを埋められる教材があれば、かなり得点があがっただろうと思います。

## 番外編 試験会場での注意
- <font color="Red">**バカ寒いです**</font>

本当にありえないぐらい寒い。寒すぎて見直しの時間取らず20分残しで退出するぐらい寒かったです。
普段は暑がりな私でも体調悪くなったぐらいなので、夏に受ける方は羽織るものをもっていった方がいいです。本当に。

- 試験会場の待合場所では勉強できない

ちょっと時間に余裕もっていったら、受付後は勉強してはいけないようで少しの間外で立って最後の復習をしていました。

## おわりに
最後までお読みいただきありがとうございました。
無事合格できてほっとしております。。。