OmniAICreator/Qiita-1.07M huggingface dataset:
windows11で、sketchup6 その72

# 概要
windows11に、sketchup6を入れてみた。
rubyで、3Dを書く。
練習問題、やってみた。

# 練習問題
セレクトされたグループを三面図のように配置するRUBYスクリプトを書け。

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/f726b705-9fdf-4b57-a6aa-eda2455041b4.png)

# サンプルコード

```
def sanmen
	ss = Sketchup.active_model.selection
	sents = []
	ss.each { |e|
		sents.push(e)
	}
	copy = Sketchup.active_model.active_entities.add_group(sents)
	copy_a = Sketchup.active_model.active_entities.add_group(sents)
	trans = Geom::Transformation.translation [-40, 0, 0]
	copy_a.transform! trans
	trans = Geom::Transformation.rotation copy_a.bounds.center, X_AXIS, 90.degrees#red
	copy_a.transform! trans
	trans = Geom::Transformation.rotation copy_a.bounds.center, Z_AXIS, 45.degrees
	copy_a.transform! trans
	copy_b = Sketchup.active_model.active_entities.add_group(sents)
	trans = Geom::Transformation.translation [-20, -30, 0]
	copy_b.transform! trans
	trans = Geom::Transformation.rotation copy_b.bounds.center, Y_AXIS, 90.degrees#green
	copy_b.transform! trans
	trans = Geom::Transformation.rotation copy_b.bounds.center, Z_AXIS, 45.degrees
	copy_b.transform! trans
	copy_c = Sketchup.active_model.active_entities.add_group(sents)
	trans = Geom::Transformation.translation [20, -30, 0]
	copy_c.transform! trans
	trans = Geom::Transformation.rotation copy_c.bounds.center, Z_AXIS, 90.degrees#blue
	copy_c.transform! trans
	trans = Geom::Transformation.rotation copy_c.bounds.center, Y_AXIS, 90.degrees
	copy_c.transform! trans
end
```

以上
AutoCAD VBA 選択フィルタ (3) - FilterDataを作るFunction -

# はじめに

SelectionSet.Selectメソッドや .SelectOnScreenメソッドでは、選択フィルタを設定することが可能です。公式ヘルプのサンプルコードの作り方では毎回書くのが面倒なので、それならFunctionプロシージャ化してしまおうというのが今回の目的です。前回はFilterTypeについて解説しました。今回はFilterDataについて解説します。

# FilterData(Variant型配列)を作るFunction

## 概要

- 配列の要素は、コンマ区切りテキストを入力し、Split関数を使って配列化します
- 配列の各要素が数値などと見做せるか判定後、型変換したりしなかったりして別の配列に格納します
- 戻り値となる配列は Selectメソッド等の引数なので、Variant型とします

## 戻り値となる配列の要素について

https://help.autodesk.com/view/OARX/2026/JPN/?guid=GUID-2553CF98-44F6-4828-82DD-FE3BC7448113

上記の「グループ コードの値のタイプ リファレンス(DXF)」にあるように、各要素には、String型、Integer型、Long型、LongLong型、Double型、Boolean型が格納されます。

今回のサンプルコードには、LongLong型とBoolean型への型変換は含んでいません。また、角度はDouble型のラジアンである必要がありますが、これも含んでいません。

## コード

```vb:AutoCAD VBA - FilterDataを作成するFunction
Public Function uMakeFilterData(ByVal aTextByComma As String) As Variant
  
  Dim uFilterTypeArrayStr   As Variant ' Split関数の結果を格納する配列
  Dim uFilterTypeArrayVar() As Variant ' 様々な型の要素を格納する動的配列
  
  ' Splitで配列化(要素はすべてString値) ※添え字の最小値は 0
  uFilterTypeArrayStr = Split(Expression:=aTextByComma, Delimiter:=",")
  
  ' 動的配列の要素数確定
  ReDim uFilterTypeArrayVar(UBound(uFilterTypeArrayStr))
  
  ' 配列の要素を文字列以外は型変換して動的配列に移す
  For n = LBound(uFilterTypeArrayStr) To UBound(uFilterTypeArrayStr)
    ' 要素が数値か否か
    If IsNumeric(uFilterTypeArrayStr(n)) = True Then
      ' 数値の場合：小数点を含むか否か
      If InStr(uFilterTypeArrayStr(n)) > 0 Then
        ' 小数点を含む：→ Double型
        uFilterTypeArrayVar(n) = CDbl(uFilterTypeArrayStr(n))
      Else
        ' 小数点を含まない：→ Long型
        uFilterTypeArrayVar(n) = CLng(uFilterTypeArrayStr(n))
      End If
    Else
      ' 要素が数値でない：→ Variant型
      uFilterTypeArrayVar(n) = CVar(uFilterTypeArrayStr(n))
    End If
  Next

  ' 戻り値
  uMakeFilterData = uFilterTypeArrayVar

End Function
```

# おわりに
前回と今回でSelectionSet.Selectメソッド等の引数となるFilterTypeとFilterDataの配列を作るFunctionの解説をしました。角度の判定については、皆さん工夫してみてください。気が向いたら私のやり方を載せるかも……

https://qiita.com/sewege11/items/ede36073251e05e41c63

https://qiita.com/sewege11/items/a1865544f79e220374e5
Weekday Coffee Morning #3 - Jazz, Bossa, Piano, Rimshot【Suno AIで作曲】【動画 3分14秒】【YouTubeチャンネルからの転記です】

この記事は、わたしの[YouTubeチャンネル](https://bit.ly/Yamanaka-YouTube "Living without things. 持たない生き方 手放す生き方")にある公開動画を転記しております。
( どこかのタイミングで、プログラミング-Google Apps Script or iPaaS-Zapier をつかって自動転記させる予定です )

転記のための時間コストを少なくしたいので、文字装飾( Markdown記法 )を極力つかわずに書いております。

こちらが動画内容です👇

***

![⭐02 YouTubeサムネイル & 再生中の画像 Suno AI _ Weekday Coffee Morning #3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386308/1ad54594-452f-4730-b80d-7162c99ddc1f.png)




* # 動画URL
    * https://youtu.be/NzulIoPcbB4

<br>

* # 動画タイトル
    * Weekday Coffee Morning #3 - Jazz, Bossa, Piano, Rimshot【Suno AIで作曲】【動画 3分14秒】

<br>

* # 動画の説明欄(一部を抜粋)

撮影日 = 2025-04-14(月)

Suno AIとは、文章から音楽を生成することができるAI( Text-to-Music-AI )です。
わたしは、2024-04-02(火)に初めてSuno AIで有償プランを契約してから、時々楽曲をつくって遊んでいます。

🎦【Suno AI】文章から音楽を生成するAI( Text-to-Music-AI )で、3分間で2曲、6分間で4曲作りました【試聴可能】1)伴侶の曲 2)税理士の曲【動画 16分11秒】
https://youtu.be/QKfhk4HgQ_g

🎦“Suno AIでつくった楽曲”シリーズ
https://www.youtube.com/playlist?list=PLpQhBHT4oghMLdiSVqwvSs_Z5y0H4VGOe

🎦“効果的にSuno AIを活用するヒント”シリーズ
https://www.youtube.com/playlist?list=PLpQhBHT4oghPuaNOVZn-N53wVvsBkeHdI


今回は、Suno AIで作曲し、 WAV 出力した楽曲を動画に仕上げました。

2025年3月～4月、毎朝のように訪れていた『WEEKDAY COFFEE ROASTERS』( https://bit.ly/Whatis-WEEKDAY-COFFEE-ROASTERS )さん。
この楽曲の舞台は、こちらのお店です。
美味しいエスプレッソやマキアートのおかげで、気が重かったプロジェクトの様々なタスクもはかどり、いつの間にか楽しみながら乗り切ることができました。
歌詞には、わたしが実際に口にした飲み物のメニューや、印象的だった会話、お店の空気感を織り込みました。
そんな素敵な時間を思い出しながら、感謝を込めて制作したファンメイドテーマソングです。

「毎朝美味しいコーヒーと、穏やかな時間をありがとうございました。ごちそうさまでした！」

この楽曲をぜひ聴いてみてください。
ぜひ、温かいコーヒーを飲みながら楽しんでください。
そしてぜひみなさんも、大好きなお店やブランドや企業への感謝を込めて、オリジナル曲をつくってみてください！

作曲日:
2025-04-04(金)

Suno AI 契約の種類:
Pro Plan

Suno AI Version:
v4

楽曲の正式名称:
Weekday Coffee Morning #3

Suno AI Library URL:
https://bit.ly/Weekday-Coffee-Morning-03

Custom Mode: On

Audio Inputs: Not Used

With Vocals:


---


Lyrics/歌詞:

[vers1]  
Weekdayの Espresso  
Weekdayの Macchiato  
Weekdayの Caffè Latte  
Weekdayの Cappuccino  

[vers2]  
Weekdayの Vanilla Latte  
Weekdayの Caffè Mocha  
Weekdayの Americano  
Tu lu lu lu… Weekdayの  

[Chorus]  
Weekdayの ありがとう  
Weekdayの 美味しいね  
Weekdayの おめでとう  
Weekdayの また明日


---


Suno AIへの指示文章( プロンプト/Prompt ): Custom Modeの場合は”Style of Music”を指定します。


🇬🇧English

[Jazz][Bossa][Piano][220 Seconds][Break][Outro]


🇯🇵日本語訳

[ジャズ][ボサノバ][ピアノ][220秒][ブレイク][アウトロ]


---


Suno AI 公式URL
https://accounts.suno.ai


---


🎥この動画と関連が強いわたしの動画
・“Weekday Coffee Morning”シリーズ
https://www.youtube.com/playlist?list=PLpQhBHT4oghNWYsHCCd7SDJ2ED3KXCX3s


・“Weekday Coffee Morning 日付降順(新しい動画を上に追加)”シリーズ
https://www.youtube.com/playlist?list=PLpQhBHT4oghMKm724o2RNIrdEVvL9CWQh


・“Suno AIでつくった楽曲”シリーズ
https://www.youtube.com/playlist?list=PLpQhBHT4oghMLdiSVqwvSs_Z5y0H4VGOe


・“効果的にSuno AIを活用するヒント”シリーズ
https://www.youtube.com/playlist?list=PLpQhBHT4oghPuaNOVZn-N53wVvsBkeHdI


🎥Shortened URL for this video | この動画の短縮URL
https://bit.ly/4jpx1li
Cache Busting とは？

## Cache Busting とは？

ブラウザは、Webページの読み込みを高速化するために、CSSやJavaScript、画像などの静的リソースをキャッシュします。それにより、ファイルを更新してもキャッシュが残っていると古いファイルが読み込まれてしまうことがあります。

これを解決するために、ブラウザのキャッシュを回避し、最新のリソースを確実に読み込ませるための手法がCache Bustingです。

## 実装方法
リソースのURLにクエリパラメータを付与します。

### 基本
CSSやJavaScriptファイルの読み込み時にクエリパラメータを追加するだけでOK

```html
<!-- バージョン番号を付与する例 -->
<link rel="stylesheet" href="style.css?v1.2.3">
<script src="app.js?v1.2.3"></script>
```

```html
<!-- タイムスタンプを付与する例 -->
<link rel="stylesheet" href="style.css?v1700000000">
<script src="app.js?v1700000000"></script>
```

### PHP の場合（サーバーサイドで自動化）

filemtime() を使うことで、ファイルの更新時刻をクエリパラメータに適用できます。

```html
<link rel="stylesheet" href="style.css?v<?php echo filemtime('style.css'); ?>">
<script src="app.js?v<?php echo filemtime('app.js'); ?>"></script>
```

### Laravel Blade の場合

mix() を使うことで、バージョン管理が可能です。

```html
<link rel="stylesheet" href="{{ mix('css/style.css') }}">
<script src="{{ mix('js/app.js') }}"></script>
```

または、asset() を使い filemtime() を適用する方法もあります。

```
<link rel="stylesheet" href="{{ asset('css/style.css') }}?v{{ filemtime(public_path('css/style.css')) }}">
```

### JavaScript で動的に設定
JavaScript を使って Date.now() をクエリパラメータに追加する方法もあります。

```js
const timestamp = Date.now();
document.write(`<script src="app.js?v${timestamp}"><\/script>`);
```
接続IPアドレスの修正

1.选中后，右击选择「プロパティ」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3795764/b7adc038-fa36-4f35-994f-2a12876416b9.png)
2.将改修后新的IP地址贴在这里，点击OK就可以l
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3795764/76de2225-69ac-4387-8105-790159364da0.png)
いい感じにSSR負荷を抑えるためのuseOptimizedArrayを作った

## 背景
先日Next.jsでとあるアプリを作っている際に、サーバサイドレンダリング(以下SSR)時のCPU負荷増大が見られた。
すごいざっくり言うと、下記サンプルのように大量の`div`要素を描画する必要があるアプリケーションであった。

<img width="150" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141888/4f1ac1c2-a038-47f9-b836-71b241cc5bb3.png">

言うまでもないが、DOMの数が増えればSSR時のCPU負荷は上がる。

## 目的
SSR時のDOMの個数を少なくしSSR時の負荷を下げること。

## 実装方法検討

大きく分けると以下の3つである。
1. `Intersection Observer`を使った方法
1. Virtual Scrollを使った方法
1. SSR時に描画範囲を決めてしまう方法

今回は、大きくソースコードをいじる必要がなく、カスタムフック1発で対応できる3つ目の方法を試してみた。



## 作ったもの

以下にソースコードを示す。

```ts
type UseOptiomizedArrayParams<T> = {
    virtualHeight: number,
    itemHeight: number,
    items: T[]
}

/**
 * サーバーサイドではfirstview分の高さ分の要素のみを、
 * クライアントサイドは全ての要素を返すカスタムフック
 */
export const useOptimizedArray = <T>(params: UseOptiomizedArrayParams<T>): T[] => {
    const [isClient, setIsClient] = useState(false)

    // useEffectを用いることで、クライアント実行時はisClient = trueが保障される
    useEffect(() => {
        setIsClient(true)
    }, [])

    // クライアント実行時は全て返す
    if(isClient) return params.items

    // サーバ実行時のアイテムの個数は、 想定されるfirstviewの高さ / アイテム1個の高さ
    const length = params.virtualHeight / params.itemHeight

    // サーバ実行時は、想定高さ分の要素のみを返す
    return params.items.slice(0, length)
}
```

実際の使い方は以下の通り。大きな配列にこのhooksをかますだけ。お手軽。

```tsx
export function ListComponent() {
    const array = [...Array(1000)]
    const optimizedArray = useOptimizedArray({
        items: array,
        itemHeight: 30,  // 要素の高さ
        virtualHeight: 1000, // 1000もあれば大体のスマホデバイスは事足りる。
    })
    
    return <div>
        {
            optimizedArray.map(((_,i) => <div key={i} className="border-2 border-black"> {`item ${i}`}</div>))
        }
    </div>
}
```

## 想定質問集
### SSR時とCSR時に結果が変わるけど、hydration missmatchは気にしなくていいの？
結論から言うとこのケースでは問題がない。useEffectによって要素が追加描画されるだけであり、HTMLレンダリングの結果が変わるわけでないため。

### `vertualHeight`は0とか小さい値じゃダメなの？小さければ小さいほどサーバ負荷が減りそうだけど？
0にしてしまうと、SSR時に何も描画されずブラウザは一度真っ白な状態を表示することになる。その後、`useEffect`により要素が追加されるような挙動になる。値が小さい場合も同様で、要素の一部だけを表示してしまうので後方の要素が後から追加されるような挙動になる。

### `vertualHeight`を固定値以外で決める方法ないの？
`Sec-Ch-Viewport-Height`というのがリクエストヘッダーにあるらしいが、今現在は残念ながらWeb標準にはなってない。ユーザエージェントから端末や高さを特定するのが良さそう。ただ、ある程度大きな値(4K想定でも2160px)を設定しておけば十分ではありそう。


## 謝辞
アイデアをくださったChatGPTさんには大変感謝します。
【GCP】BigQueryでEmbeddingモデルを使ってみて困ったことメモ【Vertex AI】

こんにちは。
今回はテキストからベクトルへの変換を目的として、BigQuery上でEmbeddingモデルを使う話をします。

設定自体は以下の内容に従うことで設定可能だと思います。
https://cloud.google.com/bigquery/docs/generate-text-embedding?hl=ja

上記は非常にシンプルかつ分かりやすい内容ですが、具体的に処理をするとなったらちょいちょい詰まったところがあったので
本記事では上記の内容に従って設定を行った状況で、どのようなSQLを動かしたのか簡単にまとめます。
コスト面についても多少言及できれば良いかなと思います。

前提知識としてEmbeddingの説明を省きますが、以下記事などを参考にしていただくと良いかと思います。
- ちゃんと読むのにおすすめ: https://qiita.com/Detroit/items/99ac1d5b6ec8c07eb48b
- ざっくり読むのにおすすめ: https://qiita.com/takarui/items/bce75aad95f1df17e93d
- ざっくり読むのにおすすめ2: https://zenn.dev/peishim/articles/c696ff85a539bd

# 使用したデータセットのテーブル構成
列数2のテーブルを用意しました。
1. id
1. content

idは識別用で、contentはEmbeddingモデルが埋め込み表現を作成する対象となるカラムです。Embeddingの対象となるカラムは必ずこの名前にする必要があります。

# 最終的に使ったSQL

```
CREATE OR REPLACE TABLE `environment.dataset.table` AS
  SELECT
    *
  FROM
    ML.GENERATE_EMBEDDING(
      MODEL `environment.dataset.model_name`,
      (SELECT * FROM `environment.dataset.table` LIMIT 10000),
      STRUCT(
        TRUE AS flatten_json_output,
        'CLUSTERING' AS task_type,
        8 AS output_dimensionality
      )
    ) 
```

# どのモデルを使ったか
`text-multilingual-embedding-002`を使いました。日本語対応してるEmbeddingモデルだからです！

## 作った時のSQL
```
CREATE OR REPLACE MODE `モデルへのパス`
REMOTE WITH CONNECTION `BigQueryにVertexAIを接続した時に取得できる接続ID`
OPTIONS (ENDPOINT = `text-multilingual-embedding-002`)
```

# 詰まったポイント. `ML.GENERATE_EMBEDDING`を入れる場所
詰まったポイントとしては、`ML.GENERATE_EMBEDDING`を`FROM`句移行に入れないと動かなさそうという点です。これはSQLを普段書いてないとか、BigQueryに慣れてないとかその辺の問題も大いにありそうです。

最初はselectで絞った時に、EMBEDDINGかけようかなと思っていたのですが
↓イメージ
```
CREATE OR REPLACE TABLE `environment.dataset.table` AS
  SELECT
    id,
    ML.GENERATE_EMBEDDING(`何かのテーブル`...
```

`ML.GENERATE_EMBEDDING`はスカラーではなく複数のカラムを返却値として持っているため設定できないっぽいです。

返却値が複数ある: https://cloud.google.com/bigquery/docs/reference/standard-sql/bigqueryml-syntax-generate-embedding#output


## 精神的に詰まったところ: コスト面
私の中で一番怖かったのはここです。OpenAIのAPIにおけるEmbeddingが安いことは知っていたものの初めて使うサービスだとドキドキしました。
最初は下記のうち上の方だけしか知らなくて、この記事を書くにあたって下の料金表を見つけました。
見つけるのむずすぎます。

Vertex AIの料金
https://cloud.google.com/vertex-ai/pricing?hl=ja
Vertex AIの料金 for Generative AI
https://cloud.google.com/vertex-ai/generative-ai/pricing?hl=ja#embedding-models


今回は13,155,264カウントで40円くらいでした。
カウントがgoogle cloud platformにおけるトークン数に当たるようです。

## 仲間募集中
株式会社ホープでは、福岡で働くエンジニアを募集中です。
ぜひ、求人を見てみてください！
▼ Wantedly求人
https://www.wantedly.com/projects/1684027
▼ コーポレートサイト
https://www.zaigenkakuho.com/recruit/
「自治体を通じて人々に新たな価値を提供し、会社及び従業員の成長を追求する」
この理念の実現に向けて、今後も自治体の課題解決に取り組んでいきます。
ご応募お待ちしております！
AutoCAD VBA 選択フィルタ (2) - FilterTypeを作るFunction -

# はじめに

SelectionSet.Selectメソッドや .SelectOnScreenメソッドでは、選択フィルタを設定することが可能です。公式ヘルプのサンプルコードの作り方では毎回書くのが面倒なので、それならFunctionプロシージャ化してしまおうというのが今回の目的です。長くなりますので、今回はFilterTypeを、次回FilterDataについて解説します。

# FilterType(Variant型配列)を作るFunction

## 概要

- 配列の要素は、コンマ区切りテキストを入力し、Split関数を使って配列化します
- 配列の各要素が数値と見做せるか判定後、Integer型に型変換して別の配列に格納します
- 戻り値となる配列は Selectメソッド等の引数なので、Variant型とします
- 数値と見做せない要素があった場合は、戻り値に False を入れて終了します

## 定義する配列は3つ

少しややこしいのですが、このプロシージャで定義する配列は 3つあります。
1. 入力したコンマ区切りテキストをSplit関数で配列化したもの
2. 1の配列の要素を Integer型に型変換して格納するInteger型配列
3. 2の配列を格納する、戻り値となるVariant型配列 ※プロシージャとして宣言

```vb:AutoCAD VBA
  ' 3の配列
  Public Function uMakeFilterType(ByVal aTextByComma As String) As Variant
  End Function

  ' 1,2の配列
  Dim uFilterTypeArrayStr   As Variant
  Dim uFilterTypeArrayInt() As Integer
```

## コード

```vb:AutoCAD VBA - FilterTypeを作成するファンクション
'[図形|選択|フィルタ] オブジェクト選択フィルター(FilterType)の配列を作成する
Public Function uMakeFilterType(ByVal aTextByComma As String) As Variant
  
  Dim uFilterTypeArrayStr   As Variant ' Split関数の結果を格納する配列
  Dim uFilterTypeArrayInt() As Integer ' Integer型の要素を格納する動的配列
  
  ' Splitで配列化(要素はすべてString値) ※添え字の最小値は 0
  uFilterTypeArrayStr = Split(Expression:=aTextByComma, Delimiter:=",")
  
  ' 動的配列の要素数確定
  ReDim uFilterTypeArrayInt(UBound(uFilterTypeArrayStr))
  
  ' 配列の要素をString型からInteger型に変換して動的配列に移す
  For n = LBound(uFilterTypeArrayStr) To UBound(uFilterTypeArrayStr)
    ' 要素が数値と見做せるかチェック
    If IsNumeric(uFilterTypeArrayStr(n)) = True Then
      ' 数値と見做せる場合、型変換して格納
      uFilterTypeArrayInt(n) = CInt(uFilterTypeArrayStr(n))
    Else
      ' 数値と見做せない場合、戻り値を False として終了する
      uMakeFilterType = False
      Exit Function
    End If
  Next
  
  ' 戻り値
  uMakeFilterType = uFilterTypeArrayInt

End Function

```

# おわりに
次回は、FilterDataを作るFunctionです。基本的には今回のコードとほぼ同じですが、細かいところが違ってきます。

https://qiita.com/sewege11/items/ede36073251e05e41c63

https://qiita.com/sewege11/items/78b529f118ff28c478a7
rust match文の中の@なの？

rustツアーでこのようなコードが

```
fn main() {
    let x = 42;

    match x {
        0 => {
            println!("found zero");
        }
        // 複数の値にマッチ
        1 | 2 => {
            println!("found 1 or 2!");
        }
        // 範囲にマッチ
        3..=9 => {
            println!("found a number 3 to 9 inclusively");
        }
        // マッチした数字を変数に束縛
        matched_num @ 10..=100 => {
            println!("found {} number between 10 to 100!", matched_num);
        }
        // どのパターンにもマッチしない場合のデフォルトマッチが必須
        _ => {
            println!("found something else!");
        }
    }
}
```

@は、コメントに書いてあるように変数に代入される。
Copyが実装されているプリミティブ型なら所有権は移動しないが、以下のような型の場合は所有権が移動する。

```
let s = String::from("hello");

match s {
    std @ _ => println!("matched{}", std),
}

println!("{}", s); // error occurs here
```
5.環境の更新情報


**5.環境の更新情報**


Appium環境
---

|パッケージ |バージョン|更新日|更新内容|備考|
|--|--|--|--|--|
|Appium|  1.22.3  |2022/1/24 |--|
|Appium  |2.0.1→2.11.0  |2024/6/27|・/appium/extensions API が追加され、利用可能な拡張機能の一覧を取得<br>・/appium/sessions や /session/:sessionId/appium/capabilities などの新しいエンドポイントが追加され、セッション管理がより柔軟に<br>・HTTP サーバーのリクエストタイムアウトを設定できるコマンドラインオプションが追加<br>・/session/:sessionId/appium/device/ 以下の一部の API が非推奨　|
|Appium  |2.11.0→2.12.0  |2024/10/15|・サーバーのシャットダウン時のタイムアウトを設定できるように　|
|Appium  |2.12.0→2.13.0  |2024/12/2|・機能名のプレフィックス指定のサポート　|
|Appium | 2.13.0 → 2.16.0 | 2025/02/19 | ・拡張機能の一覧取得APIの追加<br>・セッション関連APIの追加<br>・BiDiコマンドのサポート<br>・ | |
| Appium | 2.16.0 → 2.17.0 | 2025/03/11 | ・images-plugin の強化<br>・storage-plugin の追加 |2.17.1のリリースあり |
|~~AppiumDoctor~~   |~~2.1.13~~　|Appium 2.4.0 以降非推奨|--|--|
|Appium Inspector  |アプリバージョン: 2024.9.1→2025.3.1　<br>Electron: 31.6.0→35.0.2  |2025.3.1 |・Appium InspectorがAppiumプラグインとしても利用可能に<br>・Appium 3セッションのサポート<br>・Javaクライアントテストの修正<br>・起動速度が向上　|--|


<br>

ios環境
---

<br>

|パッケージ |バージョン|更新日|更新内容|備考|
|--|--|--|--|--|
|XCode |16.3　Build version 16E140　|2025/4/13 |--|--|
|Homebrew   |4.4.29　|2025/4/13 |--　|--|
|Node   |v22.14.0　|2024/8/21 ||LTSでv22がリリース済み|
|npm   |10.9.2　|2025/4/13|　|--|
|appium-xcuitest-driver  |7.32.0→9.2.0  |2024/11/16　|・autoClickAlertSelector 設定を有効化し、アラートの自動クリック機能が改善<br>・getWindowSizeWeb および getWindowSizeNative メソッドが非推奨となり削除　<br>・skipDocumentsContainerCheck 設定を追加し、特定の変更を適用する際の挙動を制御できるように　<br>・appium-ios-simulator を更新し、applesimutils の使用に関する修正　|--|



<br>

Android環境
---

<br>

|パッケージ |バージョン|更新日|更新内容|備考|
|--|--|--|--|--|
|Android Studio |2024.2.1 Patch 2　|2024/11/12 |--|--|
|Android SDK Command-line Tools　|V.16.0　||--|--|
|adb   |1.0.41　| |--　|--|
|Java   |v21.0.5　|2024/10/15 ||--|
|uiautomator2   |3.9.0→4.2.0　|2024/11/18|・BiDiイベントを追加<br>・Appium 3 ベータ版との互換性向上。​<br>・deep link コマンドの package パラメータをオプション化。​<br>・非推奨となった errorAndThrow API の置き換え。​<br>・contextUpdated イベント生成の調整。　|--|


<br>

スクリプト作成環境
---

<br>

|パッケージ |バージョン|更新日|更新内容|備考|
|--|--|--|--|--|
|pyenv |2.4.19→2.5.5　|2024/11/20 |・ビルド成功率UP（Apple Silicon（M1/M2））<br>・最新Python対応（3.13）<br>・macOS14との互換改善<br>・処理速度UP|--|
|Python |3.12.6　| |--|--|
|pip |24.2　| |--|--|
|Appium-Python-Client |5.0.0　|2025/4/14 |--|--|
【競技プログラミング:リハビリ】二分探索(上下左右方向)

# 既存投稿一覧ページへのリンク
[一覧ページ](https://qiita.com/o_chan_t/items/fc759695acfaef8df2cc)

# 雑記
ボンバーマンみたいなゲーム制作に使えそうな問題ですので、Unityとか使えるようC#でもまとめておくかな。


# サンプルコード
## python
```python:sample_code.py
def find_first_true(start, grid, direction):
    """
    起点から指定方向に探索し、最初にTrueが見つかる座標を返します

    Args:
        start (tuple): 探索起点座標 (row, col)
        grid (list): 2次元の真偽値リスト
        direction (str): 探索方向 'r', 'l', 'u', 'd'

    Returns:
        tuple or None: 最初のTrue座標（見つからない場合はNone）
    """
    row, col = start
    rows = len(grid)
    cols = len(grid[0]) if rows > 0 else 0

    # 各方向の探索範囲を設定
    if direction == 'r':
        for c in range(col + 1, cols):
            if grid[row][c]:
                return (row, c)
    elif direction == 'l':
        for c in range(col - 1, -1, -1):
            if grid[row][c]:
                return (row, c)
    elif direction == 'u':
        for r in range(row - 1, -1, -1):
            if grid[r][col]:
                return (r, col)
    elif direction == 'd':
        for r in range(row + 1, rows):
            if grid[r][col]:
                return (r, col)
    
    return None

if __name__=="__main__":
    grid = [
        [False, False, True, False],
        [False, True,  False, False],
        [False,  False, False, True]
    ]

    # 例1: (0,0)から右方向探索 → (0,2)を返す
    print(find_first_true((0,0), grid, 'r'))  # (0, 2)

    # 例2: (1,2)から上方向探索 → (0,2)を返す
    print(find_first_true((1,2), grid, 'u'))  # (0, 2)

    # 例3: (2,3)から左方向探索 → (2,3)の左にTrueなし → None
    print(find_first_true((2,3), grid, 'l'))  # None


```

# 関連問題
https://atcoder.jp/contests/abc370/tasks/abc370_d
実用Go言語 第1章「Goらしさに触れる」まとめ

この章では、Go言語の設計思想や、他の言語と異なるGoらしい特徴について紹介されています。  
変数名の付け方からエラーハンドリング、メモリ最適化や時刻処理まで、実践的な知識が詰まった章です。

## 1.1 名前付けの慣習

### 1.1.1 変数名
- _は使用しない
- 頭文字後は大文字にする（例：`Url`でななく`URL` など）
- エラーの変数名には接尾語に`Error`
- 短くても意味が分かる名前が推奨される（例：`request`でななく`req` など）
- Goではスコープが狭い場面で短い名前が好まれる

### 1.1.2 パッケージ名
- `main` 以外はすべて小文字単語1つが原則
- 使用例：`fmt`, `io`, `bytes`

### 1.1.3 インタフェース名
- 動詞＋erで命名（例：`Reader`, `Writer`）
- 小さなインタフェースが好まれる

### 1.1.4 レシーバー名
- 短い1〜2文字（例：`s`, `t`, `r`）
- メソッドの対象を表す

## 1.2 定数の使い方

### 1.2.1 型のない定数
- `const Pi = 3.14` のように型なしで定義可能（暗黙型変換に便利）

### 1.2.2 型付き定数
- 明示的に型を指定する場合： `const Timeout time.Duration = 3 * time.Second`

### 1.2.3 他言語との違い
- Goは「定数＝狭い用途でしか使えず厳格」として重視される

### 1.2.4 error型の定数
- エラーも`const`で定義して使い回すことが多い（例：`ErrNotFound`）

## 1.3 iotaによる列挙型

### 1.3.1 ユニークな定数列
- 自動でインクリメントされるため列挙型に便利

### 1.3.2 iotaの挙動
- 定数ブロック内で0から始まり1ずつ増加

### 1.3.3 ビットフラグとして利用
- `1 << iota`でビットごとのフラグを表現可能

### 1.3.4 適さないケース
- 途中で番号が飛ぶ・外部との互換性がある場合は避ける

### 1.3.5 文字列として出力
- `Stringer`インタフェースを実装することで定数値を人間が読める文字列に変換可能

---

## 1.4 エラーハンドリング

### 1.4.1 Goのエラーは値
- エラーは単なる値（`error`型）、if文で都度チェック

### 1.4.2 panic()は原則使わない
- 想定外の致命的な状況でのみ使用

### 1.4.3 エラーハンドリング
- `if err != nil`パターンが基本

### 1.4.4 他言語との違い
- 例外を使わず、明示的な戻り値による制御を重視


## 1.5 :=とvarの使い分け

- 基本的には `:=`（短縮宣言）が推奨
- グループ定義や関数外では`var`を使う

## 1.6 オプション引数の実現

### 1.6.1 関数を分ける
- `NewDefaultUser()`と`NewUserWithName()`のように用途別関数

### 1.6.2 構造体を使う
- 引数構造体を定義し、柔軟にオプションを渡す

### 1.6.3 ビルダーパターン
- 段階的に設定値を構築して渡す

### 1.6.4 Functional Optionパターン
- クロージャを使ってオプション指定

### 1.6.5 どれを選ぶか
- シンプルな関数が1〜2個程度なら「関数分け」や「構造体」が十分  
- 複雑・柔軟性が求められるならFunctional Option

## 1.7 プログラムを制御する引数

### 1.7.1 コマンドライン引数
- `flag`パッケージなどで簡単に取得できる

### 1.7.2 環境変数
- `os.Getenv()` を使用

## 1.8 メモリ起因のパフォーマンス低下を解消する

### 1.8.1 スライス
- `make([]T, len, cap)`で事前に容量確保するとGC効率が改善

### 1.8.2 マップ
- `make(map[K]V, size)`で初期容量を設定すると効率化

### 1.8.3 deferの落とし穴
- 多用するとパフォーマンス低下に繋がる場面もある（特にループ内）

## 1.9 文字列の結合方法

- `strings.Builder`を活用すれば効率的に連結可能

## 1.10 日時の取り扱い

### 1.10.1 `time.Time`の取得
- `time.Now()` で現在時刻取得、`UTC()`や`Local()`で変換可能

### 1.10.2 `time.Duration`
- 時間差を表す型。`1*time.Second`, `500*time.Millisecond` など

### 1.10.3 Webとのやり取り
- ISO8601形式（`RFC3339`）で文字列変換して送信：`t.Format(time.RFC3339)`

### 1.10.4 翌月を計算する落とし穴
- `AddDate(0, 1, 0)`で「翌月の同じ日」を取得するが、月末処理に注意（例：1月31日→2月28日）

## ✅ まとめ

この章では、Goにおける**明確な設計思想**（シンプル・明示的・高速）がよく表れていました。

- 名前付け → 明確で簡潔に
- 定数・iota → 安全なコードのために活用
- エラー処理 → 例外よりも戻り値
- メモリ・パフォーマンス → 予測可能な設計

Goを書くすべての開発者にとっての基本の「型」となる内容です。
【AWS】プライベートEC2のセッションマネージャー接続でプロンプトが表示されない時の確認点

みなさん、こんにちは！
AWSの検証で、プライベートサブネットにEC2を作成してセッションマネージャーで接続することがよくあります。
長期間使用しない時は一度EC2やVPCエンドポイントを削除して必要な時に再度作成しているのですが、いつもの手順で作成・接続しようとしたところ、接続はできるもののプロンプトが表示されず、画面が真っ暗なままになる現象に遭遇しました。
（ちなみにそのEC2はWindowsインスタンスで、フリートマネージャーでの接続は通常通り可能でした。）
このような事態に直面したのは初めてで解決までに時間がかかったため、備忘録として残しておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3956386/ca3ee3bc-b56c-4f25-a30e-da9da6a42374.png)

## 前提
プライベートサブネットにあるEC2にセッションマネージャーで接続する手順については、AWS公式ガイド等をご確認ください。
下記のAWS re:Postにも一連の流れや確認点が載っているページがありましたので共有します。
※参照：[Amazon VPC エンドポイントを作成することで、インターネットへのアクセスを必要とせずに、Systems Manager を使用してプライベート Amazon EC2 インスタンスを管理できるようにする方法を教えてください。](https://repost.aws/ja/knowledge-center/ec2-systems-manager-vpc-endpoints)

## 原因
セッションマネージャーの設定で（CloudWatch LogsまたはS3への）ロギングが有効化されていたにも関わらず、ロギング用のVPCエンドポイントが作成されていなかったことが原因でした。
普段はロギングせずに接続しているのでロギング用のVPCエンドポイントの作成を省略していたのですが、今回何らかの理由でロギングが有効化され、その結果プロンプトが返らないという状況になっていたようです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3956386/21522505-e883-4783-be75-59186ea88573.png)

## 解決方法
### ①S3およびCloudWatch Logsへのロギングを無効化する
ログ保管が不要であれば、セッションマネージャーの設定ページでロギングを無効化すれば接続できるようになります。
セッションマネージャーの接続画面で「設定」を押下し、画面右上の「編集」からS3とCloudWatch Logsへのロギングを無効化してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3956386/0b8162d0-893e-4ab1-9423-e3d12fc0446d.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3956386/4043a58b-2adb-4ad2-a50a-12290773adce.png)

### ②ロギングしたいAWSサービス用のVPCエンドポイントを作成する
プライベートEC2にセッションマネージャーで接続した時のログ保管が必要な場合は、下記のいずれかのVPCエンドポイントを作成する必要があります。

* com.amazonaws.[AWSリージョン].s3
* com.amazonaws.[AWSリージョン].logs

セッションマネージャーの設定ページでS3またはCloudWatch Logsへのロギング有効化とログ出力先を設定して、ログを保管したい方のVPCエンドポイントを作成してください。

## まとめ
今回のようなケースは発生頻度が少ないかもしれませんが、同様のトラブルに直面した方の一助となれば幸いです。
最後までお付き合いいただきありがとうございました！
クッキーとセッション

# はじめに
前回、ステートレスとステートフルについて解説しました。
前者は前回の状態を記憶せず、その場で完結するコミュニケーションであったのに対し、後者は前回の状態を記憶したコミュニケーションのことであるとまとめました。

しかし、状態を記憶しないステートレスな通信の場合、以前コミュニケーションをとったユーザーのことはどうやって記憶しているのでしょうか？何某かの形で記憶していないと過去の情報を知ることができません。
例えば、ECサイトを想定すると、カートに入れた商品を再度確認しようとする場合、どうやってその情報を保持するのでしょうか。
この課題をクリアする技術として**クッキー(Cookie)**と**セッション**があります。
今回はクッキーとセッションについてまとめていきます。

## クッキー(cookie)とは
Webサイトが使用しているブラウザに保存する小さなメモのことです。

この点を見ていく前に、HTTP通信の特徴を押さえておく必要があります。
そもそもHTTP通信はHTTPプロトコルを使用した通信のことで、この通信は1回ごとに通信が完結するステートレスな通信です。そのため、前回の内容を記憶しない、いわゆる状態を持たず、サーバーはクライアントの状態を覚えておく仕組みがありません。
そこでクッキーを利用することで、ユーザー状態を知った上でやり取りできるようになります。

クッキーはサーバーからクライアント（ブラウザ）に「この情報を保存しておいてね」という形で送られ、次回以降ブラウザからサーバーに自動で送信されます。これによりサーバー側で、「あっ、前回ログインしてショッピングカートにセーターを追加した人だな」と判別する材料になります。
情報はクライアントであるブラウザ側で保持することになります。

## クッキーの問題点
便利なクッキーですが、以下のような問題点があります。

**① 改ざんできる**
クッキーはブラウザに保存されるテキストデータですが、ブラウザから簡単に内容を書き換えることが可能です。
これにより、悪意のある第三者がブラウザでクッキーを書き換えたり、そのまま使用したりすることで、他人のアカウントに不正アクセスできてしまいます。
例えば、JavaScriptでcookieを設定すると、任意のセッションIDを作成することができます。
```sh: 例
// 元の値「user_id=123」を改ざん
document.cookie = "user_id=456"; 
```

**② 重要なデータが丸見えになる**
HTTPレスポンスには、Set-Cookie: credit_card=5555-1234-5678-9012;...
のような形式でデータが含まれます。
この場合、第三者に見られてしまうとまずいような重要な情報を含んでいることになります。

重要なデータをクッキーに保存すると改ざんされる危険があり、ユーザー側で管理すると漏洩するリスクが高いため、セッションという仕組みが使われます。

## セッション(session)とは
サーバー側で管理される、一連のユーザー操作に関する一時的な状態情報のことを指します。
例えば、ショッピングサイトにログインし、カートに商品を追加、そして購入せずログアウト、といったこの一連の流れを指します。

ステートレスはHTTP通信では、通常このログインする操作やカートに商品を追加する操作は独立しており、都度通信が完了してしまうため、同一ユーザーが行なっているかどうかがわからなくなってしまいます。
そこで、セッションID（ランダムな識別子をクッキーでクライアントと共有）とクッキーを使用してユーザーをサーバー側で管理することで、どのユーザーとのどんな取引かを記憶することができ、ステートレスなHTTP通信に『状態』を追加することができます。

![Image 2025-04-12 at 19.29.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3907600/4bffad03-4de3-4572-8de8-092d8039ae2e.jpeg)

サーバーはユーザーからリクエストがあると、セッションIDを発行し、クッキーにこの発行したセッションIDを含めてクライアントであるブラウザに送信します。
ブラウザはこのセッションIDをもったクッキーをサーバーに送信し、サーバーが送られてきたクッキーを照合することでどのユーザーのどんな行動かを記憶できるようになります。
こうして、ステートレスな通信でステートフルな通信を擬似的につくることができます。

# まとめ
ステートレスな通信でステートフルに近づけるために、クッキーとセッションという技術が使われていることを解説しました。
最後までお読みいただき、ありがとうございました。


# 参考・画像引用元URL
https://zenn.dev/collabostyle/articles/8949e8db686263
https://shukapin.com/infographicIT/session-management
https://zeroterasu.com/blog/php/php_session/
https://speakerdeck.com/mu_zaru/setusiyontokutukifalsemi
『イラスト図解式 この一冊で全部わかるWeb技術の基本 第2版』
https://nextribe.co.jp/posts/sessions-and-cookies
【イベントレポート】JAWS-UG朝会 #68 #jawsug_asa

いつも記事を読んでいただきありがとうございます！
モブエンジニア（[@mob-engineer](https://qiita.com/mob_engineer))です！

今回は2025.04.14（月）に開催した**JAWS-UG朝会 #68**に参加しましたのでアウトプットとしてイベントレポートを執筆しました。

初見の方でもサクッと読めるように平易な表現で執筆しておりますので、お気軽に読んでいただければ幸いです。

:::note info
誤字脱字・誤った表現に関しては極力なくすように心がけていますが、リアルタイムで執筆しております。もし、誤字脱字・誤った表現がありましたのでコメントを頂けますとありがたいです。
:::

:::note info
今回登壇したAWS Signerに関する資料は次の通りです。
https://speakerdeck.com/masakiokuda/kai-fa-shi-dian-deaws-signerwokao-etemiyou-kodoshu-ming-nosonoxian-he
:::

#### イベントページ

https://jawsug-asa.connpass.com/event/338579/

# 目次
- セッション
    - セッション① ELB vs API Gateway vs CloudFront / 結局何を選べばいいの？
- LT
    - LT① AWS Community Builders のススメ
    - LT② 地球に優しいML？AWSが見せる次世代の可能性
    - LT③ 企業内AWSコミュニティ、みんなはどうしてますか？	
- まとめ

## セッション

### セッション① ELB vs API Gateway vs CloudFront / 結局何を選べばいいの？

#### 参考サイト

https://qiita.com/yu-Matsu/items/88d9aae18bbdce723a0a

https://zenn.dev/acntechjp/articles/8bde90d02ff2ef

- 自己紹介
    - 外資コンサルファームのエンジニアの方
    - AWS資格全冠保持・GC資格全冠保持
- 前提
    - インフラアーキテクチャの検討は難易度が高い
    - 各構成速度での通信速度も見ていく
- 各サービスの利用目的
    - ELB：
        - 複数のAZ内の複数ターゲットのヘルスチェックを行う
        - 正常なターゲットのみに通信を行う
    - ALB：
        - レイヤ7のロードバランサ
        - HTTPS通信に対応したロードバランシングが可能
    - NLB：
        - レイヤ4のロードバランサ
        - 低いレイテンシーを実現できる
    - API Gateway
        - REST・HTTP・Web Socketと連携して通信制御を行える
    - CloudFront
        - エッジロケーションを経由しコンテンツのキャッシュを実現できる
- ユースケース
    - サービスを利用しない場合：単一のリソースへのアクセスのみを行う場合
    - ALBの場合：
        - ユーザからのアクセスターゲットが複数の場合
        - WAF設定・SecurityGroupの設定が可能なためNLBよりセキュリティが重要
    - NLBの場合：
        - テンレンシー通信が求められる場合
        - SecurityGroupを利用できない＋コンテンツに応じた振り分けができないためセキュリティ面での要件は考える必要がある
    - CloudFront併用時の場合
        - セキュリティ・コンテンツアクセスに関して最適化できる
    - CloudFront＋API Gateway＋NLBの場合
        - NLBの弱点であるセキュリティ設定も可能
- 検証してみた
    - 簡単なWebサーバを構築し通信速度を見てみた
        - なにも利用しないでも速度が出たのはDNS影響
        - （個人的意見）このあたりは私も深堀して検証したいですね
    - 初回アクセス時はAPI Gateway利用時のほうがレイテンシーが高い

## LT

### LT① AWS Community Builders のススメ
- 自己紹介
    - CEC所属のエンジニアの方
- AWS Community Builders（CBs）とは
    - AWSが提供しているグローバルコミュニティ
    - AWS認定以外の知識・スキルを伸ばしたい・証明したいといった方に向いている
    - 個人アカウントでAWSで検証したい方向けのクレジットもある
- CBsになって感じたこと
    - 英語力がないとCBsの特典を最大限生かせない
        - 英語登壇にチャレンジするのにハードルが高くなってしまう
    - 英語力を伸ばすことが大切
        - アウトプットレベルは気にせずにチャレンジすることが大切
        - 質を向上させるために活動を行うことが大切

### LT② 地球に優しいML？AWSが見せる次世代の可能性
- 自己紹介
    - 社会人歴2年目の方
    - 今回初登壇された方
- テーマ選定理由
    - 自然が好きなエンジニアであり、技術進化と自然保護を考えてみたいと思ったから
    - 生成AIによって電力消費量が多くなっている
- AWSの取り組み
    - AWS Gravitonを用いてEC2インスタンスの電力消費量を削減する工夫を行っている
    - （個人的意見）環境保護に関しては確かに重要な視点ですね

### LT③ 企業内AWSコミュニティ、みんなはどうしてますか？
- 自己紹介
    - ダイキン工業の技術者の方（主任技師）
    - 社内コミュニティも運営されている
- AWS Community for Daikin Co-workers
    - ACDC変換のように異なるエリアの人たちが交わる場にしていきたい
    - 2023年くらいに企画を行っている
        - 現在も200名参加しているが、一部の方しか投稿していない
        - 今後の課題として主体的に運営していくメンバーを増やしていく
- 今後の展望
    - エンタープライズ内製組織コミュニティを作っていく
    - 参加希望者を絶賛募集中

## まとめ

社内コミュニティ運営・CBsに関する内容に関して興味がありましたので、本セッションでキャッチアップすることができたので良かったです。

また、私のセッションでAWS Signer（サイナー）について話しましたが、SBOMとの関係性についても質問が上がっていましたので調べてみたいと思いました。

最後まで記事をお読みいただきありがとうございました！
#9 Git ローカルブランチを削除して、ローカルから取得しなおす

# はじめに
ローカルブランチを削除して、取り直したいということがありましたのでコマンドについて調べました。コマンドをメモしておきます。


## ローカルブランチの削除
まずはローカルブランチの削除をします。削除したいローカルブランチ以外をチェックアウトしておいてください。

```
$ git branch -d ブランチ名
$ git branch -delete ブランチ名
```

上記どちらのコマンドでOKです。ただい、このコマンドではマージ済みのブランチに限られます。
マージされていないブランチを削除したい場合は以下のコマンドで削除します。

```
$ git branch -D ブランチ名
```

## ローカルブランチの再作成
以下のコマンドでブランチを再作成します。

```
$ git checkout -b ブランチ名 origin/チェックアウトするブランチ名
```

以上です。
【Laravel小技】url()->previous() の使い方と注意点まとめ【戻るリンクやリダイレクトに便利】

# はじめに

Laravelでユーザーを「ひとつ前のページ」に戻したいとき、  
便利に使えるのが `url()->previous()` です。

戻るリンクや、処理完了後のリダイレクト、バリデーションエラー時の復帰など、  
さまざまな場面で活躍します。

この記事では、`url()->previous()` の基本的な使い方と注意点についてまとめます。

---

# `url()->previous()` とは？

Laravelのヘルパーメソッドで、  
**直前のリクエスト元のURL（前のページ）を取得**します。

```php
$url = url()->previous();
```
内部的には、HTTPヘッダーの Referer 情報を参照しています。

# ①よくある使い方
- 1.戻るリンクを作る（Blade）
```blade
<a href="{{ url()->previous() }}">戻る</a>
```
→ ユーザーを直前の画面に戻すナチュラルなリンクが作れます。

- 2.コントローラーからリダイレクト
```php
public function store(Request $request)
{
    // 保存処理...

    return redirect(url()->previous())->with('message', '投稿が完了しました');
}
```
→ 処理後に元いたページへ戻すときに便利です。

- 3.バリデーションエラー後に戻るなら back()
```php
return back()->withErrors($validator)->withInput();
```
→ これも内部的には url()->previous() を使っていますが、より安全＆Laravel流です。

# ②注意点
**Referer ヘッダーが無いと動かない**
例えば:
- ブラウザでURLを直接開いた場合
- リファラー制限されているページからの遷移
このようなときは、url()->previous() は **nullを返すこともあるので注意。**

# ③url()->previous() と back() の違い
![IMG_7779.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2246240/713c22f0-4b3e-4e84-ad0e-3799329efe8b.jpeg)

# ④まとめ
![IMG_7780.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2246240/82f74e95-bb92-4848-b0bc-e02d00d0e2bb.jpeg)
url()->previous() を知っていると、
「ユーザーがどこから来たのか」に基づいた**より自然なUI設計ができます！**
Weekday Coffee Morning #2 - Jazz, Bossa, Accordion【Suno AIで作曲】【動画 3分03秒】【YouTubeチャンネルからの転記です】

この記事は、わたしの[YouTubeチャンネル](https://bit.ly/Yamanaka-YouTube "Living without things. 持たない生き方 手放す生き方")にある公開動画を転記しております。
( どこかのタイミングで、プログラミング-Google Apps Script or iPaaS-Zapier をつかって自動転記させる予定です )

転記のための時間コストを少なくしたいので、文字装飾( Markdown記法 )を極力つかわずに書いております。

こちらが動画内容です👇

***

![⭐⭐02 YouTubeサムネイル & 再生中の画像 Suno AI _ Weekday Coffee Morning #1 (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386308/eb15a374-8811-429b-bfb1-8df01d552589.png)





* # 動画URL
    * https://youtu.be/3fFOIJjgfHg

<br>

* # 動画タイトル
    * Weekday Coffee Morning #2 - Jazz, Bossa, Accordion【Suno AIで作曲】【動画 3分03秒】

<br>

* # 動画の説明欄(一部を抜粋)

撮影日 = 2025-04-14(月)

Suno AIとは、文章から音楽を生成することができるAI( Text-to-Music-AI )です。
わたしは、2024-04-02(火)に初めてSuno AIで有償プランを契約してから、時々楽曲をつくって遊んでいます。

🎦【Suno AI】文章から音楽を生成するAI( Text-to-Music-AI )で、3分間で2曲、6分間で4曲作りました【試聴可能】1)伴侶の曲 2)税理士の曲【動画 16分11秒】
https://youtu.be/QKfhk4HgQ_g

🎦“Suno AIでつくった楽曲”シリーズ
https://www.youtube.com/playlist?list=PLpQhBHT4oghMLdiSVqwvSs_Z5y0H4VGOe

🎦“効果的にSuno AIを活用するヒント”シリーズ
https://www.youtube.com/playlist?list=PLpQhBHT4oghPuaNOVZn-N53wVvsBkeHdI


今回は、Suno AIで作曲し、 WAV 出力した楽曲を動画に仕上げました。

2025年3月～4月、毎朝のように訪れていた『WEEKDAY COFFEE ROASTERS』( https://bit.ly/Whatis-WEEKDAY-COFFEE-ROASTERS )さん。
この楽曲の舞台は、こちらのお店です。
美味しいエスプレッソやマキアートのおかげで、気が重かったプロジェクトの様々なタスクもはかどり、いつの間にか楽しみながら乗り切ることができました。
歌詞には、わたしが実際に口にした飲み物のメニューや、印象的だった会話、お店の空気感を織り込みました。
そんな素敵な時間を思い出しながら、感謝を込めて制作したファンメイドテーマソングです。

「毎朝美味しいコーヒーと、穏やかな時間をありがとうございました。ごちそうさまでした！」

この楽曲をぜひ聴いてみてください。
ぜひ、温かいコーヒーを飲みながら楽しんでください。
そしてぜひみなさんも、大好きなお店やブランドや企業への感謝を込めて、オリジナル曲をつくってみてください！

作曲日:
2025-04-04(金)

Suno AI 契約の種類:
Pro Plan

Suno AI Version:
v4

楽曲の正式名称:
Weekday Coffee Morning #2

Suno AI Library URL:
https://bit.ly/Weekday-Coffee-Morning-02

Custom Mode: On

Audio Inputs: Not Used

With Vocals:


---


Lyrics/歌詞:

[vers1]  
Weekdayの Espresso  
Weekdayの Macchiato  
Weekdayの Caffè Latte  
Weekdayの Cappuccino  

[vers2]  
Weekdayの Vanilla Latte  
Weekdayの Caffè Mocha  
Weekdayの Americano  
Tu lu lu lu… Weekdayの  

[Chorus]  
Weekdayの ありがとう  
Weekdayの 美味しいね  
Weekdayの おめでとう  
Weekdayの また明日


---


Suno AIへの指示文章( プロンプト/Prompt ): Custom Modeの場合は”Style of Music”を指定します。


🇬🇧English

[Jazz][Bossa][Accordion][220 Seconds][Break][Outro]


🇯🇵日本語訳

[ジャズ][ボサノバ][アコーディオン][220秒][ブレイク][アウトロ]


---


Suno AI 公式URL
https://accounts.suno.ai


---


🎥この動画と関連が強いわたしの動画
・“Weekday Coffee Morning”シリーズ
https://www.youtube.com/playlist?list=PLpQhBHT4oghNWYsHCCd7SDJ2ED3KXCX3s


・“Weekday Coffee Morning 日付降順(新しい動画を上に追加)”シリーズ
https://www.youtube.com/playlist?list=PLpQhBHT4oghMKm724o2RNIrdEVvL9CWQh


・“Suno AIでつくった楽曲”シリーズ
https://www.youtube.com/playlist?list=PLpQhBHT4oghMLdiSVqwvSs_Z5y0H4VGOe


・“効果的にSuno AIを活用するヒント”シリーズ
https://www.youtube.com/playlist?list=PLpQhBHT4oghPuaNOVZn-N53wVvsBkeHdI


🎥Shortened URL for this video | この動画の短縮URL
https://bit.ly/4ijN6bo
ファイルとパイプの違いに関する疑問を解決する

## 疑問の発端

プロセス間通信を学んでいると、よく登場する**パイプ**という概念。しかし、「**パイプを使えば通信ができる**」という認識はあっても、実際に**ファイルとの違い**が気になり始めました。**ファイル**と**パイプ**は一体どう違うのか？これを深掘ります。

## ファイルとパイプの違いとは？

まず、**ファイル**と**パイプ**には**アクセス方法の違い**があることがわかりました。

- **ファイル**は、データが**ディスクに保存され**ており、**ランダムアクセスが可能**です。つまり、どこからでもデータを読み書きできます。
- 一方、**パイプ**は、**カーネルが管理するリングバッファ**という一時的なメモリにデータを格納し、**FIFO（先入れ先出し）順**でデータを処理します。そのため、データは**順番通り**にやり取りされます。

## なぜパイプは競合が発生しにくいのか？

次に、**競合状態**という問題について深掘ります。通常、**複数のプロセスが同じリソースにアクセスすると競合状態**が発生し、データが壊れたり、順番が狂ったりします。しかし、**パイプはFIFO順**でデータを管理しているため、**最初に書き込まれたデータが最初に読み取られる**という特徴があることがわかります。これにより、複数のプロセスが同時にデータを書き込んでも、**書き込み順にデータが処理される**ので、競合状態が起こりにくいのです。

## パイプの高速性について

また、パイプはディスクに保存されません。つまり、**ディスクI/Oを使わずにメモリ内でデータをやり取りする**ため、非常に高速です。

## ファイルとパイプの永続性の違い

パイプは、**データが一時的にやり取りされる通信手段**であり、ディスクには保存されません。そのため**プロセスが終了するとデータは消失**します。一方で、ファイルはディスクに保存されるので、**永続的にデータを保存**し、プロセスが終了しても残り続けます。

## 結論

- ファイルは**データを保存するための手段**であり、**ランダムアクセスが可能**で、**永続的な保存**が行えます。パイプは、**プロセス間での一時的なデータのやり取り**に特化しており、**FIFO順でデータを管理**し、**ディスクI/Oが発生しないため高速**です。
  
- **パイプ**は、**競合状態を避けながら高速な通信**を実現するため、特に**プロセス間通信**に向いていることが理解できました。
ShopifyCEOが社員に伝えたAI活用方針～AI活用はトップダウンが有効的では？

# トップダウンのAI活用指示の重要性

以下の動画でタイトルのメモの存在をしりました。
たしかに良いなと思う内容でした。

<iframe width="560" height="315" src="https://www.youtube.com/embed/Y3gCeTzH7Sc?si=8O9WLiwNjCwX-i0m" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>

もとのメモは、こちらです。英語ですが、AIで翻訳や要約して読んでみると良いと思います。

https://x.com/tobi/status/1909251946235437514


以下、動画の内容を要約したものです。

:::note info　 
**Shopify社内メモから学ぶ6つの重要ポイント**

**✨️AIはまずプロトタイピングに使え！**

　アイデアをすばやく形にする段階でAIを活用することで、チーム内での共有や検討がスムーズに。紙に書くよりも直感的に伝えられる。

**✨️AI活用スキルを人事評価に組み込む**

　従業員がどれだけAIを使いこなせているかを正式な評価項目に。学び・実践を促すインセンティブにする。

**✨️ 多様なAIツールを開放して試行錯誤を促す**

 1種類に絞るのではなく、複数のAI（Copilot, Cursor, Claudeなど）を自由に使えるようにし、自発的な活用と最適化を狙う。

**✨️成功事例はスラックでシェア！**

　AI活用の好事例やプロンプトは社内チャンネルで共有し、ナレッジを組織内で循環させる文化を作る。

**✨️人員追加の前に「なぜAIではできないか」を説明させる**

 人手が欲しいと訴える前に、AIで代替できない理由を明確にさせる。考えるきっかけを社員に与え、無駄な増員を防ぐ。

**✨️経営陣自らもAIを使いこなす姿勢を見せる**

　トップが率先してAIを使い、変化への適応を示すことが、組織全体のAIリテラシー向上に直結する。
:::

AI導入支援やAI駆動開発への移行をしていて、上記のメモはそうだなと思いました。

MicrosoftでCopilotの講習会をうけたときも、経営者からの全社へ向けたこうしたAI活用へのメッセージは重要だと言われていました。

下からより、上からいってもらった方がAIは使いやすいなという気はします。
コストはある程度かかりますが、そのコスト以上に削減できる費用や得られる利益があると思います。
もっとも、活用次第ですが。

# おまけ：【起業志望向け】AIビジネスプランコンテスト ～ 先輩起業家にプレゼンしてみよう！

知り合いの会社が2025年5月17日（土）にAIビジネスプランコンテストを行います。AI分野で起業されている先輩経営者の方が審査員になっています。

AI技術そのものだけでなく、AIを活用した既存ビジネスのリフォームなど新しいAIX実現をするビジネスプランを考えてプレゼンするイベントです。

起業家同士、先輩経営者との交流などもあるようです。
大学生だけでなく、起業家や起業志望者であれば参加可能のようです。

https://ai-idea-share.connpass.com/event/350788/
[Next.js 15.3]新機能の「useLinkStatus」と「onNavigate」を使ってみる

# はじめに
Next.js15.3のアップデートで、Linkコンポーネントの新しいプロパティである「***onNavigate***」と、ナビゲーションフックである「***useLinkStatus***」が導入されました。

特に、「***useLinkStatus***」は非常に使い勝手の良い機能で、これを使うと、ページ遷移時にインジケーターを表示するなどの処理ができるようなるため、非常に便利なものかと思います。

https://nextjs.org/blog/next-15-3#onnavigate

# 使ってみよう
実際に使ってみましょう。
ヘッダーの中で実装していくので、「layout.tsx」に「Header」コンポーネントを用意しておきます。

```layout.tsx
export default async function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  return (
    <html lang="ja" className={geist.className}>
      <body>
        <Header />
        {children}
      </body>
    </html>
  );
}
```

## onNavigate

https://nextjs.org/docs/app/api-reference/components/link#onnavigate

まずは「**onNavigate**」です。
以下のコードは、ページ遷移時にコンソールを出力します。
「onNavigate」プロパティを使うためには、クライアントコンポーネントにする必要があります。

``` Header.tsx
"use client";

import Link from "next/link";

export default function Header() {
  return (
    <header>
      <Link
        href="/dashboard"
        onNavigate={() => {
          console.log("Navigation...");
        }}
      >
        Dashboard
      </Link>
    </header>
  );
}
```

以下のように動作します。
![onNavigate.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2613586/b2893797-410d-4863-a1ea-4d63ee331f3a.gif)
この機能を利用することで、ページ遷移時に何かしらの処理を入れたいといった場面で使えるかと思います。

## useLinkStatus

https://nextjs.org/docs/app/api-reference/functions/use-link-status

「useFormStatus」と同じような感じで、「Link」コンポーネントの子要素として別コンポーネントに切り出して使います。
以下のコードは、公式のサンプルコードで、ページ遷移時に砂時計を表示します。

``` loading-indicator.tsx
"use client";

import { useLinkStatus } from "next/link";

export default function LoadingIndicator() {
  const { pending } = useLinkStatus();
  return pending ? <span>⌛</span> : null;
}
```

``` Header.tsx
import Link from "next/link";
import LoadingIndicator from "./LoadingIndicator";

export default function Header() {
  return (
    <header>
      <Link href="/dashboard">
        Dashboard <LoadingIndicator />
      </Link>
    </header>
  );
}
```

以下のように動作します。

![useLinkStatus.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2613586/c9998443-933b-4bc9-88ca-f9e94ba0daa2.gif)

これを利用することで、ページ遷移時に重い処理が走り、画面表示までに時間がかかる場合でも、ユーザーにレスポンスを返すことが簡単にできるようになるので、とても便利だと思いました。

# 最後に

他にも色々な記事を書いているので、よければ読んでいってください！

https://qiita.com/hukuryo/items/b3b8f7b79c842b38e889

https://qiita.com/hukuryo/items/4a02784929b0cf0404a5

https://qiita.com/hukuryo/items/2a649d2ee018308d89f6

https://qiita.com/hukuryo/items/4e957621682a25da5f3b

https://qiita.com/hukuryo/items/e14779aeb0c0cf26c2d2
個人的備忘録：チルダ（~）の意味と使い方について、記事にまとめてみました

## はじめに
プログラミングやコマンドライン操作をしていると頻繁に見かける記号「~（チルダ）」。

:::note info
***一見すると意味が分かりにくいですが、特にUNIX系OS（LinuxやmacOSなど）ではよく使われる便利な記号です。***
:::

この記事では、チルダの基本的な意味と使い方について簡潔に紹介します。

## チルダの基本的な意味
チルダ（~）は、**カレントユーザーのホームディレクトリ**を表します。

たとえば、現在のユーザー名が `user` の場合：
```bash
~ = /Users/user （macOS）
~ = /home/user （Linux）
```

## 主な使い方

### 1. ディレクトリの移動
```bash
cd ~
```
→ ホームディレクトリに移動します。

```bash
cd ~/Documents
```
→ ホームディレクトリ配下の `Documents` に移動します。

### 2. ファイルのパス指定
```bash
nano ~/.zshrc
```
→ ホームディレクトリにある `.zshrc` ファイルを編集します。

### 3. 他ユーザーのホームディレクトリを参照
```bash
~username
```
→ そのユーザーのホームディレクトリを指します（例: `~honda`）。
※一部のシステムでは無効な場合もあります。

## 注意点
- `~` はクォート（'や"）で囲むと展開されなくなる場合があります。
- スクリプトなどで使う場合には環境やシェルに依存する挙動もあるため注意が必要です。

## まとめ
チルダ（~）は、ホームディレクトリを簡潔に表すための非常に便利な記号です。

:::note warn
コマンド操作を効率化するうえで頻繁に活用されるので、基本的な意味と使い方をしっかり押さえておくと便利です。
:::

個人の備忘録として、基本の理解に役立てば幸いです！
Claude MCPとSlack連携を試してみた

# はじめに
こちらの記事の続きです！
Claude MCPの導入手順について記載しているのでご参考ください。

https://qiita.com/does_not_exist/items/e473f92af3273f5637c1


今回はSlack連携を試してみました。


# 結果

![スクリーンショット 2025-04-14 7.31.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2889192/2c93e1db-8e18-4987-9d66-4452df7aedae.png)

![スクリーンショット 2025-04-14 7.38.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2889192/525fa9a3-9041-4cf4-a4d4-b6267228153f.png)


チャンネル投稿の他、投稿されたメッセージの取得も試してみました。
ありがちな、通知対象者をチャンネルに招待していなかった問題も親切に教えてくれました、

![スクリーンショット 2025-04-14 7.53.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2889192/b4e01944-52f9-4e9c-a758-3401234db096.png)



# 手順

Slack MCPサーバーをダウンロードします。

https://github.com/modelcontextprotocol/servers/blob/main/src/slack/README.md

Claude Desktopを使用しているので、READMEに記載されている通り、Users/username/Library/Application Support/Claude/claude_desktop_config.jsonに以下を記載します。


```json:Users/username/Library/Application Support/Claude/claude_desktop_config.json
{
  "mcpServers": {
    "slack": {
      "command": "npx",
      "args": [
        "-y",
        "@modelcontextprotocol/server-slack"
      ],
      "env": {
        "SLACK_BOT_TOKEN": "xoxb-hoge",
        "SLACK_TEAM_ID": "Thoge"
      }
    }
  }
}
```

あとはClaudeを再起動すればOKです。



# おわりに
他のサービスとの連携も試してみたり、いろいろできそうなので引き続き触ってみたいです。
個人的備忘録：S3で静的ファイルを全世界に公開するには？ポリシー例つき解説してみた

## はじめに
AWS S3では、バケットポリシーを使用することで、S3バケットに対するアクセス制御を細かく設定できます。

:::note info
**個人の備忘録程度の走り書きとなっておりますが、温かい目で見守っていただければ幸いです。**
:::

本記事では、バケット内のファイルを誰でも読み取れるようにするポリシーの例と、その意味について解説します。

## ポリシー内容
以下は、`dev-s3-content` という名前のS3バケット内のすべてのオブジェクトに対して、誰でも（匿名ユーザーを含む）読み取りを許可するバケットポリシーです。

```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "PublicReadGetObject",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::dev-s3-content/*"
        }
    ]
}
```

## 各項目の解説
- `Version`: ポリシー言語のバージョン。通常は"2012-10-17"を指定。
- `Statement`: アクセス制御の定義ブロック。
  - `Sid`: 任意の識別子。ログや管理目的に使える。
  - `Effect`: "Allow"は許可、"Deny"は拒否を意味する。
  - `Principal`: `"*"` はすべてのユーザー（匿名を含む）を指す。
  - `Action`: `s3:GetObject` はオブジェクトの取得（ダウンロード）を許可。
  - `Resource`: アクセスを許可するリソース。`/*` はバケット内のすべてのファイルを対象とする。

## 注意点
- この設定を行うと、インターネット上の誰でもバケット内のオブジェクトにアクセスできるようになります。
- 静的ウェブサイトホスティング用途などでよく使われますが、機密情報や個人情報を含むデータには絶対に使わないようにしましょう。

## まとめ
このポリシーは、静的ファイルを公開する場合などに便利ですが、セキュリティリスクも伴います。

:::note warn
***用途を明確にしたうえで、アクセス制御を慎重に設定することが重要です。***
:::

個人の備忘録でしたが、S3のアクセス制御の理解を深める技術的な支えとなれば幸いです！
位置情報ルーティングと地理的に近接性ルーティング

Route 53 の「**位置情報ルーティング（Geo Location Routing）**」と「**地理的に近接性ルーティング（Geo Proximity Routing）**」は、名前が似ていますが**仕組みも目的も異なる**ルーティングポリシーです。以下にわかりやすく整理します。

---

## 🌎 1. 位置情報ルーティング（Geo Location Routing）

### 🧠 特徴
- **DNSクエリの発信元の「地理的な位置（国や大陸）」に基づいて**、異なるIPやリソースを返します。
- たとえば「**日本からのアクセス → 東京のサーバー**」「**アメリカからのアクセス → 米国リージョンのサーバー**」などが可能。

### 📌 ユースケース
- 国ごとの法律や規制に対応したサーバー切り分け
- 言語別・地域別サービス
- 海外アクセス制限や制御

### ✅ 特徴まとめ

| 項目 | 説明 |
|------|------|
| ルーティングの基準 | **クライアントの地理的な位置情報**（国/大陸など） |
| 利点 | 地域ごとのポリシー適用が簡単 |
| 精度 | 国単位での制御がメイン（IPジオロケーションに依存） |
| 設定方法 | 各レコードに「地理情報（例：JP, US）」を割り当てる |

---

## 📍 2. 地理的に近接性ルーティング（Geo Proximity Routing）

### 🧠 特徴
- **ユーザーの現在地と、各AWSリージョン（または任意の地点）の「物理的距離」に基づいて**、最も近いリソースへルーティングします。
- 距離は **実際の距離（緯度経度）ベース**。そして「**バイアス（重み）**」を加えて調整可能です。

### 📌 ユースケース
- レイテンシを最小にしたいグローバルWebサービス
- 特定のリージョンのトラフィックを制御したい（例：東京リージョンの負荷分散）

### ✅ 特徴まとめ

| 項目 | 説明 |
|------|------|
| ルーティングの基準 | **ユーザーの現在地からの物理的な距離** |
| 利点 | **低レイテンシ**が実現できる |
| 精度 | 緯度経度ベース（Route 53トラフィックフロー or API必須） |
| 設定方法 | Route 53 トラフィックフロー + geoproximity rule で定義 |

---

## 🧭 比較表

| 比較項目 | 位置情報ルーティング | 地理的近接性ルーティング |
|----------|----------------------|----------------------------|
| 判断基準 | 国や地域（IPから特定） | 緯度経度による物理距離 |
| 対応単位 | 大陸・国・都道府県など | AWSリージョンや任意の地点 |
| 使いやすさ | 簡単（GUIで設定可能） | やや複雑（トラフィックフロー必要） |
| 利用例 | 規制・言語対応など | レイテンシ最適化・分散トラフィック |
| 調整可能性 | 固定（優先度など） | 距離バイアスを自由に操作可能 |
windows11で、sketchup6 その71

# 概要
windows11に、sketchup6を入れてみた。
rubyで、3Dを書く。
練習問題、やってみた。

# 練習問題
カメラのアングルを求めるRUBYスクリプトを書け。

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/0a27df07-0e4d-4062-9463-19c22120f71a.png)

# サンプルコード

```

def camera
	view = Sketchup.active_model.active_view
	camera = view.camera
	if camera.perspective?
		cam_type = "type:	perspective"
	else
		cam_type = "type:	orthographic"
	end
	eye = camera.eye
	vx = eye.x.to_f
	vy = eye.y.to_f
	vz = eye.z.to_f
	target = camera.target
	tx = target.x.to_f
	ty = target.y.to_f
	tz = target.z.to_f
	vfovdeg = camera.fov
	vfovrad = vfovdeg * Math::PI / 180.0
	h = Float(view.vpheight)
	w = Float(view.vpwidth)
	foc = (h / 2) / Math.tan(vfovrad / 2.0)
	hfovrad = 2.0 * Math.atan2((w / 2), foc)
	hfovdeg = hfovrad * 180.0 / Math::PI
	ar = camera.aspect_ratio
	ratio = view.vpwidth.to_f / view.vpheight.to_f
	puts(cam_type)
	puts("location:	" + vx.to_s + ", " + vz.to_s + ", " + vy.to_s)
	puts("look_at:	" + tx.to_s + ", " + tz.to_s + ", " + ty.to_s)
	puts("ratio:	" + ratio.to_s)
	puts("up	" + camera.up.x.to_s + ", " + camera.up.z.to_s + ", " + camera.up.y.to_s)
	puts("angle:	" + hfovdeg.to_s + ".degrees")
end



```

以上。
ドメインモデル貧血症は本当に悪いのか？

# はじめに
ソフトウェア開発における設計上の問題としてよく取り上げられる「ドメインモデル貧血症」。一見、避けるべきものに思えますが、果たして本当にそうなのでしょうか？結論としては、DDDの「ドメイン知識をコードで表現すること」に反する設計状態のため、基本的に避けるべきだと考えています。この記事では、ドメインモデル貧血症の原因とその影響を紹介します。


# ドメインモデル貧血症とは



ドメインモデル貧血症とは、ドメインオブジェクトに本来書かれるべきドメイン知識がドメインオブジェクトの外（サービスやコントローラーなど）に書かれてしまっている状態のことを指します。

よくGetter/Setterしかないドメインオブジェクトのことだと言われがちですが、それだけだと物足りません。
**ドメインオブジェクトの外でドメイン知識が書かれてしまっているため、結果的にGetter/Setterしかない状態になってしまうというのが適切です。**


以下はEmailという値オブジェクトでドメインモデル貧血症になっている例・ないっていない正しい例のコードです。

```ts: ドメインモデル貧血症になっている
// Email値オブジェクト（ただのデータの入れ物）
class Email {
  private _value: string;

  constructor(value: string) {
    this._value = value;
  }

  get value(): string {
    return this._value;
  }
}

function createUser(emailStr: string) {
//  呼び出し側（サービスやコントローラー）でバリデーションなどを行っている
  if (!emailStr.includes('@')) {
    throw new Error('Invalid email address');
  }

  const email = new Email(emailStr);
  // ユーザー作成処理へ進む…
}

```

```ts:ドメインモデル貧血症になっていない
class Email {
  constructor(private readonly _value: string) {
    if (!this._value.includes('@')) throw new Error('Invalid email address');
  }

  get value(): string {
    return this._value;
  }
}
//  呼び出し側（サービスやコントローラー）でバリデーションなどを行っている
function createUser(emailStr: string) {
  const email = new Email(emailStr);
  // ...
}
```
# ドメインモデル貧血症の問題点
**ドメイン知識の欠如**
 ドメインモデルが単なるデータ保持クラスに成り下がり、ビジネスルールやドメイン固有の知識が外部（サービス層など）に分散してしまいます。これにより、ドメインモデルがビジネスの意図を反映していないため、ドメインの深い理解が得られません。ドメインの深い理解がドメインモデルに表現されないというDDDの目的に反してしまいます。
 
**凝集度の低下**
ドメインモデルにロジックが持たれないため、データとロジックが別々の場所に分散し、凝集度が低くなります。これにより、同じデータに関連する処理があちこちに書かれてしまう可能性があり、変更や拡張が煩雑になります。関連する処理がどこにあるのかが分かりにくくなり、修正漏れの発生や保守性が低下します。

# ドメインモデル貧血症になる原因
**データベース中心の設計**
最初にDBのテーブルスキーマを決めて、それを元にコードを生成すると、モデルは「ただのデータ構造」になり、ロジックを持ちにくくなります。

**サービスオブジェクトの誤用**

サービスに全てのビジネスロジックを書くのが「設計ルール」と思い込み、値オブジェクトやエンティティを単なるDTOのように使ってしまうと、それらにドメイン知識が書かれず低凝集になります。

**Fat Modelを避けようとして...**
Fat Modelを避ける判断が、結果的にドメイン知識をモデルの外に分散させ、ドメインモデル貧血症につながる可能性があります。

**既存プロダクトでドメイン駆動設計の導入途中の時**

既存のプロダクトにおいて、ビジネスロジックがサービス層やコントローラー層に散らばっている場合、これをドメインモデルに移行するのは容易ではありません。移行が途中で止まったり、ロジックが分散したままの状態で、ドメインモデルが単なるデータ保持の役割を果たすことになりがちです。

# Read系のAPIのリファクタでDDDを導入するときどうするか？

Read系APIでは、QueryServiceなど使うこともあります。
しかし、ドメインオブジェクトを使いたい時もあるでしょう。
この場合、DBから取得したデータをリポジトリでドメインオブジェクトに変換して返すこともあります。しかし、DBに保存されたデータそのものは信用せず、ドメイン知識をドメインオブジェクトに反映させることが重要です。

スケジュールに余裕がない場合、すぐにドメインオブジェクトにビジネスロジックやバリデーションを追加するのは難しいことがあります。この場合、最初はDBから取得したデータをそのまま利用することで短期的な手間を省けます。しかし、この方法を続けると、ドメインモデルが単なるデータ保持用オブジェクトとなり、DDDの目的であるドメイン知識やビジネスロジックのコード化が遅れます。

そのため、後でドメインオブジェクトにビジネスロジックを組み込む計画を立てることが大切です。最終的には、ドメインオブジェクトがビジネスロジックやルールを担うべき存在となり、ソフトウェアの凝集度や保守性を高めることになります。初期段階ではデータ構造として扱い、後でロジックを追加していくことで、ビジネスルールや振る舞いを反映させることが求められます。最初から完璧なドメインモデルを作る必要はないので、継続的にモデルを育てていきましょう。



# 最後に
ドメインモデル貧血症は、ドメイン駆動設計の本来の目的である「ドメイン知識をコードで表現すること」に反する設計状態です。単にデータを保持するだけのモデルでは、変更に強く、意図が明確なソフトウェアを実現することは難しいでしょう。よって、状況にもよりますが基本的に**ドメインモデル貧血症は悪い**と言っても過言ではないと思います。

もちろん、すべてのモデルに一気にロジックを詰め込む必要はありません。特に既存プロダクトやリードタイムの厳しい環境では、段階的な導入が現実的です。まずは意識的に「ドメイン知識をどこに書くべきか？」を考え、少しずつでもモデルに責任を持たせていくことが、保守性の高い設計への第一歩となります。