OmniAICreator/Qiita-1.07M huggingface dataset:
[個人メモ]DOMとは

# 簡潔に言うと
webブラウザの開発者ツールの「要素（Elements）」パネルから表示できるこれのこと
![IMG_5549.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3638255/55fd9dd7-0673-423d-8a65-21b426bcc08c.jpeg)


# はじめに

DOM（Document Object Model）は、ウェブページの現在の状態を一元管理するためのデータモデルです。ここでは、DOMの基本概念と、Reactをはじめとする現代のウェブ開発におけるその重要性について解説します。

# 1. DOMとは？

**定義:**

DOMは、HTMLやXML文書を解析して生成される、ツリー構造のオブジェクトです。

- 元のHTML文書は、ブラウザに読み込まれるマークアップ言語としての設計図です。
- これに対して、DOMはその「生きた状態」をメモリ上に再現し、JavaScriptなどから動的に操作できるようにします。

**動的な更新:**

ユーザーの操作やJavaScriptの実行により、DOMはリアルタイムで変化します。たとえば、ボタンをクリックすると新しい要素が追加されるといった動作は、DOMの更新によって実現されます。

# 2. HTMLとDOMの違い

**HTML:**

- ウェブページの基本構造や内容を記述するマークアップ言語
- 静的なファイルとしてサーバーから送信される

**DOM:**

- HTMLをブラウザが解析・変換して作り上げる、動的なツリー構造
- JavaScriptによる操作でリアルタイムに変更される

**ポイント:**

開発者ツールの「Elements」パネルで見るDOMツリーは、初期のHTMLだけではなく、動的に更新された最新状態を反映しています。

# 3. DOMの役割と管理内容

DOMは以下の情報を一元管理します:

- **HTMLの構造:**
    各要素の階層関係や属性情報


- **CSSの適用結果:**
    要素に適用されるスタイル（Computed Stylesとして確認可能）


- **JavaScriptによる変更:**
    ユーザーの操作やプログラムによる動的な変更
    

この一元管理により、ブラウザは効率的にページの描画や更新を行うことが可能となっています。

# 4. Reactと仮想DOM（Virtual DOM）

Reactは、DOM操作のパフォーマンスを向上させるために仮想DOMという仕組みを採用しています。

**仮想DOMの仕組み:**

- 実際のDOMの軽量なコピーをメモリ上に保持
- 状態の変化があった際に、仮想DOM上で**差分**(**Diff**)を検出
- 差分があった部分だけを実際のDOMに反映することで、無駄な再描画を削減

**メリット:**

- 高速なUI更新が実現
- 大規模なアプリケーションでもスムーズなユーザー体験を提供

# 5. まとめ

- DOMとは、HTML、CSS、JavaScriptで構築されるウェブページの **"現在の状態"を管理するためのモデル** です。
- HTMLは元の設計図であり、DOMはその設計図がブラウザ上で動的に再現された実態です。
- Reactの仮想DOMは、DOM操作を最適化し、効率的な画面更新を実現するための技術です。
リスクベーステスト（RBT）とAI駆動の品質保証

## 🎯 **はじめに**

近年、開発スピードの加速やシステムの複雑化により、従来の網羅的なテストでは品質保証の負担が増大しています。そこで注目されているのが **リスクベーステスト（Risk-Based Testing, RBT）** です。本記事では、RBTの概要やメリット・デメリット、そしてAIを活用した品質保証の未来について解説します。

---

## 🔍 **リスクベーステスト（RBT）とは？**

### **従来のテストの課題**

- **網羅的なテストは時間・コストがかかる** 
    - → すべての機能を均等にテストするのは非現実的
- **開発スピードの加速に対応できない** 
    - → 短期間で品質を保証する方法が必要
- **バグの影響が均一ではない** 
    - → すべてのバグが同じリスクとは限らない

### **RBTの基本概念**

**リスクスコア = 影響度 × 発生確率**

- **影響度（1-5）**：その機能に問題が発生した場合のビジネスインパクト
- **発生確率（1-5）**：その機能がバグを引き起こす可能性の高さ

📌 **リスクが高い領域を優先的にテストすることで、品質保証の効率を向上させる手法**

### **RBTの導入メリット**

1. ✅ **重要な機能に集中** 
    - → 決済・予約管理などの高リスク部分を優先テスト
2. ✅ **効率的なテスト** 
    - → 不要なテストを削減し、開発スピードを維持  
3. ✅ **テスト自動化と相性◎** 
    - → 変更の多い機能を自動テスト化し、品質向上  

### **RBT導入の課題と解決策**

1. ⚠️ **リスク評価が難しい** 
    - → 過去のバグデータ・変更履歴を活用し、客観的に判断  
2. ⚠️ **導入負担が大きい** 
    - → まずは高リスク領域のみ適用し、段階的に拡大  
3. ⚠️ **低リスク部分が手薄** 
    - → スモークテストやユーザーフィードバックで補完  

---

## 🤖 **AIによるRBTの強化**

従来のRBTにAIを活用することで、さらに精度の高い品質保証を実現できます。

### **AIを活用するメリット**

- ✅ **リスク評価の自動化** → AIが過去のバグデータを分析し、高リスク領域を自動特定  
- ✅ **テストケースの最適化** → AIがテストの優先順位を動的に調整  
- ✅ **自律型テストエージェント** → AIがアプリを操作し、未知のバグを発見  
- ✅ **モデルベーステスト（MBT）** → AIが仕様を理解し、最適なテストケースを自動生成  

### **AIを活用した具体的な技術**

- **機械学習によるバグ予測** → バグ発生パターンを学習し、リスクの高い領域を特定
- **モデルベーステスト（MBT）** → AIが仕様モデルを解析し、自動で最適なテストケースを生成
- **ビジュアルAIテスト** → AIがUIの変化を自動検知し、視覚的なバグを発見（例: Applitools）
- **自律型テストエージェント** → AIが実際にアプリを操作し、探索的テストを実施

🚀 **AI × RBT で、より精度の高いテスト戦略を実現！**

## ⚠️ **QAの仕事はAIに奪われるのか？**

AIの進化により、テストの自動化が加速し、「QAの仕事はなくなるのでは？」という不安の声もあります。しかし、AIは **人間の判断力を補助するツール** であり、すべてのQA業務を置き換えるわけではありません。

### **QAの役割の進化**

- ✅ **AIが自動でリスクを評価し、QAが最終判断を行う**
- ✅ **テストケースの作成・実行はAIに任せ、QAは品質戦略の策定に集中**
- ✅ **ユーザー視点での探索的テストや品質評価は、依然として人間が担う**

🚀 **QAの役割は、「テスト実施者」から「品質の戦略家」へシフトする！**

---

## 📌 **リスクベーステストの実例**

リスクベーステストはさまざまな業界や企業で導入されており、効率的な品質保証を実現しています。例えば、Jenkinsの開発者による継続的リスクベーステストの導入や、ソフトウェアテスト企業による適用事例などがあります。

しかし、具体的な成功事例として公開されている情報は少なく、リスクベーステストの効果を最大限に引き出すためには、各企業独自のリスク評価の精度を高めることが重要です。

---

## 🏆 **まとめ**

✔ **RBT × AI で、品質と開発スピードを両立！**  
✔ **限られたリソースで、最適なテスト戦略を実現！**  
✔ **網羅的なテストから、リスクに基づく効率的なテストへシフト！**  

⏩ **「QA = バグを見つける人」から、「品質を作る戦略家」へ！** 🚀
【Terraform】環境ごとにポリシー（Resource部分のみ）を調整したい

# はじめに
terraformを使用して、開発（`develop`）環境と本番（`production`）環境で異なるポリシー（`Resource`部分のみ）を設定するのに少し苦戦したので備忘もかねてアウトプットします。

例として今回はそれぞれの環境で以下のS3バケットのアクセスが許可されていることを目標とします。
- 開発環境
    - `arn:aws:s3:::prd-bucket/*`
    - `arn:aws:s3:::dev-bucket/*`
- 本番環境
    - `arn:aws:s3:::prd-bucket/*`

# 作成したコード
```hcl:local.tf
locals {
    # 環境ごとのリソース定義
    resources_by_environment = {
        develop = [
        "arn:aws:s3:::prd-bucket/*",
        "arn:aws:s3:::dev-bucket/*"
        ]
        production = [
        "arn:aws:s3:::prd-bucket/*"
        ]
    }

    # 環境毎に動的に生成されるポリシー
    # ※今回は各環境で環境情報をvar.tags.Environmentとして持っている想定
    dynamic_resources = lookup(local.resources_by_environment, var.tags.Environment, [])

    # 共通ポリシー
    policy = {
        Version = "2012-10-17"
        Statement = [
            {
                Sid    = "Allow access from resources in vpc to S3"
                Effect = "Allow"
                Principal = {
                    AWS = "*"
                }
                Action = [
                    "s3:GetObject",
                    "s3:PutObject"
                ]
                # 動的に作成されたリソースが渡される
                Resource = local.dynamic_resources
            }
        ]
    }
}
```

```hcl:vpc_endpoint.tf（ポリシー設定部分のみ）
resource "aws_vpc_endpoint_policy" "s3" {
  vpc_endpoint_id = aws_vpc_endpoint.s3.id
  policy = jsonencode(local.policy)
}
```

# ポイント説明
### 1. 環境ごとに動的に生成したい部分を`local.tf`として分離
- 今回の例では、ポリシーの`Resource`を`local.tf`で作成

### 2. `lookup()`の利用
- 第1引数で指定したmapに対して、第2引数で指定したキーに対応する値を取得
    - 環境ごとに動的に`Resource`情報を生成することができた

https://developer.hashicorp.com/terraform/language/functions/lookup

### 3. `jsonencode()`の利用
- 与えられた値をJSON文字列に変換
    - `local.tf`で作成したポリシーを変換

https://developer.hashicorp.com/terraform/language/functions/jsonencode


# まとめ
今回は、`locals`と`lookup()`、`jsonencode()`を活用することで、環境ごとに異なるポリシーを作成できるコードについて試してみたことをお話ししました。
正直、terraformは1つのことに対していろいろなコードの書き方があり、正解が1つではないように感じています。
そのような奥深さを楽しみつつ、よりよい（管理しやすい）コード作成をしていきたいと思います。
ありがとうございました。
1000行で書けるOS作成を最後までやりきった話

# 概要

[1000行でOSを作ってみよう](https://operating-system-in-1000-lines.vercel.app/ja/)というオンラインブックを今年の年始に知って、隙間時間にコツコツ書いていたのがようやく全て実装できた。

元々は[GIGAZINEの記事](https://gigazine.net/news/20250110-operating-system-in-1000-lines/)で知ったんだけど日本語版の公開は2023年末だったそう。英語版が2024年12月に公開だそうなので、そのタイミングで記者が見つけたのだろうか。
初めた当初は知らなかったけど作者は[『自作OSで学ぶマイクロカーネルの設計と実装』](https://www.shuwasystem.co.jp/book/9784798068718.html)を書いた方。書店で見つけて気になっていた本だった。1000行OSはそれより小規模とのことだが無料というのはありがたい。

# 実装した感想

1000行OSはそれくらいなら何とか書けそうかなというので初めてみたけど、デバッグの仕方が独特で思ったより時間がかかった。

実装記録は以下。元のコードに比べて章ごとの実装順序のずれデバッグによるコメントアウトもそのまま残している。

https://github.com/bigbenbigben/makeos

ソース自体はいじったわけではなく、コピペはほぼ使わずでタイプミスで七転八倒したりした。

環境はWindows11Pro(23H2)とWSL2。これは本の1章にあるUbuntu版の開発環境に沿えばすぐ構築できた。

低レイヤはCはなんだかんだ書いてきたし、マイコンはそこそこ、なんちゃってでアセンブラやらFPGAやリアルタイムOSも書いたり読んだりはしてきたので感覚は分かると思ってきたけど、思ったよりもOSというもの自体の用語や概念が分からなくて戸惑った。マイクロカーネルの本を読み込めばもう少し根本の理解ができるだろうか。

レジスタで色々設定するのはマイコンぽさがあって馴染みやすかった。コンフィギュレーションをGUI使わず仕様書とにらめっこしながらビット立てて、とかやっていたのでそこは感覚が近い。なんだかんだ組込みの経験がある人は最後まで行けやすいと思う。逆に無いとひたすら写経に感じるかもしれない。

# つまづきやすいポイント

作者も書いているけどデバッグが難しい。

本当にわからなくなったらバイナリダンプして追っかけなければいけない。IDEとか専用デバッガがあれば良いのだが無いのは仕方ない（無ければ作るという領域だろう）ので、タイプミスでうまく動かないときは地道にソースとバイナリを追いかけるしかない。

最後16章のファイルシステムだけはどうしてもファイル書き込み処理がうまくいかず、コピペしてタイプミスを修正した。それ以外は何とかバイナリダンプのデバッグで乗り切った。

自分の環境が貧弱だからかもしれないが、14章で実装するシステムコールの入力に結構ディレイがあり、デバッグ中に難儀した。当然実装していないのでタイプミスしてもバックスペースは効かない。

ただ、マイコン触っているとそういう注意深さが問われる入力はしょっちゅうなのでそういう意味ではたじろぐことは無かったと思う。やはり慣れが必要か。

# 今後

マイクロカーネルの本も懐と時間に余裕ができたら買って読んでみたい。TCP/IPのネットワーク通信も実装できるということで遊びの幅が広がる。

RISC-Vなので秋月のマイコンとかに実装できるとさらに楽しいんだけど、そちらは難易度が高そう。
新しい自分へ(Qiita初投稿！！)

# はじめに
Qiita初投稿です。
27歳IT業界4年目で開発経験がいまだにないエンジニアです。
これから大きく成長するための記録として残したいと思います

# 経歴
新卒未経験で受託開発企業に入社
ヘルプデスクでコードを書くことはほとんどなかった
開発ができないため、受託開発企業を3年で退職し、SESに入社
開発経験がないため、開発案件に携われずテスターして1年経過...


# 今までの学習方法
インプットメインの学習
- Udemyの動画学習
- ハンズオン

# きっかけ
開発経験がないと現状開発ができる現場に参画は難しいと言われ、
ポートフォリオ作成しようと思ったが、
何からすればいいのか全く分からず、コードもかけなかった

案件の顔合わせで同年代の人と比べて、技術が大きく劣っていることを痛感したから




# 目標
短期：チュートリアルを進め、基礎をしっかり身につける
中期：開発ができる企業に転職する
長期：自分が作りたいと思ったものを形にできるようにする
【Mac】コマンドでGIFを圧縮する方法

gifsicleを使用するとGIFを圧縮できます。

https://github.com/kohler/gifsicle

## インストール

以下のコマンドでインストールできます。

```terminal
brew install gifsicle
```

## 使い方

1つのGIFを圧縮する。

```terminal
gifsicle --batch --optimize file.gif
```

複数のGIFを圧縮する。

```terminal
gifsicle --batch --optimize file_1.gif file_2.gif file_3.gif
```
git tagには2種類存在する

## はじめに
リリース時点のソースコードを記録するために、git tagを打つことがよくあると思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1518953/160c1362-650f-4f12-b344-9627a0a87994.png)

この時に-aオプションを付与することが推奨されるとのことです。

## git tagの2種類について
注釈付きと軽量版のタグがあります。
軽量版タグはコミットに対する目印に過ぎず、長期的に保存するものは注釈付きタグを使用が推奨されるそうです。
以下、[ドキュメント](https://git-scm.com/book/ja/v2/Git-%E3%81%AE%E5%9F%BA%E6%9C%AC-%E3%82%BF%E3%82%B0)からの引用です。
> 軽量版のタグは、変更のないブランチのようなものです。特定のコミットに対する単なるポインタでしかありません。
>
>しかし注釈付きのタグは、Git データベース内に完全なオブジェクトとして格納されます。 チェックサムが付き、タグを作成した人の名前・メールアドレス・作成日時・タグ付け時のメッセージなども含まれます。 また、署名をつけて GNU Privacy Guard (GPG) で検証することもできます。 一般的には、これらの情報を含められる注釈付きのタグを使うことをおすすめします。 しかし、一時的に使うだけのタグである場合や何らかの理由で情報を含めたくない場合は、 軽量版のタグも使用可能です。


## 最後にタグ付けの手順を記載します
### 1. タグ付けするコミットハッシュ値を確認します
```sh
git log --oneline
```
ハッシュ値を付けない場合、最新コミットに対してタグ付けされますが、
後付けすることが多いため、私はコミットハッシュ値付けることを推奨しています

### 2. git tagでタグ付けする
```sh
git tag -a [tagname] [コミットハッシュ値]
```

### 3. タグ付けができている確認する
```sh
git show [tagname]
```

### 4. pushする
```sh
git push origin [tagname]
```

## まとめ
リリースバージョンは重要な情報ですので、注釈付きタグで打つべきですね。

## 参考
https://git-scm.com/book/ja/v2/Git-%E3%81%AE%E5%9F%BA%E6%9C%AC-%E3%82%BF%E3%82%B0
atcoder_水色精進記録14_ABC231f

# Atcoder水色精進記録
ABC231
F - Jealous Two
https://atcoder.jp/contests/abc231/tasks/abc231_f

# アルゴリズム・データ構造
SegmentTree, 2分探索

# 考察
とりあえずAだけで考えてみる
Aを逆順にsortして高橋くんへのプレゼントを固定して考えてみると
高橋くんへのプレゼント(idx=Xとする)に選んだAより右にあるAは高橋くん側の条件を満たす。

青木くんの条件を満たすには、Xより右側にあるもののうち、Bx以上のBである。
Bのリストを事前にsortしておけば、2分探索でBx以上のBの個数は判定することが出来る。
そのうち右側にあるという条件はどうすればいいか?
反対に考えて、左側にあるB以上のBを数えることができればOK
→OrderdListや座標圧縮したSegtreeなどで、左側の項目を管理すればいけそう
Xより左にある、Axと同じAのプレゼントは青木くんへのプレゼントに選んでも、高橋くんの条件は満たすため、Xが変わったタイミングでSegtreeを更新としなければならない(入力例 3のケース)

計算量としては、
Xの探索がN
Bx以上のBの個数の判定がlogN
SegTreeの更新・取得がlogN
A,BのsortがNlogN
NlogN＋(N-1)(logN+logN)→NlogN

# 提出
https://atcoder.jp/contests/abc231/submissions/63421130

# 感想
SegmentTreeが空で実装できるようになってきた。
簡単なSegmentTreeの使い方も身についてきた気がする。
ネットワークのクラスとプライベートIPアドレス

## 1. IPアドレスのクラス（A/B/C）
IPアドレスは ネットワークの規模 に応じて、クラスA/B/C に分類される。
それぞれ、ネットワーク部とホスト部のビット数が異なり、持てるネットワーク数とホスト数が決まる。
| クラス | 範囲 | ネットワーク部 | ホスト部 | 最大ネットワーク数 | 最大ホスト数(1ネットワーク内） |
|:-:|:-:|:-:|:-:|:-:|:-:|
| A | 1.0.0.0 ～ 126.0.0.0  |  8ビット | 24ビット  | 126 | 16,777,214  |
| B | 128.0.0.0 ～ 191.255.0.0  |  16ビット | 16ビット  | 16384  | 65,534  |
| C | 192.0.0.0 ～ 223.255.255.0  |  24ビット | 	8ビット | 約210万  |	254 |

・クラスAは大規模ネットワーク向け（例：Google, AWSの内部ネットワーク）
・クラスBは中規模ネットワーク向け（例：企業の社内ネットワーク）
・クラスCは小規模ネットワーク向け（例：家庭やオフィスLAN）

## 2. プライベートIPアドレス
インターネット上で使われず、LAN（社内ネットワークや家庭のWi-Fiなど）で自由に使えるIPアドレス。グローバルIPと衝突しない範囲として、RFC1918 で定義されている。
| クラス | プライベートIPアドレス範囲 | サブネットマスク | 主な用途 |
|:-:|:-:|:-:|:-:|
| A |10.0.0.0 ～ 10.255.255.255   | 255.0.0.0 (/8)  |大企業・データセンター  |
| B |172.16.0.0 ～ 172.31.255.255   | 255.240.0.0 (/12)  | 企業・学校  |
| C |192.168.0.0 ～ 192.168.255.255   | 255.255.0.0 (/16)  | 家庭・小規模オフィス  |

覚え方のコツ
✅ クラスA → 「10.で始まるIPは全部プライベート」
✅ クラスB → 「172.16～172.31」（16～31の範囲）
✅ クラスC → 「192.168.」で始まる（家庭用Wi-Fiでおなじみ）

プライベートIPは直接インターネットに出られない（NATを経由してグローバルIPに変換）
プライベートIPのメリット：IPアドレスの枯渇防止、セキュリティ向上

## 3. 各クラスのネットワークとホストの具体例
| クラス | 例 | ネットワーク部 | ホスト部 | 使用可能ホスト範囲 | ブロードキャスト |
|:-:|:-:|:-:|:-:|:-:|:-:|
| A | 10.0.0.0/8  | 10  |0.0.0   | 10.0.0.1～10.255.255.254  | 10.255.255.255  |
| B | 172.16.0.0/16	  | 172.16  | 0.0  | 172.16.0.1～172.16.255.254  | 172.16.255.255  |
| C | 192.168.1.0/24  | 192.168.1  | 0 | 192.168.1.1～192.168.1.254  | 192.168.1.255  |


## 4. まとめ
✅ クラスA/B/Cの範囲とネットワーク・ホスト数を理解する！
✅ プライベートIPは「10.」「172.16～172.31」「192.168.」を丸暗記！
✅ 「クラスAは大規模、Bは中規模、Cは小規模」と用途を理解！
✅ サブネットマスク /8 /16 /24 の違いを意識する！
Instractor で LLM の返答を Ecto スキーマに格納する

## はじめに

Instractor は LLM への問い合わせ結果を Ecto のスキーマとして構造化してくれます

https://github.com/thmsmlr/instructor_ex

本記事では Livebook で Instractor を使用し、 Ollama からの応答を構造化します

Ollama はローカルマシン上で起動しており、 Livebook はコンテナで起動しているものとします

実装したノートブックはこちら

https://github.com/RyoWakabayashi/elixir-learning/blob/main/livebooks/instractor/instractor.livemd

## セットアップ

セットアップセルで Instractor をインストールします

```elixir
Mix.install([
  {:instructor, "~> 0.1.0"}
])
```

## スキーマ定義

Ollama からの応答を格納するスキーマを定義します

`@llm_doc` で各フィールドの説明を書くことで、 LLM が説明に沿った内容を格納してくれます

また、バリデーションによって正しいスキーマになっているか検証し、間違っていればリトライします

```elixir
defmodule Judgement do
  use Ecto.Schema
  use Instructor

  @llm_doc """
  ## Field Descriptions:
  - class: 文章が肯定的か否定的か.
  - reason: 判定した理由.
  - score: 肯定的の度合いを示す 0.0 から 1.0 の値.
  """
  @primary_key false
  embedded_schema do
    field(:class, Ecto.Enum, values: [:positive, :negative])
    field(:reason, :string)
    field(:score, :float)
  end

  @impl true
  def validate_changeset(changeset) do
    changeset
    |> Ecto.Changeset.validate_number(:score,
      greater_than_or_equal_to: 0.0,
      less_than_or_equal_to: 1.0
    )
  end
end
```

## LLM への問い合わせ

モデル、応答を格納するスキーマ、メッセージを指定して LLM を呼び出します

第2引数のキーワードリストで Ollama を使うように指定しています

また、今回は Livebook をコンテナ上で起動しているため、 `api_url` に `"http://host.docker.internal:11434"` を指定しています

モデルには日本語も理解できる Phi-4 を使用します

```elixir
judge = fn text ->
  Instructor.chat_completion(
    [
      model: "phi4",
      mode: :json,
      response_model: Judgement,
      max_retries: 3,
      messages: [
        %{
          role: "user",
          content: """
          文章が肯定的か否定的か判定してください
  
          <文章>
            #{text}
          </文章>
          """
        }
      ]
    ],
    [ 
      adapter: Instructor.Adapters.Ollama,
      api_url: "http://host.docker.internal:11434"
    ]
  )
end
```

「出掛けるのも吝かではない」という文章が肯定的か、否定的か判定してもらいましょう

```elixir
judge.("出掛けるのも吝かではない")
```

実行結果

```elixir
{:ok,
 %Judgement{
   class: :positive,
   reason: "文章は「出掛けるのも吝かではない」とあり、外に出ることや行動を肯定的に捉えています。この表現から前向きで楽観的なニュアンスが感じられます。",
   score: 0.8
 }}
```

結果は `:positive` で、正しく判定できています

しっかりスキーマにも格納されています

続いて「あなたの希望には添えかねます」という文章が肯定的か、否定的か判定してもらいましょう

```elixir
judge.("あなたの希望には添えかねます")
```

実行結果

```elixir
{:ok,
 %Judgement{
   class: :negative,
   reason: "文章は、願いや要求が叶うことを明示的に否定する形で提示されており、「希望には添えかねます」という表現から否定的な印象が生まれるため。",
   score: 0.2
 }}
```

こちらも正しく判定でき、指定したスキーマの通りに返ってきました

## まとめ

Instractor を使うことで LLM の応答をスキーマに格納することができました

システムに LLM を組み込む場合、出力形式が安定することは必須条件と言えます

Ecto スキーマに格納することで、単なる JSON 形式ではなく、各フィールドの型や選択肢、範囲なども制約できるのは良いですね
WSL2のDocker上でPython

## Docker構築
今後何か作るにしても、Dockerの知識は役立つだろうと思い導入した。
Docker Desktopをインストールし、ダウンロード。WSL2に構築できるようにした。
※WSL2とubuntuはインストール済み

Docker Desktop「Settings」→「General」タブで「Use the WSL 2 based engine」にチェックが入っていることを確認し、「Resources」→「WSL Integration」を開き、Ubuntu(使用するディストリ名) にチェックを入れて有効化。次にDockerのバージョンを確認。
```
docker version
```
とりあえずこれで動きそう。
目標はdocker composeでの実行であるため、Docker Compose バージョン確認済。
```
docker compose version
```
## Docker Composeを使用したコンテナ作成
docker-compose.ymlを作成。
```
version: "3.8"
services:
  web:
    image: nginx:alpine
    container_name: my-nginx
    ports:
      - "8080:80"
```
起動する。
```
docker compose up -d
```
Web ブラウザで http://localhost:8080/ にアクセスし、Nginx の Welcome ページが表示された。

## Docker ComposeでのPython実行
簡単なコードだが、ディレクトリ構成。将来的にライブラリをインストールしたいので、Dockerfileを追加。
```
my_python_app/
├─ encoder.py
├─ requirements.txt
├─ Dockerfile
└─ docker-compose.yml
```
以下は内容。

**・encoder.py**
```
import base64
import sys

def str_to_base64(x):
    """文字列をbase64表現変換

    b64encode()はbyte-like objectを引数にとる
    文字列はencode()でbyte型にして渡す
    """
    return base64.b64encode(x.encode('utf-8'))

def main():
    target = sys.argv[1]
    print(str_to_base64(target))


if __name__ == "__main__":
    main()
```
**・Dockerfile**
```
FROM python:3.9-slim

# 作業ディレクトリを指定
WORKDIR /usr/src/app

# requirements.txt をコンテナにコピーしてpip install
COPY requirements.txt /usr/src/app/
RUN pip install --no-cache-dir -r requirements.txt

# ソースコードをコピー
COPY . /usr/src/app

# コンテナ起動時に実行するコマンド
CMD ["python", "encoder.py"]
```
**・docker-compose.yml**
```
version: "3.8"

services:
  python-app:
    build: .
    container_name: my-python-app
```
requirement.txtは今回は省略。

実際にコンテナを起動及び実行してみる。
```
docker compose build
docker compose run python-app python
```
WARNINGが出力されたが今回は無視している（いろいろ実行したためであると思われる）
結果は以下となった
```
b'cHl0aG9u'
```

今回はここまで。
【AWS】S3

# はじめに
AWS DVA取得に向けた勉強の一環です。
新たな学びがあったら随時追記していきます。

正確性は保証しませんので参考程度に見てください。

# 概要
- オブジェクトストレージサービス
- 階層構造なし、各データは一意のIDを持つ
- 構造化・非構造化データの両方を扱える
- 高耐久性（99.999999999% = イレブンナイン）
- 高可用性（ストレージクラスによって異なる）
- 容量無制限で従量課金
- 用途: バックアップ、データレイク、静的コンテンツのホスティング など

# S3の基本構成
- バケット: データを格納するコンテナ
- オブジェクト: バケット内に格納されるデータ単位

- Glacierでは
    - バケットに対応するのが**ボールト**
    - オブジェクトに対応するのが**アーカイブ**

# S3のストレージクラス

| クラス | 特徴 | 用途 |
|--------|------|------|
| Standard| デフォルト、頻繁にアクセス | Webサイトホスティング、一般データ |
| Standard-IA| 低頻度アクセス、コスト低め | バックアップ、災害復旧 |
| Intelligent-Tiering| アクセス状況に応じてクラスを自動変更 | 不定期にアクセスするデータ |
| One Zone-IA| 単一AZのみ、冗長性低いが安価 | 一時データ、再作成可能データ |

# S3 Glacier
## ストレージクラス
| クラス | アクセス頻度目安 | 取得時間 |
|--------|-------------|----------|
| Instant Retrieval| 四半期に一度 | 即時 |
| Flexible Retrieval| 年一回程度 | 数分～数時間 |
| Deep Archive| 年一回未満 | 数時間（取り出し料金高） |

## 取り出しオプション
|  | 迅速 | 標準 | 大容量 |
|--------|-------------|----------|----------|
| Flexible Retrieval、Intelligent-Tiering Archive| 1~5分 | 数分~5時間 | 5~12時間 |
| Deep Archive、Intelligent-Tiering Deep Archive | 利用不可 | 9~12時間 | 48時間以内 |

# アクセス制御
| 方法 | 適用範囲 | 特徴 |
|------|--------|------|
| IAMポリシー| アカウント単位 | ユーザーやロールごとに権限設定 |
| バケットポリシー| バケット単位/オブジェクト単位 | バケット内のオブジェクトを細かく制御 |
| ACL（Access Control List）| バケット単位 | 細かい権限制御不可、現在は非推奨 |

# セキュリティ・データ管理

## 署名付きURL
- 一定期間のみ有効なURLを生成し、アクセスを許可
- 漏洩の可能性があるため完全なセキュリティにはならない

## CORS（Cross-Origin Resource Sharing）
- 複数オリジン間でのリソースを共有する

## データの暗号化
| 種類 | 暗号化のタイミング | 管理方式 |
|------|------------------|----------|
| サーバーサイド暗号化| AWSにアップロード後 | AWSが暗号化・復号化を担当 |
| クライアントサイド暗号化| アップロード前 | ユーザーが暗号化・復号化を管理 |

### サーバーサイド暗号化（SSE）
- SSE-S3: AWSが自動管理（デフォルト）
- SSE-KMS: AWS KMSを使用（カスタマーマネージドキーも可）
- SSE-C: ユーザーが独自キーを管理

### クライアントサイド暗号化（CSE）
- AWSは暗号化・復号化に関与しない

# データ保護と管理

## オブジェクトロック
- 削除・上書きを防止（読み取り専用）
- 保持期間を設定可能（期間経過後に解除）

| モード | 特徴 |
|--------|------|
| ガバナンスモード| 特定ユーザーのみ変更可能 |
| コンプライアンスモード| すべてのユーザーが変更不可（rootユーザー含む） |

- Glacierでは「ボールトロック」で同様の管理が可能

## リーガルホールド
- 法的理由によりオブジェクトを保護
- オブジェクトロックの保持期間とは独立
- オブジェクトロックとリーガルホールドの両方が無効にならないと変更不可

## バージョニング
- オブジェクトの履歴を保持し、以前のバージョンを取得可能
- バケット単位で有効化
- 削除すると「削除マーカー」が作成される
  - 削除マーカーを削除すると、以前のバージョンを復元できる
  - 完全削除には、バージョンIDを指定して削除する

# 高速転送・データ処理

## バッチオペレーション
- 大量のオブジェクトを一括処理
- 例: メタデータ更新、アクセス許可変更

## マルチパートアップロード
- オブジェクトを分割して並行アップロード
- 大容量ファイルを効率的にアップロード

## S3 Transfer Acceleration
- リージョン間のアップロード・転送を高速化
- エッジロケーションを経由

## S3 Select
- SQLクエリを使い、オブジェクトデータの一部分を抽出
- CLI, SDK, マネジメントコンソールから実行可能
単体テスト用のテストメソッドを召喚する つづき

以前の記事で書いた xUnit.net 用のコードスニペットですが、気づいたらもう一つ作って活用していたので書き残しておきます。

https://qiita.com/higege-amdeker/items/c588db5cc64e678ad693

# やりたいこと

C# xUnit のプロジェクトで `Theory` のテストメソッドを召喚したい。

https://xunit.net/docs/getting-started/v3/cmdline#write-your-first-theory

# やりかた

## 環境

- Microsoft Visual Studio Community 2022 (64 ビット)
  - Version 17.13.2

## 手順

### 1. スニペットファイルを追加する

1. スニペットファイル置き場へ
    - 僕の環境だと以下にありました。（今回は C# のスニペットを追加します）
`%USERPROFILE%\ドキュメント\Visual Studio 2022\Code Snippets\Visual C#\My Code Snippets`
2. 新規ファイルを作成 XunitTestFunctionTheory.snippet
3. ファイルをダブルクリックで開く（VisualStudio で開くと思います）

### 2. スニペットファイルを実装する

1. もうこれをドン

```xml
<?xml version="1.0" encoding="utf-8"?>
<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
  <CodeSnippet Format="1.0.0">
    <Header>
      <Title>xUnit test function [Theory]</Title>
      <Author>HigeDaruma</Author>
      <Description>Creates xUnit [Theory] test function.</Description>
      <Shortcut>theory</Shortcut>
    </Header>
    <Snippet>
      <Code Language="CSharp">
        <![CDATA[[Theory]
        [InlineData()]
        public void $FunctionName$_$Result$_When$Conditions$($end$)
        {
            // Arrange
            
            // Act
            
            // Assert
            
        }]]>
      </Code>
      <Declarations>
        <Literal>
          <ID>FunctionName</ID>
          <ToolTip>Input the function name for test.</ToolTip>
          <Default>FunctionName</Default>
        </Literal>
        <Literal>
          <ID>Result</ID>
          <ToolTip>Input the expected result of test.</ToolTip>
          <Default>ReturnsOk</Default>
        </Literal>
        <Literal>
          <ID>Conditions</ID>
          <ToolTip>Input the conditions for test.</ToolTip>
          <Default>InputIsOk</Default>
        </Literal>
      </Declarations>
    </Snippet>
  </CodeSnippet>
</CodeSnippets>
```

#### 超ざっくり説明
##### `<Header>` 
- `<Title>` `<Author>` `<Description>` 
    - コードスニペットマネージャーに表示される情報
- `<Shortcut>`
    - はスニペットを召喚するときのキーワード
##### `<Code Language="CSharp">`
- C# 向けのコードスニペット
- `<!CDATA[{ここに召喚するコードを書きます}]]>`
    - `$`で囲まれた文字は置換用のキーワード
    - `$end$` は入力完了後 Enter したときに移動する位置
##### `<Declarations>`
- 置換の設定・説明
- `<ID>`
    - 先ほど `Code` に書いたキーワード
- `<ToolTip>`
    - 置換箇所を実装中に表示されるツールチップ（マウスカーソルを当てる必要あり）
- `<Default>`
    - 召喚してすぐの時に表示される文字列

### 3. 召喚！
1. theory とタイプして Tab 2回！
1. 置換箇所を入力して Tab で移動
1. 最後に Enter

# 参考

https://learn.microsoft.com/ja-jp/visualstudio/ide/walkthrough-creating-a-code-snippet?view=vs-2022
【AWS】IAM

# はじめに
AWS DVA取得に向けた勉強の一環です。
新たな学びがあったら随時追記していきます。

正確性は保証しませんので参考程度に見てください。

# 概要
- AWSリソースへのアクセス権限管理やアカウント管理を行うサービス
- AWSアカウント作成時にルートユーザーが作成されるが、権限が強すぎるため通常はIAMユーザーを使用する
- 最小権限の原則（Least Privilege）に基づき、必要最小限の権限のみ付与することが推奨される

# IAMの主要コンポーネント

## IAMユーザー
- IAMで定義した個別のアイデンティティ
- 特定のリソースに対して特定のアクションを実行する権限を持つ
- 認証方法:
  - コンソールログイン: ID・パスワードを使用
  - アプリケーション/APIアクセス: アクセスキー・シークレットキーを使用
- アクセスキーの管理
  - セキュリティリスクがあるためIPアドレス制限や定期的なローテーションが推奨される

## IAMグループ
- IAMユーザーの集合体で、共通の権限を付与するために使用
- ユーザーごとに個別のポリシーを適用するよりも管理の手間や誤設定のリスクを減らせる

## IAMロール
- AWSリソースに特定の権限を付与する
- IAMユーザーとは異なり、一時的に認証情報を発行し、リソースに付与する
- 主な用途:
  - EC2インスタンスがS3にアクセスするためのIAMロール
  - Lambda関数がDynamoDBを操作するためのIAMロール


# IAMポリシー
- IAMポリシーはリソースに対して許可するアクションを定義する
- ポリシーの種類
  - アイデンティティベースポリシー: IAMユーザー、IAMグループ、IAMロールにアタッチ
  - リソースベースポリシー: S3バケットやSNSなどのリソースに直接アタッチ
- ポリシーの分類
  - インラインポリシー: 特定のIAMエンティティに直接埋め込む（再利用不可）
  - AWS管理ポリシー: AWSが提供する標準ポリシー、特定の職務向けのポリシーも用意されている（例: AdministratorAccess, Billing, DatabaseAdministrator）
  - カスタマー管理ポリシー: ユーザーが独自に作成し管理するポリシー

# クロスアカウント vs 単一アカウントのアクセス管理

## クロスアカウントアクセス
- 別のAWSアカウントのリソースにアクセスする際の仕組み
- AND条件: 双方のアカウントで許可されているアクションのみ実行可能
- 明示的なAllow（許可）が必要

## 単一アカウント内のアクセス管理
- OR条件: どこかで許可されていればアクセス可能
- 明示的なDeny（拒否）がない限り、許可されたアクションは実行可能


# アクセス権限の境界（Permissions Boundary）
- IAMエンティティ（ユーザーやロール）に適用できる、制限を加えるポリシー
- 元のIAMポリシーとAND条件で適用される
  - 例: ユーザーが「S3の全操作」を許可されたIAMポリシーを持っていても、Permissions Boundaryで「S3のReadOnly」に制限されていれば「S3のReadOnly」しかできない
- 制限を追加したい場合に使用


# スイッチロール（Switch Role）
- 特定のIAMユーザーが別のIAMロールに切り替えること
- クロスアカウントアクセスにも使用され、別アカウントのIAMロールを引き受けることでリソースにアクセス可能
- IAMロールは基本的にAWSリソース用だが、他のAWSアカウント向けのIAMロールも作成できる
ONLYOFFICEのTelegramボットがリリース：チャットしながらオフィスファイルで作業

ONLYOFFICEのTelegramボットをリリースしました。このボットを使えば、Telegram内で直接、文書のオープン、作成、変換、編集、そして共同作業が可能になります。以下にその詳細をご紹介します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2655664/f03f3062-e53c-4ff1-aff6-3d81edb7663d.png)

## はじめに

ONLYOFFICEボットを起動するには、以下のリンク https://t.me/ONLYOFFICE_bot をクリックして「START」ボタンを押してください。次回以降は、単に/start コマンドを入力するだけで、利用可能なオプションが表示されたスタートメニューにアクセスできます。

[**今すぐ使ってみる**](https://t.me/ONLYOFFICE_bot)

## ファイルの作成と編集

このボットでは、DOCX、XLSX、PPTX形式の新しいファイルを作成することができます。

* メニューの「作成」ボタンをクリックする
* 希望するファイル形式（文書、スプレッドシート、またはプレゼンテーション）を選択する
* ファイル名を入力する

作成が完了すると、ボットがファイルへのリンクを含むメッセージを送信します。このリンクをクリックすると、選択したファイル形式に応じたONLYOFFICEエディタが起動します。編集セッションが完了すると、ボットは保存済みのファイルを送信します。

## ファイルの共同編集

作成したファイルを共同編集するには、そのリンクが記載されたメッセージを他のTelegramユーザーに転送してください。リンクは24時間有効で、期間中に誰かがクリックするたびに、さらに24時間有効期限が延長されます。リンクの有効期限が切れるとエラーメッセージが表示され、参加者全員がエディタを閉じた時点で、更新されたファイルが即座に全員に送信されます。

## ローカルファイルを開く
デバイス内のファイルをボットに送信することで、ONLYOFFICEエディタで開くことができます。方法は2通りあります：

* コマンドを選択せずにファイルをチャットに送信する
* ボットメニューの「/start」→「開く」→「デバイスからファイルをアップロード」を選択する

どちらの場合も、ボットはファイルを開くためのリンクが記載されたメッセージを送信します。一度に複数のファイルを送信した場合、最初のファイルのリンクが生成されます。詳細は、[編集および閲覧可能なファイル形式の確認](https://github.com/ONLYOFFICE/onlyoffice-telegram/?tab=readme-ov-file#opening-local-files)をご覧ください。

## ファイルの変換

ボットを使ってファイルを変換するには、以下の手順に従ってください：

* 「/start」→「変換」を選択する
* デバイスからファイルをボットに送信する
* 変換したい形式を選択する

変換が完了すると、ボットは選択した形式の変換済みファイルをチャットに直接送信します。

## グループチャットでの利用について

グループでボットを利用する場合、以下の点にご注意ください：

* ファイル作成は「/document」、「/spreadsheet」、「/presentation」の3つのコマンドで管理され、ファイル名は自動生成されます（形式、日付、時刻、UTCを含むテンプレートに基づく）。
* 管理者権限の有無により、ボットとのやり取りの方法が異なります。管理者権限がない場合は、ボットに直接返信する必要があり、転送されたファイルメッセージ（自身のメッセージを除く）にはアクセスできません。管理者権限がある場合は、ボットがすべてのメッセージを確認でき、直接返信せずにファイルを転送できます。
* ファイルのエディタリンクを再生成するには、該当メッセージに返信してボットをタグ付けしてください。場合によっては、グループでの管理者権限が必要です。
* ファイルを開く際、チャットにただ送信されたファイルにはボットは反応しません。「/open」コマンドを使用し、返信メッセージでファイルを送信してください。
* ボットの言語は各ユーザーのTelegramプロファイルの設定に依存し、グループ全体で統一することはできません。
* ファイル変換機能は利用できません。

## さらに役立つコマンド

ボットの使い方のヒントを得るには、「/help」コマンドを利用してください。デフォルトでは、ボットはTelegramユーザープロファイルの言語設定に従い、該当する言語が利用できない場合は英語が使用されます。ボットの言語を手動で変更するには、「/lang」コマンドを入力してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2655664/e729f116-3a4c-4490-94ea-d8558a9e81b4.png)

[**今すぐ使ってみる**](https://t.me/ONLYOFFICE_bot)

## お役立ちリンク

* [ONLYOFFICEボット（Telegram）](https://t.me/ONLYOFFICE_bot)
* [GitHub – ボット](https://github.com/ONLYOFFICE/onlyoffice-telegram/)
* [その他の連携について](https://www.onlyoffice.com/ja/all-connectors.aspx?utm_source=qiita&utm_medium=article&utm_campaign=telegram_bot)
* [ONLYOFFICE Docsについて](https://www.onlyoffice.com/ja/office-suite.aspx?utm_source=qiita&utm_medium=article&utm_campaign=telegram_bot)
ECサイト作成で学んだこと①

今回はECサイトを作成で学んだことを5つに分けて記事にしていきます。

:::note warn
以下の箇条書きの記事をそれぞれ作成します。
記事が出来次第、リンクへ変更になりますのでお待ちください。
:::

- エンジニアリングについて
- Djangoについて
- Pythonの文法
- 汎用ビューについて


# エンジニアリングについて
今回は3つのことを学びました。
- セッションの適切な使い方
- Fat Viewの誕生
- トランザクションの使い所


## セッションの適切な使い方
私が作成したECサイトでは割とセッションを使いました。
### Userの判別
結論、今回はカートでユーザを判別しました。

普通なら User テーブルを作成してユーザに必要な情報を設定させユーザ名に unique 制約をつけて判別をすると思います。

しかし今回は User テーブルを作成せず、カートページに遷移したらセッションを発行するようにして、会員登録はしないようにしました。

### プロモーションコードの一時的な格納
プロモーションコードを適用する際に以下のメリットがありました。
- DBに保存せずデータの管理ができた
  - 毎回クエリを発行せずに済むのでパフォーマンスが良い
- カートに紐づく形でプロモーションコードを保持
  - チェックアウトまで保持が可能

ただDBに保存しないデメリットもありまして、
**セッションが切れたらコードが消えてしまう**ことです。
しかしプロモーションコードの性質上、一時的な管理が適しているため今回は問題ないと判断しました。

## Fat Viewの誕生
今回、私のコードがコードを書いた際にCTOからレビューいただきまして気づきました。それは、**Fat View** になっていたことです。

一例としてCartクラスのget_context_dataメソッドでFat Viewが誕生しました。
ここではざっくり以下のことをしていました。
- カートオブジェクトを取得 or 作成
- カート内の商品を取得
- バリデーションエラーを取得
- 商品情報を取得
- プロモーションコードを取得

データを取得すること目的ですが
私はカート内の商品ごとの小計の計算やカート内の商品の個数の計算を
Viewで行っておりました。

このようになってしまった原因は以下のことが考えられます。
- 何も考えずViewに殴り書きをした
- `get_context_data`が何をするメソッドなのかを理解せずに書いた
- modelはDBのカラム制約（unique, max_lengthなど)だけ書けばいいと誤認していた

以下の記事にて私はViewの役割をはっきりとさせました。

https://raruchan-techblog.com/python-django-view/

別記事にて`get_context_data`は紹介します。

## トランザクションの使い所
まずトランザクションとは
一連のDB操作を「ひとかたまりの処理」として扱うことです。
以下のようにALL or Nothingの状態です。
全ての処理が成功 → データを確定
途中でエラー発生 → 変更を取り消す

ここでは詳しい説明は割愛しますので、詳しくは以下のURLよりご覧ください。

https://qiita.com/zd6ir7/items/6568b6c3efc5d6a13865

今回のECサイトでは
購入処理の部分でトランザクションが必要となりました。
以下が機能フローです。
- 請求先住所保存
- 支払い情報保存
- 注文情報保存
- カート内商品保存
- メール送信
- プロモーションコードを使用済みに変更、使用日時を購入日時とする
- 新しいプロモーションコードを作成
- カートを削除

この8つを「ひとかたまり」として実行するようにしました。

また今回はDjangoのwith構文を使い
`with transaction.atomic()`として実行しました。
用途やシステムの複雑さによってwith構文ではなく
デコレータや他の実装方法になることもあるでしょう。

## 最後に
今回はECサイト作成で学んだこと①ということで
エンジニアリングについて記載しました。

次回はDjangoについてを書きます！
分析モデル(杉山聡) /序章

## 動機
研究室配属が差し迫っている今、自分が研究したい分野を知るためにも更に勉強が必要だと感じています。

そのために、本を読んだりコードを書いたりしながら、見返しやすい様まとめながら記事を書いていこうと思っています！

専門的知識もあまりないので、初心者なりに頑張っていこうと思います💪

今回題材に選んだ本は、研究室の先生に勧めていただいた、
「本質を捉えたデータ分析のための分析モデル入門」(杉山聡)
というものです。

下のリンクから購入できるので、一緒に読み進めてもらえたりしたら嬉しいです！
[本質を捉えたデータ分析のための分析モデル入門](https://www.amazon.co.jp/本質を捉えたデータ分析のための分析モデル入門-統計モデル、深層学習、強化学習等-用途・特徴から原理まで一気通貫-杉山聡/dp/4802613776)

## ゴール
この本には様々な分析モデルが紹介・説明されているそうなので、春休みの終わりまでに読み終わって以下のことができる様になるのが今回の目標です！
- 一般的な分析手法を学ぶ
- 分析タスクに対して最適の分析モデルを選べる様になる

早速本題です！

# 序章 (ベクトル内積とベイズの定理) 

最低限の数学の知識が書いてありました。
「ベクトル内積」や「ベイズの定理」ついて簡単に説明されていました。

「**内積は類似度を示す**」というのは何度が大学の授業でやっていたので、復習となりました。
以前RAGを触った際にもcosine similarityなどについてちょっと触れていたので、読んでいて面白かったです。

ベイズの定理は条件確立に関しての定理だよなぁという浅い理解しかできていなかったので、ここは勉強になりました。

ベイズの定理の本質は、「時間的に逆行する条件付き確率を、時間順行の条件付き確率に書き換えられる。」というものでした。

また、一般的にデータ分析は結果→原因の推定(時間逆行)なので、ベイズの定理が多用されるとわかりました。
遠方勤務制度設計（フルリモートワーク）の恩恵と弊害

会社を非難する意図はなく、状況を好転させるために文章を書いています。業務の疲れもあり、推敲が間に合っていませんが公開しながら文章を改めようと思います。

# 背景

私自身は都内 IT 企業でエンジニア職として働いており, ２０２０年のコロナ禍に伴い実家のある関東の近隣県でフルリモートワークを行なっていた。コロナ禍から回復する中で数ヶ月に一度ほど研修や懇親会で出社の機会がある中で約４年ほどを過ごした後に結婚を機に妻の実家のある地方へ移住を行なった。この移住に伴い遠方勤務者制度の枠組みで現職を継続しているが精神的に厳しく, 制度設計の粗が目立つ。制度のポジティブな側面が台無しになっており, 人材獲得ひいては企業成長戦略を足踏みさせてしまっているため, 本記事では恩恵を述べる一方で弊害を指摘する。

# 制度概要

弊社では「オフィスから片道通勤２時間以上または距離２００ km を超える者」を対象とする遠方勤務者制度を施行している。特徴としては以下の３点が挙げられる。

1. 出社を要する業務の免除
1. 年俸の５％カット
1. 出社の制限

> 出社義務の免除、および出社を必要とする業務を職務から除外することによる
職務範囲の一部縮小に伴い、以下の処遇の変更が行われます。

また上述の就業規則の一部引用から 1 の免除に対するペナルティとして 2 が存在しているが, 実際のところ隠れたペナルティ 3 が存在する。これは出社にかかる交通費支給が無くなり出社を要する業務の際には案件経費として精算が必要のルールとなっているためである。

# 恩恵

* [全国の人材を採用できる](#全国の人材を採用できる)
* [親の介護などで職を失わずに済む](#親の介護などで職を失わずに済む)

## 全国の人材を採用できる

経営層曰く全国の人材採用は積極的に行いたいとのこと。
たしかに地元指向や家庭がある人、家を建ててしまって土地から動けない人の話はよく耳にする。しかしながら個人的な印象では日本円の価値が落ちており, 海外のオフショア先が見つからないために国内でのリソース確保都合という穿った見方もしている。

## 親の介護などで職を失わずに済む

個人的にはこの制度を利用すべきは４０代、５０代で親の介護が必要になった場合のように感じている。介護理由で地元に戻る必要があるなどの理由であれば仕方がないように感じる。田舎であれば家賃差額でカット５％分はペイできるだろう。

# 弊害

* 給料カットが尾を引く
* 出社制限
* キャリアの見通しが立たない
* 本音を得る機会がない

## 給料カットが尾を引く

給料カットは社員のモチベーションを落とす。給料を上げる幸福感は一時的なものであり, しばしば退職を防ぐために支給を上げる手段が取られるが効果は一時的。逆にネガティブな感情はなかなか拭えず尾を引くためカットを避けるべきというのはよく知られている。このため, 何故他の従業員へのインセンティブの形を取らなかったのだろうか。また５％の減額をカバーしようと思うと１度の昇給では取り戻せない。

## 出社制限

出社制限はかなりエンゲージメントを下げるように感じられる。
新卒採用の場ではフルリモートは不安と感じる方もいるようだ。
仕事に慣れない時期やプロジェクト開始時のメンバー間での信頼構築期間では対面での懇親が必要に感じる。潜在層含めて採用の幅を広げる戦略上彼らを無視しても良いものだろうか。

出社制限があると管理職としては健康管理がやりづらい面もある。私のように社会関係資本がない土地に移動してしまうと人間関係が希薄になり健康を害するリスクが高まってしまい扱いに困る部分が出てくる面もあるかと思う。

また, 残業や休日作業で数年掛かりの大型案件の一区切りにおいても慰労会もなく, 新しい社員が入ってきても懇親会も参加されず, 退職される方の送別会もない。組織への帰属意識が薄れ, 本当に自分は会社員なのかと不安を感じることが多々ある。

## キャリアの見通しが立たない

できる仕事が限られる。オンラインで限定される場合にピープルマネジメントの手段に制限がかかりロールを限定されてしまう。

## 本音を得る機会がない

お酒の場ではポロッと本音で人は話してくれる。そのような機会で重要な仕事の進め方（人の関係性や力関係）を知ることができる。

# 自身の振り返りと制度に対する所感

元々は新幹線通勤で片道１時間＋ほどで月３〜４回であれば交通費の上限に収まる範囲であったため出社の必要性に応じて柔軟に働いていたが, 今回の移住より対象となり前述の特徴をペナルティとして重く感じている。結婚や家庭の事情で職を失わなくて良い側面の恩恵は大きいがエンゲージメントや持続性の点で不安がある。

制度に関しては前衛的な施作として評価している一方で前述の弊害に見られる粗さがあるように感じる。弊社は労働集約型ビジネスであるから自分自身含めて社員のつまらない理由での退職は減らさなければ事業のスケールが叶わない。

私は少しづつ新しい社会関係資本を築いていく必要のある中で, 会社とも話し合いをしていく必要があるように感じている。今思うのはフリーランスほどのリスクなく場所の制限なしに東京の仕事や自社のプライム案件をもらえる現状は恵まれているが甘えられない。辞める理由を考えるより辞めない理由を考えた方がいい。１つの組織に長期で所属することは多くの人に自分を覚えてもらえることに繋がる。人脈が次の条件の良い仕事に繋がるりギブアンドテイクをやり易くなる。

## ワーケーション

余談として世の中には出社を余儀なく働いている方も大勢おり, 全ての方がワーケーションできるわけではないのでワーケーションについて話す場合には慎重な配慮の必要性を強く感じています。
laravelのログファイルのパーミッション設定値を.envファイルに持ちたい

# 概要

- ログファイルのパーミッションを、ローカル環境では手軽さ重視で666にしたいけど、本番では横着せず664か644あたりにしたい
- という設定をlaravelの.envファイルでやりたい

# 通常の書き方（設定値直書き）

```php: logging.php
        'daily' => [
            'driver' => 'daily',
            'path' => storage_path('logs/laravel.log'),
            'level' => env('LOG_LEVEL', 'debug'),
            'days' => env('LOG_DAILY_DAYS', 14),
            'replace_placeholders' => true,
            'permission' => 0666, # ここを設定値化したい
        ],
```

# 解その１

```php: logging.php
        'daily' => [
            （略）
            'permission' => octdec(env('LOG_PERMISSION')),
        ],
```

```php: .env.dev(開発環境用.env)
LOG_PERMISSION=666
```

```php: .env.prod(本番環境用.env)
LOG_PERMISSION=664
```

解説
通常は `0xxx` のように先頭に0をつけることで8進数化させている。
envから読み込んだ値を8進数化するには、octdecを用いる。


# 解その２

```php: logging.php
        'daily' => [
            （略）
            'permission' => env('LOG_PERMISSION'),
        ],
```

```php: .env.dev(開発環境用.env)
# 8進数の666を10進数にすると438
LOG_PERMISSION=438
```

```php: .env.prod(本番環境用.env)
# 8進数の664を10進数にすると436
LOG_PERMISSION=436
```

これでもいけるけど、解１のほうが直感的かなあと。

# だめな例

```php: logging.php
        'daily' => [
            （略）
            'permission' => env('LOG_PERMISSION'),
        ],
```

```php: .env
LOG_PERMISSION=666
```

```:結果
--w--wx-wT 1 apache 1000 689998 Mar  5 21:19 laravel-2025-03-05.log
```

666を10進数として受け取り、8進数に変換した1232が適用される。

# ポエム

monologの設定値permissionが
`8進数を受け取るのが基本` なのだけど、
`10進数を受け取ると、ご丁寧に8進数に変換してくれる` というあたりが地味にいやーんだなと思う次第
Lightroomで他のアカウントに一括で写真データを移行する

# はじめに
Lightroom Classicではなく，普通のLightroomの話です
カスタマーセンターの方に教えていただいたやり方です
なお，Mac版での説明になりますので，Windowsの方は少し異なるかもしれません．
# 状況
- 学校で契約していたアカウントが期限を迎え使えなくなったので，個人アカウントに移行したい
- **編集データも残しておきたい！**
- JPEG多め
:::note warn 
クラウドに上がっているデータはサブスクリプションの契約が終了してから1ヶ月経つと消えてしまうようです．今すぐ移行しましょう！
:::
# 手順
Lightroom Downloaderを利用してみましたが，JPEGの編集データが残っていませんでした．そこで別アプローチをとります．
1. 前のアカウントにログインする
1. 移行したい写真を選択する
1. 右上の共有ボタン![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1734281/59b3f3d5-8ddc-432e-816b-e4620c5a899b.png)を押す
この中の「元画像」を押し，保存先を選択します．
1. 新しいアカウントでログインし直す
1. 左上の「ローカル」を押す
1. 「参照」の横にある![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1734281/e8970cea-286e-49d8-9206-9904ab235d1f.png)を押します
1. 先ほど選択した保存先を展開します
:::note info
もし，アクセス権がないなどのエラーが起きた場合の対処法
1. Macの設定アプリを開く 
1. 「プライバシーとセキュリティ」から「フルメディアアクセス」を選択
1. Lightroomをオンにする．もしない場合は左下の「＋」から追加する
1. Macを再起動する
:::

8\. 画像に編集データがあるかを確認する
9\. クラウドにコピーする
# 最後に
私はこの方法により一括で写真を移行することができました！
Adobeのカスタマーセンターの方，ご丁寧に説明していただきありがとうございました．
Adobeのカスタマーセンターは[こちら](https://www.adobe.com/jp/about-adobe/contact.html "優しい方々")
コードコンプリート＜上＞　−１−

第１章　ソフトウェアコンストラクションへようこそ

コンストラクション：何かを作ることの実践的な部分
ソフトウェアコンストラクションの
主なものは、**コーディング**と**デバッグ**。
他には、
- 詳細設計
- 単体テスト
- 統合テスト
- コンストラクション計画
- 統合


コンストラクション以外は、
- プロジェクトマネジメント
- 要求開発
- ソフトウェアアーキテクチャ（概略設計）
- ユーザーインターフェイス設計
- システムテスト
- 保守など

コンストラクションが重要な理由は
- コンストラクションはソフトウェア開発の30％ー80％の時間を占める
- コンストラクションへの専念は、個々のプログラマの生産性を驚くほど向上させる
- - あんまり体感していない。他の人の話を聞いてみる
- コンストラクションは、（コンストラクション前：要求仕様書、アーキテクチャ、コンストラクション後：独立テスト）
- コンストラクションは、必ず実行される唯一のアクテビティ（要求開発や設計、テストは飛ばさえてしまう場合がある）
- コンストラクションの成果物のソースコードはソフトウェアを常に書かれているもの（要求仕様書、設計書は必ずしも正しいとは言えないときもある）
Google Advanced Data Analytics Certificate & CompTIA Data+ dual credential を取得した

以前の記事で Google Advanced Data Analytics Professional Certificate と CompTIA Data+ を取得したことを書いた。

- [Google Advanced Data Analytics Professional Certificate を取得した](https://qiita.com/tatsu_sekine/items/12a858cef31771e251b2 "Google Advanced Data Analytics Professional Certificate を取得した") 

- [CompTIA Data+ を取得した](https://qiita.com/tatsu_sekine/items/23e4ae989b1c9eb62f99 "CompTIA Data+ を取得した") 

すると、ある日こんなメールが突然届いた。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2953203/23f21a88-6da8-4bb0-a735-8407ac9e7aeb.png)

何かの試験を受けた訳でもなくいきなりバッジが届くのはおかしい、スパムメールかもしれないと思い、念のためCredlyでそういったバッジがあるかどうかを確認してみた。自分で確認してみるということはITエンジニアとして殊勝な心がけです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2953203/bc2dbf01-d676-427f-95ff-e9178747398f.png)

すると、どうも[ Credly の Google Advanced Data Analytics Certificate & CompTIA Data+ dual credential のページ](https://www.credly.com/org/coursera/badge/google-advanced-data-analytics-certificate-comptia- "Google Advanced Data Analytics Certificate & CompTIA Data+ dual credential - Credly") を見ると Google 上級データアナリティクス プロフェッショナル認定証を修了し、CompTIA Data+ の試験に合格していると、女神転生の悪魔合体よろしく合体した証明書が貰えるらしい。

また、Google Advanced Data Analytics Certificate のページには記載が無かったが、[Google Cybersecurity Professional Certificate のページ](https://www.coursera.org/professional-certificates/google-cybersecurity/ "Google Cybersecurity Professional Certificate | Coursera") を見ると、グーグル・サイバーセキュリティ プロフェッショナル認定証を修了したうえで、CompTIA Security+の試験に合格すると合わせ技のような資格を取得できることが書いてあった。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2953203/e1329d17-1bf3-4761-8c7e-ee2390b5d2e4.png)

しかし、サイバーセキュリティ系は通常版で行けるのに、データ分析は通常版ではなく、上級版でないと合体した資格を取得できないのはどうにも解せぬ、とかなんとか思いながらも、遊戯王の融合モンスターばりのデュアル・クレデンシャルを融合召喚できるのであれば、喜んで貰っておこうということで、サクサクと申請して取得した。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2953203/c333e8d1-7bb0-4766-9a9b-82cf6f348321.png)

ということで、もし Google Professional Certificate と CompTIA の試験に合格している人はメールの受信箱を見返してみるといいのではないでしょうか。もしかしたら、 dual credential のバッジが届いているかもしれませんよ。


追記：
Grow with Google と CompTIA のブログを見ると、提携したんでヨロシク的な記事があった。

- [New IT support badge from CompTIA and Grow with Google](https://blog.google/outreach-initiatives/grow-with-google/-it-support-comptia/ "New IT support badge from CompTIA and Grow with Google")

- [Getting a Cybersecurity Certification With Google and CompTIA]( https://www.comptia.org/blog/getting-a-cybersecurity-certification-with-google-and-comptia "Getting a Cybersecurity Certification With Google and CompTIA")
CodeceptJS でユーザーの操作をテストコードに変換する方法

## はじめに

CodeceptJS には、ユーザーの操作を簡単に記録し、自動でテストコードに変換する方法 があります。

本記事では、CodeceptJS をメイン に、ユーザーが実際に行った操作を 自動でテストコード化する方法 を紹介します。

### 1. pause() を使って手動で操作を記録

pause() を使用すると、テストを一時停止し、手動で操作しながらコードを記録できます。

- テストコード例

```javascript
Feature('User Interaction');

Scenario('manual recording', async ({ I }) => {
  I.amOnPage('https://example.com');
  I.pause(); // ここでテストを一時停止

  // 一時停止後、手動で操作すると、対応するコードがコンソールに表示される
});
```

- 実行方法

```shell
npx codeceptjs run --debug
```

- 動作の流れ

1. pause() でテストが 一時停止
2. 手動でブラウザを操作
3. codeceptjs のコンソールに 対応する操作コード が表示される
4. 表示されたコードをテストに組み込む

**この方法を使うと、実際の挙動を見ながらテストを作成 できます。**

### 2. codegen を使ってユーザー操作を自動記録（Playwright 使用）

CodeceptJS は Playwright を利用して、ユーザーの操作を自動的にテストコードとして出力する ことができます。

- 実行コマンド

```
npx playwright codegen --target=codeceptjs https://example.com

```

- 動作の流れ

1. `https://example.com` を開いた ブラウザ が起動
2. クリック・入力などの操作を自動記録
3. 記録された操作が CodeceptJS のコードとして出力

- 出力されるコード例

```typescript
Feature('Example');

Scenario('recorded test', ({ I }) => {
  I.amOnPage('https://example.com');
  I.click('text=Login');
  I.fillField('input[name="username"]', 'testuser');
  I.fillField('input[name="password"]', 'password123');
  I.click('text=Submit');
  I.see('Welcome, testuser');
});
```

**この方法を使うことで、初心者でも簡単にテストコードを作成 できます。**

### 3. どちらの方法を使うべき？

| 方法 | 使いどころ |
|:-:|:-:|
|pause()|実際に試しながら細かく修正したい時
|playwright codegen|ユーザーの動きを自動で一気に記録したい時|

基本的には、

1. 最初に playwright codegen で大まかに記録
2. その後、pause() を使って微調整

という流れで進めるのが 最も効率的 です！

### まとめ

- pause() を活用すると、手動で操作を確認しながらテストコードを作成 できる

- Playwright の codegen を使うと、ユーザーの操作を自動で CodeceptJS のテストコードに変換 できる

**これらを組み合わせることで、効率的にテストを作成可能！**

**CodeceptJS の強力な記録機能を活用して、簡単に E2E テストを作成 しましょう！**
【kintoneノーコード開発】kintoneサンプルアプリ「営業支援パック」のアプリ構成を見てみよう

# はじめに
こんにちは、現在kintoneノーコード開発で日々試行錯誤しているばんちゃん（[@Banchan_k12](https://x.com/Banchan_k12)）です。
今回は、「営業支援パック」というサンプルアプリで用意されている３つセットになっているアプリの役割と構成を見てみようと思います。
### 対象
- これから新規アプリを作ってみようと思っている方
- サンプルアプリを使ったことがない方
# 導入
kintoneアプリを作るにはいくつか方法がありますが、「kintoneアプリストア」には様々な業務テーマに沿ってフィールド設定されたサンプルアプリが準備されています。

:::note info
サンプルアプリについて


kintoneサイト
[サンプルアプリページ](https://kintone-sol.cybozu.co.jp/apps/?_gl=1*1mkfj7c*_gcl_au*MTgxOTMwMjEzNy4xNzM0NjkzNTQy*_ga*MTgyMTg0NDA2OS4xNzM0NjkzNTQy*_ga_T5K95WXL54*MTc0MTE0NjA0NS4xNDcuMS4xNzQxMTQ2NjU3LjYwLjAuMA..*_ga_M1R7LYZ6DW*MTc0MTE0NjA0NS4xNDIuMS4xNzQxMTQ2NjU3LjYwLjAuMA..#apps"サンプルアプリページ")

kintone ヘルプ
[サンプルアプリを追加する](https://jp.cybozu.help/k/ja/user/create_app/add_app_store.html "サンプルアプリを追加する")
:::

### 準備
サンプルアプリ「営業支援パック」を追加します。

:::note info
kintone ヘルプ
[営業支援パックを使ってみよう](https://jp.cybozu.help/k/ja/id/040637.html "営業支援パックを使ってみよう")
>「営業支援パック」は、顧客や案件、商談を一元管理できる、営業活動に便利なアプリパックです。
>「顧客管理」「案件管理」「活動履歴」という3つのアプリで構成されており、アプリ同士がkintoneの機能で連携することで、それぞれに登録した情報をアプリ間で活用できます。
:::

### 確認

##### :one:　顧客管理アプリ
顧客の基本的な情報を管理するアプリ
このアプリで管理するデータを各アプリ先ルックアップ取得することで毎回入力する手間がなくなり、情報の修正変更も一か所で管理できます。また、個々の表記ゆれなどの発生が防げます。
![20250305_4.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3957411/343c00f6-397e-450b-b4eb-b07e8a34a324.jpeg)

##### :two:　案件情報アプリ
顧客案件を管理するアプリ
案件に紐づいた情報をまとめて管理、共有できます。
![20250305_5.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3957411/3e6559a5-ff7a-465f-a430-a1930e8067d6.jpeg)

##### :three:　活動履歴アプリ
営業活動を記録するアプリ
業務を行う中で、日々の活動を入力・更新して時間の経過とともにデータ量も蓄積されていきます。
![20250305_6.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3957411/c40cbb57-2424-4c4c-8ddc-cb14b4afb13d.jpeg)

:::note info
下記のフィールド機能を活用して連携しています

kintoneヘルプ参照
[アプリアクションでできること](https://jp.cybozu.help/k/ja/user/app_settings/appaction/whats_appaction.html "アプリアクションでできること")
![20250305_8.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3957411/5c184327-e5a5-4d63-8c7a-0ac7c3b360d3.jpeg)

[ルックアップとは](https://jp.cybozu.help/k/ja/user/app_settings/form/lookup/whats_lookup.html "ルックアップとは")
![20250305_9.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3957411/05dd3d0d-a3d2-47a4-a738-d109226dca68.jpeg)

[関連レコード一覧とは](https://jp.cybozu.help/k/ja/user/app_settings/form/related_records/whats_relatedrecords.html "関連レコード一覧とは")
![20250305_10.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3957411/577844f9-d534-4db1-90b4-c304b4d1e497.jpeg)
:::


「営業支援パック」は下記のように3つのアプリでそれぞれのデータをストックしていき、各アプリと連携して必要な情報を共有しています。
![20250305_3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3957411/c4b2b00b-1f70-4363-8812-5dbc7cac7354.jpeg)

:::note warn
<b>注意点</b>
ルックアップ元から取得しているアプリ内フィールドを修正、更新した場合は、手動でルックアップ再取得更新する必要があります
:::

# まとめ
今回ご紹介したのは「営業」という業務にあわせたサンプルアプリでしたが、「人事」「販売」など様々な業種、業態についても、各アプリにどんな情報を蓄積して、連携・共有するかというアプリ構築の流れをあてはめて見えてくるのではないかなと思います。
ぜひサンプルアプリを活用して実際に確認してみてください。
[RSpec] shared_contextで共通化

## はじめに
RSpecでログイン「状態」にしたいなどの共通処理を作成するための方法

APIモードでJWTでの認証方式を利用している。

以下２つが利用できるように共通化する
login_user: ユーザーのインスタンス
headers: login_userに紐づくaccess_tokenをBeare tokenに設定sheaders


必要な設定
```shell
# spec/rails_helper.rbの以下のコメントアウトを解除
ails.root.glob('spec/support/**/*.rb').sort_by(&:to_s).each { |f| require f }
```


基本
```rb
# spec/support/contexts/login_setup.rb
# 処理定義
RSpec.shared_context 'login setup' do
...
end

# 使用先
include_context 'login setup'
```

`spec/support/contexts/login_setup.rb`
letを使うかbefore doブロックを使用する
```rb
RSpec.shared_context 'login setup' do
  User.destroy_all
  let(:login_user) { create(:user, password: "Password1234!") }
  let(:login_headers) do
    post "/login", params: { user: { email: login_user.email, password: "Password1234!" } }
    token = body["token"]
    { "ACCEPT" => "application/json", "Authorization" => "Bearer #{token}" }
  end
end
```

```rb
describe "PUT /users/'id" do
    include_context 'login setup'

    it 'ユーザーを更新できる' do
      put "/users/#{login_user.id}",
        params: { user: { email: "updated@gmail.com", password: "Password1234!" } },
        headers: login_headers # ログイン状態にする

      expect(response).to be_successful
      expect(body['email']).to eq('updated@gmail.com')
    end
  end
```
【非エンジニアに読んで欲しい】システム開発に対する心得


## はじめに

この記事は非エンジニアに向けて書いています。

理由としてはクライアントや決定権を持っている人は開発やプログラミングのことをあまり知らないことが多いからです。

そのため、エンジニア側の都合とクライアント側の都合がよく衝突します。

私は受託開発の会社で働いているのですが、クライアントは売上を増やすために無理難題をぶつけてきます。

保守性を一切考えないような機能開発をしたがります。

しかし、システム開発で最も重要なことは持続可能性です。

もちろんMVPやpocレベルでは保守性を無視しても良い場合もあるでしょう。

しかし、システムが膨れ上がってしまった場合、いづれ損益分岐点に達します。

ここで適切にリファクタリングやリプレイスの提案が通れば良いのですが、私が経験した限りで言えばほとんどの場合提案は通りません。

なぜなら経営者もVCや銀行から調達した資金を投資しているからです。

これは文字通り自分の血となる金をつぎ込んでいます。

経営者は毎日自分の血を垂れ流しながら働いています。

そんな人達が、利益も出ない、表示上何も変わらない物にお金を払うと思いますか？

答えはNOです。

つまり、エンジニアは保守性の重要性を決裁者に分かるまで伝えなければいけません。

そして経営者はシステム開発を学ばなければいけません。

自らコードを書かないといけません。

お互いがお互いの利益だけを主張しても軋轢しか生まれません。

お互い相手の状況に寄り添い、想像し、創造する必要があります。

どちらかが得をしようとすると、必ず憎しみが生まれます。

お互いが利益を生み出すように、お互いが誠実にビジネスしましょう。

エンジニアも自らのアートなコードを押し付けてはいけません。

経営者側も、自分の利益だけを考えてはいけません。

この記事はシステム開発をしたいが、プログラミングがよく分からないという方の為に書いています。

## プログラミングの始め方

これは私より遥かに詳しい方が書いた記事が沢山あるので、詳しく知りたい方はそちらを読んでください。

あとはAIに聞いてください。

今やもう中学生がとんでもない、世界を変えるようなシステムを1人で開発していたりします。

誰でも簡単に情報を取得できる素晴らしい時代になったので、まずはやってみて下さい。

詰まったらAIに聞いて、とにかくガムシャラにやってみて下さい。

それでどうしても無理だったら、自分が何故上手くいってないのかをエンジニアに聞きましょう。

こういうことを言うとよく「そんな暇がないから委託しているんだ」という人がいますが、そんな考えだから搾取されるのです。

この世のビジネスの多くは情報の差分をお金に変えていると思っています。

エンジニアもそうですよね？
今までに培った知識をお金に変えています。

情報を自分より持ってない人に対して、情報を持っている人が対価を頂く。

ここに価値があります。

つまり経営者側の人は情報の差分を減らす努力をしなければいけません。

そうしないと必ず軋轢が産まれたり、搾取されたりします。

人類みな様々なチャネルに興味を持ち、常に学習し続けなくてはいけません。

人間は変化を恐れます。
ホメオスタシスがあります。

しかし、DNAは常に変化し続けたことで何十億年も持続してきたのです。

人間はただのDNAの乗り物でしかありません。

私たちは全員種の保存という観点からすると、働き蟻や働き蜂となんら変わりません。

その世界で生き残るためには、常に自身を変化させ続け、向上し続け、学習し続ける必要があるのではないでしょうか？


## システム開発になぜ保守性が重要なのか？

事業というものは情報商材屋さんでもない限りは、基本的には売上は徐々にしか伸びていきません。

売上を安定的に伸ばし、成長し続けていかないと資本主義の競争社会では生き残れないため、持続可能性という観点が非常に重要になってきます。

そして、持続可能性を保つためにはコードをクリーンに保つ必要があります。

コードをクリーンに保たないとシステムが属人化し、徐々に腐敗していきます。
組織が腐っていきます。

ただでさえ機能を追加していけばエントロピーが増大して、複雑性が指数関数的に増えていくのに、ここにスパゲッティコードも絡まると、主要メンバーが一人でも抜けてしまうと途端に崩壊するサービスの出来上がりです。

私はこの世に一つでも多くのサービスが出てきて、伸びたほうが人生が楽しくなると思っている。

だからこそ最初からクリーンな、可読性の高いコードを書き、属人化を防ぐことが大切です。

誰も知識のない人と一緒に働きたいとは思いません。

レベルの高い人はレベルの高い人と働き、レベルの低い人はレベルの低い人と一緒に働きます。

自分の水準を上げて、幸せな環境で働きましょう！


## 最後に

私は今エンジニアをしながら自身の法人を持ち、自分のサービスを作り、伸ばしているところです

もしこの記事がためになると思いましたら、いいね頂けるととても嬉しいです。

ここまでお読み頂きありがとうございました。


## 参考

https://amzn.to/4bqybu8
【AccessVBA】CurrentDb は変数に入れましょうというお話

AccessVBAで、リンクテーブルのリンク先は TableDef オブジェクトの Connect プロパティで取得できる。

```vba
    Debug.Print CurrentDb.TableDefs("T_在庫").Connect
```
とすればよい。（「;DATABASE=C:\temp\在庫管理.accdb」が返る）

なので、

```vba
    With CurrentDb.TableDefs("T_在庫")
        Debug.Print .Connect
    End With
```

としてもいけそうだが、これはエラーになる。

`CurrentDb` を変数に入れて、

```vba
    Dim db As Object
    Set db = CurrentDb
    
    With db.TableDefs("T_在庫")
        Debug.Print .Connect
    End With
```

とすればエラーにならない。

なぜ？

AI先生（ChatGPT）に聞いてみた。

ChatGPT 曰く、

あなたの2つのコードの違いは、`CurrentDb` の扱い方にあります。  

### **1つ目のコード（エラーなし）**
```vba
Dim db As Object
Set db = CurrentDb
With db.TableDefs(table_name)
    Debug.Print .Connect
End With
```
このコードでは、`CurrentDb` を `db` という変数に **一度代入して** から `db.TableDefs(table_name)` にアクセスしています。

### **2つ目のコード（エラー発生）**
```vba
With CurrentDb.TableDefs(table_name)
    Debug.Print .Connect
End With
```
このコードでは、`CurrentDb` を **直接参照** しています。

---

### **なぜ2つ目のコードがエラーになるのか？**
`CurrentDb` は **関数** であり、その呼び出しごとに **新しい Database オブジェクトを返す** 仕様になっています。  

つまり、`With CurrentDb.TableDefs(table_name)` の **`CurrentDb` が評価されるたびに別のオブジェクトが作られる** 可能性があります。  

このため：
1. `CurrentDb.TableDefs(table_name)` が **一時的なオブジェクト** となり、  
2. `With` のスコープの中で `Debug.Print .Connect` を実行する際に、  
3. **元の `CurrentDb` オブジェクトが破棄されている可能性があるため、エラーが発生する** ことがあります。

---

### **解決策**
1. **`CurrentDb` を変数に代入して使う（1つ目のコードのようにする）**
    ```vba
    Dim db As Object
    Set db = CurrentDb
    With db.TableDefs(table_name)
        Debug.Print .Connect
    End With
    ```
    これにより、**同じ `Database` オブジェクトを一貫して使用** できます。

2. **`CurrentDb` の戻り値を一時変数に格納**
    ```vba
    With (CurrentDb)
        Debug.Print .TableDefs(table_name).Connect
    End With
    ```
    ただし、この方法は Access VBA では `With` ステートメントで括弧を使えないため不可。

3. **`CurrentDb` を都度明示的に呼び出す**
    ```vba
    Debug.Print CurrentDb.TableDefs(table_name).Connect
    ```
    これは `With` を使わないので `CurrentDb` の一時オブジェクトの影響を受けません。

---

### **結論**
- `CurrentDb` は **呼び出すたびに新しいオブジェクトを生成する** ため、`With CurrentDb` を使うとスコープの途中でオブジェクトが消える可能性がある。
- **回避策として、一度変数に代入して使うのが安全**。

**→ 1つ目のコードが正しい書き方！**

ということらしいです。

`CurrentDb` は変数に入れましょうというお話でした。
Python: unittest 抽象テストケースの定義方法

# あらまし
Python test ドキュメント: [test --- Python 用回帰テストパッケージ — Python 3.10.16 ドキュメント](https://docs.python.org/ja/3.10/library/test.html#writing-unit-tests-for-the-test-package)を読んでいて、おもしろい記述を見つけた:

>できる限りテストコードを再利用するようにしましょう。時として、入力の違いだけを記述すれば良くなるくらい、テストコードを小さくすることができます。例えば以下のように、サブクラスで入力を指定することで、コードの重複を最小化することができます:
>```python
>class TestFuncAcceptsSequencesMixin:
>
>    func = mySuperWhammyFunction
>
>    def test_func(self):
>        self.func(self.arg)
>
>class AcceptLists(TestFuncAcceptsSequencesMixin, unittest.TestCase):
>    arg = [1, 2, 3]
>
>class AcceptStrings(TestFuncAcceptsSequencesMixin, unittest.TestCase):
>    arg = 'abc'
>
>class AcceptTuples(TestFuncAcceptsSequencesMixin, unittest.TestCase):
>    arg = (1, 2, 3)
>```
>このパターンを使うときには、 unittest.TestCase を継承した全てのクラスがテストとして実行されることを忘れないでください。 上の例の Mixin クラスはテストデータを持っておらず、それ自身は実行できないので、 unittest.TestCase を継承していません。

なるほど、この書き方は確かに使いやすいが `TestFuncAcceptsSequencesMixin` の中で `unittest.TestCase.assert*` を使いたい場合どうするんだ？と思ったので調査した。

# 結論
下記のようにするとよい。

```python
class TestFuncAcceptsSequencesMixin(unittest.TestCase): # ←いったんミックスインクラスをテストケースにしてしまう

    func = mySuperWhammyFunction

    def test_func(self):
        self.func(self.arg)
        self.assertEqual(1,1) # ←使える！

class AcceptLists(TestFuncAcceptsSequencesMixin):
    arg = [1, 2, 3]

class AcceptStrings(TestFuncAcceptsSequencesMixin):
    arg = 'abc'

class AcceptTuples(TestFuncAcceptsSequencesMixin):
    arg = (1, 2, 3)

del TestFuncAcceptsSequencesMixin # ←ミックスインクラスを消す！
```

こうすることで unittest のテストディスカバリからミックスインクラスの存在を隠蔽することができる。

# 参考にしました
https://stackoverflow.com/a/43353680
クォートマンとねこびっとくんの回転冒険 [第1話]


## 第1話：回転の謎を解け！

真っ青な宇宙を背景に、黄色くてピカピカのハゲ頭が輝いていました。それは、3D空間の回転を自在に操る不思議なヒーロー「クォートマン」です。

「おーい、ねこびっとくん！今日は特別な冒険の日だぞ！」
クォートマンは元気よく呼びかけました。

中学2年生のねこびっとくんは、猫耳フードをかぶった好奇心旺盛な少年。コンピュータが大好きで、クォートマンのサイドキックとして宇宙の冒険に参加していました。

「なんですか、クォートマンさん？今日はどんな冒険ですか？」
ねこびっとくんは目を輝かせて尋ねました。
クォートマンはニヤリと笑って、宇宙船のコントロールパネルに手をかざしました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30621/5645b555-fe52-4f93-8fec-8e5da847fe65.png)


「今日はな、『クォータニオン』という魔法のような数学を教えてやるぞ！これを使えば、宇宙船を思い通りに回転させることができるんだ！」



「クォータ...なんですか？難しそう...」
ねこびっとくんは眉をひそめました。

「心配するな！簡単に言えば、3D空間での回転を表す特別な数のことだ。4つの数字でできていてな、これがあれば、どんな方向にでも物を回転させられるんだ」


(つづく...)