2011/12/10

Shibuya.trac #13 - よりよい開発を目指して -

Shibuya.tracの第13回勉強会行ってきました。

立案企画の @tyobichiさん
発表者の @kanu_さん、@ikikkoさん、@kompiroさん
kompiroさんは遠路はるばるお疲れさまでした!
また、会場サポートスタッフの皆様、大変お世話になりました。

今回は、場所は日本橋のパソナエンジニアカフェさんをお借りしました。
あまりにおしゃれな建物で、しかも発表してる横に、
水耕栽培してるという、良い意味で面白く、凄い場所でしたw

目的として、よりよい開発を目指してと、かなりアバウトといえばアバウトなんですが
そこを目指すのがこのコミュニティなんで、それでいいかとも思います。
内容がタイトルに縛られないためか、おもしろいエントリがならんだのかなとか。

発表

Scrumでやってみた
@kanu_さん

Jenkins実践入門の Next Step
@ikikkoさん

Kanban - お客さんの視点に立ったアジャイルなやり方 -
@kompiroさん

の三名でした。

LT

パソナテック / エンジニアカフェのご紹介
パソナテック様

という4本だて2時間です。

開始が少し遅れて19:10からになってしまい
時間が押してしまったのが申し訳なかったです
(休憩時間をがっつりけずったり、総合QAを削ってるので
色々聞きたかった方は、Twitterとか使ってもらえるといいかなと思います)


Scrumやってみた

結論 : tracいらねぇんじゃねぇの?

というのも、ツール自体はあくまでツール
Trac.Lighningのデフォルトページにあるとおり、
Trac自体は最小限の干渉しかしないサポートツールで
開発者は、Tracにアクセスする作業が増大することで
開発に支障がでるようであれば、それは本末転倒かなぁと理解しました。

便利なプラグインは多くあるにしても、
Trac.Lightningに入っているプラグインは把握できてないし
汎用的に仕える物と、そもそも状況に応じて自分でいれて拡張することで
初めて力を発揮するのがtracかなと思いました。

開発とプロジェクト管理を両立させるのは、ますます無理だなとw
本当にtracを使って集計や方向性とかを決める材料にするのであれば
それに大して100%注力できる環境が必要なような気がします。

tracが管理のためのツールになり、第二第三のExcelにならないように
使い方をしっかりと考えて使うことが大切なのではと思いました。

「とうとうExcelがやられたか、しかし奴はBTSの中では最弱」

的な展開はしたくないところですw


Jenkins実践入門 の Next Step
(後日、発表資料公開があるらしい)

この発表は、JenkinsのTips集のような感じでした。

前半は、Jenkins本の紹介
積み本が増えてきたので、いまのものがあらかた片付いたら
読んでみようかなと思います。

後半はこうしたらいいよ!っていうTips
Jenkinsの?ボタンはほんと助かります。
いつも押す?ボタンは、スケジュールの設定のところのやつと
成果物の収集のところのやつです。お気に入りの?ボタン

高度な設定は、一通り使った後に、押してまわると面白いかなと思います。
中身は、やってみないと分からないものが多いと思うので
まずは使ってみてからの、ひと押し

実際、僕は本を読まずに、ネット + 素晴らしい先人たちが残してくれた
Jenkinsの環境設定を見ながら、Jenkinsを利用しています。
大体問題にぶち当たると、twitterで呟きつつ、自分の昔作った
プロジェクトを眺めて、あーでもねぇ、こーでもねぇとやってます。


Kanban - お客さんの視点に立ったアジャイルなやり方 -

発表時間が短くなってしまい、申し訳ありませんでした。

いつもの todo doing done のScrumボード(意味あってるのかな)じゃなく
Kanbanの仕組みと、用語の解説。
また、おもしろいサンプルケースとして、
タスクの完了期限を決めないことで、生産効率が上がった事例をお聞きしました。

Kanbanで優秀だなって思ったのは、流れが停止しないことだと単純に思ってます。
Todoは常に補充され、開発者は補充される物から順番にタスクを拾って処理していくため
機能追加が滞らない場合は、開発者はシームレスにタスクをこなすことになると。

気になるというか、辛そうだなと思うのは、まず終わりが見えずづらいこと。
TODOに入れる個数が制限されて、そこに入るタスクは、顧客側が管理するとなると
顧客のプロダクトバックログや、要求仕様を確認していかないと
プロジェクトの終了が見えないのかなと思いました。

あと、シームレスの弊害があると思って、ふりかえりや改善のタイミングは
どうやって図るのかなというのが、疑問として残りました。
これに関してはチームがここで振り返るよ!って言ったときに、
前回の振り返りからの完了タスクとかでやるのかなぁとか。

実際問題として、組み合わせちゃいけないというわけでもなく

プロジェクト管理をScrumボード タスク管理をKanbanで
とかでもいいのかなとか。
とりあえず勉強不足なので、この辺は戯れ言ですw


パソナテック / エンジニアカフェのご紹介

今回会場を提供していただいたパソナテック様のLTです。

いいね! をするがいい! という(ぉぃ


勉強会とかで会場提供して、交流を深めるのが真の目的だそうで
今度はHTML5とかゲーム開発のフレームワークの勉強会とか
結構ワクワクするような勉強会やってそうでした。

とりあえず、イイネはしてきた!

というわけで、皆様お疲れさまでした。

後日談

今回の勉強会では、司会をやらせていただきました。
時間調整で、お品書き削ったりとかしかしなかったんですが
発表者に大して、時間はあとこれぐらいで頼む!とかいうのも
有志の勉強会で、それはないなぁという意識から
そのまま流させていただきました。

おかげさまで、最後の総合QAと休憩時間を一個半削るという
暴挙をやらかしたのも反省点です・・・

とはいえ、お褒めの言葉もいただき嬉しい限りです。
また機会があれば、お手伝いしたいと思います。

司会業は、舞台度胸つけるのに結構いいんじゃないかなと
最近思ってます。あがり症なため、前にたつと
足がガクガクしてたりしますw

2011/11/22

SCMBCいってきた。

SCMBootCampいってきた。

SCMBootCampの主催者、きょんさん(@kyon_mm)、ほんとお疲れさまでした。
また、会場を提供していただいたORACLEさん
講師、スタッフの方々、大変お世話になりました、ありがとうございます。

とりあえず、内容や会場の様子は、こちらの人のブログからどうぞ。
(楽してすみません、「こちらの人」を流行らせたいです。)
SCMBootCamp in Tokyo 2に参加してきた #scmbc - Shinya’s Daily Report

んで、僕はgitで参加してきました。
選びがたかったんですけど、初参戦かつ、gitまともに使えてるのか?という疑問もあって。

自分の感想とかですが
僕、git 使えてませんでしたゴメンなさい。
これからはちゃんと勉強するので、許してください。

というのも、基本操作で使ってることが多すぎて
あ、こんなこともできたの? なに!?そんな方法が!?

っていうのが多くて、「一度、コマンドのヘルプ全部眺めてみるといいよ」
って言われた意味を、やっと理解したとか。

ただ、少し言い訳しとくと
普通に使ってるだけでも、効果は出ると思うんです。
動作を理解しないのはいけないと思うんですが、
  1. なにするか決める
  2. topic branchを作って移動(checkout -b)
  3. 作業する
  4. addする
  5. commitする
  6. (rebaseする)
  7. checkoutでマスターに戻る
  8. pullする
  9. mergeする
  10. pushする

各所で、log と status と gitk

これだけのステップで、リモートにほぼ依存することなく
開発できるってのは素晴らしいことだと思います。

僕は本を読むのが苦手なわけですが、本を読まなくても
ここまでやることができて、ある程度のことが出きるようになれば
本も読めるようになるだろうってことで、後日入門Gitも買ってきました。
そんなわけで、これを最初のステップにして、これから勉強していこうと思います。

うちのチームの成果物(Gitチートシート)は

risk/SCMBootCamp - GitHub

ここに入ってまして、いまだ少しずつ改良が進められていますw

内容的には、単純にアルファベット順にコマンド並んでるだけですが
これを一通り読むだけで、あぁこんなこと出来んのか〜って思えます。
なので、これはこれでありだなぁと思ってます。

というわけで、短いですが、これぐらいにしておきます。

そうそう、忘れてた。
思い残しが数点

きょんさんに、僕のリポジトリを君のリポジトリと統合しないか?
とか言ったんですか?と聞こうと思ってたのに忘れたこと

せっかく鼻メガネ持っていったのに、恥ずかしさに負けて
装着時間が短く、自分の勇気の無さに落胆したこと

を付け加えておきます。

最後になりますが、

同じチームで作業してくださった
@inda_re
さん @nobusueさん @Soltiさん
@sue445さん @natsu_nananaさん
講師の@tosikawaさん ありがとうございました。

いろんなおもしろい話と、他業種の話は大変興味深く
「組込み以外もおもしろそうだな」と思いました!

とりあえず、branchを切り忘れる癖から矯正しよ・・・

2011/10/28

CI(継続的インテグレーション)超入門:Jenkinsのススメ

「CI(継続的インテグレーション)超入門:Jenkinsのススメ」
に行ってきた話

内容的には、
  • CIって何?
  • jenkinsいいよー
  • 商用CIツールの宣伝
といった感じでした。

CIの説明

ソフトウェアの調理方法を。

ビルドって何?ということで、そういやあまり考えたことがなかったな
ビルド自体はには2つの意味があることを。
  • 実行可能なソフトウェアを作ること
  • 実行可能なソフトウェア自体
の意味があるんだね。

「ビルドをビルドする」は
「料理を料理する」と同じ意味合いと言われてあぁって思った。

本題ですが

提供する側が必要なことってことで

「いつでも同じビルドを届けることができることが重要」

確かに、「あの時のビルドの環境作ってほしいんだけど」
ってよく言われるので、よく分かる。
背景を説明すると、リリースと開発が平行してて

リリースした製品でxxxなバグが出たから、再現環境作りたいんだけど

とか。

そんなときに、再現可能なビルドをしとくことが重要になると。
再現可能ってのはどういうことかというと
  • いつでも誰でもビルドできる
  • ユーザーに届けたものと同じものをビルドできる

これを実現するために
必要なことが、全部とはいわないが一般的に

  • ソース
  • レシピ
  • 手順書
  • スクリプト
  • ビルドマシン
  • コンパイラ
  • ビルドツール各種
とか。

話は変わって開発環境の話ですが

開発者はサンドボックスでビルドすることが望ましい

じゃあビルドはどこでやるの?というと

ビルド専用マシンを立てましょう ということに。

んで、ビルドマシンが使うソースはどこに? というと

リポジトリが必要でしょう。
  • サンドボックス
  • リポジトリ
  • ビルドマシン

この3つを連携させて動作させると

サンドボックス」で開発して
リポジトリ」にコミットして
ビルドマシン」がビルドする

これを繰り返していくことがCIですね。
キレイな環境で作ってあげることで
安定したビルドが出来上がると。

ただ実際に開発していくと、普通ソフトは壊れます。
実行時バグとか、他の機能に干渉するとか原因はいっぱいあるけど

壊すタイミングは何かってことになると
コミットしたときにビルドの成果物が壊れるんですね。

これを避けるための、コミットポリシー

大体コミットするときのお作法として決められているような内容ですが
  • 自分のところでビルドしてエラーが無いことを確認する
  • バディビルドを実施する
  • コードレビュー
とか。

バディビルドをビルドサーバーにやらせるっていいなぁと思った。
実際にビルドサーバーがビルドするんだから、同じ環境で試しにビルドして
結果を教えてくれるなら、それが言いに決まってる。

まえに、名古屋のイケメンが話していた

自分用のブランチにコミットすると、ビルドサーバーがビルドしてくれて
OKなら、メインのリポジトリにコミットしてくれるっていう仕組みが
この流れと同じだと思うんだけど、環境構築大変そうだなぁと思ったり。

最後に、リリーストレインの話。

駆け込みコミットはお控えください
ビルドは定刻通りに発車しております。

これがすべてか。

変なタイミングのコミットは、本当に問題の元。
落ち着いて、良いリズムの開発を心がけたいものです。

まぁ一日一回のビルドだときついと思うので
デイリービルドするなら、プレビルド的な
コミットを監視してるやつも一緒に立てて上げるのがいいよなぁと思う。

jenkinsの話

なんでCIするのって話から。

インテグレーションを頻繁に行って、結合作業時に「え!?」ってならないように。

最近のCIの定義でいくと
ビルドを頻繁に行うことで、退行をできるだけ早く検出する
コードの品質検査を定期的に。

どっちにもいえることで

「機械ができることは機会にやらせればいいじゃない」

と。
僕も、ものすごくそう思います。

利点とか

リグレッションは、そのまま直訳で「後退、退化」なんですね。
うちの会社では、デグレとか読んでるソレです。
テストの場合は、前に出来たことが出来なくなることを見つけるので
リグレッションの方がしっくりくるかなぁとか思ったり。

リグレッションが早く見つかる
常にテストを書けている場合にかぎらず
成果物が常時できているので、コミットフックのビルドをかけるだけでも
結構違うと思う。

頻繁に成果物が生成されることで、ここからxxxの現象が出てるって
確認しやすくなります。

頻繁にリリースできるため、バグを早い段階で見つけることが出来
「あーそんな変更あったね(笑)」
を減らすことができます。

見える化
jenkinsさんは、情報収集が得意なので、各種情報が
jenkinsに集まり、ダッシュボードをみれば現在の状況
各種ビルドをみれば変更点やテスト状況など、みることができます。

属人制を減らす。
ビルドサーバーさえあればビルドできるはずなので
急にチームから人が消える
病気で倒れる
など、あったとしても大丈夫と。
あと、ビルドサーバーが開発のためのお手本環境になるので
各メンバーの開発環境を統一化するのにも一役かってると思います。
前に自分用Jenkinsいれた!って呟いたら、突っ込まれたのを思い出しますw

追跡可能性
バイナリが作られた原因(なんのコミット?)が分かる。
リグレッションの原因分析の手助けに使える。

かるくまとめ
CIは、手間を減らす というよりは
「人が人のやるべきことをやるために」
機械にできることは、できるだけ機械にやらせるのが良いと。

Jenkinsさんの紹介ですが

いいところをざっと。
  • 導入設定が簡単
  • 各種OSパッケージ
  • プラグインによる拡張機能
  • 450個以上のプラグインで多用な環境に
  • プラグインを自作することもでき、さらに柔軟な環境へ
ビルド以外に出来ることの紹介
  • FindBugs 静的解析かな?
  • コードカバレッジの計算と表示
  • チケットシステムとの連携
  • 分散ビルド
チケットシステムとの連携は、コミットログから飛ぶぐらいかな
って思ってたけど、jenkins自体がチケットに書き込みに行ったりするんですね。

プレテステドコミットとかは、難しそうだなぁって話してたら
かおるんに、TFSなら簡単に出来るよって言われたり。
流れてきには、
  1. 開発者が自分のトランクにコミットする
  2. jenkinsがそれを見つけて、ビルドとテスト
  3. OKならjenkinsからメインのリポジトリにコミットする
これならメインのリポジトリを破壊する可能性がグッと減りますね。

どの出来ることもそうだけど、機械には得意な事と不得意なことがあるので
得意なことはいっぱいやってもらって、あまったことだけ人間がやるのが
ベストだなぁと思います。

最後に、「具体的にはじめるには?」ってことで
  • 千里の道も一歩から、
  • ビルドの自動化
  • テストの自動化
  • コンポーネントを一つづつ
  • 自動化の島をたくさん作って大陸へ進化
コツコツが大切なんだなぁと改めて。
(苦手だ・・・)

最後の話は、未発表製品なので割愛。
静的解析ツールの話でした。

ディスカッションですが
全体的にまだ何もいれてない!ってところと
まぁそれなりに〜ってところが半々って感じだったのかな
(一番前に座ってたのであまり会場がみえなかった)

どの質問に関しても、共通して言えることは

Small start Small win

の繰り返し。

こんてぃにゅあす うぃん

です。

何事も、出来そうだなぁとおもったことをとりあえずやってみると
なんか見えると思います。

以上、勉強会レポでした。

勉強会後、
@heroweenさんとか、@shinyaa31さんとか、
@711fumiさんとか、@cyobichiさんとオムライス食べました。

いろんな話が出たけど、共通して言えることは
勉強会大好き と 開発者が楽しいって思えることを出来ないと
人は集まらないし離れていくってことでした。

さて、締めの言葉は、

「俺には前しかみえない(腹肉的な意味で)」

やっぱりこれですね。

ではでは。

boost.statechart を使ってみた。

まず普通に使ってみた。

例題は、
letsboost::statechart

ここを参考にさせていただきました、いつもお世話になってますw

まずシンプルな奴。

#include <iostream>

// boost
#include <boost/statechart/state_machine.hpp> // ステートマシン
#include <boost/statechart/simple_state.hpp> // ステート
#include <boost/statechart/event.hpp> // イベント
#include <boost/statechart/transition.hpp> // 遷移
#include <boost/statechart/in_state_reaction.hpp> // イベントアクション
#include <boost/mpl/list.hpp> // イベントテーブル

using namespace boost;

namespace gate
{


namespace events
{
// イベント
class InsertedCoin : public statechart::event< InsertedCoin > {};
class PassedThrough : public statechart::event< PassedThrough > {};
};

// 初期ステートのみを前方宣言
namespace states { class Locked; }
// ステートマシン < マシン, 初期ステート >
class Gate : public statechart::state_machine< Gate, states::Locked >
{
// メインスレッド

// イベントハンドラ
};


namespace states
{
class Locked;
class Unlocked;

// ロック状態 ステート < ステート, マシン >
class Locked
: public statechart::simple_state< states::Locked, Gate >
{
public:
// イベントを引数に取る
void alarm( const events::PassedThrough& event )
{
std::cout << "ウウウウウウウウウ ウウウウウウウウウウウウ" << std::endl;
}

// イベントテーブル
typedef boost::mpl::list<
// 遷移
// InsertedCoinイベントで、Unlockedへ遷移
statechart::transition < events::InsertedCoin, states::Unlocked >,

// リアクション
// 通過イベントで、アラームを発生 ステートは維持。
statechart::in_state_reaction<
events::PassedThrough, Locked, &Locked::alarm >
> reactions;
};

// ロック状態 ステート < ステート, マシン >
class Unlocked
: public statechart::simple_state< states::Unlocked, Gate >
{
public:
void thankYou( const events::InsertedCoin& event )
{
std::cout << "ありがとう・・・ありがとう・・・" << std::endl;
}

// イベントテーブル
typedef boost::mpl::list<
// InsertedCoinイベントで、Unlockedへ遷移
statechart::transition < events::PassedThrough, states::Locked >,

// リアクション
// コイン挿入イベントで、感謝を。ステートは維持
statechart::in_state_reaction<
events::InsertedCoin, Unlocked, &Unlocked::thankYou >
> reactions;

};

} // namespace states

} // namespace gate


int main()
{
gate::Gate gate;

// ステートマシンの初期化
gate.initiate();

// とりあえずイベントを発生させてみる
gate.process_event( gate::events::InsertedCoin() );
gate.process_event( gate::events::PassedThrough() );
gate.process_event( gate::events::PassedThrough() );
gate.process_event( gate::events::InsertedCoin() );
gate.process_event( gate::events::InsertedCoin() );

return 0;
}


内容は、そのまんまで、使ってるクラスは、大きくわけて三種類
  • イベント
  • ステートマシン
  • ステート
ステートを使ってるので当たり前だけど
ステートマシン が ステート を イベントをトリガに遷移していく動作をさせます。

イベント
boost::statechart::event テンプレート
イベントクラスがこのテンプレートクラスを継承する
テンプレートには、イベントクラスを渡す。

イベントハンドラの登録
boost::statechart::in_state_reaction テンプレート
イベントクラス、イベントハンドラを持っているクラス、イベントハンドラ を設定する。
後述するイベントテーブルに渡すことで、イベント発生時に、イベントハンドラが呼び出せる

イベントをトリガに別ステートへ遷移する
boost::statechart::transition テンプレート
イベントと遷移先のステートを設定すると、イベント発生時に指定したクラスに遷移する

ステートマシン
ステートマシン
boost::statechart::state_machine テンプレート
ステートマシンクラスが、このテンプレートクラスを継承する
テンプレートには、ステートマシンクラスと、初期ステートを設定する

ステート
ステート
boost::statechart::simple_state テンプレート
ステートクラスが、このテンプレートクラスを継承する
テンプレートには、ステートクラスと、ステートマシンを渡す。

イベントテーブル
boost::mpl::list テンプレート
ここに、イベントハンドラや、状態遷移 を登録する。

といったところです。

んで、いろいろ考えて、自分なりにごにょごにょやったのがこっち。
最終的にステート使う人が、書く量を減らせるようにというのを目標にしたんですが
いまはソースが一枚になってるので、結構ごちゃごちゃしてます。

イベントは分かる人が実装して、普通使う人が
ステートだけを実装していくような用途を想定しています。

/**
* @file statechart.cpp
* @author riskrisk
* @date Fri Oct 28 17:31:30 2011
*
* @brief statechart sample
*
* commandline : g++ -lboost_thread -lpthread statechart.cpp -o statechart.bin
*/

#include <iostream>
#include <queue>

// boost
#include <boost/thread.hpp>
#include <boost/bind.hpp>

#include <boost/any.hpp>

#include <boost/statechart/state_machine.hpp> // ステートマシン
#include <boost/statechart/simple_state.hpp> // ステート
#include <boost/statechart/event.hpp> // イベント
#include <boost/statechart/transition.hpp> // 遷移
#include <boost/statechart/in_state_reaction.hpp> // イベントアクション
#include <boost/mpl/list.hpp> // イベントテーブル

using namespace boost;

namespace gate
{

// イベント
namespace events
{
// コイン挿入
// イベント( event< Event > )
class InsertedCoin : public statechart::event< InsertedCoin > {};
// イベントハンドラ
class InsertedCoinHandler
{
public:
// イベントハンドラ( onXxx( const Event& ) )
virtual void onInsertCoin( const InsertedCoin& event ) = 0;
// ハンドラ登録( in_state_reaction< Event, HandlerClass, EventHandler > )
typedef statechart::in_state_reaction< InsertedCoin,
InsertedCoinHandler,
&InsertedCoinHandler::onInsertCoin > EventHandler;
};
// 遷移( transition< Event, TransitionState > )
template< class TARGET_STATE >
class InsertedCoinTransition
: public statechart::transition< InsertedCoin, TARGET_STATE >
{};

// 通過
// イベント( event< Event > )
class PassedThrough : public statechart::event< PassedThrough > {};
// イベントハンドラ
class PassedThroughHandler
{
public:
// イベントハンドラ( onXxx( const Event& ) )
virtual void onPassThrough( const PassedThrough& event ) = 0;
// ハンドラ登録( in_state_reaction< Event, HandlerClass, EventHandler > )
typedef statechart::in_state_reaction< PassedThrough,
PassedThroughHandler,
&PassedThroughHandler::onPassThrough > EventHandler;
};
// 遷移( transition< Event, TransitionState > )
template< class TARGET_STATE >
class PassedThroughTransition
: public statechart::transition< PassedThrough, TARGET_STATE >
{};

// イベントのシリアライズ用
typedef boost::shared_ptr< statechart::event_base > EventPtr;
};

// 初期ステートのみを宣言
namespace states { class Locked; }
// ステートマシン( state_machine < StateMachine, InitialState > )
class Gate : public statechart::state_machine< Gate, states::Locked >
{
private:

bool isExit_; // スレッドの終了
std::queue< events::EventPtr > events_; // イベントのシリアライズ

public:
// コンストラクタ
Gate()
: isExit_( false )
{}

// スレッドの終了要求
void requestExit()
{
isExit_ = true;
}

// メインスレッド
void run() {

std::cout << "machine entry" << std::endl;

// ステートマシンの初期化
initiate();

// メインループ
while( !isExit_ ) {
// イベントハンドラ
eventHandler();

// 登録イベントが無い場合は、少し待ってみる
if( isNoEvent() ) {
usleep( 100 * 1000 ); // 100msec
}
}

std::cout << "machine exit" << std::endl;
}

// イベントが無い場合に真を返す
bool isNoEvent() { return events_.empty(); }

// イベントの追加
void addEvent( events::EventPtr event ) {
events_.push( event );
}

private:

// イベントハンドラ( とても適当 )
void eventHandler() {
if( !isNoEvent() ) {
process_event( *( events_.front() ) );
events_.pop();
}
}
};

// ステート
namespace states
{
class Locked;
class Unlocked;

// ロック状態( simple_state< State, Machine > )
class Locked
: public statechart::simple_state< Locked, Gate >
, public events::PassedThroughHandler
{
public:

// イベントハンドラ
// 通過
virtual void onPassThrough( const events::PassedThrough& event )
{
// アラームを鳴らそう
std::cout << "ウウウウウウウウウ ウウウウウウウウウウウウ" << std::endl;
}

// イベントテーブル
typedef mpl::list<

// 遷移
// InsertedCoinイベント -> Unlockedステート
events::InsertedCoinTransition< Unlocked >,

// イベントハンドラ
// PassedThroughイベント
events::PassedThroughHandler::EventHandler
> reactions;
};

// アンロック状態( simple_state< State, Machine > )
class Unlocked
: public statechart::simple_state< Unlocked, Gate >
, public events::InsertedCoinHandler
{
public:

// イベントハンドラ
// コイン挿入
virtual void onInsertCoin( const events::InsertedCoin& event )
{
std::cout << "ありがとう・・・ありがとう・・・" << std::endl;
}

// イベントテーブル
typedef mpl::list<
// PassedThroughイベント ->、Unlockedステート
events::PassedThroughTransition< Locked >,

// イベントハンドラコール
// InsertedCoinイベント
events::InsertedCoinHandler::EventHandler
> reactions;
};

} // namespace states

} // namespace gate


int main()
{
gate::Gate gate;

// ざっくりとイベントを登録
gate.addEvent( gate::events::EventPtr( new gate::events::InsertedCoin ) );
gate.addEvent( gate::events::EventPtr( new gate::events::PassedThrough ) );
gate.addEvent( gate::events::EventPtr( new gate::events::PassedThrough ) );
gate.addEvent( gate::events::EventPtr( new gate::events::InsertedCoin ) );
gate.addEvent( gate::events::EventPtr( new gate::events::InsertedCoin ) );


std::cout << "start" << std::endl;

// ステートマシンを起動
boost::thread gateThread( boost::bind( &gate::Gate::run, &gate ) );

// ちょっとだけ待っておく
sleep( 1 );

// 終了要求
gate.requestExit();
// 終了待ち
gateThread.join();

std::cout << "end" << std::endl;

return 0;
}

// EOF


2011/09/04

git-svn で dcommitするときに。

久しぶりにエントリですw

相変わらず、社内で利用しているSCMは、Subversionでして、 git-svn のお世話になってます。
で、前に分散管理勉強会で git-svn の発表したときに、間違えてはいないんですが、
ちょっとなぁって思う部分があったので、そこについて補足しようと思います。

何かって言うと、コミットログについてです。

スライドの順番通りやると、コミットログが「マージしました」になります(汗
どういうことかっていうと、masterにすべてマージしてからコミットする手順で紹介してたんですね

手順的には

ブランチに master と working があるとして
  1. wokingで作業
  2. 一段落したので、コミットしようと思い立つ
  3. git checkout master でマスターブランチに移動
  4. git svn rebase で、masterを最新に更新
  5. git merge working で、masterに変更を反映
  6. git svn dcommit でsvnにコミット
これだと、5の時点で、サーバー上に反映されるログが

「Wokingをマージしました(キリ」

になります・・・

んで、正しい方法なんですが、

  1. wokingで作業
  2. 一段落したので、コミットしようと思い立つ
  3. git checkout master でマスターブランチに移動
  4. git svn rebase で、masterを最新に更新
  5. git checkout working でworkingに戻る。
  6. git rebase master で、working を最新に。
  7. git svn dcommit でsvnにコミット
という感じでできるっぽいです。(今のところ大丈夫)

実はまだ、コンフリクトしてないので、どーなるかなーとは思いつつも、
コンフリクトしない素晴らしい状況(まぁ僕のところは僕しかイジらないってだけですが)
で仕事してるので、またなんかあったら、情報更新しようと思います。

ではでは。

2011/06/15

自分のスキルマップ

自分の値段を考えたことがなかったけど、それを決めるための指標になりそうな手段

実際に、Google検索でスキルマップを検索してみると、画像検索に結構出てきたり
作り方のページが表示されたり。

ただ、見てて思うのは、

  • 表の形状にして、そこに文字を当てはめる
  • できることが数値化されているが、その数値はどこから?(5段階評価みたいなレーダーチャート)

実際に見たい、見てもらいたいデータは、分野に分かれて、その分野でどの程度のことを
やったのか、どんなことができるのか、どんな経験があるのかだと思う。

そんわけで、自分のスキルをマインドマップ化するっていうのが流行ってたし、そんなデータを自分でも作ってみた。

この図も経験とスキルに色分けされてなくてちょっと見づらい・・・

多分だけど、自分の値段がある程度正確に把握できてる人は少ないんじゃないかと思う。
(そもそも、そんなもの導き出せるのか?という話もあるけど、診断サイトとかあるしなぁ)
実際、時代の流れ(流行り廃り)でも、評価はどんどん変化するわけで、変わらないのは
自分が出来る言語や、自分の経験かなと。

上に書いたような自分の財産を見せられる「元データ」があって、

「コレだけのことをやってきて、こんなことができるんですが、僕いりません?」

と聞けるようになってたら、転職しやすいんじゃないかと思って。
お前は何ができるんだ?という疑問を投げられたときに、胸を張って、

このページを見てもらえれば!と言えれば作った価値があるってもんだ。

2011/06/09

Cygwin+Windowsのエディタで歴史改変(git rebase -i)

僕は、現状でCygwinをつかってgitをいじってます。
んで、コミットログとかの入力はWindowsアプリでやってます(terapad)

んで、最近自動コミットを試してみてたんですが、どーにもgit rebase -i を実行すると、
エディタが開いて何も表示されないことが続いてました。

ついったで、なんでじゃーってつぶやいてたら、

@riskrisk cygpathで変換してあげないとだめな気がしますless than a minute ago via TwitVim Favorite Retweet Reply

おお、なるほど、Windowsのエディタに、Cygwinのパス /homeとかああいうやつがそのままわたるのか・・・

ためしに、/lib/git-core/git-rebase--interactive の最初でパスを設定してるので、そこでechoを突っ込んでみたら
見事に、homeから始まるアドレスが出てきた!

で、解決方法も、cygpath -w でWindowsのパスに変換してくれるよ ということなので、
さっそく、スクリプトをいじって試すと動くようになったんだけど・・・

そこで、もう一通

@riskrisk 自分は引数をcygpathで変換してから渡すシェルスクリプト書いて、それをGIT_EDITORに指定してますless than a minute ago via TwitVim Favorite Retweet Reply

そりゃそうですね・・・ その方法が一番正攻法だと思います

というわけで、下記にサンプルです。

$ git config --global core.editor ~/.git-editor

これで、自分のhomeディレクトリの直下にある .git-editor を実行してくれるので、
このスクリプトを書きます。

#!/bin/sh
# editor setting
"/cygdrive/c/Program Files/TeraPad/TeraPad.exe" /cu8 `cygpath -w $1`

僕のやつはこんな感じ。

これで、git rebase -i の編集に、terapadが使えました。

ほんとありがとうございました。