天然パーマのテンパらない開発

自分の開発/勉強記録みたいなもんです

Agile Samurai Base Camp 2013/12/8 議事録

Agile Samurai Base Camp

2013/12/8に行われた、Agile Samurai Base Campの個人的なメモです。

誤字や間違った見解のメモなどあるかもしれません。。

 

TDDで開発の効率が上がるかはやってみないと分からないが、

品質向上と、不安を減らすという意味では間違いなく正しいやり方だと思います。

 

セミナーの前から、頭では分かっていても、なかなか実践できていなかったので、

この機会に少しずつテスト駆動で実装してみたいです。

 

■ 基調講演(角谷さん)

・Whole One Team

 顧客が何を作るかを決める。開発チームがどうやって作るかを決める

・テストやリファクタリングを行いながら開発する

 書いたコードはいつでも動くような状態にしておく

 テスト駆動開発をすれば、テストしやすい設計になる。

 

参考本

エクストリームプログラミング入門にジョナサンは一番影響を受けた

リファクタリング〜プログラミングの体質改善テクニック〜

エクストリームプログラミング実行計画

テスト駆動開発入門

アジャイルな見積もりと計画づくり

インセプションデッキ

アジャイルサムライ

 

ソフトウェア開発がアジャイルであるとは?

・開発がアジャイルであるということは、協調性を重んじる環境で、フィードバックに基づいた調整を行い続けること

 ベロシティとかどうとか、こだわりすぎるのに意味はそんなにない。ゴールを達成するためにどうすれば良いかを考えて改善していくことが大事。

 

1. 学んだことを他の人に共有すること

2. 常により良い方法を探し続けること

3. 楽しんでください

 

--------------------------

TDD(和田卓人さん)

 

アジャイルプロセス

・協働でゴールに向かう「チーム環境」

・高速に石橋を叩いて渡る「開発環境」

 

TDDとは

ユニットテストリファクタリングテスト駆動開発継続的インテグレーション

・動作するきれいなコード

 この完結な言葉はTDDの目標で、あらゆる理由で価値がある

・設計→実装は難しい。正解となる設計は何か、誰も言えない

・いざ作ってみたら、漏れやこっちの方が良いなどが出てくる

 

TDDサイクル

1. 次の目標を考える

2. その目標を示すテストを書く

3. そのテストを実行して失敗させる(Red)

4. 目的のコードを書く

5. 2.で書いたテストを成功させる(Green)

6. テストが通るままでリファクタリングを行う(Refactor)

7. 1〜6を繰り返す

 

リファクタリングが行えなくなると、黄金の回転が回らず、負債となっていく

リファクタリングテスト駆動開発のステップの1つ。リファクタリングをします、だけは通らない

参考本:リーダブルコード

 

TDDのこころ

1. 1つずつ、少しずつ、段を小さく

2. 大きいタスクを小さいTODOに落とし込み、それぞれをテストする

 複数を相手にしない。ひとりずつ対処する!→ TODOリストから持ってきてerrorを消していく

3. 素早くまわす(フィードバックサイクル)

4. 自分が最初のユーザ(自分で書いたコードを最初に使うのは自分)

 テストから書き始めるということは、使う側からこういうのを使いたい、という立場からコード実装に入れるということ。

 使いやすいコードを自分で判別して実装する仕組み

5. 不安をテストに

 自分の手を止めている(不安)ことに対して、テストコードを書きましょう

 getter, setterにテストは書く必要(不安)はない。メインコードだけテストすればいい

 テスト駆動開発をしておけば完璧ってことじゃなく、自分たちの中で質の高いコードを作り、他の人が参画した時に入りやすいようにする

・命綱を編む(書いてきたテストコードが自分たちを助けてくれる)

 急激な市場や設計の変更に対して柔軟な対応を行えるように。

 

TDD、Developper Testingのメリットの最大の理由は心理的なもの

・即座にフィードバックを得るため

・書いたコードに自信を持つため

・これから書くコードに自信を持つため

 

テストは目的ではなく手段

・TDDの真の目的とは、健康

 変化に対応するのは健康体のコード

 変化に対応するのは健康体のチーム

 不安の克服、健康の維持

 

テストのメンテナンスがめんどくさい→ 不吉な前兆

たくさん直さないといけない時は、実装のテストになる

テストの変更が多い時は、テストの書き方がよくない

仕様変更に対してのテストがめんどくさい、というのはTDDにとっては言語道断

カスタマイズしたテストフレームワークを独自に作っていく

  

------------------------

javascript TDD

qunit, jasmine, mocha, sinon, phantomjs

 

-------------------------

和田さんQ&A

・テストを先に書くことでストレスは感じるが、結局テストしないといけない。

 人間が出来ることを機械にさせないと。

 

・テストを書くことで実装をきれいにすることが出来る。設計を一部簡素化したり。

 気づいていなかった例外に気づけたりする

 先に書くことが駆動するということじゃない。テスト書くことでフィードバックされることが大事

 

・テストを作る設計に時間がかかってしまう

 C開発はテスト駆動開発において、ハンデをかかえている

 しかし、現在、進化が著しいのもC。仕方がない部分も大きいのでノウハウをためていくしかない

 C++はGoogleTestとかがxUnit系かな?

 

・テストが汚い

 共通化しているところとかは関数化してしまう

 テストコードのテストは実装にやらせる

 テストと実装の差が少ないうちにリファクタリングしちゃう

 

・TDDはデバッグ時間を、ほぼゼロにすることが出来る方法

 

・テストのカバレッジレベル

 カバレッジ率100を求めることではない:仕様を100%カバーしてるというわけではないため

 カバレッジ上げる作業は設計をよくしていく良い方法だが、やり過ぎるとおいしくない作業になる

eclemmaでカバレッジテスト

 

・テストデータつくるところ

 テストデータの違いだけがかけるようにして、後はFactory作ったり、パラメータ化したり、関数化することでリファクタリングする

 

・テストをリピータブルにするためには、データを統一化させておかなければいけない

 

・テストで一番大事なことは繰り返し使えること。その事前データを作ることは何よりも大事なので、DBのデータなどは必ず統一できるデータを作れるようにしておくこと。

 

テスト駆動開発は、ボトムアッププログラミング。

 1人1人のコードが全体のコードを作るような設計になる。

 そのほうが、1つ1つのクオリティが高いため、結果的にうまくいく。体感するとわかる

 テスト単体で完結しているかどうか、で独立性の高いプログラミング実装タイプになる

 

・リリース終わったもので、リファクタリングが甘いもので、なおしたいとこ見つけた場合

 Green To Greenなので、Redは考えなくてもいい

 必ずしもリファクタリングすべきでない部分は、リファクタリングしないほうがいいかも

 

・テスト名が仕様書になるので、TODOメソッドを羅列して、全部Ignoreにして、随時作っていく

 テスト駆動開発は、はじめはみんな遅い。慣れれば早くなる。

 

・テストをどこまで書けば良いか分からない

 全てのテストを自動化する必要はない

 クラス単位の動作確認は、自由にやるが、画面として組み立てた場合はブラウザからって方法などパターンはいくつかある

 どのレベルを自動化するかっていう網のレベルを決めて、どこまでjunitでやるかの決めはない

 テスト書いても安心できないっていう不安は良いこと。テスト技法を学ぶ段階。

 テスト駆動開発の先に、どこまで書けば良いのか、漏れを知る必要あるのか、っていうのがある

 そういう研究が日本で盛ん。書籍で6つくらいをテストしたら全パターン網羅するというようなテスト技法がある。(参考本:ソフトウェアテスト技法ドリル)

  

---------------------------------

MTI(中川さん)

テスト駆動開発導入前

 リリース時に大量のマンパワーを使ってテストを実施するか、デグレで障害ということも。。

・テストコードは品質保証のために書いていた

 プロダクトコードからテストすると、書きにくいという時も。仕様変更でテスト壊れる。。

・メリット

 テストコードが増えた。

 テストが壊れにくくなった

 プロダクトコードが読みやすくなった

 コードの再利用がしやすくなった

 安心して他の人が書いたコードを修正できるようになった

・難しいところ

 従来開発スタイルからの頭の切り替え

 時間的な制約

 レガシーコードとの戦い

 

---------------------------------

レガシーコードでTDD力を高めよう(@PoohSunny)

・レガシーコード改善ガイド(本)

・一部の変更が全てに影響(=レガシーコード)

 テストが書きにくい構造(実践しようにも…)

・レガシーコードの改善じゃなく、自分のTDD力を高めよう、っていう考え方

 TDDから:が最適解とは限らないため、TDDで改善は考えない

・変更は小さいところからやる

・スプラウトメソッド

  

---------------------------------

濃霧と地雷原(アルティメット 有野さん)

・不安解消、見える化、少しずつ

・Cucumberによる仕様の見える化とテストの先行実装

 HTMLレポート見るとなんとなくわかる

  

---------------------------------

質問

・従来型の開発で切り替えれない人に対してTDDしてもらう方法は?

 経験してもらうことが大事

 体験型のワークショップを社内でやったり、実際にテストコードを入れていくとかしかない

 やってもらって、やりにくいと思われたら、こういう風だからやりづらいんですよっていうことを伝えてあげる。品質向上のためじゃなく安心のためにやることを伝える。

 テストコードを書くのに懸念する人に対しては、トップダウン形式で落としている

 

テスト駆動開発を始めた時の生産性を下げない工夫は?

 最初は3割くらいは生産性が下がる。下がった分は後でカバーする。マネジメント層の理解が大事

 ただ、それがやれていくと、効率は上がって、開発者の不安は取り除かれる

 レガシーコードを分けてテストしたら逆にデバッグ工数減らせる。が、全体的には落ちるので説得も大事

 

・TDDになった場合にコードレビューする際の観点

 テストケース単体のレビューは必要。

 何がしたいテストなのか不明確な場合は明確にする

 テスト対象がどこまでの操作をするのかを見る

 小さい単位でテストができているかどうかに注目する

 テストコードが1メソッドで大量にあると、何やってるのか分からないので色々やってるところは指摘する

 

・全員がテスト駆動しているのか?

 全員やってるわけではないが、テストコードを書くようになった

 

・テスト駆動が会社に広まった時、日常的にそういう会話になったか?

 部署によって違うが、自分のところは、環境作るところからTDDでやろうみたいになった

 

・TDDで内部設計など、テスト駆動されるようになったか?

 大きいとこを全部テスト駆動は出来ない

 合わないとこは、設計で決めて、フレームワーク選定などした上で、TDD開発をしていく

 内部設計に合わせてシステムテストするなど、内容に合わせてやり方を変えていく

 ある程度出来てからTDDで入る

 Cucumberで外部仕様を決めて、その中身を実装していく

 

---------------------------------

境界なき現場を、行け(市谷さん)パパンダさん(http://about.me/papanda0806

明日からやるのは実際には難しいという人のための昔話

 

日常のしごとをこなす技術だけあればいいんだっけ?

本「達人プログラマー」

常にあなたの知識ポートフォリオに投資すること

毎年少なくとも一つの言語を学習する

 

デスマーチ

誰もが失敗するとわかっていて、それでもなお律儀に進み続けていくプロジェクト

 

理想とはたどり着くべき場所のことではなく、ありたい姿に向かい続けることなんだ!

 

理想:正しいものを正しく作る

 

ソフトウェアを創りあげるもの

・プロジェクト、ユーザ、チーム、顧客

 どういうルールで、誰のために、誰が、誰と、「何を」作るか

neo4jの導入

macでneo4jを導入してみる

参考:http://oss.infoscience.co.jp/neo4j/wiki.neo4j.org/content/Getting_Started_With_Neo4j_Server.html

 

1. ダウンロード

http://oss.infoscience.co.jp/neo4j/neo4j.org/index.html

ここからダウンロード

 

2. 展開後、neo4j起動

$ bin/neo4j start

 

3. curlで叩いてみる

$ curl -H Accept:application/json http://localhost:7474/db/data/
{
  "relationship_index" : "http://localhost:7474/db/data/index/relationship",
  "node" : "http://localhost:7474/db/data/node",
  "relationship_types" : "http://localhost:7474/db/data/relationship/types",
  "extensions_info" : "http://localhost:7474/db/data/ext",
  "node_index" : "http://localhost:7474/db/data/index/node",
  "reference_node" : "http://localhost:7474/db/data/node/0",
  "extensions" : {
  }
 

4. 新しいNodeを作成する

$ curl -H Accept:application/json -X POST http://localhost:7474/db/data/node
{
  "outgoing_relationships" : "http://localhost:7474/db/data/node/1/relationships/out",
  "data" : {
  },
  "traverse" : "http://localhost:7474/db/data/node/1/traverse/{returnType}",
  "all_typed_relationships" : "http://localhost:7474/db/data/node/1/relationships/all/{-list|&|types}",
  "property" : "http://localhost:7474/db/data/node/1/properties/{key}",
  "self" : "http://localhost:7474/db/data/node/1",
  "properties" : "http://localhost:7474/db/data/node/1/properties",
  "outgoing_typed_relationships" : "http://localhost:7474/db/data/node/1/relationships/out/{-list|&|types}",
  "incoming_relationships" : "http://localhost:7474/db/data/node/1/relationships/in",
  "extensions" : {
  },
  "create_relationship" : "http://localhost:7474/db/data/node/1/relationships",
  "all_relationships" : "http://localhost:7474/db/data/node/1/relationships/all",
  "incoming_typed_relationships" : "http://localhost:7474/db/data/node/1/relationships/in/{-list|&|types}"
}

5. リファレンスノードから、新しく作成したノードにつながるリレーションを新しく作成

$ curl -H Content-type:application/json -X POST \
>   -d '{"to": "http://localhost:7474/db/data/node/1", "type": "KNOWS"}' \
>   http://localhost:7474/db/data/node/0/relationships
{
  "start" : "http://localhost:7474/db/data/node/0",
  "data" : {
  },
  "self" : "http://localhost:7474/db/data/relationship/0",
  "property" : "http://localhost:7474/db/data/relationship/0/properties/{key}",
  "properties" : "http://localhost:7474/db/data/relationship/0/properties",
  "type" : "KNOWS",
  "extensions" : {
  },
  "end" : "http://localhost:7474/db/data/node/1"
}

6. 管理ツールにアクセス

http://localhost:7474/webadmin

 

次はJavaでNeo4jサーバを使おうと思います。

http://oss.infoscience.co.jp/neo4j/wiki.neo4j.org/content/Using_the_Neo4j_Server_with_Java.html

Jenkinsカンファレンスに参加してきました

法政大学で行われたJenkinsカンファレンスに参加してきました。

http://connpass.com/event/467/

 

以下、参加してのメモになります。

何書いてるのかいまいち分からない部分もあるかもですが、とりあえず。

 

Jenkins カンファレンス 20120729

 

**********************

12:30 - 自動受け入れテストから継続デリバリーまで

 

html publisher plugin

結果を通してメンバ全員に周知を徹底させる

 

Cobetura Plugin 

Jenkinsにプロジェクトのルールを自動的に強制させることができる

 

コードをチェックインして、テストを通し、スナップショットビルドを作ります。

そして受け入れテスト、コードメトリックス測定をして、リリース広報の生成まですること。

 

mavenのリリースプラグインでは人間の決めたタイミングでリリース候補バイナリを生成する

mavenのフローでは、場合によっては出戻りが発生してまたテスト実行に時間がかかることがあります

戦略としては、mvn version:set を使うこと

snapshotビルドを作り続けるけれども、これと決めたバージョンをリリースバージョンとしてしまうようなアプローチ

snapshotビルドではなくリリースバージョンと決めたあとは、artifactoryやnexusプラグイン(mavenリポジトリと連携させるためのプラグイン)を使って出力できます

 

ビルドプレセスを可視化、見える化したい

一定のコミットがどのプロセスまで進んだのか、どこで失敗したのかなどを見える化するのが重要

 

まとめ:

品質のテスト重要 => それによって確信を得ることができる。出荷可能であると。

受け入れテストが通っており、その受け入れテストはビジネス価値をもたらすストーリーに基づいている。

なのでコードはビジネス価値をもたらすことが保証されている。

 

----

経験的に自動化できないテストは、ユーザシナリオ、受け入れテストで「マニュアル」とマークしておくが、

その「マニュアル」とマークされているテストの割合は非常に少ない。マニュアルテストの結果のフィードバックを自動化することなども重要。

 

アプリケーションの中の設定(log4jとか)に依存をアプリケーションに閉じ込められない場合、どういうアプローチが良いか?

ー> 設定を外出しするよう心がける。同じバイナリをデプロイしつつ、デプロイ環境ではそれぞれ別の設定を運用するような。

 

**********************

13:30 - 開発以外でのJenkins活用方法

 

開発者以外の人にJenkins使ってもらう話

DTP -> 割付などの作業をコンピュータ上で行い、プリンタ出力すること

 

dprooFS

PDFをドラッグ&ドロップ

PDFの差分が見える

 

DTPと開発の共通点

人間がやらないといけないこともあるが、人間やらなくてもいいこともある。

イテレーションする

 

プラグインの活用

実行結果を通知:IRC Plugin

成果物をアップロード:Publish over XXX Plugin, Groovy Postbuild Plugin(ビルド履歴にアイコン表示とか)

 

権限周りの設定

 

APIを利用する

WebアプリをフロントエンドにしてバックエンドにJenkinsを使う

Webアプリ側では使いやすいUIの提供やJenkins側で管理しないデータを扱う

Jenkinsのスレーブ機能で処理が増えても簡単にクラスタを増やすことができる

 

リモートAPI(/api, /api/json)

 

CLI(コマンドライン・インタフェース)

$ java -jar jenkins-cli.jar -s http://jenkins-server/ groovy hello.groovy

プログラムからの利用

 

プラグインを作る

特定の処理をプラグイン化

hudson.tasks.Builderを継承して実装

Builderの実装はたくさんあるので、他のプラグインのソースを見ればわかるはず

 

Groovy Remote Control

Jenkinsとの連携をよりやりやすくするためのプラグイン

 

**********************

14:30 - 多段階ビルド事例

 

たくさんのプロジェクト

gitプラグインを使ってなかったので変更の検出が難しかった

変更がないコードなども繰り返しビルドしたり、記録が残るなどしてしまった。

→ ビルドの状況が「見える化」されていなかった。問題発生した際のトラブルシューティングが非常に難しかった

 

今ではコンポネントごと、プラットフォームごとにジョブを分けている。

現在のパッケージはすべてのコンポーネントの最新状態が必ず反映されている。

 

今でもすべてのコンポーネントを週次でフルビルドしている。コンポネントの依存順に。

可能であれば、依存関係のないコンポーネント同士を並行してビルドしている

フルビルドが完了すれば新しいリポジトリが作成される

 

新しいプロセスで助かっているのは、これまではPythonの巨大な1スクリプトであったが、

今では個別にビルド方法を調整できる。

以前より素早くチューニングできる。コードが変更されたらそれだけを個別に自動的にビルドできる。

1つのスクリプトになっていないので、何か失敗したらそこから開始することが容易

 

ジョブを分けることで何が起きているのか、どこに不具合があるのか「見える化」されるのが良い

ビルドの並行化でフルビルド時間が大幅に短縮された。結果、より改善にそそぐ余裕が生まれた。

 

 

可能な限り、広く使われている実績のあるプラグインを使っている。オレオレスクリプトではなく。

ローカルビルド環境を作ってしまえばEC2よりも安い

 

- Parameterized Trigger Plugin

汎用のパッケージングジョブを定義することができる。

コンポーネント×プラットフォームの組み合わせごとにたくさんジョブを定義する必要がない

このプラグインのすごく便利なのは、ビルドステップを定義すれば下層のビルドが自動的に走り、それが終わるのを待ってくれる

→ そして新しいアクションをまた自動的に実行してくれる

我々はすべてのプラットフォームでテストを実行し、その実行結果をまたなければならない。

このプラグインで非常に効率化できる

 

- Conditional Build Step Plugin

条件によって異なるビルドステップを実行させることができる。

色々なプラグインが個別の「token」を持っており、条件によって「token」で識別されるプラグインを実行できる

parametarized trigger plugin で色々なプラットフォームのビルドをするのは楽になったが、

例えばフルビルドでなく特定のコンポーネントだけをビルドしたい場合など便利

 

- jclouds plguin

EC2プラグインと似ているが、あらゆるクラウドプロバイダーに対応している。EC2を使わずプライベートクラウドでテストすることも。

"node pooling"機能でビルドごとにインスタンスをあげたりすることなく、既に起動済みのインスタンスでビルドを

走らせることができ、時間をセーブできる。

 

- Muti-SCM plugin

jenkins git plugin は一つのjobから複数のgitリポジトリからcheck outできない

multi-SCM pluginでは一つのJenkins jobから複数のSCMを参照できる

gitのsubmoduleで別のリポジトリを参照してる場合などに便利

 

- Description Setter plugin

正規表現でビルドログをさらい、jobのdescriptionを設定できる。

単に失敗した、ではなくHadoopが原因で失敗、とか簡単にわかるようになる

 

- Associated Files plugin

ビルドページから、そのビルドに紐付くファイルがどこにあるか一覧できるようになる。

ステージング用のファイルはここにある、とか。

ビルドが削除された場合、関連するファイルを一緒に削除してくれる。

 

Jenkins固有の話ではないが、、

S3を使わないのでバイナリのステージング環境は自分で容易しなければいけない。

 

- Cloudbees Jenkins Enterplise Template plugin

jobのテンプレートを定義できる。テンプレーを変更すればそれが既にあるjobに反映される。

コンポーネントは違うが、ほぼ同じ設定のjobがたくさんある場合便利

 

- All Changes plugin

parameterized Trigger plugin で実行されたビルド結果(の違いのある部分)をまとめて一覧表示してくれる

 

- Github plugin

ビルドをポーリングベースではなく、post-service hook(git pushしたら発動する)で、Jenkinsのjobを開始できる。

 

Q. Jenkinsのバージョンはどこかに記録してますか?

job config history plugin が好きで、どんな変更が行われたのか、誰が変更したのか記録されます。

それと、gitのスクリプトがあって、jenkinsのconfigの履歴を管理します。ただ、そこは改善の余地があると思っています。

 

Q. Cloudbees templateプラグインについて便利そう。高そう・・・

川口さんに聞くべし。高くないはず。他にもCloudbeesから色々便利なのが出てます

 

Q. job config history plugin、jenkinsのconfigをgitで管理する場合、その保存先は?

ソースコードとは違うリポジトリに保存している。Job DSL pluginではgroovyでジョブの設定を管理できる。

それを使わなければいけなかったのは、一箇所に設定を保存しておけば良くなるので楽だから。

単純に設定を保存してgitに保存するだけでは、履歴を確認するのが難しい。

 

**********************

15:30 - 反復可能なデリバリーによる常時新築システム @ohtaket

 

手順書がExcelにあって人間が作業する。。。。のがよく見られる

→ 変更があっても更新されない

 

cleanの既存プラクティス

$make all -> $ make clean all (失敗しにくい)

Win 9xをN月おきにクリーンインストール

 

デプロイ工数がめちゃかかってた

→ さぼり

→ 既存のデプロイには差分だけ適用。新規顧客を探しに行きにくくなる。

→ Jenkinsをデプロイで使うぞ!

 

ExcelをChefに置き換えた(Chef Solo)。記述が簡単。セットアップが簡単。

Jenkins側で必要な事項

1. パッケージの集約

OSバージョンとビットごとにビルドサーバ容易

Matrix Jobでビルド

ビルド後にパッケージ集約ジョブを呼び出す(Parameterized Trigger Plugin)

buildジョブからアーティファクトをコピー(Copy Artifact Plugin)

 

2. マシンの容易

・各種Cloud Plugin

- Amazon EC2 Plugin , Delta Cloud API Plugin, jClouds Plugin , vSphere Cloud Plugin ...

任意のタイミングでのVM制御が必要

Java, Git, Ruby, Chef-soloをインストールしたテンプレートVMを用意

テンプレートからVMを作りそこにデプロイ

電源を入れるジョブの例(Windows PowerShell

 

3. デプロイの実行

ノードをまたがって逐次実行するジョブ

Parameterized Trigger Plugin + NodeLabel Parameter Plugin

親ジョブと子ジョブのパラメータの定義

PaaSバックエンドシステムは複数台

Parameterized Triggerで各スレーブにデプロイ

開発環境以外の環境にも同じスクリプトでデプロイ

 

"スローデプロイ問題"

デプロイに60分かかる

スローテスト問題はテストケースを分割して並列実行が一つの解

 

4. VMスナップショット

VMをテンプレートから作る代わりにスナップショットへの復元

10分から3分に。

制約は増えるが速度のほうが重要

 

5. インターネットからの分離

インターネットからのrpmやgemのダウンロードが遅いので、事前にアーティファクト化

45分から2分に

外部影響の原因追求

インターネット接続がない環境へのデプロイ

 

6. 自前と既成の分割と冪等性

自前パッケージ - 自前のソースからbuildするパッケージ

既成パッケージ - 他者が作ったパッケージ

自前と既成で性質が異なるため、デプロイスクリプトを分割

冪等なデプロイスクリプト

[冪等でない]

$ tar zxf foo.tar.gz

[冪等]

$ rm -rf foo

$ tar zxf foo.tar.gz

 

7. 早い失敗を目指す

パイプラインのなるべく早い段階で黄や赤になるように(Fail fast)

設定ファイルではなく、設定ファイル作成プログラムを作成(Chefのレシピとテンプレートでconfigに失敗が起きない)

 

8. 環境の使い捨て

本番と同じ環境で開発

高速なデプロイと冪等なスクリプトのおかげ

 

9. ブランチごとのデプロイ

毎回新規に作られる環境による安心感

デプロイまで行うので試用ができる

 

まとめ

自動化できるものは自動化

・buildだけでなくデリバリーも自動化しましょう

・クリーンと冪等で反復可能に。

・自動化だけで終わらずに、高速化を検討すべき

・迅速なフィードバック

・速ければ使い方も変わる

・本来はCIサーバだが、CI以外もこなせる。執事を遣い倒そう

 

**********************

16:30 - LT大会

 

■ 書籍執筆で継続的デリバリー @kaorun55

SPHINX - Python Documentation Generator

JenkinsでPDF化とかを。

CloudBeesで。Javaしか動かない。Virtual Python というのがあるらしい。

 

■ The Jenkins English Community

英語圏のコミュニティは英語圏と西ヨーロッパが多い、アメリカ、フランス、ドイツ。

IRCでコミュニケーションが多い。あとML。jenkins-user-devも。

↑ プロジェクトMTGがIRCで行われているから。twitterは英語圏ではコミュニケーション用途としては使われにくい

 

■ Flash[AS3]でもJenkins @uzzu

Jenkins環境で動くの?動く。

Maven3プロジェクト

JenkinsサーバにFlashPlayerインストール

Flexmojosというmavenのプラグインを利用

コンパイルオプション、依存関係はpom.xmlに書く

Headress Serverでは追加作業。ソフトウェア入れたりPlugin追加したり。

vncserver + xvfbを利用

ジョブ開始時にjenkinsユーザでVNCサーバにリモートログイン。FlashPlayer実行

テスト実行時間遅い、64ビット環境で動作が不安定

 

■ ふつうのSIerのJenkinsのある暮らし @setoazusa

ビルドパイプライン

サポートしている環境の組み合わせが多少なことが特徴

Join Pluginを使ってる

WebコンテナへのデプロイはCargoを使用

Seleniumによるテスト実行。スキーママイグレーションも実施。リリース後Seleniumでのスモークテストも。

成果物が1回のビルドで500MB。バックアップのアーカイブが展開できない。。。

 

■ 運用でも使えるJenkins @cynipe

Jenkinsのイメージ

 開発、ビルドに使うもの。テスト走らせるもの

なんらかのイベントトリガーで実行:記録してくれるもの

運用って日次、月次のバッチやバックアップをとったり。

cronでよくあること:エラーが起きてたのに気づかないとか。。処理時間の統計知りたいとか。。

エラー通知:メールはもちろん。IP Messanger、IRC、Yammerでも可能

スレーブ機能を活用することで各ジョブを回すことができる

Join Plugin, Build Flow Pluginとかで色々できる

jenkins-capistrlo?を作ってます

 

dartをはじめる

http://www.dartlang.org/

公式サイトによると、Dartは構造化されたWebアプリケーションを作成するための新たなクラスベースのプログラミング言語と書かれています。さらに、シンプルさ、効率性、スケーラビリティを目標に開発されたとのことです。

 

とりあえず時間見つけてやっていこう。ひとまずこれだけw

node.js(jade+express+socket.io)でチャットアプリを作る

参考にしたのはこちらの資料。分かりやすい。

http://miyukki.mesolabs.com/

 

前回のexpressでひと通り入れた続き。socket.ioの部分を追加する

 

package.jsonを以下のようにしてinstall

{
    "name": "application-name"
  , "version": "0.0.1"
  , "private": true
  , "dependencies": {
      "express": "2.5.8"
    , "jade": ">= 0.0.1"
    , "socket.io": ">= 0.7"
  }
}

 

app.jsに以下を追加

// socket.io

var io = require('socket.io').listen(app);
var chatCount = 0;
var messages = []; // あとで使う
var chat = io.of('/chat').on('connection', function(socket) {
  chatCount++;
  chat.emit('count', {count: chatCount});

  // ブラウザからチャットテキストを受信した時の処理
  messages.forEach(function(data) {
    socket.emit('message', data);
  });
  socket.on('message', function(data) {
    data.timestamp = new Date().getTime();
    chat.emit('message', data);
    var length = messages.push(data);
    if (length > 100) {
      messages.shift();
    }
  });

  socket.on('disconnect', function() {
    chatCount--;
    chat.emit('count', {count: chatCount});
  });
});

 

client.jsを下記のように修正

var chat = io.connect('http://localhost:3000/chat');
chat.on('connect', function() {
  chat.on('count', function(data) {
    $('#count').text(data.count);
  });
  chat.on('message', function(data) {
    // サーバからチャットテキストを受信した時の処理
    var date = new Date(data.timestamp);
    $('#chat').append(
      '<div class="chatlog"><p>'
      + escape(data.name)
      + ': '
      + escape(data.text)
      + '</p><span class="date">'
      + date.toString()
      + '</span></div>');
    $('#chat').scrollTop(1000000);
  });
});

// サーバへチャットテキストを送信する処理
function send() {
  var name = $('#name').val();
  var text = $('#text').val();
  if (text && name) {
    chat.emit('message', {name: name, text: text});
    $('#text').val('');
  }
}

 

viewは以下のように修正

index.jade

h1= title
p 現在接続している人は
  span#count
  人います
#chat
form#form(onsubmit='send(); return false;')
  input#name(type='text', placeholder='Name')
  input#text(type='text', autocomplete='off')
  input(type='submit', value='送信')

layout.jade

!!!
html
  head
    title= title
    link(rel='stylesheet', href='/stylesheets/style.css')
    script(type='text/javascript', src='http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js')
    //script(type='text/javascript', src='http://cdn.socket.io/stable/socket.io.js')  // これだとダメ!
    script(type='text/javascript', src='http://localhost:3000/socket.io/socket.io.js')
    script(type='text/javascript', src='/javascripts/client.js')
  body!= body

 

複数タブなどで開くと、カウントが増えてチャットもできる

http://localhost:3000/

expressを試す

node.jsのWebアプリケーションフレームワークである、expressを試す

参考: http://d.hatena.ne.jp/t_43z/20101020/1287545961

npmでinstall 

$ sudo npm install -g express

以下を実行するだけで必要なファイルやディレクトリが作成される 

$ express sample

   create : sample
   create : sample/package.json
   create : sample/app.js
   create : sample/public
   create : sample/public/javascripts
   create : sample/public/images
   create : sample/public/stylesheets
   create : sample/public/stylesheets/style.css
   create : sample/routes
   create : sample/routes/index.js
   create : sample/views
   create : sample/views/layout.jade
   create : sample/views/index.jade

   dont forget to install dependencies:
   $ cd sample && npm install

 書かれてある通りに、sampleディレクトリに移動後、npm installを行った後、アプリ実行

$ node app.js 
Express server listening on port 3000 in development mode

 ブラウザアクセス

http://localhost:3000

Express

Welcome to Express

と表示されていればOK!

 


バージョンの違いかな、参考にしたサイトとapp.jsの中身がちょっと違った

/**
 * Module dependencies.
 */

var express = require('express')
  , routes = require('./routes');

var app = module.exports = express.createServer();

// Configuration

app.configure(function(){
  app.set('views', __dirname + '/views');
  app.set('view engine', 'jade');
  app.use(express.bodyParser());
  app.use(express.methodOverride());
  app.use(app.router);
  app.use(express.static(__dirname + '/public'));
});

app.configure('development', function(){
  app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
});

app.configure('production', function(){
  app.use(express.errorHandler());
});

// Routes

app.get('/', routes.index);

app.listen(3000);
console.log("Express server listening on port %d in %s mode", app.address().port, app.settings.env);

cassandraとnode.jsでアプリケーションを作ってみる

どうも、天然パーマのtyorikanです。

 

CassandraとNode.jsに興味があって、Clientあるかな?と思ったら予想通りありました。

cassandra-node

これを使ってアプリケーションを作っていきたいなと思っています。

 

まずはセットアップ。開発環境は、mac-10.6.8

バージョンは以下をインストール。事前にnode.js(0.6.10)をインストール済。

 

apache-cassandra-1.0.7

cassandra-client-0.8.2

$ npm install cassandra-client

 

Downloadしたapache-cassandraを設置

$ mv ~/Downloads/apache-cassandra-1.0.7 /usr/local/src/
$ sudo ln -s  /usr/local/src/apache-cassandra-1.0.7 /var/lib/cassandra

 

cassandra起動

$ cd /var/lib/cassandra/bin
$ ./cassandra -f

 

以下のプログラムを実行

$ vim select.js
var http = require('http');
var Connection = require('cassandra-client/node-cassandra-client').Connection;

var server = http.createServer(
    function (request, response) {
    response.writeHead(200, {'Content-Type': 'text/plain'});
    var con = new Connection({host:'localhost', port:9160,keyspace:'KeySpace1'});
    con.connect(function(err) {
        if (err) {
            response.write("err1:"+err);
            response.end();
        } else {
            con.execute('SELECT * FROM users ', [ ], function (err, rows) {
                if (err) {
                    response.write("err2:"+err);
                } else {
                    /**
                     * record1
                     */
                    // column_name
                    response.write(rows[0].cols[0].name + ":");
                    // column_value
                    response.write(rows[0].cols[0].value + ", ");

                    // column_name
                    response.write(rows[0].cols[1].name + ":");
                    // column_value
                    response.write(rows[0].cols[1].value + ".");

                    response.write("   ");

                    /**
                     * record2
                     */
                    // column_name
                    response.write(rows[1].cols[0].name + ":");
                    // column_value
                    response.write(rows[1].cols[0].value + ", ");

                    // column_name
                    response.write(rows[1].cols[1].name + ":");
                    // column_value
                    response.write(rows[1].cols[1].value + ".");
                }
                response.end();
            });
        }
    });
    }
).listen(8124);
$ node select.js 
The "sys" module is now called "util". It should have a similar interface.

 

ブラウザからアクセス

http://127.0.0.1:8124/

err1:NotFoundException: ColumnFamily or Keyspace does not exist

Keyspace作ってないから、ねーよ!って言われる。入れたらデータ取得されるはず。

 

 登録してみよう

まずはKeyspaceを作成

$ /var/lib/cassandra/bin/cassandra-cli -host localhost
[default@unknown] create keyspace KeySpace1;
[default@unknown] use KeySpace1;

 

ColumnFamilyの作成 

CREATE COLUMN FAMILY users
WITH comparator = UTF8Type
AND key_validation_class = UTF8Type
AND column_metadata = [
{column_name: name, validation_class: UTF8Type}
{column_name: value, validation_class: UTF8Type}
];

 

データ登録

[default@KeySpace1] set users['tyorikan']['name'] = 'tyorikanName';  
Value inserted.
Elapsed time: 12 msec(s).
[default@KeySpace1] set users['tyorikan']['value'] = 'tenpa';           
Value inserted.
Elapsed time: 1 msec(s).
[default@KeySpace1] set users['tyorikan2']['name'] = 'tyorikanName2';
Value inserted.
Elapsed time: 1 msec(s).
[default@KeySpace1] set users['tyorikan2']['value'] = 'tenpa2';           
Value inserted.
Elapsed time: 1 msec(s).

 

もう1度取得してみる

$ node select.js 
The "sys" module is now called "util". It should have a similar interface.

ブラウザからアクセス

http://127.0.0.1:8124/

 

name:tyorikanName, value:tenpa.   name:tyorikanName2, value:tenpa2.

 

いいね。CassandraのRead/Write速度は、0.xの頃から比べて抜群によくなったらしい。

性能比較して、良さげなら実務で使えていけたらいいな。