OmniAICreator/Qiita-1.07M huggingface dataset:
Terraformでの環境分割について

## はじめに
こんにちは、インフラエンジニアをしています。@hayaosatoです。
現在ディップではインフラのクラウドリソースの管理にTerraformを取り入れようと日々検証を行なっております。
その中でTerraformの環境分割はどのようにやるのか、自分なりに考えてみたので共有しようと思います。
参考程度に読んでいただけると幸いです。
よろしくお願い致します。

## 結論
早速結論ですが、Terraformの環境分割は`Module`を用いて行いました。
ディレクトリ構成は以下のようになっております。
こちらのディレクトリ構成はこちら(https://qiita.com/shogomuranushi/items/e2f3ff3cfdcacdd17f99)を参考にさせていただきました。

```
├── provider.tf
│
├── production
│   ├── serviceA
│   │   ├── variables.tf
│   │   ├── outputs.tf
│   │   └── main.tf
│   ├── serviceB
│   └── serviceC
├── staging
├── development
│
├── examples
│   ├── variables.tf
│   ├── outputs.tf
│   └── main.tf
│
└── modules
    └── resourceA
        ├── main.tf
        ├── outputs.tf
        └── variables.tf
```

## なぜこうしたか
Terraformの環境分割には大きく`Workspace`, `Module`, `ディレクトリ分割`があると思います。
今回、`Module`での環境分割を選定した理由としては、
*誤った環境へのリソース変更の適用を避けるため*です。
terraformでのリソース変更では破壊的変更も起きるので一歩間違えると即、サービス障害となってしまいかねません。
なので環境分割方式の選定時はこれだけは担保しようと思っていました。
もちろん、気をつけなければどの環境分割方法でもミスは起こりますし、どの環境方法でもミスを起こさない事も可能です。
その中で比較ミスを起こしにくいものとして選定しました。

### なぜModuleにしたのか
上記のように、環境をディレクトリ分割する事で、どの環境にいるのかがプロンプトに常に表示されるので
`Module`か`ディレクトリ分割`にしようと思いました。
その中で、`Module`を利用した方が共通部分のソースコード管理がしやすいので`Module`を利用することにしました。

## サーバレス
現在は管理しているリソースの種類が少ないので現状の構成となっておりますが、
今後サーバレスなアーキテクチャを管理するとなると現状の構成のままでは上手くいかないのではないかと思います。
サーバレスなアーキテクチャはアプリケーションのソースコードと親和性が高いので、
現状の構成のようにインフラ定義のみのリポジトリに配置するよりDockerfileのような感じで
アプリケーションのリポジトリに配置するのが良いのではないかと思っています。

## 最後に
今回の構成は現状のリソース管理における管理構成として考えてみました。
今後のリソース状況によってはかなり変化するのかなと思っています。
引きづつきどのように管理することがより楽な運用を実現するか、考えて行きたいと思います。

## 参考
- [Terraform Best Practices in 2017](https://qiita.com/shogomuranushi/items/e2f3ff3cfdcacdd17f99)
- [Terraformのベストなプラクティスってなんだろうか](https://future-architect.github.io/articles/20190903/)
え、なんでそんなしょうもない障害再発してるの？とならないために…

#このアドベントカレンダーについて
**初日から遅刻してしまい本当に申し訳ありません…**
このアドベントカレンダーは、ゲーム業界のQA（品質管理）における知見を共有し、業界発展に貢献することを目標としています！

ゲーム業界のQAって具体的に他業界のQAとどう違うの？という点については、↓の記事がわかりやすいので、ぜひご覧になってください！
https://qiita.com/gomez_te/items/40f0d8f898b4f619979c

#再発する障害
##概要
この記事のテーマに移らせていただきます。
運営中のタイトルで障害（本番環境での不具合）やヒヤリハットが起きたとき、QA側に責任がある場合や、開発側起因ではあるものの、QAで防ぐことが出来そうな障害の場合、大多数のQA組織では、再発防止策を設定して、同じ障害が起こらないようにしていると思います。
しかし、しっかり再発防止策を打ったのに、同じような障害がまた発生してしまう…そんな経験はないでしょうか？
この記事では、そんな再発してしまった障害について、見解を書かせていただこうと思います。
今回はよくある2パターンに分けて記載してみます。

##障害の例
以下の障害を例にして、障害が再発してしまったパターンを書いていきます。
**▼障害と再発防止策の例**
・あるイベント種（イベントA）の登場キャラを更新した際、イベント関連画面（○○画面）を開いた際にクラッシュが発生した。
そこで以下のような障害再発防止策を設定した。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320947/e095cfb8-ee28-c86a-0f80-bf868fedc822.png)

##根本原因の分析不足があったパターン
###概要
障害の根本原因を適切に分析せず、場当たり的な対応で障害が再発してしまうパターンです。
以下に極端な例を記載します
**障害再発の例**
上記再発防止策の策定後、後日イベントAとは類似しているが別種のイベント（イベントB）の登場キャラを更新した際、○○画面を開いた際にクラッシュが発生した。
**調査後の根本原因**
この障害の根本原因は、イベントA固有の問題ではなく、○○画面に関連する全イベントの登場キャラが変更されたとき、○○画面から更新後のキャラ画像が呼び出せなくなるとクラッシュが発生することだった。
###この例の場合の問題
この例では、最初にイベントAでクラッシュが発生したときに、原因と影響範囲をイベントAのみに制限して再発防止策を設定したことです。
○○画面を利用する類似イベントがあるなら、開発側と範囲のすり合わせや、QAによる類似イベントの確認をしたうえで、障害再発防止策を策定するべきでした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320947/e2422311-a0a3-9f57-5f01-e061bfd866db.png)

これは極端な例ですが、障害の根本原因を分析して、真の影響範囲を探ることは、再発防止においてとても重要な行動です。
##再発防止策が実施されていないパターン
シンプルですが、とてもよくあるパターンです。
**障害再発の例**
イベントBでの障害を受け、再発防止策を再考したが、再びイベントAの○○画面でクラッシュが発生してしまった。
**調査後の根本原因**
再発防止策として、○○画面をチェックするルールとしていたが、チームへの周知が口頭のみとなっており、チェックを実施している人としていない人がいた。
###この例の場合の問題
この例は、障害の対応を現場の担当者に任せきりになっている場合や、各関係者が高稼働状況で余裕がない場合に発生しやすい事例です。
再発防止策は策定後、運用されて初めて効果を発揮するので、QAチームの責任者は運用開始まで追跡することが望ましいです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320947/8a4ccf45-ed9f-2536-c754-d7e18ae5b1ee.png)
##では具体的にどんなことをやるといいか
###振り返り会
単純ですが、振り返り会を実施するのはとても効果的です。
振り返り会は次の2形態で開催するのがおすすめです。
握った内容は**必ず議事録に残し、チームとして有用な情報なら資料化する**ことも大切です。

**開発・QA合同の振り返り会**
効果的な再発防止策設定に役立ちます。
基本的には発生した事象をQAでまとめておき、QA側で考えられる再発防止策を開発に共有し、FBを受けるのが良いと思います。
その再発防止策が本当に効果的かの意見が聞けますし、開発側でより良い再発防止策を導き出すことにもつながります。
たとえば、入稿時のバリデーションチェックで拾えるものであれば、QA側の対策よりも、そちらで対策を打つほうがより効果的です。

**QA内の振り返り会**
再発防止策の実施状況のモニタリングに役立ちます。
FIXした再発防止策をどのように運用しているか、QAメンバーへのヒアリングを行ったり、
開発と話した内容の共有を行うことで、メンバーの意識づけやナレッジの強化につなげることが出来ます。
###BTS等を用いた障害の管理
RedmineやJIRA、もしくはスプレッドシート等でもいいので、リリース後の不具合についても、データ化して一覧で追えるようにしておくと、障害の再発防止において役に立ちます。
まずチームの障害の総数を見える化すると、品質状況についてメンバーに意識づけを行うことに役立ちます。
たとえば、障害数が少ないチームにおいては、現状の運用がうまくいっていることが明確にわかるので、現状のラインに沿ってチームを強化すればよいことがわかります。
逆に障害数が多いチームに対しては、現状の運用がうまくいっていないことが考えられるので、熱量高く改善の取り組みが必要なことがわかります。
これら見える化した障害に対してラベリングを進めていくと、障害の再発率も明らかになってきます。
また、策定した再発防止策の内容も情報として記載していくと、管理者が状況を確認する助けとなるので、効率的なモニタリングに繋がります。

#おわりに
この記事では、障害が再発してしまうよくあるパターンと、それに対する望ましい対応について記載しました。
かなりイージーなミスのようにも見えますが、チームの責任者と実運用の担当者それぞれがしっかりと意識づけしていない場合、起こりうるミスです。
簡単なことほどしっかりとやっていくことが、QAとして大事な心得かなと思います。
[TouchDesigner]pythonによるfor文のコツ

## はじめまして
趣味で映像や音楽を作ってるibuibu69と申します！
これまでmaxやprocessingを使って、VJとインストバンドなんかをやってました。。
https://www.youtube.com/watch?v=NswI72i6lCg

・・・バンドも解散したし、TouchDesignerで新しいことをやりたい今日この頃。東京在住なので、だれか友達になってください。。

では、初アドベントカレンダー投稿、さっそくいきます。

## 本題
TouchDesignerで難しいことをやろうとするとき、pythonによる制御が必要不可欠になってきます。

がしかし、、、TouchDesignerユーザーでpythonに精通しまくりな方は、（私も含め）割と少ないのではないでしょうか。。。たぶん。。

そこで、よく使うであろう、for文によるオペレータの一括操作の際のコツを紹介します。

## たくさんのオペレーターを操作

例えば、「constant1,2...9のvalue0に１を代入する」はこうです。

```python
for i in range(1,10):
    op( 'constant' + str(i) ).par.value0 = 1
```


![cfsd3-u422f.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89866/1ba0ee69-f403-40f6-fb22-9e6c0d29e30c.gif)

これは簡単ですね。

解説：
op()の中は文字列なので、iをstr()で文字列にする必要があります。



## たくさんのパラメーターへ代入する

例えば、「constant1のvalue1,2,...9に1を代入する」はこうです。

```python
for i in range(1,10):
    script = 'op(\'constant1\').par.value' + str(i) + ' = 1'
    exec(script)
print(a)
```


![7cqii-7k8am.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89866/63ce1092-1d01-9536-f4ee-c3a0de76f8f4.gif)

exec関数を使います。（私はこれを知らず、四苦八苦しました。。）

コツ：
valueの項番をイテレータとするには、まず実行したい文全体をstring型で書き、イテレータを埋め込みます。その後、exec()関数で実行します。
クォーテーションをエスケープするのを忘れずに！！

## たくさんのパラメータの値を取得する

例えば、「constant1の1,2,...10の合計値を表示する」はこうです。

```python
a = 0
for i in range(10):
    a += eval('op(\'constant1\').par.value' + str(i) )
print(a)
```

先ほどのexec関数と似てますが、今度は値を評価する関数であるevalを使ってます。

以下のように、exec関数を用いてもよいです。

```python
a = 0
for i in range(10):
    script = 'a += op(\'constant1\').par.value' + str(i)
    exec(script)
```

## まとめ

このように、TouchDesignerの組み込み関数をfor文で回したいとき、execやevalを使うことでうまくいきます。

・・・という紹介でした！！


twitterでたまーに映像や音楽をアップしてたりしています。よろしければフォローをいただけると嬉しいです。

https://twitter.com/ibuibu69
メタゲノムが嫌いな理由

# 自己紹介

@kmoooooog です。
博士号取得後民間で機械学習エンジニアやってたのですがアカデミアに舞い戻り、今年の二月からはJAMSTECでメタゲノム解析をやっております。

また、その他の活動として株式会社tayoの代表として「イケてるJREC-IN」みたいなサービスである https://tayo.jp を作っておりますのでそちらもよろしくお願いいたします。[取材記事はこちら。](https://startuptimes.jp/2019/12/02/136596/)

初日はいざわパイセンによる[ポエミィなメタゲノム賛歌](https://qiita.com/i-za-world/items/6b448b52703a23e14a1b)から始まったので、このニッチなアドベントカレンダーの発起人として僕もポエムを書かせていただこうかと思います。

せめてもの爪痕を残すために攻撃的なタイトルを付けましたが、反論ある方は是非アドベントカレンダー上でお願いします。

# メタゲノム嫌い

僕は博士課程では基本的に単離株の比較ゲノム解析をメインでやっていました。その時はすごく「メタゲノム嫌いだなぁ」と思っていて、その理由は次のような感じです。

### データの再現性が低い

僕の専門の海洋を例に取ると、例えば2017年の4月に黒潮域の海洋表層で取ったメタゲノムサンプルがあったとします。このサンプルには以下のような様々な因子が影響しています。

1. メソッドによる影響
 - サンプリング方法
 - サンプル調整方法
 - シーケンス方法
2. 環境要因による影響
 - 季節
 - 当日の海流
 - 当日の天気
 - その他あらゆる環境条件

さらに当然地球温暖化や海洋酸性化などの長いスパンでの海洋環境の変化にも影響を受けるので、2018年の4月に取ったサンプルでも同じ結果が出るかというと全くそんなことはないです。

②に列挙したように「刻一刻と変わる環境要因全ての影響を受ける」ため、本来であればメタゲノムは時系列で観測することが非常に重要なのですが、それも①の「メソッドによる影響」が邪魔をします。
近年落ち着いてきたとはいえシーケンス技術は日進月歩であり、10年前のシーケンス方法が今でも使えるかというとNOであることが非常に多いためです。僕の出身研究室では5年前ぐらいまで454が現役で動いていましたが、もはやサポートも切れており古の技術と化しています。
本当は定点観測で長期の微生物群集構造の変化を追いたいのに、シーケンス技術は数年のスパンで技術革新がどんどん来てしまうので手法がどんどん変わってしまう。この辺りのギャップにメタゲノムの苦しさを感じていました。

あと、個人的には生物学を博物学でなく科学たらしめているのは再現性だろうと思っているので「絶対に再現できないデータ」というのは単純に扱うのが怖いです。

### データの再利用性が低い

単離株のゲノムは基本的にコンプリートしてしまえばあらゆるシーケンサーで同じ結果が出ると仮定できますが、メタゲノムの場合はシーケンサーが変わると結果が大きく変わります。
遥か昔にSangarで読まれたE. coli や Synechocystis のゲノムは今後もずっと使われるでしょうが、10年後に今よりずっと進歩したシーケンサーで読まれたメタゲノムデータを2019年の技術で読まれたメタゲノムデータと統合して解析したいかと思うと微妙です(実際にはやらざるを得ないことになるんでしょうが、しんどそう)。

また、単離株ゲノムの場合は「とりあえずあんまりゲノム読まれてないグループのゲノムを読めば後々そこから発見がある」ことが往々にして考えられますが、メタゲノムだとおそらくそういうケースはずっと少ないかと思われます。ゲノムと違ってデータが積み上がらない感じにもメタゲノム解析のしんどさかと思います。

# じゃあどうするの

上記のメタゲノムdisは「自分がメタゲノム解析やりたくない理由」な訳ですが、今僕はひたすらメタゲノムデータを捌くお仕事をしています。僕がひねくれているからというのもありますが、「環境微生物学分野のバイオインフォマティシャンとしてメタゲノムを避け続ける人生は歩めないだろう」という思いもありました。

散々disっておきながらやはりここ20年ぐらいの環境微生物学の発達はほぼメタゲノム解析によるものだと思っているし、「誰が、どこで、何をしているか」という環境微生物学のビッグクエスチョンを一挙に解決する夢の手法であるのは間違いありません。

では、どうするのか。僕の思うメタゲノムで重要な点は以下です。

### 漫然とデータを取らない

「適当に読んだゲノム」には一定の価値がありますが、上記のデータ再利用性の観点から、「適当に読んだメタゲノム」は概ねゴミです。
「なんか面白いの出てこないかな〜」とか「せっかくサンプリング行くからメタゲノムも〜」みたいなふわっとしたモチベーションはよっぽど面白いサンプル取れない限りまとまった論文にするのはキツいと思うので、「研究としてのストーリー」は単離株のゲノムよりもより強く意識する必要があると思います。

### さっさと論文を書く

昨今のシーケンサーの進歩に対して僕らの論文執筆速度はあまり変わりません。ムーアの法則を超えて僕らの論文執筆速度を加速する `ネクストジェネレーションアーティクルライティングAI` みたいな技術革新を待ち続けていますが、しばらくそんな時代は来そうにないです。なのでおとなしく、「データが古くなる前に発表」は心がけなきゃいけません。 `データが古くなる前に発表` は次世代シーケンサーの関わる全ての研究に言えることだとは思いますが。

でっかいブーメランを投げちゃったのでぼくも早く論文書きます。


# 終わりに

苦しみもいっぱいありますが、不確かさが大きい分、解析には技量が問われるところがありメタゲノムデータはとても触っていて楽しいです。次はそんな話ができればなぁと思います。
基本情報12月の勉強計画

# 目標と結果
### 目標
- 午前免除に合格する。
- 基本情報技術者試験ドットコムを活用する。
- 午後問題のアセスメントを受験する。
- 午後問題11分野の中から出来そうな分野を5〜7分野ほど見つける。

### 結果
- 午前免除に合格した。

# 振り返り
### keep
- 道場を継続する

### Problem
- 1月は大学との兼ね合いで午後の勉強は難しい。

### Try
- 午後問題で挑戦する分野をはっきりさせる。

# 週次計画
###[7週目(12/02)](https://qiita.com/Yuya_nakano/private/bf1d7fe5a1f28d299970)
###[8週目(12/09)](https://qiita.com/Yuya_nakano/private/f8723d83c70f05bcc8ea)
###[9週目(12/16)](https://qiita.com/Yuya_nakano/private/8f4da3caa01ed1274388)
###[10週目(12/23)](https://qiita.com/Yuya_nakano/private/fa17656bfee4b4970a80)
###[11週目(12/30)](https://qiita.com/Yuya_nakano/private/7d2e57cfb9237d6aff9f)
Slackbotでファイルの読み書きをしよう〜PythonでのBot開発〜

本記事では、Pythonで作成したSlackbotでファイルの読み書きにする処理について説明します。

「<a href="https://se.miyabikno-jobs.com/python-read-write/" rel="noopener noreferrer" target="_blank">Pythonでファイルの読み書きを制御する</a>」にて実装した論理をSlackbotから呼び出せるようにしていきます。

ファイルを読み書きする基本論理は「Pythonでファイルの読み書きを制御する」で作成した以下のモジュールを使用します。

```python
import codecs

class FileReadWrite:

    # ファイルを読み込むメソッド
    def file_read(self, path):
        try:
            # ファイルを開く
            target_file = codecs.open(path, "r", "utf_8")
            # ファイルを読み込む
            text = target_file.read()
            target_file.close()
        except:
            # エラーが出た時の例外処理
            text = "ng"

        return text

    # ファイルを書き込むメソッド
    def file_write(self, path, text):
        try:
            target_file = codecs.open(path, "a", "utf_8")
            target_file.write(text)
            result = "ok"
            target_file.close()
        except:
            # エラーが出た時の例外処理
            result = "ng"
        return result

```

PythonでのSlackbot実装の基本については「<a href="https://se.miyabikno-jobs.com/implement-slackbot-python/">SlackbotをPythonで作成しよう</a>」をお読みください。

<h2>Slackbotの書き込み処理の実装</h2>
<span class="text_bolder">◆動作仕様</span>
上記のモジュールから書き込みメソッドを呼び出して結果によってリアクションを返します。
書き込みが成功した場合は「:ok:」、書き込みに失敗した場合は「:ng:」のリアクションを返すようにします。

```python

from slackbot.bot import respond_to
from slackbot.bot import listen_to
from filereadwrite import FileReadWrite

@respond_to('^ファイル書き込みテスト$')
def write_test(message):
    # クラスのインスタンスを生成
    f = FileReadWrite()
    # ファイルに書き込む
    action = f.file_write("./test1.txt", "あいうえお\n")
    # 結果をリアクションする
    message.react(action)
```

<span class="text_bolder">◆実行結果</span>
<a href="https://miyabi-knock.com/tools/wp-content/uploads/2018/12/slackbot_write.png" rel="noopener noreferrer" target="_blank"><img src="https://miyabi-knock.com/tools/wp-content/uploads/2018/12/slackbot_write.png" width="500" alt="ファイルの書き込み" class="alignnone size-large" /></a>

<h2>Slackbotの読み込み処理の実装</h2>
<span class="text_bolder">◆動作仕様</span>
上記のモジュールから読み込みメソッドを呼び出して結果によってテキストまたはリアクションを返します。
読み込みに成功した場合はファイルの内容を出力します。読み込みに失敗した場合は「:ng:」のリアクションを返すようにします。

<span class="text_bolder">◆botmodule.pyに記述する内容</span>
読み込みの論理を追記します。

```python
@respond_to('^ファイル読み込みテスト$')
def read_test(message):
    # クラスのインスタンスを生成
    f = FileReadWrite()
    # ファイルからテキストを読み込む
    text = f.file_read("./test1.txt")

    # 失敗した時はNGをリアクションで返す
    if text == "ng":
        message.react(text)
    else:
        # 成功した場合はテキストを返す
        message.reply(text)
```

<span class="text_bolder">◆実行結果</span>
<a href="https://miyabi-knock.com/tools/wp-content/uploads/2018/12/slackbot_read.png" rel="noopener noreferrer" target="_blank"><img src="https://miyabi-knock.com/tools/wp-content/uploads/2018/12/slackbot_read.png" width="500" alt="実行結果" class="alignnone size-large" /></a>

以上、Slackbotでのファイルの読み書き論理の実装でした。

Slackbot＋PythonまとめTOP＞＞<a href="https://se.miyabikno-jobs.com/slackbot-manual-python/">Slackbotの作り方マニュアル〜Python編〜</a>

<span class="text_bolder">◆サンプルコード</span>
<a href="https://se.miyabikno-jobs.com/download/python-slackbot-sample4/">Python Slackbot読み書きサンプルコード</a>
CloudFormationでEC2の初期構築の工数削減

# 構築目的と背景
お断り：目新しい情報はないかと思います。

業務でCloudFormationを活用するようになりました。
その中で単にEC2を作成した場合、作成後の手作業が多く自動化のありがたみが薄いと感じました。
そこでcfn-init ヘルパースクリプトを活用したいと思います。
※AmazonLinux2では上記のヘルパースクリプトが標準でインストールされている為、前準備は不要です。



# できること
- コマンドの実行
- ファイル作成
- ユーザー/グループの作成
- パッケージのインストール
- サービスの起動設定
- ソース（アーカイブファイルをダウンロード）

# 活用内容
私が活用したのはパッケージのインストールとコマンドの実行です。

## パッケージ
- yumでインストールが可能なものはパッケージ名を記載
  - バージョンに関しては[]であればOSがインストールできる最新版がインストールされます。
  - 指定のバージョンがあればリストの書式で記載してください。
  - 更に新しいバージョンを指定したい場合はrpmにURLを記載することでインストールが可能となります。

```yaml
  EC2:
    Type: AWS::EC2::Instance
    Metadata: 
      AWS::CloudFormation::Init: 
        config:
          packages:
            rpm:
              mysql80-community-release: https://dev.mysql.com/get/mysql80-community-release-el7-3.noarch.rpm
            yum: 
              python3: []
              mysql-community-client: []
              git: 
                - "2.20.1"
```

## コマンド
Amazon Linux2であればamazon-linux-extrasを使ってインストールすることもありますし、
Pythonであればpip installもあります。他にもyum以外の手段はあるかと思います。
それらは上記パッケージのインストールでは対応できない(と思ってます)のでコマンドにて対応します。

また、名前のアルファベット順にコマンドが実行される為、順番に考慮が必要な場合は
コマンド名に数字を付けておくと良いです。

```yaml
  EC2:
    Type: AWS::EC2::Instance
    Metadata: 
      AWS::CloudFormation::Init: 
        config:
          commands: 
            01php73:
              command: "amazon-linux-extras install php7.3"
            02pytest:
              command: "pip3 install pytest"
            03mount:
              command: "mkdir -p /home/storage"
            04mount:
              command: "echo \"xxx.xxx.xxx.xxx:/storage /home/storage nfs nolock,hard 0 0\" >> /etc/fstab"
            05mount:
              command: "mount -a"
```

## 適用方法
上記をCloudFormationのテンプレートに記載しただけでは適用されません。
UserDataへcfn-init ヘルパースクリプトを実行する手順の記載が必要です。

```yaml
      UserData:
        Fn::Base64: !Sub |
          #!/bin/bash
          yum -y update
          /opt/aws/bin/cfn-init --stack ${AWS::StackName} --resource EC2 --region ${AWS::Region}
```

# まとめ
上記を駆使すると工数が削減でき、手作業よりも結果にブレがなく良いのではないでしょうか。


# 余談
ユーザー作成ですがuidが選ぶことが可能ですが、強制で/sbin/nologinとして作成する為、用途が限定されてしまいます。
コマンドにて対応するとCloudFormationのテンプレートにパスワードが記載されてしまうので、ユーザー作成は別途検討が必要だと感じました。

# 参考
- [AWS::CloudFormation::Init](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-init.html#aws-resource-init-commands)
- [AWS CloudFormation による Amazon EC2 へのアプリケーションのデプロイ](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/deploying.applications.html)
[Memo] nRF Connect:Programmer & nRF Toolbox

使い方メモ.

---

# Environment
- Software
    - Windows 10
    - [nRF Connect for Desktop](https://www.nordicsemi.com/Software-and-tools/Development-Tools/nRF-Connect-for-desktop)
    - [pc-nrfutil](https://github.com/NordicSemiconductor/pc-nrfutil)
    - [iOS - nRF Toolbox](https://apps.apple.com/app/nrf-toolbox/id820906058)

- Hardware
    - nRF52-DK (nRF52832)

# Steps to burn base FW (SoftDevice and Bootloader).

- nRF Connect<br>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75594/de94a7bb-989e-8749-10a1-56ab5dfc973f.png)
<br>=> Install & Open "*Programmer*"

<!--![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75594/8adcf45b-01aa-0574-f909-8a3f99bc5ae2.png)-->

- Programmer (<font color='red'>**No device connected**</font>)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75594/6694827a-a752-7a5f-b878-40d93d6fa6c0.png)

- Programmer (<font color='red'>Device is **connected**</font>)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75594/ae96f8df-3c42-e5a0-f3ed-7e8dac518f44.png)
=> Select Device

- Programmer : Adding HEX files
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75594/87733a0f-eb75-2e09-8b48-dd29188779be.png)

    - "s132_nrf52_7.0.1_softdevice.hex" : SoftDevice(S132) for nRF52832
    - "secure_bootloader_ble_s132_pca10040.hex" : Bootloader

- Programmer : After 2 HEX files are added.
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75594/012701d3-1857-e4b4-6668-c5601966e7fb.png)

<!-- ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75594/2f386c98-59ae-644a-8835-fc76b1eb0a86.png)-->


- Programmer : "Erase all", "Read", "Write" and then "Read"
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75594/d27064f4-8fa4-7ccd-bd7c-a05bcd6bfc7f.png)

# DFU File

- Use "nrfutil" to generate Dfu file from .hex and private key.

    ```bash:Example
APPNAME=APP001
nrfutil pkg generate --hw-version 52 --sd-req 0x00cb --application-version 0x0000 --key-file ./key/priv.pem --application ${APPNAME}.hex ${APPNAME}.zip
```

- Send email with ".zip" (DFU file) to iOS device 
- Open email, do long press the attached ZIP file, and select Copy to "nRF Toolbox"

# iOS: nRF Toolbox

- Go to DFU
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75594/ace30be6-f203-f697-b667-e70567398b62.png)

- DFU<br>![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75594/5927c97f-c664-0aa7-2070-e871b69720c2.png)

    - Select File > User Files > Inbox > Select zip file 
    - Select Device<br>![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75594/bb7007da-a657-bd45-83c9-2e126a4b0e87.png)
    - Tap: Update<br>![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75594/a15e02cc-02d7-3d46-94ec-806b9583c7c2.png)


    - Done: :-)<br>![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75594/80fcc9d9-c3bd-de74-d84e-3f1f90a8deb2.png)
基本情報７週目(12/02週)

# 目標と結果
### 目標
- 参考書の演習問題を正解する。
- できない部分をそのままにしない。
- 基礎理論とアルゴリズムを勉強を続ける。
    - 時間管理、工数管理も忘れずに。
- [基本情報技術者試験ドットコム](https://www.fe-siken.com/)を使う。
    - 過去問道場
    - 講座で聞いた頻出問題を対策する。
- 火曜までに修了テストにも合格する。
- 独習ゼミの解説動画を観てみる。

### 結果
- 12月8日の午前免除試験を受験した。
    - [問題](https://www.jitec.ipa.go.jp/1_80tokurei/kakomondai/tokurei_Mondai_20191208_FE.pdf)
    - [回答](https://www.jitec.ipa.go.jp/1_80tokurei/kakomondai/tokurei_ans_20191208_FE.pdf)
        - 自己採点では70点だった。
            - 合格基準は60%(48点)


# 振り返り
### Keep
- 過去問道場を使い続ける

### Problem
- 計算問題は問題文と答えを暗記して解決してしまった。

### Try
- 午後問題で通用する様にしっかりと理解をする。
Glideでキャッシングぅううう

# はじめに
[CA Tech Dojo/Challenge/JOB Advent Calendar 2019]の2日目はbatchが書かせていただきます．

私は今年の夏にCA Tech Dojo（Kotlin編）に参加させていただきました．めちゃくそ最高のインターンだったので来年も開催される場合は，おすすめです．Dojoはある技術の初心者の導入部分をサポートしてくれるインターンなので，最近気になってる技術をメンターさんに教えてもらいながら学ぶことができます．
詳しくは[コチラ](https://batch.hatenablog.com/entry/2019/08/19/215844)

# 本題
Glideを使って画像をリスト内で表示して，リストのItemがクリックして別の画面に遷移して，遷移先でリストに表示していた画像を使いまわしたいみたいなことはよくあると思います．そこで，Navigationなどつかって遷移先にも画像のURLをStringで渡して表示するということをしても実装できますが，GlideではURLをキーとして画像をキャッシュしてまた，遷移先でおなじキーでキャッシュからデータを取ってこれるやり方があるそう．
なんかわざわざそれしなくてもかってにキャッシュしてくれてそうな感じもしますが，とりあえず明示的にキャッシュしてそれを遷移先で取得するやり方の知見共有したいと思います．
## Step1 キャッシュ
以前，[Groupieでitemクリックを実装する記事](https://batch.hatenablog.com/entry/2019/11/10/133449:embed:cite)を書きました．

今回はitemがクリックされたときに動かすと<b>はじめに</b>で言ったような動きを実装することができます．`Glide.with`のとこでcoverPathをキーとして画像をキャッシュしています．
そして，遷移先で同じキーでキャッシュから取り出したいので，actionに渡してNavigationで遷移しています．

```kotlin
        val index = this.playlistAdapter.getAdapterPosition(item)
        val coverImage = requireActivity().findViewById<ImageView>(R.id.cover_image_view)
        val coverPath = viewModel.playlists.value?.get(index).coverPath ?: return@OnItemClickListener
        Glide.with(this)
            .load(coverPath)
            .diskCacheStrategy(DiskCacheStrategy.ALL)
            .into(coverImage)
        val action = PlaylistFragmentDirections.actionMusicFragment()
        action.coverPath = coverPath
        Navigation.findNavController(requireActivity(), R.id.nav_host_fragment).navigate(action)
```

## Step2 キャッシュから取り出す
遷移先の画面では，わたされてきたcovetPathをsafeargsで受け取ってそれをキーとしてキャッシュから画像を表示させています．

```kotlin
        val coverImageView = view.findViewById<ImageView>(R.id.cover_image_view)
        val args: MusicFragmentArgs by navArgs()
        val coverPath = args.coverPath
        Glide.with(this)
            .load(coverPath)
            .onlyRetrieveFromCache(true)
            .into(coverImageView)
```
# 参考
https://bumptech.github.io/glide/doc/caching.html#cache-keys
WEBサイトに必要な情報

WEBサイトを作るのに必要な情報って意外と多いなと思ったので忘れがちなところをまとめておく備忘録。  

## meta
- title
- description
- keyword
- og:url
- og:type
- og:title
- og:description
- og:site_name
- og:image
- fb:app_id
- twitter:card
- twitter:site

## 画像
- OG画像
- favicon
- apple-touch-icon

## 構成
- パンくずの表記
- リンク先の指定

## デザイン
- PC/SPの表示切り替え（レスポンシブか否か）
- ブレイクポイント
- hover時の挙動
- retina対応の可否
- アニメーション
- font-sizeの指定方法(px?vw?rem?)

## 実装
- 解析タグ
- 対応OS/対応ブラウザ
- htmlバージョン
- 文字コード/改行コード

---

多分探すと他にも色々あると思うので思いつき次第追記します。
DJI Mavic Miniで飛行して良いかどう判断するのか

航空法での申請を要さない機体を飛ばしていいか判断するのに実際どうするのかという工程について、いろいろなサイトがありますが、結局どれも該当してないから飛ばそうという判断する人がいます。

例えば
私は、DroneBirdの西日本統括していますので
空港に比較的近く、観光スポットにもなっている、大阪府池田市の「秀望台」という場所で飛ばすことができるかを考えてみます。
自転車で勝尾寺へいくヒルクライムコースです。![IMG_5961.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/322439/1053c181-23f1-9d43-a7bc-28502bbc62e4.jpeg)

いかにも飛ばしてみたくなるロケーション！
自転車並べて、ちょっと上空からドローンで撮影したいものです。

緯度経度でいうと
N 34 49 54.17
E 135 25 38.13
です。

結論から先にMavicMiniでも無許可では駄目です。航空法第134条の3の規制に引っかかることになります。
１．DJIの専用アプリでは、空港から4km円とちょっとと微妙な感じと思いがちで水平表面には入らず、円錐区域に入ります。
飛行可能高さ　＝　飛行場の標高が12m＋水平表面は45m＝57m
ギリギリなので、57mとしてもいいでしょう。
この時点で駄目ですが、終わってしまいますので参考に続けます。

２．SORAPASSというサイトでは、9kmの円の中にあるので、規制をうけるが、これだけでは判断できかねます。

３．大阪空港の高さ制限回答システムでは、4kmの円の中に入る表示がされています。

http://www.kansai-airports.co.jp/itm_seigen/

ここで最終的に水平表面であると判断して良いと思います。

回答にはで計算式が出てきます。高さ制限内は８４ｍ（海抜）と表示されます。これは海抜表示なので注意が必要です。ちなみに「秀望台」の海抜標高は１２０ｍ地点となります。
可能高＝ 制限高－ 照会地の地盤の高さ（海抜高）
となり、マイナスとなるため、「許可なしで飛ばしてはいけません」となります。
ちなみに
ー小型無人機等飛行禁止法にはあたらない地域
ー池田市内の公園でのドローン飛行禁止条例はまだない
という状況。

空港周辺では回答システムでどう表示されてから見て、管轄している部署に連絡するという方法を取りましょう。
ルールを守って正しい飛行をエンジョイしましょう。
Nature Remo のセンサーデータを取り続けてわかったことのメモ

# Nature Remo のセンサーデータを取り続けてわかったことのメモ
Nature Remo (初代) と Nature Remo mini を使っています。
それらのセンサーデータを1時間に1回の頻度で取り続けていてわかったことのメモです。

センサーデータを 1時間に1回の頻度で取り続ける方法は、こちらの記事を参考にしました。
[リビングの環境監視ダッシュボードを６０分で作る方法（Nature Remo Cloud APIとGoogleサービス連携）](https://qiita.com/t-chi/items/01b9a9b98fbccef880c3)

### 温度は 0.6度刻み
温度の情報は、0.6度刻みのようです。

11.2度の次は 11.8度、12.4度 といったように 0.6度刻みで、取得をしているようです。
また、きれいに 0.6度刻みにはなっておらず、11.8度は 11.79度となるなど、微妙なズレもあります。

Nature Remo も、mini も、どちらも 0.6度 刻みのようです。

### 湿度は 1%刻み
湿度は、Nature Remo では 1%刻みで取得しています。 (2019年9月ごろに1%刻みで取得できるようになっています。)

### 人感センサーは、うまくとれない？
以前は取得できていなかった mo という値が、人感センサーのようなのですが、
この値が、いつ取得しても 1 になっており、0 になることがありません。
人感センサーについては、おそらく動く熱源を検知した際に イベントが送信され、created_at の時刻が更新されます。

そのため、val の値が1か0かを確認するのではなく、created_at の時刻をみて
・古い時刻 --> しばらくの間更新されていない --> 人がいない。
・最近の時刻 --> 人がいる
という使い方をすると良さそうです。なお、created_at は、日本だとは9時間ずれます。

### Nature Remo が赤点滅で接続できない状態の場合、データは取得はされるが更新されていない。

接続エラーの場合でも、APIではデータを取得ではエラーにならないようで、
スプレッドシートには前回と変わらない値が入っています。
↑ この点については、動作が気になったので、また詳細を調べて更新予定です。
並び替えして楽に値を取得する方法【SQL Server】

#並び替えしてTOP1を変数に代入する。
例えば、日付を取得したい場合に使用できる。

|対象日付|曜日|
|:--:|:--:|
|20191120|水曜日|
|20191121|木曜日|
|20191122|金曜日|
|20191123|土曜日|
|20191124|日曜日|

```sql
SELECT TOP 1 @取得日付 = DateTable.対象日付
FROM (
      SELECT 対象日付
      FROM カレンダー
      WHERE 対象日付 <= @指定納期
     ) DateTable
ORDER BY 対象日付 DESC
```


業務系システムであれば、
リードタイムから納期を算出したり、
出荷予定日を算出する場合に便利かと。
XXX Reliability Engineering というスキル

XXX Reliability Engineeringという職種を良く聞く年だったなと思ったのでまとめてみました。

# Site Reliability Engineering

大分普及してきているのでサクッと以下の様な背景で生まれたスキルかなと思っています。

* インフラエンジニアは、構築したら終わりではなく運用し続ける必要がある。
* 運用は作業ではなく、ソフトウェアエンジニアリングである
* 業務、スキルは多岐に渡る

オライリーのSRE本は後続のXREにも必要な概念が理解できると思います。

## Customer Reliability Engineering

顧客信頼性エンジニアリング

GCP Japanのブログが有名
https://cloudplatform-jp.googleblog.com/2016/10/google-cre.html

SREの考え方を応用し対顧客に対して信頼性を構築するスキル

> クラウドを導入している組織を外から見ていると、非常に不安を感じているのがよくわかります。
>
> その妥当な理由を把握するまで少し時間がかかりましたが、最終的に次のような考えに落ち着きました。
>
> 人は、自分の環境を管理したいと進化的に思ってしまうのです。これは、生き抜くための特性として本当に価値のあることです。そのため管理できないと感じると、あまりいい反応を示さなくなります。危険度が高ければ高いほど、管理できないことに対して、より大きく反応してしまいます。

サービス利用者がシステムをコントロールできない事に対して大きな不安がある事が分かったので、
その課題を解決するスキルのようです。

## Database Reliability Engineering

データベース信頼性エンジニアリング

もともと、SREチームができ始めた時に、SREと行っても領域が広いので、
OSに強いSRE、リリースエンジニアリングに強いSREなど特性があって、
その中の1つのDBに強いSREがより専門的に特化したスキルなのかなくらいの認識です。
オライリーのDBRE本のamazonのページ行ってみると、
説明には以下の内容が書かれていました。

* サービスレベルの要件とリスク管理
* 運用の可視性のためのアーキテクチャの構築と進化
* インフラストラクチャエンジニアリングとインフラストラクチャ管理
* リリース管理プロセスを促進する方法
* データストレージ、インデックス作成、およびレプリケーション
* データストアの特性と最適なユースケースの特定
* データストアアーキテクチャコンポーネントとデータ駆動型アーキテクチャ

GitLabの採用ページ

https://about.gitlab.com/job-families/engineering/database-reliability-engineer/

## Security Reliability Engineering

セキュリティ信頼性エンジニアリング

DBREと同じでセキュリティに特化してエンジニアリングかなと。
丁度、ゼロトラストネットワーク読んでいますがアプリケーションの設計もするし、
機械学習したりとセキュリティ信頼性という目的に対して必要な知識は当然幅広いですよね。

# 個人的な考え
サービス開発に携わっているソフトウェアエンジニアは、これら言葉ができる前からみんなやっていた事かなと思います。
そこにトップ組織のノウハウをフレームワークとしてまとめたり、共通の言葉として定義できる様にしたのが今かなと思っています。
Site Reliability Engineering 自体は専門性に特化した職種ではなくて、あくまでもスキルという考えです。
そのため、サービス開発するソフトウェアエンジニアだったらどの分野のスキルも必要じゃないかと思っています。
PostgreSQL バージョンごと/カテゴリーごとのサーバーパラメーター数

## この記事の内容

PostgreSQLのサーバーパラメーター（GUC）について、カテゴリーごと、バージョンごとにカウントしてみました。

## 背景

2020年2月13日に、PostgreSQL 9.4の開発コミュニティによるサポートが終了します。
PostgreSQL 9.4から上位バージョンへのバージョンアップをおこなう際の非互換調査のひとつとして、まずはサーバーパラメーターについて確認してみます。

## 調査方法

~~~sql
SELECT category, count(category) FROM pg_settings GROUP BY category ORDER BY category;
~~~

## 結果

PostgreSQL 12は、PostgreSQL 9.4にくらべて1.3倍、74個も増えています。
バージョンが上がるにつれて、パラメーター数も確実に多くなっていますね。
単純に考えても、その増えた分について把握、検討が必要ということです。

|category|9.4.25|9.5.20|9.6.16|10.11|11.6|12.1|
|---|---|---|---|---|---|---|
|Autovacuum|11|11|11|11|11|11|
|Client Connection Defaults /<br/> Locale and Formatting|14|14|14|14|14|14|
|Client Connection Defaults /<br/> Other Defaults|5|5|5|5|5|6|
|Client Connection Defaults /<br/> Shared Library Preloading|3|3|3|3|4|4|
|Client Connection Defaults /<br/> Statement Behavior|21|22|23|23|25|26|
|Connections and Authentication /<br/> Authentication|||||5|5|
|Connections and Authentication /<br/> Connection Settings|9|9|9|9|9|9|
|Connections and Authentication /<br/> Security and Authentication|14|14|14|15|||
|Connections and Authentication /<br/> SSL|||||11|13|
|Developer Options|10|9|9|10|15|15|
|Error Handling|3|3|3|3|3|3|
|File Locations|5|5|5|5|5|5|
|Lock Management|3|3|3|5|5|5|
|Preset Options|11|12|12|12|13|14|
|Process Title||2|2|2|2|2|
|Query Tuning /<br/> Genetic Query Optimizer|7|7|7|7|7|7|
|Query Tuning /<br/> Other Planner Options|5|5|6|6|7|8|
|Query Tuning /<br/> Planner Cost Constants|6|6|9|10|13|13|
|Query Tuning /<br/> Planner Method Configuration|11|11|11|12|17|17|
|Replication||1|1|1|1|1|
|Replication /<br/> Master Server|2|2|2|2|2|2|
|Replication /<br/> Sending Servers|4|4|4|4|4|4|
|Replication /<br/> Standby Servers|6|7|7|7|7|11|
|Replication /<br/> Subscribers||||2|2|2|
|Reporting and Logging /<br/> What to Log|17|18|18|18|18|18|
|Reporting and Logging /<br/> When to Log|3|3|3|3|3|4|
|Reporting and Logging /<br/> Where to Log|11|11|13|13|13|13|
|Resource Usage /<br/> Asynchronous Behavior|2|2|5|6|8|8|
|Resource Usage /<br/> Background Writer|3|3|4|4|4|4|
|Resource Usage /<br/> Cost-Based Vacuum Delay|5|5|5|5|5|5|
|Resource Usage /<br/> Disk|1|1|1|1|1|1|
|Resource Usage /<br/> Kernel Resources|1|1|1|1|1|1|
|Resource Usage /<br/> Memory|10|10|11|11|10|11|
|Statistics /<br/> Monitoring|4|4|4|4|4|4|
|Statistics /<br/> Query and Index Statistics Collector|6|5|5|5|5|5|
|Version and Platform Compatibility /<br/> Other Platforms and Clients|1|1|1|1|1|1|
|Version and Platform Compatibility /<br/> Previous PostgreSQL Versions|9|10|10|9|9|8|
|Write-Ahead Log /<br/> Archive Recovery||||||3|
|Write-Ahead Log /<br/> Archiving|3|3|3|3|3|3|
|Write-Ahead Log /<br/> Checkpoints|4|5|6|6|6|6|
|Write-Ahead Log /<br/> Recovery Target||||||8|
|Write-Ahead Log /<br/> Settings|10|11|12|12|12|14|
|<b>合計</b>|<b>240</b>|<b>248</b>|<b>262</b>|<b>270</b>|<b>290</b>|<b>314</b>|
端末から簡単に英辞郎で検索するシェルスクリプト

## download

* https://github.com/t13a/eow

を利用させて頂いたらとても便利だったため

* https://github.com/tukiyo/eow/

にて、オプションの初期値を微修正したものをパッケージ化しました。

* deb
    * https://github.com/tukiyo/eow/releases/download/20191202/opt-eow.noarch.deb
* rpm
    * https://github.com/tukiyo/eow/releases/download/20191202/opt-eow.noarch.rpm


## 必須パッケージ

* w3m
* less


## 使い方

```sh
# 日本語
eow 検索ワード

# 英単語
eow search

# 複数単語
eow multiple word
```
Ansibleでdnfコマンドを使う際の注意

Ansible作成時に詰まったのでメモ。
2019/12/02現在の話。
環境はCentOS8、ansible2.9.1

# dnf moduleコマンドがサポートされていない
まだサポートされていない模様。
参考：https://github.com/ansible/ansible/issues/64852

以下のようなコマンドがansibleのdnfだと現状使えない。
実行したい場合はcommandかshellで実行する。

```shell:ansible化したいコマンド
dnf module disable php
dnf module install php:remi-7.4
```

```yml:無理
# 以下のように書けない。
- name: php disable
  dnf:
    disable_repo: php

- name: php7.4 install
  dnf:
    name: php
    enable_repo: remi-7.4
```

```yml:こうやるしかない
- name: php disable
  shell: 'dnf module disable -y php'

- name: php7.4 install
  shell: 'dnf module install -y php:remi-7.4'
```

### 補足
話はずれるが、php7.4を入れる場合はデフォルトでは入らないので
別途remiとepelリポジトリをインストールしておくこと。

```yaml
- name: Install epel.repo
  dnf:
    name: 'https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm'
    state: present

- name: Install remi.repo
  dnf:
    name: 'https://rpms.remirepo.net/enterprise/remi-release-8.rpm'
    state: present
```

# "@"が先頭に付くパッケージのインストール
バージョンまで指定しないとエラーになる

```yml:ダメな書き方
- name: mysql8 install
  dnf:
    name: '@mysql'
```


```yml:正しい書き方
- name: mysql8 install
  dnf:
    name: '@mysql:8.0'
```

まだまだ賢くはないらしい。
goのenumは文字列でいいのではないかという話

## goにおけるenumの一般的な定義

世の中で真っ当とされているgoにおけるenumの定義は、

```go
type Zodiac int

const (
	Rat    Zodiac = iota // 子
	Ox                   // 丑
	Tiger                // 寅
	:
)
```

ですね

とはいえ数値でJSON化されたり、ログ出されたり、DBに書き込まれたりされても、
理解が一歩遅れるので、文字列化は欲しくなるわけです。
enumを文字列化するために、`String()` 設けたりします。

```go
func (z Zodiac) String() string {
	switch z {
	case Rat:
		return "Rat"
	case Ox:
		return "Ox"
	case Tiger:
		return "Tiger"
	:
	}
	return ""
}
```

何を書かされているんだ…

という悩みを解決するために Stringer とか Apache Thrift とかがよく使われます

## ハナから文字列で良くない？

そもそも、別に数値である必要はないのでは。

```go
type Zodiac string

const (
	Rat    = Zodiac("Rat")
	Ox     = Zodiac("Ox")
	Tiger  = Zodiac("Tiger")
	Rabbit = Zodiac("Rabbit")
	Dragon = Zodiac("Dragon")
	Snake  = Zodiac("Snake")
	Horse  = Zodiac("Horse")
	Sheep  = Zodiac("Sheep")
	Monkey = Zodiac("Monkey")
	Cock   = Zodiac("Cock")
	Dog    = Zodiac("Dog")
	Boar   = Zodiac("Boar")
)
```

seealso: https://play.golang.org/p/kqHy0zm0vwn

`String()` も `MarshalText()` も `MarshalYAML()` もいらない。

ライトに定義するならこれで大体良いのでは。
仕事でも3年ほど同じものを開発し続けていますが、そこでenumを定義するときもおおよそこれで困ってません。
必要なら諸々書けばいいし、必要ないなら書かなければいい。

最初に書くのがダルいって声は聞こえそうですけど、このレベルならSnippetでどうにでもなります。
Goは割と手軽にGenerateしたら良いよという文化ですが、あんまりGenerate偏重ってのもどうなのかなと思っての提案でした。

## スペシャルサンクス

@po3rin さんの vim plugin のおかげで、この記事はとても快適に書けました。
https://qiita.com/po3rin/items/9b17a206fd8661235aa1
mockmockで特定の数のmockを一括操作する

本日は[mockmockアドベントカレンダー](https://qiita.com/advent-calendar/2019/mockmock)の22日目です。

昨日やった[mockで大量生産する機能](https://qiita.com/yukabeoka/items/f3cc79f6a90e49f27f53)を使うと、mockが大量にできます。（当たり前）
100台作ったmockの操作を100回ポチポチしたくないですよね。

ご安心ください。mockmockは`一括操作ボタン`をご用意しております！

## キャパシティを変更する

もしキャパシティがcn1であればcn50に変更します。
（優先度は キャパシティ > mock数 なので、mockを量産しても実際に起動する数はキャパシティが優先されます。）
![img_28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290135/501d8eb2-2529-4d75-1f26-93c5a74e9081.png)
これでキャパシティ数50に対して、mockが101台あることになります。

## mockは101台あるけど、45台だけ起動したい

操作mock数欄に45と入力し、`一括起動ボタン`よりmockを起動します。
![img_27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290135/aa178f6f-f66c-077a-6280-83f66ce30ff7.png)

## 起動してみたら

45台起動しました!
![img_30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290135/f80914a2-52eb-6c06-82ec-c49817b7345e.png)

mockを停止する場合は、同じように台数を入力して`一括停止`するだけです。

これで台数が多くても安心です。
やったね ✨💪✨

# 明日は
@Kta-M がmockmockのAPIについて書いてくれます。

明日もよろしくお願いします！
mockmockで自動的にmockを終了させる

本日は[mockmockアドベントカレンダー](https://qiita.com/advent-calendar/2019/mockmock)の17日目です。

mockmockは、mockを起動すれば停止するまでデータを送信し続けます。
うっかりmockを起動しっぱなし！…なんてことにならないように、mockmockには自動的にmockを停止させる機能が2つあります。
やさしい！
## 最大稼働時間
mock起動後、最大稼働時間までデータを送信したら自動でmockを停止する機能です。
mockグループ>設定 > 最大稼働時間（sec） より秒数を指定してください。
サンプル画面👇の場合、mockを起動して`4分後`に自動でmockが停止します。
![img_07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290135/af6b25f0-3a31-f2da-1218-1fe19de83b7a.png)
### mockを起動する
起動後放置してましたが、4分で自動的に停止していました。
![img_17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290135/4007356b-7d05-fb0f-ebeb-21d6e5a0d0ed.png)
## 終端ステータス
状態遷移先として、終端ノード[terminate]を選択できます。 
このステータスに遷移すると、mockが自動で停止します。
### 状態遷移を設定する
今回、mockグループ > mockステータス > default > 状態遷移設定 より
`指定回数送信後による遷移`を設定します。
20回データを送信すると`terminate`に状態遷移し、mockが停止します。
![img_18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290135/6f5476e4-b87b-7136-fab7-95a53c0c6926.png)
![img_20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290135/9115552e-16a8-dfb8-fee1-e992bb902681.png)
### mockを起動する

![img_21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290135/3a76f977-7806-50d3-84ec-b3d487fb0490.png)
設定通り20回データを送信したら停止しました。

やったね ✨💪✨

# 明日は
@cheekykorkind がmockの状態遷移について難易度別に書いてくれます（なんと3連続！）
明日もよろしくお願いします！
mockmockでデータ送信間隔をランダムにしてみる

本日は[mockmockアドベントカレンダー](https://qiita.com/advent-calendar/2019/mockmock)の16日目です。

mockmockでは10秒ごとなど定期的な周期を設定して送信しますが、`最大送信間隔`と`最小送信間隔`をうまく組み合わせることで、`ランダムな周期`で送信することもできます。

今回は送信間隔がランダムな仮想デバイスを作ってみます！
## 温度が変わらない温度計をつくる
まず結果がわかりやすいように、グラフバリュージェネレーターを一定の温度にします。ゆらぎも0にしましょう。
常に25、6度？の温度計が完成しました！
![img_13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290135/a4375e55-ee2c-628f-8210-beb4b9423970.png)
## 送信間隔を調整する
mockステータス > 状態遷移設定 より
最小送信間隔を10秒、最大送信間隔を30秒に設定します。
![img_15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290135/5159ae43-5281-c51b-d9a0-7801d79e9383.png)
これだけです！
あとはmockmockがいい感じにしてくれます。
ではmockを起動してみます。

## 送ってみた

縦軸がグラフバリュージェネレーターの温度で、横軸が送信時間です。
マーカーの間隔がバラバラですね。
（ちなみにExcelの折れ線グラフだとバラバラ間隔を再現できません。下記は`散布図`で作りました。）

ランダムな間隔でデータを送信する仮想デバイスができました！
![img_14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290135/a6acbefc-3c87-2b1c-edee-5af605d208fc.png)
定期的に送信しないデバイスも、この設定で再現できそうです。

やったね ✨💪✨

# 明日は
また私！
自動的にmockを終了させてみようと思います。

明日もよろしくお願いします！
mockmockのデータテンプレートでHTTP Request Headerを使ってみる

本日は[mockmockアドベントカレンダー](https://qiita.com/advent-calendar/2019/mockmock)の14日目です。

HTTP(S)での通信をする場合、送信データにリクエストヘッダーを定義できます。
今回はヘッダーにデバイスのシリアルナンバーをつけて送信してみます！
## ヘッダーの設定
プロジェクト > テンプレート より
該当のデータテンプレートの`HTTP Request Header`欄に値を設定します。
![img_05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290135/59fb240e-bae0-b4d4-46f8-7489f6f1a5b7.png)
`Name`キーに、`mock定数`の`serial_number`を設定しました。
![img_06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290135/ea7507dc-ad57-bcb2-c65f-736da68fc6ce.png)
## チュートリアル用のAPIサーバーを設定
設定したデータテンプレートをチュートリアル用のAPIサーバーに向けて送信してみます。
プロジェクト設定 > 送信先ホスト より設定します。
![img_12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290135/e74e3965-bef7-47e5-faaf-08fea9659f32.png)
## テスト送信してみる
mockを作成し、テスト送信します。
リクエストヘッダー欄を確認すると、`Name`キーにシリアルナンバーが入っています！
![img_04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290135/4e6e8288-4deb-3c77-ca9f-f551f3de2582.png)

やったね ✨💪✨

# 明日は
@Kta-Mが「データテンプレートの生成タイプ"bulk"」について書いてくれます。

明日もよろしくお願いします！
pythonのユニットテスト用ライブラリNoseのオプション紹介-19種類-

pythonのユニットテストツールNoseのnosetestsコマンドのオプション一覧です。
一覧といいつつ途中で力尽きたので私の独断ですがよく使う順に上から並んでます。
基本的な使い方とかはのせてません。

# 1. 全てのテストを実行(何もつけないで実行)

noseの命名規則と一致するファイル・テストケースを全て実施

```
nosetests
```

# 2. 特定のファイル内のテストを実行(テストファイルへのパスをつけて実行)

```
nosetests test_settings.py
```

# 3. 特定のテストケースのみ実行(FILEPATH:ClassName.methodName)

```
nosetests test_settings.py # 特定のファイル内のテストを実行
nosetests test_settings.py:SettingsApiTestCase　# 特定のファイル内の特定のクラス内のテストを実行
nosetests test_settings.py:SettingsApiTestCase.test_get_settings　# 特定のファイル内の特定のクラス内の特定のメソッドのテストを実行
```

# 4. 前回実行で失敗したテストを実行(--failed)

```
nosetests --failed
```

# 5. 複数プロセスで並列実行(--processes=NUM)
起動プロセス数を指定。

```
nosetests --processes=4
```

# 6. テスト実行プロセスのタイムアウト(--process-timeout=SECONDS)
デフォルトは10秒

```
nosetests --process-timeout=10
```

# 7. stdoutを出力させる(-s, --nocapture)

下の例であればtest_settings.pyの中に`print()`を仕込んであればその内容が出力される

```
nosetests test_settings.py -s
```

# 8. テスト結果表示を詳細にする (-v、--verbosity=VERBOSITY)

```
nosetests sample_test.py -v
nosetests sample_test.py --verbosity=2
```

※ -vと--verbosity=2は同じ、verbosityを大きくするほど詳しくなる

# 9. テスト結果表示を簡単にする(-q)

```
nosetests test_settings.py -q
```

# 10. テストを実行しないでテストケース名のみ収集する(--collect-only)

`-v`オプションと一緒に使いテストケース名をすべて出力させたりする。

```
nosetests --collect-only -v
```

# 11. working directoryの指定(-w)

下の例の場合`./tests/`の下のtest_settings.pyを実行するようになる。

```
nosetests test_settings.py -w ./tests/
```

# 12. configファイルの指定(-c)
home directoryの.nosercかnose.cfgをデフォルトで読み込む。これを指定する場合のオプション。何も読み込まないようにするには`export NOSE_IGNORE_CONFIG_FILES=1`

```
nosetests test_settings.py -c ./config.ini
```

# 13. 特定のファイル内のテストを実行その２ (--tests)

カンマ区切りで複数のテストファイルを指定する

```
nosetests --tests=test_settings.py,test_login.py
nosetests test_settings.py test_login.py # これでも同じ
```

# 14. 正規表現にマッチするファイルを実行(-m REGEX, --match=REGEX, --testmatch=REGEX)

デフォルトでは`((?:^|\b_\.-])[Tt]est)`が指定されているため`test`等で始まるファイルを実行する。下の例であれば`test_settings.py`は実行される。

```
nosetests -m .*setting.*
```

# 15. 正規表現でテストファイルを除外(-I REGEX, --ignore-files=REGEX)

下の例ならtest_settings.pyは実行されない

```
nosetests -I .*setting.*
```

# 16. 正規表現でテストケースを除外(-e REGEX, --exclude=REGEX)

以下の例ならテストケースtest_get_settings1はスキップされtest_get_settings2は実行される

```
nosetests -e .*settings1.*
```

# 17. 追加で実行するテストファイル名を正規表現で指定(-i REGEX, --include=REGEX)

下の例だと`-m aaaaaaaaaaaaa.py`をしているので`aaaaaaaaaaaaa.py`と完全一致する物しか実行されないところ、`-i .*setting.*`を指定しているのでtest_settings.pyが実行されます

```
nosetests -m aaaaaaaaaaaaa.py -i .*setting.*
```

# 18. 失敗するまでテスト実行・失敗したらテスト停止(-x, --stop )

```
nosetests -x
```

# 19. テストのスキップを無効化する(--no-skip)

`@unittest.skip("skipping this one")`等をつけるとテストケースがスキップされるがこれをスキップされなくするオプションだと思うのだが、実行するとスキップ自体はされてテスト結果の表示の時に`OK (SKIP=1)`が`OK`となるだけのよう？？？

```
nosetests test_settings.py --no-skip
```
bashで配列の中身をランダムに抽出する。 

## やりたいこと
bashで配列の中身をランダムに抽出したい！
これってトリビアのタネになりませんか？

## やり方

bashでは`${#ARRAY[*]}`で配列のサイズが取得できる。

``` random_array.sh
#!/bin/bash
readonly ARRAY=("foo" "bar" "baz" "qux" "quux" "corge")
echo ${#ARRAY[*]}      # 6
echo ${#ARRAY[@]}      # 6 @でも取得できるらしい。
```

次にランダムな値ですが、bashではRANDOMという謎の変数が用意されているらしい。
0〜32767までが範囲になっている。

``` random_array.sh
#!/bin/bash
echo $RANDOM           # 14067
echo $RANDOM           # 31125 値がランダムに取れている。
echo $(($RANDOM%10))   # 3     0〜9までの10パターンが取得できる。
```

これを組み合わせて使えば、配列からランダムな値が取得できる！

``` random_array.sh
#!/bin/bash
readonly ARRAY=("foo" "bar" "baz" "qux" "quux" "corge")
echo ${ARRAY[$(($RANDOM % ${#ARRAY[*]}))]} # foo
```
mockmockのグラフバリュージェネレーターの原点基準の違いを試す

本日は[mockmockアドベントカレンダー](https://qiita.com/advent-calendar/2019/mockmock)の11日目です。
記念すべき初アドベントカレンダー！
mockmockチームのべっちです。

昨日は@Kta-Mによる「公式ドキュメントに載っていない、Amazon API Gatewayで作ったAPIに向けてデータを送る方法」をお伝えしました。
本日は**グラフバリュージェネレーター**についてのお話です。

# グラフバリュージェネレーターとは
連続値をあつかえるバリュージェネレーターです。
視覚的にグラフを編集しながら時間とともに変化するデータを生成できます。
また「ゆらぎ」も与えることができるので、Excel等手作業でちまちまとテストデータを作っていた人には大助かりな機能です！
## 原点基準
グラフの原点時刻（データを送り始めるスタート値）を設定できます。
今回はそれぞれの出力結果を見比べてみたいと思います！
![img_08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290135/d152a7d1-06c9-ff69-6bb2-124ef4493c66.png)
### グラフ原点時刻
グラフ原点時刻からの現在時刻の位置を「now」で表し、その値からデータを送信します。
（周期の値を変更すると`now`の移動スピードが変わります）
![img_16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290135/0c305b79-600f-0b13-a83e-8e9946c824b1.png)
![img_11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290135/03032cf4-b0f1-8450-0ddd-0d08fbb10adf.png)
### ステータス遷移時刻
グラフバリュージェネレーターの原点基準を`ステータス遷移時刻`にし、状態遷移を設定した場合、状態が変わるタイミングでグラフ原点が変わります。

テストのために、40秒ごとにdefault（グラフのなみなみ波形）→ Error（常に`0`）になるよう設定しました。
defaultに復帰するタイミングで、グラフのスタート地点がリセットされています。
「グラフの周期が120秒で、40秒ごとにエラー」となるため、「1つ目の山が終わる頃エラーになり、復帰するとまた最初からデータ送信」を繰り返しています。  
![img_09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290135/151b15e8-9b91-1d84-f714-aae44e8a35cc.png)
### mock起動時刻
mockの起動時刻がグラフ原点となります。
常にグラフの最初からデータを送信しています。（3周していますね）
![img_10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290135/76a0cfe4-200e-5c6f-383d-78baf49b53e9.png)
微妙に違う連続値の原点基準。
mockmockはデバイスの仕様に合わせて細かくカスタマイズできます。

ぜひ使い分けてみてください ✨💪✨

# 明日は
引き続き、私です！
バケットバリュージェネレーターについて書きます!
引き続きよろしくお願いいたします。
Laravel のremember_token

# Laravel の`remember_token`

私が Laravel プロジェクトを作成して、
システム開発を行っていたときに困ったことです。
備忘録としてまとめておこうと思います。

## ユーザの削除

私が実装しようとしていたのは、ユーザの退会処理でした。
退会の確認画面で、退会する選択をしたら、

- ユーザの持っている`Item`の削除
- ユーザに関するデータの削除
- ユーザのログアウト

の 3 つの処理が必要だと考え、以下のコードを記述しました。

```php:UserController.php
public function destroy () {
    $user = Auth::user();

    $user->items()->delete();
    $user->delete();
    Auth::logout();

    return redirect("/");
}
```

これで問題なく動く・・・はずでした。

## `remember_token`

いざ、テストを回してみると、
特定の条件でユーザが削除できないことに気付きました。

それは、
ログイン時に<font color="red">**ログイン状態を保持させる**</font>ことでした。

Laravel デフォルトのユーザ認証を実装すると、
ログイン状態を保持する`remember_token`があります。

コイツが悪さをしていたのです。

## ログイン状態を保持させたときの動作

色々調べてみました。
どうやら、ログイン情報を保持させると
`remember_token`が発行されて、`session`に保持されます。

そして、**ログアウトの処理時**に、
ユーザの`remember_token`が`update`処理により更新されます。

ここまでは、「そうなのか」で済む動作ですね。

### ユーザが復活！？

さて、上記のコードをテストしたと言いました。
そして、ユーザが削除できないとも言いました。
しかし、それは正しい動作の説明ではありません。

実は、しっかりとユーザの情報は削除されています。
しかし、ログアウト処理を行った際に
<font color="red">**`insert`処理が行われて**</font>いるのです。

どうやら、
`remember_token`を`session`で保持したユーザが見つからなかったとき
`insert`するようにデフォルトで組み込まれているようです。

つまり、<font color="red">**削除して追加していたため**</font>
結果として、**削除できてない**となった訳です。

```php:UserController.php
public function destroy () {
    $user = Auth::user();

    $user->items()->delete(); // Itemが削除される。
    $user->delete(); // ユーザが削除される。
    Auth::logout(); // ユーザが追加されてしまう。

    return redirect("/");
}
```

## 解決

まぁ、もしかしたらコードを見てすぐに
**順番がおかしいこと**に気付いた方もいらっしゃると思います。

まだまだ素人なため、動作の順番を誤っていました。
ブラウザで動作を確認しながら記述していた際に、
ログアウト処理を忘れており、`migrate:fresh`したときにログイン状態が保持されていることで
ログアウト処理を追加したのが原因でした。

と、いうことで、正しいコードは以下のとおりです。

```php:UserController.php
public function destroy () {
    $user = Auth::user();

    Auth::logout(); // ログアウト、update処理が行われる。
    $user->items()->delete(); // Itemが削除される。
    $user->delete(); // ユーザが削除される。

    return redirect("/");
}
```

よく考えれば、
<font color="red">**ログアウトしてから削除**</font>が正しい順序ですよね。

正しい知識に修正して、覚えていこうと思います。
PHP基礎 Part2

# 概要
PHPの独学で学んだ内容をアウトプットしていく

# 前回の内容
[PHP基礎 Part1]
[PHP基礎 Part1]:https://qiita.com/k__aizawa/items/9fe199f16af2761baf31

## データ型
[Part1]でも出てきた文字列や数字といった値には、それぞれデータ型というものが定義されている。
下の図１はデータ型の一覧である
[Part1]:https://qiita.com/aizawa_K/items/9fe199f16af2761baf31

【図1】データ型と型名

| データ型 | 型名 |
|:-----------|------------:|
| boolean | 論理型 |
| integer | 整数型 |
| float | 浮動小数点型 |
| string | 文字列 |
| array | 配列 |
| resource | リソース|
| NULL | ヌル値 |

## 変数とは
初学者向けに説明されている内容は、「データを入れる箱」とされている
これでもざっくりとした理解にはつながるが、個人的には以下の記事の内容にしっくり来るものがあった。
[なぜ日本人はオブジェクト指向をなかなか理解できないのか？](https://gihyo.jp/book/pickup/2012/0057 "技術評論社")

### 変数の定義
PHPでは変数を定義するルールとして、頭に__「$」__を付ける
こうすることで変数の定義が可能となる
PHPでは「=」は右辺のデータを左辺のデータに代入することを示す
(上で紹介した記事の内容だと「代入する」より「割り当てる」がより適した意味ではないかと提唱している)

```php:sample.php
<?php
  $number = 1; // 変数の定義を行う
  echo $number; // 定義した変数(1)を出力

  // 結果:1
?>
```

### 変数の役割
1. データの命名
2. 複数回使うデータをまとめられる

例えば直径の長さを求めるのに、変数を使う場合とそうでない場合とで想定する
変数を使う場合は以下の通りにコードが書かれる

```php:sample.php
<?php
  $radius = 5; // 半径の長さを定義
  $diameter = $radius * $radius * 3; // 直径の長さを算出し、変数$diameterへ割り当てる
  echo $diameter; // 変数$diameterを出力

  // 結果:７５
?>

```

これを使わないと以下のようなコードとなる

```php:sample.php
<?php
  $diameter = 5 * 5 * 3; // 直径の長さを算出し、変数$diameterへ割り当てる
  echo $diameter; // 変数$diameterを出力

  // 結果:75
?>
```

両方とも出力される結果は同じであるが、
下の方は仮に半径の長さが変わった場合に2箇所修正する必要がある
一方で、上のコードは変数$radiusの値を修正するだけで解決する

### 変数名の付け方
1. 英単語を用いる(変数で年齢を定義したければ「age」を用いる等、何を定義したいかが明確に判別可能な単語を使う)
2. 2語以上の場合は、大文字で区切る(例：$userName)
3. 数字から始まる命名は不可
4. ローマ字や日本語での命名は望ましくない

### 変数の更新
変数は割り当てられている値を更新することが可能

```php:sample.php
<?php
  $num = 5;
  echo $num; // 5が出力される
  // 結果:5
  $num = １０;
  echo $num; // 更新された変数の値が出力される
  // 結果:10
?>
```

また、現在割り当てられている変数の値に別の数字を足すことも可能

```php:sample.php
<?php
  $num = 5;
  $num = $num + 5; // 変数$numに5を加える
  echo $num; // 10が出力される
  // 結果:10
?>
```

これを他の四則演算も考慮した上で、省略した形が以下の形式となる

```php:sample.php
<?php
  $num = 10;
  $num += 5; // $num = $num + 5の省略系
  $num -= 5; // $num = $num - 5の省略系
  $num *= 5; // $num = $num * 5の省略系
  $num /= 5; // $num = $num / 5の省略系
  $num %= 5; // $num = $num % 5の省略系
?>
```

足す値、引く値が1のみである場合は、同じ記号を2度使うことで省略が可能
この形式をインクリメント、デクリメントと呼ぶ

```php:sample.php
<?php
  $num1 = 7;
  $num2 = 3;
  echo ++$num1; // 値は8
  // 結果:8
  echo --$num2; // 値は2
  // 結果:2
?>
```

## 文字列や変数の連結
文字列や変数を__「.」__で繋げると、文字の連結が可能になる

```php:index.php
<?php
  $term = "あいう";
  echo $term."えお"; // 変数と文字列を「.」で連結し出力
 // 結果:あいうえお
?>
```

文字列の連結は__「.=」__を用いることで省略した形で記述できる

```php:index.php
<?php
  $term = "かきく";
  $term .= "けこ"; // $term = $term . "けこ"の省略形
  echo $term; //
  // 結果:かきくけこ
?>
```

## 変数展開
ダブルクォーテーションで囲われた文字列の中に、
変数を組み込むと変数に割り当てられた値が出力される
使い方は、変数を「__{}__」で囲うこと

```php:index.php
<?php
  $today = "2019/12/0２";
  echo "本日は{$today}です"; // 全体を「""」で囲った上で、変数箇所を{}で囲う
  // 結果:本日は2019/12/02です
?>
```

## 次回
* if文
* switch文
見積もりとスケジュールについて、エンジニアとマネージャーがお互いにできること

# はじめに
エンジニアが仕事をする中で、切っても切り離せないものの一つに見積もりとスケジュールがあります。
一般的に見積もりに失敗してスケジュールに遅延が発生すると、評価が下がるのではないでしょうか?
しかし、考えてみると見積もりという予測が外れただけで、プロジェクト失敗の烙印を押されてしまっています。
これはとてももったいないことだと常々思っているので、ここではエンジニアやマネージャーとして**不確実性を減らす**ためにできることを説明していき、
世の中の開発環境が少しでも良くなってくれたらと良いと思います。

## 前提
ここではよくあるパターンとして、既存のサービスと連携する新規のサービスを作ることを想定します。
大まかな流れとして

既存のサービスの調査 → 新規サービスの設計、技術選定 → 見積もり → スケジュール → 開発 → リリース

とします。
本題の通り見積もりとスケジュールで、エンジニアとマネージャーの視点で**不確実性を減らす**ためにできることを考えていきたいと思います。

## エンジニア視点の見積もり、スケジュール
新規サービスの設計、技術選定が終わった段階でマネージャーから見積もりとスケジュール(どのくらいで終わるか)を求められるのではないでしょうか。
世の中には[不確実性コーン](https://tech.nikkeibp.co.jp/it/article/COLUMN/20131001/508039/)というものがあり、初期段階で正確な見積もりをすることは不可能です。
引用元にある通り、要求も完了していると言い難いので、スケジュールには最大で1.5〜2.0倍の遅延が発生することをマネージャーに伝えましょう。
他に不確実性を減らすためにできることとして、新規サービスにエンジニアとして使ったことがない技術がどれくらいあるかも重要になります。
使ったことがない技術が1つなら、調べながらなんとかなることが多いですが、2つ3つと増えていくとかけ算でどんどん不確実性が増えていきます。
自身やチームのスキルと相談しながら、あまりに使ったことがない技術が多い場合は、減らすことも検討したほうが良いと思います。

## マネージャー視点の見積もり、スケジュール
見積もりとスケジュールはエンジニアが出してくれます。
ではマネージャーとしては見積もり、スケジュールに対してどのように**不確実性を減らす**ことができるでしょうか。
1つは人のアサインです。先程のエンジニア視点でもあったとおり、使ったことがない技術が多い場合、それだけ不確実性が増えていきます。
もしもチームにその技術を使ったことがある人がいればそれだけ不確実性を減らすことができます。

逆に一番やってはいけないことは1人1プロジェクトを割り当てることです。
新規サービスを作る場合、インフラからアプリケーション、CI/CD、監視、運用と考えなくてはならないことが多いです。
全部できるよと言うエンジニアはいるかもしれませんが、本当に高いレベルで全部できる人はほとんどいないのではないでしょうか。
動くレベルが作れる人と今後の運用も考えて開発できる人とではアウトプットに雲泥の差があります。
直近は良いかもしれませんが、今後の開発速度の鈍化に大きく影響しますので、チームでカバーすることをおすすめします。

## 開発時にお互いに協力できること
スケジュールは一度引いたら終わりではありません。日々変化するものです。
ここでは開発時によく起こる事象からお互いに協力できることを考えていきます。

一つは見積もりとコミットメントの認識をそろえることです。
見積もりと言っても人によって見積もりの認識が違います。
見積もりをコミットメントだと考えている人もいれば、見積もりを予測だと考えている人もいます。
先程の不確実性コーンにある通り、長期の見積もり(1ヶ月以上)を確実に終わらせられる保証はありません。
ただ、1週間のタスク、更に小さく一つのタスクだけをコミットメントすることはかなりの確率で終わらせることができるのではないでしょうか。
コミットメントを約束できれば、確実にプロジェクトが進んでいることが保証できるので、それを積み上げていくことでおおよそのプロジェクトの終了時期が見えてきます。

他によくある例として、エンジニアがスケジュール通りに終わらなそうだと思っても放置をしてしまうことがあります。
これはスケジュール通りに終わらないと評価が下がるので、言い出しづらかったり、別に良いかと諦めてしまっているためです。
放置は一番悪いことです。早めに報告することによって、人をアサインすることもできるし、スケジュールを遅らせることもできるし、機能を削ることによって、期日に間に合わせることもできます。

# まとめ
エンジニアやマネージャーとして**不確実性を減らす**ためにできることについて解説をしました。
開発をするにあたり、考えなければならないことは不確実性を減らすことだけではありません。
属人性の排除やアウトプットの最大化、プロダクトの課題の特定などです。
このような内容を色々考慮にいれて開発をすることが大変なため、最近はフレームワークとしてスクラムが流行っています。
スクラムでは1sprintを1週間で行ったり、チームで開発することによって極力不確実性を減らすようになっています。
Webアプリケーションを作成するのにも1から全てを作るのではなく、ほとんどの人が考えることを減らすためにフレームワークを使っていると思います。
ぜひ、導入を検討してみてはいかがでしょうか。