Archive for the ‘技術’ category

Socialtunesからメディアマーカーにお引越し

5月 6th, 2010

books
Creative Commons License photo credit: una nos lucror

長年蔵書管理に使っていたSocialtunes* モノ系ソーシャルですが、一向にサービスが改善される気配が無いのでとうとうしびれを切らして乗り換えました。サーバのレスポンスは問題なかったのですが、ブックマークレットがメンテナンスされず動かないURLが出てきたり、他サービス連携が出来なかったり、iPhoneアプリもなかったり、今後も主力で使っていくのに不安が大きすぎたのが理由です。コトノハと同じ運営元ですが、あちらは今でもメンテナンスがされているのでしょうか…

さて移行ですが、ちょっとしたスクリプトと正規表現を使ってSocialtunesのペタページからAmazonのASINを取り出してCSVファイルにしてデータを吸い出しました。ASIN一覧ぐらいサービスでエクスポート機能があっても良さそうですが、メンテナンスされてないWebサイトでは仕方ないですね。

乗り換え先にはメディアマーカーを選びました。デザインはイマイチですが登録のしやすさ、欲しい機能の整備状況、他サービスとの連携がちょうどバランスが取れていると思います。過去の読書履歴を全部そのまま移すのは骨が折れそうなので一旦リセットして、これからまた記録していきたいと思います。

メディアマーカー – tuneのバインダー

Windows/Linux両環境で動作するC言語ソースの一元管理をGitで行う

5月 2nd, 2010

gitでリポジトリからのチェックアウト時に文字コードを変換する » tune webの続きです。
【未解決】VisualStudioとgccでコンパイルできるソースのエンコーディング » tune webでも書きましたが、問題はVisualStudioはUTF-8 BOM有のみ、gccはUTF-8 BOM無しのみ扱え、両者で問題なく扱える文字コードが存在しない事でした。gitにあるsmudge/cleanを使うとチェックアウト/ステージ時に任意のフィルタを通すことができ、BOMの除去をここでやれば出来そうなのですが、文字コード変換ソフトのnkfではBOMの有り無し以外も書き変わってしまうことがあるため実用に使えなかったのがこれまででした。

git smudge/cleanはPro Git – Pro Git 7.2 Git のカスタマイズ Git の属性に詳しく解説されています。
git smudge/cleanの設定は前の日記に書きましたが、ここでも引用しておきます。

まず.gitconfigファイルに以下を追加

[filter "fixbom"]
clean = “/usr/bin/bom_util -a”
smudge = “/usr/bin/bom_util -d”

これでsmudgeでUTF-8 BOM無し、cleanでUTF-8 BOM有りになります。

これだけではダメで、フィルタ処理をかけるファイルを指定する必要が有ります。
gitの管理フォルダである.gitがあるトップディレクトリに.gitattributesファイルを以下の内容で作成し、git checkout -fします。

*.c filter=fixbom
*.h filter=fixbom

/usr/share/git-core/templates/info/attributes を作って上記内容を書いておくとclone時に.git/info以下にコピーされてgit cloneしただけで文字コード変換が動くようになります。

上記で指定している、BOMをつけ外しするプログラムは結局自作しました。単にファイル先頭のBOMを検知して追加・削除をするだけです。ハマったこととしてgit smudge/cleanのデータは標準入力から渡され、標準出力へ書いた内容で差し替えられます。外部コマンドとして起動されるのかと思っていましたが異なるようです。
BOMをつけ外しするプログラムを下に貼っておきます。(gistはこちら→gist: 386410 – GitHub)

#!/usr/bin/ruby

require "optparse"

mode = :help

opt = OptionParser.new
opt.on("-a", "Add BOM"){|v| mode = :add}
opt.on("-d", "Delete BOM"){|v| mode = :delete}
opt.parse!(ARGV)

case mode
when :add
 STDOUT.binmode
       lines = readlines
       unless lines[0] =~ /^\M-o\M-;\M-?/ then
               print "\xEF\xBB\xBF"
       end
       print lines

when :delete
 STDOUT.binmode
       lines = readlines
 lines[0].sub!(/^\xEF\xBB\xBF/, '')
 print lines

when :help
       STDERR.puts opt.help
end

VisualStudioでの開発をメインにしているので、リポジトリ内のソースをUTF-8 BOM有、改行コードをLFCRにして運用しています。
これでLinux環境での開発がひとつやりやすくなりました。

入門Git 入門git 実用Git

Google Cloud Printに関する解説

5月 1st, 2010

少し前に発表されたGoogle Cloud Print構想ですが、まだ動くものがないせいか最初のニュースリリース以来何の進展もないのが現状です。

TechCrunchが一番詳しく報じていましたが、それでもGoogle Cloud Printが何をしてくれるのか、現状どういう状態にあるのか知ることが難しかったので元情報にあたってみました。そんなに難しい英語ではありませんが、後で参照することを考えて訳も残してあります。きちんと原文と対応する訳ではありませんが、参考にはなるんじゃないかと。

Google Cloud Printって何?
Webブラウザ/デスクトップアプリ/携帯端末全てから、ドライバの問題を気にすることなく世界中全てのプリンタに印刷出来るようにすることを目指すGoogleのプロジェクト。
GoogleはCloud Printのデザインドキュメントとプロトコルを公開し、さらにCloud Print Serviceを将来公開する。 アプリケーションは印刷指示をOSやドライバに送る代わりにGoogle Cloud Printに印刷ジョブを送る。Google Cloud Printが登録されている適切なプリンタにジョブを送り、アプリに印刷状況を伝える責任を果たす。

Googleがこのプロジェクトに取り組むのはChrome OSで全てのプリンタに対応するドライバを用意することが不可能だから。Chrome OSはCloud Printを使うように設計される、プリンタドライバは一切搭載されない。

現状何があるの?
Googleがこんなこと考えているよというデザインドキュメントだけ。
数ヶ月以内に追加の発表があるかも。

この段階でCloud Printを発表したのはプリンタメーカーとコミュニティの協力/フィードバックを早期に得るため。

どうやって実現するの?

Cloud Printではクラウド対応のプリンタと、レガシープリンタの2種類のプリンタを想定している。現在世の中にあるプリンタはWeb連携していてもレガシープリンタに分類される。Googleの考えるクラウド対応プリンタとはCloud Printで想定しているプロトコルを解釈出来るネットワーク対応プリンタを指す。かといって全てのプリンタがクラウド対応になるのを待ってるわけにも行かないから解決策も提供する。それはGoogle ChromeにCloud Printのプロトコルを解釈出来るプロキシを搭載することである。これにより、Google Chromeユーザは既存のレガシープリンタをPCをプロキシとして、Google Cloud Printのサービスを利用することが出来る。かといってこの方法だとPCもプリンタも常時電源をつけていなければならないので、例えばルータでプロキシが動くようにすればこの問題を解決出来ると考えている。(Google Cloud Printの絵にルータが書いてあるのはこのため。)

もう少し詳しい技術情報を
ユーザとプリンタの関連付けはGoogleアカウントを用いる。ユーザは既存のアカウントでログインし、はじめに利用するクラウド対応プリンタ(またはプロキシ下のレガシープリンタ)を登録する。プリンタはGoogle Docsのドキュメントのように扱うことができるので、プリンタを複数のユーザで共有することも簡単。

Cloud Print Serviceとプリンタの会話はHTTPで行う。サービスでは以下のAPIを定義

  • register : プリンタの登録
  • update : プリンタ情報の更新
  • list : 特定ユーザが利用可能なプリンタ一覧の取得
  • delete : プリンタの削除
  • control : プリントジョブの状態取得
  • fetch : 次のプリントジョブの取得

出力はjson, xml, textを選択することが出来る。

プリントジョブは永続化したXMPPコネクションを使ってGoogle Talkサーバから通知される。定期的にサーバからfetchしてもOK。

印刷データはfetch APIの出力に記載されているfileUrlから取得出来る。プリンタはfileURLにアクセスした際のHTTPのMIMEタイプを見て直接印刷可能かを判断する。 出来なければfetch APIに記載されたticketURLの方をアクセスし、PDFでデータを受け取ることができる。 当初はPDFのみをサポートするが他のフォーマット(例えばXPS)も将来サポートするかも知れない。PDFへの変換はGoogle Cloud Printが担当する。

雑感
Googleの今ある技術をうまく組み合わせてプリントジョブ管理の仕組みを作ってきたなという印象です。

プリンタドライバはジョブ管理以外にレンダリングなども担当していますが、この処理はプリンタ側に組み込む必要がありそうです。コピー機ぐらいのリソースがあれば問題ないかもしれませんが、1万から2万ぐらいの安いプリンタではリソースが厳しそうです。いずれにせよやるとなったら値段が高い方の機種から対応が進んでいくでしょう。

PDF内のデータは表示順に並んでいないと聞いたことがあります。1ページ目にある画像がファイルの後ろに格納されていると言った具合です。これではプリントジョブを受け取りながら印刷できないのでプリンタ側で一旦記録バッファリングしなくてはいけません。プリンタにはどれぐらいメモリの余裕があるんでしょう。

あとプリンタがGoogleアカウントと結びつけられるのは便利そうですが、近くに無いプリンタに出力してしまうこともよくありそうです。自宅の印刷物を会社のプリンタに出したりしては問題だと思うのですがどうするんでしょう? コピー機ではセキュアプリントなどと言った名目で、印刷ジョブを出した人がその場に行ってボタンを押さないと実際に印刷を行わないようにできます。こういう機能が一般的になるんでしょうか。

いずれにせよクラウド対応プリンタを実現するには、これまでよりもプリンタ側で製造コストをかけないとダメそうです。逆に言うとプリンタで使えるリソースが増えるのでこれまでは出来なかったことも考えられるかもしれません。プリンタメーカー各社にはピンチではなく、チャンスと思って色々考えて欲しいですね。

AdobeはなぜComputational Photographyに注力するのか

4月 23rd, 2010

a canon camera
Creative Commons License photo credit: lett -/=

最近Adobeのニュースが賑わっています。CS5の発表もありましたが、多くはAppleとやりあっているFlash関連のニュース。とうとう先日AdobeはiPhone/iPad向けのFlashから手を引き、Androidに注力することを宣言しました。業績が好調のAppleがAdobeを買収するのではという憶測も定期的に出てきています。

AdobeはFlashを共通のミドルウェア化することでWebの覇権を取りに行こうとしていますが、Flashそのものでは利益を生めません。Flashをオーサリング出来るAdobe Flash、さらにはPhotoshop, Illsutratorを買ってもらってソフトウェアで利益を上げるビジネスだと自分は認識しています。MicrosoftがOfficeの値段を下げる中、AdobeのPhotoshopはアップグレードでも48300円するそうです。まとめて購入するとMac Proが買えるぐらいの金額になります。

これだけ高いお金を払ってもらうには相応の機能が必要と考えるのが一般的です。Adobeは今回のCS5で様々な目に見える機能を実装しています。「えげつない」と評されたPatchMatchは話題になりました。

こういった新しい技術はCG技術を画像処理に応用する”Computational Photography”に分類されます。一口にComputational Photographyと言っても色々アプローチがあって、SIGGRAPHなどの有名な国際会議で活発な研究成果の発表を知ることが出来ます。Adobeは世界で最も”Computational Photography”に注力している企業の1つです。なんですが…なんでAdobeがこんなに注力するのかが自分にとって謎でした。Photoshop/Illustratorに最新の画像処理技術を組み込んでさらに魅力的にして、CS6, CS7とアップデートしてもらうのも1つの理由でしょう。でも”Computatioal Photography”は特殊なハードウェアを要求するものもあり、どんなにAdobeが頑張っても実現出来そうに無いものもあります。そこが謎でした。技術の将来性があるからといって、すぐに利益を産めないものにリソースを使いすぎなんじゃないかと。

で、教えてもらったのがフランケンカメラプロジェクトです。カメラのハードウェアとソフトウェアを切り離し、ハードウェアを共通化する。その上でソフトウェアで価値を生み出せるようにするカメラ、それがフランケンカメラです。iPhoneで沢山あるカメラアプリを想像すると、このカメラでどんな可能性が広がるか伝わりやすいかもしれません。

これがあれば、Adobeはカメラメーカーになることができます。それもレンズや撮像素子は差別化要因にならず、ソフトウェアで差別化を図る必要がある「ソフトウェアで画質が進化する次世代カメラ」です。今のカメラよりも従来のデジカメとは2世代ぐらい先を行っているでしょう。こうなればComputational Photographyに一日の長があるAdobeがカメラメーカー、携帯メーカーとは異なる軸で戦うことができます。フランケンカメラにAndroidを積んで、その上で動くUI/アプリをFlashで作れるなら現実的にAppleと戦えそうな気も少しだけしてきます。

実際Adobeぐらいの規模なら業績が悪いカメラメーカーを買収することぐらいできるでしょうから違うアプローチを取るかもしれません。カシオはソフトウェアで差別化を図っていくつもりのようなので、Adobeと波長が合うかもしれません。

以上、会社の同僚から教えてもらった話でした。
間違ってる可能性の方が高いと思いますが参考まで。

麻雀問題解いてみた

4月 4th, 2010

Mahjong set [04/04]
Creative Commons License photo credit: drdaeman

makeplex salon:あなたのスキルで飯は食えるか? 史上最大のコーディングスキル判定 (1/2) – ITmedia エンタープライズを解いてみました。ソースはtune’s itmedia_makeplex at master – GitHubに上げてありますのでリビジョンも見れるようになってます。最初のコミットを上げるまでに、面子の表示順の違いを抑えるところで詰まってチンイツの待ちを出力するプログラム – 107143955443560を参考にしました。参考にしましたというよりもC++のソースをRubyに移植しましたと言う方が近いほど同じ処理です。基本的なアルゴリズムは最後まで踏襲しています。

最初のコミットまでが3時間ぐらい、リファクタリングに1時間ぐらいです。ちょっと時間がかかりすぎですが、日常的に書いてないRubyで、日常的にプログラムしてない家のMacパソコン、プラグインが古いのか5分に1回落ちてしまうMacVimで時間がとられたと言い訳しておきます。ただの実力不足です、ごめんなさい。

成立する可能性がある面子を減らしながら、総当たりで探索しています。面子の順序違いによる重複表示を避けるのが結構面倒ですね。刻子を優先して探さなければならず、色々試行錯誤してみたのですが、参考にさせていただいたid:staebchenさんよりも良さそうな方法に達しませんでした。もっといいやり方があると思いますが、参考まで。

#!/usr/bin/ruby

class Array
  def sum
    s = 0
    self.each do |v|
      s += v
    end
    return s
  end
end

class Fixnum
  # 刻子
  def anko
    num = self+1
    "(#{num},#{num},#{num})"
  end

  # 順子
  def shuntsu
    num = self+1
    "(#{num},#{num+1},#{num+2})"
  end

  # アタマ
  def atama
    num = self+1
    "(#{num},#{num})"
  end

  # 単騎
  def tanki
    num = self+1
    "[#{num}]"
  end

  # リャンメン(ペンチャンも兼ねる)
  def ryanmen
    num = self+1
    "[#{num},#{num+1}]"
  end

  # カンチャン
  def kanchan
    num = self+1
    "[#{num},#{num+2}]"
  end

  # シャボ
  def shabo
    num = self+1
    "[#{num},#{num}]"
  end
end

#
# 雀牌を表す数字列を解析し、0〜8の配列に与えられた個数を入れて返す
#
def parsePai(str)
  pai = Array.new(9, 0)
  str.split(//).each do |p|
    pai[p.to_i-1] += 1
  end

  # 入力の妥当性チェック
  if pai.sum != 13 then
    # 与えられる牌は13枚
    raise RuntimeError
  else
    pai.each do |val|
      if val > 4 then
        # 1種類の牌が4枚より多いことはない
        raise RuntimeError
      end
    end
  end

  return pai
end

#
# 手牌を再帰的に解析し待ちを表示する
#
# 順子を刻子に優先して探索する。
# 順子はfromが9〜18の時に探索される
#
def analyzeTehai(pai, from=0, mentsu=[])
  shuntsu_phase = 9
  skip_anko_check = false

  if from >= 9 then
    skip_anko_check = true
    from -= shuntsu_phase
  end

  if pai.sum > 4 then
    # 面子を揃える

    # 刻子
    unless skip_anko_check then
      from.upto(8).each do |i|
        if pai[i] >= 3 then
          tmp = pai.dup
          tmp[i] -= 3
          analyzeTehai(tmp, i+1, mentsu+[i.anko])
        end
      end
    end

    # 順子
    from.upto(6).each do |i|
      if pai[i]>=1 && pai[i+1]>=1 && pai[i+2]>=1 then
        tmp = pai.dup
        tmp[i] -= 1
        tmp[i+1] -= 1
        tmp[i+2] -= 1
        analyzeTehai(tmp, i+shuntsu_phase, mentsu+[i.shuntsu])
      end
    end

  else
    # 残った4枚から待ちを絞る

    # アタマを探す
    0.upto(8).each do |i|
      if pai[i] >= 2 then
        tmp = pai.dup
        tmp[i] -= 2
        analyzeMachi(tmp, mentsu+[i.atama])
      end
    end

    # 面子(刻子 or 順子)があれば単騎待ち
    # 刻子
    unless skip_anko_check then
      from.upto(8).each do |i|
        if pai[i] >= 3 then
          tmp = pai.dup
          tmp[i] -= 3
          analyzeTanki(tmp, mentsu+[i.anko])
        end
      end
    end

    # 順子
    from.upto(6).each do |i|
      if pai[i]>=1 && pai[i+1]>=1 && pai[i+2]>=1 then
        tmp = pai.dup
        tmp[i] -= 1
        tmp[i+1] -= 1
        tmp[i+2] -= 1
        analyzeTanki(tmp, mentsu + [i.shuntsu])
      end
    end
  end
end

#
# 4枚から待ちを絞る
#
def analyzeMachi(pai, mentsu)
  0.upto(8).each do |i|
    # リャンメン(ペンチャン)
    if pai[i]==1 && pai[i+1]==1 then
      puts mentsu.sort.to_s + i.ryanmen
    end

    # カンチャン
    if pai[i]==1 && pai[i+2]==1 then
      puts mentsu.sort.to_s + i.kanchan
    end

    # シャボ
    if pai[i]==2 then
      puts mentsu.sort.to_s + i.shabo
    end
  end
end

#
# 単騎待ちの数字を調べて待ちを表示する
#
def analyzeTanki(pai, mentsu)
  # 単騎待ち
  0.upto(8).each do |i|
    if pai[i] == 1 then
      puts mentsu.sort.to_s + i.tanki
    end
  end
end

# 以下実際の処理
pai = parsePai ARGV[0] unless ARGV[0] == nil
analyzeTehai(pai)

Amazonの紹介料が伸びないなと思ったらアソシエイトIDが間違っていた

3月 29th, 2010

いつからかAmazonの紹介料ががくんと伸びなくなったのでみんな慣れて効果が薄れたのかなと思っていましたが、単にアソシエイトIDを間違えて設定しているだけでした。いつから間違えていたのか調べる気も起きませんが、PCをMacに差し替えたあたりが怪しいので1年近く間違えていたことになります。なんともったいない。

WordPressに貼っつけたものがほとんどなのでSearch Regexを使って一括置換で対応出来ました。もっと速くに気づくべきでしたね。まぁ便利なWordPress Pluginを見つけられたのでよしとします。

会社で使っているRedmineをgithubで公開されているものに差し替え

3月 23rd, 2010

何でこれまでやってなかったのかと言うと、うちの社内から社外のSubversionリポジトリにアクセス出来なかったからです。アクセス制限がかけれられているわけではなくて、間に挟まったプロキシがSubversionが独自に拡張したHTTP命令を解釈できないようなのです。

ということで、githubでホストされているedavis10's redmine at master – GitHubを見つけて、これをcloneして使うようにしました。masterからインストールサーバ用にカスタマイズして使いましたが、タグやリリースブランチもきちんと切ってくれているのでgitさえわかれば好きに改変して使えますね。tar.gzでダウンロードしたものを使うよりもずっと便利です。

本体をgit管理にすると、プラグインもgit管理で最新版に追従したいところなんですが、ソースの置き場所がgithubにあったり、Google Codeにあったり、RedmineのSubversionにあったり統一感が無い感じです。個人的にはgithubで統一して欲しいのですが、それぞれ事情があるのでしょうね。このあたり、ブラウザから選択してインストール出来るHudsonはよく出来ているなと感心します。

あと今日公開された日本語環境で読みやすいRedmine用テーマ「farend basic」公開 | Redmine.JP Blogも使ってみて気に入ったのでデフォルトのテーマにしました。これまで本家にあったAlternativeを使っていたのですが、メイリオの効果かfarend basicの方が文字周りが綺麗に感じます。Redmineユーザの方は一度試してみることをおすすめします。

Subversion, Git, Redmine, Hudson – 結局こうなった

3月 21st, 2010


前に考えていた開発プロセスの変更を色々試行錯誤してみてある程度固まってきました。過去の記事は以下からどうぞ。

ネットワークが切り離された外部チームとのやりとりは結局git bundleにしました。外部チームからはパッチでもらい、レビューした後に適用する。ある程度開発が進んだらgit bundleでリポジトリをコピーして外部チームに送付。外部チームはbundleファイルをそれぞれcloneして開発を行い、適宜git fetch/git pullしながら更新に追従します。タスクの粒度が1タスク1人だったこと、外部チームで別途central repositoryを設けることによるメリットが読めなかったのでこの形を取りました。開発メンバのGitレベルが上がればまたちがった使い方があるのかもしれません。チームの大半が入門Gitを読んだ程度だとこれぐらいから始めるのが混乱が少ないようです。
「masterだけ送ればいいから % git bundle create reponame.bundle master」でOKと思ってbundleファイルを作ったところclone出来ない問題が起きて半日ほどハマることがありました。「% git bundle create reponame.bundle master HEAD」じゃないと駄目みたいです。リポジトリ全部のコピーを送るなら「% git bundle create reponame.bundle –all」でもいけます。

以前はgitリポジトリの変更をSubversionに自動で書き戻すことを考えていましたが、GitとSubversionを共存させる » tune webで書いたようにSubversionに登録されたソースが削除されてしまうことがあり、結局手動にしました。週に1回ぐらい書き戻すことを想定しています。それに合わせてRedmineやHudsonが参照するリポジトリもgitに変更しました。

Hudsonのgitプラグインでポーリングする設定をしてみたのですが、ポーリングのログを書き込むところでたまにエラーが起きて止まってしまうため、gitのフックスクリプト(post-receive)でHudsonのジョブをcurlでキックするようにしました。ジョブはWindowsとLinuxとあるのですが、Windowsが苦戦しました。まずWindowsのジョブを実行するPCにmsysGitを入れて、コマンドプロンプトからgitコマンドが叩けるようにします。次にHudsonのgitプラグインでは認証を入力することが出来ないので、gitリポジトリをhttpで読めるようWebサーバの設定を行いました。gitのhttp公開は単にリポジトリのフォルダにアクセス出来るようすれば良いだけなので簡単です。あとはhooks/post-updateに”git update-server-info”を追加すればOKです(参考:git update-server-info)。

Hudsonのgitプラグインはテスト対象をワイルドカードを含むブランチ名で指定できるので、少し時間をかければpre-test commitも出来そうです。前は良く分からないなんて書いてしまいましたが、少しgitプラグインを使ってみれば感触がつかめるのではないかと思います。近々に必要な機能ではないので、また時間がある時に試してみようと思っています。

Redmineでgitを参照するにはRedmineと同じサーバにbareリポジトリを置く必要があります。別サーバで動かしているなら中央リポジトリからRedmine用のリポジトリに自動でpushする設定をすればいいでしょう。Redmineの昔のバージョンではリポジトリビューワが遅かったらしいのですが、0.9以降で試した限りでは気になるほどではありません。Subversionの頃よりも見やすくなった気さえします。trunkとbranchを切り替えて表示するのがSubversionより楽だと思います。リポジトリビューワがあまりに見やすいのでgit-webのインストールをやめたほどです。ソースレビューにgerritを検討しましたが、LDAP認証の設定をするところでうまく動かず断念してしまいました。最もr-labs – Code Review – Redmineが最近のバージョンアップでどんどん良くなっているので不要かもしれません。Redmineがより使われるようDoxygenで自動生成している内部仕様書もRedmineのRedmine – PluginEmbedded – Redmineですぐ見れるようにしてみました。

gitのフックスクリプトはhooks/post-receiveでメールを流す設定だけ有効にしています。コミットメッセージに Issue ID を含むことを強制させる Git のフックスクリプトを書きました|SNS構築の手嶋屋を参考にhooks/updateをつくってみたのですが、gitで自動生成されるコメント(マージとか)はRedmineのコミットIDを含まないのが問題になり結局止めています。この辺はまた時間をとってフックスクリプトを見直す必要がありそうです。

時間もかなり費やしましたが、昨年までよりも開発に専念出来る体制がようやくできました。Joel先生も分散バージョン管理で間違いないって、ベイビーと言ってるほどなので分散バージョン管理に移行しましょう!

Atlasianの98日リリースサイクルを読み解く

3月 6th, 2010

先月のデブサミであったAtlassianの発表は結構面白かったと思うのですが、ブログやTwitterに感想を書いている人は思ったよりも少ないみたいですね。会社説明は退屈だったかもしれないけど、社内で行っているアジャイル開発の事例は結構参考になるところがあるんじゃないかと思っています。セッションのスライドは以下から見ることが出来ます。

中でも98日間隔(14週間、約3ヶ月ですね)でリリースを繰り返すイテレーションの仕組みはもっと注目を集めても良いと思います。自分で眺めて考えてみた結果を以下にまとめてみます。

◯図のイテレーションはどうして9週目始まり?
開発の最後のイテレーション(Iteration5)と次期バージョンの仕様を決める時期が重なっているからですね。開発者は12週目から14週目の作業が少なくなっていますが、ここで自由裁量な開発期間(Googleの20%ルールみたいの)を割り当ててる人が多いと講演で言ってた気がします。

◯PMMの仕事
PMがProject ManagerならPMMは誰なんでしょう? パッと見でPMより偉い人みたいですが。PMM:Product Marketing Managerとのことです。気になったのはPMMが実施するレビューの順番です。

  • 1週目:マーケットと競合他社のレビュー
  • 2週目:Messagingレビュー(製品の打ち出し方 とかなのかな?)
  • 3週目:製品ローンチのゴールをレビュー

競合分析と最終ゴールの確認は大事ですよね。

◯PM:Product Managerの仕事
この辺は一般的? リリース基準を事前に策定するのは大事だよね。

  • 1週目:時期製品ターゲット層の検討
  • 2週目:6ヶ月先までのロードマップを更新(これより長期の計画は無いのかな? それとも別途作成?)
  • 3週目:リリース基準の策定
  • 4週目:詳細なストーリー作成(製品が使われるユースケースのことでいいのかな?)

◯デザイナの仕事
PMM/PMが製品コンセプトを固めている段階からデザイナの仕事が振ってあります。初期段階はPMと一緒に動き、開発が始まったらプログラマと協業するんですかね。

◯イテレーション
全5回、うち実質的に開発に振り分けられるのは最初の3週間。4週目は”Polishing”とある、機能追加を止めてパフォーマンスや使い勝手を作り上げていくフェーズなのかな? 5週目はリリースにあたっての準備期間の模様。
あと各イテレーションでコード書きはもちろん、バックログの整理や自動化されたテストも準備しているみたい。
社内でドッグフードを食べ始めるのはBETA1からかな?ドッグフードはイテレーションの1回目から食べ始めるそうです。デブサミの講演では「体感として1日1回は落ちる(Confluenceだったかな?)」と話されていましたが、開発直後の状態ならそれぐらい落ちても不思議ではないですね。

◯各フェーズでの確認事項
下部に書いてるのは各フェーズでの確認事項だと考えました。「顧客が求めているか、お金を払ってくれるか」「長期計画に沿っているか」「リリース出来るほど安定しているか」などなど。当たり前だけど大事なことですよね。

ということで、画像から読み取れることを自分なりに書いてみました。これぐらい短くリリース出来ると開発に緊張感が出て良いですね。どれぐらい短い間隔でリリース出来るのかという課題は突き詰めて考えてみると今のムダも見えて結構良いかもしれません。

GitとSubversionを共存させる

2月 27th, 2010

git svn cloneして、ファイル編集して、git commitして、git svn dcommitでSubversionサーバに変更を反映させる。Subversionの変更を取ってくるのはgit svn rebaseだ… なんてのがWeb上で探してすぐ見つかる情報ですが、これでは複数人でgitを使う場合の運用ですぐに行き詰まってしまいます。

実用Gitの16章に定石が載っていると聞き、さっそく買って読んでみました。他の章を飛ばして16章だけ読んだせいもあるのか自分の中ではまだうまく消化出来ていません。とりあえず手順だけ書いておきます。

◯前提条件
git svnを行う窓口は1箇所にする。git svnのオプションを変えたり、とってくるリビジョンを変えただけでもコミットオブジェクトは変わってしまう。

◯前準備
git svnを使ってSubversionリポジトリのcloneを作る

% mkdir example-svn.git
% git svn clone –stdlayout –prefix=svn/ http://example.jp/svn-repos/

git bareリポジトリを作る

% mkdir example.git
% cd example.git
% git init –bare –shared=true

git svnリポジトリからmasterとSubversionのブランチをgitのセントラルリポジトリにpushする。

% cd ../example-svn.git
% git push –all ../example.git
% git push ../example.git ‘refs/remotes/svn/*:refs/heads/svn/*’

◯Subversionにマージを書き戻す

% git checkout svn/trunk
% git merge –no-ff new-feature
% git svn dcommit

何度も実用Gitの解説を読んでいるのですが、マージを書き戻すところだけどうにも謎です。多分きちんとリモート追跡を理解できてないのでしょう。この休みにまた時間をとって勉強することにします。

実際にやってみて出来ることは確認したのですが、

  1. Subversionへの書き戻しを手動でやらないといけない
  2. Subversionのログに残るメッセージがgit mergeで生成されたものになってしまい、何の変更をしたのかSubversionからはさっぱりわからない

という問題があることも分かりました。

そこで上記でいうexample-svn.gitのフックスクリプトを作成し、example-svn.gitのmasterに変更がpushされたらSubversionに書き戻す処理を自動化してみました。動く気はしているのですが、理解が足りてないせいで、思わぬ問題を引き起こすかもしれませんのでご注意ください。

#!/bin/sh

# checkout svn/trunk
git checkout svn/trunk

# Store git log before merge
log=$(git log last-merged..master --pretty=format:"%h %s" --reverse)

# merge master to svn/trunk, don't commit
git merge --no-ff --no-commit master

# commit with git log message
git commit -a -m "$log"

# push back to svn repository
git svn dcommit

# tag last merged
git tag -d last-merged
git tag last-merged master

◯2010年3月3日追記
テスト環境ではうまく行ったのですが、本番環境でgit->Subversionの自動同期をしてみたところ、ソースファイルが削除される問題が起きてしまいました。
git push, git mergeとかのどこかでうまくいってないのにsvn dcommitまで行われたのが直接の原因ですが、なぜこうなったのかログを見ても原因が分からなかったので自動同期は止めました。

◯2010年3月4日追記
よくよく考えたらsvnのゲートウェイとなるリポジトリのmasterとsvn/trunkは別個の歴史を辿るんですね。なので前にマージされてからの差分を求めるにはsvn/trunk..masterでは駄目ですね。上のスクリプトはなんとなく書き換えてみましたが、gitの理解が足りてないですね。

Pages: 1 2 3 4 5 6 7 8 9 10 ...40 41 42 Next