OmniAICreator/Qiita-1.07M huggingface dataset:
【Swift】Swift Macroの基本

# この記事は何？

Swift 5.9から導入されたマクロについて、Appleの開発者向けドキュメントより「[Applying Macro](https://developer.apple.com/documentation/swift/applying-macros)」を独自に解説する。

マクロは、コンパイル時に定型的に繰り返されるコードを生成する。

> Swiftを基礎から学ぶには
自著、工学社より発売中の「[まるごと分かるSwiftプログラミング](https://amzn.asia/d/7YPWJwl)」をお勧めします。変数、関数、フロー制御構文、データ構造はもちろん、構造体からクロージャ、エクステンション、プロトコル、クロージャまでを基礎からわかりやすく解説しています。

# 概要

Swiftマクロは、コンパイル時にソースコードを部分的に生成するので、Swiftで反復的なコード記述を減らすことができる。
マクロの呼び出しは常に追加的に行われる。
マクロは、元のコードに新しいコードを追加するが、すでにプロジェクトの一部であるコードを変更したり、削除したりしない。

Swift標準ライブラリや多くのフレームワークは、多くのマクロを提供する。
独自のマクロを書くこともできる。

マクロはSwiftコードを生成するため、コードがマクロを使用するかどうかに関係なく、開発とデバッグに同じツールを使用すること。

マクロ展開の概要を示す図
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/70476/c637b2fd-cd95-d3e4-3dc5-c8165b782d63.png)
左側は「元のSwiftコード」だけだが、右側には「マクロによって追加されたコード」がある。

# マクロを呼び出す

マクロを呼び出す方法は、マクロを「宣言にアタッチ（添付）するかどうか」によって多少、異なる。

マクロを「宣言にアタッチする」には、マクロ名の先頭にアットマーク記号`@`をつけて、その直後にマクロ引数を指定する。
これは、属性を書くのと同じ構文。

```swift:添付マクロの呼び出し
@Observable class MyObject {
    public var someProperty: String = ""
    public var someOtherProperty: Int = 0
    fileprivate var somePrivateProperty: Int = 1
}
```

宣言にアタッチされたマクロはコードを生成して、そのコードを宣言に追加する。
たとえば、上記の`Observable()`マクロは、`MyObject`クラスにメンバーを追加して`Observable`プロトコルを採用して、`MyObject`を`Observable`に準拠する。

宣言にアタッチせずにマクロを呼び出すには、マクロ名にシャープ記号`#`をつけて、その直後にマクロ引数を指定する。
これは、`#if`やその他のコンパイル時操作と同じ構文。

```swift:自立マクロの呼び出し
let messagePredicate = #Predicate<Message> { message in
    message.recipient == "John Appleseed"
}
```

宣言に添付されていないマクロはコードを生成し、マクロを呼び出す場所にそのコードを追加する。
たとえば、上記のコードの`#Predicate`マクロは、`Predicate`構造体のインスタンスを作成する。

> `Predicate`型のドキュメントは[こちら](https://developer.apple.com/documentation/foundation/predicate)

[マクロ](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/macros)の詳細については、Swiftプログラミング言語を参照。

# 展開したマクロのコードを見る

プロジェクトをビルドすると、Swiftはコードを読み、マクロを呼び出す場所を探す。
その後、Swiftは各マクロの実装を呼び出して、コードを展開する。
最後に、Swiftは生成されたコードを含め、通常どおりプロジェクトをビルドする。

Xcodeでマクロが生成したコードを表示するには、マクロを呼び出すコードをクリックし、「Editor > Expand Macro」を選択する。
展開したコードを読んで「マクロの動作の詳細」を理解することができる。
また、拡張コードを使用してマクロを使用するコードをデバッグすることができる。
マクロによって生成されたコードにブレークポイントを設定することも可能。
DockerのImagesを作りすぎて新しいDocker環境がつくれなくなった


## 直面したエラー
オンプレサーバーの中でDockerを利用した開発環境を作成するために`docker compose build --no-cache`を多用していたところ、以下のエラーに直面しました。
```
// 略

#0 30.63 Error Summary
#0 30.63 -------------
#0 30.63 Disk Requirements:
#0 30.63    At least 346MB more space needed on the / filesystem.
```

## ディスク利用状況の確認
Dockerのディスク利用状況を確認してみると。。。
```
$ docker system df
TYPE            TOTAL     ACTIVE    SIZE      RECLAIMABLE
Images          41        2         13.91GB   13.24GB (95%)
Containers      2         2         187.7kB   0B (0%)
Local Volumes   16        1         1.285GB   930.4MB (72%)
Build Cache     435       0         12.66GB   12.66GB
```

不要なImagesとcacheがたまってそれぞれ13.91GB, 12.666GBを食っていました。

## Volumesを整理
Volumsの整理用のコマンドを実行することで解決しました。
```
$ docker system prune -a --volumes
```


## 参考
https://qiita.com/shione/items/dfa956a47b6632d8b3b3
Dependabotで依存関係を自動アップデート

# はじめに
すごく今更感がありますが`Dependabot`を使用してパッケージの依存関係を
自動でアップデートできることを最近知りました...
実際に自身のリポジトリに反映したいので、ついでに記事も書こうと思います。

# Dependabotってなんぞ？
`Dependabot`とは簡単に言うとGitHub上で自動的に
プロジェクトが依存しているライブラリのバージョンを上げた`PR`を作ってくれるボットさん。
入れておくと定期的に自動でライブラリのアップデートを確認しに行ってくれる便利ボット様なんですね。
確認頻度は調整可能らしい。ｽｺﾞｲﾈ!!!

# Dependabot様を有効化する
https://docs.github.com/ja/enterprise-cloud@latest/code-security/dependabot/dependabot-version-updates/configuring-dependabot-version-updates

では居ても立っても居られないので早速有効化してみます。
手順は以下です。

## ❶GitHub.com で、リポジトリのメイン ページへ移動
Dependabotを有効にしたいリポジトリへ移動

## ❷リポジトリ名の下にある設定をクリック
Settingsをクリック
![dependabot.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3526092/4a0ff58e-a34e-6af0-6751-a5fe1daa4523.png)

## ❸サイドバーのセキュリティセクションでコードのセキュリティと分析をクリック
Code security and analysisをクリック
![dependabot-ページ2.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3526092/dd8379c4-d9d3-f276-0ccf-a414e521f1bb.png)

## ❹Dependabot version updatesの右側にあるEnableをクリック
Enableをクリック
![dependabot-ページ3.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3526092/bba3ea35-e699-2577-2e5f-e71a3fc21360.png)
EnableクリックでDependabot構成ファイルのエディターが表示されます
![スクリーンショット 2023-09-25 10.47.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3526092/d0414c99-774e-06bc-4efc-88bdfcdff6c1.png)

## ❺Dependabot構成ファイルの変更

必要な設定としては以下の3点です
- `package-ecosystem`: パッケージ マネージャーを指定
    - npm, yarn, pnpm, ...
- `directory`: マニフェストや他の定義ファイルの場所を指定
    - package.lockのが配置されているディレクトリ
- `schedule.interval`: 新しいバージョンをチェックする頻度を指定
    - daily: 毎日
    - weekly: 毎週
    - monthly: 毎月

![スクリーンショット 2023-09-25 10.54.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3526092/2240438e-c85b-7a02-c4c5-b215722f0135.png)

基本的な設定はこちらでOKなのでコミットします

## ❻しばらく待機...
しばらく待機した後PRを見てみましょう
![スクリーンショット 2023-09-25 11.00.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3526092/69d31e5c-c824-f9b0-84d3-00f15a50db3c.png)
![スクリーンショット 2023-09-25 11.03.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3526092/a01b3fa9-ebd0-4272-0082-6cdc19ab12d8.png)

導入は超簡単ですし早速自動アップデートPRを作成してくれています。ｽ...ｽｺﾞｲﾈ...
Dependabotを知らなかった今までの自分に腹が立ちました:rage:

## 気になったこと
Dependabotはすごく便利ですが、きちんと運用を考えないといけないなと思う部分もありました
でないとDependabotのPRが放置されたり、闇雲にマージしてしまうと環境が壊れる可能性もありそう...
この辺りの運用方法はまた別途様々なプロジェクトを見て、学ぶ必要がありそうです

# 余談
## 依存関係更新のカスタマイズ
https://docs.github.com/ja/enterprise-cloud@latest/code-security/dependabot/dependabot-version-updates/customizing-dependency-updates

先ほどの`dependabot.yml`に記載した内容は最小構成です
そのほかにも依存関係をアップデートする際にさまざまなカスタマイズが可能であるようです
PRのレビューワー設定、カスタムラベル、アップデートパッケージのグループ化などなど
この辺りも網羅することでより良いDependabotライフを謳歌できそうですね！素晴らしい！！

## GitLabではできないの？
https://www.linkedin.com/pulse/dependabot-gitlab-does-work-dunelm-soft-furnishings-ltd

https://docs.gitlab.com/ee/user/application_security/dependency_scanning/

### GitLabでも依存関係の自動アップデートはできる？
一応できる
ただ、`GitLab独自の依存関係スキャン機能`を使用する場合`有料プラン`のみ使用できるらしい

### じゃあDependabotをGitLabリポジトリに導入できる？
こちらもできるらしい
ただ、GitLabのネイティブ統合ではないため、GitHub上のDependabotほど
セットアップが迅速かつ簡単ではなく、構成可能性も高くないとのこと...ﾅﾙﾎﾄﾞ...
リファクタリングの重要性について

## はじめに

ソフトウェア開発は単に新しい機能を追加するだけのものではありません。ソフトウェアの開発とメンテナンスは、どちらも組織のビジネス目標達成のための重要な要素です。長期的には、コードの品質維持と改善も非常に重要です。リファクタリングは、この過程でのコードの品質を維持・向上させるための活動であり、直接的なビジネス価値を生むことは少ないものの、中長期的な視点での多大な恩恵が期待されます。

## リファクタリングとは

リファクタリングとは、外部から見たソフトウェアの振る舞いを変えることなく、内部のコードの構造を改善するプロセスのことです。エンジニアは、これを「ソフトウェアの健康維持」と考えています。

## リファクタリングの目的

### ソフトウェアの寿命を延ばす

ソフトウェアは、定期的なメンテナンスがないと「老化」していき、時間とともにコードの複雑さが増していきます。リファクタリングを行うことで、この老化を防ぐことができます。

### 新しい機能の追加や変更を容易にする

良好に設計されたコードは変更が容易です。逆に言うと、リファクタリングが行われないコードは、新しい機能の追加や既存機能の修正が難しくなります。

### バグの発見を助ける

リファクタリングを行う過程で、隠れていたバグや問題点が見えることがあります。

## リファクタリングとビジネス価値

### 継続的なサービス提供の安定性

良好な維持されたコードは、システムのダウンタイムを減少させ、継続的なサービス提供の安定性を保つことができます。これは、顧客満足度の向上やブランドイメージの維持に直結します。クオリティの低下は、顧客からのクレーム増加やビジネスの停滞を引き起こすリスクがあります。

### 開発コストの削減

長期的な視点で見ると、リファクタリングは開発コストの削減に繋がります。良好なコードは、新しい機能の追加や既存機能の修正にかかる時間と労力を大幅に削減できます。リファクタリングが継続的に行われることで、新機能の追加やバグ修正の効率が向上します。これは、将来の開発コストの削減に直結します。

### システムの拡張性と柔軟性の向上

ビジネスニーズは常に変わります。リファクタリングを通じて良好なコードを維持することは、新しいビジネスニーズへの対応や変更を迅速に行うことが可能です。

### 市場への迅速な対応

クリーンなコードは、新しい機能の導入や変更を迅速に行うことができます。これにより、市場の変化や競合他社に対して迅速に対応することが可能となります。

### システムのセキュリティ向上

リファクタリングを行う中で、既存のセキュリティの脆弱性やリスクが明らかにされることがあります。これにより、セキュリティ対策を強化し、ビジネスのリスクを低減することが可能となります。

## リファクタリングのタイミング

### システムの変更や拡張が困難になった時

システムが複雑になり、新しい機能の追加や変更が難しくなったと感じるときが、リファクタリングの最も一般的なタイミングです。この状態を放置すると、新しいビジネスの要求に迅速に対応することができず、ビジネスチャンスを逸してしまうリスクが高まります。

### 既存のバグが頻繁に発生する時

コードの品質が低下すると、既存のバグの修正や新しいバグの発見が難しくなります。早期のリファクタリングで、バグの原因となる複雑さや不明瞭さを解消することができ、システムの安定性を保つことができます。

### 新しい技術やアーキテクチャへの移行を検討する時

技術の進化により、より効率的かつ安全な方法でシステムを構築・運用することが可能になることがあります。旧式の技術やアーキテクチャを持つシステムは、新しい要求に対応するためのコストが増加する可能性があります。

## リファクタリングへの疑問

### なぜ今やらないといけないのか

リファクタリングを先延ばしにすることで、システムの複雑さは時間とともに増加します。この複雑さが増加すると、後にリファクタリングするためのコストも大きく増加します。また、システムの不安定性や変更の困難さも増すため、ビジネスの機会損失のリスクも増加します。

### ビジネスに直結する案件を優先すべきではないか

短期的なビジネスの要求を迅速に対応することも非常に重要ですが、長期的な視点でのシステムの健全性も等しく重要です。短期的な利益を追求するあまり、長期的なリスクを無視すると、後々大きなコストが発生する可能性があります。リファクタリングは、そのリスクを回避し、長期的なビジネスの成長をサポートするための投資と捉えることができます。

## リファクタリングとビジネスのバランス

### ビジネスの緊急性

現在のビジネスの状況、市場の動向、競合他社の動きなど、外部環境からのプレッシャーが高い場合、直ちに対応が必要なビジネス上の案件が存在するかもしれません。例えば、 新しい競合商品の登場に対する対抗策、法的な変更への対応などが挙げられます。

### ソフトウェアの健全性

リファクタリングが必要とされる背景には、ソフトウェアの健全性や保守性が低下していることが考えられます。その結果、新しい機能の追加やバグの修正に時間がかかるようになり、ビジネス上の要求への対応が遅れるリスクが高まります。

### 長期的なビジョンと戦略

ビジネスの短期的な要求にのみ対応していると、中長期的な視野を失う可能性があります。リファクタリングは、中長期的なソフトウェアの健全性を保つための投資として捉えることができます。

### コストとリターン

リファクタリングの費用対効果を評価することが重要です。リファクタリングの結果、将来的な開発や保守のコストが大幅に削減される可能性があるかどうかを検討する必要があります。

## まとめ

リファクタリングは、ビジネスの持続性、成長性、そして競争力を維持・向上させるための重要な投資として位置づけることができます。ソフトウェアが直面する未来のリスクを減少させ、効率的な開発をサポートするための投資と考えることができます。短期的な収益を追求するだけでなく、中長期的な視点でのビジネスの健全性を維持するためにも、この活動は欠かせないものです。
【Rails】ネーミングのお作法：MVC編

# はじめに
Railsでの一般的な命名規則について説明していきます。

:::note info
表記法
* キャメルケース
    * アッパー
    * ロウワー
* スネークケース
* コンスタントケース
* ケバブケース
* M (Model) → 単数形
* V (View) → 複数形
* C (Controller) → 複数形
:::

## キャメルケース
キャメル（camel）はラクダのことで、コブに見立てて単語ごとの頭文字を大文字で表記します。
全体の先頭の文字は、大文字の場合と小文字の場合とがある。

### アッパーキャメルケース
主にクラス名、モジュール名で使用され
先頭が大文字のキャメルケースで表記します。

```admin_user.rb
# 例
class AdminUser
end
```

### ロウワーキャメルケース
主に`JavaScript`の変数名などで使用され
先頭が小文字のキャメルケースで表記します。

```.js
// 例
const helloWorld = "ハローワールド";
console.log(helloWorld);
...
```

## スネークケース
主に変数名、ファイル名で使用され
単語の区切りを`_`アンダースコアで表記します。
```users_controller.rb
# 例
class UsersController

    def set_user
    ...
    end

    def user_params
    ...
    end
end
```

## コンスタントケース
変更しない定数などを表現する際に使用され、
全て大文字のスネークケースで表記します。
```.rb
TAX_RATE = 0.1
```

## ケバブケース
主に`HTML`のクラス名などで使用されるケバブケース。
棒に刺さった肉の様に単語の区切りを`-`ハイフンでで表記します。

```.haml
.box
  .box-header.with-border
    %h3.box-title= "タイトル"
```

## MVC（Model-View-Controller）の命名
MVCアーキテクチャは、アプリケーションのコードを3つの主要なコンポーネントに分割します。
それぞれの命名規則を解説します。

### Model (モデル)
モデルは単数形キャメルケースの名前を使用します。
テーブル名は複数形でなければなりません。
そしてモデルクラスのファイル名は単数形スネークケースを使用します。

| アイテム | 名称 | 命名規則 |
|:-----------|:------------|--------------|
| モデル名 | admin_user     | 単数形・小文字・スネークケース   |
| テーブル名 | admin_users | 複数形・小文字・スネークケース |
| クラス名 | AdminUser    | 単数形・先頭大文字・キャメルケース   |
| ファイル名 | admin_user.rb    | 単数形・小文字・スネークケース   |

### View (ビュー)
ビューのテンプレートファイルはコントローラ名と対応するディレクトリ内に保存されます。
* ビューファイルの名前はアクション名に対応し、スネークケースを使用します。
例：`app/views/admin_users/index.html.haml`
* パーシャルビュー（再利用可能な部分ビュー）はアンダースコアで始まることが一般的です。
例：`app/views/admin_users/_form.html.haml`

#### ルーティング（Routes）
ルーティングではRESTfulなルーティングを使用し、リソース名を複数形で表現します。
```.rb
resources :admin_users
```
### Controller (コントローラー)
複数のアクションを管理するコントローラは複数形の名前を使用します。
コントローラクラスのファイル名も複数形スネークケースを使用します。
| アイテム | 名称 | 命名規則 |
|:-----------|:------------|--------------|
| コントローラー名 | admin_users     | 複数形・小文字・スネークケース   |
| クラス名 | AdminUsersController    | 複数形・先頭大文字・キャメルケース   |
| ファイル名 | admin_users_controller.rb  | 複数形・小文字・スネークケース   |

# さいごに
今回はMVCの命名についてお話しました。
次回はメソッド名や変数名などのネーミングについて書こうかと思います。
[小ネタ]ACMの証明書を再発行してもCNAMEレコード値は変わらない

## これは何?
ちょっとした小ネタではあるのですが、タイトルにもある通りACMを再作成してもCNAMEレコードの値は変わらないことについて紹介しようと思います。


## 想定されるケース
ドメインをRoute 53 で管理せず、顧客所掌のドメイン管理サービスを利用し、且つ証明書はCertificated Managerを利用するケースの場合、ACMで発行されたCNAMEレコードを外部のドメイン管理サービスに登録する必要があります。

たまにここの意思疎通が煩雑なケース(何社にも跨ぐ)ことがあるため、CNAMEレコードの登録がDNS検証のリミットである72時間経過してタイムアウトが発生する場合があります。
https://docs.aws.amazon.com/ja_jp/acm/latest/userguide/troubleshooting-timed-out.html

## 解決策
実は、これ**ACMを再作成しても、CNAMEレコードの値は再作成前のCNAMEレコードの値と差分はない**です。
https://docs.aws.amazon.com/ja_jp/acm/latest/userguide/dns-validation.html

そのため、作成された段階でCNAMEレコードが判明したら情報連携し、72時間経過後のタイムアウトが発生しても、顧客からCNAMEレコード登録完了した時点で再度ACMを作成すれば、DNS検証は完了しますため、早めの登録や周知などは必要はないかと思います。


## 終わりに
私もこういった事象に合い、ACM再作成したらレコード値が変わらってないことを知りました。
色々なサービスを触ると、顧客への提案も変わるのでこれからもいろいろなサービスに触れていきたいところです。
1Password のパスキー対応を試す

1Password のパスキー対応が正式リリースされたので使ってみた、という記事。(実装側の話は特にない)

## パスキー (passkey) とは？
(詳しい説明は割愛するのでググってください)

- FIDO アライアンスと W3C が標準規格を定めている認証方式
- 鍵ベースの認証を行うことで、ユーザにはパスワードやトークンなどを一切入力させない
- 代表的な OS や Web ブラウザの対応はほぼ完了しているので一般ユーザでも利用可能といえる

少なくともコンシューマ向けの Web アプリケーションでは今後普及していくであろう技術なので、個人的に注目している。

## 1Password がパスキーに対応した
https://www.publickey1.jp/blog/23/1password.html

従来でも Apple や Google のアカウントと紐づけてパスキーを利用することができたが、例えば Apple ID と紐付けると Windows に同期できないなど、利用できるデバイスが制限される点で不便だと感じていた。また自分は個人アカウントのパスワードマネージャとして 1Password を使用しているので、1Password でパスキーを管理できる機能の正式リリースは待望だった。

## 使ってみる
GitHub は既にパスキー認証に対応しているので、macOS から GitHub のパスキー設定をして iOS からログインできるか試してみる。

### 0. 事前準備
- macOS
    - 使用している Web ブラウザの 1Password 拡張機能を最新版に更新
    - 1Password 拡張機能の設定で「1Password をデフォルトのパスワードマネージャにする」を有効化
- iOS
    - 1Password アプリを最新版に更新
    - iOS の `設定` > `パスワード` > `パスワードオプション` でパスキーの提供元を「1Password」に設定

### 1. パスキーの作成
GitHub `Settings` > `Password and authentication` 画面に `Passkeys` の項目があるので、そこからパスキー設定を追加する。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16369/e964dd2c-9f6e-1ee5-d7be-97a13a1fc549.png)

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16369/2a361030-1b12-e105-3fa8-4fb5e7b55716.png)

特に何もしなくても 1Password の `Save passkey` 画面が出てきた。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16369/2e8d9f99-1c3f-5399-aa11-c78e081294a0.png)

パスキーの追加が完了したあと何かニックネームをつけろと言われるが、これは GitHub の設定画面でわかりやすい文字列を表示するためのものらしいので「1Password」などと入れておいた。

![04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16369/04c432d9-9499-9969-a2fc-a0c5a06daca0.png)

### 2. パスキー設定を確認してみる
再び GitHub 設定画面を見ると、パスキーが追加できていることがわかる。

![06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16369/4941066c-c434-9592-c0ff-a5bbab3e3089.png)

1Password 側でもパスキーが追加されている。

![07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16369/5ee53541-5bd4-f632-0162-b0bd9cef55e1.png)

### 3. パスキー認証を試す
macOS の Web ブラウザで一度 GitHub からサインアウトして再サインインしようとすると、1Password の `Sign in with a passkey` 表示が出るので `Sign in` を押せば何も入力することなくサインインが完了した。

![08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16369/d2cb6222-e414-9893-ce77-d33a516f9064.png)

### 4. 他デバイスからのパスキー認証を試す
macOS で作成したパスキーが iOS の 1Password アプリに同期されていることを確認する。

![09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16369/662d9241-38cb-7f96-9cf7-ae8af0f06cf1.png)

iOS Safari から GitHub にアクセスして `Sign in with a passkey` を押すだけでサインインできた。

![10_11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16369/f0b0acd5-55b9-dd42-ae53-86e8119bb28e.png)

## 所感
パスキーの生成から他デバイスでの認証まで、詰まることなくかなり簡単にできた。

利用者側として必要なものはおおよそ揃っていると感じたので、1Password でパスワード管理をしている人は使ってみたら良いのではないか。
【RPA展開#01】トップダウンとボトムアップ？～壮大なポエムの始まり～

# はじめに
みなさんこんにちは。husuiです。
UiPath（ユーアイパス）[^0]というRPA[^1]の会社で若干業務よりの人として[働いていました（過去形）。](https://qiita.com/husui/items/b047615d56f0a0cfe014)
[^0]: https://www.uipath.com/ja
[^1]: Robotic Process Automationの略です。

今回は`私見的RPA展開メソドロジー`の話です。[自爆スイッチ](https://qiita.com/husui/items/40d02dd236b4812014a1 "【気分は自爆スイッチ】UiPathのロボットを物理ボタンで実行したい！")の話ではないです。ごめんなさい。

技術（テクノロジー）のことは私よりも他の皆さんの方が詳しいと思います。
なので私はRPAツールの展開についての方法論（つまりメソドロジー）について私見をつらつら書きたいと思います。[^2]
[^2]:最近この「テクノロジー」「メソドロジー」という概念を認識しました…お恥ずかしい。

まだ体系立てておらず、自分の思考の整理の意味も兼ねて記事を書くつもりです。
たぶん`ポエム`になっちゃうかもしれません。なので皆さんにとっては読みづらいかもしれません。

一通り書き終わった後で全体を俯瞰して体系立ててみたいと思います。

:::note warn
注意
本記事はあくまで個人的見解を元とした内容となっております。所属団体の公式見解ではございませんのでご了承くださいね！
:::

# なぜこのテーマ？
それは、**前職にてシステムの狭間で苦労している業務現場の方々を多く見て、その方々を救いたいと以前から思っていたから**です。

私はUiPathに入社する以前に、某金融会社の現場業務改善のプロジェクトに携わっていました。
しかしそれは、よくあるバックエンドシステムの開発…ではありません。
事業予算やシステム仕様の都合上、システム対応できず、手作業を強いられている現場の業務改善です。
そこには様々な複雑な業務がたくさんありました。
そしてそれら大変な業務を毎日着実にこなす業務の人たちがたくさんいました。

私は様々な部門の様々な人たちとオンラインまたはオフラインでヒアリングをしました。

私はそこで彼ら、彼女たちが脳内に持つ、または体に染み付いた専門的な知識の幅広さと深さに驚きました。
この事業を支えているのは、まさに現場を知り尽くしている彼ら、彼女たちなのだと実感しました。
![rpameth0102.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3329659/8c48a3f7-bb16-9d7c-5602-95f7cfa7b877.jpeg)
また同時に私は、日々の業務のつらさや愚痴も聞くことになりました。
- システム企画開発部門は、自分たちの要望を聞き入れてくれない。
- いつもシステム機能開発の優先度が高い物は、売上施策関連ばかりで、コスト施策はあとまわし。
- 手作業のマニュアル作りも大変でほとんど人依存になっている。
- そんな中業務担当者が不足気味であり誰もがパンク状態となっている。
- レポートで扱う数字は重要なものが多く間違いが許されないためストレスが大きい。

私はすぐにこれらのネガティブ要素を排除すべきだと直感しました。
そうすれば、業務現場の方々のパフォーマンスが上がり、余力が生まれ、攻めと守りの両方の活動を行うことができ、事業全体がさらに内側から活性化すると思いました。

そのためには、専門部隊が構築する高度なシステムよりも、自分たちで構築するRPA等ツールが適しているのは明白でした。
彼ら、彼女たちがそれらのツールを使いこなせるようになってほしいと強く思うようになりました。

そんな中偶然UiPathから私に声がかかりました。

# RPA展開の様々なかたち
といってもRPA等ツール展開を会社で始める、もしくは始まるパターンは何種類もあります。
以下挙げてみますが、もしかしたら他にもあるかもしれません。
1. 現場業務担当者が自発的に使い始めるパターン
1. 情シスとかの管理部門がコスト削減等の施策案として採用するパターン
1. 会社のリーダーシップが経営目標・施策案の一つとして採用するパターン

![rpameth0103.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3329659/c8b00fcd-c969-3962-c448-bd34b8c5c390.jpeg)
1.と3.はとてもわかりやすいパターンですよね。
`ボトムアップ`と`トップダウン`の典型的なアプローチです。

1.のボトムアップは極端に言ってしまうと、
現場の日々の業務への　**「怒り」**　が原動力となって、誰かが行動を起こすパターンです。
これは一時的局所的にRPAツールの活用は盛り上がりますが、やがて予算面、体制面の壁にぶつかる未来が待っています。

3.のトップダウンは極端に言ってしまうと、
株主や他社の目を意識した会社上層部からの　**「命令」**　が原動力となって、誰かに役割がふってくるパターンです。
これは予算面、体制面の整備は急速に行われますが、やがて中身が伴わずに形骸化・空洞化する未来が待っています。

2.はボトムアップでもトップダウンでもない一番難しいパターンかもしれません。
現場の「怒り」がどこにあるのか、上層部の理解をどのようにして取ればいいのか、両方を気にしながら行動していかなければなりません。


# こんなだらだらした感じで次回に続く…
こうやって書いてみると、`「結局RPAツールをどうやっても広められないじゃん」`って思ってきてしまいました…
ですが、みなさんもすでに知っているかもですが`上記1.2.3.どれも必要`だと思うんですよね。
次回以降もうちょっと整理しながら書いてみたいと思います。
たぶん長く続きます。そして終わらないかもしれません（爆）

個人的には、政治よりも現場レベル活動のほうが優先度が高くかつ好きなので、1.のボトムアップ施策寄りになってしまうかもですが…

続編はこちらです。

https://qiita.com/husui/items/c4601656fed7c874257d


:::note info
まだ視野が狭くレベルが低い私見なので、ぜひ皆様からのアドバイスコメントよろしくお願いいたします。
ディスられると凹むのでお手柔らかにお願いします…
:::
M2macでmanimがインストールできない

M2Macのvenv上で以下のエラーに遭遇
```
...
manimpango.c:773:10: fatal error: 'cairo.h' file not found
      #include "cairo.h"
               ^~~~~~~~~
      1 error generated.
      error: command '/usr/bin/clang' failed with exit code 1
      [end of output]
  
  note: This error originates from a subprocess, and is likely not a problem with pip.
  ERROR: Failed building wheel for manimpango
  Building wheel for pycairo (pyproject.toml) ... error
  error: subprocess-exited-with-error
  
  × Building wheel for pycairo (pyproject.toml) did not run successfully.
  │ exit code: 1
  ╰─> [12 lines of output]
      running bdist_wheel
      running build
      running build_py
      creating build
      creating build/lib.macosx-13-arm64-cpython-311
      creating build/lib.macosx-13-arm64-cpython-311/cairo
      copying cairo/__init__.py -> build/lib.macosx-13-arm64-cpython-311/cairo
      copying cairo/__init__.pyi -> build/lib.macosx-13-arm64-cpython-311/cairo
      copying cairo/py.typed -> build/lib.macosx-13-arm64-cpython-311/cairo
      running build_ext
      'pkg-config' not found.
      Command ['pkg-config', '--print-errors', '--exists', 'cairo >= 1.15.10']
      [end of output]
  
  note: This error originates from a subprocess, and is likely not a problem with pip.
  ERROR: Failed building wheel for pycairo
Failed to build manimpango pycairo
ERROR: Could not build wheels for manimpango, pycairo, which is required to install pyproject.toml-based projects
```

## 解決法
1.まず以下の公式のRequirementをインストールしたか確認

https://docs.manim.community/en/stable/installation/macos.html

2.以下のページで言われてることをやったが、解決しなかった。

https://github.com/ManimCommunity/ManimPango/issues/92

この間に
`brew install Cython`
を実行

3.pkg-configをインストール。

最初のエラーをよく見ると` 'pkg-config' not found.`とある。
よって
`brew install pkg-config`
を実行したのちに
`pip install manim`を行ったらうまくインストールできた。
脅威検知のログ分析テクニック

# 目次
[1.はじめに](#1-はじめに)
[2.攻撃者からのアクセス](#2-攻撃者からのアクセスのリスク)
[3.脅威分析で攻撃者からのアクセスを見つける](#3-脅威分析で攻撃者からのアクセスを見つける)
[4.参考 URL](#4-参考URL)
[5.おわりに](#5-おわりに)

# はじめに
企業へは、攻撃者からアクセスされるという脅威が常にあります。
そのため、当ブログでは Microsoft Entra ID（以前の Azure Active Directory） や Microsoft Sentinel のサインインログからの脅威検知テクニック（サインインログからの判断方法）を紹介します。

# 攻撃者からのアクセスのリスク
「不正アクセスとは、本来アクセス権限を持たない者が、サーバや情報システムの内部へ侵入を行う行為です。その結果、サーバや情報システムが停止してしまったり、重要情報が漏洩してしまったりと、企業や組織の業務やブランド・イメージなどに大きな影響を及ぼします。
 インターネットは世界中とつながっているため、不正アクセスは世界中のどこからでも行われる可能性があります。」（[総務省](https://www.soumu.go.jp/main_sosiki/joho_tsusin/security/basic/risk/06.html)）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3555809/a6bb816f-060d-f2f5-f677-82b1a7211672.png)

そのような不正アクセスを防ぐためにも、怪しいサインインのログの判断方法を紹介していきたいと思います。

# 脅威分析で攻撃者からのアクセスを見つける
ここからが本題となります。
下記からのアクセスがあれば、不正アクセスだと判断する材料の1つになると考えられます。

### 突然古い Browser・OS
OS（現時点）であれば、Windows 11 や iOS 16 などが新しいです。
Browser（現時点）であれば、Chrome 115 や Mobile Safari 16.6 です。
普段新しい Browser・OS を使用しているユーザーが突然古い Browser・OS の使用を検知した場合は、怪しいアクセスかもしれません。

### 見慣れない国（移動時間も考慮）や様々な国から
該当のサインインがあった時間と直前のアクセスの時間が、移動した時間を考慮しても無理がある場合は注意が必要です。また、短期間の中で、複数の国からアクセスがある際は、不審性が高いと思われます。
IPアドレスなどの影響で、自分がアクセスしている場所とは異なる場所からのサインインと検知される可能性ももちろんあります。VPN の使用等によって、Location が実際いる場所と異なる場合もあります。
ですので、あくまでも判断材料の1つです。
しかしそうでない場合（例えば、日本からのアクセスとアメリカからのアクセスの時間差が3時間未満等）は脅威の可能性があります。普段と IPアドレスが異なる場合は、特に詳しく調べたほうがいいと思います。

### パスワード・サインインともに何度も失敗
パスワードとサインインが失敗していると、攻撃者がアクセスを試しているという判断材料の1つになります。しかし、普通にユーザー自身が失敗している可能性ももちろんあります。ですので、攻撃者かユーザーかの分け目は、IPアドレスです。普段利用しているものでない場合、またテナントで使用しているものでない場合は注意が必要です。
普段使用していない ISP（Internet Service Provider）からのアクセスも判断材料の１つです。ISP とは、インターネット接続に必要なインターネットプロバイダーのことです。NTT docomo や au 等であれば一般的なものですので、そこまで不審ではありません。逆に日本にいるユーザーなのに、海外の ISP を使用している等は疑ってかかり、調査を進めてもいいと思います。
![image.png](https://www.ntt.com/content/dam/nttcom/hq/jp/business/services/network/internet-connect/ocn-business/bocn/knowledge/img/archive15_thum01.png)
IPアドレスのスコアや使用している ISP は [IPInfo](https://ipinfo.io/) から調査できます。
また、[Virus Total](https://www.virustotal.com/gui/home/url) を使用してみるのもいいと思います。マルウェアが含まれているかどうかの判定ができます。


# 参考URL
https://www.soumu.go.jp/main_sosiki/joho_tsusin/security/basic/risk/06.html
https://learn.microsoft.com/ja-jp/azure/active-directory/authentication/how-to-authentication-methods-manage
https://learn.microsoft.com/ja-jp/azure/sentinel/overview
https://www.ntt.com/business/services/network/internet-connect/ocn-business/bocn/knowledge/archive_15.html
https://ipinfo.io/
https://www.virustotal.com/gui/home/url

# おわりに
今回は、脅威を防ぐための、ログからの脅威の判断方法を紹介しました。
紹介した判断材料は、いくつかが組み合わさることでより危険性が高いものと判断することができます。
この記事が読者様のお役に立てれば幸いです。
Xcode 15 でCocoaPodsを利用したプロジェクトをビルドしたら"DT_TOOLCHAIN_DIR cannot be used to evaluate LIBRARY_SEARCH_PATHS, use TOOLCHAIN_DIR instead"が発生した。

# 現象
Xcode15にアップデートしたのち、ビルドをすると以下のエラーが発生しました。

``` 
DT_TOOLCHAIN_DIR cannot be used to evaluate LIBRARY_SEARCH_PATHS, use TOOLCHAIN_DIR instead
``` 

読み取ると
デフォルトのツールチェーンの場所を指す変数```$DT_TOOLCHAIN_DIR```を```$TOOLCHAIN_DIR```に変更したようです。プロジェクト/ターゲットが```$DT_TOOLCHAIN_DIR```を使用している場合は、```$TOOLCHAIN_DIR```に置き換える必要があります。

# 解決法
下記のスクリプトをpodfileに追記します。

```ruby:podfile
post_install do |installer|
	xcode_base_version = `xcodebuild -version | grep 'Xcode' | awk '{print $2}' | cut -d . -f 1`
    # 既存のスクリプトなどで以下が記載されている場合、↑の変数だけ追加すればOK
	installer.pods_project.targets.each do |target|
		target.build_configurations.each do |config|
			# Xcode 15以上で動作します(if内を追記)
			if config.base_configuration_reference && Integer(xcode_base_version) >= 15
				xcconfig_path = config.base_configuration_reference.real_path
				xcconfig = File.read(xcconfig_path)
				xcconfig_mod = xcconfig.gsub(/DT_TOOLCHAIN_DIR/, "TOOLCHAIN_DIR")
				File.open(xcconfig_path, "w") { |file| file << xcconfig_mod }
			end
		end
	end
end
```

その後、podコマンドで各ライブラリを更新してください。
```
pod install
```

# 引用元
こちらに解決方法が丸々載っていました。

https://developerinsider.co/fix-xcode-15-dt_toolchain_dir-cannot-be-used-to-evaluate-library_search_paths-use-toolchain_dir-instead/
PL-900 Microsoft Power Platform Fundamentals(和名:マイクロソフト パワー プラットフォームの基礎) 合格まで

**受験者本人のレベルと学習環境**

Power Platform初心者。入社後、社内のPower Platform研究チームに所属し、Power BIで社内のスキル見える化という作業に着手しながら、Power BIを弄り、他案件や他のチーム員が弄っていたPower AppsとPower Automateを見よう見まねしながら、受験勉強し始めました。

**受験までの流れ**

2月9日(木) ：「Microsoft Power Platform Virtual Training Day: 基礎」にご参加
2月15日(水) ：PL-900 : Microsoft Power Platform Fundamentals 試験対策がメールに届く。

自社作業のため、忙しく本格的に試験勉強はしてなかったが、時間がある度に、power BIやpower AppsとPower Automateを実際に弄るように努力しました。(他のチーム員が制作したアプリなども参考に勉強させていただきました。)

4月頃から時間の余裕がある度に
１．PL-900 : Microsoft Power Platform Fundamentals 試験対策の動画を見ました。
２．MS　Learnを勉強ました。
３．U-demyの「PL-900（Microsoft Power Platform 基礎） 模擬問題集※日本語版」の問題集1－5までを2周しました。
４．復習として「PL-900 : Microsoft Power Platform Fundamentals 試験対策」の動画をもう一回見ました。

5月1日　PL-900に無事合格しました！:v:

**PL-900とは？**
<details>
1.出題範囲:マイクロソフト パワー プラットフォームのビジネス価値について説明する (20-25%)<br>
マイクロソフト パワー プラットフォームの基本コンポーネントを特定する (10-15%)<br>
Power BI の機能を示す (10-15%)<br>
Power Apps の機能を実証する (20-25%)<br>
Power Automate の機能のデモンストレーション (15-20%)<br>
補完的なマイクロソフト パワー プラットフォーム ソリューションのデモンストレーション (15-20%)<br>
2.問題数:40問前後
3.試験時間は45分間(かなり短めです！)
4.合格ライン ：（700点/満点は1000点）
5.受験費用 :¥12500→¥0(マイクロソフト社開催の「Microsoft Power Platform Virtual Training Day: 基礎に申込み後、参加)
</details>
参考：https://learn.microsoft.com/ja-jp/credentials/certifications/exams/pl-900/

**Microsoft　Learning紹介**
[Microsoft Power Platform のビジネス バリューについて説明する](https://learn.microsoft.com/ja-jp/training/modules/introduction-power-platform/)
[Microsoft Power Platform の基本コンポーネントを特定する](https://learn.microsoft.com/ja-jp/training/modules/introduction-common-data-service/)
[Microsoft Power Apps を使用してアプリケーションを構築する方法についての説明](https://learn.microsoft.com/ja-jp/training/modules/introduction-power-apps/)
[Microsoft Power Automate を使用した自動化の構築についての説明](https://learn.microsoft.com/ja-jp/training/modules/introduction-power-apps/)
[Microsoft Power BI の機能について説明する](https://learn.microsoft.com/ja-jp/training/modules/introduction-power-automate/)
[補完的な Microsoft Power Platform ソリューションについての説明](https://learn.microsoft.com/ja-jp/training/modules/introduction-power-virtual-agents/)

**受験感想**
受験範囲が広かった(Power PlatformのPower BI、Power Apps、Power Automateの細かい知識を知る必要があります。)ので受験勉強に３週間以上の時間がかかりました。
受験時間が短めであるため、受験の試験形式に慣れる必要があります。(問題文は長いほうで時間も短めであったため、早めに問題を問う練習が必要でした。)
試験形式も単純に知識があれば問えるベストプラクティスを聞くため、ケーススタディのような試験形式にもなれる必要がありました。
しかしながら、Udemyで問題文を問うことと実際に弄ってみて機能を覚えることとMS learnを学習すれば問題なく合格できました。

**その他参考にしたサイト**

**勉強したUdemy講座**
[PL-900（Microsoft Power Platform 基礎） 模擬問題集※日本語版](https://www.udemy.com/course/pl-900microsoft-power-platform/)

では、皆様！PL-900の合格まで頑張りましょう！ファイトです！:writing_hand::clap:
Obedient Cat writeup

# Obedient Cat
###### tags: `PicoCTF` `General Skills` `2021`

お試しで投稿してみました。

## 問題
>このファイルには丸見えの状態の(暗号化されていないとも言える)flagが入っています。

>This file has a flag in plain sight (aka "in-the-clear").

問題サイト：[PicoCTF](https://play.picoctf.org/practice)
配布されたファイル：flag

## 解答
catコマンドでファイルの中身を見てやると問題文にある通りflagがそのまま入っている。

```
$cat flag
picoCTF{s4n1ty_v3r1f13d_1a94e0f9}
```

これが解答となる。
**picoCTF{s4n1ty_v3r1f13d_1a94e0f9}**
読書の秋：エンジニアのための読書のすすめ

エンジニアとしてのキャリアを築いていく中で、技術的なスキルや知識はもちろんのこと、情報の読解力やコミュニケーション能力も非常に重要です。これらの能力を磨くための方法として、日常的な読書の習慣を持つことがおすすめです。以下、読書がエンジニアにもたらすメリットを深掘りしていきます。

1. ドキュメントの読解力向上
情報の取捨選択: 技術的な仕様やエラーメッセージを理解するためには、文章の中の要点を捉える力が必要です。小説やエッセイを読むことで、複数の情報の中から本質的な部分を抽出するトレーニングができます。

複雑な概念の理解: 技術書や学術論文は、一読してすぐに理解するのが難しいことが多いです。しかし、小説や歴史書などを読むことで、異なる背景や文脈の中での情報の結びつけ方を学べます。

2. ソースコードの質向上
言葉の選び方: 読書を通じて、言葉に対する感覚や表現のバリエーションを豊かにすることができます。これにより、ソースコードのコメントやドキュメンテーションを書く際に、適切な言葉を選ぶ力がつきます。

ロジックの構築: 物語やエッセイには、論理的な展開が隠されています。これを追うことで、プログラムのロジックを組み立てる際の思考の整理がしやすくなります。

3. コミュニケーション能力の向上
相手の視点を理解: 読書を通じて、人々の考え方や背景知識、価値観を学ぶことができます。これにより、チームでの作業や顧客とのコミュニケーションがスムーズになります。

自分の意見の表現: 読書を続けることで、自分の考えを言葉にする力がつきます。これは、プレゼンテーションやミーティングでの発言時に大変役立ちます。

まとめ
エンジニアとしてのスキル向上のためには、コードだけでなく、読書を通じた言葉の力も大切にしなければなりません。日常的に様々なジャンルの本を読むことで、多角的な視点を持つことができ、それがエンジニアとしての質を高める手助けとなります。読書の習慣を持つことで、技術者としての幅が広がることを体感してみてください。
ウイングアーク１ｓｔ株式会社のインターンシップに参加したお話

<p>ウイングアーク１ｓｔ株式会社のインターンシップに参加してきました。<br>インターンシップを通してアウトプットする大切さを学んだので振り返りながら感じたことなどをまとめてみました。</p>
<h2>インターンシップ参加の目的</h2>
<p>オンラインでのチーム内での会話の取り方や課題解決をすることで社会にどう価値を提供しているのかを肌で感じ、エンジニアとして働く解像度を上げたいと思い応募しました。<br>　今までハッカソンにチーム開発を１０回ほど経験した中で、自分たちが満足するものを創ることがゴールで使用してくださる人の気持ちまで考えて開発することはありませんでした。<br>　人事部の南様からインターンシップの内容を聞いた際に、創ることに対する価値提供を考えることが目的であると伺ったので、お客様の気持ちに立って考えることを経験したいと思い参加しました。
<h2>概要</h2>
<p>期間：９月１９日から２２日まで４日間</p><br>
<p>場所：オンライン(zoom)</p><br>
<p>使用ツール：<br><a href="https://www.dejiren.com/">[dejiren|クラウドサービスを自由に繋ぐチャット型iPaSS</a><br>
<a href="https://miro.com/ja/">Miro<a></p>

<p>チーム：４人＋メンター（武島様、丸田様、藤本様）</p>
<p>スケジュール:</p>
    <dl>
      <dt>１日目</dt>
          <dd>会社説明</dd>
        <dd>dejirenの製品説明</dd>
<dd>UX研修</dd>
<dd>課題説明・実施</dd>
<dd>社員の方と座談会</dd>
    <dt>２日目</dt>
      <dd>課題実施</dd>
<dd>レビュー会</dd>
    <dt>３日目</dt>
<dd>課題実施</dd>
<dd>レビュー会</dd>
    <dt>４日目</dt>
<dd>成果発表・振り返り</dd>
    </dl>

<h2>取り組んだこと</h2>
<p>「<strong>ユーザーの困っていることを解決する</strong>」という課題に対してUXを意識してユーザーにどう答えるかをチームで話し合い課題解決に取り組みました。<br>　１．課題解決をするためにチームの方針、ゴールを決める<br>　２．課題に対する要因を洗い出す<br>　３．ユーザーストーリーマップでユーザーとサービスのやり取りを明確にし、機能の優先順位を決める<br>　４．ワイヤーフレームに落とし込み機能が必要なのかを確認<br>　５．ワイヤーフレームからウォークスルーを繰り返しブラッシュアップ（レビューも踏まえて）<br>　６．ブラッシュアップした解決方法を成果発表</p>

<h2>学んだこと</h2>
<h4>沢山会話をする（アウトプットする）</h4>
<p>　解決に対するアプローチに対して言葉や理解の違いでメンバー内での認識にずれが生じました。お互いが理解していると思っていても解釈の仕方で全く違う認識になると気づきました。私は普段聞く側に立つことが多いので初めは話すことに勇気がいりましたが、認識のずれや自分の思いを伝えることはチーム開発で大事だと学びました。</p>
<h4>メモを取る</h4>
<p>　沢山会話をしていても前提知識にずれがあったり、振り返った際に何を話していたのかを忘れることが多くありました。座談会で「メモを取って作業記録として残しながらも言語化できるからやってみたら？」というアドバイスを頂いたので実践したところ、メンバーとの共通認識にも繋がりメモをとる大事さを体験できて今後も沢山メモを残そうと思いました。</p>
<h4>自己視点ではなくお客様視点</h4>
<p>　新しい機能を追加することだけを考えていましたが、それがお客様にとって本当に必要な機能なのか、満足するのかというところまでを考えずに進んでいた部分もありお客様の立場に真剣に入り込んで考えることが大事だということを学ぶことができました。</p>
<h2>心残り</h2>
<h4>チーム方針を早い段階で決める</h4>
<p>　１日目に課題に対する要因を話し合っていた中で、最終的にチームがどこに向かっているのかがわからなくなり違和感がありました。２日目に１時間以上チーム方針を明確化できたことで以降の作業で立ち止まった際にゴールからずれることなくスムーズに作業ができました。今後チーム開発をする際は初めに話し合うことで目的からずれない開発をしていきたいです。</p>
<h4>相づち、感謝を伝える</h4>
<p>　メンバーが相づちを沢山して聞いてくれる場面がよくありました。オンラインという環境でも実際に会って話ているような気分になり話す側としてとても心地よかったです。また、「ありがとう」「助かる」という感謝の気持ちを沢山言ってくれるメンバーで会話がしやすい環境に恵まれました。私も、普段から感謝の気持ちを伝えていこうと改めて感じました。</p>
<h2>インターンを踏まえて</h2>
<p>私の中でエンジニア＝技術がゴリゴリ書けることが求められると思っていました。今回、お客様の課題解決を行い、技術よりもお客様にどう価値提供し社会に貢献するか考えることが大事だと学びました。考えても考えても終わりはない。<strong>「開発者は頭が千切れるまで思考を投下する」</strong>。UX講座から学んだことを４日間実践して千切れるまではできませんでしたが、思考を投下して課題解決を体験することができました。メンバーにも恵まれとても充実した４日間でした。メンバーの皆さん、ありがとうございました。</p>
<h2>謝辞</h2>
<p>　４日間という短い期間ではありましたが、今後の就活を考える上で気づきが沢山得られ、貴重な体験をすることができました。インターンシップの存在を知らせてくださった長南様、面談をしてくださった南様、インターン期間中につきっきりで面倒を見てくださった武島様、丸田様、藤本様、製品について詳しく教えてくださった大畠様、レビュー会で本質的なアドバイスをしてくださった橋田様、エンジニアとしての心構えを教えてくださった崎本様、最後の発表をご清聴頂いた皆様、このようなインターンの機会を用意していただいた全ての皆様、本当にありがとうございました。</p>
引数が複数あるときのInvoke周りの書き方（C#で

# 目的
完全な備忘メモです。

# コード
``` C#
public delegate void DelegateUpdateForm(string param1, string param2);
private void UpdateForm(string s1, string s2)
{
    if (this.InvokeRequired)
    {
        this.Invoke(new DelegateUpdateForm(UpdateForm),new object[] { s1, s2 });
        return;
    }

    DateTime dt = DateTime.Now;

    this.label1.Text = s1;
    this.label2.Text = string.Format("{0:HH時mm分ss秒fff} {1}", DateTime.Now, s2);
}
```

# コード説明
タイマーやらタスクで別スレッドで動かしているやつから、フォーム上の何かを更新するときに、複数値を渡した上で、スレッドセーフに更新したいときにするやつ。

# コード　その２
ラムダ式もあるよってコメント頂いたので追加です！（感謝）

``` C#
private void UpdateForm(string s1, string s2)
{
    if (this.InvokeRequired)
    {
        this.Invoke(() => this.UpdateForm(s1, s2));
        return;
    }

    DateTime dt = DateTime.Now;

    this.label1.Text = s1;
    this.label2.Text = string.Format("{0:HH時mm分ss秒fff} {1}", DateTime.Now, s2);
}
```

# REFERENCEs
https://qiita.com/screwyscrew/items/73944d831e0c634f4fcc

# さいごに
お疲れ様でした！
New Relicアップデート情報：ワイルドカードを使ったサービスレベルのクエリ設定が可能に！

# 概要
　New Relicのサービスレベル管理は、サービスレベル指標( Service Level Indicator : SLI )を APM サービスやブラウザアプリと関連付けると、New Relic はいくつかの典型的な SLI とその NRQL のクエリを提案します。また、NRQL　を使ったカスタマイズにも対応しており、柔軟な設定が可能です。しかし、これまでは単一属性の集計にのみ対応していたため、複数の属性を合計した SLI の設定には対応していませんでした。
　2023年6月のアップデートでは、SLI のクエリでワイルドカード(%)が使用可能になりました。この機能を用いることで、送受信（transmit、 receive）やステータスコード（２XX、３XX、４XX、５XX）等を含む複数の属性を集計して SLI を設定することが可能となります。

:::note info
このアップデートの詳細はこちら。
[New Relic アップデート(2023年6月)](https://newrelic.com/jp/blog/nerdlog/new-relic-update-202306 "New Relic アップデート(2023年6月)")
[New Relic アップデート一覧](https://newrelic.com/jp/blog/nerdlog/new-relic-update "New Relic アップデート一覧")
:::

:::note info
[New Relic株式会社のQiita Organization](https://qiita.com/organizations/newrelic)では、新機能を含む活用方法を公開していますので、ぜひフォローをお願いします。
:::

# ワイルドカード（%）使い方
　SLI をカスタマイズする場合は、**Add service level** 画面の「 **Customize SLI** 」から設定が可能です。
![Customize_SLI.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3043202/844a240c-24ac-a085-6386-495e0bbe20ab.png)
　ワイルドカードは、**Event** と **Metric** どちらのデータでも使用が可能です。今回は Prometheus で収集したコンテナの送受信パケットのMetric データを使ってワイルドカード(%)を試してみましょう。
　Metric データを使用する場合は、属性の候補が多くなるため、選択肢の中に目的の属性が表示されないケースがあります。そのため **Query Your Data** の **Data explorer** で使用する属性を確認しましょう。
![スクリーンショット 2023-09-25 1.48.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3043202/e5bd61ad-cf90-f8cb-5bcd-df634175b215.png)
　コンテナの送受信パケット数は、``container_network_receive_packets_total`` と　``container_network_transmit_packets_total`` の2つ属性の合計です。
![container_network_receive_packets_total.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3043202/cfc8223d-5a3b-c377-9ca6-63e7063cebae.png)
![container_network_transmit_packets_total.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3043202/722c897b-09c5-459d-04a0-b199510d849c.png)
　それぞれの属性の共有項目を残しワイルドカードに置換するため、``Select`` に ``container_network_%_packets_total`` を入力します。設定の候補には表示されないため、直接入力して設定してください。
![container_network_%_packets_total.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3043202/42c86a91-0991-bba1-81ec-a2735e541e17.png)
ワイルドカードは、 valid event と good responses、 bad responses のどちらでも使用可能です。上記の例では ``container_network_receive_errors_total`` と ``container_network_transmit_errors_total`` をワイルドカードを利用して ``container_network_%_errors_total`` を設定しています。
![スクリーンショット 2023-09-25 2.40.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3043202/8672d8c5-ab08-8cab-aae2-40db00b8d81a.png)
　このように NRQL を使って SLI を設定できるとチャートが表示され、設定内容が確認できます。

# まとめ
　2023年6月のアップデートにより、サービスレベル指標（SLI） のクエリでワイルドカード(%)が使用可能になり、より柔軟なSLIの設定ができるようになりました。今回は、Prometheusのメトリクスを使用しましたが、カスタムイベントやカスタム属性でアプリケーションから収集した独自のデータを使ったサービスレベルの設定に利用できます。例えば、処理Aと処理Bの処理結果を集計してサービスレベルに設定するという活用方法です。この新機能を活用して、サービスレベル設定の活用の幅をさらに広げてみてください！


:::note info
このアップデートの詳細はこちら。
[New Relic アップデート(2023年6月)](https://newrelic.com/jp/blog/nerdlog/new-relic-update-202306 "New Relic アップデート(2023年6月)")
[New Relic アップデート一覧](https://newrelic.com/jp/blog/nerdlog/new-relic-update "New Relic アップデート一覧")
:::

:::note info
[New Relic株式会社のQiita Organization](https://qiita.com/organizations/newrelic)では、
新機能を含む活用方法を公開していますので、ぜひフォローをお願いします。
:::
クラウドレンダリングを試してみた

GeForce NOWのようなグラウド上でパワフルなゲームやアプリを動かす方法としてUEのPixel StreamingやTencentCloudのCAR等があります。
重たい処理があるアプリをサーバー上のVMで動作させ、その映像をブラウザ等でリアルタイムに受け取ってアプリを操作するという概念です。

今回はTencentCloudのCAR（クラウドレンダリング）を試してみました。
動作確認の用に簡易に動かせるTestモードがありますので、それで動作させるところまでをこの記事のゴールとします。

## TencentCloud CARのアーキテクチャ
![PtTx648_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/300377/8c20e435-9605-ac3b-853b-975a435d9c3a.jpeg)
(参照元:https://www.tencentcloud.com/jp/products/car)

## アプリケーションのアップロード
- TencentCloudのConsoleにログイン
- Cloud Application Renderingにアクセス
- My ApplicationsからCreate applicationをクリック
- Windows用アプリケーションか、又は、Android用アプリケーションをアップロード
![スクリーンショット 0005-09-22 13.38.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/300377/604658f2-01e3-58e9-e968-dd299b11d9f1.png)
![スクリーンショット 0005-09-22 13.38.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/300377/eb4f218d-d250-7f76-23a2-c2c0ed37d85f.png)
![スクリーンショット 0005-09-22 13.41.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/300377/49f80049-9cdb-0b36-4354-826ff5de5748.png)

## プロジェクトの設定
- ProjectsからCreate projectをクリック
- Projectを作成
![スクリーンショット 0005-09-22 14.24.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/300377/d3592f6c-b7a8-e9bc-9707-58eca7bc596f.png)
![スクリーンショット 0005-09-22 14.24.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/300377/5cf1dda2-94b7-2124-68c1-272e81c02b24.png)
## ライセンスの割り当て
- Concurrency packsからBuy concurrency packをクリック
- ライセンスを選択して購入(今回はTokyoリージョンを購入してみました）
- 先ほど作成したプロジェクトへライセンスの割り当て
![スクリーンショット 0005-09-22 14.39.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/300377/275c4e39-9706-5497-694b-910b47d3b0c5.png)
![スクリーンショット 0005-09-22 14.39.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/300377/9cd1e841-a0e3-1695-4f73-308aadcfd5d5.png)
![スクリーンショット 0005-09-25 8.42.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/300377/dc5ae627-a04e-9b05-6cd6-3a3ef0252a00.png)
## テスト実行
- プロジェクト一覧から先ほどのプロジェクトのOperation項目のうちTestをクリック
- テスト用のURLが発行
- URLにアクセスしてアプリケーションの実行
![スクリーンショット_0005-09-25_8_42_42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/300377/9bf151dd-f806-137c-52f1-2c00cad8d555.png)
![スクリーンショット_0005-09-25_8_44_00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/300377/ddccb52a-37db-b4bf-c1c4-594ad959ae7e.png)

以上の数ステップで簡単にクラウドレンダリングを試す事ができます。
詳細は[公式ドキュメント](https://www.tencentcloud.com/jp/document/product/1158/49612)をご覧ください。

## 活用事例や比較等
PixelStreamingやTencetCloud CARの活用事例や製品の比較は[こちら「Pixel StreamingやTencent Cloud CARの活用」](https://jp.vcube.com/sdk/blog/pixel_streaming_tencent_cloud_car)に詳しく掲載してますのでぜひご覧ください。

## 最後に
[**Tencent Cloudに関するお問い合わせはこちらから**](https://jp.vcube.com/form-inquiry-md06-tencent.html)
NLP keywords extraction library using a pre-trained model - 組み込みAI セルフサービス型デジタル共創体験(DSCE)

# 組み込みAI セルフサービス型デジタル共創体験(DSCE)とは

[組み込みAI セルフサービス型デジタル共創体験](https://qiita.com/trtrbohz/items/356a5a4b66624b2c94a2)に記載しておりますが、現在STT(speech-to-text)、TTS(test-to-speech)、NLU(natural-language-understanding)等のAIがサーバーに接続しなくても組み込んで利用することが可能となりました。

その情報がこちらの[サイト](https://dsce.ibm.com/)、DSCE([Digital Self-Serve Co-Create Experience](https://dsce.ibm.com/);"組み込みAI セルフサービス型デジタル共創体験"？)にて紹介されております。

今回はそのDSCEの中から、「NLP keywords extraction library using a pre-trained model」 の実施方法を説明します。
※個人的な利用は無償ですが、商用利用は有償となります。

# 今回は 「NLP keywords extraction library using a pre-trained model」 
https://dsce.ibm.com/wizard/try/results/embed-nlp-keywords-container-pt#try
今回もPlotly社製のOSSウェブフレームワークDashを使いNLP( Natural Language Processing (自然言語処理)) を利用したウェブアプリを構築します。

# 1. 前提
* ターミナル環境
mac : ターミナルを使います。[ココ](https://support.apple.com/ja-jp/guide/terminal/apd5265185d-f365-44cb-8b09-71a064a42125/mac) を見てターミナルを起動できるようにしてください。
windows : powershellを使います。[ココ](https://learn.microsoft.com/ja-jp/powershell/scripting/install/installing-powershell-on-windows?view=powershell-7.3) を見てpowershellを起動できるようにしてください。
* リソース取得
下のURLにアクセスしリソースを取得します。
https://github.com/IBM/dsce-sample-apps/tree/main
※コード改変＆プルリクをするのであれば「git clone」コマンドを使うのですが、今回はソースコードの入手が目的ですので以下の様に Zip 形式でリソースを入手します。
![スクリーンショット 2023-08-12 22.28.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682574/e97bd8bc-0767-b52e-9914-d11c0af69259.png)
リソース取得後、zipファイルを展開すると以下のようなフォルダ構成になっていると思います。今回はその中の[sentimet-analysis]配下にあるリソースを使用します。

# 2. 手順
# 2.1. [keyword-extraction]フォルダに移動
* zipファイルを解凍した場所を起点として[keyword-extraction]フォルダに以下のようにして移動します。

      cd dsce-sample-apps-main/keyword-extraction

# 2.2. 必須ライブラリのインストール

      pip3 install -r requirements.txt

# 2.3. インデックス作成
以下のコマンドを使い[hotel_review]フォルダにあるサンプルデータからインデックスを作成します。
※この操作にはマシンスペックにもよりますが、15分強時間がかかります。

     python3 build_index.py

# 2.4. アプリ実行

     python3 search.py

# 2.5. Access the local application
ブラウザを開き、[localhost:8050](localhost:8050) にアクセス
以下の様な画面が表示されます。

1. 画面上部のテキスト欄に検索したいキーワードを入力
    キーワードが複数ある場合には "," で区切ってください。
2. テキスト欄右の虫眼鏡ボタンをクリック
3. サンプルのホテルレビューが解析され、検索条件に合致したレビューデータが表示されます。

![スクリーンショット 2023-09-23 0.32.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682574/23b65838-4fd6-7f6d-fb71-58c45f586661.png)



参照：[NLP keywords extraction library using a pre-trained model](https://dsce.ibm.com/wizard/try/results/embed-nlp-keywords-container-pt#try)
javaScriptのコピーについて

javaScriptのコピーについて、少しつまづいた所があったから、備忘録として記録する。
意外と今までなんとなくで対応していたなと思ったので、今回を機に色々調べてみた。

# javaScriptの型について
javaScriptは動的型付け言語ですが、データに対してちゃんと型はある。
分類としては、**プリミティブ型・オブジェクト型**に分けることができる。

以下、例を書いておく。

プリミティブ型
- String
- Number
- BigInt
- Boolean
- Undefine
- Symbol
- Null

オプジェクト型
- Object
- Array
- function
- Date
など

プリミティブ型以外は全てオブジェクト型となるため、様々な例が考えられる。

### プリミティブ型とオブジェクト型の違い
プリミティブ型とオブジェクト型の違いとして、値の格納方法がある。
プリミティブ型は、**変数に値を直接保存**する方法に対して、オブジェクト型は、**変数にオブジェクトへの参照を保存**している。

つまり、オブジェクト型は、変数にオブジェクトへの参照（値が保存されているメモリのポインタ）が格納されているため、コピーした際他の変数にも影響してしまう。

**プリミティブ型**
```javascript:index.js
let person = 'name'
let new_person = person
new_person = 'new_name';

console.log(person, new_person)

//出力値
name new_name
```

値が直接コピーされるため、新たなメモリに保存し、変数同士が独立している。

**オブジェクト型**
```javascript:index.js
let person = {name: 'name', age: 3};
let new_person = person
new_person.name = 'new_name';

console.log(person, new_person)

//出力値
{ name: 'new_name', age: 3 } { name: 'new_name', age: 3 }
```

参照先がコピーされているため、元の変数にも影響が出ていることがわかる。

# シャローコピーとディープコピー
object型には二つのコピー方法がある。
まずはシャローコピーについて。

### シャローコピー
シャローコピーとは、コピー元のオブジェクトと同じ参照をコピーするため、参照場所のデータを共有することになる。
そのため、コピーした値を変更するとコピー元にも影響が出る可能性がある。

```javascript
let person = [
    1, 
    {name: 'name2', age: 4}, 
    {name: 'name3', age: 5}
];

let new_person =[...person]
//参照先のデータを変更
new_person[1].name = 'new_name'
console.log(person, new_person)

//出力値
[ 1, { name: 'new_name', age: 4 }, { name: 'name3', age: 5 } ]
[ 1, { name: 'new_name', age: 4 }, { name: 'name3', age: 5 } ]
```

次に、配列のネストされていない要素を変更すると、コピー元は変更されずに出力される。

```javascript
let person = [
    1, 
    {name: 'name2', age: 4}, 
    {name: 'name3', age: 5}
];

let new_person =[...person]
//
new_person[0] = 3
console.log(person, new_person)

//出力値
[ 1, { name: 'name2', age: 4 }, { name: 'name3', age: 5 } ] 
[ 3, { name: 'name2', age: 4 }, { name: 'name3', age: 5 } ]
```

つまり、シャローコピーは深さ1のみをコピーし、ネストされた値を共有しないためには、要素の中身も再起的にコピーすることで完全に独立したコピーを作成しなければならない。

### ディープコピー
ディープコピーとは、参照場所のデータを共有しない、完全に独立したコピーとなる。
そのため、コピーした値を変更するとコピー元にも影響が出る可能性は基本的にはない。

```javascript
let person = [
    1, 
    {name: 'name2', age: 4}, 
    {name: 'name3', age: 5}
];

let new_person = JSON.parse(JSON.stringify(person))
new_person[1].name= 'new_name'

console.log(person, new_person)

//出力値
[ 1, { name: 'name2', age: 4 }, { name: 'name3', age: 5 } ] 
[ 1, { name: 'new_name', age: 4 }, { name: 'name3', age: 5 } ]
```

# まとめ
今回はシャローコピーとディープコピーについてまとめてみた。
意外と基礎が疎かになっていることを最近発見してきているので、こういった知識をこれからなんとなくではなく、説明できるくらいには知識をつけていきたいと思う。
NLP entities extraction library using a pre-trained model - 組み込みAI セルフサービス型デジタル共創体験(DSCE)

# 組み込みAI セルフサービス型デジタル共創体験(DSCE)とは

[組み込みAI セルフサービス型デジタル共創体験](https://qiita.com/trtrbohz/items/356a5a4b66624b2c94a2)に記載しておりますが、現在STT(speech-to-text)、TTS(test-to-speech)、NLU(natural-language-understanding)等のAIがサーバーに接続しなくても組み込んで利用することが可能となりました。

その情報がこちらの[サイト](https://dsce.ibm.com/)、DSCE([Digital Self-Serve Co-Create Experience](https://dsce.ibm.com/);"組み込みAI セルフサービス型デジタル共創体験"？)にて紹介されております。

今回はそのDSCEの中から、「NLP entities extraction library using a pre-trained model」 の実施方法を説明します。
※個人的な利用は無償ですが、商用利用は有償となります。

# 今回は 「NLP entities extraction library using a pre-trained model」 
https://dsce.ibm.com/wizard/try/results/embed-nlp-entities-container-pt#try
今回もPlotly社製のOSSウェブフレームワークDashを使いNLP( Natural Language Processing (自然言語処理)) を利用したウェブアプリを構築します。

# 1. 前提
* ターミナル環境
mac : ターミナルを使います。[ココ](https://support.apple.com/ja-jp/guide/terminal/apd5265185d-f365-44cb-8b09-71a064a42125/mac) を見てターミナルを起動できるようにしてください。
windows : powershellを使います。[ココ](https://learn.microsoft.com/ja-jp/powershell/scripting/install/installing-powershell-on-windows?view=powershell-7.3) を見てpowershellを起動できるようにしてください。
* リソース取得
下のURLにアクセスしリソースを取得します。
https://github.com/IBM/dsce-sample-apps/tree/main
※コード改変＆プルリクをするのであれば「git clone」コマンドを使うのですが、今回はソースコードの入手が目的ですので以下の様に Zip 形式でリソースを入手します。
![スクリーンショット 2023-08-12 22.28.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682574/e97bd8bc-0767-b52e-9914-d11c0af69259.png)
リソース取得後、zipファイルを展開すると以下のようなフォルダ構成になっていると思います。今回はその中の[sentimet-analysis]配下にあるリソースを使用します。

# 2. 手順
# 2.1. [entity-extraction]フォルダに移動
* zipファイルを解凍した場所を起点として[sentiment-analysis]フォルダに以下のようにして移動します。

      cd dsce-sample-apps-main/entity-extraction

# 2.2. 必須ライブラリのインストール

      pip3 install -r requirements.txt

# 2.3. アプリ実行

     python3 entity_extraction_pii_demo.py

# 2.4. Access the local application
ブラウザを開き、[localhost:8050](localhost:8050) にアクセス
以下の様な画面が表示されます。

1. 画面上部のテキスト欄に文章を入力
    起動時にはデフォルト文章が記載されていますが、この欄にご自身で文章を入力することも可能です。
2. [Get entities]ボタンをクリック
3. 文章が解析され、Entity分析結果が表示されます。分析結果は[Entity Type][Entity Text][Score(%)]として解析された結果が表示されます。

![スクリーンショット 2023-09-22 23.55.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682574/53e2b76e-4610-7523-8d31-7f0489ad246f.png)



参照：[NLP entities extraction library using a pre-trained model](https://dsce.ibm.com/wizard/try/results/embed-nlp-entities-container-pt)
サーバーサイドのデザインパターン[Singleton Patternの章]


# はじめに
1. Singleton Patternの定義と特性
Singleton Patternとは、特定のクラスのインスタンスが一つしか存在しないことを保証し、そのインスタンスへのアクセスポイントを提供するデザインパターンです。
主に設定管理やログ管理、キャッシュなどの用途で利用されます。
2. Singleton Patternの利点
- リソースの節約
インスタンスが一つしか存在しないため、リソースを節約できます。
- 一貫性の確保
シングルトンを通じてグローバルな状態を管理できます。
- コントロールの集中
インスタンスの生成を制御できるため、特定の処理を中央化できます。
3. PythonでのSingleton Patternの実装
```python
class Singleton:
    _instance = None

    def __new__(cls):
        if cls._instance is None:
            cls._instance = super(Singleton, cls).__new__(cls)
        return cls._instance


singleton1 = Singleton()
singleton2 = Singleton()

assert singleton1 is singleton2  # これはTrueになります
```
上記のコードは、__new__メソッドをオーバーライドしてSingleton Patternを実装した一例です。
singleton1 と singleton2 は、同じインスタンスを参照します。
この実装はスレッドセーフではないため、マルチスレッド環境で利用する場合は、ロックを使用して同時アクセスを制御する必要があります。
### 注意点
多スレッド環境では、同時に複数のインスタンスが生成されないよう注意が必要です。
グローバルな状態を持つため、テストが困難になる可能性があります。
### まとめ
Singleton Patternは、特定の種類のオブジェクトが一つしか存在しないことを保証し、それにアクセスするためのグローバルポイントを提供します。このパターンは、リソースの節約、一貫性の確保、コントロールの集中の利点を有していますが、テストの困難さや多スレッド環境での利用に注意が必要です。
コールバックでのsaved_change_to_ と will_save_change_to

## はじめに
スクールにて、コールバックの設定に手間取り、その際調べることで挙動の違いを理解したつもりなので、同じようなことにハマった人のためになればいいなと、健忘録として残します。

### 開発環境
Rails 6.1.7.4
ruby 3.0.1

### 目的
管理者が、最後の１人のとき、管理者が０人とならないように権限の編集を制限する。
つまり、１人もいなくなっちゃ困るので、必ず１人は権限を在籍させたい訳です。

### 最初に試したこと（失敗したこと）
- Qiita記事や調べてまずは下記のように設定
```rb
def admin_cannot_update
  if User.where(admin: true).count == 1 && self.saved_change_to_admin == [true,false]
    throw :abort
  end
end
```
adminに設定されたユーザーがデータベースに1人だけであり、かつ対象のオブジェクトのadminカラムをtrueからfalseに変更しようとしたとき、　thow :abortで更新を中止する。と設定

内容的には合っているはずなのだが、いくら試してみても最後の1人の権限を外せてしまう。
ログを見るときちんと呼び出されているにも関わらず、ロールバックが起きない。

指定の仕方が間違っているのかと、コードを修正したりするもどうにもならなかった。

### メソッドを調べる 
根本的に間違っているのでは？　と使用しているメソッドを調べ直す

**saved_change_to_attribute(attr_name)**
> 前回の保存時の属性への変更を返します。属性が変更された場合、結果は元の値と保存された値を含む配列になります。　※参考　RailsAPI

理解力の足りない自分には？？？となってしまったが、要するに、変更を検知、保存はされる。保存された後に何かを設定するメソッド？（素人解釈です）

このメソッドでは、どうやっても（現状の自分の理解力）編集はされてしまう！と結論に至る。

### 保存前に動くメソッドを探す
**will_save_change_to_attribute?(attr_name, options)**
> 次回保存するときにこの属性は変更されますか?
このメソッドは、検証時やコールバックの前に、次の呼び出しでsave特定の属性が変更されるかどうかを判断するのに役立ちます。 ※参考　RailsAPI

保存しようとすることを検知するっぽいぞ！これだ！と早速使用

```rb
def admin_cannot_update
  if User.where(admin: true).count == 1 && will_save_change_to_admin? && !admin
    throw :abort
  end
end
```
データベースにadminが１人だけであり、かつadminを、admin権をなくそうとしているときに更新を中止させる。

変更検知だけだと、管理者が1人になったら編集ができなくなり、!adminがないと付与もできなくなる。

## 結論
 **saved_change_to_attribute(attr_name)**
- 変更がすでに保存された後に実行されるコールバック内で使用する。**変更が保存された後**に処理を行う（つまり変更はしてしまう）ため、変更されたら何か処理を行うという場合に使用する。
※使用用途は今すぐには思いつかない


**will_save_change_to_attribute?(attr_name, options)**
- 変更が保存される前に実行されるコールバック内で使用する。**変更が保存される前**に何らかのチェックや操作を行いたい場合に使用する。


追記
対象のオブジェクトを示すselfは、上記２つのメソッドについては、暗黙的に指定してくれており、いらないようです。