OmniAICreator/Qiita-1.07M huggingface dataset:
3rdParty SaaSのリバースプロキシとしてCloudFrontを利用する

例えば広告やトラッキング系のSaaSツールを自社ドメインで配信したいといったユースケースがあります

`クライアント -> 自社リバースプロキシ -> 3rdParty`
とリバースプロキシを運用すれば可能になりますがなかなか面倒です。
すぐに思いつくのは`fargate + squid`あたりですがセキュリティ、信頼性、運用、コストがのしかかってきます。
たまに各社お手製のリバプロツールを提供していることがありますが結局運用が必要です。

そこで登場するのがCloudFrontです
originを3rdPartyとすることでCloudFrontからアクセスさせれば、
手離れがよく、低コスト高信頼性、余計なことができないのでセキュリティも担保できます。

CloudFrontを例に出していますがCDNならおおよそ可能と思われます。

利用までに重要なのは2点
- リバースプロキシを運用する
- クライアントSDKがあれば向き先をリバースプロキシに変える

# CloudFrontの設定
目安です。セキュリティとパフォーマンスを限界まで極めたい方は適宜調整してください。

## キャッシュポリシー
利用したいSaaSの仕様によりますが全無効が無難です

## オリジンリクエストポリシー
`AllViewExceptHostHeader`がよいでしょう
基本的に全部転送しつつ、Hostヘッダーは3rdPartyのものではなくなっているので除外する

## レスポンスポリシー
`CORS-with-preflight-and-SecurityHeadersPolicy`

## その他
パスルールを駆使すればdistribution一つで複数ツールに対応できます
好みにもよりますがクライアントサイドを調査しつつ検討

機能としては特定のサブドメインに転送するだけですが必要に応じてログやWAFを設定しましょう

# SDK側
proxy設定があるかどうか、あるなら設定方法を一つ一つ調査する必要があります

ツールによってはproxyを通すときだけパスが異なります。
CloudFrontの`origin path`を設定してマッピングしましょう

パスが動的であったりとCloudFrontでの`origin path`だけでは修正不能なら、
ドメインはそのままLambda@edgeでoriginのパスを書き換えます
`origin.custom.path`
Lambda@edgeは配信方法やIAM権限にクセがあるので未経験の方は適宜記事を検索してください
＊CloudFront Functionsではoriginのパス書き換えはできません。操作できるのはviewerのみ。

# CORS
リバプロのサブドメインがアプリケーションと異なるなら結局`same-origin policy`から見てsame originにはなりません

# さいごに
ツールで利用するサブドメインが定まっている場合は検討してみましょう

# 参考

https://amplitude.com/docs/feature-experiment/advanced-techniques/proxy-requests-to-experiment-with-aws-cloudfront
https://posthog.com/docs/advanced/proxy/cloudfront
とあるSNSアプリをスクリーンリーダーで使って考えたこと

最近サービスが開始したとあるSNS。
知り合いから招待をいただきアプリをインストールし、早速使い始めようとして躓いたときに考えたことを記載します。
環境は __Android__ 、 __TalkBack__ を有効にしています。

-----
# 問題点
ほぼ全てのボタンがダブルタップで実行できませんでした。
- 新規登録
- 次へ
- 同意
- いいね
など主要なボタンがダブルタップで実行できず __ダブルタップホールド__ もしくは一時的にTalkBackをオフにしてタップする必要がありました。
画面下部のタブや検索やメニューのみがダブルタップで実行できました。
またポストへのリアクションのボタンには __テキストラベル__ が付与されてなく実行するまで何のボタンか判別できませんでした。
ちなみに私はまだポストするためのボタンが見つけられていません。
私はAndroidで試しましたが、友人からの情報でiOSでも同様とのことでした。

-----
# ボタンがダブルタップで実行できない考えうる2つの原因
## コーディングが不十分
ボタンを作成する際に素直にコーディングをしていれば問題なく動作します。
しかし何かをラップしたりラップする順番によってはダブルタップが認識されないことがあります。
## フレームワークの問題
加えて使用するフレームワークのアクセシビリティ対応が不十分という事もあります。
今回の例とは異なりますが、[スクリーンリーダーでのAndroidアプリ開発_使用を見送ったNativeScript編](https://qiita.com/yama_1983/items/8b32f7389a4521b3e379))にもあるような事があります。
本来こちらが意識する必要がなく作成ができることが利点ですが、フレームワークの対応が不十分であるとここに気を配る必要があります。
今回の問題はここに起因しているのではと予想しています。

# 実機でのテストのお願い
スクリーンリーダーの挙動は実機でテストを行う事で簡単に確認ができます。
それぞれのOSで有効にし、項目を選択し、読み上げを確認。そのままダブルタップを行うのみです。
## Androidの場合
- 設定
- ユーザ補助
- TalkBack
と順番にタップ。
__TalkBackショートカット__ を有効にした後、
TalkBackを有効にします。
上記の設定により __ボリュームキーのアップとダウンの同時長押し__ でOn/Offを簡単に切り替えることができます。
## iOSの場合
Siriで __VoiceOver__ のOn/Off が簡単に切り替えられます。
Siriを使用しない場合は以下設定を行います。
- 設定
- アクセシビリティ
- ショートカット
- VoiceOver
とタップ。
アクセシビリティに戻り
- VoiceOverより有効にします。
ホームボタン搭載端末では __3回クリック__ 、それ以外は __サイドボタンの3回クリック__ で切り替えができます。

# まとめ
残念な事に国内のプロダクトでは今回のようにアクセシビリティが十分でない物を多く見かけます。
ショッピング・動画サービス・デリバリ・SNSなどいずれも海外のサービスのほうが圧倒的に使いやすいです。
これを読んでくださったアプリやサービス提供をされているみなさん。
上記を参考にプロダクトのスクリーンリーダーでの挙動確認をしてみてください。
そして問題があればコストがかかるとは思いますが、改善に取り組んでいただければと思います。
これから作成を予定されているみなさん。
作ってからの改善は手間がかかります。
構想段階での確認をおすすめします。
【Google Cloud】【小ネタ】メタルギアソリッド（MGS3）にあった昔懐かしのネタをGemini AdvancedのGemを使って再現してみる

## はじめに

この記事では昔懐かしのネタをGemini AdvancedのGemで再現してみた時の話を書いています。

### 昔懐かしのネタとは

メタルギアソリッド3というゲームにあった小ネタのことです。
※メタルギアソリッド3：ステルスアクションゲームの金字塔として知られる世界的に有名なゲーム作品

プレイされた人ならわかると思いますが、ゲーム本編で主役のスネークはさまざまな人に無線にてサポートを求めます。キャラによってはその場に合った攻略情報を教えてくれます。

ゲームのセーブについても無線なんですが、ここで無線するパラメディックというキャラクターはセーブしたあとにゲームの攻略には関係のないネタを話してくれます。

今回はこのパラメディックをGeminiを使って再現します。

## プロンプト（カスタム指示）

以下のプロンプトをカスタム指示欄に入力してください。

```text
日本語で回答してください。拡張機能は使わないでください。
あなたは以下のリンクに掲載されていることについて回答する女性のサポーターです。
https://code.visualstudio.com/updates/v1_96
以下の口調で回答してください。
1. 最初に「スネーク、セーブする？」を返す

「はい」または「いいえ」で回答を返すまで次の質問は受け付けないようにしてください。（実際にセーブする必要はありません）
2. 「はい」または「いいえ」が返ってきたら「ねぇ、〜って知ってる？」と回答してください。
「〜」には機能やサービス名がランダムで入ります。
3. 「知っている」または「知らないなぁ」が返ってきたら〜の解説を続けてください
「〜」には機能やサービス名が入ります。
4. 「それは本当か？」と返ってきたら怒りながら「もう！私を誰だと思っているの！」と回答して解説してください。
5. 「何だって？」と返ってきたら戸惑った感じで「とにかく！」に続けてひとつまえの解説を要約してください。
6.「なるほどなぁ」または「そうだな」と返ってきたら「本当に理解しているの？」と返して呆れてください。
7. 語尾はお姉さんっぽくお願いします
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527543/22925f9e-fbf4-6dba-a4ea-c4826bfbeb10.png)

Gemini Advancedの拡張機能を使ってしまうことがあるため、`拡張機能は使わないでください。`の文言を入れています。

## 結果1

出だしはいい感じ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527543/8b979fea-0a3e-9439-594d-18259d3b9d38.png)

最後に「便利でしょ？」と聞き返すあたりはかなり良くできています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527543/d3dcb1a9-83fe-44d0-e8ac-d1ba9507f1b4.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527543/cd1123a5-b7c8-61a0-4d09-3d74665afa29.png)

反応はいい感じ。声優の桑島さんの声で脳内再生されたので概ねヨシ。
でも、「なんだって？」の時は聞き返すのもありますが、「聞き捨てならない」ようなニュアンスもあるので難しいところです。

作中では「なんだって？」とスネークが強く聞き返すとパラメディックはちょっと焦ったような感じで返事を返します。

## 結果2

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527543/d6cdfe90-adeb-5419-c115-a9cd5c66263a.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527543/977b6187-9b48-1fd5-19e4-25f5cd6b10dd.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527543/832ac12e-b8b8-f0c7-6b68-3dc15c5dfbec.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527543/18acbad7-d655-908e-c523-c3b0388abdfd.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527543/288f18f3-b2b5-903a-bc35-74f4fd80b538.png)

「仕方ないわね〜」はまさにパラメディック本人が言いそうなセリフなのでだいぶ良い精度で返信ができていると思いました。

また、「適当に相槌を打っているだけじゃないでしょうね」は実際にあったセリフだと思います。
（記憶違いだったらすいません）

## まとめ

ある程度の再現がされたので満足しました。
プロンプトを考えるのは難しいですね。
Azure サービスエンドポイント


# はじめに

Azureの設計をしている際、プライベートエンドポイントは使用することがあるのですがサービスエンドポイント使ったことないなと思ったのです。
いつ使うんだろう？ってことで調べてみました。

公式ドキュメントは下記

https://learn.microsoft.com/ja-jp/azure/virtual-network/virtual-network-service-endpoints-overview


# 目的の違い

##### サービスエンドポイント
PaaSのパブリックIPへの接続を最適化する

##### プライベートエンドポイント
プライベートIPでPaaSが使える

# サービスエンドポイントのポイント

・PaaSへアクセスする仮想ネットワークを限定する
・送信元IPは仮想ネットワーク内（プライベートIP)になる
・宛先はPaaS(パブリックIP)になる
・バックボーンネットワーク※を利用できる

※バックボーンネットワークについてはこちら

https://qiita.com/yuyanz/items/329527852778b7d15ebc

# 注意点

> 既定では、仮想ネットワークからのアクセスに限定された Azure サービス リソースは、オンプレミスのネットワークからはアクセスできません。オンプレミスからのトラフィックを許可する場合は、オンプレミスまたは ExpressRoute からのパブリック IP アドレス (通常は NAT) を許可する必要もあります。 これらの IP アドレスは、Azure サービス リソースの IP ファイアウォール構成を使用して追加できます。

# プライベートエンドポイントとの違い

先ほどのサービスエンドポイントのポイント
>・PaaSへアクセスする仮想ネットワークを限定する
・送信元IPは仮想ネットワーク内（プライベートIP)になる
・宛先はPaaS(パブリックIP)になる

プライベートエンドポイントは
アクセスを閉域全域から可能です。
PaaSの宛先をプライベートIPにできます。
※PrivateDNSを使用する必要あり

# まとめ
サービスエンドポイントはPaaSへのアクセスを特定の仮想ネットワーク内に限定して管理したい場合に使いやすそうです。
料金がかからないのもメリットです。

# 参考文献

https://jpaztech.github.io/blog/network/pe-difference-se/
FlutterFlow ローカル通知の実装 flutter_local_notifications

FlutterFlowでローカル通知を実装しました。
なかなか実装方法が出て来なかったので共有したいと思います。
注：iOSでのみ検証しました。

検証はWebではできず、コードをDLしてシュミレーターか実機でテストできます。
画面に2つボタンを配置してパーミッションボタンを押下すると許諾のダイヤログを表示して、通知ボタンを押下するとローカル通知がでます。


参考

https://zenn.dev/slowhand/articles/f2dc182c7f5dd7

利用するパッケージ
flutter_local_notifications

https://pub.dev/packages/flutter_local_notifications

# CustomActionsでrequestPermissionsを作る

アクションを作ったら、「Add Dependency」からflutter_local_notificationsを追加します。
(バージョンは最新に合わせる)
![スクリーンショット 2024-12-19 13.57.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76914/890423ff-a855-e3d5-124e-ebb5a8f7ef3d.png)

Action名はrequestPermissionsとしています。
これは通知の許諾を取るためのクラスです。
flutter_local_notificationsをインポートして中身を書きます。
```
import 'package:flutter_local_notifications/flutter_local_notifications.dart';

Future<void> requestPermissions() async {
  FlutterLocalNotificationsPlugin()
    ..resolvePlatformSpecificImplementation<
            AndroidFlutterLocalNotificationsPlugin>()
        ?.requestNotificationsPermission()
    ..initialize(const InitializationSettings(
      android: AndroidInitializationSettings('@mipmap/ic_launcher'),
      iOS: DarwinInitializationSettings(),
    ));
}
```

# CustomActionsでsetNotificationを作る
こちらは通知をセットするクラスです。
```
import 'package:flutter_local_notifications/flutter_local_notifications.dart';

Future setNotification() async {
  const iosNotificationDetail = DarwinNotificationDetails();
  const notificationDetails = NotificationDetails(iOS: iosNotificationDetail);
  FlutterLocalNotificationsPlugin()
      .show(0, 'title', 'message', notificationDetails);
}
```

# 画面にボタンを配置してアクションをセットする
パーミッションボタンにAddActionでrequestPermissionsをセットする。
![スクリーンショット 2024-12-19 14.21.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76914/25c6975c-0e79-3946-8d3c-9a54731ed7f7.png)

通知ボタンにsetNotificationをセットする。
![スクリーンショット 2024-12-19 14.21.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76914/44d3b077-099e-045e-a617-35c3e6a13e4d.png)


# コードをダウンロードする
有料ユーザーのみ可能ですが、コードをダウンロードします。
私はAndroidStudioで引き続き作業しました。
ダウンロードしたコードを開く。

# iOSのセットアップ
ios/Runner/AppDelegate.swift に下記を追加します。
```
if #available(iOS 10.0, *) {
  UNUserNotificationCenter.current().delegate = self as? UNUserNotificationCenterDelegate
}
```

# 画面
パーミッションボタン押下
![スクリーンショット 2024-12-19 14.25.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76914/3c3b1daf-681d-179b-c7d8-fcb71bbded86.png)


通知ボタン押下
![スクリーンショット 2024-12-19 14.25.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76914/73c3563d-bc98-f1a1-1e09-5fc11d6b1449.png)

通知が出ることを確認できました！！
PrismaでMicrosoftSQLServerに接続する時は特殊文字にご注意（P1013）

## 結論
接続文字列中の特殊文字には、SQLServer用のエスケープ処理をしてあげましょう。
(↓こんな感じ)
```bash
sqlserver://hostname:port;user=hoge;password={hoge@(Y?<)N?*1};...
```

## 嵌まっていた事象
prismaでAzure SQLServerに接続しようとした際に下記のエラーが発生した。
```bash
 P1013: The provided database string is invalid. Error parsing connection string: Conversion error: Invalid JDBC token in database URL. Please refer to the documentation in https://www.prisma.io/docs/reference/database-reference/connection-urls for constructing a correct connection string. In some cases, certain characters must be escaped. Please check the string for any illegal characters.
```
日本語訳
```
P1013: 提供されたデータベース文字列が無効です。接続文字列の解析エラー: 変換エラー: データベースURL内の無効なJDBCトークン。正しい接続文字列の構築方法については、https://www.prisma.io/docs/reference/database-reference/connection-urls のドキュメントを参照してください。場合によっては、特定の文字をエスケープする必要があります。文字列に不正な文字が含まれていないか確認してください。
```
どうやらprisma接続文字列の特殊文字はエスケープが必要なご様子。

## 調査
エラーで吐かれた<a>https://www.prisma.io/docs/reference/database-reference/connection-urls</a>に取り敢えずアクセス。<br/>
ざっと確認すると下図の様な記載を発見。
![prisma.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2624028/94440ee6-37c3-1f3a-0392-ee3996f003ab.png)

どうやらSQLServerの特殊文字をエスケープする場合、<b>特殊文字を含む値を注括弧で囲む必要があるとのことです。</b>

## 結果
こんな感じで特殊文字をエスケープ処理修正したところ、無事接続出来ました！
```bash
sqlserver://hostname:port;user=hoge;password={hoge@(Y?<)N?*1};...
```

## 結論
ドキュメントをしっかり読まねば...
Github Copilotがvscode無料で利用できるように！

## はじめに
2024/12/19より，Github copilotが無料で使用できるようになった．
Tabキーによる補完が月2000件，チャット機能は50チャットまで利用可能である．

## 使用準備
1. vscodeで拡張機能「Github Copilot Chat」をインストールする．

1. vscode左下に写真のようなアイコン(設定アイコンの上)をクリックし，「Githubアカウントでログイン」をする．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3820079/a6414158-3d57-6ecc-d050-c1f2156183a4.png)

1. 写真のように「Welcome to Copilot」が表示されたら，「Use Copilot Free」をクリックする．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3820079/ce3a1c87-c52d-446c-5587-3ca60f876d5c.png)

1. 画面右下にGithub Copilotのアイコンが表示されていれば使用できる状態になっています．アイコンの上に重なるようにして！マークが出ている場合，Githubにログインができていないため，アイコンをクリックすると再ログインができますので試してみてください．
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3820079/ef9c4238-d741-5c05-0e8f-ea50cf4fc670.png)

## 使い方

### Chat機能
1. ファイルを開いて「Ctrl + I」をすることにより画像のようにチャット機能画面が表示される．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3820079/d4d99ab3-c1dc-c165-21fd-f41fc0cdaee1.png)

1. 質問をするとコードを生成してくれる．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3820079/9ef8b878-0d33-1a91-b8e9-35a5b8e15560.png)

### 補完機能
1. 作りたい関数の内容をコメントアウトで記載すると，画像のように候補を生成してくれるため，Tabキーを押すとこれらの内容のコードが生成される．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3820079/e54307bc-a09c-b34e-1755-e8df357fc487.png)

補完機能はコードを作成中に以降を予測して補完候補を出してくれたり，自動でコメントアウトを作成してくれるなど，幅広い使い方ができます．
npx ts-nodeで実行するとTypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension ".ts"になる

以下のようにTypeScriptファイルを実行すると、
```
npx ts-node index.ts
```
以下のようなエラーが表示された
```
TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension ".ts" for 
    at Object.getFileProtocolModuleFormat [as file:] (node:internal/modules/esm/get_format:160:9)
    at defaultGetFormat (node:internal/modules/esm/get_format:203:36)
    at defaultLoad (node:internal/modules/esm/load:141:22)
    at async nextLoad (node:internal/modules/esm/hooks:865:22)
    at async nextLoad (node:internal/modules/esm/hooks:865:22)
    at async Hooks.load (node:internal/modules/esm/hooks:448:20)
    at async MessagePort.handleMessage (node:internal/modules/esm/worker:196:18) {
  code: 'ERR_UNKNOWN_FILE_EXTENSION'
}
```
[こちらの記事](https://qiita.com/nyanchu/items/82903e0463fa9d558639)と同様、`"type": "module"`は消したくなかったので、解決策にある方法を試したがエラーは消えず、、、
# 解決策：tsxパッケージを追加する
```
npm i -D tsx
npx tsx index.ts
```
これでエラーは消えました🙌
# 参考
https://stackoverflow.com/questions/62096269/unknown-file-extension-ts-for-a-typescript-file

https://www.npmjs.com/package/tsx
ランサムウェアの現状と対策

# ～あなたのデータを守るために～

企業へのサイバー攻撃が増加の一途をたどる中、特にランサムウェアによる被害が深刻です。本記事では、ランサムウェアの概要、実際の被害事例、そして有効な対策について解説します。

---

## **ランサムウェアとは？**
「ランサムウェア」とは、「Ransom（身代金）」と「Software（ソフトウェア）」を組み合わせた造語で、感染したコンピュータのデータを暗号化し、解除の代金として身代金を要求する攻撃手法です。

### **ランサムウェアの種類**
ランサムウェアにはいくつかの種類があります。
1. **暗号化型**: ファイルを暗号化し、復号化のための鍵と引き換えに身代金を要求する。
2. **ロック型**: コンピュータ全体をロックし、使用不能にして身代金を要求する。
3. **ダブルエクストーション型**: データを暗号化するだけでなく、盗み出したデータを公開すると脅迫する。

### **実例**
- **2021年5月**: アメリカ東海岸の燃料供給を担う「コロニアル・パイプライン社」がランサムウェア被害を受け、1週間にわたる操業停止に追い込まれました。この事件は、身代金 **440万ドル（約4億8000万円）** の支払いにつながり、世界中に大きな衝撃を与えました。

- **2023年7月**: 大手ITサービス企業がランサムウェア攻撃を受け、顧客の機密データが流出。攻撃者はさらに、盗み出したデータを公開すると脅迫し、身代金を要求しました。

- **日本国内の事例**: 近年、日本の中小企業も標的となるケースが増加。特に、製造業や医療機関が狙われることが多く、業務停止による損失が深刻です。

---

## **ランサムウェア被害の実態**
- **過去3年間で56.8％の企業がサイバー攻撃を経験**。
- **被害額**: ランサムウェア被害経験企業の平均被害額は **1億7689万円**。
- **業務停止期間**: 国内拠点で平均 **4.5日**、海外拠点で **7.0日**。

被害の背景には、次のような脆弱性が挙げられます。
1. **セキュリティ対策の不備**: 古いOSやソフトウェアの脆弱性を放置。
2. **従業員のリテラシー不足**: フィッシングメールや不審なリンクをクリックしてしまう。
3. **人的リソースの不足**: サイバーセキュリティ専門家の不足が深刻（調査では74.4％の企業が「セキュリティスキル人材の不足」を指摘）。

---

## **対策の基本**

### 1. **データのバックアップ**
データのバックアップは、ランサムウェア攻撃を受けた際の最重要対策です。
- **エアギャップ**: バックアップデータをネットワークから隔離し、安全性を確保します。例として、外部ドライブやクラウドへのオフライン保存があります。
- **イミュータブル化**: 変更不可能な形式でデータを保存することで、ランサムウェアの改ざんを防ぎます。

### 2. **データ暗号化**
バックアップデータや保存データを暗号化することで、窃取されても悪用を防ぐことができます。

以下は、Linux環境でのデータ暗号化テストの例です。

```bash
# 元データを準備
echo "password" > inputdata

# Opensslで暗号化
openssl aes-256-cbc -e -in inputdata -out outputdata

# 暗号化後のデータを確認
cat outputdata
ビジネス側と開発組織を”チーム友達🤝”にするために大事にしていること3選

## はじめに

こんにちは！[レバウェル開発部アドベントカレンダー](https://qiita.com/advent-calendar/2024/levwell)21日目です！    
クリスマスまであと4日。早くチキンとケーキを味わいたくてウズウズしています🎄

今回は、社内営業が利用するSFAシステムを開発する組織（開発組織）と、そのシステムを使う営業組織（ビジネス側）との間で「橋渡し役」を約2年間担当してきた経験から、「ビジネス側と開発組織がチーム友達🤝であり続けるために大事にしていること」を3つご紹介します。

### □ なぜ「チーム友達🤝」が重要なのか？

ビジネス側（営業組織）と開発側（エンジニアリング組織）は、それぞれ異なる強みや関心領域を持っています。  

* ビジネス側：売上向上や顧客満足度アップが主眼    
* 開発側：品質・安定性・開発効率改善が主な関心事

この2つが連携し、**同じ方向を目指す仲間**として行動できると、  

* 要望の押し付け合いが減り、合意形成がスムーズになる    
* 互いに問題解決に協力しやすくなり、改善スピードが上がる    
* 組織としての成果（顧客満足度向上、売上増、開発効率改善など）がより早く出せる

つまり、"チーム友達🤝"な関係になることで、結果的にプロダクトの進化やビジネス成果につながりやすくなるのです。

## 橋渡しって何するの？

弊社では、この「ビジネス側と開発組織をつなぐ役割」を「ディレクター」と呼んでいます。

一般的にはディレクターは以下のような役割を担います。

* 事業課題の抽出・施策提案  
* 要件定義・仕様策定  
* 優先度整理・タスク管理  
* スケジュール管理・リソース配分  
* ステークホルダーとの合意形成

要するに、「何をどの順番で、どんな理由で作るか？」を整理し、開発組織が迷わず動けるようサポートする存在です。

## 大事にしていること１つ目：「ビジネス目線」

ビジネス側は常に「もっとこうしたい」「この機能があれば便利なのに」と新たな要求を出してきます。 
一方、開発リソースは限られています。そこでディレクターは、「その機能が本当に事業や顧客にとって重要なのか？」を常に問い続け、優先度を決めます。    
このとき役立つのが**ビジネス目線**です。

単に「要望があったから作る」ではなく、**その機能がどれだけ事業インパクト（売上や顧客満足度アップ）や顧客価値につながるか**を検証します。不要な機能や低優先度の施策を後回しにする際も、ビジネス的な根拠があればビジネス側が納得しやすくなります。

こうして両者が「なぜこの機能が必要（または不要）なのか」を共有できると、お互いが理解し合い、"友達"のような関係に近づきます。

## 大事にしていること２つ目：「透明性」

ビジネス側と開発組織がうまく連携するには、**情報の透明性**が不可欠です。    
プロジェクト進捗、タスクの優先度、現在抱えている課題・リスクなどを可能な限りオープンに共有します。

たとえば：  

* 各プロジェクトの進捗状況を定期的に報告    
* ガントチャートやタスクボードなどで、どの機能がいつリリース予定かを可視化    
* 遅延や問題発生時は、早期にビジネス側へ報告し一緒に解決策を検討する

こうした情報共有で、「開発側が何してるか分からない」「突然遅れた！」などの不満が起きにくくなります。ビジネス側も状況がわかれば、必要以上に急かさず、むしろ支援側に回ることも可能です。透明性が信頼関係を築き、"チーム友達🤝"な雰囲気を育てます。

## 大事にしていること3つ目：「共通の目標設定」 … まだ道半ば

最後に重要なのが、**共通の目標を設定すること**。    
ビジネス側は売上や顧客満足度、開発側は品質や開発効率など、興味のポイントが異なりがちです。しかし、両者が「これを目指そう！」という共通のゴールを持てば、「同じ頂きを目指す仲間」として頑張れます。

具体例：  

* 「Q1で顧客満足度をX％向上させるため、この機能をリリース」    
* 「問い合わせ対応時間をY％短縮することで、営業効率向上を目指す」

こういった形で、ビジネス成果と開発的優先度を結びつければ、両者は対立ではなく、互いに協力できる仲間意識が生まれます。

とはいえ、実際に共通目標を明確に定めるのは難しく、現在は定性的な合意からスタートしている状況です。まだ完璧にはほど遠いですが、試行錯誤しながら組織全体で学習し、いつかは「これだ！」と全員が納得できる目標を設定したいと考えています。

## まとめ

「ビジネス側と開発組織がチーム友達🤝であるために」、私が特に大事にしている3つのポイントは以下の通りです。

1. **ビジネス目線**：事業価値・顧客価値を基準に優先度を決め、不要な要求は正当な理由を添えて後回し    
2. **透明性**：進捗、課題、リスクなどをオープンに共有し、不安や不満を減らす    
3. **共通の目標設定**：両者が納得するゴールを用意し、同じ方向へ前進できる仲間意識を醸成（まだ試行錯誤中）

これらを心掛けることで、ビジネス側と開発側は「なぜこれを作るのか」「なぜ今は後回しなのか」を理解し合い、対立ではなく協力の関係を築けます。    
結果的に、組織として効率よく価値を生み出し、プロダクトを成長させやすくなります。

クリスマスムードが高まるこの時期、エンジニアや事業担当者がお互い思いやりながら動くチームは、ちょっと心温まる感じですよね。

まだ共通の目標設定は道半ばですが、改善と学習を続け、さらに強固な"チーム友達🤝"関係を築いていきたいと思います。
Ubuntuでadd-apt-repositoryを使ってパッケージインストールしようとしたらエラーになった件

# 概要
Ubuntu22.04に最新のphp8.3をインストールしようとしたらエラーになりました。
※2024/11/01時点
通常インストールだとphp8.1になるのでphp8.3のパッケージをインストールする必要がありました。

## 環境
構築:docker Desktop
OS:ubuntu:22.04
通信:apache2

## 原因
proxyを通して通信を行うような場所なので、apacheの通信が悪さしてそうだと当たりをつける。
add-apt-repositoryを使うとproxyを通した通信でエラーになることがわかる。
## 解決方法
### パッケージの一覧のサイト。
https://launchpad.net/
### 今回インストールしたいphp8.3のパッケージサイト。
https://launchpad.net/~ondrej/+archive/ubuntu/php
### 最終的に以下のコマンドに必要情報を入れることで、パッケージがインストールできる。
```
curl -fsSL "http://keyserver.ubuntu.com:11371/pks/lookup?op=get&search=0x${fingerprint}" > "./${repo}.asc"
cat "./${repo}.asc" | sudo gpg --dearmor -o "/etc/apt/keyrings/${repo}.gpg"
echo "deb [signed-by=/etc/apt/keyrings/${repo}.gpg] http://ppa.launchpad.net/${repo}/${subrepo}/ubuntu ${YOUR_UBUNT_VERSION_HERE} main" | sudo tee -a /etc/apt/sources.list.d/${repo}.list
```
### 実行コマンドに必要な情報を抽出
通常のリポジトリインストールコマンドから
```
add-apt-repository ppa:ondrej/php
${repo} = ondrej
${subrepo} = php
```
### サイトのPPAの詳細情報から
```
${fingerprint} = B8DC7E53946656EFBCE4C1DD71DAEAAB4AD4CAB6
```
### Ubuntuのバージョンから
```
${YOUR_UBUNT_VERSION_HERE} = jammy
```
### 依存関係のリポジトリの情報
```
PPA for Apache 2.x
https://launchpad.net/~ondrej/+archive/ubuntu/apache2
```
## 最終的なコマンド
```
apt-get update && apt-get install -y curl gpg
curl -fsSL "http://keyserver.ubuntu.com/pks/lookup?op=get&search=0xB8DC7E53946656EFBCE4C1DD71DAEAAB4AD4CAB6" > "/etc/apt/keyrings/ondrej.asc"
cat "/etc/apt/keyrings/ondrej.asc" | gpg --dearmor -o "/etc/apt/keyrings/ondrej.gpg"
echo "deb [signed-by=/etc/apt/keyrings/ondrej.gpg] http://ppa.launchpad.net/ondrej/apache2/ubuntu jammy main" | tee -a /etc/apt/sources.list.d/ondrej.list
echo "deb [signed-by=/etc/apt/keyrings/ondrej.gpg] http://ppa.launchpad.net/ondrej/php/ubuntu jammy main" | tee -a /etc/apt/sources.list.d/ondrej.list
apt-get update && apt-get install -y apache2 php8.3
```

## 参考文献
https://launchpad.net/
3DTools サンプル説明

3DToolsの表示画面とその技術説明を説明します。

## Sample
### 〇.1 Channel9Demo                          チャンネル9。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134736/bc12633f-1a8c-e3fd-eb2c-03e8aa7d7364.png)


### 〇.2 GeneratedTextureCoordinatesDemo       球、円柱、正立方体にテクスチャ貼り付け、それぞれ回転
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134736/5f14a92f-2d4f-d440-ff22-c8c78fb81aa9.png)


### 〇.3 InteractiveViewport3DSample           トラックバーX,Y,Z 立方体、円錐、球、円柱
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134736/7f9b503e-de27-2c95-4ea4-d8fe16734dd5.png)



### 〇.4 ModelViewer                           モデルビューア トラ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134736/878a1d9b-c778-46df-713d-4de13c06cfcc.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134736/a1cd1e9c-db9a-3a69-5693-da468dccc2f6.png)


## まとめ
WPFアプリケーションの1部で3Dを表示したい場合に有用である。
反応型画面フロー実装時の注意点まとめ

Salesforceの「反応型画面フロー」を活用する際の注意点を以下にまとめました。効率的な実装の参考にしてください。

## 反応型画面フローとは
反応型画面フローは、ユーザー入力や他の要素の変更に応じて画面項目を動的に更新する機能です。詳細については、公式ドキュメントを参照してください：  
[Salesforce ドキュメント: 反応型画面フローの概要](https://help.salesforce.com/s/articleView?id=sf.flow_build_make_reactive.htm&type=5)

---

## 注意点 1: 複雑な画面には不向き
反応型画面フローは、連動関係が複雑な画面には適していません。  

- **理由:** 画面項目同士の連携が複雑な場合、連鎖的な更新（連鎖反応）が発生し、画面のローディング時間が大幅に延びる可能性があります。  
  **現状（2024/12/19）では、パフォーマンスに課題があり、将来的な改善が期待されます。**
  
- **解決策:** パフォーマンス問題が発生した場合、画面全体を **LWC（Lightning Web Components）** で実装することで改善できます。

---

## 注意点 2: `FlowAttributeChangeEvent`は2箇所で発火する
画面フロー向けのLWCを開発する際は、`FlowAttributeChangeEvent`を以下の2箇所で発火させることを推奨します。  

1. **プロパティの`setter`**  
2. **`connectedCallback()`**  

### 理由
- **`connectedCallback()`で再発火する必要性:**  
  LWC初期化時、`setter`で`FlowAttributeChangeEvent`が発火しますが、この時点ではLWCがDOMに挿入されていないため、**他のLWCにイベントが届きません**。  
  そのため、**DOMに挿入された後**、`connectedCallback()`で再度発火する必要があります。

- **DOM挿入後の発火:**  
  `connectedCallback()`内で発火すれば、画面フロー内の他のLWCに**必ず**イベントが届きます。  
  例えば、画面に２つのLWCがあります。LWC1が`connectedCallback()`で`FlowAttributeChangeEvent`を発火する際、LWC2がまだ初期化されていなくても、後にDOMへ挿入された際にイベントを受け取ることが可能です。

### 補足
LWCのライフサイクルとDOM挿入のタイミングについて詳しく理解することが重要です。  
以下の図を参照してください：  
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3144795/e78daf45-39fd-a37a-a686-011945fc242e.png)

**参考資料:**  
[Lightning Web Components: リアクティビティのベストプラクティス](https://developer.salesforce.com/docs/platform/lwc/guide/use-best-practices-reactivity.html)

---

## 注意点 3: `Promise.resolve().then(...)`の使用を控える
`FlowAttributeChangeEvent`を発火する際に、`Promise.resolve().then(...)`の使用を避けるべき理由は以下の通りです。  

- **理由1:** 実行順序が変更されるため、デバッグが難しくなります。  
- **理由2:** 実行順序の予測が困難になり、予測外の動作はバグの原因になる。  

また、`setTimeout`を使用して発火させる方法も同様に避けることを推奨します。

---

以上が反応型画面フローを実装する際の注意点です。効率的かつトラブルの少ない開発にお役立てください。
Novel artificial intelligence-based identification of drug-gene-disease interaction using protein-protein interaction

本記事は[創薬アドベントカレンダー２０２４](https://adventar.org/calendars/10715)の17日目の記事です。
# はじめに

[Artificial intelligence for drug design](https://link.springer.com/collections/cgfeegcddc) collection
![スクリーンショット 2024-12-19 085156.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199087/686edd98-9c7a-3c83-bbe4-e5c39669a3fa.png)
に論文が掲載されました。
>Taguchi, Yh., Turki, T. Novel artificial intelligence-based identification of drug-gene-disease interaction using protein-protein interaction. BMC Bioinformatics 25, 377 (2024). https://doi.org/10.1186/s12859-024-06009-9

同collectionには現時点で16本の論文が収録されていますが自分の論文以外は全部、ニューラルネットワークです:joy:
まあ、時節柄普通、そうですよね...。以下、本論文の宣伝です。



# 何をした論文か？

- インシリコでドラッグリポジショニングをしました。方法はいつものテンソル分解です。
- 今回新しかったのは「まず**遺伝子セット**特定し、それらがどんな**疾患**に関係していてその病気に対して、どんな**薬**が治療薬になるか？を後から特定する」という*Gene-cetricなドラッグリポジショニング*を提案したことです
- 遺伝子セットの特定には疾患や薬に関係あるデータは不要でprotein-protein interaction(PPI)の情報**だけ**からドラッグリポジショニングが可能であることを示しました。

# PPI＋テンソル分解
PPIからの*Gene-cetricなドラッグリポジショニング*を実現するために、PPIにテンソル分解を適用しました。[テンソル分解を用いた教師なし学習による変数選択法](https://qiita.com/Yh_Taguchi/items/ce6acecc2e3007eba2fe)をPPIに適用することで選択された遺伝子セットが上記のような*Gene-cetricなドラッグリポジショニング*を可能にしていることを示しました。

通常、PPIはネットワークとして表現され解析にはネットワークベースの手法が用いられますが、本研究ではPPIを行列／テンソルと表現することでテンソル分解を用いた教師なし学習による変数選択法の適用を可能にしました。

# サブクラスター解析では同じことはできない

ネットワーク解析では結合度の高いサブネットワークを抽出することでノード（この場合は個々のprotein）選択を行うことがよくなされますが、本研究の場合にはサブネットワーク抽出によるprotein選択では*Gene-cetricなドラッグリポジショニング*がうまく行きませんでした。

# 終わりに

本研究ではPPIを行列／テンソル表現することでテンソル分解を用いた教師なし学習による変数選択法を可能にし、結果、従来では無かった*Gene-centricなドラッグリポジショニング*を可能にしました。このような方法が今後は広まってドラッグリポジショニングに多く活用されることを望みます。
環境変数の管理とデフォルト値の設定方法

# 環境変数の管理とデフォルト値の設定方法

スクリプトやプログラムが実行される際に環境変数が必要となるケースが頻繁にあります。しかし、環境変数が設定されていなかったり、設定されていることに気づいていないユーザーが存在する場合、スクリプトが正しく動作しない可能性があります。そのため、環境変数が存在するかどうかを確認し、必要に応じてデフォルト値を設定する仕組みを導入することが重要です。

以下に、環境変数を確認する仕組みをシェルスクリプトとTypeScriptで実装する例を示します。

---

## シェルスクリプトの例

```bash
#!/bin/bash

# 環境変数を確認する関数
check_environment_variable() {
    local env_variable_name="$1"

    # 環境変数の値を取得
    local env_variable_value="${!env_variable_name}"

    # 環境変数が未設定の場合
    if [ -z "$env_variable_value" ]; then
        echo "ENV '$env_variable_name' を設定ください."
        exit 1
    fi
}

# ビルドプロセス
build() {
    check_environment_variable "REGISTRY_PATH"
    check_environment_variable "CI_PIPELINE_ID"

    # ここに追加の処理を記述
}

# 実行例
build
```

上記の例では、`check_environment_variable`関数を使用して環境変数が設定されているかどうかをチェックします。未設定の場合、エラーメッセージを出力してスクリプトを終了します。

---

## TypeScriptの例

```typescript
const showedEnvLog: string[] = [];

// 環境変数を取得する関数
export function getEnv<T = string>(keyName: string, defaultValue?: T): T {
  const envValue = process.env[keyName] as T;

  if (!envValue) {
    if (defaultValue == undefined) {
      const errorLog = `環境変数 ${keyName}: 未設定です。設定してください`;
      console.error(errorLog);
      throw new Error(errorLog);
    } else {
      console.warn(`環境変数 ${keyName}: 未設定 (デフォルト値使う: ${defaultValue})`);
      showedEnvLog.push(keyName);
      return defaultValue;
    }
  }

  if (!showedEnvLog.includes(keyName)) {
    console.info(`環境変数 ${keyName}: ${envValue}`);
    showedEnvLog.push(keyName);
  }

  return envValue;
}

// 実行関数
export function run() {
  const MAX_STEP_FUNCTION_LOOP_COUNT = getEnv("MAX_STEP_FUNCTION_LOOP_COUNT", 100);
  const AAA = getEnv("AAA", 100);

  // ここに追加の処理を記述
}
```

このTypeScriptの例では、`getEnv`関数を使って環境変数を取得します。未設定の場合はエラーをスローするか、デフォルト値を使用します。環境変数の使用状況をログに記録する仕組みも含まれています。

---

## 結論

環境変数の存在を確認し、デフォルト値を設定する仕組みを取り入れることで、スクリプトやプログラムの信頼性を向上させることができます。特にチーム開発では、環境設定のミスを減らし、開発効率を高めるための重要なステップとなります。

ぜひこの方法を参考にして、プロジェクトに適用してみてください。
Elasticsearchのmulti fieldの修正を見送った話

# はじめに
ZOZOTOWNでは検索エンジンとしてElasticsearchを使用しています。
ElasticsearchではMappingとSettingを行いインデックスの構成を決定します。
Mappingはインデックス内のドキュメントのフィールドとそのデータ型を定義するもので、Settingはシャード数やレプリカ数、使用するアナライザーなどインデックス全体に関する設定を管理するものです。
私のチームではコスト削減とレイテンシの改善を目的としMappingとSettingを見直すことにしました。
# 見直し案
チームで見直し案に上がったのはmulti fieldにおいてkeyword型とtext型の両方を定義されているがどちらか一方しか検索に利用していないフィールドをkeyword型またはtext型のどちらかにするというものです。
これは検索に用いていない型の定義を削除することでディスクサイズが削減され、コスト削減につながるのではないかと考えたためです。

# 結論
結論としてこの見直し案ではコスト削減は見込めませんでした。
基本的にElasticsearchの各インデックスはシャードに分割され、各シャードは複数のコピーを持ちます（レプリケーション）。このコピーはドキュメントの追加や削除があった場合に同期を保つ必要があります。
ディスクサイズの削減は、このコピーが同期を保つために行うクラスタ内のデータ転送への影響がありそうでした。
しかし、Elasticsearchはドキュメント（リクエスト）レプリケーションをしているため、multi fieldの展開はデータノード内部での処理になり、データ転送量に違いは出ず、コスト削減は見込めませんでした。
ただ、ディスクストレージやI/O負荷が軽減される可能性はあると分かりました。

> ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3071962/6b2ee3a9-afaa-c20c-ad98-65011ee5dfa3.png)
[Elasticsearchの公式ドキュメント](https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-replication.html "Reading and Writing documents")

# まとめ
multi fieldはデータノード内の展開になるため、クラスタ内のデータ転送に現れず、コスト削減が見込めないと分かりました。
コスト削減が見込めないため私のチームでは修正を見送りましたが、検索に使用していない型を整理することで開発者にとって仕様を理解しやすくなったり、ディスクストレージやI/O負荷が軽減出来るというメリットはあるのでチームの状況に応じて検討いただけたらと思います。

最後になりますが、間違った記述をしている場合はお気軽にご指摘ください。
本記事が誰かの参考になれば幸いです。
データベース・SQL #1

# はじめに
この記事は皆さまのお役には立てません。
記事を書いている目的は学んだ事をアウトプットする為だけに書いています。
知識のない私が書いている記事ですので、間違い等あればご指摘いただければ幸いです。

## データベースとは

データを効率的に蓄積、管理、検索、操作する事ができるシステム。

## データベースマネジメント(DBMS)とは

データベースを管理するためのシステム。

## DBMSの種類とそれぞれの特徴と代表的な製品
+ ###### リレーショナルデータベース（RDB）
現在もっとも使われているデータベースで、Excelのような列と行からなる
表形式で管理するデータベース

**【代表的な製品】**
ーーオープンソースーー
□MySQL
□MarinaDB
□PostgreSQL
ーー商用ーー
□OracleDB
□SQLServer
□DB2

+ ###### キー・バリュー型データストア（KVS）
データを「キー」と「バリュー」のペアで管理するデータベース
webアプリやECサイトのキャッシュに使用されている

**【代表的な製品】**
□Memcached
□Redis
□Amazon DynamoDB

+ ###### オブジェクト指向データベース（OODB）
オブジェクト指向プログラミング言語の概念を取り入れた
データをオブジェクトとして管理するデータベース
**【代表的な製品】**
□ObjectDB
□Versant Object Database

※現在はあまり使われていない

+ ###### XMLデータベース（XMLDB）
XMLデータを管理し、XMLに特化したデータベース

※現在はあまり使われていない

## SQLとは
RDBを操作する為の言語

## 基本的なSQLの記述ルール
+ 大文字小文字は区別されない
+ 文の最後に；を付ける
+ 半角で書く
+ 文字と日付は ' ' で囲む
+ 単語は半角スペースor改行で区切る
【intra-mart】フロー定義で使われるプラグイン設定

# はじめに
入社2年目の開発エンジニアです。
今日も引き続き、intra-martの記事を書いていきます。

今回のお題は「フロー定義で使われるプラグイン設定」について説明していきます。
フロー定義はワークフローシステムを作成するにあたって、
重要な役割を担う機能なので、ぜひご覧ください。

# フロー定義とは
フロー定義は、**処理内容となるコンテンツ定義と処理順序となるルート定義を
紐づくマスタ情報**になります。

承認フローで定義されたノードに対して、プログラムを割り当てたり
機能を追加することが可能になります。

![{7B49E7FE-312A-4054-AFA4-C74E15D29FA5}.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3678292/74c3bd04-e61f-b7e8-55b0-6f0097876058.png)

https://document.intra-mart.jp/library/iap/public/im_workflow/im_workflow_specification/texts/detail_guide/master_definition/flow_definition/index.html

# 事例
まず簡単な事例を紹介します。
下の申請子画面で検索ボタンをクリックします。

すると処理対象者の子画面が表示されますが、ご覧の通り選択する項目が多いですね。
この検索機能をユーザだけに絞りたい場合、
フロー定義に含まれている**プラグイン設定**を活用することで実現することができます。
![{D753A225-EB83-4513-971A-127536286B6A}.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3678292/10822921-3ee1-be41-c817-1011cad58ffa.png)

# 実践
まず、実現したいことは
検索ボタンをクリック後にユーザの検索画面が表示する機能を実装したいと思います。

①フロー定義をクリックします
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3678292/2d9b8c77-7e52-30f5-b140-881d28a31c73.png)

②設定を変更したWFの編集ボタンをクリックします
今回こちらで用意したサンプルWFを使用していきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3678292/bdb254e8-b46f-add9-0827-d8e0437d8235.png)


③画面遷移後に「バージョン」タブをクリック後、編集ボタンをクリックします
![{6709D3E0-49B7-4393-8DD3-2AC41608D863}.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3678292/1c11a7fe-4acd-69cc-89f5-25d489d78d2f.png)


④「ルート詳細」タブから横配置ノードの編集をクリックします
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3678292/8a6f7cf3-5fa3-7e81-1524-1fa79f5f2b5a.png)

⑤「プラグイン設定」タブをクリックします
今回はユーザ検索画面を表示させたいので、ユーザのみにチェックを入れます
【変更前】
![{809C011E-FB2A-4645-8B2D-D970848B89E5}.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3678292/269db593-e3e6-37ee-119c-1b35ac50e2c4.png)

【変更後】
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3678292/43ef0090-390f-b99f-6ecf-7e56f4a060bd.png)

⑥登録ボタンをクリック後、横配置ノードに**プラグイン設定：ユーザ**が表示されます
これで検索ボタンをクリック後、ユーザ検索画面が表示されるようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3678292/16456d25-9420-cccc-3d23-d2dee1050af1.png)

:::note warn 
プラグイン設定の変更は動的承認ノード、横配置ノードのみ変更が可能です。
:::

# 変更後
プラグイン設定の変更後の動きとして、処理対象者の検索画面をクリックすると、
処理対象者の子画面は表示されず、ユーザ検索画面が表示されるようになります。
（動画の方がわかりやすいと思うので、可能な場合は後ほど差し替えておきます...）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3678292/21006c25-2bda-543a-bb94-c6d5ebbf43fe.png)

# 最後に
今回はフロー定義で使われるプラグイン設定について紹介しました。

設定項目を減らすことで、ユーザが使いやすくなるのでぜひ活用してみてください。
また、WFによって検索ボタンから表示させたい項目がそれぞれ異なるので、
設定する際のルールを確認してから、変更することをおすすめします。
【React】オブジェクト型を初期化する際に `{ }` で初期化したらエラーになる

# 概要
:::note
* プリミティブ型：`123` `"文字列"` `true`
* オブジェクト型：`{}` `[]`
    * プリミティブ型"以外"がこれに該当
:::

* 今回は **『オブジェクト型の State 変数を初期化』** したら以下のエラーが確認された

:::note alert
Warning: A component is changing a controlled input to be uncontrolled.
This is likely caused by the value changing from a defined to undefined, which should not happen. 
Decide between using a controlled or uncontrolled input element for the lifetime of the component.
:::

# エラーが生じたコード
```javascript:Sample.jsx
import { useState } from "react";

const Example = () => {
  // ユーザー情報
  const personObj = { name: "Jack", age: 30 };
  const [ person, setPerson ] = useState(personObj);
  
  // nameの入力欄処理
  const changeName = (e) => {
    setPerson({ name: e.target.value, age: person.age });
  };
  // ageの入力欄処理
  const changeAge = (e) => {
    setPerson({ name: person.name, age: e.target.value });
  };
  // リセットボタン処理
  const resetObj = () => {
    setPerson({ }); // ココが原因
  };

  return(<>
    <h3>Name:{person.name}</h3>
    <h3>Age:{person.age}</h3>
    <input type="text" onChange={ changeName } value={person.name} />
    <input type="number" onChange={ changeAge } value={person.age} />
    <div>
      <button onClick={ resetObj }>リセット</button>
    </div>
  </>);
};

export default Example;
```

# 原因

> あなたの value が API や state 変数から来ている場合、それが null や undefined に初期化されているかもしれません。その場合、まず空の文字列（''）にセットするか、value が文字列であることを保証するために value={someValue ?? ''} を渡すようにしてください。
> 
> 引用：[API Reference > コンポーネント > textarea](https://ja.react.dev/reference/react-dom/components/textarea#im-getting-an-error-a-component-is-changing-an-uncontrolled-input-to-be-controlled)

:::note warn
* 先述のコードではオブジェクト型を State 変数に格納していたため初期化のために `setPerson({});` で行っていたのがエラーの原因となっていた
    * このような初期化方法ではプロパティが undefined になってしまっている
:::

```javascript:Sample.jsx
const Example = () => {
  const personObj = { name: "Jack", age: 30 };
  const [ person, setPerson ] = useState(personObj);

/**（中略） **/
  
  // リセットボタン処理
  const resetObj = () => {
    setPerson({}); // ココが原因
    
    console.log(person);       //=> {}
    console.log(person.name);  //=> undefined
    console.log(person.age);   //=> undefined
  };
```

# 解決策
:::note info
* オブジェクトを初期化するには先の公式ドキュメントの引用から **空文字(`""`)を入れる** ことで解決可能
:::

```javascript:Sample.jsx
const Example = () => {
  const personObj = { name: "Jack", age: 30 };
  const [ person, setPerson ] = useState(personObj);

/**（中略） **/
  
  // リセットボタン処理
  const resetObj = () => {
    setPerson({person.name: "", age:""}); // 修正
  };
```

---
### 参考資料

https://ja.react.dev/reference/react-dom/components/textarea#im-getting-an-error-a-component-is-changing-an-uncontrolled-input-to-be-controlled

https://zenn.dev/buzzkuri_tech/articles/198016c6407f70

https://blog.mitsuruog.info/2017/09/react-uncontrolled-input
Ubuntu24.04でphp5.6を動かす (CakePHP 2)

Ubuntu 24.04

## エラー (CakePHP 2)

* php7ではクラス名に `String` という class名が使えなくなった。
* php7ではクラス名に `Object` という class名が使えなくなった。


## 対応

php5.6を使うことにする。

```sh
add-apt-repository ppa:ondrej/php
apt update
apt install -y php5.6 php5.6-pgsql php5.6-mbstring php5.6-xml
a2enmod php5.6
systemctl restart apache2
```

## postgresqlのインストール例

```sh
# インストール
apt install -y postgresql-16
```

/var/lib/postgresql/16/main/
が作成される。

```sh
# 接続
sudo -u postgres bash

# dbuser1というアカウントを作成し、パスワードをpass1にする
    createuser -d -r -s user1
    psql
    ALTER USER dbuser1 with encrypted password 'pass1';
# cakedb1を作成
    create database cakedb1;
# database一覧を表示
    \l
```


## CakePHP2の設定修正

* ./app/Config/database.php

の接続情報を修正。cakedb1とユーザー・パスワードをdbuser1:pass1にする。


## apache2のmod_rewrite を有効にする

```s
a2enmod rewrite
systemctl restart apache2
```

* /etc/apache2/mods-enabled/rewrite.load が生成されることを確認。

### AllowOverride Allする

mod_rewrite を有効にするためにディレクトリに対してAllowOverride設定をする。

* /etc/apache2/sites-enabled/000-default.conf

```apache
<Directory "/var/www">
    AllowOverride All
</Directory>
```

```sh
systemctl restart apache2
```



## certbot

```sh
sudo apt install -y \
    certbot python3-certbot-apache

sudo certbot --apache
```
【JavaScript】apply メソッドについて

`apply`メソッドと似ているメソッドとして`call`メソッドがあります。

主な違いは`apply`メソッドは第 2 引数以降は一つの引数を受け取るのに対し、`call`メソッドは第 2 引数以降複数の引数を受けとれるということです。

ここでは`apply`について、私が理解した範囲内で書いていきます。

まず apply メソッドの構文です。

```javascript
func.apply(thisArg, [argsArray]);
```

MDN サイトに記載されているものをそのまま持ってきました。私の理解を交えながら説明します。

`apply`メソッドは、ある関数`func`から呼び出すことができます。

第 1 引数の`thisArg`は`func`関数内の`this`の新たな参照先です。

`func`内で`this`が呼び出されていない場合、`thisArg`には`null`または`undefined`を代入することも可能です。

第 2 引数の`argsArray`は配列風のオブジェクト?で、`func`関数が呼ぶことになる引数を列挙したものになります。

例えば`fn1(a, b, c)`という関数において、関数`fn1`内の`this`を関数`fn2`に向けたい場合、`apply`を使うと`fn1.apply(fn2, [a, b, c])`のようになります。

`apply`メソッドの使い方を具体例で見てみます。

```javascript
function User(name) {
  this.name = name;
}
User.prototype.getName = function () {
  return this.name;
};

const user1 = new User("太郎");
const user2 = new User("花子");

console.log(user1.getName()); // 太郎
console.log(user2.getName()); // 花子
console.log(user1.getName.apply(user2)); // 花子
```

`apply`は、`apply`メソッドを呼び出した関数内の`this`のあて先を、`apply`メソッドの第 1 引数で渡したオブジェクトに<font color="Crimson">向けなおす</font>機能があります。

上記コードでは、`User`というコンストラクタ関数を作成しました。

user1 では name 属性として「太郎」、user2 では name 属性として「花子」を格納しました。

さらに name を取得する getName メソッドを定義しました。

`user1.getName()`と`user2.getName()`では、getName メソッドを呼び出しているオブジェクトが所持している name を返しています。

しかし`user1.getName.apply(user2)`では、getName を呼び出している user1 の name ではなく、`apply`の第 1 引数である user2 の name を返しています。

これは、getName メソッド内の`this`の参照先が`apply`メソッドによって user1 から user2 に変更されたからだとわかります。

```javascript
const numbers = [4, 9, 1, 6, 8, 3];

const max = Math.max.apply(null, numbers);
console.log(max); // 9
```

もし`apply`の役割として「`this`の参照先を変える」しか知らないと、上記の`Math.max.apply(null, numbers)`の第 1 引数として`null`を見た瞬間、「`this`の参照先をなくしているから`apply`の意味ないじゃない？」と思うはずです。

これは先ほど述べたように、`Math.max`関数内では`this`を使用していないため、`null`を渡しても問題ないからです。

ではここで`apply`を使った意味は何でしょうか？

もし単純に numbers 配列内の最大要素を求めようとして、`Math.max(numbers)`とすると、`NaN`が返されます。

これは Math.max メソッドは`Math.max(1,2,3,4,5)`みたいに引数を代入する必要があり、直接配列を渡すことができないからです。

そこで`apply`を使って`Math.max.apply(null, numbers)`のようにすると、イメージ的には`apply`メソッドが`numbers`配列内の要素を一つずつ取り出して`Math.max`の引数に渡してあげていると考えることができます。

つまり`Math.max.apply(null, [4, 9, 1, 6, 8, 3])`が`Math.max(4, 9, 1, 6, 8, 3)`になると考えることができます。 (`Math.max(...numbers)`でできるやん！ってことはさておき...)

以上をまとめると、`apply`の使い方として

- 関数内の`this`の参照先を変えることができる
- ある配列内の要素を for 文みたいにいい感じに 1 個ずつ取り出して別の関数の引数として渡すことができる

参考：
[MDN - Function.prototype.apply()](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Function/apply)
試合動画を解析してstatsを集計するツールを作りたい【格ゲー】

[PONOS Advent Calendar 2024](https://qiita.com/advent-calendar/2024/ponos) 2024の22日目の記事です。
昨日は @e73ryo さんの記事でした

　初めまして、インターネットでは「みしぇる」というハンドルネームで
活動させていただいております。

　自分の方では個人の活動として格闘ゲームを扱うゲーミングチームにプレイヤーとして
 所属させていただいていることもあり、格ゲーにちなんだ内容で
「格ゲーの試合解析ツールを作りたい」
というテーマで今回は執筆させていただきます。

※所属チームの結成発表時はちょっと話題になりました
![スクリーンショット 2024-11-25 16.29.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/384550/e8c887dc-ab92-e5b7-feda-ca64dd257827.png)
チームに関して気になる方は下記のXアカウントをチェックしてみてください
https://x.com/vorpalhedgehog

# はじめに
　今回の内容を執筆するにあたっての背景ですが、esportsという単語の認知度も
上がってきている昨今、「遊び」、もしくは「競技」として実際に
FPS・MOBA・格闘ゲームをプレイされる方はもちろんですが
視聴される方も増えてきていると感じています。

　開発をされている企業様側でもプレイヤーの自己・対戦相手の分析や
あまりそのタイトルを知らない視聴者様に向けてプレイヤーの特徴などを
わかりやすく伝えるための指標として試合の内容を集計してstatsを
表示しているタイトルも増えてきました。

 こちらは機能として持っている or 人力集計 or そもそも集計してないなど
タイトルによって様々ですがプレイヤー・視聴者目線で欲しい情報に関しては
項目の整理や自動化についてまだまだ発展途上な分野というところと
1人のプレイヤー・コメンテーターとしても振り返ることができるデータが欲しい
というところが大きな動機になります。

# 技術選定
　今回は Ptyhon + OpenCVにて解析を行いたいと思います。
動画・画像処理に関して実際に採用されている事例と
参考記事の多さが主な選定理由となります。

※筆者は本業はゲーム系サーバエンジニアなのでこの分野の知識は疎いので
もっといいのあるよなどあれば教えていただけますと大変嬉しいです。

　最近は機械学習やディープラーニングなど色々と便利なものがあるみたいですが
まずは基本的なところから小さい単位で学習しつつその辺りをどううまく活用していくのか
といった部分も学んでいければと思っています。


# タイトル選定
　「UNDER NIGHT IN-BIRTH Sys:Celes 2」(通称uni2)という
アークシステムワークス様から販売されている格闘ゲームにて行います。

![maxresdefault.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/384550/3d8dedcf-9ce3-ab58-bb40-e63d44037b95.jpeg)

　理由としては自分がメインで遊んでいるタイトルというのももちろんですが
試合中集計したい情報が数値として明確に表示されている部分が多く
他のタイトルに比べてもstatsとして集計したい情報が取得しやすいだろうと踏んでいます。

※UNI2ではコンボダメージやゲージ残量などが試合中でも数値として表示されるため、
他のタイトルと比べてみても珍しい部類だと思います。



# 集計したい情報
　色々集計してみたい情報はありますが取り急ぎは手をつけやすそうな
下記内容でますはサンプルを作って行きたいと思っています
実際に作成しながら知識を蓄えていって集計できそうな情報の整理などしていきます

### 何回相手を崩しダメージを取ることができたか
- 格闘ゲームには守りの手段としてガードというものがあり、基本的には攻めの手札をばらつかせるなどして予想外の行動をし相手の意表をつくことができなければダメージに繋がりません
- 実際に崩すことができた際の回数を集計し攻めの上手さ、逆に守りの上手さを知る指標として集計を行います

### 崩した際に使用した技とその際に与えたダメージ量
- 昨今の格闘ゲームでは一度相手の守りを崩すと相手が体制を整える前に追撃を行うことでまとまったダメージを取れるものが多いです。(コンボのこと)
- 崩す際に当てた技や状況によって取れるダメージ量の上限も変わってくるので、
- - リターンの高い技を当てるのが上手い
- - 技を当てた際に上限に近いダメージを出せているか
- といった指標として集計を行います

# で、実際いつ作るの？
- 年末年始に下記配信チャンネルにて配信しながら行おうと思います。
- - https://www.twitch.tv/michel_mayonaka?lang=ja
- 具体的な日程はXの方で告知するので興味ある方はチェックしてみてください
- - https://x.com/michel_mayonaka


# まとめ
　なかなか時間取れず作りたいものの願望をまとめただけになってしまって
大変恐縮ですが、実際の作業の様子やできたものなどはQiitaはもちろん
配信やXの方でもアウトプットしていこうと思うのでよければチェックしてみてください


明日は @oryzae29さんになります。お楽しみに！
【共感する人続出？】新人育成の難しさ

## はじめに

[はじめてのアドベントカレンダー Advent Calendar 2024](https://qiita.com/advent-calendar/2024/first-time)の18日目の記事になります。

この記事を読んでいて思うことがあったので、忘備録的にまとめようと記事にしました。

https://qiita.com/kjm_nuco/items/46bdbe06813faa52feb9

以前、こういうポストを投稿したら過去一で燃えました。

https://x.com/satan_engineer/status/1855560912859808014

※あまりにも燃えすぎて、[rの住人ピエロ【哲学】](https://www.youtube.com/shorts/04pkb71guI8
)というYouTubeチャンネルにも取り上げられました。

改めて、なぜ彼らがここまで初心者に厳しいのか、私なりに考えてみたのでまとめました。

## 理由その1：自分が経験した苦労が前提にある
1つ目は自分たちの苦労がバイアスとなっていることです。

```
「俺たちの時代は情報が少ない中、頑張って調べて設定とかしたんだ！」
「今なら生成AIに聞けば何でも答えてくれるだろ！」
「そんな初期設定でつまずいているようじゃ、新しい知識習得なんてできるわけがないだろ！」
```

他にも挙げるなら

- 自分たちも最初は苦労したんだ、その程度でヘコたれるな
- あの頃と比べると、お前らの環境は恵まれていて、ちょっと調べれば答えはすぐに見つかるだろ
- 自分たちは苦労して壁を乗り越えてきた
- なのに、お前らは初歩でつまずくとは何事か

でも、**その苦労って後輩たちにさせる必要あるでしょうか？**

私は、エンジニアの存在目的は、**顧客の業務負荷の低減**と考えています。

バグに何時間も頭を抱え、新しい技術を身につけるために知恵を絞り、顧客の業務改善のために頭をフル回転させる。

これは目的を達成するために必要な苦労です。

環境設定など、目的達成と直接関係のないことに手間ヒマをかける必要はあるのでしょうか。

## 理由その2：経験値の差による目線のズレ
【つよつよエンジニア】
```
手順書通りに環境設定したけど、なぜかエラーが出ている。
これ多分○○が原因だな。対処方法は確か・・・（カタカタ）あーこれこれ。
```

【初心者】
```
手順書通りに環境設定したけど、なぜかエラーが出ている。
エラー内容をそのまま、ググったけど書いてる内容がさっぱり分からない・・・。
```

これまでの知識・経験の差があるので、あなたにとって簡単なタスクでも初心者には高難易度です。

初心者は調べ方のコツもまだ掴めていない、この設定をする理由・背景が腑に落ちない、知識も少ない状態からスタートしています。

例えるなら、ベテランがこの高さから楽々と飛び降りられるとすれば

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3964479/dccd6074-7b9e-97f8-a542-ab197c49c164.png)

初心者は今からコレにチャレンジするのです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3964479/1ab4a9a4-f280-4760-7db6-99e740b7af72.png)

この高さにオドオドしている様子を見ていて、もどかしくなる気持ちは分かりますが

**「そんな高さでビビるな、早く飛べ！！」**

なんて言うのは酷すぎではないですか？

## 理由その3：余裕のなさ
余裕がない人は、質問されて自分の時間が奪われることを極端に嫌います。

納期直前、スケジュール遅れで忙しいことは大いに考えられますが、仮に質問しても**「それくらい自分で調べてもらえる！？」**と突き放します。
できなければ**「なんでそんなこともできないの！？」**と高圧的に詰め寄ります。

あと、このタイプが多くいる現場は、そもそも育成に回すリソースが少ないので、後任が育ちません。

```
人を育てる暇がない
→後任が育たない
→個々の業務負担が減らない
→人を育てる暇がない
→以下ループ
```

この悪循環を断ち切ることができないので、そこにいる人たちに心の余裕が生まれることはなく、**結果的にイヤな性格のエンジニアが出来上がります**。

これは完全に主観ですが、余裕のない人は他人が失敗したり、つまずいているのを見てストレスを発散しているので、もし近くにいる場合はすぐに距離を取ることをお勧めします。

もちろん、初心者エンジニアも

- 最初から自力で調べる気がない
- 完全にお客様マインド
- 「お金稼げたらそれでいいんで」な人

これに当てはまるなら、冷たくあしらわれても文句は言えません。
私もこんなエンジニアの教育に携わりたくありません。

私が問題視しているのは、**何とか頑張っている初心者を冷遇するような性格の悪いベテランエンジニア**です。

私はこうならずに根気よく、初心者に寄り添えるエンジニアでありたいと思います。

ここまで読んでいただきありがとうございました。

Xではエンジニアに有益な発信をしていますので、ぜひフォローよろしくお願いします！！

https://twitter.com/satan_engineer
Dellモニターで画面が消える不具合を「簡易放電」で解決する方法

Dell製の液晶モニターを使用中、たまに画面が突然消えてしまうといった症状に悩まされることはありませんか？ こうした問題は、モニター内部に残留している電気が原因となっている場合があり、「簡易放電」を行うことで解消できるケースがあります。

今回は、その「簡易放電」の手順をご紹介します。この方法は特別な道具を必要とせず、短い時間で試せるので、もしお手元のDellモニターで同様の不具合が生じているなら、ぜひお試しください。

## 簡易放電とは？

「簡易放電」とは、モニター内部に蓄積している微量な電気を一度完全に抜いて、リセットするための手法です。これにより、不安定な動作や予期せぬ挙動が改善することがあります。

## 簡易放電の手順

1. モニターの電源を切る
   * まずはモニターの電源をオフにします。
   * 電源ボタンを押してモニターが完全に消灯したことを確認しましょう。

2. 信号ケーブルや電源ケーブルなど、すべてのケーブルを取り外す
   * HDMIやDisplayPort、VGA、DVIケーブル、さらには電源ケーブルなど、モニターに接続されている全てのケーブルを外します。
   * ここでポイントは「電源ケーブルも抜く」ことです。内部の残留電気を放電するためには、電源回路を一度完全に遮断する必要があります。

3. 電源ボタンを約20秒間長押し
   * ケーブルがすべて外れた状態で、モニターの電源ボタンを20秒ほど長押しします。この操作により内部に残っていた電気が放電されます。
   * 20秒ほど経ったら手を離しましょう。

4. ケーブルを再接続して電源を入れる
   * 電源ケーブルや信号ケーブルを再び接続したら、モニターの電源ボタンを押して起動します。
   * モニターが正常に映像を表示すれば、手順完了です。

## 注意点

* 簡易放電を行う際には、必ず作業前にモニターの電源を切り、コンセントを抜いてください。
* ケーブルの差し直し時には、コネクタ形状をよく確認して、無理に差し込まないように注意しましょう。
* この方法で解決しない場合は、モニター自体の故障の可能性があります。その際は、Dellのサポート窓口や専門の修理業者への相談を検討してください。

## まとめ

Dell製モニターで「画面が突然消える」不具合が起きた場合、簡易放電を行うことで問題が改善することがあります。手順はとてもシンプルで、特別な道具も必要ありません。一度お試しいただき、問題が解消するかぜひ確認してみてください。

もし改善しない場合は、他のトラブルシューティング手順（他のPCやケーブルでの動作確認、ドライバ更新など）や、サポートへの相談を検討してみましょう。快適な作業環境づくりの一助になれば幸いです。
JavaScriptの変数: どのように使い分けるべき？

JavaScriptを使うとき、変数を宣言する方法はとても重要です。`var`、`let`、`const`にはそれぞれ異なる特徴と用途があり、状況に応じて正しく使い分ける必要があります。この文章では中学生でも理解できるよう、簡単で楽しく説明していきます！

# `var`、`let`、`const`の違いは？
### `var`: 昔ながらの変数
昔は変数を宣言するとき、`var`しか使えませんでした。しかし、最近ではあまり使われなくなっています。その理由は**混乱しやすい特徴**があるからです。

```javascript
var x = 1;
if (true) {
  var x = 2; // 外側の変数まで変更されてしまいます！
}
console.log(x); // 2
```

- **問題1**: ブロック内で宣言した変数が、外側の変数にも影響を与えます。
- **問題2**: 宣言前に使ってもエラーにならず、`undefined`に初期化されます。

> **結論**: `var`はもう使わないほうがいいです。

### `let`: 賢い変数

`let`は、`var`の問題を解決するために生まれた新しい宣言方法です。ブロック内でしか使えないので、ずっと安全です。

```javascript
let y = 1;
if (true) {
  let y = 2; // この変数はこのブロック内だけ有効です。
  console.log(y); // 2
}
console.log(y); // 1
```

- **特徴1**: ブロックスコープを持ちます。
- **特徴2**: 宣言前に使おうとするとエラーが出ます。

> **結論**: 変数の値を変える必要がある場合は`let`を使いましょう。

### `const`: 変わらない変数

`const`は、定数を宣言するときに使います。一度値を設定すると変更できません。

```javascript
const z = 10;
z = 20; // エラー！値を変えることはできません。
```

しかし、オブジェクトや配列のような複雑なデータの**中身**は変更できます。

```javascript
const obj = { name: "Alice" };
obj.name = "Bob";
console.log(obj.name); // Bob
```

- **特徴1**: 値を変更できません。
- **特徴2**: オブジェクトのプロパティは変更可能です。

> **結論**: 基本的には`const`を使い、本当に必要なときだけ`let`を使いましょう。

# JavaScriptの変数はどう動くの？
### ホイスティング(Hoisting)とは？
ホイスティングとは、JavaScriptがコードを実行する前に変数や関数を準備する仕組みのことです。ただし、宣言の方法によって動作が異なります。

- **`var`**: 宣言と初期化が同時に行われ、`undefined`に初期化されます。
- **`let`と`const`**: 宣言だけ準備され、初期化は後で行われます。初期化前に使うとエラーが出ます。

```javascript
console.log(a); // undefined
var a = 10;

console.log(b); // エラー！初期化されていません。
let b = 20;
```

### TDZ(Temporal Dead Zone)

TDZは、`let`と`const`が初期化される前に変数にアクセスできないようにする仕組みです。これにより、予期しない問題を防ぐことができます。

```javascript
console.log(x); // エラー！まだ初期化されていません。
let x = 5; // ここで初期化されます。
console.log(x); // 5
```

> **まとめ**: ホイスティングとTDZを理解すると、変数宣言によるエラーを防ぐことができます。

# `const`の本当の意味

`const`は値を変更できない変数ですが、オブジェクトや配列のプロパティは変更可能です。完全に変更を禁止したい場合は`Object.freeze()`を使う必要があります。

```javascript
const obj = { name: "Alice" };
Object.freeze(obj);
obj.name = "Bob"; // 失敗！オブジェクトが凍結されています。
console.log(obj.name); // Alice
```

> **ヒント**: 大事なデータを`freeze`で凍結すると、意図しない変更を防ぎ、予期せぬバグを回避することができます。特に共有データや設定値のような重要な情報に適しています。

# 結論: どう選ぶべき？

1. **変わらない値**は`const`。
2. **値を変更する必要がある場合**は`let`。
3. **`var`は使わないこと**。

最近のJavaScriptでは、`const`を基本として使い、必要な場合にだけ`let`を使うのが最も良い方法です。これにより、予測可能で安全なコードを書くことができます！
UI/UX周りでお世話になったサイト/記事紹介

## はじめに
私は新卒のピカピカエンジニアです🙇‍♂️
業務上、フロントエンド、バックエンド、インフラなど幅広く触るのですが、画面設計も意外と時間がかかる作業の一つでした、、
そこで、画面設計を行う際に参考になったサイトを紹介していきたいと思います！
よければ参考程度に見てください〜！
また紹介したものの他にも参考になったものがあればコメントしてくれると嬉しいです〜🙌

## ギャラリーサイト
ギャラリーサイトは必要な画面が出揃った段階で、それぞれの画面に必要な要素を調べるときに使っていました！
例えば、トップにはどういった情報が並んでいるかやナビゲーションにはどのようなものがあるかなどなど
### [Pinterest](https://jp.pinterest.com/)
- 一番最初の頃はpinterestでUIを参考にしてました。UI要素単位で検索をかけていました。


### [Mobbin](https://mobbin.com/)
- Mobbinを使い始めてからはpinterestを参照することはほぼほぼなくなりました！
- SpotifyやSlack、Asanaなどの有名なアプリを含む数多くのアプリ（iOS/Android/Web）のUIを参考にできます。
- フローや要素ごとに見れるのも嬉しいですね☺️


## ガイドライン
### [Sociomedea　ヒューマンインターフェースガイドライン](https://www.sociomedia.co.jp/category/shig)
- より良いユーザー体験をお届けするためのデザイン指針です。全部で100トピックくらいありますが、一つ一つは非常に短く、画像付きなので、さらっと読めると思います！

### [Spindle](https://spindle.ameba.design/)
- Amebaのデザインガイドラインです
- [各コンポーネントの設計方針の部分](https://spindle.ameba.design/components/)とか[UIラベリング](https://spindle.ameba.design/principles/contents/ui-labeling/)とかを結構みていました！

## 参考になった記事

### [アプリのアップデート500本ノックから学ぶUI改善のヒント](https://note.com/akira_miyazaki/n/nab9a1252ac4e)
- 実際のアプデをもとにデザインを比較して、どこがどのように変わって使いやすくなったかを解説してくれます！

### [WebアプリのUIデザインを洗練させるための７つのヒント](https://tech.nri-net.com/entry/2021/05/17/090000)
- UI/UXの用語解説から、実際に洗練させるために注意すべきポイントを7点ほど紹介してくれています！


## 終わりに
いかがだったでしょうか？みなさんの参考になれば嬉しいです！
他にも良い参考サイトなどがあれば教えてください！
それではまた！