OmniAICreator/Qiita-1.07M huggingface dataset:
terraform-provider-awsにContributeした話

## TL;DR
TerraformでAWS環境のプロビジョニングをしていた時に遭遇したちょっとした不具合を改善してContributeした話です！

## 〜序章〜
ある日いつものようにAWS IAMのリソースをterraformでプロビジョニングしていたところ変更していないはずのIAM Groupのリソースが毎回変更されてしまうことに気付きました。毎回変更していないはずのリソースが変更されてしまうというもどかしさを抱えながら悶々とした毎日を過ごしていました。
ある日同僚のエンジニアとOSSへのコントリビュートを目標とした会を結成し何かいい題材はないかと考えていたところ前述のことがパッと思い浮かびすぐさま修正に取り掛かりました。

## Issueの発見
まずは自分と同じような悩みを抱えている人はいないかIssueを眺めていると...見つけました！
https://github.com/hashicorp/terraform-provider-aws/issues/22274
しかし長い間そのIssueは放置されたまま...どこを修正して行けば良いか実際にコードを見ていくことにしました。
すると簡単な変更で問題が解決できそうなことが分かってきました。

## 修正
実際の修正コミットはこちらです。
https://github.com/hashicorp/terraform-provider-aws/pull/23060/commits/360b394e774dfe45d9f9c44e769188a7fd86c0bd#diff-c5aeb20b1fe251f0cc7b75a1f9b30d2e25813e7f05c9e24c96d1df19ed57c0e3
やっていることは単純でterraformで記述したAssumeRolePolicyDocumentと実際のAssumeRolePolicyDocumentが同等であるかのチェックを入れるというものです。

## 〜Pull RequestからCloseへ〜
さて、コミットとプッシュが完了し単体テストもパスしました！あとはPull RequestをOpenしてメンテナの方に見てもらうだけです！
しかし、メンテナの方も日々大量のPull Requestに対応しているようでなかなかCloseされませんでした。
![PRのCloseを心待ちにする人の声.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536302/f8483660-8b32-4a04-f0de-408f36b3be56.png "PRのCloseを心待ちにする人の声")
*PRのCloseを心待ちにする人の声*

そしてPull Request Openから約4ヶ月後、ついにPull Requestがマージされました！


## 感想
小さな改善でしたが自分のコミットがterraform-provider-awsに反映されているというのは中々感動モノでした。
初めてのOSSコントリビュートということでどうやっていけば良いかはじめは手探りでしたがterraform-provider-awsは毎日大量のContributeが行われておりしかもContiributeのドキュメントも手厚く用意されていたのでそれを参考にしてすんなりと修正を完遂することができました。
日々お世話になっているOSSへの恩返しにもなると思うのでぜひOSSへのContribute挑戦してみてはいかがでしょうか！
週間のしいたけ占いのリンクをSlackに自動で送られるようにしてみた！

※まだまだ不慣れなので、温かい気持ちで読んでいただけると幸いです。

# 背景
2,3年前からお世話になってるしいたけ占い。
半期の占いも有名ですが、週間の占いも出してくれています。
大変お世話にはなっているものの、一つだけ問題が、、見に行きづらい（私感）
リンクをSlackにおくったらええやん、、よし、つくろう。

# やったこと
* GAS（GoogleAppScript）で週間占いのURLを生成
* URLを含めた文章をSlackの特定のチャンネルに投稿
※Botユーザの作成は済んでいる前提の記事となります

# GAS（GoogleAppScript）で週間占いのURLを生成
```javascript:siitake.gs
  //月曜の日付を取得
  var date = new Date();
  var diff = date.getDay() - 1;
  date.setDate(date.getDate() - diff);
  var format_date = Utilities.formatDate(date, 'Asia/Tokyo', 'yyyyMMdd')

  //Slackボットが投稿するメッセージを定義する
  let message = "";
  message = "【しいたけ占い】※"
    + format_date.substring(4,6)
    + "/"
    + format_date.substring(6)
    + "週の運勢"
    + "\n"
    + "https://voguegirl.jp/horoscope/shiitake/libra/"
    + format_date
    + "/";
```
週間のしいたけ占いのURLは、以下の構成になっています。
```
https://voguegirl.jp/horoscope/shiitake/{星座を表す文字列}/{月曜の日付}/
```
星座を表す文字列はそれぞれ以下になっています。
※ご自身の星座のURLをお使いください
　牡羊座：aries
　牡牛座：taurus
　双子座：gemini
　蟹座：cancer
　獅子座：leo
　乙女座：virgo
　天秤座：libra
　蠍座：scorpio
　射手座：sagittarius
　山羊座：capricorn
　水瓶座：aquarius
　魚座：pisces

# URLを含めた文章をSlackの特定のチャンネルに投稿
```javascript:siitake.gs
  let token = "Botトークンが入ります";
  let slackApp = SlackApp.create(token);

  //Slackボットがメッセージを投稿するチャンネルを定義する
  let channelId = "チャンネルIDが入ります。";

  //SlackAppオブジェクトのpostMessageメソッドでボット投稿を行う
  slackApp.postMessage(channelId, message);
```

# 最後に
しいたけの週間占いは12時に公開になるので、その前にURLを投稿するとプレビューが表示されません！
トリガー設定の時間は週に１回の１２時〜１３時がオススメです！

GASでめんどくさいを自動化してハッピーライフ


# 参考
[GASとは](https://developers.google.com/apps-script)
[Slackのメッセージ検索](https://api.slack.com/methods/search.messages)
[しいたけ占い](https://voguegirl.jp/horoscope/shiitake/)
Unity Cinemachine VirtualCameraを知らない人向けだけの紹介

この記事はUnityアドベントカレンダー2022https://qiita.com/advent-calendar/2022/unity の8日目の記事です

# 初めに
みなさんはCinemachine VirtualCameraをご存知でしょうか
Unity公式のパッケージであり、Unity2017の時点ですでに本リリースされている、熟しているライブラリです
ゲーム内のカメラのコントロールや演出のカットシーンを作る際にとても便利で、しかも公式ライブラリなので無料です！

それではまずはこちらをご覧ください

![sample.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49946/65667d6b-180e-3c7d-97c3-c9c3f686cb1e.gif)

この動きを簡単に作れる、とても便利なライブラリなのです

ただ、私の観測範囲のイメージでしかないのですが、
このライブラリ、使っている人は使っているが、使ってない人は存在も知らない。といった印象を受けています

そこで、本記事ではCinemachine VVirtualCameraの基礎中の基礎の紹介をさせていただきます
やることはデフォルトのパラメータやそれをちょっといじるだけでできるものに搾っています
この記事を書くためにCinemachine VirtualCameraの設定をいじったのは5分もかかっていません

なので、すでに使われている方はもちろん、Cinemachine VirtualCameraがどういうものかをすでにご存知な方にも新しい情報は無いと思われます

あくまで「ほぼ何もしなくても導入するだけでこれが作れる」と言った、まさに紹介です

## どういった機能なのか

最初に動画を出したカメラの動きですが、A地点からB地点まで設定するとそこに向かってカメラがズームする。というよくある動きです
この動画でやっていることはAのカメラとBのカメラの位置をCinemachine VirtualCameraで設定し、優先度を切り替えているだけで、他は完全デフォルトの設定です

その切り替えした時にうまくカメラの遷移をブレンドして動いてくれていますね

もちろん、カメラの位置や設定を変えればそれもまたうまくブレンドしてくれます

こういった、自分でコードやアニメーションを設定すると大変になる処理をなんかいい感じにしてくれるのがCinemachine VirtualCameraとCinemachine Brainなわけです

## 設定方法

まずはPackageManagerでCinemachineをインストールします

<img width="500" alt="インストール" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49946/ca353989-9eed-4c8b-e60c-495506f0c170.png">

そうしたらMainCameraにCinemachine Brainのコンポーネントをアタッチします
<img width="500" alt="アタッチ" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49946/0e1f1401-c61b-2c09-1ac6-1709a4c406eb.png">

その後カメラを用意し、位置や回転を調整した後に
PriorityやGameObjectのActiveでカメラの切り替えを行います
<img width="500" alt="Priority" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49946/59a0a51f-4f76-5584-b068-9f8bd4fa20c9.png">

これだけで画面のようなカメラ効果の実装が可能です

## 他にもできること

こう言った固定カメラへの移動以外にもキャラクタの移動を追従させることが可能です

![Dec-06-2022 21-54-16.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49946/c153a8e6-13bb-f7d1-553f-5f9c29e10fb3.gif)

これは単なる追従ではなく、ちょっと遅れて追従されているのがわかると思います
この動きもノーコードで設定できるのがCinemachine VirtualCameraの大きな特徴です

![スクリーンショット 2022-12-06 21.51.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49946/8213ecea-dc19-ce3f-d653-26f82eb53c71.png)

設定項目が多くてわかりにくいところですが、そう言った場合は画面内をドラッグしたりしていい感じに設定できます

また、カメラの設定中にSoloのボタンを押すとEditor上でプレビューもできるので、大変設定しやすいです
そのため、カメラの設定パラメータが何をやっているかがよくわかっていなくても
「なんかいい感じの追従カメラ」を見た目と合わせながら調整できます

<img width="500" alt="Priority" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49946/5e057eb0-0149-a7b9-5984-35c526e18a6d.png">

## 最後に
今回の紹介はあくまで最初に使う、シンプルなものでしかありません
カメラの移動可能範囲を設定できたり、Timelineと連動させて演出を作ることも可能だったりと
基本も応用もかなり使いやすいライブラリです

この記事を見て少しでも興味を持った方がいれば、まずは導入を
そしてすでに数多くの紹介記事やドキュメントがありますので
作っているゲームやアプリに最適なカメラ演出を作っていきましょう
「システム構築を納期までにまにあわせたいのですが、顧客幹部から仕様変更の依頼が来ています」をChatGPTにきいてみた

ChatGPTを試した結果を貼り付けます。参考まで。

![1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22985/b65659ff-b572-db5e-bed8-ade287e90b0f.png)

![2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22985/abda6ea3-d327-5880-b754-3cd3e6fcc2dc.png)

![3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22985/0ffee451-043e-6a26-c145-6f2567cf75b3.png)

![4.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22985/40d8f311-028b-5d44-8c5d-ec344e04574b.png)

![5.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22985/30bbb948-f1fa-30e2-0d5e-926fe216c6ad.png)

![6.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22985/9b641e12-e136-d1c0-8d4b-258d216c96d9.png)
カラーユニバーサルデザイン ~IllustratorとPhotoshopで確認してみよう! ~

# はじめに
　はじめまして、となっぴーです！Life is Tech !でWebDメンターをしています。普段は大学で生物や化学の勉強をしていて、細胞のカラーユニバーサルデザイン、ヒトの色覚について考える機会があったので、今回の記事では、
1. カラーユニバーサルデザイン
2. IllustratorとPhotoshopで色の見え方を確認する方法

を紹介したいと思います。
　メンバーやメンターが作品のデザインを考える時、スクールで発表会のためにスライドを作る時にちょっとでも参考になればうれしいです:relaxed:
# カラーユニバーサルデザインってなんだ？
　数多くの色が世界には存在していますが、実は人によって見え方は様々です。(色覚特性と言います)
　一部の人にとっては区別のつきにくい色の組み合わせが存在し、不便さを感じてしまう場面があります。情報を認識するのに「色」は欠かせないため、公共のデザインでは不便さを感じる場面が少なくなるような色を選ぶことが重要です。
　大学の実験というかアカデミックの世界でも、顕微鏡で観察した細胞の写真を画像処理する際、全ての人にとって見やすくなるよう配慮しています。
　写真は私がImageJというソフトで画像処理したものです。![スライド3.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032943/8bc6d604-ade9-1b3e-f5f4-f33925f9b8fb.jpeg)

# IllustratorとPhotoshopで色の見え方を確認する方法
それでは、 IllustratorとPhotoshopで色の見え方を確認する方法について紹介したいと思います。今回はクリスマスっぽいデザインを例に見てみましょう。
## 開発環境
Photoshop v24.1
Illustrator v27.0.1
## 具体的な例
　IllustratorとPhotshopでは **[表示]→[校正設定]** から、色の見え方を確認することができます。P型色覚、D型色覚の見え方をシミュレーションできます。
### 修正前
　まず、色覚によって全く違う風に見えていることが分かります。
P型色覚、D型色覚の場合では特に"CHRISTMAS"という文字が判別しにくくなっていますね。
(緑色に見える色覚でも、少し見づらくなっていますが、、、)
![スクリーンショット (142).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032943/06a0c0bd-8b92-ac62-b673-c8d59fed9162.png)
![スクリーンショット (143).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032943/9350c0d3-d247-eb0e-1a8e-c66056b6fe8e.png)
![スクリーンショット (144).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032943/5c83bbb8-4204-a1f9-eadb-4a03b7e2e373.png)



### 修正後
　"CHRISTMAS"の色を修正してみました。白に変更することで、背景の色との差がはっきりと出て見やすくなっています。
![スクリーンショット (145).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032943/6bf3fb81-3577-2686-eabd-1492d89503be.png)
![スクリーンショット (146).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032943/f6fbee11-4e9d-93ac-a3c2-529deca0da8e.png)
![スクリーンショット (147).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032943/5c9724a8-eacd-d272-86fb-db1dac656cdb.png)

また、[カラーユニバーサルデザイン推奨配色セット](https://www.dic-graphics.co.jp/navi/color/ud.html)というものも存在していて、見分けやすい色の組み合わせ、見分けにくい色の組み合わせなどが紹介されています。こういった配色セットを使って色を決めていくのも一つの方法かなと思います。


# おわりに
　今回はカラーユニバーサルデザインについての記事を書かせていただきました。細胞の実験から、こういった風に話題が広がるとは思っていなかったので自分でも驚いています。色を選ぶとき、「他の色覚の人からはどう見えるんだろうか？」とちょっとでも意識してもらえたらなと思います。
　一例として、IllustratorとPhotoshopで確認する方法を紹介しましたが、Chromeの拡張機能や、Webサービスなどでも確認できるものがあります。自分の使いやすいものをぜひ探してみてください:relaxed:
　
# 参考記事
https://www.dic-graphics.co.jp/navi/color/ud.html
https://helpx.adobe.com/jp/photoshop/using/proofing-colors.html
【ActionView::MissingTemplate in Tweets#index】Missing partial......エラーの解決方法

# エラー内容
・ActionView::MissingTemplate in Tweets#index　というエラーが表示された。
![ActionView MissingTemplate in Tweets#index.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710373/e68fc0ab-9b34-31c2-fbc5-1be188a98c5a.png)

# 原因
・なんでpartialが見つからんのだ！おれはちゃんと作ったぞ！としばらく彷徨いましたが、ファイル名「 _tweet.html.erb」の頭文字にスペースが入っていたのがエラーの原因でした。それは見つからんというエラーが出るわけですな。
・他サイトなどからコピペした時は、先頭に余計なものが入っていないか、要注意ですね。VSコードの文字サイズが小さかったりするとなかなか見つかりません( ﾉД`)ｼｸｼｸ…

# 解決方法
・「 _tweet.html.erb」を「_tweet.html.erb」とする。
現場の開発チームリードと経営企画の両方にいるとどうなるか

VoicyのPMM（プロダクトマーケティングマネージャー）をしている高桑です。

この記事では現場と経営の2部署配属を経験して、見えてきたことをお話しします。

所属しているチームは下記の2つです
・リスナーユーザーのアクティブグロースをミッションとする、開発チームのPdM
・中長期で会社や事業の戦略を立てる経営企画

ボトムアップとトップダウンの渦中にいるわけなので、社会人6年目にして新しい景色をたくさん見れています。

1：タイムスパンが違う
現場は短期目線、経営は中長期目線

2：前提と目的の重要性が違う
現場は前提と目的に沿った合理的な戦略を、経営は前提を見直して目的を創り出して時にはアーティスティックな戦略を、それぞれ求められること

どちらかに属すれば、あとは片方に任せた！となるのですが、
今僕は両方やっているため、どっちを先に定めるかを考えさせられました。

最終的に僕がとった行動は、「本質的にユーザーの体験が良くなるためにはどうすべきか？」の観点に立ちかえることで、要件を一つずつ決めていきました。

結果として、経営チームと現場チームA（高桑所属）の目線を合わせることができ、
現場チームの目標をボトムアップで策定、トップダウンから現場チームの目標が覆ることは起こりませんでした。

ユーザーにとって本質的にいいことであれば、どのレイヤーのどのチームでも理解はしてもらえるはずなので、まずそこを握り、dataの裏付けもとり、チームへの説明も誠実に行い、順序よく巻き込むことで実現できたと思います。

話は変わって、現場チームAは高桑が配属される前に、少し耐えどきな時期を過ごしていました。
1：施策の結果（KPI）が伸びない
2：やっと施策がヒットして結果（KPI）が伸びたのに、KGIが動かない
あたりです。

1の原因の1つに、チームの思考が既存のdataを正義としすぎていたところがあり、まずここにメスを入れました。
新しく入った僕にしかできないこと...それは「新しい風を吹かせてみんなに自信を持ってもらうこと！！」

なので、今までのdataからかけ離れたアーティスティックな施策を1発打とうと思いました。
dataはなく、直感とそれを論理武装しただけです。
ありがたいことに、チームのみんなは納得してくれたので開発することになりました。

dataぐらいしか信じられるものがなく、それでも施策がヒットしなかった状況なので、
いきなり入ってきた僕のアーティスティックな施策を受け入れるのは、簡単なことではなかったと思います。
「本能的に絶対刺さるはず」という手応えのみが、僕の自信を支えていて、そのデザインや細かい設計は細部までこだわって作り切りました。

結果、その施策はヒットしたので新しい軸で成功事例を生み出したことになり、dataの幅は広がりました。
さらには、来シーズンのチーム目標もこの施策の方向性になり、
当施策の成功を根拠に、他チームも同じ方向性で新施策を打つことが会社全体で増えていきました。
会社全体に、1つの新しい風を吹かせることができたと思います。

この成功事例を武器に、経営チームでも話を通して、目線を合わせることができました。
こうすることで、現場と経営、両方で新しい風が吹き始めました。

次は「2」です。
KGIが動かないのは、
・KPIがKGIに対して間接的すぎた（相関性の捉え方が難しい、dataサンプル数が不足しているかもしれない可能性）
・KGIを動かすには、そもそもタイムスパンが短すぎる（その目標を今の3ヶ月ではなく1年にするべきだ、など）
・KGIを直接動かすには、別の方向性の施策が必要
などのいくつかの可能性を感じたので、
さらなるdataを持ち込んで、これを解剖して、

経営チーム（高桑所属）⇆現場チームA（高桑所属）⇆現場チームB
で、役割とKPIと施策の方向性を再設計して、合計3部署に声をかけて巻き込んで、チーム横断のパフォーマンスの最大化へ今動き出しています。で、この構想提案はすでに概ね通っています。

ということで、来シーズンからはさらに強い新しい風をトップダウン、ボトムアップの双方から吹かせることができそうです。

新時代のVoicyをお楽しみください。僕は必ずやり切ります。

あ、あと社長の緒方が新書籍を発売したので、ぜひ購入してください！
僕は即日購入しました、これを読んでいつか一緒にプロダクトの話をしましょう。待ってます😁
https://amzn.to/3AQqWKL
![IMG_0364.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2970440/ee1060b2-1000-9e60-37f6-bb647a9ec39e.jpeg)
Leetcode 268. Missing Number

# 268. Missing Number

https://leetcode.com/problems/missing-number/

## 難易度
### Easy

## アプローチ
### Hashmap

```java
class Solution {
    public int missingNumber(int[] nums) {

       HashMap<Integer,Boolean> hashmap = new HashMap<>();

        for(int i = 0 ; i <= nums.length ; i++){
            hashmap.put(i, false);
        }

        Arrays.stream(nums).forEach(obj -> {
            hashmap.put(obj, true);
        });

        return hashmap.entrySet().stream()
                .filter(obj -> obj.getValue() == false)
                .findFirst()
                .get()
                .getKey();
    }
}
```
【PHP】データベースの型にdecimal(1,0)を使用する

# 初めに
:::note warn
この記事は初学者を対象に書かれています
:::
最近Laravleの改修案件に参画しているのですが、

新しくテーブル、カラムを追加する機会があったので

その時に疑問に思ったこと、学んだことを共有します。


## decimalとは
`decimal`とは固定小数点数型のことで、記述方法か以下のようになります

```
decimal(M,D)
```
>M ->桁数の合計 (精度)
D ->小数点以下の桁数 (スケール)

最大桁数 (M) は `65`
デフォルトは `10`
小数部の最大桁数 (D) は `30`
デフォルトは `0`


例えば、`decimal(5,3)`の場合、

`12.345`のように

5桁で小数点以下3桁の数字になります

## データベース設計においての有効性
データベース設計において、データの型はとても重要です。

例えば以下のようなデータベース設計はどうでしょうか？

usersテーブル
| Column | Type | Option |
|:-:|:-:|:-:|
|  id |  int |  PK |
| name  | String  |   |
|  book_id | String  | FK  |

booksテーブル
| Column | Type | Option |
|:-:|:-:|:-:|
|  id |  int |  PK |
| name  | String  |   |

このデータベース設計には一つの欠陥があります。

それは、FKのbook_idがString型であることです。

booksテーブルのidはint型で数値しか入らないのに、

それを参照するusersテーブルのbook_idはString型だと、

全角半角の違いなど、エラーや例外が発生しやすくなりデメリットしかありません。

それでは以下に直したらどうでしょうか？

usersテーブル
| Column | Type | Option |
|:-:|:-:|:-:|
|  id |  int |  PK |
| name  | String  |   |
|  book_id | int  | FK  |

booksテーブル
| Column | Type | Option |
|:-:|:-:|:-:|
|  id |  int |  PK |
| name  | String  |   |

これで良さそうに見えますが、まだ改善点があります。

そう、decimalを使うのです。

usersテーブル
| Column | Type | Option |
|:-:|:-:|:-:|
|  id |  int |  PK |
| name  | String  |   |
|  book_id | decimal(3,0)  | FK  |

booksテーブル
| Column | Type | Option |
|:-:|:-:|:-:|
|  id |  int |  PK |
| name  | String  |   |

int型だと9-10桁の整数を格納しますが、
>整数 (INTEGER) 型は、9 桁または 10 桁の精度で、-2,147,483,647 から 2,147,483,647 の範囲の整数を格納します。

decimal(3,0)だと３桁の整数までしか格納できません。

「ユーザーが持つ本の数が4桁もいかないだろう」

という時はこのように最小の型で定義してあげましょう。

DBの設計の基本の1つとして、膨大に容量が膨れやすいDBの設計は、中に何が入るのか、どのぐらいのデータになるのか予測して、その最小の型で定義していくものです。

そうしないと、サーバーの容量を食う上に読込速度も遅くなるといった無駄なことが増えるためです。

例えば1件のデータを追加するだけで定義したカラム分容量を食うので

これが数万、数千万となると適当に定義すると必要な容量が2倍、3倍と増えてサーバーのストレージのお金もかかります

## まとめ
今までは「動けばいいや」とずっとint型でやってきましたが、

これからはもっとスマートに型を決めていこうと決意しました。

参考になれば光栄です。

[decimalについて参考にしたサイト](https://www.javadrive.jp/mysql/type/index9.html)
Windows + Scoop でちゃちゃっと作る、Python開発環境

こんにちは。

僕を含むパソコンを入れ替えることが多い人にとって、開発環境を準備するというのはそれなりに手間ですよね。
そこで今回は、Python開発環境を手軽に作るためのTipsを共有したいと思います。

大きな流れとしては、たったの2ステップです。

1. **Windowsのパッケージ管理ツール Scoop をインストール**
2. **Scoop を使ってPythonランタイムをインストール**

以降の説明は、Windows 10/11上で、Scoop及びPythonをインストールしていないことを前提に説明します。

# 1. Windowsのパッケージ管理ツール Scoop をインストールする

[Scoop](https://scoop.sh/) は、Windowsで使えるパッケージ管理ツールです。

パッケージ管理ツールを使うことで、Windowsで従来「インストーラをダウンロードしてきて、実行してインストールして、環境変数設定して…」と行ってきたことが、コマンド一発ﾀｰﾝｯと叩くだけで済むようになります。

それでは、Scoopをインストールしていきましょう。必要なのは以下の2ステップだけです。

1. PowerShellを開き、 https://scoop.sh/ の `Quickstart` 項目の流れに則り、2行のコマンドを実行します。
    ```sh
    > Set-ExecutionPolicy RemoteSigned -Scope CurrentUser
    > irm get.scoop.sh | iex
    ```
2. `scoop --version` と入力し、Scoopのバージョンが表示されたらインストールが完了しています。


# 2. Scoopを使ってPythonランタイムをインストールする

Scoopがインストールできたら、次はPythonランタイムのインストールです。

これもほんの2ステップで完了します。

1. `scoop install python` のコマンドを実行します。
2. `python --version` でPythonのバージョンが表示されたらインストールが完了しています。

従来のインストーラを使った流れなら環境変数 Path の設定をする手順を踏まないと `python` コマンドは実行できないところですが、すぐに使えるようになりましたよね。ここまでの設定をよしなにやってくれるのが、Scoopが良い味を出している点の1つです。


# さらにもう一歩、Python開発を便利にしてみよう

Pythonの開発プロジェクトを管理するためツールの1つに [Poetry](https://python-poetry.org/) というものがあります。これさえあれば、pipもvenvも使うことがほぼ無くなるので大変おすすめです。(というより、Poetryが代わりになってそれらを呼び出して、よしなに管理してくれます)

使い方の紹介は [Poetryをサクッと使い始めてみる](https://qiita.com/ksato9700/items/b893cf1db83605898d8a) などの記事に譲るとして、ここではPoetryをScoopでインストールする方法についてご紹介します。…とは言っても、ここまでの流れとで何となくお分かりかもしれませんが、やることは2ステップで終わりです。

1. `scoop install poetry` を実行します。
2. `poetry --version` でPoetryのバージョンが表示されたらインストールが完了しています。

あとはPoetryを使って新規にPythonプロジェクトを作ったりしていきましょう。ちなみに
 [非公式の日本語訳Poetryドキュメント](https://cocoatomo.github.io/poetry-ja/) が公開されており、一通りの使い方は日本語で読むことができるのが嬉しいところです。
 
 
 # Scoopを使いこなすためのヒント
 
- コマンドラインから使う実行ファイルは、率先してScoopでインストールしよう。
  - Python以外もメジャーなプログラミング言語の実行ランタイムは大抵インストールできます。
- `scoop search {検索したい文字列}` で、Scoopでインストールできるライブラリを確認できます。
  - `scoop search python` のように実行してみましょう。
- "Bucket" の設定を追加すると、Scoopでインストールできるパッケージが一気に増えます。 (参考[Scoop で利用できる Bucket の解説](https://qiita.com/nimzo6689/items/5ead753169dbad72e4eb))  
例として以下のコマンドを実行すると、過去バージョンである Python 3.9 をインストールできます。
    ```
    scoop bucket add versions
    scoop install python39
    ``` 
 
# 参考リンク

- [Scoop](https://scoop.sh/)
- [Poetry](https://python-poetry.org/)
- [Poetry 日本語訳ドキュメント](https://cocoatomo.github.io/poetry-ja/)
- [Poetryをサクッと使い始めてみる - Qiita](https://qiita.com/ksato9700/items/b893cf1db83605898d8a)
- [Scoop で利用できる Bucket の解説 - Qiita](https://qiita.com/nimzo6689/items/5ead753169dbad72e4eb)
paizaラーニング「二次元配列の入力 2 Python3編」

https://paiza.jp/works/mondai/array_primer/array_primer__2dmatrix_input_step2
#### 私の解答
```Python3
n = int(input())
for i in range(5):
    values = input()
    print(values)
```
#### 解答例
```Python3
M = int(input())

A = [[0] * M for _ in range(5)]
for i in range(5):
    values = input().split()
    for j in range(M):
        A[i][j] = int(values[j])

for i in range(5):
    for j in range(M):
        print(A[i][j], end="")

        if j < M - 1:
            print(end=" ")
        else:
            print()
```
ActionController::RoutingError (No route matches [GET] "/tweets"):の解決方法

# エラー内容
ActionController::RoutingError (No route matches [GET] "/tweets"):

# 原因
・まだtweetsのルーティングを設定していないのに、`https://localhost:3000/tweets`でアクセスしていたため。
・こちらの記事の例３）に助けられました。意外と同じようなエラーなっちゃっている人いるのかも...？(;;)
https://qiita.com/KONTA2019/items/b75f940399506dfe8430

# 解決方法
・`https://localhost:3000/`でアクセスしたら解決したというなんとも肩透かしな結末。
複数アーキテクチャ用の xcframework; Rust などで作った静的ライブラリ (*.a) から


# モチベーション
Rust で作った静的ライブラリ(*.a)を, Xcode でビルドしている iOS(/Mac) アプリにリンクして使用したい.
それぞれのプラットフォーム/アーキテクチャ向けにビルドした複数の *.a (とヘッダファイル) を,
1つの xcframework にバンドルする.

## ポイント
iOS シミュレータ(や Mac) については, 動作ターゲットが
- x86_64 な Intel Mac
- aarch64(ARM64) な M1/M2 Mac

のどちらでも使えるように, x86_64 と aarch64 向けの両方を用意したい.

## Rust ? 🤔
Apple の複数プラットフォーム, アーキテクチャについてビルド済みの静的ライブラリ(*.a)をバンドルしたい, といった需要があるならば, Rust に限った議論ではない.

# Rust ビルドターゲットの整理

Apple の各プラットフォーム, アーキテクチャについて, Rust の target triple をまとめておく.
[Target Tier](https://doc.rust-lang.org/nightly/rustc/platform-support.html) は 2022/11 現在の nightly のもの.

| プラットフォーム, アーキテクチャ | Rust target triple | Rust Target Tier |
| ---------------------------- | ------------- | ---- |
| iOS | aarch64-apple-ios | 2 |
| iOS シミュレータ (x86_64) | x86_64-apple-ios ⚠️ | 2 |
| iOS シミュレータ (aarch64)| aarch64-apple-ios-sim | 2 |
| Mac (x86_64) | x86_64-apple-darwin | 1 with Host Tools |
| Mac (aarch64) | aarch64-apple-darwin | 2 with Host Tools |

:::note warn
iOS シミュレータの target triple について, x86_64 には接尾辞 -sim が付かないことに注意.
(x86 の iOS デバイスはないので自明ということか)
:::

# 手順

`crate-type=["staticlib"]` な crate を通常の手順で iOS と iOS シミュレータ向けにビルドする:
```bash
cargo build --target aarch64-apple-ios
cargo build --target x86_64-apple-ios
cargo build --target aarch64-apple-ios-sim
```

単純にこれらの静的ライブラリから xcframework の生成を試みると:
```bash
# aarch64-apple-ios
# x86_64-apple-ios
# aarch64-apple-ios-sim
xcodebuild -create-xcframework \
  -library target/aarch64-apple-ios/debug/libxxx.a \
  -headers path/to/headers \
  -library target/x86_64-apple-ios/debug/libxxx.a \
  -headers path/to/headers \
  -library target/aarch64-apple-ios-sim/debug/libxxx.a \
  -headers path/to/headers \
  -output libxxx.xcframework
```

以下のエラーメッセージが出力される:
```
Both ios-arm64-simulator and ios-x86_64-simulator represent two equivalent library definitions.
```
iOS シミュレータについて, arm64 と x86_64 のバイナリが重複している旨.
"library definition" は "target platform" くらいに読み替えてよいらしく,
1つのプラットフォーム(ここでは iOS シミュレータ) には1つの `-library` 指定しかあってはならないらしい.

## 解決策
同一プラットフォームの異なるアーキテクチャについては, [fatバイナリ](https://ja.wikipedia.org/wiki/%E3%83%95%E3%82%A1%E3%83%83%E3%83%88%E3%83%90%E3%82%A4%E3%83%8A%E3%83%AA)にまとめておく必要がある.
ここでは iOS シミュレータ用の2つのアーキテクチャ(x86_64-apple-ios, aarch64-apple-ios-sim)について行う:
```bash
# libxxx_iossim.a := x86_64-apple-ios + aarch64-apple-ios-sim
lipo -create \
  -output libxxx_iossim.a \
  target/x86_64-apple-ios/debug/libxxx.a \
  target/aarch64-apple-ios-sim/debug/libxxx.a
```

fatバイナリを用いてもう1度 xcframework の生成を行うと成功するはず:
```bash
# Thin: aarch64-apple-ios
# Fat:  libxxx_iossim.a (= x86_64-apple-ios + aarch64-apple-ios-sim)
xcodebuild -create-xcframework \
  -library target/aarch64-apple-ios/debug/libxxx.a \
  -headers path/to/headers \
  -library libxxx_iossim.a \
  -headers path/to/headers \
  -output libxxx.xcframework
```

:::note info
もちろん Mac 用にもビルドしている際にはその x86_64 と aarch64 もまとめてfatバイナリにする必要があるはず.
(x86_64-apple-darwin + aarch64-apple-darwin)

さもなくば次のようなエラーメッセージに繋がると思われる:
```
Both ios-arm64-maccatalyst and ios-x86_64-maccatalyst represent two equivalent library definitions.
```
:::

# 参考
https://developer.apple.com/forums/thread/666335
Commitに署名をしよう！！ーGPGの使い方ー


みなさん、GitのCommitに署名使っていますか？気軽に使えるので、みなさんも登録してみましょう。

もしも署名されたコミットの場合は以下のように緑文字で`Verified` と記載されます。かっこいいですね。「なりすましをしていないよ！」ということを示しています。

![スクリーンショット 2022-12-07 21.25.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/163357/f0e169d1-845d-8c87-0250-957fa53c17a5.png)


[Githubのドキュメント](https://docs.github.com/ja/authentication/managing-commit-signature-verification/generating-a-new-gpg-key)

## ざっくりとした手順
1. 全体用の鍵を作る
1. 署名用の鍵を付け加える
1. Githubに公開鍵を登録する
1. Gitにこの鍵を使うよとconfig --globalで伝える。
1. Commitする！

## 詳細手順

### 全体用の鍵の作成
macの場合は以下のアプリケーションをインストールします
https://gpgtools.org/

上記のツールをインストールした状態で以下のコマンドを入力します。
```
$ gpg --full-generate-key
```
鍵の種類は`(1) RSA と RSA (デフォルト)`を選択
RSA鍵の長さは`4096`を選択[^1] その後以下のコマンドを入力すると以下のような記述がなされているかと思います

この時点で`rsaxxx/AAAAAAAA 2222-00-00 [S]`というような表記がある場合Githubに公開鍵を登録する部分まで飛ばしてしまっても問題ありません。

```
$ gpg --list-secret-keys --keyid-format=long
-------------------------------
pub   rsa4096/550D4A48 2022-12-07 [SC]
      0１２９３８７０FAA94837AF26C7382007732
uid         [  究極  ] Hugami Hogeta <example@example.com>
sub   rsa4096/AA49243B 2022-12-07 [E]
```

### 署名用の鍵の作成

上記の場合Pubの鍵が「550D4A48」[^2]であるので以下のようにコマンドを入力
```
$ gpg --edit-key　550D4A48
gpg> addkey


sec  rsa4096/550D4A48
     作成: 2022-12-07  有効期限: 無期限      利用法: SC  
     信用: 究極        有効性: 究極
ssb  rsa4096/AA49243B
     作成: 2022-12-07  有効期限: 無期限      利用法: E   
ssb  rsa4096/5D8AC5A
     作成: 2022-12-07  有効期限: 無期限      利用法: S   
```
今度は暗号化ようの鍵を生成するため`(4) RSA (署名のみ)`を選択肢鍵の長さは前回同様`4096`を選択。このようにすると、利用方法：S　な署名用の鍵`5D8AC5A`が生成されます。

```
gpg >quit
変更を保存しますか? (y/N) y
```
gpgのインターフェースは`quit`で抜けることが可能です。

### 公開鍵の登録

```
gpg --armor --export 550D4A48

-----BEGIN PGP PUBLIC KEY BLOCK-----
(中略)
-----END PGP PUBLIC KEY BLOCK-----
```
ここでのポイントはSではなくSCの鍵を登録することです。上記で鍵を付け加えたため、公開鍵には署名に対応する鍵も含まれています。
きちんと`--BEGIN PGP`から`---END PGP`までコピーしておきましょう。Macの場合は以下のコマンドで同時にクリップボードが可能になります
```
gpg --armor --export 550D4A48　| pbcopy
```
これをGithubの[`Settings > SSH and GPG keys `](https://github.com/settings/keys)の`New　GPG　Key`ボタンから登録することで鍵の登録が可能になります。

### Gitに登録（グローバル）

```
git config --global gpg.program gpg
git config --global user.signingkey 5D8AC5A
git config --global commit.gpgsign true
git config --global tag.gpgsign true
```

あとはコンフィグをセットするだけです。ポイントとしては、`user.signkey`　に登録するのは「署名鍵の」IDを使うという点です。

## 参考文献

https://qiita.com/kanatatsu64/items/85104644d1599c244f35
https://docs.github.com/ja/authentication/managing-commit-signature-verification/generating-a-new-gpg-key
https://gpgtools.org/

----
 ### おまけ　ー　Discordの鍵流出対策が面白い話ー
GithubのPublicリポジトリにDiscordのトークンを一瞬流出させてしまったのですが、流出した瞬間にトークンが無効になりDMが飛ぶようなシステムまで作られているみたいです。

普通にすごい。
※トークンは流出しないようSecretで管理しましょう。

![スクリーンショット 2022-12-07 22.07.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/163357/3b19baeb-2909-cf58-3aaf-b2e2d1854708.png)

iOS版アプリでもポップアップで教えてくれます。ヒェッ

![IMG_7686.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/163357/3581b156-38a7-2dd1-ba9e-fa6ab26b2800.jpeg)

[^1]: Githubのドキュメントを見ると最低4096とあるので4096と選択しています。
[^2]: 上記のコマンドは今回説明用にそれっぽく書いた乱数です。
rbenv: version `バージョン' is not installed

対象バージョンがインストールされていないのでインストールします。
今回の場合は3.1.0をインストールします。

```% rbenv install 3.1.0```

適用するバージョンの指定
rbenv versionsを実行すると現在適用されているバージョンを確認することができます。
現在では2.6.5が適用されているようです。

```% rbenv versions```

```
  system
  2.5.8
* 2.6.5 (set by /Users/~~/.ruby-version)
  3.0.3
  3.1.0
```
 

以下のコマンドで対象のバージョンに指定できます。

```% rbenv local 3.1.0```
Leetcode 938. Range Sum of BST

# 938. Range Sum of BST

https://leetcode.com/problems/range-sum-of-bst/

## 難易度
### Easy

## アプローチ
### DFS

```java
package com.leetcode.easy;

public class RangeSumOfBST938 {
    public static void main(String[] args) {
        TreeNode938 treeNode938 = new TreeNode938();
        treeNode938.val = 10;

        treeNode938.left = new TreeNode938();
        treeNode938.left.val = 5;

        treeNode938.right = new TreeNode938();
        treeNode938.right.val = 15;

        treeNode938.left.left = new TreeNode938();
        treeNode938.left.left.val = 3;

        treeNode938.left.right = new TreeNode938();
        treeNode938.left.right.val = 7;

        rangeSumBST(treeNode938, 7, 15);
    }

    public static int rangeSumBST(TreeNode938 root, int low, int high) {
        dfs(root, low, high);
        return result;
    }

    public static int result = 0;

    public static void dfs(TreeNode938 treeNode938, int low, int high) {

        if (treeNode938 == null) {
            return;
        }
        if (low <= treeNode938.val && treeNode938.val <= high) {
            result += treeNode938.val;
        }

        dfs(treeNode938.left, low, high);
        dfs(treeNode938.right, low, high);
    }
}


class TreeNode938 {
    int val;
    TreeNode938 left;
    TreeNode938 right;

    TreeNode938() {
    }

    TreeNode938(int val) {
        this.val = val;
    }

    TreeNode938(int val, TreeNode938 left, TreeNode938 right) {
        this.val = val;
        this.left = left;
        this.right = right;
    }
}
```
Ruby on RailsのアプリケーションにBasic認証を導入する手順

# 概要
アプリケーションにBasic認証を導入したので、その手順を記載する。

# 実装方針
認証に必要なユーザー名やパスワードは、環境変数を呼び出す形式で実装する。
開発環境および本番環境に、環境変数を設定する。
デプロイはherokuを利用する。

# 実装条件
 適切なユーザー名やパスワードが入力された場合は、認証を通過できること。
 適切ではないユーザー名やパスワードが入力された場合は、認証は通過できないこと。


# Basic認証とは
・HTTP通信の規格に備え付けられている、ユーザー認証の仕組みのこと。
・サーバーとの通信が可能なユーザーとパスワードをあらかじめ設定しておき、それに一致したユーザーのみが、Webアプリケーションを利用できるようになる。

・Ruby on Railsにはauthenticate_or_request_with_http_basicメソッドという、Basic認証をするためのメソッドが用意されている。便利なのでこれを利用しよう！
　・ブロックを開き、ブロック内部でusernameとpasswordを設定することでBasic認証を利用できます。

# 安全性について
・HTTP通信で定義されている仕様上、漏洩のリスクはある。ログアウトの概念もないため、必要になる場合は自分で実装しなければいけない。
・完全に信頼できる認証方式ではないので、必要最低限の認証機能として利用すること。

・履歴書やポートフォリオに記載する場合・友人や知人にアプリケーションを見てもらう場合は、GitのURLに加えて、Basic認証のIDとPASSも記載しないと誰もみてくれないので要注意！笑
・逆にあやまってIDとPASSを不特定多数が見れるところに記載してしまうと、不正利用に繋がるので注意です^^


# 手順
・application_cotroller.rbに以下を追記する。
application_cotroller.rbに記載するのは、全てのコントローラーで共通して実行する必要があるため。

```application_cotroller.rb
class ApplicationController < ActionController::Base
  before_action :basic_auth

  private

  def basic_auth
    authenticate_or_request_with_http_basic do |username, password|
      username == ENV["BASIC_AUTH_USER"] && password == ENV["BASIC_AUTH_PASSWORD"]
    end
  end
end
```

・`vim ~/.zshrc`で環境変数を定義する。
　・「vim」：サーバー上で使用できるテキストエディタのこと。
　・「zsh」：ログインシェルと呼ばれるもので、プログラムを実行する時に、ユーザーの要求に一番最初に対応する役割を担う。シェルとは、「ターミナルとOSを繋ぐ窓口役」のこと。隠しファイルなので、特別な設定なしではFinderなどには表示されない。環境変数は.zshrcの中で設定する。
　・「bash」：zsh同様、ログインシェルの1つです。OSがCatalina以降であれば「zsh」、Mojave以前であれば「bash」が自動で適用される。環境変数を記載する場所は、設定ファイルである「.bash_profile」の中。


・ インサートモードに移行してユーザー名とパスワードを設定する
`export BASIC_AUTH_USER='xxxx'`
`export BASIC_AUTH_PASSWORD='xxxx'`
・escで「通常モード」に → :wqで編集した内容を保存してvimを強制終了
　・編集した内容を保存しない場合は、q!で強制終了できる。一応補足しておくと、:wは作成・編集したファイルを保存、:qはvimの終了を意味している。

・`source ~/.zshrc`
→シェルに記述された内容を実行


・application_cotroller.rbでusernameとpasswordを修正する

```application_cotroller.rb
  def basic_auth
    authenticate_or_request_with_http_basic do |username, password|
      username == ENV['BASIC_AUTH_USER'] && password == ENV['BASIC_AUTH_PASSWORD']
    end
  end
```

・以下を実行
` heroku config:set BASIC_AUTH_USER="xxxx"`
` heroku config:set BASIC_AUTH_PASSWORD="xxxx"`

・`heroku config`
→config内容を確認

・Gitにコミット・プッシュする
`git add .`
`git commit -m "Basic認証を導入"`
`git push heroku main`
【UiPath】「繰り返し (データ テーブルの各行)  (For Each Row in Data Table) 」を使用してデータテーブルの特定行を削除する

「**繰り返し (データ テーブルの各行)  (For Each Row in Data Table)** 」アクティビティ内では普通に行を削除しようとしてもエラーになります。
以下は繰り返し (データ テーブルの各行) の中で「データ行を削除」アクティビティを使用する例です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/578020/9cedeeb9-b731-1857-bb2d-f3dd3ba836f2.png)
商品名がリンゴの行だけ削除しようとしていますが、
「コレクションが変更されました」でエラーになってしまいます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/578020/cb1914aa-ebb0-a891-b73d-825bc82fec46.png)

---
対策としては繰り返し (データ テーブルの各行) を使わずに「**繰り返し (コレクションの各要素)** 」や「**データテーブルをフィルター**」アクティビティで代用するケースが多いと思いますが、
「**メソッドを呼び出し**」アクティビティを使うことで、繰り返し (データ テーブルの各行) でも特定行を削除することができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/578020/e6993ceb-960b-0d89-ac5f-410575a6d57a.png)
①繰り返しに入る前に、DataTable変数を対象にAcceptChangesメソッドを実行
②繰り返しの中で、DataRow変数を対象にDeleteメソッドを実行
③繰り返しを抜けた直後に、DataTable変数を対象にAcceptChangesメソッドを実行

事前にAcceptChangesメソッドを実行することで、Deleteメソッドを実行しても次のAcceptChangesまで行の削除が保留されます。
これにより、繰り返しの中では行削除されないためエラーにならず、繰り返しを抜けたところでDeleteメソッドを実行した特定行が一括で削除されるという流れになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/578020/4842fc29-56ee-6377-a079-3da54a0180fd.png)

## 動作環境
UiPath.System.Activities 22.10.3

## 参考
https://docs.uipath.com/activities/lang-ja/docs/for-each-row

https://learn.microsoft.com/ja-jp/dotnet/api/system.data.datarow.delete?view=net-7.0
N予備校プログラミングコースのSlackをDiscordに引越しするかも

どうも、N予備校プログラミングコース講師の @rabeneko です。

普段はN予備校で授業や特番を行っております。

# 忙しい人向け

Slackの無料プランが90日以前のログを消すようになったため、 **Discord** への移行を検討中。
今後の授業でお試しで使っていき、良さそうであれば2023年からDiscordをメインにします。

招待リンクは[こちら](https://discord.gg/K9KMBdeEbZ)

# N予備校について

N予備校はプログラミングを始め、大学受験やWEBデザイン・動画制作などを月額1100円で受講できる学習サイトです。
毎週火曜と金曜の19時から生授業を行っております。
生授業は無料で閲覧できますので、興味がございましたらぜひ覗いてみてください。

https://www.nnn.ed.nico/

# 背景

N予備校の生授業では、Slackでプログラミングの雑談・質問・相談を受け付けています。
質問は受講生同士や講師が答えており、活発なコミュニティーを形成しています。

![スクリーンショット 2022-12-07 11.50.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1972052/f42c5eed-6044-527c-1e2a-56a2bb2cd8c7.png)

ところが最近、Slackの書き込み頻度がやや落ちているように感じてきました。

# Slackの有料化

ご存知の通り、Slackは無料プランの内容変更が行われました。

![スクリーンショット 2022-12-07 15.38.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1972052/49225d3c-e7f7-40df-e295-6d06b1d67cd4.png)

過去90日以上のログが残らなくなってしまった…！

**ナンテコッタイ！！**

これまでは、Slack検索をすれば過去の質問が追えたんですよね。
それがやはり **資産** だったと感じます。

分からないことがあったら検索するのが効果的なプログラミングにおいては、かなりのマイナスです。

# Slackに課金するのはどうなのか

![スクリーンショット 2022-12-07 17.05.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1972052/10df0062-b0c5-df6c-9323-e30ef9abf2cc.png)

ログを残すにはフリープランからプロプランにする必要があります。
月925円と聞くと大したことがないように感じますが、個人で課金できるわけではなく、なんと **N予備校のSlackに参加している人全員** が課金する必要があるんです。

N予備校には2022年12月現在4588人のユーザがいますので、 **月425万円** 、 **年5100万円** 課金する必要があります（笑）

過去のアーカイブのために年5100万円はなかなか出せませんね…

Slackはエンジニアの業務でも使うことも多いツールなので、できればSlackという気持ちもありますが、無料でアーカイブが残る所に移行したほうが今後のためのように思っております。

# Discord

Discordはゲーム界隈でよく利用されているコミュニケーションツールです。
音声チャットが有名のようですが、Slackのような文字ベースのコミュニケーションも取ることができるようです。

![E1Rs7H9WQAAR0dL.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1972052/6c971e12-e1e7-2409-b82c-54ba62ab1d9c.jpeg)

もちろん有料プランもありますが、無料でもアーカイブは無期限で残るようです。

# Discordを使ってみる

さっそく、N予備校のDiscordサーバを立ち上げました。

招待リンクは[こちら](https://discord.gg/K9KMBdeEbZ)から！
N予備校生でなくても参加大歓迎です！！

https://discord.gg/K9KMBdeEbZ

## 基本的なチャット機能

基本的にはSlackと同じ感じで使うことができます。
ファイルやコードのアップロードも、問題なくできました。

![スクリーンショット 2022-12-07 21.34.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1972052/80d3c0cc-1861-aeaf-8822-eccf4db2a799.png)


## スレッド機能

スレッドも使えます。
一定時間、左側のチャンネル一覧にもスレッドへのリンクが出てきます。
便利ですね！

![スクリーンショット 2022-12-07 21.39.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1972052/8cd0de31-97cf-f6ef-39f9-14a7c0957ab7.png)

## スタンプ機能

Slackには無い、スタンプ機能もあります。

![スクリーンショット 2022-12-07 21.41.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1972052/56e589bc-37b4-bc74-4a10-21836ad7f6eb.png)

授業で使うと盛り上がりそうですね〜！！

# 今後について

DiscordがSlackの移行先としてすごく良さそうです。

今後の授業で皆さんにもお試しで使ってもらって、良さそうであれば2023年から移行していきたいと考えています。
DMM Advent Calendar

# DMM Advent Calendar

dmm23卒内定者の萩原です

この記事では

- 自分の簡単な自己紹介
- SQLインジェクションについて簡単な説明　を取り扱っていきたいと思います

<h1>自己紹介

氏名　萩原 優
年齢　21歳　(早生まれなので)
職種　エンジニア (セキュリティ)
出身　静岡

### 中学〜専門学校進学まで

生まれは静岡で中学3年で不登校になり、高校受験をしたものの内申点が一桁だったため、通信制の高校に進学しました。（後からわかったのは静岡県は学力よりも内申点を重視しているため不登校になったら少なくとも高校までは響く模様）
しかし、高校入学して約3ヶ月ほどで学校に馴染めないことや家庭環境など様々な要因が絡みあい中退しました。
その後、ガソリンスタンドで働きながら高卒認定（旧大検）を取得して、大学に行くか専門学校に行くか迷いセキュリティについて学びたかったので横浜市にある情報科学専門学校に進学しました。

### 専門学校〜現在　

専門学校では1年生の時にコンピュータの基礎を勉強して、2年生以降はセキュリティ関連の勉強をしました。3年生になった時に応用情報に合格したのですが、実務経験が無く自分の力がどれほどか試してみたかったのでのでITベンチャーで半年ほどフロントエンド、バックエンドでインターンに参加してOCRアプリの開発やシステムの運用などで修行していました。その後DMMさんの新卒採用で内定を頂きました。
有難いことに他の企業さんからも内定を頂いていたのですが
- 充実した研修
- 自分が中学生の頃から現在も使っているサービスに関われる
- 働き方

がとても自分に合っていると思ったので内定を承諾しました。

現在は内定者アルバイトとして週3で不正対策チームで働きながら、週2で学校の授業や卒業研究（神奈川県警関連）などをしています。

###  趣味

ガソリンスタンドで働いていたこともあって16歳で二輪免許を取得してから現在までバイクが大好きです（もちろん四輪も大好きです笑）
休日や暇な時はバイクで峠を走って道の駅でタバコ吸ってリフレッシュしたり、バイクの簡単な整備や洗車をしています（タバコの煙と排ガス吸ってリフレッシュって不健康すぎて意味がわかりませんが笑笑）

バイクや車以外だと音楽鑑賞が好きなのでいつもL'Arc〜en〜Ciel、GLAY、Xを聴いてます

<h1>SQLインジェクションについて

少し自己紹介が長くなりましたが、SQLインジェクションについて簡単に説明していこうと思います
SQLインジェクションとはWikipediaの説明だと
「アプリケーションのセキュリティ上の不備を意図的に利用し、アプリケーションが想定しないSQL文を実行させることにより、データベースシステムを不正に操作する攻撃方法のこと。また、その攻撃を可能とする脆弱性のことである。」
と書いてありますがこれだけだと意味不明に感じる方もいると思うので
- データベースとは
- SQLとは
- この脆弱性があったときの影響

の三つに分けて説明します

<h4>データベースとは

データベースとはECサイトなどを例に挙げると商品に関する情報、購入者のクレジットカード情報、購入者の個人情報など様々な情報が格納されているシステムになります

<h4>SQLとは

先程説明したデータベースで例えば商品Aの情報が欲しいという時にデータベースに対してある指示を出すことになります。
ここで使われるのがSQLというもので、SQLはデータベースを操作するための言語のようなものです。
先程の商品Aの情報が欲しい時にはこのような指示を出します　

SELECT * FROM テーブル名 WHERE テーブルの列名 = '商品A';

<h4>SQLインジェクションの脆弱性があったときの影響とは

SQLインジェクションがあった場合、特定のSQL文を入力することで本来管理者しか見ることのできない情報など取得することができます。そのためこの攻撃で個人情報やクレジットカード情報などを取得されてしまうと10年前にあったPSNのようにサービスを停止しなくてはならなかったり、漏れたクレジットカード情報から不正購入が行われてしまったりと多方面で影響を受けることになります

<h1>最後に

今回は自己紹介と簡単なSQLインジェクションの影響や仕組みについて説明しましたが今後何か書くことがあればもっと深く説明していきたいと思っています




<h1>引用元

https://ja.wikipedia.org/wiki/SQL%E3%82%A4%E3%83%B3%E3%82%B8%E3%82%A7%E3%82%AF%E3%82%B7%E3%83%A7%E3%83%B3

https://ja.wikipedia.org/wiki/PlayStation_Network%E5%80%8B%E4%BA%BA%E6%83%85%E5%A0%B1%E6%B5%81%E5%87%BA%E4%BA%8B%E4%BB%B6
パスワードを忘れたKVM仮想マシンにレスキューモードで入る

仮想ホストであれば、isoファイルをマウントしてレスキューモードに入っていく事ができるが、仮想マシン(KVM)の場合はvirt-rescueを実行する事で確認する事ができる。

# 実行環境
ホスト型の仮想化環境で、KVMで構築している状態である。
- ゲスト＆ホストのOS：Linux CentOs8Stream
- ハイパバイザー：KVM 1.2.8
![スクリーンショット 2022-12-07 21.46.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1288524/37686193-dd6a-9e7a-9c39-36cb19d2f53e.png)


# ツールのインストール
virtでのレスキューモードで実行できるようにするには、仮想ホスト上で以下をインストールする必要がある。 以下コマンドを、仮想ホストにて実行する。
```
sudo yum install libguestfs-tools
```
ゲストをシャットダウンする。
```
sudo virsh shutdown ゲスト名
```

# Virt-rescueでゲストを起動

以下のコマンドを実行する。この時、ゲストはシャットダウンされている事。
```
sudo virt-rescue ゲスト名
```
すると、いくつか表示が出た後、プロンプトが以下のように変化する。
```
 ><rescue> 
```


# パスワードとユーザを作る
一般ユーザがないという時に、レスキューモードから入ってパスワードを変更する&ユーザを追加する手順を記載する。

まずは、どのディスクが `/`で使われていそうか、以下コマンドを使って確認する。
```
fdisk -l
```
今回であれば、/dev/sda3が使われていそう。
```
><rescue> fdisk -l
Device      Start      End   Sectors  Size Type
/dev/sda1 2048       206847   204800  100M EFI System
/dev/sda2 206848   10692607 10485760    5G Linux filesystem
/dev/sda3 10692608 41940991 31248384 14.9G Linux filesystem
```
sda3を、/sysrootにマウントする。

以下コマンドでマウント
```
mount /dev/sda3 /sysroot/
```
以下コマンドを実行し、root以下のフォルダが見れればOK.
```
 ls -l /sysroot
```
## root環境に入る
まずはchrootコマンドで権限を変更してから、新たにユーザーとパスワードを作成する。
この時、passwdコマンドで、rootのパスワードを新たに作成する。

```
><rescue> cd /sysroot
><rescue> chroot /sysroot
><rescue> passwd root
Changing password for user root.
New password:
```
次に、新しく一般ユーザを作成する。
また、passwordも設定する。
```
><rescue>useradd -m user
><rescue>passwd user
```

アンマウントし、さらに`exit`でレスキューモードから抜ける。
```
><rescue>umount /dev/sda3
><rescue> exit
```
# ゲストにログイン
仮想ホスト上で、以下のコマンドを実行する。
```
sudo virsh start ゲスト名
```
そしてログイン
```
sudo virsh console ゲスト名
```
コンソールが起動するので、先ほど作ったuserとパスワードでログインする。

# 所感
ゲストのパスワードがわからなくても、ホストにルート権限でログインする事ができればこのように新たに
権限を追加して中に入る事ができてしまう。コンソールにつなぐ事ができるというのはそれだけ注意しなければいけない事だ。


# 参考サイト
https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/6/html/virtualization_administration_guide/sect-guide-guest_disks_libguestfs-installation

https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/7/html/virtualization_deployment_and_administration_guide/sect-guest_virtual_machine_disk_access_with_offline_tools-virt_rescue_the_rescue_shell
Jupyter Notebookのインストールと基本的な使い方について

# はじめに
今までPythonを使うときはVScodeやGoogle Colabを使っていたのですが、[とあるチュートリアル](https://neo4j.com/developer/graph-data-science/applied-graph-embeddings/)を進めていく上で、Jupyter Notebookのインストールを推奨されたため備忘録としてJupyter Notebookの基本的なことについて記事にしようと思います。

この記事がどなたかのお役に立つ日が来れば嬉しいです😆
※初学者なりに理解した内容ですので温かい目で見守ってください。

# 目次
- Jupyter Notebookについて
    - Jupyter Notebookとは
    - Jupyter Notebookを使うメリット
- インストールしていく
    - 環境
    - ターミナルにて
    - 起動
- 基本的な使い方
    - ブラウザが起動してから
    - 新規作成
    - 試しに簡単なコードを入力してみる
- まとめ

# Jupyter Notebookについて
## Jupyter Notebookとは
**Jupyter Notebook**はプログラムの作成や共有をすることができるOSS(オープンソースソフトウェア)のwebアプリケーションです。
[Jupyterプロジェクト](https://jupyter.org/)が提供するサービスの１つです。
## Jupyter Notebookを使うメリット
- 複数の言語がサポートされている。
- 他の人と簡単に共有ができる。
- セル単位で実行ができる。←Google Colabに似てるな〜って思いました。
- コードや実行結果などをHTML形式で保存できる。
- オフラインでも実行できる。
- 無償！！！🙌

# インストールしていく
Jupyter Notebookのインストールはには主に２つの方法があります。
- Anacondaをインストールする。(Jupyter Notebookが含まれている)
- Jupyter Notebookのみをインストールする。

今回はJupyter Notebookのみをインストールしていきます。
## 環境
MacOS Monterey ver.12.6
Python3を使ってます。
## ターミナルにて
pipを使ってJupyter Notebookをインストールしていきます。

まずターミナルを開き、pipコマンドが使えるように以下のコマンドを入力します。
```shell-session
$ python3 -m pip install --upgrade pip
```
次に以下のコマンドを入力します。
```shell-session
$ python3 -m pip install jupyter
```
これでインストールは完了です！
## 起動
さっそくJupyter Notebookを起動していきます。
ターミナルで以下を入力します。
```shell-session
$ jupyter notebook
```
この時サーバーが立ち上がっています。
その後、ブラウザが起動してJupyter Notebookで作業できるようになります。


# 基本的な使い方
## ブラウザが起動してから
起動すると次のようなブラウザの画面が開きます。
![pic01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2340557/8442a5fd-3e80-29ed-0084-ca43b60ff278.png)

## 新規作成
(作業用に新しいフォルダを作った方が整理しやすいかも・・・？)
作業用のフォルダを作ります。

右側の「New」のプルダウンメニューから「Folder」を選択すると新しいフォルダが作成される。
![pic02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2340557/a3402e9d-ebd5-f589-be33-776ac6b4ba97.png)

そのままだとフォルダ名がUntitled Folderのままになるので
フォルダの横のチェックボックスを選択して「Rename」を押下し変更する。
![pic03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2340557/0a0d23e4-e359-2f02-59d5-e83e987fd802.png)
名前を変更したら、フォルダをクリックして新規フォルダの階層に入り
![pic04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2340557/88b6a142-66d3-6252-a512-06543a2ec02b.png)
右側の「New」のプルダウンメニューから「Python3」を選択する。
これでプログラムを書く準備が整いました。

## 試しに簡単なコードを入力してみる🍎
右側の「New」のプルダウンメニューから「Python3」を選択した後、以下のような新しいタブが開きます。
![pic05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2340557/65f65e4e-13c7-cb65-7574-1409705cff70.png)
緑色の枠で囲まれたところ(セル)にコードを入力します。
試しにめちゃくちゃ簡単なコードを書いてみます。
![pic06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2340557/9a11d29d-28bd-9231-3bda-cb85aa7a63ae.png)
上部にあるアイコンの中の「Run」を押下して実行します。
![pic07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2340557/c49a74bf-1811-08c3-449e-99521508a93a.png)
実行するとコードを入力したセルの下に実行結果が表示されます。

簡単な計算も入力して実行してみます。
![pic08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2340557/0a4e5035-0ea0-af5f-9cce-a3035f23fd7d.png)
こんな感じです！



# まとめ
最後まで読んでいただきありがとうございます。
Jupyter Notebookをインストールして少し触ってみた感想は、Google Colabに似ているようで似てない感じで使いやすいな〜と思いました。これから、使い方の応用だったりコマンドだったりをもっと詳しく学んでいって使いこなせるようになりたいと思います。
[Vite] index.html に環境変数を書き出す

この記事は [ZOZO Advent Calendar 2022](https://qiita.com/advent-calendar/2022/zozo) #6 11日目の記事です。

12月もそろそろ折り返し、営業日換算では今年もあと10営業日で終わりという方もおられるかと思われる今日この頃、いかがお過ごしでしょうか。

今回は、フロントエンド用ビルドツール「Vite」の環境で、index.html に環境変数を書き出す方法をお伝えします。

# Vite とは
[Vite](https://ja.vitejs.dev/guide/) は、Vue.js の開発者 Evan You 氏により2020年に開発された、フロンドエンド用のビルドツールです。
Go 言語ベースで開発された esbuild を使用しており、従来の JavaScript ベースのビルドツールに比べ**めっちゃ早く**ビルドが行えます。
これにより、ローカルサーバーの立ち上げもあっという間に終わるので、気軽にローカルサーバーの再起動が行えます。

JSフレームワークやライブラリの導入も楽に行えます。
開発者が同じ Vue.js はもとより React（+ TypeScript） も、Vite プロジェクト作成時に設問に答える形でカンタンに環境の構築が行えます。

そんなお手軽＆爆速な Vite ですが、index.html に環境変数を書き出すには、2022/12 現在ちょっと一手間が要ります。

# 環境変数の書き出し
Vite にも環境変数を書き出す仕組み（e.g. `import.meta.env.ENV_VAR_NAME`）はありますが、index.html においては、その仕組みが使えません。

```.env
VITE_SAMPLE = 'サンプルだよ'
```

:::note warn
Vite では環境変数名に `VITE_` をプリフィックスとして付ける必要があります。
:::

```index.html
...
<title>import.meta.env.VITE_SAMPLE</title>
...
```
このように index.html に記述しても変数の中身は書き出されず、 `<script>` タグ内で記述しても参照できずにエラーとなります


## index.html への環境変数の書き出し
方法としては、Vite のコンフィグにて [transformIndexHtml](https://ja.vitejs.dev/guide/api-plugin.html#transformindexhtml) フックを利用したプラグインを作成して対応します。
具体的には、作成したプラグインによって特定の文字列を対応した環境変数に置換します。

### 置換用プラグインの作成

今回は、EJS チックに `%=環境変数名%` という文字列を index.html に記述した際に、対応した環境変数の値に置換して書き出す設定を行います。
（< > を付けるとタグと認識されるため、付けずに `%=...%` とします）

```index.html
...
<title>%=VITE_SAMPLE%</title>
...
```

Vite のコンフィグファイルを下記のように記述します。

```vite.config.ts
import { defineConfig, loadEnv } from 'vite';

// https://vitejs.dev/config/
export default ({ mode }) => {
  const env = loadEnv(mode, process.cwd());

  const htmlPlugin = () => ({
    name: 'html-transform',
    transformIndexHtml: (html: string): string =>
      html.replace(/%=(.*?)%/g, (match, p1) => env[p1] ?? match),
  });

  return defineConfig({
    plugins: [
      htmlPlugin(),
    ],
    server: {
      host: true,
    },
  });
};
```

`htmlPlugin` というプラグインを作成し、 `plugins` に設定しています。
（`plugins` には使用するライブラリも適宜設定してください）

以上で設定は完了です。

これにより、`loadEnv(mode, process.cwd());` によって環境変数がキーバリューの形で格納された定数に対し、`%=(.*?)%` でマッチした文字列をキーとして参照し、対応した値で該当箇所を置換します。
（対応した環境変数がなければ、マッチした文字列をそのまま書き出します）

# 余談

コンフィグ内に記述した環境変数を取り出す箇所を以下のようにすると、ビルド時に、参照している環境変数を列挙してログに表示することができるので「こんな値を参照しているんだ〜」というのが分かります。

```vite.config.ts
  const env = { ...process.env, ...loadEnv(mode, process.cwd()) };
  console.log({ env });
```

以上
【Android】Android StudioのPullRequest機能が便利すぎるので絶対使った方がいい【IDE】

この記事はand factory.inc Advent Calendar 2022 8日目の記事です。
昨日は　@ichikawa7ss さんの [【SwiftUI】明示的アニメーションと暗黙的アニメーションを理解して使い分けよう](https://qiita.com/ichikawa7ss/items/164a2dfd3c3ab2b1eae8)でした。

# はじめに

いつのバージョンからかわからないけれど、AndroidStudioのPullRequestのタブが追加されてた。(元からあった？？)
全然気にしないでいたけど、いざ使ってみたらブラウザとAndroidStudioを行き来しなくてよくなってめちゃくちゃ便利だったので、使い方を紹介するよ。

# 使い方

## 事前準備

まずはAndroidStudioでサインインする。
右上のアカウントのボタンを押して、Googleアカウントで認証を行うとサインインできる。

![スクリーンショット 2022-10-04 16.46.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/474683/405fbe93-4389-b2b5-16cd-f59442377064.png)

事前準備はこれだけ。

## 画面の見方

何もいじってなければ左にPullRequestのタブがあると思う。

![スクリーンショット 2022-10-04 16.56.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/474683/041e0114-1632-0d79-2551-5f51c44dfebc.png)

`state:open`が検索BOXに入っていて、オープンのPRがここにずらっと並ぶ。

## PRを作る

+ボタンでPRを作ることができる。
押した後の画面はこんな感じ。

![スクリーンショット 2022-10-04 16.59.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/474683/8f041106-f1ca-87e2-c619-bdd38680cbed.png)

1: baseブランチやPRを作りたいブランチを変更できる。
2: PRのタイトルや内容を編集できる。テンプレートもちゃんと反映される。
3: レビュワー、アサインなどを編集できる。

終わったらCreate Pull Requestで作れる。

## PRを見る

見る時は、リストに並んでるとこの▶︎ボタンから詳細を見れる。

![スクリーンショット 2022-10-04 17.11.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/474683/45c403fd-84f2-e3f1-3e2d-4bb3634c7710.png)

詳細を開くとこんな感じ。

![スクリーンショット 2022-10-04 17.12.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/474683/2b388c3f-319e-cdd3-2a33-c31ec063d823.png)

InfoタブではPRの内容や会話を見れる。
Filesタブでは変更があったファイルの一覧を見れる。
Commitsではコミットごとの変更を見ることができる。

レビューをSubmitするときは、FilesタブかCommitsタブからできる。

だいたいこんな感じ。

# まとめ

- GitHubのPullRequestでやれることは、だいたいAndroidStudioのPullRequestタブでできる。
- こっちでやると、ブラウザとAndroidStudioを行き来しなくても良くなるのでPR作業周りの煩わしさがなくなる。
- たまにこういう便利機能追加されてるから、AndroidStudio更新時のNewsは見とくといいね。

おわり。
Domain Modeling Made Functional から学ぶドメイン駆動開発

こちらは「[Applibot Advent Calendar 2022](https://qiita.com/advent-calendar/2022/applibot)」9日目の記事になります。

# Domain Modeling Made Functional から学ぶドメイン駆動開発

個人的に関数型言語を使って開発している者です。
Domain Modeling Made Functional を読んでドメイン駆動開発(以下、DDD)に対する考え方が少し変わりました。本書はF#を使って関数型言語でDDDを実現するための手法を説いた本ですが、それだけでなくDDDに対する一般的な考え方についても解説しており、関数型言語向けの内容の中にもオブジェクト指向で参考になるものがありました。
この記事では、本書中からオブジェクト指向でも通用するような内容をいくつか紹介します。

## 問題を理解することは、安易に解決策を作ることでは無い

上流工程から"要求"が下りてきた時、エンジニアとしてまず何を作りますか？
ER図？それではデータ駆動開発です。ドメイン駆動開発ではありません。
クラス図？それではクラス駆動開発です。ドメイン駆動開発ではありません。

データベース定義やクラスは「実装方法」であり、要求に対する**解決策**として機能します。
しかし、実装前する前にまずやるべきことは**要求を完全に整理**することです。初期フェーズで実装方法を考え始めると、データ設計やクラス設計といった**技術的な偏見**が要求に紛れ込んでしまい、本質的に必要なものを見失ってしまうかもしれません。

本書では、**技術的な偏見のない形で**要件を整理することから始めています。データベースでもクラスでもなく**ロジック**、つまり「何がしたいか」「何をするべきか」に注目し、要件に対してどのようなロジックが必要か、その入出力は何かを考えます。本書ではその入出力をデータ記述用のミニ言語で記述することから始めています。
システムにおける主役は**ロジック**であり、データ定義はその入出力から自然に求められるはずです。本書は関数型言語による設計を前提にしているためクラス設計指南はありませんが、クラス設計も同じように自然と決められるでしょう。

## レイヤードアーキテクチャの問題

多くの開発現場では、下図のように各レイヤーが内側のレイヤーに依存する「レイヤードアーキテクチャ(左図)」を採用していると思います。本書では**レイヤードアーキテクチャには問題がある**とバッサリ切り捨てています。その理由は、一連の処理を修正しようとした時に複数レイヤーのコードを書き換える必要があるからです。これを解消するには、レイヤーではなく**処理の流れ**でコードを分割する(右図)ほうが適切です。
![アーキテクチャの比較](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2357196/61f6b437-0e62-ed11-9acd-6bffe121fe11.png)
また、このような実装をシーケンス図で表すと、次のようになります。
![レイヤードアーキテクチャのシーケンス](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2357196/35547fbc-243c-621b-da29-b27460e00dbd.png)
関数指向プログラミングでは、ロジックから副作用を排除して可能な限り**純粋関数にするのが良いコード**とされています。この観点で言うと、上記のパイプラインはデータベース処理が一番内側にあるためどのロジックからも副作用を排除することができず**よくないコード**であると言えます。これを解消するには、次の図のようにパイプラインを書き換えます。
(前提として、API Logic はリクエストのデシリアライズ・レスポンスのシリアライズだけをしているものとしています)
![平坦化されたロジック](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2357196/d0ef9cb3-0dd7-a3b4-5e7c-8c2bd05647ba.png)

* I/Oなどの**副作用を伴う処理をパイプラインの端のほうに追いやり**、データはドメイン内で取得するのではなくドメインに引数として渡し、戻り値として返されるようにします。
* 真に依存している部分を除いて、ロジックが別のロジックを呼び出すのをやめ、**可能な限り引数や戻り値でやりとり**します。
  * (ここで想定している設計では)サービスはドメインに真に依存するため、サービス内でドメインを呼び出します。
  * サービスとAPI・データベースは相互に依存しません。サービスに必要なのはデシリアライズされたリクエストや取得したデータだけなので、これらは引数として渡します。結果保存やレスポンスについてはこの逆で、サービスから戻り値として返します。

このパイプラインでは、ドメインやサービスを純粋関数にすることができます。
突然現れた**グレーの層**が気になるかもしれません。この層がやっていることは**前の関数の戻り値を次の関数の引数に渡している**だけです。これは関数型言語ならほとんど「関数の合成」で実現できるため、本質的には存在しません。オブジェクト指向においても順番に関数を実行するだけの関数として実装できます(Mediatorパターンと似たようなものだと考えてください)。

---

このような構成は関数型言語にフィットするものですが、オブジェクト指向でも導入するモチベーションがあります。それは**テストが簡単になる**ことです。
レイヤードアーキテクチャにおける各レイヤーは内側のレイヤーに常に依存します。依存関係があるとテストの際にモック化が必要になりますが、**モック化は面倒な作業**であり、テストを書く~~モチベーションの低下や~~コストの増加につながります。
これに対して純粋関数はその入出力にのみ依存するため、テストは単純に引数を変えながら実行して戻り値をチェックするだけで済みます。**モック化は一切必要ありません**。

## まとめ

DDDを関数型言語で実装するという発想はあまりないものですが、本書を読むと決して実現しにくいものではなく、むしろDDDは関数型のほうが実現しやすいのではないかとさえ思えるようになります。実際の現場で関数型言語を導入するのは敷居が高いかもしれませんが、ここで紹介したような関数型の考え方を導入して管理しやすいコードを目指していきましょう。

純粋関数はいいぞ。

以上、「[Applibot Advent Calendar 2022](https://qiita.com/advent-calendar/2022/applibot)」 9日目の記事でした。
CCNA勉強後にPacketTracerいじっててうおお！ってなったこと（随時更新）

メモ程度に書いてます
・L2でVLAN間ルーティングをする際に送信元でICMPを破棄する理由→宛先に送信する前にARPをブロードキャストするが送信元のVLANには該当の宛先がないため破棄された
・PCはスイッチのMACアドレスを学習しないの？（arp -aで確認するとルータのMACアドレスしか出てこなかった）
・イーサタイプ→上位プロトコルを指定するのにARPとIPが選択できるのが不思議
・スイッチのarpテーブルが空→ネットワーク層で動作するのでL2スイッチではarpコマンドの結果が空？（推測）
・VLAN間通信をする際に経由するスイッチ全てにVLANを作成する必要がある