OmniAICreator/Qiita-1.07M huggingface dataset:
Flutter入門: 本当にシンプルなアプリケーションを作成する




## はじめに

この記事では、Flutterの基本を学びたい初心者の方々のために、最初の一歩としてシンプルなアプリケーションを作成する方法を説明します。プログラミング初心者がFlutterを始める際、環境構築からプロジェクト作成まではできても、いざコードを書こうとすると何から手を付けていいか分からなくなることがあると思います。
そこで、Flutterの初期サンプルコードをもっと簡単にして、基本的な「Hello, Flutter!」というテキストを表示するアプリを作成し、解説していきたいと思います。
## 1. lib/main.dartファイルを開く

まず、Flutterプロジェクトの`lib`ディレクトリ内にある`main.dart`ファイルを開きます。これからはこのファイルにいろいろ書いていきます。

## 2. コードの編集

初めての人はmain.dartファイルに沢山訳の分からない文字がたくさん並んでいると思うのですが、すべて消して、以下のコードを`main.dart`ファイルにコピーして追加してください。これで、画面に「Hello, Flutter!」というテキストを表示するシンプルなアプリケーションが作成されます。

```dart
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Flutter Demo Home Page'),
        ),
        body: const Center(
          child: Text('Hello, Flutter!'),
        ),
      ),
    );
  }
}

```

## コードの説明

### 1. `import 'package:flutter/material.dart';`

この行は、Flutterの基本的な部品（ウィジェット）を使えるようにするためのものです。例えば、ボタンやテキストなどの部品です。

### 2. `void main() { runApp(const MyApp()); }`

ここからアプリが始まります。`main`という関数の中で`runApp`という関数を呼び出して、`MyApp`という名前のアプリをスタートさせます。

### 3. `class MyApp extends StatelessWidget`

`MyApp`という新しいクラス（設計図）を作ります。このクラスは、画面に何を表示するかを決めるためのものです。`StatelessWidget`は「変わらない部品」を作るためのものです。

### 4. `@override`

この行は、親クラス（StatelessWidget）からメソッドを上書きすることを示しています。

### 5. `Widget build(BuildContext context)`

このメソッド（関数）は、画面に表示する部品を作るためのものです。

### 6. `return MaterialApp( ... );`

`MaterialApp`は、アプリ全体の設定を行う部品です。テーマやルート（画面のナビゲーション）を管理します。

### 7. `title: 'Flutter Demo',`

アプリのタイトルを設定します。これは後で使うことがありますが、今は表示されません。

### 8. `home: Scaffold( ... );`

`Scaffold`は、画面の基本的なレイアウトを提供する部品です。ここにアプリの主要な要素を配置します。

### 9. `appBar: AppBar( ... );`

`AppBar`は、画面の上部に表示されるバーです。ここにタイトルなどを表示します。

### 10. `body: Center( ... );`

`body`は、画面の主な内容を表示する部分です。ここでは`Center`という部品を使って、内容を中央に配置しています。

### 11. `child: Text('Hello, Flutter!'),`

`Text`は、文字を表示するための部品です。ここでは「Hello, Flutter!」という文字を表示します。

---

これで、Flutterの基本的な構造とコードの役割がわかると思います。
質問や気になる点があれば、遠慮なく聞いてください！
OSI参照モデル　TCP/IPモデル

## 概要
それぞれ通信の約束事,ルール(プロトコル)を階層に分けて定義しているモデルのことです。
OSI参照モデルは7つの階層があり、TCP/IPモデルでは4つの階層です。
どのような役割があるのかをまとめたいと思います。

---
## OSI参照モデル
国際標準化機構(ISO)が作ったモデルであり、ネットワークを理解する上で抑えたほうが良いとされるもの。


![スクリーンショット 2024-06-10 164104.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3806876/27897a67-f9ee-2d40-f68e-c85877010f4d.png)



上位層は数字が大きい層、下位層は数字が小さい層を示し、
第1層～第7層をそれぞれレイヤー(階層)と示すこともあります。
ex:第3層のネットワーク層を指す場合、「レイヤー3」,「L3」などの表記もあったりする。

#### アプリケーション層
使用するアプリケーションの動作を下位の層に渡したり、相手から受け取ったデータをアプリケーションに表示したりする役割。

#### プレゼンテーション層
コンピュータで通信しやすいように、通信したいデータの表現形式を変換する。

#### セッション層
通信内容を区別し、アプリケーションプロトコルに沿った論理的な通信路を確立する役割。
通信プログラム間の通信の確立、維持、終了の規定。

#### トランスポート層
ポート情報を付与してどのアプリケーションに渡すかの橋渡しを行っている。
通信の信頼性の担保の役割。

#### ネットワーク層
異なるネットワーク同士を中継することを担う。

#### データリンク層
接続されている同一ネットワーク内で正確なデータ伝送を実現する役割。

#### 物理層
コンピュータとケーブルを接続し、コンピュータが理解できるビットデータ(1001011001...)を電気信号に変換する役割。

---

## TCP/IPモデル
米国国防高等研究計画局(DARPA)が作ったモデル。
デファクトスタンダード(事実上の標準=市場での競争の結果の規格)になっている。

![スクリーンショット 2024-06-10 164254.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3806876/beb72933-1cd3-da14-52d2-a335c8e2fa92.png)

---

### OSI参照モデルとTCP/IPの層区切りの違い

![スクリーンショット 2024-06-12 081240.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3806876/ec435511-007b-391f-a3d8-447eef4154f5.png)



---



↓こちらを主に参考,引用しました。どの階層の何だったかな？いう際にパッと視覚的に把握しやすくまとまっていると感じました。また詳細な情報も記載してありましたので、再確認したい時や理解を深めたい時におすすめです。
私は階層の種類をまず覚えるところからですが、再確認するも多いのでよく利用しています。

https://www.itmanage.co.jp/column/osi-reference-model/

---

### **まとめ**
人間社会でもルールを守って皆が過ごしやすい環境を作り利用することと同じことが通信でも行われている。
階層ごとに約束事(プロトコル)が決められているからこそ、通信が成り立っている。
レイヤーの各工程は世界で統一されている＝**標準化**
メーカーや使用する国が異なっていても通信ができる仕組みがOSI参照モデル及びTCP/IPモデルと捉えることが重要です。
生成AIをうまく使えなかったときの話をしようか

# はじめに
生成AI、どんどん進化してますね！
みなさんは、どのくらい活用できているでしょうか。

私は、最初はうまく使えませんでした。
しかし、半年以上試行錯誤を続け、今では10倍〜20倍の効率化を実現することができました。

この記事では、私が生成AIと格闘した日々を振り返りつつ、参考になりそうな、生成AIの効率的な活用法をお伝えします。

# 何がうまく行かなかったのか

最初に生成AIという存在を知ったとき、「これは知識の塊である」と感じました。
開発エンジニアという職業から、圧倒的な知識は、すぐにでも欲しいです。

まずは無料版で、簡単な会話からスタート。
会話は普通にできて、これだけでも感動していたのが、今となっては非常に懐かしいです。

続いて、ブログを書くために、アイデア出しを依頼。
あれ？なんかいまいち。

何度やっても、あまりいいアイデアが出てきません。

「これなら、自分でやった方が早い」

そう、よくあるケースです。

### うまく行かなかったポイント　その1
無料版を使っていた。

今では無料版もかなり優秀になってきましたね。
しかし、有料版との差は必ずあります。

特に当初は、その差が顕著でした。
これは今でもあると思います。

### うまく行かなかったポイント　その2
指示が曖昧だった。

生成AIは優秀ですが、こちらの状況を知りません。
前提条件や目的、ジャンル、ターゲットなど、相手が何も知らない前提で依頼する必要がありました。

これについては、人とのやりとりでも同じですよね。
相手がどれだけ優秀であっても、伝え方や指示を間違えると、期待した結果を得ることはできません。

以前、管理職研修で

「相手がどのようなパフォーマンスを返すかは、自分次第」

と教えて頂きましたが、まさにその通りだと思います。

### うまく行かなかったポイント　その3
作業者として捉えていた。

生成AIは様々なことをやってくれますが、意思を持った作業者ではありません。

結果を求めてしまうと、結局ただの機械だった、で終わってしまいます。

このような振り返りをしてから、まずは検証を兼ねて有料プランを契約し、アシスタントとして捉え、伝え方を工夫するようになりました。

# どうしたらうまく行ったのか
### 有料版を使ってみた
月20ドル、サービスの利用料として考えたら、高いですよね。

しかし、生成AIを様々な知識があるアシスタントとして捉えたらどうでしょうか。
無料版より遥かに優秀なアシスタントが、どれだけ使っても20ドル。

人件費として考えたら、安いです。
人の時給1〜2時間分でアシスタント業務をこなしてくれます。

これで効率化できるなら、ありえない安さの人件費です。

### 指示（プロンプト）を改善した

1. **明確な指示を与えた**

生成AIは、人間のように状況を理解することはできません。そのため、**具体的な指示を与えること**が重要になります。

例えば、記事のタイトルやテーマ、キーワード、文章のトーンなどを明確に指示することで、より質の高い文章を生成することができます。

プログラミングにおいても同じで、OS、言語、フレームワーク、DB、要件をきちんと伝えることで、人間よりも遥かに優秀な、かなりシンプルなコードを書いてくれます。

生成されたコードを見て、こういう書き方があるんだ、と何度感心したか分かりません。
おかげで実装スキルが上がりました。

2. **答えではなく、提案として捉えた**

生成された文章やコードは、答えではなく、「提案」です。
きちんと自分で理解し、修正・加筆・相談する必要があります。

提案として捉えた場合、依頼したものがイメージと違っていたら、どうしますか？
指示の仕方を変えますよね。それと同じです。

# どのくらい効率化できたのか
現在、生成AIを以下の作業で使ってます。
- データ分析
- コード生成
- 画像生成
- アイデアのブラッシュアップ
- 文章校正
- ブログのたたき台

この中で、10倍以上の効率化ができたのは、データ分析とコード生成です。

データ分析は、個人情報をマスクしたアンケート結果などを渡すと、10秒くらいで分析してくれます。

コード生成は、アプリ開発で使ったところ、16倍の効率化に成功。これからさらに効率化できると思います。


# まとめ

生成AIは、私たちの仕事や生活を大きく変える可能性を秘めています。

ぜひ、この記事を参考にして、生成AIを味方に付け、うまく使いこなして、楽しい日々を過ごしましょう🙂
Slack `chat.postMessage`API: `<url|text>`形式で指定したURLに半角スペースが含まれていると、リンクが貼られない

# 環境
* slack_sdk: 3.27.1
* Python 3.12.1

2024/06/13に動作確認しました。

# はじめに
Slackの[chat.postMessage](https://api.slack.com/methods/chat.postMessage) APIでメッセージを投稿する際、`<url|text>`という形式のメッセージを`text`引数に渡すとテキストにリンクを貼れます。

https://api.slack.com/reference/surfaces/formatting#linking-urls

ドキュメントにも記載されている通り、URLに半角スペースが含まれているとリンクが貼られません。

>URLs with spaces will break, so we recommend that you remove any spaces from your URL links.

`url`部分に問題ありそうURLをいくつか指定して、Slackアプリではどのように表示されるかを確認しました。

# 結果
以下のPythonファイルを実行しました。

```python
import os
from slack_sdk import WebClient

client = WebClient(os.environ["SLACK_API_TOKEN"])

lines = []
lines.append("<https://example.com/|test1-通常のurl>")
lines.append("<https://example.com/ foo|test2-スペースが含まれているURL>")
lines.append("<https://example.com/ |test3-URLの直後にスペースあり>")
lines.append("< https://example.com/|test4-URLの直前にスペースあり>")
lines.append("<foo https://example.com/|test5-通常のメッセージの後にURLが続く>")
lines.append("<foo://example.com/|test6-存在しないプロトコル>")
lines.append("<foo-bar|test7-urlでない>")

client.chat_postMessage(channel="channel_id", text="\n".join(lines))
```


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37903/0a05f306-4d88-634b-079b-0f9bd141f961.png)

# 分かったこと
* リンクが貼られるケース
    * 正しくリンクが貼られるケース
        * スペースが含まれていない通常のURL
        * URLの直後にスペースがある
        * 存在しないプロトコル（`https`や`http`でない）を含むURL
    * 不正な状態でリンクが貼られるケース
         * URLの直前にスペースがある
* リンクが貼られないケース
    * URL部分が表示されるケース
        * URLでない
    * URL部分が表示されないケース
        * スペースが含まれているURL


# 補足
## 対応方法

`urllib.parse.quote`でパーセントエンコーディングして、解決しました。


```python
import urllib
lines.append(f"<https://example.com/{urllib.parse.quote(' foo')}|test2-スペースが含まれているURL>")
```
腰、　イ　タ　ス　ギ　‼️ ～健康になろうエンジニア～

## 皆さん、腰痛くないですか？
THEデスクワークの日々、身体中、特に腰が痛くならないですか？

新人の方も疲労が溜まって身体が痛くなってくる時期かと思います。
リモートワークによって出勤で歩くということもなくなった今、毎日身体が痛いばかりです。

【負の連鎖】
・腰回りが変な感じ、じっと座っているのがつらい
・足を組む、立膝をするなど、姿勢を崩して座る
・余計に身体が崩れる
一番上に戻り、以下ループ。

痛いというか気持ち悪いような感覚……伝わる方は一緒に改善していきましょう。

## 最近行っている改善法

### おしりストレッチ
腰が痛いのに何故おしりを？と思われるかもしれません。
一か月ほど前にX(旧Twitter)で見かけたこちらの投稿がきっかけです。

https://x.com/totsuno/status/1792482994445582692

「背中や腰のダルさ」……これだ！と思い、寝転んでいて思い出した時にやるようにしています。

習慣的にきっちり行っていないのもあって、劇的な効果は正直感じていません。
ただ、確かに整体でおしりの辺りが凝っていると言われた気がするので、おしりの凝りは全体に響くのだなと実感しています。

腰のストレッチをやっているのになぜ治らない！という方はぜひ「おしり」もほぐしてみてください。

### 腰・おしり付近に体重をかけてもらう（即効性◎）
**これが一番、即気持ち悪さが改善されます！！**
※素人判断で素人が行っているので、悪影響の可能性が充分にあります。

両手、または片足でグイ～っと体重をかけて、頭側に押してもらうイメージです。
（疑似整体と捉えていただければイメージしやすいかと思います。）

父親も腰痛持ちなのですが、よく背中や腰に乗らされていたな～という経験から実行。

まっすぐ下に体重をかけてもらうより、気持ち前方にかけてもらうとより効くことに気が付きました。

本当に即効性はあり、夜行えば翌日の午前中くらいまでは持つのですが、責任は取れませんので試す際はご了承のほどお願いいたします。

※整体経験のない方は勝手が掴めないと思うので、まずは整体に行ってみてください。

## ちゃんと改善させていきたい……。
運動や筋トレが大事なのだろうと思いながら、継続できず……。
どうにかズボラでも行える改善法はないのでしょうか。

オススメの改善法があればご教示いただけると嬉しいです。

今後どう腰痛と向き合っていくのか、発見があれば記事にしていきたいと思います。

皆さんもご自愛ください。
ログイン時のデフォルト画面が設定とは違って別画面にリダイレクトされる【未解決】


+ [ログイン時のデフォルト画面について](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007cle9E)

現状、設定＜ホーム から「デフォルトのホームページ」を設定しているのですが
代理ログインをしてみると数名のユーザーがデフォルトのホームページではなく、
取引先責任者のリストビューに飛んでしまいます。（取引先責任者は使用しておらず、タブにも表示させていません。）

+ [デフォルトホームページの設定を確認してください](https://help.salesforce.com/s/articleView?id=sf.admin_home_lex_set_default.htm&type=5)

**実は私も同じようにリダイレクトされてました**

私も一部のSandboxが何故かChatterの画面にリダイレクトされていました...
同じようにヘルプを参考に設定したのですが解決できませんでした。

あんまり意味があるとは思えなかったのですが、クラッシックに切り替えて

設定 --> アプリケーション　の中のチャターのアプリの編集でデフォルトをチャターからホームに変えたら何故かリダイレクトはされなくなりましたね。

理由は分かりません。

+ [【解決】ログイン時に表示される最初の画面について](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007es0Wn)

------------------

さらに他にもホームページにリダイレクトしないSandboxが残ってましたので、色々やってみるのですがどれも機能しないですね。 

他のユーザとしてログインしてみるとちゃんとホームページが表示されるので設定自体は間違ってないと思っています。

設定 --> ホーム --> アプリケーションおよびプロファイル別割り当て

を設定しても変わらなかったですね。 強制的にリダイレクトされているとしか思えない挙動ですが設定箇所が見つからないです。

ブラウザを変えても同じなので、クライアント側の問題でもないと思います。

# 類似の質問

+ [ログイン時に表示される最初の画面について](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007es0WnSAI)
QiitaCLIでnpx qiita pullを自動化したかった（失敗と考察）


**本稿はできなかった話です**

## 結論
- Webエディタで書かない
- Webエディタで書いたら手動でqiita pullしてpushする

特にQiitaCLIで書いた場合、特にバックアップを取る必要ないやん？という考えから対応しなくて良いとする
問題はWebエディタで書いた場合。よくあるのはキャンペーンに登録するついでにタグ変えたりしたい場合が考えられる。

### 運用所感
Webエディタで書かない、というのは本文は当然として、タイトルもタグも編集しないという意味になる
たとえば、キャンペーンに登録するために必ずWebエディタを使う必要があるが、上のようにちょっとした修正も含めて、このタイミングでは何も書かずにQiitaCLI側を対応するということに他ならない
運用上の制限ぐらいだろうと考えていたが、結構面倒くさいので、あまり現実的ではないなと感じた

## 問題と解消
CIでnpx qiita loginを解消できない

GitHub Actionsで対話モードでトークンを渡してあげる必要があるが、これがどうしても解決できない
いくつか解消方法は思いつくが、いやいやそれはあかんやろ、という主観のみで不採用としたが、誰かの役に立つはず。

1. 認証済みの環境で実施する
git cloneしてnpx qiita pullしてgit pushするshellなりを作ってcronを実行するようにさせれば解決できそう。

2. 動く環境のimageを作る
そもそもの話として、公式が用意しているusesでpushできているので、これに相当する環境を作れば解決するが、そのために努力したくないなー、というのが本音
QiitaAPIを使ってデータを取ってくる方法が考えられるが、そういう面倒臭いのをやらなくてもよいようにQiitaCLIがあるはずなので、公式が対応してくれることを願いたい。
（でもディスカッションには書いてない）

3. QiitaAPIで全記事取得する
正直、これが一番現実的な方法なんじゃないかと。
ただし、npx qiita pullの形式に合わせて記事データを取ってくる処理が必要で、特にQiitaCLIでpublishした記事の取り扱いが面倒くさい

4. Webエディタを使わない or Webエディタで書いたら手動で1. を実施
正直、現実的じゃないなぁと。いつか絶対忘れる

5. 祈る
＝何もしない。GitHub Actions対話モードでトークンを渡す方法ができるか、npx qiita loginでトークンが渡せるようになれば解決

## QiitaCLIで投稿した記事を編集でキャンペーン登録してもきちんと投稿マラソンにカウントされます
先日この辺の仕様について調査済みだったので大丈夫だろうと思ってはいたけど、Webエディタで投稿した時じゃないとダメなルールではなかったことを本稿で確認しました。
新たなチームメンバーとテスト駆動開発をやってみたので振り返る

# はじめに
数か月前に新しいメンバーが加わり、テスト駆動開発を一緒にやったので振り返りを兼ねて簡単にまとめてみます。

テスト駆動開発についてはこちらの動画を参考にしています。

https://www.youtube.com/watch?v=Q-FJ3XmFlT8

# やってみた所感
- 開発初期段階でやることの共通認識をとれる点が良い！新しいメンバーも置いてけぼりにしない！
- やることが決まっている＆テスト駆動開発の手順も決まっているので、ペアプロ、モブプロとの相性が良い！
- 後からテストを入れないといけない…と考える必要がないので安心感がある！
- たまにテストより先にメソッドを実装しようとしてしまい、メンバーからストップがかかる

# テスト駆動開発の流れ

### TODO(目標)を考える
ここでは簡単なテストケースを実装していきたいと思います。

- 正しいデータを取得できること

### テストを実装する①
以下のようなテストケースを先に実装します。
この時点でget_users()は実装していないため、テストを実行してundefinedエラーが出ればOKです。

```py:app/tests/test_methods.py
def test_get_users():
    response = get_users()
    assert reaponse == 1
```

### メソッドを実装する①
次にget_users()を実装します。

```py:app/folder/methods.py
import requests

def get_users(token: str):
    return 1
```

忘れずにテスト側でメソッドを呼び出してあげましょう。

```py:app/tests/test_methods.py
from folder.methods import get_users

def test_get_users():
    response = get_users()
    assert reaponse == 1
```

この状態でテストを実行するとundefinedエラーは解決され、テストも通ります。

### テストを実装する②

最低限のメソッドを実装し、テストを通したところで再びテストから実装していきます。
今回は「外部APIからデータを正しく取得できているか」、のテストを実装します。

```py:app/tests/test_methods.py
from unittest.mock import patch
from folder.methods import get_users

@patch('requests.get')
def test_get_users(mock_post):
    mock_post.return_value = [
            {
                "id": "1",
                "name": "taro"
            },
            {
                "id": "2",
                "name": "hanako"
            }
        ]
    response = get_users('token')

    assert response[0]["id"] == "1"

```

この状態でテストを実行すると、assertionエラーが出ると思います。
メソッド側では1を返しているのに対して、テスト側で期待している値と異なるためです。

### メソッドを実装する②
テストを実装したらそのテストが通るようにメソッドを実装していきます。

```py:app/folder/methods.py
import requests

def get_users(token: str):
    url = f"https://hogehoge"
    response = requests.get(url=url, headers=set_headers(token))
    return response
```

この状態でテストが通ることを確認できればOKです。

### リファクタリング
最低限の実装でテストが通るようになったら、最後にリファクタリングを行います。
(本記事では割愛します)


# おわりに
テスト駆動開発は楽しいので好きです。何事も最初が肝心ですね。
[TypeScript] 関数の中で使用される void って何をしている？

### 概要

初見で理解できないコードがあったため、備忘録として...

#### 対象コード
```tsx
const sample = () => {
    void "value";
}

console.log(sample());
// undefined
```

#### 疑問
ここでいう `void` は何をしているのか？

---

### 結論
:::note info
関数の中で `void` キーワードを使用すると、それに続く式の結果を評価するが、その結果を無視して常に `undefined`を返します。

関数の副作用を利用しながら、戻り値は意図的に無視したい場合に使われます。
:::

ふむふむ...なるほど

---

### より実践的なコード

1. `useEffect` で　状態を更新するための非同期処理を定義
2. 非同期処理の実行 ※戻り値は使用しないので`void`を先頭につける

```tsx
useEffect(() => {
    const load = async () => {
      setIsLoading(true);

      try {
        const usersData = await getMembers(orgCode);
        setUsers(usersData);
      } catch (err) {
        throw new Error(`organization '${orgCode}' not exists`);
      } finally {
        setIsLoading(false);
      }
    };

    void load();
}, [orgCode]);
```

---

### まとめ
void の記述がなくても動作に支障はないですが、明示的に戻り値がないことを示しておくほうが健全そう...
ChatGPT使えば結構いい感じのサイト作れるんじゃね?というお話。Part3

こんにちはAtsu1209です
今回はChatGPT使えば結構いい感じのサイト作れるんじゃね?というお話。Part3です

### Part1

https://qiita.com/Atsu1209jp/items/2c93be5930360d007c60

### Part2

https://qiita.com/Atsu1209jp/items/7a526478418eee9ec319

# 今回やること
今回はこれまで作ってた物とはまた別のものを作ります。

今回作るものはブログサイトです。
NodeやRubyといった物は置いて、HTML部分を作ってもらいます。

# 早速入力
ChatGPTに `ブログサイトを作りたいのでHTMLだけ書いてください`と入力

### 結果
```html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>ブログサイト</title>
</head>
<body>
    <header>
        <h1>私のブログ</h1>
        <nav>
            <ul>
                <li><a href="#home">ホーム</a></li>
                <li><a href="#about">私について</a></li>
                <li><a href="#contact">連絡先</a></li>
            </ul>
        </nav>
    </header>
    
    <main>
        <article>
            <h2>最初のブログ記事</h2>
            <p>これは最初のブログ記事の内容です。ここにテキストを追加します。</p>
            <p>更に内容を追加する場合は、このように段落を増やします。</p>
        </article>
        
        <article>
            <h2>二番目のブログ記事</h2>
            <p>これは二番目のブログ記事の内容です。ここにテキストを追加します。</p>
            <p>更に内容を追加する場合は、このように段落を増やします。</p>
        </article>
    </main>
    
    <footer>
        <p>&copy; 2024 私のブログ. All rights reserved.</p>
    </footer>
</body>
</html>
```
結構簡潔ですね

# CSS
CSSを書いてもらいましょうちょっと凝ったデザインにするように言いました。

### 結果
```css
/* リセット */
* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

/* ベーススタイル */
body {
    font-family: 'Arial', sans-serif;
    line-height: 1.6;
    background-color: #f4f4f4;
    color: #333;
    padding: 20px;
}

/* ヘッダー */
header {
    background-color: #333;
    color: #fff;
    padding: 20px 0;
    text-align: center;
}

header h1 {
    margin-bottom: 10px;
}

nav ul {
    list-style: none;
    padding: 0;
}

nav ul li {
    display: inline;
    margin-right: 10px;
}

nav ul li a {
    color: #fff;
    text-decoration: none;
    padding: 5px 10px;
    border-radius: 5px;
    transition: background-color 0.3s;
}

nav ul li a:hover {
    background-color: #575757;
}

/* メインコンテンツ */
main {
    margin: 20px 0;
}

article {
    background-color: #fff;
    margin-bottom: 20px;
    padding: 20px;
    border-radius: 10px;
    box-shadow: 0 0 10px rgba(0,0,0,0.1);
}

article h2 {
    color: #333;
    margin-bottom: 10px;
}

article p {
    margin-bottom: 10px;
}

/* フッター */
footer {
    text-align: center;
    padding: 20px 0;
    background-color: #333;
    color: #fff;
    border-top: 5px solid #575757;
}

footer p {
    margin: 0;
}

/* レスポンシブデザイン */
@media (max-width: 768px) {
    nav ul li {
        display: block;
        margin-bottom: 10px;
    }

    header h1 {
        font-size: 24px;
    }

    article {
        padding: 10px;
    }
}

```
適応させて見てみましょう。

### 結果
![ブログサイト-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3374328/d25896b4-09ff-25f4-5b8c-5ef3646a600c.png)

いいかんじ

# 最後に
最近AIが進化していますが、このようにWebページもAIが作れてしまう時代です。
私自身もAIはどんどん進化して、活用していきたいですが `仕事が減る`ということも
同時に発生してきます。
AIは正しく活用することが大切だなと感じました。

ではまた次の記事で(^^)/
フローを実行するためのユーザーアクセス権の制限

[Flowに関するまとめページに戻る](https://qiita.com/Keiji_otsubo/items/55ebc9c634a3216f3990)

+ [トリガーから起動されているフローの実行権限](https://qiita.com/Keiji_otsubo/items/d9fc73a485a8705d2eeb)

------------------------------------------------------

この更新に新事実があった。以下を読んでも書いてないよね？

**今回のリリース更新で影響があるのは、「画面フロー」や「自動起動フロー（トリガなし）」という他のフローや Apex から呼び出して使用するフローになります。**

**レコードトリガーフローやスケジュールトリガーフローは対象となりません。**


+ [フローを実行するためのユーザーアクセスの制限 (リリース更新)](https://help.salesforce.com/s/articleView?id=release-notes.rn_automate_flow_release_update_restrict_user_access.htm&release=246&type=5)

この更新を有効にすると、Salesforce でユーザーによるフローの実行が制限されます。フローを実行するには、ユーザーに適切なプロファイルまたは権限セットが付与されている必要があります。有効にすると、このリリース更新によって FlowSites ライセンスが廃止されます。この更新により、適切なプロファイルまたは権限セットが付与されたユーザーのみがフローを実行できるため、フローがより安全に実行されます。

+ [フローを実行するためのユーザーアクセス権の制限](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007cluwI)

以下、サポートの回答ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

前提としまして、本リリース更新については、FlowSites ライセンスのみ、影響がございます。通常、ユーザーがフローを実行するには適切に権限を設定する必要がございます。

しかしながら、過去に提供されていた FlowSites ライセンスを使用している場合には、権限の設定の有無に関わらずフローを実行することができておりました。

当該リリース更新を有効化することで、上記ライセンスによってフローを実行できていた外部ユーザーなどがフローを実行できなくなります。

なお、現在は FlowSites ライセンスは提供しておりません。

**今回のリリース更新で影響があるのは、「画面フロー」や「自動起動フロー（トリガなし）」という他のフローや Apex から呼び出して使用するフローになります。**

**レコードトリガーフローやスケジュールトリガーフローは対象となりません。**

上記のライセンスをご使用されている場合で「画面フロー」や「自動起動フロー（トリガなし）」を使用している場合は、適切な権限セットやプロファイルでのアクセス権の設定が必要となります。


**Flowsitesライセンスを契約しているか?**

お客様組織上の設定画面等から FlowSites ライセンスが付与されているかどうかについてはわからないものとなっております。

また、弊社サポートではお客様組織個別のライセンス契約状況について把握しておりません。

そのため、ご希望の場合は別途貴社担当営業までライセンスの購入状況についてご確認いただけますと幸いです。

# テクサポ 日本　フローを実行するためのアクセス権限について

◼️ プロファイルでアクセス権を付与する方法

設定画面から対象のプロファイルの編集画面を開きます。[一般ユーザー権限]にある[フローの管理]もしくは[フローを実行]権限にチェックします。

拡張プロファイルを無効にしても[一般ユーザー権限]には[フローを実行]しかないけど...

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/839638ed-b0ba-670f-2ff1-6f1c30e92f98.png)

拡張プロファイルだと、アプリケーション権限の中にある。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/de2e08c3-d30a-c373-9b42-d834d4b43eec.png)

[フローの管理]はないな。


権限セットにはフローの管理がありました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/fba54259-3ec1-b7e8-dc84-0c6eae4d4a69.png)


システム管理者のプロファイルにはある。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/cafa465b-02a8-dc7a-f0ac-2e25e347fc30.png)
Ubuntuの容量が一杯で起動できなくなった話

# 起こったこと

PCを起動してもログイン画面にたどり着くことができませんでした。
前回起動時に`ルートファイルがいっぱいになりそう`（詳細な文言はちゃんと覚えていない）といったメッセージがでていたことを思い出しました。

どうやらストレージがいっぱいになると（いっぱいになりかけでも？）Ubuntuを起動できなくなるようでした。

# 環境

Ubuntu 22.04

# やったこと

PCを起動したときに`Ctrl + Alt + F2`を押しました。
これでCUIのログイン画面に入ることができます。
タイミングの問題かCUIに入れないことがあったので、電源ボタンを押してからとりあえず`Ctrl + Alt + F2`を連打しました。

ログイン画面ではユーザー名とパスワードを打ち込む必要がありました。

CUIでログインが成功したら以下のコマンドを実行しました。

```bash
df -h
> Filesystem                 Size  Used Avail Use% Mounted on
> tmpfs                      1.2G  4.0M  1.2G   1% /run
> /dev/mapper/vgubuntu-root  232G  110G  111G  50% /
> tmpfs                      5.8G   57M  5.8G   1% /dev/shm
> tmpfs                      5.0M  4.0K  5.0M   1% /run/lock
> /dev/sda2                  704M  268M  385M  41% /boot
> /dev/sda1                  511M  8.3M  503M   2% /boot/efi
> tmpfs                      1.2G  196K  1.2G   1% /run/user/1001
```

dfコマンドとはディスクの空き容量をマウントされている各ファイルシステムごとに表示するコマンドです。
出力結果は問題を解決した後のものですが、`/dev/mapper/vgubuntu-root`の`Use%`が100%になっていました。

参考の項にあるページによると以下のコマンドで、多くのスペースを占めている上位 10 個のファイルがリストアップされるようです。

```bash
sudo du -a /home | sort -n -r | head -n 10
```

大きすぎるファイルをダウンロードしたときなどに使えますね。

私は前回起動時に行っていた作業のキャッシュがたまりすぎていることが原因だと気づくことができたので、キャッシュファイルの削除を行ってディスクの容量をあけることで無事起動することができました。


# 参考
https://askubuntu.com/questions/296172/dev-mapper-full
BroadcomのEthernet

asuswrt-merlin.ngというレポジトリのソースがdrivers/net/ethernet/broadcomに整理してありました。


|ドライバ|内容|FreeBSD|
|:--|:--|:--|
|b44|BCM4401を起源とする100Mの仕様です。もともとはPCIなチップでしたがBCM4712などのMIPS SOCにも入っています。SOCではsibaというバス仕様で使われていました|bfe|
|bcm63xx_enet|BCM63xx SOC向けの実装||
|bcmsysport|BCM7xxx SOC向けの実装||
|bgmac|SOC向けの1Gの仕様です。b44のSOC向けの後継で、バス仕様はbcma。BCM4系のMIPS,ARM SOCで使われています|
|bnx2|NetXtreme II(BCM57xx)なPCIeなチップ|bge|
|cnic|QLogicのチップのようですが、Broadcomが関わっていたのでしょうか？|
|genet|1Gのチップのようですが不明。WOLのコードもあるのでPCIチップと思いきや、そうではなさそうです||
|sb1250-mac|大昔のSOCに入ってたもの||
|tg3|Tigon3 PCIeなチップ||

BroadcomのSOCはラズパイのBCM2系以外に、ルーター向けのBCM4,5系、DSL向けのBCM6系、セットトップBOX向けのBCM7系、CATV向けのBCM3系があります。BCM2系は後から出来たのでかなり違います。他はMIPSのSOCを起源としていて、ARMになったものもあります。BCM6とBCM3は同じ機構を使っているようです。BCM7系はstbとよばれていたようです。

SysKonnectを買収したか、譲渡されたかで、SysKonnect起源な仕様もあるようです。

OpenWRTにbcm6348-enet.cというソースもありました。

Broadcomのオープンソースにetcgmac.cというコードもありました。

BCM6系のecosのコードにPHILIPS SAA9730のethernetのコードがあったんだが、なんでだろう？

BCM338Xの実装のために調べているのですがBCM3380はBCM6系のGEMACで、BCM3383はBCM7145などと同じUNIMACと、まったく別のもののようです。
(新)IBM Navigator for i の複数システム管理(新)

## Navigator for i の主な機能

***ACSは5250端末でできるほぼすべての運用・管理機能を提供しています。*** 
Navigator for i でしか提供されない機能も存在します。（例Web Administration for i から行うIWSのREST APIサービスウィザードデプロイなど）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011394/067d9a0d-64c9-0876-b369-7148a437087e.png)

※IDE, プログラミング環境にはフォーカスしていません、上図ではSQL分析系機能、データベース操作はプログラミングでも使用場面はありますが。

## (新)Navigator for i 新機能：複数システム管理

この機能はかつてのIBM i Access for Windowsで提供されていたマネージメントセントラルのシステムモニターと同様な機能です。

そもそも旧Navigator for iではログイン後の画面は基本ローカルIBM i しか見えませんでしたが、新Navigator for i では下記のように複数システムが参照できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011394/d436ce08-1ad8-1c41-6cde-e6082273c6ef.png)

### リモートシステムの追加方法
サインオンしたローカルシステム以外は追加登録が必要です。（新規ノードの追加）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011394/1a83bcda-0868-ab40-c116-955b10a42b45.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011394/1041037e-5335-54f6-8819-d373ec3d673e.png)

### 複数システムの稼働率監視グラフの作成手順

複数のシステムを登録しておけば、下記のような複数システムのCPU,MEM,DISK他の稼働率監視グラフを表示できます。（下の右側のグラフ：3つのシステムのCPU%を表示）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011394/912933ff-a513-f24c-ad0c-ca32839a6a85.png)

***手順① マルチシステム → カスタム・グラフ を選択***

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011394/f490dbdf-f2bb-ebc9-ee0f-25e5a72ed0ba.png)

***手順② 遷移したページで、グラフの構成を選択***

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011394/4850dad8-80a2-c8ae-bd71-065ad82bd62a.png)


***手順③ 必要項目を入力します***
名前：任意
選択した複数システムの単一メトリックを比較　を選択
システムの選択　からグラフ化したいシステムを選択し、右側のターゲットシステムに入れる
メトリックの選択　にグラフ化したいメトリックを選択（複数も可）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011394/1f2c70bd-1b35-feb5-94ac-cbac226d1387.png)

以上です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011394/0dd41ec9-8743-4181-c55d-678439c0f770.png)

## 新Navigator for i の全ての画面はSQLから実行できる

新Navigator for i の画面には必ず右上の方に ***SQLボタン***があります。
SQLボタンを押すと、、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011394/3c15e514-4318-247e-8f68-72965da6c234.png)

別ウィンドウが起動し 該当画面（機能）を実行するSQLが表示されます。これをコピペして使用します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011394/ec11c143-5214-9d76-9173-cae7ff17b927.png)

上で作成したグラフにはSQLボタンが無いのですが右クリックすると、
SQLの表示が見えます

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011394/ff883d51-1aef-2020-96f6-8a523e695de1.png)

下記のように表示されたSQLを任意のSQL実行画面（ACSほか）にコピペすると同じ機能を実行できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011394/41474826-b29d-91c6-b9e1-285f8aa1b985.png)

※グラフの場合、最新１時点のデータのみ取得できるため、定期的に実行して時系列取得する等が必要になります。
Lua で Welcome to AtCoder を解いてみた

[Qiita Engineer Festa 2024（キータ・エンジニア・フェスタ 2024） - Qiita](https://qiita.com/official-campaigns/engineer-festa/2024)
において、約1ヶ月で38記事という大量の記事の投稿を要求されることがわかった。
そこで、あまりコストをかけずに記事数を稼ぐ方法を考えた結果、「Welcome to AtCoder を様々な言語で解く」ことを思いついた。
単に解くだけでなく、使用する言語仕様の解説を入れれば、記事として一応成立するだろう。

# Welcome to AtCoder

[PracticeA - Welcome to AtCoder](https://atcoder.jp/contests/abs/tasks/practice_1)

Welcome to AtCoder では、以下の形式で整数 $a$, $b$, $c$ および文字列 $s$ が入力として与えられる。

```text
a
b c
s
```

この入力をもとに、与えられた整数の和 $sum = a + b + c$ および文字列 $s$ を、以下の形式で出力することが求められる。

```text
sum s
```

# 今回用いる Lua の機能

[Lua 5.4 Reference Manual](https://lua.org/manual/5.4/)

## 変数への代入

[3.3.3 – Assignment](https://lua.org/manual/5.4/manual.html#3.3.3)

```
変数 = 値
```

の形式で、変数に値を代入できる。
複数の変数にそれぞれ一気に値を代入することもできるが、今回は用いない。

## 数値の加算

[3.4.1 – Arithmetic Operators](https://lua.org/manual/5.4/manual.html#3.4.1)

`+` 演算子を用いることで、数値の加算を行うことができる。

## データの文字列化

[string.format (formatstring, ···)](https://lua.org/manual/5.4/manual.html#pdf-string.format)

`string.format` を用いると、C言語の `sprintf` 関数のように書式指定文字列とデータを指定し、データを文字列に変換できる。

## 入力

[io.read (···)](https://lua.org/manual/5.4/manual.html#pdf-io.read)
[file:read (···)](https://lua.org/manual/5.4/manual.html#pdf-file:read)

`io.read(形式)` で、標準入力から値を読み込むことができる。
「形式」は、以下が利用できる。

|形式|意味|
|:-:|---|
|`"n"`|数値を1個読み込んで返す|
|`"l"`|次の改行文字までを読み込み、改行文字を**除いて**返す|
|`"L"`|次の改行文字までを読み込み、改行文字を**含めて**返す|
|`"a"`|残りのファイル全体を読み込んで返す|
|数値|そのバイト数まで読み込んで返す|

「形式」は省略でき、省略した場合は `"l"` 相当になる。

## 出力

[6.1 – Basic Functions](https://lua.org/manual/5.4/manual.html#6.1)

`print` 関数を用いると、標準出力に値を出力し、さらに改行文字を出力できる。

今回は用いないが、[`io.write`](https://lua.org/manual/5.4/manual.html#pdf-io.write) を用いることで、改行文字を出力せず、指定した値のみを出力できる。

# 提出コード

```lua
a = io.read("n")
b = io.read("n")
c = io.read("n")
io.read("l")
s = io.read("l")
print(string.format("%d %s", a + b + c, s))
```

[提出 #54488729 - AtCoder Beginners Selection](https://atcoder.jp/contests/abs/submissions/54488729)
技術書を読んでそれを実務に活かせないとき

## この記事は何？
やる気のある新人から「技術書を読んでもそれを実務に活かせない」と相談されたときにコツをお伝えするための記事です。

## 先に結論

- 「社内調整が不要な領域」で挑戦する
- 「自分の裁量で変えられる領域」かつ「自分の興味のある領域」を見つける
- 実務での小さな成功体験を積み重ねる

## やる気のある新人

やる気のある新人エンジニアの多くは技術書を読みます。

技術書を読むと、現場とのギャップ、理想と現実のギャップを感じます。
技術書で読んだ内容を実務に反映して、現場を改善したくなるのが自然です。

しかし、最初はなかなかうまくいきません。

## 技術書をうまく業務に適用できない理由

技術書をうまく業務に適用できない多くの理由は、**反対する人がいるから**です。

特に、大きな変化をいきなり提案すると抵抗が強くなります。

例えば、ウォーターフォール開発が主流のチームで「アジャイル開発について本で学んだのでやってみたい」と提案しても、すぐに賛同を得るのは難しいでしょう。

## ではどうする？

まずは、「社内調整が不要な領域」から挑戦してみるのが良いと考えます。

最初は自分の裁量で変えられる内容に取り組むのが効果的です。

例えば、メンバークラスのエンジニアなら、コーディング方法やテスト設計など自分でやり方を決められる範囲があるはずです。このような技術領域について技術書で学び、業務に活かしていきます。

さらに、「自分の興味のある領域」だと取り組みやすくなります。

技術書の内容を業務に落とし込む経験を積めば積むほど、良い成果が出るはずです。
その結果、周りから信頼されていきます。
そして裁量が大きくなったり、提案を取り入れてもらいやすくなったりします。

## おわりに

技術書を読むこと自体は有益な活動ですが、それを業務にうまく活かすことができて、より大きな価値が生まれます。

今回紹介した「社内調整が不要な領域」で挑戦することや、「自分の裁量で変えられる領域」で小さな成功体験を積み重ねることは、その第一歩として非常に効果的です。

この記事が技術書の実務への活用に役立つ参考となれば幸いです。
PR,MR提出時のコミット整理方法 #Git

## はじめに
いつものように開発を行っていたある日のこと。
開発完了！さあレビュー依頼だ！　...ん？ちょっと待った
コミット履歴を見てみると、コミットした修正をやっぱり違うなと戻してみたり、テスト作成中にメソッドのタイポを発見して一緒にコミットしていたりとぐちゃぐちゃ...　
ということで、レビュワーの負担軽減のために（自分を頭良く見せるために）コミット履歴を整理したのでその手順メモを共有します。
PR,MRを作るときに参考になれば幸いです（余談ですが、PR：プルリクエスト → GitHubの用語、MR：マージリクエスト → GitLabの用語らしいです）。

## 手順
### 1. git checkout -b 整理用ブランチ
せっかくの修正が消えてしまっては困るので、コミット整理用ブランチを新しく作り移動します。
```bash
git checkout -b develop_MR
```

### 2. git log --oneline
```git log```で、整理が必要なコミット数を確認します。
```bash
git log --oneline
```

```bash:git log
8da95c1a (HEAD -> develop) id/102 実装・テスト追加修正
2b9f8fe8 タイポ修正
f85688a4 id/102 Fugaテスト修正xxxを考慮
38be30ef id/102 テスト追加
8ed9ed6f id/102 hoge,fugaの修正
c6351458 (HEAD -> origin/develop) Merge branch 'develop' into 'master'
ad18eccc id/101 piyoの修正
```
<font color=`#DDDDDD`>（↑コミットメッセージの書き方が一定でないし、メッセージのprefixを忘れていたりとぐちゃぐちゃな内容）</font>

### 3-1. git rebase -i HEAD~コミット数
必要なコミットの修正が少ない場合には```git rebase -i```で対応できます。解説は以下の記事が非常に詳しいのでお譲りします。

https://qiita.com/KTakata/items/d33185fc0457c08654a5

感覚的にはコミットの分割などオプションの```edit```や```exec```が必要になってきたら手順3‐2．の```git reset```を使用したほうが簡単になります。

### 3-2. git reset HEAD~コミット数
```git reset```で、整理が必要なコミット数分戻ります。
```bash
git reset HEAD~5
```

```bash:git reset
Unstaged changes after reset:
M       hoge.tsx
M       fuga.tsx
M       hoge.test.tsx
M       fuga.test.tsx
```

### 4. きれいなコミット履歴の作成
ローカルに戻した差分から、一つ一つコミット履歴を作っていきます。どのようなコミット履歴が喜ばれるのかについては以下の記事が非常に分かりやすかったです。

https://qiita.com/_mi/items/f477e95a864474187e3d

コードブロック単位のステージングなど複雑な操作にはVSCodeの機能を利用すると便利ですが、CLIを使用する方は以下の記事が参考になります。

https://qiita.com/miyohide/items/79ab0ff3b3852289a6be

### 5. git log --oneline
```git log```で、修正したコミット履歴を確認します。
```bash
git log --oneline
```

```bash:git log
hu5jikde (HEAD -> develop) id/102 xxxメソッドによる修正に伴うhogeテスト修正
8ityksp0 id/102 hogeにxxxメソッドの影響を考慮して修正
23g8er0w id/102 xxxメソッド追加に伴うfugaテスト修正
7s9v5iuq id/102 fugaにxxxメソッド追加
c6351458 (HEAD -> origin/develop) Merge branch 'develop' into 'master'
ad18eccc id/101 piyoの修正
```
<font color=`#DDDDDD`>（↑一つのコミットに一つの内容、コミットメッセージも具体的でだいぶ読みやすくなった）</font>

### 6. git push origin ローカルブランチ:リモートブランチ
コミットを整理したブランチをリモートに```git push```します。
引数に```<ローカルブランチ>:<リモートブランチ>```を指定することで別名ブランチにもプッシュが可能です。
```bash
git push origin develop_MR:develop
```

### 7. レビュー依頼
ここまで来たら晴れてレビュー依頼提出です！自分がいかにレビュワー思いのレビュイーであり、論理的に考えてプログラミング開発ができるエンジニアであるかをPR,MRを通じてアピールしましょう☆
長旅の終わり。マルチスレッド方式の並列Lisp実装が解決しました。

# 長旅の終わり
昨年の今頃から並列Lispの実装に取り組んでいました。当初、マルチスレッド方式で実装しましたが、期待した並列性能が出ませんでした。先日の記事でインタプリタでのマルチスレッド方式について改良したことをお話しました。そして、ついにコンパイルしたコードでもマルチスレッドによる並列性能を出すことができました。


# 原因
インタプリタにおいてはセル切り出しにおけるスレッドの競合が速度低下の原因でした。コンパイラにおいてはセルはそれほど多く消費しません。原因は何？　追求して遂に判明しました。L3キャッシュにおいてキャッシュミスがおきるような無駄なコードを生成していたのでした。

![bandicam 2024-06-09 16-53-40-166.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33927/259c7f3c-7952-268d-e3f1-234383348a63.jpeg)




次のLispコードはフィボナッチ数を計算する再帰関数です。この＋関数を呼び出すときにGCが起動する可能性がありました。そこで第一引数をEvalしている間にGCが起動してもいいようにシェルターと呼ばれるスタックにその値を記憶しGCにより消失しないようなコードを生成していました。

```
(defun fib (n)
    (cond ((= n 0) 0)
          ((= n 1) 1)
          (t (+ (fib (- n 1)) (fib (- n 2))))))
```


Easy-ISLispはLispコードを等価なCコードに変換しています。フィボナッチ数のLispコードは次のように変換していました。


```
static int FIB(int N, int th) {
    int res;
    
    if (CELLRANGE(N)) Fpshelterpush(N, th);
    Fcheckgbc();

    res = ({
        int res = NIL;
        if (fast_numeqp(N, fast_immediate(0)) != NIL) {
            res = fast_immediate(0);
        } else if (fast_numeqp(N, fast_immediate(1)) != NIL) {
            res = fast_immediate(1);
        } else {
            res = fast_plus(
                ({
                    int arg1, res;
                    arg1 = fast_minus(N, fast_immediate(1));
                    // Fpshelterpush(arg1, th);  // コメントアウト
                    res = FIB(arg1, th);
                    // arg1 = Fpshelterpop(th);  // コメントアウト
                    res;
                }),
                ({
                    int arg1, res;
                    arg1 = fast_minus(N, fast_immediate(2));
                    // Fpshelterpush(arg1, th);  // コメントアウト
                    res = FIB(arg1, th);
                    // arg1 = Fpshelterpop(th);  // コメントアウト
                    res;
                })
            );
        }
        res;
    });

    if (CELLRANGE(N)) N = Fpshelterpop(th);
    return res;
}

```


問題はコメントアウトした部分です。計算途中にGCが起動してもいいように挿入してあるコードです。このコードは動的リンクにより処理系本体にあるシェルターへのpush/popを呼び出しています。これはメモリ位地の離れた部分にアクセスしているのでしょう。異なるスレッドにおいてこのコードへのアクセスがL3キャッシュにおけるキャッシュミスを誘発していたものと思います。


# 改良
シェルターへのpush/popのコードを挿入しないようにコンパイラを改良しました。インタプリタは大量のセルを消費するので計算途中でGCが起動する可能性があります。しかし、コンパイルしたコードはそれほど大量のセルは消費しません。小整数は即値としていますのでフィボナッチのようなコードではほとんどセルを消費しません。リスト処理においても引数のevalの途中でGCが起動することはほぼ考えられません。カットすることとしました。



# 時間計測
mt-let、mt-callを利用した並列コードをコンパイルして実行時間を計測しました。

![bandicam 2024-06-12 18-02-06-279.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33927/18cda345-445a-c91f-3385-c291f3b01f3f.jpeg)



1.61倍程度高速化しました。黄金比に近いです。かなり良い計測結果が得られました。



# 目標達成
ver4.0にむけてマルチスレッド、マルチプロセスによる並列機能を追加することを目標としてきました。この楽しい旅は目的地に達したようです。さらに細かな改良、テストをした後にver4.0をリリースします。


Easy-ISLispはOSSです。BSD2ライセンスです。お気軽にご利用ください。
https://github.com/sasagawa888/eisl
RealSenseのROSでの導入(ubuntu)

# 目的
パソコンの実行環境をかえるたびに調べる手間を省くため、ここにIntel RealSense SDK をインストール方法とrosラッパーの導入についてめｍ。

# 結果
## 1. Intel RealSense SDKインストール
・サーバー公開鍵を登録 
```
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-key F6E65AC044F831AC80A06380C8B3A55A6F3EFCDE || sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-key F6E65AC044F831AC80A06380C8B3A55A6F3EFCDE
```
・リポジトリにコピー元サーバー情報を追加
Ubuntu 20 LTS:
```
sudo add-apt-repository "deb https://librealsense.intel.com/Debian/apt-repo $(lsb_release -cs) main" -u
```
・各種ライブラリのインストール
```
$ sudo apt update
$ sudo apt install librealsense2-dkms
$ sudo apt install librealsense2-utils
$ sudo apt install librealsense2-dev
$ sudo apt install librealsense2-dbg
```
・動作確認
RealSenseのUSBケーブルを抜き差しして以下のコマンドを実行。ウインドウが開き、左サイドバーにあるStereo ModuleとRGB Cameraをoffからonに。結果が表示されたらOK。
```
$ realsense-viewer
```
⑤ 次のコマンドを実行、realsense の文字列があれば成功。
```
modinfo uvcvideo | grep "version:"
```
  
## 2. ROSラッパーのビルド
① githubからクローン。以下を実行。
　catkin_make は catkin build でもOK。noeticの場合は最後の1行が必要。
```
$ cd ~/catkin_ws/src
$ git clone https://github.com/pal-robotics/ddynamic_reconfigure.git
$ catkin_make
$ git clone https://github.com/IntelRealSense/realsense-ros.git
$ catkin_make
$ git checkout ros1-legacy
```
② 動作確認 
以下を実行、トピックを確認できればOK。
```
roslaunch realsense2_camera rs_camera.launch
```

# 結論
パソコンの実行環境をかえるたびに調べる手間を省ける。
Javaで「配列の要素の初期化と規定値」の動作を確認してみた

# 概要

Javaで「配列の要素の初期化と規定値」の動作を確認してみました。
以下のページを参考にしました。

https://www.javadrive.jp/start/array/index5.html

# 実装

以下のファイルを作成しました。
```JSample5_1.java
class JSample5_1{
  public static void main(String[] args){
    int[] i = new int[1];
    System.out.println("int : " + i[0]);

    long[] l = new long[1];
    System.out.println("long : " + l[0]);

    double[] d = new double[1];
    System.out.println("double ; " + d[0]);

    boolean[] b = new boolean[1];
    System.out.println("boolean : " + b[0]);

    String[] str = new String[1];
    System.out.println("String : " + str[0]);
  }
}
```
```JSample5_2.java
class JSample5_2{
  public static void main(String[] args){
    String[] str = {"Apple", "Orange", "Melon"};

    for (int i = 0; i < 3; i++){
      System.out.println(str[i]);
    }
  }
}
```

以下のコマンドを実行しました。
```
$ javac JSample5_1.java 
$ java JSample5_1 
int : 0
long : 0
double ; 0.0
boolean : false
String : null
```
```
$ javac JSample5_2.java 
$ java JSample5_2 
Apple
Orange
Melon
```

# まとめ

何かの役に立てばと。
ブックマークの親フォルダを取得する【Chrome拡張開発】

# はじめに

ブックマーク関連のChrome拡張機能開発において
「ブックマーク」ではなく「フォルダ」を取得する方法について

# 必要な権限

`manifest.json`に以下の記述が必要です。
```json
"permissions": ["bookmarks"]
```

# ブックマークの「フォルダ」の仕組み

> URL が NULL または指定されていない場合は、フォルダになります。

https://developer.chrome.com/docs/extensions/reference/api/bookmarks?hl=ja#method-get:~:text=URL%20%E3%81%8C%20NULL%20%E3%81%BE%E3%81%9F%E3%81%AF%E6%8C%87%E5%AE%9A%E3%81%95%E3%82%8C%E3%81%A6%E3%81%84%E3%81%AA%E3%81%84%E5%A0%B4%E5%90%88%E3%81%AF%E3%80%81%E3%83%95%E3%82%A9%E3%83%AB%E3%83%80%E3%81%AB%E3%81%AA%E3%82%8A%E3%81%BE%E3%81%99%E3%80%82

「ブックマークとは、特定のページの**URLを保存する**機能」である 
=「URLがなければ、ブックマークではない何か」である
=「それをフォルダとする」

このような仕組みのようです。
フォルダとブックマークを同じテーブルとして管理できる、効率の良い仕組みですね。

# 「フォルダ（親）」の取得方法
```js
const parent = chrome.bookmarks.get(id) //idにフォルダ（親）のidを入れる
```

これで取得可能です。

フォルダ名を取得したいときは

```js
// 先程の続き
parent[0].title
```

で取得可能

その他のプロパティはこちら

https://developer.chrome.com/docs/extensions/reference/api/bookmarks?hl=ja#type-BookmarkTreeNode

# 「フォルダ」のidを取得したい時
特定のブックマークの親（フォルダ）を取得したい時には
まずブックマークを取得し、
そのブックマークから所属する親フォルダidを取得します。

```js
chrome.bookmarks.search(query, function(bookmarks) {
  bookmarks.forEach(async function(bookmark) {
    const parent = await chrome.bookmarks.get(bookmark.parentId);
    console.log(parent[0].title + ' / ' + bookmark.title)
    // フォルダ / ブックマーク名 というログになる
  })
})
```

`async / await` は `chrome.bookmarks.get` がプロミスを返すため使用しています。

## 関連記事：ポップアップの検証（開発者ツール）

`console.log()` の確認方法はこちら

https://qiita.com/kohki_takatama/items/40097202014a6a0adfaf

# おわりに

以上、ブックマークの「フォルダ」についてでした。

次は何を書こうかしら・・・
ChatGPT-3.5先生へ。大学入試問題の解答をurlとidの指定で、できませんでした。

・これができたら、助かります。
```
https://mathexamtest.web.fc2.com/2015/201511613/2015116130100mj.html#top-0110
の解答を日本語でお願いします。
```

ウェブを検索しています...

# 以下の問題です。
2015　兵庫県立大学　前期MathJax工学部
【５】　次の値を求めよ．
(1)cos2π/9+cos4π/9+cos8π/9
(2)cos2π/9 cos4π/9 cos8π/9

https://mathexamtest.web.fc2.com/2015/201511613/2015116130100mj.html#top-0110
ステキな問題です。

# 結果
???どの問題を表しているか、わかりませんでした。

問題1: 次の値を求めよ。
(1) √49
(2) log2(8)


# いつもと違うおすすめです。

https://qiita.com/mrrclb48z/items/5f57eac92aaca30e85c0
【Python】socket使ってみた

マシン間でデータをやり取りしたくなることありますよね？
ということで初めてsocket使ってみました。
(といいつつ今回のサンプルはlocalhostです)

ソケットそのものについては省略。

https://ameblo.jp/bakery-diary/entry-12754672383.html

## 使うもの
```socket```モジュールを使用する。それだけ。標準ライブラリなのも良い。

予めサーバー側で準備しておいた後、クライアントとサーバーのやり取りは以下のようにされる。

```mermaid
sequenceDiagram
    participant クライアント
    participant サーバー
    クライアント->>サーバー:接続要求(connect)
    サーバー->>クライアント:接続確認(accept)
    クライアント->>サーバー:データ送信(send)
    サーバー->>クライアント:データ受信(recv)
    クライアント->>サーバー:データ送信(send)
    サーバー->>クライアント:データ受信(recv)
    クライアント->>サーバー:接続終了(close)

```

## サーバー側での接続前準備(socket, bind, listen) + 接続

```python: server.py
import socket

# サーバーのIPアドレスとポート番号
host = 'localhost'
port = 12345

# socketオブジェクトの作成
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# IPアドレスとポートをソケットにバインド
server_socket.bind((host, port))

# クライアントからの接続を待ち受ける
server_socket.listen()

print(f"Listening on {host}:{port}...")

# 接続の受け入れ
client_socket, addr = server_socket.accept()
print(f"Connected by {addr}")

# クライアントからのデータを受信
data = client_socket.recv(1024)
print(f"Received: {data.decode()}")

# クライアントへデータを送信
client_socket.sendall(b'Hello from server!')

# 接続のクローズ
client_socket.close()
server_socket.close()

```

### クライアント側による接続
```python: client.py
import socket

# サーバーのIPアドレスとポート番号
host = 'localhost'
port = 12345

# socketオブジェクトの作成
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# サーバーに接続
client_socket.connect((host, port))

# サーバーへデータを送信
client_socket.sendall(b'Hello from client!')

# サーバーからのデータを受信
data = client_socket.recv(1024)
print(f"Received: {data.decode()}")

# 接続のクローズ
client_socket.close()

```

## 動作

1. terminalを2つ立ち上げる
1. 1つ目のterminalで```python server.py```を起動する
1. 2つ目のterminalで```python client.py```を起動する

今回の場合、結果は以下のように出力される。

```text:server output
Listening on localhost:12345...
Connected by ('127.0.0.1', 64120)
Received: Hello from client!
```

```text:client output
Received: Hello from server!
```

無事にclient側でサーバーからのデータを受信できていることが確認された！

## Option(超ざっくり)

###  アドレスファミリー
|アドレスファミリー|説明|指定するアドレス|
|-|-|-|
|AF_UNIX|ローカル通信用|ソケットファイルのパス|
|AF_INET|IPv4|ホスト名、ポート番号|
|AF_INET6|IPv6|ホスト名、ポート番号|

### ソケットタイプ
|アドレスファミリー|説明|
|-|-|
|SOCK_STREAM|TCP|
|SOCKDGRAM|UDP|

## 参考記事
書いた後にすごくまとまった素晴らしい記事を見つけました。
南無。。。

https://qiita.com/t_katsumura/items/a83431671a41d9b6358f
Qiita 投稿マラソン 2024 またの名を 人はいかにして学びの機会を捻出するか - DevOps 編 3 日目 Azure Boards

[Qiita Engineer Festa 2024（キータ・エンジニア・フェスタ 2024） - Qiita](https://qiita.com/official-campaigns/engineer-festa/2024)

> 投稿マラソン
> Qiita Engineer Festa 2024 の記事投稿キャンペーンに紐づけて19記事投稿すると、「Qiitaオリジナルグッズ」を必ずプレゼント！38記事投稿すると更に特別な「Qiitaオリジナルグッズセット」を必ずプレゼント！

とのことで「学び」を強制的に自分に課したいな、どこまで走れるか分からないがちょうど目の前に、学びたい [Azure DevOps Services | Microsoft Azure](https://azure.microsoft.com/ja-jp/products/devops) があるじゃない、これをテーマに走り出してみたら良いじゃないという個人的コミット駆動です。

3 日目です。テーマ詳細に入ってまいります。

ここまでの記事: 
[Qiita 投稿マラソン 2024 またの名を 人はいかにして学びの機会を捻出するか - DevOps 編 開会宣言 #AzureDevOps - Qiita](https://qiita.com/e99h2121/items/02fcccdc257a0c534fff)
[Qiita 投稿マラソン 2024 またの名を 人はいかにして学びの機会を捻出するか - DevOps 編 2 日目 Azure DevOps Labs #AzureDevOps - Qiita](https://qiita.com/e99h2121/items/f3e9672103aead998379)



## 本日のタイトル: Azure Boards

[Azure Boards とは - Azure Boards | Microsoft Learn](https://learn.microsoft.com/ja-jp/azure/devops/boards/get-started/what-is-azure-boards?view=azure-devops)

> Azure Boards は、チームが開発プロセス全体で作業を計画、追跡、議論できる Web ベースのサービスであり、アジャイル手法をサポートします。 Azure Boards には、作業項目を管理するためのカスタマイズ可能なプラットフォームが用意されており、チームは効率的に共同作業を行い、ワークフローを合理化できます。


引用: [Azure Boards ハブ](https://learn.microsoft.com/ja-jp/azure/devops/boards/get-started/what-is-azure-boards?view=azure-devops#azure-boards-hubs)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93824/60e99cd1-d363-9364-0ec3-9ecbd7cf0968.png)

カンバンです。上だけ見ていると、昔使った JIRA を思い出します。Redmine とかも。

[Jira vs Azure DevOps | Atlassian](https://www.atlassian.com/ja/software/jira/comparison/jira-vs-azure-devops)

関連:
[プロジェクトのタスク管理をどこでやるか、検討の記錄 22.01 #GitHub - Qiita](https://qiita.com/e99h2121/items/25217220c8d2c80fa633)
[オンラインでプランニングポーカーができる、Plapoが楽しかったので紹介する #アジャイル - Qiita](https://qiita.com/e99h2121/items/2bc505415e1ccfd2ff95)


用語が以下にまとまっているので暗記項目というか、知っているとお得かもしれません。


https://learn.microsoft.com/en-us/azure/devops/boards/boards/kanban-overview?view=azure-devops#kanban-concepts-and-terms

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93824/9d7394e3-aa79-c59e-708d-e8427bafefb6.png)



なんだかんだお値段が気になりますので、以下も観ます。

[Azure DevOps を1年間使ってみて押さえておくべきと思ったこと - MassKaneko.Out](https://masskaneko.hatenablog.com/entry/2020/12/06/005011)

> OSS で言えば Redmine + Gitea + Jenkins、アトラシアン製品で言えば JIRA + Bitbucket + Bamboo に相当します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93824/fa44ced7-5adc-8b12-b576-e56d3c1fd8bd.png)

でもこの辺りはチームでも使いやすいかもしれないです。
[チーム ダッシュボードの追加、名前変更、削除、管理 - Azure DevOps | Microsoft Learn](https://learn.microsoft.com/ja-jp/azure/devops/report/dashboards/dashboards?view=azure-devops)



## 本日のまとめ

タスク管理悩ましいですよね。究極 Excel でもできるし、チャットでもできる。
以下記事も見つけました。

2024.06.13 個人的注目記事
[こんな個人向けタスク管理アプリないですかね？ #Webアプリケーション - Qiita](https://qiita.com/G_R_/items/83f39cc9fdac7014f688)
[Sunsama - Make work-life balance a reality.](https://www.sunsama.com/)
[ワイ専用のタスク管理アプリを作りました #Webアプリケーション - Qiita](https://qiita.com/G_R_/items/efda47c2c820c8870b7f)


つづく

明日は [Azure Pipelines | Microsoft Azure](https://azure.microsoft.com/ja-jp/products/devops/pipelines/)
map関数で{}と()どちらを使用するかよくわからなかった件 〜アロー関数について〜

## はじめに
Reactでmap関数を使用するときに{}と()のどちらを使用するのか理解できていなかったので今回はそれについてまとめます。

先に言ってしまえばこれはmap関数の問題ではなくJavaScriptのアロー関数への理解度が低いことが問題でした。

## 問題点
Reactで以下のコードを書いていました。
ボタンを押下したら```onClickFetchUser```関数が走り、その中で```axios```を使用してデータを取得し、取得した内容を画面上に表示させるというコードです。
```jsx
    <div className="App">
      <button onClick={onClickFetchUser}>データ取得</button>
      {userProfiles.map((user) => {
        <UserCard key={user.id} user={user} />
      })}
    </div>
```
しかしボタンを押下しても画面には何も表示されません。

## 原因
mapの中で```return```を記述せずに{}を使用していたことが原因でした。

そもそもなぜこのような書き方をしてしまったかというと、Reactでコンポーネントを作成する時に以下のような書き方をするため、この書き方と混同していたためです。

```jsx
{/* Userコンポーネントを作成する場合 */}
export const User = () => {
    return (
    {/* 処理 */}
    )
}
```
同じようにreturnを書いていれば問題ないのですがアロー関数が```=>```以降のものを自動的にreturnするということが抜けていました・・・

## 解決策
上記のように{}を使用する場合は必ずreturnを明示する必要があります。個人的にはこれが一番わかりやすいです。
```jsx
      {userProfiles.map((user) => {
        return <UserCard key={user.id} user={user} />;
      })}
```

また、次のような書き方も可能です。
このようにアロー関数内の処理が1行の場合は{}とreturnは省略することができます。
```jsx
      {userProfiles.map((user) => (
        <UserCard key={user.id} user={user} />
      ))}
```
同じくアロー関数内の処理が1行の場合、次のように```=>```直後の()も省略可能です。
```jsx
    {userProfiles.map((user) => <UserCard key={user.id} user={user} /> )}
```

## 終わりに
アロー関数について改めて整理ができました。
Azure Functionsの出力バインディングにCosmosDBを設定した後にfunction.jsを編集しないと「'CosmosDB' does not exist」と言われる

# 事象
Azure Functionsの統合の出力から出力先にCosmosDB追加した場合、`context.bindings.outputDocument` を使ってCosmosDBに挿入することができる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192137/0346208f-bb96-3d52-22cf-673d996a2484.png)

### コードサンプル
```javascript
module.exports = async function (context, myBlob) {
    context.log("JavaScript blob trigger function processed blob \n Blob:", context.bindingData.blobTrigger, "\n Blob Size:", myBlob.length, "Bytes");
    const output = { "userId": 2, "message": "test" }
    context.bindings.outputDocument = JSON.stringify(output);
};
```

が、このまま実行し「呼び出し」タブを見ると`'CosmosDB' does not exist`といわれる。
```
Cosmos DB connection configuration 'CosmosDB' does not exist. Make sure that it is a defined App Setting.
```

# 対策
function.jsonを編集する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192137/81263475-6277-3872-a035-8d6a28dc3373.png)

### 編集例
collectionName -> containerName
connectionStringSetting -> connection
にする
```diff
{
  "name": "outputDocument2",
  "direction": "out",
  "type": "cosmosDB",
  "methods": [],
  "databaseName": "outDatabase",
-  "collectionName": "MyCollection",
+  "containerName": "MyCollection",
-  "connectionStringSetting": "CosmosDbConnectionSetting"
+  "connection": "CosmosDbConnectionSetting",
}
```

# 参考
https://stackoverflow.com/questions/77143924/azure-function-with-output-to-cosmosdb
Azure Functionsの出力バインディングでCosmosDBにinsertする時はIDを独自で指定しなければならない

# 事象
Azure Functionsの統合で出力を設定し出力バインディングを作った。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192137/9f496a1f-103e-76e3-db67-314b33acd8f6.png)

### コードサンプル
```javascript
module.exports = async function (context, myBlob) {
    context.log("JavaScript blob trigger function processed blob \n Blob:", context.bindingData.blobTrigger, "\n Blob Size:", myBlob.length, "Bytes");
    const output = { "userId": 2, "message": "test" }
    context.bindings.outputDocument = JSON.stringify(output);
};
```

### 遭遇したエラー
上のコードを実行すると以下のようなエラーが発生する
```
One of the specified inputs is invalid need id function
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192137/48965b07-d5d9-1009-5558-920009291036.png)

# 対策
どうやらIDは自動で設定されないらしい。Node.js SDKから実行するとIDを自動生成してくれるが、Azure Functionsから書き込む場合は設定されない。

:::note warn
**お願い**
Azureの公式情報やQ&Aの記事で上記の仕様についての記載を見つけられませんでした。もしご存じの方がいたらコメントください。
:::

### 修正版コード
UUIDを取得してidにセットしています。
```javascript
module.exports = async function (context, myBlob) {
    context.log("JavaScript blob trigger function processed blob \n Blob:", context.bindingData.blobTrigger, "\n Blob Size:", myBlob.length, "Bytes");
    const uuid = crypto.randomUUID();
    context.log("insert CosmosDB ID:", uuid);
    const output = { "id": uuid, "userId": 2, "message": "test" }
    context.bindings.outputDocument = JSON.stringify(output);
};
```
【閑話休題】TM技術のモデル図を作ってみた！


# 目次
- [まえがき](#まえがき)
- [モデル図](#モデル図)
- [おわりに](#おわりに)

# まえがき

前回の投稿から、だいぶ時間が経ってしまいました。
面目ない！
※この間に、JSTQBのALTM試験を受けて玉砕(不合格)しました。。。😢


本編のほうを書くべきなのですが、今日はリハビリがてらTM技術のモデル図を作ってみました！

第4回までの記事をお読みになった方で、「じゃぁ、そのモデル図って一体なんなのさ！」と突っ込んでいらっしゃると思い、ここでそのモデル図を書き出してみたいと思います！


急に思い立ったため、超アナログ(ノートに付箋をつけて作った)ですが、イメージだけ掴んでいただけたら幸いです！


参照元は引き続き、[事業分析・データ設計のためのモデル作成技術入門](https://gihyo.jp/book/2022/978-4-297-12946-0)から、サンプルを参照しながら書いていきます！


[<img width = 200 src = http://image.gihyo.co.jp/assets/images/cover/2022/9784297129460.jpg>](https://gihyo.jp/book/2022/978-4-297-12946-0)



# モデル図
参考にしている本から、「受注入力画面」「請求照会画面」の機能を抜き出してモデル図を作ると、こんな感じになります。
※手作り感満載で、すみません。
![FC75A525-FE73-42C9-81EF-3734A74C5338.JPEG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/310259/63582dac-c25b-7ad0-9e07-572e878ce4fb.jpeg)

画面の遷移としては、「受注入力画面」→「請求照会画面」の順で遷移していく形になります。


このモデルでは、「受注」というEventに対して、「顧客」「商品」という2つのResourceが、**1 ：多**で結ばれています。
これによって、「1人の顧客から、複数の受注データを受ける」という見方が出来、入出力する(される)データの数がわかります。


またデータの数と共に、受注→請求という流れでEvent同士も同じように結ばれています。
これが、「処理の流れ = **ユーザーストーリーの流れ**」となります。


処理の流れを「先行→後続」のEventで表し、Eventが参照しているデータをそれぞれのResourceから引っ張っている状態。また、扱うデータの数の本数を表しているのが、このモデルが指し示しているものになります。
※結んでいる線の形や、その他の詳しいことは、後の記事にて掲載します。


# おわりに
このモデル図を作成して、以下のことを実現したいと考えています。
1. テスト計画の策定時に、テストすべき処理の流れや処理全体をパッと見てわかることにより、テスト範囲を分かりやすくする。
2. テスト分析や設計時に、Eventに紐ずくResourceの数で、参照するものが足りてる or 足りていない(充足 or 不足)を判断して、仕様バグがないか判別したい。
3. ドキュメントの数を減らして、**全員共通のインプット**として使いたい。
4. 障害発生時に、モデル図から「影響している範囲(どのEventの、どのResourceが不具合を生じているか)」を直ぐに判別できるようにしたい。
5. 新しい機能を追加する際の、分析・設計用の図として使いたい。

他にも、いくつかありそうですが、大きくいうと上の5つとなるでしょう。

とにかく、プロダクトやシステムを作る時には「**プロダクトやシステムの現在の状態を表して**、テストを導出させたい」というのが目下の目標です。


これを行うことによって、「**品質の本質を捉えたテストが可能**」であると考えます。
その本質とは、「**関わる人たち(ステークホルダー)との約束を守る、そしてその約束を守り続ける**」ことです。

これが、QA歴10年目の私が思う「**QAエンジニアが品質保証活動を行う理由・目的**」です。


このことを胸に、TM技術によるモデルベースドテストの構築やこれからの品質保証活動を行っていく所存です。




さて、リハビリも終わったところで次回からは本編のほうに戻ります！第5回目です！

近日中には書く予定ですので、お見逃しなくっ！


では、また！