OmniAICreator/Qiita-1.07M huggingface dataset:
「問い」のデザイン | Designship 2024の学び


## 1. はじめに：Designshipでの発見
初めて [**Designship**](https://design-ship.jp/2024) に参加してきました！数々のセッション（講演）や展示でデザインの最前線に触れることができ、たくさんの刺激を受けました。いくつかの印象に残った講演をまとめていけたらと思います。

今回は菅俊一さんによる「問いが世界を拡げていく」という講演の振り返りと私自身の感想を交えてご紹介します。


## 2. 問いが注意を操作する仕組み
この講演では、日常の中で「見えているけれど見えていないもの」に気づくための方法として、「問いを立てること」がいかに重要かが語られました。
### 2.1 写真を用いた注意の向け方の変化
講演では、写真を例に問いが注意を操作する仕組みが紹介されました。

<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2217078/922d1aa3-a590-2340-b530-deffbeac52e5.jpeg">


- 「何か気になるものを探して」と言われた場合：  
  注目点が曖昧になり、どこを見ればよいか分からない。
  
- 「黄色くて丸いものを探して」と条件を付けられた場合：  
  指定された特徴に基づき、視覚的に絞り込むプロセスが発生。

この違いは、「問いが注意の焦点を定める力」を直感的に示しています。

### 2.2 注意を引く仕組みづくり
もう一つの例として、土足禁止エリアの事例が挙げられました。
![shoes_03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2217078/26cd9593-8028-effb-49b5-b5e56ac58e35.png)

- **注意パネルのみの場合**：  
  目に入らず、誤って土足で上がる人が多かった。
  
- **ダミーの靴を置く場合**：  
  注意が自然と引き寄せられ、間違う人がいなくなった。

禁止を押し付けるのではなく、ユーザーの自然な行動を促す仕組みづくりの重要性が示されました。

### 2.3 シャインマスカットの例：行動を操作するデザインの工夫
**シャインマスカット** のエピソードは、行動を操作するデザインの工夫の面白い例です。

<img width="200" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2217078/fc8eaba4-9970-dd00-cd59-b848ccd146c1.png">


- あるの年、冷蔵庫に「ご自由にお召し上がりください」とだけ書かれたシャインマスカットの差し入れが置かれていた。  
  このままだと、「何粒食べていいのか」「全部食べても良いのか」と迷いが生じ、誰も手をつけることができなかった。

- 翌年、シャインマスカットはカップに分けられ、「ご自由にお召し上がりください」と書かれた状態で提供された。  
  この変更により、迷いが解消され、多くの人が気軽に食べることができました。

「食べようとしやすくする」ための工夫が行動を変える力を持つことを示しています。


## 3. ヒアリングやUXデザインへの応用

### 3.1 ヒアリングでの問いの工夫
ヒアリングを行う際にもさまざまな問いを用いて注意の向け方を操作することで、相手に気づきを与えるプロセスが行われているのではと考えました。
問いを使って相手の注意を操作することで、潜在的なニーズを引き出すことができます。

- 「普段困っていることは何ですか？」  
  → 「もっとスムーズになったら嬉しい作業は何ですか？」  

質問の焦点を明確にすることで、より具体的な回答を得られるようになります。

### 3.2 業務システムのUXデザイン
複雑な業務システムでは、適切な問いや条件付けによって注意を操作し、ユーザーの迷いを軽減することが可能です。

- **具体例**：
    - 必須項目を赤いアスタリスクで示し、完了していないタスクを黄色でハイライト 
    - フォーム入力時に、入力フィールドの横に関連するヘルプテキストやサンプルを表示
    - エラー時、「赤枠＋具体的な改善例」を表示


## 5. まとめ：デザインにおける問いの重要性
講演を通じて、「問いを立てること」が新しい気づきやデザインの可能性を広げる鍵であることを学びました。特にUI/UXデザインでは、注意を引き、適切な行動を促す仕組みを取り入れることで、ユーザー体験の向上が期待できます。

デザインにおける問いは、単なる「気づき」を促すだけでなく、ユーザーに新しい視点を提供し、より直感的で心地よい体験を作り出す力を持っています。今後、問いを意識して、より使いやすく、気持ちよく使えるインターフェースを目指していきたいです。

---
material-ui v4で、Selectを選択しているときの見た目を変える

# 結論
`Selet`自体をスタイリングするのではなく、`InputBase`をスタイリングして`Select`に渡す

# 方法

https://v4.mui.com/api/input-base/#css

material-uiの`withStyles`などを使ってスタイリングする場合は、上記ドキュメントの`CSS`の`Rule name`に対してスタイリングを適用していきます。
選択している状態のスタイルは`focused`に書いていきます。

styled-componentの`styled`を使ってスタイリングする場合は、上記ドキュメントの`CSS`の`Global class`が割り当てられている場合に対してスタイリングを適用していきます。
選択している状態のスタイルは`&.Mui-focused`に書いていきます。


```tsx
import { InputBase, Select, MenuItem } from "@material-ui/core";

const StyledInputBase = withStyles(() => ({
  root: {
    outline: '1px solid black',
  },
  focused: {
    outline: '1px solid red',
  }
}))(InputBase);
```

```tsx
import { InputBase, Select, MenuItem } from "@material-ui/core";
import styled from "styled-components";

const StyledInputBase = styled(InputBase)`
  outline: 1px solid black;
  &.Mui-focused {
    outline: 2px solid red;
  }
`
```

あとは、作成した`StyledInputBase`を`Select`に渡します。

```tsx
<Select
  input={<StyledInputBase />}
  variant="outlined"
>
  <MenuItem value="foo">foo</MenuItem>
  <MenuItem value="bar">bar</MenuItem>
  <MenuItem value="baz">baz</MenuItem>
</Select>
```

このように、`Select`が選択されているときの見た目を変えることができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3640003/23b2a7c1-525b-0f46-f323-1f8d18ba43ab.png)

# 参考記事

https://zenn.dev/ryoryo16/articles/076cc7e7391467
rex0220 計算式プラグイン 文字列からチェックボックスをセット

[計算式プラグイン](https://qiita.com/rex0220/items/ae83c6d5ce50ff7a9a73)で、カンマ区切りの文字列からチェックボックスをセットする例です。

# 概要

カンマ区切りの文字列からチェックボックスの選択肢をチェックします。
チェックボックスは、複数の選択肢を持つため値を配列で設定します。

![2024-12-03_11h27_55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/39fd74e8-627f-89c0-d378-915f5566c446.png)

# 操作例

![2024-12-03_11h30_50.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/a5ba7424-1642-b466-4daa-fa43b6841f3d.gif)

# 計算式プラグイン設定

カンマ区切りを SPLIT 関数で配列に変換し、ARRAY_MAP と TRIM 関数で前後の空白を削除。
INTERSECT 関数で、チェックボックスの選択肢と突き合わせて、有効な選択肢をセットします。

![2024-12-03_11h28_43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/97b7494b-5a2b-bbe7-583d-7f03aa80be68.png)

```.js
// チェックボックス CHECK_BOX
INTERSECT(
  ARRAY("ABC","DEF","GHI"),  // 選択肢
  ARRAY_MAP(SPLIT(文字列,",",1),x,TRIM(x))  // 文字列
)
```

# 計算式で利用している関数の解説

- ARRAY 関数
    - 指定された値を配列に変換します
    - 例 ARRAY("ABC","DEF","GHI") -> ["ABC","DEF","GHI"]
- SPLIT 関数
    - 指定された文字列を指定された区切り文字で配列に変換
    - 例 SPLIT("AB,X,Y,,Z ",",") -> ["AB","X","Y","","Z "]
    - 第3パラメータで、1 を指定すると空文字要素を削除
    - 例 SPLIT("AB,X,Y,,Z ",",",1)　-> ["AB","X","Y","Z "]
- ARRAY_MAP 関数
    - 配列の要素を式で変換
    - 例 ARRAY_MAP(ARRAY("A","B","C"),x,"A"&x) -> ["AA","AB","AC"]
- TRIM 関数
    - 文字列から先頭および末尾の空白を削除
    - 例 TRIM(" AB ") -> "AB"
    - 例 ARRAY_MAP(ARRAY("A ","B "," C"),x,TRIM(x)) -> ["A","B","C"]
- INTERSECT 関数
    - 配列の積集合（両方の配列に存在する値を配列で返す）
    - 例 INTERSECT(ARRAY("A","B","C"),ARRAY("B","C","D")) -> ["B","C"]
ポーランドから日本へ：理想の職場環境との出合い

この記事は、[GLOBISアドベントカレンダー2024](https://qiita.com/advent-calendar/2024/globis) 4日目の記事です。

こんにちは！「GLOBIS 学び放題」のフロントエンドエンジニアをしているAgataです。

ポーランドから日本に移住し、ちょうど2年が経ちました。日本での生活にすっかり慣れ、充実した毎日を送っています。この記事では、初めて日本に移住し、日本の会社（グロービス）で働いた経験をご紹介します。

## 運命の面接

ポーランドから日本へ移住するにあたり、仕事を見つける必要がありました。在留資格を取得する前だったこともあり、不安な気持ちを抱えながら、職探しを始めました。

さまざまな企業の面接を受けるなかで、グロービスの面接が印象的だったことを覚えています。

面接の雰囲気が明るく、知り合いと話しているような話しやすさがありました。フロントエンドエンジニアとしてのスキルだけでなく、自分の性格や考えについて深掘る質問がありました。

面接を通して親和性を感じ、この環境で一緒に働いてみたいと感じました。


## オンボーディング
全く異なる環境で働くことは不安でしたが、入社後のサポート（オンボーディング）も手厚く助かりました。グロービスでは全社的に「オンボーディングサポーター制度」が導入されているため、私にも先輩エンジニアが付き、フォローしていただけました。

オンボーディング期間中、毎日、先輩社員と1on1を行い、疑問や問題をその場で解決することができました。業務に直接関係することだけでなく、社内手続きなどに関しても丁寧に説明いだけました。

## 開発スタイルの違い 〜チームワーク〜

前職（ポーランド）では、社内向けダッシュボードの開発をしており、チャートデータの処理など、複雑なロジックの実装を担当していました。そのため、パフォーマンス改善に関するスキルを身につけました。開発スタイルとしてはひとりで進める事が多く、そのようなスタイルが自分に合っていると感じていました。

現在の職場では、チームで動くことが多く、ソフトスキル面での成長も実感しています。初めてお客様向けの大規模なサービスのメンテナンスを担当する機会を得ました。コンポーネントの大きなアップデート、POとデザイナーとともに新機能の開発、他チームとのコミュニケーション、さらにお客様からのお問い合わせ対応など、これまで経験したことのない新しい業務に取り組んでいます。

前職では、フロントエンドエンジニアがチームに私一人だったため、エンジニア同士の交流はありませんでした。グロービスではシニアフロントエンドエンジニアの方々から多くの知識を吸収することができました。仕事に慣れてきた後は、アクセシビリティの向上など、自分からも改善提案を行うようになりました。

他にも、バックエンドエンジニアがフロントエンド開発に挑戦する際に、ペアプログラミングを通じて自分の知識を提供したり、逆に私も教わる側に回ることもあります。このようにメンバーが互いに刺激を与えながら、成長できているように感じます。
自分の成長はチームワークのおかげだと思います。


## 言葉の壁

入社した時点で、ある程度日本語を話すことができ、日本語能力試験N2の資格も持っていました。しかし、実際に働いてみると、コミュニケーションの面で不足している部分があることに気づきました。特に、難しい資料を読むのに時間がかかったり、複雑な会話を理解できなかったりしました。

そこで、グロービスのサポートを利用して、日本語レッスンの料金の一部を負担していただきました。そのおかげで、入社から半年後に日本語能力試験N1に合格することができました。

それでもやはり漢字に苦手意識がありました。そこで、マネージャーの提案で、社内の個人成長目標として最終的に漢字検定3級の合格を目指すことにしました。1年前に9級からスタートし、現在は6級に合格して、5級の勉強を進めています。最近では、専門的な本も読めるようになり、チャレンジして本当によかったと感じています。

## 最後に
日本に移住してから2年間グロービスで働き続けており、この選択をして本当に良かったと考えています。

同僚たちはみな親切でコミュニケーションが取りやすく、定期的に開催されるチーム、部門の懇親会も楽しみの一つです。また、ワークライフバランスも取れており、心身の健康を保ちながら成果を出せる環境だと感じています。

これから日本で仕事探しをされる皆さんが、自分に合った働きやすい環境と出合えることを祈っています！
子供でもわかる『情シス』『コーポレートIT』について

## はじめに
ITにまつわるあれこれって英語・カタカナ多すぎない！？問題
ただでさえ英語苦手なのに、頑張って翻訳しても結局意味が分からない（実際和製英語だったりする）
とはいえリテラシーがあまり無い人に上手く説明するにはどうしたらよいか？と考えた時、「そうだ生成AIさんに聞こう」となった次第です。
現在行っている仕事や、彼氏・彼女・親・友達がどんなことをやっているのか？ざっくり概要だけでも知る機会になればよいなと思ってます。

## 『情シス』
コーポレートITを知る前に、昔から存在する「情シス」という仕事について見ていきましょう。

> 情シス（情報システム部門）の仕事を生活に例えると、「家の便利さを守るお手伝いさん」みたいなものです！
> **①道具をそろえる人**
> パソコンやスマホは、生活で使う道具みたいなもの。情シスは、その道具がきちんとそろっていて、ちゃんと動くようにしてくれるんだ。
> **②壊れたら直してくれる人**
> 電気がつかなくなったり、水道が出なくなったりしたら困るよね。情シスは、そういう「困った！」が起きたらすぐに直してくれるんだよ。
> **③新しいアイデアを考える人**
> 「こんな便利な道具があったら、もっと楽になるかも！」って考えて、それを実際に使えるようにしてくれるんだ。
> **④家のカギを守る人**
> 情シスは、家に泥棒が入らないようにしっかり鍵をかけたり、防犯カメラをつけたりする役割もしているよ。これをパソコンやネットでやってくれるんだ。
> **つまり、情シスは、みんなが快適に、安心して仕事や遊びをできるように支えてくれる「家のお助けチーム」みたいな存在なんだよ！**

これは面白い！
十数年前は、上記にあるような道具もシンプルで、専門性が高くなくても用意したり直したり出来たなぁ、とか。
鍵だって時代の進化でピッキングしにくいものや生体認証も作られていて、重要な資産であればあるほど"しっかり鍵を閉める"ことが大事

とはいえ
**「情シス」は、家（会社）に対するお手伝いさんやお助けチーム**
という考えを悪く解釈すると
・お金が無いから（優先順位が低いから）雇えない
・外部を雇わず自分達でなんとかする！（なんとかなってない）
・お金生み出せないなら最小限のコストに抑える
と考えてしまう家（企業）もあるのだろうな、と。

Qiitaで記事を読むような皆様なら情シスの重要性は理解しているものの、世間一般に向けた説明だと悪い部分が目立ってしまうような『情シス』
本題の『コーポレートIT』ではどうなるのか？

## 『コーポレートIT』
普通にコーポレートITを聞くと以下のような感じ
> コーポレートITは、企業内のIT環境を整備・管理し、業務効率化やセキュリティ確保を支える部門です。

うーん。分かるような分からないような。

じゃあ生成AIさんに分かりやすくしてもらいましょう。

> コーポレートITを生活に例えると、「町全体を便利で安全にする町役場のチーム」みたいなものです！
> **①町のインフラ整備**
> コーポレートITは、町（会社）が毎日動くために必要な道路（ネットワーク）や電気（水道のようなクラウドサービス）を作ったり管理したりしているんだよ。
> **②住人の手助け**
> 町の住人（社員）が、「この道が通れない！」「電気がつかない！」って困ったとき、すぐに助けてくれる人たちがコーポレートITなんだ。
> **③新しい施設やサービスの計画**
> 「もっと便利な公園（ツール）」や「速い道路（通信環境）」を作るために、新しいアイデアを考えて、みんなの生活（仕事）がもっと良くなるようにしてくれるよ。
> **④町を安全に守る**
> 泥棒（サイバー攻撃）や不正（データ漏えい）から町を守るために、セキュリティをしっかり整えるのも大事な役割なんだ。
> **つまり、コーポレートITは、町全体（会社全体）がスムーズに動いて、住んでいる人（社員）が安心して暮らせるようにする「裏方のヒーロー」みたいな存在だよ！**

裏方のヒーロー・・・
なんと男心くすぐる良い響き・・・ありがとう・・・笑

## 『情シス』と『コーポレートIT』の違い
ただ気になるのは、情シスでは会社を"家"で例え、今回は"街"になった。
コーポレートITの方が広義であること、攻めの手も必要ってことなのかな？と思いつつ、こちらも確認してみた

>情シスを「家」、コーポレートITを「町」に例えたのは、それぞれのスケール感と役割の違いをわかりやすくするためです。
>1. 情シス = 家
>情シスは、会社という「1つの組織」の中での便利さや安全を整える役割がメインです。
>個別の社員（家族）の「このパソコンが動かない」「ネットが遅い」といった日々の問題に対応することが多いです。
>→ だから、「家」という個人的な空間をサポートする役割に例えました。
>2. コーポレートIT = 町
コーポレートITは、企業全体のITインフラや仕組みを戦略的に設計・運営します。
たとえば、全社員に共通するクラウドサービスを導入したり、会社全体のセキュリティポリシーを定めたりする、大規模な視点が求められます。
→ 町という「多くの人が集まり、大きな仕組みで成り立つ」存在に例えました。
まとめ
情シスは「個人や部署の視点」で動き、コーポレートITは「会社全体の視点」で動く。
そのスコープの違いを家と町という例えで表現したのです。どちらも大事で、互いに補完し合う役割です！

おぉ…めっちゃ分かりやすい。
定義ではないものの、これがごっちゃになってる企業の方が多いイメージですけどね

## 最後に
情シスとコーポレートIT、それぞれの役割や視点の違いを「家」と「町」に例えていました。
どちらも企業にとって欠かせない存在であり、互いに補完し合う関係です。

しかし、現実ではこの2つの違いが曖昧だったり、必要性が軽視されたりすることもあります。どちらか一方が弱かったり、存在しなかったりすると、家も町も住みづらくなってしまいますよね。

もし、あなたの職場で情シスやコーポレートITが頑張っている姿を見かけたら、ぜひ一言感謝を伝えてみてください。
「ありがとう！」の一言が、彼らのモチベーションアップにつながります。

ITの世界は、専門用語が多くて難しく見えるかもしれません。でも、少しずつ理解していくことで、会社全体の仕組みや仕事がよりクリアに見えてくるはずです。
これを機に、IT部門の仕事に少しでも興味を持ってもらえたら嬉しいです！
Laravel Sail小技集

# はじめに

みなさんLaravelでのWebアプリケーション開発にはDockerを使ってやってるかと思うのですが、以前紹介したこんな方法を使わずとも今は `Sail`というLaravelの便利機能で超絶簡単に、しかも安定稼働する環境が作れるようになりました。つよい。

https://qiita.com/layzy_glp/items/579b295e8cc899aef2c4

https://readouble.com/laravel/11.x/ja/sail.html

この頃は我らがBoomTechCafeのしゅんくんが色々投稿してくれても居ます。

https://qiita.com/miriwo/items/50b00137bf005699f28e

そんなSailを使うに当たってちょこちょこっとした小技を紹介します。

# PHPのバージョンを変える

Laravel11のSailで構築するとデフォルトではPHP8.3になるんですが、「8.4を使いたい！」「事情があって8.0に落としたい……」等色々ニーズがあると思います。
Laravel11のSailではPHP8.0~8.4の環境が用意されてますので、docker-compose.ymlをいじるだけで簡単に切り替えられます。

```yaml:docker-compose.yml
services:
    laravel.test:
        build:
            context: './docker/8.3'
            dockerfile: Dockerfile
            args:
                WWWGROUP: '${WWWGROUP}'
        image: 'sail-8.3/app'
```

ここの `8.3` ってなってるところを変えるだけです。
一度でも `sail up` してるとすぐには反映されないので、 `sail build` し直しておきましょう。

# Dockerfileを出力する

Laravel Sailを使うに当たって `Dockerfileがvendor下に隠蔽されてる` というのがあると思います。
とりあえずLaravelに触れたいだけならそれでも良いのですが、「入れたいミドルウェアがある」「そもそもDockerfileがないからGitHubActionでビルドしてECRに上げられへん」とかあると思います。
そんなときはこのコマンドを使ってみましょう。

```bash
./vendor/bin/sail artisan sail:publish
```

これでアプリケーションルート直下に `docker` というディレクトリが作られてDockerfileをいじれるようになります。
同時に `docker-compose.yml` 側のcontextの参照先もしれっと変更してくれるので便利です。

# Makefileこんな感じにしました

公式（の翻訳）ドキュメントにも「エイリアスコマンド作ると楽でっせ」って言うのが書かれてるのですが、私はそれすらめんどくさいのでMakefileを作ってます。
この頃は `makeじゃなくてtaskだ` って言ってる勢も多いのは重々承知なのですが、taskのインストールをお願いして回るのも面倒なのでmakeにしてます。

```makefile:Makefile
.PHONY: up
up:
	./vendor/bin/sail up -d
.PHONY: down
down:
	./vendor/bin/sail down
.PHONY: build
build:
	./vendor/bin/sail build
.PHONY: install
install:
	./vendor/bin/sail composer install && ./vendor/bin/sail npm install
.PHONY: migrate
migrate:
	./vendor/bin/sail artisan migrate
.PHONY: seed
seed:
	./vendor/bin/sail artisan db:seed
.PHONY: dev
dev:
	./vendor/bin/sail npm run dev
```

よかったら参考にしてください。
Rails のルーティング

## 大前提

RailsはMVCという設計が主流となっており、データのやり取りの流れは

```markdown
1. HTTPリクエストが送られてきたら、ルーティング（config/routes.rb）でコントローラに仕分けされる
2. コントローラでモデルに対して情報を取得
3. モデルはコントローラから送られてきたデータをDBとやりとりをしてコントローラに返す
4. コントローラでデータを作成して、ビューに渡す
5. ビューでユーザー（リクエスト）に対するレスポンスを表示する
```

となる。
その中の**ルーティング**の話をします

## 今回の題材

**今回解読するコード**

```ruby
#config/routes.rb
resources :posts do
  resources :comments, only: [:create, :index, :update, :destroy]
end
```

順を追って解読していきます。

1. `resources :posts`
    - これは `posts` リソースに対する一般的なRESTfulルーティングです
    - 以下のようなルーティングが生成されています
        - `GET /posts` -> `PostsController#index`　# 一覧を表示
        - `GET /posts/new` -> `PostsController#new`　# 新規作成フォームの表示
        - `POST /posts` -> `PostsController#create`　# 新規作成の送信
        - `GET /posts/:id` -> `PostsControllre#show`　# 特定の投稿の表示
        - `GET /posts/:id/edit` -> `PostsControllre#edit`　# 投稿編集フォームの表示
        - `PATCH/PUT /posts/:id` -> `PostsController#update`　# 特定の投稿の更新
        - `DELETE /posts/:id` -> `PostsController#destroy`　# 特定の投稿の削除
    - `resources`に関するルーティングは[こちら](https://railsguides.jp/routing.html)を参照しました

2. `resources :comments, only: [:create, :index, :update, :destroy]:`
    - これは `comments` リソースに対して、指定したアクション(`create`, `index`, `update`, `destroy`)に絞り込んだルートを定義している。ネストされた形なので、`comments` は必ずその親リソースである `post` に関連付けられる。これにより、コメントは特定の投稿に属することが示される
    - 以下のようなルーティングが生成されています
        - `GET /posts/:post_id/comments` -> `CommentsController#index`　# 特定の投稿に関連するコメントの一覧
        - `POST /posts/:post_id/comments` -> `CommentsController#create` # 特定の投稿に新しいコメントを追加
        - `PATCH/PUT /posts/:post_id/comments/:id` -> `CommentsController#update` # 特定のコメントを更新
        - `DELETE /posts/:post_id/comments/:id` -> `CommentsController#destroy` # 特定のコメントを削除
    - ここで `:post_id` は、親リソースである `post` のIDを指し、各コメントはその `post` に関連づけられている

## ではなぜネストさせるのか？

- ネストさせることでコメントが特定の投稿に紐付いていることを明確に示すことができるため
- コメントを投稿する際などにそのコメントがどの投稿に属しているかをURLで指定できる
    - データベース設計における親子関係がURLにも反映される

## 終わり

railsのルーティングも含めて勝手にやってくれること多すぎて細かく砕いて解釈しないと難しいね
【AWS】EC2 AL2とAL2023の違い ~Linux/Apache~


https://docs.aws.amazon.com/ja_jp/elasticbeanstalk/latest/dg/using-features.migration-al.generic.from-al2.html

EC2のApacheサーバーにNext/Reactの静的ビルドファイルを公開する際にはまったので、備忘録として記載する。

### SELinuxがデフォルトで有効
AL2023ではデフォルトでSELinux(Security-Enhanced Linux)が有効になっている。
有効な状態では、システム上のアプリケーション、プロセス、ファイルに対するアクセスが制限される。

確認コマンドは下記
```
sestatus
```

無効化するには、下記ファイルを修正する。
```/etc/selinux/config
sudo emacs /etc/selinux/config

#SELINUX=permissive 
SELINUX=disabled
```

ファイルを修正後、EC2を再起動する必要がある。

### .htaccessを有効化&定義
Apache httpdの設定ファイル(```/etc/httpd/conf/httpd.conf```)を下記のように修正する。
これで、/var/www/htmlのフォルダ/ファイルへのアクセスが有効化される。

次に```/var/www/html```直下に.htaccessを作成する。

```.htaccess
Options -MultiViews
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ index.html [P,QSA,L]
```

サーバーを再起動する
```
sudo systemctl restart httpd
```

これでNext/ReactのWebサイトへアクセス可能かブラウザから確認する。
もしアクセスできなかった場合は、下記コマンドでサーバーログを確認する。

```
sudo tail -f /var/log/httpd/error_log
sudo tail -f /var/log/httpd/ssl_error_log
```

### ファイル権限

```
chmod -R 755 /var/www/html/******.com
```


## 参考文献

https://httpd.apache.org/docs/2.4/misc/security_tips.html
モデルのscopeについて


初めまして、エンジニア転職目指して学習中のりんころです。
今回railsのscope機能についてちょっとまとめてみました。

 # scope機能って何？

scopeとは、モデル側であらかじめ特定の条件式に対して名前をつけて定義し、その名前でメソッドの様に条件式を呼び出すことが出来る仕組みのことです。

簡単にいうと、モデルで、特定のクエリをメソッド化しておいて、コードが読みやすいようにする機能のことです！

# 【scopeの基本形】

```ruby
class モデル名 < ApplicationRecord
  scope :スコープの名前, -> { 条件式 }
end
```
**例文**
```ruby
class Article < ApplicationRecord
  scope :published, -> { where(status: 'published') } ⬅︎statusカラムがpublishedのデータを抽出するメソッド
  scope :recent, -> { order(created_at: :desc) } ⬅︎Articleモデルのデータを作成時間降順に並び替えるメソッド
end
```

指定したscopeを以下のようにして呼び出せます。

```ruby
#Blogモデルに定義したスコープのpublishedを使用する場合
Blog.published
```

### ⭐️scopeは、コントローラーやviewでも使えます！

### **コントローラーでの使用**

コントローラーでスコープを使うと、特定の条件に合ったデータを簡単に取得できます！例えば、次のように使えます！

```ruby
class ArticlesController < ApplicationController
  def index
    @published_articles = Article.published
  end
end

```

この例では、`published`スコープを使って、公開された記事だけを取得しています。

### **ビューでの使用**

controllerでデータ抽出できたので、もちろんviewファイルでもデータを表示することができます！！
例えば、次のように書けます

```
<% @published_articles.each do |article| %>
  <h2><%= article.title %></h2>
  <p><%= article.content %></p>
<% end %>

```

ここでは、コントローラーで取得した公開された記事をループして表示しています。

スコープを使うことで、ロジックをモデルにまとめることができ、
コントローラーやビューをシンプルに保つことができます！

# scopeのメリット
1. **可読性の向上**: クエリが簡潔になり、コードの可読性が上がります
2. **再利用性**: 定義したスコープは他のクエリでも再利用できます

スコープを使うことでいちいちクエリを書き込む必要がないというのは便利ですね！
最後まで読んでくださりありがとうございました！
UniRXからR3移行時にRepeatオペレーターが廃止されていて困った話

# はじめに
みなさんこんにちは！株式会社グレンジでクライアントエンジニアをしている24新卒の原島と申します。
本投稿は[グレンジアドベントカレンダー](https://qiita.com/advent-calendar/2024/grenge)の4日目の記事です。

# 背景
社内のUnityで開発されているプロジェクトでは今までCysharp社のライブラリであるUniRXを用いてイベントの購読処理を行っていましたが、同じくCysharp社製のRxライブラリであるR3への移行をすることになりました。
R3にはUniRXの互換機能が多く備わっているためほとんどの処理は問題なく置換できたのですが、一部躓いた部分があったので備忘録として共有します！

# 困ったこと
今まではゲーム内で使うボタンのイベント購読処理をUniRXを用いて以下のように行っていました
```csharp
		/// <summary>
		/// タップイベント
		/// </summary>
		private IObservable<CustomButton> OnTapAsObservableInternal() {
			return _onPointerUpSubject
				.SkipUntil(_onPointerDownSubject)
				.TakeUntil(_onPointerExitSubject)
				.TakeUntil(OnStartLongTapAsObservableInternal())
				.Where(data => !data.dragging)
				.Repeat()
				.Select(_ => this);
		}
```

  R3からSubjectがIObservableを実装しなくなったので注意するのはそれくらいかと思い移行してみたところ…
  なんとストリームが完了したあと再度ストリームを生成するRepeat()オペレーターが廃止されていました！困った！


このままではゲーム内の挙動が変わってしまうので代替策を見つける旅へ出ることに。

# 対策①
少し調べると様々な記事でRepeatオペレーターの代替として購読する側でForEachAsync + await + ループを使用する例が紹介されていました。
https://x.com/toRisouP/status/1762496292121674176

```csharp
        while (!destroyCancellationToken.IsCancellationRequested)
        {
            await _button.OnTapAsObservableInternal()
                .ForEachAsync(x =>
                {
                }, destroyCancellationToken);
        }
```
                
挙動的には問題はないのですが、ボタンイベント処理はかなり多くの箇所から使用されており、購読している側すべてを置換するのが中々しんどい…
OnTapAsObservableInternal()関数内で完結させて購読する側は今まで通りである必要があるので断念。
仕様が限定されている実装であればこれで問題ないと思います。

# 対策②
オペレーターがCompleateしたらもう一度購読処理をするオペレーターを組めたら解決するのでは！ということでやってみました。

```csharp
private Observable<CustomButton> OnTapAsObservableInternal()
{
    return Observable.Defer(() => 
        Observable.Create<CustomButton>(observer =>
        {
            IDisposable subscription = null;
            Action subscribeAgain = null;

            subscribeAgain = () =>
            {
                subscription = CreateTapSequence().Subscribe(
                    onNext: value => observer.OnNext(value),
                    onCompleted: result =>
                    {
                        subscription.Dispose();
                        subscribeAgain();
                    }
                );
            };

            subscribeAgain();

            return Disposable.Create(() =>
            {
                if (subscription != null)
                {
                    subscription.Dispose();
                }
            });
        })
    );
}

private Observable<CustomButton> CreateTapSequence()
{
    return _button.OnClickAsObservable().Select(_ => this);
}
```

ローカルで定義したsubscribeAgain内ではCreateTapSequence()で定義したボタンのタップをそのまま購読しています。onCompletedでは現在のサブスクリプションを破棄し再起的に購読処理を行っています。
これにより繰り返し購読がされるためRepeat()と同じような挙動を再現できました。
ボタンのコンポーネント内で完結し購読する側に影響がないため今回はこちらを採用しました。

# まとめ
今までの挙動を崩さずに置換するのはかなり骨が折れました…今回はプロジェクトの事情に沿った対処療法でしたが対策①のように他のアプローチも考えられると思います。
UniRX→R3移行の手助けになったら幸いです。
TiDB関連イベント12月分

恒例のイベント案内12月分です！

PingCAP主催のもの、コミュニティイベントに参加するものの両方を記載しています。
WebinarについてはJSTで6:00-24:00に開催されるイベントを記載しています。

また、ここに記載がなくとも、イベント/社内勉強会でTiDBについて話してほしいというリクエストはお気軽に @bohnen ([X/@bohnen](https://twitter.com/bohnen)) までお気軽にご連絡ください。

## 【お知らせ】TiDB Advent calendarにご参加ください!!

https://qiita.com/advent-calendar/2024/tidb

TiDBアドベントカレンダーは（勝手に）米国時間で運営しているので一日遅れても大丈夫！（言い訳）
ゆるふわ運営なのでお気軽に参加ください。

## re:Invent 2024 ブース出展

https://www.pingcap.com/event/connect-with-us-in-las-vegas/

ただいま開催中のAWS re:Invent にも出店しています。**Booth: 1561**です。日本からもソリューションアーキテクトがブースに居ますので、お気軽にお立ち寄りください。ここにしかないノベルティもあります！

## ウェビナー: TiDB Cloud Serverlessの紹介

https://pingcap.co.jp/event/20241212-webinar/

TiDB初心者向けのウェビナーです。TiDB Cloud Serverlessを使ったことのない方はぜひ。講師はおなじみPingCAP本田さんです。


## オープンソースカンファレンス 2025 Osaka

https://event.ospn.jp/osc2025-osaka/

12月のイベントが少なかったので、1月のイベントですが、オープンソースカンファレンスに初出店します！オープンソースTiDBユーザーの皆様ぜひご参加ください。

## おわりに

今年もTiDBを応援してくださりありがとうございました！
来年もよろしくお願いいたします。
新卒研修で部門を超えたプロダクト改善のワークショップを実施しました！

この記事は[Schoo Advent Calendar2024](https://qiita.com/advent-calendar/2024/schoo)の10日目の記事です！

# はじめに
みなさんこんにちは！Schooの岩田と申します。


今回は新卒メンバーの入社を機に、エンジニア、PdM、デザイナー、事業企画、カスタマーサクセスといった異なる部門のメンバーが集まり、プロダクト改善の視点を養う「プロダクトメタ認知ワーク」 を実施しました。

その内容と学びを皆さんにシェアします😊



# 実施の背景
社内では日々お客様から多くのご意見や改善要望をいただいています。ただ、それらをどの視点から優先的に検討し、具体的な改善に繋げるべきか悩む場面も少なくありません。

今回、新卒メンバーが入社したことで、次のような目的を掲げて本ワークを企画しました。

- プロダクト改善を多角的な視点で考えられるようになること
- 部門を超えた意見交換を通じてアイデアを深掘りし、磨く力を養うこと
- 新卒メンバーが、他部門のメンバーと関わるきっかけをつくること

# ワークショップの内容
#### プロダクトメタ認知ワークとは？
このワークは、プロダクト改善をテーマにグループで議論を交わし、具体的な改善アイデアを深めていくワークショップです。

#### グランドルール
多様な職種・階層のメンバーが集まるため、意見が出しやすくなるルールを設定しました。

- 「Yes And！」：どんな意見も否定せず、まずは肯定的に受け止める
- 「なぜなぜ」：深掘り質問をして背景や意図を探る

#### ディスカッションテーマ
今回のテーマは、実際に寄せられたお客様からの改善要望である
**「携帯アプリでもオンライン集合学習機能を使えるようにしてほしい」**
をテーマにディスカッションしました。

:::note info
オンライン集合学習とは
「オンラインｘみんなで」をコンセプトに、社員同士がSchooの授業やオリジナル動画を同時に視聴しながら、コミュニケーションを取ったり学びをアウトプットできる機能です。
:::

#### 進め方
①個人ワーク
ディスカッションにあたって、まずは、以下3つの視点で自分の考えをオンラインホワイトボードmiroの付箋に書き出しました。

:point_down:ちなみに、miroのおすすめの使い方はこちらにまとまっているので、気になる人は要チェックです！

https://qiita.com/katoua08/items/446916403d05f4ad921e



- アグリー（Yes And！の精神を大切にまず最初にこのアグリーから発表します。）
この改善に賛成だと思う点
なぜ改善したほうが良いと思えるか
- 懸念
この改善を進めることに反対だと思う点
改善を進めたらこんなリスクがありそう
- 深掘り質問
背景や意図をもっと知りたい場合の質問

![スクリーンショット 2024-12-02 17.23.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3942036/30a63714-68da-5205-1979-2f559f348f92.png)

②書き出したあと、miro上に付箋を貼り付けます。


③グループ（1グループ 5人程度）に分かれて、意見を見比べながら、改善に必要な視点は何かを話し合いました。

ちなみに、実際のボードはこのような形になりました。

「携帯アプリで手軽に学ぶ人が増える」という賛成意見や、「携帯アプリではオンライン集合学習の本来の価値が下がってしまうのではないか」という意見が出るなど、意見が分かれました。さらに、「オンライン集合学習を使いたいという要望の本当の背景やペインは何か？」といった問いも飛び交い、普段オンライン集合学習の開発に関わっていないメンバーにおいても新鮮に議論することができました。

![スクリーンショット 2024-12-04 10.49.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3942036/fe498f5a-1af2-b13d-4afb-1362e595d555.png)



# やってみての感想
参加した新入社員からは以下のような感想があがりました。
- 自分が懸念点だと思ったことが、裏を返せばアグリーになることを学んだ

- 企画を進めるときに自分で考えるだけでは煮詰まる場面が多いが、複数人でやると短時間でも多くのアウトプットが出たり、深堀りやほかの観点も得られると気づきがあった

- 最近の業務でコード面・技術面に偏って学びがちだったので、実際のプロジェクトにおいてどのような議論や意思決定が行われてきたのかもしっかりキャッチアップしていきたいと思った

- エンジニアの中でも、プロダクトが届けたいものの目線を持つことも大切であり、意見を受け入れるだけではダメという話がよく出ていた中で、その目線を持つにあたって今回のフレームワーク(アグリー・懸念・深掘り質問)を使うのはとても有効だなと感じた 


# おわり
実際にやってみると、上記のような前向きな感想が出てきました。
Schooでは、部門を越えたコミュニケーションが活発で、今回のような部門を超えてつながり、学びあう行動を奨励する文化があります。 

私自身もワークショップを実施して、普段から異なる部門間で視点を共有することの重要さを改めて認識しました。

これからも、このような学びの場を継続的に設けて行きたいなと思います☺️


---


Schooでは一緒に働く仲間を募集しています！

https://corp.schoo.jp/careers/graduates

https://corp.schoo.jp/careers
Cent OS Stream に IntelliJ IDEA を入れてみる

# Cent OS Stream に IntelliJ IDEA を入れてみる
中学2年生から6年間使ってもう使う頻度が減ったノーパソに Cent OS Stream 9 をインストールして再利用した。さっそくIntelliJ IDEA を入れてみたので備忘録として記事にしたみた。
普通に調べたら出てくるかもしれないが、CentOS Stream 9 (Server with a GUI) のアプリ一覧「アクティビティ」にIntelliJ IDEAのショートカットを追加する方法が載っていなかったのでそれも含めて解説したいと思う。

### 1. 以下のサイトからIntelliJ IDEA Communityをブラウザでダウンロードします

https://www.jetbrains.com/idea/download/?section=linux

### 2. ダウンロードしたファイルの移動

```
sudo mkdir -p opt/intellijidea/
sudo mv ~/ダウンロード/ideaIC-2024.3.tar.gz opt/intellijidea/
```

※ダウンロードしたファイルの名前はバージョンによって違います。

### 3.tar.gzを展開します
```
sudo tar -zxvf opt/intellijidea/ideaIC-2024.3.tar.gz
```

ideaIC-2024.3.tar.gzはダウンロードしたファイル名です。違っていれば変更してから実行してください。

### 4. IntelliJ IDEAの起動
```
opt/intellijidea/ideaIC-2024.3/idea-IC-243.21565.193/bin/idea.sh
```

### 5. デスクトップファイルの作成 (任意)
アクティビティへショートカットを追加したいので以下のシェルでデスクトップファイルを作成します。

IDEA_DIRはIntelliJが入っている場所です。この記事通りであればそのままで結構です。

```create_idea_desktop.sh
#!/bin/bash

# IntelliJ IDEAのパス
IDEA_DIR="/opt/idea-ic243"

# シェルとアイコンのパス
IDEA_BIN="$IDEA_DIR/bin/idea.sh"
IDEA_ICON="$IDEA_DIR/bin/idea.png"

# 作成先
DESKTOP_FILE="/usr/share/applications/intellijidea.desktop"

# DESKTOP_FILE の出力
cat <<EOF | sudo tee "$DESKTOP_FILE" > /dev/null
[Desktop Entry]
Version=1.0
Name=IntelliJ IDEA
Comment=IntelliJ IDEA - Java IDE
Exec=$IDEA_BIN %F
Icon=$IDEA_ICON
Terminal=false
Type=Application
Categories=Development;IDE;
EOF

# 実効権限の付与
sudo chmod +x "$DESKTOP_FILE"
```

上記のシェルを実行すると完了です。
Advent of code 2015 Day 20 Part 1 & Part 2 を Livebook で楽しむ

## はじめに

Advent of code 2024 の準備として、過去回の Advent of code 2015 を Livebook で楽しみます

本記事では Day 20 の Part 1 と Part 2 を解きます

問題文はこちら

https://adventofcode.com/2015/day/20

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

https://github.com/RyoWakabayashi/elixir-learning/blob/main/livebooks/aoc/2015/2015_day20_part1.livemd

https://github.com/RyoWakabayashi/elixir-learning/blob/main/livebooks/aoc/2015/2015_day20_part2.livemd

## セットアップ

Kino AOC をインストールします

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

Kino AOC の使い方はこちらを参照

https://qiita.com/RyoWakabayashi/items/3d3abcf9134cee4dff05

## 入力の取得

"Advent of Code Helper" スマートセルを追加し、 Day 20 の入力を取得します

![スクリーンショット 2024-12-03 10.32.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/ce3fb287-05a7-39be-37ba-b0ee2e14b988.png)

## 私の答え

私の答えです。
折りたたんでおきます。
▶を押して開いてください。

### Part 1

<details><summary>回答</summary>

問題文を噛み砕くと、約数の合計 * 10 がパズル入力値以上になる最小の家番号を探索することになります

そのため、まず約数の取得処理を実装してみます

例えば 1 から 9 の各約数を求める場合、単純に考えると以下のような実装になります

```elixir
1..9
|> Enum.map(fn house_number ->
  1..house_number
  |> Enum.filter(fn x ->
    rem(house_number, x) == 0
  end)
end)
```

しかし、これだと 1,000,000 の約数を求める場合、 1,000,000 回計算しないといけません

1 から 1,000,000 の各約数を求める場合の計算量は `1000000 * 1000000 / 2` で膨大になります

そこで、少しでも計算量を減らすため、以下のように変更します

```elixir
1..9
|> Enum.map(fn house_number ->
  limit = :math.sqrt(house_number) |> floor()

  1..limit
  |> Enum.filter(fn x ->
    rem(house_number, x) == 0
  end)
  |> Enum.flat_map(fn x ->
    [x, div(house_number, x)]
  end)
  |> Enum.uniq()
  |> Enum.sort()
end)
```

A が X の約数である場合、 `X = A * B` （B も X の約数）となります

条件として `A <= B` とすると、　A の最大値は `A = B` のとき、つまり `X = A ^ 2` のときです

したがって、 A は 1 から X の平方根の範囲で探索すれば良いことになります

全ての A を探索したのち、各 A に対応する B を追加し、重複を排除すれば全ての約数が取得できます

これを利用して解いてみましょう

入力を数値に変換します

```elixir
target_number = String.to_integer(puzzle_input)
```

1 から 1,000,000 の範囲で探索すれば発見できます

```elixir
1..1000000
|> Enum.find(fn house_number ->
  limit = house_number |> :math.sqrt() |> floor()

  1..limit
  |> Enum.filter(fn x ->
    rem(house_number, x) == 0
  end)
  |> Enum.flat_map(fn x ->
    [x, div(house_number, x)]
  end)
  |> Enum.uniq()
  |> Enum.map(fn num -> num * 10 end)
  |> Enum.sum()
  |> Kernel.>=(target_number)
end)
```

</details>

### Part 2

<details><summary>回答</summary>

約数のうち、 50 以下とかけるものだけを使用します

（`X = A * B` のとき、 `B <= 50` となる A のみ）

```elixir
1..1000000
|> Enum.find(fn house_number ->
  limit = house_number |> :math.sqrt() |> floor()

  1..limit
  |> Enum.filter(fn x ->
    rem(house_number, x) == 0
  end)
  |> Enum.flat_map(fn x -> 
    [x, div(house_number, x)]
  end)
  |> Enum.uniq()
  |> Enum.filter(fn num -> div(house_number, num) <= 50 end)
  |> Enum.sum()
  |> Kernel.>=(target_number / 11)
end)
```

</details>

## まとめ

計算量を少なくするための工夫が必要でした（工夫しないと終わりません）
Markdwon AIに画像生成AI機能が追加！

![file (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3921729/16ef8c31-3522-126a-24f4-a368700b3ddf.png)
あなたの創造力をさらに広げる新機能がMarkdown AIに追加されました！
これからは、文章だけでなく、個性豊かな画像もMarkdwon AIの中だけで簡単に生成できます。

# 画像生成AI機能でできること
![file (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3921729/8c91f035-0fe8-0445-b54e-ae225eee51f9.png)
Markdown AIの画像生成機能を使えば、プロンプトを入力するだけ高品質な画像を作成可能です。

例えば：

**ブログ記事にピッタリなサムネイル**

**マーケティング資料やプレゼン用の画像**

**オリジナルのイラストやデザイン素材**

これらをすぐに作成/実装できます！デザインの知識やスキルは一切必要ありません。

## 直感的な操作

プロンプト入力に加え、複数のテンプレートパターンが用意されており、複雑な操作は不要。「どんな画像が欲しいか」を記述するだけで、AIがあなたのイメージを自動で形にします。Markdown AI内で全て完結するため、他のツールに切り替える必要もありません。

## 実際に試してみよう！

Markdown AIの新しい画像生成AI機能は現在無料でお試しいただけます。以下のリンクから今すぐ体験してください。

[Markdown AIはこちら](https://mdown.ai/)

## 画像生成AI機能の特長

- **高品質な画像生成**
細部までリアルで美しい画像を生成可能。
写実的な表現から抽象的なデザインまで、テンプレート選択でもプロンプト入力でも、多彩なスタイルに対応しています。

- **直感的なプロンプト対応**
シンプルな文章でも意図を正確に解釈し、理想的な画像を作成可能。
初心者からプロフェッショナルまで幅広く利用できます。

- **エディタ画面へのスムーズな挿入**
生成した画像はワンクリックでMarkdownエディタに挿入可能。
面倒な操作が不要で、使いやすさ抜群です。

- **無制限利用でさらなる自由度**
現在、Markdown AIでは画像生成機能を無制限で利用でき、制約を気にせず何度でも画像生成が可能です。

## 誰でもすぐに使える新しい画像制作体験
Markdown AIの新機能は、ブログ記事の挿絵、マーケティング資料、プレゼン用画像、デザイン素材の制作など、あらゆる用途で活躍します。テンプレートパターンの導入により、初心者でも効率よく美しい画像を作成できるため、プロジェクトの質と作業スピードを同時に向上させます。

# 創造力を無限に広げるMarkdown AI
これからのMarkdwon AIは、文章と画像の両方を駆使して、アイデアを最大限に表現することができます。個人利用からビジネス活用まで、Markdown AIはあらゆるシーンであなたをサポートします。この新機能で、あなたのクリエイティブライフを一歩進めてみませんか？

# Markdown AIとは？
![Mdown_baner1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3921729/c1520bba-a0c3-ef3f-9e8b-16eafbf452b2.png)
Markdown AIは、 **頭の中にある考えを形にできる画期的な「AI Webサイト制作ツール」** です。Markdown記法を活用し、誰でも手軽にウェブサイトを構築できるシンプルな仕組みが特徴です。
また、自身のサイトに特化したAIをカスタマイズ・実装することが可能で、**複数のAIモデルを選んでサイトの特徴に合わせて使い分けることができます。**
これにより、サイトの目的やニーズに応じた高機能なツールを作成できます。
さらに、Markdown AIは使用が**無料で、面倒なサーバー設定は一切不要。ボタン一つでサイトを公開できる**ため、初心者でも安心して利用できます。
その他にも、高い拡張性を持ち、複雑なツールやシステムの開発にも対応可能です。このように、手軽さと高度なカスタマイズ性を両立したMarkdown AIは、個人からビジネス用途まで幅広いニーズに応える制作ツールです。
![MarkdownAI_note_touka.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3921729/e0249d46-1ab8-88bd-6193-31581947a37d.png)
fedoraにCosmic Dekstopをインストールしてみた


# はじめに

この記事は、Qiita Advent Calendar 3日目の記事です。
以下の記事より、すべての記事をご覧になれます。

https://qiita.com/0_terarin_0/items/2b60d47a2d0e64a273c3

# 筆者について

現在高校3年生
（元）水泳部マネージャー
（元）生徒会長
（元）とある団体の代表

# 本編

## きっかけはCosmicのリリース

以下の記事がsystem76から公開されました。

https://blog.system76.com/post/cosmic-alpha-released-heres-what-people-are-saying

記事の内容としてはsystem76が開発しているCosmicがpop!_OS以外の一部のOSでインストールできるようになったそうです。

https://github.com/pop-os/cosmic-epoch

このCosmic Desktop、以前はGnomeをベースとしていたのですがいつしかからかRustベースに書き直したデスクトップ環境です。今回は、これを先日MacにインストールしたFedoraに入れていきたいと思います。

## Cosmicのインストール

ターミナルで以下を入力してインストールします。

```zsh
dnf copr enable ryanabx/cosmic-epoch
dnf install cosmic-desktop
```

あとはセッションをCosmicに変更してログインしたら終了です。

↓Gnome（若干カスタマイズ済み）
![Screenshot from 2024-12-03 10-11-34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/583428/8ef35460-2b68-8855-a142-a7616cfaea9d.png)

↓COSMIC Desktop
![screenshot-2024-12-03-01-14-58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/583428/de77ce5f-fc2e-3cd5-aabe-48fb4c46b544.png)

ただし、一つだけ納得がいかないのは、デスクトップマネージャーがGDM（Gnome Desktop Manager）のままであることです。ここまできたら全て統一したい！！

## ディスプレイマネージャーの変更

先に```gdm```を無効化して、```cosmic-greeter```を有効にします。じゃないと有効化できません。

```zsh
sudo systemctl disable gdm
sudo systemctl enable cosmic-greeter
```

これでリブートするとディスプレイマネージャーが```cosmic-greeter```になっています。

:::note alert
**ちょっとした注意**
僕が久しぶりにログインした時にはなぜかログインできなくなるということが発生していました。その時はコマンドでログインして```gdm```に変更してからもう一度```cosmic-greeter```を有効化します。これはなぜなのでしょうかね。
:::

# 最後に

COSMIC、個人的にはとても好きなのですがまだまだ開発途上という感じがあります。ということで、今後とも開発の続きを見守っていきたいと思います。
Mojave を M2 Macbook Air にUTM でインストール


## なぜ Mojave？
High Sierra の動くインテルMac（Mac mini）は持っています。
その次のIntel対応OSが、Mojaveだから。
あるインテルのアプリを動かしたいのですが、どのOSまで動くかわからず、一応32ビット最後のMojaveにしてみました。

## UTMインストール
先人がたくさん記事にしていますので省きます。

## Mistインストール
先人がたくさん記事にしていますので省きます。

## Mist で　Mojave をダウンロード

デスクトップにダウンロードしました。
``Install\ macOS\ Mojave\ 10.14.6_18G103.app``
ができました。


## ISO 作成
ターミナルで作業しました。

```
$ hdiutil create -o /tmp/Mojave -size 8G -layout SPUD -fs HFS+J -type SPARSE
$ hdiutil attach /tmp/Mojave.sparseimage -noverify -mountpoint /Volumes/install_build
$ asr restore -source /Users/hogehoge/Desktop/Install\ macOS\ Mojave\ 10.14.6_18G103.app/Contents/SharedSupport/BaseSystem.dmg -target /Volumes/install_build -noprompt -noverify -erase
$ hdiutil detach /Volumes/macOS\ Base\ System/
$ hdiutil convert Mojave.sparseimage -format UDTO -o /tmp/Mojave.iso
$ mv Mojave.iso.cdr /Users/hogehoge/Desktop/Mojave.iso
$ rm /tmp/Mojave.sparseimage
```

デスクトップに``Mojave.iso``ができています。

## UTM構成ファイル

下記をダウンロードしました。
他のバージョンのOSのの構成ファイルも、このgithubにあります。

https://github.com/adespoton/utmconfigs/blob/main/macOS%2010.14%20(config%20only).utm.zip

zipファイルを展開すると、``macOS 10.14 (config only).utm``ファイルができました。
ダブルクリックすると、UTMが立ち上がります。


## Mojave インストール

さきほど作成したISOファイルを``CD/DVD``に設定して起動します。
あとは指示どおりにインストール。

他のことをやりながら見てたりボタン押したりしたこともありますが、ここだけで、半日くらいかかりました。


## 一旦、完成

めでたしめでたし。
アプリの動作確認は、次回で・・
Backlog4Jでは課題に設定されたカスタム属性値を取得できない

Backlog4Jの仕様ないし不具合の話。

# Problem

Backlog API（v2）を利用してBacklog上のプロジェクトの課題の情報を抽出したい。
よく手に馴染んだ言語、そして公式サポートのライブラリを利用したい。
そこでBacklog4Jを利用して課題の情報を抽出することにしたが、__課題に設定されているカスタム属性の値を取得する方法__ がわからない。

APIクライアントの`getIssue()`ないし`getIssues()`メソッドは`Issue`オブジェクト（ないしそのリスト）を返す。`Issue.getCustomFields()`は`CustomField`オブジェクトのリストを返す。そして`CustomField`オブジェクトは・・・`getValue()`や`getValues()`メソッドを提供 __していない__。

# Solution

Backlog4Jでは課題に設定されたカスタム属性の値を抽出することは __できない__（Backlog4J v2.6.0現在）。
このため次の中からいずれかを選択しなくてはならない：

* 諦める
* 何らかの方法で迂回（ライブラリを介さず独自コードで直接HTTP要求するなど）
* 別の言語向けのライブラリを利用
* Backlog4JのGitリポジトリをクローンして修正

Backlog APIのリファレンスに含まれている[Get Issue](https://developer.nulab.com/docs/backlog/api/2/get-issue/)の解説ページを見ると、サンプルの応答のJSONが呈示されており、応答に `customFields`プロパティが含まれていることがわかる：

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50571/3608acd4-d128-ca49-09a5-3849750b25cd.png)

リファレンスではこの`customFields`プロパティがどのようなオブジェクトの配列であるか示されていない。
しかしCurlなどでコマンドラインでAPIを実行して応答のJSONを確認してみると、Backlog4Jの[CustomFieldインターフェース](https://github.com/nulab/backlog4j/blob/master/src/main/java/com/nulabinc/backlog4j/CustomField.java)に相当するオブジェクトであることがわかる。
そして応答のJSONではこのCustomFieldインターフェースに`value`というプロパティが存在しており、[CustomFieldListItemインターフェース](https://github.com/nulab/backlog4j/blob/master/src/main/java/com/nulabinc/backlog4j/CustomFieldListItem.java)におおよそ相当するオブジェクトもしくはその配列が設定されていることがわかる。

```json
{
  "id": 72619110,
  "projectId": 106780,
  "issueKey": "XXX-1",
  "keyId": 1,
  ...
  "customFields": [
    {
      "id": 321088,
      "fieldTypeId": 6,
      "name": "カスタム属性名AAA",
      "value": [
        {
          "id": 1,
          "name": "カスタム属性値aaa",
          "displayOrder": 0
        }
      ]
    }
  ],
  ...
}
```

一方であらためて[CustomFieldインターフェース](https://github.com/nulab/backlog4j/blob/master/src/main/java/com/nulabinc/backlog4j/CustomField.java)を確認すると、`getValue()`や`getValues()`メソッドが存在 __しない__（Problemで述べた通り）。
つまりBacklog APIとしてはカスタム属性の値`value`プロパティを提供しているのだが、Backlog4Jとしてそれに対応するJavaのオブジェクトを提供していない。

```java
package com.nulabinc.backlog4j;

/**
 * @author nulab-inc
 */
public interface CustomFieldListItem {

    long getId();

    String getName();

    int getDisplayOrder();
}
```

カスタム属性は単一値をとるケースと複数値をとるケースとがあって、これはカスタム属性の設定次第で変わる。
厄介なのは設定がいずれであっても、APIの応答のJSON上はカスタム属性値は同じ`value`というプロパティ名。単一値のときは `value`で複数値のときは`values`─というふうになっていればよいのだが、残念ながらそうではない。
Java言語的には「単一値でもあり複数値でもある」という曖昧なオブジェクトは表現できない。これが`CustomField`インターフェースには`getValue()`メソッドが存在しない理由らしい（←推測！）。

単一値ないし複数値のカスタム属性値のコンテナになるオブジェクトがあれば `CustomField.getValue()`メソッドを実装できるはず。しかしJavaオブジェクト-JSON間のシリアライズ／デシリアライズのロジックを考えるとその実装は意外と面倒そう。そしてBacklog4Jユーザーとしてもインターフェースの変更に追随して既存ロジックにコードを追加しなくてはならない箇所が出てくるかもしれない：

```java
public interface CustomFieldListItem {

    long getId();

    String getName();

    int getDisplayOrder();

    CustomFieldValue getValue(); // ←プロパティを追加
}

public interface CustomFieldValue {
    boolean isMultiple();
    CustomFieldListItem get();
    List<CustomFieldListItem> getItems();
}
```

ということで、Backlog4Jでは課題に設定されたカスタム属性値を取得 __できない__。
（今度時間をみつけてBacklog4JのFIXバージョンを作成したい）
SharePointリストのとある項目をPowerAutomateから1件取得しようとするとエラー

PowerAutomateを利用して作成したワークフローを運用している中で遭遇した問題です。

# Problem

PowerAutomateでとあるSharePointリストの項目を取得しようとしている。
取得したい項目は __リストの中でもとある列の値が最大のもの__（降順ソートした結果の最初の1件）。
当該リストの __項目数は5,000件を超え__ ている。

SharePointコネクターの「複数の項目の取得」でオペレーションを実行するとエラーになる：

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50571/22ec51f1-461e-8667-6736-a38fdfbd5d14.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50571/1b490866-e447-a52b-c780-884f4c49dca8.png)

```
{
  "status": 400,
  "message": "The attempted operation is prohibited because it exceeds the list view threshold.\r\nclientRequestId: d2146f4e-18fa-4746-8a17-8057094839ac\r\nserviceRequestId: 131b69a1-d0e0-4000-2419-b8eea3b714a1"
}
```

> オペレーションが禁止されている。リストビューのしきい値を超えたから。

# Solution

当該の列にインデックスを追加する。

バックエンドで起きている問題は先日の投稿「[SharePointリストに存在するはずの項目がPowerAutomateで取得できない](https://qiita.com/mizukyf/items/ddccf59f39c1124642cc)」で報告した問題と同じ模様。
ただし今回は「音もなく発生していた」ものではなく明確なエラーになってくれた。
最終的に取得したい項目はたった1件でもリスト項目のソートが必要。このためリストの項目の件数増加に伴って問題が生じる。

問題が発生しているかどうかはリスト設定ページで確認できる：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50571/6e112a27-13dc-275a-f25f-4c874432c65f.png)

> このリスト内のアイテム数がリスト ビューのしきい値 (5000 アイテム) を超えています。サーバーに過度な負荷がかかる原因となるタスク (リストの全アイテムを対象としたタスクなど) は、現在禁止されています。
> 大きなリストやライブラリを使用して、アイテムを即座に表示する方法を説明します。

対策方法も同様。リストの設定で当該リストの当該列に対してインデックスを追加する：

https://qiita.com/mizukyf/items/ddccf59f39c1124642cc
【試験】環境変数に埋め込んでリクエスト

試験結果に記録を残したいけど、機密情報を隠したい時、環境変数に保存すると便利です。特に、繰り返し機密情報を隠すのが面倒な場合、一時的に環境変数に保存することで簡略化してリクエストの形式を残せます。（また、再度試験しなおすとき実施しやすい）

## 環境変数に機密情報を設定する

以下の手順で、`auth`という環境変数に認証情報を設定し、HTTPリクエストに使用します。

### 1. **環境変数に設定**

```bash
export auth="auth-information" 
```

### 2. **値が入っているか確認**

環境変数に正しく値が設定されているか確認します。

```bash
echo $auth 
```

### 3. **リクエスト例**

設定した環境変数を使用して、HTTPリクエストを送信します。
以下は`curl`コマンドを使用した例です。

```bash
curl --request PUT -iL \
  --url http://localhost:8080/api/product/1234 \
  --header "Content-Type: application/json, x-auth-token: ${auth}" \
  --data '{
}'
```

この方法を使うことで、スクリプトやコマンドラインで機密情報を安全に扱うことができます。
[更新]CASIO fx-JP900CWをレビュー

## はじめに
こんにちは、bockringです。以前、2024年4月くらいにfx-JP900CWのレビューを投稿したのですが、更新するために記事を削除し、再投稿しました。

https://amzn.to/3QkfrT9

## 更新理由
更新理由は「前のレビューはあまりに情報が欠けていて、不完全だった」からなのですが、1回目の執筆の時は、初めての電卓であることもあり、デメリットについて触れられていませんでした。半年以上使って、改めて感じたことをまとめていこうと思ったので、どうぞよろしくお願いします。

(あとプログラム(内部構造)についても触れようとすると、書き直した方が早いというのもあります。)

## 概要
fx-JP CWシリーズは、2023年9月21日にCASIOから発売された高精細ディスプレイを搭載するClassWizシリーズの2作目です。1作目に関しては、別の記事でまとめていますのでどうぞご覧ください。

https://qiita.com/bockring/items/02d3052ccb6f541a433e

このシリーズは、直感的な操作を可能とするGUI的操作が主となっています。過去の関数電卓(グラフ電卓除く)ではあり得なかった決定キー・戻るキーの追加などがある一方で、電卓的な操作が減り、使いにくいと感じる人もいるものになります。

## ハードウェアと操作感
まず、先に操作感について述べておきます。

この電卓では、カーソル・OKキーの5キーによる階層メニューでの操作が基本となっています。今までの数字キーを押して決定する方式を廃止し、ラジオボタンによる選択などが多くなります。

そのため、今までは**カーソルキーでページを選択し、数字キーで選択する**というスタイルだったものが**連打ゲーになってしまった**ということです。一応その対策としてページめくりキーを追加されています。

:::note info
ClassWizの1作目では、Shift+(↑/↓)によるページめくりができなかったので、その点は改善点と言えるかもしれません。(他メーカーの電卓ではできるのに…)
:::

## ハードとソフトの結びつきの問題
### `=`キーと`OK`キー
この電卓は、機能を分かりやすく(笑)しすぎたせいで妙に機能がダブっているキーがあります。その顕著な例が`=`と`OK`です。長らく関数電卓では、=(イコール)キーをEnterキーとしても使用してきました(今でもほぼ全ての関数電卓でそうです)。そしてOKキーはどう足掻いてもEnterキーです。私が試したほぼ全ての場面でどちらのキーでも同じ動作をしました。唯一違ったのが`≒`で、`Shift + =(≒)`で近似値表示できますが、`Shift + OK`ではできません。OKキーは何のために配置されたのでしょう…

もちろん配線パターンは別配線のようです。おそらく、電気的には接続されていないものの、コード的にはほぼ同じ動作をするようになっているのでしょう。こんなのにキーを1つ割くくらいなら、`=`キーの=の文字の下にOKあるいはEnterという文字を印刷して、その1つのキーに別に機能を割り当てて欲しいものです(SHARPがこれに近しい印刷となっています)。

### `↩︎(戻る)`キー
何度でも言いますが、これは関数電卓で、しかも一般関数電卓です。グラフ電卓などではありません。グラフ電卓に`Esc`キーは必須ですが、一般関数電卓に戻るキーなんて必要ありません。`←`キーで戻ればいいのですから。しかも、1作目では親切に「戻れるよ」と伝える目的で、開いているメニューの1個上に階層がある場合は上部に`◀︎`のインジケーターが点灯します。これでいいのではないでしょうか。

### ページめくりキー
これに関しては搭載理由も不明なレベルですが、まず使いません。厳密に言うと統計計算あるいは数表作成機能では使いますが、`Shift + (↑/↓)`でページめくりに対応すれば良いだけです。

このように、キーの設計にもそこそこ問題があります。次に、ソフト的な**欠陥**を見ていきましょう。

## 演算について
### 良い点
まず、この電卓の数少ない利点というのは計算速度と精度でしょう。
```math:
Σ(x,1,1000)=500500
```
これくらいなら、爆速で返してくれます。この計算速度を越える電卓となると、グラフ電卓だけといったところでしょう。

さらに、計算精度も非常に良いのです。内部演算23桁なので、(弧度法での)以下の計算も表示桁数10桁で誤差なく返します。
```math:
tan(355/226)=-7497258.185
```
この精度で返してくれるなら、表示桁数も12桁にしてくれたら良いのになぁ…なんて思ってしまうほどです。

### 悪い点
こちら他のレビュワーさんも言っていますが、指数計算のアルゴリズムが**改悪とかいうレベルではないです**。1作目と2作目において同じ順番でキーを押しても、解釈のされ方が全く異なります。
![IMG_2495.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3777721/f495a2d7-aaf2-b64b-abbe-70ef0e9de31f.jpeg)

エミュレーターを用いて、キーの押下順も表示した上で同じ順にキーを押しました。しかし、この画像の通り、解釈のされ方が全くもって違います。

1作目では`6.02×₁₀23`(6.02×10²³)を1つの値として扱っていて、こちらが正しい解釈です。

しかし2作目では、指数入力キーはあくまで
![IMG_2496.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3777721/4edf67e9-d2e0-b1ec-3d36-61e80280362d.jpeg)
この4手のショートカット感が否めません。この辺りの動作はGIF動画にしましたので、動いていなかったらクリックして再生してみてください。
![My Movie.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3777721/8b1fa301-8553-0db6-3c33-eb75dda81100.gif)
(Qiitaの上限10MBをギリ超えない9.8MBなのでそこそこ重いです)

**どんなにダサくても良いから、ここだけは3作目で改善して欲しいです(切実)。**

## おわりに
まず最初に、<font color=red>**手と頭と財布の口が滑ってもこのシリーズだけは買わないでください！**</font>絶対に後悔しますし、しなかったとしても逆に煩雑な操作性によって計算ミスを生じ、大変なことになります。

私もこいつを買ったばかりのころ、計算した値を用いて電子部品を選定したら、**爆発しました**。これを買って良いことはないです。

そしてこの電卓の発売にあわせてパッケージが紙に切り替わったのですが、(悪いようにいうと)操作性の悪さを隠して関数電卓を何も知らない初心者に売り込んでいる、というようにも捉えられます。

前のモデル(1作目)が店に残っていたら、少し高くてもそちらを買いましょう。その方が幸せになれます。
プリザンター 一覧画面のボタンでサーバスクリプトを発火させる

こんにちは、株式会社シーイーシーカスタマサービスの田中です。
いつもは自社のブログで記事を書いていますが、今回はQiitaに直接投稿させていただきました。
ぜひ弊社の[プリザンターブログ](https://www.ceccs.co.jp/blog?c=pleasanter "CCSブログ")もご覧下さい。

今回は、私が実装したいと思っていたことで、少し悩んでいた「サーバスクリプトを自由なタイミングで動かしたい」の方法について書きたいと思います。

## サーバスクリプトの一覧画面での発火
サーバスクリプトは、発火するタイミング（条件）が「作成・更新前/後」や「画面表示の前」など決まったものしかなく、自分が発火させたいタイミングでの設定ができません。

しかし、プロセスなどと併用することで、プロセスで設置したボタンをクリックすることでサーバスクリプトを発火させることは可能です。
こちらの詳細はCCSブログ「[第255回）ボタンでサーバスクリプトを発火させる](https://www.ceccs.co.jp/archives/blog/%e3%80%90%e3%83%97%e3%83%aa%e3%82%b6%e3%83%b3%e3%82%bf%e3%83%bc%e3%80%91-%e7%ac%ac255%e5%9b%9e%ef%bc%89%e3%83%9c%e3%82%bf%e3%83%b3%e3%81%a7%e3%82%b5%e3%83%bc%e3%83%90%e3%82%b9%e3%82%af%e3%83%aa?hilite=%27%E7%99%BA%E7%81%AB%27 "第255回）ボタンでサーバスクリプトを発火させる")」をご覧ください。

ただ、この方法ですとプロセス機能を使用しているため、新規作成画面か編集画面でしかボタンを設置できず、一覧画面からサーバスクリプトが発火できません。単に一覧画面にボタンを設置することはできますし、そのボタンのIDを拾うことは可能ですが、ちょっと工夫が必要なため備忘録を兼ねて紹介します。

## スクリプト・サーバスクリプトの説明
今回サンプルとして、何でもよいので記録テーブルを作成し、そこにスクリプトでボタンを設置、サーバスクリプトでそのボタンクリック後の処理をさせます。
サンプルのためサーバスクリプトではログ出力のみ行います。

まずは、以下のスクリプトを追加します。
出力先は、「一覧」のみを選択してください。
```javascript:button設置スクリプト
$p.events.on_grid_load = function () {
    $("#MainCommands").append(
        $('<button id="button-exe" class="button button-icon button-positive ui-button ui-corner-all ui-widget applied" data-action="GridRows" data-method="post" onclick="$p.send($(this));">')
            .html('<span class="ui-icon ui-icon-play"></span>実行')
    );
};
```
上記は、一覧画面を表示したときに実行される **\\$p.events.on_grid_load** を使って、MainCommands領域（「戻る」や「作成」ボタンが表示される領域）にボタンを追加しています。
3行目の最後にある **onclick=\\$p.send($(this))**　とすることで、ポストバックさせています。
4行目では、UIアイコンを追加しています。

次に、上記のボタンをクリックしたときのサーバスクリプトを作成します。
条件は、「画面表示の前」としてください。
```javascript:発火用のサーバスクリプト
try {
    // 実行ボタンが押された時の処理
    if (context.ControlId === 'button-exe') {
          context.Log ('ボタンが押されました。')
      }else{
       // アラート出力
        context.Error ('エラー')
        }
} catch (ex) {
    context.Log(ex.stack);
}
```
一覧画面を表示すると、一覧画面の下に「実行」ボタンが表示されます。
![20241218.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/539869/258d838a-87e3-9693-5394-98cdda915cbd.png)

「実行」ボタンをクリックすると、コンソールに「ボタンが押されました。」と表示されます。※コンソールは、F12キーを押下するなどして表示させてください。

## まとめ
いかがでしたでしょうか？

スクリプトで処理をさせると、処理に時間がかかる場合に、処理途中で画面リフレッシュによりスクリプトが中断されてしまうことがあります。また処理自体に遅かったりする場合があります。そのため、スクリプトではなくサーバスクリプトで処理することで、そのような心配がなくなります。
ただし、注意事項としては、サーバ側で処理されるためサーバに負荷がかかりますし、エラー時にはサーバ全体に影響が出ることもあるため、慎重に使用されるようにしてください。
■ 04.QAエンジニア／テストエンジニアの違い（ソフトウェアの品質に関与する点において）

# ■ QAエンジニア と テストエンジニアについて


# はじめに

・品質保証（QA）は、ソフトウェア開発の成功に欠かせないプロセスであり、
　ソフトウェアの品質を確保する上で中心的な役割を果たすのが、
　QAエンジニアとテストエンジニアです。
<br>
・一見似ているように思えるこの二つの役割ですが、
　実際には異なる視点から品質保証に取り組む違いがあり、
　本記事では下記内容について解説します。
<br>
　-> <font color="#66cdaa">それぞれの特徴と責任範囲</font>
　-> <font color="#66cdaa">ウォーターフォール開発とアジャイル開発における役割の違い</font>


# ■ QAエンジニアとテストエンジニアの基本的な違い


**■ <font color="#00bfff">QAエンジニア**</font>

・製品全体の品質に焦点を当て、
　製品の企画からリリース後のフィードバックまで全工程を管理する

・単なるテスト実行を超えて、下記のような役割がある

　-> 品質基準の設定
　-> 品質管理プロセスの改善
　-> 開発ライフサイクル全体を通じての品質保証
<br>
**■ <font color="#00bfff"> テストエンジニア**</font>

・主にテスト活動全般に集中し、様々なテスト手法や技術を駆使して以下の役割を果たす

　-> テストケースの設計
　-> テストの実行
  　 
  ※ 結果の分析が主な業務であり、設定された品質基準に基づいてテストを実施
  ※ 主には、開発後期のテスト段階に重点を置いている
<br>
**■ <font color="#00bfff">責任範囲の比較**</font>

・**<font color="#66cdaa">QAエンジニア</font>の責任範囲**：

　-> 品質保証戦略の立案と実施
　-> 品質指標の設定と監視
　-> プロセス改善の提案と実施
　-> リスク分析と管理
　-> ステークホルダーとのコミュニケーション
<br>
・<font color="#66cdaa">**テストエンジニア</font>の責任範囲**

　-> テスト計画の作成
　-> テストケースの設計と実行
　-> バグの報告と追跡
　-> テスト自動化の実装
　-> テスト結果の分析と報告
<br>
# ■ 開発手法による役割の違い

**■ <font color="#00bfff">ウォーターフォール開発モデルにおける役割**</font>

・ウォーターフォール開発モデルは、順序立てた段階的なアプローチを取る

　このモデルにおいて：

　<INS><font color="#66cdaa">**QAエンジニア**</font></INS>

　-> プロジェクトの初期段階から関与し、要件定義や設計段階でのレビューに参加
　-> 全体的な品質保証計画を策定し、各段階での品質基準を設定
　-> テスト計画の承認や、最終的な品質評価を行う
<br>
　<INS><font color="#66cdaa">**テストエンジニア**</font></INS>

　-> 主に開発段階の後半で活動
　-> 詳細なテスト計画を作成し、テストケースを設計
　-> システムテストや受け入れテストを実行し、バグを報告
<br>
**■ <font color="#00bfff">アジャイル開発モデルにおける役割**</font>

・アジャイル開発は、反復的で柔軟なアプローチを取る
　ただし、QAエンジニアとテストエンジニアの境界がより曖昧になる傾向がある

　<INS><font color="#66cdaa">**QAエンジニア**</font></INS>
 
  　 - 各スプリントの計画段階から参加し、品質基準の設定に関与
  　 - 継続的な品質モニタリングと改善を行う
  　 - 品質を後付けではなく、
  　 　開発の初期段階から考慮する文化を推進するため、開発チームと密に協力
<br>
　<INS><font color="#66cdaa">**テストエンジニア**</font></INS>
 
  　 - 開発者と密接に協力し、各テスト戦略を立てる
  　 - 継続的インテグレーション／継続的デリバリー(CI/CD)パイプラインにテストを組み込む
  　 - 自動化テストの開発と維持に重点を置く


# まとめ

・QAエンジニアとテストエンジニアは、
　ソフトウェアの品質を保証する上で重要な役割を果たしています。

  　 - <font color="#00bfff">**QAエンジニア</INS>**</font>は、より広範囲で戦略的な役割を担う
  　 
  　 - <font color="#00bfff">**テストエンジニア**</font>は、具体的なテスト活動に焦点を当てている
<br>
・開発手法の違いにより、
　具体的な業務内容や関与の仕方は変化しても、品質を重視する姿勢は変わりません。
  
  　 - <font color="#00bfff">**ウォーターフォール開発モデル**</font>では、
  　 　QAエンジニアとテストエンジニアの役割がより明確に分かれる傾向がある

  　 - <font color="#00bfff">**アジャイル開発モデル**</font>では、
  　 　QAエンジニアとテストエンジニアの協力がより密接になり、
  　 　境界線が曖昧になることがある
<br>
　つまり、効果的な品質保証には両方の役割が必要であり、
　プロジェクトの性質や組織の構造に応じて、
　適切なバランスを取ることが重要だと思います。
<br>
<INS><font color="###ff00ff">「■ 05.Quality Assurance（テストアプローチ）テスト技法：”ブラックボックステスト”について」へ続く</font></INS>
https://qiita.com/aokimakiko/items/4b522d9367364851f24e
Javaで学ぶアルゴリズム -二分探索

# 二分探索

> ソート済みのリストや配列に入ったデータ（同一の値はないものとする）に対する検索を行うにあたって、 中央の値を見て、検索したい値との大小関係を用いて、検索したい値が中央の値の右にあるか、左にあるかを判断して、片側には存在しないことを確かめながら検索していく。
> 大小関係を用いるため、未ソートのリストや大小関係の定義されない要素を含むリストには二分探索を用いることはできない。

https://ja.wikipedia.org/wiki/%E4%BA%8C%E5%88%86%E6%8E%A2%E7%B4%A2


# 実行環境

- JUnit 5
- Java 8

# テストコード

```java:BinarySearchTest.java
public class BinarySearchTest {

	@DisplayName("正常系テスト")
	@ParameterizedTest(name = "No.{index}: {0}を探すとインデックス{1}を返す")
	@CsvSource(value = {
			"-1, -1",
			"1, 0",
			"7, 3",
			"16, -1",
			"29, 14",
			"31, -1"
	})
	void testNormalBinarySearch(int target, int expected) {
		int[] sortedArray = { 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29 };
		assertThat(BinarySearch.binarySearch(sortedArray, target), is(expected));
	}

	@DisplayName("配列が空である場合、-1を返す")
	@Test
	void testEmptyArray() {
		int[] sortedArray = {};
		assertThat(BinarySearch.binarySearch(sortedArray, 13), is(-1));
	}

	@DisplayName("要素が複数存在する場合、最初に見つかったインデックスを返す")
	@ParameterizedTest(name = "No.{index}: {0}を探すとインデックス{1}を返す")
	@CsvSource(value = {
			"2, 1",
			"4, 4",
			"6, 6"
	})
	void testWithDuplicateElements(int target, int expected) {
		int[] sortedArray = { 1, 2, 2, 4, 4, 6, 6, 6, 7 };
		assertThat(BinarySearch.binarySearch(sortedArray, target), is(expected));
	}
}
```


# 二分探索アルゴリズム

```java:BinarySearch.java
public class BinarySearch {

	/**
	 * 二分探索を実行するメソッド。
	 * ソート済みの配列sortedArray内でtargetを探し、そのインデックスを返す。見つからない場合は-1を返す。
	 *
	 * @param sortedArray 探索対象のソート済み配列（昇順）
	 * @param target 探索する整数値
	 * @return targetのインデックス、見つからない場合は-1を返す
	 */
	public static int binarySearch(int[] sortedArray, int target) {

		int start = 0;
		int end = sortedArray.length - 1;

		while (start <= end) {
			int mid = start + (end - start) / 2; // 中央のインデックスを計算

			if (sortedArray[mid] == target) {
				return mid;
			} else if (sortedArray[mid] < target) {
				start = mid + 1; // 探索範囲を右半分へ
			} else {
				end = mid - 1; // 探索範囲を左半分へ
			}
		}
		return -1;
	}
}
```