読者です 読者をやめる 読者になる 読者になる

phperがgolang書いてて調べたこと

golang php

配列のループ

<?php

foreach ($items as $index => $item) {

}
for index, item := range items {

}

まぁ違和感はない。

package

Goji使ってサーバー書いてると、コントローラーやモデルをpackage分割したくなる。例えば以下のようなディレクトリ構造にしたい。

app.go
controllers/
    helpers/
        helper.go
    user_controller.go
    item_controller.go
models/
    user.go
    item.go

この時、packageをPHPでいうところのclassと捉えるとうまくいかない。 例えば、

package user

type User struct {
    Id   string,
    Name string,
}

と定義した場合、user.goファイルは以下に設置しないといけなくて冗長になる。

models/
    user/
        user.go

さらに、import時も以下のように冗長になる。

import(
    "github.com/hatajoe/json-server/models/user"
)

なので、packageはnamespaceと捉えると良いかもしれない。

package models

type User struct {
    Id   string,
    Name string,
}
models/
    user.go

models/item.goは、

package models

type Item struct {
    Id   string
    Name string
}

となる。importは

import (
    "github.com/hatajoe/json-server/models"
)

だけでmodels以下のstructを参照出来るようになる。

尚、同じパッケージ内ならファイルが分割されていようとも相互に参照出来る。全て1つのファイルに宣言されていると思って構わない。 これを利用して、同パッケージ間で共通して利用するルーチンはmodels/common.goみたいに分けて使うと便利。 ちなみに、同パッケージ内で同じ名前の関数やグローバル変数は宣言出来ない。(型が違えば出来ても良いと思うんだけどなー。)

func Register(uuid string) error {

}

// 以下は引数が違うけど名前が同じなので宣言出来ない。
//func Register(uuid string, name string) error {
//}

また、ネストしたディレクトリの場合は、そのファイルが所属するディレクトリの名前をpackage名とするみたい。

app/
    controllers/
        helpers/
            helper.go
package helpers

import(
    "net/http"
)

func GetUUID(r *http.Request) string {
    return r.Header.Get("UUID")
}

importする場合は、

package controllers

import(
    "github.com/hatajoe/json-server/controllers/helpers"
)

気がついたかわからないけれど、自作packageをimportする時に、github.com/hatajoe/json-server/...としてる。 実は、以下のように相対パスでもimport出来る。

package controllers

import(
    "./helpers"
)

しかしこうすると、go test時にパッケージ依存が解決出来ずテストが出来なかった。(参考 http://qiita.com/shiwork/items/a213b1af2da7f7f8ea22#整理)

$GOPATH配下に存在するプロジェクトの場合は相対指定だとダメらしい。 プロジェクトを$GOPATH以下に置くかどうかをチームで共有しておかないと$GOPATH以下にシンボリックリンクを貼るハメになる人が現れる。(逆にシンボリックリンクで解決出来るっちゃ出来る)

エラーハンドリング

1つの関数内でエラー処理をたくさんする場合、

func ComplexFunc() error {
    err := hoge()
    if err != nil { // 型推論してる
        // error
    }
 
    err = fuga()
    if err != nil { // 上で型が決定してるので型推論できない
        // error
    }
 
    v, err := foo() // vの型推論をしてる。が、errをしてるようにも見えちゃう。ややこしい。
    if err != nil {
        // error
    }
 
    log.Println(v)
 
    return nil
}

同じ変数名err型推論は同じスコープ内で一度しか出来ない。んだけど、複数の戻り値を受け取る際、片方の型が決定していなければ型推論出来る。ように見える。これは、以下のようにif文のスコープを利用するとうまく出来る。

func ComplexFunc() error {
    if err := hoge(); err != nil { // errはこのif文ブロック内がスコープとなる
        // error
    }
 
    if err := fuga(); err != nil { // 綺麗に書ける
        // error
    }
 
    v, err := foo() // 逆にここはvをif文スコープ内に入れるわけにはいかないのでこのままとなる
    if err != nil {
        // error
    }
 
    log.Println(v)
 
    return nil
}

if文のスコープ。面白い。 じゃあ複数の値を返す関数を2つ以上使ってる場合はどうするの、ってなるけど、その場合は予めvar err errorを宣言しとくとかなのかな。

抽象化

モデルには大抵プライマリキーでデータを取得する以下のような関数がある。

<?php

class User extends BaseModel
{
    protected $table = "user";
    
    public static function findById($id)
    {
        return DB::where("id", $id)->get()->first();
    }
}

これは、BaseModelに宣言すれば良いじゃない。

<?php

class BaseModel extends Eloquent
{
    protected $table;
    
    public static function findById($id)
    {
        return DB::where("id", $id)->get()->first();
    }
}

こんな感じに書けたと思う。 goだと型の都合上これが出来ない。そもそも継承もない。

僕はシンプルにテーブル構造からモデルクラスを自動生成するツールを書いて対応してる。 長らくPHPとか書いてるとなんとか共通化したくなる部分だと思う。多分方法はいくつかあるんだろうけど、あまり複雑なことはしたくなかった。 簡単に出来る方法があるなら教えて欲しいです。

困ったとき

  • godoc
    • 関数リファレンス頼れる
  • github
    • READMEを読む
    • examplesがあれば読む
    • testを読む

とにかく英語多い。それが辛い・・・!

# React.jsをちょっとだけ調べたので残しとく

JavaScript React.js

うちの奥さんが珍しく子どもと出かけたのでこのチャンスを利用して話題のReact.jsを調べてみた。 前に pocket に突っ込んでいた記事を手がかりに開始。

上記記事によると、今から学ぶには以下が良いそうなので、素直に読む。

まだ1行もコード書いてないけど、把握したものを残します。

Component

React.jsは、コンポーネントと呼ばれる単位でオブジェクトを実装する。

  • 以下のサンプルコードの var CommentBoxコンポーネント
  • コンポーネントは、必ず1つの <div> を戻り値として返す。
  • ネストした <div> ならOK
  • JSの中に普通にHTMLが記述されているように見えるが、これはJSX
  • ようするにこのコードはコンパイルしないと動かない(JSXを使わない書き方も出来るがかなり冗長なので微妙な気がした)
  • 以下のサンプルコードだと、React.render で、 #contentコンポーネントが描画される。
  • コンポーネントはDOMの様に見えるけどこれは仮想的なもので、JSがメモリ上にDOMツリーを持っていて React.render するまで描画はされない。
  • 変化したDOMだけを再描画出来るためハイパフォーマンス。これはReactが勝手にやってくれる。
  • これらのコンポーネントを組み合わせてページを構築していく
  • とても再利用性が高い仕組み。ただし設計をミスると今よりつらいかもしれない。
// http://facebook.github.io/react/docs/tutorial.html
var CommentBox = React.createClass({
  render: function() {
    return (
      <div className="commentBox">
        Hello, world! I am a CommentBox.
      </div>
    );
  }
});
React.render(
  <CommentBox />,
  document.getElementById('content')
);

PropとState

Propとは、Componentに外から渡せるImmutableなデータ。 サーバーから取得したJSONデータだと思っていいと思う。

Stateとはその逆で、Component自身が管理しているMutableなデータ。 フォームへのユーザー入力などが該当すると思う。

これらはどちらも直接変更することは出来ない。変更は、setProp, setState replaceProp, replaceState メソッドを使う。 上記メソッドを呼び出した場合、コンポーネントは再描画される。 つまり、これによりDOMと仮想DOMのデータ整合性を取っているんだろうと思う。

Immutableと言いつつPropには変更を許容するI/Fが定義されている。 これはちょっと納得行ってない。まぁコンポーネント内で、

  • これはCompornent管理だから変えてもOK
  • これは外からもらったものだから変えちゃダメ

という風にわかりやすいのは良いことだと思った。

コンポーネント間のやりとり

こっちのコンポーネントでの操作をトリガーし、あっちのコンポーネントでフックする、という話。 これは、コンポーネント間で親子関係を作っておいて、

  • 子のイベントを親がフックして別の子へ
  • 親でStateを管理し、子のPropとして使う

みたいな感じらしい。わかりやすくて良い。

その他

などなど色々ある。理由は後述するが調査はここまでとした。

調べてみて

調査前の印象として、HTMLとJSの密結合って実際どうなんだ、というのがあった。ただ実際はコンポーネントという再利用性の高い仕組みによってDRYが実現可能で、より見通しの良いコードになるなーという印象に変わった。これは良い。

ただこう来ると、CSSコンポーネントに含めてしまいたくなった。 それについて少し調べてみると、以下の記事が見つかった。

CSSをComponentのPropとして定義出来るようにすればいいじゃん!的な内容だった。将来的には含まれるかもしれない。そうなったら本格的に触ってみようという気持ちになり、調査はここまで。 楽しかった。

おまけ

調査の過程をTwitterでつぶやいてたので貼っとく。

composerで自作ライブラリをインストールしたくて

php composer

したくて。

共通の処理ってあるじゃないですか。 Webアプリケーションの場合大抵のロジックはモデルに集約されていると思うんですけど、モデル間で共通のロジックってのはやっぱりあって。

ただ、多くのWebアプリケーションフレームワークって、一応ディレクトリ構造が決まっていて、大体こういった共通の処理を抜き出して置いておくいい感じのところが無いんですよね。 だからなんかルートディレクトリに Library とかディレクトリ作って云々... これがもうめちゃ微妙で、気づいたら Library 以下のソースにプロジェクト依存したコードが紛れてやれやれって感じに仕上がる。 なので、composer使いたくなる。 で、自作のライブラリをcomposerでインストールするのに3時間くらいハマったのでイライラしながらこれを書いてる。

結論から言うと、composerでライブラリをインストールするには以下の手順が必要になる。

後述と書いておきながらいきなりPackagistの話する。 結局は、Packagistに登録しなくてもうまくやる方法はあるらしい。 ただ、今回はちょっと調べきる時間が無かった(こんなものを書くくらいなら調べればいいんだけどもうちょっとどうでも良くなってきてる)。 composerのautoloaderの仕組みを良くわかっていないという点なんだと思うけど、Packagistに登録していない段階ではautoloadされず使えなかった。(ちなみにWAFはLaravel) これに数時間悩み、なんでやねんってなってたけど、Packagistに登録するとすんなり行けた。(vender/composer/autoload...にうまく追加された。ソース読んでないので理由はわからない。) ...まぁ取り敢えず目的は果たせたし、また思い立った時にソース読む。

で、意図せず自作ライブラリを公開してしまったわけだけど、これはこれでなんというかなかなか良い体験だった。というと素晴らしいライブラリが公開されたかのようだけど、内容はどうでも良くて(実際、メソッドは2つしかないしゴミみたいなライブラリで、、)

  • 共通処理を抜き出す試み
  • ドキュメントを正しいのかどうかもわからないけ英語で書いてみるチャレンジ
  • ゴミみたいなライブラリでもcomposerで自作ライブラリがインストールされる様を見るとちょっと嬉しい

こういったものが体験出来た。 ちなみにリポジトリは以下。(ホントは見せるのも恥ずい。。んだけどまぁいいや。。) https://github.com/hatajoe/php-easy-lottery

まぁ取り敢えず、ゴミだろうがなんだろうが、今後も作ったものは表に出して行くという行為をしてみようかなと思った。

如何にしてスクラムを組むに至ったか

GitHub スクラム

プログラマタスクの進捗管理って難しいじゃないですか。 ずーっと難しいなーって感じで特に何もしてこなかったので、何かこう出来ることは無いかと考えていて。 すると、進捗管理の難しさってのは、言ってしまえば以下の2点が問題だという結論に至った。

  • 工数見積が甘い
  • 個々人の能力が把握できていない

つまり、妥当性を欠いた工数上で能力不一致な人員アサインが行われ、結果、遅延する。 しかし、正確無比な工数見積や、個々人の能力把握は不可能だと思われるので、悩ましいなーと。

そこで、取り敢えず、基準値があっての実績値だと思った僕は、工数、能力の両側面における基準値とはなんぞやと考えた。 組織内で個々人の能力を基準にすることは割りと難しいので、工数というものを基準に出来ないかと考えた。工数、すなわち時間は誰にとっても同じはずなので、基準になり得るなーと。

ただ、例えばある機能があるとして、

  • Aさんは8hで見積もって7hで終わらせた
  • Bさんは4hで見積もって6hで終わらせた

みたいなことが往々にしてあって、工数を基準にするにしても人それぞれみたいな感じになってなんだかなーって感じがあった。

ただよく考えてみると、AさんとBさんは見積もり時に倍近くあったものの、実績値としては1hくらいの差であると。これは都合の良い例なんだけど、要するに、見積もり時にAさんが懸念していた点、あるいはBさんが軽視していた点をマージ出来たら、AさんBさんによってその機能の工数は6hという共通の見積もりを弾き出せるはず、つまり、チーム内の基準値作れるよねという理論が成り立つんじゃないかと。 というかこれが見積もりポーカーなんだ、という感じで。 こうすると、タスクをチーム内の基準値として利用でき、そのタスクをどれだけ捌くかで個々人の能力というものもある程度見えてくるかなと。

具体的にはGitHubマイルストーンにイシュー紐付けて、各イシューにタスクの重み(pointと呼んでる)をラベルで付与する。最初は大体1point=3hくらいの換算でやってるけど、実績値によって point:時間 の関係は変動するので多分変わってくだろうな。 ここまで準備すると、AppNeta: Burndown before you burn outを使うことでバーンダウンチャートも作ることが出来る。

最終的には、

という感じに仕上がった。これをスクラムとしてちょっと踏ん張って結果出したい。

Web API JSON Schema UI Flows

Web APIの設計にUI Flowsはすごく便利だった

以前、全てがJSONになる - ✘╹◡╹✘ を読んでなるほどなーって具合にpocketに突っ込んでいたんだけど、最近Web API設計をする機会があったので、を参考にIF仕様をJSON Schemaで作成することにした。

IF仕様書というと

  • エンドポイント定義
  • リクエストデータ定義
  • レスポンスデータ定義

みたいな構成になるかと思うんだけど、そもそもエンドポイントをどうやって導くかみたいな話になって。取り敢えず画面遷移図みたいなんが欲しいねってことに。

ただ、僕らみたいなプログラマって、PhotoshopだったりExcelだったりで画面を定義するのはちょっと辛いじゃない。そこで、これも以前pocketに入れていた 画面遷移に疑問を感じたあなたにオススメするUI Flowsというツール | Reflection | UIデザイン会社Standard Incのブログ を参考にcacooでUI Flowsを簡単に記述して、その矢印に対してエンドポイントを付ける、みたいなやり方でやってみた。

結果、作業的に割りとスムーズにエンドポイントとレスポンスデータの定義が出来た。これには少し驚いてる。 ただ、まだちょっとJSON Schemaの書き方がわからなくて英語と格闘中なう。

情報収集と保存とSlackで共有を自動化する

slack ifttt pocket twitter HBFav

社内Qiita:Teamに投稿したけど響かなすぎて承認欲求を満たすためにブログに書く。

ここから。

エンジニアを職業にしてると、情報収集がとても大切になってくるわけですが、その上企業に属していると集めた情報を社員間で共有することもとても大切になります。

1人で収集出来る情報には限界があります。
そのため、皆で集めて共有し、より早く自社コンテキストに沿いそうな情報をローカライズしていく必要がありますよね。

そこで僕が考えた最強の情報収集・共有の自動化方法を紹介します。
取り敢えず、以下のサービスを使用します。

情報収集の自動化

以下の2ツールを使用します。

Twitter

Web界隈で有名な人々をフォローしておくだけで、日々良質な情報が収集可能です。技術系情報の収集ツールとしてはノイズが多いですが、 彼らが日々どんなことを考えているのかを知ることが出来て個人的には手放せないサービスです。

HBFav

はてなブックマークTwitterのタイムラインのように表示出来るアプリです。面白いのは、 誰のアカウントでも使用可能である点です。

例えば僕のはてなidを使うと、僕がフォローしている人たちがブックマークした情報をHBFavのタイムラインに表示することが出来ます。
これを利用して、Web界隈で有名なエンジニアのidを使って 彼らが収集した良質な情報を自動で収集出来ます。

情報共有の自動化

新たに以下の2ツールを使用します。

  • IFTTT
  • Slack

HBFavは、はてなブックマークに登録する際にTwitterへ投稿するオプションを備えています。これを使うと、 自分がブックマークした記事にコメントを付けた上でTwitterへ投稿が可能になります。

これで、 自動的に得た情報を感想含めてTwitterへ共有が自出来るようになります。

Twitterへ共有するだけでは、全ての社員に僕のTwitterアカウントをフォローして貰う必要があって大変です。そのため、以下のサービスを使ってツイート内容をSlackへ流すことをします。

IFTTT

あるサービスのイベントをhookしてあるサービスの機能を呼び出すことが出来るサービスです。
これを使うと、

ことが可能になります。

ここまでを設定すると、

  • HBFav、Twitterで著名人の集めた情報を取得
  • それらからこれは役立ちそう!という情報をHBFav、あるいはTwitterでなんらかのハッシュタグ、コメントを付けて投稿
  • はてブTwitter、Slackに情報が投稿される

という感じになります。

f:id:hatajoe:20141113024838p:plain

情報保存の自動化

新たに以下のサービスを使用します。

  • Pocket

ここまでを設定すると情報収集、共有は自動化出来ますが、収集した情報はどんどん流れていってしまいます。これを保存するためにPocketというサービスを使用します。

Pocket

URLをとりあえずどんどん保存して後から検索して探せるサービスです。
僕は取り敢えず読んだ記事や後で読む系の記事をどんどん保存しています。

IFTTTを使うと

  • 例えば#pocketというハッシュタグを付けたツイート内にあるURLをPocketに保存

が可能になります。これで完成です。

  • HBFavかTwitterで#pocketタグを付けてツイート
  • ツイート内容がSlackに投稿される!
  • ツイート内のURLがPocketに保存される!

完成

 良質な情報
     | 自動で取得!
   HBFav
     | ツイートで共有!
  Twitter  
     | 自動で連携!
   IFTTT
     | 自動で情報共有・保存!
Slack/Pocket   

これで、HBFav/Twitterをチェックし、適当に#pocketタグを付けてツイートしとけば勝手にどんどん情報共有・保存が出来るようになります。

これでもう知らぬ間にどんどん情報共有が出来るわけです!これで俺らが知らないことなんて無くなんじゃね?やばくね? 皆さんも是非この自動化を体験してみてください。気持ちいいから。

ここまで。

結果、僕しかやってない。

全然最強じゃなかった... あと複数人でやると情報が被りまくってしまうな。 Slackの場合同じURLがあると二度目はページ情報が展開されないのでそれである程度わかるかな。 誰かやってくんないかな...

chef-containerを使ってみて

docker chef fig boot2docker

chef-containerで色々なコンテナを作成してみて思ったことなど。

fig良い

と言いつつ、いきなり脱線しちゃうんですが、ちょっと前に、boot2docker v1.3がリリースされ、ホストマシンからboot2docker上のDockerコンテナへディレクトリマウントが可能になりました。
また、同時にDockerコンテナを使用して開発環境を構築するための公式ユーティリティツールであるfigもv1.0がリリースされました。
これらを使用すると簡単にポコっと開発環境コンテナ群というものを立ち上げることが出来ます。(boot2docker+figの詳細は既にWebにあると思いますので割愛)

これまで開発環境にはVagrantを使用していたのですが、figを使うと簡単に全開発環境、いわゆる、ローカル環境、テスト環境みたいなものがそれぞれリポジトリをクローンして fig up とコマンド打つだけで再現出来るため、boot2docker+figに移行しました。

例えば、今開発中の案件だと以下のようなデーモン達が必要で。

これを以下のようなコンテナ群にして。

  • web (nginx + httpd + php + fluentd) → chef-containerでコンテナ作成後DockerHubへpush
  • web2 (nginx + nodejs) → chef-containerでコンテナ作成後DockerHubへpush
  • mysql → DockerHubから適当なやつ
  • memcached → DockerHubから適当なやつ
  • redis → DockerHubから適当なやつ
  • mongodb → DockerHubから適当なやつ

これらが fig up とすると立ち上がります。
さらにfigのlinkというオプションを利用すると、web1,2/etc/hosts に各バックエンドサーバーのIPアドレスと任意のホスト名を登録することが出来ます。
これにより、WAFによくあるバックエンド接続情報にその任意のホスト名を書いておけば、Dockerが動作するどの環境でも同じようにコードを変更することなく動作する環境が手に入るという感じです。素晴らしく使いやすいです。

chef-containerの話

で、chef-container。

Dockerコンテナの作成にはchef-containerを採用しました。
理由は、本番環境ではDockerコンテナを使わないからです。(ちょっと知見が足りな過ぎる気がしているのでまだ踏み切れないといった感じ。)
ただ、本番サーバーをプロビジョニングする必要は当然あるので、chef-containerを使っとくと取り敢えずレシピが残るという点で採用しました。

ただchef-containerは、コンテナ起動時に毎度プロビジョニングが実行されます。
これはまぁ仕方が無いけど正直微妙。コンテナスタンバイにまぁ数分かかっちゃう。(起動だけなら数秒なのに)

いやわかるんですけどね。
Dockeコンテナにinitデーモンが存在しない都合上、chefによってインストールされOS起動時に起動するよう設定されたデーモンを起動する術が無いから、chef-initが再度プロビジョニングすれば全部起動するよねという発想。だと思うんだけど。(cookbook_fileなどはコンテナ内にキャッシュされているものがコピーされる模様)

僕はこれを勘違いしていて、chef-containerで作ったコンテナはchef-initがプロビジョニングせずデーモンを次々起動してくれるものだと思っていて。
ただある日なんかコンテナ起動したのにブラウザでアクセスしても暫く繋がらない事案が発生してしまって。調べてみるとそういうことだった。(fig logs web1とかやると見れる)

まー割りとchefのレシピはある日突然動かなくなったりするので(特にyumリポジトリのURLが変わったりだとか、突然postfixが必要になったりだとか...)、毎度プロビジョニングも悪くは無いのかもしれないけれども。

そんなわけでDockerコンテナは開発から本番まで通して使用し、Dockerfileで構築するのがベストプラクティスな気がしたわけです。(公式まんまだけども)

そうなるとchefのレシピからDockerfileを生成出来ると嬉しいかもしれない。
Ansibleからなら比較的やりやすそうな印象あるがchefからは色々大変そうだな。。