OmniAICreator/Qiita-1.07M huggingface dataset:
エンジニアとの約束事～ユーザーストーリー～

* まともなPdMがいない
* スクラムマスター不在
* ステークホルダーに権限がない
* アジャイル経験者0

　この状態を想定して、アジャイル開発を行ったことがないチームに対してアジャイルを導入するために、非エンジニアを含めた関係者に開発としてのユーザーストーリーを浸透させるために作った資料です。

# システム開発においてのユーザーストーリー？
　システム開発向けのユーザーストーリーを今まで作ってこなかった場合、最初につまづくのがここだと思います。
　実際にユーザーストーリーはプロダクト全体で見れば使っているはずなんです。
　問題はユーザーストーリー自体、事業を起こす場合2種類存在してしまっているということです。
　１種類目はマーケティング手法としてのユーザーストーリーは例で書くとこうなりますよね？

* ペルソナの設定
* ペルソナの属性や行動
* 行動を促進するためのキャンペーンや施策
* 行動後ユーザーが得られるメリット

　さてと……それじゃぁ、ユーザーストーリーは完璧ですね（？）Qiitaと同等の機能を考えましょう。

* エンジニアは他の人とのナレッジの共有のためにQiitaで記事を書く、それによってhogehogeできるから

　さぁこれから、Qiitaの開発をしてください。
　Qiitaというサービスの前例があるんでできんことはないですが、一から作るとなると……何もかもが足りません。
　そのため、システム開発にはより具体的なものが必要になります。
　そのために以下のような情報を具体的に書いてあげる必要があります。

* システムが持つ機能
* 機能操作
* 得られるべき結果

　じゃぁQiitaの編集者をペルソナとして記事を書いてみましょう（＊社内で没になったシステム元なので雑です）

* 編集者は記事一覧を見たい、なぜなら自分の投稿を探すためだ
* 編集者は記事を作成したい、なぜなら読者に記事を提供するためだ
* 編集者は記事を確認したい、なぜなら記事の脱字などを確認するためだ
* 編集者は記事を編集したい、なぜなら誤解を生むような記事はー謝罪しないか別に
* 編集者は記事を削除したい、なぜなら都合の悪い記事を抹消するためだ

　これだと、一覧がページネーション必要か削除は論削なのかなどの詳細情報が入りません。
　そのためここからユーザーストーリーのマッピングを行う必要があります。

# ユーザーストーリーマッピング
**1. ユーザーストーリーを抽象化**
　せっかく作ったユーザーストーリーですが、重複が見られるのでいったん抽象化しましょう。
　おおまかにわけると、一覧と投稿機能に分けられると思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/381248/a3d1305c-a1c4-0e06-49ce-24b8253b41ae.png)
　面倒臭ければユーザーストーリーじゃなくいきなりここ書いてもいいんですが……経験積まないといきなりやるのは難しいので今回は手順を踏んでいます。
 **2. タスクの設定**
　ユーザーの行動には必ず何らかの目的……タスクが存在します。それを書きだしましょう、例えば記事を管理したいにまとめられた、作成、編集、削除等ですね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/381248/4c9fc264-c522-0893-0476-d4472a472e03.png)
　先ほど「システム開発においてのユーザーストーリー？」のところで語ったユーザーストーリーになりましたね。
　ここから必要な処理を細かく切り出していきましょう。
**3. 詳細なストーリー**
　ここからなんですが、各タスクで必要な処理を適当に書き殴っていきましょう。思うままに書いてください、見返してここ同じだったなとかで消してもいいので。
　私も稀に、元々のユーザーのタスク自体が足りなかったなとかありますので（実話）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/381248/d39597d1-2815-4c1c-093e-0d6f37ef267c.png)
　正直編集系は編集系でまとめた方がいいんですが……なんか縦に長くなるの嫌だなぁって理由で横に並べています。ここは伝わればいいので端折っていない限りで言えば、好みでいいでしょう。
　さて……処理の推定がより詳細になることにより、優先順位づけやどういう処理があるかなどの合意や共有ができるようになるのではないでしょうか？
　ですが、書いていくと必ずこんなにいっぺんに開発できないよーってなる時が稀によくあります。
　リリーススコープを定め、段階的なリリースにするパターンですね。
　その場合、優先順位の高い順に処理を並び替えましょう。
 

# リリーススコープ
　非エンジニアが主導権を取る場合、どうしても１画面を完璧に仕上げようとしてきますが、それはアンチです。
　私の経験したのは……例えばこんなんとかですかね？
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/381248/191aed0f-efc0-e837-b158-945f8ba045ab.png)


　なんだこの気持ち悪いリリーススコープ、レバーにきますね。実際にスコープわけするとこうなります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/381248/5230ef79-62b6-dd31-be27-f8ae272405fd.png)

 　優先度が高くかつ、まとまった単位でリリースするのが本来の意味のスコープわけですね。

# 最後に
　共有できるのであれば、タスクに分解するのと必要な処理書きなぐるだけでもいいかと思います。よっぽど天才でもない限り慣れていないのに一発で書けるとかはまずないので地道に一歩一歩書いていきましょう。
　ここら辺はプロダクトとエンジニアとの約束事でもあるので、たまにいるのが「俺がわかるから」で端折ってしまうと一人開発の一人プロジェクトなら何とかなりますが複数名だと「私はこう思っていた」でこじれるのでやめときましょう。
　一般的だからの思考も危険です。一般的だと感じているのが業界的慣習の場合……業界未経験のやつはわからんし自分が一般的だと思い込んでいるだけなので普通に教えるの忘れるし、中核メンバーがごっそり消えると仕様自体が遺失する危険性も上がります。考えるだけでレバーにきますね？
アジャイル開発：Doneの定義

# はじめに
この記事では、アジャイル開発における「Doneの定義（Definition of Done, DoD）」について記載していく。
Doneの定義をしない場合（もしくはチーム内で共有しない場合）どう言うことが起こるのか？
またプロジェクトの成功にどのような影響を与え、どのように決定すべきか例を交えながら記載していく。

# まずはDoneの定義とは？
アジャイル開発における「Doneの定義（Definition of Done, DoD）」とは、成果物が「完了」と見なされるために満たすべき基準を明確化したチェックリストです。これにより、チーム内での認識を統一し、品質を担保しつつ手戻りを防ぎます

### 主な内容
- **チェックリスト例**: 単体テストや結合テストの合格、コードレビュー完了、非機能要件の達成など
- **メリット**: 品質向上、透明性確保、リスク削減
- **注意点**: 過剰な依存や不十分な検証の可能性

DoDは継続的に見直し改善する必要があります

# 「Doneの定義」がチーム内で共有されない場合に発生しうる問題
以下のような問題が発生することが考えられる。
- **品質のばらつき**: 各メンバーが異なる基準で「完了」を判断するため、成果物の品質が一貫しない
- **手戻りの増加**: 完了基準が曖昧だと、後から修正や追加作業が必要になることが多い
- **コミュニケーション不足**: チーム内やステークホルダー間で期待値が一致せず、誤解や摩擦が生じる
- **スプリント計画の混乱**: タスクの進捗状況が正確に把握できず、計画が崩れる

完了に認識が人によって異なることになるため、成果物であるアウトプットが対応する担当者によって異なることになる。


# 「Doneの定義（Definition of Done, DoD）」をした場合
「Doneの定義（Definition of Done, DoD）」はプロジェクトの成功に以下のような重要な影響を与えます：

- **品質の向上**: 明確な基準により、成果物の一貫性と品質が担保されます
- **透明性の向上**: チーム全員が進捗状況を正確に把握でき、コミュニケーションが円滑になります
- **リスクの軽減**: 未完了作業（Undone）の発生を抑え、リリース遅延や手戻りを防ぎます
- **効率的なプロジェクト管理**: タスク完了基準が明確化され、計画と実行がスムーズになります

先ほどの項目では「Doneの定義」がチーム内で共有されない場合の問題について記載したが、
この項目では逆に逆にDoneの定義が明確であり、かつチーム内で正しく共有されていれば
誰が担当してもDoneの定義を満たしていれば成果物のアウトプットにブレは生じにくくなることになる。

特にスケジュールがタイトである場合は、Doneの定義が明確であることが非常に重要となる。
スケジュールギリギリの状態で作成されたアウトプットが、レビュアーや受け入れ担当者の意図したアウトプットと異なることを回避できる。

# Doneの定義を作成する手順
Doneの定義を適切に設定することで、チームの生産性と成果物の品質を向上させることができます。
この項目では、Doneの定義を作成する手順について記載していく。

1. チーム全員で話し合う
   - プロダクトオーナー、開発者、テスターなど、全員が参加する必要があります。

2. 顧客に提供するために必要な作業を洗い出す
   - 「プロダクトを顧客に届けるために何が必要か」を考えます。
   - コーディング、テスト、ドキュメンテーションなど、あらゆる作業を含めます。

3. 現実的に毎スプリントで実施可能な作業を選択する
   - チームの能力と現状を考慮し、実現可能な項目を選びます

4. リストを作成し、合意を得る
   - 選択した項目をリスト化し、チーム全員の合意を得ます。

5. 定期的に見直し、改善する
   - スプリントレトロスペクティブなどで定期的に見直し、必要に応じて更新します。

## Doneの定義の具体例

以下は、一般的なDoneの定義の例です：

1. コーディング完了
   - 機能が実装されている
   - コードレビューが完了している
   - コーディング規約に準拠している

2. テスト
   - 単体テストが作成され、全てパスしている
   - 結合テストが実施され、パスしている
   - 受入テストが実施され、パスしている

3. ドキュメンテーション
   - ユーザーマニュアルが更新されている
   - API仕様書が更新されている
   ※いわゆるマスタードキュメントとなるドキュメンテーションを明確にする必要がある

4. 品質
   - パフォーマンス要件を満たしている
   - セキュリティチェックが完了している

5. デプロイ
   - 開発環境にデプロイされ、動作確認が完了している
   - ステージング環境にデプロイする準備が整っている

## Doneの定義を効果的に使用するためのヒント

1. **具体的に記述する**: 「テスト完了」ではなく、「全ての単体テストがパスし、結合テストが実施されている」のように具体的に記述します。

2. **測定可能にする**: 「高品質」ではなく、「コードカバレッジ80%以上」のように測定可能な基準を設定します（※定量的に記載可能な部分は可能な限り定量的に記載する）。

3. **チーム全体で合意する**: Doneの定義はチーム全体で合意し、全員が理解し遵守する必要があります。

4. **可視化する**: Doneの定義をタスクボードの近くに掲示するなど、常に参照できるようにします。

5. **段階的に改善する**: 最初から完璧なDoneの定義を作る必要はありません。徐々に改善していくことが重要です

Doneの定義を適切に設定し、活用することで、チームの生産性が向上し、高品質な成果物を継続的に提供することができます。定期的に見直し、改善することを忘れずに、チーム全体でDoneの定義を育てていきましょう。


# Doneの定義を強化するためには？
以下のツールや方法が有効となる。
- **チェックリストの活用**: 明確な基準をリスト化し、タスクごとに適用できるようにする
- **JiraやTrelloなどのツール**: チェックリストやカスタムフィールドを活用し、各タスクに対するDoDを可視化
- **振り返り（レトロスペクティブ）**: スプリント後にDoDを評価し、改善点を議論
- **ワークショップの実施**: チーム全員でDoDを議論し、共通認識を形成
- **品質管理ツール**: 自動テストやコードレビュー支援ツールで基準達成を確認


以上
【Rails API】pagyを使用してページネーションを実装する方法

## pagyをインストールする

`Gemfile`に以下を追記します。

```rb:Gemfile
gem 'pagy', '~> 9.3' # omit patch digit
```

ターミナルで`bundle install`を実行します。

## 設定ファイルを作成する

https://ddnexus.github.io/pagy/quick-start/#2-configure

上記のページから`pagy.rb`ファイルをダウンロードし、`config/initializers`に保存します。

## セットアップする

`application_controller.rb`に以下を追記します。


```rb:application_controller.rb
class ApplicationController < ActionController::API

  include Pagy::Backend

end
```

## コントローラーを記述する

```rb:products_controller.rb

class ProductsController < ApplicationController

  def index
    @pagy, products = pagy(Product.all, limit: 10)
    render json: products
  end

end
```

## ヘッダーを追加する

レスポンスヘッダーに`current-page`、`page-items` 、`total-pages`、`total-count`を追加するために以下の作業を行います。

`config/initializers/pagy.rb`の以下のコメントアウトを外します。

```rb:pagy.rb

require "pagy/extras/headers"
Pagy::DEFAULT[:headers] = { page: "Current-Page",
                            limit: "Page-Items",
                            count: "Total-Count",
                            pages: "Total-Pages" } # default

```

次に`application_controller.rb`に以下を追記します。

```rb:application_controller.rb
class ApplicationController < ActionController::API
  after_action { pagy_headers_merge(@pagy) if @pagy }

end
```

## 参考

https://ddnexus.github.io/pagy/quick-start/

https://ddnexus.github.io/pagy/docs/extras/headers
【簡単】DeepSeek R1 をGPUなしでUbuntu で ローカルで使う CPUのみ

## 話題のDeepSeek
ブラウザ版とAndroid版のを普段から使ってきていたが，
なんせ中国の会社なので突然サービス終了したりするかもっと思ったので（根拠ない），
ローカルで動かしてみたかった．
（追記；）DeepSeekが流行りだして、アプリ版もブラウザ版も少し不安定なタイミングも

※当記事はUbuntu用です. Windows版は以下の記事をご覧ください

https://qiita.com/devtamtam/items/47d3b5a9a16cae8cee1d/




さて
今回の環境は 独立GPUなしで

- Ubuntu 22.04.5 LTS x86_64
- i5 4570 (4 core)
- 8GB ram
- デスクトップ(NEC mate)

## libfuse2 をインストール
こいつが何をしてるのかは知りません。

```
sudo apt install libfuse2
```

## LM studioをインストール．
 LM studioをインストール．いろんな
 Locall LLMが動かせるやつです.
 
https://lmstudio.ai/


サイトからAppImageをダウンロードしたら、お決まりのコマンドを。

```
cd /Downloads
chmod u+x LM-Studio-0.3.8-4-x64.AppImage
```

そしてとりあえずLM studio を起動

```
.\LM-Studio-0.3.8-4-x64.AppImage
```


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3117133/1fe9b96d-4471-9952-6baa-80d65bdc14aa.png)




## 適当なモデルを選んでダウンロード

![Screencast from 2025年01月27日 23時35分17秒.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3117133/dda1dc1c-9905-6dcd-78af-dd87b86a7a21.gif)


（これはCPUなしでも動く軽めのモデル（distill）です）
7Bとかがおすすめです。


ダウンロードが完了したら


**Load Model**ってのをクリック

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3117133/dddcfaeb-345c-c604-e872-41dafb652e3d.png)





## いざ会話開始

![Screenshot from 2025-01-27 23-41-46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3117133/ab10469b-1888-3fd0-941c-ff2d1b442fbe.png)


できました

ネットなしでも動くとちょっと感動ですね．
PL-200を受験してきた話

## きっかけ
そのうち受けようと思って以前からちょこちょこMicrosoft Learnでお勉強はしていたものの、お値段が2万飛んで300円とかわいくなかったので中々手が出なかったPL-200ですが、会社の懇親会の帰りに電車に揺られながらなんとなく最寄りのテストセンターの空きを見ていたところ翌日の昼過ぎが空いてる！受けたろ！と酔った勢いで申し込んで受けてきましたので所感のご共有です。



## PL-200の試験範囲

PL-200の試験情報はこちらから確認できます。

https://learn.microsoft.com/ja-jp/credentials/certifications/exams/pl-200/

これによると出題範囲は下記のとおり。

* Microsoft Dataverse
* Microsoft Power Apps
* Microsoft Power Automate クラウド フロー
* Microsoft Power Pages
* Microsoft Power Platform 環境

::: note warn
2025年1月時点の情報です。受験を検討する場合は必ず試験範囲を確認してください。
:::

特にMicrosoft Dataverseの設問が多かったように感じます。
ビジネスルール、ビジネスプロセスフロー、列のセキュリティプロファイル、従来のワークフローなど、Dataverseで使用できる機能は一通り把握しておきましょう。
また、Power AutomateやPower Appsなどで使用するPower FXの記述方法など、市民開発者としての知識も問われます。

Power Pagesについてはそれほど問われませんでした。Power Platform環境についてはDataverseほどは出題されませんでしたが、セキュリティロールなど重要機能については必ず押さえておきましょう。



## 勉強方法

* Microsoft Learn のドキュメントをやる

「とにかくDataverseマスターになれ」これに尽きると思います。
もちろんPower AutomateやPower Appsについても出題されますが、専ら「この要件を満たすにはDataverseのどの機能を使うのが適切か？」を考える訓練をしておくと正答率が上がってきます。
「従来のワークフロー」とか、普段からよくPower Platformを使っている人でもあまり使用頻度の高くない機能も試験範囲になってますので、みっちり勉強しておくと安心ですね。逆にPower AutomateやPower Appsの問題は普段から市民開発している人であればそれほど悩まずに答えを導けるかもしれません。

上記のPL-200の試験概要ページ下部に推奨のモジュール（1講座1モジュールくらいの認識です）をまとめたコレクションがありますので、これを順番に1つずつこなしていきましょう。

全部で40モジュールほどあり、1モジュールあたりのボリュームは公式だと1時間くらいなのでモジュールをすべて終えるのは40時間ほどかかる計算ですが、実際にはもう少し早めに終わらせられると思います。とはいえかなりの時間はかかると思うので地道に少しずつ潰していきましょう。

:::note info
一部のモジュールはPL-900と重複しているので、PL-900の勉強経験がある方はいくつかのモジュールはスキップできるでしょう。
:::


## 試験当日
受験方法は下記の2つから選択して受験できます

* テストセンターで受験する
* 自宅でオンライン受験する

テストセンターが自宅の近くに無い方は自宅でも受験ができて便利ですが、受験環境はかなり厳しく監視されています。受験前にデスクの周辺を移すように促され、受験に関係のないものは全て排除しなければなりません。私はPL-900のは自宅で受験しましたが、「机の上の白いものは何ですか」と試験監督に聞かれました。ただのゴミでしたが片づけるように言われました。
同僚は受験中に仕事の電話が入り、スマホを手に取ったら強制終了になったそうです。それはさすがにアカンでしょ。

:::note info
不正を疑われないようテストセンターでの受験をお勧めします。
:::

試験時間は100分。試験時間に対して設問数は多くなく、ゆっくり考えながら回答する余裕はあります。また、試験中、マイクロソフトのwebの公式ドキュメントで調べながらの回答が可能です！これにより、知識の浅かった項目は検索をかけて公式ドキュメント内の回答を探すこともできます。ドンピシャな回答がありますが、間接的に答えを類推できる場合もあるので、どんなことを調べるときに、どんなワードで検索をかければよいか？など、用語と用語を関連付けて覚えておくとより正解を見つけやすくなります。

:::note warn
公式ドキュメントで答えを探すのに時間をかけすぎないように注意しましょう。
:::


## 受けてみて

合格すると、下記のような他の人に共有できる認定資格ページが表示されます。
ちゃんと名前も載ってました。わあい。

https://learn.microsoft.com/api/credentials/share/ja-jp/SeishiroSato/52B2B8BC0E1DCF46?sharingId=53B948F2BBCAB22B

:::note info
PL-200に合格することで取得できる資格 "Microsoft Certified: Power Platform Functional Consultant" の有効期間は1年間です。更新のためには再度試験に合格する必要があります。なお、更新の際の受講料は無料です
:::

PL-200はどちらかというと開発者というより顧客と要件の折衝をしたりするコンサルタント向けの資格ですが、開発者でも知っておくべき知識がふんだんに盛り込まれた試験になっています。
Power Platformを扱う市民開発者の皆様はまずPower AutomateやPower Appsを触ることが多いと思いますが、この試験の受験勉強を通じてPower Platformの環境の設定や、Dataverseの各種機能についての理解を深めることで、より一歩進んだ開発を行うことができるようになるハズですので、組織の基幹業務の自動化を目指す方々はぜひ挑戦してみてください。
共有メールボックスのライセンス

共有メールボックスは無償で作成、使用が可能。
ただし統制をきかせたり、セキュリティを担保するためにはライセンス付与が必須。

・Exchange Online プラン2 を付与すると使用可能になること
　-上限が100GBになる(付与しない場合は50GB)
　-訴訟ホールド
　-アーカイブ
　-アイテム保持ポリシー
・Microsoft Defender for Office365 プラン1 を付与すると可能になること
　-安全な添付ファイル
　-安全なリンク
　-フィッシング対策保護
　-リアルタイムの検出
 
#
以下のページに記載あり

https://learn.microsoft.com/ja-jp/microsoft-365/admin/email/about-shared-mailboxes?view=o365-worldwide
 

https://learn.microsoft.com/ja-jp/office365/servicedescriptions/exchange-online-service-description/exchange-online-limits#StorageLimits

--抜粋--
「ライセンスがない場合は、共有メールボックスは 50 GB に制限されます。サイズ制限を 100 GB に増やすには、Exchange Online プラン 2 のライセンスを共有メールボックスに割り当てる必要があります。 同様に、共有メールボックスに訴訟ホールドをかける場合は、Exchange Online プラン 2 のライセンスが必要です。 Microsoft Defender for Office 365、アイテム保持ポリシーなどの高度な機能を適用する場合は、共有メールボックスにそのような機能のライセンスが付与されている必要があります。」

# 
以下のページにも記載あり

https://learn.microsoft.com/ja-jp/office365/servicedescriptions/microsoft-365-service-descriptions/microsoft-365-tenantlevel-services-licensing-guidance/microsoft-365-security-compliance-licensing-guidance

・Defender for Office365
https://learn.microsoft.com/ja-jp/office365/servicedescriptions/microsoft-365-service-descriptions/microsoft-365-tenantlevel-services-licensing-guidance/microsoft-365-security-compliance-licensing-guidance#microsoft-defender-for-office-365-plan-1-vs-plan-2-cheat-sheet

・アイテム保持ポリシー
https://learn.microsoft.com/ja-jp/office365/servicedescriptions/microsoft-365-service-descriptions/microsoft-365-tenantlevel-services-licensing-guidance/microsoft-365-security-compliance-licensing-guidance#licensing-for-retention-policies

・メールアーカイブ
https://learn.microsoft.com/ja-jp/office365/servicedescriptions/microsoft-365-service-descriptions/microsoft-365-tenantlevel-services-licensing-guidance/microsoft-365-security-compliance-licensing-guidance#licenses-for-email-archiving
[ODC]WidgetのVisible=Falseにするとどうなるか

一部UI部品で初期化をやり直したいことがあり、BlockをContainerで囲み、そのVisibleをTrue -> False -> Trueと切り替えることで再度初期化させることができた。
なぜこうなるのかを確認してみた。

# 環境情報
ODC Studio(Version 1.5.5)

# WidgetのVisible=Falseにすると対応するタグが消える
## Container・Link・Button・IconにはVisibleプロパティがある
Visibleプロパティは、対象のWidgetを、Trueなら表示させ、Falseなら非表示にさせるもの。
Container・Link・Button・Iconのような一部のWidgetのみ持っている。
![スクリーンショット 2025-01-27 23.24.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/13a0b212-9039-507f-6e08-cbacf22c6a75.png)


## 動作確認
Container・Link・Button・Iconの4つのWidgetを画面に配置し、そのVisibleプロパティを画面のLocal Variable（Boolean型）に紐付けた。
このLocal VariableをCheckboxに紐付け、画面操作でTrue・Falseを切り替えられるようにした。

以下は、ブラウザの開発者ツール > Elementsタブを使ってタグの様子を確認したもの。

Visible=Trueのとき（赤枠内が4つのWidgetに対応するHTMLタグが出力されている）
![スクリーンショット 2025-01-27 22.59.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/0566cea6-355a-9875-fc56-222c7f1d3010.png)

Visible=Falseのとき（4つのWidgetに対応するタグは無くなった）
![スクリーンショット 2025-01-27 23.02.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/028e5d04-7223-4f31-22c5-855ed858e650.png)

# Blockを囲むContainerのVisibleを変更して動作を確認
## 動作確認用実装
Blockに、Initialize・Ready・Destory Eventに対するハンドラを作成する。
ハンドラではJavaScript要素を配置して、console.logを使ってコンソールログを出力。その内容をブラウザの開発者ツール > Consoleタブで確認することで、ContainerのVisibleを変えて何が起きるかを観察した。
![スクリーンショット 2025-01-27 23.07.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/67833b55-130a-a823-7d4d-ff03ed63cedb.png)

## ContainerのVisibleをFalse→Trueにする：BlockのOnInitialzie・OnRenderが動作する
以下の通り、VisibleをFalse→Trueにした時点で、Blockの初期処理が動いていることを確認できた。
![スクリーンショット 2025-01-27 23.12.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/a9edd91f-0e5a-0451-6407-cff24a5fe128.png)

## ContainerのVisibleをTrue→Falseにする：BlockのOnDestoryが動作する
↑に引き続き、VisibleをTrue→Falseに変更すると、以下の通り、BlockのDestroyハンドラが動作していることを確認できた。
![スクリーンショット 2025-01-27 23.15.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/0aad3927-a823-4abb-bb71-02171ba7103a.png)

## まとめ
- BlockをContainerで囲み、ContainerのVisibleをTrue→Falseと切り替えることで、OnDestroyが動作する（つまり、OnDestroyを正しく実装している部品なら後始末も綺麗に動くはず）
- 同じくFalse→Trueと切り替えることで、再度初期化を発生させることができる

なお、Blockを入れ子にした場合、親Blockを含んだContainerのVisibleを切り替えることで、親Block・子Block双方にEventが発生する。順番は以下の通りで少し注意が必要。

（BlockParentが親BlockのEvent。Blockは子BlockのEvent、OnInitializeとOnDestoryは親Blockが先にEvent発生し、OnReadyは子BlockのEventが先）
![スクリーンショット 2025-01-27 23.20.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/523968c9-747d-35aa-9242-24fa86c9637b.png)
脆弱性診断ツール「OpenVAS」をMacBook（Apple Silicon）版Dockerでを動かす

開発した自作アプリのセキュリティ診断を行うため、脆弱性診断ツール「OpenVAS」を試そうと、以下のリンクを参考にDockerを用いて起動を試みたのですが、MACのApple Siliconでは動作しませんでしたので、Apple Silicon用の起動方法を記載します。

#### 参考リンク

https://qiita.com/UTDoi/items/7b2c054dcc85bc2285ca


## 手順

### 1. Dockerイメージの取得

Apple Silicon（ARMアーキテクチャ）に対応したDockerイメージを使用します。以下のコマンドで`immauss/openvas`イメージを取得します。

```bash
docker pull immauss/openvas:latest
```

実行後、しばらく待ちます。

### 2. コンテナの起動とログイン

イメージ取得後、以下のURLにアクセスしてログイン画面を開きます。

- **ログインURL**: [http://localhost:9392/](http://localhost:9392/)

ログイン情報は以下の通りです：

```bash
ID: admin
パスワード: admin
```

![ログイン画面](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2610302/7954ab33-e4aa-7f33-cf28-129f0df37c7a.png)

### 3. スキャンの実行

今回は、ローカル環境に設置しているNASサーバをスキャン対象としました。

1. **スキャンの設定**  
   NewTaskからスキャン設定をします。今回は診断要件を定めていませんので、IPアドレスを入力し、その他の設定はデフォルトのまま進めます。

   ![スキャン設定画面](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2610302/1ef10eda-2d8a-26d1-7955-6f88c48ebf24.png)

2. **スキャンの実行**  
   スキャンを開始すると、完了まで**かなりの時間**がかかります。

### スキャン結果

スキャン完了後の結果を確認します。
CVEスコアがとても高い脆弱なサーバgローカルに立っていますね。

![スキャン結果-1](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2610302/7c31f3c2-0b46-dda1-019b-de1646064172.png)

![スキャン結果-2](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2610302/f7123090-4419-e5b1-021d-aa435289649f.png)

### まとめ
MacBook（Apple Silicon）版でOpenVASの動作を確認できました。使用方法を確認して、実際の脆弱性スキャンも試してみます。
weztermで画像を表示する

## はじめに

zshの記事を漁っていたら面白い記事を発見した。

https://qiita.com/itigoppo/items/a4e68f72ff2ec2a1c883

最近ターミナル環境をiTerm2 + tmux の構成からweztermに変更したためこの方法はそのまま使えなかったのだが、weztermでも簡単に適用出来たので備忘も兼ねて。

weztermのダウンロードは以下の公式から。今回は説明スキップ。

https://wezfurlong.org/wezterm/

## コマンド

https://wezfurlong.org/wezterm/imgcat.html

```zsh
$ wezterm imgcat /path/to/image.png
```

これだけで画像が表示できる。`/path/to/image.png`は表示したい画像のパス。

![スクリーンショット 2025-01-27 22.25.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2737230/42a250af-0591-0e4e-df5e-b05683a851f0.png)

簡単！

## オプション

https://wezfurlong.org/wezterm/cli/imgcat.html

`--width`とか指定すれば大きさを変えたりできる

![スクリーンショット 2025-01-27 22.31.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2737230/dbc4ffb2-5afe-adfd-adc4-44edd295ad8a.png)

### 画像の位置を変えたい

左詰めになるので、少し左にマージンを取りたいとか思いますよね。

`--position`がそれっぽいので使ってみる。

![スクリーンショット 2025-01-27 22.34.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2737230/40a715ad-4426-3d42-a735-24a7935758d8.png)

はい（笑）上手くいきません（笑）

> Coordinates are expressed in cells with 0,0 being the top left cell position

とあるので、左上基準で表示されるみたい。

これだと困る。

## 空白文字を挿入

とりあえずすぐ思いついた対応策。

```zsh
$ echo -n "   " && wezterm imgcat $HOME/Downloads/pose_necchuu_computer_woman.png
```

![スクリーンショット 2025-01-27 22.41.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2737230/086855d4-ac08-9b70-f9cd-0415d4263880.png)


適当な空白文字を挿入してみた。間違い探しみたいになってますが、下の画像の方が左に少しスペースができてますね。

ワードで体裁を整えるために空白入れてたのを思い出します。


## command not found で表示させる

冒頭で紹介した記事と同じくcommand not found 時に表示させる場合は、.zshrcに以下を追記。

```zsh
function command_not_found_handler() {
  echo "$1ないよ"
  echo -n "   "
  wezterm imgcat $HOME/Downloads/pose_necchuu_computer_woman.png
}
```

`$HOME/Downloads/pose_necchuu_computer_woman.png`はもちろんお好みの画像のパスで。


```zsh
$ souce ~/.zshrc
```

すればOK。

![スクリーンショット 2025-01-27 22.52.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2737230/99d604fb-e4b5-1422-269d-4a513bdbc0cb.png)


## おわり

weztermは色々出来て面白いので、何か見つけたらまた記事にしたいなと思ってます。

あと、nibblesもいい加減次の実践編書こうと思ってます:joy:

https://qiita.com/Office_HxN/items/37a2645fb6d70ab81451

## 使用させていただいた画像

いらすとや様

https://www.irasutoya.com/

https://www.irasutoya.com/2016/04/blog-post_769.html
Copilotを活用して効率よくFlutterプロジェクト多言語対応

## 前言
お正月の間にFlutterを勉強してappを作ってみた。
一番感心したのはCopilotの活用でとても効率アップできたこと。
今回は一つの例として、多言語対応のやり方を共有させていただく。

## Flutterプロジェクト多言語対応時、Copilotの活用方法
まとめて言うと、Copilotに多言語のリソースファイルを作成してもらうこと。

1．多言語パッケージをインストールする
```Dart:VSCodeのTerminal
flutter pub add flutter_localizations --sdk=flutter
flutter pub add intl:any
```
2．pubspec.yamlで自動生成フラグをONにする
```
# The following section is specific to Flutter.
flutter:
  generate: true # Add this line
```
3．多言語設定ファイルl10n.yamlを作成する
```Dart: l10n.yaml
arb-dir: lib/l10n
template-arb-file: app_en.arb
output-localization-file: app_localizations.dart
output-dir: lib/l10n
synthetic-package: false
```
4．${FLUTTER_PROJECT}/lib/l10n/app_en.arbを作成する

5．VSCodeのメニュー「View＞Copilot Edits」AIとの会話画面を開いて、
「app_en.arbを参照して、ar,de,es,fr,ja,zh･･･のarbを作成してください」をCopilotに伝えて、
他言語のarbファイルを作成してもらう。

6．多言語のファイルを生成する
```Dart:VSCodeのTerminal
flutter gen-l10n
```
これで簡単に多言語対応が出来上がり！
※リソースの使用方法は説明していないけど、以下のサイトをご参照ください。
公式サイト：[Internationalizing Flutter apps](https://docs.flutter.dev/ui/accessibility-and-internationalization/internationalization)
pythonのisdigit()を使ってみた

# はじめに

今回は LeetCode の [Evaluate Reverse Polish Notation](https://leetcode.com/problems/evaluate-reverse-polish-notation/) という問題を解く際に、Python の isdigit() メソッドを使ってみたので、その記録を残しておこうと思う

# isdigit()について
isdigit() メソッドは、Python の文字列型 (str) のメソッドで、文字列がすべて数字 (0-9) で構成されているかどうかを判定する時に使う


使い方 : 
- 文字列がすべて数字の場合→True を返す
- 数字以外の文字を含む、空文字列の場合など は False を返す

注意点 : 

- isdigit()メソッドは、文字列の各文字が数字であるかをチェックする。
→ そのため、整数や浮動小数点、正負の符号は考慮しない
- あくまで、文字列が数字かどうかを判定するので、実際に数値として使う時は、int(), float()で変換する必要がある

# サンプルコード
```python
print("12345".isdigit())    # True  (すべて数字)
print("123.45".isdigit())   # False (小数点が含まれる)
print("-123".isdigit())     # False (マイナス記号が含まれる)
print("123a".isdigit())    # False (アルファベットが含まれる)
print("".isdigit())        # False (空文字列)
```

ただし、注意点として、マイナスの数字("-123"など)は isdigit() では False になってしまう。そのため、文字列の先頭がマイナス記号の場合、マイナス記号を除いた部分で isdigit() を使用するなどの工夫が必要になる。

```python
print("-123"[1:].isdigit()) # True (マイナス記号を除いた部分が数字)
```
【UE5】バージョン管理でフォルダの色を変更して共有する

# 0. 最初
Perforce等のVersion管理でフォルダの色を変更して
他のメンバーの環境でも変更が適応されるように設定します

# 1. 概要
一人で開発するときは以下の方法でフォルダの色を変更できます
 1.フォルダを右クリック
 2.「SetColor」を選択

上記の変更ではVersion管理をしているプロジェクトだと
フォルダの色は適応されません

# 2. 結果

最新を取得したデザイナーのエディタ画面です
![名称未設定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1918199/cd8d10e4-3ece-5e51-2b5b-5caa54be3373.png)

　・以下のiniファイルをテキストエディタで開く
 ```
\MyProject\Config\DefaultEditorPerProjectUserSettings.ini
 ```
　・「PathColor」を追加してパスを入力しRGBで色を指定する
 ```
[PathColor]
/Game/FolderName=(R=1,G=0,B=0,A=1.000000)//フォルダを「赤」にする
```

　・変更したiniファイルをサーバーへアップロードする
 ```
DefaultEditorPerProjectUserSettings.ini
```
　・別のワークスペースで色が変更されていることを確認できる
![スクリーンショット 2025-01-27 221638.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1918199/1a250f33-fd7b-4f68-9a00-e4fdd9248603.png)


 
# 3. 注意事項

:::note warn
フォルダパスは必ずフルパスで書かないと適応されません
 ```
 [PathColor]
 /Game/FolerName=(R=1,G=0,B=0,A=1.000000)
 ````


酷似しているiniファイルがあるので注意が必要です
```
MyProject\Saved\Config\WindowsEditor\EditorPerProjectUserSettings.ini
```
:::

# 参考文献
・https://blog.jamie.holdings/2020/02/08/unreal-engine-4-change-folder-colours-in-version-control/
・ChatGPT
【キホン】Azure上でLLMを構成する際の基本的なサービス概要

# Azureサービスを活用した基本的なLLM構成

社内のマニュアルやドキュメントを活用し、AzureサービスでLLMを構成する基本的な方法について解説します。


## 使用する主なAzureサービス５選

### 1. Azure OpenAI Service
Azure OpenAI Serviceは、GPTシリーズのLLMを活用できるサービスです。

- 特徴
  - 強力な自然言語処理能力
  - 他のAzureサービスとの統合が簡単
- LLMでの役割
  - LLMの中核を担う「自然言語処理」を実行
  - ユーザーからの問い合わせや曖昧な質問に対して、コンテキストを理解し、適切な回答を生成
- 具体的な利用
  - チャットボットやカスタマーサポートシステムで、ユーザーの質問に対する自動応答を生成する際に使用

### 2. Azure Cognitive Search
Azure Cognitive Searchは、高度な全文検索機能を提供します。

- 特徴
  - ドキュメントやデータをインデックス化して検索可能に
  - AIによる強化検索（AIエンリッチメント機能）をサポート
- 役割
  -  データのインデックス化と検索を担当し、LLMが必要とする情報を迅速に取得
  -  AIエンリッチメント機能を使って、データをより検索しやすくする
- 具体的な利用
  - ユーザーのクエリに関連するドキュメントを検索し、LLMがそれを基に回答を生成するための情報を提供


### 3. Azure Blob Storage
Azure Blob Storageは、データを安全に保存するためのストレージサービスです。

- 特徴
  - マニュアルやPDFファイルなどの大容量データを保存可能
  - Cognitive SearchやAIモデルで利用可能な形式に対応
  - アクセス制限なども設定可能
- 役割
  - 大量のデータを安全に保存し、LLMやCognitive Searchが必要とするデータを格納
  - 構造化・非構造化データの保存に対応
- 具体的な利用
  - ドキュメントやPDFファイルを保存し、Cognitive Searchがこれらをインデックス化して検索可能にする。


### 4. Azure Functions
Azure Functionsは、イベント駆動型のサーバーレス計算を可能にします。
- 特徴
  - トリガーイベントに応じてコードを実行
  - 軽量かつスケーラブル
- 役割
  - イベント駆動型の処理を実行し、LLMシステムの自動化を支援
  - 特定のイベント（例: ドキュメントのアップロード）に応じて、必要な処理をトリガー実行
  - 外部システムからのAPIリクエストを処理
- 具体的な利用
  - 新しいドキュメントがBlob Storageにアップロードされた際に、自動的にCognitive Searchでインデックス化を行うプロセスを実行


### 5. Azure Monitor
Azure Monitorは、システムのパフォーマンス監視やログ管理を支援します。

- 特徴
  - ボットや検索サービスの稼働状況をリアルタイムで監視
  - トラブルシューティングやパフォーマンスの最適化
  - エラー検知やボトルネック解消
- 役割
  - システム全体のパフォーマンスを監視し、LLMを含む各サービスの稼働状況をリアルタイムで把握
  - 問題が発生した際のトラブルシューティングを支援
  - RAG構成の稼働状況を可視化
- 具体的な利用
  - LLMの応答時間やエラー率を監視し、パフォーマンスの最適化や問題の早期発見に役立てる


さらに細かく実用化する場合、基本的なフロント構成やサーバ、ほかにも当たり前のように使うサービス（Azure ADやAzure Logic Apps）が必要です。
今回はサービス名に焦点を当てて記載しています。

## めちゃくちゃ優しい言い換え

社内専用のLLMを「社内知識という名の素材の味が染み込んだスープ」だとします。

このスープを作るために使うAzureサービスは、それぞれ以下のように例えられるかもしれません。

Azure OpenAI Service: スープの出汁
Azure Cognitive Search: 材料(社内情報)を選別するシェフ
Azure Blob Storage: 食材をたくさん保存する冷蔵庫
Azure Functions: 自動で動く調理器具（シェフは具材を選ぶだけ）
Azure Monitor: スープの味見役

これらが連携して、最高のスープ（回答）を作り出します！
私たちは食材を作ったり届けたりして、最後はスープを飲むという立場ですね。

## 補足：RAG構成の流れ

1. **データの収集**
   - Azure Blob Storageに社内マニュアルやドキュメントをアップロード。
   - ドキュメント形式：PDF、Word、テキスト、HTMLなど。

2. **データのインデックス化**
   - Azure Cognitive Searchでアップロードされたデータをインデックス化。
   - メタデータを追加して検索精度を向上。

3. **ユーザークエリ処理**
   - ユーザーが入力した質問をAzure OpenAI Serviceで解析。
   - 解析結果を基に、Azure Cognitive Searchで関連するドキュメントを検索。

4. **回答生成**
   - 検索されたドキュメント内容をLLMに入力し、最適な回答を生成。
   - 回答内容を整形してユーザーに提供。


AzureのRAG構成については、また別の記事にします。



# 最後に

巷ではAI AgentやRAG精度向上で最先端の研究が進んでいますが、実際の現場では地に足をつけた現実的なサービス展開とコストが求められています。

技術進歩のスピードが加速している今だからこそ、基本的なところから支えていける提供者になりたいです。

自分のためにも誰かのためにも、今後も基本的なことを書いていこうと思います。
MSA切り替えのためのデータクエリ・可視・信頼パターン

## データクエリパターン  
MSAソフトウェアアーキテクチャを設計する際に発生するデータクエリの課題を解決するためのパターン  

1. **API Aggregation パターン**  
必要なデータを取得するために、分離された各サービスに対してドメインごとのデータをリクエストし、それを必要に応じて **Aggregation (組み合わせ)** します。  

2. **CQRS パターン**  
Command (書き込み、更新、削除) の作業と Query (読み取り) のエンドポイントを分離し、Commandで発生したデータの変更をイベント発行を通じて、必要な形式で Query専用のデータ構造を作成します。そしてQueryを適切にリクエストする仕組みです。  

---

## 可視性パターン (Visibility, Observability)  
MSAソフトウェアアーキテクチャを設計する際、ロギングやモニタリングの課題 (可視性の欠如) を解決するためのパターン  

- ログおよびメトリクスの中央集約やフィルタリングを通じて、一箇所でモニタリングできるようにする。  
- 一つのトランザクションに対する複数サービス間のリクエストを一つのリクエストのように見られるようにするトレーシング機能。  

**ロギングとメトリクスの違い:**  
- **ロギング:** トラブルシューティングを目的とし、欠落してはならない情報。  
- **メトリクス:** サーバーやアプリケーションの指標を時系列で保存し、時間に応じた増減をアラートとして受け取るために使用。データが欠落しても大きな問題ではなく、データの全体的な傾向や推移が重要。  

「具体的に、ログやメトリクスをどのように保存し、インデックス付けして検索を行うかに集中するパターン」  

---

## 信頼性パターン (Reliability)  
MSAソフトウェアアーキテクチャによるサービス分離/分解により低下した信頼性を解決するためのパターン  
障害復旧、自己修復、無停止デプロイなどを実現するためのパターンが含まれます。  

### サーキットブレーカー (Circuit Breaker)  
信頼性を向上させるためのパターンの一つで、分散システムでの障害伝播を防ぎ、被害を最小限に抑えるためのパターンです。  

例:  
A → B → Cの順にサービスが呼び出される場合、Cで問題が発生しBが障害を起こすことがあります。この時、「100回以上500エラーが発生する」という条件を持つサーキットブレーカーは、その条件が満たされた場合、Cへのリクエストをすべて遮断します。そして、B→Cへのリクエストを行っていたAサービスに対して、HTTPコードとメッセージを送ります。  

しかし、サーキットブレーカーの役割はここで終わりではありません。定期的にCに状態を問い合わせ、問題が解決された場合、Cへのリクエスト遮断を解除します。  

---

## 外部APIパターン  
サービス間の通信における実装と関連する依存性を解決するためのパターン  
あるサービスが他の特定のサービスを呼び出す際、直接呼び出すのではなく、リバースプロキシの役割を果たすインターフェースサービスを提供することで、マイクロサービス間の内部実装に依存せず柔軟性を持つことができるパターンです。
Cloudflareのサービスの無料枠が大きすぎる！！！

Cloudflareの無料枠が神です。
それぞれ説明します。
必要そうな制限のみをピックアップしてます。詳細は下の引用元をご覧ください。
## 警告

:::note warn
これは個人がCloudflareのサービスの無料枠の制限を見る記事です。
この個人の制限の感覚は異なる場合があるためご了承ください。
また、この制限は変わる可能性もあります。
:::

## Pages
Webサーバーです。GitHubPagesと似たようなものです。
- ビルド(デプロイ)は月に最大500回(1日16回ぐらい)
- 帯域幅は無制限!!!!!
- カスタムドメインは100個まで
- ファイルは一つ25MiB、最大2万個まで
- デプロイのプレビューは制限無し!!!
- アカウント一つで作れるプロジェクトは100個まで
この制限は不正使用防止で、引き上げたいなら連絡又はリクエストフォームを使用してとのことです。
- [商用利用可!!!!!!!](https://community.cloudflare.com/t/is-cloudflare-pages-workers-free-plan-free-for-commercial-use/291741/4)

個人的にはファイル一つ25MiBが一番痛い...
それ以外は個人には十分すぎる!!!!

https://developers.cloudflare.com/pages/platform/limits/

## Turnstile
ボット判定プログラムで、公式サイトではCAPCHAの代替で、イライラするパズルを解く必要はないとの事です。

- ボリューム(呼び出し回数?)は無制限！
- ウィジェットは10個まで
- ウィジェットごとのホスト名は10個まで
- つまり100個のホストで使える
- 常時非インタラクティブモードが使えない
- Cloudflareのロゴは消せない

比べてreCAPCHAは...
- 呼び出し回数は月1万回
- 呼び出しは1秒で1000回まで

ボット排除のためにあるのにボットにreCAPCHAを大量呼出されたら他のユーザーが使えないではないですか！ボットにとって1万回なんて一瞬ですよ!?

10x10でホスト100個までは不安な気がしちゃいますが個人の範囲では十分ですよね！

https://www.cloudflare.com/ja-jp/application-services/products/turnstile/#Page-Pricing-AS

## D1
データベースです。

- 個数は10個まで
- データベースあたりの最大サイズが500MB
- つまりアカウントあたりの最大ストレージ量は5GB

ここから無料・有料共通
- SQL関数あたりの最大引数数は32個
- 最大の列数は100個
- 最大の行数は無制限!!!!(ストレージ制限を考慮しないものとして)
- SQL文の最大の長さは100KB
- 最大実行時間は30秒

ん～大規模な物は作れませんがやはり個人にとっては非常に良い...❤

https://developers.cloudflare.com/d1/platform/limits/

## Workers
NodeJSのHTTPサーバー(REST APIとか)のです。
これは厳しいらしいです。
- リクエストは一日10万回(1秒1回)、一分1000回(1秒16回)
- メモリ上限は128MB(ざっくり1GBの10分の1ぐらい)
- レスポンスのCPU時間(同期的処理の時間?)は10msまで
- 起動時間400msまで
- 1リクエストあたりの内部のHTTPリクエスト数は50回
- プログラムのサイズ上限は(圧縮後)1MBまで
- リクエストのURLサイズは16KBまで
- ボディサイズは100MBまで

CDNのエッジで動くためパフォーマンスは良さそうです。
個人的には十分なんじゃないですかね。www

https://developers.cloudflare.com/workers/platform/limits/

https://zenn.dev/catnose99/articles/d1d16e11e7c6d0

## まとめ
個人にとって十分です！個人サービスはCloudflareに統一しよう！
bunのテスト・バンドラ・サーバーと一緒に統一しよう！←?
Zabbix LTS7.0になったのでMFA認証を導入してみた

# 背景

Zabbix LTS7.0のアップデート内容をあさってる時に**MFA認証**が実装されたみたいなので導入してみた。

公式ドキュメント
https://www.zabbix.com/documentation/7.0/en/manual/web_interface/frontend_sections/users/authentication/mfa

## いざ鎌倉

* Usres > Authentication > MFA settingsからEnable multi-factor authenticationを有効化する。
* Methodsから新規のMFAmethodを作成、TypeをTOTP、Hashfunctionを任意のものにする。

![スクリーンショット 2025-01-27 18.55.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3878757/bc07432e-963a-c89c-d470-4a0a496b881b.png)

### ユーザーグループにアタッチする

* ここで問題が一つ、**自分が属しているユーザーグループにはアタッチすることができない**ので失敗したフローも考え、以下のように実施することにした。

1.自分の所属してるグループAに自分と権限を持ったadmin1を入れる。
```
## イメージ
    グループA 自分、admin1
```
2.グループAの権限内容をグループBにし複製。MFA認証をオンにし自分のみグループBに入れる。
```
## イメージ
    グループA 自分、admin1
    グループB 自分(MFA)
```
3.グループAから自分を外す。
```
## イメージ
    グループA admin1
    グループB 自分(MFA)
```
4.グループBで自分がログアウトしMFAの画面が表示されることを確認し、登録してログイン
(※失敗した場合はグループAのadmin1権限で修正する。)
5.実装通りになったらグループBにadmin1を入れてグループAを削除する。

```
## イメージ
    グループB 自分、admin1(MFA)
```

* 認証アプリは**Google Authenticator**を使用しました。

# 最後に
* LTS7.0が出てから記事にするにはちょっと遅いかもしれませんが、所属しているチームに「MFA認証があるので実施してもいいですか？」と聞いたらOKサインが出ました、提案して最新の機能を試せるのは楽しいですね。
フォーカスが外れる挙動を防ぎたくて

## 何につまづいたか
Inputエリアに記述されたTextを範囲選択した際に、色変更などのメニュー画面を表示させたかった。
そのメニューのボタンをクリックした際、Inputエリアのフォーカスが外れてしまい、ユーザーに改めてInputエリアをクリックさせることになってしまった。
メニューのボタンをクリックしても元のInputの状態を維持できるようにしたかった。

## どうやったのか？
- onClickイベントではなくonMouseDown(or onPointerDown)を使用する
- e.preventDefault()を使用してブラウザのデフォルト挙動を防いだ

コード例
```tsx
import React, { useRef, useState } from "react";

const InputWithMenu = () => {
  const inputRef = useRef<HTMLInputElement>(null);
  const [showMenu, setShowMenu] = useState(false);

  const handleSelect = () => {
    // 選択範囲がある場合にメニューを表示
    const selection = window.getSelection();
    if (selection?.toString()) {
      setShowMenu(true);
    }
  };

  const handleMenuClick = (e: React.MouseEvent) => {
    e.preventDefault(); // Blur状態を防ぐ
    console.log("メニューのボタンがクリックされました");
  };

  return (
    <div style={{ position: "relative", padding: "20px" }}>
      <input
        ref={inputRef}
        type="text"
        placeholder="テキストを選択してください"
        onSelect={handleSelect}
        onBlur={() => setShowMenu(false)} // フォーカスが外れたらメニューを閉じる
      />

      {showMenu && (
        <div
          style={{
            position: "absolute",
            top: "50px",
            left: "10px",
            background: "lightgray",
            padding: "10px",
            borderRadius: "5px",
          }}
          onMouseDown={(e) => e.preventDefault()} // メニュークリック時にフォーカスを失わせない
        >
          <button onPointerDown={handleMenuClick}>色変更</button>
          <button onPointerDown={handleMenuClick}>削除</button>
        </div>
      )}
    </div>
  );
};

export default InputWithMenu;
```

## なぜダメだったか？
onClickイベントのままhanldeMenuClickを使うと、ブラウザの挙動でクリックした対象にフォーカスが吸われてしまうので、コード例のinput要素の部分からフォーカスが外れてしまう。

これをonMouseDownに変更し、`e.preventDefault()`を実行することで、フォーカスを失わせない様にすることができる。

## onMouseDownとonPointerDownの違い
コード例では、onMouseDownを使っているが、onPointerDownを使うこともできる。
それぞれの違いを以下の表に示す。

|特徴|	onMouseDown|	onPointerDown|
|--|--|--|
|対象デバイス|	マウスのみ|	マウス、タッチ、ペンすべて対応|
|ブラウザ互換性|	古いブラウザでも完全対応|	モダンブラウザで対応|
|ジェスチャー対応|	×|	○|
|イベントの統一性|	マウスに特化|	複数デバイス間で統一的に動作|

タッチ操作が必要なアプリケーションの場合は、onPointerDownを使用すると良い。

## onBlurって？
onBlurは要素からフォーカスが外れた(失った)時に呼び出されるイベントハンドラー
その逆で、フォーカスが当たった時に呼び出されるイベントハンドラーはonFocus

onBlurはフォーカスが外れた時に呼び出されるので、例えば自動保存を行うときや入力内容の確認(例えば半角英数字のみか？)などの時に活躍する。

フォームの入力などを行う際、上手に使いこなして使い勝手の良いアプリを作れる様になりたい

## 最後に
onClick一辺倒でonPointerDownなどを知らなかったので、引き続き勉強しないと…です。
【Liquid】タグとは

# タグとは
タグは、コードの実行や処理を指示するロジックを定義するために使用される。
特定の条件下でのみコードを実行したり、同じコードを繰り返し行ったりする際にタグを使用する。

https://shopify.dev/docs/api/liquid/tags



## コンディショナルタグ（Conditional tags）

コンディショナルタグは、Liquidコードのブロックが実行されるかどうかを決定する条件を定義できる。

https://shopify.dev/docs/api/liquid/tags/conditional-tags

#### if
「もし〜ならば」の条件設定において、条件が真の場合にのみ、特定のコードを実行
#### unless
「もし〜ならば」の条件設定において、条件が偽の場合にのみコードを実行
#### elsif
ifタグで設定した条件が偽の場合で別の条件を設定するときに使用
#### else
if・elsifタグで設定した条件がすべて偽の場合に実行するコードを設定するときに使用
#### case
whenタグなどと組み合わせて活用することで、変数の値に応じたコードを実行

## イテレーションタグ（Iteration tags）
イテレーションタグはコード ブロックを繰り返し実行できる。
リストや配列内の各アイテムに対し、同じ操作を繰り返し適用する際に使用されるケース多い。

https://shopify.dev/docs/api/liquid/tags/iteration-tags

#### for
配列内の各アイテムに対して繰り返し処理を行いたい場合に使用
#### limit
商品リストの最初2つのアイテムのみを表示したいときなど、forの繰り返し回数を制限する際に使用
#### offset
forの繰り返しを開始する位置を指定可能
#### range
数値の範囲を指定して繰り返し処理を行いたい場合に使用
#### reversed
新着商品をリストの最後に表示するなど、配列のアイテムを逆順で繰り返し処理する際に使用
#### else
forの繰り返し処理が一度も行われない場合に実行するコードを指定する際に使用
#### break
forの処理を中断する条件を設定可能
#### continue
特定の条件下で現在のfor処理の繰り返しを飛ばし、次の繰り返しに進む際で使用
#### cycle
forの繰り返しで異なる文字列や値を順に出力する際に使用
#### paginate
配列が50項目など多数のアイテムを含む場合に、アイテムを複数のページに分割表示する場合に使用

## 変数タグ（Variable tags）


変数タグ使用すると、新しいLiquid変数を作成できできる
Webサイトの中で情報を一時的に保存し、さまざまな箇所で再利用することが可能。
変数タグを使うことでサイトの情報を上手に管理し、見せ方を変えたり、特定の条件下で特別な表示ができる。
また、一度設定した情報は他の場所でも使用可能です。
※定義済みのオブジェクトは、同じ名前の変数によって上書きされる可能性がある。
また、全てののオブジェクトにアクセスできるようにするには、変数名が定義済みのオブジェクトの名前と一致していないことを確認する必要がある

https://shopify.dev/docs/api/liquid/tags/variable-tags

#### assign
新たに変数を作成し、値を入力する際に使用
#### capture
商品名に応じて大文字・小文字を決定するなどの複雑な情報を変数に入れる時に使用
#### decrement
-1から始まり、数値をひとつずつ減らしていく時に使用
#### increment
0から始まり、数値を1ずつ増やしていく時に使用

## テーマタグ（Theme tags）
テーマの一部であるコンテンツを割り当てたりレンダリングしたりできる。
ストア上で、セールなどの特別な情報を記載する箇所（スニペット）を作ることで、サイト上に追加できる。

https://shopify.dev/docs/api/liquid/tags/theme-tags

#### include
Webサイトのスニペット使用時に利用されていた古い方法で、現在はサイトが遅くなるなどの理由で利用が推奨されていない
#### javascript
Shopify Liquidでjavascriptを入れる際に使用
#### layout
Webサイトの大まかなデザインを決める際に使用
#### render
includeに代わり、Webサイトのスニペットの使用時に利用可能な新しい方法
#### section
ヘッダーやフッターなどのWebサイトのセクションを表示・作成する際に使用
#### stylesheet
Webサイトのスタイルを決めるコード（CSS）をセクション内に入れるための場所


<!--
https://www.shopify.com/jp/blog/partner-shopify-template-language-liquid-overview#4
-->
【Access VBA】フォームを画面中央に移動(絶対座標使用)

```vb
Option Compare Database
Option Explicit

Public Declare PtrSafe Function GetWindowRect Lib "user32" (ByVal hwnd As LongPtr, ByRef lpRect As RECT) As LongPtr
Public Declare PtrSafe Function GetSystemMetrics Lib "user32" (ByVal nIndex As Long) As Long
Public Declare PtrSafe Function MoveWindow Lib "user32" (ByVal hwnd As LongPtr, ByVal X As Long, ByVal Y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal bRepaint As Long) As LongPtr

'GetSystemMetricsの引数
Private Const SM_CXFULLSCREEN As Long = 16 '用途：メインディスプレイの画面の幅 取得
Private Const SM_CYFULLSCREEN As Long = 17 '用途：メインディスプレイの画面の高さ 取得

'GetWindowRectの戻り値を格納するユーザー定義型
Private Type RECT
    Left As Long
    Top As Long
    Right As Long
    Bottom As Long
End Type

'フォームをメインディスプレイの画面中央に移動
Sub MoveFormToCenterOfScreen()

    Dim RectObject As RECT 'GetWindowRectの戻り値を格納するオブジェクト
    
    Dim widthScreen As Long 'メインディスプレイの画面の幅
    Dim heightScreen As Long 'メインディスプレイの画面の高さ
    
    Dim leftPosition As Long 'フォームの左座標
    Dim topPosition As Long  'フォームの上座標
    Dim rightPosition As Long 'フォームの右座標
    Dim bottomPosition As Long 'フォームの下座標
    
    Dim widthForm As Long 'フォームの幅
    Dim heightForm As Long 'フォームの高さ
    
'フォームの絶対座標の位置を取得
    Call GetWindowRect(Forms("フォーム1").hwnd, RectObject) 'フォームのRECTオブジェクト取得
    leftPosition = RectObject.Left 'フォームの左座標(絶対座標)
    topPosition = RectObject.Top 'フォームの上座標(絶対座標)
    rightPosition = RectObject.Right 'フォームの右座標(絶対座標)
    bottomPosition = RectObject.Bottom 'フォームの下座標(絶対座標)
    widthForm = RectObject.Right - RectObject.Left 'フォームの幅
    heightForm = RectObject.Bottom - RectObject.Top 'フォームの高さ

'フォームをメインディスプレイの画面中央に移動
    widthScreen = GetSystemMetrics(SM_CXFULLSCREEN) 'メインディスプレイの画面の幅
    heightScreen = GetSystemMetrics(SM_CYFULLSCREEN) 'メインディスプレイの画面の高さ
    leftPosition = (widthScreen - widthForm) / 2 'フォームを画面中央に移動する場合のフォームの左座標(絶対座標)
    topPosition = (heightScreen - heightForm) / 2  'フォームを画面中央に移動する場合のフォームの上座標(絶対座標)
    Call MoveWindow(Forms("フォーム1").hwnd, leftPosition, topPosition, widthForm, heightForm, True) 'フォームを画面中央に移動
    
End Sub
```
#0028（2024/01/27）Nginx, uWSGI, Flaskを使ったサーバー構成

以下では、Flask を使ったサーバー構成として、

1. **Flask（単独）**  
2. **Nginx + Flask**  
3. **uWSGI + Flask**  

の三つを比較し、それぞれ「何ができるのか」「どんな用途に向いているか」をまとめています。

---

## 1. Flask（単独）

### 概要
- Python のコマンド (`python app.py`) 等で起動する、Flask 標準の簡易サーバーをそのまま使う形。
- 開発用サーバーとして想定されており、本番運用（プロダクション）には推奨されません。

### できること
- **開発やテスト** : ローカル環境でアプリの動作確認を行う際には手軽で便利。
- **非常にシンプル** : 追加の設定が不要なため、とにかく素早く起動できる。

### 制限 / 注意点
- **パフォーマンスやスケーラビリティが低い** : シングルスレッド・シングルプロセスが基本で、高い負荷には対応が難しい。
- **セキュリティ面での懸念** : SSL 終端やリクエストのフィルタリング等を自前でカバーしづらい。
- **本番運用非推奨** : Flask 開発者自身も「開発・デバッグ向け」としており、負荷試験や大量アクセス対応は想定外。

---

## 2. Nginx + Flask

### 概要
- **Nginx** をフロントエンドとして、**Flask の簡易サーバー**をバックエンドとして動かす構成。
  - たとえば、`location / { proxy_pass http://127.0.0.1:5000; }` のようにリバースプロキシ設定を行い、Flask に接続する。

### できること
- **静的ファイルの配信を Nginx が担当** : 画像や CSS/JS を高速に配信可能。Flask の負荷を軽減できる。
- **SSL/TLS 終端** : HTTPS の処理を Nginx が担当するので、Flask は HTTP (ローカル通信) だけで動く。
- **基本的なリバースプロキシ機能** : IP 制限、ロードバランシング(複数 Flask インスタンスを立ち上げる場合)などを Nginx で設定可能。

### 制限 / 注意点
- **Flask の簡易サーバー自体は本番向けでない** : 依然として Flask 側の並列処理能力は限定的。
- **高負荷時の対応力は限定的** : Nginx がプロキシとして踏ん張っても、Flask の開発サーバーは限界が来やすい。
- **本格的なプロダクション対応には uWSGI や Gunicorn などのアプリケーションサーバが望ましい** : Nginx + Flask (dev server) はテストまたは限定的な運用向き。

---

## 3. uWSGI + Flask

### 概要
- **uWSGI** (Python 用の WSGI サーバ) と **Flask** アプリケーションを直接連携する構成。
- Nginx は使わない（もしくは別途導入しない）ため、uWSGI が直接クライアントからの接続を受け付けるケースもあり得る。

### できること
- **並列処理・高負荷対応** : uWSGI はマルチプロセス/マルチスレッドをサポートし、Flask を本番運用するための性能向上が図れる。
- **WSGI 標準** : Flask などの Python フレームワークとの相性が良い。

### 制限 / 注意点
- **SSL/TLS や静的ファイル配信は uWSGI で設定する** : Nginx に比べ設定が複雑になりがち。
- **負荷分散などの機能は限定的** : Nginx ほど豊富なリバースプロキシ機能がないため、大規模運用では物足りない場合がある。
- **通常は Nginx と組み合わせる** : 安定した本番環境では、やはり Nginx + uWSGI + Flask の 3 つを組み合わせる構成が一般的。

---

## まとめ

| 構成                  | メリット                                             | デメリット                                                      | 主な用途                          |
| --------------------- | ---------------------------------------------------- | --------------------------------------------------------------- | --------------------------------- |
| 1. Flask (単独)       | - 設定不要ですぐ起動<br>- 開発・テストに最適         | - 高負荷に弱い<br>- SSL や静的ファイル配信などの機能不足         | ローカル開発/デバッグ             |
| 2. Nginx + Flask      | - 静的ファイル・SSL を Nginx に任せられる<br>- リバースプロキシとして柔軟な設定可 | - Flask 側のサーバは開発用<br>- 本格的な並列処理が苦手         | 比較的軽いサービスや試験運用       |
| 3. uWSGI + Flask      | - uWSGI による並列処理性能の向上<br>- WSGI 規格に準拠 | - SSL/静的ファイルなどを自力または uWSGI に任せる必要<br>- 負荷分散機能は限定的 | 小〜中規模のプロダクション運用 (ただし Nginx なし) |

本番運用でより高い安定性やパフォーマンスを求めるなら、実際には **Nginx + uWSGI + Flask** の 3 構成（プラス、場合によってはコンテナ技術やロードバランサなど）を使うのが王道です。

- **Nginx** : フロントエンドでリバースプロキシや静的ファイル、SSL/TLS を担当  
- **uWSGI** : WSGI サーバとして Flask アプリを多数のリクエストに対応させる  
- **Flask** : アプリケーションロジックを実装するフレームワーク  

ただし、構成をシンプルにしたい場合や、トラフィックが少ない小規模サービスでは、本回答の比較表を目安に、どの程度の構成が必要か検討してみてください。
#0027（2024/01/27）Nginx, uWSGI, Flaskについて

## Nginx

### 概要
- **Nginx** は、高速かつ軽量な HTTP サーバとして知られています。
- 主に **リバースプロキシ** (Reverse Proxy) として、クライアントからのリクエストを受け取り、バックエンドサービス (たとえば uWSGI, Gunicorn など) に転送します。
- 静的ファイル (画像や CSS、JavaScript など) の配信にも使われ、負荷を軽減する役割も担います。

### 特徴
- **高いパフォーマンス** : イベント駆動型 (非同期 I/O) のアーキテクチャにより、同時接続数が多くてもリソース消費が少なく済みます。
- **設定ファイルがシンプル** : サーバブロック (server ブロック) や location ブロックを用いて、柔軟に設定を行えます。
- **負荷分散 (Load Balancing)** : 複数のバックエンドサーバに対してリクエストを振り分ける機能も持ちます。

### 代替しうる技術
- **Apache HTTP Server** : 伝統的で機能豊富な HTTP サーバ。モジュールが多彩で、長く使われています。
- **Caddy** : 設定が簡単な HTTP/2 対応サーバ。Go 言語で開発され、Let’s Encrypt による SSL/TLS 自動化が特徴。
- **HAProxy** : 主に負荷分散を得意とするプロキシソフトウェア。TCP レベル、HTTP レベルで高い性能。

---

## uWSGI

### 概要
- **uWSGI** は Python の **WSGI** (Web Server Gateway Interface) を実装するアプリケーションサーバです。
- Nginx などから受け取ったリクエストを Python の WSGI アプリケーション (例: Flask, Django など) に転送し、処理結果を返します。
- 名前の通り、**uWSGI プロトコル**を実装しており、高速に動作します。

### 特徴
- **マルチプロセス、マルチスレッド** : 高い並列処理性能を持ちます。
- **多彩な設定方法** : INI ファイル、YAML ファイルなどでの柔軟な設定が可能。
- **Flask/Django/Gunicorn など複数フレームワークに対応** : Python 以外の言語 (Perl, Ruby) と連携するモジュールも存在します。

### 代替しうる技術
- **Gunicorn** : シンプルでよく使われる Python WSGI サーバ。Flask や Django を動かすときに人気。
- **Waitress** : Python 製の純粋な WSGI サーバ。Windows 環境でも簡単に動作。
- **uvicorn** + **FastAPI** : 非同期 (ASGI) ベースのサーバ。現代的な Python ウェブ開発で注目度が高い。

---

## Flask

### 概要
- **Flask** は Python 製のマイクロフレームワークです。軽量でシンプルな構造が特徴です。
- **ルーティング (URL の振り分け)** とテンプレート、簡易的な開発用サーバを提供し、拡張やプラグインも豊富に用意されています。
- 「マイクロフレームワーク」であるため、必要に応じて機能を追加していくスタイルが好まれています。

### 特徴
- **シンプルな設計** : 必要最小限の機能のみをコアに持ち、拡張は自由度が高いです。
- **豊富な拡張機能** : SQLAlchemy を使った ORM、LoginManager による認証、JWT、管理画面など。
- **学習コストの低さ** : Python の文法に慣れていれば、すぐに理解・開発を始められます。

### 代替しうる技術
- **Django** : 大規模開発に向けた “電池付き” フレームワーク。認証や管理画面をフル装備。
- **FastAPI** : 非同期 (ASGI) を前提とした高性能 API フレームワーク。型ヒントを活用して自動ドキュメント生成が可能。
- **Bottle** : Flask よりもさらにミニマルな Python フレームワーク。依存も少なく動作が軽快。

---

## まとめ

- **Nginx** : 高速・軽量なリバースプロキシ/HTTP サーバ。Apache や Caddy といった HTTP サーバが代替候補。
- **uWSGI** : Python WSGI アプリを動かすアプリケーションサーバ。Gunicorn, Waitress なども同様の役割。
- **Flask** : シンプルなマイクロフレームワーク。Django や FastAPI、Bottle などが用途に合わせて代替可能。
依存性逆転の原則について

## SOLIDの5原則の1つである依存性逆転の原則（DIP）について、調べた／実装した内容を記載します。

### 1. 依存性逆転の原則とは
SOLIDの５原則の１つとなります。

※SOLIDの原則については以下となります。
[S：単一責任の原則(Single Responsibility)](https://qiita.com/Nori1983/items/221e32f40f3b512d7b60)
O：オープン・クローズドの原則(Open-Closed)
L：リスコフの置換原則(Liskov Substitution)
I：インターフェイス分離の原則(Interface Segregation)
D：依存性逆転の原則(Dependency Inversion)<font color="Red"> ←ここ</font>

### 2. 依存性とは
関数AControllerが関数Busecaseを参照することを、関数AControllerは関数Busecaseに依存すると言います。
コードで記載すると以下の様になります。
```main.go
package main

import "DIP/controller"

func main() {
	controller.AController()
}

```

```Acontroller.go
package controller

import (
	"DIP/usecase"
	"fmt"
)

func AController() {

	b := usecase.Busecase()

	fmt.Println(b)
}

```
```Busecase.go
package usecase

func Busecase() string {
	return "B usecase"
}

```

これを図で書くと、こんな感じです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/196226/26101ea2-8e97-7525-d559-f42d29fa59ec.png)


### 3. なぜ依存性があるの問題点について
各関数で依存性があると、以下のような問題が発生します。
・拡張性が悪くなる。
・テスト容易性が悪い。
・各関数が再利用しにくい。


### 4. 依存性逆転を意識した実装を行うと
依存性逆転を意識した実装を行うと、以下のようになります。
AControllerは、直接BUseCaseに依存しておらず、BUsecaseのインターフェースに依存しています。
こうなることで、AControllerとBUsecaseは、疎結合な状態となります。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/196226/77ed6731-9329-f174-6566-d27bfb9c7832.png)


### 5. コード
これらのコードの内容は以下の通りとなります。
```main.go
package main

import (
	"GO_DIP/controller"
	"GO_DIP/infrastructure/repositories"
	"GO_DIP/usecase"
	"fmt"
)

func main() {
	// リポジトリの初期化
	repo := repositories.NewReadUsermstRepository()
	// 依存性の初期化
	usercase := usecase.NewSearchUserInteractor(repo)

	// UserControllerの生成
	userController := controller.NewUserController(usercase)
	fmt.Println(userController.GetUserList())
}

```
```UserController.go
package controller

import (
	"GO_DIP/usecase"
)

type UserController struct {
	usermstUsecase usecase.ISearchUserInteractor
}

// Constructor
func NewUserController(searchusermst usecase.ISearchUserInteractor) *UserController {
	return &UserController{
		usermstUsecase: searchusermst,
	}
}

func (controller *UserController) GetUserList() string {
	return controller.usermstUsecase.SearchAllUsers()
}

```

```usermstusecase.go
package usecase

type ISearchUserInteractor interface {
	SearchAllUsers() string
}

// 構造体の定義
type SearchUserInteractor struct{}

// 新しいインスタンスを作成する関数
func NewSearchUserInteractor() ISearchUserInteractor {
	return &SearchUserInteractor{}
}

// 構造体のメソッドとしてSearchAllUsersを実装
func (s *SearchUserInteractor) SearchAllUsers() string {
	//Usermstの全検索
	return "UseCaseだよー"
}

```
### 結果
```
$ go run main.go
$ UseCaseだよー
```


### 6. Github
https://github.com/NoriStock1983/Go_DIP


### 参考
https://qiita.com/k2491p/items/686ee5dd72b4baf9a81a#%E3%83%86%E3%82%B9%E3%83%88%E5%AE%B9%E6%98%93%E5%A7%93

https://qiita.com/baby-degu/items/d058a62f145235a0f007

https://zenn.dev/edash_tech_blog/articles/b4629f9cd73240
君は "A" | "B" のUnion型から "AA" | "BB" 型を作れるか

Claudeくんが頭いい型定義を教えてくれたので共有。

↓のような型定義があるとき、

```ts
type AB = "A" | "B";
```

↓のような型を定義したい。どうするか。

```ts
"AA" | "BB"
```

真っ先に思いつくのは↓の形。

```ts
type AABB = `${AB}${AB}`;
```

しかし、これは実際には `"A"` と `"B"` の組み合わせになってしまう↓。

![スクリーンショット 2025-01-27 20.21.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214979/29f853ee-8c7f-8409-09e7-0a824cb34937.png)

ではどうするかというと、↓のようにすればよい。

```ts
type Hoge<T extends string> = T extends any ? `${T}${T}` : never;
type AABB = Hoge<AB>;
```

![スクリーンショット 2025-01-27 20.25.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214979/05a74847-565f-ccba-8086-279b2314e920.png)

ポイントは↓。

- `T extends any` が必ず `true` になる
- ↑の `T` が `"A"` or `"B"` のいずれかが選ばれた状態で、 `${T}${T}` により2連続で並ぶことが表現できる

以上、TypeScriptは奥が深いね〜って話でした。

## 余談

この話の使い所はAIお絵かき用の自作ツール。

`"red" | "blue" | "green"` のような色を定義したUnion型と、
別途指定した文字列型を組み合わせて、

- `"red hair ribbon -> red ribbon"`
- `"blue hair ribbon -> blue ribbon"`
- `"green hair ribbon -> green ribbon"`
 
のような文字列を型として定義したい。
そんなときにClaudeくんがこの記事のノウハウを教えてくれた。

実際のコードは↓のようなもの。

```ts
export type ColorPalette = "default" | "unchi";

export const COLOR_PALETTE = {
  default: [
    "aqua",
    "black",
    "blue",
    "brown",
    "green",
    "grey",
    "orange",
    "pink",
    "purple",
    "red",
    "white",
    "yellow",
  ],
  unchi: ["💩"],
} as const satisfies Record<ColorPalette, readonly string[]>;

type Color<T extends ColorPalette> = (typeof COLOR_PALETTE)[T][number];

type AliasableColorTag<
  T extends Color<ColorPalette>,
  U extends string,
  V extends string,
> = T extends any ? `${T} ${U} -> ${T} ${V}` : never;

export const generateColorAliasableTagTable = <
  T extends string,
  U extends string,
  V extends ColorPalette,
  W extends object,
>(
  fromTag: T,
  toTag: U,
  colorPalette: V,
  obj: W,
) => {
  type C = Color<V>;

  const entries = COLOR_PALETTE[colorPalette].map((color: C) => {
    return [
      `${color} ${fromTag} -> ${color} ${toTag}` as AliasableColorTag<C, T, U>,
      { ...obj, to: `${color} ${toTag}` },
    ] as const;
  });

  return ObjectModule.fromEntries(entries); // これはTSの型推論が💩だから作った自作のオブジェクト操作用モジュール
};
```
AIを活用したSWシステムの品質基準は...？


ISO/IEC 29119-11では、AIを活用したSWサービスで必要な品質基準を定義した。

これを知るためにはISO/IEC29119-11の文書を購入しなければならないが...Swiss Francsで199だ。

![스크린샷 2025-01-27 오전 12.59.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55902/e5bde710-a030-9f5b-884a-289d7297a609.png)


円換算すると約34,273円です。

![스크린샷 2025-01-27 오전 12.59.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55902/36daf842-213a-6a2e-ec84-cd9668c0cfe3.png)

私たちが必要なのはAIを活用したSWサービスの品質基準ですが、このくらいの値段で買うにはちょっと高いですね。

この標準を根拠にした**ISTQB Certified Tester AI Testing (CT-AI) Syllabus** があるが、この文書を見ると、ある程度どのような基準を作ったのかが分かるので、これを紹介しようと思う。

1. 適応性と柔軟性 : 次のような状況でも柔軟に適応する必要があります。

   * システムの展開時、運用環境が完全に分からない場合。

   * システムが新しい運営環境に対処することを期待する場合。

   * システムが新しい状況に適応することを期待する場合。

   * システムがいつ動作を修正すべきかを決定する必要がある場合。

2. 自律性(Autonomy)

   * 自律性の定義 : 人の監督と制御から完全に独立したもの。
   * ここでの自律性とは、システムが人の監督と制御から独立して一定期間動作できる能力をいう。
3. 進化(Evolution)

   * 変化する外部条件に対して、自ら改善するシステムの能力。
   * 自己学習システムがなければならない 
4. 透明性

   * ユーザーがAIシステムをどの程度信頼しているかについての程度。
   * 人工知能基盤システムが持つ複雑さは「説明可能な人工知能(XAI)」の出現につながった。XAIの目標は、ユーザーが人工知能基盤システムがどのように結果を導き出すかを理解できるようにすることで、ユーザーの信頼を高めることである。
5. バイアス除去

   * 人工知能ベースのシステムにおいて、バイアスとは、システムが提供する結果と「公正な結果」とみなされる値との間の距離差を表す統計的数値である。公正な結果とは、特定のグループに対する偏見を示さない結果を意味する。
6. サイドエフェクトと報酬ハッキング(Side Effects and Reward Hacking)

   * サイドエフェクトとは、例えば「できるだけ燃料を節約しながら安全な方法」で目的地まで移動することを目標とする自動運転自動車が目的地まで移動することを目標とする自動運転自動車が目標は達成するが、移動時間が長すぎて乗員が極端にイライラする副作用をもたらすことを例に挙げることができる。
   * 報酬ハッキングとは、設計者の意図を歪曲してシステム自ら「簡単な」解決策を見つけ出すこと 例えば、人工知能基盤システムがアーケードコンピュータゲームを自ら学習し、'最高得点'達成を目標に設定した場合、そのためにゲームをプレイせずに保存されたゲームデータを利用する。
     を達成することを目標に設定した場合、そのためにゲームをせずに保存された最高得点データ記録をハッキングする場合を挙げることができる。
7. 安全性(Safety and AI)

   * ここで安全とは、AIシステムが人、財産または環境に害を及ぼさないという期待を意味する。
   * 医療、製造、国防などでは、この問題は敏感である。
   * 安全性は慎重に評価する必要があり、システムが自分自身に危害を加えるよう強制する試みを含む。



7つの項目の中には「測定」がある程度可能なものもあれば、難しいものもある。しかし、重要なのは、これが測定が目的ではなく、AIを活用したサービスが目指すべき方向性を示していることだ。

参考までに、これを測定するためのテスト技法として次のように提示している。

* フェアワイズ
* A/Bテスト
* Back-To-Backテスト
* 変性テスト
* 探索的テスト



各手法については、以下にまとめていきます。