OmniAICreator/Qiita-1.07M huggingface dataset:
V7R5新命令（SND-MSG

[V7R5での変更点](https://www.ibm.com/docs/ja/i/7.5?topic=wn-whats-new-in-75-1) に掲載されいている、**新命令 SND-MSG（%MSG,%TARGET）** を紹介。（※但しこの機能は下位バージョンでもPTFを導入する事により利用可能な場合があり）

- [SND-MSG (ジョブ・ログへのメッセージの送信)](https://www.ibm.com/docs/ja/i/7.5?topic=codes-snd-msg-send-message-joblog)
- [%MSG (メッセージの取得)](https://www.ibm.com/docs/ja/i/7.5?topic=functions-msg-message-id-message-file-replacement-text)
- [%TARGET（メッセージの送信先）](https://www.ibm.com/docs/ja/i/7.5?topic=functions-target-program-procedure-offset)
- [サンプルコード](https://github.com/ushiday/qiita-rpgle/blob/main/QRPGSRC/Q231220R1.RPGLE)

## 概略

新命令 `SND-MSG` で何が出来るのか？
簡単に言うと「**RPGプログラムの内部から直接、ジョブログへ通知、例外メッセージを送信する事が出来る**」 様になった。
これまでは、RPG からCLに何ら頭のパラメータを返して、CLにジョブログ・メッセージのハンドリングをさせる形だったが、それを **直接RPGが行う事が出来る** ようになったと思えば良いだろう。

- 従来：RPG → CL → メッセージ送信
- 新：RPG → メッセージ送信

の形にプログラムを出来る。

## 使い方

使い方は、以下の①～④の項目からなる
① 命令：`SND-MSG`
② メッセージタイプ： `*INFO（省略）` or `*ESCAPE`
③ メッセージ： `固定メッセージ値` or `%MSG('ﾒｯｾｰｼﾞID' ,'ﾒｯｾｰｼﾞ ﾌｧｲﾙ' ,'ﾒｯｾｰｼﾞ ﾃﾞｰﾀ' ,...)`
④ 送信対象：`未指定＝直前の呼出元` or `%TARGET(*SELF|*CALLER:n|etc...)`

③の `%MSG` IBMi 任意のメッセージ・ファイルよりメッセージを設定する事が出来る、組込み関数となり、④の `%TARGET`  はメッセージ送信対象を指定する事が出来る。

サンプルコードでは `*SELF` で実行プログラム自身へメッセージを送信し、例外メッセージを自身で `MONITOR` しキャッチしている。もちろん例外メッセージの内容はジョブログに残っている。
また `%MSG` でメッセージIDが存在しない場合は、`エラーコード 126` で監視することも出来る。

## コードサンプル抜粋

```RPGLE

//情報メッセージ（＊ＩＮＦＯ
W#CNT1 += 1                            ;
W#MSG1  = '(' + %EDITC(W#CNT1:'X') + ')'
        + 'メッセージ＊ＩＮＦＯ（暗黙的'
;
SND-MSG W#MSG1                         ;

～～～

//％ＭＳＧ…ＭＳＧＦの取得
W#CNT1 += 1                            ;
W#MSG1  = '(' + %EDITC(W#CNT1:'X') + ')'
        + 'メッセージ＊ＥＳＣＡＰＥ（%MSG'
;
MONITOR                                ;
  W#MID = 'CPF9897'                      ;
  //W#MID = 'XXXXXXX'                      ;
  SND-MSG *ESCAPE
          %MSG(W#MID     : '*LIBL/QCPFMSG' :W#MSG1 )
          %TARGET(*SELF)    ;
ON-ERROR  126                          ;
  W#MSG2 = 'そんなＭＳＧＩＤはないぜよ'  ;
  DSPLY W#MSG2                         ;
ON-ERROR 9999                          ;
  W#MSG2 = W#MSG1                      ;
  DSPLY W#MSG2                         ;
ENDMON                                 ;

```

## 結果、感想

以下が `CALL Q231220R1` の 実行結果

![2023-12-07_191413.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100029/2fa50581-0b7c-d5dc-8ded-64c9953981c7.png)

![2023-12-07_195828.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100029/6d9630e1-46a2-ee49-1974-70e04955370d.png)

サブルーチン等の制作の際に、エラー等のハンドリングを RPG で直接出来るのは、わざわざ CL を介さなくて良いので、場面場面では良いシーンも有りそう。特に RPG でストアドプロシージャにしたのに、ジョブログだけ CL とかなっていた場面では良い感じ。
但し、処理が複雑なケースでは、単純にジョブログ・メッセージ以外のコマンド系・例外処理も他にあったりするので、何でもかんでも `SDN-MSG` を多用すると、RPG で行っているメッセージ処理と CL で行っている例外処理とが分断され、返って例外処理の見通しが悪くなる。
どんな事でもそうだが、道具は沢山あった方が便利だが、使い方が重要だと言うことだと思う。道具は上手に使いましょう。
「bash: composer: command not found」時はビルド忘れがないかチェック！

## はじめに
DockerでLaravelの環境構築を行っている時に、composerが動作せずしばらくブロックされていたので。

## 要約
「bash: composer: command not found」時は、ビルドを忘れていないか確認！

## 動作環境＆参考サイト
Docker Desktop 4.26.0

https://zenn.dev/naoyuki42/articles/ae215286ba92b2

## 問題
```terminal
$ docker compose exec php bash
$ composer create-project --prefer-dist "laravel/laravel=" .
```


上記のようにPHPコンテナ内でLaravelのプロジェクトを実行しようとすると…

    bash: composer: command not found
と表示された。

```Dockerfile:~/container/php/Dockerfile（一部省略）
# composerのインストール
RUN cd /usr/bin && curl -s http://getcomposer.org/installer | php && ln -s /usr/bin/composer.phar /usr/bin/composer
```
「composerのインストール定義部分が間違っているのかな？」と色々書き換えてみるも、特に問題なさそう。

## 解決法
解決法は単純で、もう一度ビルドしてみるというものだった。

```terminal
 $ docker compose up -d --build
```

composerのインストールを定義したDockerfileをVSCode上で保存しても、ビルドなしではインストールは実行されない。
1年SAPのプロジェクトに参画した人間によるSAPって何？


目次：
①記事記載の背景と当ブログの記載内容
②想定している読み手
③SAPって何？
④SAPのプロジェクトのポジションと必要な知識

:writing_hand_tone1:記事記載の背景と当ブログの記載内容
会社の同期からお誘いいただき、約1年ほどSAPを触ってきた時点でのアウトプットとして記事を書いてみることに決めました。
SAPの細かい知識を書くとあまりにもピンポイントすぎるので、大枠でSAPとは何か？どんなプロジェクトがあってどんな知識を持った人がいるの？という観点で記載しようと思います。


:writing_hand_tone1:想定している読み手
もちろんどんな方に読んで頂いてもよいですが、SAPの細かい部分まで記載するのはこのブログでは想定していないので
SAPって聞いたことあるけど何？
ERPって良く聞くけど何？
SAPの簡単な概要を知りたい
というような方に読んで頂けると良いのかと思います。

:writing_hand_tone1:SAPって何？
＜会社としてのSAP＞
そもそもSAPとは会社名でもあります。
もともとは”System Analysis Program Development (Systemanalyse Programmentwicklung) ”と呼ばれていた会社でしたが、略称でSAPと呼ばれるようになったようです。
現在会社としてSAPはドイツに本社を持ち、全国130箇所以上の支社をもっています。
参考：https://www.sap.com/japan/about/what-is-sap.html

＜システムとしてのSAP＞
ERP(Enterprise Resources Planning)と呼ばれるシステムのうちの1つで、他にも様々な会社がERPシステムを出しています。
ERPシステムは会社の持っているヒト/カネ/モノ/情報を1つで管理するシステムであるので、簡単にいうとSAPは会社の資源を1つにまとめて管理するシステムということになります。
このまとめられたヒト/カネ/モノについてそれぞれ担当が分かれて(モジュールと言ったりします)エンジニア、コンサルによってSAPは導入されたり保守されたりします。

:writing_hand_tone1:SAPのプロジェクトのポジションと必要な知識
ではSAPに関するプロジェクトに配属されたらどのようなポジションになるのでしょうか。ポジションと必要(と思われる)スキルについて簡単に記載していきます。
①PM、PMO
どのプロジェクトにもおそらくこのポジションの方がいらっしゃると思いますが、SAPのプロジェクトでもプロジェクトマネジャーのポジションがあります。
このポジションは社内の調整と進捗状況の管理、顧客との折衝するスキルが必要です。

②アプリコンサルチーム
モジュールごとにSAPの機能に専門性を持ち、顧客への業務理解をしながら適切にSAPの導入や保守をしていきます。必要な知識としてはSAPのアプリケーションだけでなく、一般的な業務知識などが必要です。
ちなみにモジュールとしてはFI(財務会計)、CO(管理会計)、MM(在庫管理)、SD(販売管理)、生産管理(PP)、人事管理(HR)…など多くあります。

③Basisチーム
SAPを動かすための基盤を設定するポジションです。ユーザー管理やSAPを動かす際に必要なネットワークの設定、データベースの設定など幅広く対応する必要があります。そのためコレ！といった知識というよりかは幅広い知識知見が必要です。(と思っています)

④開発チーム
標準機能でできない機能が必要だとなったときにプログラムを書いて実現するポジションです。SAPの言語は”abap"と呼ばれる言語が今までは主流でしたが、現在はJavaなどのプログラム言語でも開発できるような機能がでてきました。そのためこれからはabapだけでなく、Javaの知識を持った人が開発チームで活躍することもできそうだと私はにらんでいます。

⑤マスタチーム
SAPに登録するマスタ(取引先を登録するBPマスタや銀行情報を登録する銀行マスタ等)について取り決めしていくチームです。このチームはマスタに登録する項目を定義したり、項目自体の要件定義を行います。マスタ自体の知識とそのマスタに登録された項目がどのように使われるかを知っておく必要があるポジションです。

⑥権限チーム
SAPに登録された項目や情報についてユーザーごとに権限を決めていくチームです。例えば役員さんのお給料などは工場で在庫情報を入力するような社員には見えないようにして、経理さんだけが見えるようにするなどの設定をします。SAPには権限をつけることができる要素(トランザクションコード/権限オブジェクト/権限項目)があるので、そちらの知識が必要です。

:writing_hand_tone1:終わりに
記事を書いていて、SAPのプロジェクトで要求される知識の幅広さを改めて知りました。
まだまだSAPの知識はひよっこですが、これからもプロジェクトを通じてIT技術や知見を広げていけたらよいなと思います。技術ブログ(？)というブログでしたが、最後まで読んでくださった皆様ありがとうございました:star:
Gemini Proを使ってみる【無料版GPT-4】


https://bard.google.com/?hl=en

https://support.google.com/bard/answer/14294096

https://blog.google/products/bard/google-bard-try-gemini-ai/

https://bard.google.com/updates?hl=en

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208363/5034f514-417d-0ed7-afb3-70d749cd62c9.png)


AI と連携する新しい方法として、Bard で Gemini Pro を試すことができるようになりました。Gemini Ultra は、Bard Advanced と呼ばれる新しいエクスペリエンスで、来年初めに Bard に登場します。

本日、私たちは、洗練されたマルチモーダル推論機能を備えた最も有能なモデルであるGeminiを発表しました。柔軟性を重視して設計された Gemini は、Ultra、Pro、Nano の 3 つの異なるサイズに合わせて最適化されているため、データセンターからモバイル デバイスまであらゆる環境で実行できます。

さて、Gemini がBard 史上最大のアップグレードでBardに登場します。Gemini は 2 段階で Bard に展開されます。本日より、Bard はより高度な推論、計画、理解などのために、特別に調整された英語版の Gemini Pro を使用します。そして来年初めには、Gemini Ultra から始まる最も高度なモデルと機能に初めてアクセスできる Bard Advanced を導入します。

# Bard で Gemini Pro を試す
一般に公開する前に、私たちは Gemini Pro を多数の業界標準のベンチマークで実行しました。Gemini Pro は、8 つのベンチマークのうち 6 つでGPT-3.5 を上回りました。これには、大規模な AI モデルを測定するための主要な主要標準の 1 つである MMLU (Massive Multitask Language Understanding) や、小学校の算数推論を測定する GSM8K も含まれます。

それに加えて、Gemini Pro を Bard で特別に調整し、理解、要約、推論、コーディング、計画などの能力がはるかに向上しました。そして、素晴らしい結果が得られています。サードパーティの評価者によるブラインド評価では、Bard が主要な代替チャットボットと比較して、現在最も好まれている無料チャットボットです。

テキストベースのプロンプトについては、Gemini Pro で今すぐ Bard を試すことができます。他のモダリティも近々サポートされる予定です。まずは170 以上の国と地域で英語で利用できるようになり、近い将来、ヨーロッパなどさらに多くの言語と場所でも利用できるようになります。

# 来年初めに Bard の高度なバージョンで Gemini Ultra が登場することに注目してください
Gemini Ultra は、非常に複雑なタスク向けに設計され、テキスト、画像、オーディオ、ビデオ、コードなどのさまざまな種類の情報を迅速に理解し、それに基づいて動作するように構築された、当社の最大かつ最も機能的なモデルです。

Gemini Ultra を試す最初の方法の 1 つは、Bard Advanced を使用することです。これは、Bard の新しい最先端の AI エクスペリエンスであり、最高のモデルと機能にアクセスできます。現在、広範な安全性チェックを完了しており、来年初めにさらに多くの人に Bard Advanced を公開する前に、間もなく信頼できる[テスター プログラム](https://blog.google/products/bard/google-bard-try-gemini-ai/)を開始する予定です。

これは、Bard の立ち上げ以来、私たちが取ってきた大胆かつ責任あるアプローチと一致しています。私たちは、答えをより簡単に再確認するためのBard の「 Google it」ボタンなどのコンテキスト ヘルプの追加を含め、AI 原則に基づいて Bard に安全性を組み込みました。Bard の微調整を続ける中で、皆様からのフィードバックが改善に役立ちます。

Gemini のおかげで、Bard を世界最高の AI コラボレーターにするというビジョンにまた一歩近づいています。私たちは、Bard に最新の進歩をもたらし続けること、そしてそれを使用して作成、学習、探索する方法を見ることを楽しみにしています。今すぐGemini Pro で Bard を試してください。

# 実行例

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208363/2fbe3bff-70be-f531-3518-e9b9a7108853.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208363/0d5a83b7-9905-1b6d-034f-9e21b674688f.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208363/f6291daf-a59a-25e1-9230-71b831179db9.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208363/31b41431-95cf-8a4c-10dd-cbefbc4d33cd.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208363/19e0a3ad-ea6e-bb22-183b-579ff4348a1f.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208363/e4afd8ff-ead0-b5b9-63ff-eb501a761c2b.png)
新人アナリストが経験した失敗を曝け出す

## はじめに
この記事は[リンクアンドモチベーション Advent Calendar 2023](https://qiita.com/advent-calendar/2023/lmi)の12日目の記事になります。

今年の4月から新社会人としてリンクアンドモチベーションに入社し、半年間にも渡る研修を経て10月から正式に配属されて、日々データ出し業務に奮闘しています。

約2ヶ月半が経ったわけですが、幸せなことに多くの失敗を経験できています。
ここで自分の失敗の言語化、さらには同じような失敗をする人が一人でも減るように未来の新人の立場の方に参考にしていただきたいです。

執筆のきっかけをくれたAdvent Calendar 2023に感謝しながら楽しんで書きたいと思います。
（失敗を曝け出すことになんの抵抗もない人間です）

## 前提
僕の所属するチームは社員が6人で、尚且つそれぞれの人がそれぞれのプロジェクトを抱えており、さながら会社内にまた別のスタートアップ企業があるような形です。弊社の主力商品であるモチベーションクラウドやコミュニケーションクラウドに続く新たなプロダクトの開発や社内業務効率化に向けて日々取り組んでいます。
配属されてここまでの期間は先輩方がよりプロジェクトに専念できるようにアドホックな分析依頼や各種更新業務に取り組んできました。


## Case1　優先順位策定の失敗
とんでもなくあるあるだと思います。この失敗をしたことがない人はこの世に一人もいないのではないか、というぐらいに。
このような失敗を起こさないためには
- やることとやらないことを決める
- 重要度や緊急性を考える
- 所要時間が短いものから片付ける　　etc...

などなどあります。わかっていてもどれかが抜け落ちてしまうことがありますし、自分でも意識していたつもりでした。（ただし、この時は優先付けのフレームワークを全然知りませんでしたが）

このような自分の中に手札が少ない状態で
- タスクA： 納期二日後・重要・所要時間長そう
- タスクB： 納期二日後・重要・所要時間短そう



この二つのタスクに直面したら、みなさんはどうしますか？業務に関する知識が不十分で経験も乏しい新人に戻った気持ちで考えてみてください。直感的にタスクBに取り組みたくなると思います。そしてこれが失敗でした。十分な知識もないままでは納期以外の定性的な二点を自分で正確に測り取れる訳がないのです。
取り組んだ結果特にタスクBが早く終わるわけでもなかったですし、後々影響度を考えるとタスクAの方が先に取り組むべきでした。
両方のタスクとも「確実に納期内に完了させなければならない」という重要度は同じでしたが、その影響範囲も考えると実際の重要度は違うことを学びました。
初めてのことで余裕がないとなかなか視野が狭くなってしまうことを痛感した経験でした。

:::note info
今後は・・・
**タスクの判断軸を増やし、検討すべき軸の順から表形式で整理する！！！**
ことを意識していきます！
:::

(例)上の例を表に当てはめてみると...
|  | タスクA | タスクB |
|:-:|:-:|:-:|
|  緊急度 |  高 |  高 |  
|  重要度 | 高  | 高  | 
|  **<font color="Red">影響度</font>** |  大 | 小  | 
|  難易度(時間的コスト) | 大  | 小  | 
|  **優先順位** | **1**  | **2**  | 

今回は影響度の大小で優先順位を決めるべきであったと直感的に読み取れます。



## Case2　悪戦苦闘、そして手戻り
配属当初はSQLにもPythonにも手も足も出ず、ドメイン知識もてんで皆無であった自分にとって最初はもちろん苦闘の連続でした。そんな中でも2ヶ月ほど分析業務に携わっていくうちに、データ処理能力が上がっていることを実感してきていました。

「慣れ」とは恐ろしいもので、そういう時にこそ事件は起こります。
ある程度自分一人でできることが増えてきたことから、「これはこうやればできるはず」という思考に独りで結論づけ、ゴールだけを見て手を動かし始めてしまいました。想定外に難しい作業でデータベースの情報を調べながら悪戦苦闘を続けた結果、なんとか自分が想像しているゴールの形にすることはできました。
しかし、レビュー時に「あー、これこっちのデータベースじゃ出ないんだよね〜」と言われ、愕然としてしまいました。
結局、ほとんど最初からやり直しをしなければならない上に、先輩の時間をだいぶいただいてしまいました。
最初に手を動かす前に具体的な進め方を擦り合わせていれば防げた失敗だっただけに、代償はあったけれども自分の中で大きな経験になりました。

:::note info
今後は・・・
**いかなる場合でもプレビュー工程を飛ばさない！！！**
ことを意識していきます！
:::

## Case3　遠慮して質問を後回しに
余程分からないことであれば話は別ですが、「まあ調べればなんとかなるか」みたいなレベルのことに対して、遠慮してしまって結果無駄に時間を浪費してしまった、という失敗です。
もちろん自分自身で考える癖をつけることは大事でその工程が成長につながることは重々承知していますが、聞けば答えが出ることを1,2時間も自力で頑張り続けることは業務の遅れにつながってしまいます。
Case2とも近いような解決策ですが、過去の分析事例の共有や必要な知識の前持っての収集など、自分のタスクを最大限のスピードでこなしていくために、たとえ非同期でも質問をガンガン投げかけていくことの重要性を学びました。

:::note info
今後は・・・
**「アホ」になって質問しまくる！！！**
ことを意識していきます！
:::

## まとめ
まだまだテックブログのようなものを書けるような実力ではない自分にとって初めての執筆はこのような形しかない！と考えていたので執筆できてよかったです。
自分の失敗を言語化して振り返るということは、二度と同じ轍を踏まないための一番手っ取り早い手段だと思います。
これからも失敗をどんどん経験し、その都度言語化していきたいと思います。
「Fail Fast」の精神ですね。

未来の新人さん、ぜひ参考にしてみてくれたら嬉しいです。
明日のアドベントカレンダーも乞うご期待！
30秒で読める全然すごくないけど知っておくとちょっと便利なkintoneネタ

「すごくない」kintone Advent Calendar 2023 その2 の7日記事です。
https://adventar.org/calendars/8774

## はじめに

ども。BBです。
超久しぶりのQiita記事です。すごくないシリーズに書いてよ！という依頼もあり、今回は **「知ってる人は知っている全然大したことはない、けど覚えておくと便利なkintone hack」** について書いてみたいと思います。

この記事自体もすごくないので、たぶん30秒くらいで読めます。

## アプリ管理の「アプリの一覧」の表示件数っていつの間に増えた？

いつ頃か忘れましたがアプリの一覧の表示件数がデフォルト20件から **500件** に増えたんですよね。スペースの一覧も同様に500件に増えてると思います（手元の環境でスペース数500オーバーなものがなかった・・）

![図0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/153051/fe9594fa-a357-25cb-741c-5a76200e8e48.png)

今まで20件でめちゃくちゃアプリ調べるのに大変だったわけで、このアプデは地味に助かってます。

## でも、まだ忘れられている画面があるよ・・

どこかわかるかな？

・
・
・
・
・
・
・
・
・
・


そう。ゲストユーザーの一覧！ここはまだ20件のままなんだぜ・・・

![図1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/153051/a4976eb3-b3e0-8f25-1f5b-deceb9c83370.png)


で、これ実はURLを無理くり書き換えると100件まで表示できるよって話です。

## 「/k/admin/system/guest/#/0/100」 にしてみてごらん

`https://{subdomain}.cybozu.com/k/admin/system/guest/#/0/100` とすると・・

あら、なんということでしょう。100件まで表示ができました！

![図2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/153051/4692e27a-d799-aaef-6e06-b51572eaa64c.png)

ページ送り機能も動くぜ！

![図3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/153051/bf834226-16a4-6c90-2e04-2cabcc7dcedc.png)

## 調子にのるとだめだね

でも調子にのって `https://{subdomain}.cybozu.com/k/admin/system/guest/#/0/500` ってすると怒られますw

![スクリーンショット 2023-12-07 19.10.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/153051/1b8e6eb6-0aa4-5f72-5e2d-674ff266c2e5.png)

（このアラートメッセージは怒ってる。。）

## おわりに

もともとアプリの一覧でこの隠し機能が便利で使ってたんですけど、公式が対応しちゃって出番が少なくなったネタです。ゲストユーザーがたくさんいる環境ってそこまで多くはないと思うんですが、弊社とかは外部とのやりとりも多くてゲストユーザーが以外と多いです。そしてアカウント連携してない人を洗い出したいときとかにこの機能が便利です。
以上、すごくないkintoneでした。（この記事は30秒では書ききれなかった・・）

それでは！≧(+･` ཀ･´)≦
AWS Console-to-code でコードを生成する on EC2

# AWS Console-to-Code

https://aws.amazon.com/jp/about-aws/whats-new/2023/11/aws-console-to-code-preview-generate-console-actions/

コンソールで実行されたアクションを、 CDK や CloudFormation に変換できるよというもの。

- CDK Java
- CDK Python
- CDK TypeScript
- CloudFormation JSON
- CloudFormation YAML

なので、あまり利用したことないサービスは一旦コンソールから作成したものを動作検証して、うまく動作したらそのまま Console-to-Code で、CDK や CloudFormation に出力して運用するみたいな時は良いかもしれませんね。今後他サービスに拡大されればですが。

※ ただし、2023/12/７ 現在はプレビュー版であり、バージニア北部のみ。また、EC2 のみに対応。


# やってみる

https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/console-to-code.html

起動テンプレートを次のような形でざっくり作成します。
![スクリーンショット 2023-12-07 17.06.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280929/c7569936-7064-8ff7-9f01-eefecc783fec.png)
![スクリーンショット 2023-12-07 17.06.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280929/309e857a-078c-4f46-94e6-912c18f4dd30.png)
![スクリーンショット 2023-12-07 17.06.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280929/8c9d082f-3846-e030-7f1e-9da40c1b4ef1.png)
![スクリーンショット 2023-12-07 17.06.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280929/bfbcff3a-d249-40ef-069a-3dbd628e6d4c.png)
![スクリーンショット 2023-12-07 17.07.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280929/b5428536-3ce5-c648-77e2-cd3fc112723a.png)

画面左の Console-to-code を開きます。
タイプより、「変異を表示」を開くと、CreateLanchTemplate(起動テンプレートの作成)が出来上がっています。
画面右の「YAML コードの生成」 を開きます。
![スクリーンショット 2023-12-07 19.23.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280929/b32cc6a8-ba3e-13c4-31a3-5b079c7216ee.png)

次の通り、CloudFormation テンプレートが生成されていました。パラメータなどにしたい場合は自身で編集する必要がありますが土台は作成されてくれます。
![スクリーンショット 2023-12-07 17.09.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280929/81ad6c53-38dc-23b5-3ecc-4e7ac699c13f.png)

今度は生成された、CloudFormation テンプレートで正常にデプロイされるか確認してみると次の通り、作成されたことがわかります。
![スクリーンショット 2023-12-07 17.32.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280929/4eb37a2f-a2e0-b39b-9f48-7f2020124193.png)

まだ実際に試してみてはいませんが、一度コンソールから作成して動作確認できたもものを削除して再度　CloudFormation テンプレートでデプロイするのは面倒なので、[スタックへの既存リソースのインポート](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/resource-import-existing-stack.html) を利用すると良いかもしれません。
リファクタリング等に関する覚書（順不同）

- リファクタリングとは何か？と問われ、「無駄」と答えるか、「すべき仕事」と答えるか、「したい仕事」と答えるかで、その人のコーダーとしての品質が推察できる
- 十分な経験を積んでいないコーダーほど、ことさらに「オブジェクト指向で作れ」とか「アジャイル開発で作れ」とか言いがちだが、リファクタリングに関しての話は出てこない（もしくは知らない）
- 一端（いっぱし）のコード書きなら、常に「以前のコードを書き直したい」と思っている
- 「過去の自分のコードを見ると必ず気に入らないところがある」という状態が普通
- あるロジックに関して、初めてコードにした時よりも、よっぽどのことがない限り、二度目はもっと上手に書ける
- コード書きに修行させたいなら、いじめのようなコードレビューより、リファクタリングさせるべき
- とはいえ、リファクタリングを知らなくても、偉くなれる 🙂
firestoreのindexを別のprojectへコピーする

### ３行まとめ
- 環境分けるために複数のfirebase projectを運用してる時、firestoreのindex同期化が面倒
- firebase cliを利用し、開発のprojectで `firebase init` →本番projectで `firebase deploy` すれば解決
- firebase cliを使うdirectoryは仮で作っても、既存に使っているところでも良い

### 本文
firebaseを利用してプロダクトを開発する時、
開発環境と本番環境用でそれぞれ別のprojectを作ることがあります。

firestoreを使っている場合は
collectionが増えるとruleの、
queryが増えるとindexの更新が必要になる訳ですが…
ruleは兎も角、indexの更新が面倒なんですよね。

開発環境の方は簡単です。
とりあえずquery作って、動作させればwarning logが流れるので、
そのlogが発行してくれるlinkを踏むとconsoleが開き、勝手に必要なindexを作ってくれます。
これもindex一個に付き一度行う必要があるので、数が多ければ面倒な作業には変わりませんが。
問題は本番の方。
流石に本番デプロイの後に同じことをする訳にも行きません。
なので開発環境で発行したindexを持ってくることができれば良いですが…
firebase consoleとcliで調べてみても現在のindexを丸ごと取る方法は見つからず。
（実はあるようでしたら是非ご教示お願いします！）

それで色々試してみた結果、以下の方法で落ち着きました。

1. firebase cliをインストール
1. 開発環境でindexを作っておく
1. 適当なdirectoryで `firebase init`
1. `firestore` だけ選択して初期化を進める
1. 選択するprojectはもちろん開発環境
1. 名前を変えてなければ `firestore.indexes.json` が生成されているはずなので、中身が最新であることを確認
1. `firebase use {本番project}`
1. `firebase deploy`

もしfirebase cliでのdeployを行ったことがあるdirectoryがある場合は
普通にそこで作業しても大丈夫です。
`firebase use {開発環境}` の後、何度 `firebase init` を実行しても
都度開発環境の最新を持ってきてくれます。
`.firebaserc` `firebase.json` が既に存在してたら上書きされないか…という心配を個人的にはしてましたが
現在は特にそのようなこともありません。

indexのためだけに毎回これをやるのも若干違う感じはしますが…
現状では、多分これが一番楽だと思います。
電帳法の検索機能と改ざん防止の要件を満たす方法を考えてみる　～電子取引編～

# はじめに	
2022年1月から施行されている、改正電子帳簿保存法（電帳法）の猶予期間が終了し、2024年1月1日から電子取引データのデータ保存が義務化されます。
今回の記事では、Excel と ファイルサーバだけで検索機能と改ざん防止の要件を満たす方法を考えます。

# 電帳法で保存対象が定められているデータ
電帳法には、3種類のデータの保存方法が定められています。
今回の記事では、この中から「電子取引データの保存」を取り上げます。

<img width="70%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3631614/58b2a445-f851-4aab-31e5-cb3c0d7d73f6.png">


# 電子取引データ保存の要件
電子取引データの保存方法については、以下のような要件があります。
この中でも重要な「改ざん防止のための措置」と「検索機能の確保」に関する要件をシステム化する方法について考えてみます。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3631614/c7479f0d-a955-c06f-29a0-dee4a81f97ed.png)

# 前提	
電子取引データとして注文書のPDFファイルを電子メールで取引先に送付するケースを想定します。
取引先に注文書を送付したら、当該ファイルをサーバに格納し、Excelの管理簿にその記録を残す運用を前提とします。	
そのとき、電子帳簿保存法で求められる要件に沿って、元ファイルの取り扱い、Excelでの項目やレコードの記載がどうあった方がよいか考えてみましょう。
	
# 電子取引データとは	
電子取引データというのは、PDF形式のファイルやEDIで送受信するデータのことです。
注文書や納品書、請求書など取引関連の書類を電子データとして保存する必要があります。
なお、これらの書類を紙で授受している場合は、スキャナ保存の要件を満たす必要があります。
	
# 検索機能
まず、検索機能に関する要件に対応してみます。
検索機能に関する要件には、以下のようなものがあります。
* 取引年月日、取引金額、取引先を検索の条件に設定できること
* 取引年月日、取引金額については、値の範囲を条件に検索できること
* 2つ以上の条件をAND条件で検索できること

ファイルを直接検索してもよいのですが、ここではExcelを使って取引の管理簿を作成し、管理簿に検索機能を付けることにします。
そうすると、前述の要件を簡単に実現できます。

管理簿には、取引の情報と、基となったファイルを特定できる情報を用意します。
必要な項目を管理簿に記載したら、あとはExcelのフィルタ機能を使います。フィルタ機能は、AND条件で検索できますし、値の範囲も指定できます。
例えば、こんな感じです。簡単ですね。
「ファイルパス」のところにExcelの機能で実ファイルへのリンクを付けておくと便利です。


<img width="80%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3631614/bde45e03-ebbe-35a2-506f-9b1b02325f07.png">

# 改ざん防止

つぎに、改ざん防止に関する要件です。
改ざん防止の措置として、以下のいずれかが必要です。
　①タイムスタンプの付与
　②訂正、削除の履歴が残るシステムあるいは訂正、削除ができないシステムの利用
　③事務処理規定の備え付け

今回は②の訂正、削除の履歴が残るシステムを実現してみます。
訂正、削除の履歴を残す必要があるのは、ファイルです。しかし、ファイルだけを見て履歴を把握するのは難しいので、管理簿と合わせて履歴を把握できるようにします。

履歴を残すことになりますので、訂正や削除をする前のデータは物理削除ではなく論理削除する必要があります。
また、訂正や削除を行った年月日や担当者の記録も求められていますので、それらの項目を記録できるようにします。

必要になりそうな項目を管理簿に追加しました。
訂正前のデータを残すため、「ステータス」という項目を使い、論理削除されたデータを識別できるようにします。
そして訂正の年月日と担当者を残すため、「訂正・削除担当者」と「訂正・削除年月日」という項目を設けておきます。

こんな感じになります。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3631614/006cdecb-08f3-c307-b0c5-0f332400750b.png)

では、訂正する場合の具体的な例を考えてみましょう。

管理簿の「No3」に対応したファイルを訂正し、取引先に送付したとします。

訂正前のファイルは物理削除せず残す必要があります。
従って、訂正前のファイルは更新せずにそのまま残します。
そして、訂正後の注文情報を新規のファイルとして作成し、ファイルサーバに保存します。

管理簿上では、「No3」のレコードの「ステータス」を「削除」に変更して論理削除し、当該の取引が削除されたとわかるようにします。
訂正した年月日と担当者は、それぞれ「訂正・削除担当者」と「訂正・削除年月日」に記録しておきます。

また、訂正後のファイルに対応したレコード「No4」を管理簿に追加します。
そうすると、データは以下のようになります。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3631614/94636df9-9e4b-0691-8027-7259fc09fca7.png)


実業務ですと、これが何のデータなのかを表す項目が必要になってくると思うので、注文番号などそれっぽい項目を追加すると、次の図のようになりました。
いい感じになりましたね。

論理削除されたレコードが見えるのが邪魔になるようであれば、Excelなら別のシートに出力されるような仕組みを作るとよいかもしれません。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3631614/26b8489e-25b4-1944-ee24-e5ae350a5961.png)


管理簿によってファイルの訂正、削除履歴を確認できますし、論理削除されたファイルも残っていますので、中身を確認できます。


最後の手段は事務処理規定。
システムでカバーしきれない部分は、事務処理規定を作成すれば良いことになっています。

# まとめ
Excel と ファイルサーバだけで検索機能と改ざん防止の要件を満たす方法を考えてみました。
今回の記事は以上です。
既存のMySQLを利用したNodeJSにPrisma導入する手順

# はじめに

自身の忘備録として、MySQLを利用したNodeJSプロジェクトにPrismaを、後から導入する手順をまとめます。
<br>

※ ***注意点***
Prismaは ***Node.js >= 16.13*** を必要とするので、バージョンが適していない場合はターミナルにて、以下によって指定しtNodeJsをインストールし

```bash
nodebrew install-binary インストールしたいNodeJSのバージョン
```
または
```bash
nvm install インストールしたいNodeJSのバージョン
```

以下を実行することでバージョン変更します。

```bash
nodebrew use インストールしたNodeJsのバージョン
```
または

```bash
nvm use インストールしたNodeJsのバージョン
```

# Prismaを導入

大きな流れは[公式ドキュメント](https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases-typescript-postgresql)を参考にして書かれています。

### Prismaのインストールと初期化

まず、ターミナルにて、Prismaのインストールを行います。
```bash
npm install prisma --save-dev
```

次に、初期化を行います。
```bash
npx prisma
```

```bash
npx prisma init
```

以上でインストールと初期化が完了しました。

### MySQLの接続

はじめにDATABASE_URLを.envファイルに記述します。

MySQLの場合は以下のように記述します。

```.env
DATABASE_URL=mysql://ユーザー名:パスワード@ホスト名:3306/データベース名
```

そして、***Prisma*** フォルダの ***scheme.prisma*** にある ***datasource db*** を以下のようにします。

```
datasource db {
  provider = "mysql"
  url      = env("DATABASE_URL")
}
```

最後にターミナルにて

```bash
npx prisma db pull
```

を実行することで、既存のデータベースの構造をPrismaが認識してくれます。

これにて、Prismaを既存のMySQLに接続することが出来ました。

# 終わりに
お読みいただいた方はありがとうございます。

本記事では、既存のMySQLにPrismaを導入する手順をまとめました。

詳細なPrismaの使用法に関しては[公式ドキュメント](https://www.prisma.io/docs)がとても分かりやすいので参照してみてください！
個別対応にご用心


何らかの理由により、特定のユーザー向けに何らかの開発を行ったりデータ修正を施したりすることを、ここでは個別対応と呼ぶこととします。泥臭い話ですが、案外色々な場所で行われているらしいということ最近知りました。
そんな個別対応、思いつくものをいくつか列挙し、主観で評価してみました。


# バグなどで発生した意図しない状態のデータの解消

運用的ご用心度: ★★★
保守的ご用心度: ★

例えば、何かしらのバグを含んだリリースをしてしまったとして、差戻しなり修正リリースなりでバグった状態を解消できたとします。しかしそのバグっていた間に意図しない状態のデータが生まれてしまって、ユーザーが自力で解消するのが不可能、あるいは可能ではあるが現実的でない時間がかかる、といった場合、その状態を解消してあげる必要があります。

基本的にその場その限りでの対応であるべき状態に戻すだけのため、技術負債的な意味では大きな問題はありません。
ただし、オペレーションミスには十分に注意すべきで、
- 絶対に一人でやらない
- バックアップを取る
- どういう対応をしたのか記録に残しておく

などの対策は必要でしょう。

（そもそもバグを起こすなという話もありますが、現実問題としてバグは起きるものなので）

# 仕様上出来ないデータの変更

運用的ご用心度: ★★
保守的ご用心度: ★★

現時点でユーザーに提供している機能の範囲内では変更・削除が出来ないデータに対して、どうしても変更したいという要望があるとします。例えば、
- データの結びつけを間違えてしまったので直したい
- プリセットをたくさん作ったがもう使わない、一覧画面に溢れて邪魔なので削除したい

など。

基本的にデータの変更はしなくて済むのであればそれに越したことはないですが、対外的理由等々でどうしてもやらないといけないということも往々にしてあると思います。やるのであれば、その対応で不整合が起きないことを入念に調査した上で、問題ないことが明らかにした上でやるべきです。

ただし、こういった対応が頻発するとリソースを圧迫するので、その場合はユーザーかサポートかに裁量を渡す方針を取れるとよいと思います。
- 変更・削除をできるようにする機能を開発・提供する
    - そもそも「システム的に重要なデータなのでユーザーに迂闊に変更させたくないため、意図的に機能を提供していない」といったケースもあると思うので、よく考えてから。
- サポートに限定的な権限を付与する

# 機能提供

運用的ご用心度: ★
保守的ご用心度: ★★★

あるユーザー向けに専用の機能を提供、あるいは特定の機能をあるユーザー向けにカスタマイズする、といったことがあるかもしれません。

こういったものは、一度提供してしまうと~~主に政治的理由により~~廃止しづらくなります。
また大抵の場合、こういった専用機能は作られたとしてもチーム内に事細かに周知されることがないため、保守できる人が限られてきます。その上であまりに特殊なことをしていると、保守コストが非常に高くなってしまいます。特定のユーザー専用ではなく、全体向けへの提供を考えてみても良いかもしれません。

また他にも、機能の差異をどう実現するかによっても注意点があり、

- ソースコードで実現する場合
    - if/switch文で書いてしまうと、1つの分岐がいずれどんどん肥大化して保守性が下がる。開放閉鎖原則に則った設計にしておくのがベター。
- データで実現している場合
    - 機能の標準として「想定していないデータ」が存在すると、将来的にその機能のリファクタ・リプレイスなどをする際に、データ移行がスムーズに行いづらくなる可能性がある。

# おわりに

個別対応の要望があったときに、盲目的に「アッハイやります」ではなく
- そもそもの期待がなにか考え、妥当な代案を提案する
- 運用保守まで考えて落とし所を見つける

といったことが出来るかどうかがエンジニアとしての腕の見せ所だと思うので、頑張っていきたいですね。
Pythonで「for文の中でrange関数を使って指定した回数だけ繰り返し処理を行う」の動作を確認してみた

# 概要

Pythonで「for文の中でrange関数を使って指定した回数だけ繰り返し処理を行う」の動作を確認してみました。以下のページを参考にしました。

https://www.javadrive.jp/python/for/index5.html

# 実装

以下のファイルを作成しました。
```sample.py
num = 1
for i in range(10):
    old = num
    num *= 2
    print(str(old) + " * 2 = " + str(num))
```

以下のコマンドを実行しました。
```
$ python3 sample.py 
1 * 2 = 2
2 * 2 = 4
4 * 2 = 8
8 * 2 = 16
16 * 2 = 32
32 * 2 = 64
64 * 2 = 128
128 * 2 = 256
256 * 2 = 512
512 * 2 = 1024
```

# まとめ

何かの役に立てばと。
OpenAIを組み込んだアプリを組織内に公開する方法

本記事は [OpenAI活用法 Advent Calendar 2023 by ナレコム](https://qiita.com/advent-calendar/2023/openai-knowledgecommunication) の6日目の記事です。

OpenAI活用法 Advent Calendar 2023 by ナレコム ではGPTsを含めた最新のOpenAIの活用法について紹介します。

### はじめに

Azure OpenAI Serviceなどを組み込んだアプリケーションをTeamsに組み込みたいというニーズが増えてきました。アプリケーション自体は開発者が出来るものの、公開するためには管理者が作業する必要があります。

本記事ではアプリを公開するための方法を紹介します。

### Microsoft Teams管理センターで行うこと

まずはMicrosoft Teams管理センターにアクセスして、ポリシーの変更を行う必要があります。

1. [Microsoft Teams管理センターの「アプリを管理」](https://admin.teams.microsoft.com/policies/manage-apps) にアクセスします。
1. 以下のような画面が表示されるので、右側の「組織全体のアプリ設定」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61189/2b5ef797-9dc3-464e-6f46-0c835b6b731e.png)
1. **組織全体のアプリ設定**が表示されるので「サードパーティ製アプリ」と「カスタムアプリ」の２つを許可します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61189/30011e08-dad7-74d7-30cd-0003930cd25c.png)

### Teamsから行うこと

続いてTeamsでアプリの登録と公開を行います。この作業はTeams管理者のみ行なえます。

1. Teamsにアクセスして、左下「＋」アプリをクリックして、表示されたアプリから「**アプリを管理**」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61189/b2188247-2ac1-e3ef-cafe-a100f60110e5.png)
1. アプリを管理画面で「**↑ アプリをアップロード**」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61189/a4acffb2-2b9a-3911-1c03-8fc6f97edd5f.png)
1. 「組織のアプリ カタログにアプリをアップロードします」をクリックしてTeamsアプリ（zipファイル）をアップロードします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61189/8af864c2-7baa-0d8b-b8f8-7ecba0b77052.png)
1. 以下のように「組織向けに開発」が追加されるのでアップロードしたアプリを「**追加**」します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61189/ea0012ff-263e-f4cd-bb60-64a02311627a.png)
1. 確認画面が表示されるので、再度「**追加**」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61189/1611ea5e-e308-2386-0ae5-1d1eced28b67.png)
1. 無事AOAIとBing検索を組み込んだボットが追加できました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61189/154b8eed-9aad-1d0b-f4ee-9bda34ddf4c6.png)

### まとめ

この記事では、OpenAI技術を活用したアプリケーションをMicrosoft Teamsに統合し、それを公開するための手順を詳しく紹介しました。Azure OpenAI Serviceなどの最新技術を組み込んだアプリケーションの需要が高まる中、このような情報は特に役立つでしょう。

まず、Microsoft Teams管理センターでのポリシー設定変更から始まり、Teams内でのアプリ登録と公開に至るまでのプロセスを一歩一歩丁寧に説明しました。この流れに従えば、開発者でも管理者でも、Teamsにアプリを追加し、利用を開始することが可能です。

また、画像を用いた実際のスクリーンショットによる説明は、特に視覚的に手順を理解したいユーザーにとって有益です。これにより、テキストだけの説明では伝わりにくい部分も明確になります。

最終的に、この記事はOpenAIを利用したアプリケーションのTeamsへの組み込みと公開に関する包括的なガイドとなります。OpenAI技術を活用することに関心がある開発者や、既存のビジネス環境にこれらの技術を統合しようと考えている企業にとって、この記事は貴重なリソースとなるでしょう。

---

また、ナレッジコミュニケーションでは  **「[Musubite](https://recruiting.musubite-job.com/features/company/knowledge-communication)」** というエンジニア同士のカジュアルトークサービスを利用しています！この記事にあるような生成AI 技術を使ったプロジェクトに携わるメンバーと直接話せるサービスですので興味がある方は是非利用を検討してください！

https://recruiting.musubite-job.com/features/company/knowledge-communication
Linux環境でDoxygenの出力形式にCHMフォーマットを使う方法

API仕様などを Doxygen で生成している皆様、それを配布する際にどんなフォーマットを使っていますか？
LaTeX などを使ってPDFを生成するのも良いですが、Doxygen のフォーマットと親和性が高いもう一つの出力形式にCHM形式があります。

https://ja.wikipedia.org/wiki/Microsoft_Compiled_HTML_Help

これはHTML形式を単純に一つのファイルに纏めたような形式で、昔の Windows でヘルプファイルの形式として使われていたものです。

Doxygen では、この形式がサポートされているのですが、少し問題があります。
Doxygen はCHMの生成に HTML Help Workshop という、Microsoft のツールに含まれているHTML Help Compiler (`hhc.exe`) というプログラムを利用するのですが、このツールはもう Microsoft は配布していないようなのです。

https://learn.microsoft.com/ja-jp/previous-versions/windows/desktop/htmlhelp/microsoft-html-help-downloads

しかし、捨てる神あれば拾う神あり、オープンソース版の実装として `chmcmd` というものがあることがわかりましたので、それを使って Linux 環境で Doxygen の出力形式として CHM を使う場合の設定について共有します。

https://wiki.freepascal.org/htmlhelp_compiler

## chmcmd の入手

chmcmd は Free Pascal の開発補助ツールとして配布されているので、Ubuntu の場合、`fp-utils` というパッケージに含まれています。これをインストールしましょう。

https://www.freepascal.org/

https://launchpad.net/ubuntu/jammy/+package/fp-utils

```
sudo apto install fp-utils
```

通常 `/usr/bin/chmcmd` としてインストールされます。

## Doxygen の設定

`Doxyfile` に以下の設定をしてください。

```:Doxyfile
GENERATE_HTMLHELP      = YES
CHM_FILE               = Document.chm
HHC_LOCATION           = /usr/bin/chmcmd
```

これで、 `html/Document.chm` が生成されます。

### 補足的な設定
FAQ的な内容ですが、以下の設定をしておかないと目次に日本語がある場合に文字化けします。
本文がUTF-8でも、目次はCP932にしていないと文字化けするところが古いWindowsらしいですね。
```:Doxyfile
OUTPUT_LANGUAGE        = Japanese
CHM_INDEX_ENCODING     = CP932
```
## 動作確認した環境

* Ubuntu 22.04 LTS
[Rails] ActiveModelは何をしているのか

ActiveModelはActiveRecordっぽいオブジェクトを作るために使えるという程度の認識だったので、少し理解を深めたくて調査しました。この記事では、ActiveModel::Dirtyに焦点を当てます。

## 代表的な使い方

https://api.rubyonrails.org/classes/ActiveModel/Dirty.html

```ruby
class Person
  include ActiveModel::Dirty

  define_attribute_methods :name

  def initialize
    @name = nil
  end

  def name
    @name
  end

  def name=(val)
    name_will_change! unless val == @name
    @name = val
  end

  def save
    # do persistence work

    changes_applied
  end

  def reload!
    # get the values from the persistence layer

    clear_changes_information
  end

  def rollback!
    restore_attributes
  end
end
```

重要なのは、`save`・`reload!`・`rollback!`の三兄弟です。これらのメソッドでは、それぞれ`changes_applied`、`clear_changes_information`、`restore_attributes`が使われています。これらのメソッドが、すなわちsave、reload、rollbackに対応している訳です。

実際に何が行われているのか確認するために、`change_applied`メソッドを読んでみましょう。

## changes_appliedメソッド

```ruby
    # Clears dirty data and moves +changes+ to +previous_changes+ and
    # +mutations_from_database+ to +mutations_before_last_save+ respectively.
    def changes_applied
      unless defined?(@attributes)
        mutations_from_database.finalize_changes
      end
      @mutations_before_last_save = mutations_from_database
      forget_attribute_assignments
      @mutations_from_database = nil
    end
```

解説するまでもなく、コメントに処理内容が書いてありますね（笑）。


ActiveModelのインスタンスには、database(上の変更)をエミュレートするためのオブジェクトが二つ用意されています。一つ前の変更内容(`mutation_before_last_save`)と現在の変更内容(`mutations_from_database`)ですね。

`changes_applied`では、現在の変更内容を一つ前の変更内容へとシフトさせています。このように、データベースの変更をエミュレートすることで、あたかも背後にデータベースがあるかのような振る舞いが可能になり、ActiveRecordの代わりとして使えるようになっています。

## 使ってみよう

- 値の変更チェック

```ruby
p = Person.new

p.name = "Tanaka"
p.save

pp p.name_changed? # => false

p.name = "Suzuki"

pp p.name_changed? # => true
```

- 値の変更履歴

```ruby
p = Person.new

p.name = "Tanaka"
p.save
p.name = "Suzuki"
p.save
p.name = "Kondo"

pp p.name # => Kondo
pp p.name_was # => Suzuki
pp p.name_previously_was # => Tanaka
```
Power BIについて

現在、Power BI DesktopとPower BI Serviceと分けています。
Power BI Desktopは、ローカルPCで動いているソフトウェアです。
Power BI Serviceは、グランドサービスで動いているソフトウェアです。

# 違い
Power BI Desktop と Power BI サービスを比較する
https://learn.microsoft.com/ja-jp/power-bi/fundamentals/service-service-vs-desktop
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/368087/edb981e4-5df4-6512-48d2-0e875f907de0.png)

# Power BIワークフロー

Power BI での一般的なワークフローは、Power BI Desktop でデータ ソースに接続し、レポートを作成することから始まります。 次に、そのレポートを Power BI Desktop から Power BI サービスに発行し、それを共有することで、Power BI サービスとモバイル デバイスのビジネス ユーザーがレポートを表示して操作できるようにします。
https://learn.microsoft.com/ja-jp/power-bi/fundamentals/power-bi-overview

# 共同作業
Power BI Desktop プロジェクトと Git の統合
https://learn.microsoft.com/ja-jp/power-bi/developer/projects/projects-git
Power BI Desktop プロジェクトと Azure DevOps の統合
https://learn.microsoft.com/ja-jp/power-bi/developer/projects/projects-azdo

手順
①Power BI Desktopのオプションのプレビュー機能を選択し、「Power BIプロジェクト(.pbip)を保存」をチェック
②開発中のプロジェクトを.pbipとして保存し、gitに上げる

# 直接データ編集
Power BIのテーブルを直接編集する方法
https://soft-zou.jp/2022/07/12/powerbi-table-creation-modify/
Power BI Desktop にデータを直接入力する
https://learn.microsoft.com/ja-jp/power-bi/connect-data/desktop-enter-data-directly-into-desktop

Power BI Service
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/368087/2ec08b14-33fb-b74c-d290-bf36b705090a.png)

# 多言語対応
[Tabular Editor 2 Docs] Power BI Desktopとの連携
https://qiita.com/akihiro_suto/items/f16888c680ee226d6666

Powre BI Desktopでの実施手順
https://qiita.com/ryoma-nagata/items/ef17e6bfe8bd6e45aaea

手順
①最新版 Tabular Editorインストール
https://github.com/TabularEditor/TabularEditor/releases/tag/2.21.1
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/368087/732e282e-4371-57c8-eca0-715c83f32f72.png)

②Power BI Desktopのオプションを選択し、プレビュー機能で Enhanced Metadata を有効化し、再起動

③Power BIレポートをPower BI Desktopで表示後、"Tabular Editor"を起動。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/368087/a73812d5-34b3-4716-fca1-437fa69ba5ee.png)

④"Translations"を右クリック後、"New Translation"を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/368087/33636fa9-cc10-8739-7b47-e0cbf15f4ff9.png)

⑤"Select Culture"ウィンドウにて、"ja-Jp - Japanese(Japan)" -> "OK"を選択。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/368087/32e1ddc6-352d-eeef-5a05-2165711152d7.png)

⑥翻訳対象の項目を"Tables"にて選択し、"Translated Names"にて適切な項目（例：テスト①）を入力し保存。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/368087/ad4fce77-686d-c7e6-1f1c-49d808e57450.png)

⑦Power Bi serviceに発行
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/368087/ca232148-0ace-0eac-0211-fe1e5900b2e7.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/368087/3e78cc0d-6162-09a8-0c9f-df56400a4c1c.png)

⑧Power Bi service上で通訳されることことが確認できる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/368087/843b1f71-f4ce-3272-508b-be65dd62d59a.png)
RHF+yupでAPIのレスポンスを元にバリデーションを設定する


株式会社HRBrainでフロントエンドエンジニアをしている富岡です。
この記事はHRBrain Advent Calendar 2023カレンダー2の23日目の記事です。

https://qiita.com/advent-calendar/2023/hrbrain

## 背景

私の所属しているチームではフォームを作ることが多く、これまでは都度フォームを作成していました。
将来的な作成コスト削減のため、APIを元にフォームとバリデーションを作成することになりました。
作成する際に参考になりそうな記事を探しましたが、これというものは見つけられなかったため今回執筆することにしました。

## 主な使用技術

- react: 17.0.2
- typescript: 4.4.4,
- react-hook-form: 7.27.0
- @hookform/resolvers: 2.8.8
- yup: 1.0.0-beta.3

## 都度フォームを作成していたときの記述方法

例えば、firstName、lastName、memoの3項目のフォームを下記の条件で作る場合、

- firstName
  - text
  - 必須項目
  - 最大10文字まで
- lastName
  - text
  - 任意項目
  - 最大10文字まで
- memo
  - textarea
  - 最大100文字まで

都度フォームを作成していたときはこのように記載していました。

```ts
const schema = Yup.object().shape({
  firstName: Yup.string()
    .required("入力してください。")
    .max(10, "10文字以内で入力してください。"),
  lastName: Yup.string().max(10, "10文字以内で入力してください。"),
  memo: Yup.string().max(100, "100文字以内で入力してください。"),
});

const methods = ReactHookForm.useForm({
  defaultValues: { firstName: "", lastName: "", memo: "" },
  mode: "onBlur",
  reValidateMode: "onChange",
  resolver: yupResolver(schema),
});
```

## APIのレスポンスを元にした記述方法

APIのレスポンスを元にバリデーションを設定するようにしました。

### レスポンスの型

レスポンス内にあるinput1つに対してのレスポンスは下記のような型になっています。

```ts
type Input = {
  id: string;
  type: "text" | "textarea";
  required?: boolean;
  maxLength?: number;
};
```

※実際のプロダクトでは他のtypeや正規表現などのルールもありますが省略しています。

### バリデーションの設定

基本的な記述方法で`yupResolver`に渡していた`schema`をレスポンスを元に組み立てる関数を作成します。
それぞれのinputに対するバリデーションを下記のように記述します。

```ts
const baseSchemas = {
  text: Yup.string(),
  textarea: Yup.string(),
};

const getSchemaByInput = (input: Input) => {
  let schema = baseSchemas[input.type];

  schema = input.required ? schema.required("必須です。") : schema;

  if (schema.type === "string" && typeof input.maxLength !== "undefined") {
    const maxLength = Yup.string().max(
      input.maxLength,
      `${input.maxLength}文字以内で入力してください。`
    );
    schema = schema.concat(maxLength);
  }

  return schema;
};

const getSchema = (inputs: Input[]) => {
  const schemas = inputs.reduce(
    (accumulator, current) => ({
      ...accumulator,
      [current.id]: getSchemaByInput(current),
    }),
    {}
  );

  const schema = Yup.object().shape(schemas);

  return schema;
};
```

流れとしては、

1. typeごとにベースになるschemaを設定する
1. 必須であればrequireメソッドを付ける
1. そのほかの条件を持つschemaを作成しconcatメソッドで合成
1. idをname属性に設定しているので対応するようにschemaを設定

実際に動いているものを触った方がイメージが湧くと思うのでサンプルコードを用意しました。

https://codesandbox.io/embed/zntpjz?view=Editor+%2B+Preview&module=%2Fsrc%2FApp.tsx&hidenavigation=1

実際の実装では正規表現での指定やもっと様々なバリデーションルールやtext、textarea以外のinputにも対応し、input部分も動的に作成していますが、今回はバリデーション部分にフォーカスするためハードコーディングにしてあります。

## 最後に

HRBrainでは一緒に働くメンバーを募集しています。
日本の生産性を高めるため、HR領域に興味があるエンジニアの方がいたらぜひご連絡ください。

https://www.hrbrain.co.jp/recruit

私の転職理由を書いた[35歳のフロントエンドエンジニアがメガベンチャーから転職した理由](https://qiita.com/tomtomtommy18/items/88754bfa3e36e3069959)も参考になれば嬉しいです。

また、本記事の内容について他にもっといい方法知ってるよという方がいらっしゃいましたらぜひコメントなどで教えてください。
[8日目] 学校の食堂をIT化させる話　キャッシュレス決済に対応させる導入部分

こんにちは、なりかくんと申します。
この記事はなりかくん Advent Calender 2023の8日目の記事です。

この話は、1日目から始めた学校の食堂をIT化させる話の続きとなります。前回までは、混雑度カメラについて書いていましたが、書きたいことはある程度かけたので今回からキャッシュレス決済部分について触れていこうと思います。

# キャッシュレス決済について
まず、食堂内のキャッシュレス決済とは具体的にどのようなものなのかを簡単に説明していきます。

1日目も書いた通り、現在私の学校の食堂は現金支払いのみがが利用できるのが現状です。私は普段からQR決済やタッチ決済を利用していて、ほぼ街の中で現金を使うことはありません。

ですが、学校内ではキャッシュレスが使えないので財布を持ち歩かないといけないのが、大変でもっと利便性を向上させたいため、食堂にキャッシュレス決済を導入したいと考えました。

導入する箇所は、食堂の料理を注文する部分と購買で商品を買うときなどに対応したいと考えています。

# 具体的なキャッシュレス決済の流れ
まず流れをつかんだ方が分かりやすいと思います。まず購買の現時点（現金）の商品受け取りまでの流れが以下の通りです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549951/86d718a8-479f-98e8-4c96-5b3016c3f18a.png)

そして、以下がキャッシュレス決済導入時の商品受け取りまでの流れです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549951/2daf8d84-78c5-33ff-6a12-e006fb1b1278.png)

ざっくりとした工程数は変わりませんが、事前の注文は食堂内で行わずとも教室内からでも行えるので、事前に教室内で支払いを行った上で食堂に行くと考えると、食堂内で行う工程数が減っていることが分かります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549951/ae279156-68a7-3273-8d43-331a9064ac1a.png)

これにより、今までよりスムーズに商品の受け取りが行えるのではないかと考えます。

食堂部分に関しては、今後別の記事で詳しく書いていきたいと思いますので、今回は省略します。

# どのようにキャッシュレス決済を導入するのか
では、次にどのようにキャッシュレス決済を導入するのかです。
まず、最初に思いついたのは事前チャージをしていく電子マネー方式です。形としては、イオンなどで使える「waon」が分かりやすい例なのかなと思います。

事前に専用の機械などでチャージしておいて、支払い時にチャージしておいたカードなどをかざせばチャージ残高からお金を引いて決済完了という形です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549951/1de41165-9db7-587d-9fbc-b3e732c3e024.png)

ですが、この方法では以下のようなデメリットが生まれます。
- 専用のチャージ端末を設置しておく必要がある
- 電子マネーシステムを作る必要がある

もちろん、外部を通さないので手数料が免除されるなどはありますが、専用端末を設置するのに機器の初期費用がかかるほかそのチャージ端末に待ち列が出来れば混雑の原因になりかねません。

また、電子マネーシステムを作る場合は様々な法律が絡んできて大変なため、今回この事前チャージの電子マネー方式は却下しました。

では、他に何があるのか。今主流のクレジットカード決済はどうなのか。
クレジットカード決済は、ブランドが複数個あり「Visa」「JCB」「Mastercard」など思いつくだけでも3つ以上あります。それぞれのブランドと契約するだけで一苦労です。

また、クレジットカードの場合の手数料は決済金額の3%～5%程度を店舗側が支払う必要があるため食堂側の負担が増えてしまいます。
たとえ、3%と言え1,000万円の売り上げがあった場合に30万円が手数料として持っていかれるのはきついですよね。

そこで、QRコード決済で考えます。いま日本で一番大きいQRコード決済は何でしょうか。そうです。「PayPay」なんです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549951/5ea0edd6-2411-bd3e-acb1-2604c02d137c.png)
※ スマホ決済サービスシェア（上位10位抜粋、出典：MMD研究所）

そのため、PayPayに限定してキャッシュレス決済の導入を考えます。PayPayも手数料がありますが、通常1.98%と比較的安い手数料です。

また、開発者向けのAPIやサンドボックスなども整っているため非常にシステム開発がしやすいというのがメリットとしてあります。

そのため、今回食堂のキャッシュレス化にはPayPayを導入することを決めました。

# 最後に
今回は、キャッシュレス決済の導入部分について書きました。今後数記事に分けて更にキャッシュレス決済について書いていこうと思います。
最後までお読みいただきありがとうございました。
歴史に学ぶCCoE。即ち三国CCo(駄洒落董卓討つべし

# CCoEとは社内三国志である

### はぁ・・・そっ閉じ

**いや、(X)を押す前にちょっと話を聞いてください！！**
CCoEを推進するにあたって、悩み事が星の数だけ噴出するんだけど、悩みながら、あれ？これどっかで見た事あったな？この感覚って事があって。
ぼんやり思い出すのは小学校の図書館で放課後に夢中になって読んだ「横山光輝の三国志」
あのストーリーに重なってて、実は展開が読めてたりするような気がしてるのです。
そう、"「覚悟」があるから幸福なのだ"

※意外と緻密に前回のジョジョネタから繋がっているという・・・

そんな昭和な小学生男子がこぞって読んだ三国志のエピソードをCCoEに絡めて明文化する怪文章ポエムですｗ

## 連環の計

これが一番思い浮かぶんだけど、部署横断だから連環して施策を回すことが多い。
たぶんCCoEってのがなかったら、**各部に同じ施策を適用することは難しかっただろう**と思ってる。
XX部がやってるから、YY部もやってくださいね？がそのままツーカーに通じるのって凄くね？といつも思ってる。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2334211/61a6b4b8-3387-c586-810c-6f7938e2c355.png" width=25%>

Japanese Stable Diffusion XLも今回はイケてるかんじだ・・・

## 鶏肋

マイナーなエピソードなんだけど、曹操が何となくリアルツイートした内容を深読みされて見抜かれて死刑になるというトンデモな話です。
ここでの共通点がガバナンスが深読みに倒れるとヤバくて、良かれと思ってインスタンスサイズをガンガン最適化（縮小）すると、大事故になったりするって点です。
しかも、**縮小＝コスト削減に繋がるのでエグゼクティブも大いに同意してしまうって点が曲者**なのよね。。

## 泣いて馬謖を斬る

CCoEにはセキュリティの立ち位置もあるので自プロダクトをもってると、どうしても自分が率いるプロダクトにメスを入れなければならないケースがある。
それが**全開放ファイアウォールみたいな面目ないやつだと、他部署への説得力にならないので全力で剥がしにかからない**とならぬのよ、、、
豹変したかのように可愛い自プロダクトの最適化をしてく痛みってなかなかのものですよね。。

## 蜀の最後

姜維がガッチリガードしているところを、剣閣を迂回されて、国を落とされてしまったという最終章。
ふと思うんだけど、これだけCCoEが盛り上がってると、元々あった軽量なコミュニティ組織を偉い人が占領してきたり、
**CCoEと同様の機能が社内公式に立ち上がってジエンド**みたいな事って今後ありそうだなぁ、なんてふとよぎったりする・・・

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2334211/978cea8d-126b-95c9-64f7-b1dee8ebab91.png" width=25%>

Japanese Stable Diffusion XL Demoの描く兵どもが夢の跡感

# むすび

というわけで危機はセブンセンシズでかんじようぜ!って話でした！！（次の記事は聖闘士星矢ネタかーｗ
symbol-node-configuratorを使ってウォレットで作成したアカウントの秘密鍵からノード証明書を作る

## はじめに

「一体コレが何の役に立つんだい」
「symbol-bootstrap 使えばいいじゃん」
そんな声が聞こえてきそうです。

「ウォレットで作ったアカウントをノードメインアカウントにしたいんじゃ～」とか言う変態向けです。

## 証明書の作成

必要なパッケージをインストール。

```
pip install symbol-sdk-python pyopenssl zenlog
```

symbol-node-configurator をインストール。
新しい SymbolSDK を使用するカスタマイズ版です。
設置場所はどこでも良いです。今回の例は `/opt` に設置した場合です。
また、証明書は `/opt/symbol-node-configurator/cert` に作成します。

```bash
cd /opt
git clone https://github.com/ccHarvestasya/symbol-node-configurator.git
cd symbol-node-configurator
```

### 秘密鍵の準備

本来なら下記のように OpenSSL を使って ca.key.pem を作成するのですが…

```bash
openssl genpkey -algorithm ed25519 -outform PEM -out ca.key.pem
```

表題の通り今回はウォレットまたは Symbol CLI で作成したアカウントの秘密鍵を使用します。
`ca.key`というファイルに作成したアカウントの秘密鍵を保存します。

```bash
vi ca.key
```

```ca.key
2DE0B46CBF0367A513CE7DFF...以下略
```

### PEM ファイル作成

秘密鍵から PEM 形式の秘密鍵を生成します。

```bash
python3 /opt/symbol-node-configurator/pemtool.py --input ca.key --output ca.key.pem
```

`ca.key`は、もう必要ないので削除。

```bash
rm ca.key
```

### ノード証明書作成

`ca.key.pem` を元に `cert` ディレクトリにノード証明書を作成します。
なお、 `cert` ディレクトリは自動で作成されます。

```bash
python3 /opt/symbol-node-configurator/certtool.py --working cert --name-ca "Symbol CA" --name-node "Symbol Node" --ca ca.key.pem
```

証明書が 2 つ作成されます。
メイン(ノードアカウント公開鍵): `cert/ca.crt.pem`
トランスポート(ノード公開鍵): `cert/node.crt.pem `

## 2 つの証明書を連結

メイン、トランスポートの順で連結して `cert/node.full.crt.pem` を作成します。

```bash
cat cert/node.crt.pem cert/ca.crt.pem | tee cert/node.full.crt.pem
```

## 確認

ノード証明書をサッと参照するとトランスポートの証明書のみが見えます。

```bash
openssl x509 -inform pem -noout -text -in cert/node.full.crt.pem
```

```
Certificate:
    Data:
        Version: 1 (0x0)
        Serial Number:
            78:68:67:b4:a6:d9:00:57:aa:7c:fc:e2:f6:93:f0:49:3b:18:97
        Signature Algorithm: ED25519
        Issuer: CN = Symbol CA
        Validity
            Not Before: Dec  7 08:15:57 2023 GMT
            Not After : Dec 16 08:15:57 2024 GMT
        Subject: CN = Symbol Node
        Subject Public Key Info:
            Public Key Algorithm: ED25519
                ED25519 Public-Key:
                pub:
                    94:0a:33:b6:43:fe:f6:5c:02:98:65:c1:93:31:61:
                    d4:c7:3d:aa:eb:63:da:e1:1d:fc:de:c5:2b:2d:54:
                    61:9a
    Signature Algorithm: ED25519
    Signature Value:
        de:49:72:54:35:46:3a:a5:8f:68:5c:1e:b3:dc:1b:4c:f2:64:
        85:06:6a:69:6c:3e:1f:50:e3:5d:2d:8c:9e:3d:c5:9c:50:33:
        18:5d:3b:b3:c8:c0:d2:b5:2e:d4:63:e4:29:c9:5b:fb:25:fa:
        5e:ed:e2:5f:16:8f:68:04:28:07
```

両方同時に確認したい場合

```bash
openssl crl2pkcs7 -nocrl -certfile cert/node.full.crt.pem | openssl pkcs7 -print_certs -text -noout
```

### 他のノードの証明書を確認

実際に稼働してるノードの証明書を参照する場合
7900 ポート開放してるノードのみ見れます。

```bash
openssl s_client -showcerts -connect 11.dusanjp.com:7900 </dev/null 2>/dev/null | openssl x509 -inform pem -noout -text
```

たまにポート変更してる変態もいるので、見れない場合はポートを確認してみてください。
以下は 7911 にしている場合。

```bash
openssl s_client -showcerts -connect symbol01.harvestasya.com:7911 </dev/null 2>/dev/null | openssl x509 -inform pem -noout -text
```

## さいごに

みんなが使っている symbol-bootstrap では、全く使用しない部分でした。
マニュアルビルドする際に使うかなぁ…使わないかなぁ…とかいうレベルです。

そんな変態向けな情報でした。
レガシーなシステムと向き合う時の気持ちの持ち方

:::note info
この記事は[『Code Polaris Advent Calendar 2023』 ](https://qiita.com/advent-calendar/2023/code-polaris "Code Polaris Advent Calendar 2023")の7日目の記事です。
:::

ちなみに、このアドベントカレンダーでもう1回登場する予定です。

# レガシーなシステムと向き合っている今日この頃
最近、ASPとかbashとかOracle Database（PL/SQLもいらっしゃる）とかのサーバ載せ替え案件に参画しています。先輩と社会人2～3年目の後輩くんたちとなんとかやっているのですが、PHPとかCMSとかの案件をやってきた後輩くんたちからすると、めちゃめちゃレガシーで古（いにしえ）感たっぷりな環境で色々と進め方に戸惑っているように感じています。

そんな後輩くんたちに向けて、モダンな環境で過ごしていたのに、急に自分が生まれてもない時代に作られたようなシステムの案件に ~~放り込まれた時~~ アサインされた時の、なんとか健やかに生き残るための気持ちの持ち方について書いてみます。

同じような状況にいる方が少しでも前向きに、とりあえず今はなんとかやってみるかと思ってもらえるといいな。

# 分からなくてアタリマエ
10数年という短すぎる私のエンジニア経験の中で、レガシーなシステムのお守り（おもり）を年単位でやった経験がある身から言えることは、目の前にあるシステムのことは **「分からなくてアタリマエ」** だということ。

今までお守りをしてきたのならまだしも、急に放り込まれたのなら、全然分からなくてアタリマエ、それが正常と言っても過言ではないと思います。

だから、何か仕事を振られて、全然分からなかったとしても悲観的にならなくてOKです。たぶん一緒に働いている先輩や同僚もそう変わらないレベルで分からない状態です。

分からないことに悲観的になるよりも、やるべきことがあります。

# 分かろうとする努力をしてみる
「なんか全然分かんないけど、これってどうなっているんだろう？」と分かろうとする努力が大切です。

今あなたの目の前にあるのはレガシーなシステムですが、仮にあなたが全く知らない超絶最新最強な技術を目の前にしても、分からないという状況は同じです。その状況を変えていくのは **「分かろうとする努力」** です。努力のための具体的な行動は異なるかもしれませんが、分からないものに向き合う考え方や分かるために考えたりする思考力は、レガシーだろうが超絶最新最強だろうが、おそらく同じです。

「レガシーなシステムだから、これを理解しても今後活かせないしー」と思うのではなく、「これってどういう仕組みになっているんだろう？」「どんなデータの持ち方しているんだろう？」と何かしら疑問を持って、ちょっとでも理解しようと行動を起こしてみることは、ムダでは無いと思うのです。

先輩や同僚たちはたぶん、この分かろうとする努力をして、レガシーなシステムのことを紐解いて、分かるようになっていっていると思います。

# デバッグを怖がらない・面倒くさがらない
昔の自分もそうなのですが、今一緒に働いている後輩くんたちも同じで、デバッグに積極的ではないように感じます（もちろん世にはそうじゃない人がいることも知っていますが）。

プログラミング言語にもよりますが、デバッグって、とても地道な作業です。コマンドプロンプトでメッセージを表示させたりブレークポイントを置いたりして、プログラムのどこまで進んだか見たり、ログに文字列を出力させてデータの途中経過を追っかけたりと・・・それはそれは地味で、プログラムによっては気の遠い作業になることもあります。

昔の自分だと、何かとスマートなやり方をしたくなりがちで、地道なデバッグ作業は苦手だったし、ログを読んだりブレークポイントで止めたりするのはなんか難しいと思い込んでいたし、面倒くさがってました。

私も途中で「どこまで進んだかわからーん」と投げ出したくもなるのですが、とはいえ、そこは **「分かろうとする努力」** です。プログラムを1行ずつ追っかけて、1つずつ可能性を潰していくことで、エラーの原因が分かります。

このデバッグは、モダンなシステムや環境であっても、形や方法を変えて必要になってくるスキルだと思います。なので、レガシーかモダンかは置いといて、デバッグに慣れる機会と思えば好機です。

# レガシーなシステムでの経験は活かせるか？
たとえば、今後、超絶最新最強な技術の仕事をすることが決まっているとします。その前の案件がレガシーなシステムに関わる案件だったとして、このレガシー案件での経験は超雑最新最強な技術の仕事に活かせるでしょうか？

私は活かせると思います。

捉え方の問題で、「活かせる」「活かすぞ」と思って取り組めば、問題の本質やエッセンスが記憶に残って、将来似たような現象に当たった時に「これってあの時の考え方を活かせるかも」と思い付けるんじゃないかなと思うのです。逆に、「活かせない」と思って取り組むと、目先の問題解決だけに終わって、何も残らないような気がしています。

私の今の案件でも、せっかくよく分かっていないことがたくさんあるんだからデバッグの練習になるなと捉えようとしたり、一部分は今後も使いそうな技術があるなと感じているからその周辺を特に理解しようとしたりしています。

# レガシーなシステムと向き合う時の気持ちの持ち方
・・・とまあいろいろ書いてみましたが、ちょこっとでも前向きに捉えようとしてみると良いかなと思ってます。

でも、どうしても前向きに捉えれない時もあります。そんな時は、その気持ちは否定せず、何がイヤなのか・どうだったら良いのかに向き合ってみるのも良いかも。

ちなみに、私の今の案件はデバッグが進み、ちょっとプロジェクトに余裕ができてきました、やったね！
WARNING - FreeImage is not set up correctly. Please ensure FreeImage is set up correctly. というエラーが出た

## 経緯

UbuntuにNVIDIAのcuDNNをインストールしようとして、
公式ドキュメントの[installation Guide](https://docs.nvidia.com/deeplearning/cudnn/install-guide/index.html)に沿って進めていったところ、[1.4. Verifying the Install on Linux](https://docs.nvidia.com/deeplearning/cudnn/install-guide/index.html#verify)の
`make clean && make`
を実行したときに以下のようなのwarnningが出て、mnistCUDNNが作成できなかった。

```
test.c:1:10: fatal error: FreeImage.h: そのようなファイルやディレクトリはありません
 #include "FreeImage.h"
          ^~~~~~~~~~~~~
compilation terminated.
>>> WARNING - FreeImage is not set up correctly. Please ensure FreeImage is set up correctly. <<<
```


## 解決法


以下を実行してFreeImageをインストールする。

```bash
sudo apt-get install libfreeimage3 libfreeimage-dev
```


再度`make clean && make`以下を実行し、無事
Test passed!となった。