OmniAICreator/Qiita-1.07M huggingface dataset:
Palo Alto NetworksのPanorama/GlobalProtectの運用Tips

# 初めに
ここでは自分がPanorama/GlobalProtectに触れて気づいた点などを残しておきます。

# Q. Panorama上でADのグループマッピングを使いたいけどユーザー一覧から選択できない！出てこない！

## A. ADグループのDistinguished Nameを直接指定してやる必要があります
:::note warn
事前にADに対しエージェントを導入してUser MappingとGroup Mappingを設定しておく必要があります。
`DEVICE`→`User Identification`にある`User Mapping`と`Group Mapping Settings`にて設定できます。
デフォルトの`Group Mapping`の更新間隔は3600秒(1時間)だったと思うので、一時的に60秒とかにしておくとテストが楽になると思います。
:::

ADにアクセスできるPCで`dsquery group -name "グループ名"`を叩くと出てくるのがDistinguished Name(以下DN)です。
これをUSER/USER GROUPの箇所に直接入れるとグループ内のユーザーを一括して処理出来ました。
GlobalProtectのPortal/Gatewayの両方で適用できたことを確認済みです。
ほかの場所でも同じようにできるはずです。

# Q. 設定項目がところどころ空白でよく分からない！

## A. 英語にするとちゃんと表示されます
翻訳がクソなのか、MTUなどの設定が日本語状態では空白になり正しく表示されません。
右下の言語設定から英語に設定するとすべての項目が正しく表示されるようになります。

# Q.GlobalProtectのクライアントの最新版はどこで入手できるの？

## A. 基本的には`PANORAMA`→`Cloud Services`→`Configuration`から`GlobalProtect App Activation`で最新版をアクティベートすれば最新のものをユーザーに配信できます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3314743/d0e17c03-b7f5-b404-d2c8-cf813584b379.png)

:::note info
最初に`PANORAMA`→`Device Deployment`→`GlobalProtect Client`から`Check Now`をクリックして更新しないと出てこないかもです。
:::

ですが、この画面で新しいバージョンをアクティベートするとコミット&プッシュせずとも即座にアクティベートされてしまいます。
動作テストしてからユーザーに利用させたい場合、毎回各プロファイルでアップデートを禁止してコミット&プッシュしからてテストして許可して配布して…とやるのは結構面倒です。

若干裏技味のある方法になりますが、[公式のS3ストレージ](https://pan-gp-client.s3.amazonaws.com/)から同じ物を入手することが出来ます。
自分は[ダウンロードツール](https://github.com/kouhei-ioroi/gpclient-downloader)を自作してますが、普通にURL叩いた方が早いです。

https://github.com/kouhei-ioroi/gpclient-downloader

上記からダウンロード、少数の端末でテストして問題がないことを確認してから本番でアクティベートすると問題が少なくてみんな幸せになりますね。

# URLカテゴリ判定が間違ってるぽいので特定URLだけ通信を許可したいけどどこで設定すればいいのかわからん！

## A. `POLICIES`→`Security`→`Pre Rules`から地道に追っていきましょう

> ぶっちゃけほとんどの環境では`OBJECTS`→`Custom Objects`→`URL Category`から`White-List`に追加するだけでOKだと思います。が、そうじゃない可能性もあるので一応全手順を書いておきます。

特に重要なのはPROFILE列です。
各ルールのPROFILE列にマウスオーバーすると、`Profile Group:????`といった感じでどのグループが紐づいているのかが表示されます。
HTTP/HTTPSなど、それっぽいルールに対応するグループ名が分かったら、`OBJECTS`→`Security Profile Groups`を開き、該当のグループをクリックします。
すると、
- Antivirus
- Anti-Spyware
- Vulnerability Protectiion
- URL Filtering
- File Blocking
- Data Filtering
- WildFire Analysis

の7つのプロファイルでどれが使用されているのかが表示されます。

URLブロックを解除する場合は`URL Filtering`を変更すればよいので、`OBJECTS`→`Security Profiles`→`URL Filtering`を開き、該当のプロファイルをクリックします。

おそらくほとんどの環境ではWhite-Listが`alert`もしくは`none`で登録されていると思いますので
`OBJECTS`→`Custom Objects`→`URL Category`から`White-List`に該当のURLを追加してコミット&プッシュしてください。

:::note warn
White-Listやそれっぽいルールが無かったら頑張って作って紐づけてください
:::

以上でアクセスが許可されるようになります。
Streamlit 初心者講座

## 目次
- [概要](#概要)
- [使用例](#使用例)
- [環境構築](#環境構築)
- [よく使うもの](#よく使うもの)
- [実際に作ってみよう](#実際に作ってみよう)
- [ポートフォリオ or 自分の作りたいものを作ってみよう](#ポートフォリオ-or-自分の作りたいものを作ってみよう)

## 概要
**Streamlit**(ストリームリット)とは、PythonでWebアプリが作れるフレームワーク
特に、データサイエンスの分野で使われているらしいです。

https://streamlit.io/

**強み**
・爆速でWebアプリが作れる
・デプロイも爆速
・学習コストが低い

**弱み**
・独創性を出しづらい
・日本語の解説が少ない

## 使用例

Blenderチュートリアル動画検索アプリ

https://pablender.streamlit.app/

[github](https://github.com/kpab/paBlender)


## 環境構築
vscodeのターミナルで以下のコマンドを実行
```zsh
pip install streamlit
```

次にapp.pyというファイルを作り、そこに以下を入力してみましょう
```app.py
import streamlit as st

st.title('タイトルだよ')
```

次にターミナルで以下のコマンドを打ちます
```zsh
streamlit run app.py
```
このコマンドで、streamlitがローカルサーバーを立ち上げ自動でブラウザが開き、Webアプリが表示されます
こんな感じの画面が出ていたらOK!
![スクリーンショット 2024-10-06 21.19.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3862120/e7f1464a-7a3f-274d-6379-8e0d1efca101.png)

## よく使うもの
続いて、よく使うコンポーネントを紹介します。

https://qiita.com/pani_py/items/d1bcb4a487da0a81158b

他は公式ドキュメントをご参照ください

https://docs.streamlit.io/develop/api-reference

## 実際に作ってみよう

https://qiita.com/pani_py/items/3c1825e5013316410e29

## ポートフォリオ or 自分の作りたいものを作ってみよう
作りたいものがない方は、ポートフォリオを作ってみましょう
自分の研究について紹介するページを作るのもアリです。
俺的Ghidra設定

俺的Ghidra設定を備忘録として書いておく。

以下を参考にしている。

[リバースエンジニアリングツール Ghidra実践ガイド](https://book.mynavi.jp/ec/products/detail/id=116258)

# Tool Optionsの設定
`Edit` → `Tool Options` を開き、以下の設定をする。

## ハイライト
シンボルをクリックすると同じ文字列がハイライトされるようにする。

`Listing Fields` → `Coursor Text Highlight` を選択し、`Mouse Button To Activate` を`MIDDLE`から `LEFT` に変更。

## キーバインド
リファレンス検索のキーバインドを設定しておく。

`Key Bindings`から

- `Find References To Symbol` → `Meta` + `Shift` + `F`
- `Set Pre comments` → `Ctrl` + `Shift` + `C`

（`Find References To Symbol`を`X`にする人が多いようだが、私はなるべくデフォルトを崩したくない派。ただし、`Find References To` と同じキーバインドにするのがポイント）

## Listing Fieldsの行間

ディスアセンブルしたアセンブリの行間を揃えるために、バイトコードの折り返しをなくす。

`Listing Fields` → `Bytes Field` から、`Maximum Lines To Display`を3から1にする。

## Decompileウィンドウでコメントを表示

`Decompiler` → `Display` から、`Display EOL comments`、`Display PLATE comments`、 `Display POST comments`にチェック。



# フォントの設定

Listing Displayから、フォントをJetbrains Monoにする。また、Decompile > Displayから、フォントをJetbrains Monoにする。フォントサイズは両方とも12ptにする。

# XRefの設定

適当な`XREF`をListing Window上で探して、クリックする。カラム名をクリックして、`Add/Remove Columns` をクリックする。`Function Name` と `Function Signature` にチェックをつける。

# GolangAnalyzerExtensionの設定
GNU Disassembler, Machine Learningも一応入れとく

# FIDBとData Typeの追加
以下の2つを追加する。手順はそれぞれのリポジトリに書いてある通り
https://github.com/AllsafeCyberSecurity/Ghidra_FIDB
https://github.com/AllsafeCyberSecurity/Ghidra_Data_Type

# Ghidrathonの設定（最近やめた）

Ghidra 11.3でPyGhidraがサポートされるようになったため、使用しないことにした。
ABC374Eを解いた


筆者はレート700前後の茶色コーダ

当日解けなかったABC374のE問題を解いていく

https://atcoder.jp/contests/abc374/tasks/abc374_e

# 実装コード

解を適当に決め打ちで入れて
実現できるか否かで二分探索する

この問題のキモは
「工程iの中で最小のコストで満たす機械の個数」を求めることで、
該当する場所は、SiがBi個以下、もしくはTiがAi個以下のどちらかが成り立つようで、
その範囲を全探索すればいいようだ

```python:main.py
import sys
from math import ceil
def rI(): return int(sys.stdin.readline().rstrip())
def rLI(): return list(map(int,sys.stdin.readline().rstrip().split()))
def rI1(): return (int(sys.stdin.readline().rstrip())-1)
def rLI1(): return list(map(lambda a:int(a)-1,sys.stdin.readline().rstrip().split()))
def rS(): return sys.stdin.readline().rstrip()
def rLS(): return list(sys.stdin.readline().rstrip().split())
def err(*args): print(*args, file=sys.stderr)

def can_product_value(w,N,X,dat):
    remain = X
    for i in range(N):
        A, P, B, Q = dat[i]
        cost = float("inf")
        for j in range(B):
            k = max(0,ceil((w - A*j)/ B))
            t = j*P+k*Q
            cost = min(cost,t)
        for k in range(A):
            j = max(0,ceil((w - B*k)/ A))
            t = j*P+k*Q
            cost = min(cost,t)
        if cost > remain:
            return False
        else:
            remain -= cost
    return True
def main():
    N,X = rLI()
    # A, P, B, Q = rLI()
    dat = [rLI() for _ in range(N)]
    l = 1
    r = 10**9+7
    i = 0
    while l<=r:
        w = (l+r)//2
        if can_product_value(w,N,X,dat):
            l=w+1
        else:
            r=w-1
    print(r)

if __name__ == '__main__':
    main()

```


# まとめ

ABC374Eを解いた、解の二分探索を実装した。

# 感想

問題のキモであった部分が思いつかず
時間内に解けなかったので今回解き直した
今後はE問題の精進が必要なようだ
[Streamlit入門] よく使うコンポーネントまとめ

## はじめに
Streamlitを使うと、PythonコードだけでWebアプリを作ることができます。
今回はよく使うコンポーネントをご紹介します。

- [st.title(), st.write()](#sttitle-stwrite)
- [st.text_input()](#sttext_input)
- [st.checkbox()](#stcheckbox)
- [st.selectbox()](#stselectbox)
- [st.radio()](#stradio)
- [st.number_input()](#stnumber_input)
- [st.button()](#stbutton)
- [st.image()](#stimage)

### サンプル
こちらがサンプルです

https://tutorialit.streamlit.app/

## st.title(), st.write()
```python
import streamlit as st

# -- タイトル、見出し、テキスト表示 --
st.title('タイトル')
st.header('見出し1')
st.subheader('見出し2')
st.write('これは文字列')
st.write(12345)
```
![スクリーンショット 2024-10-07 21.07.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3862120/4191ae64-c15b-82e1-21bd-34abdf448bd4.png)

## st.text_input()
テキスト入力を受け付けるためのコンポーネントです。フォームや検索バーに利用できます。
```python
text = st.text_input('名前を入力してください:')
st.write(f'こんにちは、{text}さん！')
```
![スクリーンショット 2024-10-07 21.11.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3862120/04537c9a-a209-a5c9-d384-6ab9cc66a732.png)

## st.checkbox()
チェックボックスを使って、オン/オフの選択が可能です。
```python
if st.checkbox('表示しますか？'):
    st.write('なにもないよ')
```
![スクリーンショット 2024-10-07 21.47.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3862120/84a03068-411f-8b6e-5bb3-bc87a2c3e584.png)

## st.selectbox()
ドロップダウンメニューで選択肢を提供することができます。
```python
option = st.selectbox(
    '何にする？', 
    ('ごはん', 'お風呂', '私')
)
if option == "私":
    st.write(f'あなたは {option} を選びました！お楽しみください。')
else:
    st.error("私にしなさい")
```
![スクリーンショット 2024-10-07 21.57.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3862120/2fc40518-8b06-521d-3b90-e4a0e423e366.png)



## st.radio()
複数の選択肢から1つだけ選べるラジオボタンです。
```python
gakka = st.radio("学科を選択してください",('物理','化学','数学'))
if gakka != '化学':
    st.warning("センスないわ")
else:
    st.write("素晴らしい")
```
![スクリーンショット 2024-10-07 22.05.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3862120/ecbf1820-b451-c028-a48c-cce23c8e20c9.png)

## st.number_input()
数値入力用のフィールドで、整数や浮動小数点数の入力を受け付けるコンポーネントです。
```python
weight = st.number_input('体重を入力してください')
if weight < 50:
    st.write("痩せすぎです。もっと食べましょう")
else:
    st.write("太り過ぎです。")  
```
![スクリーンショット 2024-10-07 21.42.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3862120/3db1e9d2-a368-b93b-5ce4-913f52e10579.png)


## st.button()
ボタンを作成し、クリックした際にアクションを実行できます。
```python
btn = st.button('自爆', type="primary")
if btn:
    st.write('自爆スイッチが押されました')
```

![画面収録-2024-10-07-21.22.36.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3862120/bc89e33d-7106-2102-a952-3554807813fa.gif)


## st.image()
画像を表示するためのコンポーネントです。URLから画像を表示できます。
```python
st.image('https://www.aoyama.ac.jp/wp-content/uploads/2018/02/visual_identity_img_02-1.png', caption='イーゴ君')
```
![スクリーンショット 2024-10-07 21.31.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3862120/313e6bfc-91cd-2353-75a7-3e675cb9a5a6.png)


## 最後に
この記事では、Streamlitでよく使うコンポーネントを紹介しました。これらのコンポーネントを使えば、すぐにでもインタラクティブなWebアプリを作成することが可能です。ぜひ試してみてください！
【DAY28】データ型について(2)

この記事は以下の記事の続きとなります。
[【DAY27】データ型について(1)](https://qiita.com/Nautilus1256/items/bdbcc5e4bbbb7484caf0)
## 浮動小数点型
### 2進数の小数点
10進数同様2進数にも小数点以下が存在します。
2^-1 = 0.5
2^-2 = 0.25
2^-3 = 0.125

これらを使用することで、整数型同様小数も2進数で表すことができます。しかし、これでは非常に小さい値を表すときに必要なビット数が大きくなってしまいます。

### 指数表記
非常に大きい、または小さい値を表す時には指数表記を使用することがあります。
例）1.5×10^25
この時、1.5の部分を仮数、10の部分を基数、25の部分を指数といいます。
仮数の桁が多ければ数値の精度が上がり、指数の桁が多ければ表現できる数字の範囲が広がります。
コンピュータは2進数で処理するため、基数は2となり、仮数と指数を2進数で表現することにより、ビット数を小さくすることができます。

### float型
例えば小数点型の1つであるfloat型は32ビットですが、1bitが符号部、8bitが指数部、23bitが仮数部として使用されています。

## null型
データが存在しないこと自体をデータとして扱う時にnullが使用されます。データがないという状態に対して処理を行う時にnullが必要になります。
例えばフォームの回答をした時に未入力(null)の欄があるなどです。
PyCon JP 2024に参加しました

## はじめに
先日[PyCon JP 2024](https://2024.pycon.jp/ja)に行ってきました。
弊社はシルバースポンサー、朝食スポンサーとして協賛しており、サンドイッチやノベルティを配っていました。
スポンサー枠で参加させていただいたので、感想を記事にまとめました。

![IMG_A394926817C6-1.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3748887/60e58958-5349-c95b-593e-73680936d74b.jpeg)


## 印象に残っているセッション
#### 5年分のツケを一気に払った話
https://2024.pycon.jp/ja/talk/VEECBQ

言語やサードパーティライブラリのバージョンアップデートについて、定期的に情報をキャッチアップする必要性を強く感じました。
また、テストコードの重要性を改めて実感しました。テストが整備されていることで、アップデート時のリスクが軽減され、安心してバージョンアップに臨むことができます。

#### ORM と向き合う
https://2024.pycon.jp/ja/talk/UTWBAL

ORMについて理解を深めることができました。
ORMを使用せずにNoSQLでオブジェクトデータモデルを永続化した場合との比較があり、ORMの必要性をわかりやすく理解できました。

（Pythonで[Prisma](https://www.prisma.io/orm)が使えるのは知らなかったです。）

#### SQLModel入門 〜クエリと型〜
https://2024.pycon.jp/ja/talk/MXKU77

FastAPIを勉強する中で気になっていたSQLModelについて、基礎からハマりどころ、注意点といった実践的な使い方まで知ることができてよかったです。モデルの型を定義するだけでマイグレーション、バリデーションまでしてくれるのは便利だと思いました。
PydanticとSQLAlchemyの良い部分を組み合わせた設計だけあって、使いやすさ、機能性が両立されているなと思いました。

#### Pythonによるイベントソーシングへの挑戦と現状に対する考察
https://2024.pycon.jp/ja/talk/DAH78A

イベントソーシングとCQRSについて知ることができてよかったです。
特にCQRSパターンの非正規化データについて、非常に勉強になりました。
私が普段使用しているLaravelでも、おそらくイベントとキューを使うと同じようなことが出来ると思うので、時間があるときに試してみようと思いました。

#### WEBアプリケーションにおけるAWS Lambdaを用いた大規模な非同期処理の実践
https://2024.pycon.jp/ja/talk/TPXKZ9

大量の非同期処理(メール送信)を、AWS Lambda、Amazon SQSなどを活用したアーキテクチャに移行した際の知見を共有していただきました。
また、プロダクションレベルで運用する際に考慮すべき非機能要件(データサイズ、冪等性、エラーハンドリング等)についても具体的に解説していただき、勉強になりました。
こちらも時間があるときに実践してみようと思いました。

## さいごに
2024年2月のPHPカンファレンス以来、久しぶりのオフラインイベント参加となりました。
PHPカンファレンスとは異なり海外の方が多く、セッションの半分ほどが英語で行われていたことに驚きました。
英語力があれば参加できるセッションの選択肢が広がっていたため、英語を勉強する重要性を改めて感じました。
今回のイベントで学んだことを業務に活かして行きたいです。
[Swift] UIScreen.mainを使わずに画面の明るさを設定する

## 背景
`UIScreen.main`がiOS17以降においてdeprecatedとなっていますが、`UIScreen.main.brightness`を用いない画面輝度の設定についての情報があまりなかったのでメモとして残しておきます。

## 結論
`windowScene.screen.brightness`を使おう

## サンプルコードと補足
画面輝度を調節するだけなのであまり意味はないですが、`windowScene`の取得を
`guard let windowScene = UIApplication.shared..connectedScenes.first as? UIWindowScene`
の形を避け、
`view.window?.windowScene`
の形をとっています。
(前者の実装だとiPadのマルチウィンドウ等、複数wIndowが存在する際に意図していないwindowを取得する可能性があるため)

```swift title:SampleViewController.swift
import UIKit

final class SampleViewController: UIViewController {
    private var windowSchene: UIWindowScene?
    private var defaultBrightness: CGFloat?

    // viewWillAppearまでviewがnilなので、このタイミングで実行
    override func viewIsAppearing(_ animated: Bool) {
        super.viewIsAppearing(animated)
        windowScene = view.window?.windowScene
        defaultBrightness = windowScene?.screen.brightness
    }
}

private extension SampleViewController {
    func changeBrightness(to value: CGFloat) {
        guard let value else { return }
        windowScene?.screen.brightness = value
    }
}
モダンJavaScriptについて学んだことをまとめる

以下のUdemyの講座を受講したので、モダンJavaScriptについて学んだ事をまとめる。

https://www.udemy.com/course/modern_javascipt_react_beginner/?couponCode=KEEPLEARNING

## モダンJavaScriptの特徴

### 仮想DOM
DOMを直接操作せずに、仮想DOM上で変更点の差分を算出し、差分のみDOMに反映する。

### パッケージマネージャ
npmなどのパッケージマネージャを使用。
依存関係の自動解決、import先が明確になる、パッケージの共有が簡単になるなどのメリットがある。

### ECMAScript
JavaScriptの標準規格。
ES2015(ES6)で機能追加が多くあり、アロー関数や分割代入、スプレット構文などが利用可能になった。

### モジュールバンドラ
開発時は複数のファイルでソースを管理し、本番用にビルドする際に依存関係の解決も含め、1つのファイルにまとめるためのもの。
Webpack、Viteなどがある。
コードの管理を容易にしつつ、パフォーマンスを向上できる。

### トランスパイラ
新しいJavaScriptの記法を古い記法に変換してくれるもの。
Babel、SWCなどがある。
レガシーブラウザへの対応のため。

## モダンJavaScriptの機能
知らなかった部分を中心にまとめる。

### 変数宣言
基本的に`const`を使う。
- `var`: 再宣言可能、上書可能
- `let`: 再宣言不可、上書可能
- `const`: 再宣言不可、上書不可、constで定義したオブジェクトはプロパティの変更が可能

### テンプレート文字列
バッククオートで囲んだ文字列内で$(変数名)とすると、変数の値を文字列内で展開できる。
```
const name = "クロード"
console.log(`私の名前は${name}です。`)

→ 私の名前はクロードです。
```

### アロー関数
関数の定義時は通常`function`を使うが、アロー関数を使って定義をすることもできる。
完全な糖衣構文ではなく、`function`を利用した場合と厳密には色々違うらしい。
```
// 通常
function func1(str) {
  return str
}
console.log(func1("test"))

// アロー関数
const func2 = (str) => {
  return str;
}
console.log(func2("test"))

// 引数が1つの場合は、引数の括弧を省略できる。
const func2 = str => {
  return str;
}

// 関数の中身が単一処理の場合は、returnと波括弧を省略できる。
const func2 = (num1, num2) => num1 + num2;
```

### 分割代入
オブジェクトの内容を一度に変数に代入できる。
```
// オブジェクトの場合
const myProfile = {
  name: "クロード"
  age: 18
}
const {name, age} = myProfile

// 配列の場合
const myProfile2 = ["クロード", 18]
const [name, age] = myProfile
```

### オブジェクトの省略記法
代入元と代入先が同じ名前の場合は、コロン以降を省略できる。
```
const name = "クロード"
const age = 18

// 通常
const myProfile = {
  name: name,
  age: age
}

// 省略記法
const myProfile = {
  name,
  age
}
```

### スプレッド構文
`...`を配列の前に記載すると、配列の内容を展開できる。
```
// 配列の展開
const arr1 = [1, 2]
console.log(...arr1)
→ 1 2

// 引数の展開
const sumFunc = (num1, num2) => num1 + num2
sumFunc(...arr1)

// 残りをまとめる
const arr2 = [1, 2, 3, 4, 5];
const [num1, num2, ...arr3] = arr2

// 配列のコピー
const arr4 = [1, 2]
const arr5 = [3, 4]

const arr6 = [..arr4, arr5]
```
Angularのmoduleとstandalone

以下の記事を参考にしてAngularを勉強していると、app.moduleなどが出てきたが、src/app以下にそのようファイルは存在しない

https://dev.classmethod.jp/articles/handson-doc-angularfirebase-todo-app/

どうやら、
最近のAngularプロジェクトでは、Angular 14以降の新しいバージョンで**Standalone Components**という新しい概念が導入され、従来のモジュール（`app.module.ts`）を使用しない構造のプロジェクトも作成可能になったようです。以下に、それぞれのケースについて詳しく説明します。

### **1. Standalone Componentsを使用したプロジェクト**
- Angularの最近のバージョン（Angular 14以降）では、**Standalone Components**の概念が追加されており、これによりモジュール（`NgModule`）を使わずにアプリケーションを構築することが可能になりました。
- この場合、`app.module.ts`は必須ではなく、代わりに各コンポーネントに必要な依存を直接インポートする形で、独立した（standalone）構造を持つことができます。

### **2. モジュールベースとスタンドアロンベースの違い**
- **モジュールベースの構造**:
  - 以前のAngularのデフォルトのやり方では、各コンポーネントは一つのモジュールに依存しており、アプリ全体の設定を行うために`app.module.ts`が使われていました。
  - `app.module.ts`で`NgModule`の設定をし、アプリ内で使用するモジュール（`BrowserModule`、`AngularFireModule`など）をまとめて管理していました。

- **スタンドアロンベースの構造**:
  - `Standalone Components`を使うと、各コンポーネントが独自に必要なモジュールを直接取り込むことができます。そのため、`app.module.ts`のような集中管理のモジュールファイルは不要です。
  - この構造では、アプリケーションのメインファイルとして`app.component.ts`や、設定ファイルとして`app.config.ts`が使われます。


### **4. 既存プロジェクトにモジュールを追加する方法**
- もし、従来の`NgModule`ベースの構造を使いたい場合、以下の手順で手動で`app.module.ts`を追加することができます：

  1. **`app.module.ts`を作成**：
     - `src/app`ディレクトリ内に`app.module.ts`ファイルを新規作成します。

  2. **基本的なモジュール設定を記述**：
     - 以下のコードはfirebase導入時の例

     ```typescript
     import { BrowserModule } from '@angular/platform-browser';
     import { NgModule } from '@angular/core';
     import { AppComponent } from './app.component';
     import { AngularFireModule } from '@angular/fire';
     import { AngularFireAnalyticsModule } from '@angular/fire/analytics';
     import { AngularFirestoreModule } from '@angular/fire/firestore';
     import { environment } from '../environments/environment';

     @NgModule({
       declarations: [AppComponent],
       imports: [
         BrowserModule,
         AngularFireModule.initializeApp(environment.firebase),
         AngularFireAnalyticsModule,
         AngularFirestoreModule,
       ],
       providers: [],
       bootstrap: [AppComponent],
     })
     export class AppModule {}
     ```

  3. **`main.ts`でモジュールを指定**：
     - `src/main.ts`で、`AppModule`を使ってアプリをブートストラップします。

     ```typescript
     import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
     import { AppModule } from './app/app.module';

     platformBrowserDynamic().bootstrapModule(AppModule)
       .catch(err => console.error(err));
     ```

### **まとめ**
- **`app.module.ts`が存在しない場合**、Angularの新しい構造である`Standalone Components`が使われている可能性が高いです。この場合、アプリ全体の設定は`app.config.ts`などを使用して行います。
- **`app.module.ts`を使用した従来の構造**が必要であれば、手動でファイルを作成して`NgModule`を定義することが可能です。
- Firebaseの設定は、新しい`Standalone Components`のスタイルであれば`app.config.ts`内で行い、従来の`NgModule`ベースであれば`app.module.ts`で設定します。

プロジェクトのニーズに応じて、どちらの方法を選択するか決めていくらしいです。最近のAngularプロジェクトではスタンドアロンの方法も推奨されていルようですが、従来のモジュール構造もまだ多くのプロジェクトで利用されています。
OMC230A

https://onlinemathcontest.com/contests/omc230/tasks/5176


$1840=2^4×5×23$ なので、少なくとも$N≧23$ではありそう。

まず試しに$N=23$から$1、2$を抜いた平均は、、、
$\frac{\Sigma_{k=3}^{23}k}{21}$

計算しなくても分母が$19$の倍数にならないことがわかった。

ということで、$N$は$2$つ除くと$19$の倍数にならないといけない。
したがって、$N=19m+2$ …①

①で$m=2(N=40)$の場合、
$\frac{\Sigma_{k=1}^{40}k}{38}=\frac{410}{19} (≦\frac{1840}{19})$
ここから$2$つ除かないといけないので違う。

$m=3(N=59)$の場合、
$\frac{\Sigma_{k=1}^{59}k}{57}=\frac{590}{19} (≦\frac{1840}{19})$
これも違うし、$\frac{1840}{19}$まではまだ遠い。

$m=10(N=192)$くらいで考えてみる。
$\frac{\Sigma_{k=1}^{192}k}{190}=\frac{192×193÷2}{190}=\frac{18528}{190}$

偶然だが、$\frac{1840}{19}$より少し大きい良い感じの値になった。
$2$つの値を足して128になる数を引けば良さそう。

問題は$N$の総和なので前後も確認する。

$m=9(N=173)$だと、
$\frac{\Sigma_{k=1}^{173}k}{171}=\frac{173×174÷2}{171}=\frac{15051}{171} (≦\frac{1840}{19})$

$m=11(N=211)$だと、
$\frac{\Sigma_{k=1}^{211}k}{209}=\frac{211×212÷2}{209}=\frac{22366}{209}$
$\frac{1840}{19}=\frac{20240}{209}$
$2$つの値を足して2126になる数を引けば良いが、$N=211$なので、そのような$2$数は存在しない。

したがって、$N=192$の場合のみ$\frac{1840}{19}$になり得る。
【Laravel】モックでzipファイルを返却する方法！

泉（[@izumin_0401](https://twitter.com/izumin_0401)）です。

今回は、Laravelのモックでzipファイルを返却する方法を解説します！

# ブログ記事はこちら

https://traveler0401.com/laravel-mock-zip/

# 【Laravel】モックでzipファイルを返却する方法

```php
public function mock()
{
    $zip      = new \ZipArchive;
    $zip_path = tempnam(sys_get_temp_dir(), 'zip');

    if ($zip->open($zip_path) === true) {
        // zipファイルにcsvファイルを入れてみる
        $csv = implode("\n", [
            'id,name',
            '1,izumi',
        ]);
        $zip->addFromString('sample.csv', $csv);
        $zip->close();
    }

    $zip_file = file_get_contents($zip_path);
    unlink($zip_path);

    $this->app->bind(\App\Services\HogeService::class, function () use ($zip_file) {
        return Mockery::mock(\App\Services\HogeService::class)
            ->shouldReceive('exec')
            ->andReturn([
                'status_code' => 200,
                'body'        => $zip_file,
            ])
            ->getMock();
    });
}
```
↑みたいな感じで、zipファイルを作成した後にMockeryを使ってzipファイルを返せばOK！

# まとめ
「application/zip」ってキモいよね。

ではまた。

# 最後に
暇つぶしに[Twitter](https://twitter.com/izumin_0401)と[ブログ](https://traveler0401.com/)もやってるので見てね。
【基本情報・応用情報】システム構成技術の信頼設計覚え方！

# はじめに
システム構成技術の信頼設計は似たような言葉が多く，覚えにくい印象があります．逆に，考え方さえ覚えてしまえば似たような言葉なので覚える手間が省けるということに気づきました！！！
ここで，わたしなりの覚え方と紹介しようと思います．

**もっとわかりやすい覚え方があれば教えてください🙏**

# 信頼設計の用語

### フォールトトレランス
**意味**：障害が発生しても機能を維持する能力，主要な構成要素を多重化することで実現できる．
**目的**：システムの可用性と信頼性を高める
**動作**：障害発生時に冗長コンポーネントが機能を引き継ぐ
**特徴**：システム全体の耐障害性が向上する
**例**：RAID構成のハードディスク、冗長電源

:::note info
**覚え方**
fault（障害）をtolerate（許容する）、つまり障害があっても耐えられる
:::

### フォールトアボイダンス
**意味**：障害の発生を事前に防ぐ設計手法
**目的**：障害の発生そのものを防ぐ
**動作**：高品質な部品の使用、厳格な品質管理、定期的な保守点検を実施
**特徴**：予防的アプローチによりシステムの信頼性を向上させる
**例**：航空機の定期点検、ソフトウェアの静的解析ツールの使用

:::note info
**覚え方**
fault（障害）をavoid（避ける）だから，そもそも障害が起きないようにする
:::

### フェールオーバー
**意味**：障害時に予備システムに自動切り替えする機能
**目的**：システムの可用性を維持する
**動作**：主システムの障害を検知し、自動的に予備システムに切り替える
**特徴**：ユーザーへのサービス中断を最小限に抑える
**例**：クラスタ構成のWebサーバー、冗長化されたデータベースサーバー

:::note info
**覚え方**
fail（障害）が起きたらover（乗り越えて）別のシステムに移る
:::

### フェールバック
**意味**：フェールオーバーにより切り替えられた要素（障害が起きた要素）を障害復旧後に元の状態にもどすこと
**目的**：システムを通常の運用状態に戻す
**動作**：障害が解決された後、予備システムから主システムへ処理を戻す
**特徴**：システムの負荷分散や運用効率を元の状態に戻す
**例**：修理が完了したメインサーバーへの処理の移行

:::note info
**覚え方**
元々の状態に**バック**する
:::


### フェールソフト
**意味**：障害時に**最小限**の機能を維持する仕組み
**目的**：障害時にもシステムの基本機能を維持する
**動作**：障害発生時に非重要な機能を停止し、核心的な機能のみを継続する
**特徴**：システムの完全停止を避け、部分的な機能提供を続ける
**例**：航空機の一部システム故障時の縮小運転モード

:::note info
**覚え方**
障害の影響をsoft（柔らかく・弱く）にする
:::

### フォールバック（縮退運転）
**意味**：障害時に、機能を縮小した不完全な状態も処理や稼動を継続させること
**目的**：障害時にも可能な限りサービスを継続する
**動作**：主要な機能や方法が使用できない場合、代替手段や簡易版の機能を提供する
**特徴**：完全な機能ではないが、ユーザーに最低限のサービスを提供し続ける
**例**：高速なデータベース検索が不可能な場合に、簡易検索機能を提供する

:::note info
**覚え方**
fall（落ちる・失敗する）時にback（後退・戻る）して別の方法を使う
:::

### フェールセーフ
**意味**：障害時，あらかじめ指定された安全な状態に誘導すること
**目的**：障害発生時にシステムと周囲の安全を確保する
**動作**：障害を検知すると、事前に定義された安全な状態にシステムを移行させる
**特徴**：安全性を最優先し、必要に応じて機能を停止する
**例**：エレベーターの停電時自動ブレーキシステム、原子炉の緊急停止システム

:::note info
**覚え方**
fail（障害）が起きてもsafe（安全）な状態を保つ
:::

## まとめ
障害が起きても機能を維持する：フォールトトレランス
障害が起きないようにする：フォールトアボイダンス

正常運転 → 障害発生 → フェールオーバー（予備システムに切り替え） → 障害復旧 → フェールバック（主システムに戻す）

障害発生時の対応の流れ：
フェールセーフ（安全な状態に移行）→ フェールソフト（最小限の機能を維持）→ フォールバック（縮退運転で代替手段を提供）→ 完全復旧

※状況に応じて、これらの対応を適切に選択・組み合わせる

:::note warn
IT用語は結局英語ゲー...
:::

## 覚え方まとめ
:::note info
**フォールトトレランス**
fault（障害）をtolerate（許容する）、つまり障害があっても耐えられる
:::

:::note info
**フォールトアボイダンス**
fault（障害）をavoid（避ける）だから，そもそも障害が起きないようにする
:::

:::note info
**フェールオーバー**
fail（障害）が起きたらover（乗り越えて）別のシステムに移る
:::

:::note info
**フェールバック**
fail(障害)前の状態に**バック**する
:::

:::note info
**フェールソフト**
fail(障害)の影響をsoft（柔らかく・弱く）にする
:::

:::note info
**フォールオーバー**
fall（落ちる・失敗する）時にback（後退・戻る）して別の方法を使う
:::

:::note info
**フェールセーフ**
fail（障害）が起きてもsafe（安全）な状態を保つ
:::

# 基本情報・応用情報記事

https://qiita.com/bearl27/items/48ea517e5debbff3b2e9

https://qiita.com/bearl27/items/c08be5f2a53fd3fb7b53

https://qiita.com/bearl27/items/e63a6fb14eba0067d940

https://qiita.com/bearl27/items/f8cf339e7f966291683d

https://qiita.com/bearl27/items/849c9400ae93608331e7
SAA試験対策【ストレージ編】

# 始めに
実務でminioを用いて自社規定のファイルサーバーを構築する案件に入った。minioはawsのs3に互換性があり、性能も今のところ気にしないレベルで高いので個人開発でも取り入れていきたいと思ってる。
そんな折、minioでawsの仕組みやコマンドを調べる機会が多くなってきたのでどうせならSAA取得に向けて勉強をしてみようと思った次第である。完全に個人のアウトプットです。

# 前提
- アプリ側実装（Rubyとか、react）１年ちょい
- Azure案件に半年関わってた
- 現在minioを用いてファイルサーバ構築中

## ストレージ周りの用語集
- AMI
ソフトウェア構成を記録したテンプレのこと。AmazonMachineImage。EC2インスタンスを作成するためのテンプレート（OS、メモリ、CPU）バックアップに使える。別リージョンにコピー可能。
- IAM
AWSリソースへのアクセスを安全に管理するためのサービス。Identity and Access Management。
- EC2
サーバー構築サービス。OSを乗せた仮想環境をクラウド上に作ることができる
- S3
クラウド型のオブジェクトストレージ
- DynamoDB
フルマネージドNoSQL

## S3とは（SimpleStorageService）
- 高い耐久性、容量無制限
- ファイルストレージと異なり、ディレクトリ構造を持たない
- メタデータ（付加情報）を定義できる
- 複数のAZに複製し、冗長性をもたせる（AZ、アベイラビリティゾーン。リージョン内のデータセンター単位）
- バージョニングやMFAのより誤作動を防ぐ
- 強い整合性を持つ

## S3の用途
- バックアップ
AWSのバックエンドサービス（EBSのスナップショットに使われる）
- データレイク
ビックデータを保存する容器のこと
- 静的コンテンツ
(HTML/CSS)のホスティング。（動的言語はEC2にホスティング）

## S3の構成要素
- バケット
保存領域のこと。一意の名称を持つ
- オブジェクト
データそのもの。一意のURLを持つ
- メタデータ
作成日時、サイズなど。どんな情報をもたせるかユーザーがカスタマイズする

## S3関係で試験でそうなとこ（個人感触）
- 耐久性と可用性の違い
耐久性はイレブンナイン（9が11桁並ぶくらい強固）だが可用性（ダウンタイムのリスクの低さ）は99.99%
- STANDARD > STANDARD-IA > ONEZONE-IAのレベル
`STANDARD-IA`はコールド層のような考え。読み取りで従量課金。
`ONEZONE-IA`は単一のAZのみで構成。安い代わりにそのAZが障害起きるときつくなる。
間を取ったINTELLINGENT-TIERINGもある。最初はSTANDARD。何もしないと該当ファイルは30日後にSIAに落ちる。
- Glacierの部分
アクセス頻度が低いデータのバックアップ。安価なアーカイブ。
速度が高速（1~5分）、標準（3~5時間）、バルク（5~12時間）のオプションがある。
Raspberryでstreamlitを勉強してみる①

**streamlitとは？　（個人見解）**
Web開発の経験がなくても、Pythonを知っていれば、Webサイトが作れるツール。
（コレ ↑ が、大きなメリットと思います。フロント技術は標準で充実しています）
では、デメリットを考えると…
　・多要素認証のような複雑な仕組みを作るのには不向きな感じ。
　・JavaScriptやCSSが使えない事による弊害 ＝ 凝った画面は作れない等
　・あらゆる処理がサーバサイドに寄る ＝ １つ１つの画面操作の動作が重い感じ
以上から、同時アクセスが集中しない簡易使い方であれば、アリな気がします。
（特にプロトタイプや営業活動等の見せる部分では、有効な手法と感じました）
※実際に実装してみましょう・・・

**フォルダやファイルの構成**
拡張性を意識して、少しプログラムを分割したサンプルを用意しています。
```diff_conf:構成
└── test
    ├── venv　（仮想用フォルダ）
    ├── main.py　（Streamlitを起動するファイル）
    ├── sidebar.py　（画面横のメニュー欄）
    ├── graph1.py　（折れ線グラフ）
    └── graph2.py　（散布図）
``` 
**準備作業**
sudo mkdir /test　（作業フォルダ作成）
cd /test　（カレント移動）
sudo python3 -m venv venv　（仮想環境の構築）
sudo chmod 777 -R /test　（権限をゆるく設定）
source /test/venv/bin/activate　（仮想環境の立ち上げ）
pip3 install streamlit
```diff_python:main.py　（streamlitで起動するプログラム）
import streamlit as st
from sidebar import sidebar_process
from graph1 import show_graph as gra1
from graph2 import show_graph as gra2
if __name__ == "__main__":
    gra, val = sidebar_process()
    if gra == "折れ線":
        gra1(val)
    else:
        gra2(val)
``` 
```diff_python:sidebar.py　（サイドバーメニュー）
import streamlit as st
def sidebar_process():
    opt1 = ["折れ線", "散布図"]
    graf = st.sidebar.selectbox("グラフ選択", opt1)
    opt2 = ["いろは", "かき"]
    valu = st.sidebar.selectbox("値選択", opt2)
    return graf, valu
``` 
```diff_python:graph1.py　（折れ線グラフ）
import streamlit as st
import pandas as pd
import numpy as np
def show_graph(val):
    if val == "いろは":
        chart_data = pd.DataFrame(np.random.randn(50, 3), columns=["い", "ろ", "は"])
    else:
        chart_data = pd.DataFrame(np.random.randn(50, 2), columns=["か", "き"])
    st.line_chart(chart_data)
``` 
```diff_python:graph2.py　（散布図）
import streamlit as st
import pandas as pd
import numpy as np
def show_graph(val):
    data = pd.DataFrame({
        'weight': np.random.normal(50, 20, 30),
        'height': np.random.normal(50, 20, 30)
    })
    if val == "いろは":
        data['class'] = np.random.choice(['い','ろ','は'], 30)
    else:
        data['class'] = np.random.choice(['か','き'], 30)
    st.scatter_chart(data, x='weight', y='height', color='class')    
``` 

**テストしてみる**
（仮想環境のまま）streamlit run main.py　（streamlitが実行されます）
その後、パソコンより「http://（RaspberryのIPアドレス）:8501」へアクセスします。
streamlitらしい画面が表示されますよね？
Ctrl＋C キーで、streamlitを停止します。
deactivate　（仮想を終了します）

**streamlitをサービス起動する方法**
Apacheを使うと、そのままサービス起動するようになるのですが、streamlitの場合、systemdにてサービス登録する事で、電源を入れた時に自動起動させる事が可能です。
sudo vi /etc/systemd/system/streamlit_service.service
```diff_conf:streamlit_service.service
[Unit]
Description=Streamlit Service
After=network.target

[Service]
WorkingDirectory=/test
Environment=PATH=/test/venv/bin:$PATH
ExecStart=/test/venv/bin/streamlit run /test/main.py
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target
```
sudo systemctl daemon-reload
sudo systemctl start streamlit_service
この後、パソコンより「http://（RaspberryのIPアドレス）:8501」へアクセスします。
streamlitの画面が表示されますよね？
sudo systemctl enable streamlit_service　（サービス起動として登録）
sudo reboot　（raspberryを再起動）
この後、パソコンより「http://（RaspberryのIPアドレス）:8501」へアクセスします。
streamlitの画面が表示されますよね？
これでサービス登録も終了です。　お疲れさまでした～
ベクトル和を矢印で可視化する

## はじめに
訳あってベクトル和を可視化したくなりました．
検索してもやりたいことが出てこなかったので備忘録として残します．

## やりたいこと
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/642842/951c2700-7106-1001-6bda-9e04a160cf7b.png)

こんな感じでベクトル和を各ベクトルと一緒に表示したいです．

## 方法
入力 `U`, `V` はベクトルの成分表示とします．
始点の座標を表す配列 `X`, `Y` を `starting_point()` で取得します．
numpy の `cumsum` 関数は累積和を求める関数で便利です．

```Python
import matplotlib.pyplot as plt

def starting_point(U,V,x_start=0,y_start=0):
    # 始点なのでU,Vの最後は不要
    U2 = np.concatenate([[x_start], U[:-1]])
    V2 = np.concatenate([[y_start], V[:-1]])
    X = np.cumsum(U2)
    Y = np.cumsum(V2)
    return X, Y

def vector_sum(X,Y,U,V):
    x = X[0]
    y = Y[0]
    u = np.sum(U)
    v = np.sum(V)

    return x, y, u, v

U = np.array([1,2,-2,2])
V = np.array([1,3,5,1])
X, Y = starting_point(U, V, 1, 0.5)
x, y, u, v = vector_sum(X,Y,U,V)

plt.quiver(X,Y,U,V, angles='xy', scale_units='xy', scale=1)
plt.quiver(x,y,u,v,color=["red"], angles='xy', scale_units='xy', scale=1)
plt.xlim([-1,5])
plt.ylim([-1,12])
plt.show()

```

下図が得られます．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/642842/615d3424-3e4f-004f-8189-bd8de139563c.png)

## 参考文献
* [matplotlib.pyplot.quiver](https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.quiver.html#matplotlib-pyplot-quiver)
* [numpy.cumsum](https://numpy.org/doc/stable/reference/generated/numpy.cumsum.html#numpy-cumsum)
* [【matplotlib】plt.quiverで矢印・ベクトルを描写する](https://disassemble-channel.com/matplotlib-plt-quiver-vector/)
プログラムにおける終了コードとは？その役割とNode.jsでの活用例


## はじめに

こんにちは。HRBrainでオウンドメディア・ランディングページの開発を担当している渡邉です。

先日、終了コードを真偽値と誤認したことが原因で、ハマりかけました。

終了コードは、プログラムが終了する際にOSへ返す数値であり、その値によってプログラムの実行結果を表しています。

この記事では、終了コードの役割と、Node.jsでの具体的な活用例を解説します。

## 終了コードを真偽値と混同してはいけない

プログラムの終了コードは `0` が成功、`0以外` がエラーや失敗を表します。

これは多くのプログラミング言語やOSで採用されている標準的な仕様です。

しかし、直感的には `0` はfalseや失敗を示し、`1` はtrueや成功を意味すると思いがちです。これが誤認の原因となります。

- 終了コード
  - `0` → 成功
  - `1` やそれ以外 → 失敗
- 真偽値（一般的な解釈）
  - `0` → false
  - `1` → true

## 終了コードの特徴と一般的な値

終了コードには、以下のような特徴があります。

1. 終了コード `0` はプログラムの正常終了を、`0` 以外の値はエラーや異常終了を表す
1. 異常終了を表す終了コードは、エラーの種類に応じて使い分けられる
1. 終了コードによって後続の処理を分岐させるなどの使い方がある

広く使われている、終了コードの一般的な値は以下のとおりです。

|終了コード|意味|
|--|--|
|0|正常終了|
|1|一般的なエラー|
|2|シェル組み込み関数の誤用|
|126|コマンドの実行権限がない場合|
|127|コマンドが見つからない場合|
|128|exitへの無効な引数|
|130|Ctrl+Cによる中断で返される|
|255|終了コードが範囲外の値|

https://tldp.org/LDP/abs/html/exitcodes.html

## Node.jsでの終了コードの扱い方

Node.jsでは、`process.exit()` メソッドを使って明示的に終了コードを指定できます。

```javascript
// 正常終了
process.exit(0);

// 一般的なエラー
process.exit(1);
```

## Node.jsでの活用例

### ファイル操作

ファイル操作の成功・失敗に応じて終了コードを返す例です。

```javascript:file_operation.js
const fs = require('fs');

fs.readFile('somefile.txt', 'utf8', (err, data) => {
  if (err) {
    console.error("ファイルの読み込みに失敗しました:", err);
    process.exit(1);
  } else {
    console.log("ファイルの内容:", data);
    process.exit(0);
  }
});
```

### HTTPリクエスト

HTTPリクエストの成否に応じて終了コードを返す例です。

```javascript:http_request.js
const https = require('https');

https.get('https://www.hrbrain.jp', (res) => {
  if (res.statusCode === 200) {
    console.log("HTTPリクエスト成功");
    process.exit(0);
  } else {
    console.error("HTTPリクエスト失敗:", res.statusCode);
    process.exit(1);
  }
}).on('error', (err) => {
  console.error("HTTPリクエストエラー:", err);
  process.exit(1);
});
```

### シェルスクリプトとの連携

Node.jsのプログラムをシェルスクリプトから実行し、終了コードによって後続処理を分岐させる例です。

```bash:exit_code.sh
#!/bin/bash

node http_request.js

if [ $? -eq 0 ]; then
  echo "プログラムは正常に終了しました"
else
  echo "プログラムはエラーで終了しました"
fi
```

上記の例では、シェルスクリプト内で `http_request.js` を実行しています。

URL設定を書き換えてHTTPリクエストの成否を操作することで、出力結果を変化させることができます。

```bash
# 設定したURLがレスポンスコード200を返す場合
$ sh exit_code.sh
HTTPリクエスト成功
プログラムは正常に終了しました

# 無効なURLを指定した場合や、レスポンスコード200以外が返る場合
$ sh exit_code.sh
HTTPリクエストエラー
プログラムはエラーで終了しました
```

## まとめ

終了コードは、`0`~`255`までの数値で表され、その番号に応じてエラーの内容を表現しています。

頻繁に遭遇する、真偽値としての `1` や `0` とは意味合いが異なるので、混同しないように注意しましょう！

## PR

HRBrainでは積極的に採用を行なっているのでぜひ！

https://www.hrbrain.co.jp/recruit
AWSスイッチロールを使ってアカウント切替

### 目的
IAMロールでAWSアカウントを跨いだスイッチロールを行いたいと思い、
今回実際にAWSアカウントを跨いだスイッチロール設定そしてIAMロールのセキュリティ担保のためにいくつか設定を行いましたので記載します。

#### 設定手順
AWSコンソール＞IAM＞ロール＞ロールを作成まで進みます。
「AWSアカウント」を選択すると下記画像のようになるため「別のAWSアカウント」を選択しIAMロールの使用を許可したいAWSアカウントを記載し「次へ」をクリックしてください。
（ちなみに複数のAWSアカウント設定・MFA設定を行うことも可能です）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2146106/a45d6a59-0030-a6c7-152c-08753774261d.png)

「許可を追加」画面にて許可ポリシー選択画面に変わりますので、任意のポリシーを選択し「次へ」を選択してください。

「名前、確認、および作成」の画面に変わりますので、任意のIAMロール名・説明やタグを追加し「ロールを作成」をクリックしてください。

上記手順でIAMロールの作成は完了です。
ですが今回は作成したIAMロールに使用制限を設けたいと思います。
使用制限については。IAM＞ロール＞「上記で作成したIAMロール名」まで移動し「信頼関係」タブにて「信頼ポリシーを編集」をクリックします。

ポリシーが設定可能になりますので下記の通り設定を行いました。
下記設定を行うことで特定のAWSアカウントかつIAMユーザしか上記のIAMロールを使用できなくしました。

```
{
	"Version": "2012-10-17",
	"Statement": [
		{
			"Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::[AWSアカウントID]:user/[IAMユーザ]"
			},
			"Action": "sts:AssumeRole"
            "Condition": {}
		}
	]
}
```

また今回上記手順で作成したIAMロールにadmin権限をアタッチしたため信頼ポリシーだけでは不安でした…
（MFAはつけたくありませんでした…）
そのため上記IAMロールの信頼ポリシーの編集権限を制限するIAMポリシーを作成することでセキュリティを担保しました。

```
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "DenyTrustPolicyEdit",
      "Effect": "Deny",
      "Action": [
        "iam:UpdateAssumeRolePolicy",
        "iam:PutRolePolicy"
      ],
      "Resource": "arn:aws:iam::[AWSアカウントID]:role/[IAMロール]",
      "Condition": {
        "StringNotLike": {
          "aws:PrincipalARN": [
            "arn:aws:iam::[AWSアカウントID]:user/[IAMユーザ]",
            "arn:aws:iam::[AWSアカウントID]:user/[IAMユーザ]"
          ]
        }
      }
    }
  ]
}
```

実際にスイッチロールを行うさいは下記画面にAWSアカウントIDやIAMロール情報を入力すると思いますが、
一々コピペはめんどくさいです。
そのため今回はChororm拡張機能である「AWS Extend Switch Roles」を使いました。
「AWS Extend Switch Roles」はわかりやすく解説してくれているサイトがいくつもあるため調べてみてください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2146106/33d7211a-aaef-32a1-21f0-4595783b33b1.png)

### 最後に

業務や資格勉強で学んだことを備忘録として書いています。
Salesforceトピックについて解説してみた

本橋孝昭です。

今回はトピック機能について解説します

まずはオブジェクトのトピックからトピックを使いたいオブジェクトに「有効化」設定をします

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/f8782208-5064-64d8-b0e6-348388565460.png)

Lightningページを編集してトピックコンポーネントを追加します

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/a1e01e61-e326-c5c5-e9aa-a4425571529d.png)


※なお「オブジェクトのトピック」が有効でない場合トピックコンポーネントを表に出すとこのような画面になります

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/0d43bd89-0c52-eb0c-e897-c7e0f04942c9.png)


ここでトピックを入力しましょう

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/7f495453-3f77-a68e-e75d-74fcb6938aec.png)

Chatterにもハッシュタグでトピックを追加します

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/f94b5bee-b86a-68ab-3273-9aa21b866364.png)


そうすればトピックをクリックすれば
[フィード]にはそのトピックのChatter投稿一覧が表示されます

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/1219dac4-bf0d-726b-bf01-a46fbaf27b1b.png)

関連にはそのトピックのレコード一覧が表示されます

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/819e46b5-c64f-fd18-2af2-5c4f01b85250.png)


## トピック使い方例

例えば商談レコードのキーワードやChatterでキーワードとしてトピックを入れておくと、トピックから思わぬ関連性のあるChatter投稿やレコードが発見できるかもしれません

（例　大阪万博　などのトピックをあらかじめ仕込んでおくと「大阪万博関連の取引先、商談、Chatter投稿」がトピックから抽出され、思いの寄らない部署と思いの寄らない連携が可能になるかもしれないですね　）
累乗平均の実装方法

## 累乗平均の実装

累積平均（またはインクリメンタル平均）を実装する。この方法では、データを一つずつ受け取るたびに平均を更新するため、全てのデータをメモリに保持する必要がなく、オーバーフローのリスクを軽減できる。

```Python:incremental_mean.py

def incremental_mean(data):
    mean = 0
    count = 0
    for value in data:
        count += 1
        mean += (value - mean) / count
    return mean

# 使用例
data = [1, 2, 3, 4, 5]
print(incremental_mean(data))  # 出力: 3.0

```
XserverにGitHub Actions経由でSSH接続を行った時のエラー

## エラーの内容
ssh: handshake failed: EOF
## 何度も確認したこと
* ローカルからはSSH接続できる
* ローカルと同じ秘密鍵をGitHub Secretsに保存している
## 修正したところ
XseverのSSH設定
 **ON[国内からのアクセスのみ許可]** のところを
 **ON[すべてのアクセスを許可] ※非推奨** へ変更しました。
## 記事にした経緯
アプリを作ろうと思い、自動デプロイにチャレンジしました。ChatGPT先生に聞きながらdeploy.ymlを作りpushするところまで行ったのですが、何度試しても上記のエラーが出ていました。分かれば何でもないことですが、ここで心が折れそうな程時間を使いました。
Api を用いて EA 用 Azure サブスクリプションを作成する

# これは何？
下記ドキュメントを進めるのに苦労したのでその備忘録です。
[レガシ API を使用してプログラムで Azure サブスクリプションを作成する](https://learn.microsoft.com/ja-jp/azure/cost-management-billing/manage/programmatically-create-subscription-preview?tabs=azure-cli)

# 概要
本手順は下記の流れで行う必要があります。
1. サービスプリンシパルの作成
2. 各種 ID の取得
3. API 実行

# 1.サービスプリンシパルの作成
"アプリ用の認証情報" とでも呼ぶべき、サービスプリンシパルを作成します。
Azure Portal 上の [Microsoft Entra 管理センター] にて、 [追加] - [アプリ登録] を押下します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48302/9aeda2da-5001-8732-9576-203bdcd47bf5.png)
[アプリケーションの登録] 画面に遷移するので、以下を設定後 [登録] を押下します。

名前 : 任意の名称
サポートされているアカウントの種類 : この組織ディレクトリのみに含まれるアカウント ({アカウント名} のみ - シングル テナント)
リダイレクト URI : 任意

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48302/e489d3c7-e09b-85c2-7f26-c685812878ec.png)

作成完了後、サービスプリンシパルの情報画面に遷移します。
この "アプリケーション (クライアント) ID" が "servicePrincipalObjectId" として用いる GUID となります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48302/9e1efb2b-1529-878d-fdfb-7be599a01ff3.png)


# 2.サービスプリンシパルの登録 
Azure Cli をベースに説明します。
実行するコマンドは [az account create](https://learn.microsoft.com/ja-jp/cli/azure/account/alias?view=azure-cli-latest#az-account-alias-create) コマンドで、引数は下記のようになります。
az account create --offer-type "{offer type}" --display-name "disp name" --enrollment-account-object-id "{enrollmentAccountObjectId}" --owner-object-id "{userObjectId}","{servicePrincipalObjectId}"

## 必須
・ offer-type : サブスクリプションのオファー。下記のどちらか。
    a) MS-AZR-0017P (運用環境用) 
    b) MS-AZR-0148P (開発/テスト用)

・ enrollment-account-object-id : EA 契約番号。コマンド [az billing enrollment-account list](https://learn.microsoft.com/en-us/cli/azure/billing/enrollment-account?view=azure-cli-latest#az-billing-enrollment-account-list) から取得可能な GUID。

## 任意
・ display-name : サブスクリプション名
・ owner-object-id : サブスクリプションの Azure RBAC 所有者として追加するユーザーのオブジェクト ID

# 出典
[Microsoft Entra アプリを登録し、サービス プリンシパルを作成する](https://learn.microsoft.com/ja-jp/entra/identity-platform/howto-create-service-principal-portal#register-an-application-with-azure-ad-and-create-a-service-principal)

[サービス プリンシパルに Enterprise Agreement ロールを割り当てる](https://learn.microsoft.com/ja-jp/azure/cost-management-billing/manage/assign-roles-azure-service-principals)

[レガシ API を使用してプログラムで Azure サブスクリプションを作成する - 特定の登録アカウントの中にサブスクリプションを作成する](https://learn.microsoft.com/ja-jp/azure/cost-management-billing/manage/programmatically-create-subscription-preview?tabs=azure-cli#create-subscriptions-under-a-specific-enrollment-account)
【学習メモ】プログラミング関連英単語【随時更新】

# この学習メモについて
・プログラミング学習時に出てきたカタカナ語や英語をメモ
・意味を書いていないものは後日記載する
・随時更新する

# やっていこう！

### ERB
（埋め込みRuby: Embedded Ruby）

https://eow.alc.co.jp/search?q=embedded

### yield 
/jiːld/
生み出す

https://eow.alc.co.jp/search?q=yield


### module 
/mɑ́dʒuːl/ 
部品の集まり

https://eow.alc.co.jp/search?q=module

### abort(aborted)
/əbɔ́rt/
中断する

https://eow.alc.co.jp/search?q=abort


### array

配列

### ハッシュ

### Integer
/íntidʒər/
整数

https://eow.alc.co.jp/search?q=integer

### downcase（類：lowercase）（反：uppercase）
小文字

### region

### syntax

### reference
/réfərəns/
言及

https://eow.alc.co.jp/search?q=reference

### abstract
抽象・抜粋
/(名・形)ǽbstrækt/

https://eow.alc.co.jp/search?q=abstract

### 属性: attribute

### アクセサー（accessor

### イテレーション 【iteration】 イテレート / iterate


https://e-words.jp/w/%E3%82%A4%E3%83%86%E3%83%AC%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3.html

### stub
/stʌ́b/
切り株／プログラミングでは「ダミー」の意味で使われる

https://dictionary.goo.ne.jp/word/en/stub/#:~:text=stub%E3%81%A8%E3%81%AF

### assets

### レンダリング
レンダリングとは、特定のテンプレートや部分テンプレートを表示するために、Railsがそのテンプレートを処理してHTMLを生成するプロセスのことを指します。レンダリングは、ビューをユーザーに表示するための重要なステップです。
【学習メモ】GASを使ってみよう！～JavaScriptをつかってみる～

### 今回やったこと
Gmailで毎朝ランダムな組み合わせの文章を指定したメールアドレス先に送付する仕組みをつくった


### メモ

#### 定義づけ
let name
var name
どちらの書き方でもOK。

違いとしては…
let→厳密な定義ができる（1回のみ定義）
var→定義した内容を別の定義で書き換えることができる（複数回定義が可能）

letで定義後にvarで定義をしても変更されない。
逆にvarで定義後は再度varで別の定義をすると反映される。

#### GASを触るメリット
GAS動かしてみると、ちょっと楽しいし勉強になる
（目の前で簡単に動かせて、実際に機能して自分に影響があるのは楽しかった！）
SlackやGmailと連携して、
ルーレットをつくれたり晩御飯を自動で決めるものを作れたりもする
もし学習に疲れて気分転換したいときは触ると良いかも
データ品質改善にも使えそうな思考

# 前提知識
## TOC
TOC(制約理論)を用いて、全体最適につながるような品質改善を行う。

データがどこから生まれ、どういったライフサイクルを歩むのか？
どこに保存され、そのデータの所有権はどのコンテキストなのか？
だけでなく、データの品質改善も組織的なデータマネジメントには求められている。

データの品質改善にしても、ボトルネック部分にのみ選択集中しなくては、お金がいくらあっても足りなくなる。

## ECRS原則
業務プロセス改善の際に使う、この順番に行いなさいという原則。
詳しくは以下を参照ください。

https://qiita.com/Kudo_panda/items/339b94aa17cc28ab1b04

この原則は何もプロセス面においてのみ適用されるものではない。
データマネジメントにも適用できたので、その紹介をする。


# 多角的に把握する
あくまでも模式図であるものの、下図は立体を上から見た際の図としてみる。
たとえば辺AB部分がセキュリティの側面を表し、
辺DE部分がパフォーマンスの側面を表すとする。

![sei6kaku2.jpeg.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2781175/91f186e1-b394-4cd6-0d42-c28275e3519d.jpeg)

ある品質の側面でのボトルネックだけでなく、
他の側面のボトルネックとの力学関係も仮説を持って把握しておく。

セキュリティ上のボトルネックを解消した結果、
パフォーマンス面のボトルネックをさらに悪化させてしまうという事態は、TOCの考え方である【全体最適】には反する。

状況によっては、求められる品質特性同士のトレードオフ両立が求められ、そこに対立解消図のクラウド法が求められる場面も出てくるはずと思っている。

# 考え方の土台
ベースの考え方自体は、アプリケーションのプロセス品質改善の考え方からそっくり引用できるものが多いと踏んでいる。

# データ改善×ECRS
データの利活用前の改善段階においても、ECRS原則は使える。
DX案件やアジャイルなプロセスを必要とする不確実性の高いプロダクトでは、継続的なデータモデリングと共に、このECRSを意識した改善活動が求められる。

それでは、いくつか概要を説明していく。
通常のECRS原則同様に、まずはEから行っていくことをお勧めする。
しかしながら、その後のC(統合or分割)からは、プロセスの場合と違って順番を入れ替える必要もあった。

## Eの段階
利活用前にまずは使われていない、削除しても問題ないテーブルを掃除する。
一番削除しても問題なさそうなものから少しずつ削除する。
これ自体は、以下に記載した戦術的フォークと一緒の考え方である。

https://qiita.com/Kudo_panda/items/4c2c7922c5a8079fe73d

これを行ったうえで、次のフェーズへ移行する。

## Sの段階
簡潔にわかりやすくするフェーズ。
どういうことかというと、１つのデータドメイン内にあるテーブルが１つのみで、そこにすべてのカラムが収まっていることを想像してほしい。

簡単な例として出すなら、
注文テーブルと注文明細テーブルが１つにまとまっているとしよう。

:::note warn
※2つはすでに上の3つの工程によって、同じデータドメインに集められているものとする。
:::

これを分かりやすいと言えるだろうか？
とてもじゃないが言えない。
この程度のものならまだかわいい方だが、
そこにさらに色んなデータ責務のものがくっついていたらどうだろうか？

いわば、いろんな大量のカラムの混在した神テーブルだ！
そのままでは正規化もろくに行われておらず、メンテもしにくい。
データの重複や不整合も起こりやすいと言えるだろう。

そこでその神テーブルを正規化に従って分けていく。
その結果、１つのテーブルは１つのデータの意味を表し、
そのデータドメインが何を表すものなのか？を一発でいえる。

:::note warn
ちなみにこのフェーズを行って、１つのテーブルが１つの責務になりうるように
シンプルな構造になっていないと、後述のデータドメイン(データのコンテキスト境界)の位置の判別が難しくなる。
:::

よって、この後にCを行うことを推奨する。


## Cの段階
この段階では統合や分解を行うフェーズ。
データの観点でのコンテキスト(データドメイン)を意識した統合や分解を行う。
つまり、データドメインが異なると判断したものは、
同じスキーマに含めないで、明確に境界を張って分けるとか。
この時点でモノリスなのか？　マイクロサービスなのか？は置いておいて、概念スキーマ上は分けておくという方法を取った方が、変にデータの静的な密結合を起こしにくい。

同様にして、同じデータドメイン内のもの
たとえば強い集約関係にあるものとかは、境界を引かずに、
同じデータドメインにまとめておく。

このようにドメインを意識して保守の観点で分ける以外にも、
セキュリティなどの運用特性も考慮した上で、
データドメインの境界の位置を定義しなくてはならない。

:::note warn
特にデータの境界位置の変更は、ロジックの境界位置の変更以上に行いづらいので、慎重に議論する必要性がある。
:::

## Rの段階
入れ替えを行う段階。
もともとはアナログな帳簿からデジタルな記録媒体に組み替えるなど。

他には、もともとはRDBであったものの、
整合性よりも他の品質特性が求められるようになってきたので、
DBの種類を変えたりすることを検討するフェーズ。

RDBが有名であり、もっとも使われているので、
モノリシックなアプリでRDBから他のデータベース種別へ変えるということは余程なことがない限りない。

この種別の置き換えは、主にマイクロサービスなどのような分散システムで、データベースが各コンテキスト内に１つあるような状況下で検討する事柄。

:::note warn
実体験だが、上の3つをすっ飛ばして、いきなりこのRからやろうとしたことがある。
後戻りできる段階であったからよかったものの、あと一歩で自分が大きな負債を生み出す１人になる所であった。

同じデータドメインのものは1つの種別のDBに格納する以上、
そこに集まってるデータは、同じ品質レベルが適用されてしまう。
:::

# 注意事項
ちなみにドメイン的には、異なるスキーマであってほしいような
注文データドメインと発注データドメインがあったとしよう。

この時に安直に、それら２つを分けるってやってはいけない。
ビジネス上の都合で、そこの間に強い整合性、
トランザクション境界がその２つを包み込むようにしてあった場合には、注文と発注テーブル群を1つのデータドメイン内に配置する必要性がある。

その代わり、デメリットとしてそのデータドメインには、2つのデータの意味が混在していることも理解したビジネスモデルを構築しなくてはならないことは理解しておく必要がある。
[Module] モジュール結合度

# 一覧
|||
|:--|:--|
|強||
|内部結合|モジュールの内部を直接参照・使用している|
||ex: あるモジュールがJUMP命令を用いて他のモジュールを呼び出す|
|共通結合|``大域宣言``されたレコードや構造体などの``データ構造``を、複数のモジュールが参照している|
||ex: 大域的なデータをモジュール同士で参照する|
|外部結合|``大域宣言``された``単一のデータ``を、複数のモジュールが参照している|
||ex: 大域的な単一のデータをモジュール同士で参照する|
|制御結合|モジュールの``動作を制御する``ための要素を受け渡している|
||ex: 実行する機能や論理を決定するための引数を受け渡す|
|スタンプ結合|処理に必要なデータだけをレコードや構造体なその``データ構造``として受け渡している|
||ex: データ構造を引数で受け渡す|
|データ結合|処理に必要なデータだけを単一の``パラメータ（引数）``として受け渡している|
||ex: 単一のデータ項目を引数で受け渡す|
|弱||

# 参考リンク
- [R6S46](https://www.ap-siken.com/kakomon/20_aki/q45.html)
- [H28S47](https://www.ap-siken.com/kakomon/28_haru/q47.html)
Why the AIGP Certification is Essential for AI Governance Professionals

Artificial Intelligence Governance Professional (AIGP) Exam: A Guide to Ethical AI Governance
With the rapid growth of AI technology across industries, the need for responsible AI governance has become critical. The Artificial Intelligence Governance Professional (AIGP) certification is designed to equip professionals with the knowledge and skills needed to manage the ethical implications of AI development, deployment, and maintenance. This credential ensures that individuals are prepared to address AI risks while maintaining safety, transparency, and trust in AI systems.

Why Pursue the AIGP Designation?
The AIGP designation offers a range of benefits that are crucial for professionals in the AI landscape. Let's explore why obtaining this certification is essential:

Establish Foundational Knowledge of AI Systems
AIGP certification helps candidates build a strong foundation in understanding AI systems, their use cases, and the principles of responsible AI governance. It provides insights into how AI impacts industries and society, preparing professionals to ensure the ethical deployment of AI solutions.

Understand AI Laws and Regulatory Frameworks
As AI becomes more prevalent, understanding the legal frameworks and emerging regulations governing AI systems is essential. The AIGP exam tests candidates' knowledge of AI-related laws and helps them apply these regulations to responsibly govern AI frameworks, ensuring compliance and ethical practices.

Master the AI Life Cycle and Risk Management
Responsible AI governance requires professionals to be familiar with the AI life cycle, from design to deployment and monitoring. The AIGP credential emphasizes managing risks associated with AI at every stage of its life cycle, ensuring that AI systems are safe, secure, and transparent.

Tackle Unforeseen Challenges in AI Governance
AI governance isn't just about managing existing risks. The AIGP certification also prepares professionals to anticipate and address unforeseen concerns. This includes understanding and navigating debated issues in AI governance, such as bias, data privacy, and ethical dilemmas, making candidates more effective at ensuring responsible AI management.

IAPP AIGP Practice Test: The Key to Success
To succeed in the AIGP exam, candidates must be well-prepared and knowledgeable about AI governance concepts. One of the most effective ways to prepare is by taking IAPP Certification Programs AIGP practice tests. These tests help candidates familiarize themselves with the exam format and [IAPP Certification Programs AIGP Exam Questions](https://testinsights.com/info/iapp/aigp) types, identify their strengths and weaknesses, and build confidence before the actual exam.

Recommendation: For those aiming to excel in the AIGP exam, I highly recommend incorporating practice tests into your study plan. Practice tests provide valuable insights into the types of questions you can expect and ensure that you are thoroughly prepared to achieve success in your AI governance certification journey.
Spring環境でCSRにHandlebarsを使っている話

# はじめに（読み飛ばしてOK）
時間の流れは早いもので、気づけば開発経験2年以上になっていました。なっしーです！
練習にSpringを使ったWebアプリを作っているので、その話をしようと思います。
今回はThymeleafと一緒にHandlebarsを使っている話をします。

# 想定読者層
- Springを学び始めた人
- Thymeleafだけでは表現の限界を感じている人

# 環境
- Spring（Spring Boot）
- Thymeleafを使用

# Handlebarsとは？
Handlebarsは、JavaScriptで利用できるテンプレートエンジンです。
Thymeleafと同じように、サーバーから渡されたデータをHTMLに埋め込んでくれるものです。

ThymeleafはSSR（サーバーサイドレンダリング）を行えます。
一方、HandlebarsはCSR（クライアントサイドレンダリング）を得意としています。

# レンダリングとは
HTMLやCSS、JavaScriptなどを合体させて、ユーザーが読める形にする過程を（ブラウザ）レンダリングと言います。

（※レンダリングという単語は広義では「データを処理することで画像や音楽、テキストを表示できるようにすること」を指していたりします。）

# SSRとCSRの違い
SSRは文字通りサーバー側で、CSRはクライアント（Webブラウザ）側でHTMLをレンダリングします。
平たく言うと、組み立ての作業場所が違うってことですね。

違いを表にしてみましょう。

|  | SSR | CSR |
|:-:|:-:|:-:|
| レンダリング場所 | サーバー | クライアント |
| 初回のページ表示 | 速い | 遅い |
| ロード後のページ遷移速度 | 遅い | 速い |
| SEO | 強い | 弱い |

Thymeleafでは毎回サーバーでページのすべてをレンダリングする必要がある一方、Handlebarsでは1度ロードされた後はテンプレート部分をクライアント側でレンダリングできます。
この2つを使い分けることで、良い感じのページを作ろうってことです！

# 使い分け
Handlebarsは主に、データ量が多く、ページングやローディングの表示をさせたいものに使います。
それ以外は基本的にThymeleafを使っています。

Handlebarsには非同期通信で取ってきたデータを渡しています。

例えば、ECサイトであれば商品ページで商品の情報だけ非同期処理とHandlebarsを使って、クライアント側で表示できるようにする…といったようなことをしています。
そうすることで、ページングなどの処理が簡単に実装できます。
そして、商品情報以外の部分（≒あまり変化がないもの）はThymeleafでSSRしておけば効率が良いですよね！

# Handlebarsの基本的な使い方
### 公式ドキュメント
https://handlebarsjs.com/guide/

使い方を知るにはHandlebarsの公式ドキュメント↑を見るのが一番早いです。
とてもシンプルなテンプレートエンジンなので、ドキュメントが英語で書かれていても容易に理解できるなぁと個人的に思っています。
シンプル大好き。

データバインド（データをHTMLに埋め込むもの）やifやeachなどの基本的な処理はもちろん、自分で好きな処理を作ることもできます。
ネストされたデータも取り扱えます。

自由度が高くて学習コストが低いところが気に入っています。

# 終わりに
Handlebarsは、Thymeleafだけだと物足りない、かといってイマドキなフロントエンドフレームワークを本気で導入するほどじゃない…みたいなときにピッタリなライブラリだったと思います。
皆さんも一度使ってみてください！

ここまで読んでいただき、ありがとうございます！なっしーでした！