<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>ウノウラボ by Zynga Japan</title>
    <link rel="alternate" type="text/html" href="http://labs.unoh.net/" />
    <link rel="self" type="application/atom+xml" href="http://labs.unoh.net/atom.xml" />
    <id>tag:labs.unoh.net,2006://2</id>
    <link rel="service.post" type="application/atom+xml" href="http://www.unoh.net/mt32/mt-atom.cgi/weblog/blog_id=2" title="ウノウラボ by Zynga Japan" />
    <updated>2011-04-19T08:27:21Z</updated>
    <subtitle>Zynga Japan株式会社のデモ版サービスやTIPSなどの情報</subtitle>
    <generator uri="http://www.sixapart.com/movabletype/">Movable Type  4.261</generator>
 

<entry>
    <title>I love spacer</title>
    <link rel="alternate" type="text/html" href="http://labs.unoh.net/2011/04/i_love_spacer.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.unoh.net/mt32/mt-atom.cgi/weblog/blog_id=2/entry_id=1944" title="I love spacer" />
    <id>tag:labs.unoh.net,2011://2.1944</id>
    
    <published>2011-04-19T07:41:11Z</published>
    <updated>2011-04-19T08:27:21Z</updated>
    
    <summary><![CDATA[携帯向けXHTMLを書いているとバッドノウハウばかりが身について行くのですが、その中で私が愛してやまないspacerのことについて熱く語ってみようと思います。 私が個人的に見つけたバッドノウハウばかりですので、これら以外にもっとスマートな方法がありましたら是非ご教示ください。 一般的な使い方 &lt;br /&gt;&lt;br /&gt;での改行するなんてとんでもない、でも3キャリ対応しようと思ったらline-heightも使えないし。。。そんなことでお悩みの方が良く使っているのがこのspacer。原理は簡単、1ドットの画像をimgタグのwidthとheightで大きさを好きに変えてお好みの行間を作るのがメインのお仕事です。 気をつけること &lt;div&gt;&lt;img src="spacer画像のパス" width="X" height="Y" /&gt;&lt;/div&gt...]]></summary>
    <author>
        <name>unoh</name>
        
    </author>
    
    <content type="html" xml:lang="ja" xml:base="http://labs.unoh.net/">
        <![CDATA[<p>携帯向けXHTMLを書いているとバッドノウハウばかりが身について行くのですが、その中で私が愛してやまないspacerのことについて熱く語ってみようと思います。</p>

<p>私が個人的に見つけたバッドノウハウばかりですので、これら以外にもっとスマートな方法がありましたら是非ご教示ください。</p>

<h3>一般的な使い方</h3>
<div>&lt;br /&gt;&lt;br /&gt;での改行するなんてとんでもない、でも3キャリ対応しようと思ったらline-heightも使えないし。。。そんなことでお悩みの方が良く使っているのがこのspacer。</div><div>原理は簡単、1ドットの画像をimgタグのwidthとheightで大きさを好きに変えてお好みの行間を作るのがメインのお仕事です。</div>

<h4>気をつけること</h4>
<pre class="code">&lt;div&gt;&lt;img src="spacer画像のパス" width="X" height="Y" /&gt;&lt;/div&gt;</pre>
のみでももちろんその用途は果たせますが、一部機種にて必ず&lt;br /&gt;&lt;br /&gt;した時と同じだけのスペースが入ってしまうことがございます。
<div>その対策として。。。</div>
<pre class="code">&lt;div style="height:Ypx"&gt;&lt;img src="spacer画像のパス" width="X" height="Y" /&gt;&lt;/div&gt;</pre>
と外側のdivタグにも同じ高さを指定してあげることで見た目的には正しいスペースが表示されるようになります。

<h3>デザインを統一するために</h3>
<div>同じようなデザインのページなのに、スペースの開け方だけ全然違っていても気になる人なんてほとんどいないかとは思いますが、私のようなA型の人はぜひサイト全体でスペースの開け方を統一してみましょう！</div>
<ol>
    <li>3,4種類の行間スペースを決める<br />
    私が良く使っているのは、2px, 3px, 5px, 10pxの4種類です</li>
    <li>どの行間スペースをどんな時に使うのかを決める<br />
        例)
        <ul>
            <li>2px: デザイン上で必要な微妙なスペース</li>
            <li>3px; 文章と文章の間のスペース</li>
            <li>10px: フッター等で本当にいっぱい開けたい時</li>
            <li>5px: 上記以外で適当なスペースがほしい時</li>
        </ul>
    </li>
    <li>自分を含めコーディングする人がピクセル単位で指定出来ないようにする<br />
    人間は間違えるものです。自分で決めたルールでもあれ？どれだっけ？と忘れてしまうこともあります。厳密にはもちろん不可能ですが、たとえばHTMLヘルパー的なものでどの高さにするのかをピクセル単位ではなく種類を選ばせることによってミスは大分減り、より統一されたデザインのサイトに仕上がるかと思います。</li>
</ol>

<h3>height代わりに使う</h3>
<div>これまた3キャリ対応させようと思っていると、auの一部(?)機種にてtableタグのheightが効かないことに気付きました。</div>
<div>そんな時にもspacerは使えます！</div>
<pre class="code">&lt;table width="100%" cellspacing="0" cellpadding="0" border="0"&gt;
&nbsp;&nbsp;&lt;tr&gt;
&nbsp;&nbsp; &nbsp;&lt;td&gt;
&nbsp;&nbsp; &nbsp; &nbsp;何かの文章
&nbsp;&nbsp; &nbsp;&lt;/td&gt;
&nbsp;&nbsp; &nbsp;&lt;td width="1"&gt;
&nbsp;&nbsp; &nbsp; &nbsp;&lt;!-- 高さを100pxにしたい場合 --&gt;
&nbsp;&nbsp; &nbsp; &nbsp;&lt;img src="spacer画像のパス" width="1" height="100" /&gt;
&nbsp;&nbsp; &nbsp;&lt;/td&gt;
&nbsp;&nbsp;&lt;/tr&gt;
&lt;/table&gt;</pre>
<div>このような感じになります！</div>
<div>※見やすいようにtableとimgタグ両方にボーダーを入れています。</div>
<table width="100%" cellspacing="0" cellpadding="0" border="1">
  <tbody><tr>
    <td>
      何かの文章
    </td>
    <td width="1">
      <img src="http://labs.unoh.net/spacer.gif/spacer.gif" width="1" height="100" border="1" />
    </td>
  </tr>
</tbody></table>
<div>tableタグ自体のheightが使えなくても、無理やりspacerでその分の高さを出しているだけなのですが、こうすることにより、中身のテキストや画像が短くても一定の高さのtableがほしい場合のデザインを実現出来ます。</div>


<h3>ラインを表現するのに使う</h3>
<div>&lt;hr /&gt;タグの代わりに1pxの画像を横いっぱい伸ばして使っている場合が多いかと思いますが、そうすると、ローディング中にラインが表示されなかったり、機種によっては特別なことをしない限りテキストと一行分と同じだけのスペースをとってしまうので、少し見栄えが悪くなります。</div>
<div>そこでspacerの登場です。</div>
<pre class="code">&lt;div style="background-color:red;height:1px"&gt;
&nbsp;&nbsp;&lt;img src="spacer画像のパス" width="1" height="1" /&gt;
&lt;/div&gt;
</pre>
<div>以下のようになります。</div>
<div style="background-color:red;height:1px">
  <img src="http://labs.unoh.net/spacer.gif/spacer.gif" width="1" height="1" />
</div>
<div>何を隠そう行間用のspacerのdivに色を付けただけなんです。</div>
<div>しかし、こうすることにより、ローディング中でもきちんと表示されるラインの出来上がりです！</div>

<p>何かと制限の多い携帯向けXHTMLですが、spacerのように頭をひねれば意外といろいろが解決可能だということに気づくかと思います。<br />
全てがバッドノウハウですので、本当に役に立っているのか時たま分からなくなる時もありますが、みなさんもぜひspacerを愛でみてはいかがでしょうか？意外な使い方が見つかるかもしれません！</p>]]>
        
    </content>
</entry>

<entry>
    <title>わんわん</title>
    <link rel="alternate" type="text/html" href="http://labs.unoh.net/2011/04/post_153.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.unoh.net/mt32/mt-atom.cgi/weblog/blog_id=2/entry_id=1940" title="わんわん" />
    <id>tag:labs.unoh.net,2011://2.1940</id>
    
    <published>2011-04-01T02:19:24Z</published>
    <updated>2011-04-01T04:28:27Z</updated>
    
    <summary>きゃんきゅーんわんわおんわーんばうきゃんきゃんきゃうんわおんわおんわんきゃんきゃんきゃうんきゃんきゃん! わうわーん。 わんわーんわんわうわん。 わんわおんわんわおんわん! きゃうんわーんわうきゅーんわおんわーんばうわおんわんわおんわん。 わーんわーんきゃんわうわんわんわおん! わんきゃんきゃんわうわーんわんきゃんわおんわんわおんわん! わん。 きゃうんきゃんきゅーん。 わーんわんきゃんわうわーんばうわんわんわうきゅーんきゃんわんわーんわおんわん。 きゃうんわおんわおんわおん! きゃんわおんわおんわんばうわおんわんばうきゃんわおんきゃうんわおん! わんわおんばうきゃん! わうきゃうんきゃんわおんきゃんきゃんわおん! わんきゃんわーんわーんわんきゃうんわんきゃんきゃんきゃんきゃんきゅーんきゅーんわおんわんわおんわーんわーんわんわんわんばうわおんわんきゃんわーん! きゃんわおんきゃんばうきゃん...</summary>
    <author>
        <name>unoh</name>
        
    </author>
    
    <content type="html" xml:lang="ja" xml:base="http://labs.unoh.net/">
        <![CDATA[きゃんきゅーんわんわおんわーんばうきゃんきゃんきゃうんわおんわおんわんきゃんきゃんきゃうんきゃんきゃん!<br />
わうわーん。<br />
わんわーんわんわうわん。<br />
わんわおんわんわおんわん!<br />
きゃうんわーんわうきゅーんわおんわーんばうわおんわんわおんわん。<br />
わーんわーんきゃんわうわんわんわおん!<br />
わんきゃんきゃんわうわーんわんきゃんわおんわんわおんわん!<br />
わん。<br />
きゃうんきゃんきゅーん。<br />
わーんわんきゃんわうわーんばうわんわんわうきゅーんきゃんわんわーんわおんわん。<br />
きゃうんわおんわおんわおん!<br />
きゃんわおんわおんわんばうわおんわんばうきゃんわおんきゃうんわおん!<br />
わんわおんばうきゃん!<br />
わうきゃうんきゃんわおんきゃんきゃんわおん!<br />
わんきゃんわーんわーんわんきゃうんわんきゃんきゃんきゃんきゃんきゅーんきゅーんわおんわんわおんわーんわーんわんわんわんばうわおんわんきゃんわーん!<br />
きゃんわおんきゃんばうきゃんきゃんわーんわうわおんわーんばうわーんばうわうわんわーんわんわおんきゃんばうきゃんわーんきゃうんわん!<br />
きゃうんわおんきゃんわうきゃうんきゃんばうわーんきゃんわーんきゃんわーんわおんわうわーんきゅーんわーん。<br />
わーんわーんわうきゃんきゅーんばうわーんばうわーんわーんわうわーんわーんきゃんわーんわおんきゃうんわーんわーんきゃうんわーんわおんきゃんわーんきゃんわおんわーんわーんばうわおんわおんきゃんきゃうんきゃんきゅーんわんわおんばうわおんわおんわおんわーん。<br />
わおんわおんわーんわーんばう。<br />
わうわんきゅーんわーんきゃんきゃうんきゃうんわーんわうわーんわん。<br />
きゅーんきゃんわおんわう。<br />
きゃんわおんばうきゃんわんきゃうんばうわんきゃうんわんわんわうわーんきゃん。<br />
きゃうんわおんきゃんきゃん。<br />
わうわんきゃうん!<br />
きゃうんわおんきゃうんわんわんばうきゃうん。<br />
きゃんわう!<br />
きゃうんきゃん!<br />
きゃんわんわーんきゅーんきゃうんわん。<br />
きゃんきゃんわんわおんきゅーんわんわおんばうわーんわんばうわーんわーんわおんわおんわんわんきゃんわーんきゃうん。<br />
わおんきゅーんわおんわーんきゃうんばうわんわおんわうわおんきゃんわうわんきゃうんわんわーんきゅーんきゃうんわんきゃうんばうきゃんきゃうん!<br />
きゃんわおんわうわーんきゃんわうきゃんわーん。<br />
ばうわん。<br />
わおんばうきゃうんわおんきゅーんきゅーんわおんきゃうんわーんきゃんわーん。<br />
わう。<br />
わーんきゅーんばうきゃん。<br />
ばう。<br />
わんわん!<br />
わおんばうわんわうわおんわん!<br />
わんきゃんきゃん!<br />
わーんばうきゃん。<br />
わおんきゃん!<br />
わんきゃうんわおんわーんきゃうんわおんわんきゅーんわーん!<br />
わーんわうきゃうんわおんわーん!<br />
きゃんわーんわうわおんわーんわおんわんわおんきゃんわうきゃんきゃうんわーんわーんばうわおんわおんわんわうきゃんきゅーんわんわんばうきゃうん!<br />
きゃんきゅーんわうわおんきゃんきゃんわんきゃうんきゃうんわおんわおんきゃんわんわおんわーんわおんわおんわーんわん。<br />
わうわんわおんわおんわおんきゃんきゅーんわおんきゃんきゃん!<br />
わーんわーんきゅーんきゃんわおんきゃんばうわーんきゃうんきゃうんわんきゃうんわうわおん!<br />
わーんばうわーんわーんわんわおんわうばう。<br />
わおんばうわーんわーんきゅーんわーんわんきゃうん。<br />
わんわおんわおんきゃんきゃんわおんきゃんわおんわおんわおんわーんきゃんわんわおんわおんばうきゃんきゅーん!<br />
わうわんきゅーんきゃうんわーんきゃうんきゃんわおん!<br />
ばうわうわおんきゅーんきゃうんわーんきゃんわんきゃんきゃうん。<br />
ばうわーんきゅーんきゅーんきゃんきゃんきゃうんわおんきゃんきゅーんわおんわうわんわんばうばうわーんきゅーんわおんわんきゃんきゅーんわおんばうわおんきゃんわーんわおんわおん!<br />
わーんきゅーんわおんわーんわんわおんわんわうきゃんばうわおんわんばうわーんわんわーんきゃうんわおんきゅーんわおんわおんばうわおん。<br />
わおんわうわおんわんわおんきゅーんきゃんきゃうんきゅーんわーんきゃうんわうわんわう!<br />
わうわんきゅーんきゅーんわーん。<br />
きゅーんきゃうんわおんきゃんわんわおんわーんきゃん。<br />
わおんわーんばうわんわんわおん!<br />
わおんわうわーんきゃんきゃうんわん。<br />
きゃん!<br />
きゃうんわおんきゃんきゃんわーんわんきゃん!<br />
わうわおんきゃうんきゃうんわーんわーんきゃうんきゃんわおんわうわおんわーんわうわんわうきゅーんきゃん!<br />
わうきゃうんきゃんきゃうんわおんきゃんきゃうんきゃんわーんばう。<br />
わおんわーんわおんきゃんきゃんばうきゅーんわーん!<br />
わおんわおんわんきゅーん!<br />
きゃんわおん!<br />
わうきゃうんわおんわんきゃんわおんばうきゃんきゃんきゃんわーんわーんきゃうんわう!<br />
わおんきゃんわんわーんきゃんわおんきゃん。<br />
きゅーんきゅーんわーんきゃうんきゃうん。<br />
わおんわうきゃうんわんきゃんきゅーんわんわーんきゅーんきゃんわうばうわーんわうわうわんわんきゅーんわーんわーんわうきゃんきゃうんきゃうんわーんきゃんきゃんきゃんきゅーんきゃん<br />

<!---
<?php

class Encode_Dog
{
   protected $convert = array(
     0 => 'わん',
     1 => 'きゃん',
     2 => 'わおん',
     3 => 'わーん',
     4 => 'ばう',
     5 => 'きゃうん',
     6 => 'わう',
     7 => 'きゅーん',
   );

   public function encode($string)
   {
       $zvalue = gzcompress($string);
       $codes = unpack('C*', $zvalue);
       $result = '';
       foreach($codes as $value) {
           //base8
           $base8 = sprintf('%03s', base_convert($value, 10, 8));
           //おいこら
           for ($i = 0; strlen($base8) > $i; $i++) {
               $result .= $this->convert[$base8[$i]] . $this->addRandString();
           }
       }
       return $result;
   }

   public function addRandString()
   {
      $result = '';
      switch(mt_rand(0, 20)) {
          case 10:
              $result = "!\n";
              break;
          case 20:
              $result = "。\n";
              break;
      }
      return $result;
   }

   public function decode($value)
   {
       // 改行と「。」と「！」を削除する
       // TODO あとで実装する
   }

}
$content = <<<EOT
Keita です。
今日はエイプリルフールなので犬言に変換する簡単なプログラムを書いてみました。
デコーダーは明日くらいに実装します。
デコードできなかったら、誰か僕を抱きしめて下さい
以上、ご参考になれば幸いです。
/
EOT;

$encoder = new Encode_Dog();
$encode = $encoder->encode($content);
echo $encode;
//本当にデコードできなかったので修正しましたひれ伏してお詫びします
-->]]>
        
    </content>
</entry>

<entry>
    <title>PHPで利用出来るテストと開発に便利なツール</title>
    <link rel="alternate" type="text/html" href="http://labs.unoh.net/2011/03/php_12.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.unoh.net/mt32/mt-atom.cgi/weblog/blog_id=2/entry_id=1938" title="PHPで利用出来るテストと開発に便利なツール" />
    <id>tag:labs.unoh.net,2011://2.1938</id>
    
    <published>2011-03-24T05:41:12Z</published>
    <updated>2011-03-24T17:41:46Z</updated>
    
    <summary><![CDATA[ こんにちは。yukiです。 今日はテストや普段の開発に便利なツールのご紹介をしたいと思います。PHP限定のツールですので、ご了承下さい。 ZyngaJapanでは、昨日リニューアルオープンした「ファームビレッジ」でも、Jenkins(旧Hudson)によるCIを行って開発しており、TDDやJenkinsでのCIを利用する文化がだんだんと浸透してきています。Jenkinsのプラグインとして利用できるものも多くありますが、当然ながらコマンドラインからも利用出来ますので、コミット前に自分のコードをチェックすることもできます。 phpcpd コードの中でコピー&amp;ペーストで記述されている部分を検出してくれます。どの程度の重複から検出するかを柔軟に設定できるので、まず大きな部分から修正するなど判断ができ便利です。 $ phpcpd /path/to/project phpcpd @packa...]]></summary>
    <author>
        <name>unoh</name>
        
    </author>
    
    <content type="html" xml:lang="ja" xml:base="http://labs.unoh.net/">
        <![CDATA[
<p>こんにちは。yukiです。</p>
<p>今日はテストや普段の開発に便利なツールのご紹介をしたいと思います。PHP限定のツールですので、ご了承下さい。</p>
<p>ZyngaJapanでは、昨日リニューアルオープンした「<a href="http://www.zynga.co.jp/service/farmvillage.html">ファームビレッジ</a>」でも、<a href="http://wiki.hudson-ci.org/display/JA/Meet+Hudson">Jenkins</a>(旧Hudson)によるCIを行って開発しており、TDDやJenkinsでのCIを利用する文化がだんだんと浸透してきています。Jenkinsのプラグインとして利用できるものも多くありますが、当然ながらコマンドラインからも利用出来ますので、コミット前に自分のコードをチェックすることもできます。</p>
<h3><a href="https://github.com/sebastianbergmann/phpcpd">phpcpd</a></h3>
<p>コードの中でコピー&amp;ペーストで記述されている部分を検出してくれます。<br />どの程度の重複から検出するかを柔軟に設定できるので、まず大きな部分から修正するなど判断ができ便利です。</p>
<pre class="code">$ phpcpd /path/to/project
phpcpd @package_version@ by Sebastian Bergmann.

Found 13 exact clones with 339 duplicated lines in 17 files:

  - hoge/fuga/Foo.php:55-104
    hoge/fuga/Bar.php:85-134

0.50% duplicated lines out of 68425 total lines of code.

Time: 10 seconds, Memory: 33.00Mb</pre>
<h3><a href="https://github.com/sebastianbergmann/phpdcd">phpdcd</a></h3>
<p>どこからもコールされていないメソッドなどを検出してくれます。リファクタリング対象として確認に役立ちます。</p>
<pre class="code">$ phpdcd /path/to/project
phpdcd 0.9.2 by Sebastian Bergmann.

  - Foo::execute()
    declared in Foo.php:42

  - Bar::getActionName()
    declared in Bar.php:27

  - Hoge::execute()
    declared in Hoge.php:34</pre>
<h3><a href="https://github.com/sebastianbergmann/phploc">phploc</a></h3>
<p>以下のようにphpファイルの構成要素を算出してくれます。(数字は全てダミーです)</p>
<pre class="code">$ phploc /path/to/project
phploc @package_version@ by Sebastian Bergmann.

Directories:                                        999
Files:                                             9999

Lines of Code (LOC):                             999999
  Cyclomatic Complexity / Lines of Code:           0.01
Comment Lines of Code (CLOC):                     99999
Non-Comment Lines of Code (NCLOC):               999999

Namespaces:                                           9
Interfaces:                                          99
Classes:                                            999
  Abstract:                                          99 (9.99%)
  Concrete:                                         999 (99.99%)
  Average Class Length (NCLOC):                     999
Methods:                                           9999
  Scope:
    Non-Static:                                    9999 (99.99%)
    Static:                                           9 (9.99%)
  Visibility:
    Public:                                        9999 (99.99%)
    Non-Public:                                     999 (99.99%)
  Average Method Length (NCLOC):                     99
  Cyclomatic Complexity / Number of Methods:       9.99

Anonymous Functions:                                 99
Functions:                                            9

Constants:                                          999
  Global constants:                                   9
  Class constants:                                  999</pre>
<h3><a href="http://phpmd.org/">phpmd</a></h3>
<p>if文のネスト階層数などの複雑さ、短すぎる、または長すぎる変数名や、使われていない変数の検出など様々な条件に応じて検出を行ってくれます。</p>
<pre class="code">$ phpmd /path/to/project text codesize,unusedcode,naming

/path/to/project/hoge/huga/AAA.php:76   Avoid unused local variables such as '$foo'.
/path/to/project/hoge/huga/AAA.php:129  Avoid unused local variables such as '$bar'.
/path/to/project/hoge/huga/AAA.php:185  Avoid unused local variables such as '$foo'.
/path/to/project/hoge/huga/BBB.class.php:29    Too many fields
/path/to/project/hoge/huga/foo/CCC.php:20 Avoid variables with short names like $a
/path/to/project/hoge/huga/foo/CCC.php:20 Avoid variables with short names like $b
/path/to/project/hoge/huga/foo/EEE.php:5     The method create() has a Cyclomatic Complexity of 12.
/path/to/project/hoge/huga/foo/EEE.php:5     The method create() has an NPath complexity of 288.
/path/to/project/hoge/huga/foo/FFF.php:10     Avoid unused local variables such as '$type'.
/path/to/project/hoge/huga/foo/GGG.php:7    Avoid unused private fields such as '$object'.
/path/to/project/hoge/huga/bar/HHH.php:64  Avoid unused parameters such as '$status'.
/path/to/project/hoge/huga/bar/HHH.php:74  Avoid unused private methods such as 'setStatus'.
/path/to/project/hoge/huga/bar/JJJ.php:26    Avoid unused parameters such as '$status'.
/path/to/project/hoge/huga/bar/KKK.php:3    This class has too many methods, consider refactoring it.
/path/to/project/hoge/huga/bar/KKK.php:13   Avoid unused parameters such as '$status'.
/path/to/project/hoge/huga/bar/LLL.php:44    Avoid unused parameters such as '$status'.</pre>
<p>上記はJenkinsのプラグインとして使えるものもありますので、是非検討してみてはいかがでしょうか。</p>
]]>
        
    </content>
</entry>

<entry>
    <title>Puppet DashboardからExternal Nodesを利用する方法 </title>
    <link rel="alternate" type="text/html" href="http://labs.unoh.net/2011/03/puppet_dashboardexternal_nodes.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.unoh.net/mt32/mt-atom.cgi/weblog/blog_id=2/entry_id=1937" title="Puppet DashboardからExternal Nodesを利用する方法 " />
    <id>tag:labs.unoh.net,2011://2.1937</id>
    
    <published>2011-03-23T12:01:49Z</published>
    <updated>2011-03-24T05:47:51Z</updated>
    
    <summary>入社3ヶ月目のsaekiです。 今回はPuppetのGUIツール「Puppet Dashboard」でExternal Nodes機能を使用する方法を紹介しようかと思います。 Puppet Dashboardのインストール方法は公式ドキュメントを参考にしてください。 Puppetは0.25.5、Puppet Dashboardは1.0.4を使用しています。   ■できること   - マニフェストではなくdashboard上でnode設定ができます。 - node(またはgroup)毎にclassを設定やParameterの設定ができます。   ■使用方法   - classを登録する dashboardにclassを登録します。 1. マニフェストのclassを作成します(例はhosts)  class hosts {    file {      &quot;/etc/hosts&quot;:       ...</summary>
    <author>
        <name>unoh</name>
        
    </author>
    
    <content type="html" xml:lang="ja" xml:base="http://labs.unoh.net/">
        <![CDATA[入社3ヶ月目のsaekiです。<br>
今回はPuppetのGUIツール「Puppet Dashboard」でExternal Nodes機能を使用する方法を紹介しようかと思います。<br>
Puppet Dashboardのインストール方法は<a href="http://docs.puppetlabs.com/guides/installing_dashboard.html">公式ドキュメント</a>を参考にしてください。<br>
Puppetは0.25.5、Puppet Dashboardは1.0.4を使用しています。<br>

<h3 style="border-bottom:1px solid #6699CC;border-bottom-width:1px;border-bottom-style:solid;border-left:10px solid #6699CC;margin-top:25px;padding-left:10px;"> 
■できること
</h3> 
- マニフェストではなくdashboard上でnode設定ができます。<br>
- node(またはgroup)毎にclassを設定やParameterの設定ができます。<br>

<h3 style="border-bottom:1px solid #6699CC;border-bottom-width:1px;border-bottom-style:solid;border-left:10px solid #6699CC;margin-top:25px;padding-left:10px;"> 
■使用方法
</h3> 
- <strong>classを登録する</strong><br>
dashboardにclassを登録します。
<br>
<br>
1. マニフェストのclassを作成します(例はhosts)

<pre class="code">
 class hosts {
   file {
     "/etc/hosts":
       owner => 'root',
       group => 'root',
       mode  => 644,
   }
 }
</pre> 
<br>
2.dashboard上から[Add class]を選択して、作成したclassを登録します。<br>
<span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="class_detail.png" src="http://labs.unoh.net/class_detail.png" width="701" height="648" class="mt-image-none" style="" /></span>
<br>
<br>

3.nodeにclassを登録するには、node編集画面から[Classes]に作成したclassを登録します。<br>
classにパラメータを渡したい場合は、[Parameters]にkeyとvalueを登録すると変数として扱えます(画像の青い囲い)<br>
<span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="node_edit.png" src="http://labs.unoh.net/node_edit.png" width="890" height="657" class="mt-image-none" style="" /></span>
<br>
<br>
クライアントからpuppetdを実行してみてください。<br>
特にsite.ppなどにnodeの設定をしてなくても、hosts classのマニフェストが反映されるかと思います。<br>
<br>
<br>
- <strong>group登録をする</strong><br>
chassやnodeをgroup登録できます。サーバ機能毎やプロダクト毎にまとめたい場合に利用できるかと思います。<br><br>
1.左メニューから[Add group]を選択するとgroup編集画面になります。<br>
2.groupに登録したいclassやgroup(親group)を設定できます。group毎に使用するParameterの設定も可能です。 <br>
<span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="group_edit.png" src="http://labs.unoh.net/group_edit.png" width="899" height="633" class="mt-image-none" style="" /></span>
<br>
<br>

3.groupにnodeを登録するには、node編集画面から[Groups]に作成したgroupを登録します。 <br>
<span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="node_edit_group.png" src="http://labs.unoh.net/node_edit_group.png" width="891" height="649" class="mt-image-none" style="" /></span>

<h3 style="border-bottom:1px solid #6699CC;border-bottom-width:1px;border-bottom-style:solid;border-left:10px solid #6699CC;margin-top:25px;padding-left:10px;"> 
■利用例
</h3> 
- こんなイメージで設定ができるかと思います(webサーバgroupとして設定)
<pre class="code">
base(group)
   ├─ web(group)  
   │      ├──  httpd(class)
   │      └──  php(class)
   │
   ├── hosts(class)
   ├── ntp(class)
   └── ssh(class)
</pre> 

External NodesをGUIで扱うtoolには<a href="http://theforeman.org/projects/foreman/wiki">foreman</a>というのもあるようです。<br>
便利な機能かと思いますので、Puppet利用されている方は導入されてみてはいかがでしょうか。
]]>
        
    </content>
</entry>

<entry>
    <title>symfonyエキスパートになるために必須の1冊</title>
    <link rel="alternate" type="text/html" href="http://labs.unoh.net/2011/03/symfony14-book.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.unoh.net/mt32/mt-atom.cgi/weblog/blog_id=2/entry_id=1936" title="symfonyエキスパートになるために必須の1冊" />
    <id>tag:labs.unoh.net,2011://2.1936</id>
    
    <published>2011-03-23T10:30:00Z</published>
    <updated>2011-03-23T10:51:48Z</updated>
    
    <summary>突然ですが、symfonyのエキスパートになりませんか？HIROKIです。 PHPのフルスタックフレームワークであるsymfonyについて共著した書籍が発売されました。私はテスト駆動開発(TDD)とsymfonyによる自動テストについて執筆しました。 具体的にはLimeを利用したユニットテストをはじめ、sfBrowserを利用して、ブラウザアクセスをエミュレーションした自動テストを書くことによって、実際に人間がブラウザを通してアクセスしている内容まで自動テストにします。これを、テストファーストのアプローチで開発する内容になっています。 TDDや自動テストを書くというのは、プログラマーとして、プロとしてのスキルです。これを機会に、ばっちりテストコード書けるぜ！という人が増えることを願っております。 本書は symfonyプロジェクトに存在するドキュメントやリファレンスを読む前に必要な前提知識...</summary>
    <author>
        <name>unoh</name>
        
    </author>
    
        <category term="Tips" />
    
        <category term="symfony" />
    
    <content type="html" xml:lang="ja" xml:base="http://labs.unoh.net/">
        <![CDATA[突然ですが、symfonyのエキスパートになりませんか？[HIROKI](http://hiroki.jp)です。

PHPのフルスタックフレームワークであるsymfonyについて共著した書籍が発売されました。私はテスト駆動開発(TDD)とsymfonyによる自動テストについて執筆しました。

具体的にはLimeを利用したユニットテストをはじめ、sfBrowserを利用して、ブラウザアクセスをエミュレーションした自動テストを書くことによって、実際に人間がブラウザを通してアクセスしている内容まで自動テストにします。これを、テストファーストのアプローチで開発する内容になっています。

TDDや自動テストを書くというのは、プログラマーとして、プロとしてのスキルです。これを機会に、ばっちりテストコード書けるぜ！という人が増えることを願っております。

<span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="sf14book-image.jpeg" src="http://labs.unoh.net/sf14book-image.jpeg" width="230" height="299" class="mt-image-none" style="" /></span>

本書は

* symfonyプロジェクトに存在するドキュメントやリファレンスを読む前に必要な前提知識
* 詳しいインストール方法
* 少しハードルの低いチュートリアルといった入門者向け

といった入門者向けの内容と

* 公式ドキュメントに目を通した人が次のレベルにステップアップする為の知識
* 実開発、実運用で役立つTips

といった上級者向けの内容が盛り込まれています。

ソースコードもダウンロードできるので、実際に手を動かしながらsymfonyを体感してください。


]]>
        <![CDATA[###目次
<div class="code">
<pre>
Chapter 1 symfony 1.4の特徴と基礎知識  
1-1 symfony 1.4の特徴  
■1-1-2 symfonyのバージョン
■1-1-3 Webアプリケーション開発のベストプラクティスを実践するためのフレームワーク
■1-1-4 symfonyのコミュニティとOSS
1-2 symfonyの基礎知識
■1-2-1 symfonyを使ったプロジェクトのディレクトリとファイル
■1-2-2 プロジェクト、アプリケーション、モジュール、アクション
■1-2-3 タスクとsymfonyコマンド
■1-2-4 設定ファイルとYAML
■1-2-5 ORM（DoctrineとPropel）
■1-2-6 ルーティング
■1-2-7 フォームフレームワーク
■1-2-8 CRUD、スキャフォールディング、Adminジェネレータ
■1-2-9 プラグイン
■1-2-10 国際化（I18N）
■1-2-11 limeテストフレームワーク
1-3 コーディング規約
■1-3-1 symfonyのコーディング規約について
■1-3-2 本書のコーディング規約
■1-3-3 本書の文体
Chapter 2 symfony 1.4のインストール
2-1 symfonyを使ったアプリケーションの開発に必要な環境
■2-1-1 サーバーソフトウェア
■2-1-2 PHP
2-2 symfonyのインストール方法4種類
■2-2-1 4種類のインストール方法の概要
■2-2-2 サンドボックスパッケージを使ったインストール
■2-2-3 リリースパッケージを使ったインストール
■2-2-4 バージョン管理システム（Subversion）を使ったインストール
■2-2-5 PEARを使ったインストール
2-3 Linux環境でのインストール
■2-3-1 サーバーソフトウェアの準備
■2-3-2 動作環境の確認
■2-3-3 インストール位置の決定
■2-3-4 サンドボックスパッケージからのインストール
■2-3-5 リリースパッケージからのインストール
■2-3-6 Subversionリポジトリからのインストール
■2-3-7 symfonyコマンドでバージョンを確認
■2-3-8 .htaccessの編集
■2-3-9 sfディレクトリのコピー
■2-3-10 Webブラウザから確認
2-4 Windows環境でのインストール
■2-4-1 サーバーソフトウェアの準備
■2-4-2 動作環境の確認
■2-4-3 インストール位置の決定
■2-4-4 サンドボックスパッケージからのインストール
■2-4-5 リリースパッケージからのインストール
■2-4-6 Subversionリポジトリからのインストール
■2-4-7 symfonyコマンドでバージョンを確認
■2-4-8 .htaccessの編集
■2-4-9 sfディレクトリのコピー
■2-4-10 Webブラウザから確認
2-5 Mac環境でのインストール
■2-5-1 サーバーソフトウェアの準備
■2-5-2 動作環境の確認
■2-5-3 インストール位置の決定
■2-5-4 サンドボックスパッケージからのインストール
■2-5-5 リリースパッケージからのインストール
■2-5-6 Subversionリポジトリからのインストール
■2-5-7 symfonyコマンドでバージョンを確認
■2-5-8 .htaccessの編集
■2-5-9 sfディレクトリのコピー
■2-5-10 Webブラウザから確認
2-6 インストールした後は?
■2-6-1 Gitを使ったsymfonyのインストール
■2-6-2 NetBeans IDEでsymfonyアプリケーションを開発する
Chapter 3 symfonyアプリケーションの設置
3-1 symfonyのディレクトリ群を解剖する
■3-1-1 プロジェクトの基本構成
■3-1-2 ディレクトリ構成の変更
3-2 公開サーバーへの設置
■3-2-1 Webサーバーのドキュメントルートを割り当てる
■3-2-2 webディレクトリのみを分離して公開ディレクトリに配置する
■3-2-3 サブディレクトリでsymfonyを使う
■3-2-4 公開ディレクトリ以下にしか配置できないサーバーの場合
3-3 本番環境でのチェックポイント
■3-3-1 開発用のフロントコントローラを削除する
■3-3-2 エラーページを変更する
■3-3-3 セッション名を変更する
■3-3-4 不要なリクエストをなくす
Chapter 4 サンプルサイトで学ぶsymfony開発の基礎
4-1 開発の準備
■4-1-1 サンプルサイト「symfony楽団ホームページ」
■4-1-2 symfonyのインストール
■4-1-3 Helloモジュールの生成
■4-1-4 Hello, World!の表示
4-2 サンプルサイトの概要とデータベースの準備
■4-2-1 サンプルサイトの設計
■4-2-2 データベースのスキーマ
■4-2-3 モデルクラス群とテーブルの生成
■4-2-4 フィクスチャーの準備
4-3 モジュールとアクションの生成
■4-3-1 モジュールの設計と作成
■4-3-2 Pageモジュールのアクションの実装
4-4 ルーティングの設定
■4-4-1 routing.ymlの基礎
■4-4-2 ルーティングを使ってページ表示機能を実装する
■4-4-3 残りのルートを設定する
4-5 テンプレート
■4-5-1 デザインデータの準備
■4-5-2 CSSの適用とビューの設定
■4-5-3 テンプレートの部品化
4-6 お問い合わせフォームの作成とメールの送信
■4-6-1 sfFormフォームフレームワークの概要
■4-6-2 InquiryFormクラスの実装（基本）
■4-6-3 InquiryFormクラスの実装（完成）
■4-6-4 メール送信機能の実装
4-7 管理機能の実装
■4-7-1 backendアプリケーションの準備
■4-7-2 Pageモデル向け管理画面の生成（Adminジェネレータ）
■4-7-3 管理画面へのアクセス制限
4-8 リファクタリングと機能拡張
■4-8-1 モデル関連のコードはモデルクラスへ
■4-8-2 一覧を取得する処理はページャーを経由させる
■4-8-3 拡張のヒント
Chapter 5 公式サイトのドキュメントナビゲーション
5-1 公式サイトのドキュメントの種類
■5-1-1 symfony 1.4に対応した公式ドキュメント
■5-1-2 小規模なドキュメント
■5-1-3 過去の公式ドキュメント
5-2 ドキュメントナビゲーション
■5-2-1 Doctrine関連
■5-2-2 Propel関連
■5-2-3 フォーム関連
■5-2-4 キャッシュ関連
■5-2-5 ビュー関連
■5-2-6 タスク関連
■5-2-7 Adminジェネレータ関連
■5-2-8 ルーティング関連
■5-2-9 テスト関連
■5-2-10 メール関連
Chapter 6 Doctrine
6-1 モデルの基本
■6-1-1 モデルクラスの定義
6-2 CRUD処理の基本
■6-2-1 データの作成
■6-2-2 データの更新
■6-2-3 データの削除
■6-2-4 データの読み取り（ファインダメソッド）
■6-2-5 Doctrine_Queryを使ったデータの読み取り
■6-2-6 カスタムファインダメソッド
■6-2-7 複数データの更新
■6-2-8 複数データの削除
■6-2-9 ハイドレーション
■6-2-10 Doctrine_Connectionからの操作
6-3 ビヘイビアの利用
6-4 フックの利用
■6-4-1 レコードフック
■6-4-2 DQLフック
6-5 リレーション
■6-5-1 一対一のリレーション
■6-5-2 一対多のリレーション
■6-5-3 多対多のリレーション
6-6 キャッシュの利用
■6-6-1 2種類のキャッシュ
■6-6-2 キャッシュドライバ
■6-6-3 結果キャッシュを使う
Chapter 7 symfonyを使いこなす
7-1 フォームフォーマッタ
7-2 sfFormのウィジェットの基礎
■7-2-1 ウィジェットクラスについて
■7-2-2 ウィジェットのオプション（option）と属性（attribute）
■7-2-3 フィールドの要素をテンプレートで個別に表示する
■7-2-4 フォームクラスのメソッド
7-3 特定のフォームでだけチェックボックスのタグをカスタマイズする
7-4 出力するタグをカスタマイズしたウィジェットクラスを作る
7-5 バリデータの基礎
■7-5-1 バリデータクラスについて
7-6 より厳密なメールアドレスのチェック
■7-6-1 sfValidatorEmailのオプションで指定
■7-6-2 カスタムバリデータクラスを作成
■7-6-3 携帯キャリアのメールアドレスかどうかチェックする
■7-6-4 全角文字のチェックと半角への自動変換
7-7 複数フィールドのバリデーション
■7-7-1 POSTバリデータで複数の入力値を検証する
■7-7-2 sfValidatorCallbackでさらに複雑なバリデーション
7-8 オブジェクトルート
■7-8-1 オブジェクトルートの使い方
7-9 タスクの基礎
■7-9-1 タスクの雛形を生成する
7-10 RSSフィードを取得して処理する
7-11 イベントの基礎
■7-11-1 イベントの使い方
■7-11-2 symfonyの組み込みイベント
7-12 キャッシュクリアコマンドを拡張する
■7-12-1 独自のキャッシュをキャッシュクリアコマンドで削除する
Chapter 8 プラグインの利用と開発
8-1 プラグインとは
8-2 プラグインを利用する
■8-2-1 sfDoctrineGuardPlugin
■8-2-2 sfFormExtraPlugin
■8-2-3 sfFeed2Plugin
■8-2-4 sfJqueryReloadedPlugin
■8-2-5 sfImageTransformPlugin
■8-2-6 sfSmartyPlugin
■8-2-7 sfTaskExtraPlugin
■8-2-8 sfDoctrineMasterSlavePlugin
■8-2-9 sfWebBrowserPlugin
■8-2-10 sfThumbnailPlugin
■8-2-11 jpSimpleMailPlugin
8-3 プラグインのディレクトリとファイルの構成
■8-3-1 プラグインの各ディレクトリの概要
Chapter 9 symfonyのユーティリティクラス
9-1 オートロード
■9-1-1 オートロードとは？
■9-1-2 symfonyのオートロードの設定
9-2 sfYaml
■9-2-1 YAMLライブラリ
■9-2-2 YAMLファイルを読み込む
■9-2-3 YAML形式で書き出す
9-3 sfConfig
■9-3-1 sfConfigクラスの使い方
■9-3-2 sfConfigで取得できる設定値
9-4 sfFinder
■9-4-1 sfFinderを使ったファイル処理
9-5 sfToolkit
■9-5-1 sfToolkitクラスのメソッド
■9-5-2 sfToolkit::arrayDeepMerge()
■9-5-3 sfToolkit::clearDirectory()
■9-5-4 sfToolkit::clearGlob()
■9-5-5 sfToolkit::isArrayValuesEmpty()
■9-5-6 sfToolkit::isPathAbsolute()
■9-5-7 sfToolkit::replaceConstants()
9-6 sfContext
■9-6-1 sfContextクラスのメソッド
9-7 sfPager、sfDoctrinePager
■9-7-1 ページャークラスの基本
9-8 sfProjectConfiguration、sfApplicationConfiguration
■9-8-1 sfProjectConfiguration
■9-8-2 sfApplicationConfiguration
9-9 sfUser、sfBasicSecurityUser
■9-9-1 sfUserクラスを使ったセッション情報の操作
■9-9-2 sfBasicSecurityUserクラスを使った認証
■9-9-3 セッションストレージの変更
9-10 sfLogger、その他のロガーと設定
■9-10-1 アプリケーションからのログの記録
■9-10-2 ロギング用の設定
9-11 sfInflector
■9-11-1 sfInflectorクラスのメソッド
9-12 ヘルパー関数
■9-12-1 AssetHelper
■9-12-2 CacheHelper
■9-12-3 DateHelper
■9-12-4 DebugHelper
■9-12-5 EscapingHelper
■9-12-6 HelperHelper
■9-12-7 I18NHelper
■9-12-8 JavascriptBaseHelper
■9-12-9 NumberHelper
■9-12-10 PartialHelper
■9-12-11 TagHelper
■9-12-12 TextHelper
■9-12-13 UrlHelper
Chapter 10 マスタースレーブ構成のデータベース
10-1 レプリケーション環境のデータベースの準備
■10-1-1 データベースにレプリケーション用のユーザーを作成
■10-1-2 マスターデータベースの情報を準備
■10-1-3 ベースバックアップの取得
■10-1-4 スレーブデータベースの設定
10-2 sfDoctrineMasterSlavePluginのインストール方法
■10-2-1 テスト用のプロジェクトの作成
■10-2-2 sfDoctrineMasterSlavePluginのインストール
■10-2-3 databases.ymlにマスタースレーブの設定を追加
10-3 動作の確認
■10-3-1 テスト用のデータベースの準備
■10-3-2 テスト用のページの作成
■10-3-3 sfDoctrineMasterSlavePluginの動作の確認
Chapter 11 ソースコード管理、テスト駆動開発、デプロイ
11-1 ソースコードのバージョン管理
■11-1-1 Subversionを使ったバージョン管理
■11-1-2 Gitを使ったバージョン管理
11-2 テスト駆動開発（TDD）とsymfonyのテスト機能
■11-2-1 テスト駆動開発の基礎知識
■11-2-2 TDDのアプローチで機能を実装する
■11-2-3 ファンクショナルテスト
■11-2-4 まとめ
11-3 開発したアプリケーションのデプロイ
■11-3-1 デプロイ方法概要
■11-3-2 symfonyコマンドによるデプロイ
■11-3-3 バージョン管理システムを使ったデプロイ
■11-3-4 その他のデプロイツール
Chapter 12 大規模なソフトウェアへの応用
12-1 OpenPNE3について
■12-1-1 OpenPNE3の準備
12-2 プラグインによる拡張
■12-2-1 通常のsymfonyプラグインとOpenPNEプラグインとの差異
■12-2-2 イベント
■12-2-3 OpenPNE3独自の設定
12-3 タスク
12-4 Doctrineの利用、拡張
■12-4-1 Doctrineのイベントをsymfonyのイベントとして通知する
■12-4-2 Zend_Aclとの連携
■12-4-3 パフォーマンスチューニング
12-5 メール投稿
12-6 その他のノウハウ
■12-6-1 他アプリケーションへのリンク
■12-6-2 フィルタの使用
■12-6-3 アクションの共通化
■12-6-4 リクエスト中のヌル文字の除去
■12-6-5 動的な画像生成
■1-1-1 symfonyの歴史  
</pre>
</div>

### お買い求めはこちら
* [オンライン書店ビーケーワン](http://www.bk1.jp/product/03392317)
* [e-hon](http://www.e-hon.ne.jp/bec/SA/Detail?refShinCode=0100000000000032564150&Action_id=121&Sza_id=GG)
* [セブン＆アイのセブンネットショッピング - 書籍 -](http://www.7netshopping.jp/books/detail/-/accd/1106019683)
* [amazon.co.jp](http://www.amazon.co.jp/exec/obidos/ASIN/4798029343?ie=UTF8&tag=shuwa01-22&linkCode=as2)  
※3/23日現在amazonでの取り扱いがありません。

### サポートサイト
正誤表などサポートサイトはこちらになります。  
[http://books.symfony.gr.jp/14book/](http://books.symfony.gr.jp/14book/)]]>
    </content>
</entry>

<entry>
    <title>Varnish上でESIの機能を利用する</title>
    <link rel="alternate" type="text/html" href="http://labs.unoh.net/2011/02/varnishesi.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.unoh.net/mt32/mt-atom.cgi/weblog/blog_id=2/entry_id=1934" title="Varnish上でESIの機能を利用する" />
    <id>tag:labs.unoh.net,2011://2.1934</id>
    
    <published>2011-02-22T02:17:33Z</published>
    <updated>2011-02-22T04:13:39Z</updated>
    
    <summary>Keita です。 サンフランシスコで開かれたSymfony Liveで、Fabien Potencier氏によるHTTP Cacheという発表がありその中でESI(Edge Side Includes)の紹介がありました。 下の画像はちょっとみずらいですが、たとえばこのラボブログのレイアウトだと大枠の部分は常によりユーザに使いフロントの所（つまりCDNやキャッシュサーバ）側でキャッシュされていてAの部分とBの部分それぞれのコンテンツを別々にインクルードする形でキャッシュ制御することができます。 Symfony2のサイトsymfony-reloaded.orgでも、マニュアルがありますので、詳細はそちらを参考にしていただくとして、その中に、Varnishでもその機能が利用できることが紹介されていますので試してみたいと思います。 Varnishのインストールについては省略してとりあえず設定部...</summary>
    <author>
        <name>unoh</name>
        
    </author>
    
    <content type="html" xml:lang="ja" xml:base="http://labs.unoh.net/">
        <![CDATA[<p>Keita です。</p>

<p>
サンフランシスコで開かれたSymfony Liveで、Fabien Potencier氏によるHTTP Cacheという発表がありその中でESI(Edge Side Includes)の紹介がありました。
</p>
<p>
下の画像はちょっとみずらいですが、たとえばこのラボブログのレイアウトだと大枠の部分は常によりユーザに使いフロントの所（つまりCDNやキャッシュサーバ）側でキャッシュされていてAの部分とBの部分それぞれのコンテンツを別々にインクルードする形でキャッシュ制御することができます。
</p>

<img alt="esi.png" src="http://labs.unoh.net/esi.png" width="500" height="330" class="mt-image-none" style="" />

<p>
Symfony2のサイトsymfony-reloaded.orgでも、<a href="http://docs.symfony-reloaded.org/guides/cache/http.html">マニュアル</a>がありますので、詳細はそちらを参考にしていただくとして、その中に、Varnishでもその機能が利用できることが紹介されていますので試してみたいと思います。
</p>

<p>
Varnishのインストールについては省略してとりあえず設定部分から。<a href="http://www.varnish-cache.org/trac/wiki/ESIfeatures">VarnishサイトにあるESIの説明</a>あたりを参考にして下記のような環境を構築してみました。
</p>

<h3>Apache側(port: 10080でアクセス可能）</h3>

himote.html
<pre class="code">
&lt;html&gt;
&lt;head&gt;
himote:
&lt;/head&gt;
&lt;body&gt;
&lt;esi:include src="/time.php" /&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre>

time.php
<pre class="code">
&lt;?php
echo date('Y/m/d h:i:s');
</pre>


<h3>varnish側(port: 6081でアクセス可能)</h3>

default.vcl
<pre class="code">
backend default {
  .host = "127.0.0.1";
  .port = "10080"; // Apache
}

sub vcl_fetch {
    if (req.url == "/himote.html") {
            esi; // enable ESI
    }
}
</pre>

wget で確認
<pre class="code">
wget http://localhost:6081/himote.html -O -

&lt;html&gt;
&lt;head&gt;
himote:
&lt;/head&gt;
&lt;body&gt;
2011/02/22 11:07:37
&lt;/body&gt;
&lt;/html&gt;

# 二回目
wget http://localhost:6081/himote.html -O -

&lt;html&gt;
&lt;head&gt;
himote:
&lt;/head&gt;
&lt;body&gt;
2011/02/22 11:07:37
&lt;/body&gt;
&lt;/html&gt;
</pre>

<p>
2回目も時間がかわってないことから、正常にキャッシュしているようです。<br />
ただ、キャッシュの有効期限を設定していないので今度はExpireヘッダを出力してみます。
</p>

<pre class="code">
&lt;?php
$expire = 10; //10秒後
header('Expires: '.gmdate('D, d M Y H:i:s \G\M\T', time() + $expire));
echo date('Y/m/d h:i:s');
</pre>

動作確認
<pre class="code">
wget http://localhost:6081/himote.html -O -

&lt;html&gt;
&lt;head&gt;
himote:
&lt;/head&gt;
&lt;body&gt;
2011/02/22 11:13:47
&lt;/body&gt;
&lt;/html&gt;

wget http://localhost:6081/himote.html -O -
&lt;html&gt;
&lt;head&gt;
himote:
&lt;/head&gt;
&lt;body&gt;
2011/02/22 11:13:57
&lt;/body&gt;
&lt;/html&gt;
</pre>

<p>
何回かアクセスするとちょうど10秒目くらいに時間が変更されているので正常に動作しているようです。
</p>

<p>
本家のマニュアルを写経した程度になってしまいましたが、どのようなものかイメージをつかんでいただけたのではないでしょうか。実際にプロダクトレベルで利用するにはベンチマークやログなどの詳細な検証は必要になると思いますのでご注意ください。
</p>
<p>
本記事がご参考になれば幸いです。]]>
        
    </content>
</entry>

<entry>
    <title>サーバ情報を収集する Ruby スクリプトを書くには</title>
    <link rel="alternate" type="text/html" href="http://labs.unoh.net/2011/02/_ruby.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.unoh.net/mt32/mt-atom.cgi/weblog/blog_id=2/entry_id=1933" title="サーバ情報を収集する Ruby スクリプトを書くには" />
    <id>tag:labs.unoh.net,2011://2.1933</id>
    
    <published>2011-02-21T01:57:51Z</published>
    <updated>2011-02-21T11:03:22Z</updated>
    
    <summary>こんにちは。kyagi です。今回はサーバ情報を収集する Ruby スクリプトを書く方法をお知らせいたします。具体的にはサーバ情報収集ツール facter (※1)の紹介と使い方になります。 facter はサーバのホスト名、IP アドレス、OS、ハードウェアなど様々な情報を収集するためのツールです。RPM では「facter」というパッケージ名で提供されており 「yum install facter」 でインストールが可能です。インストール後はターミナルから 「facter」 というコマンド(※2) を実施するだけでサーバの色々な情報を一度に取得することができます。 $ facter  (... snip ...) architecture =&gt; x86_64 domain =&gt; local.hoge.bar.net (... snip ...) ipaddress_eth0 =&gt; 10...</summary>
    <author>
        <name>unoh</name>
        
    </author>
    
    <content type="html" xml:lang="ja" xml:base="http://labs.unoh.net/">
        <![CDATA[こんにちは。kyagi です。今回はサーバ情報を収集する Ruby スクリプトを書く方法をお知らせいたします。具体的にはサーバ情報収集ツール facter (※1)の紹介と使い方になります。

facter はサーバのホスト名、IP アドレス、OS、ハードウェアなど様々な情報を収集するためのツールです。RPM では「facter」というパッケージ名で提供されており 「yum install facter」 でインストールが可能です。インストール後はターミナルから 「facter」 というコマンド(※2) を実施するだけでサーバの色々な情報を一度に取得することができます。

<pre class="code">
$ facter 
(... snip ...)
architecture => x86_64
domain => local.hoge.bar.net
(... snip ...)
ipaddress_eth0 => 10.x.y.z
processor0 => Intel(R) Xeon(R) CPU           E5504  @ 2.00GHz
memorysize => 8.04 GB
(... snip ...)
</pre>

facter を rpm でインストールすると ruby 用のインターフェイスとして Facter というモジュールが /usr/lib/ruby/site_ruby/<version> 配下にインストールされます。Ruby スクリプトの中で使用するにはこの Facter モジュールを require した後に、任意のクラスに include すれば OK です。コマンドラインから取得できる情報は Facter.value(:要素名) で取得可能です。以下に基本的なサーバを示すクラスとして「BaseServer」を定義した後、そのサブクラスであるWeb サーバ専用クラス「HttpdServer」, Mysql サーバクラス「MysqldServer」を定義したコードを紹介します。

■facter を rpm でインストールすると Ruby 用に Facter module がインストールされる

<pre class="code">
$ rpm -ql facter | grep rb$ 
/usr/lib/ruby/site_ruby/1.8/facter.rb
(... snip ...)
$ grep -r Facter /usr/lib/ruby/site_ruby/1.8 | grep module
/usr/lib/ruby/site_ruby/1.8/facter.rb:module Facter
</pre>

■基本的なサーバを表すクラスとして「BaseServer」クラスを作成する

<pre class="code">
require 'facter' 
class BaseServer
  include Facter
  attr_accessor :name, :role, :ipaddress
  def initialize(*)
    @name = Facter.value(:fqdn)
    @role = self.class.name
    @ipaddress = Facter.value(:ipaddress)
  end
  def getKernel
    return Facter.value(:kernelrelease)
  end
  def getUptime
    return Facter.value(:uptime)
  end
end
</pre>

■ Web サーバクラスを「BaseServer」のサブクラスとして作成する

<pre class="code">
require 'BaseServer'
class BaseServer::HttpdServer < BaseServer
  def getApacheStatus
    (... snip ...)
  end
end
</pre>

■ Mysqld サーバクラスを「BaseServer」のサブクラスとして作成する(※別途 ruby-mysql を使用し、専用のインスタンス変数を準備する)

<pre class="code">
require 'BaseServer'
require 'mysql'
class BaseServer::MysqldServer < BaseServer
  attr_accessor :host, :user, :pass, :database
  def initialize(host, user, pass, database)
    super
    @host = host
    @user = user
    @pass = pass
    @database = database
  end
  def countTable(table)
    my = Mysql::new(host, user, pass, database)
    res = my.query("select count(*) from #{table}")
    return res
  end
end
</pre>

以上、サーバ情報収集ツールを Ruby で書いている方の参考になれば幸いです。

(※1) サーバ管理ツール Puppet も内部的に facter を使用しています。

(※2) 「要素」という意味を表す英単語としては「facter」という単語はミススペルのようです。正しくは「factor」ですが既に coreutils パッケージに因数分解をする同名のコマンドが含まれているため、故意に facter という名前にしたのではと思われます。数学に興味がある方は古い方の「factor」を使用して「seq 1 100 | factor」(=1 から 100 までを素因数分解する)、「seq 1 100 | factor | awk 'NF == 2 { print $NF }'」(=1 から 100 までの素数を抽出する) などの使い方を試してみると面白いかもしれません。]]>
        
    </content>
</entry>

<entry>
    <title>家庭用ゲームのプログラマーがSNSゲームのプログラマーに転職するために必要なもの</title>
    <link rel="alternate" type="text/html" href="http://labs.unoh.net/2011/02/post_152.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.unoh.net/mt32/mt-atom.cgi/weblog/blog_id=2/entry_id=1932" title="家庭用ゲームのプログラマーがSNSゲームのプログラマーに転職するために必要なもの" />
    <id>tag:labs.unoh.net,2011://2.1932</id>
    
    <published>2011-02-02T03:45:39Z</published>
    <updated>2011-02-03T01:37:49Z</updated>
    
    <summary>こんぬつは＆はじめまして。 １２月に入社したサカモトです。 私は元々SONYとかNintendo機向けの家庭用のゲーム開発を生業にしてきましたが、ついこの前からSNSアプリの開発をしています。 私と同じように、家庭用ゲーム機のプログラマーからSNSゲームのプログラマーに転身したいと考えている方のお役に立てればと思い、私の経験を元に　&apos;転職するために必要なもの&apos; のお話をさせていただきたいと思います。...</summary>
    <author>
        <name>unoh</name>
        
    </author>
    
        <category term="ネタ" />
    
    <content type="html" xml:lang="ja" xml:base="http://labs.unoh.net/">
        こんぬつは＆はじめまして。
１２月に入社したサカモトです。

私は元々SONYとかNintendo機向けの家庭用のゲーム開発を生業にしてきましたが、ついこの前からSNSアプリの開発をしています。

私と同じように、家庭用ゲーム機のプログラマーからSNSゲームのプログラマーに転身したいと考えている方のお役に立てればと思い、私の経験を元に　&apos;転職するために必要なもの&apos; のお話をさせていただきたいと思います。
        <![CDATA[
<h3 style="border-bottom:1px solid #6699CC;border-bottom-width:1px;border-bottom-style:solid;border-left:10px solid #6699CC;margin-top:25px;padding-left:10px;">
採用されるために必要なもの
</h3>
ご自身で事業を始める場合には必要の無い事ですが、どこぞの会社さんに所属したいとなるとまず雇って頂くほかありません。そこで、採用されるために必要とされるスキルや経験を挙げてみたいと思います。

身近なところで弊社ZyngaJapanのエンジニアの<a target='_blank' href="http://www.zynga.co.jp/recruit/recruit.php?siteid=unohlabs">採用ページ</a>を見てみると「必須スキル・経験」として以下のような事が書いてあります。

<blockquote><em>
 	3年以上のプログラミング業務経験<br>
	または、個人でwebサービス/ソーシャルアプリを作成したことがある<br>
	または、オープンソース活動で実績があること<br>	
	プロジェクトの管理経験（業務経験ありの場合）<br>	
	チームのリーダーとしての経験（業務経験ありの場合）<br>
 	web系の開発に携わったことがある<br>
	LinuxとRDBMSの経験がある<br></em>
<em><u>2011年1月31日現在</u></em>
</blockquote>

これらを元に、一般的に必要とされる、必要なスキルと経験についてお話させていただきます。

<h5 style="border-bottom:1px solid #6699CC;border-bottom-width:1px;border-bottom-style:solid;border-left:10px solid #6699CC;margin-top:25px;padding-left:10px;">
プログラミングの経験が必要
</h5>

まずプログラミング経験についてです。
経験の場については業務経験でも個人でも良いと謳ってますが、家庭用ゲーム開発（以下ゲーム屋さん）は基本的に業務で行っていると思いますので、ここでは「3年以上のプログラミング業務経験」が必要ということになります。
３年という時間については、一つでも高級プログラミング言語（今時アセンブラしか書けませんという方はあまり居ないと思いますが念のため「高級」つけときます）を意のままに使いこなせることが必要、という基準なのかなと思います。が、確認はしていないので定かではありません（汗）石の上にも３年て言いますし、そういうことなのかなと思います。
なぜマスターすることが必要なのか？というと、個人的にも周りをみてても思いますが、一つでも言語をマスターしていれば、PHPだろうが、Javaだろうが、Pascalだろうが大概は理解ができるものだからです。SNSのゲームの開発では開発言語として、PHPとかJavaとかRubyとかPerlとか、ゲーム屋さんにはあまり縁のなかった言語を採用している事が殆どなので、CとかC＋＋ではない新しい言語をマスターする必要があります。そのための素養としても、相応のプログラミングの経験が求められます。
尚、マスターの定義が曖昧なので、ここでは「他人に教える事ができるレベル」に定めたいと思います。

というわけで必要な事の一つ目として、
「高級言語を一つ以上マスターしていること」
を挙げます。

また、エンジニアをしていく上で必要なのは、プログラミングの能力だけではありません。
そこに該当してくるのが弊社の募集要項にある「プロジェクトの管理経験」や「チームのリーダーとしての経験」で求められているものなのかなと思います...しかしこちらも確認していないのでやっぱり定かではありません（泣）
ただこれはけっこうハードルが高い条件だと思います。プログラマのリードはやってても、プロジェクトの管理は普通やっていないと思います。現に他社ではまず見ない条件です。
ということで、こちらの件には触れないでおきたいと思います。

<h5 style="border-bottom:1px solid #6699CC;border-bottom-width:1px;border-bottom-style:solid;border-left:10px solid #6699CC;margin-top:25px;padding-left:10px;">
web系開発の知識が必要
</h5>

次に「web系の開発に携わったことがある」ですが、webアプリはPOSTとかゲットとかの仕組み知らないと作れなかったり、適当に作るとヤバいものが出来てしまうので全般の知識が必要です。仕組みについては「<a target='_blank' href='http://www.amazon.co.jp/%E3%83%8D%E3%83%83%E3%83%88%E3%83%AF%E3%83%BC%E3%82%AF%E3%81%AF%E3%81%AA%E3%81%9C%E3%81%A4%E3%81%AA%E3%81%8C%E3%82%8B%E3%81%AE%E3%81%8B-%E7%AC%AC2%E7%89%88-%E7%9F%A5%E3%81%A3%E3%81%A6%E3%81%8A%E3%81%8D%E3%81%9F%E3%81%84TCP-IP%E3%80%81LAN%E3%80%81%E5%85%89%E3%83%95%E3%82%A1%E3%82%A4%E3%83%90%E3%81%AE%E5%9F%BA%E7%A4%8E%E7%9F%A5%E8%AD%98-%E6%88%B8%E6%A0%B9/dp/4822283119'>ネットワークはなぜつながるのか</a>」あたりに書いてあるhttpの仕組みの知識があれば良いのだろうと思います。ただ、弊社の要項が具体的に何を求めているかは、確認していないので正確にはわかりません（本当にごめんなさい泣）。ただ家庭用ゲームが、ゲーム機の仕様がわかっていないとゲームが作れないのと同じように、webの仕様がわかっていないとちゃんとしたアプリは作れません。

というわけで必要な事の二つ目として、
「web開発の知識が必要」
を挙げます。

具体的には、自分でWebのアプリを作ってみるとかのアクションが必要になると思います。そういった職種に一旦転職するとかの選択肢もありますが、時間がかかりすぎるので現実的ではありません。
ちなみに私は、一時期ゲーム屋を離れてシステム屋になったときに知識を得ました。ゲーム屋からSEになるのはそんなに難しくありません。ちゃんとした社会人で「ゲーム屋とはもう縁を切ります」と言えれば雇ってくれますw

<h5 style="border-bottom:1px solid #6699CC;border-bottom-width:1px;border-bottom-style:solid;border-left:10px solid #6699CC;margin-top:25px;padding-left:10px;">
RDBMSの知識が必要
</h5>
設計に関わるので、使いこなせるレベルの知識が必要です。またDBの部分は速度的にボトルネックになる部分なので、負荷の高くないクエリを書く為の知識や、最適なデータ構造を作るための設計知識が必要です。
平和なゲーム屋さんの場合、このRDBMSが一番縁遠いところだと思います。
ただ使う分にはまったく難しいものではないので、自分でWebのアプリを作る等して知識を身につければよいと思います。ただし負荷問題に関わる部分の知識は、負荷のかからない状況下ではなかなか身に付かないと思います。最適な学習法は思いつきませんが、耳年増的にそういったことがあるという事を知っておくだけでも違うと思うので、書籍等から情報を得てください。手練のゲーム屋さんの皆様には言うまでもないことですが、動けば良いというものではプログラムもDBのクエリもロクなものができません。常にこれが最適解なのか？と、疑って甘んじない姿勢が大切だと思います。

というわけで必要な事の三つ目として、
「RDBMSを使う為の知識が必要」
を挙げます。

<h5 style="border-bottom:1px solid #6699CC;border-bottom-width:1px;border-bottom-style:solid;border-left:10px solid #6699CC;margin-top:25px;padding-left:10px;">
Linuxの知識
</h5>
殆どのアプリケーションサーバーがLinux（もしくはUnix系OS）を採用してると思いますので、当然Linuxでオペレーションができないと困ります。実際就職先を探すにあたり、募集要項を確認したすべての会社がLinuxもしくはUnix系OSの知識を求めていました。
オペレーションについて具体的に挙げるとファイル操作系のコマンド全般(ls,cp,mv,rm,chown,cd,mkdir,cat),検索系のコマンド(find,grep),その他(pwd,history,less)が使えて、さらにエディタ（vimとかemacs）が使えればなんとかなると思います。

というわけで必要な事の四つ目として、
「Linuxの基本的なオペレーションが出来る事が必要」
を挙げます。

<h5 style="border-bottom:1px solid #6699CC;border-bottom-width:1px;border-bottom-style:solid;border-left:10px solid #6699CC;margin-top:25px;padding-left:10px;">
その他
</h5>
他社の募集要項では上記以外にも

<em>
	MVCを理解していること
	オブジェクト指向プログラミングの知識
	ゲームが好きであること
</em>

などが挙げられています。
「ゲームが好きであること」は「ソーシャルネットワークゲームが好きであること」に言い換えたほうがいいと思います...
MVCはsymfonyのチュートリアルで勉強してください。
オブジェクト指向は...まったくの心得が無い方は「<a target='_blank' href='http://www.amazon.co.jp/%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E8%84%B3%E3%81%AE%E3%81%A4%E3%81%8F%E3%82%8A%E6%96%B9%E2%80%95Java%E3%83%BBUML%E3%83%BBEJB%E3%82%92%E3%83%9E%E3%82%B9%E3%82%BF%E3%83%BC%E3%81%99%E3%82%8B%E3%81%9F%E3%82%81%E3%81%AE%E7%A9%B6%E6%A5%B5%E3%81%AE%E5%9F%BA%E7%A4%8E%E8%AC%9B%E5%BA%A7-%E7%89%9B%E5%B0%BE-%E5%89%9B/dp/4798104183'>オブジェクト脳のつくり方</a>」がオブジェクト指向とはなにかを教えてくれると思います、多分。

<h5 style="border-bottom:1px solid #6699CC;border-bottom-width:1px;border-bottom-style:solid;border-left:10px solid #6699CC;margin-top:25px;padding-left:10px;">
「歓迎するスキル」
</h5>
歓迎するスキルに書いてあるものは重要です。当てはまるものがあればあるほど、転職に於ける自身のマイナス点（年齢とか、転職回数とか）を補ってくれます。
他社のものも交えてざっと挙げると以下のようなものになると思います。

<em>
大規模なシステムの開発経験
Webサービス開発経験
ソーシャルアプリ開発経験
携帯サイト開発経験
PHPを利用した開発経験
Railsやsymfonyなどのフレームワークを利用した開発経験
Flash/Flash Liteを用いた開発経験
iPhone/Androidなどのスマートフォンアプリ開発経験
Amazon EC2を利用した開発経験
オブジェクト指向設計、UMLなどの知識
アジャイル開発(テスト駆動開発など)に関する知識
</em>

実務系の経験や、より具体的な要件、必須にすると応募数が少なくなりそうなもの、または、あったらいいな的なものが並びます。
独学出来るもの、たとえばPHPやSymfony、Flash、テスト駆動開発等々は最初に述べた理由により取り組む価値が高いと言えます。

<h5 style="border-bottom:1px solid #6699CC;border-bottom-width:1px;border-bottom-style:solid;border-left:10px solid #6699CC;margin-top:25px;padding-left:10px;">
まとめ
</h5>

まとめると、家庭用のゲーム開発者がSNSゲーム開発者に転身するために必要となる技能は最低でも以下のものが必要です。
「高級言語を一つ以上マスターしていること」
「web開発の知識が必要」
「RDBMSを使う為の知識が必要」
「Linuxの基本的なオペレーションが出来る事が必要」
</div>

そして、より魅力を醸す為にはなるべく多くの、先に挙げたような歓迎要件に当てはまるものを会得している事が大事です。

<h5 style="border-bottom:1px solid #6699CC;border-bottom-width:1px;border-bottom-style:solid;border-left:10px solid #6699CC;margin-top:25px;padding-left:10px;">
家庭用のゲーム開発者がSNSゲーム開発者に転身するための技能を得る具体的なアクション
</h5>
一番良いのは仕事をしながら技能を身につけていく事です。しかしながら、C言語（あるいはC++）ができてNDSのゲームが作れますというだけでSNSゲーム開発者として雇い入れてくれるところはそうそうないでしょう。
その場合には自分でWebアプリを作成し、独学で技能を身につけることをお勧めいたします。

最低限必要なものを簡単に記します。

★有料なもの
	PC一式　- Linux（もしくはUnix系OS）が動作するならなんでも可

★無料なもの
	webサーバー - セットアップに関する情報の多さからapacheがお勧めです
	言語処理プログラム - PHPがお勧めです。が、RubyでもJavaでもお好きな言語でどうぞ。
	RDBMS - MySqlかpostgreSqlの２択です

★あったらいいもの
	常時接続回線 - SNSアプリを作る場合にはサーバーを外部に公開する必要があります


とりあえずこれだけあれば作れちゃいます。
インストールの方法や設定の方法は、これでもかというぐらいネットに公開されていますので、書籍などをわざわざ買う必要もありません。あ、もちろん購入されてもよいと思いますが。
最初はなにがなにやらわからないとは思いますが、別段難しいことはないと思います。
是非、トライしてみてください。

<u><strong><small>サーバーを外部に公開する際にはセキュリティ対策を万全に行う必要があります。クラッカーにサーバーを乗っ取られて、知らぬ間に自らが攻撃者になることなどは決してあってはならないことですので十分注意してください。</small>
</strong></u>

ではまた〜

<div style="margin:0;padding:.5em;border:2px solid #ccc">Zynga Japanでは積極的にエンジニアを採用しています。<br /> 
<a href="http://www.zynga.co.jp/recruit/recruit.php?siteid=unohlabs">採用ページ</a>をご覧になり、興味のある方はぜひご応募ください。</div> ]]>
    </content>
</entry>

<entry>
    <title>都市伝説の検証！Flash CS5のswfはCS4よりファイル容量が大きい!?</title>
    <link rel="alternate" type="text/html" href="http://labs.unoh.net/2011/01/flash_cs5swfcs4.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.unoh.net/mt32/mt-atom.cgi/weblog/blog_id=2/entry_id=1926" title="都市伝説の検証！Flash CS5のswfはCS4よりファイル容量が大きい!?" />
    <id>tag:labs.unoh.net,2011://2.1926</id>
    
    <published>2011-01-28T05:32:48Z</published>
    <updated>2011-01-28T10:53:21Z</updated>
    
    <summary>flashエンジニアのnaoです。 ディスカバリーチャンネルの番組に「怪しい伝説」(Mythbusters)ってのがありますよね。そう、&quot;ワイヤーが切れて自由落下するエレベーター、地面に衝突する寸前に中でジャンプしたら助かるんじゃね？&quot;とか、あほう　希少な検証をやるあの番組です。 ちょっと考えればわかりそうな事を真面目に検証する彼らを生暖かく見守る私ですが、この度自分自身、都市伝説に遭遇いたしました。 その都市伝説というのが、標題の「Flash CS5のswfはCS4よりファイル容量が大きい!?」なワケであります。 私の所属するプロジェクトでは、前任のflashエンジニアがFlash Profesional CS4で開発を行い、私を含めた後任のチームはCS5で開発を行っております。 この時に、前任からの引き継ぎ注意事項として 『swfファイルはCS4で書きだしたほうが軽くなる』 という物が...</summary>
    <author>
        <name>unoh</name>
        
    </author>
    
        <category term="ActionScript" />
    
    <content type="html" xml:lang="ja" xml:base="http://labs.unoh.net/">
        <![CDATA[flashエンジニアのnaoです。

ディスカバリーチャンネルの番組に<a href="http://ja.wikipedia.org/wiki/%E6%80%AA%E3%81%97%E3%81%84%E4%BC%9D%E8%AA%AC">「怪しい伝説」(Mythbusters)</a>ってのがありますよね。そう、"ワイヤーが切れて自由落下するエレベーター、地面に衝突する寸前に中でジャンプしたら助かるんじゃね？"とか、<del>あほう</del>　希少な検証をやるあの番組です。
ちょっと考えればわかりそうな事を真面目に検証する彼らを生暖かく見守る私ですが、この度自分自身、都市伝説に遭遇いたしました。
その都市伝説というのが、標題の「Flash CS5のswfはCS4よりファイル容量が大きい!?」なワケであります。


私の所属するプロジェクトでは、前任のflashエンジニアがFlash Profesional CS4で開発を行い、私を含めた後任のチームはCS5で開発を行っております。
この時に、前任からの引き継ぎ注意事項として

<p><h2><font color = red>『swfファイルはCS4で書きだしたほうが軽くなる』</font></h2></p>

という物があり、実際に前任から引き継いだflaファイルでswfを書きだしてみると、本当にCS5とCS4で容量が違ったのです。CS5で書きだしたswfは、3KBほど容量が重い。
<b><font color=red>なにこの怪奇現象こわい</b></font>。
flash liteを利用する製品では、3KBは命取りです。
臆病風に吹かれまくって天高く舞い上がった私は、CS4のライセンスを持っているチームメンバーに依頼して書き出しをしたのですが、上空の偏西風に流されてミッドウェイあたりまで来たところで、はたと気が付きました。

<p><font color=yellow><b>同じ処理をしている100KB程度のバイトコードで、3KBもサイズが違うのって、明らかにおかしくね？</b></font></p>

100KBのうちの3KBといえば、全体の3%である。1989年に導入された当時の消費税率と同じである。当時の消費税の税収は、なんと6兆円！まぁ、金額は関係ないのですが。

flashのバイトコードは、1処理で2バイトとか3バイト程度。それに変数名が付いたって、ActionScriptの1行分の処理でもせいぜい数十バイトである。いったい、どこで容量が増えるのだろうか？
<p class="code">【実験1】
まず私が試したのは、diffコマンドによって差分を比較する実験。swfファイルの差分を取って比べてみたら、何かわかるのではなかろうか、と思ったのですが、この実験はあえなく失敗。考えてみたら、バイナリの状態のコードなんて人間が一覧して分かるわけがない。実験以前に問題だった。Mythbustersを哂えない。
</p>
<p class="code">【実験2】
次に行ったのは、swfmillをインストールしてswfファイルをテキスト化し、再びdiffを取る実験。こちらは成功。そらそうだ。
内部の構造を追っていくと、ActionScript部分は変化がない。しかし、途中で謎のベクタ描画のグラフィックスオブジェクトに遭遇する。CS4には存在しない。CS5で書きだしたswfにのみ存在するオブジェクトなのだ。<font color=red><b>犯人のしっぽをつかんだ</b></font>。
</p>
<p class="code">【実験3】
初心に返り、Flashで書き出す際にファイルサイズのレポートを出力してみる。グラフィックスオブジェクトが書き出されているなら、何か記述されているはずである。
しかし、全てのオブジェクト名をチェックしたが、見覚えのないオブジェクトは存在しない。
</p>
<p class="code">【考察】
・ActionScript部分の変化は観察されない
・内部に謎のグラフィックスオブジェクトが挿入されており、これがファイルサイズ増の原因らしい
・しかしサイズレポートには怪しいオブジェクトは記述されていない
</p>
さて、この謎のグラフィックスオブジェクトは何か。レポートには名前も出ない存在だけのデータである。が、よくよくサイズレポートを見ているうちに、重大なものに気がついた。

なんと
<p><h2><font color = red>デバイスフォントが埋め込み処理されている</font></h2></p>
のである。


-再現イメージ-
 <p class="code">_等幅 : 確たなﾃﾞりなまﾀ認しくｰ<p>

いやいやいやいや、ないわー。完全にFlash Profesional CS5のバグである。
原因がわかれば対処方法も簡単。埋めこまれてしまっているなら、再定義してやればいい。
今回は以下のような手順で修正を行いました。


<p class="code">・デバイスフォントを指定しているテキストボックスを選択
・別の日本語フォント(_明朝でも何でもいい)に変更する
・全部のデバイスフォントのテキストボックスで上記を行う
・ファイルを保存して閉じる
・ファイルをもう一度開く
・全部のデバイスフォントのテキストボックスを、もう一度、等幅などのデバイスフォントに戻す
・保存して閉じる</p>以上である。すみませんね、手動作業で。
回避方法はあるかもしれないけど知りません。だってもう、私の環境では関係ないから。

書きだしたswfファイルは、みごとCS4で書きだしたswfと完全に一致しました。
現在では無事、CS5で開発を行っております。
<b><font color=red>なお、この不具合はCS4で編集したファイルをCS5で読み込む場合に発生します。
一度対応するか、初めから CS5で製作されたファイルでは発生しません。</font></b>

こうして、Flash CS5のswfはCS4よりファイル容量が大きい!?疑惑は嘘っぱち（まぁバグっぽい物ではあったのですが）都市伝説と証明され、事なきを得ました。
何事も検証してみることが大事だよね☆

<a href="http://www.youtube.com/watch?v=PnntGTOopDE&feature=player_embedded
" target="_blank">都市伝説の例</a>
あやしい！と思った人は検証してみればいいと思うよ。

<div class="amazlet-box" style="margin-bottom:0px;"><div class="amazlet-image" style="float:left;margin:0px 12px 1px 0px;"><a href="http://www.amazon.co.jp/exec/obidos/ASIN/B000NO23W6/unoh-22/ref=nosim/" name="amazletlink" target="_blank"><img src="http://ecx.images-amazon.com/images/I/51o7q-LAOUL._SL160_.jpg" alt="Mythbusters: Collection 1 [DVD] [Import]" style="border: none;" /></a></div><div class="amazlet-info" style="line-height:120%; margin-bottom: 10px"><div class="amazlet-name" style="margin-bottom:10px;line-height:120%"><a href="http://www.amazon.co.jp/exec/obidos/ASIN/B000NO23W6/unoh-22/ref=nosim/" name="amazletlink" target="_blank">Mythbusters: Collection 1 [DVD] [Import]</a><div class="amazlet-powered-date" style="font-size:80%;margin-top:5px;line-height:120%">posted with <a href="http://www.amazlet.com/browse/ASIN/B000NO23W6//ref=nosim/" title="Mythbusters: Collection 1 [DVD] [Import]" target="_blank">amazlet</a> at 11.01.28</div></div><div class="amazlet-detail">Discovery Channel (2007-05-22)<br />売り上げランキング: 79419<br /></div><div class="amazlet-sub-info" style="float: left;"><div class="amazlet-link" style="margin-top: 5px"><a href="http://www.amazon.co.jp/exec/obidos/ASIN/B000NO23W6/unoh-22/ref=nosim/" name="amazletlink" target="_blank">Amazon.co.jp で詳細を見る</a></div></div></div><div class="amazlet-footer" style="clear: left"></div></div>]]>
        
    </content>
</entry>

<entry>
    <title>iPhone向けのサイトを作るときのちょっとした気配り</title>
    <link rel="alternate" type="text/html" href="http://labs.unoh.net/2011/01/small-tips-for-iphone-web-pages.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.unoh.net/mt32/mt-atom.cgi/weblog/blog_id=2/entry_id=1931" title="iPhone向けのサイトを作るときのちょっとした気配り" />
    <id>tag:labs.unoh.net,2011://2.1931</id>
    
    <published>2011-01-24T09:23:33Z</published>
    <updated>2011-01-24T09:35:00Z</updated>
    
    <summary>yamaokaです。 だいぶiPhoneやAndroidといったスマートフォン向けのwebページを作ることが増えてきたのではないでしょうか。ちょっとした気配りで使いやすくなるケースもあるかなと思うので、いくつか使えそうな工夫について書いてみたいと思います。 ただし、今回はiPhone向けです。 タップされた場所をハイライトする iPhoneのSafariでは「-webkit-tap-highlight-color」という拡張された属性があり、タップされた箇所に色を付けることができます。CSS3ではRGBaによる色指定ができるので、半透明の色を指定すればタップされた箇所をわかりやすく示すことができます。例えば、-webkit-tap-highlight-color:rgba(255,0,0,0.40);と指定すると薄い赤色を付けることができます。「outline:none;」と併せてリンク文...</summary>
    <author>
        <name>unoh</name>
        
    </author>
    
    <content type="html" xml:lang="ja" xml:base="http://labs.unoh.net/">
        <![CDATA[<p>yamaokaです。</p>

<p>だいぶiPhoneやAndroidといったスマートフォン向けのwebページを作ることが増えてきたのではないでしょうか。ちょっとした気配りで使いやすくなるケースもあるかなと思うので、いくつか使えそうな工夫について書いてみたいと思います。</p>

<p>ただし、今回はiPhone向けです。</p>


<h3>タップされた場所をハイライトする</h3>

<p>iPhoneのSafariでは「-webkit-tap-highlight-color」という拡張された属性があり、タップされた箇所に色を付けることができます。CSS3ではRGBaによる色指定ができるので、半透明の色を指定すればタップされた箇所をわかりやすく示すことができます。例えば、<pre class="code"><code>-webkit-tap-highlight-color:rgba(255,0,0,0.40);</code></pre>と指定すると薄い赤色を付けることができます。「outline:none;」と併せてリンク文字列に指定するといいかもしれませんね。</p>

<h3>数字を電話番号のリンクにしない</h3>

<p>iPhoneのSafariはHTMLに含まれる数字を電話番号として検出、自動的に電話番号のリンクにしてしまいます。タップすると電話がかけられるので便利な場面もあるのですが、「123.45」のような小数点を含む数字や「100-0001」のような郵便番号、「2001-2011」のようなcopyrightの年号表記までリンクになってしまうのです。</p>

<p>この挙動を無効にするには<pre class="code"><code>&lt;meta name=&quot;format-detection&quot; content=&quot;telephone=no&quot;&gt;</code></pre>とmeta要素を使って記述します。どうしても電話番号を表示したい場合は明示的にtelto:で指定してあげればいいので自動検出は無効にしてしまうのがオススメです。</p>

<h3>文字のサイズをコントロールする</h3>

<p>PC向けに作成されたサイトをiPhoneで見た場合、フォントの大きさがPCで表示した場合と違った比率で表示されることがあります。iPhoneのSafariは文字の大きさを自動で調整してくれるのですが、自分でコントロールしたい場合もあるのではないでしょうか。</p>

<p>自動調整を無効にしたい場合、CSSで<pre class="code"><code>-webkit-text-size-adjust:none;</code></pre>を指定します。先程の「-webkit-tap-highlight-color」と同様、iPhoneのSafariで拡張されているCSSの属性です。ただし自動調整がされなくなってしまうので、Media Queryなどを使ってスクリーンの大きさにあったfont-sizeを指定してあげる必要があります。</p>

<p>自動調整を無効にした場合でも、画面の向きが変わってローテートされた場合の表示の調整は行われます（iPhoneの場合）。</p>

<p>また、あえて自動調整にまかせるという選択肢もあると思うので、この属性を使用する場合はきちんとサイト全体の方針を決めてから使うのがいいのではないかと思います。</p>

<h3>終わりに</h3>

<p>iPhone向けの小さなtipsを3つ紹介しました。小さな画面で操作することが多い分、ちょっとした気配りで操作性が上がることも多いのではないでしょうか。少しでも気の届いたページを作っていけたらいいなと思います。</p>

<p>SafariのHTMLとCSSについてはAppleのリファレンスを見れば載っているので、参考にどうぞ。</p>
<ul>
<li><a href="http://developer.apple.com/library/safari/#documentation/AppleApplications/Reference/SafariHTMLRef/Introduction.html">Safari HTML Reference: Introduction</a></li>
<li><a href="http://developer.apple.com/library/safari/#documentation/AppleApplications/Reference/SafariCSSRef/Introduction.html">Safari CSS Reference: Introduction to Safari CSS Reference</a></li>
</ul>

]]>
        
    </content>
</entry>

<entry>
    <title>WebエンジニアにやさしいYamahaルータRTX-*** 設定方法（導入編） </title>
    <link rel="alternate" type="text/html" href="http://labs.unoh.net/2011/01/webyamahartx-.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.unoh.net/mt32/mt-atom.cgi/weblog/blog_id=2/entry_id=1927" title="WebエンジニアにやさしいYamahaルータRTX-*** 設定方法（導入編） " />
    <id>tag:labs.unoh.net,2011://2.1927</id>
    
    <published>2011-01-12T10:50:35Z</published>
    <updated>2011-01-12T11:27:39Z</updated>
    
    <summary> こんにちは。入社６ヶ月目のyusukeです。 Webエンジニアの方がルータを触る機会は、少ないと思います。 ということで、Yamahaルータを例にルータの設定方法を紹介します。 1. Yamahaルータへのログインについて Yamahaルータへのログインは、通常以下の２つの方法いずれかでログインします。 - シリアルコンソールケーブルを使用したログイン シリアルコンソールケーブルを直接Yamahaルータに接続します。 シリアルコンソールケーブルはクロスケーブルとDSUB9 or 25 と RJ45 変換コネクタでも自作できます。(ルータの購入時に付属している場合もあります。) - telnetまたはsshを使用したログイン これは、ご存知のようにtelnetコマンドやsshコマンドを使用したログインです。 いずれもログインした後の設定方法は同じです。 ログイン時パスワードを入れてログイン...</summary>
    <author>
        <name>unoh</name>
        
    </author>
    
    <content type="html" xml:lang="ja" xml:base="http://labs.unoh.net/">
        <![CDATA[
<p>こんにちは。入社６ヶ月目のyusukeです。</p>

<p>Webエンジニアの方がルータを触る機会は、少ないと思います。<br/>
ということで、Yamahaルータを例にルータの設定方法を紹介します。</p>

<h3 style="border-bottom:1px solid #6699CC;border-bottom-width:1px;border-bottom-style:solid;border-left:10px solid #6699CC;margin-top:25px;padding-left:10px;">
1. Yamahaルータへのログインについて
</h3>

<p>
Yamahaルータへのログインは、通常以下の２つの方法いずれかでログインします。<br/>

<h3>- シリアルコンソールケーブルを使用したログイン</h3>
<p>
シリアルコンソールケーブルを直接Yamahaルータに接続します。</br>
シリアルコンソールケーブルはクロスケーブルとDSUB9 or 25 と RJ45 変換コネクタでも自作できます。(ルータの購入時に付属している場合もあります。)
</p>

<h3>- telnetまたはsshを使用したログイン</h3>
<p>これは、ご存知のようにtelnetコマンドやsshコマンドを使用したログインです。<br/>

いずれもログインした後の設定方法は同じです。<br/>
ログイン時パスワードを入れてログインしますが、設定を行うには<br/>
以下のコマンドを入力して管理者モードに移行してから行います。<br/>
</p>

<pre class="code">
 $ administrator
</pre>

<h3 style="border-bottom:1px solid #6699CC;border-bottom-width:1px;border-bottom-style:solid;border-left:10px solid #6699CC;margin-top:25px;padding-left:10px;">
2. お勧めする初期設定
</h3>

<h3>- コンソールの表示文字コードを設定する</h3>
<pre class="code">
 $ console character ascii
</pre>

<p>
 文字コードを設定します。euc, sjisなどにするとエラーなどが日本語になったりします。
</p>

<h3>- コンソールの表示行数のリミットを外す</h3>
<pre class="code">
 $ console columns infinity
</pre>

<p>
show ** 等でページ送りをしないように設定します。<br/>
show configコマンドなどを一度に表示して保存する場合などに最適です。<br/>
ページ送りを行いたい場合は、show ** | less で行えます。
</p>

<h3>- プロンプトの設定</h3>
<pre class="code">
 # console prompt zynga
</pre>
<p>
これは、プロンプトの先頭文字列を設定するコマンドです。(例： zynga$ )<br/>
bashなどの$PS1と同じようなものです。ただし、特殊変数などは使えません。
</p>

<h3 style="border-bottom:1px solid #6699CC;border-bottom-width:1px;border-bottom-style:solid;border-left:10px solid #6699CC;margin-top:25px;padding-left:10px;">
3. コマンド入力記法について
</h3>
<h3>- showコマンドとクエスチョンマーク( ? )</h3>
<p>
自分の設定した内容を見るときは $ show configと入力します。また、設定内容と現在の動作状況を見るときは $show tech または $show techinfoと入力します。<br/>
その他、show コマンドを入力後 ? を入力することでヘルプが表示されます。<br/>
</p>

<h3>- noコマンド</h3>
<pre class="code">
 $ no console character ascii
</pre>
<p>
今まで、入力したコマンドを無効にしたいときなどに使用します。<br/>
show configで表示されるコマンドの先頭に no をつけて実行することにより該当行のコマンドが無効化または、デフォルト状態に戻ります。
</p>

<h3>- 設定の一括投入</h3>
<p>
一度に行う設定が複数ある場合、設定の反映はコピペで一括で行うことができます<br/>
初期設定時やネットワークを遮断した際の設定は一括で行った方が効率がよいと思います。<br/>
今までの設定は以下で行えます。管理者モードで以下３行をコピペすることで反映されます。
</p>
<pre class="code">
console character ascii
console columns infinity
console prompt zynga
</pre>

<h3>- 設定の保存</h3>
<pre class="code">
 # save
</pre>
<p>
設定内容を不揮発性メモリに保存して、ルータの再起動後でも設定が残るようにしておきます。
</p>

<p>
最後に、オンラインでの設定変更は十分にマニュアルや設定例などを読んだ上行ってください。予期せぬ再起動。通信断を招く可能性があります。
</p>

<div style="margin:0;padding:.5em;border:2px solid #ccc">Zynga Japanでは積極的にエンジニアを採用しています。<br /> 
<a href="http://www.zynga.co.jp/recruit/recruit.php?siteid=unohlabs">採用ページ</a>をご覧になり、興味のある方はぜひご応募ください。</div> ]]>
        
    </content>
</entry>

<entry>
    <title>30分でわかる PHP Extensionの作り方を学べる記事をかいたよー ＼(＾o＾)／</title>
    <link rel="alternate" type="text/html" href="http://labs.unoh.net/2011/01/30_php_extension_o.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.unoh.net/mt32/mt-atom.cgi/weblog/blog_id=2/entry_id=1925" title="30分でわかる PHP Extensionの作り方を学べる記事をかいたよー ＼(＾o＾)／" />
    <id>tag:labs.unoh.net,2011://2.1925</id>
    
    <published>2011-01-11T07:13:02Z</published>
    <updated>2011-01-11T10:12:19Z</updated>
    
    <summary>こんにちは。12月に入社した@chobi_eです。 私が所属しているチームではお菓子系男子が30%を超えているという素敵チームで 毎週チーム内の漢の子がお菓子を焼いてくるという状況でハッピハッピハッピーです。 今日は私が学んできたPHP Extension作成についてのノウハウの一部を 公開しようと思います。 PHPExtension作成についての資料はklabさんやyoyaさん rskyさんの記事が参考になりますが私のようにPHPは書けてもCが書けない人には具体的にhello world以降何をすればいいのかがサッパリよく分かりません。 そこで先人達が作ってくれた偉大なライブラリをPHPで扱えるようにする為にC/MigemoのPHPバインディングを作ってみましょう ...</summary>
    <author>
        <name>unoh</name>
        
    </author>
    
    <content type="html" xml:lang="ja" xml:base="http://labs.unoh.net/">
        <![CDATA[<p>こんにちは。12月に入社した<a href="http://twitter.com/chobi_e">@chobi_e</a>です。</p>


<p>私が所属しているチームではお菓子系男子が30%を超えているという素敵チームで
毎週チーム内の漢の子がお菓子を焼いてくるという状況でハッピハッピハッピーです。
</p>

<p>今日は私が学んできたPHP Extension作成についてのノウハウの一部を
公開しようと思います。</p>

<p>PHPExtension作成についての資料はklabさんやyoyaさん
rskyさんの記事が参考になりますが私のようにPHPは書けてもCが書けない人には具体的にhello world以降何をすればいいのかがサッパリよく分かりません。</p>


<p>そこで先人達が作ってくれた偉大なライブラリをPHPで扱えるようにする為にC/MigemoのPHPバインディングを作ってみましょう</p>
]]>
        <![CDATA[
<h3 style="border-bottom:1px solid #6699CC;border-bottom-width:1px;border-bottom-style:solid;border-left:10px solid #6699CC;margin-top:25px;padding-left:10px;">C/Migemoをインストールしてみる</h3>

<p>読者の方の中にはC/Migemoをご存知でない方もいらっしゃるかと思いますので簡単に説明するとC/MigemoはKoRoNさんが作成されているローマ字のまま日本語を(インクリメンタルに)検索する」ための正規表現を生成するライブラリです。</p>

<pre class="code"><a href="http://www.kaoriya.net/#CMIGEMO">http://www.kaoriya.net/#CMIGEMO</a></pre>

<p>私は普段Ubuntuで開発をしているのでUbuntuでのC/Migemoの導入方法の説明を書きます。
OSXやWindowsの方はC/MigemoのREADMEを読みつつコンパイルしてください。</p>

<pre class="code">sudo aptitude install nkf

svn co http://cvs.kaoriya.net/svn/CMigemo/trunk migemo
cd migemo
./configure
make gcc

make gcc-dict
cd dict
make utf8
cd ..
sudo make gcc-install
</pre>

<p>これでC/Migemoのインストールが完了しました。C/Migemoには簡単な動作を確認する為の
プログラムが付属しているのでそれを使って試してみましょう。</p>

<p>cmigemoを起動してchobiという文字列を入力してみます。</p>

<pre class="code">chobie@air:~/src/migemo$ cmigemo -d /usr/local/share/migemo/utf-8/migemo-dict
migemo_open("/usr/local/share/migemo/utf-8/migemo-dict")=0x820d008
clock()=0.210000
QUERY: chobi
PATTERN: (ﾁｮﾋﾞ|チョビ|ちょび|ｃｈｏｂｉ|chobi)</pre>


<p>chobiに対応した正規表現が生成されましたね！</p>


<h3 style="border-bottom:1px solid #6699CC;border-bottom-width:1px;border-bottom-style:solid;border-left:10px solid #6699CC;margin-top:25px;padding-left:10px;">PHP Extensionの下準備</h3>

<p>まずはPHP Extensionの設計を自分がよく理解できる言語でふわっと書いてみましょう。</p>

<pre class="code">&lt;?php
/**
* これは実装するExtensionの目標で実際には使いません。
*/
class Migemo{
    public function __construct()
    {
      //migemoのロードを行う
    }

    public function query($query)
    {
      //migemoに問い合せて正規表現を返す
    }
}
</pre>

<p>せっかくなのでUnitTestも書いておきましょう。</p>

<p>PHPExtensionを作成する場合は別途テスト用のrun-test.phpというのが付属してるんですが、自分で使う分には慣れ親しんだツールを使ったほうが楽なので今回はPHPUnit3を使います。</p>

<pre class="code">sudo pear channel-discover pear.phpunit.de
sudo pear channel-discover components.ez.no
sudo pear channel-discover pear.symfony-project.com
sudo pear install phpunit/PHPUnit</pre>

<p>テストを書きます。</p>

<li>MigemoTest.php</li>
<pre class="code">&lt;?php
class MigemoTest extends \PHPUnit_Framework_TestCase{


    /**
     * Migemoロードされているかしらべるよ
     */
    public function testMigemoIsLoaded()
    {
        $this->assertEquals(true,extension_loaded("migemo"));
    }

    /**
     * Migemoクラスがあるかしらべるよ
     * @depends testMigemoIsLoaded
     */
    public function testMigemoClassExists()
    {
        $this->assertEquals(true,class_exists("Migemo"));
    }

    /**
     * @depends testMigemoClassExists
     */
    public function testQueryMethodExists()
    {
        $reflection = new \ReflectionClass("Migemo");
        $this->assertEquals(true,$reflection->hasMethod("query"));
    }

    /**
     * @depends testQueryMethodExists
     */
    public function testQuery()
    {
        $migemo = new Migemo();
        $this->assertEquals("(ﾁｮﾋﾞ|チョビ|ちょび|ｃｈｏｂｉ|chobi)",$migemo->query("chobi"));
        unset($migemo);
    }

    /**
     * @depends testQuery
     */
    public function testQueryCycle()
    {
        $migemo = new Migemo();
        for($i = 0; $i < 30; $i++){
            $this->assertEquals("(ﾁｮﾋﾞ|チョビ|ちょび|ｃｈｏｂｉ|chobi)",$migemo->query("chobi"));
        }
        unset($migemo);

    }
}
</pre>

<p>さて、これでExtension作成までの準備が出来ましたのでサクサク書いていきます。</p>

<h3 style="border-bottom:1px solid #6699CC;border-bottom-width:1px;border-bottom-style:solid;border-left:10px solid #6699CC;margin-top:25px;padding-left:10px;">PHP Extensionを書く</h3>


<p>私は容量悪い系の人間なのでコツコツ書いてきますよ！みなさんも写経についてきてくださいね</p>

<li>config.m4</li>

<pre class="code">PHP_ARG_ENABLE(migemo,
  [  --enable-migemo      Enable "migemo" extension support])

if test $PHP_MIGEMO != "no"; then
  export CFLAGS="$CFLAGS -lmigemo"
  PHP_SUBST(MIGEMO_SHARED_LIBADD)
  PHP_NEW_EXTENSION(migemo, migemo.c, $ext_shared)
fi</pre>

<p>phpizeというビルド環境をチェックしつつコンパイルに必要な設定を書いてくれるconfig.m4というマクロファイルを書きます。とりあえずこう書けばOK</p>

<p style="color:999;">本来はもうちょっとPHP Extensionらしい書き方が有るんですが長くなるので今回はこんな形でごまかしちゃいましょう。</p>


<p>続いてPHPにExtensionを登録するためのコードを書きます。</p>

<li>php_migemo.h</li>

<pre class="code">#ifndef PHP_MIGEMO_H
#define PHP_MIGEMO_H

#define PHP_MIGEMO_EXTNAME "migemo"
#define PHP_MIGEMO_EXTVER "0.1"


#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "php.h"
#include <migemo.h>

extern zend_module_entry migemo_module_entry;
#define phpext_migemo_ptr &migemo_module_entry;

PHPAPI zend_class_entry *migemo_class_entry;

#endif /* PHP_MIGEMO_H */
</pre>


<li>migemo.c</li>

<pre class="code">#include "php_migemo.h"

PHPAPI function_entry php_migemo_methods[] = {
    {NULL, NULL, NULL}
};

PHP_MINIT_FUNCTION(migemo) {
    return SUCCESS;
}

PHP_MINFO_FUNCTION(migemo)
{
    return SUCCESS;
}

zend_module_entry migemo_module_entry = {
#if ZEND_MODULE_API_NO >= 20010901
    STANDARD_MODULE_HEADER,
#endif
    PHP_MIGEMO_EXTNAME,
    NULL, 					/* Functions */
    PHP_MINIT(migemo),	    /* MINIT */
    NULL, 	                /* MSHUTDOWN */
    NULL, 	                /* RINIT */
    NULL,	                /* RSHUTDOWN */
    PHP_MINFO(migemo),	    /* MINFO */
#if ZEND_MODULE_API_NO >= 20010901
    PHP_MIGEMO_EXTVER,
#endif
    STANDARD_MODULE_PROPERTIES
};

#ifdef COMPILE_DL_MIGEMO
ZEND_GET_MODULE(migemo)
#endif
</pre>

<p>そいでは準備ができましたのでコンパイルしてみましょう。</p>

<pre class="code">phpize
./confiugre
make
sudo make install

# migemo本体の共有ライブラリいれてからldconfigしてなかったので初回だけ。
sudo ldconfig
</pre>

<p>php5のconfファイルにmigemo.soを追加します。</p>

<li>/etc/php5/conf.d/migemo</li>

<pre class="code">extension=migemo.so</pre>

<p>これでPHPにMigemo Extensionを登録するだけのExtensionが作れました。</p>

<pre class="code">chobie@air:~/src/php-migemo$ php -m | grep migemo
migemo
</pre>

<p>確かにPHPExtensionがロードされているようですね。UnitTestも実行しておきましょう。</p>

<pre class="code">chobie@air:~/src/php-migemo$ phpunit MigemoTest.php 
PHPUnit 3.5.6 by Sebastian Bergmann.

.FSSS

Time: 0 seconds, Memory: 3.00Mb

There was 1 failure:

1) MigemoTest::testMigemoClassExists
Failed asserting that <boolean:false> matches expected <boolean:true>.

/home/chobie/src/php-migemo/MigemoTest.php:19

FAILURES!
Tests: 2, Assertions: 2, Failures: 1, Skipped: 3.
</pre>

<p>きちんとモジュールが読み込まれるテストは成功していますね。</p>

<h3 style="border-bottom:1px solid #6699CC;border-bottom-width:1px;border-bottom-style:solid;border-left:10px solid #6699CC;margin-top:25px;padding-left:10px;">クラスだけを実装する</h3>

<p>それではMigemoクラスをExtensionで実装してみましょう。まずは単純にクラスの定義だけを行ないます。PHPで言えばこんなコードになります。</p>

<pre class="code">
&lt;?php
class Migemo{}
</pre>

<p>新しいクラスを定義するにははPHP_MINIT_FUNCTION(migemo)に3行追加するだけで出来ます。</p>

<li>migemo.c</li>

<pre class="code">PHP_MINIT_FUNCTION(migemo) {
    <span style="background:green">zend_class_entry ce;</span>
    <span style="background:green">INIT_CLASS_ENTRY(ce, "Migemo", php_migemo_methods);</span>
    <span style="background:green">migemo_class_entry = zend_register_internal_class(&ce TSRMLS_CC);</span>
    return SUCCESS;
}
</pre>

<p>コレだけです。zend_class_entry `migemo_class_entry`は前もってphp_migemo.h
で宣言しておいたのでPHP_MINIT_FUNCTIONで使うことができます。</p>

<p>INIT_CLASS_ENTRYは一番目にzend_class_entry、2番目にクラス名、3番目にクラスに
対応したfunction_entryを渡せばOKです。</p>

<p>それでは再度コンパイルしてチェックしてみましょう。</p>

<pre class="code">sudo make install

chobie@air:~/src/php-migemo$ phpunit MigemoTest.php 
PHPUnit 3.5.6 by Sebastian Bergmann.

..FII

Time: 0 seconds, Memory: 3.00Mb

There was 1 failure:

1) MigemoTest::testQueryMethodExists
Failed asserting that <boolean:false> matches expected <boolean:true>.

/home/chobie/src/php-migemo/MigemoTest.php:28

FAILURES!
Tests: 5, Assertions: 3, Failures: 1, Incomplete: 2.
</pre>

<p>2つテストが成功しました。クラスも定義できたのでどんどん進みましょう。</p>

<h3 style="border-bottom:1px solid #6699CC;border-bottom-width:1px;border-bottom-style:solid;border-left:10px solid #6699CC;margin-top:25px;padding-left:10px;">queryメソッドを実装してみる</h3>

<p>ひとまずこれでMigemoクラスが扱えるようになったので地味な部分はとりあえずおいておいてqueryメソッドを実装してしまいましょう。</p>


<p>メソッドの追加は先程`INIT_CLASS_ENTRY`で指定した`php_migemo_methods`に
どんなメソッドがあるかを追加しておけばOKです。</p>

<pre class="code">PHPAPI function_entry php_migemo_methods[] = {
    <span style="background:green">PHP_ME(migemo, query, arginfo_migemo_query, ZEND_ACC_PUBLIC)</span>
    {NULL, NULL, NULL}
};
</pre>

<p>function_entry配列のお約束は最後は必ず{NULL,NULL,NULL}で締める、という事を守っておけばOK。PHP_MEなどのfunction_entry用マクロのあとは
,は必要ありません。大体一緒なので雰囲気で書いちゃいましょう。</p>

<p>これでMigemoクラスにはqueryというメソッドがあるよ！というのを定義出来ました。
肝心の実装はどう書くかというと。</p>

<pre class="code">ZEND_BEGIN_ARG_INFO_EX(arginfo_migemo_query, 0, 0, 1)
    ZEND_ARG_INFO(0, query)
ZEND_END_ARG_INFO()
PHP_METHOD(migemo, query)
{
    migemo *m;
    char *query;
    int ret = 0;
    int query_len = 0;
    unsigned char *result;
    if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
        "s", &query, &query_len) == FAILURE){
        return;
    }

    m =  migemo_open("/usr/local/share/migemo/utf-8/migemo-dict");
    result = migemo_query(m, query);

    RETVAL_STRING(result, 1);
    migemo_release(m, result);
    migemo_close(m);
}
</pre>

<p>こんな感じです。Zend Engine2周りの関数やマクロが入ってきて若干分かりづらいかもしれませんがこれはこういうもんだと思っておけば大丈夫です。<p>

<p>RETVAL_STRINGはZEND_APIで定義されているマクロの一つでメソッドや関数の返り値を
簡単に設定できるマクロです。RETVAL系のマクロを使うとCの型からPHPの型に簡単に
変換しつつ返り値の設定をしてくれるので便利ですね。</p>


<p>それではまたコンパイルして試してみましょう</p>

<pre class="code">sudo make install

chobie@air:~/src/php-migemo$ phpunit MigemoTest.php 
PHPUnit 3.5.6 by Sebastian Bergmann.

.....

Time: 7 seconds, Memory: 3.00Mb

OK (5 tests, 34 assertions)
</pre>

<p>おー、ちゃんと動いていますね！</p>


<p>しかし今のままだとqueryメソッドを呼ぶ際に毎回migemoの初期化と解放をしているのが気に入りません。</p>


<p>それではコンストラクタを実装してみましょう。</p>

<h3 style="border-bottom:1px solid #6699CC;border-bottom-width:1px;border-bottom-style:solid;border-left:10px solid #6699CC;margin-top:25px;padding-left:10px;">コンストラクタを実装</h3>

<p>コンストラクタの実装と行きたいのですがよく考えてみると一つ困ったことがでてきました。
migemoポインタはどこに格納しておけばよいのでしょう？</p>


<p>クラスのインスタンス関連付けて何かしらの構造を持ち回したい場合は自前の
構造体を定義してクラス生成時のオブジェクトの生成をハンドリングする方法を使います。</p>

<p>オブジェクトの生成をハンドリングする為にはオブジェクトを作るための関数と、オブジェクトが作ったメモリを開放するための関数を定義してzend_class_entry->create_object にオブジェクトを作成する為の関数を設定してあげます。</p>

<li>migemo.c</li>

<pre class="code">typedef struct{
    zend_object zo;
    migemo *migemo;
} php_migemo;
</pre>

<p>構造体のキャストを行なっているので先頭はzend_objectでなければいけません。</p>

<p>続いてオブジェクトの生成と解放を行う関数を追加します。殆ど同じなのでこういうもんだと思ってコピペすればOKです。大事なところは緑でマーキングしておいたので自分で違うのを作る場合は参考にしてください。</p>

<li>migemo.c</li>

<pre class="code">static void <span style="background:green">php_migemo_free_storage</span>(<span style="background:green">php_migemo *object</span> TSRMLS_DC)
{
    zend_object_std_dtor(&object->zo TSRMLS_CC);
    
    <span style="background:green">if(!object->migemo){</span>
      <span style="background:green">migemo_free(object->migemo);</span>
    <span style="background:green">}</span>
    <span style="background:green">object->migemo = NULL;</span>
    efree(object);
}

zend_object_value <span style="background:green">php_migemo_new</span>(zend_class_entry *ce TSRMLS_DC)
{
	zend_object_value retval;
	<span style="background:green">php_migemo *obj</span>;
	zval *tmp;

	obj = ecalloc(1, sizeof(*obj));
	zend_object_std_init( &obj->zo, ce TSRMLS_CC );
	zend_hash_copy(obj->zo.properties, &ce->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));

	retval.handle = zend_objects_store_put(obj, 
        (zend_objects_store_dtor_t)zend_objects_destroy_object,
        (zend_objects_free_object_storage_t)<span style="background:green">php_migemo_free_storage</span>,
        NULL TSRMLS_CC);
	retval.handlers = zend_get_std_object_handlers();
	return retval;
}
</pre>

<p>コンストラクタを追加します。</p>

<pre class="code">PHP_METHOD(migemo, __construct){
    php_migemo *this = (php_migemo *) zend_object_store_get_object(getThis() TSRMLS_CC);

    this->migemo = migemo_open("/usr/local/share/migemo/utf-8/migemo-dict");
}
</pre>

<p>コンストラクタを追加したのでメソッド定義とクラスの初期化部分に少し手を入れます。</p>

<pre class="code">PHPAPI function_entry php_migemo_methods[] = {
    PHP_ME(migemo, __construct, NULL, ZEND_ACC_PUBLIC)
    <span style="background:green">PHP_ME(migemo, query, arginfo_migemo_query, ZEND_ACC_PUBLIC)</span>
    {NULL, NULL, NULL}
};

PHP_MINIT_FUNCTION(migemo) {
    zend_class_entry ce;
    INIT_CLASS_ENTRY(ce, "Migemo", php_migemo_methods);
    migemo_class_entry = zend_register_internal_class(&ce TSRMLS_CC);
<span style="background:green">migemo_class_entry->create_object = php_migemo_new;</span>

    return SUCCESS;
}
</pre>

<p>コンストラクタ側でmigemoの生成行うようにしたので、それに合わせて
queryの実装を変更します。</p>

<pre class="code">PHP_METHOD(migemo, query)
{
    <span style="background:green">php_migemo *this = (php_migemo *) zend_object_store_get_object(getThis() TSRMLS_CC);</span>
    char *query;
    int ret = 0;
    int query_len = 0;
    unsigned char *result;
    if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
        "s", &query, &query_len) == FAILURE){
        return;
    }

    result = migemo_query(this->migemo, query);

    RETVAL_STRING(result, 1);
    migemo_release(this->migemo, result);
}
</pre>

<p>これで実装が完了しましたね。もう一回コンパイルして試してみましょう。</p>

<pre class="code">chobie@air:~/src/php-migemo$ phpunit MigemoTest.php 
PHPUnit 3.5.6 by Sebastian Bergmann.

.....

Time: 0 seconds, Memory: 3.00Mb

OK (5 tests, 34 assertions)
</pre>

<p>ユニットテストの時間が短縮されていて効果が出ていますね。これで実装が終了しました！</p>


<h3 style="border-bottom:1px solid #6699CC;border-bottom-width:1px;border-bottom-style:solid;border-left:10px solid #6699CC;margin-top:25px;padding-left:10px;">あとがき</h3>

<p>どうでしたか？思っていたより簡単に開発できたのではないでしょうか？</p>

<p>PHPバインディングから始めるExtension作成は割と身近で親しみやすく、
次に自分が何を調べるべきかという目標が明確に分かるのでとっかかりには
オススメだと思います。</p>


<p>最後に参考になるリンクと宣伝を貼っておきます。</p>

<li>php-migemo <a href="http://github.com/chobie/php-migemo">http://github.com/chobie/php-migemo</a></li>

<p>今回作成したExtensionのGitリポジトリです。</p>

<li>php-git <a href="http://github.com/chobie/php-git">http://github.com/chobie/php-git</a></li>

<p>php-gitはlibgit2をPHPで扱えるようにする為のPHPバインディングです。最近作り始めたばかりなので
まだまだalpha developmentで課題はたくさん有りますがPHPでgit repositoryを使った操作が行えます。</p>


<li>ZendEngine 勉強会グループ <a href="http://groups.google.com/group/php-zendengine/">http://groups.google.com/group/php-zendengine/</a></li>

<p>2011年2月か3月に東京でZendEngineについての勉強会を行ないます。私もLT予定ですので
ご興味のある方はぜひぜひどうぞ！</p>

<li>[klabさん] <a href="http://dsas.blog.klab.org/archives/50777398.html">PHP Extension を作ろう第１回 - まずは Hello World</a></li>
<li>[klabさん] <a href="http://dsas.blog.klab.org/archives/50782987.html">PHP Extension を作ろう第２回 - 引数と返値</a></li>
<li>[klabさん] <a href="http://dsas.blog.klab.org/archives/50903613.html">PHP Extension を作ろう第３回 - クラスを作ろう</a></li>
<li>[yoyaさん] <a href="http://pwiki.awm.jp/~yoya/?PHP/ext">PHP extension の作り方</a></li>
<li>[rskyさん] <a href="http://gihyo.jp/dev/serial/01/php-module/0006">実例で学ぶPHP拡張モジュールの作り方 第6回　PHP 5.3の変更点（その2）</a></li>


<p>それでは、みんなも作ってア・ラ・モード☆</p>

<div style="margin:0;padding:.5em;border:2px solid #ccc">Zynga Japanでは積極的にエンジニアを採用しています。<br />
<a href="http://www.zynga.co.jp/recruit/recruit.php?siteid=unohlabs">採用ページ</a>をご覧になり、興味のある方はぜひご応募ください。</div>]]>
    </content>
</entry>

<entry>
    <title>flashlite1.1で文字圧縮してみた</title>
    <link rel="alternate" type="text/html" href="http://labs.unoh.net/2011/01/flashlite11.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.unoh.net/mt32/mt-atom.cgi/weblog/blog_id=2/entry_id=1923" title="flashlite1.1で文字圧縮してみた" />
    <id>tag:labs.unoh.net,2011://2.1923</id>
    
    <published>2011-01-07T10:37:00Z</published>
    <updated>2011-01-08T08:05:20Z</updated>
    
    <summary>FlashLite 1.1で文字圧縮を使ってみる。</summary>
    <author>
        <name>unoh</name>
        
    </author>
    
        <category term="ActionScript" />
    
    <content type="html" xml:lang="ja" xml:base="http://labs.unoh.net/">
        <![CDATA[<p>明けましておめでとうございます＆はじめまして。12月に入社した加藤です。</p>
<p>FlashLite 2.0をやるつもりで入ってみたらバリバリ1.1だったので、出す機会を逸していたネタをここで出したいと思います。</p>
<p>FlashLite 1.1の制限にはいろいろありますが、開発する上で一番困るのは100KB制限です。<br />
  100KBと言うと、このページの右カラムに並んでいる著者一覧の写真が一つだいたい8KBくらいですので、だいたい12枚分になります。その中にグラフィックとスクリプト両方をつめ込まねばなりません。<br />
  普通のFLASHならパブリッシュ設定の「ムービーの圧縮」にチェックを入れれば圧縮が有効になるのですが、残念ながらFlashLite 1.1ではその機能はグレーアウトされて使えません。<br />
  そういうわけでFlashLite 1.1のエンジニアは日々シェイプの最適化から変数名の文字数まで、地道な作業に血道をあげています。</p>
<p>しかし、生成エンジンで変数差し込みをする場合、いくらswfを最適化したところで「100KB-swfのファイルサイズ」分のデータしか入れられません。Twitterクライアントを作っていたとき、これだと50件表示までしか出来なくて何とかして100件表示にしたいと思い辿り着いたのが文字圧縮です。</p>]]>
        <![CDATA[<p>圧縮というとzipやらrarやらといったでお馴染みのアレですが、通常の圧縮形式は圧縮率を稼ぐために符号化やらなにやら様々な処理を行っていて、圧縮率が高い代わりに圧縮／展開処理が複雑で実行にも時間がかかります。いろんな意味で非力なFlashLite1.1では実装も難しい上、圧縮は疎か展開するにも非常に時間がかかってしまい、現実的ではありません（と言いつつ一人ハフマン符号化して圧縮を実装した人を知っていますが）。そこで目をつけたのはBPEという方法です。</p>
<p>BPEとはByte Pair Encodingの略で、「隣り合った二文字を使われていない一文字で置き換える」という圧縮方法です。例えば、「ABCDABCDABCDABCDABCD」という文字列をBPEで圧縮すると、ABを使われていないXに、CDをYに置き換え、「XYXYXYXYXY」となります。あとはX=AB、Y=CDという置換対応表を別で持っておけば、「XYXYXYXYXY」を「ABCDABCDABCDABCDABCD」に<span style="font-weight:bold">文字列置換だけで戻すことができます</span>。とても単純です。ただし、その替りに圧縮率が悪く、このままではどうやっても50%以下には縮みません。しかし、その単純さ故に殆どCPUパワーを食わないため、とてもFlashLite向きと言えます（圧縮処理は重いという特徴もあるのですが、変数差し込みに使う場合それはサーバ側で行えばよく、問題になりません）。</p>
<p>では実際の文章で試してみましょう。まずは圧縮からです。今回は「吾輩は猫である」を使います。<br />
英文を圧縮する場合は隣り合った2文字を1文字で置き換えますが、この場合は文章が日本語なので、2バイト文字を使われていない1バイト文字で置き換えます。頻出度合いが低くなると圧縮効果が落ちますので、今回は頻出上位60文字を抽出し置き換えました。方法は割愛。</p>
<dl>
<dt>元の文章</dt>
<dd><blockquote>
<p>　吾輩は猫である。名前はまだ無い。<br />
　どこで生れたかとんと見当がつかぬ。何でも薄暗いじめじめした所でニャ―ニャ―泣いていた事だけは記憶している。吾輩はここで始めて人間というものを見た。しかもあとで聞くとそれは書生という人間中で一番獰悪な種族であったそうだ。この書生というのは時々我々を捕えて煮て食うという話である。しかしその当時は何という考もなかったから別段恐しいとも思わなかった。ただ彼の掌に載せられてス―と持ち上げられた時何だかフワフワした感じがあったばかりである。掌の上で少し落ちついて書生の顔を見たのがいわゆる人間というものの見始であろう。この時妙なものだと思った感じが今でも残っている。第一毛をもって装飾されべきはずの顔がつるつるしてまるで薬缶だ。その後猫にもだいぶ逢ったがこんな片輪には一度も出会わした事がない。のみならず顔の真中があまりに突起している。そうしてその穴の中から時々ぷうぷうと煙を吹く。どうも咽せぽくて実に弱った。これが人間の飲む煙草というものである事はようやくこの頃知った。</p></blockquote>
</dd>
<dt>BPE圧縮後</dt>
<dd>
<blockquote>
<p>　RN-O&amp;/*。名前-E1無&quot;。<br />
　_0&amp;?4#,$]$:[.&lt;,ぬ。H&amp;'薄暗&quot;&gt;I&gt;I)#所&amp;ZYKZYK泣&quot;(&quot;#A1け-記憶)(&quot;*。RN-00&amp;`I(;9$&quot;%'!8:#。),'/$&amp;聞@$34-B?$&quot;%;9D&amp;C番獰悪2種族&amp;/+#3%1。0!B?$&quot;%!-6F我F8捕え(煮(食%$&quot;%話&amp;/*。),)3![6-H$&quot;%考'2,+#,7別段恐)&quot;$'PG2,+#。#1彼!Q5載T74(スK$持VSげ74#6H1,X^X^)#W&gt;./+#ば,\&amp;/*。Q!S&amp;少)落V&lt;&quot;(B?!J8:#!.&quot;Gゆ*;9$&quot;%'!!:`&amp;/ろ%。0!6妙2'!1$P+#W&gt;.今&amp;'残+(&quot;*。第C毛8'+(装飾さ4べき-U!J.&lt;*&lt;*)(E*&amp;薬缶1。3!後O5'1&quot;ぶ逢+#.0]2片輪5-C度'出会G)#A.2&quot;。!み27UJ!真D./E\5突起)(&quot;*。3%)(3!穴!D,76FL%L%$M8吹@。_%'咽Tぽ@(実5弱+#。04.;9!飲むM草$&quot;%'!&amp;/*A-よ%や@0!頃知+#。</p>
  </blockquote></dd></dl>
<p>文字数は双方450文字と変わりませんが、サイズは元が896バイトに対し、圧縮後は539バイトになりました。約60%に圧縮されたということになります。この時、置換対応表は以下のようになります。</p>
<blockquote>!=の<br />
  &quot;=い<br />
  #=た<br />
  $=と<br />
  %=う<br />
  &amp;=で<br />
  '=も<br />
  (=て<br />
  )=し<br />
  *=る<br />
  +=っ<br />
  ,=か<br />
  -=は<br />
  .=が<br />
  /=あ<br />
  0=こ<br />
  1=だ<br />
  2=な<br />
  3=そ<br />
  4=れ<br />
  5=に<br />
  6=時<br />
  7=ら<br />
  8=を<br />
  9=間<br />
  :=見<br />
  ;=人<br />
  &lt;=つ<br />
  &gt;=じ<br />
  ?=生<br />
  @=く<br />
  A=事<br />
  B=書<br />
  C=一<br />
  D=中<br />
  E=ま<br />
  F=々<br />
  G=わ<br />
  H=何<br />
  I=め<br />
  J=顔<br />
  K=ー<br />
  L=ぷ<br />
  M=煙<br />
  N=輩<br />
  O=猫<br />
  P=思<br />
  Q=掌<br />
  R=吾<br />
  S=上<br />
  T=せ<br />
  U=ず<br />
  V=ち<br />
  W=感<br />
  X=フ<br />
  Y=ャ<br />
  Z=ニ<br />
  [=当<br />
  \=り<br />
  ]=ん<br />
  ^=ワ<br />
  _=ど<br />
  `=始</blockquote>
<p>あとはこれを元に展開すればいいわけです。FlashLite1.1には置換系のメソッドがないので少々面倒ですが、僕は以下のように実装しました。</p>
<dl>
<dt>1フレーム目</dt>
<dd>
<pre class="code">
stop();

//デコードキー
keys = "!\"#$%&'()*+,-./0123456789:;<>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`";
//デコード文字列
vals = "のいたとうでもてしるっかはがあこだなそれに時らを間見人つじ生く事書一中ま々わ何め顔ーぷ煙輩猫思掌吾上せずち感フャニ当りんワど始";
//圧縮後文字列
bpe_text = "　RN-O&/*。名前-E1無\"。\n　_0&?4#,$]$:[.<,ぬ。H&'薄暗\">I>I)#所&ZYKZYK泣\"(\"#A1け-記憶)(\"*。RN-00&`I(;9$\"%'!8:#。),'/$&聞@$34-B?$\"%;9D&C番獰悪2種族&/+#3%1。0!B?$\"%!-6F我F8捕え(煮(食%$\"%話&/*。),)3![6-H$\"%考'2,+#,7別段恐)\"$'PG2,+#。#1彼!Q5載T74(スK$持VSげ74#6H1,X^X^)#W>./+#ば,\&/*。Q!S&少)落V<\"(B?!J8:#!.\"Gゆ*;9$\"%'!!:`&/ろ%。0!6妙2'!1$P+#W>.今&'残+(\"*。第C毛8'+(装飾さ4べき-U!J.<*<*)(E*&薬缶1。3!後O5'1\"ぶ逢+#.0]2片輪5-C度'出会G)#A.2\"。!み27UJ!真D./E\\5突起)(\"*。3%)(3!穴!D,76FL%L%$M8吹@。_%'咽Tぽ@(実5弱+#。04.;9!飲むM草$\"%'!&/*A-よ%や@0!頃知+#。";

// キーの数を取得
key_count = length(keys);

// 繰り返し使うので連番変数にしてしまう。rkが半角文字、rcは全角文字。
for (i=1; i<=key_count; i++) {
	set("rk" add i, substring(keys, i, 1));
	set("rc" add i, mbsubstring(vals, i, 1));
}

// BPEをデコード
text_length = mblength(bpe_text);
decoded_text = "";
for (j=1; j<=text_length; j++) {
	// 一文字ずつ変数cに格納
	c = mbsubstring(bpe_text, j, 1);
	call("DECODE");
	decoded_text = decoded_text add c;
}
// 元の文章が出力される筈
trace(decoded_text);
</pre>
</dd>

<dt>2フレーム目</dt>
<dd>
<pre class="code">
// フレームラベル「DECODE」とつける
for (m=1; m<=key_count; m++) {
    if (get("rk" add m) eq c) {
        set("c", get("rc" add m));
        break;
    }
}
</pre>
</dd></dl>
<p>一文字ずつ走査してcに文字を代入し、DECODEフレームでキーと合う文字列があったら置き換える、といった方法で圧縮された文字列を展開して元の文章に戻しています。<br />
上ではデコードキーとデコード文字列を連結して渡し、flash内で1文字ずつ変数化していますが、もちろん変数化した後の値を渡しても構いません。<br />
経験則では日本語の文章はだいたい70%以下にまで縮みますので、50KBの所に70KB程の文字列が入る事になります。これはTwitterの発言に換算しますと、1発言が最大140文字で全てが2バイト文字の場合は140*2で280バイトになりますので、ざっと50発言程多く入れられる計算です。</p>
<p>圧縮は兎も角展開については割と簡単な実装で実現できますので、文字列が多く差し込まれるswfで容量が厳しいときは検討してみてはいかがでしょうか？</p>


<div style="margin:0;padding:.5em;border:2px solid #ccc">Zynga Japanでは積極的にエンジニアを採用しています。<br />
<a href="http://www.zynga.co.jp/recruit/recruit.php?siteid=unohlabs">採用ページ</a>をご覧になり、興味のある方はぜひご応募ください。</div>]]>
    </content>
</entry>

<entry>
    <title>入社後なるべく早くキャッチアップするために心がけたこと</title>
    <link rel="alternate" type="text/html" href="http://labs.unoh.net/2011/01/site.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.unoh.net/mt32/mt-atom.cgi/weblog/blog_id=2/entry_id=1922" title="入社後なるべく早くキャッチアップするために心がけたこと" />
    <id>tag:labs.unoh.net,2011://2.1922</id>
    
    <published>2011-01-06T00:00:00Z</published>
    <updated>2011-01-07T15:31:22Z</updated>
    
    <summary>あけましておめでとうございます。 chunoです。 弊社には(身内自慢になるかもしれませんが)手練のエンジニアが老若男女問わず揃っており、ギークでもスーパープログラマでもない私にとっては 「一番の下手くそ」 でいられる、成長するためには理想的な環境です。 ※参考「情熱プログラマー」第一章の4 とは言え、そういう状況で安穏としているわけにもいかないので、少しでも早く周囲にキャッチアップできるよう努めました。 それらについて、これから述べます。...</summary>
    <author>
        <name>unoh</name>
        
    </author>
    
    <content type="html" xml:lang="ja" xml:base="http://labs.unoh.net/">
        <![CDATA[<p>あけましておめでとうございます。<br />
chunoです。</p>

<p>弊社には(身内自慢になるかもしれませんが)手練のエンジニアが老若男女問わず揃っており、ギークでもスーパープログラマでもない私にとっては</p>
<div>「一番の下手くそ」</div>
<p>でいられる、成長するためには理想的な環境です。</p>
※参考「<a href="http://www.amazon.co.jp/dp/4274067939/">情熱プログラマー</a>」第一章の4</p>
<p><br /></p>
<p>とは言え、そういう状況で安穏としているわけにもいかないので、少しでも早く周囲にキャッチアップできるよう努めました。</p>
<p>それらについて、これから述べます。</p>

]]>
        <![CDATA[<p><br />
</p><h3>■周りの人の助力を仰ぐ</h3>&nbsp;入社直後にアサインされたプロジェクトが佳境を迎えていたことに加え、個人的な経験やスキルは以下のような状況でした。<br />
<ul><br />
	<li>symfony→使ったこと無し</li>
	<li>TDD(テスト駆動開発)→未経験</li>
	<li>memcached→使ったこと無し</li>
	<li>Git→使ったこと無し</li></ul><br />
&nbsp;結構テンパっていたのですが、良き先輩であるチームメンバーに積極的に教えを乞いました。<br />
&nbsp;質問する際は、ノートに図を書いたりして持って行くと、こちらの「聞きたいこと、理解できていないこと」が伝わりやすくなります。<br />
<small>※無闇矢鱈と質問しに行ってお仕事の邪魔をしたことがあります、ゴメンナサイ...</small>

<p><br />
</p><h3>■ペアプログラミングの提案</h3>
&nbsp;TDDに不慣れだったり、自分の開発手法に不安があったりする場合は、ペアプログラミングをお願いするのも手です。<br />
開発方法が学べたり、コードの質も向上します。<br />
&nbsp;ただし、ものすごく疲れるので、細目に休憩は取ってください。<br />
※喫煙者の方と組むと「そろそろタバコ休憩しますか」という提案をしやすいのでオススメです(半分冗談です...)。

<p><br />
</p><h3>■意見することを恐れない</h3>
&nbsp;マンツーマンの面談だとそうでもないでしょうが、大勢で参加しているミーティング等で自分の意見を述べるのは、多少の勇気を必要とします。<br />
&nbsp;ですが、<strong>意見を持てるということは、それだけ物事を真剣に考えている証拠でもある</strong>ので、思うところがあるのなら是非とも自信を持って口に出すべきです。<br />
　(もちろん、発言の仕方には十分な配慮が必要ですが...)<br />
&nbsp;なお、意見することで自分が感じたメリットには以下のようなものがあります。<br />
<ul><br />
	<li>皆にとって良い意見であれば採り入れてもらえます</li>
	<li>自分の考え方と異なる意見を聞く機会ができます</li>
	<li>自分の発言がキッカケで新たな建設的な議論が始まる可能性もあります</li><br />
</ul>

<p></p><h3>■指摘を受けたら素直に受け入れる</h3>
&nbsp;ミスを犯した際はもちろん、各種ミーティングや、設計レビュー、ペアプログラミング等で耳の痛いことを言われても、自分が成長するためのキッカケだと考えて素直に受け入れました。<br />
&nbsp;また、これらをノートやWiki、ブログ等に書き留めておくと、同じ失敗を繰り返す確率が減りますし、自分だけの財産にもなります。

<p><br />
</p><h3>■自動化できるところは自動化する</h3>
&nbsp;私はVimで開発を行っていますが、ケアレスミス防止のために、以下のようなスクリプトを「.vimrc」に書きました。<br />
ファイル書き込み時に自動でPHPの構文チェックをしてくれます。<br />
(同様なものは既に色々な方々がネット上で公開されていますが...)<br />
<pre class="code">autocmd BufWritePost *.php :call PHPLint()<br />
function PHPLint()  let result = system( &amp;ft . ' -l ' . bufname(""))<br />
  let headPart = strpart(result, 0, 16) <br />
  if headPart != "No syntax errors"<br />
    echo result<br />
  endif<br />
endfunction</pre>

<p></p>

<h3><br /></h3><h3>■できないことはできないと言う</h3>
&nbsp;どうしても遠慮がちになったり、「期待に応えないと！」という気持ちが強くなったりで、なかなか「No」と言いづらいものですが、スケジュール的なことだったり、その他諸々について無理だと思ったら、正直に伝えたほうが良いです。<div>それで相手の心象を悪くすることはありませんし、&nbsp;</div><div>「では○○だったら可能ですか」&nbsp;</div><div>「△△だったら可能です」&nbsp;</div><div>といった歩み寄りのやり取りで、双方にとって好ましい結果に落ち着かせることができます。&nbsp;</div><div>※「俺ヤル気ねーよ、やりたくねーよ」みたいな態度は論外ですが。

<p><br />
</p><h3>■見ている人は見ている</h3>
&nbsp;良い意味でも悪い意味でも、見られているものです(普段の立ち居振る舞いだったり、SVNのコミットログだったり...)。<br />
特に入社したばかりの人は目につきやすいので、勤務態度等には気をつけましょう。<br />
&nbsp;そして、淡々と実直にお仕事をしていれば、徐々に周囲の人達も認めてくれるようになり、飲みの席でも一層話が弾むようになります。<br />
そうなるまである程度時間はかかりますが、焦らないことが肝要です。<br /><font class="Apple-style-span" style="font-size: 0.7em; ">
※myChuno.class.phpとかmyChuno◯◯ってデータの入ったyamlをコミットしてしまってゴメンナサイ...</font></div><div>

<p></p>

<p><br />
</p><h3>■勉強会やセミナーに参加する</h3>
&nbsp;都合がつけば、ドシドシ参加してみましょう。</div><div>(私は、<a href="http://phpcon.php.gr.jp/2010/">PHPカンファレンス2010</a>や、弊社で行われた<a href="http://news.zynga.co.jp/2010/11/22/symfony2-2/">第一回Symfony2勉強会</a>に参加しました)</div><div>他社様の開発事例を耳にしたり、会社の同僚や先輩が発表する様子を目にしたり、自社以外で活躍されているエンジニアの方々と出会うことで、自分に足りないものを認識したり、自分が自信を持てるものを見つけたり...と、得られるものは多々あります。</div><div>※なお、<a href="http://news.zynga.co.jp/2010/12/27/symfony2_1_15/">第二回Symfony2勉強会</a>も弊社で開催します！
<p></p><hr>

<p>以上です。</p><p>
新しい環境下で不安な気持ちを持たれている方の一助となれば幸いです。</p></div>
そして...
<div style="margin:0;padding:.5em;border:2px solid #ccc">Zynga Japanでは積極的にエンジニアを採用しています。<br />
<a href="http://www.zynga.co.jp/recruit/recruit.php?siteid=unohlabs">採用ページ</a>をご覧になり、興味のある方はぜひご応募ください。</div>

もし、本ブログをご覧いただいた方々と一緒に働くことができたら、最高です！
]]>
    </content>
</entry>

<entry>
    <title>Valgrindを使って楽々PHP拡張モジュール開発のデバッグ</title>
    <link rel="alternate" type="text/html" href="http://labs.unoh.net/2011/01/valgrindphp.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.unoh.net/mt32/mt-atom.cgi/weblog/blog_id=2/entry_id=1920" title="Valgrindを使って楽々PHP拡張モジュール開発のデバッグ" />
    <id>tag:labs.unoh.net,2011://2.1920</id>
    
    <published>2011-01-05T08:53:18Z</published>
    <updated>2011-01-07T11:25:34Z</updated>
    
    <summary>明けましておめでとうございます。@emorinsです。 みなさんモジュール開発ではどのようにデバッギングしていますか？モジュールになると普段使い慣れたデバッグツールが使えず、手動の動作確認だけで済まされている方もいらっしゃるのではないでしょうか。 今回はC/C++開発ではメジャーなメモリデバッガ『Valgrind』をPHP拡張モジュールの開発で活用することで、普段使い慣れたツールでのデバッグの例をご紹介します。 1.PHP拡張モジュールの作成 まず開発用にPHPをデバッグモードでビルド。 #cd ./php-5.x.x #./configure --enable-debug #make #make install PHP拡張モジュールを作成 #cd ./ext #./ext_skel --extname=zynga_func #cd zynga_func 16行目から18行目のコメントアウ...</summary>
    <author>
        <name>unoh</name>
        
    </author>
    
    <content type="html" xml:lang="ja" xml:base="http://labs.unoh.net/">
        <![CDATA[<p>明けましておめでとうございます。<a href="http://twitter.com/emorins">@emorins</a>です。</p>
<p>みなさんモジュール開発ではどのようにデバッギングしていますか？モジュールになると普段使い慣れたデバッグツールが使えず、手動の動作確認だけで済まされている方もいらっしゃるのではないでしょうか。</p>
<p>今回はC/C++開発ではメジャーなメモリデバッガ『<a href="http://valgrind.org/">Valgrind</a>』をPHP拡張モジュールの開発で活用することで、普段使い慣れたツールでのデバッグの例をご紹介します。</p>

<h3>1.PHP拡張モジュールの作成</h3>
<p>まず開発用にPHPをデバッグモードでビルド。</p>
<pre class="code">#cd ./php-5.x.x
#./configure --enable-debug
#make
#make install</pre>

<p>PHP拡張モジュールを作成</p>
<pre class="code">#cd ./ext
#./ext_skel --extname=zynga_func
#cd zynga_func</pre>

<p>16行目から18行目のコメントアウトを外す</p>
<pre class="code">#emacs config.m
- dnl PHP_ARG_ENABLE(zynga_func, whether to enable zynga_func support,
- dnl Make sure that the comment is aligned:
- dnl [  --enable-zynga_func           Enable zynga_func support])
+ PHP_ARG_ENABLE(zynga_func, whether to enable zynga_func support,
+ Make sure that the comment is aligned:
+ [  --enable-zynga_func           Enable zynga_func support])</pre>

<p>拡張モジュールのビルド</p>
<pre class="code">#phpize
#./configure
#make
#make install</pre>

<p>php.iniに以下を追加</p>
<pre class="code">extension=zynga_func.so</pre>

<p>同一ディレクトリ内に生成されているテスト用PHPコードを実行</p>
<pre class="code">#php zynga_func.php</pre>

<p>以下のように出力されたらモジュールの正常な読み込みに成功。</p>
 <pre class="code">Functions available in the test extension:
confirm_zynga_func_compiled

Congratulations! You have successfully modified ext/zynga_func/config.m4.
Module zynga_func is now compiled into PHP.</pre>

<p>これで正常にPHP拡張モジュールの生成と読み込みが確認できたので、Valgrindでデバッギングしてみましょう。</p>

<h3>2.Valgrindによるデバッグ</h3>
<p>Valgrindにはいくつかのツールが付属したツール群になっていますが、まず最も使用するであろうMemcheckによるメモリーリーク、初期化・開放などのメモリ周りのデバッグログを出力してみましょう。</p>

<pre class="code">#valgrind php zynga_func.php
==2107==
==2107== HEAP SUMMARY:
==2107==     in use at exit: 104,669 bytes in 9 blocks
==2107==   total heap usage: 10,973 allocs, 10,964 frees, 2,127,924 bytes  allocated
==2107==
==2107== LEAK SUMMARY:
==2107==    definitely lost: 0 bytes in 0 blocks
==2107==    indirectly lost: 0 bytes in 0 blocks
==2107==      possibly lost: 0 bytes in 0 blocks
==2107==    still reachable: 104,669 bytes in 9 blocks
==2107==         suppressed: 0 bytes in 0 blocks
==2107== Rerun with --leak-check=full to see details of leaked memory
==2107== 
==2107== For counts of detected and suppressed errors, rerun with: -v
==2107== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)</pre>

<p>※ログの見方</p>
<ul>
<li>HEAP SUMMARY: どれだけのヒープ領域を使用し、解放したかの数値。</li>
<li>LEAK SUMMARY: メモリーリークが起きているbyte数とblock数。</li>
<li>ERROR SUMMARY: エラー数</li>
</ul>

<p>ログから、メモリーリークは一切起きておらず、ヒープ領域も僅かに開放されていない箇所もあるが、正常に動作していると言えます。</p>

<p>次にわざとメモリーリークを起こすコードを関数内に埋め込んでみます。zynga_func.c内の、PHP_FUNCTION(confirm_zynga_func_compiled)関数が、先ほどzynga_func.phpで実行された関数になるので、その中の処理を書き換えます。</p>

<p>mallocで確保しているにも関わらずfreeで開放していないため、メモリーリークが起きるコード。</p>
<pre class="code">#emacs zynga_func.c
void f(void)
{
    int* x = malloc(10 * sizeof(int));
    x[10] = 0;        // problem 1: heap block overrun
}                    // problem 2: memory leak -- x not freed
PHP_FUNCTION(confirm_zynga_func_compiled)
{
    f();
    ....</pre>
<p>ビルドして反映。</p>
<pre class="code">#make
#make install</pre>

<p>valgrindで確認。</p>
<pre class="code">#valgrind php zynga_func.php
==4934== Invalid write of size 4
==4934==    at 0x101231C14: f (in /usr/local/lib/php/extensions/debug-non-zts-20060613/zynga_func.so)
==4934==    by 0x101231C3B: zif_confirm_zynga_func_compiled (in /usr/local/lib/php/extensions/debug-non-zts-20060613/zynga_func.so)
==4934==    by 0x100308AF3: zend_do_fcall_common_helper_SPEC (in /usr/local/bin/php)
==4934==    by 0x100309A06: ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER (in /usr/local/bin/php)
==4934==    by 0x1003084FB: execute (in /usr/local/bin/php)
==4934==    by 0x1002DD728: zend_execute_scripts (in /usr/local/bin/php)
==4934==    by 0x100279F64: php_execute_script (in /usr/local/bin/php)
==4934==    by 0x10036A507: main (in /usr/local/bin/php)
==4934==  Address 0x1010b1298 is 0 bytes after a block of size 40 alloc'd
==4934==    at 0x10062D79F: malloc (vg_replace_malloc.c:236)
==4934==    by 0x101231C07: f (in /usr/local/lib/php/extensions/debug-non-zts-20060613/zynga_func.so)
==4934==    by 0x101231C3B: zif_confirm_zynga_func_compiled (in /usr/local/lib/php/extensions/debug-non-zts-20060613/zynga_func.so)
==4934==    by 0x100308AF3: zend_do_fcall_common_helper_SPEC (in /usr/local/bin/php)
==4934==    by 0x100309A06: ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER (in /usr/local/bin/php)
==4934==    by 0x1003084FB: execute (in /usr/local/bin/php)
==4934==    by 0x1002DD728: zend_execute_scripts (in /usr/local/bin/php)
==4934==    by 0x100279F64: php_execute_script (in /usr/local/bin/php)
==4934==    by 0x10036A507: main (in /usr/local/bin/php)
==4934==    Congratulations! You have successfully modified ext/zynga_func/config.m4. Module zynga_func is now compiled into PHP.
==4934== 
==4934== HEAP SUMMARY:
==4934==     in use at exit: 104,709 bytes in 10 blocks
==4934==   total heap usage: 10,974 allocs, 10,964 frees, 2,127,964 bytes allocated
==4934== 
==4934== LEAK SUMMARY:
==4934==    definitely lost: 40 bytes in 1 blocks
==4934==    indirectly lost: 0 bytes in 0 blocks
==4934==      possibly lost: 0 bytes in 0 blocks
==4934==    still reachable: 104,669 bytes in 9 blocks
==4934==         suppressed: 0 bytes in 0 blocks
==4934== Rerun with --leak-check=full to see details of leaked memory</pre>

<p>今度はリークしている箇所と、byte数・block数がログに出力されるのを確認できました。</p>
<p>Valgrindはメモリーリークの検出以外に、初期化されていないメモリ領域の使用、freeされたメモリ領域の使用、ヒーププロファイラ、キャッシュプロファイラなど多用の機能を備えています。</p>
<p>普段使い慣れたツールで、開発に負荷のかからないデバッグを行っていきましょう。</p>


<div style="margin:0;padding:.5em;border:2px solid #ccc">Zynga Japanでは積極的にエンジニアを採用しています。<br />
<a href="http://www.zynga.co.jp/recruit/recruit.php?siteid=unohlabs">採用ページ</a>をご覧になり、興味のある方はぜひご応募ください。</div>
]]>
        
    </content>
</entry>

</feed> 


