<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Born Too Late</title>
	<atom:link href="http://blog.yuyat.jp/feed" rel="self" type="application/rss+xml" />
	<link>http://blog.yuyat.jp</link>
	<description>ドゥームとサイケを愛する Web エンジニア。赤坂の音楽関連企業勤務。技術、音楽、書籍などについて。</description>
	<lastBuildDate>Sat, 21 Aug 2010 16:22:33 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>ja</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Ruby 1.9.x ではイテレータにおけるスコープが変わった模様</title>
		<link>http://blog.yuyat.jp/archives/421</link>
		<comments>http://blog.yuyat.jp/archives/421#comments</comments>
		<pubDate>Sat, 21 Aug 2010 16:21:11 +0000</pubDate>
		<dc:creator>Yuya Takeyama</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Tech]]></category>

		<guid isPermaLink="false">http://blog.yuyat.jp/?p=421</guid>
		<description><![CDATA[
			
				
			
		
ささたつ (@sasata299) さんの「Rubyのスコープややこしや〜 」を読んで、ちょっと驚きだったので、調べてみました。
検証用コード
ささたつさんのコードとはちょっと違いますが [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fblog.yuyat.jp%2Farchives%2F421"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fblog.yuyat.jp%2Farchives%2F421&amp;source=yuya_takeyama&amp;style=normal&amp;service=bit.ly" height="61" width="50" /><br />
			</a>
		</div>
<p><a href="http://twitter.com/sasata299">ささたつ (@sasata299) さん</a>の<a href="http://blog.livedoor.jp/sasata299/archives/51477436.html">「Rubyのスコープややこしや〜 」</a>を読んで、ちょっと驚きだったので、調べてみました。</p>
<p><strong>検証用コード</strong></p>
<p>ささたつさんのコードとはちょっと違いますが、調べようとしていることは特に変わりません。</p>
<p><script src="http://gist.github.com/542482.js?file=check_scope.rb"></script></p>
<p><strong>Ruby 1.8.7</strong></p>
<p>apt-get でインストールした MRI の場合。</p>
<pre class="brush:bash">$ ruby -v
ruby 1.8.7 (2010-01-10 patchlevel 249) [i486-linux]
$ ruby check_scope.rb
r = 15
n = 10</pre>
<p>?!</p>
<p>これはつまり、はじめに定義した変数 n が、イテレータにより上書かれていることを意味します。</p>
<p><strong>JRuby 1.5.1 </strong></p>
<p>ソースコードから手動インストールした JRuby。</p>
<pre class="brush:bash">$ jruby -v
jruby 1.5.1 (ruby 1.8.7 patchlevel 249) (2010-06-06 f3a3480) (OpenJDK Client VM 1.6.0_18) [i386-java]
$ jruby check_scope.rb
r = 15
n = 10</pre>
<p>1.8.7 と全く同様の結果に。Ruby 1.8.7 を実装したものなので、当然といえば当然ですね。</p>
<p><strong>Ruby 1.9.2</strong></p>
<p>先日リリースされたばかりの最新版。ソースコードから手動インストールしました。</p>
<pre class="brush:bash">$ ruby192 -v
ruby 1.9.2p0 (2010-08-18 revision 29036) [i686-linux]
$ ruby192 check_scope.rb
r = 15
n = 100
</pre>
<p>こちらでは、イテレータ内での変数 n はローカルに閉じており、はじめに代入した n は上書かれていないことがわかります。</p>
<p>1.9.2 の動作が、一般的に見て自然と思われるものではないでしょうか。これ、いつのタイミングで変わったんですかね ?</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.yuyat.jp/archives/421/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>GAE で Rails 2.3.8 が動くようになっていた</title>
		<link>http://blog.yuyat.jp/archives/411</link>
		<comments>http://blog.yuyat.jp/archives/411#comments</comments>
		<pubDate>Sun, 25 Jul 2010 23:11:37 +0000</pubDate>
		<dc:creator>Yuya Takeyama</dc:creator>
				<category><![CDATA[Google App Engine]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Tech]]></category>
		<category><![CDATA[GAE]]></category>
		<category><![CDATA[Rails]]></category>

		<guid isPermaLink="false">http://blog.yuyat.jp/?p=411</guid>
		<description><![CDATA[
			
				
			
		
昨日の記事『Ubuntu 10.04 で JRuby on Rails on GAE を始めるまでの作業ログ』では、Rails 2.3.5 で GAE プロジェクトを作りましたが、Rai [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fblog.yuyat.jp%2Farchives%2F411"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fblog.yuyat.jp%2Farchives%2F411&amp;source=yuya_takeyama&amp;style=normal&amp;service=bit.ly" height="61" width="50" /><br />
			</a>
		</div>
<p>昨日の記事<a href="http://blog.yuyat.jp/archives/395">『Ubuntu 10.04 で JRuby on Rails on GAE を始めるまでの作業ログ』</a>では、Rails 2.3.5 で GAE プロジェクトを作りましたが、Rails 2.3.8 でも作れるようになっていました !</p>
<ul>
<li><a href="http://gist.github.com/486250">Rails 2.3.8 on App Engine (DataMapper)</a></li>
</ul>
<p>で、書かれていた通りやってみたところ、あっさり動きました。</p>
<p>作業上の変更点は以下のような感じだとおもいます。</p>
<ul>
<li>Gemfile を手書きで書き足さなくてよくなった</li>
<li>ails238_appengine.rb に tiny_ds オプションはあるものの、動かない ?</li>
</ul>
<p>というわけで、昨日書いた記事は、書いた時点で既に陳腐化してということですね &#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.yuyat.jp/archives/411/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Ubuntu 10.04 で JRuby on Rails on GAE を始めるまでの作業ログ</title>
		<link>http://blog.yuyat.jp/archives/395</link>
		<comments>http://blog.yuyat.jp/archives/395#comments</comments>
		<pubDate>Sun, 25 Jul 2010 06:14:32 +0000</pubDate>
		<dc:creator>Yuya Takeyama</dc:creator>
				<category><![CDATA[Google App Engine]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Tech]]></category>
		<category><![CDATA[GAE]]></category>
		<category><![CDATA[Rails]]></category>

		<guid isPermaLink="false">http://blog.yuyat.jp/?p=395</guid>
		<description><![CDATA[
			
				
			
		
注意
この記事は既に情報が古くなっています。
2010 年 7 月 26 日現在での最新の情報は以下を参照してください。

GAE で Rails 2.3.8 が動くようになっていた

 [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fblog.yuyat.jp%2Farchives%2F395"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fblog.yuyat.jp%2Farchives%2F395&amp;source=yuya_takeyama&amp;style=normal&amp;service=bit.ly" height="61" width="50" /><br />
			</a>
		</div>
<p><strong>注意</strong></p>
<p>この記事は既に情報が古くなっています。<br />
2010 年 7 月 26 日現在での最新の情報は以下を参照してください。</p>
<ul>
<li><a href="http://blog.yuyat.jp/archives/411">GAE で Rails 2.3.8 が動くようになっていた</a></li>
</ul>
<p>この記事では、GAE (Google App Engine) 上で Ruby on Rails を動かすまでに必要な作業を紹介します。</p>
<p>既に GAE を利用している人であればご存知かと思いますが、GAE では Java か Python しか動かすことができないので、通常は Ruby を動かすことはできません。しかし、Java が動くということは、<a href="http://jruby.org/">JRuby</a> は動くので、その中で Rails を動かしてみよう、というものです。</p>
<p>この記事は、ほとんどが <a href="http://twitter.com/urekat">@urekat</a> さんによる<a href="http://d.hatena.ne.jp/urekat/20100220/1266691037">記事</a>のトレースです。ただし、現在は、@urekat さんの記事そのままでは動かない部分もあるので、そこも吸収しながら紹介していきます。</p>
<p>@urekat さんの記事が書かれたのが 2010 年 2 月 20 日で、半年も経たずにインストール作業が変わってしまっているので、この記事も数ヶ月後には役に立たなくなっているかもしれません。<strong>以下はすべて、2010 年 7 月 25 日現在の情報である</strong>、ということにご注意ください。</p>
<p>今回は、Ruby のインストールから始めます。</p>
<p><strong>Ruby, Rubygems, Java のインストール</strong></p>
<p>Ruby は MRI (Matz&#8217; Ruby Implementation) の 1.8.7 を用います。ここでは JRuby でないことにご注意ください。</p>
<p>Rubygems というのは、Ruby 用のパッケージ管理ソフトです。</p>
<p>Java は 1.6 を用います。</p>
<pre class="brush:bash">sudo apt-get install ruby rubygems openjdk-6-jdk</pre>
<p>正常にインストールされれば、以下の用にバージョンの確認ができるはずです。</p>
<pre class="brush:bash">$ ruby -v
ruby 1.8.7 (2010-01-10 patchlevel 249) [i486-linux]
$ gem -v
1.3.5
$ java -version
java version "1.6.0_18"
OpenJDK Runtime Environment (IcedTea6 1.8) (6b18-1.8-0ubuntu1)
OpenJDK Client VM (build 14.0-b16, mixed mode, sharing)</pre>
<p><strong>Rails のインストール</strong></p>
<p>先ほどインストールした Rubygems でインストールできます。</p>
<pre class="brush:bash">$ sudo gem install rails --version 2.3.5 --no-ri --no-rdoc
Successfully installed rake-0.8.7
Successfully installed activesupport-2.3.5
Successfully installed activerecord-2.3.5
Successfully installed rack-1.0.1
Successfully installed actionpack-2.3.5
Successfully installed actionmailer-2.3.5
Successfully installed activeresource-2.3.5
Successfully installed rails-2.3.5
8 gems installed</pre>
<p>現在、Rails は 2.3.8 が最新ですが、rails_appengine パッケージが 2.3.5 を必要賭しているようなので、2.3.5 を指定しています。</p>
<p>&#8211;no-ri &#8211;no-rdoc オプションは、ドキュメントのダウンロードをスキップするものです。ドキュメントが必要であれば、これらのオプションは外して構いません。</p>
<p><strong>google-appengine パッケージのインストール</strong></p>
<p>ここでは、先ほどインストールした Rubygems でインストールを行います。</p>
<pre class="brush:bash">$ sudo gem install google-appengine --no-ri --no-rdoc
Successfully installed jruby-jars-1.5.1
Successfully installed appengine-rack-0.0.11
Successfully installed appengine-apis-0.0.18
Successfully installed appengine-sdk-1.3.5
Successfully installed bundler08-0.8.5
Successfully installed rubyzip-0.9.4
Successfully installed appengine-tools-0.0.15
Successfully installed google-appengine-0.0.15
8 gems installed</pre>
<p>これだけで GAE 関連のライブラリ・ツールが一気にインストールされます。</p>
<p>しかし、通常このままでは appcfg.rb や dev_appserver.rb といったツールにパスが通っていないと思うので、Rubygems の bin ディレクトリにパスを通します。好みのエディタで ~/.bashrc ファイルを開き、一番下にでも以下のような記述を追加します。</p>
<pre class="brush:bash"># Rubygems
export PATH=$PATH:/var/lib/gems/1.8/bin</pre>
<p>続いて、~/.bashrc を再読み込みすれば反映されます。</p>
<pre class="brush:bash">source ~/.bashrc</pre>
<p>パスが通ったか、の確認は以下のように行うことができます。</p>
<pre class="brush:bash">$ which appcfg.rb dev_appserver.rb
/var/lib/gems/1.8/bin/appcfg.rb
/var/lib/gems/1.8/bin/dev_appserver.rb</pre>
<p>ここまでは @urekat さんの記事とほとんど変わりません。ここから先に、変更点を多く含みます。</p>
<p><strong>プロジェクトを作成する</strong></p>
<p>ここでいう「プロジェクト」とは「ひとかたまりの Rails アプリケーション」ぐらいの意味です。そのテンプレートにあたるファイル群を生成します。</p>
<p>プロジェクトはひとつのディレクトリ内で行うので、適当にディレクトリを作成し、その中に移動します。</p>
<pre class="brush:bash">$ mkdir test_app
$ cd test_app</pre>
<p>この中で、先ほどインストールし、パスを通した appcfg.rb コマンドを使います。最後の引数の . (ドット) に注意してください。</p>
<pre class="brush:bash">$ appcfg.rb generate_app .
=> Generating gemfile
=> Bundling gems
Calculating dependencies...
Updating source: http://gems.rubyforge.org
Downloading appengine-rack-0.0.11.pre.gem
Caching: jruby-jars-1.5.1.gem
Caching: jruby-rack-1.0.1.gem
Caching: rack-1.2.1.gem
Installing jruby-jars (1.5.1)
Installing rack (1.2.1)
Installing jruby-rack (1.0.1)
Installing appengine-rack (0.0.11.pre)
Done.
=> Packaging gems
=> Installing jruby-core-1.5.1.jar
=> Installing jruby-stdlib-1.5.1.jar
=> Installing jruby-rack-1.0.1.jar
=> Installing appengine-rack.jar
=> Generating rackup
=> Generating app.yaml</pre>
<p>これで、GAE 上で JRuby アプリケーションを動かすためのテンプレートが生成されました。</p>
<p>私自身は試していませんが、例えば <a href="http://www.sinatrarb.com/">Sinatra</a> を GAE 上で動かす、というときも、ここまでは同じ作業が必要になると思います。</p>
<p>次に、Rails のファイル群を生成します。途中「robots.txt を上書きしてもいいですか ?」と聞かれますが、Yes で問題ありません。</p>
<pre class="brush:bash">$ wget http://appengine-jruby.googlecode.com/hg/demos/rails2/rails2_appengine.rb
$ ruby rails2_appengine.rb
=> Bundling gems
Calculating dependencies...
Updating source: http://gems.rubyforge.org
Caching: actionmailer-2.3.5.gem
Caching: actionpack-2.3.5.gem
Caching: activerecord-2.3.5.gem
Caching: activeresource-2.3.5.gem
Caching: activesupport-2.3.5.gem
Downloading addressable-2.1.2.gem
Caching: appengine-apis-0.0.18.gem
Caching: appengine-rack-0.0.11.gem
Downloading dm-appengine-0.0.9.gem
Downloading dm-ar-finders-0.10.2.gem
Downloading dm-core-0.10.2.gem
Downloading dm-timestamps-0.10.2.gem
Downloading dm-validations-0.10.2.gem
Downloading extlib-0.9.15.gem
Caching: rack-1.0.1.gem
Caching: rails-2.3.5.gem
Downloading rails_appengine-0.0.4.gem
Downloading rails_dm_datastore-0.2.9.gem
Caching: rake-0.8.7.gem
Installing activesupport (2.3.5)
Installing extlib (0.9.15)
Installing rails_appengine (0.0.4)
Installing rack (1.0.1)
Installing actionpack (2.3.5)
Installing actionmailer (2.3.5)
Installing rake (0.8.7)
Installing addressable (2.1.2)
Installing dm-core (0.10.2)
Installing dm-timestamps (0.10.2)
Installing dm-validations (0.10.2)
Installing dm-appengine (0.0.9)
Installing appengine-rack (0.0.11)
Installing appengine-apis (0.0.18)
Installing dm-ar-finders (0.10.2)
Installing activerecord (2.3.5)
Installing rails_dm_datastore (0.2.9)
Installing activeresource (2.3.5)
Installing rails (2.3.5)
Deleting gem: rack (1.2.1)
Deleting gem: appengine-rack (0.0.11.pre)
Done.
=> Packaging gems
=> Installing appengine-api-labs-1.3.5.jar
=> Installing appengine-api-1.0-sdk-1.3.5.jar
=> Installing jruby-core-1.5.1.jar
=> Installing jruby-stdlib-1.5.1.jar
=> Installing jruby-rack-1.0.1.jar
=> Installing appengine-rack.jar
      exists
      create  app/controllers
      create  app/helpers
      create  app/models
      create  app/views/layouts
      create  config/environments
      create  config/initializers
      create  config/locales
      create  db
      create  doc
      create  lib
      create  lib/tasks
      create  log
      create  public/images
      create  public/javascripts
      create  public/stylesheets
      create  script/performance
      create  test/fixtures
      create  test/functional
      create  test/integration
      create  test/performance
      create  test/unit
      create  vendor
      create  vendor/plugins
      create  tmp/sessions
      create  tmp/sockets
      create  tmp/cache
      create  tmp/pids
      create  Rakefile
      create  README
      create  app/controllers/application_controller.rb
      create  app/helpers/application_helper.rb
      create  config/database.yml
      create  config/routes.rb
      create  config/locales/en.yml
      create  db/seeds.rb
      create  config/initializers/backtrace_silencers.rb
      create  config/initializers/inflections.rb
      create  config/initializers/mime_types.rb
      create  config/initializers/new_rails_defaults.rb
      create  config/initializers/session_store.rb
      create  config/environment.rb
      create  config/boot.rb
      create  config/environments/production.rb
      create  config/environments/development.rb
      create  config/environments/test.rb
      create  script/about
      create  script/console
      create  script/dbconsole
      create  script/destroy
      create  script/generate
      create  script/runner
      create  script/server
      create  script/plugin
      create  script/performance/benchmarker
      create  script/performance/profiler
      create  test/test_helper.rb
      create  test/performance/browsing_test.rb
      create  public/404.html
      create  public/422.html
      create  public/500.html
      create  public/index.html
   identical  public/favicon.ico
overwrite public/robots.txt? (enter "h" for help) [Ynaqdh] y
       force  public/robots.txt
      create  public/images/rails.png
      create  public/javascripts/prototype.js
      create  public/javascripts/effects.js
      create  public/javascripts/dragdrop.js
      create  public/javascripts/controls.js
      create  public/javascripts/application.js
      create  doc/README_FOR_APP
      create  log/server.log
      create  log/production.log
      create  log/development.log
      create  log/test.log
+ ./LICENSE
+ ./README
+ ./Rakefile
+ ./init.rb
+ ./lib/active_record/connection_adapters/nulldb_adapter.rb
+ ./lib/nulldb_rspec.rb
+ ./spec/nulldb_spec.rb
+ ./tasks/database.rake
##
## Now type './script/server.sh'
##</pre>
<p>最後に、Gemfile というファイルに以下の記述を追加します。</p>
<pre class="brush:ruby">gem 'appengine-rack', '0.0.10.pre'
gem 'jruby-openssl'
gem 'jruby-jars'</pre>
<p>appengine-rack パッケージは、現在 0.0.11 が最新のようですが、どうもそれだと動かないようなので、0.0.10.pre を指定しています。</p>
<p><strong>開発サーバーを起動する</strong></p>
<p>以上が問題なく完了すれば、開発サーバーを起動して、動作確認してみましょう。</p>
<pre class="brush:bash">$ dev_appserver.rb .
=> Bundling gems
Calculating dependencies...
Updating source: http://gems.rubyforge.org
Downloading appengine-rack-0.0.10.pre.gem
Downloading jruby-openssl-0.7.gem
Installing jruby-openssl (0.7)
Installing appengine-rack (0.0.10.pre)
Deleting gem: appengine-rack (0.0.11)
Done.
=> Packaging gems
=> Installing appengine-rack.jar
=> Installing appengine-api-labs-1.3.5.jar
=> Installing appengine-api-1.0-sdk-1.3.5.jar
=> Installing jopenssl.jar
=> Installing bcmail-jdk15-144.jar
=> Installing bcprov-jdk15-144.jar
=> Installing jruby-core-1.5.1.jar
=> Installing jruby-stdlib-1.5.1.jar
=> Installing jruby-rack-1.0.1.jar
=> Booting DevAppServer
=> Press Ctrl-C to shutdown server
# 中略
情報: The server is running at http://localhost:8080/</pre>
<p>初回は上記の用に、必要な Rubygems を jar ファイルとしてインストールする動作が伴うので時間がかかりますが、それ以降は普通にサーバーが起動するのみです。</p>
<p>http://localhost:8080/ にアクセスすれば、Rails のデフォルト画面が表示されているはずです。</p>
<p>「About your application’s environment」というテキストをクリックすると、以下のように表示されるはずです。</p>
<pre>Ruby version	1.8.7 (java)
RubyGems	disabled
Rack version	1.1
Rails version	2.3.5
Action Pack version	2.3.5
Active Support version	2.3.5
DataMapper version	0.10.2
Environment	development
JRuby Runtime version	1.5.1
JRuby-Rack version	1.0.1
AppEngine SDK version	1.3.5
AppEngine APIs version	0.0.18
Auth domain	gmail.com
Application id:version	new-app:1</pre>
<p>ここまでで、Ubuntu 10.04 のローカル環境において、GAE 開発サーバー上での JRuby on Rails の準備は終わりです。</p>
<p><strong>その後どうするか</strong></p>
<p>このあとは、自分なりのアプリケーションを開発したり、それを GAE 本番環境にデプロイしたりとしていくわけですが、それらについては @urekat さんの記事のままで問題ないようなので、ここでの説明は省きます。</p>
<p>これ以降については私自身も知らない部分が多いので、自分でアプリを作っていきながら、紹介していければと思います。</p>
<p>JRuby on Rails に興味を持った方は、<a href="http://groups.google.co.jp/group/jruby-users-jp">日本 JRuby ユーザ会</a>のイベントに参加してみましょう ! 次回 2010 年 8 月 6 日のイベントでは、@urekat さんの GAE についてのプレゼンも聞けます。</p>
<p><strong>関連ページ</strong></p>
<ul>
<li><a href="http://d.hatena.ne.jp/urekat/20100220/1266691037">[gae]GoogleAppEngine/JRuby+RailsでscaffoldからTwitterBotまで</a></li>
<li><a href="http://gist.github.com/269075">Rails 2.3.5 on App Engine (TinyDS)</a></li>
<li><a href="http://groups.google.co.jp/group/jruby-users-jp">日本 JRuby ユーザ会</a></li>
<li><a href="http://atnd.org/events/6595">日本JRubyユーザ会 第1回 : ATND</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.yuyat.jp/archives/395/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>PHPUnit によるテスト駆動開発 #03 コードを育てる編</title>
		<link>http://blog.yuyat.jp/archives/375</link>
		<comments>http://blog.yuyat.jp/archives/375#comments</comments>
		<pubDate>Sun, 18 Jul 2010 06:26:14 +0000</pubDate>
		<dc:creator>Yuya Takeyama</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Tech]]></category>
		<category><![CDATA[Test Driven Development]]></category>
		<category><![CDATA[PHPUnit]]></category>
		<category><![CDATA[TDD]]></category>

		<guid isPermaLink="false">http://blog.yuyat.jp/?p=375</guid>
		<description><![CDATA[
			
				
			
		
前回のおさらい
前回『#02 テストを書いてみる編』では、「とりあえず、とにかく、テストを書き、PHPUnit で実行すること」という目標のもと、簡単なテストコードの書き方を学びました。 [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fblog.yuyat.jp%2Farchives%2F375"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fblog.yuyat.jp%2Farchives%2F375&amp;source=yuya_takeyama&amp;style=normal&amp;service=bit.ly" height="61" width="50" /><br />
			</a>
		</div>
<p><strong>前回のおさらい</strong></p>
<p>前回<a href="/archives/342">『#02 テストを書いてみる編』</a>では、「とりあえず、とにかく、テストを書き、PHPUnit で実行すること」という目標のもと、簡単なテストコードの書き方を学びました。</p>
<p><strong>今回の目標</strong></p>
<p>テストコードを拡張しながら、仕様変更に対応する。また、リファクタリングする。</p>
<p><strong>仕様変更</strong></p>
<p>前回は、引数に 2 つの数字を引数に受け取り、その合計値を返すだけの <strong>add メソッド</strong>を作成しました。</p>
<p>今回は、<strong>数字が 2 の場合だけでなく、数字が 3 つの場合も、同じように合計値を返す</strong>必要が出てきたと仮定し、話を進めます。</p>
<p><strong>テストコードを拡張する</strong></p>
<p>add メソッドの他に addThreeNumbers メソッドを作ることもできますが、これでは足し算をする際に、数値が 2 つなのか 3 つなのかを意識しないといけないので、ナンセンスです。どちらの場合も add メソッドで処理できるようにしましょう。</p>
<p>前回はは「実際のコード」 -&gt; 「テストコード」という順序でしたが、今度は「テストコード」を先に書いてみます。つまり、<strong>「テストファースト」</strong>です。</p>
<p><script src="http://gist.github.com/480133.js?file=CalcTest.php"></script></p>
<p>testAddThreeNumbers メソッドを追加しました。</p>
<p>ここで一旦話はそれますが、<strong>テストメソッドの名前を test~ とするのは、PHPUnit のルール</strong>です。test~ という名前のメソッドだけが、テストとして実行されます。 一応、その他にもテストとして実行させるためのルールはありますが、とりあえず置いておきます。</p>
<p>もし、テストケースの中だけで使うサブルーチン的メソッドが必要であれば、test~ とは違う名前をつければ、そのメソッドはテストとして実行されることはありません。</p>
<p>それでは話を元に戻し、このままテストを実行しましょう。</p>
<pre class="brush:bash">$ phpunit CalcTest.php
PHPUnit 3.4.15 by Sebastian Bergmann.

.F

Time: 0 seconds, Memory: 4.75Mb

There was 1 failure:

1) CalcTest::testAddThreeNumbers
Failed asserting that &lt;integer:2&gt; matches expected &lt;integer:3&gt;.

/path/to/CalcTest.php:16

FAILURES!
Tests: 2, Assertions: 2, Failures: 1.</pre>
<p>当然失敗します。Calc オブジェクトの add メソッドはまだ、2 つの数値の足し算にしか対応していません。</p>
<p>一見無駄なように見えますが、この<strong>「初めに失敗する」</strong>というプロセスも、テスト駆動開発 (Test Driven Development; TDD) においては重要です。そもそものテストコードが間違っていた場合、「常に成功する」という状態になっていることもあり得るからです。</p>
<p><strong>「初めは失敗するが、コードを正しく実装することにより初めて成功する」</strong>というプロセスを踏むことによって、より堅実に TDD を行うことができるのです。</p>
<p><strong>コードを育てる</strong></p>
<p>それでは、追加された仕様、そしてテストコードに対応すべく、実際のコードを育ててみましょう。前回のコードは以下のようになっていました。</p>
<p><script src="http://gist.github.com/479238.js?file=Calc.php"></script></p>
<p>これを、以下のように書き換えます。</p>
<p><script src="http://gist.github.com/480133.js?file=Calc.php"></script></p>
<p>条件分岐により、第 3 引数がセットされていた場合の処理を追加しています。</p>
<p>ここで再びテストを実行します。</p>
<pre class="brush:bash">$ phpunit CalcTest.php
PHPUnit 3.4.15 by Sebastian Bergmann.

..

Time: 0 seconds, Memory: 4.75Mb

OK (2 tests, 2 assertions)</pre>
<p>見事成功しました !</p>
<p>この成功は、今回の「3 つの数値の合計値を返す」が達成できただけではなく、前回作った「2 つの数値の合計値を返す」をも損なうこと無く、コードを育てることができたことを意味します。</p>
<p><strong>テストコードにおける共通処理を一元化する</strong></p>
<p>仕様変更への対応が終わったので、今できているテストコードを振り返ってみましょう。</p>
<p>この記事の冒頭で、testAddThreeNumbers メソッドを作りましたが、「Calc オブジェクト生成」のための記述が、testAdd メソッドと重複していることがわかります。</p>
<p>このような共通処理は、<strong>setUp メソッドにより一元化</strong>させることができます。</p>
<p><script src="http://gist.github.com/480133.js?file=CalcTest_02.php"></script></p>
<p>このように、Calc オブジェクトの生成を一元化することで、各テストメソッドで同じことを繰り返す必要がなくなりました。これは DRY (Don&#8217;t Repeat Yourself; 同じことを繰り返さない) の原則に合致していると言えるでしょう。</p>
<p>この例のような短いコードにおいては、コードの絶対量が増えてしまっていますが、実際の開発において、テストコードはどんどん増えていくものですから、特に理由の無い限りは、setUp メソッドを使って共通化させましょう。</p>
<p>なお、setUp メソッドは、それぞれの<strong>テストメソッドが実行される前</strong>に、フックされる形で実行されます。なので、testAdd メソッドの $this->calc と、testAddThreeNumbers の $this->calc は、<strong>オブジェクトとしては別物</strong>ということに注意しましょう。</p>
<p><strong>リファクタリング</strong></p>
<p>さて、今度は実際のコードを振り返ってみましょう。</p>
<p>今回の改修では、if の条件分岐により、引数が 2 つでも 3 つでも合計値を返すよう、処理しています。</p>
<p>しかし今後、4 つの数値を合計も返さないといけなくなってしまったら、どうしましょう。一番簡単なのは、コピペ的に else if で分岐していき、引数が 4 つの場合も同じように処理することです。</p>
<p>しかし、それがまた、5 つ 6 つと増えて行ったら・・・。</p>
<p>この問題を解決するには、add メソッドの処理を根本的に書き換えなくてはなりません。今後のためとはいえ、今動いているものが壊れてしまうかもしれない、というリスクを犯してまで、リファクタリングする必要があるのでしょうか。</p>
<p>この場合、TDD であれば、リファクタリングを取ります。リファクタリングがある程度のリスクを抱える行為だとしても、それを安全に行うことができるのであれば、そして、放置する方が将来より大きなリスクとなることがわかっているのであれば、どちらを選ぶべきかは自明です。</p>
<p>では、今度は、引数がいくつだろうと処理できるよう、add メソッドをリファクタリングしてみましょう。</p>
<p>さっきと同じく、先にテストコードから書きます。</p>
<p><script src="http://gist.github.com/480133.js?file=CalcTest_03.php"></script></p>
<p>testAddTenNumbers メソッドを書いて、引数が 10 個の場合のテストを追加しました。これを実行すると、やはり失敗します。</p>
<pre class="brush:bash">$ phpunit CalcTest.php
PHPUnit 3.4.15 by Sebastian Bergmann.

..F

Time: 0 seconds, Memory: 5.00Mb

There was 1 failure:

1) CalcTest::testAddTenNumbers
Failed asserting that &lt;integer:6&gt; matches expected &lt;integer:55&gt;.

/path/to/CalcTest.php:26

FAILURES!
Tests: 3, Assertions: 3, Failures: 1.</pre>
<p>今度は、このテストが成功するよう、実際のコードをリファクタリングします。</p>
<p><script src="http://gist.github.com/480133.js?file=Calc_02.php"></script></p>
<p>func_get_arg() を使って、可変引数に対応できるよう、リファクタリングを行いました。再びテストを実行します。</p>
<pre class="brush:bash">$ phpunit  CalcTest.php
PHPUnit 3.4.15 by Sebastian Bergmann.

...

Time: 0 seconds, Memory: 5.00Mb

OK (3 tests, 3 assertions)</pre>
<p>見事成功しました !</p>
<p>元のコードを根本的に書き換えていますが、数値が 2 つ、もしくは 3 つの場合の動作も壊すこと無く、引数がいくつ来ても合計値を返すことができるようになりました。</p>
<p><strong>まとめ</strong></p>
<p>今回は、以下のことを学びました。</p>
<ul>
<li>「テストコードを書く」 -&gt; 「テスト実行 (失敗)」 -&gt; 「実際のコードを書く」 -&gt; 「テスト実行 (成功)」<br />
というサイクルにより、着実にコードを育て、リファクタリングすることができる。</li>
<li>まず「失敗する」ことを確認してから実装を行うことで、テストコード自体のミスを防ぐことができる。</li>
<li>テストケースにおいて、テストメソッドは test~ と命名する必要がある。</li>
<li>setUp メソッドを使うことで、テスト中の共通処理を一元化することができる。</li>
</ul>
<p>今回は、前回一旦無視した<strong>「テストファースト」</strong>というスタイルにのっとり、解説を行いました。</p>
<p>ですが、実際の開発においては、より大きなプログラムを扱うこととなるため、<strong>クラス設計</strong>がしっかりできる人で無い限り、「テストファースト」の実践は難しいでしょう。</p>
<p>しかし、TDD を実践し続けることで、クラス設計のセンスも向上する、とも言われています。次回はその辺りの、TDD がもたらす<strong>副産物</strong>について話を進めて行きます。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.yuyat.jp/archives/375/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHPUnit によるテスト駆動開発 #02 テストを書いてみる編</title>
		<link>http://blog.yuyat.jp/archives/342</link>
		<comments>http://blog.yuyat.jp/archives/342#comments</comments>
		<pubDate>Sat, 17 Jul 2010 05:51:50 +0000</pubDate>
		<dc:creator>Yuya Takeyama</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Tech]]></category>
		<category><![CDATA[Test Driven Development]]></category>
		<category><![CDATA[PHPUnit]]></category>
		<category><![CDATA[TDD]]></category>

		<guid isPermaLink="false">http://blog.yuyat.jp/?p=342</guid>
		<description><![CDATA[
			
				
			
		
目的
とりあえず、とにかく、テストを書き、PHPUnit で実行すること。
想定される読者

PHP5 の基本的な文法を理解している
テスト駆動開発 (Test Driven Devel [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fblog.yuyat.jp%2Farchives%2F342"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fblog.yuyat.jp%2Farchives%2F342&amp;source=yuya_takeyama&amp;style=normal&amp;service=bit.ly" height="61" width="50" /><br />
			</a>
		</div>
<p><strong>目的</strong></p>
<p>とりあえず、とにかく、テストを書き、PHPUnit で実行すること。</p>
<p><strong>想定される読者</strong></p>
<ul>
<li>PHP5 の基本的な文法を理解している</li>
<li>テスト駆動開発 (Test Driven Development; TDD) という言葉は知っているが、やってみたことは無い</li>
<li>PHPUnit 3.4 以降をインストールしている</li>
</ul>
<p>TDD を知らない、PHPUnit をまだインストールしていない、という方は前回の記事<a href="/archives/327">『#01 インストール編』</a>をご覧ください。</p>
<p>逆に、上記項目より上を行く方にとっては、特に参考になることは無いかもしれません。</p>
<p><strong>テストされるコード</strong></p>
<p>初めに、実際にプログラム上で使われるコードを用意します。</p>
<p>TDD の世界には「テストファースト」という言葉があります。それは、「実際のコードよりもテストコードを先に書く」というスタイルを表していますが、ここではそういった細かいことは気にせず話を進めます。</p>
<p><script src="http://gist.github.com/479238.js?file=Calc.php"></script></p>
<p>2 つの引数を足し算するだけの簡単なメソッドを持った、非常にシンプルなクラスです。</p>
<p><strong>テストするコード</strong></p>
<p>以下のようなコードを用意します。</p>
<p><script src="http://gist.github.com/479238.js?file=CalcTest.php"></script></p>
<p>これが、PHPUnit でテストを書く際の最小単位である、テストケースです。</p>
<p>注目すべきは、<strong>testAdd メソッドの中身</strong>です。これは、assertEquals というメソッドが、「$calc オブジェクトの add メソッドに、引数として 1 と 1 を渡せば、2 になるよね」といったことを確かめるためのコードです。</p>
<p>その他の部分は、PHPUnit でテストケースを書くためのおまじないみたいなものです。細かいルールについては次回以降、徐々に説明するとして、とりあえず次に進みます。</p>
<p><strong>テストを実行する</strong></p>
<p>ターミナル上で以下のコマンドを実行します。</p>
<pre class="brush:bash">$ phpunit CalcTest.php
PHPUnit 3.4.15 by Sebastian Bergmann.

.

Time: 1 second, Memory: 4.75Mb

OK (1 test, 1 assertion)</pre>
<p>最後の行の「OK」は、このテストが成功し、コード (Calc.php) が正確に実装されていることを示しています。また、1 つのテスト (1 test) と 1 つのアサーション (1 assertion) が実行された、ということも示されています。</p>
<p>もし add メソッドに間違いがあった場合は、PHPUnit の実行結果は以下のようになります。</p>
<pre class="brush:bash">$ phpunit CalcTest.php
PHPUnit 3.4.15 by Sebastian Bergmann.

F

Time: 0 seconds, Memory: 4.75Mb

There was 1 failure:

1) CalcTest::testAdd
Failed asserting that &lt;integer:1&gt; matches expected &lt;integer:2&gt;.

/path/to/CalcTest.php:10

FAILURES!
Tests: 1, Assertions: 1, Failures: 1.</pre>
<p>これは、add メソッドが 2 を返すはずなのに、実際は 1 が返ってきてしまったために、テストが失敗してしまったことを示しています。</p>
<p>このような場合は、テストが成功するまでコードを修正しましょう。</p>
<p><strong>アサーションとは</strong></p>
<p>アサーションとは、変数の値や、メソッドの返り値をチェックすることです。さっきのテストケースでいえば、assertEquals メソッドがそれを行っています。</p>
<p>ざっくり言ってしまえば、前回からの繰り返しになりますが、<strong>「このメソッドにこの引数を与えると、この値が返ってくるよね」</strong>といったことをチェックすること、と言えるでしょう。</p>
<p>アサーションには多くの種類があり、例を挙げれば、</p>
<ul>
<li>assertEquals()<br />
2 つの値が等しいか</li>
<li>assertTrue()<br />
値が true であるか</li>
<li>assertFalse()<br />
値が false であるか</li>
<li>assertType()<br />
値の型が正しいか</li>
</ul>
<p>などなど、たくさんあります。</p>
<p>ですが、とりあえずは <strong>assertEquals と assertTrue だけ使えれば大抵のことは何とかなる</strong>ので、他は必要に応じて調べながら覚えていけばよいでしょう。</p>
<p><strong>まとめ</strong></p>
<p>今回は、テストを書くこと、そして実行すること、に的を絞って解説しました。</p>
<p>次回は、テストコードを拡張させながら、PHPUnit でテストを書く際のルールについて、もう少し踏み込んでいこうとおもいます。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.yuyat.jp/archives/342/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHPUnit によるテスト駆動開発 #01 インストール編</title>
		<link>http://blog.yuyat.jp/archives/327</link>
		<comments>http://blog.yuyat.jp/archives/327#comments</comments>
		<pubDate>Sun, 11 Jul 2010 14:54:36 +0000</pubDate>
		<dc:creator>Yuya Takeyama</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Tech]]></category>
		<category><![CDATA[Test Driven Development]]></category>
		<category><![CDATA[TDD]]></category>

		<guid isPermaLink="false">http://blog.yuyat.jp/?p=327</guid>
		<description><![CDATA[
			
				
			
		
テスト駆動開発とは
テスト駆動開発 (Test Driven Development; TDD) とは、テストケースを書くことからプログラミングを始める、開発手法です。
ざっくり言うと、 [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fblog.yuyat.jp%2Farchives%2F327"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fblog.yuyat.jp%2Farchives%2F327&amp;source=yuya_takeyama&amp;style=normal&amp;service=bit.ly" height="61" width="50" /><br />
			</a>
		</div>
<p><strong>テスト駆動開発とは</strong></p>
<p>テスト駆動開発 (Test Driven Development; TDD) とは、テストケースを書くことからプログラミングを始める、開発手法です。</p>
<p>ざっくり言うと、「このメソッドにこの引数を与えると、この値が返ってくるよね」といったことを、テストコードを用いて検証しながら、開発を進めていくスタイルと言うことができるでしょう。</p>
<p>TDD を知らない人がこの説明を聞くと、「TDD はコードの安全性のための手法である」と思われるかもしれません。<br />
確かに、TDD はコードの安全性をもたらします。<br />
しかし、TDD がもたらすものの中には、<strong>「コードの簡潔性」</strong>をも含まれます。</p>
<p><strong>何故コードが簡潔になるのか</strong></p>
<p>これは私見ですが、簡潔で読みやすいコードは、<strong>「入力と出力の束である」</strong>ことが多いです。<br />
それはつまり、メソッド・関数が適切な単位で細かく文節され、それらの協調により組み立てられているコードです。</p>
<p>逆に読みづらい・わかりづらいコードは、「1 つのメソッド・関数が頑張り過ぎている」コードです。<br />
1 つのメソッドが長いと、開発やデバッグの際に、「コード中のどこにバグが潜んでいるのか」を見つけ出すことが困難になります。</p>
<p>TDD による開発では、<strong>「テストしやすいコードを書く」</strong>ために、必然的に、コードが<strong>細分化</strong>されます。<br />
その 1 つ 1 つに対して「このメソッドにこの引数を与えると、この値が返ってくるよね」を書いておけば、大幅なリファクタリングも、コードの同質性を検証しながら行うことができます。</p>
<p><strong>TDD と私</strong></p>
<p>新卒で Web エンジニアとして就職した 1 年前、私は TDD を知りませんでした。</p>
<p>そのうち、ブログなどで TDD について知り、Ruby の標準ライブラリ test/unit を使って、遊び程度にテストを書くようになります。</p>
<p>その後、<a href="http://regional.rubykaigi.org/tokyo03">東京 RubyKaigi 03</a> における、<a href="http://d.hatena.ne.jp/t-wada/">和田卓人氏</a> (<a href="http://twitter.com/t_wada">@twada</a>) のワークショップで <a href="http://d.hatena.ne.jp/t-wada/20100228/p1">RSpec の写経</a>を行うことで、TDD の威力を実感することになります。</p>
<p>それ以来、仕事でも、PHPUnit を用いての、TDD による開発を心がけています。</p>
<p>プログラミングについては少しずつ勉強していますが、その中でも一番インパクトがあったのは間違いなく TDD であったと言いきることができます。<br />
とはいえ、まだまったくの初心者レベルなので、勉強しながら、このブログで発表していこうと思います。</p>
<p><strong>PHP Unit をインストール</strong></p>
<p>Ubuntu 10.04 上の LAMP 環境で、PHP5 以上 (筆者は 5.3) 、そして pear がインストールされていることを前提としています。</p>
<p><a href="http://www.phpunit.de/manual/3.4/ja/installation.html">公式ドキュメント</a>に倣いますが、root 権限が必要となるため、sudo 付きで実行します。</p>
<pre class="brush:bash">sudo pear channel-discover pear.phpunit.de
sudo pear channel-discover pear.symfony-project.com</pre>
<p>上記コマンドで PEAR チャネル (ライブラリのインストール元のサーバ) を追加し、次のコマンドで PHPUnit がインストールされます。</p>
<pre class="brush:bash">sudo pear install phpunit/PHPUnit</pre>
<p>これでインストール完了です。引数無しで phpunit コマンドを実行して、バージョン情報と Usage が表示されれば成功です。<br />
2010 年 7 月 11 日現在では、PHPUnit 3.4.14 がインストールされます。</p>
<p>本日はここまで。<br />
次回は実際にテストコードを書いていく予定です。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.yuyat.jp/archives/327/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>mb_addslashes() というのを作った</title>
		<link>http://blog.yuyat.jp/archives/321</link>
		<comments>http://blog.yuyat.jp/archives/321#comments</comments>
		<pubDate>Sun, 16 May 2010 15:36:04 +0000</pubDate>
		<dc:creator>Yuya Takeyama</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Tech]]></category>
		<category><![CDATA[mbstring]]></category>

		<guid isPermaLink="false">http://blog.yuyat.jp/?p=321</guid>
		<description><![CDATA[
			
				
			
		
社内勉強会にて、PHP のセキュリティについてプレゼンすることになりました。その中で、addslashes() はマルチバイト文字のことを考慮していないから使用禁止 ! ということを話す [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fblog.yuyat.jp%2Farchives%2F321"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fblog.yuyat.jp%2Farchives%2F321&amp;source=yuya_takeyama&amp;style=normal&amp;service=bit.ly" height="61" width="50" /><br />
			</a>
		</div>
<p>社内勉強会にて、PHP のセキュリティについてプレゼンすることになりました。その中で、<strong>addslashes()</strong> はマルチバイト文字のことを考慮していないから使用禁止 ! ということを話すのですが、代案を示さないのもよくないので、<strong>mb_addslashes()</strong> というものを作りました。</p>
<p>ただ、addslashes() がマルチバイトに対応したところで、<strong>SQL 文のエスケープとして適切か ?</strong> というと必ずしもそうではないので、今度は mb_mysql_real_escape_string() (長い) を作ろうと思います。</p>
<p>ともあれ、せっかく書いたので公開します。<strong>mbstring</strong> 必須です。</p>
<p><script src="http://gist.github.com/402780.js"></script></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.yuyat.jp/archives/321/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>xml.parsers.expat で XML 文書を解析する</title>
		<link>http://blog.yuyat.jp/archives/311</link>
		<comments>http://blog.yuyat.jp/archives/311#comments</comments>
		<pubDate>Sun, 02 May 2010 18:26:04 +0000</pubDate>
		<dc:creator>Yuya Takeyama</dc:creator>
				<category><![CDATA[Google App Engine]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Tech]]></category>
		<category><![CDATA[GAE]]></category>
		<category><![CDATA[XML]]></category>

		<guid isPermaLink="false">http://blog.yuyat.jp/?p=311</guid>
		<description><![CDATA[
			
				
			
		
Google App Engine (以下 GAE) 上で Amazon の Product Advertising API を扱うべく、Python の XML ライブラリについて調べ [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fblog.yuyat.jp%2Farchives%2F311"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fblog.yuyat.jp%2Farchives%2F311&amp;source=yuya_takeyama&amp;style=normal&amp;service=bit.ly" height="61" width="50" /><br />
			</a>
		</div>
<p><strong>Google App Engine</strong> (以下 GAE) 上で Amazon の Product Advertising API を扱うべく、Python の XML ライブラリについて調べていました。どうも Pythonista の間では <strong>lxml</strong> というのがメジャーらしいので、さっそく組み込んでみたのですが、どうも<strong>動かない</strong>。</p>
<p>調べて見たところ、GAE 上では、セキュリティの関係上、<strong>C 拡張による Python ライブラリは動かない</strong>とのことで、lxml は使えないようです。</p>
<p><strong>代替ライブラリを探す</strong></p>
<p>C 拡張がダメということは、つまり <strong>Pure Python</strong> なライブラリなら OK、という解釈でいいのでしょうか。探してみたところ、ちょうど先日購入した <strong><span class="isbn_anchor"><a href="http://www.amazon.co.jp/o/ASIN/4873112761/yuyat-22/">Python クックブック 第2版</a></span></strong> の p.479 に「<em>XML 文書を Python のオブジェクトツリーに変換</em>」というレシピが載っていました。</p>
<p><strong>写経、そして修正</strong></p>
<p>さっそく写経してみたのですが、<strong>動かない</strong>。しばらく調べた結果、誤植によるものと思われるバグを発見。その他いくつかの修正を加えたものを GitHub に公開しました。</p>
<p>主な変更点は以下の通りです。</p>
<ul>
<li>Xml2Obj.EndElement が上手く動かないのを修正</li>
<li>UTF-8 に対応</li>
<li>ファイルからではなく、文字列を XML として読み込むよう変更</li>
<li>__getattr__ メソッドにより、Element.getElements() のショートカットを作成 (詳細は後述)</li>
</ul>
<p>ただし、あくまでも習作であり、エラー処理等もかなり甘いので、実用的とは言えません。<br />
その代わり、ちょっと遊ぶ程度にはちょうどいい手軽さかも。</p>
<p><strong>コード</strong></p>
<p><script src="http://gist.github.com/387300.js?file=xml2obj.py"></script></p>
<p><strong>テストコード</strong></p>
<p><script src="http://gist.github.com/387300.js?file=xml2objtestcase.py"></script></p>
<p><strong>__getattr__ による Element.getElements() へのショートカットについて</strong></p>
<p>__getattr__ というのは、インスタンスに存在しないプロパティを呼び出そうとしたときに呼び出されるもので、PHP でいうと、マジックメソッドの <a href="http://jp.php.net/__get">__get</a> にあたるものと言えるでしょう。</p>
<p>これにより、以下のようなショートカットを実現しています。意味はどちらも同じです。</p>
<p><script src="http://gist.github.com/387300.js?file=sample.py"></script></p>
<p><strong>終わりに</strong></p>
<p>もともと GAE に組み込むことを目的として上記ライブラリを修正したわけですが、実はまだ組み込めてません・・・。ただ、expat を GAE に組み込んでいる例はネット上に転がっているので、まぁこれもいけるのではないかと。真相はまた今度。</p>
<p><strong>関連リンク</strong></p>
<ul>
<li><a href="http://www.python.jp/doc/2.4/lib/module-xml.parsers.expat.html">xml.parsers.expat &#8212; Expat を使った高速な XML 解析</a></li>
<li><a href="http://typea.info/blg/glob/2009/08/amazon_product_advertising_api_1.html">Amazon Product Advertising API を GAE/Python に組み込む</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.yuyat.jp/archives/311/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Google App Engine の開発サーバーで DataStore を保持し続ける</title>
		<link>http://blog.yuyat.jp/archives/307</link>
		<comments>http://blog.yuyat.jp/archives/307#comments</comments>
		<pubDate>Sat, 01 May 2010 11:51:17 +0000</pubDate>
		<dc:creator>Yuya Takeyama</dc:creator>
				<category><![CDATA[Google App Engine]]></category>
		<category><![CDATA[Tech]]></category>
		<category><![CDATA[GAE]]></category>

		<guid isPermaLink="false">http://blog.yuyat.jp/?p=307</guid>
		<description><![CDATA[
			
				
			
		
ゴールデンウィーク中にサービスをひとつリリースするべく、Google App Engine (以下 GAE) に奮闘中です。なので、しばらくは、Google App Engine 上での [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fblog.yuyat.jp%2Farchives%2F307"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fblog.yuyat.jp%2Farchives%2F307&amp;source=yuya_takeyama&amp;style=normal&amp;service=bit.ly" height="61" width="50" /><br />
			</a>
		</div>
<p>ゴールデンウィーク中にサービスをひとつリリースするべく、Google App Engine (以下 GAE) に奮闘中です。なので、しばらくは、Google App Engine 上での開発を行うにあたっての Tips 的なエントリーが続きそうです。</p>
<p>さて、本題ですが、DataStore はもともと永続化しているものですが、ここでの話は<strong>「開発環境の再起動をする度に DataStore がクリアされるのを何とかしたい」</strong>という話です。</p>
<p>どういうことかというと、GAE の開発サーバー dev_appserver.py (Python 版) では DataStore のファイルがテンポラリーフォルダ (Linux だと /tmp) に保存されるので、<strong>OS を再起動したりすると、DataStore がクリアされてしまう</strong>ので、それを防ごう、という話です。</p>
<p><strong>やり方</strong></p>
<p>dev_appserver.py の起動時に、&#8211;datastore_path というオプションで保存ファイル名を指定してあげれば OK。</p>
<pre class="brush:bash">
$ dev_appserver.py . --datastore_path=PATH
</pre>
<p>こうすれば、テスト時のデータを保持し続けることができます。</p>
<p><strong>注意</strong></p>
<p>GAE プログラムのフォルダ内に保存すると、本番環境へのデプロイ時に一緒にアップロードされるので、保存先は外のフォルダに保存しましょう。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.yuyat.jp/archives/307/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>JavaScript で private なインスタンス変数 (のようなもの) を作る</title>
		<link>http://blog.yuyat.jp/archives/301</link>
		<comments>http://blog.yuyat.jp/archives/301#comments</comments>
		<pubDate>Tue, 13 Apr 2010 05:13:44 +0000</pubDate>
		<dc:creator>Yuya Takeyama</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Tech]]></category>
		<category><![CDATA[OOP]]></category>

		<guid isPermaLink="false">http://blog.yuyat.jp/?p=301</guid>
		<description><![CDATA[
			
				
			
		
通勤電車の中で思いついたコードを、昼休みを利用して書いてみました。動いたので公開。ただし、バッドノウハウなので要注意。

解説
まず、クロージャを利用して、外からは見えない privat [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fblog.yuyat.jp%2Farchives%2F301"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fblog.yuyat.jp%2Farchives%2F301&amp;source=yuya_takeyama&amp;style=normal&amp;service=bit.ly" height="61" width="50" /><br />
			</a>
		</div>
<p>通勤電車の中で思いついたコードを、昼休みを利用して書いてみました。動いたので公開。ただし、バッドノウハウなので要注意。</p>
<p><script src="http://gist.github.com/364324.js"></script></p>
<p><strong>解説</strong></p>
<p>まず、<strong>クロージャ</strong>を利用して、外からは見えない privateNameSpace という名前空間を作ります。この privateNameSpace 自体は、言わば <strong>private static</strong> なものなので、Dog オブジェクトが個別に持つものではなく、Dog クラスに紐づく (ように見える) 空間です。</p>
<p>これを、各インスタンス毎に分けて使えるよう、Dog コンストラクタで objectId というメンバ (これは public) を作っています。objectId は、ミリ秒単位の時間と、乱数を文字列として結合したもので、<strong>およそユニークである</strong>ことが期待されています。とはいえ、理論上は衝突の可能性もあり得るのですが・・・。</p>
<p>この objectId をキーに、privateNameSpace の中に、連想配列オブジェクトを作れば、インスタンスごとに private な名前空間を持つことができる、というわけです。</p>
<p>2 番目のコードを動かしてみると、何となくそれらしく動いていることが確認できます。</p>
<p>ただ、大きな問題は、<strong>objectId を乗っ取ることができてしまう</strong>ということです。3 番目のコードのようにすることで、もともとは pochi オブジェクトだったものが、あたかも taro オブジェクトであるかのように振舞うようになってしまいます。</p>
<p><strong>まとめ</strong></p>
<p>上記の問題の他にも、メンバの取得のための記述が煩雑なところも大きな問題と言えます。もう少し抽象化できれば書きやすくなるかもしれませんが、いずれにせよ、実用的な方法では無いでしょう。</p>
<p>似たようなことを実現するためのノウハウはネット上にいろいろ転がっているようなので、そちらも読んでみたいと思った次第です。</p>
<p><strong>あとで読む</strong></p>
<ul>
<li><a href="http://www.crockford.com/javascript/private.html">Private Members in JavaScript</a></li>
<li><a href="http://d.hatena.ne.jp/llamerada/20050903/1125720037">JavaScript で private/public の実現</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.yuyat.jp/archives/301/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
