OmniAICreator/Qiita-1.07M huggingface dataset:
AWS SDK for .NET を使って EC2 インスタンスの一覧を取得する

## 概要
AWS SDK for .NET を使用して EC2 インスタンスの一覧を取得する。
.NetCore 向けの部分ではまった点も有ったので備忘のために作成。

## 検証環境
```
OS: amazon linux2(ami-0c3fd0f5d33134a76)
スペック: t2.micro
言語: C#
フレームワーク: .Net Core 2.2
```

## 手順
### 事前準備
- EC2 割り当て用のロール作成。権限は"AmazonEC2ReadOnlyAccess"をつける。
- EC2 インスタンスをaws上に1台立てる。とりあえず ssh で繋げられればOK。前述で作成したロールを割り当てておく。
- .Net Core インストール

```sh:
$ sudo rpm -Uvh https://packages.microsoft.com/config/rhel/7/packages-microsoft-prod.rpm
$ sudo yum update -y
$ sudo yum install -y dotnet-sdk-2.2
```
- Project の作成

```sh
$ dotnet new console -o aws_sdk
$ ls
aws_sdk
$ cd aws_sdk
$ dotnet run
Hello World!
```
- AWSSDK アセンブリのインストール

```sh
$ pwd
/home/ec2-user/aws_sdk
$ dotnet add package AWSSDK.EC2 --version 3.3.118.3
```
参考URL: https://www.nuget.org/packages/AWSSDK.EC2/

### プログラムの作成と実行
- Program.csの編集

```cs
using System;
using System.Collections.Generic;
using Amazon;
using Amazon.EC2;
using Amazon.EC2.Model;

namespace aws_sdk
{
    class Program
    {
        static void Main(string[] args)
        {
            var ec2Client = new AmazonEC2Client(RegionEndpoint.APNortheast1);

            var request = new DescribeInstancesRequest
            {
                Filters = new List<Filter> {
                    new Filter {
                        Name = "instance-type",
                        Values = new List<string> {
                        "t2.micro"
                        }
                    }
                }
            };

            List<Reservation> response = ec2Client.DescribeInstancesAsync(request).Result.Reservations;

            foreach (Reservation reservation in response)
            {
                foreach (Instance instance in reservation.Instances)
                {
                    Console.WriteLine(instance.InstanceId);
                    Console.WriteLine(instance.State.Name);
                    Console.WriteLine(instance.PrivateIpAddress);
                }
            }
        }
    }
}
```
参考URL: https://docs.aws.amazon.com/sdkfornet/latest/apidocs/

- プログラムの実行

```sh
$ dotnet run
i-00c6d881e4fa13468
running
192.168.0.116
```

## 終わりに
AWS Document にあるコード例を参考に DescribeInstances を実行しようとして何度もエラーになってはまった...。.NET Core は非同期の呼び出しパターンのみをサポートするって書いてあったのに気付かず...。ドキュメント見逃しパターンって一生治らん気がするわ。まあ、何となく .NET SDK の使い方はわかったから良しとする。
URL短縮のシステムデザインを考える

面接の問題でよくあるとされる。TinyURLのシステムデザインを考えていきます

# 仕様

URLを短縮変換する機能
短縮されたURLにアクセスして元のURLにリダイレクトする機能

# アクセス数をだいたい見積もってみる


短縮変換 1回/1分
短縮URLにアクセス 100回/1分

# 機能をもう少し具体的にする

URLを短縮する機能とは元のURLを example.com/xxxxxxx のようにユニークなURLにマッピングすることである

# URLの短縮についてざっとアーキテクチャを書いてみる

![](https://s3-ap-northeast-1.amazonaws.com/nulab-hackmd/uploads/upload_2beb12afdb55d54d68c959a941d75fe9.png)

## LB

アプリサーバーが水平スケールすることを見越して置いとく

## アプリサーバー

example.com/`xxxxxxx` の`xxxxxxx`の部分を生成する。

## Database

RDBを使用する。NoSQLにすれば水平スケールは容易になるが、今回ぐらいのアクセスならRDBでも全く問題なく捌けると判断
また今後アカウントの作成やアドミン機能での短縮URLの変更とかを考えたりするとRDBの方が簡単に運用できそうだと思った

# 短縮のURLの生成について

## URLの長さ
短縮URLはMD5を使おうと思う。
8文字あれば32^8 = だいたい1兆通りくらいのURLを網羅できるので今回のケースでは十分そう。

## ロジックについて

アプリサーバーにて元のURLから短縮後の文字列をhashの先頭8文字を取り出す。それをDatabaseに保存する

## スキーマについて

多分こんな感じ
![](https://s3-ap-northeast-1.amazonaws.com/nulab-hackmd/uploads/upload_2dcdf76413e3d6499e6fc1d760aa12a8.png)


## 重複した場合にどうするか

テーブル上のhashにunique keyを貼っておけば後からきたhashにてついてはエラーが起きるのでリトライじにその時点でのunixタイムを加えた元のURLでもう一度hashを生成し直す。
元のURL複数に対して違うURLが生成されるが使用上問題ない気がする

# 短縮URLのリダイレクトについて

アプリサーバーがDBを参照してリダイレクト先のURLにユーザーをリダイレクトさせる。

# スケールについて

## もし短縮URLがtwitterでバズったらどうするか

想定1000回/秒 とするとその都度SQLにアクセスしてたら少し心もとない。アプリサーバーは水平スケールするとしてもDBサーバーがボトルネックとなりそう。
のでRedisを用意してアプリサーバーにはRedisを参照させるようにする。
Redisにはアクセス数の昇順に1000件程度保存させとけば良さそうな気はしている。(人気のURLは多いがロングテールなURLは都度DBに問い合わせても大丈夫な気がするので )

## サイトそのものが人気になり短縮URLをたくさん発行する時

更新系の負荷につられて参照の遅延を防ぐため更新のDBを分ける。参照はSlaveを参照するため短縮URLに適応に少し時間をとった方が安全ではある。

# URLの重複を完全に防ぐ

## DBにオフラインで一意なURLを発行しておく

UnUsedHasTableとUsedHashTableを用意してアプリケーションサーバーはUnUsedHashTableをUsedHashTableに移動させて、元のURLとの対応するテーブルを更新するようにする。
ユーザーに返却するのはUnusedHashTableのUIDなので必ず一意なURLを提供することができDBチェックがいらなくなる。
その代わりUIDをオフラインで発行するサービスが必要になる。
リモートサーバーでnode.jsをバックグラウンド実行する方法

## なぜバックグランド実行が必要か

リモートサーバーにSSH接続してReactやVueの開発を行っている場合、`npm start`などのコマンドで開発サーバーを実行する場合がある。

しかし、これだとSSH接続を解除すると処理が停止してしまうため、チームメンバーやクライアントに確認してもらいたい場合に困る。

そこで、SSH接続を解除しても処理が実行されるようにバックグラウンド実行が必要になる。

## バックグラウンド実行する方法

コマンドは至ってシンプルです。

```shell
nohup npm start
```
これで、package.jsonの`start`コマンドに登録されているスクリプトをバックグラウンドで実行することができます。

こうしておけばSSH接続を解除しても処理が実行され続けるので確認することが可能です。

## TODO
- ログの出力先を変更する方法

## 終わりに
もっといい方法をご存知の方がいればコメントで教えていただけると幸いです。
【RDS for  Oracle】 接続方法

#事前準備（Oracle Instant Clientのダウンロード）
まずは[こちらのOTN](https://www.oracle.com/technetwork/jp/topics/index-099943-ja.html)からOracle Instant Clientをダウンロードします。

`※Oracle Instant Clientとは、10g以降に提供されているOracleに接続するためのライブラリ（OCIライブラリ）の最小構成です。無償で利用できます。
OTNからモジュールをダウンロードする際はOracleのアカウントが必要です（無料で作成可）。
`

今回は、RDSへの踏み台としてEC2（Amazon Linux）経由で接続するので、以下をダウンロードしました。
　- instantclient-basic-linux.x64-19.3.0.0.0dbru.zip
   　　 →Oracle Instant Clientを使用する際は必須。
　- instantclient-sqlplus-linux.x64-19.3.0.0.0dbru.zip
    　　→SQL*PLUSを使う場合は必要。
　- instantclient-tools-linux.x64-19.3.0.0.0dbru.zip
　　    →Data PumpやSQL*Loaderなどを使う場合は必要。

ダウンロードしたInstant ClientをEC2に配置し解凍します。

```
$ unzip -q instantclient-basic-linux.x64-19.3.0.0.0dbru.zip
$ unzip -q instantclient-sqlplus-linux.x64-19.3.0.0.0dbru.zip
$ unzip -q instantclient-tools-linux.x64-19.3.0.0.0dbru.zip
```
instantclient_19_3ディレクトリが作成されます。

次に環境変数を設定します。

```
$ cd ~/
$ vi .bash_profile
```
記述内容

```
export ORACLE_HOME=/Users/hogehoge/instantclient_18_1
export PATH=${ORACLE_HOME}:${PATH}
export LD_LIBRARY_PATH=${ORACLE_HOME}
```
 　　※Linuxの場合は、LD_LIBRARY_PATHが必要なようです。

環境変数を反映

```
$ source .bash_profile
$ env | sort
```

SQL*PLUSの起動確認

```
$ sqlplus
```

#SQL*PLUSでの接続方法

```
$ sqlplus <マスターユーザ名>/<マスターユーザのパスワード>@<エンドポイント>:1521/<DB名>
```
マスターユーザ名はRDS作成時に指定したユーザ名です。
RDSではSYS、SYSTEMユーザでのログインができなくなりました。
このマスターユーザがRDSにおける管理用のユーザになります。

エンドポイントはRDS作成後にマネージメントコンソールから確認できます。
ちなみに、ポートはデフォルトで1521です。

```
$ sqlplus test/Passw0rd@oracle-instant1.XXXX.rds.amazonaws.com:1521/orcl
(略)
SQL>
```

上記でも接続できますが、毎回エンドポイントを打つのが面倒くさいのでオンプレのOracle同様、[tnsnames.ora](https://www.shift-the-oracle.com/oracle-net/tnsnames.html)に接続識別子を記述したら楽です。

```
$ cd $ORACLE_HOME/network/admin
$ touch tnsnames.ora
$ vi tnsnames.ora
```

記述例

```
ORCL =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = oracle-instant1.XXXX.rds.amazonaws.com)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = ORCL)
    )
  )
```

ネットサービス名を指定し接続

```
$ sqlplus test/Passw0rd@ORCL
(略)
SQL>
```

「SQL>」と表示されたら接続完了です。

もし接続できない場合は以下を確認してみましょう。
　- tnsname.oraの記述
　- 環境変数
　- セキュリティグループ
gitで最新コミットの差分ファイルだけをディレクトリ構造ごと抜き出したい

「あー、gitで変更のあったファイルだけディレクトリ構造はそのままに抜き出したいー」ということが結構ありますよね？　僕は今まであまりなかったのですが、まぁ、そのような業務が発生することがありましたので、調べました。

```shell:最終コミットで変更があったファイルをシンプルに表示する
git log --pretty="" --name-status -1
```

これとシェルスクリプトを組み合わせて、変更のあったファイルだけを抽出する。

```
#!/bin/bash -u

SCRIPT_DIR=$(cd $(dirname $0); pwd)
LOCAL_GIT_REPOSITORY=/path/to
WORK_DIR=$SCRIPT_DIR/$(date +"%Y%m%d%I%M%S")_$(basename $LOCAL_GIT_REPOSITORY)

cd $LOCAL_GIT_REPOSITORY

# git リポジトリじゃない場合はexit
if [ ! -e .git ]; then
    echo 'ERROR: Here is not git repository.'
    exit 1
fi

for file in $(git log --pretty="" --name-status -1 | grep -v "^D" | cut -f 2-)
do
    result_dir=$WORK_DIR/$(dirname $file)
    mkdir -p $result_dir
    cp $file $result_dir
done
```
UnityでStandardAssetsをインポートしたのにImport Packageに表示されないでお困りの方へ

Asset StoreでStandard Assetsのダウンロード・インポートまで終えた後、「Assets」→「Import Package」と開いても「Custom Package…」としか表示されず、困っている方へ。

インポートまで終わっているならば「Projectビュー」の中に「Standard Assets」が出来ているはずなのでそこから必要なデータを取り出して使用すれば良いです。
![StandardAssetsのインポート先.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/447365/362665f7-2e20-6435-5087-e70e07a34767.jpeg)


これだけです。
以下は補足説明ですので読まなくても作業に支障はありません。

上記の説明を聞いても「.unitypackage」形式のStandard Assetsが無いけど大丈夫…？と私と同じように心配される方もいらっしゃるかも知れません。
結論から言うと何も問題ありません。
どうしても「.unitypackage」形式のStandard Assetsが見たい方はUnityのホームページにある旧バージョンがダウンロードできるページでUnity2018.1.9の「ダウンロード」→「標準アセット」をダウンロードすれば見られます。
https://unity3d.com/jp/get-unity/download/archive
![標準アセットのDL.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/447365/47b095e6-8452-6680-4a6b-584b4867cc46.jpeg)

ダウンロードした.unitypackage形式のデータはUnityから「Assets」→「Import Package」→「Custom Package」→「（必要なStandard Asset）.unitypackage」と展開すると使えるようになります。
しかし、結局ProjectビューにStandard Assetsが入るので、上の解決策と同じ結果になります。

ちなみに私はStandard Assetsを使った事が無かった為なのか、Terrainなどと同じように「上のバー（「Assets」→「Import Package」）からStandard Assetsを選ぶとInspectorビューにパラメーターなどの項目が出現するのでは？」と思い込んでいたり、Assetsフォルダ内の整理をしていなかった為にProjectビューの中にStandard Assetsが入っている事になかなか気が付きませんでした…。


また、「Assets」→「Import Package」の中にStandard Assetsが入ってる、と紹介されているのを見てこの問題にぶつかった方が多いと思いますが、現在はその仕様から変更になっているようです。

何でも、現状（2019年6月28日）のStandard AssetsはUnity5の時代のもので、今後新しいStandard Assetsに切り替えたい為に仕様を変えたようです。

参考にさせて頂いたwebページ
https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q10198555765
http://learnbyonestep.blog.fc2.com/blog-entry-254.html
Line Notifyでメッセージサイズが上限（1000文字）を超えていたら分割して送信する(python3)

# 背景

LINE Notify通知が送信文字数上限（1000文字）超えでエラーになっていたので分割送信するようにしました。

![](https://i.gyazo.com/f66cecee994e9f10676d6da19b4b5e3d.png)

# 実装

AWS Lambda（Python3.6）を利用していますが、どこでも動作すると思います。

```python
import requests

MESSAGE_SIZE_LIMIT = 1000
LINE_NOTIFY_URL = "https://notify-api.line.me/api/notify"
LINE_NOTIFY_TOKEN = "your-token"

def line_notify(long_message):
    headers = {"Authorization" : "Bearer "+ LINE_NOTIFY_TOKEN}
    message_length = len(long_message)
    i = 0
    while message_length > 0:
        if i == 0:
            buf = long_message[:MESSAGE_SIZE_LIMIT]
        else:
            buf = long_message[MESSAGE_SIZE_LIMIT * i:MESSAGE_SIZE_LIMIT * (i+1)]
        payload = {"message" :  buf}
        i += 1
        message_length -= MESSAGE_SIZE_LIMIT

        r = requests.post(LINE_NOTIFY_URL, headers = headers, params = payload)

        if r.status_code != 200 :
              pass # エラー処理

```

# 関連URL

[公式ドキュメント](https://notify-bot.line.me/doc/ja/)
【Rails】フロントエンドとバックエンドを分けて開発する時に注意すること

## 【Rails】フロントエンドとバックエンドを分けて開発する時に注意すること
RailsのMVCモデルでの開発経験しかないと、APIを使いフロントエンドとバックエンドを分けて開発する時に戸惑うかもしれません。

僕が色々やってきて分かったことは、サーバーを2つ用意すると便利だということです。

無理やり1つのサーバーでフロントとバックエンドを対応することも可能な場合もありますが、デプロイなどが面倒になります。

この記事が参考になれば幸いです。
## 終わりに
私は現在、Web3のサービスの開発をしています。詳しくはこちらの記事をご覧下さい。
        [無料でイーサリアムが当たる、Web3時代の寄付サイトを作った話](https://note.com/kenroda/n/n814347fbdcd7)
Sequel ProをMySQL 8で使う

MacOSでMySQLのGUIツールと言ったら[Sequel Pro](https://sequelpro.com/)が定番。でもMySQL8には対応していない。クラッシュする。（2019年6月現在）

長らくバージョン変わっていないし、いよいよ他を探さないといけないかなあ。。と思っていたら[Test Build](https://sequelpro.com/test-builds)だと対応していたんですね。正式な公開版では無いのでとんでもないバグが潜んでいる可能性もあり。全て自己責任。

MySQLをマックにインストールする場合、homebrewで

```bash
brew install mysql
```

続いて

```bash
brew services list
```

とするだけで、インストールから自動起動の設定までできちゃうので簡単。ただし。これだと最新版のMySQL8が入ってしまいます。MySQL5.7のインストールには簡単な別手順が必要。詳しくは[グーグル](https://www.google.com/search?q=MySQL+5.7+macOS+インストール)で。

有償のMacOSでデータベースのGUIツールは、[tableplus](https://tableplus.io/)とか良さそう。開けるタブ・ウインドウ制限付きでたっぷりと無償試用もできる。MySQL以外にも使うデータベースが出てきたら試してみるかも。

tableplusにはMacとは別に[iOS版](https://tableplus.io/blog/2018/10/tableplus-for-ios.html)が出ました。iPadでもウエブ開発できる環境がどんどん整ってきている。
メディアクエリにmin-widthとmax-widthを混在させてはいけない

#拡大表示した際に、スキマができてしまう
結論から言うとメディアクエリにmin-widthとmax-widthを混在させると、ブラウザの拡大表示時に、適用されるメディアクエリと、メディアクエリの間にスキマができてしまいます。

#スキマができる理由
例えば、「min-width:501px」と「max-width:500px」というメディアクエリを書き、ブラウザの拡大率110%で表示した場合で説明します。

まず、ブラウザで拡大表示した場合には、メディアクエリに指定したサイズに拡大率を乗算した値が、メディアクエリとして解釈されるようです。これを前提に、それぞれのブレイクポイントを計算すると

501px × 110% = 551.1px
500px × 110% = 550px

となります。つまり、ウィンドウの幅が551pxの時に、適用されるスタイルのスキマができてしまいます。

下記のサンプルで見てみます。
```html:test.html
<style type="text/css">
　　@media screen and (min-width:501px) {
　　　　.red_or_blue {
　　　　　　background-color: red;
　　　　}
　　}
　　@media screen and (max-width:500px) {
　　　　.red_or_blue {
　　　　　　background-color: blue;
　　　　}
　　}
</style>
<div class="red_or_blue">wide</div>
```

幅550pxの場合
![スクリーンショット 2019-06-28 23.30.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179668/5b76c96c-e2f9-d858-b5f8-6c4e9ed68847.png)

幅５５２pxの場合
![スクリーンショット 2019-06-28 23.30.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179668/f2bab28c-661a-fbfb-57de-25105c5b9733.png)

幅551pxの場合
![スクリーンショット 2019-06-28 23.32.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179668/fd371adf-4241-c692-eeec-9e0d15dba547.png)

幅551pxの場合にスタイルが適用されていないのがわかります。

#まとめ
メディアクエリにmin-widthとmax-widthを混在させることは避けましょう。
そもそも、そんな書き方はする必要ないのでやらないとは思いますが。今回、業務で古いサイトを触る機会があり、それが上記のような指定をされていて、事象が発生していることに気がつきました。
ruby on rails のプロセス番号の調べ方

vagrantなどのローカル環境の中railsで作業をしているときにサーバーのプロセスを終了するためにプロセス番号を調べて終了するはずがうっかり調べずにデータを消してしまった場合にターミナルにps aux | grep pumaを打ち込むと
vagrant   4472  0.1 10.0 858284 102352 ?       Sl   16:46   0:04 puma 3.12.1 (tcp://192.168.33.10:3000) [/]                                  
vagrant   8023  0.0  0.0 103332   912 pts/0    S+   17:54   0:00 grep puma

と出てきます。最初に出てきた4472が今のプロセス番号であり,その後の8023がこれから作成しようとしている番号である。

削除する場合は kill -9 4472(4472の番号はでできたプロセス番号）
で削除でき、新たにサーバーを立ち上げて作業を開始できます。
JMeterでのレコードには証明書のインストールが必要

JMeterでプロキシサーバーを利用してテストシナリオのレコーディングをするには、「《JMeterの解凍先》¥bin」に作成されるダミー証明書ファイル（.crt）のインストールが必要です。

# 実行環境
* windows10
* ApacheJMeter5.1.1

# 手順
一度プロキシサーバーを立ち上げると「.crt」ファイルがbinフォルダ配下に作られるので、それを開いて画面の指示に従って進めます。

# 参考
[JMeter概要](https://www.techscore.com/tech/Java/ApacheJakarta/JMeter/index/)
[JMeter簡易リファレンス](http://sy5.sakura.ne.jp/jmeter/ref/)
[JMeter のインストールから負荷テストまで](https://qiita.com/shotets/items/d553d7be0d407a9a9a53)
[JMeterでHTTPプロキシサーバーを使いHTTPSサイトでもシナリオの自動作成を行う](https://qiita.com/kter/items/24e74c7b6900a3ab2226)
[プロキシ配下＆日本語でJMeter4.0を起動する](https://qiita.com/segur/items/66257aad638806b2f27a)
[Apache JMeter実行時ログの日時表記を人が見てわかる形式(yyyy/mm/dd形式)にする]( http://labs.timedia.co.jp/2012/04/jmeter-log-dateformat.html)
ヘルスケアwebサービスを自分で作る医者の日記~

methodオプションではHTTPメソッドの種類を指定します。何も指定しなければGETになる。

```
class LikesController < ApplicationController
  before_action :authenticate_user

  def create
    @like = Like.new(user_id: @current_user.id, post_id: params[:post_id])
    @like.save
    redirect_to("/posts/#{params[:post_id]}")
  end
  
  def destroy
    @like = Like.find_by(user_id: @current_user.id, post_id: params[:post_id])
    @like.destroy
    redirect_to("/posts/#{params[:post_id]}")
  end
```

```
<% if Like.find_by(user_id: @current_user.id, post_id: @post.id) %>
        <!-- 以下の1行をdestroyアクションへのリンクに書き換えてください -->
        <%= link_to("いいね！済み", "/likes/#{@post.id}/destroy", {method: "post"})%>
      <% else %>
        <%= link_to("いいね！", "/likes/#{@post.id}/create", {method: "post"}) %>
      <% end %>
```

```
post "likes/:post_id/create" => "likes#create"
  post "likes/:post_id/destroy" => "likes#destroy"
```
where メソッドは DBから探し、[]配列になる
RubyとRailsの情報収集をする

一旦、公開にしますが、随時更新していこうと思います。
他にも、なにかいい情報源がありましたらコメントいただけると嬉しいです🎉

---

# 開発時に参照したい
## Ruby
#### ■  [Ruby-Doc](https://ruby-doc.org/) 
#### ■  [ruby-lang.org](https://docs.ruby-lang.org/en/2.6.0/)
#### ■  [Ruby リファレンスマニュアル](https://docs.ruby-lang.org/ja/)
#### ■  [Rubyで使われる記号の意味](https://docs.ruby-lang.org/ja/latest/doc/symref.html)

## Rails
#### ■  [Rails Guild](https://guides.rubyonrails.org/)
#### ■  [Railsガイド(日本語版)](https://railsguides.jp)
#### ■  [api.rubyonrails.org](https://api.rubyonrails.org)

## 設計
#### ■ [Refactoring guru](https://refactoring.guru/refactoring/smells) 
コードの臭いと解決法が書かれている。個人的には、Refactoring Ruby Edition という本の内容がここにまとまっている印象


# ニュースを読みたい
#### ■  [Rails.org](https://weblog.rubyonrails.org/)
#### ■  [Rubyメーリングリスト](http://www.ruby-lang.org/ja/community/mailing-lists/)
#### ■  [リリースガイド](https://railsguides.jp/6_0_release_notes.html)
ver6のリリースガイド（翻訳ありがとうございます）
#### ■  [TechRacho](https://techracho.bpsinc.jp/) (週刊Railsウォッチなど、Railsに関する話題が豊富)
#### ■  Web+DB press (書籍)

# 勉強会に参加したい
#### ■  [Connpass](https://connpass.com/dashboard/)

## 学習
#### ■ 初めてのRuby ✅
最初に読んだRubyの本。これを読んでRubyやりたい！と思うようになった。
#### ■ オブジェクト指向設計実践ガイド ✅
気づいたらコードが汚れてしまっているのをなんとかしたい人が大いなる知恵をもらえる
#### ■ パーフェクトRuby on Rails ✅
特にPart4「一歩先行くRails」はRailsのバージョンを超えて使える設計技術なので読んでおきたい。
#### ■ メタプログラミングRuby 📚
読みたい。現場で、Railsの拡張などを見かけて、そういうのを実践できるようになりたい人向けなのかな？と思っている。

# 将来的な憧れ
#### ■ [日本Rubyの会](https://ruby-no-kai.org/) # 登録するとメーリングリスト
ABEJA Platformのテンプレートを使用して、ノンプログラミングで機械学習モデルをデプロイする

## はじめに

本記事は、以下の手順をまとめた記事です。
- ABEJA Platformのテンプレートを使用して、画像分類の機械学習モデルをノンプログラミングでデプロイする

（本記事の前編はこちら）
ABEJA Platformのテンプレートを使用して、ノンプログラミングで機械学習モデルを学習する
https://qiita.com/yushin_n/items/6852ad042913617d8892

## モデルの作成

前編で、いくつかのハイパーパラメーターを組み合わせて、モデルを学習しました。今回は学習済みのモデルの中で精度が最も高いモデルを、Web APIとしてデプロイします。

まずは、Validation Accuracyが最も高くなった学習ジョブのIDを控えておきます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/376869/3883c14f-1c7a-0dec-c0eb-a6e523647372.png" width=80%>

続いて、モデルの「モデルの作成」をクリックして、アップロードの「テンプレート」を選択します。「作成後にデプロイ」にチェックを入れます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/376869/8f18249d-80e6-36e4-c277-24026d2dd70a.png" width=80%>

ジョブ定義から、ジョブ定義とValidation Accuracyが最も高くなった学習ジョブIDを選びます。これでデプロイの準備ができました。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/376869/f5303ca0-5d00-8ddb-5b41-deda50f5594c.png" width=80%>

## HTTPサービスの作成
コンソールのデプロイメントに移動すると、先ほど作成したデプロイメントが見つかると思います。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/376869/239efaf7-00a8-3646-5107-41c74e0332db.png" width=80%>

デプロイメントの名前をクリックして、「HTTPサービスを作成」をクリックします。バージョンとインスタンスタイプ、インスタンス数を選択します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/376869/9105c438-66a0-e113-e67c-91ff9c8d04f1.png" width=80%>

数分待つと、ステータスが「使用可能」になり、モデルがWeb APIとしてデプロイされます。学習が完了してから、わずか数分間でモデルをデプロイできてしまいました。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/376869/a9389c61-2b47-e5df-5324-f3e1e8f6ab0c.png" width=80%>

「✔︎確認」をクリックして、テストを行います。

URLをクリックして、[Wikipediaのタンポポの写真のリンク](https://upload.wikimedia.org/wikipedia/commons/4/4f/L%C3%B6wenzahn_uhf.JPG)を貼ります。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/376869/3e570be1-1577-3c11-2f4a-d3e44ade27f3.jpeg" width=30%>

送信をクリックすると・・推論結果が返ってきました！

Probabilityが98.99%で、DANDELION（タンポポ）と予測しています。いい感じです。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/376869/d65ddad7-193e-e929-ed60-0d32f91c22a0.png" width=80%>

チューリップの写真でも試してみます。アップロードをクリックして、ファイルをドラッグ＆ドロップします。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/376869/9d4547c8-0c1f-99ba-1be4-c5ddeec98b2d.jpeg" width=30%>

Probabilityが99.99%で、TULIP（チューリップ）と予測しました！
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/376869/625dbce2-f7b6-f772-5270-0dce1fb408ee.png" width=80%>

## まとめ
本記事では、ABEJA Platformのテンプレートを使用して、画像分類の機械学習モデルをノンプログラミングでデプロイする手順をまとめました。この機能を活用すれば、機械学習初心者でも、ちょっとした機械学習のアプリをつくることができそうです :dog:

## 参考
LINE BotとABEJA PlatformのWeb APIを連携する方法はこちらの記事を参照下さい。
https://qiita.com/peisuke/items/f46e46a98692c3490f15

ABEJA Platformは、トライアルも提供しています。気になられた方は、是非、お気軽にお問い合わせください。また、フォーラムもありますので、是非、ご活用ください。

ABEJA Platformに関するお問い合わせ
https://abejainc.com/platform/ja/contact/

ABEJA Platform Forum
https://forums.abeja.io/
Railsのform_withを使ってシンプルな検索機能を実装する

# はじめに
ransackというgemを使えば簡単に検索機能を実装できますが、今回は勉強のために、gemを使わないシンプルな検索機能の作り方を紹介します。

前提として、私の環境は下記の通りです。

```ruby
Ruby 2.6.3

Rails 5.2.3
```

# 目的
検索をしたい任意の文字列と、タスクのタイトルが部分一致するデータの集合を取得する。

今回扱うタスクモデル・コントローラー・ビューをscaffoldで一括生成します。

```ruby
rails g scaffold task title:string
```

タスクモデルはこのようになったと思います。

```ruby
ActiveRecord::Schema.define(version: 2019_06_28_130239) do
  create_table "tasks", force: :cascade do |t|
    t.string "title"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end
end
```

# 実装方法
それではタスク一覧`tasks#index`に検索機能を実装しています。

まずはviewから作りましょう。`form_with`ヘルパーを使います。
`url: tasks_path`と指定することで、ユーザーが入力した文字列を`tasks_controller`の`indexアクション`に送ります。
データを取得したいので`method: :get`を指定しましょう。
また、form_withはデフォルトでajaxを使うようにになっているので、`local: :true`と指定して、ajaxを解除しましょう。

`form.text_field :search`とすることで、indexアクション側で`params[:search]`を使って、入力した文字列を受け取れるようにします。

```erb:app/views/tasks/index.html.erb
<%= form_with url: tasks_path, method: :get, local: true do |form| %>
  <%= form.text_field :search %>
  <%= form.submit 'Search', name: nil %>
<% end %>
```
このような検索欄（テキストフィールド）が表示されていると思います。
<img width="318" alt="スクリーンショット 2019-06-28 22.43.50.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/344685/29e12c0b-7b08-eedb-f0b9-a241f1b61732.png">

次にcontrollerを書いていきます。

`@tasks.where('title LIKE ?', "%#{params[:search]}%")`で、ユーザーが入力した文字列に部分一致するデータを検索し、取得しています。
`"%#{params[:search]}%"`このように`%%`で囲むことによって、部分一致の検索を行っています。

```ruby:app/controllers/tasks_controller.rb
def index
  @tasks = Task.all

  @tasks = @tasks.where('title LIKE ?', "%#{params[:search]}%") if params[:search].present?
end
```

イメージは次の通りです。
(1) hogeと検索欄に入力し、Searchをクリック
<img width="429" alt="スクリーンショット 2019-06-28 23.02.58.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/344685/61b4d0c3-9d36-1671-4173-947cf0e7fa33.png">

(2) titleがhogeに部分一致するタスクを表示
<img width="444" alt="スクリーンショット 2019-06-28 23.03.21.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/344685/1f0a021d-8d5a-bd63-261a-28ae8c9f3d6c.png">


ちなみに、`where('title LIKE ?', "%#{params[:search]}%")`を`where("title LIKE %#{params[:search]}%")`のように直接変数を入れることはSQLインジェクションの危険があるので、避けましょう。

以下はRAILS GUIDESからの引用です。
>条件文字列の中に変数を直接置くと、その変数はデータベースに そのまま 渡されてしまいます。これは、悪意のある人物がエスケープされていない危険な変数を渡すことができるということです。このようなコードがあると、悪意のある人物がデータベースを意のままにすることができ、データベース全体が危険にさらされます。くれぐれも、条件文字列の中に引数を直接置くことはしないでください。

以上です。

# 参考
[Active Record クエリインターフェイス - Rails ガイド](https://railsguides.jp/active_record_querying.html)
[Rails セキュリティガイド - Rails ガイド](https://railsguides.jp/security.html)
OracleマスターSilver 12ｃ パフォーマンスの管理: SQLチューニング

※用語はなるべく、Oracle® Databaseリファレンス　12c リリース1 (12.1) より抜粋しております。

###■公式チェックリストより出題範囲
●パフォーマンスの管理: SQLチューニング
　・SQLチューニング・アドバイザを使用する

####試験内容チェックリストから除外されたトピック
●パフォーマンスの管理
　－Enterprise Managerを使用してパフォーマンスを監視する
　－自動メモリー管理を使用する
　－メモリー・アドバイザを使用してメモリー・バッファのサイズを変更する
●パフォーマンスの管理：SQLチューニング
　－オプティマイザ統計を管理する
　－SQLアクセス・アドバイザを使用してワークロードをチューニングする

－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－
###要点
どれもこれもＡＷＲとＡＤＤＭに絡んでくるので出題されないんじゃないかと思っている。
ひとまず公式チェックリストのSQLチューニングアドバイザに関しては押さえておこう。


－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－
###SQLチューニング
■SQLチューニングアドバイザ
　SQLチューニングアドバイザは、１つ以上のSQL文を入力ソースとして受け取り、実行計画を最適化する方法をアドバイスします、アドバイスされた処理を適用することによって、パフォーマンスがどの程度向上するかなども併せて表示します。

■SQLチューニングアドバイザによって分析される要素
●統計分析：SQL文がアクセスしているオブジェクトに統計情報の欠落/失効があるかどうか分析し、対象となる統計情報を収集するための推奨事項を作成する。
●SQLプロファイリング：SQL文に対して作成された実行計画を検証し、その実行計画の誤りを排除するための情報を収集する。最適化された実行計画は「SQLプロファイル」として作成し、友情モードでの実行時でも実装できるようにする、
●アクセスパス分析：欠落している索引がないか分析し、新しい索引の採用によってアクセスパスが買いzん出来る場合は、索引を作成するための推奨事項を作成する。
SQL構造分析：不適切な実行計画を使用しているSQL文を識別し、SQL文を再構築するための提案を行う

■SQLチューニングアドバイザの入力ソース
**トップアクティビティ**：現在んのインスタンスじょうで動作しているカーソルキャッシュから1つ以上のSQL文を選択できる
履歴SQL：AWRスナップショットを選択して、SQLチューニングセットを作成するかADDMタスクを作成してSQL分析をさせることができる
SQLチューニングセット：複数のSQL文とSQL文の実行に関連する情報を格納したオブジェクト、現在メモリー上にあるSQL文やAWRスナップショットから作成するかDBMS_SQLTUNEパッケージを使用して手動で作成できる


■自動メンテナンスタスクによるSQLチューニングアドバイザの自動的な実行
デフォルトで1時間を限度に実行されます。
①AWRによる候補SQLの抽出
②各SQLを自動的にチューニング
③自動チューニング
・SQLチューニングアドバイザの実行（推奨事項の生成）
・SQLプロファイルのテスト
・SQLプロファイルの実装
④自動SQLチューニングレポート

●SQLチューニングアドバイザの特徴について
　・SQLプロファイルを推奨させるには有効範囲を包括モードにする
●SQLチューニングアドバイザの自動実行について
　・自動適用可能なのはSQLプロファイルのみ

自動ＳＱＬチューニングはの実行タイミングは、自動化メンテナンスタスクに設定されたメンテナンスウインドウで決定されます。

おまけ。出題されないかも。
####SQLパフォーマンスアナライザ
　SQLパフォーマンスアナライザは、変更前と変更後のSQL実行パフォーマンスを検証するために使用機能です。変更後の結果にパフォーマンスの悪化したSQL文が存在した場合は、SQL計画管理で変更前の実行計画を使えるよう構成するか、チューニングアドバイザでチューニングすることができます。

本番環境で変更後のワークロードを実行せずに、**テスト環境で変更を行い、変更後のSQL文のパフォーマンスの変化を確認することができます**
【変更に該当する内容】
・**データベースのアップグレード**
・アドバイザによって推奨されたチューニングの実装
・スキーマの変更
・オプティマイザ統計の収集
・**データベースの初期化パラメーターの変更**
・**OSやハードウェアの変更**
atcoderのテストケースを通すvim pluginを作った

qiita初投稿のため、いたらないところもたくさんあると思いますがご指摘いただけると助かります。
# はじめに
こんにちは、飛べない豚です。
題名の通りatcoderのテストケースをチェックするvimpluginを作りました。
https://github.com/cannot-fly-pig/vim-atcoder
![screenshot0.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449829/75846920-6551-ada6-cdfc-1dbfb3b7e7a1.jpeg)
![screenshot1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449829/190eb6f7-f2b4-e0ea-5920-3b1d862caf3d.jpeg)
↑こんな感じ
# 使い方
```
:Atcoder コンテスト名 コンテスト番号 task(aとかbとか)
```
(例

```
:Atcoder ABC 131 c
```
と入力してエンターすると今開いているコードを実行してACかWAかを判定してくれます。
詳しくは[README.md](https://github.com/cannot-fly-pig/vim-atcoder)を読んでください。

# 仕組み
1. curlを使ってatcoderのコンテストのページを取得
2. 正規表現を使ってパース、入力と出力を取得
3. 2で取得した入力を使って実行、正解かどうかを判定
4. データの整形、出力

と、まぁやってることは単純ですね
# 改善点
* 今の所c++しか実行できないので対応言語を増やす
* 企業コンへの対応
* 非同期処理化

# 最後に
いかがだったでしょうか。
vimでatcoderをしている皆さん、そしてvimpluginを作ってみようと思っている皆さんの助けになれば幸いです。
ありがとうございました。
Jetson NanoでJetbotならぬROS対応のRotsonを作ったよ

nVidiaのJetsonNanoが販売されました。
そして、Nanoを搭載したJetbotが公表されました。
https://github.com/NVIDIA-AI-IOT/jetbot
しかし、３Dプリンターで出力が必要なことと、３Dプリンターも能力によっては製作できないケースもありました。
そこで私は、ROSでエンコーダーモーターまで動かせるJetbotを板金で製作しました。

Jetbot
![jetson-jetbot-illustration_1600x1260[1].png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/929b0b3f-05a4-8128-33f7-4c52d3319b27.png)
(C)https://github.com/NVIDIA-AI-IOT/jetbot

私のRotsonはこちら
![ROTSON.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/25b684e5-41a0-ce37-09c9-99d31d7e0519.jpeg)
![ROTSON.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/222cab77-4427-339a-15ac-3595fd54efa5.jpeg)
![jetbot-mecanum.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/99e2f713-d112-a9ed-dc38-2e6d2204b8c4.jpeg)
Realsenseを搭載した様子
![DSC_0253 (2).JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/b03db3b5-c654-6f2a-4ffc-d651d8aa7379.jpeg)
Lidarやエンコーダーモーター、メカナム、デブスとしてRealSense D435が使用可能です。
現状は、TTモーターと、モータードライバー（PCA9685+TB6612）、OLEDで構成しています。
バッテリーは、Kinps モバイルバッテリー 10000mAhが使用可能でした。
少し値上がりしていましたが（今は前よりも安い1080円）安くてお勧めです。

製作編はこちら
https://qiita.com/usashirou/items/533be5e706a4ca5c99bf

Youtubeはこちら
https://www.youtube.com/watch?v=ZSWyX4AB6z4
Git 作業流れ(間違って他ブランチで作業)

間違って自分以外のデータに変更していて、コミットする前に気づいた時、

~GIT操作内容~
①変更を加えたデータを退避させ
②自分のブランチに退避させたデータを充てる


````
git stash
git checkout feature/k_190609
git stash list
git stash apply stash@{0}
````
Deep Learning推論用デバイスその１ Intel NCS2

## はじめに
今回は深層学習用のエッジコンピューティングデバイスの市場調査を行ったので、まとめました。

* [Deep Learning推論用デバイスその１ Intel NCS2](https://qiita.com/habakan/private/41763b92ae20e91c4138)
* [Deep Learning推論用デバイスその２ Nvidia Jetson Nano](https://qiita.com/habakan/private/5643681c8faf367cc764)
* [Deep Learning推論用デバイスその３ Google Edge TPU](https://qiita.com/habakan/items/72f05734be2290537aff)

## 調査したデバイス
調査したデバイスは以下の３つです。

*    Intel Neural Compute Stick2
*    NVIDIA Jetson Nano
*    Google EdgeTPU

デバイス間の比較をする前にまず、それぞれのデバイスの特徴などをまとめていこうと思います。
今回の記事ではIntel Neural Compute Stick2について紹介したいと思います。

## Intel Neural Compute Stick2
![center](https://software.intel.com/sites/default/files/managed/9d/c4/ncs2-angled-down-lid-off-500x334.png)
Neural Compute Stick2(NCS2)はIntelが発売したDeepLearning推論用のUSB型外部演算装置です。既存のマシンに対してUSBからNCS2を接続することで、演算をさせることができます。NCS2は以前に発売した「Movidius Neural Compute Stick」の新型となります。公式サイトより、旧型と比べ8倍ほど推論時間が速くなっていると記述されています。
こちらがNCS２のスペック表です。

|要素|Spec|
|---|---|
|プロセッサ	|The Intel Movidius Myriad X VPU|
|開発環境	|The Intel Distribution of OpenVINO toolkit|
|対応OS	        |Ubuntu 16.04.3 LTS (64 bit),Windows 10 (64 bit), or CentOS 7.4 (64 bit)|
|対応フレームワーク	|TensorFlow, Caffe, Apache MXNet, ONNX(PyTorch, PaddlePaddle)|
|接続方法	|USB 3.0 Type-A|
|サイズ	|72.5mm X 27mm X 14mm|
|運用温度	|0° - 40° C|

### Myriad X VPU
Intel NCS2には*Myriad X Vision Processing Unit(VPU)*というプロセッサが搭載されています。VPUは内部には*SHAVE processor*と呼ばれるVLIWベクトルプロセッサがあり、旧世代のNCSにさらに4個追加した計16個のSHAVE processorが搭載されています。このSHAVEプロセッサによってニューラネットワークの推論計算を一部分並列化することができます。

### Open VINO
IntelはNCSと同時にDeepLearning用のSDKであるOpenVINOを発表し、NCS2にも対応させています。
OpenVINOはIntelが提供しているハードウェアに対して最適化されたC++の推論APIです。
[OpenVINOのドキュメント](https://software.intel.com/en-us/openvino-toolkit/documentation/featured)
また、IntelからONNX RuntimeのプロバイダとしてOpenVINOをサポートするようなコードがforkされて実装されています。
https://github.com/intel/onnxruntime/tree/master/onnxruntime/core/providers/openvino
今後、正式にサポートされることになれば、対応しているFramework（Tensorflow・Caffe)のみならず、様々なFrameworkからOpenVINO経由で推論できることになりそうです。

### 対応OS
旧世代ではUbuntuのみの対応でしたが、Windows・CentoOSなど対応OSが増えました。
他にもRaspbianなども対応されており、OpenVINOのツールキットをインストールできる環境であればそのOSが載っているマシンにNCS2を接続させることで推論させることができます。

### 対応フレームワーク
旧世代のNCSではCaffe, Tensorflowのみ対応ということですが、NCS2ではそれに加えMXNetやONNXなどに対応しています。特にONNXに対応したことによってPyTorchなどで実装されたモデルをONNXに変換してNCS2で推論するなどといったことが可能になっております。

### 運用温度
運用温度は0度〜40度と公式では記述されていますが、フォーラムなどを見ると推論時の温度が高くなってしまう問題が一つのトピックになっています。

## 今後について
ONNX対応による様々なフレームワークへの対応環境、OpenVINOによる推論最適化などがNCS2を通してやられています。またIntelは2019年の4月にVNNI命令セットを発表しており、CascadeLakeというCPUには畳み込み層の計算を高速化するような命令セットが用意されています。このあたりの命令セットもVPUなどに搭載されるとより高速な処理が可能になるのではと予想されます。また、熱問題に関してはフォーラムで議論されていますが、NCS2をプロダクトとして利用する場合には重要な要素となるので、一番最初にUSBスティック型推論デバイスを出したIntelが今後どのように対応していくかは注目です。

## 参考文献
- [Intel® Neural Compute Stick 2 | Intel® Software](https://software.intel.com/en-us/neural-compute-stick)
PostgreSQLサーバーの起動を確認したい時

##必ず接続できるデータベースに接続できれば起動が確認できる

```
$ psql -d template1
```

template1はpostgresによって作成されたデータベースであり、すべてのインストールに存在します。
なのでPostgreSQLサーバーが動いていれば、必ず接続できるデータベースなのです。


以上
2018/06/28 PATH変数やパスを通すについて

#1. PATH変数とは

[参考にした記事](https://qiita.com/fuwamaki/items/3d8af42cf7abee760a81)

[参考にした記事２](https://tech.nikkeibp.co.jp/it/article/COLUMN/20060224/230596/)

[参考にした記事3]
(https://tech.nikkeibp.co.jp/it/article/COLUMN/20060224/230596/)

# 2.Linuxで出来ること

[参考にした記事](https://eng-entrance.com/you_can_do_linux#9_CUI)
Webページ上のレイアウトや文言をサクッと変更して見た目を試せるChrome ExtensionのVisBugの紹介

# 導入
このYoutubeで紹介されていたうちの一つのChrome ExtensionのVizBugの紹介です。
https://www.youtube.com/watch?v=U_gANjtv28g

今までChrome Developer Toolを開いて見た目調整のお試しをしていたような作業の一部を、ブラウザ上で直感的にできるようになりそうです。

# こんな感じ
### 文章の調整
文章追加とサイズ変更、左寄せ右寄せ変更とかだと以下の動画のようにできます

![visbug demo.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144064/45fb2073-0f1c-89e4-00fd-650124415f6b.gif)

### 要素の場所の変更
![visbug demo2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144064/0eb0065d-01b1-fc70-44d0-244c9c8622d4.gif)


### 他にも色々
あとはPaddingどれくらいかとかをグリッド付きで見せてくれたり、リストの並び替えを簡単にできたりとかできそうです。結構高機能なのでもっと色々できます。

# 使い方
Chrome Extensionなので追加するだけです。
ページ上でいじるだけなので特に特殊な権限とかは求められませんでした。
https://chrome.google.com/webstore/detail/visbug/cdockenadnadldjbbgcallicgledbeoc
だめなコードを修正する!

# tl;dr
仕事仲間から渡されたPythonコードをみて愕然とした。一関数1000行、いわゆるサブルーチン化も十分なされてない。極めつけは、関数をコピペして部分的に書き換えた二系統のコードを実装。いわゆる[アンチパターン](https://ja.wikipedia.org/wiki/%E3%82%A2%E3%83%B3%E3%83%81%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3)。自分でフルスクラッチで書き直したほうが早いもかもしれないが、コードの管理責任は彼にあり、最悪コードが二重化する恐れも。ということでこちらでリファクタリング（コード整理）してから返すという形にした。今回は、そのときの手順を公開する。一応、特定の言語に限定しないようには書いてみる。

# 事前準備
1.構成管理ツールを準備しソースをコミットする
リファクタリングするのだから変更履歴を参照できるように、svnやgitで管理したほうがよい。サーバーが準備できなくてもsvnならローカルで運用もできる。
2.リファレンスの処理結!果データをつくる
本当はテストコードを書くのが好ましいが、短いプログラムだとテストコードを書くほどではない場合もある。それでもリファクタリングするなら、改変前後で処理結果が変わらないことを確認できるように処理結果データを作る。
3.差分比較ツールをインストールする
Windowsなら、WinMergeがオススメ。
http://winmerge.org/?lang=ja
4.コードフォーマッタをインストール、整形し、構成管理にコミットしておく。
c++ならclang format。pythonならYAPF。統合開発環境ならツールに組み込まれているか、プラグインになっていることが多い。ちなみに、Visuaul　Studio 2017をc++で使う場合には、独自のコードフォーマッタとclang formatがあるが、clang formatがオススメ。.clang-formatファイルをプロジェクトディレクトリに置くことで、プロジェクトのコードスタイルを他メンバーに強制できる。本題に戻って、リファクタリングするときは、最初にカッコやインデント、タブの書式をそろえるべき。あとからフォーマットを変えるとなると差分比較が難しくなってしまう。そこでコードフォーマッタを使うことを勧める。

# 今回のリファクタリング目的
A. 処理内容を理解しやすいコードに改変する
B. 冗長なコードを集約してコードの記述量を減らす（コードのメンテナンスが容易な状態にする）

# リファクタリング
## 1.各所ある複数ステップからなる共通の処理を関数化し、関数コールに置き換える
## 2.関数の行数が多い場合、一塊の処理を関数化し、関数コールに置き換える
まあ、コメントや空行を除いても100行以内か。100行を超えるのは、論理的に意味のある複雑なif分や、どうしても必要な巨大なswicth文が存在する場合か。関数化することで処理に適切な名前をつけることになり（つけるべきであり）、コメントを追加しなくても、全体の処理の流れが短い行数で把握しやすくなる。
## 3.使わない関数、変数はコメントアウトする<br>
本当に使わないことが確定したらコードが除去する
## 4.標準ライブラリに同様の機能の関数やクラスがある場合、標準ライブラリを使うように書き換える
標準ライブラリーにあることを知らずに自作したり、標準ライブラリーの拡充により、同じ機能の標準関数が存在するということがあり、基本は標準ライブラリを集約していくことが望ましい。高速化した実装が使われていたり、デグレの危険を犯したくない場合は、あえて書き換えないという判断もある。
## 5.コメントを書き足す
初見でコードの挙動がわからず、読み込んだらわかったということがある。そのときはコメントを足しておこう！
## 6.不要なコメントを消すか書き換える（意外と重要！）
だめなコードの割にコメントをまめに書く人がいる。ただ読めばわかるコードのコメントは不要。不要と思ったら思い切って消してしまえ！あと、リファクタリングの結果コメントに矛盾が発生する場合もある。それも削除するか正しい内容に書き換える。
## 7.新しい構造体やクラスを作ったり、用意されている構造体やクラスを使うことによって変数を集約する
例えば、座標を表現する場合、x,yを独立して扱うのでなく、x,yをメンバ変数にもつPoint型を介して扱うなど。
## 8.似た目的で使われる変数は集約する
例えば状態管理が二重になっている場合は一元化する。
## 9.大きすぎる構造体やクラスを分割する
## 10.メンバ関数化を考える
グローバルな関数もメンバ関数化できないか考える。
## 11.関数の引数を最適化する
一つの基準として、関数を呼び出すたびに変化する値は単一の引数とする。それ以外は構造体にパックして構造体の変数にするか、メンバ変数とする。ここは個人の好みによるところが大きいが、全体のコードで一貫性をもたせたほうがよい。
## 12.変数名、関数名、クラス名、ファイル名を、適切な意味のあるものに書き換える
意味のない名前をつけていることがあり、意味のある名前につけかえることで、コードを理解しやすくさせる。

→数十行書き換えたら、（コンパイルが必要な言語はコンパイルし）、実行し、処理結果データ比較して変化がないことを確認してコミット。もし結果が違ってしまったらコミットしてあった前のバージョンのコードと変更点を比較して問題発生の箇所を特定する。基本は１から順にやっていくとよいが、ある程度リファクタリングが進むとやり残しを気づいたところから改変していくことになる。もちろん、テストコードが存在するならリファクタリングしながら適宜実施しましょう。

# 雑記
だいたいだいこんなことをやった！
c++のリファクタリングはよくやるが、pythonのリファクタリングは初めてやった。個人的にはコンパイル言語のほうが、まずコンパイルができることで一定のコード妥当性が確認できるので、リファクタリングしやすいと思った。まあ、どんな言語でも他人に提供するなら、コード読みやすく、メンテナンスが容易な状態にしてから渡すようにすべき。コーディング規約を決めてそれに則って書くとなおよいと思います。
vim-multiple-cursors で Vim 上で複数行同時編集する

## はじめに

Vim には矩形選択して編集することができますが、複数行を同時に編集することができないかやり方を探していました。

その中で見つけた、[vim-multiple-cursors](https://github.com/terryma/vim-multiple-cursors) というプラグインが便利そうだったので紹介します。

## vim-multiple-cursors とは

[vim-multiple-cursors](https://github.com/terryma/vim-multiple-cursors) とは、Vim 上で Sublime Text でのような複数行同時編集ができるようになるプラグインです。

以下、[vim-multiple-cursors の README](https://github.com/terryma/vim-multiple-cursors) からイメージ画像を引用します。矩形選択した後、それぞれの行でキー入力が反映されていることがわかると思います。

![](https://raw.githubusercontent.com/terryma/vim-multiple-cursors/master/assets/example2.gif)

## インストール

インストールはお好みのプラグインマネージャーを使って行います。以下は dein.vim での例です。

```vim:.vimrc
call dein#add('terryma/vim-multiple-cursors')
```

## 使い方

[vim-multiple-cursors の README](https://github.com/terryma/vim-multiple-cursors) にはたくさんの使い方が載っていますが、取り急ぎ Visual モードでの使い方のみ記載します。

Visual モードで編集したい対象の範囲を選択した後、`<C-n>` と入力すると、vim-multiple-cursors の複数行入力モードが有効になります。

その後、`i` や `a` で Insert モードに入り、キー入力すると、複数行入力モードで選択されているカーソルの部分に文字が入力されていきます。

## おわりに

簡単な紹介になりましたが、こちらのプラグインによってテキスト編集の幅が広がる気がしました。これから使い込んでいこうと思います。
VM環境でmount先のディレクトリにシンボリックリンクを貼る


## 前提
vagrantでマウントできていること

#### vagrantがマウントできない人
一旦、vagrantをhaltして、以下コマンドを叩く

```ruby
$ vagrant plugin install vagrant-vbguest
```
```ruby
$ vagrant reload
```

vagrant up時に自動的に新しいバージョンのGuest Additionsに更新してくれる「vagrant-vbguest」というプラグインをインストール

## 以下の手順で開発をしやすくしてみた

(1). mountコマンドで下準備

``` vim
$ sudo mount -t C:\Users\Owner\Desktop\VM\public ~/vagrant/public -o username=share,password=share,iocharset=utf8,file_mode=0777,dir_mode=0777
```

(2). シンボリックリンクを貼る

```vim
$ ln -s ~/vagrant/public /var/www/html/
```

## ちゃんと実行できているか疎通確認
1. ホストもゲストも空である  
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57249/bb526417-2a06-88f2-3db3-7828d7936857.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57249/8822dcff-ba56-8625-5ada-b4a213a44a41.png)

2. ゲストにファイルつくる 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57249/5e576b4b-7121-655a-c5a2-29c7e88acdb8.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57249/9bd2fb82-daa2-3391-e197-07e6714857ca.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57249/0c9dccab-2ecd-bd9f-081d-13ec65713d32.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57249/d8d4b093-288d-dac0-e416-431578fd1c70.png)
【ScalaMatsuri2019 ログ】Scala Driven Management

https://2019.scalamatsuri.org/#conference-day
2019-06-28 13:00 から @ A会場

> 関数型、型安全、型推論、Java資産活用など、Scalaのプログラミング言語としての性質は、しばしば開発プロセスそのものに様々な影響を与えます。その結果、各エンジニアが業務での開発にどう向き合うか、育成していくか、といったエンジニアリングマネジメントのプロセスにも影響があることがあるでしょう。業務での実例を交えながら、Scalaを開発言語として選択することがエンジニアリングマネージメントにどのように影響するかを説明します。

> 発表者
> 平岩 二郎 氏 (Opt, Inc. CTO)

自己紹介
-----------

アドテクおじさん
https://twitter.com/hiraiva


開発に直接携わることは、あまり多くない。


マネジメントとは(今日の定義)
-------------------

### 他人を通して成果を得ること

### 矛盾した事項に対処すること

これはよく「マネジメントになりたくない理由」として挙げれられる印象だが、
私は好き。

矛盾は必ず起こる。
それを解決したときにカタルシスを感じる。


要素
---------

### 人のマネジメント



### 事業やチームなどのマネジメント

同じゴールを目指す
心理的安全域
矛盾の解決



経験談
-------

社内向けツール
便利ツール
早く作るべき
社員自分だけ + 業務委託3名

SPA Scala+Angular

### Conflict

リソース不足
委託→Scalaわからん

### やったこと

業務委託の方は、Java経験はあった → ScalaText読んでもらった
水島さんに感謝

コアな部分はちょっと書いたけど、基本はPR見るだけ
隅々は見れないので、Typesafeか、要件、というあたりを見た


### 結果

4ヶ月で小さな成功


Scalaがどう役に立ったか
-------


テストは最低限書いた

Typesafeにはこだわった

CaseClass便利
API側が整理されてたのでそれをCaseClassに
Javaできる人ならキャッチアップできる

業務委託さんが「成長機会」と捉えてくれるのも良い


疎結合なマネジメント
----------------

PR見る時に Typesafe だけ気にしてれば良い(型に守られている安心感)ので楽だった。
小規模なものなら特にやりやすいと思う。
【Ruby】変数の種類と違い(グローバル変数・ローカル変数・インスタンス変数)

# はじめに
今回はRubyの変数の種類と、それぞれの違いについて説明します。
どこでどの変数を使用すべきか把握できていないと、思わぬエラーの原因になったり、
あるいは保守性が下がってしまったりします:sweat_drops:
しっかり把握して使い分けが出来るようになりましょう。
変数自体が何かがわからない方はググってください。

# 変数の種類
### グローバル変数
グローバル変数とは、簡単にいうと**"そのプロジェクト内、どこでも使用できる変数"**のことです！
どこで定義しても、どこからでも使用できる変数です。
一見とても便利ですが、どこでも使えてしまうからには一意である必要があります。
どこかで変数名が被ってしまうとエラーの原因になります。
使用する際は、本当にグローバルじゃなければダメなのかしっかり検討する必要があります！

定義の仕方は以下のように、変数の先頭に**$**マークをつけるだけです！

```test.rb
$animal = "cat"

def animal_type
  puts "This animal is #{$animal}"
end

animal_type
# 出力結果==> This animal is cat
```

### インスタンス変数
インスタンス変数は、次に紹介するローカル変数と合わせてよく使う変数のうちの１つです。
インスタンス変数は、インスタンスごとに値を持つことが出来、クラス内の全メソッド内で使用することが出来ます。
定義の仕方は以下のように、変数の先頭に**@**マークをつけるだけです！

```test.rb
class User
  def set_name(str)
    @user = str #インスタンス変数@userをここで宣言！
  end

  def put_name
    puts @user #違うインスタンスメソッドで呼び出してみます
  end
end

user = User.new #インスタンスを作成
user.set_name("まいける") #インスタンスに対してそれぞれのメソッドを実行すると
user.put_name

# 出力結果==>　まいける
#ちゃんと表示されました！
```
### ローカル変数
ローカル変数は、その変数が宣言されたメソッド内やブロック内のみで使用できます。
使用範囲(スコープ)が一番狭い変数です！
定義する際は、変数の先頭に**何もつける必要ありません！**
以下は同一メソッド内でローカル変数を宣言し、使用している例です。

```test.rb
class User
  def set_name(str)
    user = str #ローカル変数userをここで宣言！
    puts user #同じメソッド内で出力してみます
  end
end

user = User.new
user.set_name("まいける")

# 出力結果==> まいける
# 同じメソッド内であれば問題ないことがわかりました！

```

次に宣言したメソッドと別のメソッドでローカル変数を使用した場合どうなるか見てみます。

```test.rb
class User
  def set_name(str)
    user = str
  end

  def put_name
    puts user
  end
end

user = User.new
user.set_name("まいける")
user.put_name

# 出力結果==> undefined local variable or method `user' for #<User:0x00007fda840d20f8> (NameError)
# put_nameメソッド呼び出し時のローカル変数userが宣言されていませんよ。というエラー
```
ローカル変数は宣言したメソッド内でしか使用できないので、当然エラーになりました。

###まとめ

|    変数の種類　　 　　　　　|   　　　　　　　　　特徴　　　　　　　　　　　　　　　　　　　 |
|:------------------------|-------------------------:|:-------------------------:|
| グローバル変数| プロジェクト内どこからでも呼び出すことができる。|
| インスタンス変数| 同一クラス内のメソッドであればどこでも使用できる。|
| ローカル変数 | 宣言したメソッド、ブロック内のみ使用できる。|

#さいごに
実は他にも変数は種類があるのですが、今回は基本的な上記３種類を紹介させて頂きました！
特にインスタンス変数とローカル変数はよく使用するので
ざっくりでも違いを理解されていた方が良いかと思います！

最後までご覧頂きありがとうございました:relaxed:
[WPF/xaml]Segoe MDL2 FontFamilyを使って、いいね！っぽいボタンをつくる

# やりたいこと
標準のコントロールを使うと、殺風景な画面になるので、せめてボタンとか表示に使うアイコンだけでもなんか見栄えのよいものにして、華やかにしてやりたい。
例えばfacebookの「いいね！」っぽいボタンとか、画面に置いてみたい。

# やり方
よく使われそうなアイコンに相当するフォントをたくさん含んでいる「Segoe MDL2 Assets」フォントファミリーを使って実現する。

とりあえず下記のように書くと、TextBlockにいいねマークが出てくる。
FontFamilyにSegoeを指定し、Textにフォントの番号を指定する。
フォントの番号は、下で紹介するページにあるものを使用する。

```cs
<TextBlock Text="&#xE8E1;" FontFamily="Segoe MDL2 Assets"/>
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352601/e613c817-de58-c4d1-1f31-6b0baeb01750.png)

# どんなアイコンがあるか？
下記のページから探せる。

**Segoe MDL2 icons**
https://docs.microsoft.com/ja-jp/windows/uwp/design/style/segoe-ui-symbol-font

**Segoe MDL2 Assets - Cheatsheet**
http://modernicons.io/segoe-mdl2/cheatsheet/

上の例の「Text="&#xE8E1;"」のところの値を、これらのページにある値に変えてやると、好きな記号がつかえる。

# サンプルコード

```a.xaml
<Window x:Class="WpfApp31.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp31"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <!-- http://modernicons.io/segoe-mdl2/cheatsheet/ -->
    <Grid Background="Black">
        <TextBlock Text="&#xE8E1;" FontFamily="Segoe MDL2 Assets"/>
        <Viewbox>
            <StackPanel>
                <TextBlock Text="&#xE7C9;" FontFamily="Segoe MDL2 Assets" Foreground="White" HorizontalAlignment="Center"/>
                <Button  Content="&#xE8E1;" FontFamily="Segoe MDL2 Assets" Foreground="White" Background="#55FFFFFF" Width="30" Height="30">
                    <Button.Template>
                        <ControlTemplate TargetType="{x:Type Button}">
                            <Grid>
                                <Ellipse Stroke="{TemplateBinding Foreground}" Fill="{TemplateBinding Background}"/>
                                <Viewbox Margin="5">
                                    <ContentPresenter Content="{TemplateBinding Content}"/>
                                </Viewbox>
                            </Grid>
                        </ControlTemplate>
                    </Button.Template>
                </Button>
            </StackPanel>
        </Viewbox>
    </Grid>
</Window>

```

上記を動かすと、下記のような画面がでる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352601/dcf5f600-d1c6-e62a-6c46-8372c823243f.png)

# C#コードからsegoeのコードを表示する

下記のようにすれば、コードからsegoeのアイコンを表示できる。

xamlで`FontFamily`にsegoeを指定するのを忘れないようにして、

```a.xaml
<TextBlock Name="str"  FontFamily="Segoe MDL2 Assets" />
```

Textに文字コードを指定する。

```cs
str.Text = "\uE8E1";
```

結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352601/2c1677b1-a866-8d89-af40-01e06a4e6a60.png)
【ScalaMatsuri2019 ログ】Scalaライブラリを作る前に知っておきたいメンテナンスのこと

https://2019.scalamatsuri.org/#conference-day
2019-06-28 10:10 から @ C会場

> 「コードの再利用」がいかに強力であるかについては議論の余地はないでしょう。我々は何度も誰かがどこかで解いたことのある問題を繰り返し別の手段で解く必要などないのです。そのための仕組みが「ライブラリ」になるわけですが、当然作っておしまいではダメで、利用者が今後も困ることなく使っていけるようにメンテナンスされる必要があります。この発表では
> 
> - 複数Scala/JDKバージョンへの対応
> - バージョニング
> - バイナリ互換性
> - Javaとの相互運用性
> 
> といったScalaライブラリを長く適切にメンテナンスしていく上で知っておきたいトピックについて解説します。
> 
> 
> 発表者: 渋谷 充宏 氏
> (株式会社オプト　データテクノロジー開発部　チームマネージャー)


自己紹介
-----------------

https://twitter.com/m4buya

Scalaガチ勢ではない
「Scala は 型のあるRubyだよ」派


前提
-----------------

### 問題意識
再利用可能なコードを書くにはコストがかかる
多くの人に使ってもらえないと、作った甲斐がない

### 使われない理由

- 知名度、期待との乖離、使いにくい
- 特定環境でしか動かない、簡単に壊れる

後者2つの対策が今日のScope

多くの話が
https://github.com/opt-tech/bigquery-fake-client
の経験がベース


複数 Scala / JVM / JDK バージョンへの対応
-----------------

作る分には特定バージョンだけに対応するのが楽だけど、そのぶん使ってもらえなくなる。

### JVMバージョン

Version間で後方互換性があるので、
一番小さいJDKでCompileすればOK

### Scalaバージョン

2つめの数字が変わると互換性がない
その分だけビルドが必要

SBTの機能で crossScalaVersions を使う

```
sbt> +complile // この プラス が肝。
```

### 意図せず壊れないようCI

クロスビルドの機能は有名所のCIならあるはず


Javaとの相互運用性
-----------------

Javaから呼んでもらえるようにするには

ScalaのがJavaよりも言語機能が多いため、呼び方がトリッキーになることもある。

Some of Scala features are specially encoded to JVM bytecode.

Singleton object は Javaから呼ぶには謎の$を書く必要がある
Companion object なら自然に呼べる。

### Javaから呼びやすくするには

以下のアプローチがある。

- Scala特有の機能を使わない
    - https://github.com/scala/scala-java8-compat みたいなツールもある
- JavaでWrapperを書く

### テスト

JUnitで書いてScalaプロジェクト内から呼べる


互換性
-----------------

### ソース互換性

「ライブラリのバージョンを上げたらビルドが通らなくなる」のがソース非互換。

ちなみに「バイナリ互換だけどソース非互換」というケースも有る
例: メソッドをPackagePrivateにした


### バイナリ互換性

「ライブラリを新しくコンパイルして差し替えたら動かなくなる」のがバイナリ非互換。

JVMの仕様としてLazyにロードされる
見過ごしやすい

dependency hell になる原因。

#### どういうときにバイナリ非互換になるか

例1: adding method parameters with default values
配慮できてるように見えるがメソッドシグネチャ変わってるのでアウト!

他にもいろいろ


#### ツールで解決しよう

MiMa is the standard and easiest way for checking binary compatibility.

http://kmizu.hatenablog.com/entry/2016/03/16/203416
https://github.com/lightbend/mima


バージョニング
-----------------

バージョニングは、ユーザーとのコミュニケーションの手段
非互換だよ、というのを伝えながら出す手段

Scalaの世界では2つある

### Semantic Versioning

これは他の言語でも広く使われている
https://semver.org/lang/ja/


### Java/Scala Style Versioning

正式な名前はないと思うけど、みんなこんな感じで呼んでる。

epoch.major.minor

#### epoch
謎です。でっかい根本的な変更で上げる、みたいな。

#### major
非互換なときに上げる

#### minor
互換なときに


### どっちを使う?

今から作るならSemVerだと思う。
どっちにしても、明示することが大事。
ユーザーが混乱しないように。


#### メジャーどころだと

Play: epoch
Cats: Sem

それぞれちゃんと宣言している


#### めちゃ使われてる場合

Persistent Versioning
もう名前も変えちゃう。
アパッチとかで使われている

### Changelog大事

https://keepachangelog.com/en/1.0.0/
がシンプルでわかりやすい


QA
--------

### Q1. 依存性地獄にハマった時の解決エピソードを聞きたい
#### A. まぁ上げれないよね。根気との勝負になる(笑)

### Q2. 質問というか補足です

> Java/Scala Style Versioning
> 正式な名前はないと思うけど、みんなこんな感じで呼んでる。
> epoch.major.minor
> 
> epoch
> 謎です。でっかい根本的な変更で上げる、みたいな。

Epoch は、もともと Linux の Debian系にて、
バージョニングルール/体系 が変わったときに上げる、という位置づけで使われていたもの。
「これまで末尾を英数字でやってたのが、次から数字でやっていきます」みたいなときに。

### Q3. Q2について

Scalaの 2 から 3(Dotty) はそうではない(バージョニングルールを変えたいわけではない)ですよね。
Java界が曲解した?

#### Q2の方

たしかにその意味では「謎」と言える
Amazon Pinpointのここがツラい[AWS]

AWS Pinpointを前職で使い倒したのでその経験を書く。規模としては1PUSHにつき100万-1000万デバイスがターゲット。
世界で1番ユーザーデバッグしたと思う。

----- 
AWSの公式漫画で紹介されていたのでむしゃくしゃしてかいた。
https://aws.amazon.com/jp/campaigns/manga/vol5-2/

2017/12-2018/10ぐらいまでの話なので今はもっと良くなっているかも？

## ドキュメントにないステータスが返されるのは基本
例えば、CampaignActivityのstatusはこう書いてあるが
> The state of the activity. Valid values: PENDING, INITIALIZING, RUNNING, PAUSED, CANCELLED, COMPLETED

https://docs.aws.amazon.com/pinpoint/latest/apireference/rest-api-campaign-activities.html

実際はSKIPPEDやFAILEDなども来る。
たちの悪いことにFAILEDのまま放置するといつのまにかCOMPLETEDに変わっていたりする。
（実際は失敗している）

そもそも各ステータスがどういう時に返されるのか、どこにも書いていない
Campaignに限った話ではなく、Jobなどでも発生する。

## デバイス毎の配信ステータスはAPIで取れない
1. API ドキュメントに「EndoointのEndpointStatusにデバイス毎の配信ステータスが入る」と書いてあったのでそれを元に設計
1. 作成してテストしてみたところ、不正なEndpointを登録して配信しても常に「Success」しか返ってこない
1. AWSサポートに問い合わせしたところ、１ヶ月後に「このパラメータは使えないのでドキュメントを更新した」という返信がくる
1. ドキュメントの説明が「Not used.」になった
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/47513/cdb75b48-592e-3bc5-cc58-a38b24c5b9c6.png)

https://docs.aws.amazon.com/pinpoint/latest/apireference/rest-api-endpoint.html

結果、前提が崩れたのでアーキテクチャ設計からやり直しに。
一応kinesisからfirehoseでS3にログを吐いてそのログをGCMとAPNSでレコード毎に分析すればステータスが取れることは判明したが、、

## ドキュメントから必須項目がわからない＆勝手に必須項目が変わる
つらい。変えるときはせめてアナウンスして。βじゃないんだから。

## Campaign.Limits.MaximumDurationを設定しないと配信が60分で打ち切られる
1. 60分超えの配信を行うと配信失敗数が増える事象を検知
1. 問い合わせしたところ数週間後にキャンペーン最大実行時間が3600秒で打ち切りになるデフォルト値が設定されているとの回答あり。
1. コンソールのSettingに「キャンペーン最大実行時間」という項目があり、有効にするチェックボックスがアクティブでなくとも全体にデフォルト値が設定されるらしい。

（これに関してはコンソール側の設定にその項目があることを認識してなかった、CampaignのMaximumDurationを設定しない≒無制限だと思っていた自分も悪いが、、）

## iOSの証明書を更新しても切り替わらない
コンソールのSettingから証明書を更新しても切り替わらないことがある。
一度iOSのチェックを外して保存して再度登録するとうまくいく。

## 設定の組み合わせで配信の失敗確率が上がる
IsLocalTimeと何か（忘れた）を組み合わせると失敗しやすくなる等々。とりあえずIsLocalTimeは使うな。

## 配信数がマイナスになる
バグ

## 配信ステータスが一週間以上配信中のまま
バグ

## 同じ端末に二重送信される
バグ

## CSVの取り込み件数が一致しない
バグ

## 月数回ペースで配信が失敗する
kinesis経由でS3にログを出す設定は絶対に入れること
これがないとサポートに問い合わせてもほとんど原因不明で返ってくる。

## その他
思い出したら書く。
【snippets】 React Todoアプリ その2

## App.js

[前回に引き続き](https://qiita.com/Abbiscuit/items/6a9a4fca56fa8bdb3d0e)、AddTodoコンポーネントを追加。

```react:App.js
import React, { Component } from 'react';
import Todos from './components/Todos';
import AddTodo from './components/AddTodo';

class App extends Component {
  state = {
    todos: [{ id: 1, content: 'Buy milk' }, { id: 2, content: 'Play with dog' }]
  };

  deleteTodo = id => {
    const todos = this.state.todos.filter(todo => {
      return todo.id !== id;
    });
    console.log(todos);
    this.setState({
      todos: todos
    });
  };

  // 追加
  addTodo = todo => {
    todo.id = Math.random();
    let todos = [...this.state.todos, todo];
    this.setState({ todos: todos });
  };

  render() {
    return (
      <div className="todo-app container">
        <h1 className="center blue-text">Todo's</h1>
        <AddTodo addTodo={this.addTodo} />
        <Todos todos={this.state.todos} deleteTodo={this.deleteTodo} />
      </div>
    );
  }
}

export default App;

```
## AddTodo.js

```react:AddTodo.js
import React, { Component } from 'react';

class AddTodo extends Component {
  state = {
    content: ''
  };

  handleChange = e => {
    this.setState({ [e.target.name]: e.target.value });
  };

  handleSubmit = e => {
    e.preventDefault();
    // 親コンポーネントにあるaddTodoを使う
    this.props.addTodo(this.state);
    this.setState({ content: '' });
  };

  render() {
    return (
      <div>
        <form onSubmit={this.handleSubmit}>
          <label>Add new todo:</label>
          <input
            name="content"
            type="text"
            onChange={this.handleChange}
            value={this.state.content}
          />
        </form>
      </div>
    );
  }
}

export default AddTodo;

```

### 学習メモ

```react
 handleChange = e => {
    this.setState({ [e.target.name]: e.target.value });
  };


 <input name="content" //"name"をtargetに
        type="text"
        onChange={this.handleChange}
        value={this.state.content} />
```

以上はAddTodo（content内容に変更を加える）用のinputタグとなるが、inputが複数個あるときは`e.target.name`とすると、handleChangeメソッドを使いまわすことができる。