2013年2月11日月曜日

ブログ移行しました

Markdownで更新できる環境が欲しかったので以前までのBloggerからGithub+Octopress環境に移行してみました。

新しいブログはこちら。 - Thinking megane - 

Ruby, Vim, Java, Android に関する情報を公開していきます。

2012年9月13日木曜日

git pull 時の rebase オプションのススメ


今日は、Git で複数人作業を行う際に共有リポジトリから pull する際の rebase オプションの必要性について検討してみました。

タイトルで結果は想像つくような気がしますが、順を追ってみましょう。

  1. git pull でやってること
  2. merge と rebase
  3. git pull と git pull --rebase
  4. まとめ



  1. git pull でやってること

git pull コマンドは、fetch, merge をまとめて実行しています。
つまり、リモートブランチの最新のコミット情報をローカルトラッキングブランチへ持ってきて(fetch)、持ってきた最新のコミット情報とローカルブランチをマージ(merge)します。

参考:3.5 Git のブランチ機能 - リモートブランチ


  2. merge と rebase

ブランチを統合するには、マージの他にリベースがあります。

mergeでは、ブランチAコミット1から派生したブランチA2コミット2とブランチA3コミット3を統合した場合、統合結果のコミットオブジェクト4が統合先のブランチ上に作成されます。

これに対し、リベースでは、その名のとおり、基点を移動するかのような挙動をとります。
つまり、コミット3の基点がコミット1ではなく、コミット2とし、コミット2に対してコミット3の差分を適用します。

参考:3.6 Git のブランチ機能 - リベース


  3. git pull と git pull --rebase

共有リポジトリから資産を取得するのに通常は、git pull を利用しますが、このコマンドにはオプションとして --rebase オプションが用意されています。

rebase オプションをつけた場合は、fetch後の挙動がmergeではなく、rebaseとなります。

以下、それぞれの挙動と、それによるコミット履歴の差を確認してみました。

環境

確認用に以下のシンプルな構成で分散環境を構築します。
  • リモートリポジトリ:gitPullTest.git
  • ローカルリポジトリ(Alice):gitPullAlice
  • ローカルリポジトリ(Bob):gitPullBob
  • バージョン管理対象:gitPullTest.txt

以下の動作検証を行います。
  • リポジトリは全てローカルマシン上に作成する。
  • Alice役とBob役がそれぞれ独自の編集を行う。
  • Aliceが先にプッシュし、Bobは、git pull、git pull --rebase で変更を取り込む。
  • 例を単純にするため、masterブランチのみとする(git flowは利用しない)

準備(共有リポジトリ、Alice, Bob リポジトリ作成と内容の同期)


git pull(マージによるコミット)


git pull --rebase(リベース)


結果(コミット履歴)







コミットログ最下部は、初期登録時のコミット
下部2番目から4番目までが、git pull によるコミット履歴(3コミット)
下部5番目から6番目までが、git pull --rebase によるコミット履歴(2コミット)


  4. まとめ

このように、マージの場合、マージコミット分が履歴に残るのに対し、リベースでは(例えコンフリクトが発生したとしても)コミット履歴は直線的に保たれます。
このことから、共有リポジトリを介した頻繁に資産のやり取りが発生するような開発ではgit pull 時のrebaseオプションは以下のように使い分けるべきだと考えられます。

  • 通常の資産共有の一環としてのgit pull では、リベースを用いる。
  • 統合した事実を残しておくべき場合(リリースブランチへの機能追加など)はマージを用いる。


やはり、通常開発時はリベースを用いることのメリットのほうが多いと思います。
(資産のやり取りごとに不要なマージコミットができるのは避けたいはず)
また、マージを用いるべき箇所に関してはgit-flowなどの運用フローを採用することで意識しないようにするほうが確実です。

git-flowに関しては、以下を参考にしてください。
ゼロからわかるgit-flow

Gitに関しては、色々な運用方法があるので、他にもよいプラクティスがあれば教えてもらえればうれしいです。

ではでは。

2012年8月12日日曜日

エンジニアとしてのアイアンマンがステキな件

DVDでアイアンマンを見た。


















主人公トニースタークが、捕虜になり脱出のためにリアクターとスーツを開発、
その後、人工知能を搭載した試作機を経て実用機を完成させ、陰謀に立ち向かうストーリー。


ストーリの感想はまた別の機会として(話や役者さんも個人的には満足でした)
スーツの開発を進めていく、エンジニアとしてのアイアンマンがステキだった。

捕虜の環境で開発した最初のスーツは全て手作業。
組み立ても、装着も、ウェポン発動のギミックも全て。

でもスーツを洗練していくのにあわせて、組み立ても装着も自動化されていく。
組み立ては設計をインプットして5時間後に塗装済みのものが用意され、
複雑な装着もロボットアームが的確にこなしていく。

制御の複雑化には人工知能で対応。
音声制御で、主人公は自分の動きに専念する。



プロダクトの洗練において周辺環境含め、常に自動化、省力化を念頭におく。
これ大事だと思う。
そうでなければ、いつまでたったって本質に注力することなんてできない。

それはトニースタークのような天才的な頭脳でなくても、やり方として使っていけることで、
システム開発でもテスト自動化や継続的デリバリーを使って、本質に注力していけたらなと思うのです。

以上、そんなことを考えさせられたアイアンマンでした。



着陸時の姿勢、かわいいですよね、アイアンマンw

2012年8月11日土曜日

SwimmyStudy #9 Jenkins実践入門 vol.3 に行ってきました

8/8(水)にSwimmyStudy #9 Jenkins実践入門 vol.3 に行ってきました。
SwimmyStudy #9 Jenkins実践入門 vol.3

書籍「Jenkins実践入門 ~ ビルド・テスト・デプロイを自動化する技術」をもとにした勉強会です。
現在、初級者向け、初中級者向けのグループに分かれてそれぞれが書籍ベース、実践ベースで勉強会を行っています。

自分はAndroid開発で利用経験があるので初中級者向けに参加しています。
以下、主に初中級者向けグループに関する参加レポートです。

  1. 初中級者向けグループ(JFK)概要
  2. 初中級者向けグループ(JFK)実施内容
  3. 所感


  1. 初中級者向けグループ(JFK)概要

  • Jenkins経験者が中心となって、Jenkinsとバージョン管理、バグ管理のシステムと組み合わせた効果的な開発環境とルールづくりを模索していく。
  • バージョン管理には、Gitとgit-flow、バグ管理にはRedmineを想定しており、複数人の開発者と管理者による疑似プロジェクトとして上記環境構築とルールづくりを検討することとする。
  • なお、プロジェクト資産は、CakePHPによるサンプルブログシステムを利用する。

今回は、JFKでの第一回ということで、上記疑似プロジェクトに基づき、バージョン管理システムとJenkins連携部分を検討しました。


  2. 初中級者向けグループ(JFK)実施内容

LT

バージョン管理システムとしてGitとgit-flowを採用するにあたり、以下のLTを行い、前提知識を合わせました。
ゼロからわかるgit-flow

Git, git-flow実践

サンプルシステムを用いながら、git-flowのフィーチャー、リリース作業を複数人で実践しました。


課題

  • プロジェクトで用いるサンプルブログシステムが主にDB周りで起動できなかったため、急遽、簡易的なテキストファイルを対象としたバージョン管理を行うことになった。
    [対策]:次回、DBをMySQLからSQLiteに変更して環境依存部分を極力減らす。
  • git-flowまわりの経験不足もあり、複数人でのブランチのマージ、コミットで時間を要してしまった。
    [対策]:git-flowまわりのノウハウを増やす(参考:Git-Flow-Example
    [対策]:複数人で行う場合の構成を再度検討する必要がある。(後述)


Jenkins連携の検討

前述の課題を踏まえてJenkins連携の検討を行いました。

  • origin/developへ各開発者が直接pushを行うと別開発者とのマージが頻発したため、各開発者ごとにoriginとなるリモートリポジトリを設け、中央originへの集約は管理者が行う。
  • git-flowのリリースブランチの開始、終了はmasterへの変更が発生するため、管理者が行う。
  • 中央originのdevelopをJenkinsと連動させ、結合テストを定期実行させる。
  • 中央originのmasterをJenkinsと連動させることを検討したが、masterへのコミット後のテストとなるため、バグがあった場合にmasterブランチを汚してしまう。
    回避策としてgit-flowのリリースブランチに対して受け入れテストを実行させる。
    テスト完了後、必要に応じてJenkins側からリリースブランチのfinishを行い、masterへのコミットを行う運用とする。
  • JFKではリモートリポジトリ間としてGit、リポジトリ間のやりとりにPullRequestを用いる。

以下、構成イメージを示す。




















次回

次回は、上記構成を実際に検証してみます。

以下の事前準備を行っておけるとベターです。
  1. GitHubのアカウント
  2. 自端末へのGit, git-flowが動作する環境。
  3. (できれば)サンプルブログアプリ(CakePHP SQLite)の動く環境。

  3. 所感

Jenkinsとの連携までは今回行けませんでしたが、事前準備としては課題等も見え有意義な会だったと思います。
やはり複数人で実際に行うことで見えてくる課題もあり、それらを(業務のタイムリミット関係なしに)検討することができるのが非常によいです。

あっという間の2時間半でした。待ちきれないので次回からスパンを短めにとることになりましたw

次回は8/29(水)です。
SwimmyStudy #10 Jenkins実践入門 vol.4 

Jenkins関連のLT大会もあるので、興味ある方はぜひ!

2012年8月9日木曜日

Android Night in Fukuoka vol.28 に行ってきました。

8/6(月)にAndroid Night in Fukuoka vol.28 に行ってきました。
Android Night in Fukuoka vol.28

今回は、参加者20名ほど。会場のAIP Cafe がものすごい暑くなりながらのNightとなりました。
内容を一応まとめておきます。
  1. 宣伝
  2. LT
  3. 所感

  1. 宣伝

今回は、以下の勉強会について宣伝がありました。

  • 日程調整中 初心者勉強会
  • 8/25(土)Android ドM(次回ペアプロ)
  • 毎週月曜日 輪講する会(Andorid高速化プログラミングの輪講)


  2. LT


@kenz_firespeedさん

Android 4.1(JellyBeans)の新機能紹介を行っていただきました。

報告内容はご本人のブログにてまとめられています。
Android Nightに参加してきました

4.1では様々な改良が加えられており、性能面でもかなり改善されているみたいなので楽しみです。
個人的には通知エリアの機能拡張が気になったので別途調べてブログにまとめてみたいなと思っています。

詳細は8/18 GDG九州in宮崎にて行うとのことですので、興味ある方は参加してみてはいかがでしょうか。


@monochromegane

自分からは、以前公開した状態保存のライブラリBundleSaver改めStateSaverの紹介を行ってきました。

振る舞いのよいAndroidアプリのために。BundleSaver。
続・振る舞いのよいAndroidアプリのために。StateSaver。
GitHub / monochromegane / BundleSaver 


GitHubのPullRequestをお待ちしておりまーす。


@yuutoさん

支部長からは、Androidで使える軽量なライブラリ(AQuery)の紹介LTがありました。

AQuery
AndroidのUI操作にまつわる各種記述を単純にするためのライブラリ。
IDを指定してビューを取得、値の設定、リスナー設定といった記述をメソッドチェーンで書くことができます。
その他、非同期通信に関しても簡潔に記載できるので、開発工数削減することができそうです。

リスナー設定等、アノテーションを利用しているので性能面は注意が必要とのこと。
ライセンスはApache2.0でした。

いつも楽しげなライブラリを紹介してくれる支部長さんに感謝。
これもまた今度使ってみたいと思います。


@kenz_firespeedさん

本日2度目のLTです。
福岡と世界をつなぐ「Hello World」プロジェクトについての構想を語っていただきました。

こちらも報告内容がご本人のブログにてまとめられています。
Android Nightに参加してきました


昨年、私もアメリカ行きましたが、やはり英語の必要性を痛感しました。
こういったプロジェクトを通じて世界とつながる機会を持っていきたいですね。




  3. 所感


固定の顔ぶれも多いですが、毎回、新しい方も参加しています。
最近感じるのは、業務でAndroidを触ったのがきっかけで参加しているかた(Web界隈の方)が増えてきていることでしょうか。それだけ世間に浸透してきたという証拠なのでうれしいことです。

趣味として個人で触っている方が減ってきた気もするので、次回のLTは、個人作成のアプリでも紹介してみようかなと思っているところです。

毎回所感に書いてますが、色んな人に知り合えるので、情報交換、収集の場にちょうど良い会です。
ここからネットワークが広がることが多いので興味のあるかたは是非参加してみてください。

-----------------------------
次回、Android Night in Fukuoka vol.29 は、9月初旬のはずです。
興味湧いた方は、お気軽にどうぞ!

ではでは。

2012年8月6日月曜日

SQLiteの高速化:クエリのトランザクションは本当に有効か測定してみた

書籍「Androidアプリ高速化プログラミング」の輪講会に参加しています。

Androidアプリ高速化プログラミング















先日の第1章の輪読の際に、クエリの高速化の項で気になった点があったので検証を行ってみました。

  1. 書籍の主張:クエリの高速化
  2. 書籍の主張:推論
  3. 性能測定してみる(条件など)
  4. 性能測定してみた
  5. まとめ(?)
  6. 参考(計測に利用したクラス)


  1. 書籍の主張:クエリの高速化

気になった記述は、以下の箇所です。

第1章 Javaコードの最適化 (P.36) 1.7.3 クエリ
複数のトランザクションを使う場合、iterateBothColumns()は61ミリ秒かかるが、iterateFirstColumn()は23ミリ秒で実行される。すべての行を1つのトランザクションにまとめると、すべての行の処理にかかる時間はさらに短くなる。iterateBothColumns()は11ミリ秒かかるが、iterateFirstColumn()は7ミリ秒で実行される。
iterateXXColumn()は、SQLiteデータベースに対してクエリを発行するメソッドであり、それぞれ、カラムを指定しない場合、する場合で処理速度に差が発生するという内容なのですが、それに対する説明で、「すべての行を1つのトランザクションにまとめると」という記載があり、性能がさらに改善する上記の記述があります。


  2. 書籍の主張:推論

上記、書籍の主張ですが、輪読会でも全レコードを一括で取得するクエリに対して、「すべての行を1つのトランザクションにまとめると」というのがイメージがつかないよねーという話になりました。

推論1:
一回のクエリでもトランザクションを制御することで処理速度が向上する(そんなバカな)


推論2:
Selectクエリでもトランザクションが開始、終了しており、複数回のクエリをひとつのトランザクションにまとめることで処理速度が向上する。

以下、各推論に対して処理速度の計測を行ってみました。


  3. 性能測定してみる(条件など)

以下の条件でクエリの性能測定を行ってみました。

環境

Android:2.3.3
機種:エミュレータ


テーブル構造

テーブル名:cheese ※世界のチーズ一覧を格納します。
レコード数:650件

カラム名
idINTEGER ※インデックスカラム
nameTEXT
originTEXT


測定パターン

いずれも全件に対するクエリを発行。
取得対象のカラムと、トランザクション制御の違いを検証します。

取得方法トランザクション制御
全レコード(一括)AutoCommitあり
全レコード(一括)AutoCommitなし
各レコードAutoCommitあり
各レコードAutoComitなし


  4. 性能測定してみた

全レコードを一括で取得















全レコードを一括で取得(Where句なしのSelect文)では、トランザクション制御を手動で行った場合のほうが、処理時間が長くなってしまいました。

いずれもクエリ回数は一回であるため、トランザクションを操作するオーバヘッドが差につながったのではないかと推測されます。

推論1は、あえなく崩れました。
それでは、書籍のトランザクションをまとめて扱うとはどういうことなのでしょうか。
おそらく、下記のパターン(推論2)のことを言っているのではないでしょうか。


全レコードを個別に取得















全レコードを個別に取得(Where句にIDを指定し、レコード数だけループで全件取得)では、トランザクション制御をループの前後のみで行った場合のほうが処理時間が短くなりました。

このことからSelect文を複数発行する場合、ひとつのトランザクションとして扱ってあげるほうが性能の向上が見込めることがわかります。

ただし、処理時間自体は、クエリの回数が増えているため、一括で取得する場合に比べて大幅に増加してしまっています。
書籍のような7ミリ秒での実行からは離れてしまいました。


  5. まとめ(?)

複数回のクエリに対してトランザクションをまとめることが処理性能に有効だということは確認できました。

ただし、検証の結果、ますます書籍の言っていることがわからなくなってしまうという情けない結果になってしまいました。とほほ…。

書籍でいうような処理速度改善の方法があればアプリに適用したいのですが…。

検証結果、書籍の内容について、アドバイス等いただければ幸いです。


  6. 参考(計測に利用したクラス)

性能測定で利用したクラスです。

これらのTaskを別途準備した計測用のクラスに渡して計測を行いました。

こういう計測を行ったほうが効果的だよというのがあればご指摘もらえればと思います。


以上です。

2012年7月24日火曜日

WindowsでGit共有リポジトリをさくっと構築

プロジェクトのGitサーバをWindows機で構築する機会があったので、簡単に手順をまとめておきます。

通常はLinuxで構築することが多いと思いますが、今回はプロジェクトの制約でWindows機を使うことになりました。

ここで紹介する手順は、小規模な社内環境を想定していますので認証、セキュリティは考慮していませんが、「最小の構成でよいから手軽に構築したい」といった場面でのご参考にしていただければと思います。

  1. 環境
  2. インストール
  3. 共有リポジトリの作成
  4. 外部接続の設定
  5. 接続確認


  1. 環境

今回、構築する環境は以下のとおりです。

  • 共有GitリポジトリはWindows機上に構築
  • GitにはmsysGitを用いる
  • 共有Gitリポジトリとの接続はgitプロトコルを用いる
  • クライアント側のGit環境は構築済みとする

接続にgitプロトコルを用いることで、SSH鍵等の準備する手順を削減しています。


  2. インストール

以下のサイトからWindows用のGit「msysGit」をダウンロードします。
msysGit

以下のようなexeファイルが対象となりますので、最新版をダウンロードしてください。
Git-1.7.XX-previewXXXXXXXX.exe

※1.7.10未満のバージョンでは、日本語ファイル名が正しく扱えないとのことなので、
1.7.10以上のものを選ぶようにしてください。

ダウンロードしたexeを実行し、インストールを行います。
インストール時に聞かれる選択肢に関しては、特に悩むところはないと思います。


  3. 共有リポジトリの作成

共有リポジトリのベース作成

今後、共有リポジトリを格納していくベースとなるフォルダを決め、該当フォルダを作成します。
ここで決めたベースを後述するGitDaemonに設定しておくことで、クライアント側からのアクセス時にベース以降を指定できるので便利になります。
(ここでは、D:¥Git¥reposをベースとします。)


共有リポジトリのフォルダ作成

先ほど作成したベース配下に、共有リポジトリとなるフォルダを作成します。
(ここでは、sample.gitを共有リポジトリとなるフォルダとします。)


共有リポジトリの初期化

作成したsample.gitフォルダを右クリック->Git Bashを選択し、以下のコマンドを入力します。
sample.gitフォルダ配下に各種ファイルが生成されたことを確認します。


  4. 外部接続の設定

外部から共有リポジトリに接続するための設定を行います。

GitDaemonの起動

gitプロトコルを用いて外部からの接続を行う際に必要となるGitDaemonサービスを起動します。

GitBashから以下のコマンドを実行します。

※都度、実行するのは煩わしいので、以下のようなバッチをスタートアップに登録するのがよいと思われます。
GitHub:Gist / RunGitDaemon.bat
各定義は、お使いの環境にあわせて変更してください。

Windowsファイヤーウォールの設定

GitDaemonが通信に利用するポートであるTCP/9418を、Windowsファイヤーウォールで受信可能にします。



  5. 接続確認

クライアント側で、以下のコマンドを実行し、接続できることを確認してください。



--------------------
以上です、Windows Git 共有リポジトリ環境の構築を行う際の参考になれば幸いです。