OmniAICreator/Qiita-1.07M huggingface dataset:
【Java】正規表現を使って数値をチェックする方法

#プログラミング勉強日記
2020年12月4日
正規表現を使うことで、書き方によってばらつきが生じることにも対応した検索や処理を行うことができる。今日はJavaの正規表現を使った数値をチェックする方法を学んだのでまとめる。

#正規表現とは
　まず、正規表現について紹介する。正規表現は文字列のパターンを表現するための記号の組み合わせのこと。正規表現を使うことでその文字が漢字・数値・メールアドレスといった特定のパターンであることを判別することができる。

##正規表現の書き方
　正規表現の意味と記号を紹介する。

| 記号 | 記号の説明 |
|:--:|:--:|
| . | 任意の1文字。改行文字は除く |
| * | 直前の1文字の0回以上の繰り返しと一致 |
| ^ | 行の先頭 |
| $ | 行の末尾 |
| [ ] | カッコ内の任意の1文字と一致。`-`で範囲指定可。|
| [^ ] | カッコ内の任意の1文字と不一致。`-`で範囲指定可。|
| + | 直前の文字の1個以上の繰り返しと一致 |
| ? | 直前の文字が0個または1個の場合に一致 |
| { } | カッコ内の数値の繰り返しと一致 |
| &#124; |　直前、直後どちらかのパターンに一致 |
| ( ) | カッコ内をグループ化。マッチした内容は参照可。|

```
[0-9]{3}-[0-9]{4}-[0-9]{4}
```
　携帯の電話番号のような「090-1234-5678」といった文字列を検索したい場合はこのようになる。0から9の数字が3回続いた後に`-`(ハイフン)があって、また0から9の数字が4桁続いて…というように判定する。

##Javaでの正規表現の使い方
　Javaでは正規表現を扱うためのライブラリが用意されている。2つのクラス(以下に示す)を使うことで、正規表現を利用したJavaのプログラムを書くことができる。

- 正規表現文字列（パターン）を扱うためのクラスであるjava.util.regex.Patternクラス
- 検査対象文字列がパターンに合致するか判定するためのクラスであるjava.util.regex.Matcherクラス　

#サンプルコード

1. 文字列を用意する
2. 数値チェック用の正規表現パターンを用意する
3. JavaのPatternクラスとMatcherクラスを使って2のパターンに1が一致するかチェックする

```java
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Main {
  public static void main(String[] args) {
    // １．文字列を用意する
    String numberStr = "0312345678" ; // 半角数値のみ
    String numberStrNG = "03TechAchademy" ; // 英字が混ざっている

    // 2. 正規表現パターンを用意する
    String regex_num = "^[0-9]+$" ;

    // 3.Javaの正規表現ライブラリで事前準備をする
    Pattern p1 = Pattern.compile(regex_num); // 正規表現パターンの読み込み
    Matcher m1 = p1.matcher(numberStr); // パターンと検査対象文字列の照合
    boolean result1 = m1.matches(); // 照合結果をtrueまたはfalseで取得する

    // ４．結果をコンソールで出力
    if(result1) {
      System.out.print("numberStr は数値です。");
    } else {
      System.out.print("numberStr に数値以外の文字列が混じっています。");
    }
  }
}
```

```:実行結果
numberStr は数値です。
```



#参考文献
[Javaで正規表現を使って数値チェックをする方法を現役エンジニアが解説【初心者向け】](https://techacademy.jp/magazine/28637)
無料ライセンスコード付きiCare Data Recovery Pro Crack

最新のライセンスコード、シリアルキー、keygen、シリアル番号、アクティベーションコード、登録コード、kickassなどを含む<a href="https://jp.bitwar.net/howto/windows/2425.html">iCare Data Recovery</a>クラックを無料でダウンロードしようとしていますか？ それを止めてください、もっと安全なデータ復旧ソフトウェアを用意しています。


<strong>ファイルが見つからないのはなぜですか？</strong>

実際、見られるデータ損失の4つの一般的な原因があります。

   1.安全に取り外す前に、コンピューターからメモリーカードを引き出します。

   2.偶発的な削除。

   3.不適切なパーティションフォーマット。

   4.コンピューターが水や熱い火などに落ちた。


貴重なデータがなくなったときの痛みは誰もが知っていますが、したがって、重要なファイルが消えたとき、それを復元う方法を見つける必要がありますが、誤って削除またはフォーマットされたファイルをレスキューするために無料ライセンスコードでiCare Data Recoveryクラックを検索している場合は、信じないでください！


<strong>iCare Data Recovery Crackを信じないでください！</strong>


iCare Data Recoveryは、さまざまな種類のデジタルデバイスから削除されたデータを回復するために使用されることがわかっています。ただし、最初の2 GBは無料で復元でき、ソフトウェアを継続的に使用したい場合は、公式Webサイトからライセンスを購入するために69.99ドル以上を費やす必要があります。


しかし、これはインストールプログラムが常にウイルス、マルウェア、アドウェア、スパイウェアと共にパッケージ化されているため、iCare Data Recoveryクラックを使用する理由ではなく、個人情報の漏洩、ファイルの破損、またはウイルス攻撃やトロイの木馬によってシステムがクラッシュしたことさえあります感染。

 

だから、今すぐ正しい決断をしてください。 iCare Data Recoveryソフトウェア会社から完全な著作権付きライセンスコードを購入するか、より安全で無料の別のソフトウェアであるBitwar Data Recoveryを使用する必要があります。


著作権で保護されたBitwar Data Recoveryは、30日間の無料トライアルに最も適したソリューションです。任意のデバイス（デジタルカメラ、ハードドライブ、SDカード、TFカード、その他の外部ストレージメディアなど）からデータを救出できます。ウイルス感染、ハードウェア障害、または不正な操作によるファイルの損失が原因であるかどうかにかかわらず、この強力なファイルレスキューソフトウェアレスキューを起動するだけで、数回クリックするだけで必要なファイルを取得できます。不足しているファイルを含むパーティションにソフトウェアをダウンロードしてインストールしないように注意してください。

   詳しくは、「<a href="https://jp.bitwar.net/howto/windows/2425.html">無料ライセンスコード付きiCare Data Recovery Pro Crack</a>」をご参照ください。
Raspberry Pi OS 2020-12-02 Release-note 翻訳

(追記: 2021/1/14にRaspbian OS 2021-01-11がリリースされています)
https://qiita.com/utaani/items/51441b64544476355db4

https://downloads.raspberrypi.org/raspios_full_armhf/release_notes.txt

2020-12-02：

  - PulseAudioが含まれ、デフォルトで実行されるようになりました
  - BluealsaのBluetoothインターフェイスが削除 - BluetoothオーディオはPulseAudioで処理されるようになりました
  - LXPanel音量コントロールプラグインはPulseAudioバージョンに置き換えられました
  - ChromiumWebブラウザ バージョン84.0.4147.105が含まれています
  - Thonny バージョン3.3.0が含まれています
  - Flashプレーヤー バージョン32.0.0.453が含まれています- 2020年の終わりにサポートが終了するので、これがFlashの最終リリースになることに注意
  - CUPSプリンターシステムにsystem-config-printer CUPSGUIおよびHPプリンタードライバーが含まれます
  - raspi-configのメニュー構造がRaspberryPi構成タブにあうように再配置されました
  - GPIO接続のファンのサポートがraspi-configおよびRaspberryPi構成に追加
  - Pi400およびPiZeroの電源/アクティビティLEDの制御がraspi-configおよびRaspberryPi構成に追加されました
  - いくつかのアプリケーションでスクリーンリーダの音声プロンプトが改善されました
  - いつでもOrcaスクリーンリーダーをインストールできるctrl-alt-spaceショートカットを追加しました
  - バッテリーモニタープラグインに低電圧警告を追加しました
  - ポインターがアイコンの上にあるときに、拡大鏡プラグインのズームをスクロールホイールで変更できるようになりました
  - 通知ポップアップへの変更 - どこでもクリックすると閉じるのではなく、直接クリックした場合にのみ閉じるようになりました
  - Bookshelfは、書籍や雑誌の翻訳版と互換性をもつようになり、システム言語設定を基に、利用可能な場合は翻訳版を提供します
  - スロットル検出が失敗するとCPU温度プラグインがクラッシュするバグを修正
  - Orcaが実行されている場合、シャットダウンコマンドとシャットダウンダイアログは、再起動またはシャットダウンプロセスをロックしないように強制的に強制終了するようにバグ修正
  - さまざまな追加の言語翻訳が追加されました
  - さまざまなマイナーなバグ修正とUIの調整
  - RaspberryPiファームウェアb324aea801f669b6ab18441f970e74a5a7346684
  - Linuxカーネル5.4.79
アドベントカレンダー2日目：SREを読んでみた「イントロダクション」編①

アドベントカレンダー2日目です。前回はSREの「[はじめに](https://qiita.com/user_h/items/c1f25dcf62bc6c39b76a)」を読みました。
今回は、SREの１章「イントロダクション」について、読み進めていこうと思います。
本の内容的には、ほぼ歴史の話になります。個人的に歴史は好きですし、重要だと思っているので、それだけでまとめることには価値があると思いますが、読んでもらえるのか不安な回です。なので、すこし物語を付けました。

## サービス管理の歴史：シスアド編

> **歴史的に、企業は複雑なコンピューティングシステムを動作させるためにシステム管理者を雇用してきました。
シスアドとも呼ばれるこのシステム管理者のアプローチでは、既存のソフトウェアコンポーネントを組み合わせてデプロイし、それらを共に動作させてサービスを作り出します。シスアドはサービスを運用し、イベントが発生したり、イベントに応じてアップデートが必要になるたびに対処します。**<sup>1</sup>

まずは、既存のシスアドの説明が書かれています。この説明には、特に疑問はありません。自分のイメージとも合っています。
シスアドによるサービス管理のモデルには、以下のようなのメリットがあると書かれています。


> **企業がサービスの運用やスタッフ割り当てを決めるにあたって、このアプローチは比較的実施しやすい方法であり、業界では馴染みのあるパラタイムであることから、学んだり真似たりできる例が多くあります。また、関連する能力を持つ人員も広く集めることができます。こうして構築されたシステムの稼働を支援してくれる既存のツールやソフトウェアコンポーネント（出来合いのものかどうかにかかわらず）は、熟練していないシスアドのチームでも車輪の再発名やゼロからのシステム設計をせずに済むのです。**<sup>1</sup>

こう言われると、シスアドのモデルは悪くないように思えます。企業にもシスアドにもやりやすい環境ができているように感じます。しかし、このモデルにもデメリットがあり、それは直接的なコストと間接的なコストに大別できるそうです。

> **直接的なコストは明らかです。変更管理やイベント処理を手作業に頼るチームがサービスを稼働させる場合、サービスそのものの成長やトラフィックの増大に伴いコストがかさんでしまいます。これは、そのシステムの運用における負荷の増大に伴って、チームも大きくしていかざるをえないためです。**<sup>1</sup>

これは、かなりぞっとする話です。仮にシステムの不具合が起きたとき、１つの環境だけなら、いいですが、２つなら？３つなら？（１００個なら？）恐竜は巨大化したことによる維持費が支払えなくて、絶滅した種もあると聞いたことがあります。
このコストの軽減の為に、ますます将来に備えて、自動化することが重要だという気になってきますが、しかし、将来に備えると言っても、一体何をすればいいのでしょうか？何から自動化していくべきなのでしょうか？また疑問が増えました。
（あと、さらっと人員が増える前提で書かれてるけど、そんな簡単に増えるものなの？というか、増えたとしてもその人に教えるコストもかかるじゃん。というか...)

シスアドとプロダクトの開発者は、大きく異なるスキルセットを求められます。そのため、シスアドと開発者は区別され、異なるチームに割り当てられます。間接的なコストは、このグループ化による分断に原因があると書かれています。

> **これらのコストは、２つのチームのバックグラウンド、スキルセット、動機付けがまったく異なることから生じるものです。この２つのチームは、状況を説明する際に異なる用語を使います。そして、技術的な解決策のリスクや可能性についても異なる推定をします。またプロダクトの安定性のターゲットレベルに対する想定も異なります。これらのグループの分断は動機づけにとどまらず、コミュニケーション、目標、そして最終的には信頼と尊重にまで及ぶこともあります。そしてその結果、病的な状態になってしまうのです。**<sup>1</sup>

## あったかもしれない会話
開発A君：一生懸命、サービスを作って、お客さんに気に入ってもらえれば、お客さんは喜ぶし、上司からも、褒められる。よし！頑張って、いいサービスをつくるぞ！
運用B君：お客さんが使っているサーバーに問題があっちゃいけない。万が一、止まってしまったら、たくさんの人に迷惑をかけてしまう。きちんとサーバーを管理しないと。

開発A君：B君、新しいサービスをつくったんだけど、サーバーに追加してもらってもいい？
運用B君：いいけど、この前の追加で問題起きたよね？再発防止のチェックリスト作ったと思うけど、それは全部クリアした？
開発A君：クリアしたけど、あのリストさ、無駄が多いんだよ。重要度の高いものだけに絞れない？
運用B君：でも、あそこに書いてあるのは、全部昔起きた障害の防止策だよね？やっとかないとまずいと思うよ？
開発A君：（うーん。チェックも大事だけど、早くリリースしたいんだよな。）

#### 後日
開発A君：B君！サーバーに追加してもらいたい機能があるんだけど。
運用B君：チェックリストは？大丈夫？
開発A君：いや、今回は、大きい変更じゃなくて、マイナーアップデートだから、チェックしなくても、大丈夫だよ。あと、大した変更じゃないんだけど、ここだけチェリーピックしていい？

運用チームは、サービス稼働中に問題が起きないようにしたいと考えます。サービスの追加に関門を設け、問題を極力減らそうとします。
開発チームは、新しい機能を追加し、早くユーザーに届けたいと考えます。大きいハードルを越えることを避け、小さな変更を繰り返すようになります。


> **２つのチームの目標は基本的に対立関係にあるのです。**<sup>1</sup>   

> **どちらのグループも自分たちの関心事を優先させるため、塹壕戦のような状態に陥ります。**<sup>1</sup>

## 歴史を振り返る
この歴史を振り返ると、初めは単に求められるスキルセットが違うという理由からチームとして分けられただけでした。
しかし、そのチームで自分たちの役割を果たそうとすればするほど、本来協力すべき相手と対立関係になってしまっています。その結果、相手を疑ったり、うまく欺く方法を考えるようになります。（その気はなくても）
目の前のタスクをこなすことに忙殺されてしまうと忘れてしまいますが、タスクをこなせば仕事になるわけではない。がっくりとしてしまいますが、これが現実なようです。

しかし、そんな残酷な現実も解決する方法はあります。
そうSREならね。

次回 サービス管理：SREのアプローチ編

## まとめ
* 構造が争いを生む。
* 相手のことを考えよう！

## 雑感
今日進んだページ数１ページ半、終わるのか？
まだ、イントロダクションなので、仕方ないですが、この本の後半ではトレーニングもあるらしいので、取り組んでみたいです。行けるのか？

#### 引用
1. Betsy Seyerほか　SRE サイトリライアビリティエンジニアリング　オライリー　3-4
Uncaught SyntaxError: Unexpected token < in JSON at position 0というエラーの解決方法

Laravelでアプリを開発しており、JavaScriptのAjax
を使っていると下記のようなエラーに遭遇しました。

```
Uncaught SyntaxError: Unexpected token < in JSON at position 0
```

3~4時間ぐらいずっとエラーで悩んでいたけど、こちらの記事（　https://stackoverflow.com/questions/53771865/error-uncaught-syntaxerror-unexpected-token-in-json-at-position-0 )の

>In my experience, Ajax calls returning HTML is a sign that there has been an error in the back end. If you use your browser's developer tools, you'll be able to track your Ajax call and read its response.

という文章が参考になり解決しました。

結論を言うと『コントローラーからjsonを返していなかったから』です。

```
return response()->json(値);
```
と返してあげれば上手くいきました。

以上です。(*´ω｀*)ﾉ
ただのオタクによる自己紹介

ごきげんよう、FluffyMadeCafe（フラッフィーメイドカフェ）と言う、電子工作を中心とした、もの作りのサークル代表をしている、ちゃまおです。

この記事では、サークル名の由来や、代表者の簡単な自己紹介をしようと思います。

#サークル名の由来
FluffyMadeCafeを単語に区切って日本語訳すると・・・「Fluffy：ふわふわ」、「Made：作るを意味するmakeの過去形」、「Cafe：喫茶店」です。某アニメの某喫茶店をベースにして、サークル代表者が好きなメイド（Maid）と、もの作り（Made）をかけています。完全にサークル代表者の趣味嗜好です。でも、活動内容は、真面目。

#サークル代表者の経歴
- 某国立大学で博士（工学）を取得。
- 専門は計算神経科学。
- 使用歴の長いプログラミング言語はC。PythonやMATLABもちょっと分かる。
- プログラミングの際に使用しているエディタはVSCode。
- パソコン環境は、ノートパソコン（Windows 10）と、自作デスクトップパソコン（Windows 8.1 + Ubuntu 18.04.3 LTS）。
- Raspberry Piシリーズのファンだけど、ガチ勢では無い。
- 趣味はオタク活動全般。秋葉原の空気を吸いに行くことが多い。

#Qiitaの運用方針
これまでは、分からない事があったら、海外サイトや、Qiitaの投稿記事を中心に色々と調べて、知識をInputしていました。

これからは、自分の持っている知識をOutputして、誰かの役に立てればいいなと思っています。将来的には薄い本出せたらいいなー（追記：同人誌と商業誌出しました）。
railsのdeviseではhas_secure_passwordはいらない

deviseを使用しており、password_digestを使おうとuserモデルにhas_secure_passwordを追加したら、「undefined method `password_digest=' for #<> Did you mean? password_digest」というエラーが出た。

##結論
deviseはhas_secure_password の代わりにencrypt_passwordを使用している。
よって、userモデルにhas_secure_passwordを追加する必要はない。

マイグレーションファイルを見てみると、

```
t.string :encrypted_password, null: false, default: ""
```

と確かに書いてあった。

参考：https://qiita.com/kents1002/items/4079e3d05d322febe00e
javaの基礎の基礎①

・Java言語とは？
①プログラミング言語の一種です。コンピュータに「何をどうするのか」という指示を出します。
②Java言語は機種依存性が非常に少ない言語です。
　あるコンピュータ上のJava言語で開発したプログラムが他の機種のコンピュータ上でも動作するということです。
③Java言語は「型」の制約が厳しく誤りをおかしにくい言語です。
④使われなくなったメモリは自動的に回収される仕組み(ガーベッジコレクション)が用意されており、メモリの開放忘れなどが起きません。
⑤Java言語はオブジェクト指向言語です。ハードウェアが数多くの部品で構成されているように、プログラムも数多くの部品で構成されています。
　Java言語ではプログラム全体がオブジェクトという部品によって構成されています。
⑥Java言語はマルチスレッドを取り扱うことのできるプログラミング言語です。
　複数のスレッド(動作してる主体)を簡単に扱うことができ、平行プログラミングを行うことが出来ます。

・開発環境
①Java開発環境(JDK)
　JDK(Java Development Kit)はJava言語で使用することができる標準的なクラスが含まれており、実質的にJavaの標準的な開発環境になっています。
②総合開発環境(IDE)
　ソースコードの編集からプログラムの実行、デバックまでを１つの開発環境で　行うことのできる開発環境です。(Eclipseなど)

・Javaのプログラムの書き方
①public class Hallo {
「パブリック　クラス　ハロー」と読みます。publicとclassはJava言語で特別な意味を持つ単語で、
　Halloはこれから作るプログラムにつけた名前です。
　この行は「いまからHalloという名前のクラスを宣言します」という意味です。
　Java言語では大文字と小文字の区別はとても重要です。クラスの名前は大文字で始める慣習になっています。
　中カッコ｛｝の中に書かれている内容がクラスの宣言の範囲を表しています。

②public static void main(String[] args) {
　「パブリック　スタティック　ヴォイド　メイン　(ストリング　アーグス)」と読みます。
　public static voidはJava言語で特別な意味を持つ単語(予約語)です。
　この行ではmainという名前を持つメソッドというものを宣言しています。(メソッドとはクラスに付属している関数のようなもの)
　Javaの仮想マシンは最初にmainという名前のメソッドから実行します。
　mainというメソッドが実行開始位置であり、スタートポイントです。
　｛｝の範囲がmainというメソッドの宣言範囲です。
③System.out.println("Hello!");
　「システム　アウト　プリントライン　(ハロー！)」と読みます。
　System.out.printlnは言葉を画面に表示するメソッドを表しています。そのメソッドへの入力(引数という)が続いてのカッコの中に書かれいます。
　カッコの中にあるのは"Hello!"です。これはHello!という６文字を"という記号ではさんだものです。
　"は二重引用符(ダブルクォーテーション)と呼ばれる記号で、Java言語では文字列を表すためのものです。
　最後の;はセミコロンという記号で、Java言語では処理の一区切りを表すときに使う記号です。
④全体の流れ
　全体としてはHelloというクラスを宣言し、宣言内容としてmainというメソッドが1つ宣言されていました。
　メソッドmainの宣言内容として文字列"Hello!"を表示する文が書かれていました。
　プログラムを書くときは、プログラムの構造がわかるように字下げ(インデント)を行います。

・計算をしてみよう
①加減乗除
　加減乗除とは足し算、引き算、掛け算、割り算のことです。この４つの計算のことをまとめ、四則演算とよぶこともあります。
　「＋」は文字列の連結も行ってくれる。
　Java言語では数をいくつかの型と呼ばれるグループに分けて扱います。Java言語の整数演算では割り切れなかった小数部分は切り捨てられます。

・変数と型
①変数とは何か
　変数とは一言でいえば何かを入れておく箱のようなものです。
　変数という箱に対しできることは「変数を作る(変数宣言)」、「値を入れる(代入)」、「値を見る(参照)」の３つです。
②変数を作る(変数宣言)
　何かを入れておく箱を作ることをjava言語では「変数を宣言する」、あるいは「変数を定義する」といいます。
　変数を定義するときは、プログラムに「int x」と書きます。これで「int」(整数)型の「x」という名前の箱ができました。
　java言語では変数を宣言する場合、必ず「その箱は何を入れる箱なのか」を指示します。箱に入れるモノの種類の事を「変数の型」と呼びます。
③値を入れる(代入)
　変数という箱に何か入れる、すなわち変数に値を入れることを「代入」といいます。
　「x = 4;」とプログラムに書けば、変数「x」に「4」という値を代入したことになります。
　変数に値を代入する場合は、必ず「変数は左辺に書く（x = 4;）」ことを忘れないでください。
　「4 = x;」とは書けません。「＝」という記号は「左辺の変数に右辺の値を代入する」という処理を行います。
　変数への代入は何回でも行うことができます。
　「x = 4;」
　「x = 3;」
　とプログラムに書いた場合、初めの「x = 4;」で変数「x」に「4」が代入され、次の「x = 3;」で変数「x」に「3」が代入されることになります。
　その時、直前に代入された「4」という値は影も形もなくなります。
④値を見る(参照)
　変数の中に入ってるものを、その変数の値といい、変数の値を見ることを「変数を参照する」と言います。
⑤変数の初期化
　変数は宣言と同時に値を定めることもできます。この場合は代入とは呼ばず、「初期化」と呼びます。(int x = 4;)
　「int x ;」と書かれた場合には、変数「x」は未定義の値になります。
⑥java言語の型
　java言語の型は大きく分けると「基本型」と「参照型」に分類できます。
　基本型とは論理値および数値を表す型です。例えば整数を表す「int型」や文字を表す「char型」などが基本型です。
　参照型とはクラス、インターフェイス、配列やenum型を表す型です。文字列を表すstringクラスは参照型です。
QAの私にとって心強かった、バグを出さないエンジニアの特徴3つ

# バグもういやだよォォォ！！！！！！
![tenor.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/893521/e1e3ea45-cc70-1463-661d-c375d74dfe88.gif)
そんな方に読んで頂ければと思っています。

# 自己紹介
モチベーションクラウド開発チームでQAリーダーをしている小島です。
大規模改修から新機能実装まで幅広くテストを行うなかで、多くのエンジニアと協働する機会に恵まれてきました。

# 残念なことに
どれだけベテランになっても**バグは出るもの**らしいです。

だからこそ、**バグと向き合いながらどう気持ちよく開発していくか**こそが大事なのだと感じました。

そう気付かせてくれたのは一緒に働いてきたエンジニアのみんなです。
一緒に働く中で「頼りになるなぁ」と感じたエンジニアの特徴と感謝をまとめます。

# 1. 重要な要件に熱量を注ぐ
**「どこで不具合が出たら重大なインシデントになるか？」
「ユーザー価値の肝となる要件はどこか？」**
と問い続けながら実装を進めてくれるエンジニア。

**限られた時間の中で重要な機能を判別し実装戦略を立てる**方は、バグが出ても顧客影響が軽微な場合が多いです。
裏を返せば、重要ではないと判断した要件は必要に応じリリース速度を重視して下さることもあります。
ザ・目的立脚。

「ユーザー目線で実装する」と言うだけなら簡単ですが、
**コード1行1行のどこがユーザーにとって重要なのか**を考えるのはそう簡単なことではないはずです。すごい。

# 2. 不安点を積極的に共有する
**「この辺の機能がちょっと不安なんだよね。ちょっと厚めにテストしてくれない？」**
**「トランザクションまわりで考慮漏れしやすいから、クエリログまで見てくれない？」**
と頼ってくれるエンジニア。

エンジニアとテスト担当が同じ課題を見て進められるからこそ、一緒に働いていて一切不安を感じさせません。

特に**実装の癖や考え方の傾向を鋭く自己分析している**方はスマートな頼り方をしてくれます。
ここまでくると、弱みを相互補完できる関係を構築する能力なのかもしれません。

息が合いすぎて「我々はゴールデンコンビなのでは！」と運命さえ感じましたが、きっとみんなにそう思わせてしまう凄さがあるんだと思います。

# 3. バグを直すチャンスに貪欲
**「リリースまでにここまで直し切ろう！」
「ここの時間削れたら、あと1個バグ改修できる！」**
と、プロダクトをここぞとばかりに磨き上げるエンジニア。

常に計画の隙間を縫って良いプロダクトをつくろうと行動して下さる方がいると、プロダクトの質を高めることに対するチームの熱量が一気に変わります。
**納得のいくプロダクトをつくることに誇りを持っているエンジニア**と働けることは、正直とても楽しいです。

バグを直すチャンスに貪欲な裏には、プロダクトやコードに対するオーナーシップの高さや「良いプロダクトをつくりたい」という思いがあるようでした。

# 終わりに
テストを「バグを指摘してくる人」としてではなく、**「良いプロダクトを一緒につくる仲間」**だと信じて下さるみんなにいつも感謝しています。

明日の記事は我らがテックリード、@vankobeの記事が配信されます！
「レビューする人も、される人も知っておきたい！開発プロセスごとのレビュー観点チェックリスト」をお楽しみに！
AWS Amplify Admin UIは使いやすいのか

POLアドベントカレンダー4日目担当、[ゲバラ](https://twitter.com/POL53297840)です。
先日発表されたAWS Amplify Admin UIを触ってみます。
そもそもAWS Amplifyって何？という方は[こちらからどうぞ](https://note.com/guevara01/n/n2660e232ca8d)

#AWS Amplify Admin UIとは
Amplifyのバックエンド環境をUI上で設定できる管理画面です。先日の[re:Invent](https://aws.amazon.com/jp/blogs/aws/aws-amplify-admin-ui-helps-you-develop-app-backends-no-cloud-experience-required/) にて発表されました。AWSアカウントを作成しなくても管理画面専用のユーザアカウントを発行することができ、管理ハードルかなり下がりました。最初にアプリを作る場合でもデータモデリングとローカルでテストまでならAWSアカウントが必要ないそうです。AWS上にデプロイするときAWSアカウントが必要になります。

#AWS Amplify Admin UIの始め方
##最初からアプリを作成する場合
Amplifyが提供しているサンドボックスからアプリを作り始めることができます
https://sandbox.amplifyapp.com/getting-started

ベースとなるデータモデルを選択したり
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/541992/cea5869d-e5ee-0881-a9ba-25f22542fc76.png)

UI上でデータモデリングすることができます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/541992/3f851d38-340d-4a77-3626-42bba888de82.png)

ローカルでアプリを動かすことができます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/541992/706a8734-16b2-904d-420b-baf48386f8a6.png)

AWS上にデプロイするためにAWSアカウントと紐付けます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/541992/09886ce0-b427-f240-c750-5fcadcf478a3.png)


##すでにアプリを作成している場合
Amplifyコンソールのメニューに「Admin UI management」が追加されており、そこからAdminUIを使用するためにOnにします
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/541992/7229c2bb-02a9-8178-922e-aac0a59a6307.png)

しばらく待つとバックエンド環境ごとにAdminUIのURLが発行されます。この画面からAdminUIドメインを変更したり、管理ユーザを作成することができます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/541992/15667601-83dd-2b36-0df1-6f9621e9421c.png)
感動したのはAmplify CLIもAWSアカウントが必要になくなりました。amplify pullでAdminのログイン画面に遷移しログインすることでCLIが使用することができます。

#実際のUI
管理画面にログインするとこんな感じ。AWSにしては見やすい。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/541992/8ab9e16c-c753-e0bb-664f-9466fa66b7a8.png)

##データモデリング
前まではスキーマのコードを書いて定義していましたが、UIで定義することができます。非常に直感的に操作することができてわかりやすいです。リレーションも貼りやすい。難点は@Authのようにモデルの権限周りはどうやら設定できなかったのでここはスキーマで定義する必要がありそうです。ここはアップデートに期待です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/541992/df7366fb-7d5a-3548-c389-722f51403f81.png)

##ユーザ・グループ管理
ユーザ・グループ管理もすっきりしたUIで行うことができます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/541992/0ce72cbd-489a-9c72-2a13-46c0ea433a72.png)

##認証設定
こちらもわかりづらいCognaiteのUI比べ、必要な項目のみに絞られて設定しやすいUIに変わっています。OAuthやサインインのリダイレクトURLなどが設定できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/541992/d302b226-59da-815a-c1b5-828c0a95988c.png)

##コンテンツ管理
こちらは使ってみてませんがデータモデルのデータを編集できるコンテンツ管理が可能となりました、非エンジニアでもアプリのコンテンツをここで作成できるようになります。マークダウンで書けるとか最高。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/541992/c919b2cb-f8c7-e237-8b09-86138a32c8f2.png)
参考：https://docs.amplify.aws/console/data/content-management

いかがだったでしょうか。バックエンド環境はCLIやコードベースで管理していたものが、UI上で管理できるようなることでますますAmplifyが使いやすくなりそうですね。広がれAmplifyの輪！！

明日はPOLのインフラ守護神[@takahiro-yamada](https://qiita.com/takahiro-yamada)さんです。
AWS Lambda LayerのTerraform化でハマったこと

# この記事の目的
AWS Lambda LayerをTerraform化しました。
一部手間取ったので、自分と同僚用にメモを残します。

# まず結論
最終的に出来上がったTerraformはこちらです。

## Terraform version
```
$ terraform version
Terraform v0.12.24
```

## Layerを使用するLambda側
```
resource "aws_lambda_function" "main_lambda" {
  filename      = "../../lambda_function/test_lambda/test_lambda.zip"
  function_name = "test_lambda"
  role          = aws_iam_role.lambda_iam_role.arn
  handler       = "lambda_function.lambda_handler"
  timeout       = 30
  runtime       = "python3.8"
  layers        = ["${aws_lambda_layer_version.lambda_layer.arn}"]
}
```

## Layer側
```
resource "aws_lambda_layer_version" "lambda_layer" {
  layer_name          = "test_layer"
  filename            = "../../lambda_layer/test_layer/test_layer.zip"
  compatible_runtimes = ["python3.8"]    # Lambda関数と互換性のあるruntimeを設定
  source_code_hash    = "${filebase64sha256("../../lambda_layer/test_layer/python.zip")}"
}
```

# ハマったところ①
Layerのfilenameに設定しているzipファイルの圧縮単位にコツがいった。

初めは、`../../lambda_layer/test_layer/test_layer.py`の`test_layer.py`をzip化していた。
ところが、Terraforを実行してLambdaとLayerが作成されるも、LambdaからLayerが読み込めない。

どうやら、LayerはLambda内の`/opt/python`に展開しないといけないらしい。
そこで、Layerを`../../lambda_layer/test_layer/python/test_layer.py`に置き、`python`ごとzip化したら解決。

# ハマったところ②
Layerにはバージョンというものがあり、Layerのpyファイルを更新して再度アップロードすると、Layerのバージョンが上がるようになっている。
古いバージョンのLayerも残っており、使用することができる。
おそらく、Lambda Aではバージョン1のLayer、Lambda Bでは最新バージョンのLayerを使用したい、という使い分けのためだろうと思われる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/927086/4a4a6508-a0e6-c6db-d4ce-dcd8ef53730f.png)

初め、以下のように`source_code_hash`を設定していなかった。
すると、`test_layer.py`を更新して`test_layer.zip`を再作成しても、Terraform実行後のLayerのバージョンが上がらない。ずっと1のままだ。

```
resource "aws_lambda_layer_version" "lambda_layer" {
  layer_name          = "test_layer"
  filename            = "../../lambda_layer/test_layer/test_layer.zip"
  compatible_runtimes = ["python3.8"]    # Lambda関数と互換性のあるruntimeを設定
}
```

`source_code_hash`を設定すると、Layer自体のバージョン及びLambdaにひもづくLayerのバージョンも最新のものに上がるようになった。

でもこれ、今はいいけどいずれTerraform上でLambda毎にLayerのバージョン指定したくなったらどうするのか……
`aws_lambda_layer_version.lambda_layer.arn`はバージョン付きのARNだけど、`aws_lambda_layer_version.lambda_layer.layer_arn`はバージョンなしのARNらしいので、その辺をうまく使うのかもしれない。
必要になったら検証します。報告するかは不明。

以上
JavaのWebアプリケーションをDockerのマルチステージビルドでデプロイする

本記事は[東京学芸大学 櫨山研究室 Advent Calendar 2020](https://qiita.com/advent-calendar/2020/hazelab)の四日目の記事になります．

# 概要

- Javaで作成したWebアプリケーションをDockerを使ってデプロイする

本記事のコードは以下のGitHubリポジトリで公開しています．

<a href="https://github.com/wf-yamaday/java-docker-sample-app"><img src="https://github-link-card.s3.ap-northeast-1.amazonaws.com/wf-yamaday/java-docker-sample-app.png" width="460px"></a>

# 動作させるアプリケーション

> ~~Building Java Web Applications, https://guides.gradle.org/building-java-web-applications/~~
> Building Java Web Applications, https://medium.com/@tutorialspointexamples/building-java-web-applications-760d656061e4

にあるサンプルアプリケーションをDockerで動作させてみます．

※Gradleの公式ドキュメントがリンク切れだったので同じコードを紹介している別のリンクを載せています．

# マルチステージビルド

コンテナを用いた開発では本番環境向けにサイズの小さいDockerイメージを作成することは重要になります．
よってビルド後の生成物だけを含んだイメージを作成するのが理想となります．

Dockerのマルチステージビルドはこのような要求を簡単に実現する方法になります．

今回のJavaのWebアプリケーションをマルチステージビルドの流れを図に起こすと以下のようになります．

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225901/41f9250c-19dc-18a1-cbd9-4070074f82bd.png" width="800">


はじめに**ビルドステージ**と命名したステージでソースコードをビルドし`warファイル`を生成します．
その次の**本番用ステージ**と命名したステージで`warファイル`をjettyに配備します．

# Dockerfile

この流れを記述した`Dockerfile`は以下のようになります．

```Docker
# ビルドステージ
FROM adoptopenjdk/openjdk8:alpine as builder
WORKDIR /webapp

# プロジェクトの配置とビルド
ADD ./ ./
RUN ./gradlew war

# 本番用ステージ
FROM jetty:9-jdk8

EXPOSE 8080

COPY --from=builder ./webapp/build/libs/sample-app.war /var/lib/jetty/webapps
```


公式の[jettyイメージ](https://hub.docker.com/_/jetty)では`/var/lib/jetty/webapps/`配下に`war`ファイルを配備することでデプロイが完了します．

# Dockerイメージのビルドとコンテナの起動

dockerイメージのビルドし，コンテナを起動しアプリケーションが正常に動作しているかを確認します．

```sh
docker image build -t sample-app:latest .
docker container run -p 8080:8080 sample-app:latest
```

正常に起動したら，http://localhost:8080/sample-app/ にアクセスをします．
以下の画面になっていたら成功です．

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225901/6d9ea5ac-0cfb-c094-5a75-cb5dd2b66d46.png" width="450">

テキストフィールドに`world`と入力し`Say Hello`ボタンをクリックしましょう．

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225901/c58ef0ee-1723-d318-21f0-33cb2fa45819.png" width="450">

きちんと`Hello, world!`と出力されました．
これで正常に動作していることが確認できました．

# Docker Imageのサイズを確認

サンプルアプリケーションでそもそものアプリケーションのサイズがとても小さいので比較にもなりませんがDockerのイメージサイズを確認しておきます．

```sh
# ベースのjettyのイメージサイズ
$ docker image ls jetty            
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
jetty               9-jdk8              12fc9041849d        10 days ago         525MB

# アプリケーションを配備したイメージサイズ
$ docker image ls sample-app
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
sample-app          latest              4096cac4f49a        10 minutes ago      525MB
```

本格的な開発ではDockerイメージの大きさがどの程度かを確認する癖をつけると良いでしょう🙇‍♂️

# 参考文献

マルチステージビルドの利用，https://matsuand.github.io/docs.docker.jp.onthefly/develop/develop-images/multistage-build/
Python小技：文字列から特定の文字コードに含まれない文字を削除する

文字列 `string` から、特定の文字コード（サンプルではCP932）に __含まれない__ 文字を削除するためには以下のようにするのがおそらく簡単です。

```python
string = string.encode('cp932', errors='ignore').decode('cp932')
```

要するに、以下の処理をしています。

1. 最初に文字列を CP932 でエンコードします。この際エンコードできない文字を削除するために `encode` メソッドに `errors='ignore'` をオプションとして渡します。
2. 出来上がったバイト列を再度デコードして文字列に直します。

## 補足: 実験した環境

```python
> py --version --version
Python 3.9.0 (tags/v3.9.0:9cf6752, Oct  5 2020, 15:34:40) [MSC v.1927 64 bit (AMD64)]
> py
>>> string = "Some string \u200b" # \u200bはCP932の範囲外
>>> print(len(string))
13
>>> string = string.encode('cp932', errors='ignore').decode('cp932')
>>> print(string)
Some string
>>> print(len(string))
12
```
配列内に特定の部分配列が存在するか判定する

## Code

```python
target = [1, 2, 3, 4, 5, 6, 7, 8, 9]
pattern = [2, 3]

found = False
for i in range(len(target) - len(pattern) + 1):
    if pattern == target[i:i+len(pattern)]:
        found = True
        break

print(found)
```
文字列データの送受信方法




#はじめに
こんにちは。
今回は文字列データの送受信方法が分からないという人の為に説明します。
#POSTとGETの違いとは?


form method="POST" action="testform.php"


まずPOSTの事について説明します。どちらもデータ送受信の時に使うコマンドですが、GETとはURLの最後に値を付与するので、外部からも情報を見られてしまいます[1]。POSTというのは、URLに値を付与しない方法なので大事な情報を見られずに済むという利点が有ります[1]。しかし、POSTというのは文字数が制限されていますので、1つのところに多くのデータや文字を書くことには適していません[2]。
それに対しGETだと文字数の制限がありませんので、たくさんの文字を書く時に適しているコマンドです[2]。
次にactionについて説明します。action属性を使う事で送信先を指定することが出来ます。この場合ですとtestform.phpにデータを送信します。次にこのtypeについて説明します。このtypeで"text"と指定する事により、テキストボックスでデータを送信することが出来ます。



#参考文献
[1]https://kyo-blog.com/php-get-post/#GETPOST-2
[2]https://php-junkie.net/beginner/reserved_variables/get_post/#diff
チャンピオン - ティアリスト

![微信截图_20201204183742.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/471610/3a3a1ab0-3b6a-1713-d1dc-0d056eb66b56.png)
![微信截图_20201204184051.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/471610/74dc2317-8e78-03ea-8c42-75c1110ddc45.png)
![微信截图_20201204185212.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/471610/7a6f684f-ddfe-2b02-2d32-f54903a993ca.png)
AWSの基礎知識

##はじめに

本日はAWS（Amazon Web Services)の基礎中の基礎について投稿していきたいと思います。

これまで、herokuでのデプロイ経験しかありませんでしたが、皆様の記事と書籍を参考にしながら、AWSの知識を蓄えていきたいと思います。


##そもそもAWSとは？

私たちが普段利用しているAmazon様が提供しているクラウドコンピューティングサービス。
（クラウドコンピューティングサービス：サーバーやネットワークなどをインターネット経由で貸してくれること）

昔から、サーバーを貸してくれる会社はあったそうですが、AWSの特徴は、いろんな会社からそれぞれに借りなければいけなかった、ウェブサービスを提供するために必要なインフラたちを、まとめてAWSで調達できること！


##AWSのサービスについて

実に160種類以上ものサービスを提供しているみたいですが、その中でも代表的？なものについて取り上げてみたいと思います。

**Amazon EC2**
サーバー、OS、ソフトウェアなどを一式用意できるもの

**Amazon S3**
インターネット上に画像などのデータを保存する箱を借りられるサービス（Herokuは再起動すると画像が消えてしまうので助かっています。。。）

**Amazon VPC**
AWSアカウント専用の仮想ネットワーク。ルートテーブルやネットワークゲートウェイの設定などをして、仮想ネットワーキング環境を構成。

**Amazon RDS**
リレーショナルデータベースの製品（MySQL,MariaDBなど)をクラウド上で利用できるサービス。（私の実装ではMariaDBを使用予定です）

**Amazon Route 53**
DNS（ドメインネームサービス）。


他にも数えきれないほどのサービスがあるみたいで、全部使いこなしてみたいなあと思っていますが、果てしないことのように思えてきました。。。この続きは徐々に更新していきます。。。
php artisan serveに任意のphp.iniを指定する方法

#結論
```
php -c php.ini artisan serve
```

#背景
php artisan serveで動かしている開発用のサーバー上で大きなファイルをアップロードする必要があり、実際にアップロードしたところIlluminate\Http\Exceptions\PostTooLargeException とエラーが出た。

ここはphp.iniを変更すれば通るだろうと考え、upload_max_filesizeとpost_max_sizeを変更したものの、なぜか同じエラー。phpinfoで確認すると値はきちんと更新されている。

#原因
いろいろ調べてみたところ、php artisan serveは別のphp.iniを読みに行っているということまでは判明。

#解決
ただ、どのphp.iniを読みに行っているのか分からない。

php.iniと同じディレクトリにphp-cli.iniを作成するとそれを読みに行ってくれるとか、その他色々な情報があったものの結局、動いたのは冒頭で示したやり方。

元々読みに行っていたファイルを変更したほうがスマートな気もするが、Webサーバーで使用される設定ファイルと同じものを指定できるならそれはそれで分かりやすくて便利な気がする。

コマンド中での指定される"php.ini"は現在のWebサーバーで使用されているファイルを見に行くようなので、php -iで場所を確認してから編集する。

```
$ php -i | grep php.ini
Configuration File (php.ini) Path => /etc/php/7.4/cli
Loaded Configuration File => /etc/php/7.4/cli/php.ini
```

編集後、php artisan serveを実行すると変更したパラメーターが反映された設定でサーバーが起動する。
Overleaf に論文の語数をカウントさせる

卒論や修論などの学位論文では「本文（Introduction から Conclusion まで）が 5000 語以上あること」などというように語数指定がされている場合があるかと思います。
自分で語数をカウントするのは大変ですが、Overleaf には語数カウント機能が付いています。左上の「メニュー（Menu）」から「文字数（Word Count）」をクリックすると、語数が表示されます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/233069/c6d2ce18-2dad-b8e5-3f01-24f1da508640.png" width="400px">

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/233069/a9d5e4cf-ab3e-6277-5efa-a6ff5eda91ca.png" width="600px">

この語数カウント機能の詳細は以下のドキュメントに記載されています。

- [Is there a way to run a word count that doesn't include LaTeX commands?](https://www.overleaf.com/learn/how-to/Is_there_a_way_to_run_a_word_count_that_doesn't_include_LaTeX_commands%3F)

このドキュメントによると、**references, headers, captions, floats, displayed math etc are not included in the count.** とあります。つまり、引用部・セクションの見出し・図表のキャプション・display スタイルの数式は語数にカウントされません。
逆に、アブストラクトや謝辞はデフォルトではカウントされています。これを防止するためには、カウントして欲しくない部分を `%TC:ignore` と `%TC:endignore` で囲います。例えば [東京大学理学部情報科学科 卒業論文 テンプレート](https://ja.overleaf.com/latex/templates/dong-jing-da-xue-li-xue-bu-qing-bao-ke-xue-ke-zu-ye-lun-wen-tenpureto/dypcftrrrcct) においては

```tex
%TC:ignore
\begin{eabstract}
Abstract abstract abstract, 
abstract abstract abstract abstract abstract abstract. 
Abstract abstract, abstract abstract abstract abstract abstract abstract: 
...
Ack ack ack. 
\end{acknowledge}
%TC:endignore
```

というように eabstract の開始部から acknowledge の終了部までを囲うことで、本文のみの語数カウントが可能になります。
Webサーバー上のPHPをhtmlの拡張子で表示させたい。

そんな時はこのような記述を行うと多分うまくいきます。

```html:.htaccess
RewriteEngine on
RewriteBase /
RewriteCond %{REQUEST_URI} \.html$
RewriteRule ^(.*).html$ $1.php [L]
```
PhpUnit 備忘録: 処理の後半に呼ばれるはずのメソッドに処理が辿り着いているかをテストする

## こういう処理があるとします

```php7
    /**
    * キャッシュにdataがあればそれを返却
    * なかったらDBからのdataを取ってきてから返却
    * @return array
    */
    public function get()
    {
        $dataFromCache = $this->getCachedData();
        if (!empty($dataFromCache)) {
            return $dataFromCache;
        }

        $dataFromDb = $this->getDataFromDb();
        if (!empty($dataFromDb)) {
            return $dataFromDb;
        }

        throw new \RuntimeException('no data anywhere');
    }
```

## テストしたい事

テストしたいのは、この処理の主な仕事である「キャッシュされたdataがなかったら、DBからのdata取得をする」こと自体が**できているかどうか**です。
実際にDBにある値をちゃんと取得できているかどうかは、 getDataFromDb() をテストすることで確認するので、今はそこは見なくていいです。

## 今までよく書いていたテストコード

大体、こんな流れのUTを書いていました：

- getCachedData() の戻り値が空になるような状態を作り
    - キャッシュファイルを空で作り成すか消す
- getDataFromDb() が呼ばれて結果で get() の返り値として事前にDBにセットしたdataが取得されているかを確認する

テスト実行環境にそもそもDBも必要ですし、DB内にテストデータを事前に用意しないといけないなど、手間が結構かかるやり方です。

## 今回覚えた新しい方法

社内でやった勉強会で別のやり方もあると聞いてやってみたら、UTの書く手間も実行コストも少なそうと思ったので、備忘録を残すことにしました。

どうやってテストするかというと：

- get()の内部で呼ばれている2つのメソッドをモックします
- ちゃんと2つ目のメソッドに処理がたどり着くような条件を作ります
    - 具体的に、getCachedData() の返り値が空になるようにします
- getDataFromDb() が呼ばれたかどうかだけを確認します

テストコードの例はこちら：

```php7

    /**
     * @test
     * @covers get()
     */
    public function testIfGetCallsLastMethod()
    {
        $fakeClass = $this->getMockBuilder('MyClass')
        ->setMethods(['getCachedData', 'getDataFromDb'])
        ->getMock();

        //ここで getCachedData() の返り値が空になるようにしておく
        $fakeClass->method('getCachedData')->willReturn([]);

        //getDataFromDb()から何も返されないとExceptionが発生するのでなにかを返す
        $fakeClass->method('getDataFromDb')
            ->willReturn(['param' => 'result']);

       // getDataFromDb()が1回呼ばれたことを期待するとして、get()を実行させる
        $fakeClass->expects($this->once())->method('getDataFromDb');
        $fakeClass->get();
    }
```

## 上記を実行するに使った環境

- php 7.0.2
- PHPUnit 5.2.3

ちなみに今回は Mock を使っていますが、 Prophecy というライブラリもあってそれも面白そうで今度やってみようかなと思います。
今回は ```expects($this->once())``` を使って「一回実行されたか」をチェックしているのですが、Loop 内でイテレーション回数に応じた実行回数をテストする英語の記事をネットで見かけたのでそれも今度試そうかなと思います。
高位合成言語アセンブラを作る。 その15

# 概要

高位合成言語アセンブラを作る。
練習問題、2bit乗算器、やってみた。

# コードを書く。


```
make 12
in 0 3
and 0 2 4
and 1 2 5
and 1 3 11
and 0 3 6
xor 5 6 10
and 5 6 7
xor 4 7 9
and 4 7 8
out 8 11

```

# コンパイル結果

```
module x(input a, input b, input c, input d, output i, output j, output k, output l);
    assign e = a & c;
    assign f = b & c;
    assign l = b & d;
    assign g = a & d;
    assign k = f ^ g;
    assign h = f & g;
    assign j = e ^ h;
    assign i = e & h;
endmodule

module testbench;
    reg a, b, c, d;
    x u(.a(a), .b(b), .c(c), .d(d), .i(i), .j(j), .k(k), .l(l));
    initial
    begin
        $display("a b c d i j k l ");
        $monitor("%b %b %b %b %b %b %b %b ", a, b, c, d, i, j, k, l);
        a = 0; b = 0; c = 0; d = 0; #10;
        a = 0; b = 0; c = 0; d = 1; #10;
        a = 0; b = 0; c = 1; d = 0; #10;
        a = 0; b = 0; c = 1; d = 1; #10;
        a = 0; b = 1; c = 0; d = 0; #10;
        a = 0; b = 1; c = 0; d = 1; #10;
        a = 0; b = 1; c = 1; d = 0; #10;
        a = 0; b = 1; c = 1; d = 1; #10;
        a = 1; b = 0; c = 0; d = 0; #10;
        a = 1; b = 0; c = 0; d = 1; #10;
        a = 1; b = 0; c = 1; d = 0; #10;
        a = 1; b = 0; c = 1; d = 1; #10;
        a = 1; b = 1; c = 0; d = 0; #10;
        a = 1; b = 1; c = 0; d = 1; #10;
        a = 1; b = 1; c = 1; d = 0; #10;
        a = 1; b = 1; c = 1; d = 1; #10;
        $finish;
    end
endmodule





```

# 成果物

https://embed.plnkr.co/plunk/JTHP5cEUbaJ5P4uT

# 真理値表で確認。

![無題.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/6ec204e3-d08f-ae37-a0c8-8328b86c50bf.jpeg)

# 成果物

https://embed.plnkr.co/plunk/cnQm2JpfH7kOozKj

# 回路図で確認。

![無題.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/602df181-d865-b13a-d6d3-e7344676b493.jpeg)


# 成果物

https://embed.plnkr.co/plunk/lI2l8FZqWXwCuIyB

# 実行結果

```

a b c d i j k l
0 0 0 0 0 0 0 0
0 0 0 1 0 0 0 0
0 0 1 0 0 0 0 0
0 0 1 1 0 0 0 0
0 1 0 0 0 0 0 0
0 1 0 1 0 0 0 1
0 1 1 0 0 0 1 0
0 1 1 1 0 0 1 1
1 0 0 0 0 0 0 0
1 0 0 1 0 0 1 0
1 0 1 0 0 1 0 0
1 0 1 1 0 1 1 0
1 1 0 0 0 0 0 0
1 1 0 1 0 0 1 1
1 1 1 0 0 1 1 0
1 1 1 1 1 0 0 1




```


以上。
MySQL接続エラー　<自分メモ>

###環境
mac os 11.0.1
appコンテナ　php:7.4-apache
dbコンテナ　mysql:5.5(MySQLのバージョンはHerokuアドオンのClearDBに合わせている)

####エラー内容

```
Warning: mysqli_connect(): (HY000/2002): php_network_getaddresses:
getaddrinfo failed: Name or service not known in /var/www/html/book_log.php on line 3
```
ここはホスト名が、localhostだったのでエラーになったみたいです。

参考記事
[DockerのLAMP環境でPHPからMySQL接続に詰まった話](https://qiita.com/gat3ta/items/562e227e1c778445cced)
[Dockerで動かしているMySQLに作成したユーザーでPHPから接続できないときの対処方法](https://codeaid.jp/blog/docker-mysql-php/)

再度エラー

```
Warning: mysqli_connect(): (HY000/2002): php_network_getaddresses: 
getaddrinfo failed: Name or service not known in /var/www/html/book_log.php on line 3
```
翻訳
php_network_getaddresses：getaddrinfoが失敗しました：3行目の/var/www/html/book_log.phpで名前またはサービスが不明です

名前とサービス名が間違えているのか！

host名を、mysqlからdbに変更したが、またしてもエラー

```
Access denied for user 'book_log'@'172.20.0.3' 
(using password: NO) in /var/www/html/book_log.php on line 3
```
接続の際に,パスワードを入力していなかったので、$passwdの部分を追加！

書式
```mysqli_connect($host,$username,$passwd,$dbname,$port,$socket)```

今回は、```$link = mysqli_connect('サーバー名','ユーザー名','パスワード')```の部分まで入力!


これで無事接続できました!

何かお気づきの点がありましたらコメントやアドバイスいただけますとありがたいです！！



参考にさせていだきました。
ありがとうございます!

[PHPからMySQLに接続する方法を簡単に解説]
(https://blog.codecamp.jp/php-mysql)

[DockerでPHPエラー「php_network_getaddresses: getaddrinfo failed: Name or service not known」](https://tech.pjin.jp/blog/2018/02/27/docker%E3%81%A7php%E3%82%A8%E3%83%A9%E3%83%BC%E3%80%8Cphp_network_getaddresses-getaddrinfo-failed-name-or-service-not-known%E3%80%8D/)
Wio Terminalの保護シート（低反射タイプ）

twitterで流れてきたコレ。
https://twitter.com/visavis_miyavix/status/1322052870108229632
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109634/74ed62c8-c2b5-634c-f457-928f61aadebe.png)

ミヤビックスというところから、Wio Terminalの保護シートを販売しているらしい。

https://www.visavis.jp/shop/shopbrand.html?search=Wio%20Terminal
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109634/52f1787b-c393-1f5e-f7db-b07f9f7ae071.png)

いつも、写真撮るときに自分が映りこんじゃって照明ズラしたり変な体勢になったりと、困っていたんだよねー、ということで**低反射タイプ**を購入。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109634/24c870c9-ab09-0523-e98c-f1d4411503c9.png)

保護シートとホコリを拭くシートと、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109634/0308d553-a844-823b-b27e-bc99b34a8275.png)

さらに、クロスとウェットシートが付いていました。親切。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109634/0cdc87db-19f7-3138-d523-701f63caab40.png)

わざと液晶に映りこんじゃって取った写真がこちら。

保護シート無しと、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109634/96f81e6e-4cf9-0f88-e267-04b5ada371fb.png)

保護シート有り。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109634/43a4c12f-da08-27f0-0b92-88f9e2ec87d5.png)

指紋も付きにくくなって、スバラシイ商品でした。
セッションマネージャを導入する話

こんにちは。CAMPFIRE SREのsakakibaraです。

現在、セッションマネージャをプロダクトに導入中で、今回はそのセッションマネージャについてまとめてみたいと思います

## セッションマネージャって何？
> Session Manager はフルマネージド型 AWS Systems Manager 機能であり、インタラクティブなワンクリックブラウザベースのシェルや AWS Command Line Interface (AWS CLI) を介して Amazon Elastic Compute Cloud (Amazon EC2) インスタンス、オンプレミスインスタンス、および仮想マシン (VM) を管理できます。Session Manager を使用すると、インバウンドポートを開いたり、踏み台ホストを維持したり、SSH キーを管理したりすることなく、監査可能なインスタンスを安全に管理できます。また、Session Manager を使用すると、マネージドインスタンスへの簡単なワンクリックのクロスプラットフォームアクセスをエンドユーザーに提供しつつ、インスタンスへの制御されたアクセス、厳格なセキュリティプラクティス、完全に監査可能なログ (インスタンスアクセスの詳細を含む) が要求される企業ポリシーに簡単に準拠できます。

https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/session-manager.html

とありますが、`インスタンスに便利で安全に接続できるもの` です。


## セッションマネージャー入れると何がよいの？
- インスタンスへのアクセスの制御がしやすい
- 行動ログがとれる
- 鍵管理から解放される
- SSHポートを閉じれる

### インスタンスへのアクセス制御がしやすい
セッションマネージャでインスタンスへのアクセスを管理すると、管理者はIAMポリシーのみ気にしていればよくなります。
セッションマネージャ経由でインスタンスにアクセスする場合は、awsコマンド or コンソール画面からアクセスすることになるので、IAMポリシーで権限がないユーザーはインスタンスにアクセスできなくなります。

### 行動ログがとれる
![スクリーンショット 2020-12-04 17.34.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/769487/8c923c47-c6a9-8414-7d87-bcf0d47ccede.png)

何かあったときに、ユーザがなにをしたか知りたいですよね？
セッションマネージャなら、ユーザーの行動ログがs3バケットと連携するだけで簡単にとれます。

### 鍵管理から解放される
IAMユーザーでインスタンスへのアクセスを制限するため、鍵管理から解放されます

### SSHポートを閉じれる
SSHでのアクセスを許容しなくても良いため、SSHポートを閉じれます。
つまり、セキュリティグループの管理もなくなります。
→地味に嬉しい


## セッションマネージャ導入大変なの？
めっちゃ簡単です。
セッションマネージャを利用するためには`ssm-agent` が必要ですが、最新のAmazonLinuxにはデフォルトでインストールされています。
そのため、`AmazonEC2RoleforSSM`ポリシーをもつIAMロールをEC2インスタンスに設定すればOK

※古いAMIイメージの場合は、ユーザーデータにssm-agentのインストールするコマンドを追記しておくだけ

## まとめ
規模が大きかったり、個人情報を扱うプロダクトの場合は、セキュリティは常に意識したいものです。
セッションマネージャなら、すべてのポートを塞ぐことができるので安全かつ、お手軽に導入できるので、ぜひ試してみてくださいー！
Intelli JでGitHub操作する

## 概要
Intelli Jを使ってGitHubに接続し、Pull requestをするまでの操作メモです。

## Intelli Jについて
JetBrainsが提供しているJava系の言語での開発をメインとしたIDEです。
(Java, Kotlin, Groovy, Scalaなど)
[ダウンロードURL](https://www.jetbrains.com/ja-jp/idea/download/)

IntelliJ IDEA Community版はオープンソースで利用することが可能です。

今回はterraformの改修に当たって利用しましたが、Pluginとして`HashiCorp Terraform / HCL language support`を追加することで入力補完やsyntax highlightなどの機能を使うことができます。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252317/4ae8676f-8afc-10f0-6c1f-52586b6cf530.png" width=70%>

## 環境
IntelliJ IDEA 2020.1.1(Community Edition)

## GitHubアカウント登録
GitHubにログインした状態で`preferences`→`Version Control`→`GitHub`を開き、`Add Account`をクリックします。 Intelli JにGithubアカウントを登録できます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252317/f4b9f3e5-2419-49e1-ebb6-66568d23503c.png" width=70%>

### git clone
上部メニューの`VCS`→`Git`→`clone`から`GitHub`を選択すると、アカウントに紐づくリポジトリを選択出来るのでcloneします。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252317/cf523d23-270b-1d9b-58d0-851c3470ee63.png" width=70%>

### git brunch
画面右下にローカルのブランチが表示され、クリックすると派生元を指定して新しいbrunchを作成出来ます。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252317/920721bd-ad6b-8585-d55a-2d7788faef35.png" width=50%>

### git commit
画面右上のcommitボタンを押すとcommitされます。changelistを押すとdiffで変更内容を確認出来ます。
問題なければ左下のcommitボタンによりcommitが出来ます。
![ezgif.com-gif-maker.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252317/cd6c0c56-249e-7b7c-d077-551479681d4d.gif)

### git pull
上部メニューの`VCS`→`Git`→`pull`を選択するとPull画面が表示され、Rootやbranch、オプションを指定してpullすることが出来ます。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252317/f9045dba-6fcd-1389-7c09-8fbe06061d8b.png" width=70%>

### git push
上部メニューの`VCS`→`Git`→`push`を選択するとPush画面が表示され、diffで変更内容を確認しpushすることが出来ます。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252317/4142a7db-5873-68cf-fc12-46718e8084a5.png" width=70%>

### git brame
ファイルの行番号を右クリックし`Annotate`を選択するといつ誰が変更したかが表示されgit brameが確認できます。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252317/134168a6-5873-1a09-67c7-5dad795cfbcf.png" width=70%>

### pull request
上部メニューの`VCS`→`Git`→`Create Pull Request`を開き、必要事項を入力し、OKをクリックすることでPull Requestを作成することができます。このままレビューも行えます。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252317/d613d835-d47b-52ad-f3af-363d1d64f7aa.png" width=70%>

Github画面にも反映されています。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252317/c6bf478f-3ed5-1678-f83c-375e52d6bd44.png" width=80%>

## 結果
簡単なGitHub操作についてIntelli Jで行うことが出来ました。
CUIで視覚的に操作出来るので初心者でも分かりやすいです。

## 参考
https://blog.mmmcorp.co.jp/blog/2020/02/02/compare-vscode-intellij/
https://dev.classmethod.jp/articles/intellij-idea-pull-request/
EC2上のCakephp4でRDSを使う

# 前提
EC2(Amazon Linux 2 AMI)にCakePHP4をインストールしてあることを前提としています。
今回、PHPのversionは7.4とします。
基本的に[前回の投稿](https://qiita.com/Aurum64/items/96ede43b1e5cdedfaa2f)の続きです。

# RDSの立ち上げ
RDSの立ち上げは[公式サイト](https://aws.amazon.com/jp/getting-started/hands-on/create-mysql-db/)にもありますのでここでは省略します。
初心者の方は[こちら](https://n2p.co.jp/blog/tech/serverside/rds/)がおすすめです。

# MySQLとPHP拡張モジュールのインストール
MySQLとそれに繋ぐためのPHP拡張モジュールをインストールします。

```
$ sudo yum install -y mysql
$ sudo yum install -y mysql57-server php74-mysqlnd
```
以下のコマンドで先ほど立ち上げたRDSに接続できると思います。

```
$ mysql -h db-resume.crcdiqvbtctf.ap-northeast-1.rds.amazonaws.com -P 3306 -u admin -p
Enter password: (パスワードを入力)
Server version: 8.0.20 Source distribution

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MySQL [(none)]> 
```

# Cakephp接続設定
git管理下にあるconfig/app.phpにデータベースのパスワードやらをのせるのはまずいと思いますので、
接続情報は app.php ではなく、デフォルトでgitignoreされている app_local.php に書いておくのが無難だと思います。

```php
<?php
return [
    // 他の設定
    'Datasources' => [
        'default' => [
            'className' => 'Cake\Database\Connection',
            'driver' => 'Cake\Database\Driver\Mysql',
            'persistent' => false,
            'host' => 'testdb.abcdefghijkl.ap-northeast-1.rds.amazonaws.com',
            'username' => 'cakephp',
            'password' => 'secret',
            'database' => 'testdb',
            'encoding' => 'utf8mb4',
            'timezone' => 'Asia/Tokyo',
            'cacheMetadata' => true,
        ],
    ],
    // 他の設定
];
```
port番号を設定しなくても自動で探してくれるらしいです。
Oracleのテーブルに登録されているデータをCSV形式で出力する。

# TL;DR
OracleのテーブルからデータをCSV形式で出力したい場合、SQLDeveloperなどに機能で出力するのが一番手っ取り早いが、やむを得ない理由でSQL*Plusを利用して出力したい場合に、Oracle12.2以降のSQL*Plusであればコマンドを利用して出力できるようになっているのでそのメモ。

# コマンド
**SET MARKUP CSV [ON] [[DELIMITER '<任意の記号>'] [QUOTE \<ON OR OFF\>]]**

```sql
SQL> select * from test_manage_table where report = 650;

-->結果
"KAISYA","FUNCTION","REPORT","IDENTIFIER","SELECT_ORDER","ITEM_ORDER","MASTER_DIV","MASTER_KAISYA","MASTER_ID","UNION_SPECIFY","SYMBOL1","SYMBOL2","COMPARISON","LANG_ID","CONTENTS1","CONTENTS2","UPDATE_DATE","UPDATE_MAN"
1,214,650,3,1,7,"0",0,0,"0",,,1,,"部門",,"20-12-04","TEST"
1,214,650,5,1,4,"0",0,0,"0",,,1,,"H170",,"19-07-30","TEST"
```

- 文字列型の項目のみDelimiterで囲われている。
- 本当はQUOTEもシングルクォートが指定できればよかったけど、ONOFFしか設定できない。

このままではNULL項目がブランクで出力されており、Insert文に流用する際に面倒なのでNULLも表示するよう設定する。

```sql
SQL> set NULL 'NULL'
SQL> select * from test_manage_table where report = 650;

-->結果
"KAISYA","FUNCTION","REPORT","IDENTIFIER","SELECT_ORDER","ITEM_ORDER","MASTER_DIV","MASTER_KAISYA","MASTER_ID","UNION_SPECIFY","SYMBOL1","SYMBOL2","COMPARISON","LANG_ID","CONTENTS1","CONTENTS2","UPDATE_DATE","UPDATE_MAN"
1,214,650,3,1,7,"0",0,0,"0","NULL","NULL",1,NULL,"部門","NULL","20-12-04","TEST"
1,214,650,5,1,4,"0",0,0,"0","NULL","NULL",1,NULL,"H170","NULL","19-07-30","TEST"
```
- 数値型項目がうまく「NULL」で出力されているのは良いが、文字列項目かつNULLの場合も「"NULL"」が表示されてしまうのはいただけない。

:::note info　
追記
NULLデータのカラムをブランクとして出力したい場合は、単純に`SET NULL """"""`とすれば「""」と
表示される。
:::

- 列名ヘッダーが不要な場合は`SET HEAD OFF`、「～が選択されました」のフィードバックが不要な場合は`SET FEEDRBACK OFF`をつければよい。
リモートだからこそSlackでわがままになろう

# はじめに
この記事は [WESEEK Advent Calendar 2020](https://qiita.com/advent-calendar/2020/weseek) の4日目です！
発起人をカウントしないとすると、2番乗りです！

非エンジニアである私は技術系の記事が書けないので、こう過ごしたら楽なんじゃない？的なものをつらつらと綴ります。
今回は、**Slackってもっと気軽でいいんじゃないの？**というライフハック的なことをお話しようかなと思い、筆を執りました。

# 筆者の前提条件
 
- 以前ゲーム開発会社に在籍しており、エンジニア/プログラマと触れ合ってきた
- 現在はエンジニアに囲まれて、非エンジニアな職に就いている
- かつ、人とのコミュニケーションをとてもとても大切にしている

では、参ります。

# Slackくらいわがままでいいじゃん
Slackを使って数年が経ち、やっと実践できるようになったこと。

- チャットツールまで相手の顔色を気にする必要なんて、ない！
- 相手が今忙しいかどうかなんて関係ない
- 今伝えたいことは今メンションをしよう
- 明日やろうは馬鹿野郎

対面で話すと、恐縮してしまったり話しかけづらい人っていますよね。
上の例は相手に対して持つ感情ですが、そもそも面と向かって会話するのが苦手。という人は少なくないと思います。

「忙しそうにしていたり、集中していそうだから話しかけていいのかわからない…」

こんな風に思う事ないでしょうか。そういう時が私にもありました。
今でも、エンジニア/プログラマに話しかける時は少しだけ気にしてもいます。
※この話題については、別の日に後述するつもりです

でも！Slackだとそれ、いらないのでは？と考えてみませんか。

だって目の前にいないんですよ。相手が今集中していようがいまいが、関係ないのです。関係ないって思おう！
メンションが来ても、今集中しているなら見なければいい。寝ていたらあとで見ればいい。
緊急な用件はメンション後に電話が来るはずです。

リモートワークが主流だからこそ、相手の様子が目で見えないからこそ、Slackでわがままになってみませんか。

# 小島よしおになろう
「今忙しい？でもそんなの関係ねぇ！でもそんなの関係ねぇ！」と、小島よしおになってみましょう。

そういう、『今自分が伝えたいことを伝えられる気軽さ』がチャットツールの良さだと思うのです。
そして相手が気づいていないようだったら何度でもメンションしよう。スルーされて困るのは自分だったりするのだから。

`@channel`は気軽に、もっと積極的に使おう！！！そして、わがままになろう！と声を大にして言いたいのです。
![20201204_slack_mayuko.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/915398/2fd5f474-6c38-7239-66c4-64bfeba5eacf.png)
ちなみにこの記事はまさに今日、20201204の13:57に執筆をしているのですが。本日はすでに3回`@channel`を使っている…！
どうしても回答してほしいアンケートがあったからなのですが、昔の自分だったらこれも躊躇していたかもしれません。
むやみに使うものではないけれど、わがままを適切に使っているつもりです。

# エンジニアの使い方に近づける意識
これを最近は意識しています。
会社の使い方に近づける、と言い換えたほうが適切なのかもしれないです。

垂れ流しの文化が奨励される場所では、`general`がピコンピコンしたって誰もなんとも思わないし、誰か助け舟を出してくれるかもしれない。
なんなら言わないほうが悪と考える人の方が多いな？という空気を感じています。
それに似た思想を持った非エンジニアがその方向に寄った結果、そこそこ気楽にSlackを使えているんじゃないかなと実感している今日この頃です。
非エンジニアなりの、エンジニアとのコミュニケーション方法だ！と豪語したい。

# おわりに
私は普段、基本的には礼節正しい人間である…と自負しています。
適切な場では適切な言葉を使う。
だからこそ、Slackくらいは簡潔でいいんじゃないかと思っています。

チャットツールなのだしな。と思うと少しは気が楽になりませんか？
今日からあなたも`@channel`マスターだ！

# おわりのおわりに
Qiitaの使い方として適しているのか、とても不安ではあるものの、適していなかったらもっと濃くしていけばよいだけのことだ。
と思って投稿しています。
[WESEEK Advent Calendar 2020](https://qiita.com/advent-calendar/2020/weseek) はまだまだ続きますので、どうぞお楽しみください！

※この記事は [WESEEK Tips wiki](https://tips.weseek.co.jp/) に 2020/12/04 に投稿された記事の転載です。
Tips wiki では、IT企業の技術的な情報やプロジェクトの情報を公開可能な範囲で公開してます。
xamarin-forms-tab-badgeでバッジ表示してみる(Xamarin, Android)

## はじめに
モバイルアプリケーションを開発するときに、Xamarinを採用することもあると思います。
Xamarinについての説明はここでは割愛し、xamarin-forms-tab-badgeを利用して、通知のバッジを表示することに関して記載します。
ライブラリのドキュメントに使い方があるのでそれで十分なのですが、日本語の情報があまり見当たらなかったので、何かの参考になれば嬉しいです。
（なお、Androidエミュレータでしか確認していないため、iOSでは未確認です。）

■ 参考
Xamarin：[Xamarin(ザマリン) とはなんぞや](https://qiita.com/amay077/items/38ee79b3e3e88cf751b9)
xamarin-forms-tab-badge：https://github.com/xabre/xamarin-forms-tab-badge

## 完成イメージ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/105279/375bac66-5806-40ac-305d-32ac9704c25f.png)
通知タブに赤丸でバッジが表示される。
タブの位置やスタイルに関しての実装については割愛します。
参考：[TabbedPage](https://docs.microsoft.com/ja-jp/xamarin/xamarin-forms/app-fundamentals/navigation/tabbed-page)

## 実装
注：タブ機能の簡易な実装方法として、Xamarin.Forms Shellというものがありますが、こちらを利用するとバッジ表示ができないようなので、TabbedPageを利用します。

### xamarin-forms-tab-badgeのインストール
VisualStudioのソリューションエクスプローラ上でプロジェクトを右クリック＞NuGetパッケージ管理をクリック
![plugin.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/105279/e6b5057a-7233-33cb-7436-9411bef69688.png)
Plugin.Badgeを検索し、[インストール]ボタンをクリック

### AssemblyInfo.csを修正
[プロジェクト名].Android/Properties/AssemblyInfo.cs を開き、以下を追加

```AssemblyInfo.cs
[assembly: ExportRenderer(typeof(TabbedPage), typeof(BadgedTabbedPageRenderer))]
```

必要に応じて、usingを追加

### TabbedPageの実装
TabbedPageのサブクラスをMainTabPage(任意)として実装する。
バッジを付けたい項目に属性として`plugin:TabBadge.BadgeText="{Binding NotificationCount}"`を追加

```MainTabPage.xaml
    <NavigationPage Title="通知" 
                    IconImageSource="{FontImage FontFamily={StaticResource MaterialFontFamily}, Glyph={Static icons:MaterialIcon.Bell}, Size=50}"
                    plugin:TabBadge.BadgeText="{Binding NotificationCount}">
        <x:Arguments>
            <local:NotificationListPage />
        </x:Arguments>
    </NavigationPage>
```

コードビハインドにバッジを変更するメソッドを用意

```MainTabPage.cs
    public partial class MainTabPage : TabbedPage
    {
        public MainTabPage()
        {
            InitializeComponent();
            BindingContext = new { NotificationCount = "" };
        }

        public void ChangeNotificationBadge(int count)
        {
            if (count == 0)
            {
                BindingContext = new { NotificationCount = "" };
            } else
            {
                BindingContext = new { NotificationCount = "" + count };
            }
        }
    }
```

### バッジ表示の実装
今回はAppから通知をつける場合を実装する。
上で実装したバッジ変更のメソッドを呼び出す

```App.cs
   if (Current.MainPage is MainTabPage tabPage)
   {
       tabPage.ChangeNotificationBadge(1);
   }
```

## まとめ
Shellが使えず、自分でTabbedPageを実装しないといけないのは少し面倒ではありますが、ライブラリを利用すると簡単にバッジ表示機能が実装できました。
iOSの場合はLinkerの設定などあるらしいので、もう一手間必要そうです。