OmniAICreator/Qiita-1.07M huggingface dataset:
ブックマーク集（技術系の参考書籍）

# ブックマーク集（技術系の参考書籍）
　
技術系の参考書籍を探したい時に、参考になるWebサイトのブックマークをここに記載する。
***
### HTML & CSS
https://mrzw-design.com/html-css-books/

### Next.js
IoT百葉箱プロジェクト第２弾

## プロジェクト概要
私の趣味の一つである気象観測に関するプロジェクトです。
ラズベリーパイと温度、湿度、気圧が図れるセンサーBME280を接続して、観測データを毎時00分と30分にTweetしてます。
[X(Twitter)](https://x.com/weathertakz2001)

第１弾はこちら↓
https://qiita.com/takz2001/items/c544dc04e08f852dfa64

第２弾の今回はラスパイカメラを接続して、空の写真を撮影して、Tweerに載せました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587072/559a4272-0380-6b8d-c794-28610a1ff2ee.png)

## カメラについて
本来はベランダ設置の百葉箱にカメラを設置したいのですが、地べたに置いているのでいい高さからの写真がとれません。ベランダの柵が画角に入ってしまうんですよね。
百葉箱の定義をなしていませんがw

## 百葉箱の定義
"地上から1.2～1.5mに設置する"とあるので、その高さから撮ればいいのですが、将来的に足をつけて高くしようと思っています。

![tenki_hyakuyoubako_open.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587072/1b5fa965-3f1c-01b3-8b86-5839c9c1c27d.png)


ということで室内にもう一台カメラ接続のラズパイを設置して1.7mぐらいの高さから撮影することにしました。

## 別ラズパイのカメラ設定
raspistillコマンドを使って撮影します。

```raspistillコマンド
raspistill -w 1920 -h 1080 -q 100 --annotate "$datetime" -ae 50 -n -o photo.jpg
```

オプションの説明
-w 幅(width)
-h 高さ(height)
-q 品質(qualty)
-ae 文字の大きさ
-o 出力ファイル名

このphoto.jpgを百葉箱ラズパイからsshpassでコピーしています。

## 今後の野望
前述の通り地べた設置なので、足をつけたいです。

設定的にはJSONファイル作成してAmbientに送信（うまく行ってません）、ガスセンサーの設置、太陽光パネルの設置などです。
C_TS422_2021 SAP Certified Application Associate SAP S/4HANA Production Planning and Manufacturing対策（69/100）

【69日目】
トピック 8：SAPS/4HANAの製造指図（1/15）

≪問題69≫
指図タイプ依存パラメータの設定によって影響を受けるビジネスプロセスは以下のどれですか。
（２つ選択）
□管理会計との統合を定義する。
□自動利用可能在庫確認を実行する。
□マスタデータを選択する。
□製造指図の日程計画を実行する。

≪解答≫
□管理会計との統合を定義する。
□自動利用可能在庫確認を実行する。
■マスタデータを選択する。
■製造指図の日程計画を実行する。

≪解説≫
◆製造指図は、常に指図タイプへの参照とともに登録されます。
◆指図タイプにより、以下のような指図のビジネスプロセスが制御されます。
（1）指図数量と日付の定義
（2）マスタデータの選択
（3）日程計画
（4）能力所要量の決定
（5）計画原価計算
Log Analytics と  Azure Monitor ワークスペース の違い

# はじめに
久しぶりに Log Analytics ワークスペース を 新規デプロイしようとしたところ、Azure Monitor ワークスペース というのがあるみたいで、どっちを使えば良いのか迷いました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1619637/33ada8ea-4f67-b873-0301-16602452860b.png)

最初は、同じものなのか、新サービスへ移行していくのか・・・とか考えたのですが、違っていたので、その点を記事にしておこうと思いました。

# 結論
引き続き、Log Analytics ワークスペース を使っていけば良さそうです。

公開情報を参照する限り、将来的に Azure Monitor ワークスペース に すべてのメトリックが収集されるようになる計画があるようですが、現時点では **Prometheus メトリック** のみが収集対象になっている様子です。

どのみち、メトリックが対象な様子ですね。

なので、メトリック と ログ の両方を収集可能な Log Analytics を引き続き利用していけば良さそうです。

:::note info
この結論は、2024/7/15 時点の公開情報の記載に基づいて、私の見解を述べたものになります。
:::

# 公開情報
## FAQ より
**Azure Monitor ワークスペースと Log Analytics ワークスペースの違いは何ですか?**
https://learn.microsoft.com/ja-jp/azure/azure-monitor/essentials/azure-monitor-workspace-overview#whats-the-difference-between-an-azure-monitor-workspace-and-a-log-analytics-workspace
（2024/7/15 時点のキャプチャ）
（赤字）＝ 将来的な話
（緑字）＝ 現在の状況
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1619637/d4921631-ac44-ae2f-ae6d-a3aa05312250.png)

## Prometheus メトリックとは？
以下の記事に記載されていることを見る限り、メトリックのような情報を収集することが目的であって、個人情報のようなデータを保存するものでは無い事が明記されています。
セキュリティ情報をガンガン保存していく Log Analytics とは前提が違ったもののようですね。

https://learn.microsoft.com/ja-jp/azure/azure-monitor/essentials/prometheus-metrics-overview

:::note alert
（上記の記事より抜粋）
**重要**
Prometheus 用の Azure Monitor マネージド サービスは、顧客のマシンとアプリケーションのサービス正常性に関する情報を格納することを目的にしています。

個人を特定できる情報 (PII) やエンド ユーザーを特定できる情報 (EUII) として分類されるデータを格納するためのものではありません。

Azure Monitor マネージド サービスに、メトリック名、ラベル名、ラベル値などの Prometheus フィールド用に機密情報 (ユーザー名、クレジット カード番号など) を送信しないことを強くお勧めします。
:::

## Azure Monitor メトリックの概要
Azure には、どのような メトリック が存在するのかが明記された記事です。

https://learn.microsoft.com/ja-jp/azure/azure-monitor/essentials/data-platform-metrics

（上記の記事より抜粋）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1619637/09209c00-20ac-7be3-c4a5-f93491171711.png)
この図のうち、**Native** と **Custom** は 既定で Azure 内のデータストア に保存され、**Prometheus** の入れ物が Azure Monitor ワークスペース であると思われます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1619637/e582a401-759b-1ea4-0700-73540b89f22a.png)

「既定で Azure 内のデータストア」とは、Azure で作成されたリソースって、利用者が何も手配しなくても 各リソースの左ペインにある、**メトリック** というメニューから 参照できる アレです。このデータは 最大 93 日間保存されますが、以後 自動削除されていきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1619637/8b98d892-6c69-6f1c-1807-3cf73c925dec.png)

**メトリックの保有期間**
https://learn.microsoft.com/ja-jp/azure/azure-monitor/essentials/data-platform-metrics#retention-of-metrics

現状は、もっと長期間 保存しておきたい場合には、メトリックを Log Analytics へ転送することで、データを保持していくという考え方になっています。

以上です。同様に疑問に思った人が居られたら、この記事を見て スッキリして頂ければと思います。
Python NumPyを活用したバッチデータの数値計算高速化テクニック

## はじめに

大量のデータを扱うデータサイエンスや機械学習の分野では、効率的な数値計算が非常に重要です。Pythonの標準ライブラリだけでは処理速度に限界がありますが、NumPyを活用することで驚くほど計算速度を向上させることができます。この記事では、NumPyを使ってバッチデータの数値計算を高速化するテクニックをいくつか紹介します。

```mermaid
graph LR
    A[NumPyを活用した<br>バッチデータの<br>数値計算高速化<br>テクニック]

    A --> B[ベクトル化演算]
    B --> B1[ループ不要]
    B --> B2[配列全体に対する演算]

    A --> C[ブロードキャスティング]
    C --> C1[異なる形状の<br>配列間で演算]
    C --> C2[小さい配列を自動拡張]

    A --> D[高度な索引操作]
    D --> D1[複雑なデータ操作]
    D --> D2[条件付き<br>フィルタリング]

    A --> E[ユニバーサル関数<br>ufunc]
    E --> E1[要素ごとの演算]
    E --> E2[C言語で実装された<br>高速関数]

    A --> F[メリット]
    F --> F1[処理速度の向上]
    F --> F2[コードの簡潔化]
    F --> F3[メモリ効率の改善]

    A --> G[注意点]
    G --> G1[メモリ使用量と<br>速度のトレードオフ]
    G --> G2[適切な方法の選択]

    classDef default fill:#fff,stroke:#333,stroke-width:2px;
    classDef main fill:#e6f3ff,stroke:#333,stroke-width:4px;
    class A main;
```
## 1. ベクトル化演算

NumPyの強力な機能の一つが、ベクトル化演算です。これにより、ループを使わずに配列全体に対して演算を行うことができます。

```python
import numpy as np
import time

# 通常のPythonリスト操作
def python_sum(n):
    return sum([i**2 for i in range(n)])

# NumPyのベクトル化演算
def numpy_sum(n):
    return np.sum(np.arange(n)**2)

n = 10000000
start = time.time()
python_sum(n)
print(f"Python: {time.time() - start}")

start = time.time()
numpy_sum(n)
print(f"NumPy: {time.time() - start}")
```

この例では、NumPyのベクトル化演算を使用することで、通常のPythonリスト操作と比較して大幅に処理速度が向上します。

## 2. ブロードキャスティング

ブロードキャスティングは、異なる形状の配列間で演算を行う際に、小さい方の配列を自動的に拡張してくれる機能です。

```python
import numpy as np

# 2D配列と1D配列の加算
a = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
b = np.array([1, 0, 1])

print(a + b)  # bは自動的に[[1, 0, 1], [1, 0, 1], [1, 0, 1]]に拡張される
```

この機能により、明示的なループを書くことなく、効率的に異なる形状の配列間で演算を行うことができます。

## 3. 高度な索引操作

NumPyの高度な索引操作を使うことで、複雑なデータ操作を簡潔かつ高速に行うことができます。

```python
import numpy as np

# 複雑な条件に基づくフィルタリング
data = np.random.randn(1000000, 4)
result = data[(data[:, 0] > 0) & (data[:, 1] < 0) & (data[:, 2] + data[:, 3] > 1)]

print(result.shape)
```

この例では、複数の条件を組み合わせて大量のデータから特定の条件を満たす行を抽出しています。

## 4. ユニバーサル関数（ufunc）の活用

NumPyのユニバーサル関数を使うことで、要素ごとの演算を高速に行うことができます。

```python
import numpy as np

def custom_sigmoid(x):
    return 1 / (1 + np.exp(-x))

x = np.random.randn(1000000)

# NumPyのufuncを使用
result = custom_sigmoid(x)
```

ユニバーサル関数は内部でC言語で実装されているため、純粋なPythonで書かれた関数よりも高速に動作します。

## まとめ

NumPyを活用することで、バッチデータの数値計算を大幅に高速化することができます。本記事で紹介したテクニックを組み合わせることで、より効率的なデータ処理が可能になります。ただし、メモリ使用量と処理速度のトレードオフに注意しながら、適切な方法を選択することが重要です。

NumPyの機能は非常に豊富で、ここで紹介したのはほんの一部に過ぎません。公式ドキュメントを参照しながら、自分のユースケースに最適な方法を探ってみてください。
フレックスボックス復習

<h1>フレックスボックスとは？
<p>ブロックボックスは縦に並んでいる
<p>（例）h1〜h6 p ul

![ブロックボックス縦に並ぶ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3717237/56e10df6-1a96-a946-3a92-814a91e99629.png)

<h2>■フレックスボックス
<p>フレックスボックスはブロックボックスを横並びに出来る
<p>“ul” “li” のブロックボックスの時の並び
<p>縦並びになる

![ブロックボックスの時.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3717237/0b1c07bd-4229-93b2-d66f-a9a884f1fe8e.png)

<p>“ul” “li” のフレックスボックスの時の並び
<p>ブロックボックスが横並びになる

![li_横並び.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3717237/7f4df168-e81a-e295-09ae-4126632a6514.png)

<h3>■Flexbox（フレックスボックス）の2ステップ

<p>①横並びにしたい親要素を確認する<br>
②親要素に display:flex; を指定する

<p>“ul” “li” の場合は<br>
“ul”が親要素で<br>
“li”が子要素<br>
子要素 ”li” を横並びにしたい場合

HTML

![HTML.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3717237/b6aee46e-203d-b712-54ce-ea9639da8863.png)


CSS

![CSS.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3717237/ec7c12f1-419d-5115-a399-7fd066bbcdff.png)

<p>横並びになる

![li_横並び.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3717237/e7102a00-dd8a-6335-6e25-d2ff28d05358.png)
Python Pandasを使った大規模CSVファイルの高速処理方法

## はじめに
こんにちは！今回は、Pythonの人気データ処理ライブラリであるPandasを使って、大規模CSVファイルを効率的に処理する方法をご紹介します。大量のデータを扱う際、メモリ使用量や処理速度が問題になることがありますが、適切な手法を用いることでこれらの課題を克服できます。

## 目次
1. [チャンクを使った読み込み](#チャンクを使った読み込み)
2. [データ型の最適化](#データ型の最適化)
3. [不要な列の削除](#不要な列の削除)
4. [並列処理の活用](#並列処理の活用)
5. [CSV書き出しの最適化](#CSV書き出しの最適化)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2648069/8d216b23-52c4-876a-9691-feafb724d7b7.png)

## チャンクを使った読み込み

大規模なCSVファイルを一度に読み込むとメモリ不足になる可能性があります。Pandasの`read_csv`関数の`chunksize`パラメータを使用することで、ファイルを小さな塊（チャンク）に分けて読み込むことができます。

```python
import pandas as pd

chunk_size = 100000  # 各チャンクのサイズ
for chunk in pd.read_csv('large_file.csv', chunksize=chunk_size):
    # チャンクごとの処理をここに書く
    process_chunk(chunk)
```

この方法を使えば、大きなファイルでもメモリ使用量を抑えながら処理できます。

## データ型の最適化

Pandasはデフォルトでは64ビットのデータ型を使用しますが、多くの場合これは過剰です。データ型を適切に指定することで、メモリ使用量を大幅に削減できます。

```python
dtypes = {
    'id': 'int32',
    'value': 'float32',
    'category': 'category'
}

df = pd.read_csv('large_file.csv', dtype=dtypes)
```

特に、カテゴリカルデータに対して'category'型を使用すると、メモリ使用量が大幅に削減されます。

## 不要な列の削除

大規模なCSVファイルには、処理に不要な列が含まれていることがあります。これらの列を早い段階で削除することで、メモリ使用量を減らし、処理速度を向上させることができます。

```python
useful_columns = ['id', 'value', 'category']
df = pd.read_csv('large_file.csv', usecols=useful_columns)
```

## 並列処理の活用

Pandasは単一のCPUコアでの処理が基本ですが、`multiprocessing`ライブラリを使用することで、並列処理を実現できます。

```python
from multiprocessing import Pool

def process_chunk(chunk):
    # チャンクの処理ロジックをここに書く
    return processed_chunk

if __name__ == '__main__':
    pool = Pool(processes=4)  # プロセス数を指定
    results = []

    for chunk in pd.read_csv('large_file.csv', chunksize=100000):
        results.append(pool.apply_async(process_chunk, (chunk,)))

    processed_chunks = [result.get() for result in results]
    
    # 処理結果の結合
    final_result = pd.concat(processed_chunks)
```

## CSV書き出しの最適化

処理結果を再びCSVファイルに書き出す際も、チャンクを使用することで効率的に行えます。

```python
chunk_size = 100000
for i, chunk in enumerate(pd.read_csv('large_input.csv', chunksize=chunk_size)):
    # チャンクの処理
    processed_chunk = process_chunk(chunk)
    
    # 最初のチャンクの場合はヘッダーを書き出し、それ以外はヘッダーなしで追記
    mode = 'w' if i == 0 else 'a'
    header = i == 0
    processed_chunk.to_csv('large_output.csv', mode=mode, header=header, index=False)
```

以上の方法を組み合わせることで、大規模なCSVファイルでも効率的に処理することができます。データの特性や処理内容に応じて、最適な方法を選択してください。

大規模データ処理において、メモリ使用量と処理速度のバランスを取ることは重要です。これらの手法を適切に活用することで、より効率的なデータ処理が可能になります。Happy coding!
RLoginで文字化け回避

シリアル通信をしているとターゲットの電源OFF/ONで不正なデータが送られてきて、文字化けして固まる事があります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/699d6d1f-53dc-5e6d-1373-decd0fb69115.png)

これはオプション設定->スクリーン->制御コードの「?8454 C1制御コードを無視する」にチェックを入れると回避できるようです。

ターゲットによっては固まらないですが、文字化けは発生するようです。その時はリセット->すべてリセットしてください。
robloxでassistant その127

# 概要
robloxでassistantやってみた。
練習問題やってみた。

# 練習問題
スクリプトだけで、ボタンでパーツを上下左右前後させよ。

# 手順
- ReplicatedFirstに、LocalScriptを追加。
- スクリプトを書く。
```


local Players = game:GetService("Players")
local Player = Players.LocalPlayer
local PlayerGui = Player:WaitForChild("PlayerGui")
local Gui = Instance.new("ScreenGui")
Gui.Parent = PlayerGui


local button0 = Instance.new("TextButton")
button0.AnchorPoint = Vector2.new(4, 0.9)
button0.Size = UDim2.new(0.05, 0, 0.1, 0)
button0.Position = UDim2.new(0.5, 0, 0.5, 0)
button0.Text = "up"
button0.Parent = Gui
local button1 = Instance.new("TextButton")
button1.AnchorPoint = Vector2.new(4, 0)
button1.Size = UDim2.new(0.05, 0, 0.1, 0)
button1.Position = UDim2.new(0.5, 0, 0.5, 0)
button1.Text = "down"
button1.Parent = Gui
local button2 = Instance.new("TextButton")
button2.AnchorPoint = Vector2.new(4, 0.9)
button2.Size = UDim2.new(0.05, 0, 0.1, 0)
button2.Position = UDim2.new(0.6, 0, 0.5, 0)
button2.Text = "right"
button2.Parent = Gui
local button3 = Instance.new("TextButton")
button3.AnchorPoint = Vector2.new(4, 0)
button3.Size = UDim2.new(0.05, 0, 0.1, 0)
button3.Position = UDim2.new(0.6, 0, 0.5, 0)
button3.Text = "left"
button3.Parent = Gui
local button4 = Instance.new("TextButton")
button4.AnchorPoint = Vector2.new(4, 0.9)
button4.Size = UDim2.new(0.05, 0, 0.1, 0)
button4.Position = UDim2.new(0.4, 0, 0.5, 0)
button4.Text = "front"
button4.Parent = Gui
local button5 = Instance.new("TextButton")
button5.AnchorPoint = Vector2.new(4, 0)
button5.Size = UDim2.new(0.05, 0, 0.1, 0)
button5.Position = UDim2.new(0.4, 0, 0.5, 0)
button5.Text = "rear"
button5.Parent = Gui

wait(1)
local part = Instance.new("Part", workspace)
part.Anchored = false
part.Size = Vector3.new(1, 1, 1)
part.Position = Vector3.new(0, 5, 0)
local att = Instance.new("Attachment")
att.Parent = part
local LV = Instance.new("LinearVelocity")
LV.Attachment0 = att
LV.MaxForce = 10000
LV.VectorVelocity = Vector3.new(0, 0, 0)
LV.Parent = workspace




button0.MouseButton1Click:Connect(function()
	print("up")
	LV.VectorVelocity = Vector3.new(0, 1, 0)
end)
button1.MouseButton1Click:Connect(function()
	print("down")
	LV.VectorVelocity = Vector3.new(0, -1, 0)
end)
button2.MouseButton1Click:Connect(function()
	print("right")
	LV.VectorVelocity = Vector3.new(1, 0, 0)
end)
button3.MouseButton1Click:Connect(function()
	print("left")
	LV.VectorVelocity = Vector3.new(-1, 0, 0)
end)
button4.MouseButton1Click:Connect(function()
	print("front")
	LV.VectorVelocity = Vector3.new(0, 0, 1)
end)
button5.MouseButton1Click:Connect(function()
	print("rear")
	LV.VectorVelocity = Vector3.new(0, 0, -1)
end)




```

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/f72bcc0b-10ab-6f24-c91a-02af5c2c5f21.png)


以上。
Javaで「メソッドの使い方」を動作を確認してみた

# 概要

Javaで「メソッドの使い方」を動作を確認してみました。
以下のページを参考にしました。

https://www.javadrive.jp/start/method/index1.html

# 実装

以下のファイルを作成しました。
```JSample1_1.java
class JSample1_1{
  public static void main(String args[]){
    int eigo = 78;
    int suugaku = 90;
    int kokugo = 68;

    check("英語", eigo);
    check("数学", suugaku);
    check("国語", kokugo);
  }

  private static void check(String kyoka, int seiseki){
    System.out.print(kyoka + "の試験結果は");
    if (seiseki > 80){
      System.out.println("合格です");
    }else{
      System.out.println("不合格です");
    }
  }
}
```

以下のコマンドを実行しました。
```
$ javac JSample1_1.java 
$ java JSample1_1 
英語の試験結果は不合格です
数学の試験結果は合格です
国語の試験結果は不合格です
```

# まとめ

何かの役に立てばと。
【Go言語】Trim関数

# Trim関数とは？

[strings](https://pkg.go.dev/strings)パッケージの[TrimLeft](https://pkg.go.dev/strings#TrimLeft)、[TrimPrefix](https://pkg.go.dev/strings#TrimPrefix)などのTrimXXXとなる関数のこと。

特に、TrimRight と Trimsuffixを混同してしまいがちなので、解説していきます。

# TrimRight

`TrimRight`は、末尾の文字が、第二引数に指定したルーンの集合に当てはまったら、その文字を削除します。

```go
fmt.Println(strings.TrimRight("123oxo", "xo")) // 123
```

`123o`になりそうですが、oは`xo`の一部なので、削除されて123となります。

# TrimSuffix

TrimSuffixは、与えられた接尾辞の文字列を末尾から取り除いた値を返します。

```go
fmt.Println(strings.TrimSuffix("123oxo", "xo")) // 123o
```

## TrimLeft

`TrimRight`と同様に、頭の文字が、第二引数に指定したルーンの集合に当てはまったら、その文字を削除します。

```go
fmt.Println(strings.TrimLeft("xoxxo123", "xo")) // 123
```

## TrimPrefix

TrimPrefixは、与えられた接頭辞の文字列を末尾から取り除いた値を返します。

```go
fmt.Println(strings.TrimPrefix("xoxxo123", "xo")) // xxo123
```

## Trim

Trimは、全ての文字列から第二引数に指定したルーンの集合に当てはまったら、その文字を削除します。

```go
fmt. Println (strings. Trim ("oxo123oxo", "ox")) // 123
```

# TrimFunc

Trimは、全ての文字列から第二引数に指定したカスタム関数に当てはまったら、その文字を削除します。

```go
customFunc := func(c rune) bool {
    return strings.ContainsRune("xo", c)
}

fmt.Println(strings.TrimFunc("xoxox123xoxox", customFunc)) // 123
```

# TrimLeftFunc

頭の文字が、カスタム関数の返すルーンの集合に当てはまったら、その文字を削除します。


```go
customFunc := func(c rune) bool {
    return strings.ContainsRune("xo", c)
}

fmt.Println(strings.TrimLeft("xoxox123xoxox", customFunc)) // 123xoxox
```

# TrimRightFunc

最後の文字が、カスタム関数の返すルーンの集合に当てはまったら、その文字を削除します。

```go
customFunc := func(c rune) bool {
    return strings.ContainsRune("xo", c)
}

fmt.Println(strings.TrimRight("xoxo123xoxox", customFunc)) // xoxo123
```

# TrimSpace

最初と末尾のスペースを全て削除します。

```go
fmt.Println(strings.TrimSpace("　　　123　　　")) // 123
```

# スライド

<script defer class="speakerdeck-embed" data-id="52b0d477d76f4bbc93c81c428a4afc80" data-ratio="1.7777777777777777" src="//speakerdeck.com/assets/embed.js"></script>

# 参考文献

1. [Japanese Version - 100 Go Mistakes and How to Avoid Them](https://100go.co/ja/)
1. [【Go】strings パッケージ関数まとめ](https://zenn.dev/kou_pg_0131/articles/go-strings-functions)
2024/7/15主にITとかセキュリティの記事

相次ぐ不正アクセス、全国で３倍増＝中小企業、認識進まず―コストかけない対策も(7/13)
https://www.risktaisaku.com/articles/-/93365

「Zoom」に最大深刻度「High」の脆弱性 ～最新版では修正済み／Windows版「Zoom Workplace」アプリで不適切な入力検証により権限昇格の恐れ(7/11)
https://nordot.app/1184025909415281422

Appleは98カ国のiPhoneユーザーに有料スパイウェア攻撃について警告(7/12)
https://voi.id/ja/teknologi/397889

ＶリーグＨＰが改ざん被害＝海外カジノへリンク、既に削除―上位表示狙い？　情報流出確認されず(7/13)
https://www.risktaisaku.com/articles/-/93364
https://news.yahoo.co.jp/articles/30cbe5565502d9855ab2732b8a2859f1a5870f53

KADOKAWA 悪質なネットやSNSでの拡散行為473件確認 削除要請へ(7/13)
https://www3.nhk.or.jp/news/html/20240713/k10014510751000.html

ＫＡＤＯＫＡＷＡ、ハッカー集団が流出させた情報の拡散など「悪質な４７３件」に法的措置へ(7/13)
https://www.yomiuri.co.jp/national/20240712-OYT1T50203/

【サイバー犯罪の新たな脅威】BlackSuitランサムウェアグループとは？
https://cybersecurity-park.com/1915/

米ＡＴ＆Ｔにハッキング、1億件の顧客データ流出(7/13)
https://jp.reuters.com/economy/industry/VN62DIV6AJL2NNY53OKSDYVAZI-2024-07-12/

米AT&T、1億1000万人分の顧客情報が漏洩　今年2度目(7/13)
https://www.nikkei.com/article/DGXZQOGN12DUE0S4A710C2000000/

携帯キャリア1億900万人の顧客通信データ、ハッキングで盗まれる事件が米国で発生。(7/13)
https://smhn.info/202407-at-and-t-incident

MYSTIC STORY、不審なメールの流布に注意を呼びかけ「当社の役職員や特定部署を装っている」(7/13)
https://news.livedoor.com/article/detail/26782567/

JAXA内部の情報、ダウンロードされて流出　理事長が会見で謝罪(7/12)
https://news.livedoor.com/article/detail/26780474/

AWS Supply Chain は ESG データコンプライアンスを簡素化します(7/12)
https://aws.amazon.com/jp/blogs/news/aws-supply-chain-simplifies-esg-data-complianceaws-supply-chain-esg/

QA Gathering Day 2024年7月 の開催レポート 〜社内のQAエンジニアの横のつながりを強化するために〜(7/13)
https://blog.cybozu.io/entry/2024/07/13/080000

マイクロソフト、ジェネレーティブAI競争でアマゾンとグーグルを大きくリード シティの調査結果によると(7/12)
https://jp.investing.com/news/stock-market-news/article-432SI-805661

騙されるな！　高校生のポイ活には危険がいっぱい　個人情報の流出や巧妙な有料課金登録(7/13)
https://nordot.app/1184677550393885266?c=724086615123804160

漏洩情報の拡散行為に対する措置ならびに刑事告訴等について(7/13)
https://www.excite.co.jp/news/article/Prtimes_2024-07-13-7006-15001/

総務省 令和6年版情報通信白書 (2024.07.05)(7/13)
http://maruyama-mitsuhiko.cocolog-nifty.com/security/2024/07/post-4f5ec4.html

防衛省不祥事、日米情報共有に影響せず　米国防総省「自衛隊との関係に自信」(7/13)
https://www.sankei.com/article/20240713-4NP443LAKJMMLJBNELM5SQKO2A/

防衛白書（2024年）(7/13)
http://maruyama-mitsuhiko.cocolog-nifty.com/security/2024/07/post-d0e528.html
iphoneでmarkdownを書くなら「 # Type」がおすすめ

iphoneでmarkdownファイルを読み書きするのにいいアプリはないかと探したところ、

「**\# Type**」 [^1]というアプリに出会いました。

「**\# Type**」 はiphoneユーザーのqiitaをよく使う人におすすめできるmarkdown editor アプリだと思います。

以下、おすすめする理由と使い方を紹介します。

# iphoneのファイル内の.md形式のファイルを自由に開いて編集できる

## 使い方

右上のボタンを開けば、iphoneのファイルが開きます。

![fK1U39SctfVxS1X1Gyfnr27neyF3/0cUWQjpc2OWAXNi3.jpg](https://firebasestorage.googleapis.com:443/v0/b/type-c1c71.appspot.com/o/fK1U39SctfVxS1X1Gyfnr27neyF3%2F0cUWQjpc2OWAXNi3.jpg?alt=media&token=ee66e48d-e130-404a-bec1-6c789b8c9f4b)


# qiita への投稿機能付き

## 使い方
右上の共有ボタンから
Qiitaを選びます。

![fK1U39SctfVxS1X1Gyfnr27neyF3/IRHMmCPS5mtKULgi.jpg](https://firebasestorage.googleapis.com:443/v0/b/type-c1c71.appspot.com/o/fK1U39SctfVxS1X1Gyfnr27neyF3%2FIRHMmCPS5mtKULgi.jpg?alt=media&token=3d714d87-d9d6-4b75-a13a-057e18294b10)


qiitaにログイン[^2]すれば、
Qiitaボタンから投稿できるようになります。

![fK1U39SctfVxS1X1Gyfnr27neyF3/f5RiXdim7sEe5KOM.jpg](https://firebasestorage.googleapis.com:443/v0/b/type-c1c71.appspot.com/o/fK1U39SctfVxS1X1Gyfnr27neyF3%2Ff5RiXdim7sEe5KOM.jpg?alt=media&token=195542a1-7cee-4f27-b513-a2460046ff2a)


# markdownを書くときに便利なツールバー

「#」や「*」などよく使う記号がまとまっています。

特に便利なのは、
qiita への数式投稿に便利な「$\Sigma$ 」ボタンです。

一見するとΣ記号を入力するボタンに見えますが、
実は、mathコードブロックを作成するボタンです。

![fK1U39SctfVxS1X1Gyfnr27neyF3/WSrdoM01NYM1sSSS.jpg](https://firebasestorage.googleapis.com:443/v0/b/type-c1c71.appspot.com/o/fK1U39SctfVxS1X1Gyfnr27neyF3%2FWSrdoM01NYM1sSSS.jpg?alt=media&token=30060697-2a99-42b0-953d-7c4b265ec482)

# 結び

この記事も「\# Type」アプリから投稿しました。

ちなみに、アプリのダウンロードは以下のリンクから

<div class="appreach"><img src="https://is1-ssl.mzstatic.com/image/thumb/Purple115/v4/72/12/d5/7212d5b7-e5c8-d434-d4c5-f7a6cc4c8bc8/AppIcon-0-1x_U007emarketing-0-10-0-85-220.png/512x512bb.jpg" alt="# Type" class="appreach__icon"><div class="appreach__detail"><p class="appreach__name"># Type</p><p class="appreach__info"><span class="appreach__developper">fromKK</span><span class="appreach__price">無料</span><span class="appreach__posted">posted with<a href="https://mama-hack.com/app-reach/" title="アプリーチ" target="_blank" rel="nofollow">アプリーチ</a></span></p></div><div class="appreach__links"><a href="https://apps.apple.com/jp/app/type/id1214613873?uo=4" rel="nofollow" class="appreach__aslink"><img src="https://nabettu.github.io/appreach/img/itune_ja.svg"></a></div></div>


[^1]:ググラビリティが低いのが玉に瑕
[^2]:最初googleアカウントでロクインしたところ、googleのセキュリティ上、ブラウザアプリ以外からのwebへのログインを許可してくれなかったので、qiitaへパスワードを設定してからログインした
個人的に気に入ったUnityのアセット #1

ネタ記事です。

### Suburb Neighborhood House Pack

筆者はUnity素人ですが、3Dでリアルな街並みを作れないかなと
"Suburb Neighborhood House Pack"[^1]というアセットを買いました。

これは以下の通り、北米あたりの郊外の街並み（家や家具、庭、木、道路など）のアセットです。値段は高めですが、その分クオリティは高く人気があります。(筆者は$98で購入)

- Asset Storeのページで紹介されている画像[^1]

<img width=600 alt=Asset001 src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490241/4d83f029-b9a4-8000-e0ca-6e003529e3db.png>

<img width=600 alt=Asset002 src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490241/bbeea614-471f-a5eb-3837-ef9730f9d13b.png>

以下、勝手ながら筆者が使ってみての感想（レビュー）を書きたいと思います。

#### アセットのクオリティがとても高い

まず第一に、クオリティが重視されているアセットです。オブジェクトの形状・質感・光沢など、数あるハウスアセットの中でも、よりリアリティを追求して作られていると感じました。ユーザーレビューでは9割のユーザーが⭐︎5をつけるほどで、コメントでもクオリティについて高く評価されていることがわかります。

#### 家具やオブジェの種類は家4, 5軒分くらい

次にオブジェクトの数量ですが、種類は大体4, 5軒分くらいのバリエーションがある思います。ただこれも物によりで、車に関しては2台（赤・グレー）です。以下はグレーの車を置いているところです。

<img width=600 alt=Asset003 src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490241/26633a4e-7bcf-2901-22e5-7969d73a6766.png>

家具は種類が豊富で、カーテンや写真立てのような小物も種類があるので面白いです。ただし全て洋風になります。

<img width=600 alt=Asset006 src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490241/ba470057-a15f-3e26-e248-637f43b09727.png>

インテリアだけではなく、ガーデニングのオブジェクト（花やポット、フェンスなど）も充実しています。

<img width=600 alt=Asset008 src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490241/f2da622e-103d-d8f2-d337-73d143c0fced.png>

<img width=600 alt=Asset009 src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490241/909e58ff-8560-3025-72ec-6c199a17eff3.png>

#### 家は外観だけのオブジェクトで、内部を作るには外壁を組み立てる必要がある

買うまで知らなかったのですが、すでに形ができている家は外観だけのもの（1つのオブジェクト）です。例えば、上のグレーの車を置いた家は外観だけのオブジェクトです。外観だけなので内側に入ることはできません。内側を作りたい場合は、外壁・内壁のオブジェクトがあるので、それらを使って家自体を組み立てることになります。以下は作りかけの家なのですが、カーソルの当たっているのが外壁のオブジェクトです。壁にも窓付きのものなど複数の種類があり、カスタマイズすることができます。

<img width=600 alt=Asset004 src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490241/7bf3426c-c36a-1020-861e-a388ab14a7d5.png>


#### オブジェクトの種類が多く、配置は結構大変
オブジェクトの種類が多く、一から家を作ろうとすると、配置だけでも中々大変だと思います。また、使い方がわかりにくいオブジェクトも幾つかあります。Ceilingという透明なオブジェクトがあるのですが、最初何に使うのか分かりませんでした。Ceilingはその名の通り天井のオブジェクトで、下から見たときだけ色がついており、天井に配置して内装を整えるものでした。ただAssetsの一覧だと透明に見えます。

<img width=600 alt=Asset007 src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490241/0152cb17-7b7a-e6ce-4eb5-0caf4db10fa5.png>

<img width=600 alt=Asset010 src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490241/c2955beb-3c11-dc31-a1ce-30bb4e6cc54c.png>

#### クオリティが高いため処理が重くなる可能性がある
クオリティが高いアセットに共通していますが、処理が重くなるといったパフォーマンスに影響する可能性があります。またGPUに載せる場合はメモリ消費が大きいほうだと思います。詳しくないのですが、実際はゲーム用途よりも個人でハウスアセットを楽しむ人向けだと思っています。

#### NullReferenceExeptionが出ている
アセットのものだと思いますが、筆者の環境では2件の参照エラーが出ています。筆者の用途では今のところ問題はないのですが、気になる場合は事前に調べておいた方が良さそうです。

<img width=600 alt=Asset011 src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490241/55b6f22d-4be2-9109-65a6-bcf046300e89.png>

以上です。"Suburb Neighborhood House Pack"は時間をかけてでもリアルな住宅をスクラッチで作りたいユーザーに向いているアセットでした。

---

Unity 2023.1.18f1
macOS Sonoma 14.5

[^1]:https://assetstore.unity.com/packages/3d/environments/urban/suburb-neighborhood-house-pack-modular-72712
XcodeでArchive実施した際にDerivedData内のキャッシュ名の競合でエラーが発生した件(備忘録)

## 経緯
Flutterアプリ開発時に今まで使用できていたとあるライブラリのバージョンを更新したところ、flutter build iosコマンドは成功するものの、Archive実施時に以下のエラーが発生した。

```
Prepare build
error: Multiple commands produce '/Users/xxx/Library/Developer/Xcode/DerivedData/Runner-fcxhffjmdtbzsbcfbguxqatlgxnj/Build/Intermediates.noindex/ArchiveIntermediates/Runner/IntermediateBuildFilesPath/UninstalledProducts/iphoneos/Library.bundle'
    note: Target 'AAA-Library' (project 'Pods') has create directory command with output '/Users/xxx/Library/Developer/Xcode/DerivedData/Runner-fcxhffjmdtbzsbcfbguxqatlgxnj/Build/Intermediates.noindex/ArchiveIntermediates/Runner/IntermediateBuildFilesPath/UninstalledProducts/iphoneos/Library.bundle'
    note: Target 'BBB-Library' (project 'Pods') has create directory command with output '/Users/xxx/Library/Developer/Xcode/DerivedData/Runner-fcxhffjmdtbzsbcfbguxqatlgxnj/Build/Intermediates.noindex/ArchiveIntermediates/Runner/IntermediateBuildFilesPath/UninstalledProducts/iphoneos/Library.bundle'


Multiple commands produce '/Users/xxx/Library/Developer/Xcode/DerivedData/Runner-fcxhffjmdtbzsbcfbguxqatlgxnj/Build/Intermediates.noindex/ArchiveIntermediates/Runner/IntermediateBuildFilesPath/UninstalledProducts/iphoneos/Library.bundle'
```

対象エラーをもとに類似例がないか確認したところ、今回のバージョン更新後に他ユーザーも同様に発生していることを確認したため、回避策はないか調査を実施した。
(本記事の趣旨とは外れますが、同時にXcodeのバージョンも15.x台にアップデートしたため、その影響の可能性もあるかもしれません。)


# 解決方法(回避策)
原因を確認したところDerivedData内のキャッシュ名の競合が発生していると思われたため、Archive時にキャッシュ場所、名称を変更する方法がないか調べPodfileに「PRODUCT_NAME」と「CONFIGURATION_BUILD_DIR」を変更する内容を記述して再度Archiveを試しました。

```
post_install do |installer|
  installer.pods_project.targets.each do |target|
    case target.name
    when 'AAA-Library'
      target.build_configurations.each do |config|
        config.build_settings['PRODUCT_NAME'] = 'AAA-Library_unique_name'
        config.build_settings['CONFIGURATION_BUILD_DIR'] = '$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/AAA-Library_unique_name'
    when 'BBB-Library'
      target.build_configurations.each do |config|
        config.build_settings['PRODUCT_NAME'] = 'BBB-Library_unique_name'
        config.build_settings['CONFIGURATION_BUILD_DIR'] = '$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/BBB-Library_unique_name'
      end
    end
  end
end
```

結果として競合が発生することなくArchiveを成功させることができました！


## 感想
今回はビルド時の中間ファイルの作成場所を変更しているだけですが、Podfileについては正直雰囲気で実装している面が強く、勉強せねばと感じました。
特にXcodeは躓くとエラー地獄になることが多々あるため、適切な理解を深めていきたいですね。
記事投稿していて変化したマインド

## はじめに
最近、Qiitaで記事を投稿していて感じてきたことがあります。
やれなかったではなくて、やらなかったんだなと。
どういうことかと言うと、何かを学んでみたい、何かを作ってみたいとか、やりたいけどやれないと自分に言い訳をしてきたことです。
でも、記事を投稿しながら、何かにチャレンジするたびに気づきました。
**やらなかったんだなって**

## 記事投稿で変化したマインド
私はまだ知識、経験どれも、ほかの先輩エンジニアと比べるとまだまだです。
何か、できないことがあると一通り調べますが、それでも分からなければ先輩エンジニアを頼ります。
それは悪いことではなく、仕事をしていくうえで、一人で抱え込まず誰かを頼るのは良いことだと思います。
ただ、頼っているだけでは成長しないと感じました。
それはできないからと、頼っていてはいつまでも親鳥を追いかけるひよこです。

### 上司から言われた言葉が響く
「エンジニアは会社で仕事しているだけでは成長できない」
上司の言った言葉が、私の中で響いています。
仕事で、要件定義をして、DB設計をして、プログラミングをしていれば、ある程度の知識は学ぶことができるでしょう。
ただ、本気で自分の目指したいエンジニアになりたいなら、仕事以外でも学ぶことを続けないと真のエンジニアとしては成長できないでしょう。

<font color="red">「これってどうやるんですか？」</font>
いつまでも、そう聞いているのでしょうか。

### 記事投稿を始めて
Qiita Engineer Festaがあり、投稿を続けてみようと思いました。
初日は、何を書こうか悩んでいたのですが、ふと気づきました。
<font color="red">学んでみたいことが自分にはたくさんあったことに。</font>
やらなかったことがたくさんありました。
それをやってみて、記事に書けばよかったのです。

### 変化するマインド
記事投稿を続けていると、なんで今までやってこなかったんだと反省しました。

記事投稿をしていくことで、やりたいことがたくさんあってそれをできていなかったことに気づかされました。
学んで、実践し、記事に書く。

楽しくなってきました。

学ぶって楽しくて、わくわくすることですね。
いつからか学ぶことを避けている自分がいました。でも、学ぶって楽しいことだと改めて気づかされました。

## 終わりに
私は今まで後悔したことはありません。
そのときそのときで自分ができる最善のことをやってきたからです。
ただ、反省はします。
こうすればよかったと次に生かすための反省はします。

**今回はやらなかったことを反省しました。これからは色々なことを学んでいきます。**
【cherry-pick】別repoのcommitを取り込みたい🍒

# はじめに
フォークを開発しているときに「また別のフォークの機能を借りてきたい」みたいな経験、ありませんか？
それ、`cherry-pick`で実現できます。


# cherry-pick って？
異なるブランチの特定コミットだけをいい感じにブランチしてくれる機能です。

イメージとしてはこんな感じ。

![Frame 1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3283241/64f19fa2-77c7-d95a-913e-77ea6c3d1e36.png)


この時、
```
git ccheckout A
git cherry-pick [#1のcommit id] [#2のcommit id]
```
とすることで、#1と#2のコミットのみをBranch Aに取り込むことができます。


# 別リポジトリのcommitを取り込むには
作業の前に、取り込む機能に合わせて作業用のブランチを切っておくといいでしょう。

まず、リモートのリポジトリを追加し、fetchします。

```bash
git remote add [任意の名前] [取り込みたい機能のあるリモートリポジトリのURL]
git fetch [remoteで追加した任意の名前]
```

そして、cherry-pickします。
```bash
git cherry-pick [取り込みたいcommit id]
```

たったこれだけです。

# コンフリクトの解消
cherry-pickを実行すると、場合によって稀にコンフリクトが発生することがあります。

この場合、Gitは自動的にマージできない部分を示してくれますので、それを手動で解決する必要があります。

コンフリクトの解消については、ローカルでのそれと変わらないので、[ここ](https://qiita.com/crarrry/items/c5964512e21e383b73da)あたりを参照するといいでしょう。

https://qiita.com/crarrry/items/c5964512e21e383b73da

# さいごに
cherry-pickを利用することで、異なるブランチやリポジトリから特定のコミットだけを取り込むことができます。
私もmisskeyのフォークを開発している中で何度もお世話になりました。

この記事が誰かのお役に立てれば幸いです。

それでは。
【紹介】「認可」を実装する方法3選_Rails

# はじめに
「認証」は、多くのRailsアプリケーションで、`devise`が使用されているかと思います。
ただ、「認可」に関しては、皆さんどのように実装されていますでしょうか？

今回実装するにあたって、考えた方法を3つご紹介いたします。

:::note warn
「認証」と「認可」の違いに関しては、本記事では解説いたしません。
詳しくは、以下の記事が参考になりますので、ご覧ください。
:::

https://www.sailpoint.com/ja/identity-library/what-is-the-difference-between-authentication-and-authorization/


# 3選の紹介
## ① Pundit ・ cancancan
https://github.com/varvet/pundit

https://github.com/CanCanCommunity/cancancan

上記2つとも、認可周りをサポートしてくれるgemです。
ライブラリを使用すると、実装が楽になるのはとても良いですね。

昔からあるイメージですが、直近（2024/07時点）も更新されているので、安心して使用できそうです。


## ② ymlで管理
ymlファイルを準備して、そこで権限を管理する方法です。
以下は一例になります。

```yml
default: &default
  writer:
    controllers:
      dashboard: 
        - index
        - new
        - create
  admin:
    controllers:
      users:
        - index
        - edit
        - update

development:
  <<: *default
```

役割（ロール）に対して、許可するコントローラーとアクションを記載します。
そうして、`ApplicationController`で、`controller_name`と`action_name`を受け取り、ymlファイルで許可しているかどうかを判断します。

最小限で始められるので、そこまで多く管理しない場合はオススメかと思います。
ただ、機能が多くなったり、権限も多くなってしまうと、ymlファイルでは管理が難しくなりそうです。


## ③ DBで管理
権限用のテーブルを用意して、データとして管理します。

```sh
- admin_usersテーブル
    - role_idを持って、アソシエーションを組む
- rolesテーブル
    - 役割をまとめる
- permissionsテーブル
    - controller_nameとaction_nameを整理する
- role_permissionsテーブル
    - 役割に対して、どのような権限を持たせるかまとめる
```

大体、上記のようになるかと思います。
これも`controller_name`・`action_name`を受け取り、許可されているかDBをみて判断する実装をします。

これのいいところは、管理画面に機能を作成すれば、**リリース無し**で権限の付与をすることができます。
DB管理のメリットではあるかと思います。

# まとめ
以上、「認可」を実装する方法を3つまとめました。
そのアプリの規模感によっても、実装する方法は変わってくるかと思います。

個人的には、以下の感じに思っています。

- ミニマムに始めるなら
    - ymlで管理
- 今後しっかり管理していきたい
    - Pundit・cancancan
    - DBで管理

上記以外にも、実装する方法はたくさんあるかと思います。
今回はあくまでも例ですので、ご自身の実装しているシステムに合った、あるいはチームで相談の上、実装方針をすり合わせてください。

最後までご覧いただき、ありがとうございました。
社内でなんちゃってVをやっていたので、配信ソフトを公開します。


ここ2年くらい、
社内のオンライン会議はだいたいアバターで通してた私の
社内Web会議で利用しているソフトを公開します。

# この記事が言いたいこと
ビール4本飲んで酔っ払って
[VTuberなんだが配信切り忘れたら伝説になってた第二話](https://animestore.docomo.ne.jp/animestore/ci_pc?workId=27162&partId=27162002)見たら、
トップ声優のV再現が素晴らしかったので、
「技術情報の共有」という建付けで、
Qiita記事で[VTuberなんだが配信切り忘れたら伝説になってた](https://animestore.docomo.ne.jp/animestore/ci_pc?workId=27162)の宣伝をします。

酔ってるんで、技術目的以外のQiita使いかたしてもいいですよね！！？
技術情報「も」書くんで。。。
みんなも「[VTuberなんだが配信切り忘れたら伝説になってた第二話](https://animestore.docomo.ne.jp/animestore/ci_pc?workId=27162&partId=27162002)」を見よう！！！

## [VTuberなんだが配信切り忘れたら伝説になってた第二話](https://animestore.docomo.ne.jp/animestore/ci_pc?workId=27162&partId=27162002)の感想

やっぱりトップ声優すげぇなぁと。
Vで「奇跡」と呼ばれるような瞬間の演技を、
狙って出せるのがとても素晴らしいです。
いや、Vの人も計算して仕込めば出せるんでしょうけど。
でも、狙って再現できるのはすげぇ！

というわけで、
多少Vかじった方は、
[VTuberなんだが配信切り忘れたら伝説になってた第二話](https://animestore.docomo.ne.jp/animestore/ci_pc?workId=27162&partId=27162002)
見るのをおすすめします。

# 技術情報
## V配信の経緯とか
5年くらい前にV関係の企画をした関係で、
2～3年前から、
社内のオンライン会議はアバター使ったVっぽい感じに統一しています。
社外でも許されそうな場はアバター使ってる感じ。
というわけで、
その配信環境を共有します。

## 配信環境
### 利用PC
社給PCです。
GPU積んでないので複雑な事はできませんが、
以下のソフトくらいなら同時で動かして配信できます。

#### 社給PC君
・CPU：Core-i5 4コア8スレッド
・メモリ：16GB
・グラフィック：インテル UHD グラフィックス
・GPU：なし
・備考
　・ごく普通の業務用スペックです。
　・GPU積んでません。
　・普通のソフトは動くけど、重いソフトは重いです。

### 配信ソフト
#### Vを動かすソフト：VMagicMirror
・VMagicMirror：https://malaybaku.github.io/VMagicMirror/
顔だけトラッキングモードを利用しています。
VRMアバターを用意すれば動きます。

##### ハンドトラッキングまでしたい場合
・VMaggicMirrorのトラッキング
・Webcam Motion Capture
を利用すれば動くことはわかっていますが、
いろいろ試した結果、
CPUのみ（GPUを利用しない場合）は
リアルタイムトラッキングは難しいと判断しています。
自宅PC（[アプライド i5-13500君](https://qiita.com/kit/items/ddd1e09d590f7a92dc01)）を利用しているときは、
ごくたまにハンドトラッキングありで配信しています。

#### VRMアバター制作：VRoidStudio
・VRoidStudio：https://vroid.com/studio
デフォルトアバターに近いアバターをつくって、
VRM書き出しして使っています。

#### キャプチャ＆仮想カメラ：OBS Studio
・Obs Studio：https://obsproject.com/ja
VMagicMirrorの画面を
OBSでキャプチャして仮想カメラに配信しています。

### Web会議（配信）ソフト
・Teams
・Zoom
大抵の場合はカメラ設定の変更で動作します。
仮想カメラを禁止していない配信ソフトであればほぼ大丈夫です。

### 音声環境
普通のマイクを利用しています。
ガチV配信する・歌う場合はちゃんとしたマイク使ったほうが良さそうですが、
普通の会議で利用する場合は
Web会議対応しているマイクであれば大丈夫です。

#### ボイス変換について
私は利用していません。
ソフトウェアベースの変換だとGPU積んでないマシンは割と厳しいと思います。
ハードウェアベースの変換はマジわかんないです。ごめんなさい。

## 配信における注意事項とかノウハウとか
どういう場合に発生しているのかわからないですが、
上記の配信環境だと、
・5回に1回くらいのペースでビデオ配信が乱れる
・20回に1回くらいのペースでTeams・Zoomが落ちる
というトラブルが発生します。
トラブルは発生するという意識の元、
・ボイスだけの会議に切り替える
・別端末で入ってチャットだけでも確保する
・重要な会議は2端末以上で入って通話を確保する
などの対策をしておいたほうがいいです。

## 配信デモ
後日取ろうかね。

## ワイが使ってるアバター
今はこの子。
![img_05_tcm102-7492482_tcm102-2750236-32.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154954/f68b89a0-cc4b-4f93-f84f-af8b5384113a.jpeg)


# 最後に
## 最近の3DアニメやV関係のアニメが楽しい
・ガールズバンドクライ
・VTuberなんだが配信切り忘れたら伝説になってた
等、界隈をちょっとかじった人的には
とても楽しいアニメが最近多いです。
やっと、一般視点として、
・見られるクオリティになってくれた
・伝えたいことを伝えるための表現方法として足るものになってくれた
という印象。5年前に夢見た世界が来てくれました。
アニオタとしてはこれからさらに期待ですね。
（ちな、昔あった、
　「バーチャルさんは見ている」は流石に面白くなかった。早すぎたんだ。。。）
たった1コマンドで完結！お手軽なDocker導入方法

# はじめに
Docker、使ってますか？
私はかなり使い込んでいます。

Dockerの導入はGPGキーを保存して、リポジトリを追加して～と、地味にめんどくさいですよね。
特に、VMを複数立ててその上にDockerを構築する～みたいなことを繰り返していると鬱になってしまいそうなくらい面倒です。

この記事では、そんな面倒なDockerの構築をたった1つのコマンドでできるような方法をご紹介します。

# "get.docker.com"を覚えよう
https://get.docker.com にてDocker公式が配布しているシェルスクリプトを実行すると、実行しているディストーションを自動で判別して適切なものを適切な形でセットアップしてくれます。便利ですね。


# つかいかた
## 準備
インストールする環境に`curl`が導入されているか確認します。

```bash
which curl
```

もし、導入されていなければ導入してください。
aptが使える環境であれば、

```bash
sudo apt install curl
```

で導入が可能です。

## 導入
```bash
curl https://get.docker.com/ | sudo sh
```
これだけでインストールが完了します。
簡単ですね。

TLDをioと間違えないようにしてくださいね。
一応、リダイレクトはされるようですが、curlがうまくうごきません。

ちなみに、社内環境などプロキシが設定されている環境では、インストール中にapt-keyコマンドが失敗することがあるようです。
そのような場合、正常に動作させるためには以下のコマンドでGPGキーを追加してあげるとうまくいきます。

```bash
curl -fsSL https://get.docker.com/gpg | sudo apt-key add -
```


# さいごに
以上の手順で、簡単にDockerをインストールすることができます。
この方法を使えば、面倒な手作業を省き、素早くDocker環境を構築することが可能です。
ぜひ試してみてください。

それでは。


# 参考
https://docs.docker.com/engine/install/ubuntu/#install-using-the-convenience-script
https://github.com/docker/docker-install
Arrow function っていつ使う？

## 結論

メソッド内でコールバック関数を書くときは、Arrow function を使うと便利です。

## 理由

Arrow function の `this` は、暗黙的な引数として `this` を受け取らず、関数が定義されたスコープの `this` を参照します。
この特性により、Arrow function を使うと単純に `this` を使うことができます。

例えば、次のコードを見てください：

```javascript
class Timer {
  constructor() {
    this.seconds = 0;
  }

  start() {
    setInterval(function () {
      this.seconds++;
      console.log(this.seconds);
    }, 1000);
  }
}

const timer = new Timer();
timer.start(); // ここでの this は Timer インスタンスを指していないため、エラーになります。
```

上記の例では、通常の function を使うと `this` が `setInterval` のコンテキストを指すため、`this.seconds` は定義されていないというエラーになります。

一方、Arrow function を使うと次のように動作します：

```javascript
class Timer {
  constructor() {
    this.seconds = 0;
  }

  start() {
    setInterval(() => {
      this.seconds++;
      console.log(this.seconds);
    }, 1000);
  }
}

const timer = new Timer();
timer.start(); // ここでの this は Timer インスタンスを指すため、秒数が正しくカウントされます。
```

このように、Arrow function を使うと、`this` が Timer インスタンスを正しく指すため、コールバック関数内でも簡単に `this` を扱うことができます。

## メソッド内でコールバック関数を書くとき以外は？

複雑な`this`のバインディングや、プロトタイプチェーンを使うときを除いて、通常の function と Arrow function のどちらを使っても問題なさそうです。

個人的には、上記の通りthisの扱いが簡単になるのでArrow functionに統一しても良いかなと思っています。

現場に合わせておくのが無難かもですね。

## 参考

<https://jsprimer.net/basic/function-this/>
WSL2内にNode.jsが動作するDocker環境を用意した

# これはなに？

WSL内に、Nodeが動作するDocker環境を作成してみました

# 環境

- Windows11
    - WSL2
        - Ubuntu 20.04
    - Docker Desktop
- VS Code
    - Remote WSL

# 準備

必要なファイルを作成します

![folder.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266407/8f566143-760a-aad9-ef75-120846987efe.png)

## package.json

ファイルがないので、以下のコマンドで作成しました

```console
$ yarn init
```

作成されたファイルを少し修正して以下のようにしました

```json
{
  "name": "test",
  "version": "1.0.0",
  "description": "",
  "main": "main.js",
  "scripts": {
    "start": "node main.js"
  }
}
```

## yarn.lock

一旦空ファイルで用意しました

## Dockerfile

以下に、部分ごとに説明します
```dockerfile
FROM node:lts-bullseye-slim
WORKDIR /app

COPY package.json yarn.lock ./
RUN yarn install

COPY . .
CMD [ "yarn", "start" ]
```

### ベースイメージ

```dockerfile
FROM node:lts-bullseye-slim
```

**lts**

LTS（Long-Term Support）
ソフトウェアの特定の版（バージョン）を長期間安定的にサポートする
開発元によってそのような長期サポートが約束されたバージョン

https://e-words.jp/w/LTS.html

**bullseye**

Debianのコードネームになります
- bookworm: Debian12
- bullseye: Debian11

https://ja.wikipedia.org/wiki/Debian%E3%81%AE%E3%83%90%E3%83%BC%E3%82%B8%E3%83%A7%E3%83%B3%E5%B1%A5%E6%AD%B4

**slim**

公式に説明がありますが、node を実行するのに必要な最小限のパッケージのみ含まれている

> node:<version>-slim
This image does not contain the common packages contained in the default tag and only contains the minimal packages needed to run node. Unless you are working in an environment where only the node image will be deployed and you have space constraints, we highly recommend using the default image of this repository.

https://hub.docker.com/_/node

### パッケージのインストール

```dockerfile
COPY package.json yarn.lock ./
RUN yarn install
```

https://qiita.com/righteous/items/e5448cb2e7e11ab7d477

https://qiita.com/yamatai12/items/9e80d3221afc8e2433bf

### アプリケーションに必要なファイルをコピーして、実行

package.jsonに記載したscriptsのコマンドを実行します
```dockerfile
COPY . .
CMD [ "yarn", "start" ]
```

## main.js

`Hello world`を表示します
```js
console.log("Hello World!");
```

# イメージの作成

VS CodeのTerminalで以下のコマンドを実行します
```console
$ docker build . -t node
```

# コンテナ起動

作成したイメージからコンテナを作成して起動します
※作成したコンテナは終了したら削除するようにしています

実行されて `Hello World!`が表示されました
```console
$ docker run --rm node

yarn run v1.22.22
warning package.json: No license field
$ node main.js
Hello World!
Done in 0.06s.
```

# 最後に

WSL内でDockerコンテナが起動して、Node.jsが動作する環境を用意することができました
誰かの参考になれば幸いです:relaxed:
WSL2 + VS Code(Remote-WSL)でGitリポジトリをクローンしてみた

# これはなに？

WindowsにWSL2をインストールした状態の環境にGitリポジトリをクローンしてみました
VS Codeを使って作業します

# 環境

- Windows11
    - WSL2
- VS Code
    - Remote WSL

以下の記事を参考にしながら、必要な環境は用意しました

https://qiita.com/zakoken/items/61141df6aeae9e3f8e36

https://zenn.dev/s_ryuuki/articles/4b9631674adea4

# Githubに新しいリポジトリを作成

プライベートリポジトリを作成します

![screencapture-github-repositories-new.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266407/a176703a-67d5-262e-500a-e458adc3e9ea.png)

# WSL上に作成したリポジトリをCloneします

VS Codeから作成したいと思います

1. VS Codeの左下にあるリモートウィンドウをクリックしてメニューから`WSLへの接続`を選択します
![vscode_remote_wsl.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266407/4b4d55ee-cefd-149a-5bcd-46135afb80ef.png)　![remote_window.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266407/3d2ee998-3ca9-d7ce-4eea-e938974d8cfc.png)

2. VS Codeのメニューから`Terminal`を起動します
![vscode_terminal_new.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266407/a4f73cb6-a46b-4afb-b663-e5e63d99a2b9.png)

3. WSL内の作業スペースでリポジトリをクローンします
    - 下のコマンドは例になります
    ```console
    $ git clone git@github.com:xxxxxx/test.git
    ```

4. VS Codeのエクスプローラーから`OpenFolder`を選択して先ほどクローンしたフォルダーを選択します
![vscode_openfolder.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266407/eadd5863-f780-1ac5-c304-07181fc1aef7.png)

5. これでWSLに接続している状態のVS Codeが完成しました

# 最後に

自分がよくWSLを使った初期のプロジェクトの作成方法を忘れてしまうため、今回まとめました
誰かの参考になれば幸いです:relaxed:
Goのfor文について

## Go言語のfor文の使い方と注意点
Go言語には、一連のステートメントを繰り返すための強力な制御構文であるfor文があります。この記事では、for文の基本的な使い方から、for-range文、無限ループ、そして注意点について詳しく解説します。
## 基本的なfor文の使い方
for文は、初期化、条件式、後続処理の3つの部分から構成されます。以下は基本的なfor文の構文です。
```go:goファイル
for i := 0; i < 10; i++ {
    fmt.Println(i)
}
```
```:結果
0
1
2
3
4
5
6
7
8
9
```
### 条件式のみのfor文
他の言語のwhileループに似た形式で、条件式のみを使ったfor文も可能です。
```go:goファイル
i := 0
for i < 10 {
    fmt.Println(i)
    i++
}
```
この記法でも0から9までを出力します。
### 無限ループ
無限ループは、条件式を書かずにforを使用することで実現できます。システムの監視やユーザーの入力待ちなどに使われます。
```go:goファイル
for {
    fmt.Println("Loop")
    break
}
```
無限ループはbreakもしくはreturnで関数から抜けるまで永遠に続きます。
### for-range文
for-rangeループは、Goで配列、スライス、マップ、文字列、その他のコレクションを反復処理する簡潔な方法です。
#### 配列の例
```go:goファイル
package main

import "fmt"

func main() {
    numbers := [5]int{1, 2, 3, 4, 5}
    for i, number := range numbers {
        fmt.Println(i, number)
    }
}
```
```:結果
0 1
1 2
2 3
3 4
4 5
```
##### スライスの例
```go:goファイル
package main

import "fmt"

func main() {
    fruits := []string{"apple", "banana", "cherry"}
    for i, fruit := range fruits {
        fmt.Println(i, fruit)
    }
}
```
出力結果は以下の通りです。
```:結果
0 apple
1 banana
2 cherry
```
##### マップの例
```go:goファイル
package main

import "fmt"

func main() {
    grades := map[string]int{"Alice": 85, "Bob": 90, "Charlie": 95}
    for name, grade := range grades {
        fmt.Println(name, grade)
    }
}
```
出力結果は以下の通りです（順序は保証されません）。
```:結果
Alice 85
Bob 90
Charlie 95
```
文字列の例
```go:goファイル
package main

import "fmt"

func main() {
    message := "Hello, world!"
    for i, char := range message {
        fmt.Println(i, string(char))
    }
}
```
```:結果
0 H
1 e
2 l
3 l
4 o
5 ,
6  
7 w
8 o
9 r
10 l
11 d
12 !
```
### for文の注意点
##### 空のループはCPUを消費する
何もしない空のループはCPUを無駄に消費してしまいます。これを避けるためにスリープ関数やチャネルの操作などを使用してループを制御しましょう。
```go:goファイル
for 条件 {
    time.Sleep(1 * time.Second) 
}
```
#### 無限ループは極力避ける
無限ループはCPUリソースを大量に消費する可能性があります。どうしても無限ループの実装が必要な場合はスリープ関数などの待機処理と合わせて使いましょう。
#### スコープに注意
forループで宣言された変数はループの外ではアクセスすることができません。ループ内で宣言した変数をループ外で使用したい場合は、ループの外で予め宣言しておく必要があります。
```go:goファイル
var i int
for i = 0; i < 10; i++ {
   // ループ内の処理
}
```
#### for range使用時の変数再利用
for rangeでは同じ変数が何度も再利用されます。そのためループ内でゴルーチンを起動する際に注意が必要です。変数の現在の値をゴルーチンに渡す場合は、値をローカル変数にコピーする、もしくは直接引数として渡す必要があります。
```go:goファイル
for _, v := range values {
    go func(val Type) {
        // valを使用
    }(v)
}
```
## まとめ
Go言語のfor文は非常に強力で柔軟な制御構文です。基本的なfor文からfor-range文、無限ループまで、さまざまな用途に対応できます。ただし、使用する際にはCPUリソースの消費や変数のスコープに注意する必要があります。
【Rails6.1】デプロイ時のZeitwerk::NameError

## はじめに
自動デプロイを設定していたのですが、mainにマージした後、確認してみたらサイトが表示されなくなってしまいました。

おかしいと思って、GithubのActionsを確認すると「×」になっていてデプロイに失敗していたことが発覚。

原因は単純なことだったので簡単に記録しておきます。

## エラーの解消

Githubのデプロイに失敗したActionsで表示されていたメッセージがこちらです。

```
***/app/controllers/admin/searches_controller.rb to define constant Admin::SearchesController, but didn't (Zeitwerk::NameError)

      raise Zeitwerk::NameError.new(msg, cref.last)
      ^^^^^
```

どうやら「searches_controller.rb」に問題があるようです。
確認してみるとファイルの中は以下のようになっていました。

```ruby:searches_controller.rb
# 後で消す

# class Admin::SearchesController < ApplicationController
#   before_action :authenticate_admin!

#   def search
#   :
#   :
```
※これは、このコントローラは使う必要がなくなったはずだけど、念のためコメントアウトして残しておいて、様子を見て問題がなければ消そうと思っていたが故の記述です。

ZeitwerkはRailsの命名規則にのっとって自動でファイルを読み込んでくれるGemです。

https://railsguides.jp/classic_to_zeitwerk_howto.html

開発環境では問題なく動いていたので良しとしていたのですが、恐らく、「searches_controller.rb」というファイルには「SearchesController」という名前が設定しているはずなのに見つけることが出来なくてデプロイ時に起動をストップさせたのでしょう。

このファイルは不要なことを確認したので、削除して再びmainにpushするとデプロイに成功してサイトを表示することができました。

エラーで表示されていたように、ただの「NameError」でした。


## ちなみに余談

今回のデプロイに失敗してしまう問題は、解決したのですが、デプロイ時のメッセージに気になる記述が…

```
warning package-lock.json found. Your project contains lock files generated by tools other than Yarn. It is advised not to mix package managers in order to avoid resolution inconsistencies caused by unsynchronized lock files. To clear this warning, remove package-lock.json.
```

>警告 package-lock.json が見つかりました。プロジェクトには、Yarn 以外のツールによって生成されたロック ファイルが含まれています。同期されていないロック ファイルによって引き起こされる解像度の不一致を避けるために、パッケージ マネージャーを混在させないことをお勧めします。この警告をクリアするには、package-lock.json を削除します。

これで止まってしまうということはなかったのですが、ちょっと気になる内容だったので調べてみることにしました。

https://zenn.dev/mo_ri_regen/articles/package-lock-yarn-lock

どうやら、「package-lock.json」と「yarn.lock」が共存しているとエラーになることがあるようです。

https://qiita.com/adgjmptwgw/items/cb08aa4a33fecc478422

「package-lock.json」と「yarn.lock」は両者ともパッケージのバージョン管理をしてくれるもので、npmで導入するかyarnで導入するかによって管理するファイルが変わるようです。

確かに、うっかりnpmとyarnで同じライブラリを別のバージョンで入れてしまったりしたら不具合が起きるのかも…？
パッケージ管理の際も、npmかyarnで統一したり、注意が必要そうです…。

## おわりに
開発時には問題なかったはずなのに、本番環境でエラーが出ると焦ってしまいます。

よくよく確認してみると単純なことが原因だったりするので、エラーが出たときこそ落ち着いて対応する必要があるなと感じました。
カメラの映像をCanvas要素に描画する

# はじめに

フィルターをかけたり、画像処理を加えたりするために

webcamの映像をCanvas要素に描画する方法をまとめておきます。

# プロジェクトの作成

getUserMediaでvideoの権限を要求する。

videoのstreamをvideo.srcObjectに設定。

loadeddataのEventでCanvas要素に描画する。

```Javascript:index.js

// 権限を要求
navigator.mediaDevices.getUserMedia({ video: true, audio: false })
  .then(stream => {
    const video = document.getElementById('myVideo'); 
    const canvas = document.getElementById('myCanvas'); 
    const ctx = canvas.getContext('2d');
    video.srcObject = stream;
    // 描画を開始
    video.addEventListener('loadeddata', () => {
      canvas.width = video.videoWidth;
      canvas.height = video.videoHeight;
      function draw() {
        ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
        requestAnimationFrame(draw);
      }
      draw();
    });
  })
  .catch(err => {
    console.error('エラー:', err);
  });

```

下記のようにHTMLを設定する

```HTML:index.html

<video style="visibility: hidden;height: 0;width: 0;position:
fixed;pointer-events: none;" id="myVideo" muted autoplay playsinline></video>
<canvas id="myCanvas"></canvas>
<script type="module" src="./index.js"></script>

```

これで実装完了！！


# まとめ

Video要素を使う機会がなかったのでいい勉強になりました。📝

上記をベースにしてフィルターや画像処理を実装してみたい。💪

※間違い等ありましたら、ご指摘いただけると助かります。
「オブジェクト指向は1回忘れよう。10分でわかる設計のツボ「高凝集/低結合」」を見ました

## はじめに

DDDの権威である松岡幸一郎さんの「オブジェクト指向は1回忘れよう。10分でわかる設計のツボ「高凝集/低結合」」という動画を見たので感想とその内容をアウトプットしようの記事です。

該当Youtubeは以下

https://www.youtube.com/watch?v=hX9kCwdR8dc

記事の内容は以下のリンクにございました

https://little-hand-s.notion.site/10-d85b38b1846048cea37a015a52636d53

### どうしたら設計をよくできるのか

> - エンジニアの永遠のテーマの一つ
> - 参考にすべき原則、パターンはたくさんある
>     - オブジェクト指向の原則
>         - SOLID
>     - デザインパターン
>     - その他原則
>         - 抽象度統一原則
>         - KISS
>     - おすすめ書籍
>         - プリンシプルオブプログラミング
>             - 色々な原則が載っている
>         - クリーンコード
>             - 具体例込みで即効性のある原則が紹介されている


そもそも原則確かに多いなと思う、それを知らないとコミュニケーションがそもそもできないみたいなこともあり
ハードルが高いな〜事前に詰め込むべき知識が多すぎないか...と新人の時は思っていた。

### 色々考えた結果、これかなというのを見つけた

> - 一つ抑えるだけで、複数の利点を得られる物があるらしい
> - それが **「高凝集、低結合」**

# こんなにいいことがあるらしい

> 英語版Wikipediaより

> - 理解容易性: コードを読んで理解しやすくなる
> - 拡張性: コードを修正、拡張しやすくなる
> - 信頼性: 修正時にバグを埋め込みにくくなる
> - 再利用性: 同じコードを別の場所で再利用しやすくなる
> - テスト容易性: テストを実施しやすくなる

そんな大事な原則があったなんて、まずはそれを理解しよう！

### 凝集度、結合度とは

> - ソフトウェアの品質を表す指標(メトリクス)
> - 1974年に提唱され、以後ソフトウェア工学の標準用語となった

#### 凝集度

> - モジュール内の要素同士がどれだけ関連しているかを示す指標
> - クラスの責務、クラスのメソッドとデータの関連の強さ
> - 責務とは、「そのクラスは何をする(表す)クラスか」という問いへの答え
> - 高い方が良い (高凝集)

#### 結合度

> - モジュール間の依存度の高さを示す指標
> - 依存度が高い→依存先の修正の影響を受けやすくなる
> - 低い方が良い(低結合、疎結合)

凝集度と結合度の意味を理解した！

凝集度は高ければ高いほど良い◎
クラスの責務が明瞭で、誰が見てもこのクラスがどのようなことをするクラスかわかるもの、
人に説明するときに悩まないもの。
**クラスの責務と属性とメソッドがちゃんと関連しているかを説明できること。**
「Util」や「Service」の名前がついていると怪しい。

結合度は低ければ低いほど良い◎
振る舞いが外側から推測が難しいものは依存度が高い、
一発で見てわからない、コードを先まで読み解かないといけなくなっていて
読んでいる人がその知識を知っていることが前提になってしまっているようなコードは
結合度が高くなっている。

### ドメイン駆動設計との繋がり

> - 責務・凝集度の話は設計を考える上で常に重要
> - アーキテクチャのレイヤー化時に考えることは
>     「**レイヤーによる**責務の切り分け」
> - エンティティ、リポジトリなどの設計を考えることは
>      「**クラスによる**責務の切り分け」
> - とにかく責務を考え、凝集度を上げる
> - この原則でかなりの領域をカバーできる


アーキテクチャのレイヤーで気にする責務

- ドメイン層はドメインのルールや制約を表現する
- ユースケース層はユースケースを組み立てる
- プレゼンテーション層はクライアントとの入出力をユースケース層との間で変換する
エンドポイントを定義する

エンティティ、リポジトリなどの設計を考える責務

- エンティティや値オブジェクトはドメインモデルを表現するのが責務
- リポジトリはそのドメインモデルの永続化層とやりとりする

### クラス設計時に考えるべき問い

> - まずは責務を考える
>     - そのクラスの責務は何か？そのクラスは何をする(何を表す)クラスか？
>     - そのクラスのメソッド、属性は、責務とあっているか？

## さいごに

設計のレビューなどをするときに気にすべきツボを学ぶことができました。
シンプルだけど本質！といった感じで
頭ではわかったけどこれを実践に移すには経験が必要だなと感じています。
**高凝集、低結合** というワードも初めて知ったので常に気を使いながら設計をしてきたいです。