OmniAICreator/Qiita-1.07M huggingface dataset:
思わぬところに眠っていたボトルネック

CakePHPで書かれたシステムが妙に重いと思ったら、想像もしないところにボトルネックがあったのを発見してしまった、ということがありました。

## もともとの状況

ローカル環境で開発を始めたのですが、データベースへのアクセスもほぼないであろう、固定的なテンプレートを取得するのにすら[^1]1秒以上かかっていることに気づいて、いくらビルトインサーバと言ってもさすがに「これはおかしい」と調べてみることにしました。

## Xdebugを仕掛ける

こういうときは慌てず騒がず、まずは「推測より計測」ということで、PHPに[Xdebug](https://xdebug.org/)を入れてプロファイリングしてみることにしました。`xdebug.profiler_enable_trigger = 1`と設定しておくことで、`XDEBUG_PROFILE`という名前のGET/POSTパラメーター、あるいはCookieをセットすることで、必要なときだけプロファイリングを行うことができます。

そんな感じでプロファイリングデータを取得して、調査を行ってみたところ、1つのライブラリ内で70%以上の時間を消費していることに気づきました。

## DeviceDetectorとは

[piwik/DeviceDetector](https://github.com/piwik/device-detector)は、ユーザーエージェントを解析して、ブラウザ種類やバージョン、ユーザーの環境を判定するためのツールです、そして、消費時間がかかっていたのは、判定に使うための情報がキャッシュされず、**毎回YAMLを解析していた**ためでした。

さすがにそれはまずいと、CakePHPのキャッシュへとつなぐ部分を作成してDeviceDetectorに渡したのですが、それでも毎回YAMLの解析が続いていました。

### 呼び出すメソッドの問題
さらに調べ続けてみると、`DeviceDetector::getInfoFromUserAgent`を呼んでいることに気づきました。コード自体を確認してみると、

```php:DeviceDetector.php
    /**
     * Parses a useragent and returns the detected data
     *
     * ATTENTION: Use that method only for testing or very small applications
     * To get fast results from DeviceDetector you need to make your own implementation,
     * that should use one of the caching mechanisms. See README.md for more information.
     *
     * @internal
     * @deprecated
     *
     * @param string $ua UserAgent to parse
     *
     * @return array
     */
    public static function getInfoFromUserAgent($ua)

    /* 後略 */
```

というようになっていました。そもそもこの関数自体がキャッシュ非対応だったということで、正しくインスタンスを作成してそちらから呼ぶようにしたところ、処理時間の過半を占めていたYAML解析は綺麗サッパリ消え去って、一気に速度が改善しました。

## 後日談
あとからRedisを入れたので、CakePHP自体のキャッシュもRedisへ振り替えたところ、それだけでレスポンスタイムが100ミリ秒ほどさらに改善しました。そして、デバイスによって挙動を変える必要自体がないAPI系のコントローラーでは、DeviceDetectorの呼び出し自体を行わないようにして、関連する処理時間をゼロとしています。

[^1]: ブラウザ表示の時間でなく、「リクエスト→CakePHPがHTMLのレスポンスを返す」までが1秒超えという状態でした。
Zabbix タイムシフトを使って同一時刻比較

今日は、Zabbixのタイムシフトの機能を活用する方法をご紹介。
Zabbixは監視した結果をRDBMSに保存する仕組みになっています。保存期間は各監視アイテムごとに自由に設定可能です。
DBに過去の監視結果が保存されるため、過去の監視結果を活用した監視を実施することが可能です。

# タイムシフト

Zabbixは、監視結果に対してトリガーを設定することで障害の検知ができるようになります。このトリガーの条件式に利用できるトリガー関数はこちらのURLに記載の通り様々あります。

https://www.zabbix.com/documentation/3.2/manual/appendix/triggers/functions

この各トリガーの中には引数にタイムシフト設定ができるものが多数あります。
例えば、last関数です。

last関数は、監視結果に対して指定したポイントの最後の値を評価対象とする関数です。
last関数の引数としては以下のような設定が可能です。

***last (sec|#num,time_shift)***

第１引数には評価したい値を指定するための秒数または個数を指定します。last(60)と指定すると６０秒前の直近の監視結果が評価対象となります。last(#10)直近から数えて１０番目の監視結果が評価対象となります。
第２引数を指定すると、その指定した時間分過去にずらした上で第１引数で指定したタイミングの値が評価対象となります。
例えば、**last(0, 1d)**と指定すると、１日前の監視結果の値が評価対象となります。

このように過去のデータを評価対象として管理することができるため過去とくらべてどうかを評価して障害の判定ができるようになっています。
よく利用されるパターンとしては、このようにトリガーの関数にタイムシフト設定して評価させるケースが多いですが、今回はタイムシフト機能を使って、１つのグラフ上に描画して視覚的に変化を見やすくする方法を紹介します。

# 計算アイテム

グラフ化の設定の前、計算アイテムについて紹介します。計算アイテムは先程紹介したような各トリガー関数や四則演算等を使って監視結果の値に対して計算した結果を更に監視結果として登録するためのアイテムです。先程のトリガーを使っての評価だけだと、評価のために一時的に値を算出しますがデータベースにはそのトリガー関数の評価結果等は保持されません。そのためグラフ化するにはここで紹介する計算アイテムの利用が必要となります。

ある監視結果に対して１日前の結果を計算して保存するアイテムは以下のように設定します。
※計算アイテムの構文は[こちらの公式ドキュメント](https://www.zabbix.com/documentation/2.2/jp/manual/config/items/itemtypes/calculated)を参照してください。

![zabbix-cal1.png](https://qiita-image-store.s3.amazonaws.com/0/45851/5c8a9eb5-536c-290c-7601-8559b432661b.png)

式の設定欄を見ると、last関数を使って監視アイテムの1日前(1d)の直近のデータを監視結果として登録する定義になっています。更新間隔はもとの監視アイテムの更新間隔とあわせています。

このように計算アイテムを登録することで１日前のデータが監視結果として蓄積されていきます。

# グラフへの重ね合わせ

元の監視結果のグラフと計算アイテムで取得した値のグラフを重ね合わせると以下のように見ることができます。

![zabbix-timeshift.png](https://qiita-image-store.s3.amazonaws.com/0/45851/c432bf81-1c56-86ea-77dc-061db213b4ee.png)

このように重ね合わせてグラフで見ることで視覚的にも明らかな変化を見て取れます。

# まとめ

このように同一時刻の情報を画面で表示させると視覚的に状況を捉えることができるので場合によっては効果があるかもしれないです。
注意点としては、タイムシフトの機能を使うことで過去のデータを内部で処理することになるため、あまりに多くのデータを扱うようなタイムシフトの設定だと多少処理の負荷が高まる恐れがあります。
使いすぎ・無理しすぎには注意です。
FileMaker の Web 公開 機能を活用する「FX.php」を使う準備（インストール方法）

# FX.php
「FX.php」は PHP で FileMaker のデータベースを扱うための「[2大ライブラリ](http://news.mynavi.jp/column/fmxphp/001/)」のうちの一つです。

# ダウンロード方法
[GitHub にリポジトリがある](https://github.com/yodarunamok/fxphp)ので、それを落としてきましょう。「releases」は無いので、Clone するか zip で落としましょう。

# インストール方法
落としたファイルを任意のディレクトリに解凍しましょう。ここでは例えば`/opt/fm_api/lib/`に展開したとします。

# PHP で require してコードを書く
あとはコードを書くだけです。ライブラリのルートにある`FX.php`を`require`すれば、全てのクラスやメソッドが使えます。以下は`/opt/fm_api/`から`require`する例です。

```php
<?php
include_once('./lib/FX.php');
```
Optimistic Concurrency Controlについて

## Optimistic Concurrency Control

コミットまでロックを獲得せずに実行する方式の並行制御方式。
まず、更新のたびにバージョン番号が増加する複数のデータを読む際、読んだデータのバージョン番号とデータのペアで手元で保持しておけば、再度読んだ時にバージョン番号の変動を確認すれば値が書き換わっていないかを検出できる。

![read.png](https://qiita-image-store.s3.amazonaws.com/0/1716/8f59e3e3-52a5-cb42-f632-55282272d1b4.png)

この図の中の緑色の領域の中で値が変わっていない事をバージョン番号から保証できる。
これは対象となるデータがいくつに増えても同様である。

![ssread.png](https://qiita-image-store.s3.amazonaws.com/0/1716/ff20e8a7-a535-bb10-0350-a205c4ab22df.png)

こうすれば複数の値を論理的に一瞬で読めた事になる。これを一般に**スナップショット読み出し**と言う。
これに2PLを組み合わせる事で、トランザクション中で読み書きする値に一切ロックをかけずにコミット時のバージョン比較で代用できることになる。

**Optimistic Concurrency Control**(OCC)はこの考え方を拡張したもので、トランザクション実行中は

- 値を読み出す時はバージョン番号とセットでローカルに複製
- 値を書き込む時は書き込まずにローカルに保存

という手順で実行し、コミットする段階になった際に

1. 書き込み対象のデータのLockをすべて獲得する
2. 読みだした値のバージョン番号をすべて確認
3. 一致した場合に限り書き込みを行う
4. アンロック

という順番で実行する。この1.と2.の順序が肝心で「ロックを取ってからアンロックするまではAtomic操作になる」というロックによる一斉書き込みと「バージョン番号を取得してから再度同一のバージョン番号を確認するまでの間は変更が無いことが保証できる」という2つの一貫性保証の保証範囲をうまく重ねている。

![occ.png](https://qiita-image-store.s3.amazonaws.com/0/1716/99f7cedb-0a91-10c6-f6ba-932d6eb89bc2.png)

この図の緑の領域が**スナップショット読み出し**で、青の領域が**2PL**で守られた一貫性保証ゾーンで、この二つが重なる領域が発生するのが**OCC**における最重要なポイントである。

なお、他にもデータ毎にLockを持たずに単一のロックを全体で共有する実装など、さまざまな亜種はあり、ここでは良く応用される典型的なパターンを説明している。**OCC**の原典「[On optimistic methods for concurrency control](http://dl.acm.org/citation.cfm?doid=319566.319567)」とも少し違う。

比較的枯れたテクニックではあるが

- Webアクセスなどを支えるDBは読み出しが書き込みの10倍以上あることはザラ
- Readがキャッシュラインを汚さないので、コア数に対して性能が伸びやすい

という技術的な素性によって最近提案されるアルゴリズムはOCCから改良したものである事は多い。
また、この考え方自体は汎用的なので、理解しておくと思わぬところで役に立つかも知れない。
Java Silverつまりどころ(その４)

# つまりどころ〜

　　
こんにちは。

Java Silver来年ほんきだす。

## 継承

あるクラスから機能や属性を引き継ぎ、取り込む仕組みのこと。
継承した機能や属性は自クラスの振る舞いとして利用することが可能だー。

```java:
class Main {
     public static void main(String[] args) {
          CarA carA = new CarA();
          carA.brake(20);
     }
}

class Car {
     public int speed = 60;

     public void brake(int _speed) {
          speed = _speed;
     }
}

class CarA extends Car {

}
```

CarAクラスはCarクラスを継承している。

継承するにはextendsの後ろに継承したいクラスを指定する。

CarAクラスはbrakeメソッドを定義していないが、
親クラスであるCarクラスが定義しているためにCarAクラスのメソッドのように使うことが可能。
また、子クラスで親クラスのメソッドを上書き(オーバーライド)することもできる。

```java:
class Car {
     public int speed = 60;

     public void brake(int _speed) {
          speed = _speed;
     }
}

class CarA extends Car {
     public void brake(int _speed) {
          speed = (_speed * 2);   // オーバーライド！
     }
}
```

上記のように親クラスのメソッド（brake）をオーバーライドした場合は、
子クラスのbrakeメソッドが呼び出されることになるので、親クラスのbrakeメソッドを子クラスから呼び出したい場合は明示的に記述する必要がある。

```java:
class CarA extends Car {
     public void brake(int _speed) {
          super.brake(_speed); // superとすることで親クラスを指す
     }
}
```

継承の仕組みを使うことで様々なクラスで共通の処理を親クラスに集約し、
個別の処理のみを子クラスに定義することでメンテナンス性の向上や、コードの可読性向上につながっていく。

　　
　　
アウトプットして、ちしき固めていくぞ〜。
Delphiでレイトレ実装して，超2次楕円体を描画してみた

# はじめに
はじめまして，N.Mと申します．

今慶應義塾大学学部4年で卒業研究の実装にはまっている身なのですが，ずっと同じことばかりしても飽きてきてしまうので，飽きないように息抜きで初投稿です．

今回は今年6,7月にDelphiで実装したレイトレーサについての話です（[luxidea](http://qiita.com/luxidea)さんに指導していただいたり，ライブラリを提供していただいてます．本当にありがとうございました）．以下のスライド，ソースと一緒に記事をご覧ください．
[スライド](https://www.slideshare.net/secret/sWIXofq44nfl4L)
[ソース](https://github.com/HexagramNM/RayTracer)

Delphiのアドベントカレンダーの企画をluxideaさんに紹介してもらい，スライドとソースだけでも良いから投稿してと勧められたのですが，それだけだとつまらないと思ったので補足とかも交えながら，いろいろ書こうかと思います．Delphiというよりかはレイトレーサといった理論的な話が多くなってしまいますがご了承ください．

![raytrace.jpg](https://qiita-image-store.s3.amazonaws.com/0/152791/93cd40bf-72c9-be10-eb1e-68ae2b351c1a.jpeg)
↑今回作った画像（サイト用にすこし画質は落としてます）．クリスマスオーナメントに使えそう，使えそうじゃない？

# レイトレーシング
みなさんご存じだと思いますが，画素に向かってレイを飛ばし，画素に向かう光がどの物体に当たって反射したものか追跡して画素の色を決める手法です（スライドの3ページ目参照）．表面の頂点位置をパラメタを用いたりして明示的に与えてポリゴンを張る陽的（explicit）なモデルに対して，表面の頂点情報は与えられておらず立体を陰関数として表現した陰的（implicit）なモデルを描画するのに向いている**低速だけど高品質に描画できる**レンダリング手法です．
#超2次楕円体
上の画像の一番左の列から左から5番目の列までに表示された形状のことです．パラメタを変えることで球をはじめ角が取れたような立方体，円柱等を表現できます．式はスライドの2ページ目に書いていますが，**小数の累乗が出てくる**など解析的な観点から見ると複雑な式です．

# 問題点
レイトレーサで描画するにはレイと物体との当たり判定，言い換えると直線と立体との当たり判定が必要です．球といった簡単な立体の場合は立体の式を用いて方程式をたてて，それを解いて交点を求めるという感じで最初は超2次楕円体についてもそれでやろうとしました．超2次楕円体の場合，小数の累乗を含む方程式になり，解析的に解くことは困難なので**ニュートン法**を用いて解こうとしましたが下のように穴が空いちゃったり，描画できてなかったりと失敗しました．
![badresult.png](https://qiita-image-store.s3.amazonaws.com/0/152791/9b74ab8f-0b41-a823-e4b3-2d2666a14527.png)
レイトレーサでは**カメラ中心に最も近い**直線と立体との交点が必要で，ニュートン法ではそれが安定してできなかったんですね･･･
#そのための改善策，あとそのためのスフィアトレーシング･･･？
そこでluxideaさんに教えて頂いたのが**スフィアトレーシング**です．簡単にどういう手法か説明すると，直線上の点（Pとします）をカメラ中心に配置し，各立体表面からPまでの距離を計算．その最短距離だけPを直線上に沿って進めるということを点Pの位置が収束するまで繰りかえす方法で，この方法だと安定して直線と立体とのカメラ中心に最も近い交点を求めることができました．さらに，方程式を解く必要はなく表面からの距離（しかも厳密な距離じゃなくても距離より必ず小さくなる尺度なら可）を求めれば良く，新しい立体もその距離を計算する関数を組むだけで簡単に追加できます．またブーリアン演算（スライド10ページ目）も簡単に実装できました．

![slideanime.gif](https://raw.githubusercontent.com/HexagramNM/RayTracer/master/slideanime.gif)
↑スライドの5ページ目にも載っけたスフィアトレーシングを説明するアニメーション

![result2.png](https://qiita-image-store.s3.amazonaws.com/0/152791/5c69cec1-a691-8ec8-2163-ffb3b0a56ef5.png)
↑ブーリアン演算を実行した例．立方体と球について左からOr，And，Minusの演算を行ったもの．一番最初の画像の正八面体，正十二面体，正二十面体も平面のAndをとって作ってます．

# 超2次楕円体の距離関数
スライドの8~9ページに書いたように超2次楕円体の式を距離関数として用いました．luxideaさんに教えてもらった[この論文](http://graphics.cs.illinois.edu/papers/zeno)を参考にしています．

# Delphiでの実装
RAD Studioには**TImage**という画像パーツがあるようなので，レイトレーシングのアルゴリズムで決定した画素の色をそれに書き込めば良いようです．RAD Studioでないと画像表示するにもC/C++だったらOpenCVとか入れないと1から画像表示をさせるのは大変なのでRAD Studio様様です．あとその他実装について詳しいことは[ソース](https://github.com/HexagramNM/RayTracer)をご覧ください．

こんな感じに今回はDelphiでもレイトレーサが作れるよというお話でした．最後までお付き合い頂きありがとうございました．
Action Mailerのdelivery_methodに独自の配信方法を追加する

Action Mailerのdelivery_methodに独自の配信方法を追加してみます。

Action Mailerは内部で [mail gem](https://github.com/mikel/mail) を使っていますが、このgemは配信方法がpluggableになっており、
配信方法にsmtp、sendmail、file(メールをファイルとして保存する)、testが選べます[^1]。

で、自社でメール送信APIというものを作った[^2]のでAction MailerからそのAPIにリクエストを投げるようにしたい。

Railsはとてもカスタマイズ性が優れており、実は独自の配信方法を簡単追加できるようになっている。


まず普通にAction Mailerのクラスを作る。

```ruby
# app/mailers/user_mailer.rb

class UserMailer  < ActionMailer::Base
  def welcome_email
    mail(from: 'from@example.com',
		 to: 'to@example.com',
		 subject: 'my subject')
  end
end
```

`app/views/user_mailer/welcome_email.html.erb`や`app/views/user_mailer/welcome_email.text.erb`も適当に作る。

次に独自の配信方法を行うクラスを作る。
引数を1つ持った`initialize`メソッドと引数を1つ持った`deliver!`メソッドを作る。

`initialize`メソッドの引数には、後述する設定ファイルで設定した値が渡ってくる。
`deliver!`メソッドには、UserMailerクラスのmailメソッドに渡した値が渡ってくる。
詳しくはmail gemの[この辺のソース](https://github.com/mikel/mail/tree/master/lib/mail/network/delivery_methods)を読むとよいです。

```ruby
# app/mailers/my_mail_api_delivery.rb

class MyMailApiDelivery

    def initialize(settings)
        @settings = settings
    end

    def deliver!(mail)
	# ここでAPI送信処理を呼び出す
	MailApi.deliver({from: mail.from.first,
				  to: mail.to.first,
				  subject: mail.subject,
				  text_body: mail.text_part.body.raw_source,
				  html_body: mail.html_part.body.raw_source,
				  reply_to: @settings[:reply_to],
				  return_path: @settings[:return_path]
				})    
    end
end
```

次に設定ファイルに独自の配信方法を設定する。
add_delivery_methodメソッドを呼ぶと、xxx_settingsというアクセサメソッドが[定義される](https://github.com/rails/rails/blob/fe1f4b2ad56f010a4e9b93d547d63a15953d9dc2/actionmailer/lib/action_mailer/delivery_methods.rb#L56)。
要は`smtp_settings`みたいに使える。

```ruby
# config/application.rb

  ActionMailer::Base.add_delivery_method :my_mail_api_delivery, MyMailApiDelivery
  config.action_mailer.delivery_method = :my_mail_api_delivery
  config.action_mailer.my_mail_api_delivery_settings = {
      reply_to:     'reply_to@example.com',
      return_path:  'return_path@example.com'
  }
```

あとはいつものように` UserMailer.welcome_email.deliver_now`のようにメール送信すれば、API経由でメール送信がされる。

[^1]: ActionMailerではその4つだが、mail gemでは配信方法にSMTP、Sendmail、Exim、FileDelivery、SMTPConnection、Testが選べる。
[^2]: メール配信停止ユーザには送らないようにする処理とか、メールの種類によってメール配信ソフトウェア独自のヘッダーを付与したりする処理とか、メール開封ログをとるための処理とかを共通化するために各システムから利用可能なAPIを作った次第
redashからHiveのData Sourceを作ってもTest Connectionが失敗する

表題の件、調べた結果をメモしておく。

環境
* Amazon Linux AMI release 2016.09
* Redash Version: 0.12.0.b2449

# 背景
EC2上にRedashをインストールしてみたが、Data SourceにTreasureDataを設定したところPrestoは正常に動作するが、HiveがTest Connectionでこける事象が発生した。

# 調査

Test Connectionが失敗したときのRedashのapi_error.logに以下のようなメッセージが出力されていた。

```
[2016-12-01 23:57:06 +0000] [13701] [CRITICAL] WORKER TIMEOUT (pid:13716)
[2016-12-01 23:57:06,207][PID:13716][INFO][metrics] method=POST path=/api/data_sources/3/test endpoint=datasourcetestresource status=500 content_type=? content_length=-1 duration=30242.46 query_count=5 query_duration=33.58
[2016-12-01 23:57:06 +0000] [13716] [INFO] Worker exiting (pid: 13716)
[2016-12-01 23:57:06 +0000] [7475] [INFO] Booting worker with pid: 7475
```

これを調べたところ、Redashが使っている[Gunicorn](http://docs.gunicorn.org/en/stable/index.html#)というWSGI serverが出しているエラーだった。


このWGSI serverを使ってRedashのserverプロセスはマスタプロセス+workerプロセス(デフォルトで4個)という構成でリクエストを捌いている。

Gunicornの機能として、マスタプロセスとworkerプロセス間でハートビート通信をしていて、一定時間（デフォルト30秒）以上応答がないworkerプロセスを強制的にプロセス停止し、新規workerプロセス立ち上げをする機構が存在している。
上記のCRITICALエラーメッセージ`WORKER TIMEOUT`はこの際に発生する。

つまり、

1. HiveのData Sourceに対してTest Connectionボタンを押すと、いずれかのWorkerプロセスが実際の処理を開始する
2. 処理が30秒たっても終わらないため、マスタプロセスにより当該Workerプロセスが強制停止されてしまう

という事象が起きていると思われる。
PrestoはOKでHiveがダメだったのは、Hive特有の初期化処理に時間がかかるという特徴でこのタイムアウトに引っかかってしまったためだろう。


# 対策

Gunicornのドキュメントを参照したところ、以下のいずれかがある。
http://docs.gunicorn.org/en/stable/settings.html

* Workerプロセスのハートビート通信応答のタイムアウト値を伸ばす
* workerプロセスのタイプを変えて処理とハートビート応答を非同期にできるようにする

1つ目は対処療法なので、なるべくなら2つ目を取りたいところ。

1つ目はgunicorn起動時のパラメータオプション`-t/--timeout`に秒数を渡せばよい。
2つめは、gunicorn起動時のパラメータオプション`-k/--worker_class`にWorkerのタイプを指定する。

## 指定できるWorkerのタイプ

デフォルトで、以下のクラスが指定できるようだ。それぞれ、Pythonのパッケージが必要なので`pip`で別途インストールしないといけない。

* sync : デフォルトでの設定
* eventlet : eventlet >= 0.9.7 が必要
* gevent : gevent >= 0.13 が必要
* tornado : tornado >= 0.2 が必要
* gthread - Python 2 requires the futures package to be installed
* gaiohttp - Requires Python 3.4 and aiohttp >= 0.21.5

そのほか、自分で独自のWorkerクラスを実装することもできる。

## Redash用の対策

今回は、Workerクラスにgeventを指定する方法で解決することができた。

```
$ sudo pip install gevent
```

した上で、Redashの起動スクリプトにてgunicorn起動を行なっている箇所で起動時のオプションパラメータを追加する。

```supervisord.conf
[program:redash_server]
command=/opt/redash/current/bin/run /usr/local/bin/gunicorn -b 127.0.0.1:5000 --name redash -w 4 -k gevent redash.wsgi:app
```

これで、Workerプロセスにおいて、HiveのTest Connectionの処理とマスタプロセスとのハートビート通信応答処理が非同期に行われるようになり、HiveのData SourceもRedashから扱えるようになる。


# 考察
Gunicornのドキュメントにて記載されているように、以下のような場合にはWorkerクラスの設定を非同期にする検討をした方がよい。

* 長時間のブロッキング呼び出しを実行する（外部のWebサービスを利用する）
* インターネット越しのリクエスト応答を行う
* ストリーミング処理を行う
* ある程度長い時間のポーリング処理を行う
* WebSocketsを利用
* Cometを利用

http://docs.gunicorn.org/en/stable/design.html#choosing-a-worker-type

今回の場合、Redashから外部のWebサービスであるTreasure DataのHiveサービスを利用しようとしていたので、まさに該当していたというわけ。

クラウドでなくてもRedashから30秒以上かかるクエリを実行することは普通にあると思われるので、Redashを使う際にはWorkerクラスの設定は非同期に変えておくのが良さそう。

以上。
【数学】関数の表現力

この記事は [Mathematica Advent Calendar 2016 - Qiita](http://qiita.com/advent-calendar/2016/mathematica) の7日目の記事です。

Mathematica は普段使っていないので、凝ったことは全くできないのですが、枠が空いていたので僕の好きな関数を紹介します。

---

## ハート関数 - Heart Curve

その名の通りですが、ハートの形をした関数です。数学検定１級を大学生のときに取得したのですが、１級の試験に出題されたのを今でも覚えています。

<p align=center>
  <img alt="heart-curve.png" src="https://qiita-image-store.s3.amazonaws.com/0/3353/7e737c6d-c94a-c985-bc47-fca087b3cff7.png" />
</p>

### Mathematica Notebook

```mathematica
PolarPlot[
  Abs[Tan[t]]^Abs[Tan[t]]^(-1), {t, 0, Pi}
]
```

### Wolfram Alpha

Wolfram Alpha は無料で使えるので、こちらでも確認ができます。

[Wolfram|Alpha: Computational Knowledge Engine](http://www.wolframalpha.com/input/?i=polar+plot+abs(tan(t))%5E(1%2Fabs(tan(t))))

## More

今回、記事を作成するにあたって、[Heart Curve -- from Wolfram MathWorld](http://mathworld.wolfram.com/HeartCurve.html) というリンクを見つけたので是非こちらも参考にしてみてください。

<p align=center>
<img src="https://qiita-image-store.s3.amazonaws.com/0/3353/f63ff029-a594-eb91-0161-463f0c93a169.png" />
</p>

### Notebook

```mathematica
PolarPlot[
  2 - 2 Sin[t] + Sin[t] Sqrt[Cos[t]]/(Sin[t] + 7/5), {t, 0, 2 \[Pi]}
]
```

## おわりに

Mathematica はやっぱり高いっすね…
Bashで便利なフレームワーク

[bash-oo-framework](https://github.com/niieani/bash-oo-framework)(Bash Infinity)というものがあります。

ShellScriptを書くときは、これが便利になることがあります。

Bashでフレームワークを使うこと自体にはあまり意味があるとは思えませんが(Bashは速度及び、環境にあまり左右されず使えるため)、しかし、ShellScriptの可読性は向上すると思われます。

```bash
$ bash
$ which bash
/usr/local/bin/bash
$ git clone https://github.com/niieani/bash-oo-framework
$ cd bash-oo-framework
$ vim your-script.sh
```

基本的には`lib`フォルダの上にスクリプトを置けば動作します。`example`フォルダを参考にしながら使い方を理解します。

```bash:bash-oo-framework/your-script.sh
#!/usr/local/bin/bash

source "$( cd "${BASH_SOURCE[0]%/*}" && pwd )/lib/oo-bootstrap.sh"

import util/log util/type
Log::AddOutput util/type CUSTOM

passingArrays() {
  passingArraysInput() {
    [array] passedInArray
    $var:passedInArray push 'will work only for references'
    $var:passedInArray push 'test'
  }

  array someArray=( 'one' 'two' )
  passingArraysInput $ref:someArray
  $var:someArray toJSON
}

passingArrays
```

```bash
$ ./your-script.sh
["one", "two", "will work only for references", "test"]
```

これで少しはShell Scriptが読みやすくなりますね。
vim-easymotionに慣れたいので最初のキーを自動化してみた

[vim-easymotion](https://github.com/easymotion/vim-easymotion)と言うものがあります。これは、少ないキーでカーソル移動を実現するプラグインです。また、視覚的にわかりやすいというメリットもあります。移動先を視覚で強調してくれるためです。

ただ、このプラグインをインストールしてもなかなか慣れませんでした。慣れなというのは、具体的にはあまり使うことがなかったのです。

その理由を考えた時、最初のキータッチが面倒であることを思いつきました。よって、入力がなくて一定時間経過した時に`vim-easymotion`で設定した最初のキー(easymotion-bd-wl)を実行するプラグイン?を作ってみました。

```vim:~/.vim/plugged/vim-easymotion-auto/plugin/vim-easymotion-auto.vim
""" setting {{{
"" on plugin
"let g:air_vim_easymotion_auto = 1
"" set keymap
"nm <Leader>f  <Plug>(easymotion-auto-start)
"nm <Leader>ff <Plug>(easymotion-auto-stop)
"" }}}

if !exists("g:air_vim_easymotion_auto")
	let g:air_vim_easymotion_auto = 0
en

if g:air_vim_easymotion_auto >= 1
	set updatetime=3000
	let s:air_get_line = getline('.')
	let s:count = 0
	let s:two_count = 1
en

fu! s:air_easy_test()
	if mode() == "n"
		let s:count += 1
		let s:air_test_line=getline('.')
		if s:air_get_line != s:air_test_line
			call feedkeys("\<Plug>(easymotion-bd-wl)")
			let s:air_get_line=getline('.')
		en
	en
endf

fu! s:air_vim_easymotion_auto_start()
	aug air_easy_test
	    au!
	    au CursorHold,CursorHoldI * call s:air_easy_test()
	aug END
endf

com! EasyMotionAutoStart call <SID>air_vim_easymotion_auto_start()
com! EasyMotionAutoStop au! air_easy_test

nn <Plug>(easymotion-auto-start) :EasyMotionAutoStart<CR>
nn <Plug>(easymotion-auto-stop)  :EasyMotionAutoStop<CR>

if g:air_vim_easymotion_auto >= 1
	call <SID>air_vim_easymotion_auto_start()
en
```

内容に関してはvim-pluginとしての出来は全然よくありません。

一つは、`call feedkeys("\<Plug>(easymotion-bd-wl)")`の部分で、`feedkeys`を使わないやり方をあまり思いつきませんでした。

他にも良くないアンチパターンがたくさんあると思います。コメントにて指摘していただけるとうれしいです。

あと、このプラグイン、作ったもののあまり使いませんでした...。
Python Boot Campで得たもの

# 今来た３行
わい、Python Boot Campの教科書作ったんや
んで、講師もやったんや
そしたら結構楽しかったんや

# 初めに
これは[PyCon JP Advent Calendar 2016](http://www.adventar.org/calendars/1741)の12/7担当記事やで。
このカレンダーのテーマは「Pythonと私の想い出」や。ほんまええセンスしとるでしかし。

# 詳細
## 何かきーついたら[教科書](http://bootcamp-text.readthedocs.io/index.html)を作ってたんや
今年の夏ごろやと思うんやけどな、なんでそうなったかは忘れてもーたんやけど、[Python Boot Camp](https://www.pycon.jp/support/bootcamp.html)なるもんに参加したんや。
ようは地方でもPythonの縄張り作って、ウェーイさせようちゅうやっちゃ。
細かーいうと、Python初心者(今はどうか知らんねんけどな、初めは、他の言語を使って開発経験あるけど、Pythonは０、もしくはちょっとだけっていう人)に向けて、初心者向けのテキストを作って、一緒に書いたり説明したりして、腕上げようという感じやったんや。
で、そこで使うテキストを最初の方、気付いたらせっせと作ってたんや。
[元ネタ](http://gihyo.jp/book/2015/978-4-7741-7320-7)があったから大分助かったんやけど、なんかよくわからんけどファイルあげたら自動でコンパイルされてビビったんや。
いい感じにWebにデプロイ(readthedocs?っていうらしい)もされて、ほんまいい感じやったんや。ほんまやで。

## 最初人集まらずびびったんや、でも案外集まったんや
んで[募集かけた](https://pyconjp.connpass.com/event/33014/)んやけどな、見てもろたらわかるやろうけど、募集が6/3で実行が6/15や。えらい急や。日本憲法でも公布と施行まで結構あったで。そんでか知らんけど、直前まで人ほんまおらんかってん。
ほんま焦ったわ。わしがえーとこの偉いさんやったらもっとはよーに集まったんやろうけどな。
でもなんだかんだ集まったんや、5人ぐらいかな、7人かも、嘘や、10かもしれん。知らんけど。とにかくほんま焦ったわ。

## びびりながら講師やったんや、人に教えるってめっちゃむずいな
その様子が[これ](http://pyconjp.blogspot.jp/2016/06/python-boot-camp-in-kyoto.html)や。
わしみたいなもんが、人様に何を教えれるのかと思ったんやけどな、結果的に何とかなったんや。
サポートのこーらもえらい優秀でな、場所の準備から困った時の対応まで全部やってくれて、ほんま助かったで。
家出るとき嫁に「お前みたいな人に迷惑しかかけないアホンダラが、またいらんことするんちゃうんか」って言われたんやけど、ほんま何とかなってよかったでしかし。

## 終わってから雀荘行ったんや、もちろん負けたで
人生そんなもんや
MySQL 8.0 新機能 Persisting configuration variables

この記事は [MySQL Casual Advent Calendar 2016](http://qiita.com/advent-calendar/2016/mysql-casual) の7日目です。

MySQL 8.0 Developer Milestone Release (ベータ版みたいなもの) が９月にリリースされました。
MySQL 8.0 で導入された「Persisting configuration variables」について紹介します。

## これまで（MySQL 5.7まで）の設定変更の手順とその課題
MySQL の設定には、再起動不要で動的に変更できるものと、できないものがあります。
動的に設定変更するには ``SET GLOBAL`` を実行します。

例）wait_timeout の変更

```
mysql> SET GLOBAL wait_timeout=60;
Query OK, 0 rows affected (0.00 sec)
```

SET GLOBALは現在起動中のMySQLのみに影響を及ぼします。
そのため、MySQLが再起動したときに備えて設定ファイル（my.cnf）も、設定した値にあわせて編集しておく必要があります。

```
// SET GLOBAL に加えて設定ファイルの編集が必要
$ sudo vi /etc/my.cnf
```

この仕組みには以下のような課題があります。

1. 2つ変更しないといけないので面倒。特にサーバ台数が多い場合ツライ。
2. my.cnf の編集を忘れがち。再起動したら設定が戻ってしまった:scream: など事故のもとに・・・ 
3. DB管理者にファイルを編集させるためOSアカウントを与えないといけない

個人的には３つ目が一番の課題だと感じています。DB管理者がユーザデータにアクセスできないようDBアカウントの権限分離をしていたとしても、OSレイヤーからアクセスできてしまっては意味がありません。

## Persisting configuration variables
Persisting configuration variables を使うことで上記の課題を解決できます。

※ Oracle Database を使ったことがある方は、SPFILEと同じものだと考えて頂ければよいでしょう。

設定変更時に ``SET GLOBAL`` の代わりに ``SET PERSIST`` を使います。

```
mysql> SHOW GLOBAL VARIABLES LIKE 'wait_timeout';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| wait_timeout  | 28800 |
+---------------+-------+
1 row in set (0.00 sec)

mysql> SET PERSIST wait_timeout = 60;
Query OK, 0 rows affected (0.00 sec)

mysql> SHOW GLOBAL VARIABLES LIKE 'wait_timeout';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| wait_timeout  | 60    |
+---------------+-------+
1 row in set (0.00 sec)
```
``SET PERSIST`` では、このようなJSONファイルが生成されます。

```
$ sudo cat /var/lib/mysql/mysqld-auto.cnf
{ "mysql_server": {"wait_timeout": "60" } }
```

この設定ファイルは再起動時に読み込まれるので、my.cnf を手オペで編集する必要はもうありません！
SQLでファイルを編集できるため、OSアカウントをDB管理者に与える必要もなくなりました。


ちなみにデフォルト値に戻すと、mysqld-auto.cnf から、ちゃんと消えてくれます。


```
mysql> SET PERSIST wait_timeout =  28800;
Query OK, 0 rows affected (0.00 sec)
```
```
$ grep wait_timeout /etc/my.cnf

$ sudo cat /var/lib/mysql/mysqld-auto.cnf
{ "mysql_server": { } }
```

以上 Persisting configuration variables の紹介でした。
fluentdからChatWorkに投稿するプラグイン「fluent-plugin-chatwork（旧：fluent-plugin-out_chatwork）」

表題の通り [fluentd](http://www.fluentd.org/) から [ChatWork](http://www.chatwork.com/) に投稿するプラグインです

* https://github.com/sue445/fluent-plugin-out_chatwork
* https://rubygems.org/gems/fluent-plugin-chatwork

# 使い方
設定ファイルはこんな感じ

```
<match **>
  @type        chatwork
  api_token    YOUR_SECRET_TOKEN
  room_id      0000000000
  message      Hello ChatWork!\n<%= record["value"] %>
</match>
```

`message` ではerbや `¥n` の改行に対応しているのが特徴です

# ユースケース
社内GitLabのwebhookをtd-agentで受けてchatworkに通知するのに大活躍しています。

古い資料ですがやってるこんな感じです。

[fluentd初心者がgitlabとChatWorkを連携してみた - くりにっき](http://sue445.hatenablog.com/entry/2014/06/29/094035)

# いまだに後悔してること
初めて作ったfluentプラグインでプラグインの命名ルールがよく分かっておらず、fluent-plugin-out_chatworkという名前になっています :cry: （おそらく fluent-plugin-chatwork という名前の方がよかった気がする）

## 【追記】 fluent-plugin-chatwork v1.0.0をリリースした
コメントの @repeatedly さんの[アドバイス](http://qiita.com/sue445/items/f6ce8a32aba82045a2fb#comment-209590db1070607527ab)を参考に名前を変えました :bow:

https://rubygems.org/gems/fluent-plugin-chatwork

破壊的な変更なのでv0.0.3からv1.0.0にしています

古い名前のgemはfluent-plugin-chatworkをdependencyにしつつ、移行用としてv0.0.99.0をリリースしています。[^v0.0.99.0]
https://rubygems.org/gems/fluent-plugin-out_chatwork

[^v0.0.99.0]: このバージョンはrspec 2.99.0を意識しています。

`gem install` しようとすると下記のような警告が出るようにしています。 [^post_install_message]

[^post_install_message]: post_install_message を利用。http://guides.rubygems.org/specification-reference/#post_install_message

```shell-session
$ gem install fluent-plugin-out_chatwork
Fetching: fluent-plugin-chatwork-1.0.0.gem (100%)
Successfully installed fluent-plugin-chatwork-1.0.0
Fetching: fluent-plugin-out_chatwork-0.0.99.0.gem (100%)
===========================================================================
[DEPRECATION WARNING] fluent-plugin-out_chatwork is deprecated.
Please install fluent-plugin-chatwork instead of fluent-plugin-out_chatwork
===========================================================================
```

GitHubのリポジトリ名を変えると古いURLにリンクされている場合にリンク切れになるのが嫌だったのでそのままです。
【デザイナー生態学】デザイナーって、なに考えてるんだろう？

この記事は[CrowdWorks Advent Calendar 2016](http://qiita.com/advent-calendar/2016/crowdworks) 7日目の記事です。

##ひとりのデザイナーがCrowdWroksに入社した
2016年3月、ひとりのデザイナーがCrowdWroksに入社した。
広告会社出身で、デザイナーといってもWeb系では全く無い。
…まあ、私のことなんですが。

というわけで、CrowdWorksで~~面倒くさい~~デザイナーをしている浜野です。
[WoW!me（ワオミー）](https://wowme.jp/home)のデザインをやらせていただいています。

今年の3月、5年間過ごした広告系の仕事から一転、事業会社のWebデザイナーへとジョブチェンジをしました。

何を書いてよいやらと考えた結果、**デザイナー生態学**という内容をWoW!meの事例に合わせて書かせていただこうと思います。
…どちらかといえばグラフィックデザイン領域の話ですが、Webデザインにも活用できる内容だと思います。


##ロゴづくりから見えてくる変態性
デザイナーって**変態**であるべきだと思うんです。
言い方が悪いかもしれませんが、**こだわる**って意味ですよ。
@takeru0757 が言っていたように、1pxの差異をとても大切にしているんです。


![wowme_logo_01.jpg](https://qiita-image-store.s3.amazonaws.com/0/146955/60da126e-85c9-121c-e7cc-179496786737.jpeg)
ここにふたつのWoW!meロゴがあるじゃろ？
最後の最後に、どうしても気に入らないので調整をしたのですが、
どこが変わったか、わかりますか？

正解は…
<img width="462" alt="wowme_logo_03.png" src="https://qiita-image-store.s3.amazonaws.com/0/146955/3ecd1999-6551-1559-3763-a732878c73fc.png">
【！】の調整でした。


このロゴに至るまでに30を超えるロゴのプロトタイプを作り、【！】の位置を1px、下に移動させたり右に移動させたり、101％拡大してみたり99%縮小させてみたりを延々と繰り返していました。

![01.png](https://qiita-image-store.s3.amazonaws.com/0/146955/96c73922-e7c7-dca0-6c53-bb8fe115c17e.png)
######今は懐かしいWoW!me最初のロゴマトリクス。Please Easyという意味の造語、pleeeasy（プリージー）というサービス名も候補に上がっていました。


だいたい2日間かけてノートなどにラフを描き、PC上でプロトタイプを作成、マトリクスに落としこんでいきます。
そしてチーム間でディスカッションをし、サービスの方向性などの観点から候補をいくつか絞り込みます。

ここからまたひたすら**こだわりタイム**です。
2日ぐらい、ひたすらブラッシュアップを重ね、再びチームとのディスカッションを経て、WoW!meのロゴが完成しています。


##なんでそこまでこだわるの？
すべては「伝えるため」です。
デザインの根源は、洒落っ気づくことでも、飾り付けることでもなく、物事をより的確に伝えるためにあるのだと思います（なかにはお洒落であれ！みたいなデザインがあるとは思いますが）。

例えば同じ言葉ひとつとっても、デザインによって伝わる意味は大きく変化します。
**文字の形は声色**を、**文字の大きさは声の大きさ**を、**文字の間隔はしゃべる速度**を表します。

さて、下のA〜Cのうち、どの人が一番ヤバそうでしょうか。
![toilet.jpg](https://qiita-image-store.s3.amazonaws.com/0/146955/fc6065b8-ff28-4a60-7d09-d230d55f2b19.jpeg)
A：まだまだ余裕ですね。
B：今すぐ行かせてあげてください。
C：間に合わないかもしれませんね。

このように、**伝えたいことをもっとも伝わるカタチで伝達**する方法を突き詰めることこそがデザインなのではないかと思います。

※会議の最中に本当にトイレに行きたくて仕方が無い場合、この話を思い出してみてください。




##でも1pxの調整ってめちゃくちゃ大変だった
ここまで偉そうに1pxにこだわることこそ正義！みたいなことを書いていますが、WoW!meをデザインしている際に@takeru0757 の記事にもあったように「デザインカンプとちょっと違う！」とムスっとしていた時期もありました。
コーディングをまったくしなかった私も、自分でコーディングをしていく中で、1pxの調整にかかる労力がいかに大変かを身を持って知ることになりました。

仮想ボディがどうたらとか、カーニングとか、字切りがどうだとか…WoW!meチームのみなさん、ナマ言ってすみませんでした…。

※仮想ボディなど、気になった人は調べてみてください。その先に楽しい文字の世界が広がっています。

##それでも1pxの感覚を捨てないことが大切
本当に必要なのは、エンジニアとデザイナーがそれぞれ大切にしていることを理解しあえることなんだと思います。
どうしても譲れないとき、それがなぜ必要なのかを伝えることが大切だと思います。
もちろん、エンジニアの大切にしているものを理解した上でこだわる。

##CrowdWorksではデザイナーは希少生物！？
現状、CrowdWorksには4名のデザイナーが在籍しています。
エンジニアさんとの比率を考えると、ものすごく少ないですね。
様々なプロジェクトが進行しているなかでも、デザイナーが本格的に参画しているプロジェクトって少ないんです。

そんなわけで、CrowdWorksのプラットフォームサービスを一緒にデザインしていただける方を探しています！
少しでも興味がある方は[こちら！](https://www.wantedly.com/projects/56406?ql=gaJpZM4AKck0)

この記事は[CrowdWorks Advent Calendar 2016](http://qiita.com/advent-calendar/2016/crowdworks) 7日目の記事でした。明日は**言葉のスペシャリスト** @takeshiatarashi が何か書きます。
Unityでキャラをジャンプさせてみた

昨年、Macの使い方がわからなーい！
と嘆いた記事を初めて書いてから1年以上が経ちました。
今はqnoteに入社してMacもそこそこ？使いこなしていると思っている新人。
家ではWindowsを使ってるんですが、変換する時ついついスペースの横を押しちゃうくらいMacに染まりつつあります。

#本題へ
今回はUnityでキャラをジャンプさせるお話。
ほぼ独学でちょっとしたゲームを作っているのですがUnityは奥が深い。使いこなすなんて到底無理！わからない機能ばかり。。。
今度は、Unityの使い方がわからなーい！って記事書けばいいんですかね。。。

冗談は置いときまして本題ですね。
脱線しまくってて申し訳ないです。
というわけで、備忘録も兼ねて書きたいと思います。

先ほどからUnityと言っていますが、正しくはUnity2Dで作成してます。
ジャンルはラン&ジャンプ(ウインドランナー的なあれ)で題名がラン&コナンです。(嘘です)
UnityとMonoDevelopを使います。
使用言語はC#です。
今回参考にさせていただいたサイトは[こちら](http://0310unity.hateblo.jp/entry/unity_2d_jump)

#ジャンプさせる前に地面に立たせる
現在の画面はこんな感じ
![スクリーンショット 2016-12-06 14.13.21.png](https://qiita-image-store.s3.amazonaws.com/0/100756/deef4e3e-a8d8-a05a-9be8-b30379a5c427.png)
背景、地面はAssetStoreから「2d platformer summer (package4)」をダウンロードして使用しました。
キャラクターはプロジェクト作成時に入れられる「Standard Assets」の中からロボットくんを使用しました。
地面に「BoxCollider2D」ロボットくん上半分に「BoxCollider2D」と下半分に「CircleCollider2D」を追加して地面に立つようにします。

余談になりますが
なぜ、ロボットくんに2つColliderを設定するのか。
BoxColliderだけにしてしまうと段差などで引っかかってしまうんですよね。
そのため下半分にはCircleColliderを設定して段差で引っかからないようにします。

#クリックでジャンプ
いよいよジャンプさせてみます！
ロボットくんにC#スクリプトを追加します。

```C#:jump.cs
void FixedUpdate()
{
     if (Input.GetMouseButtonDown(0))
　　　{
       regidbody2D.AddForce(Vector2.up * 250);
     }
}
```

簡単に書くとこれだけでジャンプできちゃいます。
しかし、このままだと地上、空中関係なく無限にジャンプできてしまうので、地面に接地している時だけジャンプできるようにしましょう。

```C#:jump.cs
    [SerializeField]
    bool jump = false;

    void FixedUpdate()
    {
        jump = Physics2D.Linecast(transform.position,
            transform.position - transform.up * 1, ground);


        if (Input.GetMouseButtonDown(0) && jump)
　　　   {
           regidbody2D.AddForce(Vector2.up * 250);
        }
    }
```

これで地面に接地している時だけジャンプできるようになります。
Physics2D.Linecastを使うと自分の「Collider」と「指定したレイヤーのCollider」の当たり判定を判断してくれます。
実際にスクリプトを反映したスクショを貼って説明します。
![スクリーンショット 2016-12-06 20.11.29.png](https://qiita-image-store.s3.amazonaws.com/0/100756/738cc61e-6573-eb88-d795-13b8ebe30ee2.png)
白い線が入ってるのがわかると思いますが、これが地面と接地している時だけジャンプします。
`transform.position`
は開始点となりここを基準に下へ伸びています。
`transform.position - transform.up * 1`
これが開始点からどれだけ伸ばすかというコードになります。
長さは自分で調節する必要がありますね。

最後の
`ground`
はレイヤー名です。
ここは自分の好きなレイヤー名をつけて構いません。
ただし、オブジェクトに付けたレイヤー名と一致していないと意味ないのでご注意ください。

#まとめ
AdventCalendarに初めて参加させていただきました。
現在業務でもUnityを使っているのでまたUnityのことに関して書けたらなと思います。
※ジャンプスクリプトUpdateと書いていましたが、AddForceを使う場合はFixedUpdateを使います。
Webサイトのキャッシュ設計における基礎の基礎みたいなもの

こんにちは。[mediba advent calendar 2016](http://qiita.com/advent-calendar/2016/mediba)の7日目担当 メディアシステム開発部の森です。

書きたいネタはあれど時間がかかりすぎてしまうので、
ひとまず箸休め的な記事として、Webサイトにおけるページキャッシュ設計の進め方について軽くまとめました。

第一線で開発しているエンジニアにとっては当たり前の事だと言われそうですが、
初心にかえってみようという趣旨であります。

Webサイトのある１ページを例に挙げ、キャッシュ設計の流れを（ちょっと雑に）追ってみたいと思います。

## 今回の例 

>LAMP環境（Smarty利用）
>
>・ページ概要
>　要件1.会員制のサービスだが、非会員も利用できるコンテンツがある
>　要件2.会員と非会員で表示させたいコンテンツが違う（コンテンツはDBに格納されている）
>　要件3.会員状態は外部サーバに格納されており、提供APIにて取得
>　要件4.スマートフォン(iOS、Android)対応。
>　要件5.URLは一つで、会員状態やOSにより変わったりはしない

# STEP1.ブラウザキャッシュの扱い
まずはブラウザキャッシュの扱いについて決めます。
ページの要件として、

- 動的要素が存在し、かつ重要
- 情報の鮮度が重要
- 情報の更新タイミングが重要
- ユーザーの状態（会員非会員といった要素）が重要

これらの要素がある場合、ブラウザキャッシュは使えません。

ブラウザキャッシュを使う場合、レスポンスヘッダの設定値だったりプロキシキャッシュ対策だったりと考えることは色々あります。
しかし使えない場合も __ブラウザキャッシュを残さない__ 実装をきっちり考える必要があります。（意外と見落としがち）

今回の例の場合、要件2において __会員状態における表示コンテンツの違い__ という要素がありますので、基本的に __利用不可__ です。

ブラウザキャッシュが存在すると、__非会員 → 会員にユーザー状態が変わった__にもかかわらず、キャッシュをクリアしない限りユーザーには __非会員状態のページ内容が表示__ されてしまいます。
※ ブラウザキャッシュを残さない実装が甘い場合も同様です。

お金のやり取りが発生するサイトだと、結構Critcalな問題に発展する要素をもっています。


# STEP2.ページの閲覧パターン整理

ブラウザキャッシュが使えない場合、サーバー側でキャッシュを用意する事を考えないといけません。
まずはユーザーステータスやOSといった出し分け要素を整理して、ページの表示パターン数をまとめます。
※Smartyを利用しているので、テンプレート(tpl)単位で切り分けています。

![cache_img.png](https://qiita-image-store.s3.amazonaws.com/0/148768/4f968671-9cec-c23a-32be-6244545a1634.png)

今回の場合、図のように最低でも４パターンのキャッシュを生成する必要があります。

OSでの出し分けに関しては、表示コンテンツに差異がない場合は別tplではなくCSS側で表示制御を巻き取って一つにするというやり方もあるかもしれませんが、__OS依存・ブラウザ依存の闇は深いので__ やめておいた方が無難です。


# STEP3.キャッシュできる情報があるかの整理
サーバー側でキャッシュできる情報がないかを整理します。
今回の例において、ページの表示内容を決定する最終的な要素は以下の３つです。

- コンテンツ
- 会員状態
- OS

今回の例ではどうしたかを、各要素ごとに簡単に書きます。

### コンテンツ
コンテンツ情報をDBに問い合わせて取得する必要があります。
まず思い浮かぶのがクエリキャッシュですが、__DBサーバには問い合わせは発生__してしまいます。
DBサーバの性能如何によっては問題ないかもしれませんが、できればDBへのアクセス自体を少なくする方向にした方がよいでしょう。

ということで、今回の例においては膨大なデータ量でもないので __会員ステータスごとのコンテンツ情報をAPCuにキャッシュさせる__ 方向にしています。

### 会員状態
これに関してはWebサイトにもよりますが、会員・非会員状態はリアルタイムで取得することが理想です。
ただ、今回は要件3で挙げているように外部APIサーバへの問い合わせが発生します。
こちらのDBで会員状態をもっていれば工夫の仕様はあるのですが、この例においては __外部サーバが負荷に耐えられる事を信じる他ありません。__


結論から言うと、最初から外部サーバが負荷に耐えられないことはわかっていたので__会員状態をKVSに格納する__方向にしました。

### OS
最終的なtplです。ユーザーの会員状態とOSに対応したtplが、最終的な表示画面となります。
OSという括りをしていますが、PCとスマホ両方に対応している場合はデバイスも考慮に入れる必要があります。

# STEP4.キャッシュの有効期間
STEP3で挙げた各要素に関して、それぞれのキャッシュの有効期間を決める必要があります。

### コンテンツ
コンテンツ情報の更新頻度によって変わります。
１週間毎にしか更新されないのであれば、極論でいえばキャッシュの有効期間もその感覚で問題ないかもしれません。

実際には不測の事態でコンテンツ情報の更新が必要な事もあるかと思いますので、30分〜1時間あたりにしておけば不都合がないかもしれません。

### 会員状態
非会員 →　会員といった状態変更のための一連の操作と画面遷移が完了するまでに、最低でも何分かかるのかを踏まえて設定します。

状態変更操作に2分程度かかるのであれば、キャッシュの有効期間を60秒にしておく事で、限りなくリアルタイムに近い状態を維持でき、さらに外部APIへの問い合わせを少しでも減らすことができます。

### OS
コンテンツのキャッシュ有効期間と矛盾が無いように決める必要があります。
コンテンツのキャッシュ有効期間を1時間に設定してあっても、最終的なtplキャッシュが30分に設定されていては意味がありません。

tplの有効期間をコンテンツより長くした上で、コンテンツが更新されたら裏でtplを削除する処理を仕込んだり、毎時0分に必ずtplを削除するなどといったアプローチが必要です。

# STEP5.データの処理フローを整理する

![cache_flow.png](https://qiita-image-store.s3.amazonaws.com/0/148768/13649be2-5985-01cb-68a4-313feb47e29f.png)

図のように整理する事で、対象のページがどのようにキャッシュされて表示しているかを確認します。

青い枠の処理がキャッシュがある状態だとスキップされます。
ひとまずWebサーバ・DBサーバ・外部APIサーバにかかる負荷は軽減されることが予想されます。

# まとめ

軽く流すつもりでだったのですが、進めていくうちに思いの外書くことが膨らんでいき、
結果的にすごく分かりにくい内容になってしまいました・・・。

次回があれば、キャッシュについて徹底的に調べてリベンジしたいです。
オープンなslackチャンネルを運用した理由と結果

コミュニケーションアドベントカレンダー7日目の記事です。

僕達の会社では今年の1月からエンジニアのためのオープンなslackチームを運用しています。

[エンジニアのためのオープンな slack チームを作りました](http://blog.covelline.com/entry/2016/01/slack-team/)
[covelline-public.slack.com](https://covelline-public.herokuapp.com/)

今回はどういう意図でこのチームの運用を開始したのか、その結果どうなったのかをまとめます。

## なぜチームの運用を始めたのか

弊社では毎週水曜日に「アイデア会」と言って様々なアイデアを発表する機会がありますが、その中で弊社の活動をもっとオープンにする方法の一つとして僕が提案をしました。狙いとしては

- 開発環境とかフローとか、わりと自慢したい
- 他の会社の人とかが、どうなってるのかが何となく知りたい
- Slackでｸﾞﾀﾞｸﾞﾀﾞ、会話するスペースがあると面白い気がする
- エンジニア向け空間

と言った物がありました。開発環境のフローなどはブログや qiita にまとめるのですが、更新が追いついていなかったり情報が古いものが上がっているケースがあります。例えば昨年のアドベントカレンダーに書いた [他の人が何をやっているのか分かるツールを作った話](http://qiita.com/numa08/items/2f1679a9077ddae21167) で紹介したツールはすでに利用されていません。

そういった変更をリアルタイムで共有し合う空間を目指しました。

そしてもう一つが他の会社の中がどうなっているのかです。僕達の働き方がまだあまり多くの会社と接点を持つような働き方をしていません。そして、それはもしかしたら普通のことかもしれません。でも、僕達が目指す会社の形は世間一般の言う普通の会社とはちょっと違う形です。

よりオープンに情報を発信すること、他の会社から良いところも積極的に取り入れて吸収をする仕組みを作る狙いがありました。

また、そういった意識の高い目標ではなくてもグダグダと最新の話題のテクノロジー関連のニュースについて話し合ったり、ブログを書いたものを公開したり、 twitter や facebook では言いにくい会社の内情をさらけ出したり・・・と言ったエンジニア的クローズドなSNSとして利用されることも目指していました。

## 運用をした振り返り

総評としては良かったと思います。僕たちは積極的に会社の環境やワークフローの共有を行ってきて、それに関してチーム内での議論が発生しました。

また、新しくツールを導入してみた話や自分自身の開発環境を整えた時の話なんかをチーム内部でゆるい感じで会話することもよくあります。

他にも自分がウォッチをしていなかったデバイスやサービスに関しての情報を教えてもらうことも多かったですね。情報のチャネルは多い方がいいです。

## まとめ

弊社ではオープンな slack チャンネルとして [covelline-public.slack.com](https://covelline-public.herokuapp.com/) を運用していて、どういう意図でこのチームの運用を開始したのか、その結果どうなったのかを書きました。
数値で結果を評価できるものではないと思うので、あやふやな感じですが1年近く運用をしてみて中々良い感じの環境ではないかと思います。

ぜひ皆さんも [covelline-public.slack.com](https://covelline-public.herokuapp.com/) へ参加をしてみたり会社ごとでオープンなチームを作ってみてくださいね。

それでは来年もよろしくお願いします。
Paper Plane xUI(PPx)からエントリーへのsed

[前回の記事](http://qiita.com/wordijp/items/d90a64b807a7b39e4d1b)ではエントリーへのgrepを行いました、今回はそのsed版です。
今までは、ファイルやディレクトリへのfind、ファイルへのgrepとなっていましたが、sedではgrep -nの結果から、置換したい行を選択してsedができます。
おそらくLinuxコマンドを直接叩く場合は実現が困難な機能になると思います、PPx様様です。


# デモ

![seddemo.gif](https://qiita-image-store.s3.amazonaws.com/0/51728/bc19eef8-7557-09a0-ce9b-e5fbdbc703e1.gif)

sedメニューの場合は何をやったか分かりやすいように、PPbにコマンド内容も表示するようにしています。

sedメニューを実行すると、まずエントリーがファイル名か、grep -nの行単位の検索結果なのかを判別します、ファイル名ならばそのファイルを置換し、grep -n結果ならば選択行のみを置換します。

nkfはおまけです、選択したファイルの文字コードを変換します。


# ツール構成

今回はsedとRubyのワンライナーを使ってるだけなので、それらの環境さえあれば動作します。
なお、ワンライナーをRubyで書いているのは、エスケープ文字の展開をして欲しくなかったためです、gawkだと文字列内のエスケープ文字が展開されてしまうため、正規表現を利用した際に不都合がありました。


## PPx設定

差分のみです。
**※自身の設定が消えないように、適用前にバックアップを取るか、追加取り込みをしてください**
**※スクリプトのパスは自身の環境へと合わせて下さい**

```:PPx.CFG
KC_main	= {	; PPcメイン窓
^R	,%M_menuCustomReplace
}

M_menuCustomReplace	= {	** comment **
&sed(ファイル、行単位自動判別)	= 
	*set dummy='エントリへのsed(ファイル、行単位自動判別)'
	*set ENTRY_FILE=%'temp'\entryfile.tmp
	*set ARG=%"sedオプション([行]s/src/dest/g)"%{%|src%|/%}
	*set CMD=ruby -ne "a=$_.split(':'); fmt=\"sed -i -e '\"+'%%ss/%'ARG'/g'+\"' %%s\"; if a[1] =~ /^\d+$/; cmd=sprintf(fmt,a[1],a[0]); puts '$ '+cmd; system cmd; else; cmd=sprintf(fmt,'',a[0]); puts '$ '+cmd; system cmd; end"
	*script %0\script\entry2file.js, %'ENTRY_FILE'
	%OBsq cat %'ENTRY_FILE' | nkf -Lu -w | %'CMD'
n&kf	= 
	*set dummy='エントリへのnkf'
	*set ENTRY_FILE=%'temp'\entryfile.tmp
	*set ARG=%"nkfオプション(-w:utf8,-s:Shift_JIS,-Lu:LF,-Lw:CRLF)"%{-%|w%|%}
	*set CMD=ruby -ne "cmd='nkf %'ARG' --overwrite '+$_; puts '$ '+cmd; system cmd"
	*script %0\script\entry2file.js, %'ENTRY_FILE'
	%OBsq cat %'ENTRY_FILE' | nkf -Lu -w | %'CMD'
}
```

Rubyのワンライナーが読み辛いので、ここだけ別途解説します。

```rb:sedワンライナー部分.rb
a=$_.split(':') # -nオプションで実行してるので、行毎の文字列が入ってる
fmt="sed -i -e '" + '%%ss/%'ARG'/g' + "' %%s"
#fmt="sed -i -e '%%ss/%'ARG'/g' %%s" # XXX これはダメ、エスケープが展開される
if a[1] =~ /^\d+$/
  # 「:」分割でき、かつ行番号があった(= grep -n結果)
  cmd=sprintf(fmt,a[1],a[0])
  puts '$ '+cmd
  system cmd
else
  # それ以外(= find or grep -l結果)
  cmd=sprintf(fmt,'',a[0])
  puts '$ '+cmd
  system cmd
end
```

判別方法はエントリー文字列を「:」で分割出来たかで判別しています、「:」はファイル名にする事ができないので、この方法でfind/grep -l結果、grep -n結果の処理を切り替えられています、ただ単純な判定のため、それ以外のエントリー文字列が渡されるとsedに失敗します、その時はPPbに失敗内容が表示されます。

# まとめ

これでfind、grep、sedとソース編集時の基本コマンドが出揃いました、PPxにそれらを集められたので、エディタやIDEが変わってもPPxさえあれば何とかなるんじゃないかなと思います！[^1]

[^1]: そう言いつつ僕はVimばっか使ってます。
GoからCのライブラリを呼ぶ

Go言語でアプリケーションを開発しているときに、どうしても既存のCライブラリを使いたくなる場合があります。
Go言語では簡単にC言語を呼び出せる仕組みが提供されています。
詳しくは [cgo](https://golang.org/cmd/cgo/) などを参照してください。

Go言語側からC言語側（ライブラリ）への参照だけでなく、C言語側からGo言語側を参照することもできますが、今回はGo言語側からOpenSSLを呼び出してみます。

# やること
* Go言語から OpenSSLのライブラリ内にある SHA256 系の関数を使って **ABCDEFG** という文字列のダイジェスト値を得る。

## 補足
* 結果はバイナリなので、Base64した値を表示して確認します（面倒なのでBase64はGoでやります）。
* ちなみに結果は **6akqLtDVNzKsE7AxonsHGBQjHIYzyfQYRMy6iE1IKxY=** です。
* コマンドラインでやるとしたら、以下の感じです。

```sh:例
$ echo -n 'ABCDEFG' |openssl sha -sha256 -binary |base64
6akqLtDVNzKsE7AxonsHGBQjHIYzyfQYRMy6iE1IKxY=
```


# おためし

## とりあえずソース

```go:main.go
package main

// #cgo CFLAGS: -I/usr/local/Cellar/openssl/1.0.2j/include
// #cgo LDFLAGS: -L/usr/local/Cellar/openssl/1.0.2j/lib -lssl -lcrypto
// #include <openssl/sha.h>
import "C"
import "fmt"
import "encoding/base64"

func main() {
  ibuf := []byte { 'A', 'B', 'C', 'D', 'E', 'F', 'G' }
  obuf := make([]byte, C.SHA256_DIGEST_LENGTH)

  ctx := &C.struct_SHA256state_st{}
  C.SHA256_Init(ctx)
  _ = C.SHA256_Update(ctx, C.CBytes(ibuf), C.size_t(len(ibuf)))
  _ = C.SHA256_Final((*C.uchar)(&obuf[0]), ctx)

  b64 := base64.StdEncoding.EncodeToString(obuf)
  fmt.Println(b64)
}
```


## 実行

```sh:例
$ go run main.go
6akqLtDVNzKsE7AxonsHGBQjHIYzyfQYRMy6iE1IKxY=
```

## ポイント

### import "C" と cgo への命令
```go:例
// #cgo CFLAGS: -I/usr/local/Cellar/openssl/1.0.2j/include
// #cgo LDFLAGS: -L/usr/local/Cellar/openssl/1.0.2j/lib -lssl -lcrypto
// #include <openssl/sha.h>
import "C"
```

* import "C" の上に怪しげなコメントがありますが、これが [cgo](https://golang.org/cmd/cgo/) というツールに渡されます。ですので、ただのコメントではなく、意味があります。今回はOpenSSLのヘッダファイルとライブラリの場所をそれぞれ CFLAGS, LDFLAGS で指定しています。これらの値は cgo がコンパイラに指定する時に使われます。
* `#include <openssl/sha.h>` からはC言語のソースになります。ちなみに #include だけでなく、普通にCのコードが書けます。ですので構造体や関数の定義がその場でできます。今回は定義されているものを使うだけでしたので、 `sha.h` の include しかしていません。

### 呼び出し

```go:例
  ctx := &C.struct_SHA256state_st{}
  C.SHA256_Init(ctx)
  _ = C.SHA256_Update(ctx, C.CBytes(ibuf), C.size_t(len(ibuf)))
  _ = C.SHA256_Final((*C.uchar)(&obuf[0]), ctx)
```

* ヘッダファイル（今回で言うと **sha.h** ）で定義されている構造体や関数は `C.なになに` で使えます。今回の場合、 `ctx := &C.struct_SHA256state_st{}` で、`SHA256state_st` を使用しています。`C.struct_構造体名` となっていますが、構造体や共用体、列挙型にはプリフィクスがつくことになっており、（そのままですが）それぞれ以下の通りです。
	* struct ... C.struct_
	* union ... C.union_
	* enum ... C.enum_
* **C.SHA256_Init**、 **C.SHA256_Update** 、 **C.SHA256_Final** はライブラリ内の関数呼び出しをしています。ただし、CとGoで型が合わない場合が多いので、Cパッケージが変換用にいくつか関数を用意してくれています。以下は例です。
	* func C.CString(string) *C.char
	* func C.CBytes([]byte) unsafe.Pointer
	* func C.GoString(*C.char) string
	* func C.GoStringN(*C.char, C.int) string
	* func C.GoBytes(unsafe.Pointer, C.int) []byte

# まとめ

Go言語からのCライブラリを利用するには以下を行います。

* import "C" の上にコメントで必要なライブラリの指定コンパイラオプションを指定する。
* 同じくimport "C"の上にコメントで、必要なCのコード（#include等）を書く。
* 型の変換をなんとかして呼び出す。
	* 呼び出しは **C.関数名** 。
	* 構造体は **C.struct_** 、他。
右も左も分からないdocker初心者が少しだけ触ってみた

#はじめに

##なぜやるか
あるイベントで知り合った学生に、「dockerって知ってますかw？」と聞かれたのですが、その時僕はdockerについて何も分からず、答えることができなかったので、少し調べてみることにしました。

##Dockerって?
wikipediaにはこう書いてありました
>Docker（ドッカー[2]）はソフトウェアコンテナ内のアプリケーションのデプロイメントを自動化するオープンソースソフトウェアである。
Linuxカーネルにおける「libcontainer」と呼ばれるLinuxコンテナ技術[3]とaufsのような特殊なファイルシステムを利用してコンテナ型の仮想化を行う[4]。VMware製品などの完全仮想化を行うハイパーバイザー型製品と比べて、ディスク使用量は少なく、インスタンス作成やインスタンス起動は速く、性能劣化がほとんどないという利点を持つ。

うーん、分からない。
まずコンテナってなに？

####結局はこういうこと

VMはハイパーバイザ型のアプリケーションを使ってホストOSの上に仮想環境を作るものです。

しかし、コンテナは１つのホストOS上で複数のアプリケーションを**分離**させた環境で動かすことができる技術のことです。
つまり、アプリケーションごとに異なるOSを立ち上げることで分離し、運用します。そのOS自体は非常に軽量なため、大量のコンテナを起動させることができます。

##なぜコンテナが注目されるのか
たとえば、今まで一つのサーバー上で複数のアプリケーションがホストOSのリソースを共有して使っていたとします。それらはどれかのアプリケーションが落ちてしまうと、サーバー自体の機能が果たせなくなります。

しかし、コンテナでサーバーを管理すると、ホストOSのリソースを共有することができ、さらにどれかのアプリケーションが落ちてしまっても、その他のアプリケーションには影響がないため、落ちたアプリケーションのみを再度立ち上げるだけでよくなります。



#####では実際に使ってみましょう

## Dockerのインストール
###mac
```
brew cask install docker
```
をターミナルで実行します。

これでdockerはインストールができました。

入ってくるコマンドは以下の3つです。

```
docker  # 実際にdockerを動かせる
docker-compose  # 複数のコンテナを管理できる
docker-machine  # Dockerホストを作成できる
```

今回は`docker`コマンドのみを使ってみます。

```
docker run -it ubuntu /bin/bash
```
はい、おわりです。

これでubuntuが起動でき、rootユーザでbashが動いたと思います。

ちなみに、ローカルにubuntuのdockerイメージがない場合は、自動でDocker Hubからダウンロードするため、初回起動時は時間がかかるかもしれません。

ubuntuから抜けるときは`exit`を打つことで、抜けることができ、それと同時にコンテナも自動で終了します。

##次に、Dockerfileを作成し、オリジナルのイメージを作ってみましょう
任意の作業ディレクトリを作成してください。

その中にDockerfileを作成します。また、appというディレクトリも作成します。このappをホストOSとdockerとで共有したいと思います。

今回、dockerイメージはubuntuをベースにします。

```Dockerfile
FROM ubuntu 

RUN useradd -g sudo test 
RUN passwd -d test
RUN apt-get update
RUN apt-get install sudo

COPY app /app

USER test

CMD ["echo","docker"]
```

このDockerfileをビルドするときは

```
docker build -f {Dockerfile名} -t {REPOSITORY}:{TAG} .
```

少し説明を付け加えると、Dockerfile内の```RUN```はbuildした時に実行されるコマンドです。
```CMD```はdockerを起動するときの```docker run -it {dockerイメージ名}```をした時に実行されるコマンドです。

しかし、上記のrunのあとに```/bin/bash```などの実行させたいコマンドを入力した場合は、CMDがオーバーライドされるため、```/bin/bash```が実行されます。

ログインユーザを作ることについてですが、プロセスがdocker内でrootとして実行されることを防ぐためです。必ず設定しましょう。

以上です。

Dockerについてのコマンドとかは[Dockerの備忘録](http://qiita.com/issa/items/25d5ee40ebfbe6ad2b5f)に書きました。


コンテナの削除などについては[こちらの方のgist](https://gist.github.com/koudaiii/82d1f578397fcd58deef)をご参考ください。

#さいごに
まだ私はdockerを勉強しはじめたばかりなので、間違っていることも多々あると思うので、ご指摘いただけるとありがたいです。
みんなのPythonWebアプリ編を参考にURLパラメータをレスポンスに出力する。

#初心者診断員はWebアプリがどう動くかわかっているほうが良い
私は開発こそしたことはないですが、何とかWebの仕組みを理解しようと常にコードを動かしています。将来は開発をやるかもしれないし、サーバーを扱ったセキュリティ人材になるかもしれない。そんな気持ちがあるので、どんどん手を動かして、新人診断員の人たちにも役に立ってもらえればなと思う。

#Python3系で書いたURLパラメータをレスポンスに反映するコード

フォルダ構成は以前紹介した記事[Python3.5のcgiモジュールを使ってページ間で値を受け渡す](http://qiita.com/shuichi0712/items/84427a7722463a5cb4dd)のCgi-binフォルダに下記のコードを格納

```querytest.py
#!/usr/bin/env python
html_body = """
<html><body>
foo = %s
</body></html>"""
import cgi
form=cgi.FieldStorage()    
print("Content-type: text/html\n")
print(html_body % form['foo'].value)    
```

cgiサーバをローカルで立ち上げて、以下のURLを実行
http://127.0.0.1:8000/cgi-bin/querytest.py?foo=bar

実行結果
![GET.png](https://qiita-image-store.s3.amazonaws.com/0/127391/c852e58e-a36e-9f22-2303-fe41b56761b0.png)

ローカルプロキシで、生リクエストとレスポンスを表示するとこんな感じです。
![request.png](https://qiita-image-store.s3.amazonaws.com/0/127391/00baf110-bac2-ecc0-911f-98fa4a2c7235.png)


![response.png](https://qiita-image-store.s3.amazonaws.com/0/127391/c076bacf-c664-ab28-70f7-34f744a8f41b.png)



流れとしては
URLでパラメータを受け取って、サーバ側で処理を行ってレスポンスしてWebブラウザに出力するという流れでWebアプリケーションは構成されている。ここの仕組みを学ぶためにも、少しでも手を動かしておいたほうが、将来役に立つと思います。
ローカルプロキシを挟んでコードを書いたほうがより理解が深まります。

是非ご参考までに。
##参考サイト
みんなのPython Webアプリ編 
http://coreblog.org/ats/stuff/minpy_web/04/index.html
Common Test と EUnitの使い分け

# Common Test と EUnitの使い分け

Erlangには単体テスト用のEUnit (eunit) と結合テスト用のCommon Test (ct) が提供されている.
ただ, これらの使い分けは非常に曖昧で書く人によるところが大きい.
OTPはctで統一されていたり, 大抵の人はeunitで済ましてしまうことが多いだろう. Elixirにはctがないという話を見たような記憶もある.

自分なりに確立した使い分けについてここで紹介する.

## ctの使いどころ

### 時間がかかるテストの切り分け

eunitのtimeoutはデフォルトで1テストあたり5sであるのに対し, ctはinfinityがデフォルトである.
ということもあり, スローテストはctに纏めるようにしている.

### ファイルの書き込み/読み込みを行うテスト

eunitはファイルパスが実行パス依存 (カレントディレクトリ依存) になるが, ctではテストの度に生成される`priv_dir`と`SUITE`毎に用意できる`data_dir`が存在する.
その為, ファイルの入出力を行う場合はctを使うようにしている.

入力ファイルは`data_dir`から取れば良いし, 出力ファイルは`priv_dir`に書けばテストの度にディレクトリ自体が変わるので, テスト中で削除しなくても良い.
(良い訳ではないが, 大した容量じゃない時は消すコードを自分は書かない)

余談だが, rebarとrebar3では実行パス周りが変わっている為, eunitにファイル入出力があると移行した際に全部書き直す必要があったはずである.

なお, `priv_dir`と`data_dir`は以下のコードで取得することができる.

```erlang
-include_lib("common_test/include/ct.hrl").

PrivDir = ?config(priv_dir, Config),
DataDir = ?config(data_dir, Config).
```

### 同じテストを引数/モジュールを変えて実行したい場合

テストジェネレータを使えばeunitでも同様のことができるが, 遥かにctの方が書きやすく結果が見やすい.

例えば, bbmustacheでは連想配列, mapそしてkeyの種類としてstring, binary, atomをサポートしている.
[これらを全て同じテストにかける為に使っている](https://github.com/soranoba/bbmustache/blob/v1.4.0/ct/bbmustache_SUITE.erl#L33-L51).

他にも, behaviourのテストに使える.
そのbehaviourに必要な関数の仕様をctにしておき, モジュールが増える度に, ct内で定義した実行対象モジュールのリストに追加してあげれば終わりだ.

## eunitの使いどころ

### 関数単位のテスト

単体テストの名の通り, 依存関係のないテストは圧倒的にeunitの方が書きやすい.
何よりテストジェネレータの恩恵が大きい. ([例](https://github.com/soranoba/preminder/blob/v0.2.0/test/preminder_util_tests.erl#L48-L54))

この例はdescriptionがないので, まさかりが飛んでくるコードだが...
趣味コードだとテストジェネレータでdescriptionなしテストを量産してしまう.

### 細かい挙動をテストしたい場合

○○の機能を付けたgen_serverを作ったとする. 色々なところに使うとなると, かなり細かくテストを書きたくなる.
こういう時はやはりeunitを使う.

[moyoのeunit.hrl拡張](https://github.com/dwango/moyo/blob/a257f011b37c8127cd9c0312dfe40c3e1ad9e293/include/eunit.hrl#L66-L129)にあるようなマクロを使い, プロセスのダウン時の挙動などをテストする.
挙動を変える為に[meck](https://github.com/eproxus/meck)も使う.

### internal functionのテスト

eunit/ctに限らずできるが, rebar3のprofilesを使って, [testの場合のみexport_all](https://github.com/soranoba/bbmustache/blob/v1.4.0/rebar.config#L29)するのは, 自分はよくやる.
rebar時代は

```erlang
% test用にexport
```

というコメントを書いていた物だが, 大分楽になった.

## まとめ

実行のオーバーヘッドが小さいeunitとオーバーヘッドが大きい代わりに高機能(?)なct.
基本的にはeunitで良いと思うが, ctが重宝するケースは確実にあるので, 使ったことがない人がいれば是非使って欲しい.
BitriseのScheduled Buildを使ってキューが詰まる問題を改善する

皆さま、CIサービスは何をお使いでしょうか？
私は現在、業務のメインプロダクトではBitriseを使っています。

Bitriseは価格やXcode Betaへの対応の早さなど、多くの良い点がありますが、一番気に入っているのはScheduled Buildです。

Scheduled Buildを使うと、重い処理をGitHubへのPush時からは切り離し、深夜に定期実行することができるため、日中はCIのキューが詰まりづらくなります。

# CIのキューが詰まる問題
CIのキューが詰まる問題の要因の一つが、時間のかかる処理が頻繁に実行されることにあります。
iOSアプリ開発の場合、アプリの配布処理がボトルネックになりがちです。

私の場合、developブランチにmergeされるたびに、以下の3つの処理が走っていたのがキューが詰まる原因でした。

1. Debug Build + Unit Test
2. Release Build（Development環境）+ Fabric Betaへの配布
3. Release Build（Production環境）+ Fabric Betaへの配布

上記の処理で、33分程度かかっていました。
Pull Requestが一つmergeされるたびに33分もかかれば、キューも詰まっちゃいますよね。

![fril-ios_-_Bitrise.png](https://qiita-image-store.s3.amazonaws.com/0/8803/86353937-5fae-899f-718a-dd54dc3b6399.png)

（上記の画像は、深夜の定期実行に移した後のものです）

# アプリの配布処理を深夜に行う
テスト向けの社内配布であれば、配布するアプリは前日までの変更が反映されていれば事足りる場合がほとんどです。
そのため、配布処理を平日深夜2時に1度だけ行うようにし、Push時はUnit Testのみを行うようにしました。

BitriseのScheduled BuildはBuild一覧から簡単に設定することができます。

![fril-ios_-_Bitrise.png](https://qiita-image-store.s3.amazonaws.com/0/8803/796bf544-b5d8-caa4-4677-4b6e5e5c2d0e.png)

また、Bitriseは手動で任意のブランチをビルドすることもできるため、テストで最新の状態のアプリが必要になった場合にも対応できます。

# 結果
Push時には8分程度で済むようになり、キューが詰まらなくなっため、日中の開発がストレスなく進むようになりました。

![fril-ios_-_Bitrise 2.png](https://qiita-image-store.s3.amazonaws.com/0/8803/d907ff47-ebb2-de41-1a83-c85795369b00.png)

# まとめ

BitriseのScheduled Buildを使うと、アプリの配布処理のような重い処理を深夜の定期実行に移すことができるため、日中のキューが詰まりづらくなります。
BondとRealmの組み合わせサンプルから感じた、アプリ開発における「守破離」

[Bond](https://github.com/ReactiveKit/Bond)と[Realm](https://realm.io/jp/)を組み合わせて、ステキなMVVMを作り出そうと考えて、サンプルを作ってみた。

https://github.com/nishiyamaosamu/ESBondRealmSample

- Xcode 7.3.1
- Swift 2.3

Qiita APIから最新アイテムをとってきて、tableViewに表示し、タップするとお気に入りに追加される。
それらの一連を、Alamofire, SwiftyJSON, Realm, Bondを組み合わせて実装している。


## Swiftアップデートの辛さ 
しかし、事件は（起こるべくして）起こった。

数ヶ月前にこのサンプルを作ったので、Swift2.3で書かれている。Qiitaに載せる前に、最新の方が今後役立つだろうとSwift3に上げておこうと思い、使っているライブラリをcocoapodsでアップデートしてみたところ、大量のエラーが吐き出される。
Swiftがv2→v3になり、Bondv4→v5は大幅に変更されているし、Alamofireもv3→v4でGETリクエストすら修正しないと動かない。

「仕方がない、修正しよう」と直し始めるのだが、こんな小さなサンプルなのになんと手間がかかるのだろう。またBondの仕様がいろいろと変わっているので、学習コストも必要になった。
自社でもいくつものアプリ開発に携わっているのだが、Swiftのバージョンアップは非常に大変な作業になる。

## 賢人たちの声

そんなことを思っていたら、こちらのエントリーのこの一言に、強い納得しかなかった。
>ライブラリを使わなくて済むならそれが一番じゃないですかね？
>[今から新規でiOSアプリを書き始めるなら。2016年冬](http://qiita.com/yimajo/items/5a7333fd709e625b60da)



さらに、
もう数日前にこんなのも目にしていた。

>(…世界中のアプリ関係者の皆様…聞こえますか… いまあなたの心に直接語りかけています… プラットフォームのデザインガイドラインは神…ガイドラインを読まずに…アプリのディレクションをしては…ダメ…絶対…独自仕様の95%は…プラットフォーム準拠する方がマシな品質になります…）
>[深津さんによる経営者、開発者に向けたつぶやき](http://togetter.com/li/1055013)


プログラミングにおいても、デザインにおいても、何かのプラットフォームに乗っている時、基礎を無視して一見イケているような事をしても、すぐに風化してしまうのだろう。
 

## 本当に必要なライブラリとは？

今回のサンプルで定番と呼ばれるライブラリを入れているが、最低限に絞るならRealmだけで良い気がする。BondによるViewバインディングは非常に強力だが、故にアプリの動脈となるだろう。この動脈を維持していくには、それなりのスキルと覚悟がないと製品版アプリを生かして続けておくことは出来ない。
RealmはNotificationやKVOに対応しているので、Realmをフルに活かす方がよっぽどマシではないだろうか。

# アプリ開発にも守破離

「守破離」という言葉を思い出す。

>剣道や茶道などで、修業における段階を示したもの。
>「守」は、師や流派の教え、型、技を忠実に守り、確実に身につける段階。
>「破」は、他の師や流派の教えについても考え、良いものを取り入れ、心技を発展させる段階。
>「離」は、一つの流派から離れ、独自の新しいものを生み出し確立させる段階。
>[守破離（シュハリ）とは - コトバンク](https://kotobank.jp/word/%E5%AE%88%E7%A0%B4%E9%9B%A2-689006)


私（私たち）は、すでに「守」(SwiftやiOS標準)を身につけた上で、「破」（外部ライブラリ）を取り入れようとしているのか。

そういう問いを自分に投げかけ、私はまだまだ修行が足りなすぎると実感するのであった。