OmniAICreator/Qiita-1.07M huggingface dataset:
Synthetic テスト：わかりやすく解説

![表紙](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3967621/9c81eb92-1a02-47c4-a4de-565c4616ff07.png)

「Syntheticテスト」という言葉を何度も耳にしたことがあるでしょう。特に監視プラットフォームを販売しているSaaS企業に関わったことがあるならなおさらです。

しかし、ここで問題なのは、どのベンダーも「Syntheticテスト」の説明が曖昧で、まるで混乱を利用して利益を得ようとしているかのように感じられることです（正直に言うと、たぶんその通りです）。

例えばDatadogの場合、こんな説明をしています：

> Synthetic テストでは、世界中からのシミュレートされたリクエストとアクションを使用して、システムとアプリケーションがどのように実行されているかを観察できます。Datadog は、バックエンドからフロントエンドまで、さまざまなネットワークレベル (HTTP、SSL、DNS、WebSocket、TCP、UDP、ICMP、gRPC) で、制御された安定した方法で Web ページと API のパフォーマンスを追跡します。障害のある動作 (リグレッション、機能の破損、応答時間の長さ、予期しないステータスコードなど) を警告します。

なるほど、Datadogさん、良いイントロですね。でも…そもそもSyntheticテストって何でしょう？

マーケティング担当者の混乱を招く説明（彼らは自分が売っているものを本当に理解しているかのように振る舞う）とはおさらば。この記事では、Syntheticテストを簡潔に解説します。

## Syntheticテストの核心：自動化

Syntheticテストの本質は自動化です。

想像してみてください：ブラウザが特定のウェブページをひたすら訪れ、特定の操作を実行し、すべてが正しく動作していることを確認します。これがSyntheticテストの本質であり、ブラウザ自動化テストと何ら変わりません。

簡単に言えば、Syntheticテストはブラウザ自動化テストにいくつかの機能を追加したものです。

Playwright、Puppeteer、Seleniumのようなツールが通常、自動化テストに使用されます。これらのツールの比較については、[別の記事](https://qiita.com/Leapcell/items/6aeffb0a60586b5eb3dd)で詳しく解説しています。

したがって、自動化テストに少しでも触れたことがあるなら、すでに半分は理解しているということです。しかし、Syntheticテストは単なるテストでは終わりません。それが「Synthetic」である理由のためです。

## Syntheticテストの「Synthetic」の部分

「Synthetic」は、「合成」です。

では、この「Synthetic」とは何でしょう？具体的に何が合成されているのでしょう？

- **アクセスコンテキスト**：Syntheticテストは通常、世界中の異なる地域にあるマシンから1日に何度もテストを実行します。例えば、東京とニューヨークでアプリがどのように動作するか気になったことはありませんか？Syntheticテストがその疑問に答えます。

- **ネットワークデータ**：単にタスクが完了するかどうかを確認するだけではありません。Syntheticテストは、ネットワークパフォーマンスの主要な指標（例えばレイテンシやリクエストエラーなど）も記録します。不具合があればすぐにわかります。

- **フロントエンドパフォーマンス**：ページの読み込み速度、リソースの読み込み時間、レンダリング時間など、Syntheticテストはこれらを測定します。遅いウェブサイトでは、顧客が必要ないと判断してページを閉じるまでの時間が十分にあります。

Syntheticテストは単に「動作するか？」というチェックを超え、「どこでも、どんな条件下でも、ちゃんと動作しているか？」を問います。

## Syntheticテストの利点：包括的な問題発見

Syntheticテストの特徴は、問題を包括的に検出できる点にあります。ブラウザ自動化テストと合成されたモニタリングデータを組み合わせることで、潜在的な問題の全体像を提供します。以下のような点で優れています：

- **タスクの完了**：Syntheticテストは、ログイン、購入、フォーム送信などのトランザクションやタスクが正常に完了することを確認します。

- **パフォーマンスの洞察**：単に動作するかどうかを確認するだけでなく、「どれだけ良く動作するか」を確認します。例えば、ある地域では3秒で読み込まれるページが、別の地域では30秒かかるといった洞察を提供します。

- **早期問題検出**：合成されているため、実際のユーザーが遭遇する前にシナリオをテストできます。

- **スケーラビリティ**：Syntheticテストは、世界中のロケーションで24時間365日テストを実行でき、人間のQAチームでは到底及ばない規模で実現します。

## 結論

Syntheticテストは、ブラウザ自動化テストに合成されたモニタリングデータの先見性を加えた拡張版であり、アプリケーションがどこでも常に信頼性高く動作することを保証します。

次に「Syntheticテスト」という言葉を耳にしたときには、その正体を正確に理解し、曖昧な説明に惑わされることなく対応できるようになるでしょう！😉

---

クラウドでブラウザ自動化テストをホストする方法をお探しなら、[Leapcell](https://leapcell.io/?lc_t=q_st)をお試しください！

[![Leapcell](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3967621/feab1df5-1d5f-a185-04af-d019f6aab153.png)](https://leapcell.io/?lc_t=q_st)

[Leapcell](https://leapcell.io/?lc_t=q_st)は、分散アプリケーション向けに設計された最新のクラウドコンピューティングプラットフォームで、PythonおよびNode.jsコードをサーバーレス方式でホストできます。リソースを使用した分だけ支払う**従量課金モデル**を採用し、アイドルコストをゼロに抑えます。

Playwrightのデプロイ例については、[ドキュメント](https://docs.leapcell.io/examples/testing/playwright/)をご覧ください。
dtype=と.astype()の使い方

# ■目的

これまでなんとなくで書いていたが、`dtype=str` と `.astype(str)` の違いが急に分からなくなって発狂した。
今更でもちゃんと違いを理解して両方を適切に使用できるようにする。


# ■定義の確認

`dtype=` と `.astype()` は、どちらもデータフレームの全ての列を文字列型に変換するために使用されるが、使用されるタイミングと方法が異なる。

以下、基本どのデータ型でもやることは同じなので、文字列型(str)を例にして記載していく。


## `dtype=str`
`dtype=str` は、`pd.read_csv` 関数の引数として指定され、CSVファイルを読み込む際に全ての列を文字列型として読み込むように指示する。これにより、読み込み時点で全てのデータが文字列型になる。

コード例：
```python
df = pd.read_csv(file_path, dtype=str, encoding='utf-8')
```

## `.astype(str)`
`.astype(str)` は、データフレームが既に読み込まれた後に、全ての列を文字列型に変換するためのもの。これは、データフレームが読み込まれた後に型変換を行う方法である。

コード例：
```python
df = pd.read_csv(r"C:\XXXX\XXXX.csv", encoding='utf-8').astype(str)
```

# ■主な違い
1. **タイミング**:
   - `dtype=str`: CSVファイルを読み込む際に全ての列を文字列型として読み込む。
   - `.astype(str)`: データフレームが既に読み込まれた後に全ての列を文字列型に変換する。

2. **処理の効率**:
   - `dtype=str`: 読み込み時に全ての列を文字列型にするため、読み込みが一発で済む。
   - `.astype(str)`: 読み込み後に全ての列を文字列型に変換するため、追加の処理が必要。

3. **コードの簡潔さ**:
   - `dtype=str`: より簡潔で、読み込み時に型を指定するため、コードが短い。
   - `.astype(str)`: 読み込み後に型変換を行うため、コードが少し長くなる。

# ■まとめ
- **推奨方法**: 全ての列を文字列型として読み込みたい場合、`dtype=str` を使用する方がラク。
- **例外的な場合**: 既に読み込まれたデータフレームの型を後から変更したい場合は、`.astype(str)` を使えば良い。

したがって、以下のように書くのが最も効率的：

```python
df = pd.read_csv(r"C:\XXXX\XXXX.csv", dtype=str, encoding='utf-8')
```

これにより、CSVファイルを読み込む際に全ての列が文字列型として読み込まれる。



列ごとにデータ型を指定したい時は以下のように書く：

```python
import pandas as pd

# CSVファイルを読み込む際に、特定の列のデータ型を指定
df = pd.read_csv('file.csv', dtype={'column1': 'int64', 'column2': 'float64'})

# データフレームの特定の列のデータ型を変換
df['column1'] = df['column1'].astype('str')
```

# ■感想
どっちでも同じやろと`.astype()` を使いがちだったが、`dtype=`も適宜使っていこうと思う。

とはいうものの、前ゼロと末尾にブランクを含むコードのデータフレームを良かれと思って`dtype=str`で読込んだおかげで大事故を起こして切腹したことがあるので、`.astype()` と`dtype=`のどちらを使うかだけでなく、処理ごとのデータフレームの行数、列数、要約した感じ等の確認を徹底してやっていくことの方がもっと重要だろうなとは思う。
Rust 関数風マクロRTA (最小構成の関数風マクロ)


こちらの記事は [Rustマクロ冬期講習アドベントカレンダー](https://qiita.com/advent-calendar/2024/rust-macro) 16日目の記事です！

> アドカレまとめ記事はこちら！: [Rustマクロ作成チートシート！](https://qiita.com/namn1125/items/d601d2cbbf2cc7b5d3dc)

関数風マクロはRustの手続きマクロの一種です。では作っていきます。

# 最小構成の関数風マクロ

ライブラリクレートを作成します。

```bash
cargo new --lib func_like_macro
cd func_like_macro
```

`Cargo.toml` を書き換えます。

```diff_toml:Cargo.toml
[package]
name = "func_like_macro"
version = "0.1.0"
edition = "2021"

+[lib]
+proc-macro = true

[dependencies]
```

`src/lib.rs` を書き換えます。余計なクレート等入れるのは面倒なので入力をそのまま出力する関数風マクロにします。

```rust:src/lib.rs
use proc_macro::TokenStream as S;

#[proc_macro]
pub fn m(t: S) -> S {
    t
}
```

動作確認します。

```rust:src/main.rs
use func_like_macro::m;

fn main() {
    m!(println!("Hello, world!"););
}
```

```bash
cargo run
```

無事にコンパイルまでされたところでタイマーストップ。

# まとめ・所感

あ、時間測り忘れた...w

「ただの手抜き記事じゃないか」って...？そうですよ...！

でもミニマルな技術記事も需要ってありますよね...？というわけで同じ形式を属性風マクロとderiveマクロでもやります！
テレワークにおける自宅ネットワーク機器交換の落とし穴（Wi-Fiルータ）

## はじめに
こんにちは。エンジニアの長谷川です。
今日は最近ハマったことを備忘の意味も込めて記載します。

## 環境まわり
普段、現場貸与のPCでテレワークをしています。
現場指定のVPNクライアントを使用して現場のネットワークに接続しています。
先々週に自宅のWi-FiルーターをTP-LinkからAtermに変えました。

## 起こったこと
先週あたりから現場のGitサーバーに繋がりづらくなりました。
NASなど他のアクセスは問題ないのにGitサーバーのみアクセスしづらい状態です。

## 試したこと＆確認したこと
・困ったときのPC再起動
  ってことで再起動すると繋がりました！！
　ただ、1時間ほど経過するとまた繋がらなくなりました。。。

・Windows Update
  確認したものの、ちゃんと更新されていたため特に何もできず。。。

・ipconfigの確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3780649/63dcb74a-a09b-19a0-b51d-b9a45ee8e453.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3780649/eb89acfa-f68c-8c1a-563b-ff8b15c81bba.png)
　VPNクライアントと思われる箇所が「不明なアダプター」表記に。
　なんか怪しい・・・

・VPNクライアントのステータス確認
 　![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3780649/c532f9c6-9944-4d71-6ead-54fead920dbb.png)
　あ、DNSのセグメントがWi-Fiと被ってる！！

## 結果的に
　Wi-Fiルーターの第3セグメントがVPNクライアントが指定しているDNSサーバーの第3セグメントと被っていることで発生していた事象でした。
 Atermの設定画面からLAN側の設定を変更することで解決しました。
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3780649/4099a137-c925-3e55-27e4-4a7c472b69fb.png)

ただ、変更すると「基本的には初期値使ってね！！」といった注意が表示されました。

## 最後に
自宅のWi-Fiルーターの交換から思わぬ地雷を踏みました。。。
テレワークで会社のLANにVPN経由で接続しているという人は起こりえる問題だと思いますので、
機器交換後に接続しづらくなった・・・と感じた場合は同じようにネットワーク設定を確認すると良いかもしれません。

以上、長谷川でした。
【Python】Python経由でPowerPointにパスワードをかける方法（win32com）

Python経由でパワポにパスワードをかける方法の紹介です。

**Pythonからpowerpointを操作することのできるモジュール`python-pptx`はファイルの保護に対応していません。** そのため、Pythonオンリーでpowerpointファイルにパスワードをかけようと思うとこちらの方法が候補になってくると思います。

# 動作条件
- Windows
- PowerPointのインストール

# コード
``` Python
from win32com.client.gencache import EnsureDispatch

# 以下は実際に使用するパスやパスワードを入れてください
input_path = 'hogehoge.pptx'
output_path = 'fugafuga.pptx'
password = 'mokomoko'

ppt_app = EnsureDispatch("PowerPoint.Application")
slide = ppt_app.Presentations.Open(input_path)
ppt_app.DisplayAlerts = False
slide.Visiable = False
slide.Password = password
slide.SaveAs(output_path)
slide.Close()
ppt_app.Quit()
```
:::note warn
Excelでは、SaveAsメソッドの引数にパスワードを設定しますが、PowerPointではPasswordメソッドでパスワード設定を行います
:::

# 参考
win32comを利用した、同様の方法でエクセルにパスワードをかける方法はこちらの記事にて紹介されています。

https://qiita.com/lystahi/items/fdae6a77fefe8d1019cc

（Excelにも、pythonから操作することができる`openpyxl`というモジュールがあるのですが、このモジュールではファイルの保護ができないので、win32comを使った上記の方法が有効です）

# Appendix
win32comの機能はVBAのAPIを使用しているため、基本的にはVBAのリファレンスに載っているメソッドを活用できます。OfficeのアプリケーションをPython(win32com)で動かしたいときはこのリファレンスを見ればスムーズに実装できるかと思います。

https://learn.microsoft.com/ja-jp/office/vba/api/overview/
Pythonのライブラリの名称の意味について

## はじめに
ITスクールRareTECHで学習しているsio-irukaです。
Pythonのライブラリの名称の意味について、簡潔にまとめてみました。

## NumPy
「Numerical Python」の略。
Pythonの数値計算ライブラリ。
効率的な数値計算やデータ処理を行うための強力なツールを提供する。

## pandas
「panel data s」の略。
（※パネルデータ（Panel Data）は、同じ観測対象（個体や事象）について、異なる時点でのデータを収集したデータセットのことを指す。パネルデータは、時間的な変化を追跡しながら、個体間の違いを分析するのに非常に有用。）
Pythonのデータ分析ライブラリ。
特にデータ操作やデータ解析に特化している。
pandasは、データの読み込み、前処理、操作、集計、可視化などを簡単に行うための強力なツールを提供する。

## Matplotlib
「MATLAB plotting library」の略。
MATLABのようなグラフ描画機能をPythonで実現するために開発されたライブラリ。
MATLABのユーザーがPythonに移行しやすくするために、似たようなインターフェースを提供している。

## SciPy
「Scientific Python」の略。
Pythonプログラミング言語を使用して科学技術計算を行うためのライブラリ。
数値計算、データ処理、最適化、統計、信号処理など、さまざまな科学技術的なタスクをサポートするために設計されている。
SciPyは、NumPyを基盤としており、NumPyの配列を利用して効率的な計算を行う。これにより、科学技術計算やデータ分析の分野で非常に広く使用されている。

## scikit-learn
「SciPy Toolkit for Machine Learning」の略。
具体的には、SciPyライブラリの一部として開発された機械学習のためのツールキットを指す。

## おわりに
ここまで読んでいただきありがとうございます！
【OSINT】Google mapに関するあれこれ

# はじめに
こんにちは，しがないOSINTerのTaku_Taku_Takuです．
今回は個人的にGoogle mapを見ていて感動したことを書きます！

# その１：ストリートビューで過去の姿が見える

イメージ（2010/10 ごろの弊学．まだキャンパスがないころ）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3805709/5631227d-25cd-3fcb-b849-6a0ecb273b3f.png)

:::note info
今と昔を比較するとより面白い．
:::

# その２：3Dにできる
PCでレイヤを”航空写真”にして，ctrlを押しながらカーソルを触ると3Dマップにできる．
わざわざ，Google Earthを開かなくてもよい．特に平面の地図と気軽に見比べられるのがいい！
イメージ（弊学の最寄駅）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3805709/bb49d755-ed34-a2e0-fe81-f8f1c725cd03.png)

# その３：座標を簡単に入手できる
OSINTをやっていないと感じないメリットですね（笑）
やり方は，座標が欲しい地点をクリックし，画面中央下から生えたボックスの青いところをコピーするだけ！
ex)`34.811771, 135.561106`
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3805709/0644b130-8451-f1cb-3760-d875974cddda.png)


# 余談：what3words
３つの単語で3m×3mの正方形の地点を一意に定めることができる．
住所よりも精度が高い．（入口などを指定する場合は特に）

気になった方は以下からどうぞ

https://what3words.com/ja/about

# おわりに
3月のTukuCTF2024や，2025年6月開催のDiverOSINTCTFが楽しみです！！！
OSINTのCTFはなかなか無いから...（悲）
【K8s】Next.jsをK8sのIngressで動かしてSSLでハマった話


:::note warn
コロナでアドカレ完走ギリギリになりました。
日付過ぎて申し訳ないです...
記事の内容は保証するのであとは笑ってください()
:::

みなさんこんにちは、 ~~コロナでぶっ倒れた~~ あかつきゆいとです。
おそらくK8sユーザーの中にはNext.jsを動かしている方もだいぶいるでしょう。
今回はNext.jsのコンテナを動かしてIngressで公開しようとしてハマったお話です。

## IngressとCertmanagerとは

K8sユーザーの皆さんなら一度は耳にしたことがあるでしょう。
Ingressというのは、要はリバースプロキシみたいなことをしてくれるもので、これをサービスに紐つけておけば、一つのExternalIPで複数のサービスをドメイン振り分けで使うことができるものです。
そして、Certmanagerというのは、そのIngressを使用する上で、勝手にSSL化してくれるシステムです。

今回はそのCertmanagerの設定でつまづいた話です。

:::note warn
CertmanagerやIngressのインストールに関しては今回は紹介しませんのでご注意ください。
:::

## ことのあらまし

ぼく「よし、自分のプロフサイト、デプロイしちゃうよ〜！！」

```yaml:ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: yuito-work
  labels:
    name: yuito-work
  annotations:
    # http01でACME認証するClusterIssuer
    cert-manager.io/cluster-issuer: le-http-prod
    nginx.ingress.kubernetes.io/ssl-redirect: "false"
    nginx.ingress.kubernetes.io/force-ssl-redirect: "false"
    nginx.ingress.kubernetes.io/from-to-www-redirect: "true"
spec:
  ingressClassName: nginx
  rules:
  - host: www.yuito.work
    http:
      paths:
      - pathType: Prefix
        path: /
        backend:
          service:
            name: yuito-work
            port: 
              number: 80
  tls:
    - hosts:
      - yuito.work
      - www.yuito.work
      secretName: yuito-work-tls
```

Certmanager「ACME通りませんでした。」
ぼく「ha?」

## 原因を調査する

まずはログを調査してみることに...

```ログ
“GET /.well-known/acme-challenge/WWVTqAHf89uqumxI02ti1I_GGhBE7B2QbfoZJIltZGI HTTP/1.1” 404 ...
```

何やら、ACMEの`.well-known`に対して404が出ている模様...
Chromeでアクセスしてみたり、Curlでアクセスしてみると、Next.jsの404が出ていることが判明...

そう、原因は、 **Next.jsの404ページもIngressのリバースプロキシ範囲に含まれてしまっている** ことだ。

## 解決法

Ingressの設定項目について、いろいろ調べてみると、正規表現が使える模様...
正規表現を最大限に使って`.well-known`を除外してみます。

```diff_yaml:ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: yuito-work
  labels:
    name: yuito-work
  annotations:
    # http01でACME認証するClusterIssuer
    cert-manager.io/cluster-issuer: le-http-prod
    nginx.ingress.kubernetes.io/ssl-redirect: "false"
    nginx.ingress.kubernetes.io/force-ssl-redirect: "false"
    nginx.ingress.kubernetes.io/from-to-www-redirect: "true"
+   nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
  ingressClassName: nginx
  rules:
  - host: www.yuito.work
    http:
      paths:
      - pathType: Prefix
+       path: /(?!\.well-known/.+)(.*)
-       path: /
        backend:
          service:
            name: yuito-work
            port: 
              number: 80
  tls:
    - hosts:
      - yuito.work
      - www.yuito.work
      secretName: yuito-work-tls
```

これで除外することができました。

## 現在は

そもそも、現在はCloudflareを通してClusterIssuerをCloudflareのdns-01にしているので今は使っていません。
Cloudflareの話に関しては以下をご覧ください。

https://qiita.com/yuito_it_/items/6813ccdb832fac00a6a4

## 最後に

これを治すのに2時間くらいぐるぐるしていたので、そういう方の助けになればなと思います。

ちなみに今回のサイトやマニュフェストファイルなどは、以下のものです。
よければアクセスしてみてください。

https://www.yuito-it.jp

https://github.com/yuito-it/yuito.work
【PHP】不正にファイルがアクセスされる？ディレクトリトラバーサル攻撃に注意せよ

# ディレクトリトラバーサル攻撃とは (Directory Traversal)
ファイルのパスを操作して通常ルートではアクセスできないファイルへアクセスをする攻撃のこと。

# 例として入力情報をそのまま利用

文章じゃわからないと思うので極端な例だが、以下のコードだとどうだろうか？

```php
<?php
echo file_get_contents($_GET['filename']);
?>

<input type="text" name="filename" />
```

このコードはクライアント側(ブラウザ)からファイル名を入力してサーバー上にあるファイルを読み込んで中身を表示するだけの処理をするものだ。

しかし、絶対パスや相対パスなども入力される可能性はないだろうか？

## 考えられる危険性

例えば、以下のようにサーバー上にそのままユーザー情報が入っているとする。
`data/` は `.htaccess` で守られているとして

- data/
    - userlist.txt
- .htaccess
- txt/
    - aaa.txt
    - bbb.txt
- index.php

そしてコードは以下のようなものとする

```index.php
<?php
echo file_get_contents($_GET['id'] . '.txt');
?>

<input type="text" name="id" />
```

aaa、bbbと入力してaaaやbbbのテキストファイルを取得するだけならいいが、
もし、`../.htaccess` や `../data/userlist` と入力されるとfile_get_contents('../data/userlist.txt') として実行され、表示されてしまうかもしれない。

`../.htaccess` に関しては.txtが末尾に付くので問題ないが、その末尾に拡張子を付けるのもなければそれも見られてしまう可能性がある。
そしてhtaccessが見られると権限設定からファイル構造などもバレてしまう可能性もある。

# だからbasename() を使おう！

[basename - PHP マニュアル](https://www.php.net/manual/ja/function.basename.php) によると
> basename - パスの最後にある名前の部分を返す

つまり、ファイル名のみを取得できる。
例えば `basename('aaa/bbb/hoge.txt')` ならば `hoge.txt` となる。

先ほどのコードを以下のように修正するだけで対策できるのである。
```php
<?php
echo file_get_contents(basename($_GET['id']) . '.txt');
?>

<input type="text" name="id" />
```

# さいごに
こんなこと言っときながら、やらかしてるのは自分なんです。攻撃は受けていないんですが、よく考えたら、file_get_contentsってまずくないかって急に思ったんですよ。

ウィキのレンタルサービスを開発していて一時的にユーザー名とパスワードを保存しているテキストファイルがあったんですね。そしてそのファイルはユーザー名で保存していまして。
つまり、この記事で紹介した通りの攻撃される可能性もゼロではないかなと思い、試したところできちゃいました。

そしてパスワードは今ではハッシュで保存しているのですが、昔はそのままの状態で保存していたので大問題でしたね。開発者は私一人だけでしたのでまだよかったんでしょうけど。パスワードもハッシュで保存しておけば運営側も悪用できませんし、パスワード設定した本人しか知ることができないのでハッシュ化しましょう。
Python における例外処理 まとめ

# はじめに
本記事では Python の例外処理についてまとめています。

**例外処理**は、プログラムの**実行中に**予期せぬエラーが発生した場合に、プログラムを正常に終了させたり、適切な処理を行うための仕組みです。これにより、プログラムの安定性と信頼性を高めることができます。

# 例外の種類
Pythonでは、様々な種類の例外が定義されています。

- `ZeroDivisionError`: ゼロで除算しようとした場合に発生
- `NameError`: 未定義の変数や関数を参照しようとした場合に発生
- `TypeError`: オブジェクトの型が間違っている場合に発生
- `KeyError`: 辞書型でキーが存在しない場合に発生
- `FileNotFoundError`: ファイルが存在しない場合に発生

https://docs.python.org/ja/3/library/exceptions.html


# 例外処理の基礎
Pythonでは、`try-except` ブロックを用いて例外処理を行います。

```python
try:
    # エラーが発生する可能性のあるコード
    x = 10 / 0
except ZeroDivisionError:
    # ZeroDivisionError 発生時の処理
    x = 0
```
- **`try` ブロック**
   エラーが発生する可能性のあるコードを記述。
- **`except` ブロック**
   特定のエラーが発生した場合に実行されるコードを記述。

# finally ブロック
必ず実行したい処理がある場合は、`finally` ブロックを使用します。

```python
try:
    f = open("my_file.txt", "r")
    data = f.read()
    # データの処理
except FileNotFoundError:
    print("ファイルが見つかりません")
finally:
    f.close()
    print("ファイルを閉じました")
```
# else ブロック
`try` ブロック内のコードが例外なしに正常に実行された場合にのみ実行されるブロックです。

```python
try:
    # 例外が発生する可能性のあるコード
    result = 10 / 2
except ZeroDivisionError:
    print("ゼロで除算することはできません")
else:
    print("計算結果は:", result)
```
# 複数の例外処理
複数の例外に対応するためには、複数の `except` 句を使います。

```python
try:
    x = 10 / 0
except ZeroDivisionError:
    x = 0
except TypeError:
    x = 10
```


# 入れ子状の try-except ブロック

入れ子構造により、それぞれのレベルで別々の例外を処理できます。

```python
import requests

def get_webpage_data(url):
    try:
        response = requests.get(url)
        response.raise_for_status()  # ステータスコードが異常な場合に例外を発生させる

        try:
            # 取得したHTMLを解析する処理
            # ...
        except ValueError:
            print("HTMLの解析中にエラーが発生しました")
    except requests.exceptions.RequestException as e:
        print(f"リクエスト中にエラーが発生しました: {e}")
```

# 例外の再投げ

例外を抜け消すのではなく、最上レベルに再投げする場合に使用します。

```python
try:
    try:
        result = 1 / 0
    except ZeroDivisionError as e:
        print("内部で例外を処理")
        raise  # 再投げ
except Exception as e:
    print(f"グローバルな例外処理: {e}")
```

# エラー情報を収集する方法
例外発生時に詳細なエラー情報を取得するには、以下の方法を使用できます。

**`except` 句で変数を使用**
```python
try:
    result = 1 / 0
except Exception as e:
    print(f"エラータイプ: {type(e).__name__}, 詳細: {e}")
```

**`sys.exc_info()` を使用**
```python
import sys

try:
    result = 1 / 0
except:
    exc_type, exc_obj, exc_traceback = sys.exc_info()
    print(f"エラータイプ: {exc_type.__name__}, 詳細: {exc_obj}")
```

**traceback モジュールを使用**
```python
import traceback

try:
    result = 1 / 0
except Exception as e:
    print("\n".join(traceback.format_exception(None, e, e.__traceback__)))
```
micro:bit V2用MicroPythonの録音機能を試す

2023年10月30日の[v2.1.2](https://github.com/microbit-foundation/micropython-microbit-v2/releases/tag/v2.1.2)以来、リリースのなかった micro:bit 用 MicroPython であったが、ひさびさに github を覗いてみたら [audio-recording](https://github.com/microbit-foundation/micropython-microbit-v2/tree/audio-recording)なんてブランチがあって、「お、マイクから録音できるようになった？」ということで試してみました。

# インストール

正式リリースされていないので、当然ソースコードからのビルドが必要となる。arm-none-eabi-gccのツールチェーンはセットアップしておこう。

その上で、以下を実施。

```bash
$ git clone -b audio-recording https://github.com/microbit-foundation/micropython-microbit-v2.git
$ git submodule update --init
$ make -C lib/micropython/mpy-cross
$ cd src
$ make
```

MICROBIT.hex ができあがるので、micto:bit V2 を USB に繋いでマウントされるストレージにコピーするとインストール完了。

# サンプルを動かしてみる

test_recoed.py というサンプルがあるので、MicroPython のファイルシステムに main.py にコピーする。私はいつもながら mpremote を利用。

```bash
$ mpremote cp test_recoed.py :main.py
```

リセットしたら、録音スクリプトのスタート。

Aボタンを押しながら内蔵マイクに向かって話す。Aボタンを話したら録音終了。Bボタンを押すと内蔵スピーカで再生される。音はけっこうひどいが、話したように聞こえないこともない。外付けのスピーカーを使えば少しは音が良くなる。

# API

まだドキュメントがないので調べてみる。

## 録音

### audio.AudioRecording クラス

録音データ格納用のバッファらしい。コンストラクタの引数は durationとrate。

### microphone.record_into() 関数

録音する。引数は buffer (AudioRecordingオブジェクト)とwait (録音終了を待つか。デフォルト True。Trueのときはどうやって録音止めるのだ？　バッファ尽きるまで？)。

録音結果を返す。

### microphine.is_recording() 関数

録音中なら True を返す。

### microphone.stop() 関数

録音を終了

### audio.play() 関数

引数は必須の source が 録音結果(microphone.record_into() の戻り値)、wait (再生終了を待つか。デフォルトはTrue)、pin (音の出力先。デフォルトは内蔵スピーカー)、return_pin (使い方不明)。

## audio.sound_level()

再生音のレベルを返す。サンプルではこの値で口の動きのアニメーションを動かしていた。
【ChatGPT・初心者】体験レポ Vol.2

こんにちは。東です。
ChatGPTに触れる機会があったのでそちらのレポを複数回に
渡って投稿したいと思います。
基本、遊ぶように使うので「真面目な記事が欲しいよ！」
という方には何か違うかもしれません。ご了承ください！

[第1回目はこちら！](https://qiita.com/pesysyon/items/47a67baf0001b63aade3)
良ければご覧ください

# 創作活動の支援
前回ChatGPTに何ができるか聞いたところ
>__創作活動__: 詩やイラストのアイデア、物語のプロットなどの創作を支援します。

とあったのが面白そうだったのでいくつか試してみました。

### 詩を作ることができる？
詩のアイデアを支援しますとあったので、何ができるか聞いてみました。
結構色々なことができるみたいです。

>1.テーマやキーワードを提案します
自然、愛、孤独などテーマやキーワードを考えます。
2.詩の形式や構成案を提案します
俳句、短歌、自由詩など形式や構成案を提案します。
3.表現や語彙選びをサポートします
比喩や語彙を工夫し、リズムや音の美しさを高めます。
4.詩の草案作成やアイデアのブレストを行います
草案を一緒に作成し、方向性を模索します。
5.完成した詩のレビューや改善案を提供します
完成した詩にフィードバックを行い、改善点を提案します。

あくまでも支援という題なので、無理かと思いましたが
ダメもとで詩を作ってもらいました。

__テーマは「猫」と「夢」、形式は「俳句」で詩を作成してください。__

その結果
>影揺れて
夢路をたどる
月の猫

生成してくれましたね！GPTおしゃれです...

テーマはそのままに今度は”短歌”形式にしてもらいました。
>月影に
たゆたう猫の
足音よ
夢のほとりに
静かに響け

なんかカッコイイですね。
調べたところもちろんそんな詩はなかったのでChatGPTのオリジナルでした。

<img width="200" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3780649/9a9620b1-b191-3ff2-1758-9754c253d01a.png"> 猫はGPTもすき。

### 物語を作ることもできるのか？
続いて面白そうだったのは、物語を作ることができるとの機能。
今回もGPTが物語について何ができるか聞いてみました。

>1.ストーリーの骨組みを考える
テーマやジャンルを決め、構造を組み立て、キャラクターの関係性や背景を考えます。
2.キャラクター設定を深める
性格や動機を練り、ドラマや対立を具体化し、ユニークな設定を提案します。
3.舞台設定を考える
世界観や社会のルール、文化、地理などを構築し、詳細な描写を考えます。
4.プロットを展開する
シーンの展開、伏線、ツイスト、重要イベントのアイデアを提案します。
5.インスピレーションの提供
キーワードやランダムな組み合わせで新しいアイデアを生み出します。
6.テキストのアドバイス
テキストのフィードバックや文体、ストーリー改善案を提案します。
7.課題解決のサポート
ジャンルに応じたアイデアを深掘りし、詰まりの解消を手伝います。

詩も生成できたのだから、物語なんて楽勝でしょう。
さっきの詩のテーマと同じ「夢」と「猫」でやってみました。

__テーマは「猫」と「夢」で物語を作成してください。__

>__タイトル: 「夢見る猫の物語」__
あらすじ:
主人公は小さな町に住む孤独な青年・翔（しょう）。ある日、彼は不思議な黒猫「ルナ」と出会う。その猫はただの猫ではなく、人の夢の中に入り込む能力を持っていた。翔はルナに導かれ、自分の夢の中で見知らぬ風景や、不思議な出来事に遭遇する。そこには彼が忘れていた過去や、本当は叶えたかった夢が潜んでいた。
ルナと共に夢の世界を旅するうち、翔は次第に現実で自分が抱えている孤独や後悔と向き合うようになる。しかし、夢の世界には「夢喰い」と呼ばれる存在が現れ、翔の夢を飲み込もうとする。翔は現実と夢の境目が曖昧になる中で、ルナの正体と夢喰いの目的を知る。最後に彼が選ぶのは、夢の中で生きるのか、それとも現実を変える勇気を持つことか。
登場キャラクター:
翔（しょう）: 内気で夢を追う勇気を失った青年。
ルナ: 謎の黒猫。夢の中で翔を導く。
夢喰い: 人の夢を糧とする不気味な存在。翔の夢を奪おうとする。
舞台:現実の小さな町: 静かで平凡だが、どこか寂しげな雰囲気。
夢の世界: 翔の記憶や願望が形となった幻想的な場所。時に美しく、時に不気味。
主なテーマ:自分の本当の夢を見つけること。
過去と向き合い、未来への一歩を踏み出す勇気。
猫の持つ神秘性と、夢の中の冒険の融合。

何か波瀾がありつつも、素敵な物語を作ってくれました。
プロットをこうして作ってもらえると作家の人たちはスランプのときに
何か突破口になってくれるかもしれないですね。
本でも書いてみたくなりました。

<img width="200" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3780649/8262389c-d2b7-8296-d055-990b688c5d2f.png"> 私にそんな習慣はなかった..

# まとめ
今回は生成AIの所以たる機能を試させてもらいました。
結構アイデアにまつわることがこうも自然と作成できるなんて、
恐ろしくも面白いですね。
次回は画像なども生成してみたいと思います。
HTML 上の SVG をダウンロードして PNG に変換する

# やりたいこと

今日 (2024/12/25 (水))、PC 版の X (https://x.com/home) を開くと、ページの左上に謎のだるまがいました。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6697/6041ea7d-dbfe-a5a1-74aa-e11022466b0e.png" alt="謎のだるまがいる" width=400>

これは SVG のようです。可愛いのでこの SVG をダウンロードして PNG に変換したいです。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6697/7438a27d-398f-cf51-e5df-b2ac83012240.png" alt="謎のだるまは SVG" width=400>

# 方法

## 前提

- Google Chome などのブラウザの開発者ツールで任意の JavaScript を実行できること。
- [qlmanage](https://ss64.com/mac/qlmanage.html) コマンドが利用できること。
  - macOS にデフォルトで用意されています。

## SVG のダウンロード

開発者ツールのコンソールで以下のコードを実行します。該当の SVG の XML 文字列をファイルとしてダウンロードするための擬似的なアンカー要素を作り、それをクリックするコードです。

```js
const downloadSVG = ({ selector, filename }) => {
  const svg = document.querySelector(selector);
  svg.setAttribute('xmlns', 'http://www.w3.org/2000/svg');

  const blob = new Blob([svg.outerHTML]);

  const a = document.createElement('a');
  a.download = filename;
  a.href = window.URL.createObjectURL(blob);
  a.click();
  a.remove();
};

// selector の "r-4qtqp9" は可変なので、実際のクラス属性の値に置き換えること。
downloadSVG({ selector: 'header svg.r-4qtqp9', filename: 'x.svg' });
```

## SVG を PNG に変換

以下のコマンドを実行すると `~/Downloads/x.svg.png` に長辺が 1024px の PNG ファイルが生成されます。

```shell-session
$ qlmanage -t -s 1024 -o ~/Downloads/ ~/Downloads/x.svg
```

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6697/a3aaa47d-6a90-6986-5e14-4eef50057131.png" alt="x.svg.png" width=400>

# 参考

- [SVGの属性について理解する #SVG - Qiita](https://qiita.com/mt877/items/182061c78b9c86941823)
  - SVG を外部ファイルとして使用する場合は xmlns 属性が必須でした。
  - この属性を指定しないと PNG ファイルが真っ白になってしまいます。
- [【Mac】SVGからPNGへの変換を高画質で無料で行う方法 #Mac - Qiita](https://qiita.com/c_tomioka/items/8784a2c533137e712b5c)
  - qlmanage コマンドについて調べました。
個人でAWSを使用する時の最低限のセキュリティのメモ

#### 1.IAMユーザーを作成してMFAを設定
rootユーザーは使わない。
MFAはauthorizaerなどを使えばOK。
#### 2.AWS CloudTrailを有効化
APIアクセスに餡するログサービス。
CloudTrailから「証跡の作成」ボタンを作成後、それを保存するS3バケットを作成。
#### AWS Configを有効化
リソースの変更履歴を管理するサービス。
デフォルトで良いなら、1-Clickセットアップを、細かく設定したいなら今すぐ始めるをクリック。
#### Amazon GuardDutyを有効化
AWS上の様々な脅威を検知するサービス。（アクセスキーの漏洩事故、コインマイニングの検知、など）
「今すぐはじめる」→「GuardDutyを有効にする」をクリック。

さらにAmazon SNSによる通知も有効化させておきます。
SNSのページを開いて「トピックの作成」をクリック。
guard-duty-email-topicという名でスタンダードタイプ、他デフォルトで作成。
サブスクリプションではプロトコルをEmail、エンドポイントにメアドを指定。
プロトコルをEmailにした場合、受信許可のメールが該当アドレスに届きます。
この時gmail指定した場合、迷惑メールに入っているので注意。

続いてAmazon EventBridgeの設定。
ルールタイプはイベントパターンを持つルール、イベントソースはAWSイベントを選択、作成メソッドはパターンフォームを使用、イベントパターンとしてAWSのサービス、GuardDuty、GuardDuty Findingを指定、必要に応じて、パターンの編集で詳細を編集していきます。
このままだと全部通知きてうるさいので、一旦下記のように設定。
```
{
  "source": ["aws.guardduty"],
  "detail-type": ["GuardDuty Finding"],
  "detail": {
    "severity": [{
      "numeric": [">=", 4]
    }]
  }
}
```

あとはGuard Dutyの設定で「検出結果サンプルの生成」をクリックして、実際にメールが来ればOK。
【PHPカンファレンス2024参加レポート】PHPerのための計算量入門

## 概要
```
計算量とは、アルゴリズムが問題を解くために必要とするリソース、特に時間やメモリの量を指します。プログラムはただ動けばいいだけではありません。膨大なデータを扱う現代において、計算量はアルゴリズムのパフォーマンスを左右する重要な要素です。皆さんのコードはどれだけ効率的ですか？計算量の基本から、時間計算量や空間計算量の理解を深めることで、あなたのプログラミングスキルを次のレベルに引き上げましょう！

本トークで話す内容

計算量とはなにか？
時間計算量、空間計算量
実装時に意識すること
```
https://fortee.jp/phpcon-2024/proposal/ec0aee68-5c85-4c64-8582-d1263fecba22

## 所感
ただただ聴き入ってしまった、計算量のお話。

基調講演でPHPのコアな部分の話が聞けてテンション上がった！って言ったんですが、
これまたコア〜なお話で、個人的には非常に興味深かったです。

処理の重さや効率は意識してコードを書いているつもりですが、
その実態までは考えられてなかった事に気付かされました。

PHP書き始めて約8年、独学でここまでやってきたので、本当、寝耳に水というか、
ここで聞けてよかった。

実際ループの処理なんかは計算量が増える、というのは直感的にわかりやすいですが、
それらが実際どのように計算処理されているのか。

opcodeの存在も初めて知り、これは実際に見てみたいと思いました。

開発系の多くのセッションは、心構えや意識、手法なんかを説いていくものが多く直接的な開発スキルに影響するような内容って、少ないと個人的には思っているのですが、
この話は開発スキルにダイレクトに影響を与える、学びある話でした。

エンジニアレベルがいくらか上がった気がしております。


## スライド
https://speakerdeck.com/hanhan1978/complexity101-for-phper

## 受講メモ
```
## 計算量とは？
PHPコードは配列opCodeに変換され実行される

オーダー記法（O記法）
計算量の目安を表す便利な記法
for文の場合、回数に応じて計算量は線形に増える→o(n)
単一処理の場合、1回だけの計算→o(1)

時間計算量
	計算の回数
空間計算量
	メモリ使用量


計算量オーダーを下げる
in_arrayはo(n)関数、
array_key_existsはo(1)関数


データ量が少なければ特に差はない。
なんでも計算量を下げる必要はない

配列関数はPHPの中でも便利な関数
O記法で考える時に何に分類されるかを確認しておく
　Laravel コレクションも。

複雑な要件を放置しない
ビジネスロジックも込みで考える
```
【PHPカンファレンス2024参加レポート】20年続くレガシープロダクトに10年携わったエンジニアが思う、システム長期運用のカギ

## 概要
```
結婚準備クチコミ情報サイト「Wedding Park」は今年でクチコミサービス開始から20周年を迎えたウェブサイト。
このレガシープロダクトでは、幾度もPHPで動くシステムのバージョンアップやシステムリプレイスのプロジェクトが生まれてきました。

・PHPのバージョンアップ
・Laravelフレームワークへのリプレイス
・オンプレサーバからAWSへの移行
・コンテナ化　など

システム運用者として定期的にアップデートしていきたい想いと、長期にわたる大規模プロジェクトとなり頻度高く実施ができない。そんな悩みとぶつかっていました。

その歴史の中で約10年、アプリケーションエンジニアとSRE、各視点で向き合って運用・開発してきた経験を基に、

・これまでのシステム改善の変遷と知見
・運用と開発視点でのプロダクトとの向き合い方
・新たな価値を継続的に提供し続けるための長期計画
をご紹介します。
```
https://fortee.jp/phpcon-2024/proposal/63791fa7-feed-49bf-91e7-f6823fbb40dc

## 所感
サービスを開発、運用保守をしている身としては、サービスには長く続いて欲しい。
我が子が、活躍する姿を長く見ていたいですよね。

ネックになる運用保守。バージョンアップ、セキュリティアップデートは、絶対についてまわるもの。
そういう面において、やはり実際の経験談というのは、とても参考になります。

印象に残った言葉として、「再現性のある開発体制」、というのがあるのですが、本当、わかりみが深いです。

自分たちのプロダクトでも最近、コンテナ化しk8sで管理した事が運用保守面においてメリットデカかったね、という話をしたのですが、本当、先のことを考えた柔軟で再現性のある開発。

難しいですけど、とても重要ですね。

## スライド
https://speakerdeck.com/azumen/20nian-sok-kuregasipurodakutoni10nian-xi-watutaenziniagasi-u-sisutemuchang-qi-yun-yong-nokagi

## 受講メモ
```
## 大規模リプレイス
### 課題
システムの老朽化　5年経過
つかわているか不明瞭な機能
仕様に明るい人が少ない
当時の事業拡大を支える開発基盤を目指したい

### 実施内容
php5 -> 7、zend frameworl1 -> Laravel
機能整理と断捨離
共通モジュール導入で服機能の再利用性向上
APIのPHP->goリプレイス
APIドキュメントの作成やテストコードの作成

## AWS移行
### 課題
オンプレサーバー運用）
　複数のアプリが相乗り
	サーバー構築工数が大きい
システム料休暇
→単一障害点

### 解決
AWS移行

## コンテナ化
アプリケーションの肥大化
アップデートの手間
サーバー設定依存のアプリ
サーバー構築の手間

### 解決
コンテナ化
IaCの実現


## これまでの経験を経て
構成変更をはじめはしぃシステム構成になった

高頻度なアップデートができない
毎回長期プロジェクトになる

再現性のある開発体制
年月を経て、人員構成は変わっていく
ノウハウの継承
俗人化を回避する
```
【PHPカンファレンス2024参加レポート】終了の危機にあった15年続くWebサービスを全力で存続させる〜Twilog・Togetter統合の舞台裏〜

## 概要
```
2023年5月、Twitter（現X）が提供するAPIが突如として有料化し、2009年から個人により運営されてきたTwilogがサービスの終了を発表しました。
そこに手を差し伸べる1つの企業がありました。そう、Twitter関連企業のTogetterです。

華麗な買収エピソードの裏側で、Twilogの統合プロジェクトがスタートします。

RubyからPHPへのフルスクラッチでのコード移行
15年間貯め続けたテラバイト級のDBの移管作業
コストを抑えてAWS環境へ移管するための試行錯誤
などなど、1年間に及んだ移行作業の全容についてお話しします。
```
https://fortee.jp/phpcon-2024/proposal/6e4865d8-6876-414e-b7df-b4ecb76b2e05

## 所感
多分、この界隈で知らない人はいないと思うサービス、TogetterとTwilog。
twitterがXになり、APIの利用事情が大きく変わった事で、クリティカルに影響を受けた両サービスが統合する事になり、その際の舞台裏を、赤裸々にお話いただきました。

時間にすると45分ぐらいのセッションですが、非常に濃い内容で、とても面白かったです。

中々普段、TB級のデータを移行させる事なんかないですし、
理路整然としたデータならまだしも、個人開発スタートであるが故にその整理も含めて行う必要があった、
沢山の苦労、苦悩。沢山の意思決定。

それらを経て、無事統合しサービスが継続されている両サービスには、本当に拍手を送りたい。

詳細は公開されているスライドをぜひ読んでほしいのですが、
データ移行、システム統合するにあたって様々な試みが行われた事、そのトライ＆エラーに、エンジニアのプライドを感じました。尊敬。

また、スピーカーの方とは懇親会でもお話する事ができ、さらに突っ込んだ事も聞けて、それも含めて面白かった、個人的には今回のベストセッションかもです。


## スライド
https://speakerdeck.com/yositosi/zhong-liao-nowei-ji-niatuta15nian-sok-kuwebsabisuwoquan-li-decun-sok-saseru-phpcon2024

## 受講メモ
```
Twitter　APIが有料化→月600万

ドメインの統合
twlogではAPIが停止。ログイン機能を復旧し、twggterドメインに。

アプリケーションの統合
同スペックをAWSに構築すると高コストになる。

めもりーさんにコード移行を依頼
Togetterのコードは把握済み
rubyからPHPへ
twlogには仕様書もテストもない。あるのはコードだけ
rubyを知らなかっためもりーさん。
２ヶ月で予定通り移行完了

AWSとさくら間でのmysql接続は失敗
検証までは良かったが、デプロイ後に処理が詰まってダウン

F2、DBをAWSへ移行
TB級のデータ移行
sqldump、mysqldump
データ生成、転送、復元
EC２スペックを一時的にとにかくあげる
途中失敗するとやり直し
工程の自動化、途中から再開できる工夫、ロギング

１５年間のうち1日だけ欠損していてやり直し。。。


ストレージコスト増大に対する対策
案１：S3にログデータをテキストとして保存し、S3 Selectを使って全文検索を実現
案２：SqLite。１ユーザー１SQLiteをS3に保存し、運用
→案２

100万ツイートあるようなユーザーのツイート検索でエラー

SQLliteをマスターに、サーバーローカルにmysql Myisamを構築運用
→ん？戻ってない・・？

Twitter API v1.1が終了するアナウンスがあり、デプロイせざるを得ない状況に

SQLliteの廃止
ChaceのMysqlがうまく動いているので、マスターに昇格させる
WriteとReaderの２台構成

事前の負荷テスト
nginxのリクエストをミラーリングして新環境にも流してみることで検証

現在月10万程度のコストで構成

S3 Selectでのコスト試算で数百万
```
【PHPカンファレンス2024参加レポート】ALBと外部IDプロバイダーで認証しつつ、LaravelではGate・Pollicyを使わずシンプルにアクセス制御する方法

## 概要
```
Laravelにおいて認証・認可はGate・Policyの仕組みに沿えばイージーに実装が可能です。
しかし、OktaやMicrosoft Entra IDといった外部IDプロパイダーを使用し、認証自体はWebアプリケーションに到達する前に行いたい場合もあります。

このトークでは、AWS ALBと外部IDプロバイダーを使用しOIDCで認証を行いつつ、LaravelではCasbinという複数言語をサポートしているアクセス制御するための認可ライブラリを使ったRBACの実装例を紹介します。
また、ALBの誤った設定によるALBeastと呼ばれる脆弱性についても触れます。
```
https://fortee.jp/phpcon-2024/proposal/a416eb40-9fe3-44ba-a287-f07c4ac9afde

## 所感
認証認可を外部に任せる、という点で似た状況にあったので、
技術面・手法として参考になりました。

開発って、コードを書いてプログラム組んでシステムにして・・・、
っていう作業なわけですが、既に存在するサービスやライブラリを利用する事で、書かなくてもいいコードも沢山あるわけで。

今はそういう、何と何をどう組み合わせればシステムを作れるか、という観点でエンジニアをするのも、とても大事になりましたね。

これは非常にいい例なのではないかな、と思います。

## スライド
https://speakerdeck.com/ryosukes/albtowai-bu-idpurobaidaderen-zheng-situtu-laraveldehagatepolicywoshi-wazusinpuruni-akusesuzhi-yu-surufang-fa

## 受講メモ
```
## 管理画面のアクセス制限
basci認証
Oauth

アプリレベル
アプリ前段
ネットワークレベル

サービス規模
組織やチームの状況
求められるセキュリティレベル


## 外部IDPとcasbin
ユーザー管理を一括管理
認証をAppの外に出せるので責務が減る
Laravelを使わない他でも応用可能

デメリット
Laravelで完結しない


## ALBとIdPの設定

OIDC準拠のIdPであれば簡単
ALBルールアクション定義に必要な情報を入れるだけ
ALB自体がIdPにリクエストできるようにセキュリティグループの考慮

## 設定の管理
ALB、SCGはTerraform管理

## ALBeastを避ける
設定、検証漏れによる脆弱性
JWTの署名の検証、sigerフィールドに含まれるALBのarnを検証
Appは特定のALBに限定通信

## 注意
Google認証は、gmail.comを含め任意のアカウントを通してしまう
```
【PHPカンファレンス2024参加レポート】良いテストコードを書くためのガイドライン〜作成から運用まで〜

## 概要
```
テストコードはプロダクトの持続可能な成長には不可欠で、私の所属する開発チームでは書くことが必須となっています。
しかし、書き方が人によって異なり、テストケースに過不足があったり、実装の仕方やレビューで悩んだりすることがありました。
そこで、テストコードの書き方のガイドラインを策定しました。現在では開発チーム全体で運用され、一定の効果を発揮しています。

本トークでは、このガイドラインの内容をもとに、テストコードを書くうえで最低限気をつけたいことについてお話します。
また、チーム全体で運用するための、策定のポイントについてもお話しする予定です。

テストコードの書き方を知りたい人はもちろん、テストコードレビューで悩んでいる人、チームで統一したコーディングルールを運用したい人にとって有益なものとなれば嬉しいです！
```
https://fortee.jp/phpcon-2024/proposal/7edc5567-d741-4d6a-bfa7-732afb7dd311

## 所感
テストコードに関しては、もちろん書いてはいるものの、チームとしてはまだまだ経験が足りず課題を感じていたポイントだったので、非常に参考になる話でした。

しかもちょうど、テストコードの構成について試行錯誤した後だったので、自分事として聞けました。

特に共感したのは、
> 作って終わりにしてはいけない

本当にその通りだと思うし、なんならそれを定着させる部分が1番、力がいりますよね・・・。

今後のテストコード運用において、とても参考になるお話でした。

## スライド
https://speakerdeck.com/riku929hr/tesutokodonogaidorain-zuo-cheng-karayun-yong-made

## 受講メモ
```
何を検証したいかぱっと見でわからないテストコード
リファクタしたらテストが落ちた

ガイドラインあればいいんじゃない？

書籍から学んだテストの基本

なぜ実施する？
安全にリリースできる状態を継続的に維持する

バグを正しく検出できる
自信を持ってコード変更できる
実装の詳細ではなく振る舞いをテストする

振る舞いをテストする
実装の詳細
　処理の具体的ななk毎
振る舞い
	最終的な出力、返される結果

実装の詳細
モックを利用したテスト

実装の詳細を公開するとテストしづらい
振る舞いだけを公開する

モックの利用は最小限に


何をどうテストすればいいか

どこにどんなテストを書けばいいかわからに

ちょっとしたことで可読性は向上する
テストケース名
適切なアサーション
assertSameで大体できるか、continなど糸に合ったものを使う方が可読性がいい


ガイドライン
具体的な行動に結びつける
厳しくしすぎない

Redux style guideを参考に
項目ごとにpriorityがついている

ガイドラインではなくスタイルガイド
サンプルも用意

作って終わりにしてはいけない
```
【PHPカンファレンス2024参加レポート】オープニング〜基調講演

# PHPカンファレンス2024参加レポート
## まず初めに
2024年、12月22日。
東京蒲田で開催されたPHPカンファレンス2024に参加してきました。

前々から気になっていて、でも都合が合わず参加出来ていなかったPHPエンジニア、通称PHPerのための開発イベント。
PHPを書き始めて約8年。

とても楽しみにしていました。

普段は大阪、京都で仕事しているのですが、PHPカンファレンス関西には参加できなくて悔しい思いをしたので、一層ワクワクしていました。

日曜ですが、懇親会も参加したく、大阪から東京へ、
交通費・宿泊費、そして月曜日のリモート（結局半休取ったけど）を許可し快く送り出してくれた会社に感謝。

さて、ここからは参加レポートとして、
聴講したセッションや会場の様子などをお伝えしていければと思います。

*開催概要は下記を参照*

https://phpcon.php.gr.jp/2024/

## 基調講演 「PHPの今とこれから2024 」
基調講演は、タイトルの通り、PHPの今と未来のお話。
もしかしたら毎回なんですかね、初参加だったのでそこはわかりませんが、
個人的にはとてもワクワクしました。

普段、PHPを書いていて、PHPのバージョン情報やPHPが見ている先、なんかはほとんど意識する事がありません。
僕らの関心は、PHPを書く事で実装する機能であり、得られる結果であり、ビジネスへの貢献です。

だからこそ、今回ここでPHP自身の話を聞けたのは、新鮮さもあって非常にワクワクしました。
個人的には、開発モチベーションが一段上がった感覚。

よくよく考えてみれば、1プログラミング言語のカンファレンスが1000人規模で開催されているって、凄いなと。
PHPはOSSであり、それを保守し支えているエンジニア達がいる。

様々な経緯を経て、組織化されシステマチックに運営されている。

先ほども言いましたが、普段コードを書いている中では全く意識していない部分で、
バージョン情報として、追加機能や廃止情報を確認はすれど、それらをメンテし運営している背景までは、中々想像してきませんでした。
（もちろん存在そのものは認知し、理解していますが）

この日をもってそこの解像度がぐっと上がり、PHP言語がより身近に感じられるようになった気がします。
PHPのコアな部分を知れた事で、僕の中のエンジニア精神が、高まったのかなぁと思いました。

ともあれ、ここからカンファレンスがスタートします。
テンションを上げられた状態での、最高のスタートを切った、と思います。

### 基調講演メモ
```
## php
1995年に誕生したwebアプリケーション言語
webと共に成長、進化してきた。

サーバーサイド言語のシェアとしては75%

## phpの開発体制
phpはOSS
開発アカウントは2000名（15名）
コア150名（5名）
PHPGroup10名

### ニュース
コアを支える2名のエンジニア
　1名が離脱を宣言
個人おモチベに依存
SW維持の関心が低い

財団を設立
184の団体、企業が支援
個人1600名以上がサポート

主要なエンジニア6名をサポート

## バージョンシェア
- 7系49.2%
- 8系37.8%
- EOL（８系まで）７割

## リリースサイクル
サイクルが延長；4年バグ修正2年、セキュリティ2年、年末まで
php7,8はEOL。EOL以降は危険

## PHPエンジン
PHP 8 JIT　より早く快適に
php8系の中ではそこまでかわらない

## php8.4　機能強化改善ポイント
### JIT強化：IRフレームワーク導入

### プロパティアクセスフック
setter、getterをメソッドとして定義→簡略化

### 非対称プロパティ可視性
非対称な可視性を設定できる（publicで書き込みを制限）
readonlyよりも自由度が高い
制約を緩くすることはできない　protected publicは不可
継承時は可視性を狭くできない

### 遅延オブジェクト
Lazyオブジェクト：状態が参照または変更されるまで初期化を遅延
普通はインスタンス時に初期化
→遅延の場合は、インスタンス後、参照される時に初期化

### HTML5対応、DOM対応改善

### PDO：ドライバ固有のサブクラスを導入
DB固有の機能がPDOメソッドとして実装されていてわかりにくかった

### BCMath：オブジェクトAPI追加

### Deprecatedアノテーション追加
廃止対象となった関数・メソッド定数にアノテーション追加

### array_find関数追加
条件に一致する配列要素を見つける4種類の関数が追加

### php8.4で廃止予定項目
暗黙のnulll宣言
E_STRICT定数
GET/POSTによるsession伝搬→クッキーのみに


## FRANKEN PHP
Go＋Cで書かれたアプリケーションサーバー

```

## 受講セッションレポート
各レポートの所感は個人的な感想です。また、受講メモは荒いものあるため、参考程度に。
ほとんどのスピーカーの方がスライドを公開しているため、そちらも合わせてご確認ください。
（スペシャルサンクス！）
- [良いテストコードを書くためのガイドライン〜作成から運用まで〜](https://qiita.com/yukiMiyoshi_fcafe/items/dd6b156e91be31065034)
- [ALBと外部IDプロバイダーで認証しつつ、LaravelではGate・Pollicyを使わずシンプルにアクセス制御する方法](https://qiita.com/yukiMiyoshi_fcafe/items/ffd663727e77d23f92a7)
- [終了の危機にあった15年続くWebサービスを全力で存続させる〜Twilog・Togetter統合の舞台裏〜](https://qiita.com/yukiMiyoshi_fcafe/items/25173979affecac46757)
- [20年続くレガシープロダクトに10年携わったエンジニアが思う、システム長期運用のカギ](https://qiita.com/yukiMiyoshi_fcafe/items/6796108808f81cefcd1a)
- [PHPerのための計算量入門](https://qiita.com/yukiMiyoshi_fcafe/items/05b1f7b55f3f2428ee82)
非エンジニア（デザイナー）がワイヤーフレームを作成する前に必要だと思ったプロセスをまとめた記事

## 自己紹介
縁あってエンジニアの方と近い距離でお仕事をしています。

## 記事投稿の背景
エンジニアではないお仕事に携わっていますが、コーディングの基礎知識を習得したいと思っています。
コーディングをする前に必要なこととしてWebデザインが必要なのですが、更にはその前段階でワイヤーフレームを作る必要があります。が…ワイヤーフレームの作成をする前に大前提のところを整理する必要があり、自身の進捗・振り返りとして活用するためにも大枠を書いてみました。

:::note info
自身の学びのために記載しています。
細分化できる内容はありますので、その都度学んだことを更新していきたいと思っています。
:::

### 要件定義
- サイト制作の前に整理・準備
    - 制作の「背景」「目的」「目標」の共通認識を持つこと。プロジェクトに携わるメンバーが共通の認識を持たないと解決のためのアプローチも異なりそうです

### タスクの洗い出し
- 「いつまでに」「どのような状態」までに完成させるのか
    - スケジュール管理は必須ですね…

### 分析
- 「市場分析」「データ解析」
    - 目的・目標が定まったところで、市場を知るための情報収集
    - データ解析は既存サイトやベンチマークとなるサイトの解析を指しています

### コンセプト策定
- 「誰に」「何を」「どのように伝えるのか」「サイトに訪れたときのユーザー体験」
    - サイトへの入口と出口の体験がつながるようにすることがユーザー体験を提供するのか考えていくとよさそうだと思いました

### 情報の整理
- サイトマップ、コンテンツの整理
    - ユーザー体験や行動に紐づく形でサイトマップを作成します
    - 掲載したい情報をジャンル別に整理

### ワイヤーフレーム制作
- 具体的なページの設計図に入ります！

## サイト制作に必要なこと
ランディングページを完成させるまでの体験をしたいと思い、何となくワイヤーフレームからちょっと取り掛かってみようかなとしたのですが、ストーリー性がなく着地しないことに気づき、基本的なところから振り返りながら実施することにしました。ランディングページ1つ作るにしても、様々な工程がありそれぞれの役割を持った方々がいることで制作できるものだと思います。
サイト制作以外にも仕事を進めるうえで必要な基本的なことだと思いますので、日々の業務を反省・振り返りながら応用できるようにしたいと思います。
【TIPS】forの多重リスト処理

この記事は、[Elixir Advent Calendar 2024 シリーズ12](https://qiita.com/advent-calendar/2024/elixir) の24日目です

---

【本コラムは、15分で読め、5分で試せます】

[piacere](https://twitter.com/piacere_ex) です、ご覧いただいてありがとございます :bow:

@RyoWakabayashi さんの [配列から全順列の組み合わせを拾うコラム](https://qiita.com/RyoWakabayashi/items/1715ca5306b84616642b) で `for` による多重リスト処理と再帰の組み合わせテクニックがあったので解説します

# 基本

下記は、`[1, 3]` の要素を1つずつ出し、そこに `[2, 4]` の要素を1つずつ乗算するという、`for` による2重リスト処理の例です

```diff_elixir
iex> for x <- [1, 2], y <- [3, 4], do: x * y
[3, 4, 6, 8]
```

2重だけで無い多重リストも指定可能です

```diff_elixir
iex> for x <- [1, 2], y <- [3, 4], z <- [5, 6], do: x * y * z
[15, 18, 20, 24, 30, 36, 40, 48]
```

# 変動するリストの指定

固定リストだけで無く、動的に変動するリストの指定も可能です

```diff_elixir
iex> for x <- Enum.shuffle([1, 2]), y <- Enum.shuffle([3, 4]), do: x * y
[8, 6, 3, 4]
iex> for x <- Enum.shuffle([1, 2]), y <- Enum.shuffle([3, 4]), do: x * y
[6, 8, 4, 3]
iex> for x <- Enum.shuffle([1, 2]), y <- Enum.shuffle([3, 4]), do: x * y
[6, 8, 3, 4]
```

# 要素同士が重複しない組み合わせを作る

`for` の2重リスト目を、`y <- list -- [x]` と1重リスト目の要素を除外するように作ると、1重リスト目と2重リスト目で同じ要素が出ない組み合わせを生成できます

```diff_elixir
iex> list = [1, 2, 3]
iex> for x <- list, y <- Enum.map(list -- [x], & [&1]), do: [x | y]
[[1, 2], [1, 3], [2, 1], [2, 3], [3, 1], [3, 2]]
```

このように、各リストが影響し合う多重リスト処理も作れます

# 配列から全順列の組み合わせを拾うコラム

上記までの知識があれば、下記 @RyoWakabayashi さんの [配列から全順列の組み合わせを拾うコラム](https://qiita.com/RyoWakabayashi/items/1715ca5306b84616642b) も読みこなせるようになれます

こちらのコードは、再帰の中で、再帰を繰り返し元として呼ぶ `for` が、下記「＋」にあります

```diff_elixir
defmodule Permutations do
…
  def all(_, 0), do: [[]]
  def all([], _), do: []

  def all(list, n) do
    for x <- list,
        rest = list -- [x],
+       perm <- all(rest, n - 1),
      do: [x | perm]
  end
end
```

これを上記例と同じ書き方に改めると、こうなります

なお、削除した `rest = list -- [x]` のように、中間変数を定義し、多重リスト処理に利用できることも `for` の高度な仕様です

```diff_elixir
defmodule Permutations do
…
  def all(_, 0), do: [[]]
  def all([], _), do: []

  def all(list, n) do
    for x <- list,
+       perm <- all(list -- [x], n - 1),
      do: [x | perm]
  end
end
```

もっと同じような記述に改めると、より読みこなしやすくなるでしょう

```diff_elixir
defmodule Permutations do
…
  def all(_, 0), do: [[]]
  def all([], _), do: []

  def all(list, n) do
+   for x <- list, y <- all(list -- [x], n - 1), do: [x | y]
  end
end
```

# p.s.このコラムが、面白かったり、役に立ったら…

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155423/907a8695-4d83-1b5c-8052-d0ce52de5f66.png) にて、どうぞ応援よろしくお願いします :bow:
🌟 Exciting News: LPI Exams Are Now Published! 🌟

🌟 Exciting News: LPI Exams Are Now Published! 🌟
Are you ready to boost your Linux expertise and stand out in the tech industry? We’re thrilled to announce that Linux Professional Institute (LPI) exams are now available! Whether you're just starting your Linux journey or looking to advance your skills, these certifications are the perfect stepping stones to success.

Why Choose LPI Certifications?
🌐 Globally Recognized: Gain credentials that are respected worldwide.
💼 Career Advancement: Qualify for higher-paying roles in IT, DevOps, and system administration.
📚 Comprehensive Coverage: From fundamentals to advanced topics, LPI offers certifications tailored to all skill levels.
Available LPI Exams
🎯 Linux Essentials (010-160): Perfect for beginners to learn the basics of Linux.
🎯 LPIC-1 (101-500 & 102-500): Start your professional journey with essential Linux administration skills.
🎯 LPIC-2 (201-450 & 202-450): Advance your expertise with network management and system security.

Get Ready to Succeed!
We’ve published all the details you need:
✅ Exam Requirements
✅ Target Audience
✅ Exam Preparation Tips
✅ Benefits of Certification

🌟 Don’t wait—your Linux journey starts now! 🌟
Explore the exams and take the first step toward becoming a Linux pro!

#Linux #Professional #Institute, #LPI #Certification, #Linux ECareer, Linux Essentials, #LPIC1, #LPIC2, #awslagi

https://awslagi.com/course-category/lpi/
可変長引数(＊引数名)

>個数に制限のない引数のことを可変長引数と言います。自分で定義するメソッドで可変長引数を使いたい場合は、引数名の手前に`*`をつけます

```rb
def メソッド名(引数1, 引数2, *可変長引数)
    # メソッドの処理
end
```
>可変長引数は配信として受け取ることができます。例えば次は引数として渡された人名の全員に挨拶をするメソッドです（コードで使われているjoinメソッドは、引数の区切り文字を使って配列を一つの文字列にするメソッドです）。

https://gihyo.jp/book/2017/978-4-7741-9397-7

```rb
irb(main):005* def greeitng(*names)
irb(main):006*   "#{names.join("と")},こんにちは"
irb(main):007> end
=> :greeitng
irb(main):008> greeitng("田中さん")
=> "田中さん,こんにちは"
irb(main):009> greeitng("田中さん", "鈴木さん", "佐藤さん")
=> "田中さんと鈴木さんと佐藤さん,こんにちは"
```
AWS CLIでS3操作をする際にregion周りで引っかかったこと

こんにちは、サーバエンジニアの池脇です。
今回はS3をAWS CLIを使って操作する際に引っかかったことについてご紹介します。

## AWS CLIとは
**AWS CLI(AWS Command Line Interface)** とは、AWSサービスをコマンドラインから操作・管理するためのツールです。コマンドライン操作を利用してAWSで行う複数の作業の自動化し、作業効率を上げることが可能となります。
詳しい内容は以下のリンクをご覧ください。

https://aws.amazon.com/jp/cli/

またAWS CLIには **v1** と **v2** が存在します。最近はほとんどなくなっているとは思いますが、古い記事を参照するとv1の可能性があるので新しい記事を参照するようにしましょう。

## どんな問題が起きたのか
今携わっているプロジェクトでAWS CLIを利用して複数リージョンにあるS3バケットに対して共通の操作を行なうのですが、とあるバケットへのアクセス時に以下のエラーが発生しました。
```
An error occurred (IllegalLocationConstraintException) when calling the ListObjectsV2 operation: The af-south-1 location constraint is incompatible for the region specific endpoint this request was sent to.
```
`IllegalLocationConstraintException`はリージョンの指定がされていないという内容のエラーです。すなわち`--region af-south-1`をオプションとして設定することでエラーを解消することができます。

しかし問題は複数リージョンに対して同じ操作をしている中、なぜ`af-south-1`でのみこのエラーが発生したのかということです。

弊プロジェクトでは

1. `aws s3 ls`でバケット一覧を取得
1. grepで絞り込みを行い、操作を行うバケットのみ抽出
1. 各バケットに共通の操作を行う

という流れで作業を行なっています。
今回はこの3番目の作業時にエラーが発生していました。

いろいろと検証を進めた結果、原因は **デフォルトで有効なリージョンでない場合、バケットを指定してS3の操作を行う際にリージョンの指定が必要になる** というものでした。

:::note
こちらの原因ついては公式の資料を見つけられなかったため、あくまで検証結果からの推測となります。
詳しい情報について知っている方いらっしゃればコメントいただければと思います。
:::

そのため手動で有効化した`af-south-1`でのみエラーが発生したようです。


## どう対応したのか
AWS CLIでのS3操作の際、デフォルトで有効なリージョンではリージョン指定の省略が可能ですが、指定をできないわけではありません。
また不要な操作を防ぐ意味でリージョンは指定すべきという意見もあると思います。

そのため今回はバケットへの操作を行う前に`aws s3api get-bucket-location`を使ってリージョンを取得し、S3操作の際には必ずリージョンを指定するようにすることで対応しました。

```
$ aws s3api get-bucket-location --bucket bucket-name
{
    "LocationConstraint": "af-south-1"
}
```

最後に今回作成したShellスクリプトを参考として載せます。

```bash
#!/bin/bash

FILE_PATH=$1
FILE_NAME=$(basename "$FILE_PATH")

BUCKETS=$(aws s3 ls | grep 'search-name' | awk '{print $3}')

if [ -z "$BUCKETS" ]; then
    echo "No buckets found."
    exit 1
fi

for BUCKET in $BUCKETS
do
    REGION=$(aws s3api get-bucket-location --bucket "$BUCKET" --query 'LocationConstraint' --output text)
    if [ $? -ne 0 ]; then
        echo "Error: Could not retrieve region for bucket $BUCKET. Skipping."
        continue
    fi

    if aws s3 ls "s3://$BUCKET/" --region "$REGION" > /dev/null 2>&1; then
        # ここで何かしらのS3の操作を行う
        # s3 cpの場合の例
        DESTINATION="s3://$BUCKET/$FILE_NAME"
        aws s3 cp "$FILE_PATH" "$DESTINATION" --region "$REGION"
    else
        echo "s3://$BUCKET/ does not exist. Skipping."
    fi
done
```

## まとめ
AWS CLIで業務効率化を行うスクリプトを作成する際には、不要なバグを防ぐために省略可能でもリージョン指定を行うようにしましょう！
Power Apps のフォームコントロールの間に線や文言を追加する


Power Apps のフォームコントロールで、入力項目が多い場合、例えば、以下のように、途中で文言を入れたり線を入れたりしたいときがあると思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/b85a9b09-434c-4cd5-1ee5-53111a05e81a.png)

フォームコントロールは簡単に利用できますが、デザインの柔軟性が低いのが悩ましいところです。

そして、上記のようなことをしたいときに、フォームコントロールの外にラベルを配置すると、以下のように、フォームコントロールをスクロールすると、文字の位置がずれてしまいます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/b5696507-edc6-5367-5b6a-09c90dbc648b.png)

対策としては以下のようにカスタムカードを追加する方法です。データ送信には関係ないですが、間にカスタムカードを追加し、そのカードの中にラベルや図形などを入れることで、入力の区切りのように見せることができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/2199dff7-a8e0-146c-170b-f6df42497e71.png)

方法としては、以下のように、カスタムカードを追加して並べ替えをして、そのカスタム カードのなかにラベルコントロールを追加します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/33d85e00-fdf8-11bd-405d-cb11acf1515d.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/8b1f42da-e11b-054c-753b-c8a530e98f57.png)

こうすることで、フォームコントロールをスクロールしても、常に同じ位置に区切り用の文字が表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/72f4bbb0-1d5d-bfda-8cc3-3884afd0477b.png)

こんな感じで区切り線を入れることも出来ます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/d9a7ccf9-80f9-5dcf-3870-9204e5d27e94.png)
dSPACEでシリアル通信

# 1. はじめに
dSPACEとarduinoとをシリアル通信するための方法をまとめました．
今回はPythonで実装しますが，プラットフォームの端子とSimulinkのシリアル通信用のブロックでも実装できるような気もしています．

# 2. メソッド
pyserialを使います．
シリアル通信を無限ループ内で実行する場合は抜けるためにkeyboardライブラリもいれましょう．

# 3. 記述例
4自由度のアームのエンコーダ角度情報を送信するプログラム
- マイナスの場合は360度から引いて正の値で表現
- 画面のフリーズを防ぐためにスレッド使用
- 無限ループから抜けるためのキーボード検知

```python
import sys
import keyboard
import serial
import time
from win32com.client import Dispatch, DispatchWithEvents
from dspace.com.threads import STAThread

MyPlatform = Application.ActiveExperiment.Platforms["Platform"]

def main():
    Angle = [0.0, 0.0, 0.0, 0.0]
    Angle[0] = MyPlatform.ActiveVariableDescription.Variables['Platform()://Model Root/EncoderSubsystem/angle [deg]1/In1']
    Angle[1] = MyPlatform.ActiveVariableDescription.Variables['Platform()://Model Root/EncoderSubsystem/angle [deg]2/In1']
    Angle[2] = MyPlatform.ActiveVariableDescription.Variables['Platform()://Model Root/EncoderSubsystem/angle [deg]3/In1']
    Angle[3] = MyPlatform.ActiveVariableDescription.Variables['Platform()://Model Root/EncoderSubsystem/angle [deg]4/In1']

    # Start thread.
    print("[python] Start serial communication.")
    serialSendThread = STAThread(Hoge, "Hoge", (Angle,Application))
    serialSendThread.start()

def Hoge(Angle, Application):
    while (True):
        angles = [(int)(Angle[0].ValueConverted), \
            (int)(Angle[1].ValueConverted),	\
            (int)(Angle[2].ValueConverted),	\
            (int)(Angle[3].ValueConverted)]

        for	i in range(0, len(angles)):
            if (angles[i] <	0):
                angles[i] =	360	- angles[i]
	
        # example: b/090180045000
        #print(str(angles[0]) + ", "	+ str(angles[1]) + ", "	+ str(angles[2]) + ", "	+ str(angles[3]))
        serialCommand =	str(angles[0]).zfill(3)	+ str(angles[1]).zfill(3) +	str(angles[2]).zfill(3)	+ str(angles[3]).zfill(3) +	"\r\n"
        writeSer = serial.Serial('COM4', 115200, timeout=3)
        writeSer.write(serialCommand.encode())
        writeSer.close()
        time.sleep(0.05)
        
        # Stop serial communication by escape key.
        if (keyboard.is_pressed('escape')):
            print("[python] Stop serial communication.")
            sys.exit()

if __name__ == "__main__":
    main()
```
品質は品質計画の品質で決まる、と思う

# この記事は

[過去の自分に教えたい、ソフトウェア品質の心得を投稿しよう by QualityForward Advent Calendar 2024](https://qiita.com/advent-calendar/2024/qualityforward01) に参加しています。
（遅刻してすみませんでした)

### それを書く私は

1. ソフトウェアエンジニアとして働くようになって「プロジェクトがうまくいかないのは【おかしい】」と思い
1. プログラムを作る技術はあるのに、それでも品質問題でプロジェクトがうまくいかないなら、品質を何とかする技術が必要なんだと思い
1. テスト技法やら定量化手法やら、小手先の技術を勉強し
1. もっとプロセスよりの問題だと気づいて品質プロセスを勉強しはじめる

といった過去を持つ者です。

はい、2～4あたりの自分を想定した記事になっております。


# 品質ってなんぞや

かの狩野先生（ダジャレじゃない）が説明されている動画がこちらです。

https://www.youtube.com/watch?v=QIJYJhuZImo&t=605s

うまく聞き取れなかったところは巻き戻したり、古すぎる笑いポイントは聞き流したり、しながら5回ぐらい視聴すると凡人の私でも「何となく」わかった気がします。

上の動画ではとっても大事なことが山ほど語られているのですが、
今回の記事で大事なのは

* 「品質とは "ふたつ" の比較から生まれる」ので、比較対象がないと品質は語れない

という点です。


# 何を作るかが決まらないと品質も決まらない

「いま作っている/作ろうとしているモノの品質」を語るためには比較対象が必要です。

大抵のソフトウェア開発では
プロジェクトを立ち上げる前かプロジェクトの初期で「何を作るか」を決めています。
なので、「いま作っているモノの品質」を知りたいとき、
「いま作っているモノ」と「作ると決めたモノ」の比較をすることになります。

ということで、「何を作るか」を決めるのが大事です。

　

……。

　


この段階で納得しないでくださいね？


# 「何を作るか」は比較可能か

比較というのは、**対象が同じ評価軸の上に乗っかっているのが大前提**です。

レシピに「ジャガイモ（大）2個」としか書いてなかったとき、
あなたの手元にあるジャガイモのどれをどれだけ使うか悩みませんか？
手元のジャガイモは大きさなり重量なりを計れますが
レシピの「大」は同じ軸にないから比較しようがないですよね。

翻って
①「いま作っているモノ」を表現している指標
と
②プロジェクトを立ち上げる前かプロジェクトの初期で決めた「何を作るか」の表現
って
***比較可能ですか？？？***


この記事では①を「（開発中に使う）品質指標」、②を「要件」と名付けましょう。

要件を考えるとき、
大抵のプロジェクトでは、ビジネスや実現性のことを考えていると思います。
要件を定義する人達はプロジェクト完了後に得られるモノにフォーカスしているので
プロジェクトの真っ只中のことまで気を回している余裕がありません。
「要件定義書」は、開発途中に使う品質指標と比較できない文章で書かれているか、
偶に品質指標が出てきたとしても、開発中「それだけで事足りる」には足りません。


# 「品質計画」で比較可能にする

レシピに「ジャガイモ（大）2個」と書いてあったら。

* そこそこ料理の経験があり、かつ、自分一人向けの料理で、加熱済みだったら量も味も不問である！というときは、手元のジャガイモから適当に選んで使ってしまいますね。
* その料理の熟練者だったら、今までの経験から多分こんなものという量がわかっているので、手元のジャガイモから適当に選んで使ってしまいますね。
* 初めて作る料理で、人に提供するから「ふつーにおいしい」はクリアしたい！てときは、多くの人は「ジャガイモ　大　重さ」とかでググったり、今なら「はろーぐーぐる、ジャガイモ大の重さを教えて」なんてやるんじゃないでしょうかー。そして手元のジャガイモを秤に乗せて、ちょうど良さげなものを選びますよね。
　

ソフトウェア開発は毎回あたらしいものを作るので、かつ、ビジネスなので失敗もしたくないので、大抵のプロジェクトでは、3番目と同じで、比較対象が同じ評価軸に乗っかるようにします。

**それが「品質計画」です。**
　


品質計画の具体的なやり方、品質計画書とはこういうもの、という情報は
世の中に山のように良い情報がありますので（無数の玉石混交の中に）
そっちを見てください。

そして、沢山の情報や、肌馴染みのない単語に埋もれて「品質計画って難しいし、何かアカデミックで使いこなせる気がしない」と思ったら。
いろんな情報をそぎ落として、以下だけ頭に残してください。

**品質計画は「いま作っているモノ」と「作ると決めたモノ」の比較ができるようにすること**

その目的がブレなければ、たぶん、「じゃあ何をするの？」「じゃあいつやるの？」といった疑問を解消していく内に、品質計画っぽいのができていると思います。

「自分たちが比較できるように」を忘れなければ、使わない/使えない品質計画になることもないでしょう。

ソフトウェアエンジニアとして責任感があれば、ちゃんと作れているかな？という不安は常に湧くでしょう。
手を動かし始めたら直ぐに比較したくなるハズです。そのときに「品質計画がなかったら比較できない」と覚えていれば、プロジェクトの初期に「品質計画ほしい！」てなると思います。

そして。
「いま作っているモノ」をどれだけ適切に比較できるかは、品質計画の質によります。
作っている最中に適切に評価できれば、リリースするものがおかしなことになることは、大抵はありません。
↑
はい、タイトル回収しました。

おわり。