OmniAICreator/Qiita-1.07M huggingface dataset:
複数の作用がセットのAction発行とどう向き合うか

[Redux](https://github.com/reactjs/redux) を仕事と個人で使い始めて 3・4 週間という経験値なのですが、「唯一の状態である state の唯一の更新手段である Action 発行」が、更新以外の作用を伴うことに頭を悩ませていて、この点についてのお話をさせてもらいたいと思います。

なお、前提とする Redux ミドルウェアや周辺ライブラリは、公式推奨である以下です。

- [redux-thunk](https://github.com/gaearon/redux-thunk)
- [React](https://github.com/facebook/react)
- [react-redux](https://github.com/reactjs/react-redux)


## Action 発行に伴う 3 つの作用

Redux の Action 発行（＝ [dispatch](http://redux.js.org/docs/basics/Store.html#dispatching-actions) の実行）は、以下の 3 つの作用をセットで実行する処理だと、自分は考えています。

1. state の更新をする。
2. state のコピーをする。[^1]
3. 描画を実行する。つまり React の `render` 関数を実行する。[^2]


## それらの作用は常に全てが必要ではない
それぞれは勿論必要な処理ですが、常にセットで必要とは限りません。

### 3 が困る場合
単純に、描画に関係のない状態の更新であれば、実行をしない選択が出来る方が有り難いです。

React 側の「同期的な描画関数の実行は一回にまとめてくれる機能」を前提としても、例えば「60 fps でゲームプレイ時間を更新する」という処理がある場合、各フレームの処理は非同期であり、それぞれで描画が実行されてしまいます。

その場合は、「表示時間は秒単位だから、秒が繰り上がるときだけ描画する」ような調整をしたいです。

### 2 が困る場合
描画エンジン側が state に対して持つ参照の期間が不明な点を考慮するなら、一般的なプログラミングのルールとしては適切だと思います。

ただ一方で、巨大なオブジェクトや配列がそこに含まれる可能性もあり[^3]、その際に、state の更新に対して都度変数のコピー処理が実行される仕組みは、規模の想定ミスやコーディングのイージーミスから大きな問題につながることが予測され、この点は良いことではありません。

これが Redux 内で必須の作法だとされているのは、3 のために都度描画関数に投げるためだと思ってますが、そもそもその 3 が要らないのであれば両方不要になります。

### なお、1 だけを実行したい場合とは

ということで、もし 1 の state の更新を行いたいだけの場合も、2・3 の作用も発生してしまいます。

state の更新のみをしたい場合は数多くあり、先程のタイマーの例のように内部状態の変更が出力の変更にならない状況や、その他、時間の掛かる処理（Web-API アクセスなど）の結果を予め実行して保持して置きたい場合などがあります。


## 現在どんな Action / Reducer 設計にしているか

そのような Action の仕組みを受けて、個人的に今どういう設計にしているかです。

Reducer はいわゆる「リソース」別に定義しているとは思いますが、基本的にそのスコープが許す全体を何も考えずに更新する Action を一つ定義して、ほぼそれだけしか定義しません。
例えば、配列なら `UPDATE_FOOS` 、オブジェクトなら `EXTEND_FOO` のような感じです。

これは、Action の実行回数を減らすため、もしくは書き直しの手間を省くためです。
わかり難いので例を書くと、例えば、配列のある 1 行を更新する `UPDATE_ROW` を定義してしまったとして、その後もし複数行の更新が必要な Action が必要になった場合に、前述の理由で `UPDATE_ROW` をループして dispatch する処理は不適切なことが多いです。
その際に `UPDATE_ROWS` を別に作るくらいなら、最初から `UPDATE_ROWS` を定義してしまえ！という判断でした。

必定、その Action が取りうる引数の範囲は広くなるため、state を守るためのバリデーション処理や変換処理などが別途大量に必要になりますが、それは適当にオレオレモジュールを作り、Action Creator 内で呼び出して全てを適切に処理します。

Reducer 側で何もしないので、処理の本体はそのオレオレモジュール群の集合となり、一体 Redux とは何だったのか・・・[^4]という有様です。[^5]

加えて、そのオレオレモジュール群ですが、state がプレーンオブジェクトであるべきという制約上、クラスインスタンスで状態の保持ができないので、「第一引数に、ある決まったスキーマのプレーンオブジェクトを要求して計算して返す」ような表現の関数だらけになります。
JSON スキーマ大好きな人は幸せですが、自分はそうではないので単なる縛りプレイです。


## 以上

自分の Redux の理解がどこか間違ってるといいなって思って書きました。
色々ミドルウェアを使う前に生 Redux の力を知りたいです。[^6]


----

[^1]: Redux 実装上の制約があるわけではありませんが、[Reducers](http://redux.js.org/docs/basics/Reducers.html) に "We don't mutate the state" 以下の様に記載されているので、必須の処理だと考えられます。
[^2]: [Usage with React](http://redux.js.org/docs/basics/UsageWithReact.html) や [Examples](https://github.com/reactjs/redux/tree/master/examples) （特に React を使わない [counter-vanilla](https://github.com/reactjs/redux/tree/master/examples/counter-vanilla)）から、dispatch 時に render するのが意図した設計だろうと考えました。
[^3]: 最大で Reducer で分割された範囲内だけのコピーだとしても、です。
[^4]: 当記事公開から 2 週間実装を積み重ねた今の感想ですが、この通りに Reducer は単なる setter でありその処理や判断はしない、という設計がしっくり来るような気がしています。（※個人の感想です）
[^5]: [redux-saga](https://github.com/yelouafi/redux-saga) などの Action を別用途に使うミドルウェアもありますが、そこでオレオレモジュールを呼び出すだけなのであんまり変わらなさそうです。
[^6]: 趣旨から外れるので書きませんが、「初期状態の定義場所が一箇所に明確に限定される」など良いと感じた点もあります。
Azure App ServicesのTwitter認証を使用してサーバサイドでTwitterAPIを使用する為のトークン等を取得する

Azure App ServicesではTwitter認証を使用することができます。
これによりサーバサイドでも認証ユーザのアクセストークンを使用してTwitterAPIを利用することができます。

Twitter認証に関しては
[Twitter ログインを使用するように App Service アプリケーションを構成する方法](https://docs.microsoft.com/ja-jp/azure/app-service-mobile/app-service-mobile-how-to-configure-twitter-authentication?toc=%2fazure%2fapp-service%2ftoc.json)

TwitterApiをC#から行う場合には[CoreTweet](https://github.com/CoreTweet/CoreTweet/wiki/Home(%E6%97%A5%E6%9C%AC%E8%AA%9E))が便利です、

アクセスユーザのアカウントを使用してTwitterAPIを使用するためにはTwitterのアプリ登録で取得したコンシューマキー,コンシューマシークレットとOAuth認証にて取得されたアクセスキー,アクセスシークレットが必要になります。

それらはフレームワークとしては用意されていないので取得する拡張メソッドを作成してみました。

```csharp
    public static class TwitterUtils
    {
        public static void SetupUser(this HttpContext context, out string userId, out string accessToken, out string accessTokenSeacret)
        {
            var claims = context.User as ClaimsPrincipal;
            userId =
                claims?.Claims.SingleOrDefault(
                    x => x.Type == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier")?.Value;
            accessToken = context.Request.Headers.GetValues("X-MS-TOKEN-TWITTER-ACCESS-TOKEN")?.FirstOrDefault();
            accessTokenSeacret = context.Request.Headers.GetValues("X-MS-TOKEN-TWITTER-ACCESS-TOKEN-SECRET")?.FirstOrDefault();

        }
    }
```
来年こそGraphQLをちゃんと使うんだ

2016年、SPA作る事は出来たけどやっぱりSPAに対してサーバ側のエンドポイント周りの技術があまり追えてない。今年もRESTfulで終わってしまう。
https://firebase.google.com/docs/database/?hl=ja
FirebaseのリアルタイムDBとかは触ったけど、気になってたGraphQLはちゃんといじれてないので来年の自分にむけて書き記しておく。

## 入門する
https://learngraphql.com/basics/introduction
基本的な扱いはそんなに難しく無さそう。
JSONAPIとかで作ったAPIにしんどさを感じた人が喜びそう。

## フロントエンドの扱いについて追う
SPA系フレームワークからの扱い方が気になる。
ViewコンポーネントとGraphQLのTypeを対応させるように書いても面白そうな気はする。
実用の話は[Relay(React.js)](https://facebook.github.io/relay/)が当然一番すすんでるけれど、他のパターンどうなるんだろう。

## サーバーサイドでの扱いについて追う
Railsとかだと

```
rails g graphql Article
```
みたいな感じで上手く使えるようになるのだろうか。
公式では今すぐには無いと思うけど結構良さそう。

## まずはサーバレスにつかってみるとか
SERVERLESS FRAMEWORKにはもうGraphQLのプラグインがある
https://www.npmjs.com/package/serverless-boilerplate-graphql
ちゃんとしたWebアプリを作るのも大変そうなので、権限管理が要らなそうな軽いサーバレスなしくみを作って行くことをまずやる。

### アイソモーフィックWeb開発と相性良さそう。
スキーマ等モデル定義を１箇所でするとC/S間で共通で扱えるんじゃないか。



## 参考文献

GraphQL - http://graphql.org/
Let's Learn GraphQL - https://learngraphql.com/
【css】transform:matrix3dのちょっとしたお話

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

こんにちは。[OthloTech](http://www.othlo.tech)にデザイナーとして参加しているちーずです。
今回はあまりスポットを当てられていないけどなかなか面白そうな**transform:matrix3d**についてお話します。

# matrix3dについて

リファレンスにはこのように記載されています。

>transformプロパティのmatrix3d()関数は、要素に3D変形を適用する際に使用します。 マトリクスとは行列のことで、matrix3d()関数では行列を使用して3D変形を指定します。

>変形の内容は16個の数値で指定します。 基準となる値は、matrix(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 )で、この場合には座標は変化しません。

>指定すべき数値が16個もあると複雑に感じますが、以下のように4×4に分けて考えると理解しやすいでしょう。 16個の数値とはつまり、4x4の行列を指定していることに他なりません。

>(引用元：[htmq.com](http://www.htmq.com/css3/transform_matrix3d.shtml))

簡易的に言えば、**行列を使って3d変形ができる**って感じですね。
行列って聞くとちょっと難しそう。。。。
実際、css以外にも様々な言語で関数として用意されていて、glMatrix, mjs といった専用ライブラリを使用して計算することが多いみたいです。

##書き方
上記のとおり、16個の数値で4×4の行列を表しています。
よって、コードを書くときは下記のような書き方が良いです。
    
    matrix3d(
        a, b, c, d, 
        e, f, g, h, 
        i, j, k, l, 
        m, n, o, p 
    )

なお、行列の計算のしかたは[こちらのサイト(http://scene-live.com/)](http://scene-live.com/page.php?page=81)がとてもわかりやすかったのでご覧ください。

## webサイトでの使われ方
matrix3dを使ってるサイトは正直多くはありませんでした。
(探したのですが、あまりみつからず。。。。)
その数少ない使用例を紹介します。

<img width="699" alt="スクリーンショット 2016-12-19 1.11.58.png" src="https://qiita-image-store.s3.amazonaws.com/0/142322/8967de88-9df8-d807-2291-f3ed9cf59476.png">

### [franklinta.com](http://franklinta.com/2014/09/08/computing-css-matrix3d-transforms/)<br>
こちらは、実際にmatrix3dを紹介している記事です。
イラストの中の画面に合うようにmatrix3d()を使ってdivを変形させて、その中にwikipediaの記事を表示させてます。
このように、中の要素も全て変形した状態になるので、工夫すれば面白い見せ方ができますね！



<img width="1202" alt="スクリーンショット 2016-12-19 1.12.31.png" src="https://qiita-image-store.s3.amazonaws.com/0/142322/5d541daa-c41f-b946-f3b3-028d7d563f6a.png">

###[HYPER MARKET](http://hyper-m.jp/)<br>
こちらは、渋谷のモバイルアクセサリー店の「HYPER MARKET」さんのサイトです。
記事が書いてある紙をちょっと奥ゆきをもたせるように立てさせ(?)、それをスクロールして記事を読めるようなデザインになってます。
しっかり影も動いていたり、奥行きをリセットさせたり、様々な工夫がされているサイトですね。

# まとめ
matrix3dは行列の知識を必要とするため、数学が苦手な人は使わないことをお勧めします。
rotateやperspectiveを駆使して動きを作成した方が簡単かも。。。？
実際にmatrix3dを使ってcssで3dの動きをつけたいときは[css3 Generater](http://ds-overdesign.com/)を使うことをおすすめします。

####　ちょっとした感想
初めての投稿で、書き方に迷うことがとても多かったです。
もし間違った情報や、書き方に誤りがあった場合、コメントをお願いします。
(codepenの使い方ミスでDEMOをお見せできなかったので　、今後追加いたします。)
Microsoft Bot Framework を使ってみた

#はじめに
Microsoft Bot Framework　とはマイクロソフトが提供しているボットのフレームワークです。
一回作ってしまえば、色々なアプリと連携できるので便利です！
誰でもわかるように解説したいと思います。

#Microsoft Bot Framework使ったアプリをデプロイ
[こちら](https://docs.botframework.com/en-us/csharp/builder/sdkreference/gettingstarted.html)のサイトの**Getting started in .NET**という部分の１〜５通りに進めれば基本的に上手くいきます！
まず、ダウンロードBot Frameworkを[ダウンロード](http://aka.ms/bf-bc-vstemplate)する。するとZIPをダウンロードできるので解凍したものを下記の下の場所に設置する

\%USERPROFILE%\Documents\Visual Studio 2015\Templates\ProjectTemplates\Visual C#\

すると、VisualStudio2015のプロジェクト作成時に**Bot Application**が選択できるようになる
そこで、下図のようにプロジェクトを作成する

<img width="1280" alt="1.png" src="https://qiita-image-store.s3.amazonaws.com/0/130097/bdbe7f6b-e9e1-ef46-1882-1264368a76ec.png">

##エミュレータによる実行
[こちら](https://aka.ms/bf-bc-emulator)からエミュレータをダウンロードする
作成したプロジェクトを**RUN**すること下図のようになるので、URLをコピーする

<img width="1099" alt="2.png" src="https://qiita-image-store.s3.amazonaws.com/0/130097/1de8ebf0-a58d-ec40-defa-1dc1b0fdfdd0.png">

エミュレータのURLヘッダ部分に **[URL]/api/messages**と入れることでコネクション貼れる
ここでは、http://localhost:3979/api/messages
Bot自体は文字を入力すると送信した文字列の長さが返ってくる。
下図では**hi**と入力したことでボットから**2**と返ってきてる

<img width="939" alt="3.png" src="https://qiita-image-store.s3.amazonaws.com/0/130097/b6c1ed45-876b-5eb1-7c78-bca3d3f00086.png">

##AzureでWebAppを作成する
[Azure](https://portal.azure.com)のポータルで**App Service**を下図のように作成する

![4.png](https://qiita-image-store.s3.amazonaws.com/0/130097/0bea384d-9707-e247-313e-f18dad89929d.png)

ここではアプリ名を**bottestpro**にした

![5.png](https://qiita-image-store.s3.amazonaws.com/0/130097/6e497d06-7f3d-509c-7624-62fcc9dd8b80.png)

##デプロイ
VisualStudio2015に戻り、プロジェクトを右クリックして**【公開】**を選択する
その後、下図のように**Microsoft Azure App Service**を選択

<img width="706" alt="6.png" src="https://qiita-image-store.s3.amazonaws.com/0/130097/b2b01ce3-b08e-64d1-abd7-d043338594ff.png">

先ほど作成したアプリを選択する

<img width="797" alt="7.png" src="https://qiita-image-store.s3.amazonaws.com/0/130097/25041dd7-1012-3c9a-3214-df73ce765131.png">

そのまま発行する

<img width="704" alt="8.png" src="https://qiita-image-store.s3.amazonaws.com/0/130097/c719b867-d353-a102-603b-8d393d0be19b.png">

#Microsoft Bot Framework portal 
[Microsoft Bot Framework portal](https://dev.botframework.com)にアクセスし、下図のように設定を行う

- Bot Profile : 任意に設定して大丈夫です！
- Configuration : デプロイした**App Service**のURLを**https**にして、URLの後ろに/api/messagesと追加したものを挿入する
- **Manage Microsoft App ID and password** : 下のAppIDのパスワードを確認する。
- Admin : 設定しなくても良い

全ての設定を終えたら保存する

![9.png](https://qiita-image-store.s3.amazonaws.com/0/130097/e75d22e1-268a-4396-1621-8cf1e80675af.png)

##プロジェクトにIDとPassの挿入
VisualStudio2015のソニューションエクスプローラーの**Web.config**のBotId(Bot handleのこと)とAppID,AppPasswordを挿入し、もう一度**デプロイ**する

<img width="1275" alt="10.png" src="https://qiita-image-store.s3.amazonaws.com/0/130097/73cd9646-2b32-0659-f7f5-ce86660fcfd9.png">
##実行
Microsoft Bot Framework portalのTestを押すとsucceededと出れば成功！
すると右のChatで作成したBotと楽しめる

![11.png](https://qiita-image-store.s3.amazonaws.com/0/130097/d1e85fc7-c227-3729-c650-a243b44501df.png)

#おわりに
色々組み合わせてみたり、オリジナルのボットを作ってみましょう！
Swift 3 対応時にハマったString Interpolate

Swift 3 対応時にハマったString Interpolateについて書きます。

# String Interpolateとは？
たぶんあまり聞き慣れないんじゃないかなぁと思います。僕も今回の件を調査するまで英語でなんて言うか知りませんでした。
日本語だと`文字列内の式展開`とか`式評価`でしょうか。

機能としては単純で文字列を定義する時に他の文字列を入れ込むときに使います。
こんな感じ。

```swift
let name = "y_koh"
let message = "Hello, \(name)"
```

モダンな言語には必ずある機能だと思いますが、Objective-C時代には無かったですよね（遠い目...）。

# Swfit 3 対応でどんな風にハマったか
さて、そんなString Interpolateですが、こんなところでハマってしまいました。

**画像が表示されない**

```swift
let image = UIImage(named: "layout_\(name)")

// -> image is nil
```

**ラベルに`Optional("hoge")`と表示されてしまう。**

```swift
let name = "\(tag.name)・"

// -> Optional("誕生日")・Optional("ケーキ")・
```

これのとても困るところが、落ちないんですよね。Imageがnilでも表示されないだけですし、文字列はOptionalと表示されるだけですし。

# なぜそうなってしまうのか
勘の良い人はもう気付いていると思いますが、これは[IUO(ImplicitlyUnwrappedOptional)が廃止](https://github.com/apple/swift-evolution/blob/master/proposals/0054-abolish-iuo.md
)されたことによるものです。

IUOとは`var name: String!`みたいな書き方のことですね。

SwiftからObjective-Cを呼び出す際に`nonnull`、`nullable`が付いていない場合もIUOとして扱っていましたがこれも同様にOptional型になります。

Optional型であるということは、つまり、明示的にunwrapする必要があります。

Optional型をそのまま使おうとすると普通はコンパイルエラーになるのですが、**String Interpolateを使っている場合はコンパイルエラーになりません**。

個人的にはエラーにしても良いと思うのですが、おそらくデバッグ等で使うためにそのまま使えるようにしているのかなと予想しています。実はそんなことなかったというのが後ほど分かるのですが。

# これって開発者が気をつけるしか無いの？
さすがにそれは辛いので、何かしら自前実装でも良いのでチェックする機構を作れないものかと思いました。`print()`であればグローバルに定義されているだけなのでオーバーライドすればいかようにも出来るのですが、String Interpolateは言語仕様なので無理っぽいです。

色々と調べているとこんな記事が。
[Optionals and String Interpolation By Ole Begemann](https://oleb.net/blog/2016/12/optionals-string-interpolation/)
まさにドンピシャな記事です。

> Swift 3.1 will actually actually raise a warning when you use an optional in string interpolation like this because this behavior may be surprising.

Swift 3.1 でワーニングが出るようになるとのことです。これは助かりますね。正直ワーニングだと埋もれがちなので、Swift 3 対応を考えるとエラーの方が嬉しいのですが、これから書く分に関してはワーニングでも十分かもしれません。

こちらのPull Requestで修正されて既にmasterマージされていました。
[Extend Optional-As-Any Warning to String Interpolation Segments #5110](https://github.com/apple/swift/pull/5110)

またこの現象はバグとしてIssueがあがってました。仕様ではなかったのですね。バグなのでSwift Evolutionには載せる必要はないとLattner氏は言ってるそうです。
https://bugs.swift.org/browse/SR-1882

# まとめ
色々と調べた結果、ワーニングが出ないのはバグでそのうち直るという結果でした。今回ちょっと難しかったのがそもそもこの機能何て言うんだっけ？というところです。`String Interpolation`という機能名を知っていればもっと早く上記記事にたどり着けたはず。。機能名をちゃんと知っておくことはこういう時に大事だなぁと思いました。
In-Memory DB

近年のデータベースはよく「最新のインメモリ技術を採用して高速化」などという宣伝が出回っている。

参考: [既存の概念を覆す！Oracle Database In-Memoryのテクノロジー Vol.1](https://www.ashisuto.co.jp/corporate/column/technical-column/detail/1197182_2274.html)
参考: [SQL Server 2016の概要とIn-Memory OLTP の改善点(前編)](https://enterprisezine.jp/dbonline/detail/7133) 

従来のデータベースだって世の中のほぼすべてのソフトウェアも最終的には(キャッシュ)メモリの中で計算処理をしているわけで、何をもってして「インメモリ技術」と呼ぶのか誤解を招いているケースが身の回りで多発していた。

## ディスクDBの時代

昔、例えばOracleV2が発売した1979年では、NECからPC-8001が発売され、市販されるコンピュータのメモリは64KBとか48KBほどだった。エンタープライズ製品であればMB級のものもあるだろうとは思うがお値段も相当のものだった。
会社の業務を回すにあたって、全データが64KBに収まる前提でアーキテクチャを組むなんて考えられなかった時代なので、商用DBは必然的にデータはハードディスク等に収める前提になり、メモリはそれに対するキャッシュ・バッファとして使うアーキテクチャを取っていた。

ディスク上のDBとキャッシュ・バッファとしてのメモリをうまく活用する方法はこれまでの記事で取り上げて来たように、ページ・WAL・Undo/Redoログなどなど様々な要素が複雑に絡み合っている。
そのため、速度を稼ぐためには様々な工夫が為されてきた。

## インメモリDBの時代

そのあたりのボトルネックを詳細に調査した論文がSIGMOD2008のStavros Harizopoulosらの[OLTP Through the Looking Glass, and What We Found There](http://dl.acm.org/citation.cfm?id=1376713)である。
この論文では典型的なディスクDBの中で発生しているオーバーヘッドの詳細に踏み込んで、機能を削いだり再設計することでどこまでパフォーマンスが上がりうるかというベンチマークをとっている。
衝撃的な図を引用すると

![looking_glass.png](https://qiita-image-store.s3.amazonaws.com/0/1716/d06ba828-0605-e967-4278-289bfb8d6b7e.png)

なんとデータベースの行っている作業のうち、本当に仕事に寄与しているのは6.8%で、他のほとんどのCPUパワーをバッファ管理やラッチやログやらに食われているというものである。

- データは全部メモリに置く
- ディスクからのリカバリは諦める
- シングルスレッドでトランザクションを実行する

というように様々な事を一気に諦めたら効率が20倍ほどになった、と報告している。

## インメモリDBの論文

インメモリDBの考え方自体は1992年のHector Garcia-Molinaらによる[Main Memory Database Systems: An Overview](http://dl.acm.org/citation.cfm?id=627538)の中で登場している。この論文には大まかには、ディスクDBからインメモリDBになればバッファ管理周りが不要になり、ページにとらわれないデータ構造をよりアグレッシブにCPUに最適化していくことができる旨が書かれている。

最近の論文だと[VLDB2016のPer-˚Ake LarsonらによるTutorial](http://vldb2016.persistent.com/modern_main_mem_db_sys.php)の[Modern Main-Memory Database Systems]
(http://www.vldb.org/pvldb/vol9/p1609-larson.pdf)が短くて良くまとまっている。ページを使わないのでARIESスタイルのリカバリを使わなくなり、Undoログが要らなくなってRedoのみを保存すれば良い。
HekatonのBw-TreeやMass-Treeといったマルチコア環境向けに特化した高速B+ツリーの亜種を紹介し、更にはボトルネックがCPUに移るため従来のいわゆるボルケーノスタイルの操作抽象化がボトルネックになるのでJITコンパイルすることの必要性を論じている。

他にはカーネギーメロン大学の[2016年のDatabase Systemsの講義資料](http://15721.courses.cs.cmu.edu/spring2016/schedule.html)も素晴らしい。最近のインメモリDBによく出てくる論文をまとめて英語の講義映像も含めて載っている。学生の演習課題がBw-Treeの実装だったり[Peloton](https://github.com/cmu-db/peloton)への独自改造だったりと非常に激しい。

今日は個別の実装には触れず、ディスクDBからインメモリDBへの大きな潮流を紹介した。
伝統的なページ管理によるDBはアカデミックの分野では近年あまり注目されず、圧倒的な性能を誇るインメモリDBの論文が多い。
今後はインメモリDBとして注目しておきたいトランザクションエンジンについて説明する。
文系だけど、数学やり直したい！

私は、数学が苦手です。数式を見るだけで、体が固まってしまいそうになります。

できることなら、数学と関わらずに過ごしたいと思っていたのですが、機械学習の勉強会に行って、深層学習の話を何となく聴いているうちに、集中して聴き入っている自分に気付いてしまったのです。
普段集中して、聴くことなんて滅多にない私が、なぜか、難しいディープラーニングの話に魅入られてしまいました。
どうして、脳神経の構造をコンピュータ上に模することができるのかは、全く分からなかったけど、やってみたいと思いました。

でも、そこに立ちはだかるのは、数学でした。
なので、数学をはじめよう！ってなりました。

まずは、何から、はじめようかと思ったのですが、
線形代数なんて、ほんと、はじめてきいたって言葉なくらいなのですが、
いきなり、線形代数のことを少し調べて、どういうものかをぼんやりでいいから分かって、線形代数に入るための準備と思って、とりあえず線形代数についてわかったことを、
下記のようにまとめてみました。

■線形代数とは、線形な形をした式を取り扱うための手法だそうです。

・線形代数とは、行列の計算を扱う分野

・線形代数とは、行列を詳しく勉強する分野

・行列を使ってコンピュータで計算するためには、行列を管理する数学が必要

・行列に割り算は存在しない

・普通の数字の計算と、何が共通で何が違うかを知っておくことが大事

・行列というのは、数字をかけ算しているみたいに気楽に計算できない

・割り算はないけど、それに変わる演算として逆行列がある

・行列式が0ならば逆行列が存在しない

・連立方程式が解ける　⇆行列式は０ではない

・連立方程式が不定または不能⇆行列式は０

・行列を勉強する際に重要な概念として一次変換がある

・ある点を行列で別の点に移すことを一次変換という

・一次変換は点を変換するというより空間を変換する

・ax+byというような形の式を一次結合という

・一次変換で元々平面だったものが直線に変換されるのはどういう時かというと、
　行列式=0の時である。

・行列式が0ではない時→連立方程式は解が１通り存在し、
　一次変換は平面を平面に変換する

・行列式が０の時→連立方程式は解が無数に存在するか、または存在しないし、
　一次変換は平面を直線や点に変換する

・行列の逆行列を求める方法の一つを掃き出し法という

・掃き出し法と言うのは、四則演算だけで計算できるから、
　計算機にとっては簡単な手法

![suu.jpg](https://qiita-image-store.s3.amazonaws.com/0/131990/93afc9a0-2e31-4d56-3fc7-49143b6fca29.jpeg)

数学慣れしていない、文系の私だけど、来年は、数学頑張ろう！って思ってます。

読む本を読んで、数学アレルギーを解消したいなぁ。

あと、こんな講義のページも見つけたので、数学の基礎から学びなおそうと思います。
http://ocw.ouj.ac.jp/tv/1234030/
Azure まとめ(CSP, RemoteApp, Office365編)

#Azure CSPのライセンスについて

[Micorosft CSP(主にAzure/Office365/Dynamics365) & SPLAのライセンスパターン （2016/12月更新）](http://tech.exceedone.co.jp/microsoftazure/csp-azure-office365-dynamics365-spla-201612/)



#Azure CSP 購入時に最初にすることについて。(What to do first when purchasing Microsoft Azure CSP.)
[パスワードリセットの設定(Password reset setting.)](http://tech.exceedone.co.jp/microsoftazure/csp-passwordreset/)
[アカウントの新規追加(Add new account.)](http://tech.exceedone.co.jp/microsoftazure/csp-add-new-account/)


#Azure RemoteApp(リモートデスクトップ)
[Azure RemoteApp for Office365 ProPlus　Japanese (日本語) – インストール](http://tech.exceedone.co.jp/microsoftazure/office365-proplus-japanese-azue-remoteapp-install/)
[Azure RemoteApp for Office365 ProPlus　Japanese (日本語) – ファイル共有(Azure Files)](http://tech.exceedone.co.jp/microsoftazure/office365-proplus-japanese-azue-remoteapp-azurefiles/)
[Azure RemoteApp から XenApp “express” へ 　（Office365は使えるのか？)](http://tech.exceedone.co.jp/microsoftazure/azure-remoteapp-xenapp-express-office365/)
[Azure RemoteApp(IaaS) とOffice365 – Office 2016 ProPlusを仮想マシンで作成する](http://tech.exceedone.co.jp/microsoftazure/azure-remoteapp-iaas-office365-office-2016-proplus-virtualmachine/)
[Azure RemoteApp(IaaS) へiOSから接続する](http://tech.exceedone.co.jp/microsoftazure/azure-remoteappiaas-iaas-ios/)
[Azure RemoteApp(IaaS) とOffice365 – メニューの追加編集とメニューの重複](http://tech.exceedone.co.jp/microsoftazure/azure-remoteappiaas-office365-add-edit-menu/)
[Azure RemoteApp(IaaS) のライセンスアクティブ化](http://tech.exceedone.co.jp/microsoftazure/azure-remoteappiaas-licence-activate/)
[Azure RemoteApp(IaaS) のRD セッション ホスト サーバーの証明書](http://tech.exceedone.co.jp/microsoftazure/azure-remoteappiaas-rd-session-host-server-certificate/)
[Azure RemoteApp(IaaS) のRD Webでパスワード変更画面を提供する](http://tech.exceedone.co.jp/non-category/rd-web-password-reset/)
Nutanix基本のき: ストレージの概念と構造

# はじめに
この記事は、[Nutanix Advent Calendar 2016](http://www.adventar.org/calendars/1783) 12月18日の分として作成しました。本記事の内容はこの日付の情報に基づいています。

Nutanixのアーキテクチャを説明する際に、混乱しがちな項目の一つにストレージの概念があります。Nutanixではソフトウェア定義型のストレージを提供しており、従来のRAID技術を中心としたストレージアレイの考え方とは異なります。非常にシンプルでストレージ設計の労力がそれほどかからないのですが、やはり概念がわからないと混乱することもあります。
今回の記事では、Nutanixのストレージの概念と構造を解説します。

# ストレージの概念
Nutanixでは分散ストレージファブリックという名称でストレージサービスを提供しています。
分散ストレージファブリック内では、ストレージを「StoragePool」「Container」「vDisk」という3つの構造で管理しています。
これらはNutanix Bibleの[分散ストレージファブリック](http://nutanixbible.jp/#anchor-分散ストレージ-ファブリック-52)の節に解説されています。本項でも定義などはNutanixBibleより引用します。

## StoragePool
[Nutanix Bible](http://nutanixbible.jp/#anchor-データ-ストラクチャ-53)からStoragePoolの定義を引用します。
> 主な役割： 物理デバイスのグループ
説明： ストレージ プールは、クラスタのPCIe SSD、SSD、HDDデバイスを含む物理ストレージ デバイスのグループです。ストレージ プールは、複数のNutanixノードにまたがることができ、クラスタの拡大に合わせ拡張することができます。ほとんどの構成で単一のストレージ プールが使用されます。

Prismから表示したStoregePoolの一覧画面は下図のようになります。

<img width="1280" alt="StoragePool" src="https://qiita-image-store.s3.amazonaws.com/0/83432/383a4054-23dc-161b-f189-c2fbbca2ed7d.png">


いくつか混乱しやすいポイントを箇条書きでまとめます。


- StoragePoolはSSDやHDDなどのデバイスをひとまとめにして管理します。例えば上図では"DISKS"が"18"となっていますが、これはSSDとHDD合わせたディスクの本数が18本あるという意味です
- StoragePoolで表示されるストレージの容量は**物理容量**です。実効容量ではないので注意が必要です
- Nutanixのクラスターを拡張した際に単一のStoragePoolが設定されていた場合はStoragePoolも自動的に拡張します
- StoragePoolはNutanixのクラスターに対して1つが強い推奨です 

## Container
[Nutanix Bible](http://nutanixbible.jp/#anchor-データ-ストラクチャ-53)からContainerの定義を引用します。
>主な役割： VM/ファイルの集合
説明： コンテナは、ストレージ プールの論理的なセグメントであり、VMまたはファイル (vDisk) のグループを含みます。コンテナ レベルで複数の構成オプション（例えばRF）の利用が可能ですが、その適用は個別のVM/ファイル レベルになります。通常コンテナは、データストアと1対1の関係になります（NFS/SMBの場合）。

Prismから表示したContainerの一覧画面は下図のようになります。
<img width="1269" alt="ctr01.png" src="https://qiita-image-store.s3.amazonaws.com/0/83432/9cdc7d7e-9512-6381-6ac0-2a7c17999d9a.png">

これらのContainerをvSphere Web Clientから表示すると下図のようになります。

<img width="782" alt="ds01.png" src="https://qiita-image-store.s3.amazonaws.com/0/83432/5665668a-041b-5e1a-68e4-bb6275d09905.png">

いくつか混乱しやすいポイントを箇条書きでまとめます。

- ContainerはハイパーバイザーからはESXiではNFSのデータストア、Hyper-VではSMBのシェアとして認識されます
- Containerで管理される容量は実効容量です。データを2重書きするRF=2では、物理容量の約半分となります
- 一つのNutanixクラスターに対して複数のContainerを作成可能です。この場合は一つのStoragePoolが提供する容量を**複数のContainerで共有します**
- Nutanixのクラスターを拡張した際にはContainerも自動的に拡張します
- 重複排除、圧縮、Erasure CodingなどのストレージポリシーはContainer単位に設定することが可能です。

### 複数のContainerで物理ストレージ容量を共有する
Containerは従来型ストレージのVolumeとは異なり、容量が固定されていません。単一のStragePoolが提供する物理容量を複数のContainerで共有して消費します。

例えば、上図ではCTR01とCTR02という2つのContainerが設定されています。これらのContainerは同一のStoragePoolに紐づいています。StoragePoolの物理容量は11.09TiBですので、RF=2で実効容量が約半分になるとするとCTR01の5.54TiBがそれに相当します。しかし、CTR02の容量はこれよりも少ない5.39TiBとなっています。これはCTR01が158.48GiB使用されているのでその分がCTR02の容量から差し引かれているのです。

文章で書くと煩雑そうですが、ストレージ設計時のポイントは**「個々のContainerの容量設計を行う必要はなく、全体の容量だけを留意すれば良い」**ことです。

# 終わりに
Nutanixが提供するストレージの概念と構造をご紹介しました。この辺りは実際にPrismから設定してみると感覚が掴みやすいです。Nutanixでは無償で2時間クラウド上のNutanix Community Editionをお試しできる、[Nutanix Test Drive](https://www.nutanix.com/testdrive/)を提供しています。アカウント登録は必要なく、お名前やメールアドレスなどを入力いただくだけでお手軽に試用することが可能です。是非お試しください。
n秒後に1回実行、もしくは実行をキャンセル

#具体的にはこんなことをしたい時の処理
iosで長いローディングが始まってからn秒後に広告を出す
もしくはn秒以内にローディングがキャンセルされたら広告を出さない


isCancelフラグをもってdispatch_afterで分岐させようとしたがダメだった

うまくいいったソースは以下の通り

#実装(Objective-C)
```objc
static dispatch_source_t _timer;
static int N = 5;

//N秒後に１度だけ実行
-(void)hoge{
   //タイマーを生成
  _timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue());
  //イベントを設定
  dispatch_source_set_event_handler(_timer, ^{
    /********************
    N秒後に１度だけやりたいことをここに書く
    *******************/
    //一度実行したらキャンセル
    dispatch_source_cancel(_timer);
  });
  //開始時間を設定
  dispatch_time_t start = dispatch_time(DISPATCH_TIME_NOW, N * NSEC_PER_SEC);
  //タイマーをセット
  dispatch_source_set_timer(_timer, start, 100 * N * NSEC_PER_SEC, 0);
  //タイマーを実行
  dispatch_resume(_timer);
}

//N秒以内にこのメソッドを呼べば実行しない
-(void)cancelTimer{
  if(_timer) dispatch_source_cancel(_timer);
}
```


#さいごに
スニペットとかありそうな気がするけど見つからず...
もっと良い方法ありそう
あとそろそろswift覚えよ
Werckerでnpm-scriptsが実行できなくなったときは

@Quramy です。

「アドカレやろうぜ」とか言い出した割には書くネタが全く思い付かないので、少し前に [Wercker](https://app.wercker.com/) でドはまりした話を書きます。

Node.js でフロントエンドの開発をしていると、npm-scriptsにタスクを定義しておき、`npm test` や `npm run deploy` のように利用することは多いと思います。

```js:package.json
  "scripts": {
    "test": "mocha",
    "deploy": "webpack && gh-pages -d dist"
  },
  "devDependencies": {
    "gh-pages": "^0.12.0",
    "mocha": "^3.2.0",
    "webpack": "2.2.0-rc.1",
    ...
  },
```

`npm run` では、./node_modules/.bin にPATHが通るので、ローカルにnpm iした mockaやwebpackのコマンドが使えるというアレです。

折角定義したタスクはCIでも利用したいのが人情です。Wercker の場合、次のようにyamlの `script` 部分に指定するだけです。

```yaml:wercker.yml
box: node:6.9

test:
  steps:
    - npm-install

    - script:
      name: test
      code: npm test

deploy:
  steps:
    - script:
      name: deploy
      code: npm run deploy
```

ところが、上記yamlのように `test` と `deploy` というように複数のpipelineに分割していると、問題が発生します。
2つめ以降のpipelineでnpm-scriptsが正常に機能しないのです。

より正確には、npm-scriptsに記述している `webpack` のようなコマンドが正しく動きません。`ls -la node_modules/.bin` で確認してみると分かるのですが、node_modules/.bin配下のsymbolic linkが壊れてしまっているのです。

```
lrwxr-xr-x 1 root root 0 12 19 00:48 gh-pages
lrwxr-xr-x 1 root root 0 12 19 00:48 mocha
lrwxr-xr-x 1 root root 0 12 19 00:48 webpack
```

上記のような状態になります。各コマンドの実行権限は残っているので、音もなくreturn code 0で終了するという状態になります。

symlinkが正常な状態であれば /.bin配下から各パッケージのコマンドへlinkが参照できるはずです。

```
lrwxr-xr-x 1 root root 18 12 19 00:48 mocha -> ../mocha/bin/mocha
```

werckerでは、各pipelineの最後にstoreというstepが実行されます。store stepで、プロジェクトルート配下をまるごと一時的にコピーし、次のpipelineではコピーした内容を復旧してからユーザー定義のstepが開始されます。
Werckerは1つのpipelineにつき、1つのcontainer を起動するため、pipelineを分けると別containerでの実行となるため、このような機構があるのでしょう。そして (何故かは分かりませんが) werckerのstore/restoreの過程でsymlinksが破壊されてしまいます。


storeする際にsymlinkが破壊されるのであれば、それは復旧すれば良いじゃない、ということで werckerのstepを作ってみました。 [wacul/store-link](https://app.wercker.com/applications/5852ece0e4bd710100cb8677/tab/details/) 。


```yaml:wercker.yml
box: node:6.9

test:
  steps:
    - npm-install

    - script:
      name: test
      code: npm test
      
    - wacul/store-link:
      type: store
      prefix: node_modules/.bin

deploy:
  steps:
    - wacul/store-link:
      type: restore
      prefix: node_modules/.bin

    - script:
      name: deploy
      code: npm run deploy
```

指定したディレクトリのsymlink情報を引っこ抜いて保持しておき、restoreに再度 `ln -s` するstepです。上記のように、pipelineの最後にlinkをstoreし、他のpipelineの先頭でrestoreして使います。

よくよく考えたら、 `node_modules/.bin` であれば、`npm rebuild` を叩けば復旧できるんじゃないか、という事に気づいたのは、このstepを作ってしまってからです。
こいつの場合 `node_modules` に限らず、simlink全般に対して汎用的に使えるので、全くの無意味だったわけではないですが。

もし似たような問題で悩んでいる人がいたら、お試しください。それでは、また。
Javaがあまり好きでない素人プログラマがを「Javaプログラマであるかを見分ける10の質問」を解いてみた

# はじめに
私は過去の投稿からわかる通り普段はC++やRubyを使っています
そしてタイトルからわかる通り私は**あまりJavaがあまり好きではありません**
嫌いな理由はパッケージとか名前空間で長文になったりデザインパターンがわかりづらかった点でしょうか
C言語からオブジェクト指向言語を触った時の初めの抵抗もあるかもしれません
なのでPerlの方が性にあっていて今のRubyにつながっています(Perl風で書きやすいです)
そんな感じですが,Javaはたびたび触ったこともありますし,Javaで書かれたソースもよく読みます
**そんな自分がJavaをどれくらい理解できているのかテストしてみた**
テストに使ったページは下のサイトです
[Javaプログラマであるかを見分ける10の質問](http://d.hatena.ne.jp/shuji_w6e/20110305/1299288660)
#問題
1. ==演算子とequalsメソッドの違いは何か？
2. 文字列の+演算子による連結とStringBuilderを使った連結の違いを説明せよ。
3. List<Integer>のようにジェネリクス型を使う主たる目的は何か？
4. オブジェクトがガベージコレクション（GC）される主たる条件は何か？
5. チェック例外と非チェック例外の違いを型と例外処理の観点で説明せよ。
6. フィールドのアクセス修飾子をprivateにしgetter/setterメソッドを提供する事でフィールドを参照する設計方針を取る主な理由を説明せよ
7. NullPointerExceptionが発生するのは主にどういう状況か？
8. オーバーロードとオーバーライドの違いは何か？
9. コンストラクタとは何か？
10. インターフェイスを利用する目的を１つ説明せよ

#私の回答
1.
 「==」は**クラスが同一であるかの比較**,「equals」は**内部のデータ(Stringだと格納文字)が等しいかの比較**.
Rubyだと「==」はJavaの「equals」と基本同じ扱いですね
2.
「+」は**二つのStringクラスを組み合わせたStringを新しく作り返す**.
StringBuilderは伸び縮みが可能なクラスで**StringBuilderに連結すると自身に文字が拡張される**.
Rubyでいうところの非破壊的か破壊的かの違いみたいなイメージ
3.
**様々な型(クラス)で使えるようにするため**.
例えばintには対応しているけどfloatには対応していないというのは不便.
だからといって全てのクラスについて定義するのもよろしくない,そういった状況を解消する.
一応C++プログラマなのでこれは間違いないかと
4.
メモリマッピングしていったときに指定幅を越えたとき?**タイミングまでは知りません**
5.
 **チェック例外や非チェック例外は名前自体聞いたことがないのでわかりません**
6.
 **クラスに思わぬデータの使わせ方をさせたくないため**.
例えば文字数と格納文字を保持するMyStringクラスが会った時,文字数と格納文字を同時に書き込むとお互いのデータで整合性が取れないヒューマンエラーなどを引き起こす要因となりうる.
そこでsetterクラスを用いることによって文字を格納すると同時に文字列の長さを変更することで細かな操作をクラス利用者が意識しなくてよくなる.
7.
 **例えばNullを参照したとき**, `1+Null` を演算させたときなど.Rubyでもあるある.
8.
 オーバーロードは**引数の型や数の異なる同名のメソッドを同一クラス内に作ること**.オーバーライドは**親クラスから継承されたメソッドを上書きすること**.なにげに演算子の再定義はなぜオーバーロードなのかわからずに言ってったりする(私としてはオーバーライドの感覚が近い)
9.
 **クラスを作ったときの最初の処理**,主に初期化処理をする部分
10.
 **多重継承が許されないJavaにおいてインターフェース内のメソッドを親クラスなしに複数のクラスで共通化できる**
これによりポリモーフィズム設計に適する

#おわりに
Java好きじゃないといいつつなんだかんだ基本的な問題はいくつか解けました
でも,うわべだけの知識なのでおそらく結構間違っているでしょう
ここまで見てくださった親切なJavaプログラマさん,もし時間が空いていましたら採点コメントのほどよろしくお願いします
Jetson TK1にUbuntu Core 16.04をインストール

## モチベーション
Jetson TK1に用意されているLinux環境はUbuntu 14.04 LTSであり、あまりにも古すぎる。**CUDAをはじめとするNVIDIA GPUのうまみを失ってでも**16.04 LTSに変更し、Cortex A15クアッドのサーバー機として使えないか。

## 概要
Linux For TegraのrootfsディレクトリにUbuntu Core 16.04の内容を展開、SDカードブート形式で動作させた。不具合は検証中。

### 他のOSのインストール例
http://elinux.org/Jetson_TK1#Linux_distributions_running_on_Tegra
Jetson TK1に標準以外のOSをインストールする試みは何件か行われており、基本的には公式提供されているLinux For Tegraのrootfsディレクトリに別のディストリビューションのファイル群を展開するとうまくいくようだ。

### Ubuntu Coreの利用
https://www.ubuntu.com/core
Ubuntu Coreのarmhf(hard-float)用イメージファイルを、ここでは単なる最小構成のUbuntuとして扱う。収録内容が厳選されすぎてsudoやviすら入っておらず、もちろんUbuntuなのでrootは無効化されているという初心者には困った仕様ではある。
また、正規の方法でインストールすると作業途中で初期アカウントの通知があるとのことだが、今回の方法ではその通知がなく実際にアカウントも作成されない。

## 作業内容
作業はParallels上のUbuntu 14.04で行った。

### 配布ファイルの展開
``` sh
$ wget https://developer.nvidia.com/embedded/dlc/l4t-Jetson-TK1-Driver-Package-R21-5
$ sudo tar jxpf l4t-Jetson-TK1-Driver-Package-R21-5
$ cd Linux_for_Tegra/rootfs/
$ wget http://cdimage.ubuntu.com/ubuntu-base/releases/16.04/release/ubuntu-base-16.04-core-armhf.tar.gz
$ sudo tar xpf ubuntu-base-16.04-core-armhf.tar.gz
$ sudo mv ubuntu-base-16.04-core-armhf.tar.gz ../..
$ sudo rm README.txt
$ cd ..
$ sudo ./apply_binaries.sh
```

### SDカードブートのための変更
``` sh
$ cd Linux_for_Tegra/rootfs/boot/extlinux/
$ sudo cp jetson-tk1_extlinux.conf.sdcard extlinux.conf
```

### 書き込み前の初期設定
実機転送前にroot作業をしてしまう。ARMバイナリをx64環境で走らせるためQEMUをインストールし、ユーザーモードエミュレーションを利用する。
下準備後は以下の作業を行っている。

- sudoを使えるユーザubuntuの作成
- aptリポジトリの編集
- sudoそのものやvim, lessの導入
- ネット接続パッケージ導入 (net-tools, isc-dhcp-client, r8168-dkms)

``` sh
$ sudo apt-get install qemu-user-static
$ cd Linux_for_Tegra/rootfs/
$ sudo cp /usr/bin/qemu-arm-static usr/bin/
$ sudo mount chproc ./proc -t proc
$ sudo mount chsys ./sys -t sysfs
$ sudo cp /etc/resolv.conf ./etc/resolv.conf
$ sudo LC_ALL=C LANGUAGE=C LANG=C chroot .
# adduser ubuntu
# gpasswd -a ubuntu sudo
# vim /etc/apt/sources.list
# apt-get update
# apt-get install sudo vim less net-tools isc-dhcp-client
# apt-get install r8168-dkms
# exit
$ sudo reboot
```

### SDカードへ転送
SDカードを/dev/sdb1とする。

``` sh
$ sudo umount /dev/sdb1
$ sudo mkfs.ext4 /dev/sdb1
$ sudo mkdir -p /mnt/sdcard
$ sudo mount /dev/sdb1 /mnt/sdcard
$ cd Linux_for_Tegra/rootfs/
$ sudo cp -a * /mnt/sdcard
$ sync
$ sudo umount /dev/sdb1
```

### 実機をSDカードブートに変更
``` sh
$ cd Linux_for_Tegra
$ sudo ./flash.sh jetson-tk1 mmcblk1p1
```

### 実機でのネット接続操作
``` sh
$ sudo dhclient eth0
```
Lita にオウム返しをしてもらう

# 概要

Slack などのサービスに参加できるchat bot, lita に、オウム返しをしてもらうための機能を追加する

* Slack に参加している Lita に parrot handler を実装する

![動作イメージ](https://qiita-image-store.s3.amazonaws.com/0/7148/7b54fff6-805a-3e43-c482-baaefc1cf0d1.png)


# 前提

* git
* 開発環境で `lita` コマンドが使用できる( `gem install lita` 済み)
* Lita がSlack に参加済み
* lita-parrot の名前でGitHub にリポジトリを作成済み
* [Slack API Token](https://api.slack.com/docs/oauth-test-tokens) ( `xoxp-xxxxxxxxxx-xxxxxxxxxx-yyyyyyyyyyy-zzzzzzzzzz` ) を環境変数として参照できる

# 手順

大まかな手順としては :

* handler の初期化・作成
    * Slack API を叩くgem を依存関係として追記・利用
    * 入力された内容をそのまま返事として返すメソッドの定義
* lita 本体にこの機能を登録

## parrot handler プロジェクトの初期化

Lita に機能を追加するために、handler ( ≒ 振る舞い)を新規プロジェクトとして作成し、そこに実際の機能を記述していく

```sh
cd ~
lita handler parrot # => ~/lita-parrot ディレクトリにハンドラプロジェクトが作成される
cd lita-parrot

# git の初期化・最初のコミット
git init
git add .
git commit -m 'Initial commit'
```

### Slack API を叩くgem の使用

slack-ruby-client を利用する

**Note** :
入力された内容をただ返すだけでなく、送信相手の名前も加えて返答(通知)するように機能を追加したい

しかし、Lita が把握しているのは mention に使える名前ではなく、Slack の内部ID( ... `U00FEEE99` な形式)
...なので、そのID をもとに、なんとかして mention に使える名前に変換する必要がある

解決方法として、Slack API を利用する。Slack の内部IDをもとに問い合わせることで、mention に使える名前を得られる

#### ハンドラに「ID → mention 名」に変換するメソッドを定義する

```lib/lita/handlers/parrot.rb
require 'slack-ruby-client'

module Lita
  module Handlers
    class Parrot < Handler
      def find_user_name(user_id)
        ::Slack.configure do |config|
          config.token = ENV['SLACK_API_TOKEN']
        end

        client = ::Slack::Web::Client.new
        user_info = client.users_info(user: user_id)
        user_info.dig(:user, :name)
      end
    end
  end
end
```

##### 依存関係をgemspec ファイルに追記

slack-ruby-client gem を利用しているので、依存関係を明示する( `bundle install` を忘れずに)

```lita-parrot.gemspec
Gem::Specification.new do |spec|
  # spec....
  # ...
  spec.add_runtime_dependency 'slack-ruby-client'
end
```

### オウム返しメソッドの定義

```lib/lita/handlers/parrot.rb
require 'slack-ruby-client'

module Lita
  module Handlers
    class Parrot < Handler
      # 反応するワードの定義(echo, parrot)
      route(/echo/, :parrot)
      route(/parrot/, :parrot)

      def parrot(response)
        user_name = find_user_name(response.user&.id) rescue ''
        response.reply "@#{user_name} #{response.message.body}"
      end

      def find_user_name(user_id)
      # ...
      end
    end
  end
end
```

## lita 本体に組み込み

先程までの作業をGitHub に作成済みの lita-parrot リポジトリに commit & push する

その後 lita 本体のgem にこのhandler を追記する

```Gemfile
# ...
gem 'lita-parrot', git: 'https://github.com/gouf/lita-parrot'
```

( `bundle install` , git での commit & push, 本体の deploy も忘れずに)

# まとめ・注意点

Lita は adapter 機構により、さまざまなサービスに参加できるが、サービス固有の機能については それぞれのAPI に問い合わせる必要が出てくる

API の利用を簡単にしてくれるgem などを活用して、よりLita を活躍させてあげたい

# Links

* [slack-ruby/slack-ruby-client: A Ruby and command-line client for the Slack Web and Real Time Messaging APIs. - GitHub](https://github.com/slack-ruby/slack-ruby-client)
* [Plugin Authoring Guide - Lita.io](https://docs.lita.io/plugin-authoring/)
* [Create and regenerate API tokens – Slack Help Center](https://get.slack.help/hc/en-us/articles/215770388-Create-and-regenerate-API-tokens)
* [API Methods | Slack](https://api.slack.com/methods)
IntelliJIDEA でJSPにCSSを適用してみた

IntelliJIDEA でjspにCSSを適用する方法についていろいろ調べて苦戦していたが、
実際のjspのファイルの配置パスによってurlを指定するといいでしょう。
適用するのに成功したので、注意する点を以下でメモする。



![屏幕截图(11).png](https://qiita-image-store.s3.amazonaws.com/0/117741/d6166307-1667-c1ea-d1f9-48fa5f9fbada.png)


**（重要）IntelliJIDEAでのファイル構成は図の通り、cssファイルや、img素材ファイルをすべてWebコンテキストルートの下、 WEB-INFファイルの外に置く。なぜならば、/WEB-INFはWebアプリケーションの構成情報やクラスファイルなどを格納するためのディレクトリです。 
外部から直接アクセスすることはできません。(出典：https://teratail.com/questions/638)**




ご覧の通り、jspファイルは二つのところに置いてある。一つはweb-index.jsp,もう一つはweb-WEB-INF-jsp-....

1)webファイルの直下であるindex.jspにcssファイルを適用:urlを相対パスで指定

```qiita.rb
 <link href="css/style.css" rel="stylesheet" type="text/css" media="all">
```
2)WEB-INFの中にあるjspファイル群にcssファイルを適用:urlをルートからの絶対パスで指定


```qiita.rb
<link href="/docotsubu/css/style.css" rel="stylesheet" type="text/css" media="all">
```

[docotsubu]はproject名



適用後のページ↓↓↓↓↓↓↓


![屏幕截图(10).png](https://qiita-image-store.s3.amazonaws.com/0/117741/48b002a3-d3d2-589e-7b87-df7e23ff719f.png)


もし適用できなかったら、次の方法で調べよう。

ブラウザでjspファイルのコードを調べる。
![屏幕截图(12).png](https://qiita-image-store.s3.amazonaws.com/0/117741/515cb57c-ce9d-0540-f5e5-a4f54366e81e.png)
下線が引いているcssを指定するパスをクリックし、もしエラーになったら、ブラウザのアドレス欄でcssファイルのurlを調べてみよう。

```qiita.rb
localhost:8080/プロジェクト名/ルートからcssファイルまでのパス
```
になるはずだが、間違っているかどうかを調べよう。

次は正しく反映されたURLです。

![屏幕截图(14).png](https://qiita-image-store.s3.amazonaws.com/0/117741/49e42501-f3dc-b142-badc-70b34e2d9ee4.png)

以上で、IntelliJIDEA でjspにCSSを適用してみた。
Excelで書いたパラメータシートから、ネットワーク機器(Catalyst)のコンフィグを自動生成する

# 1. はじめに

[NetOpsCoding AdventCalendar2016](http://qiita.com/advent-calendar/2016/netopscoding)の18日目の記事です。

当方は某SIerにてお客様のネットワーク設計・構築したり、ネットワークの維持管理をしていたりします。

構築の際に作る資料としてExcelで書かれたパラメータシートなるものがあります。
よくあるのはこんな感じの設定項目ごとにパラメータが記載されている資料です。

![sample.jpg](https://qiita-image-store.s3.amazonaws.com/0/38761/162b5a09-a8f6-082a-db40-2cea27788079.jpeg)

このパラメータシートを基にネットワーク機器のコンフィグを作成、機器に設定します。

しかし数十~数百台のスイッチに設定を入れる場合、スイッチの設定をしつつ、
パラメータシートがちゃんと更新するというのは結構神経がすり減る作業です。

納品前のレビューで上司に「ここコンフィグとパラメータシートの値違うけど（またかよこいつ :anger: ）」と指摘されないようにするには、パラメータシートからコンフィグを生成すればいいんじゃね？ということで今回の記事を書くことになりました[^1]。

NetOpsCodingか？というのはありますが、ソフトウェアでのNW機器の設定効率化ってことで…。

[^1]: パラメータシートからコンフィグを生成することを己に義務付けないとしないと結局一緒ですけどね

なおすべてのパラメータに対してコンフィグが生成できるようにするようには間に合わなかったため、プログラムは未完成です:fearful:[^2] 。[githubのレポジトリはこちらになります。](https://github.com/tossh0095/pyxl2nwcfg)

[^2]: 基本設定しか生成できません

# 2. 使った道具

使った道具・環境は下記の通りです。

|Software|Version|
|:-:|:-:|
|OS|Windows 10|
| Excel|Excel 2013|
|Python|3.5.1|
|openpyxl|2.4.1|
|jinja2|2.8|

Excelファイルは下記のリンクのものを例として使います。

[excelファイル](https://github.com/tossh0095/pyxl2nwcfg/blob/master/sample_conf.xlsx?raw=true)

スイッチはCatalyst2960-8TC-L(IOS 15.0(2)SE8)を使っています。

コンフィグ生成はExcelのマクロだけでできなくはないのですが、最近読んでる[python本](https://www.nostarch.com/automatestuff)[^3]にopenpyxlというpythonからexcelを操作するライブラリがあるというのを知ったので勉強がてら、使うことにしました。

[^3]: オライリーさんから翻訳出るらしいです

将来的にはCatalyst以外の機器もサポートするため、テンプレートエンジンのjinja2を使って生成元となるデフォルトコンフィグを分けておきます。


# 3. 使い方

```txt
# python pyxl2nwcfg.py sample_conf.xlsx
```

でsample_conf.xlsxのxlsxファイルをsample_conf.txtの名前のコンフィグを生成します。

# 4. プログラムの構造

```text
------ pyxl2nwcfg.py
   +-- template ------ c2960-8tc-l.template.txt
   |               +-- etc
   +-- lib ----------- gennwconf.py
                   +-- pyxl2catalystcfg.py
```

pyxl2nwcfg.pyでは下記のように処理します。

1.excelファイルの読み込み
2.lib配下にある利用するジェネレータの選出
3.コンフィグの出力

gennwconf.pyでは将来的に機種によって利用するコンフィグ生成器を分けます。

pyxl2catalystcfg.pyでは

1.templateファイルを読み込み
2.xlsxの内容を解析
3.templateエンジンにrenderし、文字列を返す

といった処理をします。

# 5. まとめ

書いてみて気づきましたが、めちゃくちゃ課題があります。

1.Excelの形式が崩れるとすべて書き直しになる。->スクレイピングしやすいようにExcelの設計が必要
2.新しい設計項目、機種に対応するにはどうするか

プログラム自体については引数チェックや例外処理を全然書いていないので、ブラッシュアップが必要です。

まだまだ育てていく必要がある感じなので、アドバイスあればお願いします[^4]。

[^4]: そもそも未完成ですけどね・・・
Flash がなくてもツイキャスが見たい！

# JKのライブ配信事情

Twitter が Periscope 提携によるライブ配信を始めましたが、[ツイキャス](http://twitcasting.tv)の需要は未だ高いままですね。
特にティーンズ層にリーチしたいときは、LINE Live とツイキャスが2強を作っている状況ではないでしょうか。

2018.8.20 追記： 最近は TikTok が強いですね。こいつは Android/iOS がないとお手上げです。

# 目標
というのは前置きで、真面目な話はここまでです。
理由はどうあれ、ツイキャスが見たいのです。
閲覧のみできればよく、ライブはしません。

# 課題
しかし、手元にあるのは Ubuntu 16.04 上の Firefox 50.0.2 なのです。

**Flashがありません。**

## 信念
技術的には Flash が動かせるのは知っています。
Google Chrome をインストールしたり、Chromium をもごもごしたりすればよいのです。
Firefox でも、 wine と連携して何とかなるモノ(名前は忘れましたが)があったはずです。

でも、断固 Flash は動かしたくないのです。
奴等は Linux サポートを打ち切ったのですから。
今更、ヘコヘコしてまで Flash を使う義理はありません。

そう、我々には HTML5 の時代に相応しい方法があるはずなのです！

/*
つまらぬことを書きましたが、Flash はなんだかんだ脆弱性が多いとか、
オープンソースじゃないとか、Linux 上で動かしたくない理由はいくらでもあります。
*/

## 方針
手持ちの Android デバイスでツイキャスを開いたところ、
普通に HTML5 の video エレメントっぽいモノが表示されていました。
→ユーザーエージェントを偽装すれば良さそう

## アドオン？知らんなあ……
ツイキャスのためだけに新しいアドオンを入れるのもアレなので、
Firefox 標準搭載の機能を使いましょう。

## レスポンシブデザインモード
`Ctrl-Shift-M` でレスポンシブデザインモードを呼び出します。
Mac の人は `Command-Option-M` だそうです。KEINOS様ありがとうございます。

当然このままでは何も起こりません。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/116845/c130dc40-ae60-e8ce-a835-b127e9266a65.png)


右上の `Custom User Agent` に適当な Android っぽいユーザーエージェント文字列を入力します。
ここでは 
```Mozilla/5.0 (Linux; Android 4.1.1; Nexus 7 Build/JRO03S) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166 Safari/535.19```
を使いました。

よく見てみたらこれ Gecko じゃありませんが、問題なさそうです。

テキストボックスからフォーカスを外すと、自動的にページがリロードされて……

# 問題
![image.png](https://qiita-image-store.s3.amazonaws.com/0/116845/4e9a8b6e-3360-da9d-c744-774afa6bfd79.png)
＿人人人人人人人人人人人人人人人人人人人人人人人＿
＞　Video format or MIME type is not supported.　＜
￣Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y￣

フォーマットがないと言われたら、もうあの方に頼るしかありません。

## ♪赤いコーンの～
![Screenshot from 2016-12-19 00-46-07.png](https://qiita-image-store.s3.amazonaws.com/0/116845/6dd4a3fc-4b37-c851-1e31-6423201ecee4.png)
件の video エレメントのコンテキストメニューで `View Video` を選択すると、ダウンロードのダイアログが出ます。
ここで VLC を使って開くことを選択して OK すると、

# 解決
無事 VLC のインスタンスが立ち上がり、ライブを視聴できるようになりました。
ただし、ライブ終了時に自動的に次のライブに遷移することはできないようなので、そこは手動で行う必要があります。

(Ubuntu 標準搭載の Videos で同じことができるかどうかは確認していません)

この方法でライブを聞きながらツイキャスの他のページをいじれるようになったので、かなり重宝しています。
クライアント側で自前のSymmetric Keyを使ってAzure Storage BLOBを暗号化／複合化してみる

# はじめに
はじめまして、１９日目担当のネクストスケープ配信部の小泉です。
配信に居ながら、配信とはあまり関係ない記事を書こうと思います。。。

今回は、Azureを使っている方なら皆知っている機能であろう、StorageのBLOBで使えるクライアント暗号化機能について紹介していきます。

# Azure Storage Clientで暗号化／複合化するメリット
配信部では動画や楽曲といったコンテンツを取り扱う機会が多く、クライアント様によってはコンテンツホルダーから「ファイルを暗号化してクラウド上に保存すること」という規約があったりする場合もあるので、ファイル暗号化してアップロードするという順序で行っていました。

どうしても処理する過程で、暗号化する処理ロジックを書いたり、暗号化したファイルをローカルにテンポラリ保存したり、ファイルを操作する際の例外処理を書いたり、色々面倒なことをする必要がありました。

それが、Azure Storage Client側で行うことが出来るようになったのです！

# なぜ"自前の" Symmetric Key で暗号化／複合化してみる
Key Vaultを使ったチュートリアルは、Azureのドキュメントに書かれていますが、自前の"Symmetric Key"を使ったチュートリアルやサンプルのコードが見つからず。

以前からAES暗号化をしていたので、以前と同等の暗号化でファイルを暗号化しながらファイルをアップロードしたかったのです・・・

# やってみた
必要なもの
まずは、nugetから下記のライブラリを入れます。

- Microsoft.WindowsAzure.Storage
- Microsoft.Azure.KeyVault
- Microsoft.Azure.KeyVault.Extensions

特にExtensionsが無いとSymmetric Keyが使えないという罠があるので注意。

```
static void Main(string[] args)
{
    var storageAccount = new CloudStorageAccount(new StorageCredentials("{Storage Account}", "{Storageキー}true);
    var blobClient = storageAccount.CreateCloudBlobClient();
    var blobContainer = blobClient.GetContainerReference("container");
    var blob = blobContainer.GetBlockBlobReference("hello.txt");

    // 暗号化キーの設定（AES128bit）
    byte[] encryptkey = Convert.FromBase64String("gsef2ugs+w1MKrfe848Iesq=="); // Testキー
    SymmetricKey key = new SymmetricKey("TestKey", encryptkey);

    // 暗号化ポリシーの設定
    BlobEncryptionPolicy policy = new BlobEncryptionPolicy(key, null);
    BlobRequestOptions options = new BlobRequestOptions() { EncryptionPolicy = policy };

    // 暗号化しながらアップロード
    blob.UploadText("hello world!!", Encoding.UTF8, null, options, null); // <- お馴染みの文言付けてみましょう。

    // 復号化しながらダウンロード
    string decryptText = blob.DownloadText(Encoding.UTF8, null, options, null);
    Console.WriteLine("DecryptText: {0}", decryptText);
    // DecryptText: hello world!! <- ちゃんと複合されて読めますね。

    // 復号化しないでダウンロード
    string nondecryptText = blob.DownloadText(Encoding.UTF8, null, null, null);
    Console.WriteLine("NonDecryptText: {0}", nondecryptText);
    // NonDecryptText: Q??2@H?,p?????|?　<- 複合出来ずに化けてます。
}
```
これだけで暗号化しながらアップロード／複合化しながらダウンロードすることが出来るようになりました。
面倒なローカルでテンポラリファイルを作り、暗号化するなんていう面倒な作業が不要になります。

# 気を付けたいこと
Azure Storage側で暗号化している訳ではなく、クライアント側で暗号化しています。
そのため、マシンスペックにもよりますが、非暗号化のアップロードよりも当然アップロード速度が遅くなることが考えられます。
実装する際には、十分な検証を行ってから入れましょう。。。

# さいごに
かなり無駄な処理を省くことが出来るようになったので、個人的には嬉しい機能だなと感じました。
やはり、楽をしたいですよね。（少なくとも私はそうです。。。）
今回はBLOBに限って書きましたが、Queue、Tableについても同様に暗号化が出来る様なので、セキュアに守りたい内容を送る場合には一考にいれるのもありかなと思います。

# 参考
[チュートリアル: Azure Key Vault を使用した Microsoft Azure Storage 内の BLOB の暗号化と復号化](https://docs.microsoft.com/ja-jp/azure/storage/storage-encrypt-decrypt-blobs-key-vault "チュートリアル: Azure Key Vault を使用した Microsoft Azure Storage 内の BLOB の暗号化と復号化")
[Microsoft Azure Storage のクライアント側の暗号化と Azure Key Vault](Microsoft Azure Storage のクライアント側の暗号化と Azure Key Vault "Microsoft Azure Storage のクライアント側の暗号化と Azure Key Vault")
node-http-proxy-agentを使ってgulp-webserverのproxiesでProxyを越えて接続する

下記みたいに、gulp-webserverのproxiesオプションを使うと、
とある/hogeというリクエストを別サーバのhttp://fuga.com/fuga にプロキシすることができます。

```js:gulpfile.js
var gulp = require('gulp');
var webserver = require('gulp-webserver');

gulp.task('webserver', function() {
  gulp.src('app')
  .pipe(webserver({
    proxies: [ {
      source: '/hoge',
      target: 'http://fuga.com/fuga'
    } ]
  }));
});
```

ここで、このhttp://fuga.com/fuga がProxyを越えて接続しないといけない場合についての接続方法について紹介します。
（例えば、APIサーバがAWS上にあるとか）

# node-http-proxy-agent

node-http-proxy-agentというnpmモジュールを使うことでProxyを越えてgulp-webserverのproxies先に接続することができます。

```js:gulpfile.js
var gulp = require('gulp');
var webserver = require('gulp-webserver');
var HttpProxyAgent = require('http-proxy-agent');

gulp.task('webserver', function() {
  gulp.src('app')
  .pipe(webserver({
    proxies: [ {
      source: '/hoge',
      target: 'http://fuga.com/fuga',
      options: {
        agent: new HttpProxyAgent(process.env.https_proxy)
      }
    } ]
  }));
});
```
Xcode8から画像付きUIButtonのレイアウト変更はSize Inspector

## Xcode7まではAttributes Inspector

xcode7まで<strong>Attributes Inspector</strong>にてEdgeを調整します。

参考：画像付きUIButtonのレイアウトを変更する
http://qiita.com/exilias/items/7867a4cb6afe85084b8e

## xcode8から設定場所がSize Inspector

xcode8からは<strong>Size Inspector</strong>で設定するように変わっているようです。

<img width="301" alt="スクリーンショット 2016-12-19 0.36.11.png" src="https://qiita-image-store.s3.amazonaws.com/0/111366/a3b1568a-21d8-29f6-8a12-817440d4a685.png">

## 参考
http://stackoverflow.com/questions/40458915/no-uibutton-edge-option-in-xcode-8
Debian8 jessie のbind9でipv6を無効化

ipv6を使わないので無効にしようと思い、幾つかサイトを見ると`/etc/default/bind9`の`OPTIONS="-f -u bind"`に`-4` を追加して`OPTIONS="-f -u bind -4"`にする手順が書かれているが、そのように設定してもダメ。
要するに`/etc/default/bind9`が効かない。
こうやったらできた

* `/etc/systemd/system/bind9.service`が無いことを確認。#既に有ればそれを編集すれば良いと思う。
* `# cp /lib/systemd/system/bind9.service /etc/systemd/system/bind9.service`でファイルを作成。
* `/etc/systemd/system/bind9.service`の内容は

```
[Unit]
Description=BIND Domain Name Server
Documentation=man:named(8)
After=network.target

[Service]
ExecStart=/usr/sbin/named -f -u bind
ExecReload=/usr/sbin/rndc reload
ExecStop=/usr/sbin/rndc stop

[Install]
WantedBy=multi-user.target
```
となっているはずなので、ExecStartを書き換える。

```diff
--- /lib/systemd/system/bind9.service   2016-11-02 02:41:51.000000000 +0900
+++ /etc/systemd/system/bind9.service   2016-12-18 22:06:27.551045089 +0900
@@ -4,7 +4,7 @@
 After=network.target
 
 [Service]
-ExecStart=/usr/sbin/named -f -u bind
+ExecStart=/usr/sbin/named -f -u bind -4
 ExecReload=/usr/sbin/rndc reload
 ExecStop=/usr/sbin/rndc stop
 ```
* `# systemctl reenable bind9` で設定反映
* `# systemctl restart bind9` で再起動（~~もちろん`# /etc/init.d/bind9 restart`でもいい~~ と思っていたが、本当はダメらしい）

これで、`/var/log/syslog`に出ていた`named[13161]: error (network unreachable) resolving 'pipe.skype.com/AAAA/IN': 2620:0:37:`の様にipv6で名前解決をやろうとして失敗するログが無くなった。

参考サイト
https://wiki.debian.org/Bind9#Bind_Chroot
 
追記：
要するに、`init`じゃなくて`systemd`に変わったって事なんですよね。
Debian久しぶりに触ったから知らなかった...

---
ちなみに環境
HW:PriusGear GN33k （10年以上前に買ったノートPC）
使っていないノートPCが有ったので、自宅サーバ用にセットアップ。Ubuntu入れようと思ったのですが、CPUが対応していなかった...。なのでDebianで。
サーバ用途なのでX入れてません。
$ uname -a
Linux prius 3.16.0-4-586 #1 Debian 3.16.36-1+deb8u2 (2016-10-19) i686 GNU/Linux
Spring Boot 1.4以降でStatus Codeに 200 OK (Reason Phrase) を出力する。

# 経緯

先日Spring BootでAPIを作成していた際に、呼び出し側から
「お前のところのAPIどうやって叩いても正常なレスポンスを返さない」
と連絡を受けました。
こちらではHttp Status に200を返しているログも残っているしネットワークの問題かしらん？と思い詳しい話を聞いてみると
「Http Status Codeの200 OKの"OK"が出力されていないから正常じゃない！」
とのことでした。

# RFC的にはどうなっているか

RFC 7230
https://tools.ietf.org/html/rfc7230#section-3.1.2

A client SHOULD ignore the reason-phrase content.

クライアントはreason-phrase(OKの部分)を無視すべきと記載があるのですが。。。
でも、呼び出し側は社会的信用の高いところなので、こちらが折れるしかないですね！

# 原因調査

Spring Boot 1.4.0: HTTP Status Issue
https://github.com/spring-projects/spring-boot/issues/6548

SpringのIssueを見てみると、Spring Boot 1.4からTomcatを8.5系に上げたのが原因だけどTomcatの問題(?)だからSpring側ではどうしょもないよ。とのこと

missing reason phrase in tomcat 8.5.x
https://bz.apache.org/bugzilla/show_bug.cgi?id=60183

Tomcatの開発チームも、RFC7230でも無視してって書いてあるし無駄だから8.5でなくしたよ。
と修正するつもりは無さそうです。

# 対応

Tomcatのソースコードを読んで自分でなんとかする事にしました。

調査の結果org.apache.coyote.http11.ConstantsにStatus Codeの文字列が定義されいる事がわかりました。
Class loadingの順番を変えて定義されている内容を置き換える事も検討しましたが、
バージョンアップの事を考えると単純なclass置き換えは不安が残ります。
(この対応を忘れてバージョンアップして問題あるけど動くには動くみたいな状況は危険です。)

幸いStatus Codeは定数として定義されていたため、必要な箇所だけSpring起動時にリフレクションで書き換える事にしました。
ただし、対象がfinalなフィールドだったため、リフレクションでも簡単には変更する事はできませんでした。
そのあたりのナレッジは[別記事](http://qiita.com/5at00001040/items/83bd7ea85d0f545ae7c3)として投稿しています。

# サンプルコード

```java:SpringBootApplication.java
@SpringBootApplication
public class SpringBootApplication {

    public static void main(String[] args) throws Exception {

        Field statusBytes200 = org.apache.coyote.http11.Constants.class.getDeclaredField("_200_BYTES");
        byte[] _200_OK = "200 OK".getBytes();

        Field modifiersField = Field.class.getDeclaredField("modifiers");
        modifiersField.setAccessible(true);
        modifiersField.setInt(statusBytes200, statusBytes200.getModifiers() & ~Modifier.FINAL);
        statusBytes200.set(null, _200_OK);

        SpringApplication.run(SpringBootApplication.class, args);
    }
}
```