OmniAICreator/Qiita-1.07M huggingface dataset:
コンテナデザインパターン

# 背景
KubernetesのPodには、マルチコンテナの構成で、`サイドカーパターン`・`アンバサダーパターン`・`アダプターパターン`というコンテナデザインパターンが存在します。ただ、それぞれ具体的にどのような構成のことを指すのか、うまく言語化できない状態だったので、調べてまとめることにしました。

# コンテナデザインパターンとは
前述した通り、コンテナデザインパターンには3種類あります。それぞれについて、図を用いて解説します。
解説には、[Design patterns for container-based distributed systems](https://www.usenix.org/system/files/conference/hotcloud16/hotcloud16_burns.pdf)を参考にしています。

## サイドカーパターン
サイドカーパターンは、メインのコンテナと、**補助的な機能を提供するコンテナ**で構成されます。
補助的な機能とは、以下の図のような、ログファイルを転送するコンテナ、Gitリポジトリの更新をローカルのストレージに反映するコンテナ、などが該当します。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/112715/1ba368ee-f78e-ef26-5206-c7bc17fb01de.png" width="100%">
サイドカーパターンのメリットはいくつかあります。

- メインコンテナには優先的にCPUを割り当て、低レイテンシで応答させることができる
- コンテナはパッケージングの単位なので、コンテナに分けることで、2つのチームに開発の責任を簡単に分担することができ、独立してテストできる
- コンテナは再利用でき、サイドカーコンテナは複数の異なるメインコンテナと組み合わせることができる
- コンテナは障害を封じ込める境界線を提供し、障害がシステム全体に波及することを防ぐことができる
- コンテナはデプロイの単位であり、各機能をアップグレードしたり、必要に応じてロールバックすることができる

これら5つのメリットは、後述する他のコンテナデザインパターンにも当てはまります。

## アンバサダーパターン
アンバサダーパターンは、メインのコンテナと、**外部システムとの接続を中継するコンテナ**で構成されます。
例えば、データベースや、S3やGCPなどのオブジェクトストレージと接続するアプリケーションがあるとします。
アンバサダーパターンを用いることなく実装した場合は、接続先の情報を環境変数に設定するなどして、アプリケーションのコンテナから直接接続することが一般的だと思いますが、これではアプリケーションと外部システムの結合度が強くなってしまいます。
しかし、アンバサダーパターンを用いると、その結合度を下げることができます。外部システムと接続するのはアンバサダーコンテナに任せ、アプリケーションのコンテナは`localhost`を指定して、アンバサダーコンテナに接続します。これにより、**アプリケーションは環境による差異を考慮する必要がなくなります。**

以下の図は、アンバサダーパターンの例です。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/112715/f0526b37-671a-25ab-efcd-236d73746915.png" width="100%">


## アダプターパターン
アダプターパターンは、メインのコンテナと、**外部システムからの接続を中継するコンテナ**で構成されます。
以下の図のような、レガシーアプリケーションを含む複数のアプリケーションのPodに対して、統一されたインターフェースを提供できます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/112715/869ae608-89b9-8965-60ef-d548cc1672a7.png" width="60%">

# まとめ
これらのコンテナデザインパターンは、補助的な機能を、組み込み式ではなくコンテナとして提供したり、外部システムとの結合度を下げるために考えられた設計です。アプリケーション開発者とKubernetes管理者の責任の所在が明確になりますし、それぞれがその領域に集中できるので、メリットは大きいと思います。すでにKubernetesを導入している方、または今後導入を検討している方は、開発者と管理者で連携して、これらのコンテナデザインパターンの導入も合わせて検討してみてはいかがでしょうか。

# 参考
- [Design patterns for container-based distributed systems](https://www.usenix.org/system/files/conference/hotcloud16/hotcloud16_burns.pdf)
micro:bitから簡単にmp3再生できるカスタムブロックと接続ケーブルを作った

micro:bitで音は比較的簡単に鳴らせますがmp3などの音楽を再生させるのは簡単にできません。
それを簡単にするためのカスタムブロックとデバイスを作りました。

ケーブルはワニ口クリップを改造してPHコネクタをつけたもの。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58795/71e1853f-217a-b95e-dc40-ba5d438cb7e1.png)

DFR0534というメモリ内蔵の音声プレイヤーに接続できるようになっていて、これはモノラルですがSDカードなども必要なくシリアル通信で制御ができるものです。
https://akizukidenshi.com/catalog/g/gM-13708/
他にもよくあるものでDF Player miniなど安価なものはありますが、SDカード代が結構高くつくので個人的には全部コミコミでこの値段なのでこちらの方がおすすめです。ただしボタン操作などの端子がないのでそういう操作を考えてるならおすすめはできません。

スピーカー部分もワニ口クリップにしたのでイヤホンやスピーカーともよくあるV1.5でのmicro:bitで音を出す時と同様に接続することができます。

動作させたのはこちら。
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">コードの作りが悪くてレスポンスが遅かっただけでした。効果音に使える感じ。V2対応もしたので指パッチンでもMP3が鳴ります！ <a href="https://t.co/Krms7byKgH">pic.twitter.com/Krms7byKgH</a></p>&mdash; wakasa masao (@wks) <a href="https://twitter.com/wks/status/1339791763716784128?ref_src=twsrc%5Etfw">December 18, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


カスタムブロックは以下を参照して雛形ベースにして作りました。
https://qiita.com/wakasamasao/items/eedf7f8d6308e828986a

コードはDFPlayer miniを操作できるブロックをベースに改造しました。
https://github.com/51bit/dfplayermini

とりあえず、曲番号指定で音楽が流れてVolumeが操作できればよいかなとそれだけしか書いてません。
コマンド自体は以下のサイトを参照にしています。
https://wiki.dfrobot.com/Voice_Module_SKU__DFR0534

コメントに書かれたものがブロック名になったりするので、そのあたりはいい感じに書いておいたほうが良いです。

```
//% weight=100 color=#0fbc11 icon=""
namespace dfr0534 {
    let isConnected: boolean = false;

    function sendData(dataArr:number[]): void {
        let myBuf = pins.createBuffer(10);
        for (let i = 0; i < 10; i++) {
            myBuf.setNumber(NumberFormat.UInt8BE, i, dataArr[i])
        }
        serial.writeBuffer(myBuf)
        basic.pause(100)
    }

    /**
     * Connect DFR0534
     * @param pinRX RX Pin, eg: SerialPin.P2
     * @param pinTX TX Pin, eg: SerialPin.P1
     */
    //% blockId="DFR0534_connect" block="connect to DFR0534, RX:%pinRX|TX:%pinTX"
    //% weight=100 blockGap=20
    export function connect(pinRX: SerialPin = SerialPin.P2, pinTX: SerialPin = SerialPin.P1): void {
        serial.redirect(pinRX, pinTX, BaudRate.BaudRate9600)
        isConnected = true
        basic.pause(100)
    }

    /**
     * Specified Audio 
     * @param track Track Number, eg: 1
     */
    //% blockId="DFR0534_specifiedAudio" block="Specified Audio Play(1~255):%track"
    //% weight=99 blockGap=20 track.min=1 track.max=255
    export function specifiedAudio(track: number): void {
        if(track<1) track=1
        if(track>255) track=255
        sendData([0xAA,0x07,0x02,0x00,track,track+0xB3])
    }


    /**
     * Set Volume
     * @param volume Volume, eg: 10
     */
    //% blockId="DFR0534_volume" block="set volume(0~30):%volume"
    //% weight=98 blockGap=20 volume.min=0 volume.max=30
    export function volume(volume: number): void {
        if(volume<0) volume=0
        if(volume>30) volume=30
        sendData([0xAA,0x13,0x01,volume,volume+0xBE])
    }
}
```

実際に作ったコードはこちらを参考に。
https://makecode.microbit.org/_HgF0rKD6j9Ta

これで簡単にmp3が再生できる環境が整ったのでいろいろ遊べると思います。
特にブロック言語で作れるようにしたので、Radioで飛ばしたりいろんなデバイスと連携したりが容易になります。
地方在住者がデータサイエンス案件へ参画するまでに1年間で実践したこと


# はじめに
皆さんはじめまして、フリーランスエンジニアの毛利です。

本記事は、「データ分析人材のキャリア（データラーニングギルド） Advent Calendar 2020」の18日目となります。

私は、フリーランスの立場でSIer業界でアプリケーション開発をしつつ、1年間データサイエンス案件への参画を目指して活動してきました。
その結果、来年1月からギルドコミュニティを通じて、データ分析基盤の構築案件へ参画することが決まりました！

ここでは、私の1年間の経験を踏まえ、
* 地方でデータサイエンス案件に参画する難しさ
* 活動する上で良かった点と失敗した点
を整理しました。

私自身フリーランスの立場で活動しているので、そこを軸にお伝えしますが、
サラリーマンのキャリア戦略としても転用可能かと思います。

# 案件参画までの流れを理解する
地方でデータサイエンス案件に参画する難しさを考える上で、
フリーランスエンジニアが新規案件に参画するまでの流れを理解しておく必要があります。

大まかには、このような流れになります。

①　自分が参画したい案件を探す
②　案件に応募する
③　一定のスキルがあることを評価される
④　案件の参画が決定する

案件への参画角度を上げるには、

* 参画したい案件数を増やす
* スキルが評価される
のいずれかが重要となります。

特に私のようにデータサイエンス案件の実務経験がない場合、フリーランスの立場として、案件参画角度が下がってしまいます。このため案件数を増やす必要があります。

# 地方でデータサイエンス系案件に新規参画する難しさ
データサイエンスの案件数として、他の開発案件と同様に首都圏に集中する傾向があります。
このため、肌感としては、地方都市で首都圏の10%前後、地方に行けばさらに少ないという感覚です。

選択肢を増やすためにも可能であれば上京を検討するのが良いかと思います。

ただ、私のように地方にいながら案件を探したい、という方にとっても、
上記の考え方を理解しておくと、選択できる案件が少しでも増えるのでオススメです！

# 2020年に実践したこと
## 独学でデータサイエンスを学ぶ(1〜3月)
まずは書籍やWEBの情報をベースに機械学習などを学習しました。Udemyで有名な講座もひと通り受講し、Kaggleなどにもチャレンジしました。
ただ、当時は抽象度の高い問題に対して、自分で解決する力が身についていない点に課題を抱え、チュートリアルを終えて終了という状況でした。

## オンラインスクール(データラーニングスクール)・データラーニングギルドへの参加(4月〜6月)
この課題を解決するため、[データラーニングスクール](https://guild.data-learning.com/school-term-4)を受講することにしました。3ヶ月に渡りデータサイエンスで必要とされる知識を網羅的に学習しました。

併せて、データラーニングギルドと呼ばれるオンラインコミュニティに参加することで、自分が目指す環境へ進むための方法を相談にのっていただくなど、非常に濃い経験が積めました。

## 機械学習モデルを利用したWEBアプリケーション実装(7月〜8月)
YouTubeに公開されていた[【4時間でPython AIアプリ開発】Python Django scikit learnでAIアプリを開発](https://youtu.be/_87RY9rb79I) という動画を元に、機械学習モデルを利用したアプリケーションの学習を進めました。

## ポートフォリオ作成(9月以降)
この知識を活かし、WEBアプリケーション+機械学習+データパイプライン処理のポートフォリオ作成に着手しました。
ただ、機能を盛り込みすぎて工数が跳ね上がった結果、進捗がなかなか進まない状況となりました。

ポートフォリオについては、こちらの記事が非常にわかりやすく整理されているので、オススメです！
[【保存版】データサイエンティスト転職を決めるポートフォリオのガイドライン](https://qiita.com/masso/items/44437b48706483ce9f30)

# まとめ
ポートフォリオを作り切り、関西圏でデータサイエンス案件に参画するのは、かなり難しかったかと思われます。それに比べ、ギルドなでのオンラインコミュニティを通じて案件を探すことができれば、選択肢が増えるため、フリーランス以外の新たな案件獲得の選択だと考えています。
これはサラリーマンとして副業を行う際にもうまく利用できる考え方かと思います。

# さいごに
ここまでお付き合いいただきありがとうございます。

引き続き、2021年は、データエンジニアとして実績を作りつつ、皆さんのキャリア形成に少しでも役立つ情報を提供したいと思います。

ご興味があれば、 [Twitter](https://twitter.com/engineer_takuto)のフォローよろしく思います！
【初学者向け】これであなたもホワイトハッカー

# はじめに
エンジニアの皆さん、そうでない方もこんにちは。私はみなさまよりほんの少しだけセキュリティに明るいエンジニアです。記事を開いていただきありがとうございます。

早速ですがみなさまの関わっているプロジェクトや組織の**情報セキュリティ**は大丈夫でしょうか? 昨今、オリンピックが開催される背景もあり、日本企業は世界中のハッカーから狙われまくっており、情報を抜かれまくっています。日々ニュースをみて大企業のインシデントに怯える毎日ではありませんか? 「偉い人から**ある日突然セキュリティ担当を任された**りして困っていませんか。そんなお困りの方も、セキュリティに困っていない方も、これからセキュリティをやりたい方、そんな皆さん向けの素晴らしい講座を本日ご紹介します。

## 【情報セキュリティ】Ethical Hacking：ホワイトハッカー入門
![スクリーンショット 2020-12-18 0.57.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235988/d0d396b8-af3d-1543-ec03-37ab5f1b2a3e.png)

https://www.udemy.com/course/ethical-hacking-jpn1/

講座紹介より※

>この講座ではホワイトハッカーに必要な基礎知識を身につけ、世界に通用するセキュリティ技術者を育てます。

すごい、この動画を見れば世界に通用するセキュリティ技術者になれるので**世界中からくるハッカーからの攻撃から自社の情報セキュリティを防ぐことができます。** 7.5時間もあるためリモートワークのお供に作業用BGMとしても最適です。昨今、セキュリティエンジニアは憧れの職業の一つであり、「なりたい職業ランキング」では「鬼殺隊、youtuber」を抜いて「セキュリティエンジニア」が1位だそうです。(社内Slack調べ) 





## どういった内容を扱っているのか

この講座では、情報セキュリティとは何か、攻撃とは何か、防御の手段とは何か....と様々な方面からセキュリティを学ぶことができます。

こちらが講座でフォローされる内容です。
(セクションのタイトル抜粋)

* 情報セキュリティとホワイトハッカー
* 情報収集概論
* 偵察技術
* スキャニング技術
* サーバへの攻撃
* DoS攻撃
* Webアプリケーション攻撃
* アクセスの維持
* 痕跡の消去
* ネットワーク盗聴
* マルウェア
* ソーシャルエンジニアリング
...etc

情報セキュリティにお金をかけられない会社様は、情シスの社員を捕まえて1日この講座を受講させれば**社内の情報セキュリティはもう大丈夫です。**高いお金を払って社外のセキュリティコンサルを呼ぶ必要はなくなります。

## どういった知識が身に付くか

幅広な情報セキュリティに関する知識が身につきます。この講座では実際のサイバー攻撃がどのように行われるかを知ることができるので、今まで漠然とアクセスログを見ていた方も「**うーん、これは攻撃!**」と明瞭なジャッジができるようになり、社内からの信頼は鰻登りになることでしょう。また、情報セキュリティに対する幅広な知見が身に付くため、自身のセキュリティスキルのベースを作るのに役立ちます。
![スクリーンショット 2020-12-18 1.06.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235988/0bf04fb6-83a2-2e84-3c07-d86ddf335eb6.png)「**うーん、これは攻撃!**」


事実、私は過去にこの講座を購入してから、100サイト以上の脆弱性診断に従事し、情報安全確保支援士、CEH、CND、SecuriSTなどのつよセキュリティ資格の有資格者となりました。

この講座はセキュリティの資格取得にも役立ちます。講師の阿部ひろき先生はCEH(Certified Ethical Hacker), CND(Certified Network Defender)の教育パートナーとしても活躍している背景もあり、この講座で学べる内容がCEHの講座内容も概ねフォローされているというメリットがあります。この講座の受講後に力試しをしたい、さらなるスキルアップをしたいという方は、[CEH](https://www.gsx.co.jp/academy/ceh.html)の資格取得に臨むのが良いでしょう。ただし、このCEHという資格は受講費用がそれなりに高額のため、ご自身の熱い思いを上司に伝えて、会社に費用負担をしてもらうことを推奨します。熱意を伝えて決裁者にお金を積んでもらうのに非常に参考になるリンクもご紹介しておきます。
[(進研ゼミ)部活も合格も諦めないキミの志望校合格Story](https://chu.benesse.co.jp/comic_rn/index.html?s1=dm&s2=3&s3=5)


## さぁ、始めてみましょう
ここまでご覧になったあなたは、**【情報セキュリティ】Ethical Hacking：ホワイトハッカー入門**を受講したくなったことでしょう。まずは一歩を踏み出してみましょう。鉄は熱い内に打つのが肝心です。この記事を読み、やる気になっているあなたに朗報です。この記事の執筆中、この講座の通常価格¥24,000- が9割引の¥2,400-になっていました。めちゃ安いですね、買っておきましょう。記事の公開中にセールが終了しているかもしれませんが、Udemyはときたま9割引の大セールをしているので、頻繁に覗いてみることを推奨します。
※記事の校正中にもセールが行われていました。

## おわりに
記事をごらんいただきありがとうございました。
よければ少し画面を戻って「LGTM」を押していただけると幸いです。スタバでリモートワークをするためにMacBookが欲しいのです。


※...著作権者の許諾を得て掲載しております。また、講座を提供するBLKSmith.incの講座紹介ページのコンテンツ内容でありUdemyの講座内のスクリーンキャプチャではありません。
macでいきなりはじめるPHPにチャレンジする！(3) mySQL編

#はじめに
前回までの記事ではPHPを始めるにあたっての設定を書いてきました。「いきなりはじめるPHP」の本では初期設定の後、アンケートページを作成し、それをmySQLに保存するというプロセスで進んでいきます。
このうちアンケートページの作成は、本の通りに作れば問題なく動作するのでここでは省きます。

これまでの記事でも書いたように、mySQLの起動、本ではXAMPPを使用していますが、macではMAMPを使用した方が良いとされています。MAMPでは操作方法や、コードなどが一部異なっているので、本の丸写しだとエラーとなってしまったり、また操作方法がわかりにくいことがあります。ここではその辺りの操作の違いを中心に書いていきます。

#mySQLの起動、データベースの作成
mySQLの起動は、MAMPではローカルサーバーの起動と同時に行われます。詳しくは(1)に記載しています。
ローカルサーバーを起動すると、スタートアップ画面が表示されますが、それを下にスクロールするとPHP、MySQL、SQLiteの3つの管理メニューがあります。MySQLをクリックすると画像のような画面になります。
![mysql2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/891157/62f009f5-a716-3cf8-8f30-6b658341fe80.png)
ここからphpMyadminをクリックすると、データベース参照、作成ページに飛ぶことができます。もちろんこれ以外の方法でもデータベースをいじくることはできるそうですが、本ではphpMyadminを使用する方法が書かれているので、それで進めていきます。

phpMyadminについて、操作方法は本と現在ではややレイアウトが異なるものの、ほぼ同じです。
![mysql3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/891157/e737568c-b5b4-af7e-eabf-b5fd466952cf.png)
アクセスするとこんな画面から始まります。Languageで日本語を選ぶと日本語化されるのでより操作しやすいと思います。

![mysql4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/891157/b027c020-92e8-dd71-b049-d11cb14d8914.png)
データベースの作成もこの新規作成をクリックして、名前、照合順序を入れるだけで簡単に作れます。ちなみにmySQLのフォルダーの中に新しく作るのではなく、普通に新規作成をクリックしたらいいそうです、僕はなぜか読み違えて、mySQLのフォルダーの中に丁寧に作っていました・・・
作成したデータベースをクリックするだけで、テーブル、カラムの作成がかんたんにできます。やはりグラフィカルに操作できるのは素晴らしいなと思いました。

#データベースへの接続
データベースへの接続は本に載っているコードだと以下のようになっています。

```php:thanks.php
<?php
$dsn='mysql:dbname=phpkiso;host=localhost';
$user='root';
$password='';
$dbh=new PDO($dsn, $user, $password);
$dbh->query('SET NAMES utf8');

〜（真ん中は省略)〜

$sql = 'INSERT INTO anketo(nickname,email,goiken)VALUES("'.$nickname.'","'.$email.'","'.$goiken.'")';
$stmt = $dbh->prepare($sql);
$stmt->execute();
```

MAMPの場合、このコードだとエラーが出ます。その理由はmySQLのパスワードが空っぽになっていることです。上に貼った1枚目の画像にある通り、passwordは初期だとrootになっているので、それを指定しないといけません。
それに加えて修正すべき点として、文字コードの指定部分です。文字コードはデータベースの文字化けを防ぐため指定する必要がありますが、現在のバージョンのPHPでは脆弱性が発生するのを避けるためSETNAMESを使用しないそうです。
ちなみに$sql=以下の部分は、変更の必要はないそうです。
そこで以下のようなコードに、調べながら変更しました。

```php:thanks.php
<?php
$dsn='mysql:dbname=phpkiso;host=localhost;charset=utf8';
$user='root';
$password='root';
$dbh=new PDO($dsn, $user, $password);
```
このようにpasswordを指定し、また文字コードの指定部分を頭に持ってきました。これでエラーなくMySQLに接続できました！

#MySQLのみ切断する
MAMPでは前述の通り、ローカルサーバーを起動すると自動的にMySQLに接続されてしまいます。なのでサーバーだけを起動させて、MySQLを止めるということができません。これの何が問題かというと、本の中にもデータベースに接続できなかった時の障害発生を示す文章を表示させる方法がありますが、それが実際に表示できるかどうか容易に確認できません。
そこでmySQLのみを切断する方法を調べたところ、ターミナルで以下のコードを入れればいいそうです。

```
/Applications/MAMP/bin/stopMysql.sh
```

みたままMAMPのstopMysqlを作動させるという形のコマンドになっています。これを入れるとMySQLを止めることができるのですが・・・MAMPの最新バージョンだとMySQLの作動ランプがなく、一目で作動が分からなくなっています。なので実際にデータを送信して試すしかないようです。
ちなみに一度サーバーを停止し、改めて起動するとmySQLも起動することができます。

#まとめ
ここまで3つの記事でまとめたように進めると、macおよびMAMPを使用している環境下でも無事にこの本一冊を終えることができました。少しでも参考になれば幸いです！初学者なので間違いなどがあるかもしれません、何かあればご指摘をよろしくお願いいたします。
JavaScript,9,比較演算子,（＝＝＝, ＞, ＜, ＞＝, ＜＝）初心者向け

JS（JavaScript)で比較演算子（＝＝＝, ＞, ＜, ＞＝, ＜＝）などの違いも紹介しています。


2 > 2        （f）
2 >= 2   （２も含んだ数字 true）
2 <= 2      （true）
2 == 2     （true あまり使わない）
2 === 2     （コッチを使う右と左が一緒 true）
2 != 1      （右と左が一緒ではない　true）
2 > 1 && 3 <= 3 （&で繋げるもの全て右と左どちらも正しいか　true）
2 > 1 || 3 <= 3 （||でまたいだものどれか正しいか　true）
【読書録】わかりやすい提案書の３RULE５DESIGN

##この文書について
この本([わかりやすい提案書の３RULE５DESIGN](https://www.amazon.co.jp/%E3%82%8F%E3%81%8B%E3%82%8A%E3%82%84%E3%81%99%E3%81%84%E6%8F%90%E6%A1%88%E6%9B%B8%E3%81%AE-%EF%BC%93RULE-%EF%BC%95DESIGN-%E7%94%9F%E7%95%91%E7%9B%AE-%E6%98%9F%E5%8D%97-ebook/dp/B07MY48RZN))に対する個人の読書メモ

対象読者 : 掲題の書籍について何が書いてあるか知りたい人

##本書を選んだ理由
みなさんは本を選ぶとき何を重視しますか？
わたしは、以下のことを重視して選定しています。
・知りたい内容が要点を絞って、わかりやすく書かれている
・評価が高い・レビューに良い内容が書いている
・デザインが読みやすく、ページ数が少ないほうが良い（多い場合もあるが）

具体的に本書は、
・わかりやすい提案書を書くノウハウ○
・評価☆5(6件とも満点)...すごい！
・デザイン○、ページ40ページ！

はい、完璧ですね！わたしが重視しているポイントすべてを兼ね備えた１冊です。

##本書の特徴
本書は、提案書を作る上での考え方、読み手に取って負担の無いデザインを
ポイントで絞って解説しています。
__・第１章：前提をおさえる__
__・第２章：提案書における３つのルール__
__・第３章：デザインの基本要素とポイント__

##第１章：前提をおさえる
１章では「わかりやすい」とは何か？の説明から始まります。
以下引用文を見てください。

>真のエクセレント・カンパニーを目指して
>今、IT業界は革命の時代に突入しています。
>2000年初頭に起こったパラダイムシフトにより様々なキャズムが取り払われ、各社のコアコンピタンスがコモディティ化された結果、先の見えない不況が我々の駅前に覆いかぶさってきています。
>○○○は自社の強みでもあるファクトペースにおけるブルーオーシャン戦略、いわゆるボトルネックを排除したペネフィット創出事業にフルコミットする事で、安定的な成長を続けています。

専門用語ばかりで言葉の意味を理解するのに時間がかかります。
では、理解できるように専門用語をそのまま変換してみましょう。

>真の超優良企業を目指して
>今、IT業界は革命の時代に突入しています。
>2000年初頭に起こった劇的な革命により様々な障壁が取り払われ、各社の主力事業や能力、価値が一般化した結果、先の見えない不況が我々の眼前に覆いかぶさってきています。
>○○○は自社の強みでもある、事実を見極め未競合市場を開拓する戦略をとり、弱みを排除して価値創出事業に全力で責任をもって取り組むことで、安定的な成長を続けています。

さらにシンプルに書くと、

>真の超優良企業を目指して
><font color="Red">・未競合市場を開拓する戦略を取ります。</font>
><font color="Red">・弱みを排除して価値を創出する事業に取り組みます。</font>
>これらを行うことで安定的な成長を続けています。

「わかりやすく伝える」という目的では、３つ目の文章が最適でしょう。
上記の引用文から以下のことがわかります。
・脳の処理が長時間＝わかりにくい！
・脳の処理が短時間＝わかりやすい！

また、１つ目の文章では「専門用語の変換」と「内容の理解」を脳が同時進行で行い、マルチタスク状態になります。人間の脳は、マルチタスクに向いていません。
その為、提案書の内容も<font color="Red">一貫性を持たせることが大事です！</font>
__「前提」→「目的」→「目標」→「内容」→「デザイン」__

■前提
例えば、
・顧客と自社の関係性は？　・競合サービスを既に利用していないか？
・顧客のニーズは何か？　　・顧客の業界の動向は？　・顧客の予算は？

■目的（○○のために）
例えば、
・サービスの利用価値を実感して購買を決定してもらうために
・担当者に納得してもらい、決定権を持つ上司とのアポのために

■目標（○○をする）
例えば、
・契約書にサインをいただく
・次回商談の日付を確定する

これらの内容を踏まえて提案書のデザインを考える必要があります。

##第２章：提案書における３つのルール
２章では、提案書の内容を考える上で何を押さえるべきか説明しています。
押さえておきたい３つのルールはこれです！
__・「OSOM」の原則__
__・「KISS」の原則__
__・「PYSS」の原則__

###■「OSOM」の原則とは
<font color="Red">One Slide One Message</font>
<font color="Red">(１つのスライドには１つのメッセージを込めろ！)</font>

１つのメッセージに複数の情報を詰め込むと受け手は混乱するので、本原則は__必ず実行しましょう！__

###■「KISS」の原則とは
<font color="Red">Keep It Simple Stupid</font>
<font color="Red">（馬鹿でもわかるシンプルさを保て！）</font>

ご老人や小学生の子供でも分かる言葉を用いて提案書を作りましょう！
__Simple Is The Best!!__の言葉どおりです。

###■「PYSS」の原則とは
<font color="Red">Put Yourself in Someone's Shoes</font>
<font color="Red">（相手の靴を履いて考えなさい）</font>

お客様の立場に立って考えなさいとよく聞くが、その人が身に着けているものや置かれている状況、見えている視界、受けている感情など自分自身がそっくりそのまま相手になったらどうか？という立場で考え、どんな提案が必要か考えることが大事です。

##第３章：デザインの基本要素とポイント
デザインについては、ポイントを箇条書きでまとめます。

・配置を揃えて統一感を持たせる

・シーンに応じた適切な文字を使う

・ゴシック体で14pt以上を使用（おすすめフォントはメイリオ or 游ゴシック）

・配色には3種類を使い分けていく
　→　ベースカラー（基本となる文字の色）・・・全体の60-70%
　→　メインカラー（見出しやボックスに使う色）・・・全体の20-30%
　→　アクセントカラー（強調したい箇所に使う色）・・・全体の5-10%

・強調の仕方にも統一感を。やりすぎには注意！
　→　例えば、見出しには下線。POINTには赤字というルールを全ページに適用することで
　　　読み手が「強調したい箇所」を把握できる。

・間＝余白は読み手に安心感を与え、ストレスフリーの状態を作る

##まとめの一言
”クセ”のないシンプルな提案書を心掛けよう！
たった３行で汚いデスクトップをきれいにしましょう


## ☝ はじめに

Windowsのデスクトップを３行バッチできれいに保ちましょうのエントリーになります

### 👉きれいにするの定義

- デスクトップ直下に「ショートカット以外のファイルを配置するのは良くない」という考え
- ショートカット以外のファイルがある場合、当日日付のフォルダを作成してそこに移動させるただそれだけ

## ☝ はじめましょう！

### 1.以下を保存！

```bat:clean-desktop.bat
set DATE_STR="%date:~0,4%-%date:~5,2%-%date:~8,2%"
mkdir "C:\Users\%username%\Desktop\%DATE_STR%"
ROBOCOPY "C:\Users\%username%\Desktop" "C:\Users\%username%\Desktop\\%DATE_STR%" * /MOV /XF *.lnk
```

### 2.スタートアップ登録

- ファイル名を指定して実行(`Ctrl + Win`)
- `shell:startup`を入力、Enter
    - スタートアップのディレクトリが開くので作成したバッチファイルを配置

### 3.That's All!!

以上になります！

これで、PC起動時に実行日付のフォルダを作成し、ショートカット以外のファイルをそこに移動させてくれるようになりました。

## ☝最後に

もちろん、作成された日付フォルダは定期的にメンテナンスを！
【Rails】起動時・再起動時のエラーを二つのコマンドとプロセス番号で解消する。

##はじめに
Railsをローカル環境内で実行する時に起動にエラーが発生する場合があります。
この場合は、プロセス番号でrailsを停止する事が可能です。
コマンドを二回うつだけでrailsの起動に関する問題を解決できます。

【 control + C 】でrailsを停止しようとしても反応がしない。
ターミナル再起動したけど 【A server is already running.】により起動することができない。
そんな時に新規ターミナルで強制終了することができます。

環境やバージョンにより実行が異なる場合があります。

####実行環境
pc: macOS Catalina
shell: zsh
rails: 6.0.0
ruby: 2.7.2


railsを起動や再起動しようとし、以下のコマンドを実行しエラーになった。

```tarminal
% rails s
=> Booting Puma
=> Rails 6.0.3.4 application starting in development 
=> Run `rails server --help` for more startup options
A server is already running. (省略)
```

こちらはrailsのサーバーを起動した状態で、
「ターミナルを終了してしまった。」や「control + Cで終了し再起動した。けど．．．ダメだ。」
この様なエラーは様々です。

早速コマンドを実行して起動を終了します。
まず以下のコマンドを実行しプロセス番号を取得します。


```tarminal
% lsof -i tcp:3000　 もしくは　　lsof -wni tcp:3000　
　
COMMAND  PID   USER       FD   TYPE                     DEVICE SIZE/OFF NODE NAME
ruby     7361  UserName   12u  IPv6 0x310cb952b8b0dc9d  0t0  TCP localhost:hbci (LISTEN)
ruby     7361  UserName   13u  IPv4 0x310cb952bbe4ce0d  0t0  TCP localhost:hbci (LISTEN)

```

次にプロセス番号（PID）を取得できたら以下のコマンドでrailsの停止をする事ができます。
この場合であれば,7361がプロセス番号です。

```
% kill PID もしくは kill -9 PID
```

以上でrails　sで起動してくれるのではないでしょうか。

###解説
```
lsof -i 
```
lsofは開いているファイルなどを取得するコマンド
-iはやプロセス番号やポート番号を検索し取得するlsofのオプション
-wniは-iと役目は変わりません。

```
lsof -i tcp:3000
```


上記のコマンドでもプロセス番号を取得することは可能なのですが、多くの情報を取得してしまいます。
そうなると探し出すのが大変になるので、local で以下の様にすることで情報を限定するとピンポイントで取得する事ができます。

「ローカル3000で起動しているプロセス番号と使用ファイルの情報を取得」となります。
killコマンドはプロセスにシグナルを送るコマンド

```
kill -9　プロセス番号

もしくは

kill -i プロセス番号
```
−９はオプション・シグナルと呼ばれるます。
以下のコマンドは「起動中のプロセス番号に停止する」となります。


###一言
僕も知識はまだまだです。
何か誤りがあれば訂正いたしますので、
新しい情報もあれば宜しくお願いいたします。
【Rails carrierwave】画像アップロード  未選択状態でもエラー画面に遷移しない方法

# 解決方法
requireではなく、fetchメソッドを使用することで、paramsがnilの場合を許容する。

``` 
private

  def food_record_params
    params.fetch(:food_record, {}).permit(:image)
  end
```

# 使用技術

carrierwaveを使用して、画像アップロード機能を実装。

```
gem 'carrierwave'
```

carrierwaveの使用方法
https://qiita.com/uchida0331/items/f99aba46fd1a6df9e753



# 問題点
画像アップロード画面で、画像未選択の状態で登録ボタンを押下すると、エラー画面に遷移する事象が発生。
![スクリーンショット 2020-12-18 0.28.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/688968/f4ecd723-2e5d-2d4c-aecd-d6a9ee66f18a.png)

![スクリーンショット 2020-12-18 0.26.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/688968/932587d4-0f3c-64d3-5632-a0a98530bdcf.png)

# 原因
エラーログの通り、requireメソッドではparameterに値が入っていないと、エラーになってしまう。
requireは、paramsに値が入っていない場合に、例外を出すためのメソッドだからである。


# 参考資料
ruby2.7リファレンス
https://docs.ruby-lang.org/ja/latest/method/Hash/i/fetch.html
コードで書くGoogleSpreadSheet(VLOOKUP編)

今回はGoogleスプレッドシートの鬼便利関数、
**VLOOKUP**について書いていきます。😏

####`今回すること`

**<みんなのタイムスケジュール>**
<img width="300"alt="sheet1" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407730/bf00d720-2068-e499-500b-8fe967efb5ca.png">

**＜個々のタイムスケジュール＞**
<img width="300"alt="sheet2" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407730/ec14e360-1769-ebc2-7574-801ab550873f.png">
みんなのタイムスケジュールのデーターをとってきて、プルダウンで選択した人（個々）のタイムスケジュールを作成していきます🌞

##準備編

・<a href="https://qiita.com/uizprg/items/bdf1da6667d5e36ac174#%E3%83%97%E3%83%AB%E3%83%80%E3%82%A6%E3%83%B3%E4%BD%9C%E6%88%90">プルダウン作成方法</a>
・**<みんなのタイムスケジュール>**作成

##実践編

######`同じシートから値をとってくる時`

<img width="650"alt="pic1" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407730/9ba29ee9-a75b-f29f-7680-17e9819b93d1.png">

```
=VLOOKUP(G1,C4:D4,2,FALSE)
```

<font color="Crimson">意味：</font>**登壇者[C女]**<font color="MediumBlue"> (G1)</font>を検索、**<みんなのタイムスケジュール>**の**担当**〜**プレゼンする内容**の**列**の範囲から**[C4〜D4]**<font color="MediumBlue">(C4:D4)</font>。そして、C４から左から２列目<font color="MediumBlue">(2)</font>の値を引っ張る。C女以外の値を取らない。**完全一致**の値を引っ張る<font color="MediumBlue">(FALSE)</font>

<font color="DimGray">※**TRUE**に選択した場合、名前の場合支障は少ないが数字の場合、”1.2”の値だけを取ろうとしても、"1"の情報も取ってくる。（近い値も取ってくる）
↑データーのズレが生じる恐れがあるため、基本的に**FLASE**にしておくことを勧めます。</font>

<font color="DimGray">※**TRUE** = 1 , **FALSE**= 0 と置き換えることもできる</font>

****
######`違うシートから値をとってくる時`

<img width="380"alt="pic3" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407730/915a5840-5959-4186-4219-b80e2922e1d3.png">

```
=VLOOKUP(B2,'シート1'!C4:D4,2,FALSE)
```
<font color="Crimson">意味：</font>**登壇者[C女]**<font color="MediumBlue"> (B2)</font>を検索、**<みんなのタイムスケジュール>[シート１]**の**担当**〜**プレゼンする内容**の**列**の範囲から**[C4〜D4]**<font color="MediumBlue">(C4:D4)</font>。そして、C４から左から２列目<font color="MediumBlue">(2)</font>の値を引っ張る。C女以外の値を取らない。**完全一致**の値を引っ張る<font color="MediumBlue">(FALSE)</font>

##オマケ
<img width="300"alt="pic3" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407730/fe777e6d-2948-5ada-7805-2e71604fccc3.png">

値がない時（登壇しない時）、画像のように**#N/A**と表示されないよう、
値がない時はどのような結果を出すべきか指定することをオススメします😁

詳しくはこちら → <a href="https://qiita.com/uizprg/items/bdf1da6667d5e36ac174#%E3%82%AA%E3%83%9E%E3%82%B1iferror">[コードで書くGoogleSpreadSheet（IFS&IFERROR編）]</a>

****
お疲れ様でした😴👏
テスタビリティとメンテナビリティ

---
この記事は[Ateam Hikkoshi samurai Inc.× Ateam Connect Inc. Advent Calendar 2020](https://qiita.com/advent-calendar/2020/hikkoshizamurai-connect) 18日目の記事です。

---

# はじめに
「テストを書きやすいコードは、メンテナンス性に優れる」ということがよく言われます。
日常的にテストを書いておられる方々はその意味をご認識されていると思いますが、テスト初心者の方、テストを書いていこうと思っている方々に向けて、その具体例をご紹介したいと思います。



# テストしにくいコードとメンテしにくいコード

```sample.rb
class Hoge
  # 略
  def puts_by_weekday
    business_day = BusinessDay.new
    if business_day.holiday?
      p "今日は休日！！！！"
    else
      p "今日は仕事"
    end
  end
end
```

上記の例では、曜日によって処理を変えています。
一つのメソッドの中でTimeクラスから曜日を呼び出して条件分岐に使っています。
このような場合、おそらく下記のようなテストコードになるでしょうか

```sample_spec.rb
describe "#puts_by_weekday" do
  subject { Hoge.new.puts_by_weekday }
  context "平日の時" do
    before do
      allow_any_instance_of(BusinessDay).to receive(:holiday?).and_return(false)
    end
    it { is_expected.to eq "今日は仕事" }
  end

  context "土日の時" do
    before do
      allow_any_instance_of(BusinessDay).to receive(:holiday?).and_return(true)
    end
    it { is_expected.to eq "今日は休日！！！！" }
  end
end
```

御覧のように、条件分岐をテストしようとすると、Timeインスタンスのwdayメソッドをスタブしてそれぞれの条件でテストしなければなりません。
今回は二通りですが、パターンが増えるとしんどそうです。
また、言語によってはスタブやモックができないこともあります。
例えばGo言語などではこの場合テストを書くのが非常に困難になるでしょう。


ではメンテナビリティの観点ではどうでしょうか？


例えば、下記のように条件分岐のパターンが増える場合を想定してみましょう。

```sample.rb
class Hoge
  # 略
  def puts_by_weekday
    business_day = BusinessDay.new
    if business_day.holiday?
      p "今日は休日！！！！"
    elsif business_day.public_holiday?
      p "今日は祝日！！！！"
    else
      p "今日は仕事"
    end
  end
end
```

各条件分岐の中において、簡単のために文字列を出力しているだけですが、さらに条件分岐を重ねる必要のあるような要件だった場合、肥大化していくことは避けられないでしょう。また１つのメソッドに
このように、テストが書きにくいだけなく柔軟性に欠いた実装になってしまうことになりかねません。


# SOLIDの原則を意識した実装
このような場合、SOLIDの原則を意識した実装をすることで、よりテストしやすく、より柔軟なコードを書くことができます。

```sample.rb
class HolidayInformer
  def initialize
  end

  def inform
    p "今日は休日！！！！"
  end
end

class WorkdayInformer
  def initialize
  end

  def inform
    p "今日は仕事"
  end
end

class Hoge
  def initialize(business_day_informer)
    @business_day_informer = business_day_informer
  end

  def puts_by_weekday
    @business_day_informer.inform
  end
end


business_day = BusinessDay.new
if business_day.holiday?
  business_day_informer = HolidayInformer.new
else
  business_day_informer = WorkdayInformer.new
end

Hoge.new(business_day_informer).puts_by_weekday
```

休日と平日の処理をそれぞれクラスを用意してそちらで実装するようにし、Hogeクラスからはそのメソッドを呼ぶだけにしました。
この場合のRspecは以下のように書けます。

```holiday_informer_spec.rb
describe "#inform" do
  subject { HolidayInformer.new.inform }
  it { is_expected.to eq "今日は休日！！！！" }
end
```

```workday_informer_spec.rb
describe "#inform" do
  subject { WorkdayInformer.new.inform }
  it { is_expected.to eq "今日は仕事" }
end
```
このように各クラスごとにメソッドを実装しているので、Rspecもそれぞれでテストを書いていくことができます。
スタブなどが使う必要がなく、そのような機能をサポートしていない言語でもテストを書くことが容易になります。

また、メンテナンスの観点からもSOLID原則にのっとることで恩恵があります。
条件分岐が増えても、新たにクラスを追加するだけでHogeクラスをいじる必要がなくなり、システムの安定性に寄与します。

# 最後に
いかがでしたでしょうか。
テストの書きやすいコードとメンテナンスのしやすいコードというのは共通点があると思います。
ぜひこういったことを取り入れてハッピーな開発できるようにしていきましょう！

# 次回
明日は @m-otsukaさんの記事です！お楽しみに！
プログラミングスクールで「Qiitaで発信しよう」とすすめられたSNS苦手系女子が、Qiitaの活用法を考えた。

他人の「いいね！」に振り回されないように、SNSと向き合ってこなかったツケが回ってきました。
これがQiita初投稿。
今後、私がエンジニアとしてQiitaとうまく付き合っていけるようになるための、自分宛のメッセージです。



## 大丈夫、誰も見てないから。

「みんなが知ってることをわざわざ自分が発信する意味ある？」
「投稿していいね！来なかったら萎えるジャン」

自意識過剰な私よ、心配するな。
みんな忙しいから、私の発信なんて見てやしない。

だから、学習で得た気付き・学びをストックする場所だと思って、自分のために知識を貯めていこ。まずは自分のために。
自分のコップを満たして溢れた分でしか、人を満たすことはできない（≧∇≦）★

＝＞活用法①まずは自分のための知識をストックする。

## ただ慣れてないだけ。

発信できないのは、今まで発信してこなかったから、単に慣れてないだけ。
RailsのMVCを理解できたように、向き合えばちゃんとモノに出来る。
スマートに発信できていたら、今頃もっと違う世界にいるわ。

だから、期間限定キャンペーンやってみよう？
週に1回、プログラミングスクール卒業までは発信し続ける。
質問でもOK。
この期間を乗り越えたら、一つ小さな自信になるはず＼(^ω^)／

＝＞活用法②期間限定で、週1回投稿をやってみる。

## TTP

とはいえ、慣れないことをするのは億劫。
こういう時こそTTP（＝徹底的にパクる）のだ。

Qiitaエンジニア白書2020にも、「エンジニアの83%はスキル習得方法にQiitaを利用している」とある。


![スクリーンショット 2020-12-17 21.55.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/933481/4c5c277e-bace-e398-171f-652baf7b6c82.png)

苦手なら、出来る人から学ぶ。
記事のコピペはしない。自分の力にならないから。
話題の切り取り方だったり、コードの説明だったりを見て、徹底的に真似るところからスタートしてみよう(=´∀｀)人(´∀｀=)

＝＞活用法③良いと思った発信者を徹底的にパクって発信力を磨く。

## 【Qiita活用法まとめ】

①まずは自分のための知識をストックする。
②期間限定で、週1回投稿をやってみる。
③良いと思った発信者から徹底的にパクって発信力を磨く。

うん、これでやってみよう。
行動あるのみ！
CSS適用の優先順位

#はじめに
適用順序の備忘録。

##指定元による優先順位

CSSの指定は、制作者以外にもユーザー、ブラウザのデフォルトのスタイルシートからも指定できる。
→(ブラウザのデフォルトスタイルシートは自動で適用される)
これ以外の指定元も存在するが、基本的な指定元は下記。
<ul>
  <li>製作者</li>
  <li>ユーザー</li>
  <li>ユーザーエージェント(ブラウザのこと)</li>
</ul>

###CSSの指定が競合した場合

####基本的な優先順位

制作者の指定 > ユーザー > ユーザエージェント

!importantで優先順位を高くする
「制作者」「ユーザ」「ユーザエージェント」の指定元による優先順位は、CSSの宣言(プロパティ:値)の後ろに
[!important」を追加することで優先順位の変更ができる。

```
p {
  color: #FFF; !important;
}
```

!importantを付けた場合の優先順位 (降順)

ユーザーエージェント !iportatnt付き

ユーザー　!importatnt付き

制作者　!important付き

制作者

ユーザー

ユーザーエージェント

同じ指定元の中での競合の場合、後の指定が優先される(詳細度が同じ場合)
!importantをつけると順序や詳細度にかかわらず同じ指定元内でも優先される。

####詳細度 Specificity
詳細の度合い。
要素の種類だけで指定するセレクタは詳細度は低く、IDで1つの要素を限定的に指定するセレクタの詳細度は高くなる。

##セレクタの詳細度による優先順位の計算方法
CSS3では3桁の数字で計算する。
CSS2.1までは4桁だったが、無くなった1桁はstyle属性による指定かどうかを判定するもので、
style属性であれば無条件に詳細度が最も高くなる仕様になった為、計算対象外になった。

セレクタの中に含まれるシンプルセレクタの種類ごとの個数を次のように各桁に入れる。
この3桁の数値が大きいものほど詳細度が高い。

1桁目
要素系のセレクタの個数
・要素名 タイプセレクタの個数
・疑似要素の個数 ::xxx
2桁目
属性系のセレクタの個数
・クラスセレクタの個数 .xxx
・属性セレクタの個数　xxx
・疑似クラスの個数　:xxx

3桁目
IDセレクタの個数　#xxx

数字は
3桁目 2桁目 1桁目

####例外
ユニバーサルセレクタ(*)は、詳細度に関係ない、
疑似クラス :not()は()内にあるセレクタは個数に加えますが、:not()自体は個数には加えない。

###セレクタとその詳細度の例(降順)
<table>
  <tr>
    <th>セレクタ</th>
    <th>詳細度</th>
  </tr>
  <tr>
    <td>body div#wrapper</td>
    <td>102</td>
  </tr>
  <tr>
    <td>div#wrapper</td>
    <td>101</td>
  </tr>    
  <tr>
    <td>#wrapper</td>
    <td>100</td>
  </tr>    
  <tr>
    <td>p.subtitle</td>
    <td>011</td>
  </tr>    
  <tr>
    <td>.subtitle</td>
    <td>010</td>
  </tr>    
  <tr>
    <td>body h1</td>
    <td>002</td>
  </tr> 
  <tr>
    <td>h1</td>
    <td>001</td>
  </tr> 
  <tr>
    <td>*</td>
    <td>000</td>
  </tr> 
</table>
詳細度を示す3桁の数値は、各桁がいくつになっても繰り上がらない。
詳細度が低くても!importantがつけば最優先。
Xcode11でiOS14の実機デバッグができない

# 発生したこと
Xcode11でiOS14の実機デバッグを開始しようとすると、RUNするとエラーが発生する。
> An error was encountered while attempting to communicate with this device. (The service is invalid.) 
Please try rebooting and reconnecting the device. (0xE8000022).
>> このデバイスと通信しようとしたときにエラーが発生しました。

![スクリーンショット 2020-09-18 11.28.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208579/005080b7-8287-23a6-a44b-8986ce345a14.png)

ちなみにビルドは成功する。

# やったこと
1. iOS 14のDevice Supportをダウンロード
2. `/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport/ `に配置
3. Xcode再起動
4. RUN

参考：[Xcodeのバージョンを上げずに、新しいOSが入った端末でデバッグする方法（iPhoneのOSをアップデートしちゃったあと） - すっさんぽ](https://sussan-po.com/2019/10/12/new-ios-device/)

# 調べたこと
## issue
[iOS 14 doesn't work with Xcode 11.7 · Issue #69 · filsv/iPhoneOSDeviceSupport · GitHub](https://github.com/filsv/iPhoneOSDeviceSupport/issues/69)


## Xcode 12リリースノート
[Xcode 12 Release Notes | Apple Developer Documentation](https://developer.apple.com/documentation/xcode-release-notes/xcode-12-release-notes)
>Xcode 12 now encrypts the connection between Xcode and paired devices, protecting against an attacker in a privileged network position executing arbitrary code on connected iOS, iPadOS, watchOS, or tvOS devices during a remote debug session. (60386733)
These security benefits are available when Xcode 12 connects to devices running iOS 14, iPadOS 14, watchOS 7, tvOS 14, or later versions. These OS versions also refuse debugger connections from older Xcode releases. Xcode 12 continues to support debugging for older OS versions, but without the new encryption.
>>これらのセキュリティ上の利点は、Xcode 12がiOS 14、iPadOS 14、watchOS 7、tvOS 14以降のバージョンを実行しているデバイスに接続する場合に利用できます。これらのOSバージョンでは、古いXcodeリリースからのデバッガ接続も拒否されます。

# 結果
Xcode12にあげるしかない
C#とMobile Blazor BindingsでWindowsとMac用の動画ビューワーを作成したお話

この記事は [C# Advent Calendar 2020](https://qiita.com/advent-calendar/2020/csharplang) 12月18日分の記事です。

# 自己紹介
はじめまして。
kawaと申します。
主にゲーム系のプログラマーとして働いてきました。 (お仕事募集中なので何かお話などいただけると助かります)
業務ではNintendo 3DS・WiiU・Nintendo Switch向けソフトの開発やスマートフォン向けアプリの開発を行ってきました。
また、プライベートではC#でアプリケーションを作ったり、Unityをいじって動画やゲームを作ったりしていました。
一通り使用できる言語はC#, C++, ちょっとできるのはJava, javascript, PHPなどですが、言語の中ではC#が特に好きです。
[Twitterプロフィール](https://twitter.com/kawa0x0A)
[Githubプロフィール](https://github.com/kawa0x0A)

# やったこと
[C#とBlazorでホロライブファン向けの動画ビューワー『ホロビューワー』を開発しました](https://qiita.com/kawa0x0A/items/24ce1bda92d596f51926)
こちらの記事にある通り、Blazorを使用してWindows/Macで動作する動画ビューワーを作成しました。
こちらの記事も読んでいただけると嬉しいです。

# なぜやった
(上記の記事と一部重複しますが)

* Blazorの勉強がしたかった
    * C#とHTMLが組み合わせられるとか面白そう
    * C#に関連する新しいものなのでとりあえず触ってみたかった
* WindowsとMac両対応のアプリケーションを作成してみたかった
    * 開発で苦労するポイントなどを知って経験値を貯めたかった
    * 邪な考えとして、アプリケーションを使ってもらえる可能性のある層を広げたかった

# Mobile Blazor Bindingsとは
[リポジトリページ](https://github.com/xamarin/MobileBlazorBindings)
[ドキュメントページ](https://docs.microsoft.com/ja-jp/mobile-blazor-bindings/)
要はBlazorとXamarinを組み合わせることでWebアプリケーションだけじゃなくて、Windows・Mac・Android・iOSアプリを開発できるようにするフレームワークだよ とのことです。

**注意**
リポジトリページやドキュメントページにも書かれている通りMobile Blazor Bindingsは「Experimental」日本語に訳すと「実験的」なフレームワークです。
なので、機能的にもまだまだ足りないところや不具合と思われる動作などが色々と見られます。
もしご利用の際にはその点にご注意ください。

# やってみた感想やBlazorについての印象など
* C#を混ぜてWebページを記述できるのでBlazor最高
* 実験的なフレームワークでも割となんとかなる (↓なんとかなったり、ならなかった例)
    * [Blazorアプリケーションをリファクタリングしようとして失敗しているお話](https://qiita.com/kawa0x0A/items/3ab5fb6ff900844bb2da)
    * [Blazor(Mobile Blazor Bindings)でWebViewの描画範囲だけスクショする方法 (Windows WPFの場合)](https://qiita.com/kawa0x0A/items/8cd5f398bf3a5b772bc7)
* 将来的にBlazorが色々なところで使われるようになってほしい (100%個人的願望)
* ただ、VisualStudioでの開発中にソースコードのインデントがちょくちょくバグることがあったので、そこが直ってくれると嬉しい

---

あまり内容が無く、宣伝メインの記事になってしまい、すみません。

明日は[neuecc](https://qiita.com/neuecc)さんの「ソースジェネレーター Part2」とのことです。
[SwiftUI] Qiitaのタグみたいに表示されるTextFieldを作る

SwiftUIのTextFieldはカスタマイズ性に乏しいのですが、見かけだけでもそれっぽくしてみました。
![ezgif-3-929af5259172.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/638786/0ff58fbb-01b6-a172-fde1-4ca284c09697.gif)

# 実装

```Swift 
struct TestView: View {
    @State private var text: String = ""
    var body: some View {
        ZStack{
            TextField("入力", text: $text)
                .foregroundColor(.clear)
            HStack(spacing: 0){
                let strings = text.split(separator: " ", omittingEmptySubsequences: false)
                ForEach(strings.indices, id: \.self){i in
                    Text(strings[i])
                        .background(
                            Color(.sRGB, red: 0.847, green: 0.917, blue: 0.992)
                                .cornerRadius(5)
                                .overlay(
                                    RoundedRectangle(cornerRadius: 5)
                                        .stroke(Color(.sRGB, red: 0.745, green: 0.866, blue: 0.988))
                                )
                        )
                        .padding(.horizontal, 2)
                }
                Spacer()
            }
        }
    }
}
```
## ポイント
`TextField`は制約が大きすぎるので色を`clear`にして見えなくし、その上から好きなように表示します。

# 制約
上からテキストを被せている都合上、カーソルが見えなくなります。これを防ぐためには例えばテキストの背景のカラーを透明色にすればいいのですが、色を合わせるのが大変だったので断念しました。
ISO-TP入門

## 概要
車載ネットワークで標準的に使われているプロトコルの一つに**CAN**があります。CANはOSI参照モデルの物理層・データリンク層に相当します。
CANの詳細は参考リンクにお任せします。
本記事では、その上位層のプロトコルにあたる**ISO-TP**のデータ送信の流れを簡単に紹介します。

## ISO-TP
ISO-TP(またはISO 15765-2)はCAN上に実装されるネットワーク層・トランスポート層のプロトコルです。


### 何ができるのか
CANでは1フレームで最大8バイトのデータが送信されています。
ISO-TPでは複数のフレームを用いて最大4095バイトのデータを送ります。

### アドレッシングフォーマット
ISO-TPには4つのアドレッシングフォーマットというものがあります。

- Normal addressing
- Normal fixed addressing
- Extended addressing
- Mixed addressing

ここでは説明しやすい
Normal fixed addressingを取り扱います。

### Normal fixed addressing

#### 流れ
まず、シングルフレーム送信とマルチフレーム送信で分けられます。
シングルフレームは8バイト未満のデータを送るために使われ、
その名の通りこのフレームを送るだけで送信が終わります。

マルチフレーム送信は次の図のようになります。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/650521/ad828390-fe13-49d2-0164-8fff6a001e1a.png" width=50%>
では、図のパラメータとともに流れを説明していきます。

- FirstFrame (FF)
    - 最初に送信されるフレームで、データ長とデータを含みます。
    - データ長(byte)の表現に12ビット与えられているため、4095バイトまでのデータを送信できます。
- FlowControl frame (FC)
    - FSとBSとSTminを含みます。
    - Flow Status (FS)
        - 送信許可(CTS)、待ち(WAIT)などの状態を示します。
    - BlockSize (BS)
        - 指定した数のCF毎にFCを送信します。
    - SeparationTime minimum(STmin)
        - CFの送信間隔を示します。
- ConsecutiveFrame (CF) 
    - Sequence Number(SN)とデータを含みます。
    - SNはCFの順番を表します。
    - SNは0x01からインクリメントされ、0xffの次は0x00に戻ります。
    - 最初が0x01なのはFFを0x00として見ているからです。
    - (FFはSN=0x00確定なのでSNを含みません)


#### データ構造
![図1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/650521/27adcc0e-099d-2a7f-ad1f-30c4edd4f471.png)
※DAは1対1で送信する物理アドレス、DBは1対多で送信する機能アドレスの役割
※[N_TA]はターゲットアドレス、[N_SA]はソースアドレスが入ります
※DL=データ長

 

## 最後に
省いている部分が多くなってしまいましたが初Advent Calendarありがとうございました。
自動車業界のIT技術に触れ始めたばかりですが面白いです。

## 参考
ISO15765-2
ISO11898-1
[はじめてのCAN/CAN FD](https://www.vector.com/jp/ja/know-how/beginners/beginners-cancan-fd-jp/)
電源回路の「しくみ」と「基本」2章 (2)電源に使う部品の必要定格

[前の記事](https://qiita.com/ikenohotori/items/da97815e40cd6169d8d1)では、電源とは何か、という概要から、ブリッジ整流回路までを記載した。
今回はブリッジ整流回路につかう電子部品の選定に関わる話。

# 電源に使う部品の必要定格
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581044/907db562-8e14-98b5-4547-84454c4a2767.png)
この回路を例に、使用する電子部品の定格について解説してする。
定格とは、指定された条件における仕様、性能、使用限度などのこと(wiki)。

## ダイオードの定格
###最大電流
電源投入時、コンデンサには電荷がないため、コンデンサを充電するために電流が一気に流れ込む[^1]
[^1]: コンデンサは電荷を貯める性質をもち、電圧は0Vの状態から電源電圧まで上昇する。コンデンサの電圧が電源電圧に達すると、回路には電位がなくなり電流は流れなくなる。
これは短絡状態と同じになるため、ダイオードを無視すれば、負荷はトランスの二次側だけとなる。
よって、ダイオードの電流は以下の式で求まる。

__I(ダイオードの電流) = Vm(二次側電圧の最大値) / R(二次側巻線の抵抗)__
※直列回路の電流 ＝ 電源電圧 / 回路全体の抵抗のため

###平均電流
ダイオードの平均電流は定格で守らなければいけない。
平均電流の求め方は半波整流と全波整流で異なり、
半波整流回路のダイオード平均電流：負荷電流IL
全波整流回路のダイオード平均電流：負荷電流IL / 2 となる。

###逆電圧
ダイオードには、逆方向に印加して良い電圧が規定されている。
ブリッジ整流回路の場合、（並列回路のため逆方向のダイオードにも順方向と同じ電圧がかかるため）逆電圧は入力電圧の最大値に等しい。


## トランスの定格
トランスの電流は、正弦波の場合だと電源電圧/回路全体の抵抗で素直に求まる。
しかし整流を行った場合、実効電流は負荷電流ILと以下の関係となる。
半波整流のトランス実効電流：2.3L
全波整流のトランス実効電流：1.65L

## 平滑コンデンサの定格
コンデンサ毎に印加してよい電圧が定められているため、出力電圧より高いものを選ぶ必要がある。
電流についても許容できるリプル電流が決まっているが、これはシュミレーションをして確認する。
【超簡単！】Three.jsでUIを作る(2) 

# あらすじ

←[前回：【超簡単！】Three.jsでUIを作る(1)](https://qiita.com/Yamkaz/items/9862541dd81196f3d149)
![text2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276138/0707e58c-5482-c346-7ffa-c04e9f2b39e1.gif)

僕の大好きな、「[Experiments with Google](https://experiments.withgoogle.com/)」が制作した「[Assisted Melody](https://experiments.withgoogle.com/assisted-melody)」のWebアプリケーションがUIがWebGLで制作されていました。こんなUI簡単に実装したいですよね..。

探しても、この辺りの情報をまとめてくれている人がいなかったので自分で作ることにしました。

# sample02. 四角形を並べる + スクロールで変形

今回も簡単です。四角形を並べる処理と、
スクロールに合わせて移動する処理のみで作られたシンプルなコードを書きました。

コード内に解説は全て書いたので、読んでください。
![text4.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276138/f3cf32f1-35ce-99ca-41fa-59a7bc525606.gif)


<p class="codepen" data-height="865" data-theme-id="dark" data-default-tab="js,result" data-user="yamkaz" data-slug-hash="RwGVxyr" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="ThreeJS: Plane Geometry * 10 + Scroll">
  <span>See the Pen <a href="https://codepen.io/yamkaz/pen/RwGVxyr">
  ThreeJS: Plane Geometry * 10 + Scroll</a> by やまかず / Kazuyuki Yamamoto (<a href="https://codepen.io/yamkaz">@yamkaz</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

<script async src="https://production-assets.codepen.io/assets/embed/ei.js"></script>

→次回作 
[【超簡単！】Three.jsでUIを作る(3) sample03. マウスの位置に向く四角](https://qiita.com/Yamkaz/items/ae9e720da9c8c2035105)
[CSS] Flex box 

#要素を横並びにする
要素を横並びにするには、横並びにしたいブロック要素の一つ上の階層に`display: flex`を指定します。

#並べたい要素の幅が親要素の幅を超える場合
`nowrap` 折り返さず、それぞれの要素の幅を縮める。
`wrap`　　はみ出した要素を折り返す。　→→↓
`wrap-reverse`　はみ出した要素を折り返す。（`wrap`と逆方向）→→↑!
[Rails] モデル.find(params[:id]) 読み方

コード
=========
```user_controller.rb
def show
  @user = User.find(params[:id])
end
```
コントローラーファイルで
こんなコードを目にするかと思いますが、
いまいち理解していなかったのでまとめてみました



findメソッド
=========
findメソッドは`テーブルからレコードを1行取得できるメソッドです`
引数は`idしか指定できない決まりがあります`


params
======
paramsは`送られてきたパラメーターを入れる箱のようなメソッドです`
パラメーター（情報）は`コントローラーはそのままの形で受け取れません`
なので箱に入れてから送ります

クライアント送られてくる情報(リクエストパラメータ)は主に、getのクエリパラメータとpostでフォームから送信されるデータの2つです

`params[:カラム名]`で値を受け取ることができます

リクエストパラメーターの流れ
=====================
例えば、リクエストパラメーターの流れはこんな感じです

①クライアントから「商品ページ見せて！」みたいなリクエストと同時に、その中に含まれる
　情報（リクエストパラメーター）がルーティングに送られる

②paramsに格納される

③コントローラに送られる

コードの解説
=========
```user_controller.rb
def show
  @user = User.find(params[:id])
end
```
以上を踏まえて
`usersテーブル内の指定したレコードからidカラムの値を取得して@userに代入する`
このような理解をしました

ニュアンスや知識のズレがあるかもしれないので、
もし見つけられた方はご指摘いただけると幸いです
Maya scriptノードに対抗する闇の魔術 を書きたかった


## 始めに
今年はscriptノードの被害が多い一年だったようですね！

知り合いのTAからも、送られてきたシーンに変なデータが含まれていて色々大変だったと聞きました。

自分は運よく遭遇せずに済んで、件のデータを見てないので何も言えないですが
(まあ見てても言えないですけど)
今日はそんなシーンをどうにかする方法を考えます。

今回想定したファイルは、シーンを開いたときにpolyCubeを一つ作るscriptノードですね。

## 今回のコンセプトについて

たしかscriptノードのイベント発火はscriptJobなどと同じく、MayaのIdle時だった気がする[^1]ので、
そのイベント発生前にノードを削除すればいいわけです。

[^1]: 未検証

今回はscriptノードを削除するコールバックをOpenMayaのMMessageに登録してみましょう！！！
闇には闇をぶつけんだよ！って発想ですね。

(こういう発想するから変なシーンが産まれ、送られてくるんだろうなあ……)

今回は`MCommandMessage`を使います！

`MCommandMessage` はMayaのコマンド、プロシージャが走るたびに発生するイベントで、
`addCallback`して関数オブジェクトを登録すれば、Mayaのコマンドが走った直後に関数が実行されます！

## やってみた

```python
def remove_script_node_cbk(message, *args, **kwargs):
    if message.startswith('createNode "script"'):
        # 可読性が悪い！！！
        node = message.strip().split(" ")[-1].replace(";", '').strip('"')
        cmds.delete(node)

        
id_ = OpenMaya.MCommandMessage.addCommandCallback(remove_script_node_cbk)

# 登録を解除するときはこれ。
# OpenMaya.MCommandMessage.removeCallback(id_)
```

はい、`.ma`を開くときにノードの復元するために`createNode`コマンドが走り、
走ったコマンドを読んで、`createNode "script"`コマンドを拾って、
拾ったノードをdeleteすれば無害化できますね。

これで手元のシーンもpolyCubeを作られませんでした！

ですがコレ、`maya ascii` シーンでは動くんですが、`maya binary`シーンでは動きませんね。
やっぱり駄目だったよ……まあでも、納品物を全部`.ma`にすればいいか……


---

では次鋒！`MSceneMessage`！

```python
def delete_script_node(*args, **kwargs):
 cmds.delete(cmds.ls(type="script") or [])

id_ = OpenMaya.MSceneMessage.addCallback(OpenMaya.MSceneMessage.kAfterOpen, delete_script_node)
# OpenMaya.MCommandMessage.removeCallback(id_)
```

ma, mb共に、手元のデータでは上手く動きましたね！やったね！！

あとはプロジェクトごとに許可するscriptノードのリストを用意して、
それ以外の不正なscriptノードは削除すればよさそうですね！

---

明日はpaty-6991さんの記事です。楽しみですね！
コンテナって何かを調べた

#コンテナって？
<b>ホストOS</b>上で「<b>コンテナエンジン</b>」を使い動かすアプリケーションに必要な`OS`・`ミドルウェア`・`アプリケーション`をまとめてパッケージ化した物のこと。個別のサーバーのように使える。
　　
この技術により<b>仮想マシン</b>に<b>ゲストOS</b>を起動しなくてもアプリケーション実行環境を作ることが出来るようになりました。
コンテナを用いれば<b>ホストOS</b>のみの稼働なので、CPUやメモリの消費は少なく、ストレージの使用もわずかとなります。そのため、仮想マシンに比べて起動時間が短く、コスト低減＆パフォーマンス向上が可能となります。
　<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/836751/bed8a8ab-9ec7-11a2-bac7-6afb2ec371fe.png" width="600">
と、ここで疑問が生じます。
「あれ？<b>ホストOS</b>だけの稼働なのにOSがパッケージに含まれてない？」

そう！それです！！！
このパッケージに入っているOSは、なんちゃってOSです。
なんとなくそれっぽい動作環境を作っているだけの擬態OSとなります。
やり取りするのはあくまで<b>ホストOS</b>となります。
では、ホストとコンテナでOSが違っててもいいの？と思いますが大丈夫です。
アプリケーションはOSの中にある`カーネル`とやり取りをしているため、多少違っても心配いりません。（ Linuxの互換性 ）
ホストがMacとWindowsでも！？とお思いでしょう。。。Dockerの場合、その時はひっそりLinuxの仮想マシンが起動するようになっているみたいです。すごいですね！！！
ただ、コンテナで作ったアプリ環境（OS）と違うOS環境でデプロイすると動かないよってのは注意しましょう。

###コンテナは１つのプロセス
コンテナは<b>ホストOS</b>からすると<b>1つのプロセス</b>として扱われます。
※プロセス ・・・ 実行中のプログラムの事
どうしてそんな事が出来るのかと言うと、コンテナは `Namespace` `cgroup` `Capability` の要素技術を駆使し `プロセス` `システムリソース` `権限` を分けて管理していることで１つのプロセスとして実行されています。

- Namespace → ユーザーIDやホスト名など名前をつける事で他と区別させる

- cgroup → プロセスを分けてリソース(CPU、メモリ、ディスクI/Oなど)の利用を制限・隔離する

- Capability →　rootが持っている絶対的な権限を細かく分け，必要な権限だけを与える仕組み

　
###と言うわけで
低コストで簡単に素早く作れ、１つのサーバー上にいくつも作れる技術がコンテナでした。
システム開発や運用面ではコンテナ内で環境設定が出来ているため、どこにデプロイされても一貫性がありますし開発環境とテスト環境での想定が本番環境が同じに出来るからバグが少なく済むので作業効率UP。
また、どのOSでも汎用機でもクラウドでも場所を問わずに使えてとても便利な技術です。



##参考
https://thinkit.co.jp/article/17301
https://tech-lab.sios.jp/archives/18811
https://pfs.nifcloud.com/navi/tech/container_virtualization.htm
WKWebViewでSPAなサイトの遷移を監視する方法

# 概要
SPAのようなページを構築していてURLを監視したいけどdelegateが呼ばれず検知出来ない


# 解決法
KVOでWKWebViewの`url`プロパティを監視する。

```swift
class ViewController: UIViewController{
    var webView: WKWebView
    private var _observers = [NSKeyValueObservation]()
    //中略
    override func viewDidLoad(){
        _observers.append(webview.observe(\.url, options: .new) { _, _ in
            print("URL: \(self.webView.url)")
        })
    }
}
```

https://stackoverflow.com/questions/47829963/how-can-i-detect-when-url-of-amp-page-changed-with-wkwebview/48273950

https://qiita.com/ObuchiYuki/items/d00ce5f44725672184da
よく使うVSCodeショートカット

#はじめに
　コード用のテキストエディタだからこそ私が、よく使うショートカットをまとめておきます。少しでも参考になれば幸いです。
##生産効率爆上がり最低限のショートカット

（範囲を選択していない状態で）command + c
→その行をコピー

command + z
→一つ前に戻る

command + shift + z
→一つ後に進む

command + 矢印
→一気にカーソルを移動

option + 左右矢印
→単語単位でカーソルを移動

option + 上下矢印
→その行を入れ替える

範囲が選択された状態でtab
→インデントを作る

shift + command + k
→その行を削除

##最後に
　ちゃんとまとまっていなくて、見づらくなってしまいました…。
Shoryuken + SQSで非同期処理にした

[シーエー・アドバンス Advent Calendar 2020 - Qiita](https://qiita.com/advent-calendar/2020/ca-advance) 18日目の記事です。

## Shoryuken導入の経緯
数万件のCSVデータを登録する機能を作成しましたが、処理に時間がかかってしまい処理が完了する前にタイムアウトしてしまう事象が発生しました。
タイムアウトを延長も検討しましたが付け焼き刃的対応であるため、数万件登録でも対応できるよう非同期処理できる機能が必要でした。

検討した処理の流れは以下となります。

- SPA画面よりCSVをアップロードした際、S3に保存してキューをSQSに登録する
- Workerにてキューを取得しバックグラウンドでS3からCSVをダウンロードしてCSV内のデータをDBに登録する

## [Shoryuken](https://github.com/phstc/shoryuken)とは
AWS SQSと連動したActive Job Worker。
sidekiqが有名みたいですが、そちらがRedisをqueueStoreとしているのに対し、ShoryukenはSQSをqueueStoreとしています。
最初Sidekiqの導入を検討しましたが、耐障害性の高いSQSを使用したかったため他にもないと探していた際に目的にあったShoryukenを発見。即導入に至りました。

## キューの作成
SQSにあらかじめキューを作成しておきます。

![201218-0001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68003/6f3e9a54-120a-0570-ab92-569d31f03d6a.png)


## 導入

```:Gemfile
gem 'shoryuken'
```
`bundle install` します

```shell
$ bundle install
```

設定ファイルは以下になります。
1処理の件数が多いため、スレッド数は控えめにしました。

```yaml:config/shoryuken.yml
concurrency: 5
delay: 30
require: /usr/src/app/app/workers
pidfile: /usr/src/app/tmp/pids/shoryuken.pid
queues:
  - sqs_queue_sample
```

メッセージを取得するサーバー設定を作成します。
今回、キューの取得のみShoryukenを使用しますが、キュー登録の場合は、`configure_client` を定義すると、Shoryuken経由でキューの登録が行えます。

workerはECS fargateでコンテナ作成するため、ログはCloudwatch Logsで確認できるよう標準出力するようにしてます。

```ruby:config/initializers/shoryuken.rb
Shoryuken.configure_server do |config|
  config.sqs_client = Aws::SQS::Client.new(
    region: "ap-northeast-1",
    access_key_id: ENV['AWS_ACCESS_KEY_ID'],
    secret_access_key: ENV['AWS_SECRET_ACCESS_KEY'],
    verify_checksums: false
  )
  Rails.logger = Shoryuken::Logging.logger
  Rails.logger.level = :info
end

Shoryuken::Logging.initialize_logger(STDOUT)

```
workerのメイン処理を実装します。
キューにメッセージが登録されると`perform` メソッドが実行され、メッセージが受け取れます。
あとは、CSVデータの登録処理を書いていきます。

```ruby:workers/do_worker.rb
class doWorker
  include Shoryuken::Worker

  shoryuken_options queue: 'sqs_queue_sample', auto_delete: true, body_parser: json

  def perform(sqs_msg, body)
    (ここにworker処理を書く)
  end
end
```

あとは、下記コマンドで起動させればOKです。
コンテナで運用する場合は、dockerfileの`CMD`に下記コマンドを追加でworkerとして起動します。

```shell
$ bin/bundle exec shoryuken -R -C config/shoryuken.yml
```

## 導入後
CSV登録処理をバックグラウンド化したことで、CSVレコード数でタイムアウトせず、
またSQSとShoryukenでスレッド化することで過剰な負荷がかかることがなくなりました。
稼働させて1ヶ月弱ですが、不具合などは発生していません。

gemモジュールを使用することでサクッと実装できました。
開発環境ではSQSの代わりにFakeSQSを実装したかったのですが、時間的都合で見送りとなりました。
開発用SQSキューを作成していますが、料金は発生してしまうので、FakeSQSコンテナで開発を行えるようにするつもりです。

## 参考
- [Shoryukenでつくるバッチ処理基盤 - トレタ開発者ブログ](https://tech.toreta.in/entry/2016/06/09/120610)
- [shoryuken gemで簡単にSQSを使ったJob Queue WorkerをRailsに作成する | Developers.IO](https://dev.classmethod.jp/articles/shoryuken-gem/)
[Swift] Tab Bar Controller の使い方

#Tab Bar Controller とは
このように切り替えができるあれです！
使っているアプリとかを良く見ると、あると思います。
今回はこれについて書いていきます。
![ezgif.com-gif-maker.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/755375/b6c83423-4f7c-3009-87b2-29f483d8606b.gif)
#使い方
使い方はシンプルな気がします。
まず、初期であるviewControllerを消します。
次に、Tab Bar Controllerを置きます。
![スクリーンショット 2020-12-17 23.21.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/755375/fc221cab-c3b3-4366-3447-2a57c36f18bf.png)
viewControllerを消したので初期画面が設定されてない状態です。なので初期画面をTab Bar Controllerに設定します。
Tab Bar Controllerを選択して、右の欄のIs Initial View Controllerにチェックを入れます。
![スクリーンショット 2020-12-17 23.24.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/755375/fb560d60-3e04-a26d-17e8-63fdeb346e51.png)
ファイルを作成して、それぞれの画面に割り当てます。
![スクリーンショット 2020-12-17 23.27.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/755375/fe1370d4-96e1-934a-a8cb-aaa2731ccf52.png)
Cocoa Touch Class を作成。
![スクリーンショット 2020-12-17 23.28.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/755375/7feb8f8e-59db-9fe8-d1ca-5bdf7b524f9b.png)
ファイルを割り当てます。
![スクリーンショット 2020-12-17 23.30.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/755375/ea0fee3e-6c58-4412-62d7-07f7a852463b.png)
それぞれの画面に割り当てられたら、完了です。
Spring Bootをgradle build with Docker

長いことビルドはmaven派でしたがgradleを使う必要性が出てきたので備忘録として
Spring Bootをdockerを使ってgradle buildしていく
マルチステージビルドにしてCloud RunもしくはECSにデプロイする手順も後日公開予定

## Spring Bootプロジェクトの作成

Spring Initializr https://start.spring.io/
を使ってSpring Bootプロジェクトの雛形を作成する

<dl>
  <dt>Project</dt>
  <dd>Gradle Projectに変更</dd>
  <dt>Dependencies</dt>
  <dd>ADD DEPENDENCIES...からSpring Webを選択</dd>
</dl>

![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/475244/b52637df-1d52-ce5e-3b5e-36536d39ea50.png)

GENERATEをクリックするとzipファイルのダウンロードが開始
解凍した中身がプロジェクトファイルになっている

## プロジェクトを開く

テキストエディタでもIDEでも何でもいいのでプロジェクトを開く
今回は普段使わないIntelliJ IDEAの手順を記載

File → New →　Project from Existing Source → 解凍したフォルダを選択 →　Open
Import project from external modelをチェック → Gradleを選択 → Finish
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/475244/c9a808c4-0e69-2ade-01ce-7ecb82115f00.png" width=70%/>

## コントローラー追加

初期状態ではコントローラーが無いためシンプルな文字列を返すコントローラーを追加していく
プロジェクト/src/main...の下にある~Application.javaと同じパッケージにHelloController.javaを作成する

```java:HelloController.java
package com.example.demo;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {

    @RequestMapping("/")
    public String index() {
        return "Hello Spring Boot!";
    }

}
```

IDEを使っている人はこの時点でSpring Bootアプリケーションを実行して動作確認ができる
アプリケーションを実行してlocalhost:8080にアクセス
Hello Spring Boot!
が表示されれば正常に動作できている

IntelliJ IDEAの場合は右端のGradleから実行できる
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/475244/2a2f5177-a12e-190a-5c7d-1468d8f648c2.png" width=70%/>

## Dockerfile作成

プロジェクトの直下にDockerfileを作成する
ファイルをコピーしてビルドコマンドを実行するだけの簡単なイメージ

```dockerfile:Dockerfile
FROM gradle:6.7.1-jdk11
COPY --chown=gradle:gradle . /home/gradle/src
WORKDIR /home/gradle/src
CMD ["gradle", "build", "bootJar"]
```
gradle:6.7.1-jre11をベースイメージに使うとビルド中にヌルポで落ちる
jdkのイメージは大きいので本当であれば避けたい

## Dockerビルド & 起動
コンソールでプロジェクトのディレクトリに移動して以下のコマンドを実行

```
docker build -t bootbuilder:v0.1 . 
docker run -it --rm -v "$PWD":/home/gradle/src bootbuilder:v0.1
```
~build/libs内にjarが作成されていればビルド完了

#### 参考資料
https://spring.io/guides/gs/spring-boot/