OmniAICreator/Qiita-1.07M huggingface dataset:
Go言語で単純移動平均を返すAPIサーバー



## 必要なもの
- Go環境をセットアップ。IDEにIntellijのGoLandを使いました。
- PostgreSQL
- Kabu+の株価一覧表のcsvをDBに投入する https://kabu.plus/


## 結果
先にどういったデータを取得できるか示します。

下記のエンドポイントにアクセスして
`http://localhost:8000/sma?code=1333&date=2018-08-07`

このような結果が得られます。

```
[
    {
        "code": 1333,
        "price": 3820,
        "sma": 4084.2,
        "tstamp": "2018-08-07T00:00:00Z"
    }
]
```

1333マルハニチロの8/7における終値が3820。その日の25日移動平均は4084.2です。

## ソースコード
https://github.com/nrm176/SampleGoServer/blob/master/src/server.go

## ポイント

- Go言語は初めて触れたのですが、URLルータとディスパッチャのライブラリであるGorillaが理解しやすくかつ書きやすいです。サンプルコード読んでたら、多くのTutorial/Get Started系の記事で使われていました。
http://www.gorillatoolkit.org/


- Postgres側でmoving_averageという関数を用意します。引数は順に銘柄コード、日付、移動平均日数です。今回は25日で固定にしました。/sma?length=5などとクエリパラメターに加えてもよかったと思います。

- 下記のコードはテーブルから行を取得し、それをJSONに変換するパートです。 1. db.QueryでPostgresの関数の実行結果を取得。 2. columnsがcode, price, sma, tstampと4つあるので `for i, column := range columns`の部分でループを回す。 3. objectはmap、それをarray of mapのobjectsに追加するイメージです。

```go
func query(code string, dt string) ([]byte, error) {
	var objects []map[string]interface{}

	rows, _ := db.Query("select * from moving_average($1,$2, 25)", code, dt)

	for rows.Next() {
		columns, err := rows.ColumnTypes()
		if err != nil {
			return nil, err
		}

		values := make([]interface{}, len(columns))
		object := map[string]interface{}{}
		for i, column := range columns {
			object[column.Name()] = reflect.New(column.ScanType()).Interface()
			values[i] = object[column.Name()]
		}

		err = rows.Scan(values...)
		if err != nil {
			return nil, err
		}

		objects = append(objects, object)
	}

	return json.MarshalIndent(objects, "", "\t")
}
```
同じことFlaskでもDjangoでもできると言われればそれまでなんですが、Go言語を触ってみるにはいい機会でした。
合法にUITabBarButtonを取得する

- Swift4

# 動機
https://qiita.com/KosukeOhmura/items/71e50615fb7e95fe5d61
↑特定のタブバーアイテムにのみこれがしたい

# 問題
非公開クラスである `UITabBarButton`や `UITabBarSwappableImageView`に直接アクセスするとリジェクト理由になる。
`isKindOfClass`や`is NSClassFromString()`を使うのもも避けたい。
なるべくAppleの逆鱗に触れないように特定のTabBarItemのアイコンのバッジをカスタムしたい。

カスタムビューとか作るのめんどくさい。
ライブラリ探すのめんどくさい。

# 実装

```swift
extension UITabBar {
    // タブのボタンをとりだして配置後のx座標でソートしてindex番目を返す レンダリング後に呼ぶ didLoad等では動かない
    func findButtonByXOrder(_ index: Int) -> UIView? {
        // 子のうち一番横幅のおおきいもの（= background）を取り除く
        let buttons: [UIView] = subviews.filter({ $0 != subviews.max(by: { $1.frame.width > $0.frame.width }) })
        if index < 0 || buttons.count <= index  { return nil }
        
        // frame.origin.xでソートしてindex番目を返す
        return buttons.sorted(by: { $0.frame.origin.x < $1.frame.origin.x })[index]
    }
}
```

UITabBarのサブビューはUITabBackground（だっけ?）とUITabBarButtonであり、
横幅で判定してバックグラウンドを弾いてのこりのUIView継承してるクラスのインスタンスのframe.origin.xでソートしてindex番目取り出しました。

あとはうまく使ってください。
タブ大量に作って省略されると使えないので気をつけてください。あとレンダリング後に使ってください。どちらも座標が重複していてアレになります。

おしまい。
javascriptで配列のソート

###ソート　その１
単純な配列のソート

```main.js

//データ
let ary = [5,3,9,1,10]

//昇順
ary.sort((a,b) => {return a - b;});

console.log(ary);  //[1,3,5,9,10]

//降順
ary.sort((a,b) => {return b - a;});

console.log(ary);  //[10,9,5,3,1]
```

###ソート　その２
オブジェクト配列のソート

```main.js

//データ
let ary = [{id : 5, data : "aaaa"},
           {id : 7, data : "bbbb"},
           {id : 1, data : "cccc"},
           {id : 2, data : "dddd"},
           {id : 4, data : "eeee"}];

//idでソート（昇順）
ary.sort((a,b) => {return a.id - b.id;});

//idでソート（降順）
ary.sort((a,b) => {return b.id - a.id;});

```

###ソート　その３
文字列のソート
[リンク](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#%E9%9D%9EASCII%E6%96%87%E5%AD%97%E3%81%AE%E3%82%BD%E3%83%BC%E3%83%88)

```main.js
//データ
const aryData = [
  {id: "id_2", data: "データ２"},
  {id: "id_4", data: "データ４"},
  {id: "id_3", data: "データ３"},
  {id: "id_1", data: "データ１１"}
]

//ソート（昇順）
aryData.sort((a,b) => a.data.localeCompare(b.data, "ja", { numeric: true }));
```
Chart.jsの折れ線グラフでデータが無い箇所があっても補完して欲しい場合

## spanGaps
datasets内で `spanGaps: true`とすると補完して表示してくれる。

```
  datasets: [
    {
      label: '最高気温(度）',
      spanGaps: true,
      data: [35, , 37, 35, 34, 35, 34, 25],
```

##参考元
https://qiita.com/serv-platong/items/ff42761373302f2d472e
rails カラムの複数追加

$ rails generate migration add_カラム名_To_テーブル名 カラム名:データ型 カラム名:データ型
（例）
$ rails generate migration add_basic_info_to_users basic_time:datetime work_time:datetime

$ rails db:migrate
$ rails db:migrate:reset

```20181218130615_add_basic_time_to_users.rb
class AddBasicTimeToUsers < ActiveRecord::Migration[5.1]
  def change
    add_column :users, :basic_time, :datetime
    add_column :users, :specified_working_time, :datetime
    add_column :users, :affiliation, :string #ここに追加したいカラムを指定
  end
end
```
$ rails db:migrate


ちなみに、以下コマンドのようにカラムを複数追加することもできます。Detailsの箇所はどんな名前でもOKです。

postsテーブルにstring型のtitle項目とauthor項目を追加する
$ rails generate migration add_basic_info_to_users basic_time:datetime work_time:datetime

$ rails db:migrate

https://reasonable-code.com/rails-column/
各ヘルスケアサービスのBMR

# はじめに

弊社で運用しているサービス(あすけん)で各ヘルスケアサービスのBMRを調べたので記事にしてみました(´･ω･`)

# BRMとは

基礎代謝率
人間が何もしなくても消費するカロリー量

# BMRの代表的な計算式

## 厚生労働省

基礎代謝基準値×体重（kg）
[Ⅴ運動の基礎科学 - 厚生労働省](https://www.mhlw.go.jp/bunya/shakaihosho/iryouseido01/pdf/info03k-06.pdf)


## Harris-Benedict

  男性：66.47 + （13.75 × 体重kg） + （5.00 × 身長cm） - （6.78 × 年齢）
  女性：655.1 + （9.56  × 体重kg） + （1.85 × 身長cm） - （4.68 × 年齢）

## Harris-Benedict(日本人版)

  男性：66 + （13.75 × 体重kg） + （5.0 × 身長cm） - （6.8 × 年齢）
  女性：655.1 + （9.56 × 体重kg） + （1.7 × 身長cm） - （7.0 × 年齢）

## 国立健康・栄養研究所

  男性：((0.1238 + (0.0481 × 体重kg) + (0.0234 × 身長cm) - (0.0138 × 年齢) - 性別\*1)) × 1000 / 4.186
  女性：((0.1238 + (0.0481 × 体重kg) + (0.0234 × 身長cm) - (0.0138 × 年齢) - 性別\*1)) × 1000 / 4.186
  注）*1；男性=0.5473×1、女性=0.5473×2

## 国立スポーツ科学センター(JISS)

  基礎代謝量＝28.5 × 除脂肪体重
  除脂肪体重＝体重kg - 脂肪量
  脂肪量＝体重kg × 体脂肪率

## Mifflin-St Jeor

  男性：(9.99 x 体重kg) + (6.25 x 身長cm) - (4.92 x 年齢) + 5; 
  女性：(9.99 x 体重kg) + (6.25 x 身長cm) - (4.92 x 年齢) - 161. 

# 各ヘルスケアサービスのBMR

## あすけん

Mifflin-St Jeor 方式を採用

## iOS Health App

BMRの自動計算機能はない。
Apple Watch等から取得する必要がある。

## Google fit

| sex | height | weight | time | calories burned |
| --- | --- | --- | --- | --- |
| female | 150 | 40 | 11:01 | 510 |
| female | 160 | 40 | 11:00 | 537 |
| female | 170 | 40 | 11:03 | 569 |
| female | 150 | 55 | 11:05 | 582 |
| female | 160 | 55 | 11:10 | 615 |
| female | 170 | 55 | 11:11 | 646 |
| female | 150 | 70 | 11:22 | 698 |
| female | 160 | 70 | 11:20 | 709 |
| female | 170 | 70 | 11:16 | 721 |
| male | 150 | 40 | 11:40 | 539 |
| male | 160 | 40 | 11:44 | 573 |
| male | 170 | 40 | 11:46 | 606 |
| male | 150 | 55 | 11:47 | 619 |
| male | 160 | 55 | 11:52 | 645 |
| male | 170 | 55 | 11:49 | 682 |
| male | 150 | 70 | 11:45 | 690 |
| male | 160 | 70 | 11:41 | 717 |
| male | 170 | 70 | 11:32 | 739 |

## fitbit 

Mifflin-St Jeor 方式を採用

## My fitnesspal

Mifflin-St Jeor 方式を採用
https://www.myfitnesspal.com/ja/tools/bmr-calculator

# まとめ

Harris-Benedictよりも正確と言われている、
Mifflin-St Jeorを採用しているところが多かったです(´･ω･`)
岩手の寒い冬はガスセンサで身を守ろう

この記事は[IoTLT Advent Calendar 2018(neo)](https://qiita.com/advent-calendar/2018/iotlt_neo)の19日目の記事です。

岩手（ただ言ってみたかっただけ）の寒い冬を越すために必要な「石油ストーブ」。
今回は、この石油ストーブから出るガス（一酸化炭素など）で死なないようにガスセンサで空気中のガス濃度を可視化できるようにします。
僕自身岩手に住み石油ストーブを使っているため本気で取り組んでいきたいと思います！

# 実は本州一寒い岩手県
皆さんは本州一寒い県は知っていますか？
タイトルにも書いてしまっていますが実は岩手が一番寒いそうです。
ワカサギ釣りで有名な「[岩洞湖](https://www.fishing-v.jp/wakasagi/page.php?field_cd=7&pref_cd=3)」は皆さんもご存知かもしれません。
そんな岩洞湖は岩手県盛岡市薮川にあり、寒い時は氷点下30度にもなる本州一寒い場所となります。

# とても怖い一酸化炭素

皆さんは一酸化炭素をご存知でしょうか。
一酸化炭素とは？
> ガス機器や石油機器が正常な燃焼を行うためには充分な空気（酸素）が必要ですが、正しく使わないことで酸素が不足して不完全燃焼を起こすと、一酸化炭素（CO）という有毒なガスが発生します。

> 一酸化炭素（CO）は色も臭いも無く、毒性が強い気体のため、ほんの少しでも吸い込んでしまうと気づかないうちに中毒になる危険があります。
一酸化炭素（CO）中毒の最初の症状は風邪に似ていて、なかなか気づきにくく、次第に頭痛、吐き気がしてきて、手足がしびれて動けなくなり、重症になると、人体に強い機能障害を起こしたり、意識不明になって死にいたることもあります。

[一般社団法人　日本ガス石油機器工業会](http://www.jgka.or.jp/gasusekiyu_riyou/anzen/co/index.html)より引用

みなさんもこのような石油ストーブは一度は見たことがありますよね。
正しい使い方をしないとこれが危険なものとなります。
![stove2.png](https://qiita-image-store.s3.amazonaws.com/0/143395/079b8650-f5a8-cc7e-6942-de1a4c79b7f7.png)

# これで安心安全！（？）ガスセンサを使ったガス濃度可視化法
さて、前置きはこれくらいにして早速本題に入りましょう。

## 考えたもの
石油ストーブを使う際は必ず換気をしますよね？
これをしないと一酸化炭素が充満し最悪の場合死に至ります。
それを防ぐため一酸化炭素濃度をLEDで可視化します。

<img width="757" alt="スクリーンショット 2018-12-18 19.45.39.png" src="https://qiita-image-store.s3.amazonaws.com/0/143395/8c38d9f9-881e-8992-ac94-831487f6d903.png">




## 使ったもの

- [Arduino Uno](https://www.switch-science.com/catalog/789/)
- [MiCS5524搭載 ガスセンサモジュール](https://www.switch-science.com/catalog/2837/)

　ちなみにこのセンサでは一酸化炭素以外にも天然ガスや口臭のチェックができるそうです。

　※このセンサは確実にガスを検出してくれるものではありません。

- ブレッドボード
- 150オームの抵抗4つ
- ジャンパ線9本

## 回路

<img width="890" alt="スクリーンショット 2018-12-18 20.10.46.png" src="https://qiita-image-store.s3.amazonaws.com/0/143395/228e93f4-3145-91e7-859c-1be388b5280f.png">

ガスセンサモジュールのパーツがなかったためそれっぽいものを使用しています。
ガスセンサモジュールの端子を右から順にArduinoの5V、GND、A0に繋いでいます。
LEDはアノード（足が長い方）にDIGITALピンの0~4に繋ぎ、カソード（足が短い方）とGNDの間に抵抗を挟んで繋いでいます。

## プログラム

```gas_sensor.ino
int gasVal = 0;

void setup() {
    pinMode(0, OUTPUT);
    pinMode(1, OUTPUT);
    pinMode(2, OUTPUT);
    pinMode(3, OUTPUT);
    pinMode(4, OUTPUT);
 }

void loop() {
  gasVal = analogRead(0);
  if (gasVal < 200) {
    ledOut(1);
  } else if (200 <= gasVal && gasVal < 400) {
    ledOut(2);
  } else if (400 <= gasVal && gasVal < 600) {
    ledOut(3);
  } else if (600 <= gasVal && gasVal < 800) {
    ledOut(4);
  } else if (800 <= gasVal && gasVal <= 1000) {
    ledOut(5);
  }
}

void ledOut(int gasLevel) {
  for (int i = 0; i < 5; i++) {
    digitalWrite(i, LOW);
  }
  for (int i = 0; i < gasLevel; i++) {
    digitalWrite(i, HIGH);
  }
}

```

今回はLEDを５個使っていてセンサで測れる値が1~1000だったので200ずつに区切って光らせるようにします。


# 結果

![20181218_202212.jpg](https://qiita-image-store.s3.amazonaws.com/0/143395/434b0bed-f963-4cee-b480-47c511187ff8.jpeg)

できた！
部屋のガスのレベルが5段階で可視化できるようになりました！
レベルが高くなったら換気するなどの対策ができて良いですね！
これで岩手の寒い冬でも快適な反射式ストーブライフを送れそうです！

※今回使用したMiCS5524搭載ガスセンサモジュールは医療目的や火災等の煙を確実に検出できるものではないので使用する際は自己責任でお願いします。
iPadのSafariで表示しているページをデバッグする

iPadやiPhoneなどのSafariでWebアプリを表示させた際にデバッグをしたい、ということがあると思います。
Safariには「Webインスペクタ」という開発者ツールが準備されており、このツールを使うことでMacからデバッグを行うことができます。


###iPad側の準備
Webインスペクタの機能をONにします。

iOS12の場合
設定アプリ > Safari > 詳細 > WebインスペクタをON

###Mac側の設定
MacのSafariの設定を行います。

Safariを立ち上げる > Safariのメニューの中から環境設定を選択する > 詳細 > メニューバーに"開発"メニューを表示にチェック

画面上部のメニューバーに「開発」メニューが表示されていることを確認します。

###つなげる
iPadとMacをUSBで接続します。

###デバッグ画面を開いてデバッグする
iPadのSafariで対象のWebページを開いた状態にします。
MacでもSafariを起動した状態にします。

MacのSafariの「開発」メニューを開くと、接続しているiPadが表示されているはずです。
マウスオーバーすると、iPadで開いているWebページが表示されるのでこれをクリックします。
こうすることでWebインスペクタが開き、デバッグを行うことができます。
YesodでHelloWorld!

YesodでHelloWorldします。

Yesodを検索するとデフォルト画面の出し方や、シェークスプアテンプレートを使わないサンプルはよく見るのですが、ページを追加してHelloWorldする記事があまりなく、少しはまったので記事にしました。

OS: Windows8.1 64bit
Stack: 1.7.1

まずはstackでmy-projectプロジェクトを作成。

```
stack new my-project yesod-sqlite 
cd /d my-project
```

yesodをインストール。

```
stack install yesod-bin --install-ghc
```

ここまででyesodのデフォルトページが作成されています。
実行してみます

```
stack build
stack exec -- yesod devel
```

http://localhost:3000　
にアクセスすると、こんな感じのデフォルトページが表示されます。

![p1.png](https://qiita-image-store.s3.amazonaws.com/0/87133/5e89c4c9-c692-1c87-86e0-0d73f1080302.png)

Ctrl+Cでいったん止めます。

HelloWorldを表示するページを作成。
スキャフォルド機能でページを追加します。

```
stack exec -- yesod add-handler
```

下記のように質問されるので、それぞれ Hello, /Hello, GETと入力します。

```
Name of route (without trailing R):Hello
Enter route pattern (ex: /entry/#EntryId):/Hello
Enter space-separated list of methods (ex: GET POST): GET
```

/Helloというページが作成されますが、アクセス許可を与える必要があります。
my-project\src配下のFoundation.hsファイルで設定します。

162行目あたりに

```
-- Routes not requiring authentication.
```

という記載があるので、その下に一行追加します

```
isAuthorized HelloR _ = return Authorized
```

実行してみます。

```
stack build
stack exec -- yesod devel
```

http://localhost:3000/Hello
にアクセスすると下記のように表示されます。
![p2.png](https://qiita-image-store.s3.amazonaws.com/0/87133/f7071028-9fd6-4bf2-f1c5-de083fdc9006.png)

Ctrl+Cで止めて、HelloWorldが表示されるように修正します。

my-project\src\Handler配下のHello.hsファイルを修正します。
開くと下記のように作成されています。  

```
module Handler.Hello where

import Import

getHelloR :: Handler Html
getHelloR = error "Not yet implemented: getHelloR"
```

先頭行にライブラリを追加し、最下行をコメントアウトして、一行追加します。

```
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeFamilies #-}

module Handler.Hello where

import Import

getHelloR :: Handler Html
--getHelloR = error "Not yet implemented: getHelloR"
getHelloR = defaultLayout $(widgetFile "hello")
```

my-project\templatesにhello.hamletファイルを作成して下記のように記載します。

```
<p>HelloWorld!
```

閉じタグは不要です。

実行します。

```
stack builid
stack exec -- yesod devel
```

http://localhost:3000/Hello
にアクセスすると下記のようにHelloWorld!が表示されます。
![p3.png](https://qiita-image-store.s3.amazonaws.com/0/87133/5208ba3c-7be0-0ba6-decc-353fbe610e8b.png)

めでたしめでたし。

[https://github.com/ringo-apo/qiita_hs_yesod_hello](https://github.com/ringo-apo/qiita_hs_yesod_hello)  

##参考
[[Yesod入門(1)] Stack,Yesodのインストール～起動 │ Web備忘録](https://webbibouroku.com/Blog/Article/yesod-1)
書籍　Haskellで作るWebアプリケーション
SEの転職活動の質問メモ

## 技術的な質問

1. パフォーマンスチューニングの経験は

2. DIコンテナをわかりやすく説明して

3. デザインパターンって何が言える?何を使ったことある。

4. コードを格上で守っている規約は。また気を付けていることは何。

5. テーブルの正規化って何？

6. 正規化しないパターンはどんなとき

7. パフォーマンスチューニングの経験は

8. アクセス修飾子でしっているものと違いを述べて

9. テストはどのようにする？

19. 知っているJavaScriptのライブラリをあげて

11. JavaScriptのコンソール（デバック方法）

12. テーブルを０から作った経験は

13. ソースコードレビューしたことある？

14. どんなサーバサイドJavaScript使ったことある
Sublime Text3で「Finderでフォルダを開く」ショートカットを設定する

Sublime Text3でコーディングしているときに、ショートカットキーで現在開いているファイルのある場所をFinderで開きたいときがままある。

そこで、「Finderでフォルダを開く」ショートカットを設定したので手順をメモしておく。

1. Package controlから[Open Finder](https://packagecontrol.io/packages/Open%20Finder)をインストールする
2. ```Preference → KeyBindings```を開き、User側の設定ファイルの```[...]```の中に以下を追加する。```Keys```にはお好みのキーバインドを書く。

    ```json
        {
            "keys": ["super+shift+o"],
            "command": "open_finder",
            "args": {}
        }
    ```

3. 設定を保存すれば現在開いているファイルのあるフォルダをFinderで開ける。
Vue CLI3で始めるVue.js

## Vueでの環境構築

弊社では、Vue.jsでのフロントエンド開発が増えており、今までjQueryに慣れ親しんでいた人もVue.jsに移行していたりします。

しかし、その際Vue.jsの環境構築につまづくことがありました。
本記事ではそのときにまとめたVue.jsの環境構築の方法を記載しています。

## Vue.jsの環境構築方法

Vue公式では、下記3つの方法を用意しています。

- CDN
- NPM
- CLI

今回私のチームでは、ライブラリの導入しやすさ、単一コンポーネントの使用の点を考慮し、CLIを使ったVue.jsの導入をすることにしました。


## Vue CLI3を使った環境構築
Vue CLI3を使って環境構築していきます。

### 1. インストール
```
$ npm install -g @vue/cli
```

※-gを付加し、グローバルにインストールしたくない場合は、npxを使うこともできます。
※Vue CLI3を使用するにあたって、**Node.js(v8.9以上)が必要**です。```node -v```を実行し、条件を満たしていなければ、先にnodeをインストールする必要があります。

### 2. インストール確認

```
vue --version
```
### 3. プロジェクト作成

```
vue create [プロジェクト名]
```
[プロジェクト名]: 任意のプロジェクト名を入力(```vue create vue-sample```など)

### 4. 色々回答
TypeScript / Vuex / Vue Router / 各種テストツール / リントを入れたりと、色々選択できます。特にわからなければ、デフォルトでも大丈夫です。

ここでは、[Babel]のみを選択します。

1. [Manually select features] を選択

1. [Babel]を選択

1. [In dedicated config files]を選択

1. [Save this as a preset for future projects? (y/N)]では[N]を選択

### 5. 開発用でVueを起動してみる。
標準出力に書いてあるとおりに下記を実行します。
 
```
$ cd vue-sample
$ npm run serve
```

サーバの起動ができたので、アクセスしてみます。
LocalもNetworkも基本的には変わりませんが、Networkの方であれば、スマホからでもアクセス可能です。(PCとスマホで同じネットワークに属している、かつ、セパレータ等の機能がネットワーク機器に設定されていない場合)

  App running at:
  - Local:   http://localhost:8082/ 
  - Network: http://192.168.0.63:8082/


![e5098f00-1b61-60bf-c0e8-5ad3209bb092.png](https://qiita-image-store.s3.amazonaws.com/0/147186/f6d4280e-8f8f-ba14-8f7e-29e1c0e1195c.png)


### 6.本番用でVueを起動してみる
```
$ npm run build
$ cd dist
$ php -S localhost:8080 # dist直下にあるファイルは、HTTPサーバ経由でアクセスする必要があります。ここではPHPを使いましたが、それ以外でも大丈夫です。
```
[http://localhost:8080](http://localhost:8080/)にアクセス

## Vueの最小構成

プロジェクトを作成した直後はsrc/App.vueはこのようになっていますが、

```src/App.vue
<template>
  <div id="app">

    <HelloWorld msg="Welcome to Your Vue.js App"/>
  </div>
</template>

<script>
import HelloWorld from './components/HelloWorld.vue'

export default {
  name: 'app',
  components: {
    HelloWorld
  }
}
</script>

<style>
#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>
```

下記のように書き換え、さらに[src/assets/logo.png]と[src/components/HelloWorld.vue]を削除すれば、Vue.jsの最小構成となります。

```src/App.vue
<template>
  <div>
    最小構成だよ
  </div>
</template>

<script>
export default {
}
</script>

<style>
</style>
```

## 注意点
Vue.jsの公式ガイドを見てみると、CDNによるVue.js環境構築を前提としたコーディングが説明されており、dataを扱う場合は下記のように説明されています。

```
data: {
  message: 'Hello Vue!'
}
```

しかし、単一ファイルコンポーネントとして、dataを使う場合は下記のようにreturnする必要があります。

```
data: {
  return {
    message: 'Hello Vue!'
  }
}
```

## 参考URL
[Vue CLI 3](https://cli.vuejs.org/)
[Vue.js](https://jp.vuejs.org/)
[コンポーネントのデータ-必須](https://jp.vuejs.org/v2/style-guide/#%E3%82%B3%E3%83%B3%E3%83%9D%E3%83%BC%E3%83%8D%E3%83%B3%E3%83%88%E3%81%AE%E3%83%87%E3%83%BC%E3%82%BF-%E5%BF%85%E9%A0%88)
Perlから始めないCGI入門


思い出したようにCGIってどんな仕組みだっけ？と学び直そうと調べたのですが、
shebangを読み込んでプログラムが実行され標準出力がクライアントに送信される簡単な仕組みだったのですね。

## サーバー設定

dockerでapacheを起動します。
httpdの公式dockerイメージではCGIが有効になっていないので、httpd.confを編集しながら起動します。

```bash
 $ docker run -it -p 80:80 -v $PWD:/usr/local/apache2/cgi-bin httpd sh -c 'sed -ri "/cgid_module|cgi-script/s/#(.*)/\1/" /usr/local/apache2/conf/httpd.conf && httpd-foreground'
```

## Hello,World!
shebangには1つだけオプションが渡せるので、CGI の Hello,World! は以下のように書くことができます

```bash:sed.cgi
#!/bin/sed 1d
Content-type: text/plain; charset=utf-8

Hello,World!
```

```bash:tail.cgi
#!/usr/bin/tail -n+2
Content-type: text/plain; charset=utf-8

Hello,World!
```

## プロキシサーバー

プロキシサーバーも２行で十分ですね。……これはプロキシサーバーなのでしょうか？
とりあえず ``` http://localhost/cgi-bin/proxy.cgi?http://www.google.com/ ``` のようにアクセスするとCGI経由でコンテンツを取得できます。

```bash:proxy.cgi
#!/bin/bash
curl -sSi "$1" | sed -r '1d;/^Transfer-Encoding/d'
```

httpdの公式dockerイメージではcurlが入っていないのでcurlをインストールする必要があります。

```bash
$ docker exec -it YOUR_CONTAINER_ID sh -c 'apt-get update && apt-get install curl -y'
```

## 改めてPerlのCGIでHello,World!

shebangが重要になるのであれば プログラム言語のCGIでは
``` /usr/bin/env ```で始めるべきで、PerlのHello,World!は下記になるのでしょうか？

```perl:hello.cgi
#!/usr/bin/env perl
print <<EOS
Content-type: text/plain; charset=utf-8

Hello,World!
EOS
```
調べてみるとやはり、[```#!/usr/bin/env perl``` でなく ```#!/usr/bin/perl``` だとハマることもあるみたいです。](https://qiita.com/DQNEO/items/6116bf9986932bc56c9f)

しかし[Perl, Python 及び Ruby スクリプトにおける正しいshebangの書き方](https://qiita.com/tueda/items/369215b99316b2e9f3d8) によると、
```#!/usr/bin/env perl```では駄目らしく、Perlでの正しいshebangは７行くらいある下記が正しいようです。

```perl:hello.cgi
#! /bin/sh
eval '(exit $?0)' && eval 'PERL_BADLANG=x;PATH="$PATH:.";export PERL_BADLANG\
;exec perl -x -S -- "$0" ${1+"$@"};#'if 0;eval 'setenv PERL_BADLANG x\
;setenv PATH "$PATH":.;exec perl -x -S -- "$0" $argv:q;#'.q
#!perl -w
+push@INC,'.';$0=~/(.*)/s;do(index($1,"/")<0?"./$1":$1);die$@if$@__END__+if 0
;#Don't touch/remove lines 1--7: http://www.inf.bme.hu/~pts/Magic.Perl.Header
print <<EOS
Content-type: text/plain; charset=utf-8

Hello,World!
EOS
```
……私にはまだPerlでCGIを書くのは早かったみたいです。

かつて学生だった頃に意味を理解せずにPerlでCGIを書いていた記憶がありますが、
標準入出力さえアレばどんなプログラムでもよかったのですね。
また、dockerを使えばワンライナーでサーバーを立ち上げられる時代になったのは嬉しいですね。
今後CGIで書くことは無いと思うので、特に意味はない気がしますが……

## 参考

[シバン (Unix)](https://ja.wikipedia.org/wiki/%E3%82%B7%E3%83%90%E3%83%B3_(Unix))
[開眼☆シェルスクリプト CGIスクリプトを作る(1)―Webサーバへのデータは標準出力で渡す](https://uec.usp-lab.com/JOURNAL/CGI/JOURNAL.CGI?POMPA=KAIGAN_journal19)
[シェルスクリプトでCGI](https://qiita.com/mutz0623/items/d728c4b27cf5db741356)
Angular -  Can't resolve './' エラー

## Angular -  Can't resolve './' エラー

Angular触っていて、TemplateもStyleも使わないコンポーネントを作ったときに

```
Failed to compile.

./src/app/foo.component.ts
Module not found: Error: Can't resolve './' in 'foo/src/app/foo'
```

みたいな、コンパイルエラーが出るときは、

```foo.ts
@Component({
  selector: 'app-foo',
  template: ``,
  styleUrls: ['']
})
export class FooComponent implements OnInit {
```

上記のように、`styleUrls: ['']` としていませんか？
正しくは、`styleUrls: []`です。

```foo.ts
@Component({
  selector: 'app-foo',
  template: ``,
  styleUrls: []
})
export class FooComponent implements OnInit {
```

忘れがちなのでメモ
国内格安sim: mineo-Dのnichephone-s 4Gでの利用方法

これまでiPhone 5sでmineドコモ回線を使ってきたのですが，nichephone-s 4Gの導入にあたりいつでも復元できるよう各設定をまとめておきます。

## iPhone 5s (docomo sim locked) + mineo-D sim

私のiPhone 5sは以前にdocomoで購入したものになるのでsimロックされており，APN設定は全く操作できない仕様になっております。そのため[mineo-D契約用のプロファイル](https://support.mineo.jp/setup/guide/ios_network.html)をダウンロードして適用すればOKです。

## nichephone-s 4G (sim free) + mineo-D sim

一方でnichephone-s 4Gはsimフリー端末なので，APN設定を詳しく操作できます（というかしなければなりません）。mineo-D simはベンダーのFuture Modelの方できちんと[検証](http://futuremodel.co.jp/product_list/Niche_Phone-S-4G-SIM_Simplicity.html)されており，下記の利用が推奨されています（端末上では設定＞モバイルネットワーク＞APN>新しいAPNから入力）。

APN: mineo-d.jp
ユーザー名: mineo＠k-opti.com
パスワード: mineo
認証方式: CHAP

本来ならばこれを入力するべきところなのですが，私が購入時点でのnichephone-s 4gにはmineoやIIJmioなどの動作検証済みSIM，動作保証外SIMのAPN設定がそれぞれ入っており，設定＞モバイルネットワーク＞APN>APNからどれかを選べるようになっていました。

<img width="600" alt="apn.png" src="https://qiita-image-store.s3.amazonaws.com/0/327826/69e02029-9e0a-1e5e-83ba-3a07e343eb07.png">

後はmineo電話の回線を使って通話できるように，設定＞モバイルネットワーク＞プレフィックス発信を選んで「0063」を登録しておく。これで任意の電話番号に対して0063をつけたプレフィックス発信が使えるようになります。

しばらく使ってみましたが，この小ささは癖になりますw
耐久性がどの程度かは今後の運用とともに評価ですね。
Ada言語 6日目 if文

# はじめに
変数についてもっとやってからやろうと思ったのですが、やっぱり制御文がやりたくなってしまったので今日は条件文をやりました。

#ソースと結果

```main.adb

with Ada.Text_IO;
use Ada.Text_IO;

procedure main is

    hennsuu1 : Integer := 0;

begin

    if hennsuu1 = 1 then
        Ada.Text_IO.Put_Line("hennsuu1 = 1");
    elsif hennsuu1 = 2 then
        Ada.Text_IO.Put_Line("hennsuu1 = 2");
    else
        Ada.Text_IO.Put_Line("hennsuu1 = other");
    end if;

end main;

```

`実行結果 : hennsuu1が1のとき "hennsuu1 = 1"`
`実行結果 : hennsuu1が2のとき "hennsuu1 = 2"`
`実行結果 : hennsuu1が1でも2でもないとき "hennsuu1 = other"`

#最後に
Ada言語では、C言語とは異なり、評価はイコール一つ(=)で記述するようです。
イコール二つ(==)にすると、` == shuld be = `と、エラーが出ます。

#日記一覧へ
[Ada言語を習得する日記一覧](https://qiita.com/C_Assembly/items/50a0f9d8542679d92ea8)
Nefry BTでGrove人感センサをサクッと扱う


こんにちは、ちゃんとくです。この記事は[Nefry Advent Calendar 2018](https://qiita.com/advent-calendar/2018/nefry) 4日目の記事です。

## Nefry BTって？

[![Image from Gyazo](https://i.gyazo.com/7a03cd802d043a75ac63bcfd1e6820f9.png)](https://gyazo.com/7a03cd802d043a75ac63bcfd1e6820f9)

Nefry BTは「ESP-WROOM-32」というWi-Fi・BLE通信モジュールを搭載した、Arduinoと同じように開発できるマイコンボードです。

[Grove](https://dotstud.io/docs/grove/)という刺すだけで配線できるモジュール対応のコネクタを搭載していて、ハードウェアをあまり意識せずに開発できます。

この記事は下記のNefry BT環境構築・初期設定が済んでいる前提で進めます。

- [Arduino IDEをPCにインストール](https://dotstud.io/docs/arduinoide-setup/)
- [Nefry BTの環境構築（Arduino IDE）](https://dotstud.io/docs/nefrybt-setup-arduino-ide/)
- [Wi-Fi情報を設定](https://dotstud.io/docs/nefrybt-setup-wifi/)

## Groveって？
![Image from Gyazo](https://i.gyazo.com/c8398ee929c599bf002de21b82bd234a.png)
中国の[Seeed Studio](https://www.seeedstudio.io/?gclid=EAIaIQobChMIgK602I6p3wIVTKSWCh3ruQDCEAAYASAAEgLhtPD_BwE)社が開発・販売している**刺すだけで配線できるモジュール**です。電源、信号線がソケットにまとめられており、回路の知識があまりなくても配線を行えます。

温湿度センサ、照度センサ、磁気スイッチ、サーボモータなど基本のモジュールは大体網羅しており、現在は**100種類以上**あるようです。（中の人に聞いたところ「数を把握しきれていない」とのことでした…！）

## 人がいることを検知する
![motion_sensor.jpg](https://qiita-image-store.s3.amazonaws.com/0/119003/2720a43b-fc54-694c-a660-ef349d95ee4a.jpeg "motion_sensor.jpg")

人を検知できる人感センサ（PIRモーションセンサ）です。最大6m範囲、120度角の範囲に人がいるかどうか判定します。（[公式Wiki](http://wiki.seeedstudio.com/Grove-PIR_Motion_Sensor/)）

### 配線
![connection.jpg](https://qiita-image-store.s3.amazonaws.com/0/119003/15b7ea66-bb71-9a65-6771-8d18bfc279e4.jpeg "connection.jpg")

人感センサは「D2」というソケットに差し込みます。少し硬いですが、カチッと言うまで押し込めます。配線作業は常に電源オフの状態で行います。

### プログラム

```
#include <Nefry.h>

#define PIR_MOTION_SENSOR D2

void setup()
{
    pinMode(PIR_MOTION_SENSOR, INPUT);
}

void loop()
{
    if(digitalRead(PIR_MOTION_SENSOR)) {
        Nefry.println("誰かきたよ");
    } else {
        Nefry.println("監視中");
    }
    delay(200);
}
```

### シリアルモニタで確認

![serial_monitor.png](https://qiita-image-store.s3.amazonaws.com/0/119003/02444b64-a748-8676-7450-9df8336c9eb2.png "serial_monitor.png")

メニューの**`ツール>シリアルモニタ`** を選択して開きます。

※シリアルポート接続（PCにUSB接続）できない人 → [Nefryポータル](https://dotstud.io/docs/nefrybt-basic-portal/)の「Web Console」を見ましょう

![bps.png](https://qiita-image-store.s3.amazonaws.com/0/119003/3b9aee15-195b-4115-ad0a-19b28471ad65.png "bps.png")
Nefry BTのデフォルトは115200bpsになっています。右下のbps設定を「115200bps」に変更します。

![adaf9534c9e944f3131336058a304671.gif](https://qiita-image-store.s3.amazonaws.com/0/119003/8bec5354-b890-30af-3af8-6a7e994d5c53.gif "adaf9534c9e944f3131336058a304671.gif")

人がいるとアラートメッセージがでます。

## その他
「アラートメッセージをメールやLINEに通知したい！」などという時は[**LINE Notify**](https://notify-bot.line.me/ja/)や[**IFTTT**](https://ifttt.com/)を使った連携が便利です。

- [Nefry BTとLINE Notifyをサクッと連携](https://qiita.com/tokutoku393/items/1b8d6204915505ebb044)
- [Nefry BTとIFTTTをサクッと連携](https://qiita.com/tokutoku393/items/0235a9624aa6a29b2d55)

サービス側の設定をすれば`LineNotify.send()`、`IFTTT.send()`といった関数でサクッと試せますので、ぜひご参照ください。
RedmineをView Customize pluginを使ってカスタマイズ～引用折り畳み編～

# 要件

- BtoCサービスのスタッフ向けに構築したRedmineで特定顧客とのメール履歴をチケットに集約した

その結果、下記のような課題がスタッフより上がってきたので、その課題の解決を`View Customize plugin`で行った。

## 課題

- メールの引用部分が長すぎて、メール本文を見るのが大変
- チケットの履歴欄にメールの送受信履歴が縦に並んでいくので見づらい

## 解決案

- 引用部分はクリックで表示、非表示を切り替えできるようにする
- LINEの画面のように、相手と自分でメッセージを左右に寄せて、吹き出しの色を変える

今回は上記課題の`メールの引用部分が長すぎて、メール本文を見るのが大変`を`引用部分はクリックで表示、非表示を切り替えできるようにする`にて解決する手順を紹介。

もう一つの課題解決は以下記事を参照。
[RedmineをView Customize pluginを使ってカスタマイズ～LINE風チャット画面実装編～](https://qiita.com/yuta-yoshinaga/items/fbaf542acf41a445e72b)

## 環境
- Redmine Ver. 3.4.6
- View Customize plugin Ver. 2.0.0
- テーマ Farend basic

## View Customize pluginでの設定手順

[View Customize plugin](https://github.com/onozaty/redmine-view-customize)のインストール方法など公式リポジトリを参照。
以下はView Customize pluginがインストールされている前提での設定手順

1. Redmineの管理ボタンを押す
2. 日本語環境であれば`表示のカスタマイズ`を押す。
3. `新しい表示のカスタマイズ`を押す
4. パスのパターンに`/`を入力する。
5. 挿入位置を`チケット詳細の下`にする。
6. 種別を`JavaScript`にする。
7. コードに下記コードを入力する。

```javascript
$(document).ready(function () {
    $('blockquote').each(function (index, element) {
        $(this).hide();
        var style = "\n\t\t\tbackground-color: #bdc1c6;\n\t\t\tborder-radius: 5.5px;\n\t\t\tborder-color: #cdcdcd;\n\t\t\tcursor: pointer;\n\t\t\tcolor: #6b6c6e;\n\t\t\tfont-weight: bold;display:inline-block;\n\t\t\tmargin-bottom: 10px;\n\t\t";
        $(this).after('<div title="コンテンツをすべて表示する" style="' + style + '">・・・</div>');
        var toggle = $(this).next('div');
        toggle.on('click', function () {
            var tgt = $(this).prev('blockquote');
            tgt.toggle();
            if (tgt.is(':visible')) {
                // 表示されている場合の処理
                $(this).attr('title', 'コンテンツを非表示にする');
            }
            else {
                // 非表示の場合の処理
                $(this).attr('title', 'コンテンツをすべて表示する');
            }
        });
    });
});
```

## 解説

解説といっても大したことはしていなくて、Redmineの全てのページに対して、上記のスクリプトを埋め込んでいる。
Redmineは引用部分(行頭が>で始まる行)をblockquoteタグで囲ってくれるので、ページ内に含まれるblockquoteタグをデフォルトで非表示にして、blockquoteのすぐ後ろに表示・非表示を切り替えるボタンのコードを挿入している。

## 所感

時間がなくて調べ切れていないが、これくらいなら既存プラグインで同一機能とかもしくは標準機能でもありそうな気がする。
Airflow tutorial解説入れながらやってみた

これはRetty Inc. AdventCalendar2018 19日目の記事です。 
昨日は@masadooonさんの[Rettyの意思決定を最大化！データ分析チームの取り組み](https://engineer.retty.me/entry/2018/12/18/115020)をご紹介でした。

# はじめに
Rettyでインターンをしているものです。
Rettyではluigiを集計に使用しているサービスがありますが、分析基盤ではAirFlowを使用していることもあり統一しようとしています。
現在インターンでの業務としてAirflowに移行できるかどうかの検証を行っており、まず理解するためにAirflow Tutorialをやっていましたので解説していきたいと思います。

# Airflowとは
- 言語 : Python
- Airflowは、ワークフローを記述、実行、監視するためのツール
- タスクの依存関係を管理

# Airflow Tutorial 実践


公式
https://airflow.apache.org/index.html
Tutorialに書いてある通りsetupしていきます

## Python 環境構築
まずアップデートします
`$ apt-get -y update`

pipをインストールします。
`$ apt-get install python-pip`

インストールしたpipをupgradeします。
`$ pip install --upgrade pip`


## Airflow 構築
パスを通します
`$ export AIRFLOW_HOME=~/airflow`

airflowをインストールします。
`$ pip install apache-airflow`

### 構築時に起きたエラー 1
出なかった場合読み飛ばしてください

**事象**

```
$ pip install apache-airflow
File “/usr/bin/pip”, line 9, in <module> from pip import main ImportError: cannot import name main
```

**対応策**
vim をインストールします。
`$ apt-get install vim`

ファイルの一部を書き換えます。
`$ vi /usr/bin/pip`

```
from pip import __main__
if __name__ == '__main__':
    sys.exit(__main__._main())
```

### 構築時に起きたエラー 2
出なかった場合読み飛ばしてください

**事象**

```
Command "python setup.py egg_info" failed with error code 1 in /tmp/pip-install-xg1yeW/apache-airflow/
```

**対応策**
公式でも同じようなことが書いてあります。
https://airflow.apache.org/installation.html

`$ export AIRFLOW_GPL_UNIDECODE=yes`

## Airflow起動

データベース初期化
`$ airflow initdb`

Webサーバー起動
`$ airflow webserver -p 8080`

### 起動時に起きたエラー
出なかった場合読み飛ばしてください

**事象**

```
Traceback (most recent call last):
  File "/usr/local/bin/airflow", line 28, in 
    args.func(args)
  File "/usr/local/lib/python2.7/dist-packages/airflow/bin/cli.py", line 791, in webserver
    gunicorn_master_proc = subprocess.Popen(run_args)
  File "/usr/lib/python2.7/subprocess.py", line 711, in __init__
    errread, errwrite)
  File "/usr/lib/python2.7/subprocess.py", line 1343, in _execute_child
    raise child_exception
OSError: [Errno 2] No such file or directory
```

**対応策**
gunicornコマンドがないようなのでインストールしたいと思います。

gunicornをインストール

`$ sudo apt-get install gunicorn`

## Airflow
http://localhost:8080 へアクセスすると
<img width="1392" alt="3.png" src="https://qiita-image-store.s3.amazonaws.com/0/309906/3035f2ca-3618-cad5-a632-a6f6b4306ee8.png">
このように表示されていれば成功です。

次にDAGのtutorialをクリックします
<img width="1392" alt="2.png" src="https://qiita-image-store.s3.amazonaws.com/0/309906/1eb69e14-78fe-4746-203d-1e1b8d62b5fd.png">
この画面でツリー表示が見れます。

Codeを次に見てみましょう。
<img width="1392" alt="1.png" src="https://qiita-image-store.s3.amazonaws.com/0/309906/bc2b5295-efe3-23d0-a81b-48f192d0abf6.png">
ここで先ほどのワークフローがどのようにできているのかを確認できます。

## 最後に
ここまでで、Airflow Tutorialのための導入を実際に行ってみました！
今後は実際の業務に繋げていき、本格的な開発を頑張って行きます！

以上、ありがとうございました。

明日は@takumi-suzukiさんです！
独断と偏見で選ぶre:Invent2018で刺さったセッションベスト3

## 自己紹介
渋谷　充宏 @m4buya

* 株式会社オプト テクノロジー開発部 チームマネージャー
* ADPLAN SREチームリーダー
* Ruby / Scala / インフラ
* https://github.com/mshibuya
* RailsAdmin/CarrierWave committer

---

このLTでは、私渋谷がre:Inventにて聴講したブレイクアウトセッション中で特によかった！と考えるものベスト３をひたすら紹介します。

re:Inventのセッションは発表スライドに加え動画もYoutubeで公開されているので、ぜひ皆様も動画でご覧になって臨場感を味わってください！

---
# 第３位

---
## SRV373-R Building Massively Parallel Event-Driven Architectures

[![Youtube](http://img.youtube.com/vi/dLn5J7L6HLE/0.jpg)](http://www.youtube.com/watch?v=dLn5J7L6HLE)

[Slideshare](https://www.slideshare.net/AmazonWebServices/building-massively-parallel-eventdriven-architectures-srv373r1-aws-reinvent-2018)

---
## 見どころ
Massively Parallelとあるように、非常に大規模なデータを並列処理できるアーキテクチャをイベント駆動で作るための方法論です。イベントの発生、ルーティング、処理の各フェーズにおいてどのような検討事項があり、それぞれどんなAWSのサービスがフィットするのかを議論しています。
実際にそのようなアーキテクチャを構築・運用しているMapbox社での事例紹介もあり、大いに刺激となる内容です！

---
![slide](https://image.slidesharecdn.com/building-massively-parallel-ev-a5093103-5853-40ea-90d7-ae1ae2309aba-1052036120-181130000929/95/building-massively-parallel-eventdriven-architectures-srv373r1-aws-reinvent-2018-8-638.jpg?cb=1543536602)

---
![slide](https://image.slidesharecdn.com/building-massively-parallel-ev-a5093103-5853-40ea-90d7-ae1ae2309aba-1052036120-181130000929/95/building-massively-parallel-eventdriven-architectures-srv373r1-aws-reinvent-2018-11-638.jpg?cb=1543536602)

---
# 第2位

---
## DEV315-S Building SRE from Scratch at Coinbase during Hypergrowth

[![Youtube](http://img.youtube.com/vi/YDr1_-Tttz0/0.jpg)](http://www.youtube.com/watch?v=YDr1_-Tttz0)

[Slideshare](https://www.slideshare.net/AmazonWebServices/building-sre-from-scratch-at-coinbase-during-hypergrowth-dev315s-aws-reinvent-2018)

---
## 見どころ
Datadogによるスポンサーセッションになるのですが、SREについてのたいへん平易で本質をついた説明がされており必見！
「システムのみならず、人や組織をも計測・改善する」といった基本姿勢から「非難のないポストモーテムの文化」まで、SREとして重要な考え方が網羅されており、SREに馴染みのある方にもそうでない方にもおすすめできる内容となっていますー

---
![slide](https://image.slidesharecdn.com/building-sre-from-scratch-at-c-74f20aac-ce4f-4762-95dc-08ac80c3f244-1692775388-181127235928/95/building-sre-from-scratch-at-coinbase-during-hypergrowth-dev315s-aws-reinvent-2018-13-638.jpg?cb=1543363185)

---
# 第1位

---

## DAT401 Amazon DynamoDB Deep Dive: Advanced Design Patterns for DynamoDB

[![Youtube](http://img.youtube.com/vi/HaEPXoXVf2k/0.jpg)](http://www.youtube.com/watch?v=HaEPXoXVf2k)

[Slideshare](https://www.slideshare.net/AmazonWebServices/amazon-dynamodb-deep-dive-advanced-design-patterns-for-dynamodb-dat401-aws-reinvent-2018pdf)

---
## 見どころ
これは自分にとってはDynamoDBのみならずNoSQL全般を見る目が変わりました。
RDBはストレージに最適化しているのに対しNoSQLは計算に最適化している！との主張をベースに、NoSQLなデータベースの特性を引き出すにはRDBのそれとは全く異なるデータモデルが必要であることを説いています。特にRDBの経験が長いものの、NoSQLはあんまりピンと来なかったんだよね…って方に見て欲しい!!

---
![slide](https://image.slidesharecdn.com/amazon-dynamodb-deep-dive-adva-6198eeb3-f4e5-455b-b7de-b6bf6bd2bf38-1013877029-181128214501/95/amazon-dynamodb-deep-dive-advanced-design-patterns-for-dynamodb-dat401-aws-reinvent-2018pdf-25-638.jpg?cb=1543441533)

---
# まとめ

- re:Invent 2018で印象に残った3セッションを紹介しました
- ブレイクアウトセッションは無数にあって、タイトルだけ見て申し込んでは見たものの「思ってたのと違う…」となっちゃうことも
- 詳細を読むのはもちろんですが、レベルで高めのほうを選んでおくとハズレにくいと感じてます（Introductoryとかなってるのは本当に初学者向けのことも）

---
# re:Invent、本当に楽しかった。絶対また行きたい〜
potatotips #57 Android発表まとめ

potatotips #57 Android発表のまとめです
https://potatotips.connpass.com/event/109263/

![074B3DF8-CEC7-4ED9-8AC0-A7D4BF15BE03.jpeg](https://qiita-image-store.s3.amazonaws.com/0/16400/83f2712b-6779-97fd-009e-c018b52779da.jpeg)

会場は株式会社アイスタイルさんです。

![45F01090-2A53-4919-AFE3-6E38A88352A3.jpeg](https://qiita-image-store.s3.amazonaws.com/0/16400/08e4e469-9758-3108-1769-48203c3cecd7.jpeg)


## [gyamoto](https://twitter.com/farundorl)「Firebaseで解決するAndroidの機種依存」

https://speakerdeck.com/gya/firebase-solve-android-device-difference

- BLEの強度と感覚が機種依存
    - 出力やアドバタイズ間隔が機種によって違う
        - Galaxy系は出力を上げないと間隔が安定しない
- Firebase UserProperty / RemoteConfigでアプリの振る舞いを変える
    - RemoteConfig
        - 出力や間隔についてのパラメータを変える

### 感想

機種依存のパラメータをRemoteConfigで調整するのそれっぽい使い方でいい。
Galaxyは出力を上げないとアドバタイズ間隔が安定しないとかはやらないとわからないことなので貴重な話だった。
複数のパラメータが相関関係あるときとか、とくにいいのかもしれない...

## [URI](https://twitter.com/yuyuyuyuyuri)「Behavior of nested async in Kotlin Coroutines」

https://speakerdeck.com/uri/behavior-of-nested-async-in-kotlin-coroutines

- Kotlin コルーチンの正式版がリリースされたので対応した話
    - v0.30.0
        - ネストしたasyncのエラーが親のコルーチンにも伝搬するようになった
            - コルーチンビルダーであるlaunchにも伝わる
        - 解決方法は4つ

### 感想

もともとのコルーチンの呼び出し元コルーチンにエラーが伝搬しないのはどうなるんだろう。
エラーが握りつぶされたんだろうか。

## [Kubode](https://twitter.com/swiz_ard)「KTSで社内マルチモジュールライブラリを配信する」

https://speakerdeck.com/kubode/distribute-a-company-local-library-with-kts

- なぜ社内で配布
    - デザインシステムのため
        - デザインの原則とかコンポーネントをまとめる
        - デザインのコストを削減したい
- デザインシステムの設計の１つ
    - アトミックデザイン
- どう配信するか
    - S3
        - GradleはS3のURIをサポート
            - 認証も使える
    - maven-publishプラグイン使う

### 感想

KTS=Kotlinのスクリプトでっていう、そんなのあるんすね。

## nagais「RecyclerViewとGridLayoutについて学んだ話」

- RecyclerViewの中にGridLayoutでViewを配置  
    - 動的にカラム数を変えたりするメソッドについて



## bigbackboom「Android開発でmitmproxyを使った話」

https://speakerdeck.com/bigbackboom/androidkai-fa-demitmproxywoshi-tutahua

- レスポンスの値を書き換えてレスポンスの値を書き換えて本番環境でアプリの強制アップデートのテストしたい
    - mitmproxyでSSL利用の際のルート証明書入れる
    - Android側でマニフェストファイルに設定する必要がある

### 感想

「レスポンスの値を書き換えてレスポンスの値を書き換えて本番環境でアプリの強制アップデートのテストしたい」っていう要望面白い。
（けど、AndroidでもCharlesでできそうな気がするけど本当にできないのかな、と思ったらやっぱりできることが分かったとのこと）
Vue.jsのロードマップが落ちてたので読んでみた

この記事は、[2018年アドベントカレンダーVue.js #3](https://qiita.com/advent-calendar/2018/vuejs-3)の20日目の記事です。

今回は、vuejsのレポジトリを漁っていたら、ロードマップ（将来構想）が公開されてたので見てみることにしました。
原文: https://github.com/vuejs/roadmap

## Vue.js 2.6はSSRに対する修正
> Various improvements regarding error handling, functional components, SSR

とあるように、SSR（サーバーサイドレンダリング）周りのエラーハンドリングやfunctional componentsの修正らしいです。フロントで使ってる人にはあまり関係なさそうですね。

## 2.x-nextではIEを捨てる
2.x系と同時に2.x-nextというのをリリース予定らしいです。
2.x-nextは大きな変更はしないものの、エバーグリーンブラウザ（ユーザーの手動更新ではなく、自動更新されるようなブラウザ）を対象とするものです。
IEを捨てて、ES2015を内部的に使うためにフル活用しちゃうよってことらしいです。

## 3.xはTypeScriptを内部的に採用
ESを捨てるという話ではなく、TypeScriptへの対応を強化するという感じらしいです。
また、内部的に責務の細分化などを行う予定らしいです。
APIは2系と殆ど変わらない予定とのこと。（よかった）

## 4.xではmapXXXがなくなる
4系ではAPIを大胆に変える予定があるとのこと。まだ構想段階ではあり時期も名言されてませんが、界隈がざわつくのは間違いなさそうです。


## 最後に
Vueは[Reactを抜かしてGitHubのスター数3位になり](https://qiita.com/a________kaito/items/9e8d86094c3821d0611a)、注目度が最も高いフロントフレームワークになったので、今後の動向も追っていきたいですね
Pythonと共に百人一首で勝ちたい

![SnapCrab_NoName_2018-12-18_19-1-5_No-00.png](https://qiita-image-store.s3.amazonaws.com/0/269030/bfb525e0-a836-5ab7-458b-aff42e047c6f.png)
#はじめに
皆さん！
百人一首をやったことがありますか？
学校の授業で百人一首をやったときに覚えておきたいですよね！
（冬休みの課題で覚えろって言われた僕

しかし…
覚えられないんです！　どうしても…

#どうやって覚える？
https://www.excd.jp/fuda/kimariji.html
このサイトには決まり字について書かれています。

ひらめいた！！！

これをセットで一問一答形式でやりまくれば…
百人一首の名人になれるのでは？

そこで、Pythonを使って問題を出してもらい答えてもらうコードを書くことにしました。

下のブログにも詳細が載ってあります。

[ブログ](https://chizuchizu.com/2018/12/18/python%E3%81%A8%E5%85%B1%E3%81%AB%E7%99%BE%E4%BA%BA%E4%B8%80%E9%A6%96%E3%81%A7%E5%8B%9D%E3%81%A1%E3%81%9F%E3%81%84/)

#このソフトの目的
問題は決まり字のみなので、声を聞いたらすぐ札を取れるようにする練習です。
覚えることを最小限にさせて、なおかつ実践的にしました。

#大まかな処理
上の句を詠んでもらう
↓
下の句を答える

合ってたら…　次の問題

間違ってたら…　もう1度（最初の文字のヒントを出す

#コード
```python
import random
import pandas as pd


def load():
    return pd.read_csv("百人一首.csv")


def loop(simo, kami):
    while True:

        n = random.randint(0, 99)  # 詠む番号を決める
        i = 0

        while True:
            j = 1
            simo_n = simo[n]
            kami_n = kami[n]

            print("【", j, "問目】下の句は", simo_n, "\n")

            s = input()
            if s == "end":  # endは終了
                break

            if kami_n == s:  # 正解ならもう次のループ
                print("正解です！\n")
                break
            else:
                print("不正解です…")
                while i &lt; 3:
                    print("後2回チャンスを与えます")
                    if len(kami_n) != 1:
                        print("上の句の一文字目は", kami_n[0])

                    s = input()
                    if s == "end":
                        break
                    if kami_n == s:
                        print("正解です")
                        break
                    else:
                        print("不正解です")
                        if i == 2:
                            print("正解は", kami_n)
                    i += 1
                break

        j += 1
        if s == "end":
            break

def main():
    df = load()  # データの読み込み

    kami = df["上"]
    simo = df["下"]

    # ルール説明
    print("【チズチズの決まり字特訓】\n")
    print("【ルール】")
    print("下の句（決まり字）を詠むので、上の句の決まり字を答えて下さい。")
    print("辞めたかったら「end」って言ってね！\n")

    loop(simo, kami)


if __name__ == "__main__":
    main() # 実行
```

百人一首.csvとさっきのコードの更新履歴等は下のGitHubにて公開しています。
[GitHub](https://gist.github.com/Chizuchizu/bb4f067beaabc80e7c64bf461f36c095)


#使い方
変数kを指定することで、何枚の札から問題を出すか変えられます。

例えば　最初は5を選択して6枚の札…　次は　10を選択して11枚の札…

つまり…

自分のレベルに合わせて暗記できる！！


#今後
GUI化させたり、ウェブアプリケーション化させてみたいです。

加えて、スコア機能の実装や保存機能等も追加していきたいです！

ゲームっぽくさせて覚えやすく！

#まとめ
初めて作った自作ソフトだが、結構便利で覚えやすかったから重宝していきます。
オブジェクト指向を理解しているようで、実装できなかったためクラスを追加させたり色々やってみたいです。

アドバイス欲しいのでコメント下さい。
あの手この手でTypeScriptからJSON形式データをimportする

# はじめに
この記事は[LIFULL その2 Advent Calendar2018](https://qiita.com/advent-calendar/2018/lifull2)の19日目の記事です。
TypeScriptを使用した際に、外部ファイル化したJSON形式のデータをどのようにimportすれば良いのかを何パターンか表してみました。
(あくまで思いついたもののみとなります。)

## JSON形式で管理する
ハッシュ形式のデータはJSON形式で管理したいというケースになります。

### ▶︎ 型定義ファイルで拡張
TypeScriptの型定義ファイルをJSON用に作成します。
この定義ファイルにより、JSON形式のデータをimportできるようになります。
汎用性のため、anyで定義しているので補完や型は使用できません。

|補完|型|
|:--|:--|
|×|×|


#### ディレクトリ構成
```
├── index.ts
├── data
│   ├── comment.json
│   └── user.json
└── typings
    └── json.d.ts
```

#### ソースコード
```json:~/data/user.json
{
  "id": 0,
  "name": "Taro"
}
```

```ts:~/typings/json.d.ts
declare module '*.json' {
  const data: any;
 
  export default data;
}
```

```ts:index.ts
import user from '~/data/user.json';
 
console.log(user.id); // 0
console.log(user.name); // Taro
```

### ▶︎ それぞれの型定義ファイルで拡張
先ほどとは異なり、JSONファイル個々に型定義ファイルを作成します。
これにより、JSONファイルの形式を型定義できるので補完が効くようになります。

|補完|型|
|:--|:--|
|◯|◯|

#### ディレクトリ構成
```
├── index.ts
├── data
│   ├── comment.json
│   └── user.json
└── typings
    ├── commentJson.d.ts
    └── userJson.d.ts
```

#### ソースコード
```json:~/data/user.json
{
  "id": 0,
  "name": "Taro"
}
```

```ts:~/typings/userJson.d.ts
declare module '~/data/user.json' {
  interface UserData {
    id: number;
    name: string;
  }
 
  const data: UserData;
 
  export default data;
}
```

```ts:index.ts
import user from '~/data/user.json';
 
console.log(user.id); // 0
console.log(user.name); // Taro
```


### ▶︎ どうしても型定義ファイルとデータファイルは同じ場所で管理したい
先ほどとほぼ同様ですが、型定義ファイルとJSONデータファイルが別々の場所にあると管理しづらいと言った場合に一つのディレクトリにまとめます。

|補完|型|
|:--|:--|
|◯|◯|

#### ディレクトリ構成
```
├── index.ts
└── data
    └── user
        ├── index.js
        ├── index.d.ts
        └── data.json
```

#### ソースコード
```json:~/data/user/data.json
{
  "id": 0,
  "name": "Taro"
}
```

```ts:~/data/user/index.d.ts
interface UserData {
  id: number;
  name: string;
}
 
declare const data: UserData;
 
export default data;
```

```js:~/data/user/index.js
var json = require('./data.json');

module.exports = json;
```

```ts:index.ts
import user from '~/data/user';
 
console.log(user.id); // 0
console.log(user.name); // Taro
```

## JSON形式以外で管理する
ハッシュ形式のデータの管理は、JSON形式でなくとも良いケースになります。

### ▶︎ JSで定義
JavaScriptでデータを定義します。
補完も利用でき、型推論により型も参照できます。

|補完|型|
|:--|:--|
|◯|◯|

#### ディレクトリ構成
```
├── index.ts
└── data
    ├── comment.js
    └── user.js
```

#### ソースコード
```js:~/data/user.js
const data = {
  id: 0,
  name: 'Taro'
};
 
export default data;
```

```ts:index.ts
import user from '~/data/user';
 
console.log(user.id); // 0
console.log(user.name); // Taro
```

### ▶︎ TSで定義
TypeScriptでデータを定義します。
interfaceを定義しているので、補完も型も使用できます。

|補完|型|
|:--|:--|
|◯|◯|

#### ディレクトリ構成
```
├── index.ts
└── data
    ├── comment.ts
    └── user.ts
```

#### ソースコード
```ts:~/data/user.ts
interface UserData {
  id: number;
  name: string;
}
 
const data: UserData = {
  id: 0,
  name: 'Taro'
};
 
export default data;
```

```ts:index.ts
import user from '~/data/user';
 
console.log(user.id); // 0
console.log(user.name); // Taro
```

# おわりに
TypeScriptからJSON形式データをimportする方法をいくつかあげてみました。
これだけではないかも知れませんが、お好きな方法を使用してみてください！
AWS ML University の Amazon SageMaker Ground Truth 動画を訳してみた

# はじめに

re:Invent 2018で発表された Amazon SageMaker の追加機能である Groud Truth について、AWS ML University 内で提供されている動画を訳しながら紹介していきたいと思います。

コンテンツへのアクセス方法は[こちら](https://qiita.com/Yoshiyuki03/items/bfbf416ab47ef5121927)に記載しています。

また Ground Truth を実際に手を動かして試した記事は以下になります。

[Amazon SageMaker Ground Truth を試してみる](https://qiita.com/SatoshiGachiFujimoto/items/e4ab624d3527237ca9e9)

# Amazon SageMaker Ground Truth とは
## 概要
![image.png](https://qiita-image-store.s3.amazonaws.com/0/321349/d188a6cb-7b3d-d083-f72f-1bd6d98036ca.png)

Ground Truth は、Amazon SageMaker 上で機械学習を行う上で必須となるデータセットを素早く正確にラベルリングすることが可能になる新機能です。データセットのラベル化の一部を自動的に行い、AWSが提供するアルゴリズムを駆使することでより正確なデータに変換して提供します。
## 学習データを用意するための課題
![image.png](https://qiita-image-store.s3.amazonaws.com/0/321349/db3dc997-5625-fd8f-dea2-73597251e3c7.png)

通常学習データの作成は、多大な労力とミスが伴う作業です。学習データの作成は多くの人員が必要になるので、結果的にコストとミスの増加に繋がります。なおかつ複雑な工程となるために完成させるのに数ヶ月かかる作業です。

## Ground Truth による解決

![image.png](https://qiita-image-store.s3.amazonaws.com/0/321349/b7df170a-d19b-17db-4c80-4fd42fc1def3.png)

Ground Truthはそういった問題を解決することができる機能を備えています。

- S3にあるデータを活用し、高精度なデータラベルの作成を簡単に行うことが可能
- 数クリックでデータのラベル化を完成させることが可能
- 類似したラベルのタスクにはテンプレートが提供される
- ラベリングを行うサポートする人材を選ぶパターンが3つ提供される

データのラベル化の作業が一通り完了すると、データはS3に遷移します。これにより高精度なデータのラベル化が可能となります。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/321349/f5b25208-56cb-866c-4534-af2d0da388d2.png)

人の手によるラベル化を行う場合、3つの選択肢の中からどれか1つを選ぶことができます。

- Amazon Mechanical Turkに登録されている作業員
- AWS Marketplaceに登録されているサードパーティベンダーの従業員
- 自社内で抱えている作業員

![image.png](https://qiita-image-store.s3.amazonaws.com/0/321349/c266eaff-5370-c79b-e267-76c9ed1083e4.png)

## Ground Truth によるラベリング

Ground Truth により高精度なデータラベル化を可能にする理由は、UX 技術の進化とビルトインアルゴリズムによるものです。この UX は全てのテンプレートに搭載されており、どのようなラベル化のタスクにも対応しています。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/321349/795cdb35-a53d-ab48-3d95-612a7de06997.png)

Ground Truthがより高精度なデータラベル化を可能としている仕組みは上図の通りです。Ground Truthは自動ラベル化という機能を搭載しております。これにより高精度なデータのラベル化を可能とします。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/321349/1c216db0-c6c3-b857-02a5-05f27975f050.png)

自動ラベル化の仕組みを少し詳しく紹介します。この機能の特徴は Ground Truth 側で学習データを調べ、Groud Truth でのデータ理解度によって自動でラベル化するのか、それとも手動で行うかを選別する機能があります。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/321349/2ec816b9-807a-82a8-dbbe-b24a445bc6c8.png)

以上のことから、Ground Truthを利用することで3つのメリットを得られます。

- データのラベル化にかかるコストを70%以上も削減
- データセットの管理をセキュアにすることが可能
- 検証データセットをより高精度なものにすることが可能

# おわりに
以上が Amazon SageMaker Ground Truth の動画内容のまとめとなります。
機械学習の工程の中で9割以上を占めると言われる学習データの用意が劇的に楽になると思われます。機械学習技術をビジネスに導入する際のハードルが大きく下がっていくのではないでしょうか。すごいサービスが世の中にどんどん登場しそうですね！
一瞬でターミナルにプログレスバーを表示するモジュールを作った

Pythonには進捗を簡単に表示するためのtqdmという有名なモジュールがあります。
nodeだとどうも使い勝手の良いものが無かったので書いてみました。

[nqdm - npm](https://www.npmjs.com/package/nqdm)

![](https://raw.githubusercontent.com/Yuhsak/nqdm/images/nqdm.gif)

`for ~ of構文`を使う時にオブジェクトをnqdm()でラップすることで簡単にプログレスバーを表示することが出来ます。

また、他のループにも対応できるように手動で進捗を更新する機能もついています。

開発に利用したnodeのバージョンは`v10.10.0`です。

## 使い方

### インストール

```sh

npm install nqdm
```

### 使用例

```js

const nqdm = require('nqdm')
 
// ラップするだけのパターン
const arr = [...Array(1000)]

for(const v of nqdm(arr)) {
    // ここで何かする
}

// 手動での更新も可能
const bar = nqdm(arr.length)

arr.forEach(v => {
    bar.process()
})

```

↓

```sh

  4.70% [==>                      ] 00:00:04 00:01:37 [19.72 iter/sec]
```

こんな感じで進捗、経過時間、残り時間、1秒あたりの処理数を自動的に表示します。

## オプション

出力先やコールバックなどを指定することができ、Generatorにも対応しています。
詳細はGithubのリポジトリに書いておきました。

[Yuhsak/nqdm: Simple progress indicator for node.js](https://github.com/Yuhsak/nqdm)

## 中身の話

ECMAScript 2015にはiterable(反復可能)オブジェクトという概念があります。
具体的には組み込みのオブジェクトだとString、Array、TypedArray、Map、Setが該当するのですが、ざっくり言うとfor~of文で回せるオブジェクトですね。

iterableなオブジェクトは自分で作ることも出来て、任意のオブジェクトの[Symbol.iterator]プロパティに「nextメソッドを実装したiteratorを返す関数」を実装すればOKです。

[反復処理プロトコル | MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Iteration_protocols)

何を言っているのかわからないよ！という方は上記の解説が非常に詳しく書いてあって分かりやすいので読んでみてください。

nqdmは渡されたオブジェクトからiteratorを取得し「自身のイテレーション時に渡されたオブジェクトをイテレートした値を返す」新たなオブジェクトを生成して返します。

こうして生成したオブジェクトをはさんでラップすることでfor~ofによるイテレーションをフックして進捗の更新を行っています。

簡略化したコードはこんな感じです。だいたい雰囲気つかめるでしょうか。

```js

const wrapped = (iterable) => {
	const iterator = entity[Symbol.iterator]()
	let i = 0
	const wrapperIterator = {
		next: () => {
			// ここにイテレーション時にフックしたい処理を書く
			i = i+1
			console.log(`${i} times iterated.`)
			return iterator.next()
		}
	}
	const wrapperIterable = {
		[Symbol.iterator]: () => wrapperIterator
	}
	return wrapperIterable
}
```

自分の環境ではとても便利に使えています。

オブジェクトを`nqdm()`でラップするやり方はfor~in構文`には対応していないので注意して下さい。

for~inを使う時は反復可能プロトコルは利用されずにオブジェクトの持つlengthプロパティを参照しているようなので、今回の実装では対応していません。`.process()`を呼んで手動で更新する必要があります。

もしうまく動かなかったりしたら僕に教えてくれるかプルリク飛ばしてもらえると嬉しいです。
Jestで標準出力(console.log())してデバッグする方法



## 概要

引数を与えてあげればできる。

デフォルトでは `--silent` がtrueなので `--silent=false` を指定すればOK。

## 実行コマンド 
```
jest --silent=false
```

しかし、このままだとテスト対象ファイルのconsole.logしか表示できない。

テストファイル自体のconsole.logなどを表示したい場合は`--verbose false`を実行時コマンドに含める必要がある。

つまり、全てのconsole.logを表示したい場合は

```
jest --silent=false --verbose false
```
以上のコマンドを実行すればOK。

## 参考リンク
[Jest CLI Options · Jest](https://jestjs.io/docs/ja/cli#silent)
テスト管理者として大事な事~テスト項目の改修編~

#はじめに
プロダクトとQAを繋ぐブリッジ業務を行い、テスト設計や障害削減を行うのがテスト管理者です。
そのテスト管理者にとって何が必要なのか、どんな心構えで開発側と向き合わければいけないのか、考えは様々ですよね。

今回は第一弾として**【テスト設計と改修】**について共有させていただければと思います。
偉そうなこと言ってますが、**私の体験ベースで感じたことなので、生暖かい目で読んでいただけると幸いです！**
#設計と改修で起きた苦悩
管理者に必要な技術として、テスト設計は一番最初に思いつくのではないでしょうか
項目を作成するのはもちろんですが、前任者が作成した項目の改修も業務の一部として加わってきます。

1から項目を作成するのは仕様書か読み解けば簡単なのですが、すでに項目があるものを改修するのは、前任者がどのような意図で項目を作成したのかがわからず、中々削減に踏め込めないことがしばしば...

**「これは削減していいのか？それともこの項目がないと障害が発生するのか？」**と四苦八苦しながら改修したのを昨日のことのように覚えています。
#何が苦悩だったのか
上でも「前任者の項目改修が苦悩」と記載していますが、何が苦悩だったんだ！と思いますよね。
自分が担当しているプロダクトのテスト項目で起きていた"本当にあった項目の話"です。

**①:項目が属人化している**
一番多いのではないでしょうか
長年そのプロダクトを担当している人にしかわからない,テスター歴が長ければわかって当然という前提である項目がとても多く、項目はあるが障害が発生していまうケースが多々ありました。

**②:必要最低限の確認しかない**
仕様書から項目を作成するのは簡単ですが、起こりえるイレギュラーな確認項目がありませんでした。
新規施策を追加した際の既存部分へ起こりえる影響への考慮、新規アイテムを組み合わせた時に起こりえそうな不具合を確認する項目がなく障害につながるケースが多数発生していました。


**③:同じ項目が重複している**
時間があったら再度チェックしたかったのだろうか...


**④:アイテムなどの効果を考察する項目がある**
![20181218_195039.png](https://qiita-image-store.s3.amazonaws.com/0/328167/b12ff298-e80c-ff1d-045f-3cd171592f38.png)
おぉっ？んんっ！？
考察した結果、どうしたらいいのかが全くわからない...いやまず「考察」ってなんだ？動作確認でもないし...
「これテスト実行者はどうやってチェックしてたんだ...」とテストの体制が不安定でした。

この問題点を見たときに、「あ、今まで開発が見ていてくれていたんだ...それか今迄運よく発生してなかったんだ...」とヒヤリしたのと同時にQAの存在についても考えさせられました。
#Let's改修！
①~④までの問題点を洗い出せたのでここから項目の改修開始です！
自分の中でまず改修するにあたって、下記を解決策とおいて項目の改修を行いました。

**①:テスト初心者でも出来る項目にする。**
属人的ではないと見つけられないものを項目化し、だれでも出来る項目を改修

**②:イレギュラーチェック,影響範囲の項目をテストケースに追加**
フリーデバッグだと経験則で検知にばらつきが出てしまうと考え、それなら項目化してしまえ！という考えで項目化

**③:重複している項目を削減**
項目の粒度的に2度見る必要がないと判断し、削減

**④:テスターが曖昧にチェックしている個所を聞き出し項目を修正・削除する**
一番苦労したのが上記でした。
テスターから「ここの項目がわからないです」と質問来たときに「いや、君先月もこれ確認してるで」というやり取りが多発していました。
その部分を改修・不要な部分を削減しました。

結果、**5500項目の削減**と**障害も45%削減**が出来ました(´◔౪◔)۶ﾖｯｼｬ!
#まとめ
あくまで私のやり方でおこなったテスト項目の改修方法なので
これが正しいやり方でもなく、もっと効率よく削減と改修が出来るし、方法はもちろんあると思います。
しかしながら、その人がいなければテストが出来ない環境というのは、急にいなくなってしまったときに障害が発生するリスクとなりうるので、テストの標準化を目的としている方に、参考になればと思います。