OmniAICreator/Qiita-1.07M huggingface dataset:
IDでテーブルを結合する 内部結合と完全外部結合(SPSS Modeler データ加工逆引き6-1)

# IDでテーブルを結合する（内部結合と完全外部結合）

![スクリーンショット 2022-06-30 14.43.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/cc4f57ea-20c2-e5fa-d9e6-bb377bac9db7.png)

＊部分外部結合と逆結合はデータ加工逆引き6-2をご覧ください。

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

・マスタデータの結合
・特徴量作成のための統計量の結合

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

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

## 3.サンプルストリームの説明
![スクリーンショット 2022-06-30 14.45.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/7cd48c83-5cd2-789f-90c1-de60d5f8093c.png)

a.入力するデータひとつ目は以下の通りです。
![スクリーンショット 2022-06-30 14.47.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/bd39a235-9d24-d4d6-ff15-dc1d58bb2834.png)

b.入力するデータ２つ目は以下の通りです。
![スクリーンショット 2022-06-30 14.47.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/268cf6fd-ce9e-9aa3-32a6-cacc9713bc8d.png)

#### 内部結合(inner join)

c.[レコード結合]ノードを編集します。[レコード結合方法]を[キー]にして[会員ID]を[結合キー]にします。ラジオボタンは[一致レコードだけを含める（内部結合）]を選択します。
![スクリーンショット 2022-06-30 14.48.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/5db9ea3d-dfb0-3d94-1521-b65e94762006.png)

[プレビュー]をします。２つのテーブルに登場した会員のレコードが表示されました。
![スクリーンショット 2022-06-30 14.48.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/16d114c9-e4ab-264d-978b-cc7fd706b5f5.png)

#### 完全外部結合(full outer join)

d.[レコード結合]ノードを編集します。[レコード結合方法]を[キー]にして[会員ID]を[結合キー]にします。ラジオボタンは[一致レコードと不一致レコードを含める（完全外部結合）]を選択します。
![スクリーンショット 2022-06-30 14.48.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/26012076-9124-02c8-0574-e6f0bac8d0cd.png)

[プレビュー]をします。会員は全て登場して、該当のないセルには欠損値Nullが割り当てられました。
![スクリーンショット 2022-06-30 14.49.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/65b0435e-e550-43b8-2301-94dbdca53d17.png)

#### 注意事項

会員IDは整数か文字列で統一している必要があります。また片方のフィールド名称が会員番号だった場合にはあらかじめ[フィルター]ノードで会員IDにリネームしておきます。

## 4.参考情報

#### [レコード結合]の解説記事

https://www.ibm.com/blogs/solutions/jp-ja/spssmodeler-push-node-13/

https://qiita.com/416nishimaki/items/be61a82c12cd83558def


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

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

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

https://qiita.com/416nishimaki/private/4bf813e6cba84b2a1008
N対N結合で組み合わせテーブルを作成する(SPSS Modeler データ加工逆引き6-3)

# N対N結合で組み合わせテーブルを作成（cross join）

![スクリーンショット 2022-06-30 18.48.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/6b63c00b-c96b-3edd-40f1-82ffad00d247.png)

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

・マスターデータの作成
・シミュレーションのための組み合わせテーブルの作成

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

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

## 3.サンプルストリームの説明
![スクリーンショット 2022-07-01 8.07.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/3aba76cf-1d99-ed6e-8167-7ecfcea1d711.png)

a.入力するデータひとつ目は以下の通りです。
![スクリーンショット 2022-07-01 8.07.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/014237c3-b5d6-c787-7d2b-31db7e16016b.png)

b.入力するデータ２つ目は以下の通りです。
![スクリーンショット 2022-07-01 8.08.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/c1befafa-b3ef-7971-22d6-93988fd30609.png)

c.[レコード結合]ノードを編集します。[レコード結合方法]を[キー]にして[結合キー]をブランクのままにします。
![スクリーンショット 2022-07-01 8.09.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/846a2b70-471f-1886-5e14-997c31cad365.png)

[テーブル]を実行します。果物が３つと野菜が4つの12通りの組み合わせテーブルが作成されました。
![スクリーンショット 2022-07-01 8.11.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/38723cd7-b144-0b0d-23b8-76d72c8ce9ab.png)


#### 注意事項

組み合わせによって膨大なテーブルになる可能性があるため注意してください。
表示する前に先に[レコード集計]ノードを接続、[プレビュー]してレコード数を確認してください。

## 4.参考情報

#### レコード集計で統計量を算出して元データに戻す利用方法を解説した記事

https://qiita.com/416nishimaki/private/71a7ce6c3c4cad8f4544#3%E3%82%B5%E3%83%B3%E3%83%97%E3%83%AB%E3%82%B9%E3%83%88%E3%83%AA%E3%83%BC%E3%83%A0%E3%81%AE%E8%AA%AC%E6%98%8E

#### [レコード結合]の解説記事

https://www.ibm.com/blogs/solutions/jp-ja/spssmodeler-push-node-13/

https://qiita.com/416nishimaki/items/be61a82c12cd83558def

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

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

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

https://qiita.com/416nishimaki/private/4bf813e6cba84b2a1008
行と列を入れ替える(SPSS Modeler データ加工逆引き7-3)

# 行と列を入れ替える（行列入替）

![スクリーンショット 2022-07-07 13.51.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/a7f6833a-916d-055b-709b-dd29389c39e6.png)

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

・集計表の作成
・時系列予測のためのデータ加工
・予測モデルのための特徴量作成

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

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

## 3.サンプルストリームの説明
![スクリーンショット 2022-07-01 14.43.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/e5aad947-586e-2bc6-b565-c836db7c9258.png)

a.入力するデータは以下の通りです。
![スクリーンショット 2022-07-01 14.52.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/8946c38b-14a3-e9a2-69f3-7dc04b8f8264.png)

#### 時系列横持ちを縦持ちに入れ替えます

b.[行列入替]ノードを編集します。[行列入替方法]を[フィールドとレコードの両方]にして[値の読み込み]ボタンを押します。
![スクリーンショット 2022-07-07 13.54.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/0d3a316d-2a4e-953c-1609-319f642e4a32.png)

[プレビュー]します。
![スクリーンショット 2022-07-07 13.55.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/ac279d72-168a-5f74-c183-9eef66d399d9.png)

#### 時系列縦持ちを横持ちに入れ替えます

c.[行列入替]ノードを編集します。[行列入替方法]を[フィールドとレコードの両方]にして[値の読み込み]ボタンを押します。
![スクリーンショット 2022-07-01 14.47.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/15ebe214-9955-0adf-fd5d-8a27ce568204.png)

[プレビュー]します。
![スクリーンショット 2022-07-01 14.48.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/9a970096-d581-bd26-2f00-25c6fcf2d7ff.png)

#### 注意事項

[値の読み込み]ボタンでメンバーがリストされない場合にはストリームの上流でデータ型を確定しているか確認してください。

## 4.参考情報

#### [行列入替]の解説記事

https://qiita.com/416nishimaki/items/c7362fdbbed9e6658689

https://qiita.com/kawada2017/items/41484aece5a62f463a95

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

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

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

https://qiita.com/416nishimaki/private/4bf813e6cba84b2a1008
フラグ変数/ダミー変数作成　縦持ちを横持ちへ(SPSS Modeler データ加工逆引き7-1)

# フラグ変数/ダミー変数作成（縦持ちを横持ちへ）

![スクリーンショット 2022-07-01 11.07.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/15c8ccb9-6a9b-087f-3dbb-aae6bd480b30.png)

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

・統計モデルのためのダミー変数の作成
・アソシエーションや予測のために顧客の商品購買有無の特徴量作成
・設備ログから異常や故障に関連する特徴量の作成

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

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

## 3.サンプルストリームの説明
![スクリーンショット 2022-07-01 11.20.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/5df254c5-ecf6-fb76-ae3b-327ea4aba684.png)

a.入力するデータは以下の通りです。
![スクリーンショット 2022-07-01 11.48.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/2404795a-e040-96ce-7bd5-7940b1e8f067.png)

#### フラグ化(ダミー変数の作成)

b.[フラグ設定]ノードを編集します。[集計キー]をブランクにするとレコード（行）を保持したまま商品をフラグ化します。
![スクリーンショット 2022-07-01 11.22.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/fa6a9d6d-bfb3-052f-cd62-26a9b226f708.png)

[プレビュー]します。
![スクリーンショット 2022-07-01 11.22.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/4ad882e8-2b8a-0cc3-6241-35f408ade401.png)

#### IDと日付を集約してフラグ化

c.[フラグ設定]ノードを編集します。[集計キー]を[顧客ID]と[利用日]にします。レコードを集約して商品をフラグ化します。
![スクリーンショット 2022-07-01 11.22.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/4d010b23-8e7e-0511-e4da-5bce885f3b23.png)

[テーブル]を実行します。11行が8行に集約されました。
![スクリーンショット 2022-07-01 11.23.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/7b3ccb7f-8d14-a608-9d45-81e80008e0a9.png)

#### IDで集約してフラグ化

d.[フラグ設定]ノードを編集します。[集計キー]を[顧客ID]のみにします。レコードを集約して商品をフラグ化します。
![スクリーンショット 2022-07-01 11.23.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/d0ab7c81-dce5-5f91-04da-ec4f586fd18e.png)


[テーブル]を実行します。11行が3行に集約されました。
![スクリーンショット 2022-07-01 11.24.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/fd090ceb-e938-f627-a682-c0c11addb5ef.png)


#### 注意事項

サンプルストリームでは入力ノードで[商品]のデータの型を確定してあります。新たなデータを適用する際に[フラグ設定]の[利用可能なセット値]がリストされない場合には[データ型]ノードで[値の読み込み]ボタンを押してカテゴリメンバーを確定してください。

## 4.参考情報

#### レコード集計で統計量を算出して元データに戻す利用方法を解説した記事

https://qiita.com/416nishimaki/private/71a7ce6c3c4cad8f4544#3%E3%82%B5%E3%83%B3%E3%83%97%E3%83%AB%E3%82%B9%E3%83%88%E3%83%AA%E3%83%BC%E3%83%A0%E3%81%AE%E8%AA%AC%E6%98%8E

#### [フラグ設定]の解説記事

https://qiita.com/416nishimaki/items/bcaec1cd8e455c3f68a9

https://qiita.com/kawada2017/items/fb2f4128caae452a7a49

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

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

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

https://qiita.com/416nishimaki/private/4bf813e6cba84b2a1008
Oracle Property Graph と Neo4j のベンチマーク結果

# はじめに
この記事はJames Steiner氏の記事
[Oracle Database Property Graph outperforms Neo4j in LDBC Social Network-BI benchmark](https://blogs.oracle.com/oraclespatial/post/oracle-database-property-graph-outperforms-neo4j-in-ldbc-social-network-bi-benchmark)の一部加筆を加えた日本語版です。

# 概要
Oracle Property Graphは標準的な [Linked Data Benchmark Councilの Social Network Benchmark](https://ldbcouncil.org/benchmarks/snb/)の25クエリのうち19クエリでNeo4jを上回りました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706384/9ca70051-11c2-0e1a-3d7f-56f5c223c02c.png)

Neo4jは4つのクエリでのみOracleよりも良い結果を示し、両製品とも2クエリでタイムアウト閾値に達しました。

今回のテストで利用されたLDBC Social Network Benchmark (SNB)ビジネス・インテリジェンス(BI)ワークロードでは、ビジネスクリティカルな要件に対応するための分析クエリを含んでいます。テストは同等のシステムに揃えたオラクルクラウド上のOracle Property Graphと、AWS上のNeo4jで行われました。詳しい比較結果は[こちら](https://www.oracle.com/a/tech/docs/ldbc-graph-benchmark-2020-06-30-neo-only-v3.1.pdf)

# ベンチマーク結果
Oracle Property Graphは、University of California-Mercedが行ったNeo4jの公開テストと比較して、5時間以内に完了するクエリで最大250倍高速化されました。また、3つのクエリではOracle Graphは完了できましたがNeo4jでは完了できなかったものもありました。

# Oracleグラフの概要
Oracle Property Graphは速いだけでなく、機能も充実しています。
PGXサーバーと呼ばれるハイパフォーマンスでインメモリのグラフサーバーは、グラフクエリとアルゴリズムを実行するために最適化されています。このネイティブグラフエンジンはグラフクエリとアルゴリズムのパラレル実行も可能で、約60個もの既に実行可能なアルゴリズムがOracle Property GraphとRDF Graph の両方に対して呼び出しや適用が可能で、ユーザー自身で定義したJavaとOracle Property Graphコンパイラを利用したアルゴリズムも実行可能です。

さらに、Oracle Property Graphには、SQLライクなネイティブグラフ問合せ言語のPGQL、グラフ可視化コンポーネント、そしてノートブックが含まれています。
Oracle Property GraphとOracle RDF Graphは[コンバージドデータベース](https://www.oracle.com/a/otn/docs/database/oracle-converged-database-technicalbrief.pdf)の一部となっています。コンバージドデータベースはマルチモデル、マルチテナント、マルチワークロードのデータベースで、データモデルやアプリケーションが必要とするアクセス方法をサポートしています。

# 関連情報
グラフの詳細については[こちら](https://www.oracle.com/autonomous-database/what-is-graph-database/)
[Laravel]フォームリクエストでバリデーションを実装する

# はじめに
今回は、Laravelでフォームリクエストを使ったバリデーションについて書きたいと思います。
公式ドキュメントを参考に、実装を進めていきます。

https://readouble.com/laravel/8.x/ja/validation.html

# 1. FormRequestとは
Laravelでかけることのできるバリデーションの１つで、コントローラーの処理に入る前のリクエストの処理でバリデーションを行います。
バリデーションロジックを別クラスに切り離すことでコントローラーをシンプルにし、可読性を上げる目的で使われます。

# 2. FormRequestを作成する
以下のコマンドでFormRequestを作成します。
今回は`TargetRequest`という名前で実装を進めていきます。
```php
php artisan make:request TargetRequest
```

```php
<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;
use Illuminate\contracts\Validation\Validator;
use Illuminate\Http\Exceptions\HttpResponseException;

class TargetRequest extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return false;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        return [
            //
        ];
    }
}
```
`rulesメソッド`には以下のような形式でルールを記述します。
```php
    public function rules()
    {
        return [
            '項目名' => '検証ルール' | '検証ルール',
            '項目名' => '検証ルール' | '検証ルール',
             //略
        ];
    }
```
今回は、以下のようなルールを指定しました。
```php
    public function rules()
    {
        return [
            'name' => 'required|max:50',
            'amount' => 'required|integer',
        ];
    }
```
`messagesメソッド`を追加することで、エラーメッセージをカスタマイズできます。
今回は、以下のように指定しました。
```php
    public function messages()
    {
        return [
            'name.required' => '目標は必須です。',
            'name.max' => '文字数をオーバーしています。',
            'amount.required' => '目標額は必須です。',
            'amount.intger' => '正しい形式で入力してください。',
        ];
    }
```
また、API実装時のバリデーションエラーでJSONレスポンスを返したいときには、
FormRequestの`failedValidationメソッド`をオーバーライドして、エラー時のフォーマットを変更することができます。
```php
    protected function failedValidation(Validator $validator): HttpResponseException
    {
        $response = response()->json([
            'status' => 'validation error',
            'errors' => $validator->errors()
        ], 422);
        throw new HttpResponseException($response);
    }
```
# 3. コントローラーを編集する
### FormRequestを使用しない場合
FormRequestを使用しない場合は、以下のような記述でバリデーションをかけることができます。
```php
    public function store(Request $request)
    {
        $rule = [
           'name' => 'required|max:50',
           'amount' => 'required|integer',
        ];

        $this->validate($request, rule);

        //略
    }
```
### FormRequestを使用する場合
コントローラーのメソッドで、作成したFormRequestをタイプヒントで指定します。
```php
    public function store(TargetRequest $request)
    {
        //略
    }
```
バリデーションロジックをコントローラーから分離することができました。
以上で実装完了です。

FormRequestでバリデーションを作成することで可読性・保守性が上がります。
Fat Controllerを防ぐことにつながるので、積極的に活用していきたいです。

# 4. 参考文献

https://www.kamome-susume.com/laravel-validation
［エラー］SpringBoot 　@Autowiredでエラー　原因はSpringコンテナの未登録



# 概要
SpringBootでエラーが出たので投稿します。
この辺りはまだ自信が無いので話半分程度で聞くかご指摘お願いします。

# エラー内容
＠Autowiredのアノテーションを付けたクラスでエラーが発生。
ビルドは成功します。実行するとエラーになります。

```Source.java
@Autowired
CsvMapper mapper;

```


実行すると以下のエラーメッセージが発生。


```Error.

Description

Field mapper in com.example.spring_boot_memo.csv.CsvService required a bean of type 'com.fasterxml.jackson.dataformat.csv.CsvMapper' that could not be found.

The injection point has the following annotations:
	- @org.springframework.beans.factory.annotation.Autowired(required=true)


Action:

Consider defining a bean of type 'com.fasterxml.jackson.dataformat.csv.CsvMapper' in your configuration.

```



# 原因

CsvMapperがSpringコンテナに登録されていないことが原因です。
＠AutowiredはSpringコンテナに入っているCsvMapperクラスを呼び出します。
SpringコンテナにはCsvMapperクラスが登録されていませんでした。
そのため＠AutowiredでCsvMapperを呼ぶことができずエラーが発生しました。

CsvMapperのソースコード見ると自動的にSpringコンテナに登録してくれる＠Service ＠Controllerといったアノテーションはありません。
（SpringBoot特化のクラスではないので、そりゃそうですよね…）
私はいつもアノテーションに頼ってばっかでしたので、原因を探すのに苦労しました…

```Csvmapper.java
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
// (一部抜粋)です RYA234
package com.fasterxml.jackson.dataformat.csv;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.AnnotationIntrospector;
import com.fasterxml.jackson.databind.BeanDescription;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectReader;
import com.fasterxml.jackson.databind.ObjectWriter;
import com.fasterxml.jackson.databind.cfg.MapperBuilder;
import com.fasterxml.jackson.databind.introspect.AnnotatedMember;
import com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition;
import com.fasterxml.jackson.databind.util.NameTransformer;
import com.fasterxml.jackson.databind.util.ViewMatcher;
import com.fasterxml.jackson.dataformat.csv.CsvSchema.ColumnType;
import com.fasterxml.jackson.dataformat.csv.impl.LRUMap;
import java.util.Collection;
import java.util.Iterator;
// アノテーションが無い　RYA234
public class CsvMapper extends ObjectMapper {
    private static final long serialVersionUID = 1L;
    protected final LRUMap<JavaType, CsvSchema> _untypedSchemas;
    protected final LRUMap<JavaType, CsvSchema> _typedSchemas;

    public CsvMapper() {
        this(new CsvFactory());
    }


```




# 対処方法
方法は２つあります。
1.CsvMapperクラスに＠Serviceを追記してSpringコンテナに登録する。
2.Beanを使って、CsvmapperクラスをSpringコンテナに登録します。実装方法としては＠ConfigurationがあるクラスにBean登録する。
CsvMapper.javaは読み取り専用なので１の方法は使えません。
よって今回は２の方法を採用します。

## 実装
```BeanConfig.java
package com.example.spring_boot_memo.csv;

import com.fasterxml.jackson.dataformat.csv.CsvMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class BeanConfig {
    @Bean
    public CsvMapper getCsvMapper()
    {
        return new CsvMapper();
    }
}
```


# まとめ
外部のクラスに対して＠Autowiredを使うときはSpringコンテナに登録しよう！


# 参考資料


https://www.lifestyle12345.com/2019/04/spring-di-annotation.html
損益分岐点のグラフはなぜ分かりにくいのか

基本的なことだろうけど、損益分岐点を調べてグラフを久々に見たときにアレ？
ってなったので備忘録。
素朴な疑問かもしれませんが、
損益分岐点のグラフって分かりにくいと感じたことはありませんか？

![損益分岐点グラフ1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2728006/458df2af-05ed-b6e3-d83b-6f0a450e2736.png)

疑問を解消できるよう、出来る限りかみ砕いて説明します。
分かりやすいと感じて頂けたら幸いです。

## 分かりにくい理由は２つのグラフを重ね合わせているから

損益分岐点のグラフ、実は２つのグラフを重ねているんですね。
その２つのグラフとはどんなグラフなのかを説明します。

#### １つめのグラフ：販売数と売上額のグラフ

![損益分岐点グラフ2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2728006/ed597ee7-76d5-a19b-e34c-3704e2408f3f.png)

#### ２つめのグラフ：販売数と販売にかかった総費用のグラフ

![損益分岐点グラフ3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2728006/e9f23b31-6bca-85f9-69fb-1548a1b9bbef.png)

２つのグラフを重ねているにもかかわらずY座標の名称が１つしか表示されていなかったり、明確でないから分かりにくくなってしまう訳ですね。

こういうグラフであれば分かりやすいでしょうか？

![損益分岐点グラフ4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2728006/951fd8de-42dc-2b32-45f1-64e883fc058b.png)

以上です。
ここまでお読み頂き、ありがとうございました。
Docker基本コマンド


- イメージのビルド
dockerfileを編集した場合に使う
```
$ docker-compose build
```
- コンテナの作成と起動
`-d`オプションでバックグラウンドで実行。
ターミナルがログで占領されなくなる
```
$ docker-compose up -d
```
- コンテナの停止と削除
```
$ docker-compose down
```
- コンテナ一覧確認
```
$ docker-compose ps
```
- ログ表示
```
$ docker-compose logs
```
- コンテナのシェルを起動
`docker-compose exec web ~~~`と入力しなくてもコマンドが実行できる
exit で退出
```
docker-compose exec web /bin/bash
```
【Serverless Framework】コンテナイメージを使ってPackageする際はアーキテクチャに気を付ける【Python】


# はじめに
Pythonで書かれたLambda関数のコードをServerless Frameworksを使ってデブロイする際に、[serverless-python-requirements](https://www.serverless.com/plugins/serverless-python-requirements) プラグインを使うことで依存関係を含めることができる。

Dockerコンテナを使ったパッケージングにも対応しており、`cryptography` のようにコンパイルが必要なライブラリが含まれる際はそれを使うのだが、設定によってはLambda実行でエラーが発生することがある。

# 環境
- Python 3.9
- Serverless Framework 3.19.0

# 事象
`cryptography` を含むPythonアプリをServerless Frameworkを使ってDockerコンテナでパッケージ & デプロイ。
その後Lambdaを実行すると、Importで以下のようなエラーが発生した。

> [ERROR] Runtime.ImportModuleError: Unable to import module 'lambda_handler': /var/task/cryptography/hazmat/bindings/_rust.abi3.so: cannot open shared object file: No such file or directory

# 原因
上記はビルド環境と実行環境のアーキテクチャの違いによって発生したエラー。

元々これを防ぐためにDockerコンテナを使ってパッケージしたのだが、指定したコンテナイメージが実際のLambdaの実行環境と異なっていたことが原因。

まず、現在Lambdaは `x86_64` と `arm64` の2つのアーキテクチャが存在する。

https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/foundation-arch.html

Serverless Frameworkでは、serverless.ymlの `architecture` パラメータでどちらのアーキテクチャを使うのかを指定でき、未指定は  `x86_64`。

https://www.serverless.com/framework/docs/providers/aws/guide/serverless.yml#general-function-settings

私の環境では `architecture` パラメータは未指定であり、そのためアーキテクチャ `x86_64` となっていた。

また、パッケージ用のコンテナイメージには、AWS SAMの公式イメージである　[public.ecr.aws/sam/build-python3.9:latest](
https://gallery.ecr.aws/sam/build-python3.9) を指定していた。


```yaml:serverless.yml
custom:
  pythonRequirements:
    dockerImage: public.ecr.aws/sam/build-python3.9:latest
    dockerizePip: true
```

**しかし、このイメージの `latest` タグは、`arm64` ベースのイメージとなっており、それによってビルド環境と実行環境で差異が生じ、先のエラーが発生した。**



> 【補足】
コンテナイメージ未指定の場合は [lambci/lambda](https://hub.docker.com/r/lambci/lambda/) がパッケージングに使われるのだが、現在Python 3.9のイメージはなく、プロジェクトも更新が滞っている。
現在、[AWS公式のコンテナイメージ](https://docs.aws.amazon.com/ja_jp/serverless-application-model/latest/developerguide/serverless-image-repositories.html#serverless-image-repository-uris) (本来はSAM用) が存在するため、そちらを使うようにイメージを指定していた。


# 解決策
**パッケージに使うコンテナイメージと`architecture` パラメータに指定するアーキテクチャを `x86_64` or `arm64` のどちらかに統一する。**

[AWS SAMの公式イメージ](https://gallery.ecr.aws/sam/build-python3.9)には `x86_64` と `arm64` の両方が用意されており、タグで指定できる。

- {version}-arm64
- {version}-x86_64

アーキテクチャ名が含まれないタグは `arm64` ベースのイメージである。

今回は `arm64` に統一し、serverless.ymlは以下のように修正した、

```diff_yaml:serverless.yml
 ...
 custom:
   pythonRequirements:
-    dockerImage: public.ecr.aws/sam/build-python3.9:latest
+    dockerImage: public.ecr.aws/sam/build-python3.9:latest-arm64
     dockerizePip: true
...
 provider:
   name: aws
   runtime: python3.9
+  architecture: arm64
 ...
```
【備忘録】同じ階層にあるpyファイルをipynb上でimportできなかった

自分用のメモです。

# 問題
jupyterlabでipynbを動かしていて、同じ階層にある```module.py```という自作モジュールから```EarlyStopping```という関数をimportしたかったが、
```
---------------------------------------------------------------------------
ImportError                               Traceback (most recent call last)
<ipython-input-20-5c119319e129> in <module>
----> 1 from module import EarlyStoppping

ImportError: cannot import name 'EarlyStoppping'
```
と出て動かなかった。
# 解決策
ipynb上で自作モジュールを読み込みたいときは、対象のpyファイルに```module.py```という名前を付けないほうが良いっぽく、```my_utils.py```にしたらインポートできた。


## ディレクトリ構造

> 202207/
　├ test.pynb
　├ module.py
SourceTree（ソースツリー）| reflog（リフログ）| ログを参照する

## reflog（リフログ）とは
### reference + log = ログを参照する
レポジトリ内で行われた全てのコマンドの履歴を参照する
- コミット（コミット、マージ、プル、リバート）
- 書き換え（リセット、リベース）
- ブランチ切り替え（チェックアウト）
## コマンドでのやり方
### 注意：SourceTree ではできないのでコマンドを使用
```
git reflog
```
## ログの見方
```
①コミット番号 ②(参照名) ③HEAD@{n}: ④Gitコマンド: ⑤処理内容
```
▼
```
c1234567 (HEAD -> develop) HEAD@{0}: checkout: moving from master to develop
```
## NEXT ACTION
### 特定の時点まで戻す
nに戻りたい地点の数字を入力
``` 書き方
git reset --hard HEAD@{n}
または
git reset --hard @@{n}
```
### 参考
- [第7話 間違えて reset しちゃった？git reflogで元どおり【連載】マンガでわかるGit ～コマンド編～ - itstaffing エンジニアスタイル](https://www.r-staffing.co.jp/engineer/entry/20191227_1)
- [【Git】git reflogとは何かを完全理解（HEAD@{n}や@@{n}とは何か？違いは？）使い方を実例で解説｜git resetで間違って消したコミットを復活・復元させる方法](https://prograshi.com/general/git/reflog-head-at-and-git-reset/)
Pythonで文字起こし

# PythonでWavファイル→音声認識
wav fileの中身でなんて喋ってる聞くのがめんどいので、pythonで文字起こししてそのテキストだけみればええやん

```v2t.py
import speech_recognition as sr

r = sr.Recognizer()

def v2t(path:str) -> str:
    with sr.AudioFile(path) as source:
        audio = r.record(source)
    return r.recognize_google(audio, language='ja-JP')
```

おわり．langのところいじれば日本語以外もいける

# 利用例
https://github.com/nyanko3141592/give_id2wavs.git
【Android】棒グラフを描画する

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/694762/37007428-2a3f-8cb0-0561-bd54466c7f77.png" width="30%">

# 概要
`MPAndroidChart`を用いて棒グラフを描画する。ここでは最低限の処理のみ記載。

# 手順
ライブラリの導入

```build.gradle
implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0'
```

```settings.gradle
repositories {
	//(省略)
	maven { url "https://jitpack.io" }
}
```

レイアウト作成
```activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<com.github.mikephil.charting.charts.BarChart
	xmlns:android="http://schemas.android.com/apk/res/android"
	android:id="@+id/chart"
	android:layout_width="match_parent"
	android:layout_height="match_parent"/>
```

描画処理
```MainActivity.kt
val value = listOf(
	BarEntry(0f, 32f),
	BarEntry(1f, 3f),
	BarEntry(2f, 25f),
	BarEntry(3f, 47f),
	BarEntry(4f, 10f)
)

binding.chart.data = BarData(BarDataSet(value, ""))
binding.chart.invalidate()
```
アカウント名がダサすぎて変更しようか迷っているが中々名前が決まらないそこの貴方に。

そろそろ名前を変えたくなる時期ですよね。
名前と言えば実は僕の前のアカウント名はHiroCodeTripって名前だったんですけど
これが`とんでもなくダサい！！！！`
github含めて色々な媒体で使うので其処彼処で言っていると
>Hiroのコード旅行です。

って自己紹介してるみたいな気分になってきて、恥ずかしくなってくるんです...
いやまあ別に気にしなければいいのですが、みんな名前がカッコよすぎるんですよ...

*他の人の名前*
> mattn, esazaki ...

*僕の名前*
> HiroCodeTrip

僕の名前中学生が考えたみたいですね...苦笑

まあともかくそんなわけで名前を変えることにしたんです。

# なぜダサいと感じるか？
さてなぜ僕は自分の名前がダサいと感じるのでしょうか？
### 英単語を連ねるのがダサいと感じるのか？
> BlueColor

うーん確かにダサい
でもダサいのってBlueとColorが意味的な繋がりを持つからダサいんじゃないんだろうか？

### 関係しない単語を連ねてみる
> AssignmetClue

なるほど確かに少しダサさが減少したような気がします
でも単純に意味不明でダサさが認識できないだけな気もしますね。
ほんとかどうか検証して見ましょう。

### 自分の名前を入れてみて

> HiroBearLang

Hiro Bear Lang　という風に独立した単語が連なっていて意味的なつながりを認識できませんね。
なんだか少しよくなったように感じますね。

### さらにキャメルケースを導入してみる
> hiroBearLang

なんだかいい？
でもこのまま行くと厨二病チックな名前が出来上がりそうなのんで他の人の命名も参考にして見ましょうか。

## 他の人の命名の仕方

>ラテン語、アナグラム、
英語名、あだな、機械語

こんな記事もあるようです

https://www.wantedly.com/users/394681/post_articles/32021

むむむ、自分の場合は変な単語ばかり出てきてダメそうですね...
でもあだ名や機械語等は参考になりそうです

## 解決策
- githubや多くの人が登録する媒体では単語などは基本取られているので諦めましょう。
- 意味の繋がりが薄い単語を使う
- 自分の名前は唯一無二なことが多いのでそれを使おう(ただしそのまま使うのは迷う...)
- 名前の子音を使って自分の名前を省略して使う
- キャメルケースを使う

ちなみに僕は最終的に
`名前の子音を使う+苗字の頭文字をASCIIコードで` => hrak0x59
という風に解決しました。

## 注意点
- インターンとかに提出済みのリンクが名前を変更したことにより見えなくなる。
- githubレポジトリ内の名前が使用されている箇所は自動で変更されない

など色々あるので特にgithubの変更確認画面はちゃんと読みましょうね！

## 最後に
ダサくない名前に変更して快適なプログラミングライフを！

## 参考
https://www.wantedly.com/users/394681/post_articles/32021
OVFテンプレート Export / Import でVMware仮想マシンの移行を試してみた #1 オンプレミスVMware仮想環境からVMware Cloud on AWSへの移行

# 1. はじめに
自宅のホームラボをオンプレミスVMware仮想環境に見立てて、「[VMware Cloud on AWS](https://www.vmware.com/jp/products/vmc-on-aws.html)」への仮想マシン移行を試します。いわゆるクラウドマイグレーションです。

通常VMware Cloud on AWSへの移行の際には[「VMware HCX」](https://www.vmware.com/jp/products/hcx.html)や[「AWS Backup」](https://aws.amazon.com/jp/backup/)など対応するバックアップソリューションを活用した方法がまず候補になるかと思います。

ですが今回はVMware 他にもお手軽な手段があるということで、OVFテンプレートのExport/Importを利用した移行手順をご紹介します。

> VMware仮想環境におけるOVFテンプレートの扱いについては、次のVMware Docsもご参考ください。
> [OVF および OVA テンプレートの展開 (VMware Docs)](https://docs.vmware.com/jp/VMware-vSphere/7.0/com.vmware.vsphere.vm_admin.doc/GUID-AFEDC48B-C96F-4088-9C1F-4F0A30E965DE.html)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864151/bfcdddb1-2b88-ce36-72b3-7b05fcc862ef.png)

> 上図は全体構成のイメージ図

AWS BackupによるVMware Cloud on AWSのバックアップ・リストアについてはこちらの過去記事もご参考ください。

https://qiita.com/sanjushi003/items/7d250088875463005dd3

# 2. ところでOVFってなんだっけ？ 聞き慣れない方向けに。
OVF (Open Virtualization Format) とは、仮想マシンの標準化された形式のひとつです。標準化することで異なる仮想環境間で自分のシステム環境を持ち運ぶことができます。本記事ではオンプレミスVMware仮想環境 (ホームラボ)からVMware Cloud on AWS環境に仮想マシンを移行させます。
普段アプリケーション開発をされている方は、(Docker)コンテナを類推すると分かりやすいかもしれません。

こちら2009年の記事ですがOVFが登場した頃の雰囲気が掴めるかもしれません。

https://www.publickey1.jp/blog/09/ovfos.html

# 3. 早速やってみる
## (1) オンプレミスVMware仮想環境 (自宅のホームラボ)からOVFテンプレートのExport
#### (1)-1 オンプレミスVMware仮想環境 (自宅のホームラボ)のvCenterにログイン
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864151/81c8d3ea-b58e-066a-e6b1-39cf0429d823.png)

#### (1)-2 移行対象の仮想マシンを選択し、「OVFテンプレートのエクスポート」を実行
「OK」を選択すると、OVFテンプレートがダウンロードされます。
移行対象の仮想マシンOSは軽量Linuxでお馴染みの「Tiny Linux」を利用しています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864151/8eb59564-2905-8b00-d80a-1f4e210c7e63.png)

## (2) VMware Cloud on AWS環境でOVFテンプレートのImport、仮想マシンのデプロイ
#### (2)-1 VMware Cloud on AWS環境のvCenterにログイン
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864151/4dc4e298-8c36-54ef-d80b-09705c359999.png)

#### (2)-2 移行対象の仮想マシンのデプロイ先にて、「OVFテンプレートのデプロイ」を選択
「ローカルファイル」を選択し、「ファイルのアップロードを実施」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864151/025c8a4b-ca92-de0f-6dc0-b2aa47098bbf.png)
(1)-2でダウンロードしたOVFテンプレートを選択する ※ダウンロードした全てのファイル一度に選択する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864151/351fd64e-5f0b-d7bd-bb5c-291247f4acbd.png)

#### (2)-3 必要なパラメーターを設定し、仮想マシンをデプロイする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864151/fe8f9a46-8e4d-b209-7f63-e4f058bd9b60.png)

#### (2)-4 完了！デプロイされた仮想マシンが稼働することを確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864151/56597450-50b7-8ad3-8557-0afb5fb337c0.png)

# 4. さいごに
VMware仮想環境を運用していると、追加のコンポーネントなどをインストールするのが難しいなど色々な制約が出てくるかと思います。そのような場合に仮想マシンを移行する選択肢の１つとして、OVFテンプレートのExport/Importという手段があると思い出していただけると幸いです！

# 5. 参考記事

https://qiita.com/sanjushi003/private/c065bdcde57e112ce10d

https://qiita.com/sanjushi003/items/7d250088875463005dd3

https://qiita.com/sanjushi003/items/4d20c85b80032e6f6b25
pyenvでpythonバージョンが変更できないときのちょっとしたミス

`pyenv global 3.6.3`や`pyenv local 3.6.3`でバージョンが変更できないとき、ぐぐるといろんな対処法が出てきますが、ちょっとしたミスの場合に出くわしたのでメモしておきます。

# 原因

ルートディレクトリに`.python-version`がある。←これだけ

# 対処法

`.python-version`を消して、`pyenv`コマンドを打つ。
【AWS入門ハンズオンやってみた】 ECSでコンテナイメージを作って動かしてみよう！！

## はじめに
つい先日、AWS Hands-on for BeginnersにAWSの入門者向けECSコンテナハンズオンが追加されました！（2022年6月末）
https://t.co/RIhTYFngCI

今回はその概要と感想を書きたいと思います。

AWS Hands-on for Beginnersシリーズは<font color="red">わかりやすい解説動画と手順書はAWSによって用意</font>されていますが、<font color="red">AWSアカウントは自分で用意</font>する必要があります。

## ハンズオンの概要
概要は以下の公式ブログにまとめられています。
https://aws.amazon.com/jp/blogs/news/aws-hands-on-for-beginners-21/

このハンズオンの対象者は以下のように記載されてます。
> - コンテナに今まで触れたことが無く、新たに学習したい方
> - Amazon ECS を使って、インターネットにコンテナを公開する方法を知りたい方
> - ステップバイステップの説明を動画で確認しながら、ハンズオンを進めていきたい方

つまり、以下のような内容についてはあまり言及されていません。
- Dockerfileのベストプラクティス的な話
- EKS（Kubernetes）
- コンテナセキュリティ

上記の内容はNext Stepとして[AWS サービス別資料](https://aws.amazon.com/jp/aws-jp-introduction/aws-jp-webinar-service-cut/#containers)が紹介されているので、観てみると良いかと思います。

アジェンダはこんな感じ↓
![hanson.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2109911/aa35739a-7e13-cc63-103c-ccac2f838c11.png)


中身に関しては手順書と動画が充実しすぎているため、スクリーンショット等を貼って補足する必要がないです！！
## 詰まったところ
- サービスデプロイに失敗する
    - タスク定義でイメージURLを入力する際、手順書に記載のパラメータを一部書き換える必要がある
    - 手順書に記載のパラメータをそのまま入れてしまいサービスデプロイに失敗する
    - [停止されたタスクでのエラーの確認](https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/stopped-task-errors.html)の手順でエラー内容を確認し、「[CannotPullContainerError](https://aws.amazon.com/jp/premiumsupport/knowledge-center/ecs-pull-container-error/)」が発生していたため、タスク定義に問題があると判明
    - クラスター、タスク定義、サービス間の依存関係のせいか、タスク定義だけを修正しても上手くデプロイできなかったため、クラスターの作成からやり直して、どうにか完遂。
- サービスのDNS名をクリックし、コンテナにアクセスしようとしたところ503エラーが出る
    - [停止されたタスクでのエラーの確認](https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/stopped-task-errors.html)の手順でエラー内容を確認し、「Task failed ELB health checks in」とエラーが出ていた。
    - 「[Fargate での Amazon ECS タスクのヘルスチェックの失敗をトラブルシューティングするにはどうすればよいですか?](https://aws.amazon.com/jp/premiumsupport/knowledge-center/ecs-fargate-health-check-failures/)」を参考にタスク定義のコンテナポートを確認したところ、ポートが76になっていた。
    - ポートを修正して再デプロイしたらヘルスチェック が通った。

<font color="red">結論：手順書をちゃんと読め！</font>
## 感想
- 書籍やネットの記事等、テキストと画像の無料ハンズオン資料はたくさんあります.
- しかし、分かりづらかったり、読むのが面倒だったりで途中で自分は挫折することがあります。
- そう考えると動画でハンズオンで手元を映してくれているだけで、ハンズオンが捗ると思いました！

## 余談
- ハンズオンが終わった後に気づいたのですが、コンソール上からポチポチとECSリソースを作成している裏で、実はCloudFormationのスタックが作成されていました。
AWS CLIとかを使ってECS関連のリソースを作成した方が理解が深まりそうに感じます。

↓クラスター、タスク定義、サービスでスタックが作成されている。
![Cfn.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2109911/3efdfc01-4d02-6c7b-f398-e974c7a946f0.png)


## おわりに
最近、コンテナに関するAWSトレーニングが充実してきている気がします！
それだけ需要があるということなので、このコンテナの波に個人として乗り遅れないために、
「まだコンテナを触ったことがない」
「コンテナに関しては自信がない...」
という方はこの機会にぜひハンズオンをやってみてください！！
【Qiita】記事テンプレート作成

# はじめに
今後記事を記載するにあたって、体裁が統一されていると読者も筆者自身も読みやすくなるのではないかと思ったため、テンプレートとなる文書を作成した。

# テンプレート本体
```:記事テンプレート
※ {記事タイトル}の形式は自由だが、タイトルの頭に「【[主要となる言語名または開発プラットフォーム名など]】」をつける。

# はじめに
目的、ターゲット、背景などを記載

# 内容
最初に結論を持ってくる、なるべく簡潔に、そしてポイントを押さえる
ここを読んだだけで、何を言いたいのかがすぐにわかるように簡潔な記載
箇条書きもOK

```:言いたいこと

- あれはこれです
- これはあれです

```:

# 詳細
結論の内容を説明する詳細な内容を記載
番号付き見出しのまとめ

## 1. 詳細情報1
説明を記載

## 2. 詳細情報2
説明を記載

# 参考文献
- [リンクテキスト](URL)
- [リンクテキスト](URL)
- こっちにコードを用いた具体的な実装あってもいい

# その他部品
```言語名:ファイル名.拡張子
コードブロック
```:
[リンクテキスト](URL)

| No |    内容     |    備考    |
|---:|-------------|------------|
| 1  |             |            |
| 2  |             |            |
```:
iPhoneアプリからAWS Appsyncに繋げるときにデータをキャッシュさせない

iPhoneアプリからAWSAppSyncでAppsyncにアクセスすると、ディフォルトではアプリ内に持ってるDBにデータをキャッシュしておく機能がONだったのでOFFにした。

電波が切れた時とかに便利そうなんだけど、いらないので

最初は　AppleDelegate.swiftの

```
let appSyncConfig = try AWSAppSyncClientConfiguration(
　　　　　　　　　　　　　　　　　　　　　　　　　　appSyncServiceConfig: appSyncServiceConfig,
             cacheConfiguration: cacheConfiguration)
```

このcacheConfigurationを外してやればいけると思ったんだけど、ダメだった。

ちょっとハマってしまったので、ダメもとでApoploクライアントのコマンドのオプションを受け付けるか試したら、動いた（笑）

元ネタはこのページ
https://www.apollographql.com/docs/ios/api/Apollo/enums/CachePolicy/

結局、fetchする箇所で cachePolicyに　fetchIgnoringCacheDataを追加したら、キャッシュを見なくなる。

```
try self.appSyncClient?.fetch(
        query: GetHogeHogeQuery(id: self.hogehogeId), 
        cachePolicy: .fetchIgnoringCacheData
)  
```


後付けだけど、appsyncのSDKの中身をfetchIgnoringCacheDataで調べてみたら、、、、

https://github.com/awslabs/aws-mobile-appsync-sdk-ios/search?q=fetchIgnoringCacheData

Apolloクライアント使ってるみたいね。勉強になった！

おしまい
Rubyの実行

progateなどで書き方はわかったけど、実際どうやって実行するのか知らなかったので

## 1. Rubyのインストール
## 2. gemのインストール
## 3. .rbファイルの作成
## 4. 使用するgemを記述
```
require 'gem名'
```
## 5. プログラムを記述
## 6. ターミナルから実行
```
$ ruby ファイル名.rb
```
Railsを使うまでもない簡単なプログラムはこれでおk
LaravelのAuthファサードを使って認証済みのユーザーを取得したいんですけどっ！？？

# イントロ

今回はLaravelの`Auth`ファサードを使って認証済みのユーザーを取得する方法をご紹介したいと思います。

本記事はLaravelドキュメントの[認証](https://readouble.com/laravel/8.x/ja/authentication.html
)を分かりやすく噛み砕いたものになります。

# ログインしているユーザー

「認証しているユーザー」とは簡単に言うと「現在ログインしているユーザー」という意味です。

Laravelの`Auth`ファサードを使うと、そのWebアプリに現在ログインしているユーザー、すなわち現在認証しているユーザーの情報を取得することができます。

ちなみに認証は英語で「authentication」です。

# 認証しているユーザーを取得する

現在認証しているユーザーを取得するには`Auth`ファサードに`user`メソッドを使います。

```PHP
use Illuminate\Support\Facades\Auth; // Authファサードを読み込む
$user = Auth::user();
```

これをすることで認証しているユーザーの情報を取得することができます。

# 認証しているユーザーのIDを取得する

これに似たメソッドで`id`メソッドを用いると、現在認証しているユーザーのID番号を取得することができます。

```PHP
use Illuminate\Support\Facades\Auth;
$user_id = Auth::id();
```

これをすると、$user_idに認証しているユーザーのID番号が取得できます。
ロググループのメトリクスフィルターで検知した文字列をDatadogに流してログ監視する

## What's This
CloudWatch Logsに出力されたログで、特定文字列があった場合に、
メトリクスフィルターで検知したい文字列を設定し、メトリクスフィルター作成時に生成されたcustom metricsをDatadogに流して、Datadogモニターで検知する

仕組みを作ったときのメモです。
あくまでメモなので、参考にされる場合は、公式ドキュメントの副読的な感じで読まれると幸いです。

## AWSでの設定

#### テスト用にロググループ作成

![スクリーンショット 2022-06-22 15.12.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1740345/dddf7e45-cc78-2c12-122d-81234da29381.png)

#### メトリクスフィルターを作成
"Error"文字列が出現したらカウントするように設定

![スクリーンショット 2022-06-22 15.14.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1740345/d89c8845-510b-0eb0-9dbc-434dbca2f5cc.png)

#### ログイベントを作成

![スクリーンショット 2022-06-22 15.23.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1740345/dc4e8c8b-2228-f35f-711e-6abf2f8acdda.png)

#### カスタムメトリクスが作成されていることを確認

上記で作成したメトリクスフィルターの、Metricから飛べます。

![スクリーンショット 2022-07-01 11.50.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1740345/688e64ff-cb9b-35f8-2cc4-af812cb386fe.png)


検知の文字列が発生していないと、メトリクスとして反映されない感じだった気がします。
反映されるまで少し時間がかかることも。
ここで、文字列がカウントされていることを確認できます。

## Datadogでの設定

#### Datadogのインテグレーション設定でcollect custom metricsにチェックが入っていることを確認

#### Datadogにカスタムメトリクスが流れてきたことを確認

Metic Explorerか、New monitorで、（上記メトリクスフィルターで生成された）Metricの名前

で、流れていることを確認。

![スクリーンショット 2022-07-01 11.47.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1740345/528f0e78-d3d0-91e6-a723-546af274d2a9.png)


#### ほか

モニター作成し、文字列が発生していないのに、なぜかアラート状態になる期間があり、原因の対策として
適切かは不明ですが、default_zeroをクエリに追加したところ、発生していない時は正常判定になりました。
以下で設定できます。

![スクリーンショット 2022-07-01 11.36.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1740345/86ba728e-1520-311b-057c-e9532bcde1dd.png)

![スクリーンショット 2022-07-01 11.37.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1740345/9f89878a-bfff-1a6b-d172-62819760ba3f.png)

## Reference
・https://cloudpack.media/18996
・https://docs.datadoghq.com/ja/metrics/custom_metrics/
・https://stackoverflow.com/questions/58414654/how-can-i-monitor-aws-cloudwatch-customized-metric-on-datadog
・社内有識者

参考になりました。ありがとうございます。
猫が教えてくれた組織変革のヒント!?

在宅時間が長い昨今、子供の情操教育を兼ねて、我が家で猫を飼いはじめ、家族が変わりました。

家族は「組織」であり、そこを一般化すれば、ひょっとして職場の変革のヒントになりうる（保証なし）と考え、共有してみます。

# 変わったこと

* 片付けるようになった
床に物があったり、台所に食べ物や食器が出ていたりすると、猫に荒らされる可能性があるので、自分も含め、みな率先して片付けるようになりました。「片付けろ」とさんざんいっても変わらず、しぶしぶ我慢したり自分で片付けたのに...物が片付けきれないということで導入を見送ってきたお掃除ロボットを導入できそうです。
* 騒音に気を付けるようになった
以前はけっこううるさかったんです。猫をびくびくさせないよう、足音や奇声が減りました。
* メディアから離れるようになった
コロナや夏休みで在宅時間が多い子供たちが、ゲーム・テレビ・ストリーミングメディアに費やす時間が以前は多かったのですが、猫が来てからそうした不健康な時間が減り、猫と触れ合い、家族で笑いあう時間が増えました。

# 結論
以上を一般化して教訓風にすると、家族と言う組織の変革は次のプロセスで起きたと言えます：

- 猫という**外部刺激により、問題がわかりやすい形で顕在化し、全員が解決の必要性に納得し行動した**。
- 猫を愛でるという**共通の目的のもとに全員が団結した**。

あなたの職場の「猫」は何ですか？
（そういや日本オラクルが会社で犬を飼っていますがいまもいるようですね。）

![kohaku.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2721295/b6f818d7-31f4-c03b-927d-13f9baea31f1.jpeg)
Laravelのwhereメソッドで取得するデータの条件を絞りたいんですけどっ！？？

# イントロ

以前にLaravelのEloquentを使って、モデルから全部のデータを取得する方法をご紹介しました。

https://qiita.com/Sunasuna24/items/fae5cefc4e8a136f7399

全部のデータではなくて、Eloquentに条件をつけて「一部の」データを取得するにはどんな方法があるのでしょうか。

今回はそちらをご紹介したいと思います。

本記事はLaravelドキュメントの[データベース:クエリビルダ](https://readouble.com/laravel/8.x/ja/queries.html?header=Where%25E5%258F%25A5#basic-where-clauses)を噛み砕いて説明したものになります。

:::note
今回紹介するEloquentは厳密にはクエリビルダですが、各Eloquentはクエリビルダとして機能するため、本記事では便宜上Eloquentとしてご紹介させていただきます。
:::

# `where`メソッドで条件を絞る

Eloquentに条件をつけてモデルを取得するときは`where`メソッドを使いましょう。

この`where`メソッドには3つの引数が必要です。

1. カラムの名前
1. 演算子
1. カラムの値と比較する値

簡単に書くと以下です。

```PHP
where(カラムの名前, 演算子, カラムの値と比較する値)
```

例えば、usersテーブルの`votes`列の値が`100`に等しく、`age`列が`35`より大きいユーザーを取得する方法は以下です。

```PHP
use App\Models\User;
$users = User::where('votes', '=', 100)->where('age', '>', 35)->get();
```

:::note warn
`where`メソッド単体は条件を絞る機能しかないので、`where`メソッドで条件を絞ったら最後は`get`メソッドでデータを取得するのを忘れないようにしてください。
:::

:::note warn
Laravelのドキュメントではいきなり条件を2つで絞っているが、`where()`や`get()`を繋げるときは`->`を書いて続ける。
:::

また一般にメソッドが増えるにつれて1行で続けると長くて見えづらいことがあるので、見えやすくするために以下のように改行することも多いです。

```PHP
$users = User::where('votes', '=', 100)
    ->where('age', '>', 35)
    ->get();
```

# `=`の省略形

絞りたい条件が`=`であるときは`where`メソッドの省略形が使えて、`=`を書かなくてもOKです。

```PHP
$users = User::where('votes', 100)->get(); // 2つ目の引数「=」を省略してもいい
```

# `where`メソッドを使った取得例

年齢が**18歳以上**で、性別が**男**のユーザーを取得

```PHP
$users = User::where('age', '>=', 18)->where('sex', 'male')->get(); // 「=」の省略形を使っている
```

ステータスが**公開済み**で、公開日が**2022年1月1日以降**の記事を取得

```PHP
$articles = Article::where('status', 'published')->where('published_at', '>=', '2022-01-01')->get();
```

# 他にも`where`メソッドに似たメソッドがたくさんあるよ

Laravelは非常に便利で多くのメソッドを用意しています。

「または」という条件を付与できる`orWhere`メソッドや、2つの値の間にある条件を加える`whereBetween`メソッド、値が`NULL`の条件を加える`whereNull`メソッドなど、たくさんあります。

これら`where`の派生的なメソッドはこちらLaravelのドキュメントを見てみてください。

https://readouble.com/laravel/8.x/ja/queries.html
プログラミング初心者が学ぶべき言語の選定

こんにちは。
長野県某所のA型事業所にいまは体験で入っています。
みなさん障害福祉事業ということで関心が高いようでこの前の記事もだいぶ伸びていました。

長野県のここら辺の地域はA型事業所バブルで、かなりA型事業所が乱立しています。
私の知っているところだけでも4カ所か5カ所くらいが新しく設立されているようです。
これは障害者の法定雇用率があがったことも関係しているそうです。
良い事業所があるのはありがたいことです。

事業所では私はプログラミングをしています。
目下Javascriptを覚えないといけないのですが、その次のアクションとして覚えていくべき言語を選定していました。

目的としてはアプリ開発をどの言語で行うか、ということですね。
以前の記事でSwiftやKotlinのはなしをしました。
ですが、特にKotlinは経験者向けの言語で、素人がやるにはハードルが高く、文献があまり見当たりませんでした。
Swiftのほうがまだ本などがたくさんあったので、やるならSwiftかな？とも思ったのですが、それよりも良い方法はないかな？と探してみているところです。

ちょっと前だったらXamarinという選択肢もあったと思いますが、すっかりはなしも聞かないですし、こちらも初心者向けではないそうです。というわけで候補からは外れました。
マルチプラットフォームで何か良い言語はないかな？と思っていたんですが、ヒントになったのは実際に案件があるかどうかというところです。

仕事の合間を縫って「複業クラウド」というアプリに登録して、実際に業務を受ける前にどんな言語が需要が高いのかとかを調べていました。
そこで名前を見たのがFlutterという言語です。

Googleさまが開発した言語で、マルチプラットフォームで動いてよさそうな感じでした。
難点としては英語でしか文献がないところのようですが、英語は抵抗はないので、良いかもしれませんね。
FlutterはiOS/Androidどちらにも対応しており、Dartという言語を使うそうです。この言語はJavascriptと親和性が高いそうで、今後の学習のプランとして、Javasrciptの後にFlutterというのはよさそうと思いました。

Kotlinの初心者向けの本や講座がもっとあればKotlinでよいかなと思いますが、そこはいろんな事情があり、一筋縄ではいかないもんだなと感じました。
Swiftの本も良いものがないか探してみて、SwiftやFlutterをやってみる方針でまとめてみたいと思います。何か良い言語があったら教えてくださいね。

それでは、今日の記事はこんなところです。
来週はわかりませんが、ちょっとずつ出勤の頻度は上がっていく予定ですので、その都度、記事を書いていきたいと思います。
暑いので、無理せずまいります。

それでは、また。
Ubuntuで足りないファイルを解決するパッケージの調べ方

## 概要

lddコマンドで不足するファイルを見つけたが、どのパッケージをインストールすれば良いのかが分からない。。。

```sh
$ ldd ./hoge
libnssutil3.so => not found
```

そんなときは下記のサイトでファイルを含むパッケージを検索しよう。

https://packages.ubuntu.com/

例えば、**パッケージの内容を検索**にlibnssutil3.soを入れて検索すると、、、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235642/0094e8bf-6f7c-4d45-e9ad-7a4c6904feed.png)

パッケージ**libnss3**に含まれていることが分かった！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235642/ee9dd58a-3e90-06b6-ea8b-2bb3e383ca73.png)

これで解決。

```sh
$ sudo apt install libnss3
```

## おまけ: apt-fileを使った検索について

> There is also apt-file. Because this method required updating the files database, however, I prefer the other, instant option.
>
> apt-fileもあります。しかし、この方法ではファイルデータベースを更新する必要があるため、私はもう一つの即席のオプションを好みます。

参考
https://askubuntu.com/questions/2493/apt-get-or-aptitude-equivalent-to-yum-whatprovides
AWS EFSの用語要点まとめ（自分用メモ

・Amazon EFS（Elastic File System）
NFS（Network File System）プロトコルをサポートするファイルストレージサービス。NFSとはネットワーク上にある複数のコンピュータからストレージを共有することができるプロトコルのこと。EFSはNFSに対応したAWSサービスおよびオンプレミス（自社運用）のシステムから利用できる。
NFSを利用したファイル共有では、誰かがファイルを更新している際は他の誰かが更新できないようにしたり、参照のみであれば複数人がアクセスできるようにするなど、ファイルに対するロック（排他制御）がなされている。

●フルマネージド型のファイルシステム
EFSは以下の特徴を持つ、フルマネージド型のストレージサービスです。
・容量無制限：EFSではデータ量に伴い自動的にスケーリング（拡張・縮小）が行われるため、利用開始にあたり事前に容量を確保する必要はありません。保存したデータ量に応じて課金が発生。
・可用性：EFSはリージョン内の複数のAZにまたがってサービスを提供しているため、単独AZの障害にも影響を受けません。またデフォルトでAWS Backupを使ったバックアップが有効。
・堅牢性：EFSはデフォルトで保管時のデータの暗号化が有効になっています。また、EFSのファイルシステムマウント時にTLS（Transport Layer Security：セキュアな通信を行うプロトコル）を使うこともできるので、転送データを安全に扱える。

※EBSとの大きな違いは、複数インスタンス（複数ユーザー）からの同時アクセスを前提としていること。またEBS（およびインスタンスストア）は同一AZ内でのみ利用可能でしたが、EFSでは異なるAZのEC2インスタンスからもアクセスが可能。

●パフォーマンスモードとスループットモード
EFSでは、ファイルシステムに対する読み取り・書き込み性能（パフォーマンス）をユーザーが調整できる。パフォーマンスの設定には、ファイルシステム作成時にのみ設定する「パフォーマンスモード」と、運用中に変更が可能な「スループットモード」があります。パフォーマンスモードではファイルシステムの基本的な性能を設定し、スループットモードでは秒間の転送容量（GB/秒）を調整して一時的な高負荷に対応することができます。

パフォーマンスモード（EFS作成時に設定）：
・汎用パフォーマンスモード ... 一般的な用途向けのモード
・最大I/Oパフォーマンスモード ... ビッグデータの解析などの大容量データや、数千台のクライアントの処理向けのモード

スループットモード（運用中に変更可能）：
・バーストスループットモード ... ストレージの容量に従ってベースライン性能（基本性能）が設定され、一時的に負荷が高くなった場合はベースライン性能の2倍まで性能向上できる
・プロビジョンドスループットモード ... ユーザーが予約した（provisioned）性能をAWSが保証してスループットを提供

バーストスループットモードのベースライン性能はストレージの容量によって設定されるため、データ量が多ければ多いほど高いスループットを得ることができます。逆に、データ量は少ないがアクセス頻度の多いようなケースではバーストスループットモードでは性能要件を満たせない場合があります。その場合はプロビジョンドスループットモードに設定することで最適な性能を得ることができます。
Webpack5 複数の起点ファイル毎にバンドルJSを吐き出す

調べてもパッと出てこなかったので自分用メモとして。
もっといいやり方があれば教えてください。
## やりたいこと
各ディレクトリにある起点ファイルを元にバンドルしてそれぞれ吐き出したかった。
```:フォルダ構成
root/
  ├─ apps/
  │    ├─ app1/
  │    │    └─ index.ts <-個別でバンドルしたい！
  │    │
  │    └─ app2/
  │         └─ index.ts <-個別でバンドルしたい！
  └─ other/
```
```:理想の出力結果
root/
  ├─ apps/
  │    ├─ app1/
  │    │    ├─ index.ts
  │    │    └─ index.bundle.js <-それぞれ吐き出してほしい！
  │    └─ app2/
  │         ├─ index.ts
  │         └─ index.bundle.js <-それぞれ吐き出してほしい！
  │    
  └─ other/
```
## やり方
### 1. npm globでパターンにマッチしたファイルパスを動的に取得する。
globのインストール
```
npm i glob --save-dev
```
https://www.npmjs.com/package/glob
```javascript
const glob = require("glob");
const pattern = "./apps/*/index.ts";
const filePaths = glob.sync(pattern);
```
### 2. マッチしたファイルパスを元にwebpackの構成ファイルに合わせてオブジェクトを組み立てる。
JavaScript歴は激浅なのでココは超絶適当です...。
```javascript

//拡張子を除いたファイルパスを取得する関数
getBaseName = str => str.substring(0, str.lastIndexOf("."));

//拡張子を除くファイルパスをキー名としたオブジェクトを組み立てる
// { "file/path/to/index" : "file/path/to/index.ts" }
const entries = {};
for (const filePath of filePaths) {
    const baseName = getBaseName(filePath);
    entries[baseName] = filePath;
}
```
### 3. webpackの構成ファイルに組み立てたオブジェクトを指定する。

outputのfilenameに **[name].bundle.js** を指定するのがミソです。
[name]には先程組み立てたオブジェクトのキー名が展開されるので出力先が分岐します。
細かい仕様に関しては全く理解していません。。。
```javascript
const path = require("path");
module.exports = {
    mode: 'production',
    devtool: 'source-map',
    entry: entries, //組み立てたファイルパスを直接entryに指定する
    output: {
        path: path.resolve(__dirname),
        filename: "[name].bundle.js" //[name]にパスが展開されて出力先が分岐する
    },
    module: {
        ...
    }
};
```
## 完成形
```javascript:webpack.config.js
const glob = require("glob");
const pattern = "./apps/*/index.ts";
const filePaths = glob.sync(pattern);
getBaseName = str => str.substring(0, str.lastIndexOf("."));

const entries = {};
for (const filePath of filePaths) {
    const baseName = getBaseName(filePath);
    entries[baseName] = filePath;
}

//ここから基本設定
const path = require("path");
module.exports = {
    mode: 'production',
    devtool: 'source-map',
    entry: entries, //組み立てたファイルパスを直接entryに指定する
    output: {
        path: path.resolve(__dirname),
        filename: "[name].bundle.js"
    },
    module: {
        ...
    }
};
```

## まとめ
やりたいことができてよかったです。webpackの構成ややこしすぎる...。

https://webpack.js.org/concepts/entry-points/

https://webpack.js.org/configuration/output/

https://qiita.com/twinemarron/items/7adca7b911caa2718823

http://webdesign-dackel.com/2015/09/10/webpack-multiple-output/
配列に対して`for`ループを回そうとした時にちょっと失敗した話

# はじめに

私が仕事で書いていたコードで、配列に対する`for`ループを書いた時、想定外の結果が出てしまったことについて書いていきます。

# JavaScriptの`for`文について

JavaScriptでは、`for`を用いる構文が幾つかあります。
まず、C言語等を扱ったことがある方にはお馴染みの
```javascript
for (let index = 0; index < 20; index++) {
  // 処理
}
```
があります。
また、オブジェクト指向言語ではよくある、配列やオブジェクトの中身を直接用いることができる、

```javascript
for (const element of array) {// 実際は「array」のところには、配列に限らず「反復可能オブジェクト」であれば何でも入れることができる
  // 処理
}
```

```javascript
for (const key in object) {// keyにはオブジェクトのキーが代入される
  // 処理
}
```

という記法を用いることができます。
ここでは書きませんが、非同期の反復可能オブジェクトに対しての構文もあります。

# 実際に書いてしまった内容

以上軽く説明しましたが、私が実際にコードを書いた時、ドキュメントをチラ見してうろ覚えで書いてしまった結果が以下になります。

```javascript
for (const element in array) {
  // 処理
}
```

これを書いて実行した結果何が起こったかと言いますと、「`element`が配列の要素ではなく、配列のindex(数字)になってしまった」です。

# 説明

上記で、`for..in`構文ではObjectに対して用い、そのkeyが代入されると説明しましたが、配列も内部的にはそのindex(数字)をkeyとして持つObjectとみなすことができるようです。
そのため、配列に対して`for..in`構文を用いると、内部的に持っているkey(index)を代入してしまうようです。

# おわりに

ドキュメントはしっかり読みましょう…(自戒)
Core Web Vitals CLS対策メモ



## はじめに
最近行っていた案件の中で、CLS対策を行いましたのでそのメモになります。


### CLSとは
   
2021年５月Googleの検索結果のランキングの評価対象として、コアウェブバイタルという３つの指標が定められました。
3つの指標とは、LCP（速度）、FID（応答性）、CLS（視覚要素安定性）です。
その中で、今回はCLSの対策を行いました。
CLS（Cumulative Layout Shift）とは直訳すると「累積レイアウトシフト」の意味になります。
CLSは、ページの視覚的な安定性を測る指標で、読み込みフェーズで予期しないレイアウトのズレがどのくらい発生したかを表します。
詳しくは、下記を参照
https://web.dev/optimize-cls/
### CLSの低下の要因
>CLS が低下する要因としては、一般的に以下のものが考えられます。
・サイズが指定されていない画像
・サイズが指定されていない広告、埋め込み要素、iframe
・動的に挿入されたコンテンツ
・FOIT/FOUT の原因となる Web フォント
・ネットワークの応答を待ってから DOM を更新するアクション
### CLSのスコア
CLSのスコアを0.1以下にすることで、ユーザビリティの向上につながります。
スコア0.1未満が「良好」、0.25以下は「改善が必要」、0.25を超えると「不良」と判断されます。


### 実装手順
具体的に今回行った具体的な手法を紹介します。
基本的には、画像の要素に対しての領域の確保をHTMLとCSSで行います。

#### 画像領域の確保
imgタグ内にwidth属性とheight属性を指定します。
<pre><code>&lt;img src="fuga.jpg" width="100px" height="200px"&gt;</code></pre>
レスポンシブ画面やモバイルは、CSSで対応します。
<pre><code>@media screen and (min-width: 900px) {
  img {
　　width: 100px;
　　height: 200px;
　　}
}</code></pre>
#### 要素の領域の確保
幅や高さを固定しても問題なさそうな要素に対して、領域の確保をします。
div要素などに対しても、画像領域の確保のようにサイズを指定します。
<pre><code>.hoge{
　width: 100px;
　height: 200px;
}</code></pre>親要素のサイズを設定することで、レイアウトシフトの防止になります。
### 検証ツール
#### Lighthouse
Google Chromeの拡張機能になります。
SEOにおける分析レポートが表示されます。
今回は主にLighthouseを使用しました。
https://chrome.google.com/webstore/detail/lighthouse/blipmdconlkpinefehnmjammfjpmpbjk?hl=ja

#### Google Chromeの開発者ツール
開発者ツールのPerformanceタブに移動し、計測します。
細かな静止画が表示され、レイアウトシフトしている箇所を確認できます。
#### PageSpeed Insights
Googleが提供している公式の検証ツールになります。
スコアの表示とレイアウトシフトされている箇所が表示されます。
しかし、ベーシック認証がされているページは計測することができません。
https://pagespeed.web.dev/?utm_source=psi&utm_medium=redirect&hl=ja
### 所感

・SEO対策の一環としてCLS対策を行いましたが、SEOは奥が深く今後CLS以外にもSEOについて学んでいきたいと思います。
・少しの工夫で、スコアの改善につながり、検索結果の上位表示につながるので突き詰めていきたいと思いました。

### 参考資料
　　出典：株式会社イーノバ公式ページ　（最終閲覧日：2022年6月15日）
　　　　https://innova-jp.com/core-web-vitals-cls/
　　出典：web.dev　（最終閲覧日：2022年6月15日）
　　　　https://web.dev/optimize-cls/
『リーダブルコード』が優れたコードについて本当に言いたかったこと

# はじめに

某『リーダブルコード』の要約記事に始まる、優れたコードに関する不毛な議論がコメント欄で始まっていたので、『リーダブルコード』が本当に言いたかったことを説明します。

なぜ私が説明するかって？
それは、私が『リーダブルコード』のファンだからです。

なお、某記事では記事の著者にブロックされていてコメントできないため、新規記事にしました。

# 『リーダブルコード』の本当の内容

> 1.1　「優れた」コードって何？

この章では、まず直感的に優劣を付けられる例を挙げ、それから件のコードが登場します。

(以下、P2～P3から引用)
> でも、どちらが優れているかわからないことも多い。例えば、このようなコードは、

```c++
return exponent >= 0 ? mantissa * (1 << exponent) : mantissa / (1 << -exponent);
```

> 以下のコードよりも優れているのだろうか。

```c++
if (exponent >= 0) {
    return mantissa * (1 << exponent);
} else {
    return mantissa / (1 << -exponent);
}
```

>　前者のほうが簡潔だ。でも、後者のほうが安心できる。「簡潔」と「安心」はどちらが大切なことなんだろう？　君ならどうやって決めるだろうか？

[引用ここまで]

つまり『リーダブルコード』はどちらのコードが優れているとは言ってません。
優れたコードの判断基準をどこにおけばいいのかを考えるための材料を提示しているのみです。

# 『リーダブルコード』の結論

> 1.2　読みやすさの基本定理

> 鍵となる考え
> コードは他の人が最短時間で理解できるように書かなければいけない。

そう、これが結論です。
『リーダブルコード』は、これを実現するための様々な考え方やテクニックを説明する書籍です。

# 要約記事を読むより書籍を買って読む方がコスパ高いよ

t/o

# 最後に

なお、私はこの記事の内容に関しての議論はしたくありません。
あしからず。