Hatena::ブログ(Diary)

潜在推力

about - top - rss - archive

2000 | 01 |
2008 | 02 | 03 | 04 | 07 | 10 | 11 | 12 |
2009 | 01 | 02 | 03 | 04 | 07 |
2010 | 09 |
2011 | 07 |

Scala | PS2.0CTP | F#1.9 | IronRuby0.1 | ASP.NET | Cloud Foundry


 

2011-07-19

cloudfoundry + sinatra + sequel + mysqlメモ(1)

先週から、cloudfoundry + sinatra + sequel + mysqlで簡単なアプリケーションを動かしていて、基本的にはすんなり行けたんだけど、何点か詰まった個所のメモ。

Rubyのバージョン指定方法

vmc pushでデプロイするとき、勝手にJavaなのかRubyなのか、RoRなのかsinatraなのか、等を判別してくれるけれど、rubyのランタイムは指定しないと自動で1.8になるよう。1.9を使いたい場合は、"vmc push --runtime ruby19"。

gemの取り扱い

ほとんどのgemはrequireに書くだけで動いたけど、一部(というか一部以外?)bundlerでgemを同梱しないと動かなかった。bundlerを全然知らないので正直良く理解できてないけど、この辺とか参考。

https://github.com/cloudfoundry/vcap/issues/54

(*)sinatra, haml, sequelは確かbundlerなしで大丈夫、mysqlが駄目だったかな

起動しない場合/起動中のログ確認

vmc logs applicationname

mysqlの接続文字列

MySQLを利用する前、vmcコマンドでサービス作成、アプリケーションとバインドしたあと、sequelの場合は自分で接続情報を設定しないといけない。RoRだと勝手にyamlをなんかしてくれて繋がる、ような記述も見かけたけどRoRを知らないし、試してません。

http://support.cloudfoundry.com/entries/505124-sample-app-to-mysql-connection

接続情報は環境変数にJSONで入っているので、パースして利用するのが正しいようだけど、面倒だったら環境変数をsinatraでブラウザに出力させて、そこからサーバー名、ポート、ユーザー、パスワード、データベース名をコピペでハードコーディングしてもとりあえず動く。

2010-09-29

Scalaでダイジェストを生成する

インターネットから取得した画像をキャッシュとしてファイルで保存しておきたいなー、と思いました。キャッシュなのでURLからファイル名が特定できなければいけない。最初はURLのString#hashCodeを使えばいいのかな、と思ったのですが、hashCodeは衝突する可能性があるらしい。そうかー、どんなアルゴリズムであれ衝突する可能性はあるよなー、と思ってMap[String, String]にURLとファイル名の対応を保持しておき、プログラム終了時にxmlで保存するようにしてたのですが。

ちょうどその頃、たまたま「入門Git」を読んでいて、 その中に、Gitではオブジェクトを管理するのに、SHA-1ハッシュ値を利用しているとの記述がありました。どうもこれを利用すればいいらしいなーという気がします。

なにしろ、SHA-1ハッシュ値が重複してしまう可能性というのはとてつもなく低いのです。「Pro Git」から引用すると、

しかし、そんなことはまず起こりえないということを知っておくべきでしょう。SHA-1 ダイジェストの大きさは 20 バイト (160 ビット) です。ランダムなハッシュ値がつけられた中で、たった一つの衝突が 50% の確率で発生するために必要なオブジェクトの数は約 2^80 となります (衝突の可能性の計算式は p = (n(n-1)/2) * (1/2^160) です)。2^80 は、ほぼ 1.2 x 10^24 、つまり一兆二千億のそのまた一兆倍です。これは、地球上にあるすべての砂粒の数の千二百倍にあたります。

http://progit.org/book/ja/ch6-1.html/

で、Scalaで、というかJavaでSHA-1ハッシュ関数を利用してダイジェストを生成するのはとても簡単、@IT:Java TIPS -- Javaでダイジェストを生成するにサンプルのコードが記載されていました。

これを元に、ScalaでStringからSHA-1で生成したダイジェストの文字列を返すクラスは以下のように定義できました。

import java.security.MessageDigest

class Sha1Digest(str: String) {
  val digestString: String = {
    val md = MessageDigest.getInstance("SHA-1")
    md.update(str.getBytes)
    md.digest.foldLeft("") { (s, b) => s + "%02x".format(if(b < 0) b + 256 else b) }
  }
}

ダイジェストを取得する際、Stringのメソッドであるかのように使いたいので、implicitすると、以下のようになります。

object App {
  def main(args: Array[String]) =
    List("全部", "違う", "値になります").foreach { str => println(str.digestString) }

  implicit def String2Sha1Digest(s: String): Sha1Digest = new Sha1Digest(s)
}

自分のプロジェクトでは、MyPreDefのようなObjectを定義してimplicitを並べてimportしており、その中に紛れ込ませて使っています。

2009-07-05

型付データセットをインターフェース越しに扱う

型付データセットが大好きなので出来る限り型付データセットだけでいろいろなことを済ませたい。

済ませたいんですが、Partialクラスにメソッド追加して便利にしていくだけだと余分なところが隠せないのでインターフェース越しに扱うのはどうなのかなー、という話を書きます。

もっと簡単に同じような動きを実現できるのではないのかなーと思いつつ出来てない……。なんか、メジャーなやり方があるんでしょうか……。

たとえば、こういうテーブルがあったとして、

f:id:ps1:20090705230458p:image

CHAR(1)である、sex列には0:男性、1:女性というフラグが入るとします。それ以外の値は入れてほしくないので、SEXという列挙体を定義して、その列挙体でsexカラムを扱えるようにします。なんか紛らわしいですが、SEXが列挙体の型名で、sexが自動生成されたDataRowのカラム、SexがPartialクラスに定義したプロパティです。ちなみに、sexというのは英語で性別という意味です。

ついでに、姓 + 名を返してくれる、読み取り専用のFullNameというプロパティも定義しています。

f:id:ps1:20090705230453p:image

これで、以下のように、Sexには特定の値しか設定できないようになりました。

f:id:ps1:20090705230457p:image

しかし、自動生成されたsexプロパティのほうにも依然としてアクセスできるので、こいつに直接値を設定することで、"0"、"1"以外の好きな値、"x"などを入れられます。そして、次回Sexプロパティにアクセスしたとき、Enum.Parseが出来なくて死ぬ……(死にません。例外が出る)。

sexに直接値が入れられる以外にも、CustomerRowにはDataRowから継承した、データアクセス層以外からは触るべきでないようなものがいっぱい公開されてて、そいつらには触れないようにしたい。

f:id:ps1:20090705230459p:image

↑なんかよくわかないのが一杯出るけど全然いらない。そこで、公開したいメンバだけ設定したインターフェースを定義して、こいつ越しに扱うルールにしてみます。名前は、ICustomerDataRowです。普段は名前にIとかつけませんが考えるのが面倒だったので……。

f:id:ps1:20090705230456p:image

こんな感じで、使いたい奴だけ出てくるようになりました。

f:id:ps1:20090705230454p:image

しかし、このままだと、CustomerDataTableからインデクサや、Select、foreachで取り出した時に毎回CustomerRowではなく、ICustomerRowとして扱うのを忘れないようにしないといけないので、最初からICustomerRowで返してくれる、ICustomerDataTableというのも定義してみる。

f:id:ps1:20090705230455p:image

CustomerDataTableは使わせないで、ICustomerDataTableだけでまわそうとすると、最低限NewRow系やらも使えるようにしておかねばならず面倒くさい……。あと、型付データテーブルのインターフェースが必要なのと同じ理由で、型付データセットに対応するインターフェースも定義した方が良い、とかいうことになる……。

まぁ、面倒だけど定型的な作業は自動化するか、新人にやらせろ、という格言もあるので行けるのかなぁー。データアクセス層だけアセンブリ分けるときは、DataSet自体はinternalにしてinterfaceだけパブリック、とかにすることもあるんでしょうか。知りませんが……。

2009-04-16

なぜwinver.exeの画像は汚いのか?

日記のタイトルが疑問文だと答えがあるのかと思ってしまうかもしれませんが、単に純粋な疑問で、なんでこんな画像になっているのか全然わからない……。winver.exeというのはWindowsのエクスプローラー、ヘルプ -> バージョン情報、で出てくるこんなウィンドウです。ためしに、Windowsキー + R、"winver"、Enterキー、で起動してみてください。僕の手元で集められたものを列挙してみます。

# ライセンス情報を消してます

Windows XP SP3。滲みすぎ……。

f:id:ps1:20090416220354p:image

Windows Server 2003。サーバだし普段目にしないから適当に作ったのかも。

f:id:ps1:20090416220351p:image

Windows Vista。XPまでは、たまたまやる気がなかったのかな、と思ってましたが、Vistaも汚いのでなにか特別なこだわりがあるのかもしれない、という疑いも拭いきれない感じになってきました。

f:id:ps1:20090416220352p:image

IE6での検証用に配布されてたWindows XPのイメージ。Virtual PC上。これはきれい。

f:id:ps1:20090416220353p:image

最後の奴だけきれいですが、英語版だときれいなのでしょうか。Windows 7のはきれいだという話も聞きましたが、日本語版の話なのでしょうか。

2009-04-05

開発現場でPowerShellを使う

4/2にTech Fieldersセミナー「スクリプトを使用した Windows Server 管理の自動化」でライトニングトーク(五分貰って好きなこと喋る)をしてきたので、しゃべった(つもりの)内容を置いておきます。あまり緊張しないほうだと思ってたんだけど、やっぱ緊張するなー。一応書きたいことを羅列したものは作っておいたんだけど、きっちり五分でしゃべる内容決めといたほうがいいんだろうな。あたりまえだけど……。ちなみに、ライトニングトークでは最後に投票をして、一番票を集めた人がマイクロソフトのプレゼン用マウスをもらえるんですが、貰えなかったので次出ることがあったらもっと改善して票を集めるのを目標に挑みたい……。

ということで、PowerShellを開発現場で使って、簡単・便利なツールを作る方法についての自分なりのコツを紹介したいと思います。

f:id:ps1:20090405140804p:image

この図は最近まで開発してたシステムです。.NET Frameworkとしては、標準的な構成かな、と思います。DBがあって、Webサービス経由が、あって、UIとして、ASP.NETか、Windowsフォームのアプリケーションがあります。

PowerShellではテスト用のツールなどを作っていたんですが、今日紹介するのは、図の1.と2.の部分です。

まず、1.のツールなんですが、これは特定の条件でDBからデータを取得し、ファイルに落とし込みます。そして、任意のタイミングでDBに書き戻します。これはどういう用途に使うかというと、

  1. テストをしてデータが書き換わったときに元に戻したい
  2. 本番環境からテスト環境にデータを持ってきたい

なんて時に使います。

もう一つの下側、2.ですが、これは、ログからリクエストを拾ってきて、Webサービスのリクエストを再現するのに使います。リクエストはシリアライズしてログに記録してるので

  1. Webサービスのテストに使う
  2. 本番のリクエストをテスト環境で再現する
  3. いろいろなマシンで同時に実行すれば負荷テストも出来るかも(やったことないけど)

とかって使い方になります。

どちらも、データやリクエストはシリアライズしてXMLでファイルにしているので、データを一部エディタで書き換えたり、コピーして微妙に違うものを作るなんてことが出来ます。

f:id:ps1:20090405140759p:image

具体的な作り方を説明します。この二つのツールは非常に似通ったつくりになってるので、そのつくりを図にしてみました。

Webサービスへのリクエストを行ったり、DBデータの取得、反映などの、肝になる動作はほとんどほとんどVisual Studioが自動生成するソースでできてしまいます。

Webサービスで言うと、WSDLを参照してプロキシクラスを作ってくれるんですが、そいつにデシリアライズしたオブジェクトを渡すだけです。DBだったら、型付DataSetとテーブルアダプタです。

ただ、そのままだとPowerShellから扱いにくいので、使いやすいレベルで動作をまとめて、C#なり、VB.NETなりで、スタティックメソッドにまとめてしまいます。スタティックメソッドにするのはPowerShellから呼び出しやすいからです。

スタティックメソッドに渡す引数は、基本的にXMLシリアライズしてファイルに落とし込んだオブジェクトをデシリアライズして使います。XMLなのでDBに反映したい中身や、Webサービスに渡したいリクエストの中身をエディタで編集もできて便利です。

スタティックメソッドは呼び出しが楽とはいっても、さすがにそのまま使うのはなんなので、PowerShellのfunctionでラップします。実際にツールとして使うときは、この関数を呼び出して使う形になります。

基本的に、上で紹介したようなツールはほとんど自動生成されるソースを、C#でちょこちょこっとラップしてあげるだけで出来てしまいます。簡単・便利なのでぜひご利用ください……。

ちなみに、自作のアセンブリ、DLLでもEXEでもかまいませんが、を読み込んでPowerShellから利用するには、

[System.Reflection.Assembly]::LoadFile({ファイル名})

オブジェクトをXMLシリアライズしてファイルに落とすのは、

 $s = 'System.Xml.Serialization.XmlSerializer'
 $f = 'System.IO.FileStream'

 $slzr = New-Object $c -A @({クラス名})
 $fs = New-Object $f -A @({ファイル名}, 'Create')
 try { $slzr.Serialize($fs, {シリアライズ対象}) } finally { $fs.Close() }

デシリアライズは

 $fs = New-Object $f -A @({ファイル名}, 'Open')
 try { $o = $slzr.Deserialize($fs) } finally { $fs.Close() } 

でできます。多分……