<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>でこてっくろぐ</title>
        <link>http://dekokun.github.io</link>
        <description><![CDATA[でこてっくろぐのRSSフィード]]></description>
        <atom:link href="http://dekokun.github.io/rss.xml" rel="self"
                   type="application/rss+xml" />
        <lastBuildDate>No date found.</lastBuildDate>
        <item>
    <title>「第2回 スタートHaskell2」行ってきた</title>
    <link>http://dekokun.github.io/posts/2012-07-22.html</link>
    <description><![CDATA[<!doctype html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7" lang="ja"> <![endif]-->
<!--[if IE 7]>    <html class="no-js lt-ie9 lt-ie8" lang="ja"> <![endif]-->
<!--[if IE 8]>    <html class="no-js lt-ie9" lang="ja"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="ja"> <!--<![endif]-->
  <head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# article: http://ogp.me/ns/article#">
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <title>「第2回 スタートHaskell2」行ってきた</title>
    <meta name="description" content>
    <meta name="author" content>

    <meta name="viewport" content="width=device-width">
    <meta property="fb:app_id" content="351187098330864">
    <meta property="og:type" content="article">
    <meta property="og:image" content="http://dekokun.github.com/img/dekokun.png">
    <meta property="og:title" content="「第2回 スタートHaskell2」行ってきた">
    <meta property="og:description" content="@dekokunの技術日記">
    <meta property="og:site_name" content="でこてっくろぐ">
    <meta name="twitter:widgets:csp" content="on">

    <link rel="stylesheet" href="../css/bootstrap.css">
    <link rel="stylesheet" href="../css/bootstrap-responsive.css">
    <link rel="stylesheet" href="../css/style.css">
    <style>
    body {
      padding-top: 60px;
      padding-bottom: 40px;
    }
    </style>
    <link href="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.css" type="text/css" rel="stylesheet">
    <script src="../js/libs/modernizr-2.5.3-respond-1.1.0.min.js"></script>
    <script>
      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

      ga('create', 'UA-39650556-1', 'auto');
      ga('send', 'pageview');
    </script>
  </head>
  <body>
  <!--[if lt IE 7]><p class=chromeframe>Your browser is <em>ancient!</em> <a href="http://browsehappy.com/">Upgrade to a different browser</a> or <a href="http://www.google.com/chromeframe/?redirect=true">install Google Chrome Frame</a> to experience this site.</p><![endif]-->
    <div id="fb-root"></div>
    <script>(function(d, s, id) {
      var js, fjs = d.getElementsByTagName(s)[0];
      if (d.getElementById(id)) return;
      js = d.createElement(s); js.id = id;
      js.src = "//connect.facebook.net/ja_JP/all.js#xfbml=1&appId=351187098330864";
      fjs.parentNode.insertBefore(js, fjs);
      }(document, 'script', 'facebook-jssdk'));
    </script>
    <header>
      <nav class="navbar navbar-fixed-top">
        <div class="navbar-inner">
          <div class="container">
            <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
            </a>
            <a class="brand" href="../index.html">でこてっくろぐ</a>
            <div class="nav-collapse">
              <ul class="nav">
                <li><a href="../index.html">ほーむ</a></li>
                <li><a href="../posts.html">あーかいぶ</a></li>
                <li><a href="../aboutme.html">あばうとみー</a></li>
              </ul>
            </div><!--/.nav-collapse -->
          </div>
        </div>
      </nav>
    </header>

    <div class="container">
      <div class="row">
        <article class="span9">
          <h1>「第2回 スタートHaskell2」行ってきた</h1>

<p>by <em><a href="https://twitter.com/dekokun">@dekokun</a></em> on <strong>2012/07/22 07:28</strong></p>

<p>Tagged as: <a href="../tags/Haskell.html">Haskell</a>, <a href="../tags/勉強会.html">勉強会</a>.</p>

<p>初技術ブログ。スタイリングがイケてない部分はおいおい変えていきましょう。あれ、「つっこみいただけたらと」って書いたけどコメント欄ないんじゃね？</p>
<h2 id="イベント概要">イベント概要</h2>
<ul>
<li>PARTAKE <a href="http://partake.in/events/e2f99b6b-a96f-4819-80d5-c5d61d2b427c">第2回 スタートHaskell2</a></li>
<li>月に1度くらいのペースで<a href="http://www.amazon.co.jp/すごいHaskellたのしく学ぼう-Miran-Lipovača/dp/4274068854">すごいHaskell楽しく学ぼう</a>をテキストに、セミナーと演習で進んでいく</li>
</ul>
<h2 id="内容">内容</h2>
<ul>
<li>詳細については以下ブログに詳しいのでそちらにお任せします <a href="http://makopi23.blog.fc2.com/blog-date-20120722.html">makopi23のブログ 「第2回 スタートHaskell2」に参加しました</a></li>
<li>ちなみに私もSKIコンビネータの話にはついていけませんでした…切ない…</li>
</ul>
<h2 id="演習問題発表補足">演習問題発表補足</h2>
<ul>
<li>演習問題にて、myAndやmyOrなどの実装(論理演算子(&amp;&amp;)や(||)を自分で実装する)について発表しました</li>
</ul>
<h3 id="私の回答は以下">私の回答は以下</h3>
<pre><code>myNot :: Bool -&gt; Bool
myNot True = False
myNot False = True

myAnd :: Bool -&gt; Bool -&gt; Bool
myAnd True True = True
myAnd _ _ = False

myOr :: Bool -&gt; Bool -&gt; Bool
myOr False False = False
myOr _ _ = True

myXor :: Bool -&gt; Bool -&gt; Bool
myXor True False = True
myXor False True = True
myXor _ _ = False</code></pre>
<p>で、Twitterを見ていたらツッコミをいただいていたのです。</p>
<blockquote>
<p>このmyAndは右の引数に対して正格になるから myAnd False _ = False myAnd _ b = b のほうがいい思うのだけど、これはどうなんじゃろ #start_haskell <a href="https://twitter.com/tanakh/status/226948910785126400">@tanakh</a></p>
</blockquote>
<p>確かに、私のmyAndだと最初に両引数を評価してしまいますので遅延評価を行うHaskellの論理演算子とは挙動が違います(よね…？)</p>
<h3 id="再回答">再回答</h3>
<p>というわけで、myAndとmyOrについて私が正しいと思うように作りなおしました。</p>
<p>こんな感じでいいのでしょうか。ツッコミいただけたらと。</p>
<pre><code>myAnd :: Bool -&gt; Bool -&gt; Bool
myAnd False _ = False
myAnd _ b = b

myOr :: Bool -&gt; Bool -&gt; Bool
myOr True _ = True
myOr _ b = b</code></pre>
<p>xorはどうあっても両引数を評価しないとダメという認識</p>
<p>以上。</p>
<h2 id="注">注</h2>
<p>この日記は以前書いた別のブログの日記を移設したものです(2012/08/05)</p>

<div id="disqus_thread"></div>
<script type="text/javascript">
    /* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */
    var disqus_shortname = 'dekokun'; // required: replace example with your forum shortname

    /* * * DON'T EDIT BELOW THIS LINE * * */
    (function() {
        var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
        dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js';
        (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
    })();
</script>
<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
<a href="http://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a>

          <ul class="social">
            <li class="kindle"><div class="kindleWidget"><img style="vertical-align:middle;" src="https://d1xnn692s7u6t6.cloudfront.net/white-15.png" /><span style="vertical-align:middle;margin-left:3px;">Send to Kindle</span></div></li>
            <li class="facebook"><div class="fb-like" data-send="false" data-layout="button_count" data-width="100" data-show-faces="true" data-font="arial"></div></li>
            <li class="twitter"><a href="https://twitter.com/share" class="twitter-share-button" data-via="dekokun" data-lang="ja">ツイート</a></li>
            <li class="hatena-bookmark"><a href="http://b.hatena.ne.jp/entry/" class="hatena-bookmark-button" data-hatena-bookmark-layout="standard" title="このエントリーをはてなブックマークに追加"><img src="http://b.st-hatena.com/images/entry-button/button-only.gif" alt="このエントリーをはてなブックマークに追加" width="20" height="20" style="border: none;"></a><script type="text/javascript" src="http://b.st-hatena.com/js/bookmark_button.js" charset="utf-8" async="async"></script></li>
            <li><a data-pocket-label="pocket" data-pocket-count="horizontal" class="pocket-btn" data-lang="en"></a>
            <script type="text/javascript">!function(d,i){if(!d.getElementById(i)){var j=d.createElement("script");j.id=i;j.src="https://widgets.getpocket.com/v1/j/btn.js?v=1";var w=d.getElementById(i);d.body.appendChild(j);}}(document,"pocket-btn-js");</script></li>
          </ul>

        </article>
        <aside class="span3">
          <div class="sidebar-module">
            <div class="title">プロフィール</div>
            <p class="id"><a href="https://twitter.com/dekokun">dekokun</a></p>
            <p><a href="https://twitter.com/dekokun"><img src="../img/dekokun.png" alt="dekokun"></a></p>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.io/";
              Hatena.BookmarkWidget.title = "人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 200;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.com/";
              Hatena.BookmarkWidget.title = "旧人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 0;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module visible-desktop">
            <div class="title">twitter</div>
            <a class="twitter-timeline" data-dnt="true" href="https://twitter.com/dekokun" data-widget-id="306408547573440513">@dekokun からのツイート</a>
            <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
          </div>
          <div class="sidebar-module hidden-phone">
            <div class="title">RSS</div>
            <p><a href="../rss.xml"><img src="../img/rss.gif" alt="rss"></a></p>
          </div>
        </aside> <!-- /span3 -->
      </div> <!-- /row -->
      <footer>
        <p>©<script type="text/javascript">$y=2012;$ny=new Date().getFullYear();document.write($ny>$y?$y+'-'+$ny:$y);</script> <a href="https://twitter.com/dekokun">dekokun</a></p>
      </footer>
    </div> <!-- /container -->

    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script>window.jQuery || document.write('<script src="../js/libs/jquery-1.7.2.min.js"><\/script>')</script>
    <!-- /ツイートボタン -->
  <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>

    <script src="../js/libs/bootstrap/bootstrap.min.js"></script>

    <script src="../js/script.js"></script>
    <script>
      var _gaq=[['_setAccount','UA-XXXXX-X'],['_trackPageview']];
      (function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
      g.src=('https:'==location.protocol?'//ssl':'//www')+'.google-analytics.com/ga.js';
      s.parentNode.insertBefore(g,s)}(document,'script'));
    </script>
    <!-- Code syntax highlight -->
    <script type="text/javascript" src="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.js"></script>
    <script type="text/javascript">
    $(function(){ 
        $('pre').css({
            'overflow-x': 'scroll',
            'background-color': '#f6f6f6',
            'border': '1px dotted #ccc',
            'padding': '0.8em'
        });
        $('pre code').addClass('prettyprint');
        prettyPrint();
    });
    </script>
    <script type="text/javascript" src="https://d1xnn692s7u6t6.cloudfront.net/widget.js"></script>
    <script type="text/javascript">(function k(){window.$SendToKindle&&window.$SendToKindle.Widget?$SendToKindle.Widget.init({"content":"article"}):setTimeout(k,500);})();</script>
  </body>
</html>
]]></description>
    <pubDate>No date found.</pubDate>
    <guid>http://dekokun.github.io/posts/2012-07-22.html</guid>
</item>
<item>
    <title>ブログ移設しました！！！</title>
    <link>http://dekokun.github.io/posts/2012-07-23.html</link>
    <description><![CDATA[<!doctype html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7" lang="ja"> <![endif]-->
<!--[if IE 7]>    <html class="no-js lt-ie9 lt-ie8" lang="ja"> <![endif]-->
<!--[if IE 8]>    <html class="no-js lt-ie9" lang="ja"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="ja"> <!--<![endif]-->
  <head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# article: http://ogp.me/ns/article#">
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <title>ブログ移設しました！！！</title>
    <meta name="description" content>
    <meta name="author" content>

    <meta name="viewport" content="width=device-width">
    <meta property="fb:app_id" content="351187098330864">
    <meta property="og:type" content="article">
    <meta property="og:image" content="http://dekokun.github.com/img/dekokun.png">
    <meta property="og:title" content="ブログ移設しました！！！">
    <meta property="og:description" content="@dekokunの技術日記">
    <meta property="og:site_name" content="でこてっくろぐ">
    <meta name="twitter:widgets:csp" content="on">

    <link rel="stylesheet" href="../css/bootstrap.css">
    <link rel="stylesheet" href="../css/bootstrap-responsive.css">
    <link rel="stylesheet" href="../css/style.css">
    <style>
    body {
      padding-top: 60px;
      padding-bottom: 40px;
    }
    </style>
    <link href="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.css" type="text/css" rel="stylesheet">
    <script src="../js/libs/modernizr-2.5.3-respond-1.1.0.min.js"></script>
    <script>
      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

      ga('create', 'UA-39650556-1', 'auto');
      ga('send', 'pageview');
    </script>
  </head>
  <body>
  <!--[if lt IE 7]><p class=chromeframe>Your browser is <em>ancient!</em> <a href="http://browsehappy.com/">Upgrade to a different browser</a> or <a href="http://www.google.com/chromeframe/?redirect=true">install Google Chrome Frame</a> to experience this site.</p><![endif]-->
    <div id="fb-root"></div>
    <script>(function(d, s, id) {
      var js, fjs = d.getElementsByTagName(s)[0];
      if (d.getElementById(id)) return;
      js = d.createElement(s); js.id = id;
      js.src = "//connect.facebook.net/ja_JP/all.js#xfbml=1&appId=351187098330864";
      fjs.parentNode.insertBefore(js, fjs);
      }(document, 'script', 'facebook-jssdk'));
    </script>
    <header>
      <nav class="navbar navbar-fixed-top">
        <div class="navbar-inner">
          <div class="container">
            <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
            </a>
            <a class="brand" href="../index.html">でこてっくろぐ</a>
            <div class="nav-collapse">
              <ul class="nav">
                <li><a href="../index.html">ほーむ</a></li>
                <li><a href="../posts.html">あーかいぶ</a></li>
                <li><a href="../aboutme.html">あばうとみー</a></li>
              </ul>
            </div><!--/.nav-collapse -->
          </div>
        </div>
      </nav>
    </header>

    <div class="container">
      <div class="row">
        <article class="span9">
          <h1>ブログ移設しました！！！</h1>

<p>by <em><a href="https://twitter.com/dekokun">@dekokun</a></em> on <strong>2012/07/23</strong></p>

<p>Tagged as: <a href="../tags/日記改造.html">日記改造</a>.</p>

<p>ブログ移設だ！！ワッショイワッショイ！！</p>
<h2 id="ブログ説明と移設の経緯">ブログ説明と移設の経緯</h2>
<ul>
<li>このブログはGitHub PagesとHaskellのHakyllで作られております</li>
<li>勉強会などにも参加するようになった私は「よし、技術ブログを作ろう！！！」と思い立ったのでした</li>
<li>以前よりTumblrにブログを書いていたこともあり、新しい技術ブログもTumblrに開設したのでした</li>
<li>右記がそのブログ <a href="http://www.tumblr.com/blog/dekotech">机上日記</a></li>
<li>会社で技術ブログを作ったことを嬉々として報告していると、隣の方から、「技術者ならGitHubか自前サーバでやれ」「Tumblrは印象がよくない」「どうせなら『すげー』とか思われるようなことしようよ」とご指摘が</li>
<li>２つ目のご指摘についてはよくわからないですが、3つ目のご指摘については至極最もに思えましたので、では前から気になっていたGitHub Pagesで作りましょうねと相成ったのでした</li>
<li>さて、GitHub Pages、調べたところ、Ruby製のjekyllなるツールを使えば比較的簡単に使えるそうだ</li>
<li>実際ローカルで使ってみて問題なさそうだったため、以下のようなツイートをしたのであった</li>
</ul>
<blockquote>
<p>Github Pagesでブログを書くためjekyllを導入した。 <a href="https://twitter.com/dekokun/status/227379652736475137">@dekokun</a></p>
</blockquote>
<ul>
<li>するとこのような返信が…</li>
</ul>
<blockquote>
<p>@dekokun hakyllもあるよ！ <a href="https://twitter.com/dekosuke/status/227379999064330242">@dekosuke</a></p>
</blockquote>
<ul>
<li>なるほどHaskell製のjekyllのようなものらしい</li>
<li>イバラの道としか思えねど、せっかく最近Haskellを学んでいるということもあり、Hakyllを使ってみることにしたのでした</li>
<li>めでたしめでたし</li>
</ul>
<h2 id="今後">今後</h2>
<ul>
<li>現在、スタイルシートを全く適用しておらず、また、1枚のHTMLに全てをぶち込むことしかできていないので、今後うまくやっていきたいなと思いました</li>
<li>と思ったら頑張ったらできた</li>
<li>HaskellもよくわからんのにHakyllのソースコードとか読む必要が出てくるのだろうな…(遠い目</li>
</ul>
<h2 id="課題">課題</h2>
<ul>
<li>h2タグのidが日本語になってるな。。これはいかんでしょ。。Markdownで書いているんだけども、Markdownの変換エンジンによるものだよね。いきなりHaskellコードを読まなくてはならないのかな…</li>
<li>現在、引用の部分が非常にわかりづらいのでわかりやすくなるようなスタイルを適用したい</li>
<li>その他、全面的にスタイルを変更したい</li>
<li>google code prettyでも使ってコードのシンタックスハイライトを実現しましょう</li>
<li>シンタックスハイライトはgist貼り付けによって実現したほうがいいかもしれない</li>
<li>このブログの題名「ブログ移設しました！」だけども、まだ移設出来る段階ではないと思われるので、並行稼動してこっちは「どう変えていったか」を綴っていくとしようと思います</li>
<li>RSS機能追加(隣の方から「RSSがないブログなんて読んでくれないよ！」とのご指摘！ご最も！！)</li>
</ul>

<div id="disqus_thread"></div>
<script type="text/javascript">
    /* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */
    var disqus_shortname = 'dekokun'; // required: replace example with your forum shortname

    /* * * DON'T EDIT BELOW THIS LINE * * */
    (function() {
        var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
        dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js';
        (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
    })();
</script>
<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
<a href="http://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a>

          <ul class="social">
            <li class="kindle"><div class="kindleWidget"><img style="vertical-align:middle;" src="https://d1xnn692s7u6t6.cloudfront.net/white-15.png" /><span style="vertical-align:middle;margin-left:3px;">Send to Kindle</span></div></li>
            <li class="facebook"><div class="fb-like" data-send="false" data-layout="button_count" data-width="100" data-show-faces="true" data-font="arial"></div></li>
            <li class="twitter"><a href="https://twitter.com/share" class="twitter-share-button" data-via="dekokun" data-lang="ja">ツイート</a></li>
            <li class="hatena-bookmark"><a href="http://b.hatena.ne.jp/entry/" class="hatena-bookmark-button" data-hatena-bookmark-layout="standard" title="このエントリーをはてなブックマークに追加"><img src="http://b.st-hatena.com/images/entry-button/button-only.gif" alt="このエントリーをはてなブックマークに追加" width="20" height="20" style="border: none;"></a><script type="text/javascript" src="http://b.st-hatena.com/js/bookmark_button.js" charset="utf-8" async="async"></script></li>
            <li><a data-pocket-label="pocket" data-pocket-count="horizontal" class="pocket-btn" data-lang="en"></a>
            <script type="text/javascript">!function(d,i){if(!d.getElementById(i)){var j=d.createElement("script");j.id=i;j.src="https://widgets.getpocket.com/v1/j/btn.js?v=1";var w=d.getElementById(i);d.body.appendChild(j);}}(document,"pocket-btn-js");</script></li>
          </ul>

        </article>
        <aside class="span3">
          <div class="sidebar-module">
            <div class="title">プロフィール</div>
            <p class="id"><a href="https://twitter.com/dekokun">dekokun</a></p>
            <p><a href="https://twitter.com/dekokun"><img src="../img/dekokun.png" alt="dekokun"></a></p>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.io/";
              Hatena.BookmarkWidget.title = "人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 200;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.com/";
              Hatena.BookmarkWidget.title = "旧人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 0;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module visible-desktop">
            <div class="title">twitter</div>
            <a class="twitter-timeline" data-dnt="true" href="https://twitter.com/dekokun" data-widget-id="306408547573440513">@dekokun からのツイート</a>
            <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
          </div>
          <div class="sidebar-module hidden-phone">
            <div class="title">RSS</div>
            <p><a href="../rss.xml"><img src="../img/rss.gif" alt="rss"></a></p>
          </div>
        </aside> <!-- /span3 -->
      </div> <!-- /row -->
      <footer>
        <p>©<script type="text/javascript">$y=2012;$ny=new Date().getFullYear();document.write($ny>$y?$y+'-'+$ny:$y);</script> <a href="https://twitter.com/dekokun">dekokun</a></p>
      </footer>
    </div> <!-- /container -->

    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script>window.jQuery || document.write('<script src="../js/libs/jquery-1.7.2.min.js"><\/script>')</script>
    <!-- /ツイートボタン -->
  <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>

    <script src="../js/libs/bootstrap/bootstrap.min.js"></script>

    <script src="../js/script.js"></script>
    <script>
      var _gaq=[['_setAccount','UA-XXXXX-X'],['_trackPageview']];
      (function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
      g.src=('https:'==location.protocol?'//ssl':'//www')+'.google-analytics.com/ga.js';
      s.parentNode.insertBefore(g,s)}(document,'script'));
    </script>
    <!-- Code syntax highlight -->
    <script type="text/javascript" src="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.js"></script>
    <script type="text/javascript">
    $(function(){ 
        $('pre').css({
            'overflow-x': 'scroll',
            'background-color': '#f6f6f6',
            'border': '1px dotted #ccc',
            'padding': '0.8em'
        });
        $('pre code').addClass('prettyprint');
        prettyPrint();
    });
    </script>
    <script type="text/javascript" src="https://d1xnn692s7u6t6.cloudfront.net/widget.js"></script>
    <script type="text/javascript">(function k(){window.$SendToKindle&&window.$SendToKindle.Widget?$SendToKindle.Widget.init({"content":"article"}):setTimeout(k,500);})();</script>
  </body>
</html>
]]></description>
    <pubDate>No date found.</pubDate>
    <guid>http://dekokun.github.io/posts/2012-07-23.html</guid>
</item>
<item>
    <title>シェルスクリプトでクロージャ(的な何か)</title>
    <link>http://dekokun.github.io/posts/2012-07-24.html</link>
    <description><![CDATA[<!doctype html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7" lang="ja"> <![endif]-->
<!--[if IE 7]>    <html class="no-js lt-ie9 lt-ie8" lang="ja"> <![endif]-->
<!--[if IE 8]>    <html class="no-js lt-ie9" lang="ja"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="ja"> <!--<![endif]-->
  <head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# article: http://ogp.me/ns/article#">
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <title>シェルスクリプトでクロージャ(的な何か)</title>
    <meta name="description" content>
    <meta name="author" content>

    <meta name="viewport" content="width=device-width">
    <meta property="fb:app_id" content="351187098330864">
    <meta property="og:type" content="article">
    <meta property="og:image" content="http://dekokun.github.com/img/dekokun.png">
    <meta property="og:title" content="シェルスクリプトでクロージャ(的な何か)">
    <meta property="og:description" content="@dekokunの技術日記">
    <meta property="og:site_name" content="でこてっくろぐ">
    <meta name="twitter:widgets:csp" content="on">

    <link rel="stylesheet" href="../css/bootstrap.css">
    <link rel="stylesheet" href="../css/bootstrap-responsive.css">
    <link rel="stylesheet" href="../css/style.css">
    <style>
    body {
      padding-top: 60px;
      padding-bottom: 40px;
    }
    </style>
    <link href="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.css" type="text/css" rel="stylesheet">
    <script src="../js/libs/modernizr-2.5.3-respond-1.1.0.min.js"></script>
    <script>
      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

      ga('create', 'UA-39650556-1', 'auto');
      ga('send', 'pageview');
    </script>
  </head>
  <body>
  <!--[if lt IE 7]><p class=chromeframe>Your browser is <em>ancient!</em> <a href="http://browsehappy.com/">Upgrade to a different browser</a> or <a href="http://www.google.com/chromeframe/?redirect=true">install Google Chrome Frame</a> to experience this site.</p><![endif]-->
    <div id="fb-root"></div>
    <script>(function(d, s, id) {
      var js, fjs = d.getElementsByTagName(s)[0];
      if (d.getElementById(id)) return;
      js = d.createElement(s); js.id = id;
      js.src = "//connect.facebook.net/ja_JP/all.js#xfbml=1&appId=351187098330864";
      fjs.parentNode.insertBefore(js, fjs);
      }(document, 'script', 'facebook-jssdk'));
    </script>
    <header>
      <nav class="navbar navbar-fixed-top">
        <div class="navbar-inner">
          <div class="container">
            <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
            </a>
            <a class="brand" href="../index.html">でこてっくろぐ</a>
            <div class="nav-collapse">
              <ul class="nav">
                <li><a href="../index.html">ほーむ</a></li>
                <li><a href="../posts.html">あーかいぶ</a></li>
                <li><a href="../aboutme.html">あばうとみー</a></li>
              </ul>
            </div><!--/.nav-collapse -->
          </div>
        </div>
      </nav>
    </header>

    <div class="container">
      <div class="row">
        <article class="span9">
          <h1>シェルスクリプトでクロージャ(的な何か)</h1>

<p>by <em><a href="https://twitter.com/dekokun">@dekokun</a></em> on <strong>2012/07/24 10:43</strong></p>

<p>Tagged as: <a href="../tags/ShellScript.html">ShellScript</a>, <a href="../tags/Advent Calender.html">Advent Calender</a>.</p>

<h2 id="まえがき">まえがき</h2>
<p>どうも、社会人生活4年目にしてようやく技術ブログを書き始めました<a href="https://twitter.com/dekokun">@dekokun</a>です。</p>
<p>変態アドベントカレンダー in Summer(http://atnd.org/events/29918) 11日目となります。</p>
<p>前回は<a href="http://twitter.com/megascus">@megascusさん</a>の<a href="http://d.hatena.ne.jp/megascus/">大人数開発を支える技術</a>でした。</p>
<h2 id="やること">やること</h2>
<p>変態ってなんでしょうね。よくわかりませんが、最近やってて「変態的」と言われたシェルスクリプトに関するTipsを今日は書いていきます。</p>
<p>というわけで、シェルスクリプトでクロージャ(的な何か)を実装したいと思います。</p>
<p>クロージャとは何か、ざっくり言えば、関数に環境が紐付いているものですよね多分。</p>
<p>(ちなみに、クロージャの定義を「親関数の外に参照が渡される内部関数をクロージャと呼ぶ」とかにすると今回のものは全く以てクロージャではなくなります。ですので、このタイトルは「クロージャ(的な何か)」なのです)</p>
<h2 id="やろうと思った経緯">やろうと思った経緯</h2>
<p>最近、シェルスクリプトでちょっとしたプログラムを書くことが増えてきて、グローバル変数が漏洩しまくるシェルスクリプトに嫌気がさしたので内部状態を持つ関数をつくってみたのでした。</p>
<h2 id="実装動作">実装・動作</h2>
<p>早速、シェルスクリプトで作られたクロージャ(的な何か)の実装を見てみましょう</p>
<pre><code>#!/bin/zsh

func(){
  echo 1
  local pre_func_definition
  local pre_count
  local new_func_definition
  pre_func_definition=$(which func)
  pre_count=$(echo $pre_func_definition | awk 'NR==2, NR==2 {print $2}')
  new_count=$(expr $pre_count + 1)
  new_func_definition=$(echo $pre_func_definition | sed -e &quot;s/echo $pre_count/echo $new_count/&quot;)
  eval $new_func_definition
}

echo &quot;1回目&quot;
func
echo &quot;2回目&quot;
func
echo &quot;3回目&quot;
func
echo &quot;4回目&quot;
func
echo &quot;5回目&quot;
func</code></pre>
<p>こちらを実行した際、出力が何になるか分かるでしょうか？</p>
<p>正解は以下の通り</p>
<pre><code>$ ./test.sh
1回目
1
2回目
2
3回目
3
4回目
4
5回目
5</code></pre>
<p>関数が呼び出される度に値がインクリメントされているのがお分かりかと思います。</p>
<h2 id="説明">説明</h2>
<p>上記関数が呼び出された際に何を行なっているかというと、whichで自分自身の関数定義を文字列として取得し、それをsedで書き換えevalで評価することによって関数定義自体を書き換えて内部状態(?)をもたせています</p>
<p>では、細かく何を行なっているのか。関数定義をコメント付きでどうぞ。</p>
<pre><code>func(){
  # 以下の&quot;1&quot;の部分が関数が呼び出される毎に書き変わっていく
  echo 1

  # 関数内のみで使用する変数宣言
  local pre_func_definition
  local pre_count
  local new_count
  local new_func_definition

  # 自分自身(func関数)の定義取得
  pre_func_definition=$(which func)
  # 上記echo 1の&quot;1&quot;の部分を取得
  pre_count=$(echo $pre_func_definition | awk 'NR==2, NR==2 {print $2}')
  # 上記で得られた値に1を足している
  new_count=$(expr $pre_count + 1)
  # sedによって、関数定義の文字列中のechoで出力する値を上記で得られた数値で置き換える
  new_func_definition=$(echo $pre_func_definition | sed -e &quot;s/echo $pre_count/echo $new_count/&quot;)
  # 上記で書き換えられた関数定義の文字列をevalで評価し、新たな関数を定義する
  eval $new_func_definition
}</code></pre>
<p>うん、こんなことができるんです。</p>
<h2 id="問題点">問題点</h2>
<p>先ほど、「グローバル変数が漏洩しまくるシェルスクリプトに嫌気がさしたので内部状態を持つ関数をつくってみたのでした。」と書きましたが、グローバル変数が漏洩することよりこんなわけのわからないプログラムが記述されているほうが保守コスト圧倒的に上がるよね。</p>
<p>こんなん私が読まされたらキレるわ。</p>
<p>まぁそれはいいとして、上記クロージャ(的な何か)には現在、以下問題点を抱えております。</p>
<ul>
<li>bashでは動かない…orz</li>
</ul>
<p>shebangに“/bin/zsh”とあるところから「何か怪しいぞ」と思った人はご明察、bashで動かないのです。。</p>
<p>致命的です。。。。zshスクリプトなんて使わねぇよ！！！</p>
<p>なぜ動かないかといいますと、bashのwhichが関数の文字列をとってきてくれないからです。(他にも、bashだとevalが改行文字含んだ関数定義を解釈してくれないっぽいという問題もあるが、それはどうにでもなる)</p>
<p>誰か、bashで関数定義の文字列を取得するコマンドを知っていたら教えていただけたらと思います。是非！！！</p>
<h2 id="質問">質問</h2>
<p>ちなみに、教えて欲しいのですが、これまで、ずっと「クロージャ(的な何か)」で通してきましたが、実際、こういうのって一般的にクロージャっていうんですか…？？？</p>
<p>新たな関数を関数内で定義しているだけなので、「内部状態を持つ」とすら言えないのかもしれない…</p>
<p>ご意見募集中。</p>
<p>以上、11日目のアドベントカレンダーはこれにて終了。次回はもっと変態的なネタをもってこれたらなと思います。</p>
<h2 id="今後など">今後など</h2>
<p>現在、<a href="http://dekokun.github.com/">HaskellとGitHubPagesを使用したブログ</a>への移行遂行中なので、次回はそっちで書けたらなと (というか、アドベントカレンダーって期間が終わるまで何週もするんですね。やばい！もうネタ切れ！！もっと変態ネタ集めなきゃ！！)</p>
<h2 id="注">注</h2>
<p>この日記は以前書いた別のブログの日記を移設したものです(2012/08/05)</p>

<div id="disqus_thread"></div>
<script type="text/javascript">
    /* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */
    var disqus_shortname = 'dekokun'; // required: replace example with your forum shortname

    /* * * DON'T EDIT BELOW THIS LINE * * */
    (function() {
        var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
        dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js';
        (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
    })();
</script>
<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
<a href="http://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a>

          <ul class="social">
            <li class="kindle"><div class="kindleWidget"><img style="vertical-align:middle;" src="https://d1xnn692s7u6t6.cloudfront.net/white-15.png" /><span style="vertical-align:middle;margin-left:3px;">Send to Kindle</span></div></li>
            <li class="facebook"><div class="fb-like" data-send="false" data-layout="button_count" data-width="100" data-show-faces="true" data-font="arial"></div></li>
            <li class="twitter"><a href="https://twitter.com/share" class="twitter-share-button" data-via="dekokun" data-lang="ja">ツイート</a></li>
            <li class="hatena-bookmark"><a href="http://b.hatena.ne.jp/entry/" class="hatena-bookmark-button" data-hatena-bookmark-layout="standard" title="このエントリーをはてなブックマークに追加"><img src="http://b.st-hatena.com/images/entry-button/button-only.gif" alt="このエントリーをはてなブックマークに追加" width="20" height="20" style="border: none;"></a><script type="text/javascript" src="http://b.st-hatena.com/js/bookmark_button.js" charset="utf-8" async="async"></script></li>
            <li><a data-pocket-label="pocket" data-pocket-count="horizontal" class="pocket-btn" data-lang="en"></a>
            <script type="text/javascript">!function(d,i){if(!d.getElementById(i)){var j=d.createElement("script");j.id=i;j.src="https://widgets.getpocket.com/v1/j/btn.js?v=1";var w=d.getElementById(i);d.body.appendChild(j);}}(document,"pocket-btn-js");</script></li>
          </ul>

        </article>
        <aside class="span3">
          <div class="sidebar-module">
            <div class="title">プロフィール</div>
            <p class="id"><a href="https://twitter.com/dekokun">dekokun</a></p>
            <p><a href="https://twitter.com/dekokun"><img src="../img/dekokun.png" alt="dekokun"></a></p>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.io/";
              Hatena.BookmarkWidget.title = "人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 200;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.com/";
              Hatena.BookmarkWidget.title = "旧人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 0;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module visible-desktop">
            <div class="title">twitter</div>
            <a class="twitter-timeline" data-dnt="true" href="https://twitter.com/dekokun" data-widget-id="306408547573440513">@dekokun からのツイート</a>
            <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
          </div>
          <div class="sidebar-module hidden-phone">
            <div class="title">RSS</div>
            <p><a href="../rss.xml"><img src="../img/rss.gif" alt="rss"></a></p>
          </div>
        </aside> <!-- /span3 -->
      </div> <!-- /row -->
      <footer>
        <p>©<script type="text/javascript">$y=2012;$ny=new Date().getFullYear();document.write($ny>$y?$y+'-'+$ny:$y);</script> <a href="https://twitter.com/dekokun">dekokun</a></p>
      </footer>
    </div> <!-- /container -->

    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script>window.jQuery || document.write('<script src="../js/libs/jquery-1.7.2.min.js"><\/script>')</script>
    <!-- /ツイートボタン -->
  <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>

    <script src="../js/libs/bootstrap/bootstrap.min.js"></script>

    <script src="../js/script.js"></script>
    <script>
      var _gaq=[['_setAccount','UA-XXXXX-X'],['_trackPageview']];
      (function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
      g.src=('https:'==location.protocol?'//ssl':'//www')+'.google-analytics.com/ga.js';
      s.parentNode.insertBefore(g,s)}(document,'script'));
    </script>
    <!-- Code syntax highlight -->
    <script type="text/javascript" src="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.js"></script>
    <script type="text/javascript">
    $(function(){ 
        $('pre').css({
            'overflow-x': 'scroll',
            'background-color': '#f6f6f6',
            'border': '1px dotted #ccc',
            'padding': '0.8em'
        });
        $('pre code').addClass('prettyprint');
        prettyPrint();
    });
    </script>
    <script type="text/javascript" src="https://d1xnn692s7u6t6.cloudfront.net/widget.js"></script>
    <script type="text/javascript">(function k(){window.$SendToKindle&&window.$SendToKindle.Widget?$SendToKindle.Widget.init({"content":"article"}):setTimeout(k,500);})();</script>
  </body>
</html>
]]></description>
    <pubDate>No date found.</pubDate>
    <guid>http://dekokun.github.io/posts/2012-07-24.html</guid>
</item>
<item>
    <title>シンタックスハイライト追加</title>
    <link>http://dekokun.github.io/posts/2012-07-29-2.html</link>
    <description><![CDATA[<!doctype html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7" lang="ja"> <![endif]-->
<!--[if IE 7]>    <html class="no-js lt-ie9 lt-ie8" lang="ja"> <![endif]-->
<!--[if IE 8]>    <html class="no-js lt-ie9" lang="ja"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="ja"> <!--<![endif]-->
  <head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# article: http://ogp.me/ns/article#">
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <title>シンタックスハイライト追加</title>
    <meta name="description" content>
    <meta name="author" content>

    <meta name="viewport" content="width=device-width">
    <meta property="fb:app_id" content="351187098330864">
    <meta property="og:type" content="article">
    <meta property="og:image" content="http://dekokun.github.com/img/dekokun.png">
    <meta property="og:title" content="シンタックスハイライト追加">
    <meta property="og:description" content="@dekokunの技術日記">
    <meta property="og:site_name" content="でこてっくろぐ">
    <meta name="twitter:widgets:csp" content="on">

    <link rel="stylesheet" href="../css/bootstrap.css">
    <link rel="stylesheet" href="../css/bootstrap-responsive.css">
    <link rel="stylesheet" href="../css/style.css">
    <style>
    body {
      padding-top: 60px;
      padding-bottom: 40px;
    }
    </style>
    <link href="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.css" type="text/css" rel="stylesheet">
    <script src="../js/libs/modernizr-2.5.3-respond-1.1.0.min.js"></script>
    <script>
      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

      ga('create', 'UA-39650556-1', 'auto');
      ga('send', 'pageview');
    </script>
  </head>
  <body>
  <!--[if lt IE 7]><p class=chromeframe>Your browser is <em>ancient!</em> <a href="http://browsehappy.com/">Upgrade to a different browser</a> or <a href="http://www.google.com/chromeframe/?redirect=true">install Google Chrome Frame</a> to experience this site.</p><![endif]-->
    <div id="fb-root"></div>
    <script>(function(d, s, id) {
      var js, fjs = d.getElementsByTagName(s)[0];
      if (d.getElementById(id)) return;
      js = d.createElement(s); js.id = id;
      js.src = "//connect.facebook.net/ja_JP/all.js#xfbml=1&appId=351187098330864";
      fjs.parentNode.insertBefore(js, fjs);
      }(document, 'script', 'facebook-jssdk'));
    </script>
    <header>
      <nav class="navbar navbar-fixed-top">
        <div class="navbar-inner">
          <div class="container">
            <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
            </a>
            <a class="brand" href="../index.html">でこてっくろぐ</a>
            <div class="nav-collapse">
              <ul class="nav">
                <li><a href="../index.html">ほーむ</a></li>
                <li><a href="../posts.html">あーかいぶ</a></li>
                <li><a href="../aboutme.html">あばうとみー</a></li>
              </ul>
            </div><!--/.nav-collapse -->
          </div>
        </div>
      </nav>
    </header>

    <div class="container">
      <div class="row">
        <article class="span9">
          <h1>シンタックスハイライト追加</h1>

<p>by <em><a href="https://twitter.com/dekokun">@dekokun</a></em> on <strong>2012/07/29</strong></p>

<p>Tagged as: <a href="../tags/日記改造.html">日記改造</a>.</p>

<p>ブログを改築していく</p>
<h2 id="やりたいこと">やりたいこと</h2>
<ul>
<li>シンタックスハイライトがしたい</li>
<li>コードを貼り付けるとシンタックスハイライトができるようになりたいですね</li>
<li>gist貼り付けも行いたい</li>
</ul>
<h2 id="シンタックスハイライトその1入力したコードをハイライト">シンタックスハイライトその1(入力したコードをハイライト)</h2>
<ul>
<li>以下ページを参考にしてできました</li>
<li><a href="http://blog.sanojimaru.com/post/17991023585/tumblr-markdown-google-code-pretty-syntax">tumblr+markdown+google-code-prettyでsyntax highlightingする</a></li>
<li>pandocにおいては“```”でコード部分を囲むことでコードと認識される(preタグ、codeタグに囲まれる)</li>
</ul>
<pre><code>&lt;!-- Code syntax highlight --&gt;
&lt;link href=&quot;http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.css&quot; type=&quot;text/css&quot; rel=&quot;stylesheet&quot; /&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js&quot;&gt;&lt;/script&gt;
&lt;script type=&quot;text/javascript &quot; src=&quot;http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.js&quot;&gt;&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot;&gt;
$(function(){ 
    $('pre').css({
        'overflow-x': 'scroll',
        'background-color': '#f6f6f6',
        'border': '1px dotted #ccc',
        'padding': '0.8em'
    });
    $('pre code').addClass('prettyprint');
    prettyPrint();
});
&lt;/script&gt;</code></pre>
<h2 id="シンタックスハイライトその2gist埋め込み">シンタックスハイライトその2(gist埋め込み)</h2>
<ul>
<li>gistの右上の“embed”をクリックして出るスクリプトを埋め込めばOK</li>
<li>こんな感じ
<script src="https://gist.github.com/3099398.js?file=func.sh"></script>
</li>
</ul>
<h2 id="感想">感想</h2>
<p>意外と簡単にできました</p>

<div id="disqus_thread"></div>
<script type="text/javascript">
    /* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */
    var disqus_shortname = 'dekokun'; // required: replace example with your forum shortname

    /* * * DON'T EDIT BELOW THIS LINE * * */
    (function() {
        var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
        dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js';
        (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
    })();
</script>
<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
<a href="http://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a>

          <ul class="social">
            <li class="kindle"><div class="kindleWidget"><img style="vertical-align:middle;" src="https://d1xnn692s7u6t6.cloudfront.net/white-15.png" /><span style="vertical-align:middle;margin-left:3px;">Send to Kindle</span></div></li>
            <li class="facebook"><div class="fb-like" data-send="false" data-layout="button_count" data-width="100" data-show-faces="true" data-font="arial"></div></li>
            <li class="twitter"><a href="https://twitter.com/share" class="twitter-share-button" data-via="dekokun" data-lang="ja">ツイート</a></li>
            <li class="hatena-bookmark"><a href="http://b.hatena.ne.jp/entry/" class="hatena-bookmark-button" data-hatena-bookmark-layout="standard" title="このエントリーをはてなブックマークに追加"><img src="http://b.st-hatena.com/images/entry-button/button-only.gif" alt="このエントリーをはてなブックマークに追加" width="20" height="20" style="border: none;"></a><script type="text/javascript" src="http://b.st-hatena.com/js/bookmark_button.js" charset="utf-8" async="async"></script></li>
            <li><a data-pocket-label="pocket" data-pocket-count="horizontal" class="pocket-btn" data-lang="en"></a>
            <script type="text/javascript">!function(d,i){if(!d.getElementById(i)){var j=d.createElement("script");j.id=i;j.src="https://widgets.getpocket.com/v1/j/btn.js?v=1";var w=d.getElementById(i);d.body.appendChild(j);}}(document,"pocket-btn-js");</script></li>
          </ul>

        </article>
        <aside class="span3">
          <div class="sidebar-module">
            <div class="title">プロフィール</div>
            <p class="id"><a href="https://twitter.com/dekokun">dekokun</a></p>
            <p><a href="https://twitter.com/dekokun"><img src="../img/dekokun.png" alt="dekokun"></a></p>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.io/";
              Hatena.BookmarkWidget.title = "人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 200;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.com/";
              Hatena.BookmarkWidget.title = "旧人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 0;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module visible-desktop">
            <div class="title">twitter</div>
            <a class="twitter-timeline" data-dnt="true" href="https://twitter.com/dekokun" data-widget-id="306408547573440513">@dekokun からのツイート</a>
            <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
          </div>
          <div class="sidebar-module hidden-phone">
            <div class="title">RSS</div>
            <p><a href="../rss.xml"><img src="../img/rss.gif" alt="rss"></a></p>
          </div>
        </aside> <!-- /span3 -->
      </div> <!-- /row -->
      <footer>
        <p>©<script type="text/javascript">$y=2012;$ny=new Date().getFullYear();document.write($ny>$y?$y+'-'+$ny:$y);</script> <a href="https://twitter.com/dekokun">dekokun</a></p>
      </footer>
    </div> <!-- /container -->

    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script>window.jQuery || document.write('<script src="../js/libs/jquery-1.7.2.min.js"><\/script>')</script>
    <!-- /ツイートボタン -->
  <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>

    <script src="../js/libs/bootstrap/bootstrap.min.js"></script>

    <script src="../js/script.js"></script>
    <script>
      var _gaq=[['_setAccount','UA-XXXXX-X'],['_trackPageview']];
      (function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
      g.src=('https:'==location.protocol?'//ssl':'//www')+'.google-analytics.com/ga.js';
      s.parentNode.insertBefore(g,s)}(document,'script'));
    </script>
    <!-- Code syntax highlight -->
    <script type="text/javascript" src="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.js"></script>
    <script type="text/javascript">
    $(function(){ 
        $('pre').css({
            'overflow-x': 'scroll',
            'background-color': '#f6f6f6',
            'border': '1px dotted #ccc',
            'padding': '0.8em'
        });
        $('pre code').addClass('prettyprint');
        prettyPrint();
    });
    </script>
    <script type="text/javascript" src="https://d1xnn692s7u6t6.cloudfront.net/widget.js"></script>
    <script type="text/javascript">(function k(){window.$SendToKindle&&window.$SendToKindle.Widget?$SendToKindle.Widget.init({"content":"article"}):setTimeout(k,500);})();</script>
  </body>
</html>
]]></description>
    <pubDate>Sun, 29 Jul 2012 00:00:00 UT</pubDate>
    <guid>http://dekokun.github.io/posts/2012-07-29-2.html</guid>
</item>
<item>
    <title>Hakyllで作成したブログにRSS機能追加</title>
    <link>http://dekokun.github.io/posts/2012-07-29-3.html</link>
    <description><![CDATA[<!doctype html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7" lang="ja"> <![endif]-->
<!--[if IE 7]>    <html class="no-js lt-ie9 lt-ie8" lang="ja"> <![endif]-->
<!--[if IE 8]>    <html class="no-js lt-ie9" lang="ja"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="ja"> <!--<![endif]-->
  <head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# article: http://ogp.me/ns/article#">
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <title>Hakyllで作成したブログにRSS機能追加</title>
    <meta name="description" content>
    <meta name="author" content>

    <meta name="viewport" content="width=device-width">
    <meta property="fb:app_id" content="351187098330864">
    <meta property="og:type" content="article">
    <meta property="og:image" content="http://dekokun.github.com/img/dekokun.png">
    <meta property="og:title" content="Hakyllで作成したブログにRSS機能追加">
    <meta property="og:description" content="@dekokunの技術日記">
    <meta property="og:site_name" content="でこてっくろぐ">
    <meta name="twitter:widgets:csp" content="on">

    <link rel="stylesheet" href="../css/bootstrap.css">
    <link rel="stylesheet" href="../css/bootstrap-responsive.css">
    <link rel="stylesheet" href="../css/style.css">
    <style>
    body {
      padding-top: 60px;
      padding-bottom: 40px;
    }
    </style>
    <link href="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.css" type="text/css" rel="stylesheet">
    <script src="../js/libs/modernizr-2.5.3-respond-1.1.0.min.js"></script>
    <script>
      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

      ga('create', 'UA-39650556-1', 'auto');
      ga('send', 'pageview');
    </script>
  </head>
  <body>
  <!--[if lt IE 7]><p class=chromeframe>Your browser is <em>ancient!</em> <a href="http://browsehappy.com/">Upgrade to a different browser</a> or <a href="http://www.google.com/chromeframe/?redirect=true">install Google Chrome Frame</a> to experience this site.</p><![endif]-->
    <div id="fb-root"></div>
    <script>(function(d, s, id) {
      var js, fjs = d.getElementsByTagName(s)[0];
      if (d.getElementById(id)) return;
      js = d.createElement(s); js.id = id;
      js.src = "//connect.facebook.net/ja_JP/all.js#xfbml=1&appId=351187098330864";
      fjs.parentNode.insertBefore(js, fjs);
      }(document, 'script', 'facebook-jssdk'));
    </script>
    <header>
      <nav class="navbar navbar-fixed-top">
        <div class="navbar-inner">
          <div class="container">
            <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
            </a>
            <a class="brand" href="../index.html">でこてっくろぐ</a>
            <div class="nav-collapse">
              <ul class="nav">
                <li><a href="../index.html">ほーむ</a></li>
                <li><a href="../posts.html">あーかいぶ</a></li>
                <li><a href="../aboutme.html">あばうとみー</a></li>
              </ul>
            </div><!--/.nav-collapse -->
          </div>
        </div>
      </nav>
    </header>

    <div class="container">
      <div class="row">
        <article class="span9">
          <h1>Hakyllで作成したブログにRSS機能追加</h1>

<p>by <em><a href="https://twitter.com/dekokun">@dekokun</a></em> on <strong>2012/07/29</strong></p>

<p>Tagged as: <a href="../tags/日記改造.html">日記改造</a>.</p>

<p>ブログをどんどん改築していく</p>
<h2 id="やりたいこと">やりたいこと</h2>
<ul>
<li>RSS機能をつけたい</li>
</ul>
<h2 id="rss機能をつけてみよう">RSS機能をつけてみよう</h2>
<ul>
<li>以下ページを参考にしてできました</li>
<li><a href="http://hackage.haskell.org/packages/archive/hakyll/3.2.7.2/doc/html/Hakyll-Web-Feed.html">Hakyll.Web.Feed</a></li>
<li>現在、絶賛RSSフィード生成中 http://dekokun.github.com/rss.xml</li>
<li>RSS生成ができるようになるためのdiffは以下の通り</li>
</ul>
<script src="https://gist.github.com/3196214.js?file=hakyll.diff"></script>

<h2 id="感想">感想</h2>
<p>意外と簡単にできました。あとは、ブログのサイドバーに表示するようにしなくては</p>

<div id="disqus_thread"></div>
<script type="text/javascript">
    /* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */
    var disqus_shortname = 'dekokun'; // required: replace example with your forum shortname

    /* * * DON'T EDIT BELOW THIS LINE * * */
    (function() {
        var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
        dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js';
        (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
    })();
</script>
<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
<a href="http://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a>

          <ul class="social">
            <li class="kindle"><div class="kindleWidget"><img style="vertical-align:middle;" src="https://d1xnn692s7u6t6.cloudfront.net/white-15.png" /><span style="vertical-align:middle;margin-left:3px;">Send to Kindle</span></div></li>
            <li class="facebook"><div class="fb-like" data-send="false" data-layout="button_count" data-width="100" data-show-faces="true" data-font="arial"></div></li>
            <li class="twitter"><a href="https://twitter.com/share" class="twitter-share-button" data-via="dekokun" data-lang="ja">ツイート</a></li>
            <li class="hatena-bookmark"><a href="http://b.hatena.ne.jp/entry/" class="hatena-bookmark-button" data-hatena-bookmark-layout="standard" title="このエントリーをはてなブックマークに追加"><img src="http://b.st-hatena.com/images/entry-button/button-only.gif" alt="このエントリーをはてなブックマークに追加" width="20" height="20" style="border: none;"></a><script type="text/javascript" src="http://b.st-hatena.com/js/bookmark_button.js" charset="utf-8" async="async"></script></li>
            <li><a data-pocket-label="pocket" data-pocket-count="horizontal" class="pocket-btn" data-lang="en"></a>
            <script type="text/javascript">!function(d,i){if(!d.getElementById(i)){var j=d.createElement("script");j.id=i;j.src="https://widgets.getpocket.com/v1/j/btn.js?v=1";var w=d.getElementById(i);d.body.appendChild(j);}}(document,"pocket-btn-js");</script></li>
          </ul>

        </article>
        <aside class="span3">
          <div class="sidebar-module">
            <div class="title">プロフィール</div>
            <p class="id"><a href="https://twitter.com/dekokun">dekokun</a></p>
            <p><a href="https://twitter.com/dekokun"><img src="../img/dekokun.png" alt="dekokun"></a></p>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.io/";
              Hatena.BookmarkWidget.title = "人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 200;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.com/";
              Hatena.BookmarkWidget.title = "旧人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 0;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module visible-desktop">
            <div class="title">twitter</div>
            <a class="twitter-timeline" data-dnt="true" href="https://twitter.com/dekokun" data-widget-id="306408547573440513">@dekokun からのツイート</a>
            <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
          </div>
          <div class="sidebar-module hidden-phone">
            <div class="title">RSS</div>
            <p><a href="../rss.xml"><img src="../img/rss.gif" alt="rss"></a></p>
          </div>
        </aside> <!-- /span3 -->
      </div> <!-- /row -->
      <footer>
        <p>©<script type="text/javascript">$y=2012;$ny=new Date().getFullYear();document.write($ny>$y?$y+'-'+$ny:$y);</script> <a href="https://twitter.com/dekokun">dekokun</a></p>
      </footer>
    </div> <!-- /container -->

    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script>window.jQuery || document.write('<script src="../js/libs/jquery-1.7.2.min.js"><\/script>')</script>
    <!-- /ツイートボタン -->
  <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>

    <script src="../js/libs/bootstrap/bootstrap.min.js"></script>

    <script src="../js/script.js"></script>
    <script>
      var _gaq=[['_setAccount','UA-XXXXX-X'],['_trackPageview']];
      (function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
      g.src=('https:'==location.protocol?'//ssl':'//www')+'.google-analytics.com/ga.js';
      s.parentNode.insertBefore(g,s)}(document,'script'));
    </script>
    <!-- Code syntax highlight -->
    <script type="text/javascript" src="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.js"></script>
    <script type="text/javascript">
    $(function(){ 
        $('pre').css({
            'overflow-x': 'scroll',
            'background-color': '#f6f6f6',
            'border': '1px dotted #ccc',
            'padding': '0.8em'
        });
        $('pre code').addClass('prettyprint');
        prettyPrint();
    });
    </script>
    <script type="text/javascript" src="https://d1xnn692s7u6t6.cloudfront.net/widget.js"></script>
    <script type="text/javascript">(function k(){window.$SendToKindle&&window.$SendToKindle.Widget?$SendToKindle.Widget.init({"content":"article"}):setTimeout(k,500);})();</script>
  </body>
</html>
]]></description>
    <pubDate>Sun, 29 Jul 2012 00:00:00 UT</pubDate>
    <guid>http://dekokun.github.io/posts/2012-07-29-3.html</guid>
</item>
<item>
    <title>GitHub Pagesでのビルド失敗</title>
    <link>http://dekokun.github.io/posts/2012-07-29-4.html</link>
    <description><![CDATA[<!doctype html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7" lang="ja"> <![endif]-->
<!--[if IE 7]>    <html class="no-js lt-ie9 lt-ie8" lang="ja"> <![endif]-->
<!--[if IE 8]>    <html class="no-js lt-ie9" lang="ja"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="ja"> <!--<![endif]-->
  <head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# article: http://ogp.me/ns/article#">
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <title>GitHub Pagesでのビルド失敗</title>
    <meta name="description" content>
    <meta name="author" content>

    <meta name="viewport" content="width=device-width">
    <meta property="fb:app_id" content="351187098330864">
    <meta property="og:type" content="article">
    <meta property="og:image" content="http://dekokun.github.com/img/dekokun.png">
    <meta property="og:title" content="GitHub Pagesでのビルド失敗">
    <meta property="og:description" content="@dekokunの技術日記">
    <meta property="og:site_name" content="でこてっくろぐ">
    <meta name="twitter:widgets:csp" content="on">

    <link rel="stylesheet" href="../css/bootstrap.css">
    <link rel="stylesheet" href="../css/bootstrap-responsive.css">
    <link rel="stylesheet" href="../css/style.css">
    <style>
    body {
      padding-top: 60px;
      padding-bottom: 40px;
    }
    </style>
    <link href="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.css" type="text/css" rel="stylesheet">
    <script src="../js/libs/modernizr-2.5.3-respond-1.1.0.min.js"></script>
    <script>
      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

      ga('create', 'UA-39650556-1', 'auto');
      ga('send', 'pageview');
    </script>
  </head>
  <body>
  <!--[if lt IE 7]><p class=chromeframe>Your browser is <em>ancient!</em> <a href="http://browsehappy.com/">Upgrade to a different browser</a> or <a href="http://www.google.com/chromeframe/?redirect=true">install Google Chrome Frame</a> to experience this site.</p><![endif]-->
    <div id="fb-root"></div>
    <script>(function(d, s, id) {
      var js, fjs = d.getElementsByTagName(s)[0];
      if (d.getElementById(id)) return;
      js = d.createElement(s); js.id = id;
      js.src = "//connect.facebook.net/ja_JP/all.js#xfbml=1&appId=351187098330864";
      fjs.parentNode.insertBefore(js, fjs);
      }(document, 'script', 'facebook-jssdk'));
    </script>
    <header>
      <nav class="navbar navbar-fixed-top">
        <div class="navbar-inner">
          <div class="container">
            <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
            </a>
            <a class="brand" href="../index.html">でこてっくろぐ</a>
            <div class="nav-collapse">
              <ul class="nav">
                <li><a href="../index.html">ほーむ</a></li>
                <li><a href="../posts.html">あーかいぶ</a></li>
                <li><a href="../aboutme.html">あばうとみー</a></li>
              </ul>
            </div><!--/.nav-collapse -->
          </div>
        </div>
      </nav>
    </header>

    <div class="container">
      <div class="row">
        <article class="span9">
          <h1>GitHub Pagesでのビルド失敗</h1>

<p>by <em><a href="https://twitter.com/dekokun">@dekokun</a></em> on <strong>2012/07/29 15:03</strong></p>

<p>Tagged as: <a href="../tags/日記改造.html">日記改造</a>, <a href="../tags/GitHub.html">GitHub</a>.</p>

<h2 id="現象">現象</h2>
<ul>
<li>以下ページを作成したら“[dekokun.github.com] Page build failure”なる通知が…</li>
<li><a href="http://dekokun.github.com/posts/2012-07-29-3.html">Hakyllで作成したブログにRSS機能追加</a></li>
<li>「Jekyllのビルドが失敗している」とかなんとか。詳細は以下。</li>
</ul>
<blockquote>
<blockquote>
<p>github said about 3 hours ago: The page build failed with the following error: Unable to run Jekyll. Please see https://help.github.com/articles/pages-don-t-build-unable-to-run-jekyll for help.</p>
</blockquote>
</blockquote>
<ul>
<li>Jekyllを走らせられなかったとのことなのだが、そもそもJekyllをビルドには使っていないのだが…(Markdownで書いたものをローカルでコンパイルし静的ファイルをコミットしてプッシュしている)</li>
</ul>
<h2 id="調査">調査</h2>
<ul>
<li>上記メッセージのリンク先を読んでも、思い当たるフシはない…</li>
<li>問題のあるコミットをリバートし、対象ファイルから1つ1つファイルを抜き出しコミットしてはプッシュしてを繰り返し、どの部分が悪いかを特定しました(リモートにプッシュしないとテストできないのが辛いところ…)</li>
<li>どうも、markdownの中に“+”で始まる行が3連続するとJekyllのビルドが失敗するらしい</li>
<li>今回は、diffをmarkdownの中に埋め込んでいたのでそこがひっかかっていた</li>
</ul>
<h2 id="対処">対処</h2>
<ul>
<li>コミットとプッシュしまくりにつかれたので、一旦diff部分をgistに記載しそこをブログに埋め込むことで対処した</li>
<li>もっと検証したいな…</li>
</ul>

<div id="disqus_thread"></div>
<script type="text/javascript">
    /* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */
    var disqus_shortname = 'dekokun'; // required: replace example with your forum shortname

    /* * * DON'T EDIT BELOW THIS LINE * * */
    (function() {
        var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
        dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js';
        (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
    })();
</script>
<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
<a href="http://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a>

          <ul class="social">
            <li class="kindle"><div class="kindleWidget"><img style="vertical-align:middle;" src="https://d1xnn692s7u6t6.cloudfront.net/white-15.png" /><span style="vertical-align:middle;margin-left:3px;">Send to Kindle</span></div></li>
            <li class="facebook"><div class="fb-like" data-send="false" data-layout="button_count" data-width="100" data-show-faces="true" data-font="arial"></div></li>
            <li class="twitter"><a href="https://twitter.com/share" class="twitter-share-button" data-via="dekokun" data-lang="ja">ツイート</a></li>
            <li class="hatena-bookmark"><a href="http://b.hatena.ne.jp/entry/" class="hatena-bookmark-button" data-hatena-bookmark-layout="standard" title="このエントリーをはてなブックマークに追加"><img src="http://b.st-hatena.com/images/entry-button/button-only.gif" alt="このエントリーをはてなブックマークに追加" width="20" height="20" style="border: none;"></a><script type="text/javascript" src="http://b.st-hatena.com/js/bookmark_button.js" charset="utf-8" async="async"></script></li>
            <li><a data-pocket-label="pocket" data-pocket-count="horizontal" class="pocket-btn" data-lang="en"></a>
            <script type="text/javascript">!function(d,i){if(!d.getElementById(i)){var j=d.createElement("script");j.id=i;j.src="https://widgets.getpocket.com/v1/j/btn.js?v=1";var w=d.getElementById(i);d.body.appendChild(j);}}(document,"pocket-btn-js");</script></li>
          </ul>

        </article>
        <aside class="span3">
          <div class="sidebar-module">
            <div class="title">プロフィール</div>
            <p class="id"><a href="https://twitter.com/dekokun">dekokun</a></p>
            <p><a href="https://twitter.com/dekokun"><img src="../img/dekokun.png" alt="dekokun"></a></p>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.io/";
              Hatena.BookmarkWidget.title = "人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 200;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.com/";
              Hatena.BookmarkWidget.title = "旧人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 0;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module visible-desktop">
            <div class="title">twitter</div>
            <a class="twitter-timeline" data-dnt="true" href="https://twitter.com/dekokun" data-widget-id="306408547573440513">@dekokun からのツイート</a>
            <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
          </div>
          <div class="sidebar-module hidden-phone">
            <div class="title">RSS</div>
            <p><a href="../rss.xml"><img src="../img/rss.gif" alt="rss"></a></p>
          </div>
        </aside> <!-- /span3 -->
      </div> <!-- /row -->
      <footer>
        <p>©<script type="text/javascript">$y=2012;$ny=new Date().getFullYear();document.write($ny>$y?$y+'-'+$ny:$y);</script> <a href="https://twitter.com/dekokun">dekokun</a></p>
      </footer>
    </div> <!-- /container -->

    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script>window.jQuery || document.write('<script src="../js/libs/jquery-1.7.2.min.js"><\/script>')</script>
    <!-- /ツイートボタン -->
  <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>

    <script src="../js/libs/bootstrap/bootstrap.min.js"></script>

    <script src="../js/script.js"></script>
    <script>
      var _gaq=[['_setAccount','UA-XXXXX-X'],['_trackPageview']];
      (function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
      g.src=('https:'==location.protocol?'//ssl':'//www')+'.google-analytics.com/ga.js';
      s.parentNode.insertBefore(g,s)}(document,'script'));
    </script>
    <!-- Code syntax highlight -->
    <script type="text/javascript" src="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.js"></script>
    <script type="text/javascript">
    $(function(){ 
        $('pre').css({
            'overflow-x': 'scroll',
            'background-color': '#f6f6f6',
            'border': '1px dotted #ccc',
            'padding': '0.8em'
        });
        $('pre code').addClass('prettyprint');
        prettyPrint();
    });
    </script>
    <script type="text/javascript" src="https://d1xnn692s7u6t6.cloudfront.net/widget.js"></script>
    <script type="text/javascript">(function k(){window.$SendToKindle&&window.$SendToKindle.Widget?$SendToKindle.Widget.init({"content":"article"}):setTimeout(k,500);})();</script>
  </body>
</html>
]]></description>
    <pubDate>Sun, 29 Jul 2012 00:00:00 UT</pubDate>
    <guid>http://dekokun.github.io/posts/2012-07-29-4.html</guid>
</item>
<item>
    <title>夏サミ感想(グリーを支えるソーシャルコーディングのすべてについて)</title>
    <link>http://dekokun.github.io/posts/2012-07-29.html</link>
    <description><![CDATA[<!doctype html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7" lang="ja"> <![endif]-->
<!--[if IE 7]>    <html class="no-js lt-ie9 lt-ie8" lang="ja"> <![endif]-->
<!--[if IE 8]>    <html class="no-js lt-ie9" lang="ja"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="ja"> <!--<![endif]-->
  <head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# article: http://ogp.me/ns/article#">
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <title>夏サミ感想(グリーを支えるソーシャルコーディングのすべてについて)</title>
    <meta name="description" content>
    <meta name="author" content>

    <meta name="viewport" content="width=device-width">
    <meta property="fb:app_id" content="351187098330864">
    <meta property="og:type" content="article">
    <meta property="og:image" content="http://dekokun.github.com/img/dekokun.png">
    <meta property="og:title" content="夏サミ感想(グリーを支えるソーシャルコーディングのすべてについて)">
    <meta property="og:description" content="@dekokunの技術日記">
    <meta property="og:site_name" content="でこてっくろぐ">
    <meta name="twitter:widgets:csp" content="on">

    <link rel="stylesheet" href="../css/bootstrap.css">
    <link rel="stylesheet" href="../css/bootstrap-responsive.css">
    <link rel="stylesheet" href="../css/style.css">
    <style>
    body {
      padding-top: 60px;
      padding-bottom: 40px;
    }
    </style>
    <link href="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.css" type="text/css" rel="stylesheet">
    <script src="../js/libs/modernizr-2.5.3-respond-1.1.0.min.js"></script>
    <script>
      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

      ga('create', 'UA-39650556-1', 'auto');
      ga('send', 'pageview');
    </script>
  </head>
  <body>
  <!--[if lt IE 7]><p class=chromeframe>Your browser is <em>ancient!</em> <a href="http://browsehappy.com/">Upgrade to a different browser</a> or <a href="http://www.google.com/chromeframe/?redirect=true">install Google Chrome Frame</a> to experience this site.</p><![endif]-->
    <div id="fb-root"></div>
    <script>(function(d, s, id) {
      var js, fjs = d.getElementsByTagName(s)[0];
      if (d.getElementById(id)) return;
      js = d.createElement(s); js.id = id;
      js.src = "//connect.facebook.net/ja_JP/all.js#xfbml=1&appId=351187098330864";
      fjs.parentNode.insertBefore(js, fjs);
      }(document, 'script', 'facebook-jssdk'));
    </script>
    <header>
      <nav class="navbar navbar-fixed-top">
        <div class="navbar-inner">
          <div class="container">
            <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
            </a>
            <a class="brand" href="../index.html">でこてっくろぐ</a>
            <div class="nav-collapse">
              <ul class="nav">
                <li><a href="../index.html">ほーむ</a></li>
                <li><a href="../posts.html">あーかいぶ</a></li>
                <li><a href="../aboutme.html">あばうとみー</a></li>
              </ul>
            </div><!--/.nav-collapse -->
          </div>
        </div>
      </nav>
    </header>

    <div class="container">
      <div class="row">
        <article class="span9">
          <h1>夏サミ感想(グリーを支えるソーシャルコーディングのすべてについて)</h1>

<p>by <em><a href="https://twitter.com/dekokun">@dekokun</a></em> on <strong>2012/07/29</strong></p>

<p>Tagged as: <a href="../tags/勉強会.html">勉強会</a>.</p>

<p>「ブログ環境が構築できてないから旧ブログで書こう」というのを繰り返していると新ブログ環境を構築していく気概が失われるのでこちらで書きましょう</p>
<h2 id="夏サミとは">夏サミとは</h2>
<ul>
<li>毎年行われているデブサミの夏バージョン。7/27(金)に開催</li>
<li>メインテーマは「エンタープライズでのソフトウェア開発技術の革新」だそうです</li>
<li>参考URL:<a href="http://codezine.jp/article/detail/6701">ソーシャルエンタープライズにフォーカスした「夏サミ2012」、本日開幕！</a></li>
</ul>
<h2 id="グリーを支えるソーシャルコーディングのすべてのまとめなど">「グリーを支えるソーシャルコーディングのすべて」のまとめなど</h2>
<ul>
<li>このセッションだけ参加しました</li>
<li>togetterまとめはこちら http://togetter.com/li/345680</li>
<li>講演してくださったのはグリー株式会社開発本部 CTO室 エンジニアの大場光一郎さん(<a href="https://twitter.com/koichiroo/">@koichiroo</a>)</li>
<li>大場さんは開発環境全般の改善などを行なっていらっしゃるそう</li>
<li>グリーがGitHubを導入していたのは一時期話題になっていたので知っており、GitHubを使用してpull requestのワークフローを行なっていることも小耳にはさんでいたため実際にどのようなワークフローを行なっているかを知りたくて参加した</li>
</ul>
<h3 id="内容まとめ">内容まとめ</h3>
<h4 id="グリーの課題">グリーの課題</h4>
<ul>
<li><p>急激な増員 現在、月に50人ほどずつ増加中</p></li>
<li><p>業種の増加 1口にエンジニアと言っても、細分化され(Web、ネイティブアプリ、ネットワークなど)業種が増えてきている</p></li>
<li><p>国際化 日本にも英語ネイティブが増えており、また、グリーは世界各国に計9拠点あり現地のエンジニアも増えてきている</p></li>
</ul>
<h4 id="周辺の動向">周辺の動向</h4>
<ul>
<li>SVNからGitへの移行真っ盛り Gitを更に便利にするため、GitHubが出てきている</li>
</ul>
<h4 id="githubの利点便利な点">GitHubの利点(便利な点)</h4>
<ul>
<li>Forkができる</li>
<li>pull requestができる(自分でバグを直せば開発元に変更を教えて上げることができる！)</li>
<li>Githubはソーシャルグラフを持っている(PJ中心ではなく人間が中心になった)</li>
<li>Git導入により分散repoによって複数人でのシステム開発がやりやすくなったが、GitだけではPJを越えて開発するための機能が足りない</li>
</ul>
<h4 id="グリーのバージョン管理の歴史">グリーのバージョン管理の歴史</h4>
<ul>
<li>2004~ SVN</li>
<li>2010~ Git</li>
<li>2012~ GitHub導入</li>
</ul>
<h4 id="github導入の目的">GitHub導入の目的</h4>
<ul>
<li>OSS開発でよいとされている手法を導入</li>
<li>PJ間のコラボレーション機能</li>
<li>埋もれているプログラムの発掘</li>
<li>国際化対応(どの国のエンジニアもGitHubは使用しているためアカウント情報だけ教えれば使ってくれる)</li>
</ul>
<h4 id="実際の効果">実際の効果</h4>
<ul>
<li>以前はgitsisを使用していたのだが、gitsis時代はリポジトリメンテナみたいな人がいて、申請が必要だったした。するとソースコード公開が面倒なので行わなくなる</li>
<li>GitHub導入によって、リポジトリはひとりいくつでも手軽に作成可能に</li>
<li>ログイン方法さえ教えておけば、外国の人もすぐ使える！！</li>
<li>誰が何を開発しているか可視化(あのPJの担当者は誰かとか)</li>
<li>手元で書き捨てるようなコードも共有可能に</li>
<li>作った人でなくても修正して使い続けられる</li>
<li>プログラム作成者が退職したりPJに興味がなくなりメンテされなくなっても、別の人によってメンテされる！！(更新されないプログラムは死ぬが、GitHubはソフトウェアの寿命を伸ばしてくれる)</li>
</ul>
<h4 id="ガイドライン">ガイドライン</h4>
<ul>
<li>Githubを使用したワークフローとガイドラインをしっかり作るのが課題。現在整備中</li>
<li>GitHubを企画、デザイナーにどう使っていってもらうか(PJ全体に使ってもらう方法)を模索している</li>
</ul>
<h4 id="githubエンタープライズについて">GitHubエンタープライズについて</h4>
<ul>
<li>ソースコードを社外に置くのは難しいという会社のためGitHubエンタープライズがある(社内にGitHubサーバを建てられる)</li>
<li>グリーでは、GitHubエンタープライズを使用(Social or security)(人数が増えれば、エンタープライズでもソーシャル性がある)</li>
<li>GitHubエンタープライズを使用する場合、使用ユーザが少ないとせっかくのGitHubのソーシャル性が犠牲になる</li>
<li>実感として、使っているユーザが100人くらいだとGitHubのもつソーシャル機能を活かすのは難しい(現在のグリーの人数ならば大丈夫)</li>
<li>サーバを自分たちで運用をする必要がある(そんなに手はかからないが、何度かダウンはしている)</li>
<li>動作が重くなる場合も(リポジトリ数が1000、ユーザ数が500くらいで仮想サーバを増強した)</li>
<li>GitHubのアップデートに追従するためのアップグレード機能がある</li>
<li>管理コンソール(SSHでメンテナンスできるような裏コマンドもある)</li>
<li>LDAP認証可能</li>
</ul>
<h4 id="質問など">質問など</h4>
<p>私の欲していた、GitHubを使用したワークフローに関して質問してみました</p>
<ul>
<li>Q. pull requestのワークフローを導入しているという話を聞いたが、実際どうか</li>
<li>A.チームによる。本流への反映をpull requestのみで行なっているチームもあり、バグ発生が目に見えて下がった</li>
<li>Q. pull requestのワークフローなど導入する場合、プロジェクトのメンテナがいて、メンテナがpull requestを反映するような形で行なっているのか</li>
<li>A. メンテナがいるわけではなく、チーム全員でレビューをし、その後pull requestをマージする。ブランチ作成などのワークフローについてはは自社で作成した<a href="http://labs.gree.jp/blog/2011/05/3528/">git daily</a>というツールを使って行なっている</li>
</ul>
<p>その他、他の方の質問など</p>
<ul>
<li>Q. デザイナやディレクタにGitを使用してもらうためにどのようなことを行なっているか</li>
<li>A. デザイナなどでアンテナの高い人を探し新GitHub派を作りその人達に教え、他のデザイナには新GitHub派の人から良さや使用法を伝えてもらう</li>
</ul>
<p>他にもいくつか質問はありましたがメモしていない…</p>
<p>以上です。</p>
<h3 id="感想">感想</h3>
<p>pull requestのワークフローなどについて、簡単にでも伺えたのでよかったです。また、運用についてなど、実際に導入してしかわからないことが聞けたのもよかったです。</p>
<p>pull requestのワークフローは自分で少し行なった限りでは非常に使えるものだと思っているので(GitHubのpull requestのUIはコミットとコメントが時系列順に並び、コードレビュー的な観点から非常に強力。「ここ直せ」「直してpushしました」「ナイス!」みたいなやり取りがしやすい)、私のほうでももう少し使って利点を発信していきたいです。</p>
<p>グリーのGitHubを使用したワークフローについてのブログ記事なども今後出てきて欲しいなど思いました。</p>
<p>誰が何を行なっているかの可視化もできるというのはある程度大規模な会社では有用だと思った</p>
<h2 id="その他夏サミに関係ない話">その他夏サミに関係ない話</h2>
<ul>
<li>このブログ、スタイルシートなどほとんど使用しておらず、真っ白なブログですね。ヘッダフッタナビゲーションもないし。</li>
<li><a href="http://kachibito.net/web-design/initializr-with-twitter-bootstrap.html">Initializr</a>使おうかな</li>
<li>このブログはHakyllを使用しており、HakyllはMarkdownをHTMLに変換するのにpandocを使用しているのだが、pandocの変換エンジンはネストしたリストを取り扱えないようだ。</li>
</ul>

<div id="disqus_thread"></div>
<script type="text/javascript">
    /* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */
    var disqus_shortname = 'dekokun'; // required: replace example with your forum shortname

    /* * * DON'T EDIT BELOW THIS LINE * * */
    (function() {
        var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
        dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js';
        (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
    })();
</script>
<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
<a href="http://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a>

          <ul class="social">
            <li class="kindle"><div class="kindleWidget"><img style="vertical-align:middle;" src="https://d1xnn692s7u6t6.cloudfront.net/white-15.png" /><span style="vertical-align:middle;margin-left:3px;">Send to Kindle</span></div></li>
            <li class="facebook"><div class="fb-like" data-send="false" data-layout="button_count" data-width="100" data-show-faces="true" data-font="arial"></div></li>
            <li class="twitter"><a href="https://twitter.com/share" class="twitter-share-button" data-via="dekokun" data-lang="ja">ツイート</a></li>
            <li class="hatena-bookmark"><a href="http://b.hatena.ne.jp/entry/" class="hatena-bookmark-button" data-hatena-bookmark-layout="standard" title="このエントリーをはてなブックマークに追加"><img src="http://b.st-hatena.com/images/entry-button/button-only.gif" alt="このエントリーをはてなブックマークに追加" width="20" height="20" style="border: none;"></a><script type="text/javascript" src="http://b.st-hatena.com/js/bookmark_button.js" charset="utf-8" async="async"></script></li>
            <li><a data-pocket-label="pocket" data-pocket-count="horizontal" class="pocket-btn" data-lang="en"></a>
            <script type="text/javascript">!function(d,i){if(!d.getElementById(i)){var j=d.createElement("script");j.id=i;j.src="https://widgets.getpocket.com/v1/j/btn.js?v=1";var w=d.getElementById(i);d.body.appendChild(j);}}(document,"pocket-btn-js");</script></li>
          </ul>

        </article>
        <aside class="span3">
          <div class="sidebar-module">
            <div class="title">プロフィール</div>
            <p class="id"><a href="https://twitter.com/dekokun">dekokun</a></p>
            <p><a href="https://twitter.com/dekokun"><img src="../img/dekokun.png" alt="dekokun"></a></p>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.io/";
              Hatena.BookmarkWidget.title = "人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 200;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.com/";
              Hatena.BookmarkWidget.title = "旧人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 0;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module visible-desktop">
            <div class="title">twitter</div>
            <a class="twitter-timeline" data-dnt="true" href="https://twitter.com/dekokun" data-widget-id="306408547573440513">@dekokun からのツイート</a>
            <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
          </div>
          <div class="sidebar-module hidden-phone">
            <div class="title">RSS</div>
            <p><a href="../rss.xml"><img src="../img/rss.gif" alt="rss"></a></p>
          </div>
        </aside> <!-- /span3 -->
      </div> <!-- /row -->
      <footer>
        <p>©<script type="text/javascript">$y=2012;$ny=new Date().getFullYear();document.write($ny>$y?$y+'-'+$ny:$y);</script> <a href="https://twitter.com/dekokun">dekokun</a></p>
      </footer>
    </div> <!-- /container -->

    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script>window.jQuery || document.write('<script src="../js/libs/jquery-1.7.2.min.js"><\/script>')</script>
    <!-- /ツイートボタン -->
  <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>

    <script src="../js/libs/bootstrap/bootstrap.min.js"></script>

    <script src="../js/script.js"></script>
    <script>
      var _gaq=[['_setAccount','UA-XXXXX-X'],['_trackPageview']];
      (function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
      g.src=('https:'==location.protocol?'//ssl':'//www')+'.google-analytics.com/ga.js';
      s.parentNode.insertBefore(g,s)}(document,'script'));
    </script>
    <!-- Code syntax highlight -->
    <script type="text/javascript" src="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.js"></script>
    <script type="text/javascript">
    $(function(){ 
        $('pre').css({
            'overflow-x': 'scroll',
            'background-color': '#f6f6f6',
            'border': '1px dotted #ccc',
            'padding': '0.8em'
        });
        $('pre code').addClass('prettyprint');
        prettyPrint();
    });
    </script>
    <script type="text/javascript" src="https://d1xnn692s7u6t6.cloudfront.net/widget.js"></script>
    <script type="text/javascript">(function k(){window.$SendToKindle&&window.$SendToKindle.Widget?$SendToKindle.Widget.init({"content":"article"}):setTimeout(k,500);})();</script>
  </body>
</html>
]]></description>
    <pubDate>No date found.</pubDate>
    <guid>http://dekokun.github.io/posts/2012-07-29.html</guid>
</item>
<item>
    <title>シェルスクリプトでMaybeモナド(その1)</title>
    <link>http://dekokun.github.io/posts/2012-08-05.html</link>
    <description><![CDATA[<!doctype html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7" lang="ja"> <![endif]-->
<!--[if IE 7]>    <html class="no-js lt-ie9 lt-ie8" lang="ja"> <![endif]-->
<!--[if IE 8]>    <html class="no-js lt-ie9" lang="ja"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="ja"> <!--<![endif]-->
  <head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# article: http://ogp.me/ns/article#">
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <title>シェルスクリプトでMaybeモナド(その1)</title>
    <meta name="description" content>
    <meta name="author" content>

    <meta name="viewport" content="width=device-width">
    <meta property="fb:app_id" content="351187098330864">
    <meta property="og:type" content="article">
    <meta property="og:image" content="http://dekokun.github.com/img/dekokun.png">
    <meta property="og:title" content="シェルスクリプトでMaybeモナド(その1)">
    <meta property="og:description" content="@dekokunの技術日記">
    <meta property="og:site_name" content="でこてっくろぐ">
    <meta name="twitter:widgets:csp" content="on">

    <link rel="stylesheet" href="../css/bootstrap.css">
    <link rel="stylesheet" href="../css/bootstrap-responsive.css">
    <link rel="stylesheet" href="../css/style.css">
    <style>
    body {
      padding-top: 60px;
      padding-bottom: 40px;
    }
    </style>
    <link href="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.css" type="text/css" rel="stylesheet">
    <script src="../js/libs/modernizr-2.5.3-respond-1.1.0.min.js"></script>
    <script>
      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

      ga('create', 'UA-39650556-1', 'auto');
      ga('send', 'pageview');
    </script>
  </head>
  <body>
  <!--[if lt IE 7]><p class=chromeframe>Your browser is <em>ancient!</em> <a href="http://browsehappy.com/">Upgrade to a different browser</a> or <a href="http://www.google.com/chromeframe/?redirect=true">install Google Chrome Frame</a> to experience this site.</p><![endif]-->
    <div id="fb-root"></div>
    <script>(function(d, s, id) {
      var js, fjs = d.getElementsByTagName(s)[0];
      if (d.getElementById(id)) return;
      js = d.createElement(s); js.id = id;
      js.src = "//connect.facebook.net/ja_JP/all.js#xfbml=1&appId=351187098330864";
      fjs.parentNode.insertBefore(js, fjs);
      }(document, 'script', 'facebook-jssdk'));
    </script>
    <header>
      <nav class="navbar navbar-fixed-top">
        <div class="navbar-inner">
          <div class="container">
            <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
            </a>
            <a class="brand" href="../index.html">でこてっくろぐ</a>
            <div class="nav-collapse">
              <ul class="nav">
                <li><a href="../index.html">ほーむ</a></li>
                <li><a href="../posts.html">あーかいぶ</a></li>
                <li><a href="../aboutme.html">あばうとみー</a></li>
              </ul>
            </div><!--/.nav-collapse -->
          </div>
        </div>
      </nav>
    </header>

    <div class="container">
      <div class="row">
        <article class="span9">
          <h1>シェルスクリプトでMaybeモナド(その1)</h1>

<p>by <em><a href="https://twitter.com/dekokun">@dekokun</a></em> on <strong>2012/08/05 13:46</strong></p>

<p>Tagged as: <a href="../tags/ShellScript.html">ShellScript</a>, <a href="../tags/Advent Calender.html">Advent Calender</a>.</p>

<h2 id="まえがき">まえがき</h2>
<p>どうも、<a href="http://dekotech.tumblr.com/">以前使ってたブログ</a>は開始1ヶ月たたないうちにこのブログに移設しました<a href="https://twitter.com/dekokun">@dekokun</a>です。</p>
<p><a href="http://atnd.org/events/29918">変態アドベントカレンダー in Summer</a> 22日目となります。</p>
<p>21日目は<a href="http://twitter.com/megascus">@megascusさん</a>の<a href="http://d.hatena.ne.jp/megascus/20120804/1344041860">“変態”を色々な文字集合で表したものをHexDampしてみる</a>でした。</p>
<h2 id="注意書き">注意書き</h2>
<p>ツッコミ歓迎(まだこのブログ、コメント欄がないですが…→コメント欄できました！！)</p>
<h2 id="やること">やること</h2>
<p>シェルスクリプトでモナド作成します。今回、中途半端なのですが、まぁ、このアドベントカレンダー、3周目も回ってくると思いますのでそこまでに完全版を提出できたらと。</p>
<h2 id="やろうと思った経緯">やろうと思った経緯</h2>
<p>せっかく、前回のアドベントカレンダーの記事をシェルスクリプトにしたわけだし(<a href="http://dekokun.github.com/posts/2012-07-24.html">シェルスクリプトでクロージャ(的な何か)</a>)、変態アドベントカレンダー発案者(?)のdaiksyさんはScalaを愛用している様子だったので、では関数型言語の人が好きそうなモナドをシェルスクリプトで作成してみようかしらと思いまして…</p>
あと、以前、以下のようなツイートをしていたのですが、
<blockquote class="twitter-tweet" lang="ja"><p>
「戻り値はMaybeだ」とか言っている横でシェルスクリプトの戻り値をreturnか標準出力にするかどうか考えてるのは非常にダメな感じある。
</p>
— でこくんさん (@dekokun) <a href="https://twitter.com/dekokun/status/220723064831361025" data-datetime="2012-07-05T03:37:34+00:00">7月 5, 2012</a>
</blockquote>
<script src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
そうしたら以下のような反応がありまして、
<blockquote class="twitter-tweet" lang="ja"><p>
シェルスクリプトって Maybe モナド使えますよね
</p>
— こば@v4(experimental)さん (@KOBA789) <a href="https://twitter.com/KOBA789/status/220723337750523904" data-datetime="2012-07-05T03:38:39+00:00">7月 5, 2012</a>
</blockquote>
<script src="//platform.twitter.com/widgets.js" charset="utf-8"></script>

<p>というわけで、作りたいなぁと思っていたというのもあります。</p>
<h2 id="maybeモナドとは">Maybeモナドとは</h2>
<p>現在、かの有名な<a href="http://www.amazon.co.jp/すごいHaskellたのしく学ぼう-Miran-Lipovača/dp/4274068854">すごいHaskellたのしく学ぼう!</a>でHaskellを学んでいるのですが、なんとまだモナドのところに達していません(現在アプリカティブファンクター)。 それにも関わらず、Maybeモナドを作ろうなどとひたすら恐れ多い感じではありますが、まぁいろんなところからまさかり飛んできたら楽しいなぁと思っているところです。</p>
<p>それはいいとして、Maybeモナドとは、失敗する可能性があることを表すMaybe型を返す関数の連鎖をうまくやってくれるように色々してくれるものです。 詳しくはこちらを見るといいのではないでしょうか。 http://www.sampou.org/haskell/a-a-monads/html/maybemonad.html</p>
<p>もうちょっと具体的には、失敗する可能性のある関数の連鎖において途中で関数が失敗したらその後の関数は実施せず、関数失敗の結果を返すような機構を提供するものという理解。</p>
<p>Haskellでの具体例は以下の通り(参考：<a href="http://d.hatena.ne.jp/shunsuk/20100917/1284728273">RubyでMabyeモナドを実装してみた。 - このブログは証明できない。</a>)</p>
<script src="https://gist.github.com/3261755.js?file=Maybe.hs"></script>

<p>途中で計算が失敗する場合は以下の通り</p>
<script src="https://gist.github.com/3261755.js?file=Maybe_fail.hs"></script>

<p>簡単に言うとすべての計算が成功したら“Just 計算結果”が返ってきて、途中の計算が一つでも失敗すれば“Nothing”が返って来るわけですね</p>
<h2 id="戦略">戦略</h2>
<p>シェルスクリプトには、既にMaybeモナドの&gt;&gt;=に似たようなものとしてパイプが存在します。しかし、パイプは、前の関数が失敗した際も次の関数を実施してくれてしまいますので、Maybeモナドの&gt;&gt;=とは異なりますよね。</p>
<p>というわけで、自作します。</p>
<p>また、そもそもシェルスクリプトでMaybe型をどう表すかという点ですが、シェルスクリプトにおいては返り値として0を返すか1を返すかでJustかNothingかを表し、標準出力の部分でJust hogeのhoge部分を得ることができます。そうすると、既存のコマンドをそのままMaybe型を返す関数として扱えるため極めて都合がよくその方向で考えていたのですが、ちょっと色々あって一旦「標準出力が文字列のNothingであればNothing値、他の値であれば、Just値」という方向でこの日記は進みます。ひどい戦略ですね。</p>
<p>Just “Nothing”という値が返せないですしね(両方とも文字列のNothingですので)…</p>
<p>まぁ、次回の変態アドベントカレンダーまでにちゃんとしたものを作りたいなと思いながら、今日はこのひどい戦略に沿っていきます。</p>
<h2 id="方針">方針</h2>
<p>こんな感じで使えるようなものを目指す</p>
<pre><code>ret monad.sh | bind &quot;ls&quot; | bind &quot;cat&quot;</code></pre>
<p>この場合、monad.shが存在すればそのファイルのcatまで行なってくれますが、存在しなければNothingが標準出力に出力されます。</p>
<p>Haskellのreturn, &gt;&gt;=がそれぞれret, パイプ+bindとなっております。bindされる関数が文字列で渡されるのが非常に辛い感じありますが、まぁシェルスクリプトだとしょうがないよね…</p>
<h3 id="nothingを標準出力で表現することにした理由">Nothingを標準出力で表現することにした理由</h3>
<p>上記でパイプを使うようにしたおかげで、次の関数で前の関数の返り値(returnで返って来る値)が取得できなくなり、しかたなく標準出力が文字列NothingかどうかでJustかNothingを判定することにしたのでした…誰か、パイプの前の返り値を取得する方法しりませんか…</p>
<p><code>ls hoge | echo $?</code>(hogeは存在しないファイル)は1ではなく0が出力されてしまうのです…<code>ls hoge; echo $?</code>と同様に1が出力されるとよかったのですが…</p>
<h2 id="実装">実装</h2>
<p>前回の<a href="http://dekokun.github.com/posts/2012-07-24.html">シェルスクリプトでクロージャ(的な何か)</a>とは異なり、ちゃんとbashで動きます。</p>
<script src="https://gist.github.com/3261755.js?file=monad.sh"></script>

<h2 id="テスト">テスト</h2>
<p>まずはMaybe型を返す(というか標準出力に出力する)関数を自作する必要があります。</p>
<script src="https://gist.github.com/3261755.js?file=maybe_func.sh"></script>

<h3 id="実際に使ってみる">実際に使ってみる</h3>
<pre><code>ret &quot;hoge&quot; | bind &quot;maybe_add_line hogehoge&quot; | bind &quot;maybe_cat&quot;
# -&gt; hogehoge
ret &quot;fuga:存在しない&quot; | bind &quot;maybe_ls&quot; | bind &quot;maybe_cat&quot;
# -&gt; Nothing</code></pre>
<p>ちゃんと動いているように見えますね</p>
<h3 id="モナド則のテスト">モナド則のテスト</h3>
<p>モナドには満たすべき法則があるようで、モナドを作る際はちゃんとそれを満たしてあげましょう。</p>
<p>Haskellでモナド則を表すとこんな感じらしい</p>
<script src="https://gist.github.com/3261755.js?file=monad_law.hs"></script>

<p>今回のシェルスクリプト版ではこうなるんですかね。 標準出力を返り値とみなしているため、標準出力を比較する形となります、</p>
<script src="https://gist.github.com/3261755.js?file=monad_law.sh"></script>

<h4 id="モナド則1つ目">モナド則1つ目</h4>
<script src="https://gist.github.com/3261755.js?file=monad_law1.sh"></script>

<h4 id="モナド則2つ目">モナド則2つ目</h4>
<script src="https://gist.github.com/3261755.js?file=monad_law2.sh"></script>

<h4 id="モナド則3つ目">モナド則3つ目</h4>
<script src="https://gist.github.com/3261755.js?file=monad_law3.sh"></script>

<p>ご存知のように、Linuxにおいて0は正常ステータスを表しますので、この例においては無事全てのモナド則が満たされていることが分かるかと思います。</p>
<h2 id="感想">感想</h2>
<p>本当にこれで正しいのかどうか全くわからんが、まぁそれっぽいのができたので比較的満足している。 よく見ると、標準出力を出力する関数は全てMaybe型を返す関数となっているのですね。なんかおかしくないかこれ…よくわからん…</p>
<h2 id="次回への課題">次回への課題</h2>
<p>上のほうにも書いていますが、終了ステータスが0で標準出力がhogeの場合にJust hoge, 0以外の場合をNothingとなるようにJust,Nothingを定義することにより、Linuxが提供している全てのコマンド/関数が自動的にMaybe型を返す関数になり非常に便利ですので、今度はそういうMaybeモナドを作成したいです。 誰か、パイプでつないだ前の関数の終了ステータスを得る方法を教えて下さい…もしくは、And演算子(&amp;&amp;)でつないだ前の関数の標準出力を得る方法でもいいです…</p>
<h2 id="あとで気付いたこと">あとで気付いたこと</h2>
<p>これ、わざわざこんなもん作らずとも&amp;&amp;で繋いで最後の標準出力と最後の終了ステータス見るだけでよかったんじゃねってなってるところ</p>
<p>シェルスクリプトにははじめからMaybeモナドが実装されてたんや！！！！！！</p>
<h2 id="更にあとで気付いたこと">更にあとで気付いたこと</h2>
<p>違う違う、&amp;&amp;では前の標準出力を使用できないからダメなんだよ！！！自分でそうやって書いてるじゃないか！！</p>
<blockquote>
<p>誰か、パイプでつないだ前の関数の終了ステータスを得る方法を教えて下さい…もしくは、And演算子(&amp;&amp;)でつないだ前の関数の標準出力を得る方法でもいいです…</p>
</blockquote>

<div id="disqus_thread"></div>
<script type="text/javascript">
    /* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */
    var disqus_shortname = 'dekokun'; // required: replace example with your forum shortname

    /* * * DON'T EDIT BELOW THIS LINE * * */
    (function() {
        var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
        dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js';
        (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
    })();
</script>
<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
<a href="http://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a>

          <ul class="social">
            <li class="kindle"><div class="kindleWidget"><img style="vertical-align:middle;" src="https://d1xnn692s7u6t6.cloudfront.net/white-15.png" /><span style="vertical-align:middle;margin-left:3px;">Send to Kindle</span></div></li>
            <li class="facebook"><div class="fb-like" data-send="false" data-layout="button_count" data-width="100" data-show-faces="true" data-font="arial"></div></li>
            <li class="twitter"><a href="https://twitter.com/share" class="twitter-share-button" data-via="dekokun" data-lang="ja">ツイート</a></li>
            <li class="hatena-bookmark"><a href="http://b.hatena.ne.jp/entry/" class="hatena-bookmark-button" data-hatena-bookmark-layout="standard" title="このエントリーをはてなブックマークに追加"><img src="http://b.st-hatena.com/images/entry-button/button-only.gif" alt="このエントリーをはてなブックマークに追加" width="20" height="20" style="border: none;"></a><script type="text/javascript" src="http://b.st-hatena.com/js/bookmark_button.js" charset="utf-8" async="async"></script></li>
            <li><a data-pocket-label="pocket" data-pocket-count="horizontal" class="pocket-btn" data-lang="en"></a>
            <script type="text/javascript">!function(d,i){if(!d.getElementById(i)){var j=d.createElement("script");j.id=i;j.src="https://widgets.getpocket.com/v1/j/btn.js?v=1";var w=d.getElementById(i);d.body.appendChild(j);}}(document,"pocket-btn-js");</script></li>
          </ul>

        </article>
        <aside class="span3">
          <div class="sidebar-module">
            <div class="title">プロフィール</div>
            <p class="id"><a href="https://twitter.com/dekokun">dekokun</a></p>
            <p><a href="https://twitter.com/dekokun"><img src="../img/dekokun.png" alt="dekokun"></a></p>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.io/";
              Hatena.BookmarkWidget.title = "人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 200;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.com/";
              Hatena.BookmarkWidget.title = "旧人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 0;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module visible-desktop">
            <div class="title">twitter</div>
            <a class="twitter-timeline" data-dnt="true" href="https://twitter.com/dekokun" data-widget-id="306408547573440513">@dekokun からのツイート</a>
            <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
          </div>
          <div class="sidebar-module hidden-phone">
            <div class="title">RSS</div>
            <p><a href="../rss.xml"><img src="../img/rss.gif" alt="rss"></a></p>
          </div>
        </aside> <!-- /span3 -->
      </div> <!-- /row -->
      <footer>
        <p>©<script type="text/javascript">$y=2012;$ny=new Date().getFullYear();document.write($ny>$y?$y+'-'+$ny:$y);</script> <a href="https://twitter.com/dekokun">dekokun</a></p>
      </footer>
    </div> <!-- /container -->

    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script>window.jQuery || document.write('<script src="../js/libs/jquery-1.7.2.min.js"><\/script>')</script>
    <!-- /ツイートボタン -->
  <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>

    <script src="../js/libs/bootstrap/bootstrap.min.js"></script>

    <script src="../js/script.js"></script>
    <script>
      var _gaq=[['_setAccount','UA-XXXXX-X'],['_trackPageview']];
      (function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
      g.src=('https:'==location.protocol?'//ssl':'//www')+'.google-analytics.com/ga.js';
      s.parentNode.insertBefore(g,s)}(document,'script'));
    </script>
    <!-- Code syntax highlight -->
    <script type="text/javascript" src="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.js"></script>
    <script type="text/javascript">
    $(function(){ 
        $('pre').css({
            'overflow-x': 'scroll',
            'background-color': '#f6f6f6',
            'border': '1px dotted #ccc',
            'padding': '0.8em'
        });
        $('pre code').addClass('prettyprint');
        prettyPrint();
    });
    </script>
    <script type="text/javascript" src="https://d1xnn692s7u6t6.cloudfront.net/widget.js"></script>
    <script type="text/javascript">(function k(){window.$SendToKindle&&window.$SendToKindle.Widget?$SendToKindle.Widget.init({"content":"article"}):setTimeout(k,500);})();</script>
  </body>
</html>
]]></description>
    <pubDate>No date found.</pubDate>
    <guid>http://dekokun.github.io/posts/2012-08-05.html</guid>
</item>
<item>
    <title>「HTML5 Conference」行ってきた 「次世代Web技術を切り開くゲーム開発者たち」メモ</title>
    <link>http://dekokun.github.io/posts/2012-09-08.html</link>
    <description><![CDATA[<!doctype html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7" lang="ja"> <![endif]-->
<!--[if IE 7]>    <html class="no-js lt-ie9 lt-ie8" lang="ja"> <![endif]-->
<!--[if IE 8]>    <html class="no-js lt-ie9" lang="ja"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="ja"> <!--<![endif]-->
  <head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# article: http://ogp.me/ns/article#">
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <title>「HTML5 Conference」行ってきた 「次世代Web技術を切り開くゲーム開発者たち」メモ</title>
    <meta name="description" content>
    <meta name="author" content>

    <meta name="viewport" content="width=device-width">
    <meta property="fb:app_id" content="351187098330864">
    <meta property="og:type" content="article">
    <meta property="og:image" content="http://dekokun.github.com/img/dekokun.png">
    <meta property="og:title" content="「HTML5 Conference」行ってきた 「次世代Web技術を切り開くゲーム開発者たち」メモ">
    <meta property="og:description" content="@dekokunの技術日記">
    <meta property="og:site_name" content="でこてっくろぐ">
    <meta name="twitter:widgets:csp" content="on">

    <link rel="stylesheet" href="../css/bootstrap.css">
    <link rel="stylesheet" href="../css/bootstrap-responsive.css">
    <link rel="stylesheet" href="../css/style.css">
    <style>
    body {
      padding-top: 60px;
      padding-bottom: 40px;
    }
    </style>
    <link href="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.css" type="text/css" rel="stylesheet">
    <script src="../js/libs/modernizr-2.5.3-respond-1.1.0.min.js"></script>
    <script>
      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

      ga('create', 'UA-39650556-1', 'auto');
      ga('send', 'pageview');
    </script>
  </head>
  <body>
  <!--[if lt IE 7]><p class=chromeframe>Your browser is <em>ancient!</em> <a href="http://browsehappy.com/">Upgrade to a different browser</a> or <a href="http://www.google.com/chromeframe/?redirect=true">install Google Chrome Frame</a> to experience this site.</p><![endif]-->
    <div id="fb-root"></div>
    <script>(function(d, s, id) {
      var js, fjs = d.getElementsByTagName(s)[0];
      if (d.getElementById(id)) return;
      js = d.createElement(s); js.id = id;
      js.src = "//connect.facebook.net/ja_JP/all.js#xfbml=1&appId=351187098330864";
      fjs.parentNode.insertBefore(js, fjs);
      }(document, 'script', 'facebook-jssdk'));
    </script>
    <header>
      <nav class="navbar navbar-fixed-top">
        <div class="navbar-inner">
          <div class="container">
            <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
            </a>
            <a class="brand" href="../index.html">でこてっくろぐ</a>
            <div class="nav-collapse">
              <ul class="nav">
                <li><a href="../index.html">ほーむ</a></li>
                <li><a href="../posts.html">あーかいぶ</a></li>
                <li><a href="../aboutme.html">あばうとみー</a></li>
              </ul>
            </div><!--/.nav-collapse -->
          </div>
        </div>
      </nav>
    </header>

    <div class="container">
      <div class="row">
        <article class="span9">
          <h1>「HTML5 Conference」行ってきた 「次世代Web技術を切り開くゲーム開発者たち」メモ</h1>

<p>by <em><a href="https://twitter.com/dekokun">@dekokun</a></em> on <strong>2012/09/08 16:45</strong></p>

<p>Tagged as: <a href="../tags/HTML5.html">HTML5</a>, <a href="../tags/勉強会.html">勉強会</a>.</p>

<h2 id="まえがき">まえがき</h2>
<p>前回、「シェルスクリプトでMaybeモナド」の前半部分の記事を起こし、次の変態アドベントカレンダーの順番が回ってきた際に後半部分を起こそうと思っていたのですが気付いたら変態アドベントカレンダー事態が終わっており、まだ原稿も作成しておらず、別の話題になりますなー。 本日慶応の日吉キャンパスで行われたHTML5 Conferenceに行って来まして、その中で「次世代Web技術を切り開くゲーム開発者たち」というのが面白かったのでここに概要というかメモを載せておきます。</p>
<h2 id="発表者">発表者</h2>
<ul>
<li>村岡 正和(バスタイムフィッシュ代表/HTML5-WEST.JP)</li>
<li>城戸 総史(株式会社ディー・エヌ・エー)</li>
<li>坂本 一樹(グリー株式会社)</li>
<li>清水 亮(株式会社ユビキタスエンターテインメント)</li>
</ul>
<p>UEIの清水さんの話を聞けたのが個人的には嬉しかったですね。</p>
<h2 id="html5でゲーム開発する場合に一番重視したこと">html5でゲーム開発する場合に一番重視したこと</h2>
<h3 id="木戸">木戸</h3>
<ul>
<li>如何に早くゲームが立ち上がり、如何にサクサク動くか</li>
<li>最初の頃はFlashを移植しようとしていた</li>
<li>CanvasとCSSアニメしかない場合、Flashでオーサリングしたデータをどう持っていくか</li>
</ul>
<h3 id="城戸">城戸</h3>
<ul>
<li>如何に古い端末の古い標準ブラウザに対応するか</li>
</ul>
<h3 id="清水">清水</h3>
<ul>
<li>PCと携帯で同じプログラムが動かない touchstartとmousemoveなど</li>
<li>キーボート向けのゲームなど移植できない</li>
<li>ゲームデザインの面でPCでもモバイルでも動かしても問題ないものを作るのが難しい</li>
<li>モバイルのパフォーマンスはそこまで問題ないが、このバージョンではCanvasよりDOM操作などのほうがいいなどあり、全然クロスプラットフォームではない</li>
</ul>
<h2 id="html5ならではのしんどかったことはない">HTML5ならではのしんどかったことはない</h2>
<h3 id="城戸-1">城戸</h3>
<ul>
<li>日々しんどい</li>
<li>アニメーションは世界中で問題になっている</li>
<li>これといったCanvas向けオーサリングツールがない</li>
<li>Adobe edgeなどはCSSアニメーションに頼っており、CSSアニメはアンドロイドでうまく動かない</li>
<li>ChromeとかAndroidとかの新しいブラウザなど出ると「今度はどのバグが出るか」</li>
<li>リリース後に新端末で動かしたら止まった…とか</li>
<li>同じOS、同じ端末だが片方の端末はclearectを呼ぶと止まる時があるなどあった…</li>
</ul>
<h3 id="坂本">坂本</h3>
<ul>
<li>Androidの特定のバージョンだとScaleが2回かかったなど(-1倍したい場合に虚数を使わなくては…)</li>
<li>Android固有の不具合を如何に潰すか</li>
<li>如何にユーザ様に新しいバージョンを使ってもらうか</li>
</ul>
<h3 id="清水-1">清水</h3>
<ul>
<li>webkitのナイトリービルドで回転と移動を同時にやると回転しないとか</li>
<li>WebGLの実装で変数があまり多いシェーダで動かすとマシンごと落ちる</li>
<li>「こっちのMacでは動いてもこっちのMacでは動かない」などのWebGLの問題が</li>
<li>Chromeがおかしくなった少しあとに、同じくwebkitを使っているSafariがおかしくなる</li>
<li>とにかくマイクロソフト</li>
<li>海外のイベントでマイクロソフトのエバンジェリストが発表すると席を立つ</li>
</ul>
<h2 id="html5やったことでどんなメリットがあった">HTML5やったことでどんなメリットがあった</h2>
<h3 id="城戸-2">城戸</h3>
<ul>
<li>最初からHTML5しか選択肢がなかった</li>
<li>クロスプラットフォームで動かすには昔はHTMLしかなかった</li>
<li>Webでしか提供できないもの</li>
<li>インストール不要(Twitterなどで拡散されたらすぐ使える)</li>
<li>アップデートが即座</li>
</ul>
<h3 id="坂本-1">坂本</h3>
<ul>
<li>iOSならコードのダウンロードはダメ</li>
<li>ダウンロードしてコードを実行する場合はHTML5を使う(UIWebViewみたいな感じ)</li>
<li>HTML5を選択することで開発コストを下がる場合があるので</li>
<li>Canvasのほうが全体的に早い</li>
<li>古いOSをサポートするならCSS</li>
</ul>
<h3 id="清水-2">清水</h3>
<ul>
<li>関数型プログラミングがJSで使えるのでよい</li>
<li>意識しないでカリー化、意識しないで高階関数。関数型の良さがわかった</li>
<li>書く量が非常に少なくて済む</li>
<li>iOS向けに5万行</li>
<li>JSだと700行(enchant.js)</li>
<li>9分でゲームを作るコンテストをしている(4回コンパイルしたら時間が終わってしまう)</li>
<li>HTML5は、JSとCanvasさえあればよい DOMもいらない</li>
<li>ソースが隠せないのもとてもよい</li>
<li>ソースを公開させる(GPL)などを強制する必要がなく強制させられる</li>
<li>HTML5上の成果は強制的に開示させられるため、人類全体によい</li>
</ul>
<h2 id="これからのゲーム製作で期待できる新しいhtml5仕様は">これからのゲーム製作で期待できる新しいHTML5仕様は？</h2>
<p>こうなってほしいなども含めて</p>
<h3 id="城戸-3">城戸</h3>
<ul>
<li>ローカルキャッシュ系の発展</li>
<li>ローカルストレージは非同期ではない</li>
<li>ローカルストレージは5MB</li>
<li>indexedDBなど非常に期待</li>
</ul>
<h3 id="坂本-2">坂本</h3>
<ul>
<li>ローカルキャッシュ系</li>
<li>WebGL系</li>
<li>Google Native Clientが来たらひっくり返るのでは</li>
</ul>
<h3 id="清水-3">清水</h3>
<ul>
<li>WebGL</li>
<li>WebGLはマシン語が書ける感じなので危険ではある</li>
<li>AppleのWebViewではWebGLは使える。safariでは使えない</li>
<li>現実的な問題があるので難しい</li>
<li>CSS3で中途半端で3Dが使えるのがよくない。アレのせいでMSがWebGLをいらないとか言っちゃう</li>
<li>CSS3とWebGLの中間の3Dを動かすものが欲しい</li>
<li>立体視</li>
<li>カメラ系API</li>
<li>音声系API</li>
<li>DRM関係のもの</li>
<li>DRMがないと作らせてもらえないものとかがある</li>
<li>仕様の中で作られていって、安心してできるようになるとネイティブのように使える</li>
</ul>
<h2 id="今まで専用機がプラットフォームだったゲーム業界と比べてどう変わる">今まで専用機がプラットフォームだったゲーム業界と比べてどう変わる？</h2>
<h3 id="城戸-4">城戸</h3>
<ul>
<li>スマートフォンを持っていれば大抵のものが遊べる</li>
<li>昔は、ゲームセンターにいかないとだめ、次は、ハードウェア、次は、ゲームボーイなどで持ち歩き、今は、みんな持っているスマートフォン上で動く</li>
<li>欧米ではハイリスク・ハイリターンのゲーム製作をしている(ゲーム一本でハリウッド映画並み)。もっと簡単につくれるHTML5などもあり新しい収益源になるのでは</li>
</ul>
<h3 id="坂本-3">坂本</h3>
<ul>
<li>今ではネットワークにつながっているのが当たりまえ</li>
<li>PS2はモデム持っている人と持ってない人で遊び方が違うが、今ではネットワークにつながっているの前提で企画が立てられる</li>
<li>ユーザに喜んでもらえるために、お金の払い方が変わってきている(フリーとぅ～プレミア？)</li>
<li>開発的な何かで作り方が大きく変わったかどうかについては、ネットワークにつながっているつながっていないくらいか</li>
</ul>
<h3 id="清水-4">清水</h3>
<ul>
<li>ゲーム業界はwebゲームというジャンルは西暦2000年に作っていたが存在感はそんなに大きくなかった</li>
<li>PSやXBOXなどを作っている人から見ると「そんなんあったの」的な</li>
<li>内部的なエンジンでHTML5を読めるエンジンが乗っている</li>
<li>あまりにもプログラミング観点、ゲームデザイン的な観点が違いすぎて参入しづらいのでは(HTML5 game conferenceというので出た、ゲームをそのままWebGLに移植したものが16GBメモリが必要だったなど)</li>
<li>ファミコンで出たゲームを携帯に移植したら儲かるのではと思って、ある程度儲かったが、「勝手が違うな」という印象。「新しいゲームボーイが出た」と思ったら、文化など全く違った</li>
<li>テクノロジーからしたら、そんなに大したことはいあんが、HTML5が主流になることによりゲーム体験という観点では全く変わってくる</li>
</ul>
<h2 id="既存のコンシューマゲームの市場はあるがソーシャルゲームの市場はコンシューマゲームの市場を越えるか">既存のコンシューマゲームの市場はあるが、ソーシャルゲームの市場はコンシューマゲームの市場を越えるか</h2>
<h3 id="城戸-5">城戸</h3>
<ul>
<li>異質なもの。映画とテレビのようなもの。共存可能。タイアップもできる</li>
<li>Webゲームの市場は伸びるし、ユーザが望む以上はトリプルゲーム市場も残るのでは。どっちも栄える</li>
</ul>
<h3 id="坂本-4">坂本</h3>
<ul>
<li>同じ意見</li>
<li>両方とも強くて戦い続けるのがいいのでは</li>
<li>ユーザが楽しむのであれば、どうでもいい</li>
</ul>
<h3 id="清水-5">清水</h3>
<ul>
<li>ソーシャルゲームについては本音で話せない</li>
<li>キャッシュマシンとしてのゲームは、ソーシャルゲームに遠くコンシューマゲームは及んでない</li>
<li>海外ではコンシューマゲームのほうが売れている</li>
<li>日本のゲームは海外にて強くない</li>
<li>全体としてパイがシュリンクしているのでは</li>
<li>日本のゲームはカルチャーの違いでそんなに海外では売れない</li>
<li>20億投下して30億回収する戦略より、1000万投下して10億回収できるかもしれないというほうがよいのでは。開発費が上がっているというのはあれど</li>
<li>日本の映画くらいにシュリンクしたら、困る</li>
</ul>
<h2 id="web製作と違うゲーム製作フローを教えて">Web製作と違うゲーム製作フローを教えて！</h2>
<ul>
<li>キノトロープさんのワークフローなど公開されている</li>
</ul>
<h3 id="城戸-6">城戸</h3>
<ul>
<li>ディレクター、サーバサイドエンジニア、フロントサイドエンジニア、UI専門家、ユーザエクスペリエンス専門家など、専門分野化している</li>
<li>お互い専門分野はあるが、一つのチームとしてどうなればよくなるかを考えゲームを育てる</li>
</ul>
<h3 id="坂本-5">坂本</h3>
<ul>
<li>キャラクターを動かすのは専用のアニメーターがオーサリングして作るもの</li>
<li>専用のオーサリングツールなど作り、ムダをなくす</li>
</ul>
<h3 id="清水-6">清水</h3>
<ul>
<li>最初にシナリオハンティングを行う</li>
<li>怪盗は燃えない</li>
<li>ファンタジーかなー</li>
<li>フランス(チューリッヒ)いこうぜ！</li>
<li>アビニョンには龍が住んでいるので、龍に会いに</li>
<li>崖の上の城を見つけて実際に行ってみる
<ul>
<li>ここにワイバーンが攻めてきたらどうなるかな</li>
</ul></li>
<li>みたいにイメージをふくらませる</li>
<li>その後企画書を作成し提出</li>
<li>イラストどうしよう</li>
<li>角川、講談社にイラストレーターを頼んだら「優秀なのは渡せない」</li>
<li>Pixiv
<ul>
<li>この子は毎日絵を描いているから暇に違いない</li>
<li>絵がどんどんバージョンアップしている</li>
<li>そんな感じで、2~30人プロとして集めた</li>
</ul></li>
<li>イテレーションも大事だがその前のイマジネーションの段階でどこまで膨らませるか</li>
<li>興味のない雑誌を読む</li>
<li>釣りのゲームがヒット</li>
<li>作るまで釣りをやったことはなかった</li>
<li>釣っても魚気持ち悪くて触れない</li>
<li>通りがかりのおっさんがハリを抜いてくれて一緒に釣った</li>
<li>それをそのままゲームにした
<ul>
<li>釣っている最中におっさんに絡まれる</li>
<li>無視しているとメールが来て、釣れたことが分かる</li>
</ul></li>
</ul>
<h2 id="web製作者がゲーム製作に参加するためのアドバイス">Web製作者がゲーム製作に参加するためのアドバイス</h2>
<h3 id="城戸-7">城戸</h3>
<ul>
<li>ゲームを作る手段、ツールが充実しているので作りたければ作れる</li>
<li>興味があれば参加してください！！</li>
<li>弊社も半分以上はWeb製作出身</li>
<li>特別なことは現場に入って学ぶもの</li>
<li>エンタメ好き、ゲームづくりが好きな人がいいのでは</li>
</ul>
<h3 id="坂本-6">坂本</h3>
<ul>
<li>Web製作とかゲーム製作とかくくりがわからないが、作りたければだれでもいいのでは、</li>
<li>すぐに応募して、実際に働いてみよう！飛び込もう！</li>
<li>楽しいことしかやってない</li>
</ul>
<h3 id="清水-7">清水</h3>
<h4 id="一緒に仕事をするかもしれない人という感じで考えると">一緒に仕事をするかもしれない人という感じで考えると</h4>
<ul>
<li>変わった人</li>
<li>カンボジア学科(5人くらいとか)</li>
<li>普通の人が知らない視点を持っている</li>
<li>普通の人が興味をもたない視点</li>
<li>知らないことと出会うのがエンターテイメント</li>
<li>清水が知っていることを知っている人はゲーマーにとってはいいのでは</li>
<li>僕でも楽しみを分かるように落としていこうよ というのがよい</li>
<li>「関係ないことをしているけど金にならない」くらいがいい</li>
<li>ゲームはそんなに好きじゃない くらいでもいいのでは</li>
</ul>

<div id="disqus_thread"></div>
<script type="text/javascript">
    /* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */
    var disqus_shortname = 'dekokun'; // required: replace example with your forum shortname

    /* * * DON'T EDIT BELOW THIS LINE * * */
    (function() {
        var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
        dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js';
        (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
    })();
</script>
<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
<a href="http://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a>

          <ul class="social">
            <li class="kindle"><div class="kindleWidget"><img style="vertical-align:middle;" src="https://d1xnn692s7u6t6.cloudfront.net/white-15.png" /><span style="vertical-align:middle;margin-left:3px;">Send to Kindle</span></div></li>
            <li class="facebook"><div class="fb-like" data-send="false" data-layout="button_count" data-width="100" data-show-faces="true" data-font="arial"></div></li>
            <li class="twitter"><a href="https://twitter.com/share" class="twitter-share-button" data-via="dekokun" data-lang="ja">ツイート</a></li>
            <li class="hatena-bookmark"><a href="http://b.hatena.ne.jp/entry/" class="hatena-bookmark-button" data-hatena-bookmark-layout="standard" title="このエントリーをはてなブックマークに追加"><img src="http://b.st-hatena.com/images/entry-button/button-only.gif" alt="このエントリーをはてなブックマークに追加" width="20" height="20" style="border: none;"></a><script type="text/javascript" src="http://b.st-hatena.com/js/bookmark_button.js" charset="utf-8" async="async"></script></li>
            <li><a data-pocket-label="pocket" data-pocket-count="horizontal" class="pocket-btn" data-lang="en"></a>
            <script type="text/javascript">!function(d,i){if(!d.getElementById(i)){var j=d.createElement("script");j.id=i;j.src="https://widgets.getpocket.com/v1/j/btn.js?v=1";var w=d.getElementById(i);d.body.appendChild(j);}}(document,"pocket-btn-js");</script></li>
          </ul>

        </article>
        <aside class="span3">
          <div class="sidebar-module">
            <div class="title">プロフィール</div>
            <p class="id"><a href="https://twitter.com/dekokun">dekokun</a></p>
            <p><a href="https://twitter.com/dekokun"><img src="../img/dekokun.png" alt="dekokun"></a></p>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.io/";
              Hatena.BookmarkWidget.title = "人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 200;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.com/";
              Hatena.BookmarkWidget.title = "旧人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 0;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module visible-desktop">
            <div class="title">twitter</div>
            <a class="twitter-timeline" data-dnt="true" href="https://twitter.com/dekokun" data-widget-id="306408547573440513">@dekokun からのツイート</a>
            <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
          </div>
          <div class="sidebar-module hidden-phone">
            <div class="title">RSS</div>
            <p><a href="../rss.xml"><img src="../img/rss.gif" alt="rss"></a></p>
          </div>
        </aside> <!-- /span3 -->
      </div> <!-- /row -->
      <footer>
        <p>©<script type="text/javascript">$y=2012;$ny=new Date().getFullYear();document.write($ny>$y?$y+'-'+$ny:$y);</script> <a href="https://twitter.com/dekokun">dekokun</a></p>
      </footer>
    </div> <!-- /container -->

    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script>window.jQuery || document.write('<script src="../js/libs/jquery-1.7.2.min.js"><\/script>')</script>
    <!-- /ツイートボタン -->
  <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>

    <script src="../js/libs/bootstrap/bootstrap.min.js"></script>

    <script src="../js/script.js"></script>
    <script>
      var _gaq=[['_setAccount','UA-XXXXX-X'],['_trackPageview']];
      (function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
      g.src=('https:'==location.protocol?'//ssl':'//www')+'.google-analytics.com/ga.js';
      s.parentNode.insertBefore(g,s)}(document,'script'));
    </script>
    <!-- Code syntax highlight -->
    <script type="text/javascript" src="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.js"></script>
    <script type="text/javascript">
    $(function(){ 
        $('pre').css({
            'overflow-x': 'scroll',
            'background-color': '#f6f6f6',
            'border': '1px dotted #ccc',
            'padding': '0.8em'
        });
        $('pre code').addClass('prettyprint');
        prettyPrint();
    });
    </script>
    <script type="text/javascript" src="https://d1xnn692s7u6t6.cloudfront.net/widget.js"></script>
    <script type="text/javascript">(function k(){window.$SendToKindle&&window.$SendToKindle.Widget?$SendToKindle.Widget.init({"content":"article"}):setTimeout(k,500);})();</script>
  </body>
</html>
]]></description>
    <pubDate>No date found.</pubDate>
    <guid>http://dekokun.github.io/posts/2012-09-08.html</guid>
</item>
<item>
    <title>PHP5.3にてタイプヒンティングでスカラー型が使える！？(勘違い編)</title>
    <link>http://dekokun.github.io/posts/2012-12-05.html</link>
    <description><![CDATA[<!doctype html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7" lang="ja"> <![endif]-->
<!--[if IE 7]>    <html class="no-js lt-ie9 lt-ie8" lang="ja"> <![endif]-->
<!--[if IE 8]>    <html class="no-js lt-ie9" lang="ja"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="ja"> <!--<![endif]-->
  <head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# article: http://ogp.me/ns/article#">
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <title>PHP5.3にてタイプヒンティングでスカラー型が使える！？(勘違い編)</title>
    <meta name="description" content>
    <meta name="author" content>

    <meta name="viewport" content="width=device-width">
    <meta property="fb:app_id" content="351187098330864">
    <meta property="og:type" content="article">
    <meta property="og:image" content="http://dekokun.github.com/img/dekokun.png">
    <meta property="og:title" content="PHP5.3にてタイプヒンティングでスカラー型が使える！？(勘違い編)">
    <meta property="og:description" content="@dekokunの技術日記">
    <meta property="og:site_name" content="でこてっくろぐ">
    <meta name="twitter:widgets:csp" content="on">

    <link rel="stylesheet" href="../css/bootstrap.css">
    <link rel="stylesheet" href="../css/bootstrap-responsive.css">
    <link rel="stylesheet" href="../css/style.css">
    <style>
    body {
      padding-top: 60px;
      padding-bottom: 40px;
    }
    </style>
    <link href="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.css" type="text/css" rel="stylesheet">
    <script src="../js/libs/modernizr-2.5.3-respond-1.1.0.min.js"></script>
    <script>
      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

      ga('create', 'UA-39650556-1', 'auto');
      ga('send', 'pageview');
    </script>
  </head>
  <body>
  <!--[if lt IE 7]><p class=chromeframe>Your browser is <em>ancient!</em> <a href="http://browsehappy.com/">Upgrade to a different browser</a> or <a href="http://www.google.com/chromeframe/?redirect=true">install Google Chrome Frame</a> to experience this site.</p><![endif]-->
    <div id="fb-root"></div>
    <script>(function(d, s, id) {
      var js, fjs = d.getElementsByTagName(s)[0];
      if (d.getElementById(id)) return;
      js = d.createElement(s); js.id = id;
      js.src = "//connect.facebook.net/ja_JP/all.js#xfbml=1&appId=351187098330864";
      fjs.parentNode.insertBefore(js, fjs);
      }(document, 'script', 'facebook-jssdk'));
    </script>
    <header>
      <nav class="navbar navbar-fixed-top">
        <div class="navbar-inner">
          <div class="container">
            <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
            </a>
            <a class="brand" href="../index.html">でこてっくろぐ</a>
            <div class="nav-collapse">
              <ul class="nav">
                <li><a href="../index.html">ほーむ</a></li>
                <li><a href="../posts.html">あーかいぶ</a></li>
                <li><a href="../aboutme.html">あばうとみー</a></li>
              </ul>
            </div><!--/.nav-collapse -->
          </div>
        </div>
      </nav>
    </header>

    <div class="container">
      <div class="row">
        <article class="span9">
          <h1>PHP5.3にてタイプヒンティングでスカラー型が使える！？(勘違い編)</h1>

<p>by <em><a href="https://twitter.com/dekokun">@dekokun</a></em> on <strong>2012/12/05 22:13</strong></p>

<p>Tagged as: <a href="../tags/PHP.html">PHP</a>.</p>

<h2 id="まえがき">まえがき</h2>
<p>どうも、最近PHPとHaskellを学んでおります。今日はPHPネタ。php5.3でスカラー型のタイプヒンティングが使えるという勘違いが発生したお話。</p>
<h2 id="発端">発端</h2>
<p>皆さんご存知の通り、PHP5.3までは、arrayもしくはオブジェクトの場合はタイプヒントが使用できるのですが、integerやstringなどのスカラー型に対してはタイプヒントは使えません。</p>
<ul>
<li>参考：<a href="http://php.net/manual/ja/language.oop5.typehinting.php">PHP: タイプヒンティング - Manual</a></li>
</ul>
<p>しかし、ある日、私はPHPでタイプヒンティングについてググっていたら、下記のようなサイトを発見したのでした</p>
<ul>
<li><a href="http://bbs.php.gr.jp/topic-282.html">日本PHPユーザ会 掲示板: PHP 5 » プリミティブな型でもタイプヒンティングが働きます</a></li>
</ul>
<p>そこに載っていたコードはこんなです。</p>
<pre><code>function myfunc(int $i) {}
myfunc('abc');

-&gt; PHP Catchable fatal error:  Argument 1 passed to myfunc() must be an instance of int, string given, called in - on line 5 and defined in - on line 4

Catchable fatal error: Argument 1 passed to myfunc() must be an instance of int, string given, called in - on line 5 and defined in - on line 4</code></pre>
<p>ふむふむ確かにエラーメッセージを見た限りではintかどうかを判別しているっぽい。実際に自分でもコードを動かし、同じエラーメッセージが出力されるのを見て、私は以下のように完全に勘違いしてしまいました。</p>
<blockquote class="twitter-tweet" lang="ja"><p>
おいPHPのタイプヒンティングってintやstringのような型では使えないんじゃなかったのか。マニュアルにそう書いてあるぞ。
</p>
— でこくんさん (@dekokun) <a href="https://twitter.com/dekokun/status/275800555224461314" data-datetime="2012-12-04T03:15:51+00:00">12月 4, 2012</a>
</blockquote>
<blockquote class="twitter-tweet" lang="ja"><p>
php -r ‘function myfunc(int $i) {}; myfunc(“abc”);’ -&gt; PHP Catchable fatal error:Argument 1 passed to myfunc() must be an instance of int
</p>
— でこくんさん (@dekokun) <a href="https://twitter.com/dekokun/status/275800590800523264" data-datetime="2012-12-04T03:15:59+00:00">12月 4, 2012</a>
</blockquote>
<script src="//platform.twitter.com/widgets.js" charset="utf-8"></script>

<p>すみません、若干マニュアルをdisってしまいました。。しかし比較的すぐに誤りに気付き、myfuncに実際にint型のものを渡して実験してみました</p>
<blockquote class="twitter-tweet" lang="ja"><p>
php -r ’function myfunc(int $i) {}; myfunc(1);’PHP Catchable fatal error:Argument 1 passed to myfunc() must be an instance of int,
</p>
— でこくんさん (@dekokun) <a href="https://twitter.com/dekokun/status/275800746795085824" data-datetime="2012-12-04T03:16:36+00:00">12月 4, 2012</a>
</blockquote>

<p>あれ、intでタイプヒントしているところにintの1を渡してもエラーになっているぞ！？</p>
<h2 id="解決編">解決編</h2>
<p>上記の正確なエラーメッセージはこんな感じ</p>
<blockquote>
<p>PHP Catchable fatal error: Argument 1 passed to myfunc() must be an instance of int, integer given, called in Command line code on line 1 and defined in Command line code on line 1 PHP Stack trace: PHP 1. {main}() Command line code:0 PHP 2. myfunc() Command line code:1</p>
</blockquote>
<p>ここが重要そうなメッセージ</p>
<blockquote>
<p>Argument 1 passed to myfunc() must be an instance of int, integer given</p>
</blockquote>
<p>このメッセージを見ると、「なるほどタイプヒントに使うべき型名はintじゃなくてintegerだったか」という感じがしますのでintegerに変えてもう一発</p>
<pre><code>function myfunc(integer $i){};
myfunc(1);</code></pre>
<blockquote>
<p>PHP Catchable fatal error: Argument 1 passed to myfunc() must be an instance of Integer, integer given, called in /Users/dekokun/test.php on line 13 and defined in /Users/dekokun/test.php on line 12 PHP Stack trace: PHP 1. {main}() /Users/dekokun/test.php:0 PHP 2. myfunc() /Users/dekokun/test.php:13</p>
</blockquote>
<p>あれ、駄目だ。エラーメッセージを読んでも、問題なさそう。だって、</p>
<blockquote>
<p>must be an instance of integer, integer given</p>
</blockquote>
<p>「integerである必要があって、integerが与えられた」って、全然エラーじゃないじゃないですか！！！</p>
<p>まぁ、聡明な皆さんはお気づきかと思いますが、上記エラーメッセージの最初にある<em>integer</em>はクラス名を表し、次の<em>integer</em>はスカラー型のintegerのことを表しているわけですな。わかりづらいですね。</p>
<p>上記エラーを回避するためには、Javaのようにラッパークラスを作ってあげなくては…</p>
<p>というわけで、全くやるきのないラッパークラスを作りました。なんの役にもたちませんね。最低限の礼儀として不変型にしておきました(intは値がコピーされますし不変型になってますよね？)ので許してください。</p>
<pre><code>class Integer
{
  private $i;
  function __construct($i)
  {
    $this-&gt;i = intval($i);
  }

    public function __get($key)
    {
        return $this-&gt;$key;
    }
}</code></pre>
<p>実際に使ってみた</p>
<pre><code>function myfunc(integer $i){};
myfunc(new Integer(1));</code></pre>
<p>エラーは出ませんでした。めでたしめでたし。(どうでもいいですが、クラス名って大文字小文字区別しないんですね。上記実験で初めて知りました。)</p>
<p>すべては私の勘違いだったのであった(PHPの出力するエラーがわかりづらいというのも間違いなくあると思うが)。</p>
<script src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
<blockquote class="twitter-tweet" lang="ja"><p>
勘違い恥ずかしい。
</p>
— でこくんさん (@dekokun) <a href="https://twitter.com/dekokun/status/275800801023238144" data-datetime="2012-12-04T03:16:49+00:00">12月 4, 2012</a>
</blockquote>
<script src="//platform.twitter.com/widgets.js" charset="utf-8"></script>

<h2 id="あとがき">あとがき</h2>
<p><s>PHP5.4ではintなどに対してもタイプヒントが使えますので</s>(2013/02/05 PHP5.4にタイプヒントが取り込まれるというのは間違い。参考：<a href="http://nikic.github.com/2012/03/06/Scalar-type-hinting-is-harder-than-you-think.html">Scalar type hinting is harder than you think</a> PHP5.5に乞うご期待！)スカラー型のタイプヒントを行いたい方々も多いと思いますが少々お待ち下さい。</p>
<p>ところで、関係ない話ですが、Rubyとか使ってる人たちは、タイプヒンティングがない世界でどのようにストラテジーパターンなどを実現しているのでしょうか。メソッドの存在を信じるしかないのでしょうか。</p>
<blockquote class="twitter-tweet" lang="ja"><p>
ダックタイピング全盛なRubyとかでメソッドを呼び出す時って、メソッドが存在することを信じて呼ぶんだっけ。まさか毎回メソッドを呼ぶ前にメソッドの存在確認をしてから呼ぶということはあるまい。PHPにはインターフェースとタイプヒンティングがあるが。
</p>
— でこくんさん (@dekokun) <a href="https://twitter.com/dekokun/status/275457959109218304" data-datetime="2012-12-03T04:34:29+00:00">12月 3, 2012</a>
</blockquote>
<script src="//platform.twitter.com/widgets.js" charset="utf-8"></script>

<blockquote class="twitter-tweet" data-in-reply-to="275457959109218304" lang="ja"><p>
@<a href="https://twitter.com/dekokun">dekokun</a> メソッドミッシングとかあるし、信じるしかないんじゃないんですかね。よくわかんないけど。
</p>
— あやぴー（２１）さん (@ayato_p) <a href="https://twitter.com/ayato_p/status/275458332981092352" data-datetime="2012-12-03T04:35:59+00:00">12月 3, 2012</a>
</blockquote>
<script src="//platform.twitter.com/widgets.js" charset="utf-8"></script>

<p>確かに言われてみればそうかも。</p>
<blockquote class="twitter-tweet" data-in-reply-to="275457959109218304" lang="ja"><p>
@<a href="https://twitter.com/dekokun">dekokun</a> railsのコード見ると、respond_to?よく見かける
</p>
— くろさん (@closer009) <a href="https://twitter.com/closer009/status/275472170719780865" data-datetime="2012-12-03T05:30:58+00:00">12月 3, 2012</a>
</blockquote>
<script src="//platform.twitter.com/widgets.js" charset="utf-8"></script>

<p>やはり必要なところではメソッドの存在を確認するのか…だるいな…</p>
<blockquote class="twitter-tweet" lang="ja"><p>
まぁ、タイプヒンティングがあろうが実行時エラーであることには変わらんが。
</p>
— でこくんさん (@dekokun) <a href="https://twitter.com/dekokun/status/275458594533687296" data-datetime="2012-12-03T04:37:01+00:00">12月 3, 2012</a>
</blockquote>
<script src="//platform.twitter.com/widgets.js" charset="utf-8"></script>

<p>以上、最近、静的型付けの言語にとりつかれ気味な私なのでした〜</p>

<div id="disqus_thread"></div>
<script type="text/javascript">
    /* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */
    var disqus_shortname = 'dekokun'; // required: replace example with your forum shortname

    /* * * DON'T EDIT BELOW THIS LINE * * */
    (function() {
        var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
        dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js';
        (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
    })();
</script>
<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
<a href="http://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a>

          <ul class="social">
            <li class="kindle"><div class="kindleWidget"><img style="vertical-align:middle;" src="https://d1xnn692s7u6t6.cloudfront.net/white-15.png" /><span style="vertical-align:middle;margin-left:3px;">Send to Kindle</span></div></li>
            <li class="facebook"><div class="fb-like" data-send="false" data-layout="button_count" data-width="100" data-show-faces="true" data-font="arial"></div></li>
            <li class="twitter"><a href="https://twitter.com/share" class="twitter-share-button" data-via="dekokun" data-lang="ja">ツイート</a></li>
            <li class="hatena-bookmark"><a href="http://b.hatena.ne.jp/entry/" class="hatena-bookmark-button" data-hatena-bookmark-layout="standard" title="このエントリーをはてなブックマークに追加"><img src="http://b.st-hatena.com/images/entry-button/button-only.gif" alt="このエントリーをはてなブックマークに追加" width="20" height="20" style="border: none;"></a><script type="text/javascript" src="http://b.st-hatena.com/js/bookmark_button.js" charset="utf-8" async="async"></script></li>
            <li><a data-pocket-label="pocket" data-pocket-count="horizontal" class="pocket-btn" data-lang="en"></a>
            <script type="text/javascript">!function(d,i){if(!d.getElementById(i)){var j=d.createElement("script");j.id=i;j.src="https://widgets.getpocket.com/v1/j/btn.js?v=1";var w=d.getElementById(i);d.body.appendChild(j);}}(document,"pocket-btn-js");</script></li>
          </ul>

        </article>
        <aside class="span3">
          <div class="sidebar-module">
            <div class="title">プロフィール</div>
            <p class="id"><a href="https://twitter.com/dekokun">dekokun</a></p>
            <p><a href="https://twitter.com/dekokun"><img src="../img/dekokun.png" alt="dekokun"></a></p>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.io/";
              Hatena.BookmarkWidget.title = "人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 200;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.com/";
              Hatena.BookmarkWidget.title = "旧人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 0;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module visible-desktop">
            <div class="title">twitter</div>
            <a class="twitter-timeline" data-dnt="true" href="https://twitter.com/dekokun" data-widget-id="306408547573440513">@dekokun からのツイート</a>
            <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
          </div>
          <div class="sidebar-module hidden-phone">
            <div class="title">RSS</div>
            <p><a href="../rss.xml"><img src="../img/rss.gif" alt="rss"></a></p>
          </div>
        </aside> <!-- /span3 -->
      </div> <!-- /row -->
      <footer>
        <p>©<script type="text/javascript">$y=2012;$ny=new Date().getFullYear();document.write($ny>$y?$y+'-'+$ny:$y);</script> <a href="https://twitter.com/dekokun">dekokun</a></p>
      </footer>
    </div> <!-- /container -->

    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script>window.jQuery || document.write('<script src="../js/libs/jquery-1.7.2.min.js"><\/script>')</script>
    <!-- /ツイートボタン -->
  <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>

    <script src="../js/libs/bootstrap/bootstrap.min.js"></script>

    <script src="../js/script.js"></script>
    <script>
      var _gaq=[['_setAccount','UA-XXXXX-X'],['_trackPageview']];
      (function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
      g.src=('https:'==location.protocol?'//ssl':'//www')+'.google-analytics.com/ga.js';
      s.parentNode.insertBefore(g,s)}(document,'script'));
    </script>
    <!-- Code syntax highlight -->
    <script type="text/javascript" src="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.js"></script>
    <script type="text/javascript">
    $(function(){ 
        $('pre').css({
            'overflow-x': 'scroll',
            'background-color': '#f6f6f6',
            'border': '1px dotted #ccc',
            'padding': '0.8em'
        });
        $('pre code').addClass('prettyprint');
        prettyPrint();
    });
    </script>
    <script type="text/javascript" src="https://d1xnn692s7u6t6.cloudfront.net/widget.js"></script>
    <script type="text/javascript">(function k(){window.$SendToKindle&&window.$SendToKindle.Widget?$SendToKindle.Widget.init({"content":"article"}):setTimeout(k,500);})();</script>
  </body>
</html>
]]></description>
    <pubDate>No date found.</pubDate>
    <guid>http://dekokun.github.io/posts/2012-12-05.html</guid>
</item>
<item>
    <title>DevLOVE Conference 2012 に参加した後、これからの私にとって最も大切なこと</title>
    <link>http://dekokun.github.io/posts/2012-12-16.html</link>
    <description><![CDATA[<!doctype html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7" lang="ja"> <![endif]-->
<!--[if IE 7]>    <html class="no-js lt-ie9 lt-ie8" lang="ja"> <![endif]-->
<!--[if IE 8]>    <html class="no-js lt-ie9" lang="ja"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="ja"> <!--<![endif]-->
  <head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# article: http://ogp.me/ns/article#">
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <title>DevLOVE Conference 2012 に参加した後、これからの私にとって最も大切なこと</title>
    <meta name="description" content>
    <meta name="author" content>

    <meta name="viewport" content="width=device-width">
    <meta property="fb:app_id" content="351187098330864">
    <meta property="og:type" content="article">
    <meta property="og:image" content="http://dekokun.github.com/img/dekokun.png">
    <meta property="og:title" content="DevLOVE Conference 2012 に参加した後、これからの私にとって最も大切なこと">
    <meta property="og:description" content="@dekokunの技術日記">
    <meta property="og:site_name" content="でこてっくろぐ">
    <meta name="twitter:widgets:csp" content="on">

    <link rel="stylesheet" href="../css/bootstrap.css">
    <link rel="stylesheet" href="../css/bootstrap-responsive.css">
    <link rel="stylesheet" href="../css/style.css">
    <style>
    body {
      padding-top: 60px;
      padding-bottom: 40px;
    }
    </style>
    <link href="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.css" type="text/css" rel="stylesheet">
    <script src="../js/libs/modernizr-2.5.3-respond-1.1.0.min.js"></script>
    <script>
      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

      ga('create', 'UA-39650556-1', 'auto');
      ga('send', 'pageview');
    </script>
  </head>
  <body>
  <!--[if lt IE 7]><p class=chromeframe>Your browser is <em>ancient!</em> <a href="http://browsehappy.com/">Upgrade to a different browser</a> or <a href="http://www.google.com/chromeframe/?redirect=true">install Google Chrome Frame</a> to experience this site.</p><![endif]-->
    <div id="fb-root"></div>
    <script>(function(d, s, id) {
      var js, fjs = d.getElementsByTagName(s)[0];
      if (d.getElementById(id)) return;
      js = d.createElement(s); js.id = id;
      js.src = "//connect.facebook.net/ja_JP/all.js#xfbml=1&appId=351187098330864";
      fjs.parentNode.insertBefore(js, fjs);
      }(document, 'script', 'facebook-jssdk'));
    </script>
    <header>
      <nav class="navbar navbar-fixed-top">
        <div class="navbar-inner">
          <div class="container">
            <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
            </a>
            <a class="brand" href="../index.html">でこてっくろぐ</a>
            <div class="nav-collapse">
              <ul class="nav">
                <li><a href="../index.html">ほーむ</a></li>
                <li><a href="../posts.html">あーかいぶ</a></li>
                <li><a href="../aboutme.html">あばうとみー</a></li>
              </ul>
            </div><!--/.nav-collapse -->
          </div>
        </div>
      </nav>
    </header>

    <div class="container">
      <div class="row">
        <article class="span9">
          <h1>DevLOVE Conference 2012 に参加した後、これからの私にとって最も大切なこと</h1>

<p>by <em><a href="https://twitter.com/dekokun">@dekokun</a></em> on <strong>2012/12/17 00:38</strong></p>

<p>Tagged as: <a href="../tags/勉強会.html">勉強会</a>.</p>

<h2 id="まえがき">まえがき</h2>
<p>開発(Develop)を愛する人たちの集まり、DevLOVEの100回目のイベント、<a href="http://devlove2012.devlove.org/">DevLOVE Conference 2012</a>に参加してきました。</p>
<p>いろいろ思うところありましたが、現在、明らかに体調が良くないので、一番大切だと思えることだけ。</p>
<h2 id="これからどうしていくか">これからどうしていくか</h2>
<p>「世界を変えるのは他の誰かではない、世界を変えるのは、自分自身だ」が今回のDevLOVE 2012のテーマであるわけですが、では、自分自身が世界を変えるには、まず自分が変わらなくてはならない。</p>
<p>そして、自分が変わるためには、これから、これまでとは違う何かをしていかなくてはならない</p>
<p>というわけで、これから何をするかだけ宣言して今日は寝ます。</p>
<p>具体的には、1日目の宮川さんのセッション、<a href="http://devlove2012.devlove.org/speaker#speaker_14">再び歩き出す物語</a>(資料はこちら→http://www.slideshare.net/WarlockReport/ss-15654184)にて、「DevLOVE 2012から現場に戻ったら、何をする？何をしたい？どうなりたい」を紙に書き隣の人と話し合ったのですが、そこで紙に書いて話したことをこのブログに書きます。内容は以下です。</p>
<ul>
<li>社内朝勉強会を行う
<ul>
<li>はじめに、「今日は○○をします」と宣言するだけで後は勝手にどうぞな勉強会</li>
<li>「社内の他の人が何をしているか、何に興味を持っているかが全くわからないので知りたい」「朝は効率が良いので早朝に作業をすることを自分に強いるため」という２つの目標を達成するためのもの</li>
<li>私の他に誰も参加者がいなくても目標の1つは達成できるが、もう1つの目標を達成するためにも他の人を動員する方法を考えねば</li>
</ul></li>
<li>リファクタリングをしまくる(今もしているけど。継続)
<ul>
<li>リファクタリングをしまくるには、自動テストがあることが前提となってくるため、テストの充実もあわせて行う</li>
</ul></li>
<li>ブログを書く(頻度とかを考えてなかった。。最低、月1回くらいでかな)</li>
<li>yesodでWebアプリを作って公開</li>
<li>DevLOVEカンファレンスに弊社の人間が4人来ていることをFacebookで流し、他の人にも「俺も勉強するかー」となってもらう(もらえたらいいなー)(すでに実施済み)</li>
</ul>
<p>以上、やっていきます。</p>
<h2 id="あとがき">あとがき</h2>
<blockquote class="twitter-tweet" lang="ja"><p>
和田さんとTDDBCでペアプロをしてから1年経ったわけだが、この1年、私はどう変わっただろうか。
</p>
— でこくんさん (@dekokun) <a href="https://twitter.com/dekokun/status/280223766699732992" data-datetime="2012-12-16T08:12:06+00:00">12月 16, 2012</a>
</blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>

<p>今思えば、ちょうど1年前にTDDBCのために会社休んで東京から九州まで行き、和田さんとペアプロをさせていただいたことが私の転機になっている気がします(このあたり、ちゃんと1年の振り返りをしなくては)。そして、このイベントによって更に私は変わります。また新しい1年が始まりますね。</p>
<h2 id="追伸">追伸</h2>
<p>和田さんのセッションで「SQLの閉包性」という言葉が出てきて、何かわからなかったためググったら以下のサイトがヒットした。</p>
<ul>
<li><a href="http://www.geocities.jp/mickindex/database/idx_database.html">リレーショナル・データベースの世界</a></li>
</ul>
<p>このサイト、とてもおもしろい。特に、「基礎理論」の部分が。まだ全部読んでないけど</p>

<div id="disqus_thread"></div>
<script type="text/javascript">
    /* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */
    var disqus_shortname = 'dekokun'; // required: replace example with your forum shortname

    /* * * DON'T EDIT BELOW THIS LINE * * */
    (function() {
        var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
        dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js';
        (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
    })();
</script>
<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
<a href="http://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a>

          <ul class="social">
            <li class="kindle"><div class="kindleWidget"><img style="vertical-align:middle;" src="https://d1xnn692s7u6t6.cloudfront.net/white-15.png" /><span style="vertical-align:middle;margin-left:3px;">Send to Kindle</span></div></li>
            <li class="facebook"><div class="fb-like" data-send="false" data-layout="button_count" data-width="100" data-show-faces="true" data-font="arial"></div></li>
            <li class="twitter"><a href="https://twitter.com/share" class="twitter-share-button" data-via="dekokun" data-lang="ja">ツイート</a></li>
            <li class="hatena-bookmark"><a href="http://b.hatena.ne.jp/entry/" class="hatena-bookmark-button" data-hatena-bookmark-layout="standard" title="このエントリーをはてなブックマークに追加"><img src="http://b.st-hatena.com/images/entry-button/button-only.gif" alt="このエントリーをはてなブックマークに追加" width="20" height="20" style="border: none;"></a><script type="text/javascript" src="http://b.st-hatena.com/js/bookmark_button.js" charset="utf-8" async="async"></script></li>
            <li><a data-pocket-label="pocket" data-pocket-count="horizontal" class="pocket-btn" data-lang="en"></a>
            <script type="text/javascript">!function(d,i){if(!d.getElementById(i)){var j=d.createElement("script");j.id=i;j.src="https://widgets.getpocket.com/v1/j/btn.js?v=1";var w=d.getElementById(i);d.body.appendChild(j);}}(document,"pocket-btn-js");</script></li>
          </ul>

        </article>
        <aside class="span3">
          <div class="sidebar-module">
            <div class="title">プロフィール</div>
            <p class="id"><a href="https://twitter.com/dekokun">dekokun</a></p>
            <p><a href="https://twitter.com/dekokun"><img src="../img/dekokun.png" alt="dekokun"></a></p>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.io/";
              Hatena.BookmarkWidget.title = "人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 200;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.com/";
              Hatena.BookmarkWidget.title = "旧人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 0;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module visible-desktop">
            <div class="title">twitter</div>
            <a class="twitter-timeline" data-dnt="true" href="https://twitter.com/dekokun" data-widget-id="306408547573440513">@dekokun からのツイート</a>
            <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
          </div>
          <div class="sidebar-module hidden-phone">
            <div class="title">RSS</div>
            <p><a href="../rss.xml"><img src="../img/rss.gif" alt="rss"></a></p>
          </div>
        </aside> <!-- /span3 -->
      </div> <!-- /row -->
      <footer>
        <p>©<script type="text/javascript">$y=2012;$ny=new Date().getFullYear();document.write($ny>$y?$y+'-'+$ny:$y);</script> <a href="https://twitter.com/dekokun">dekokun</a></p>
      </footer>
    </div> <!-- /container -->

    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script>window.jQuery || document.write('<script src="../js/libs/jquery-1.7.2.min.js"><\/script>')</script>
    <!-- /ツイートボタン -->
  <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>

    <script src="../js/libs/bootstrap/bootstrap.min.js"></script>

    <script src="../js/script.js"></script>
    <script>
      var _gaq=[['_setAccount','UA-XXXXX-X'],['_trackPageview']];
      (function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
      g.src=('https:'==location.protocol?'//ssl':'//www')+'.google-analytics.com/ga.js';
      s.parentNode.insertBefore(g,s)}(document,'script'));
    </script>
    <!-- Code syntax highlight -->
    <script type="text/javascript" src="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.js"></script>
    <script type="text/javascript">
    $(function(){ 
        $('pre').css({
            'overflow-x': 'scroll',
            'background-color': '#f6f6f6',
            'border': '1px dotted #ccc',
            'padding': '0.8em'
        });
        $('pre code').addClass('prettyprint');
        prettyPrint();
    });
    </script>
    <script type="text/javascript" src="https://d1xnn692s7u6t6.cloudfront.net/widget.js"></script>
    <script type="text/javascript">(function k(){window.$SendToKindle&&window.$SendToKindle.Widget?$SendToKindle.Widget.init({"content":"article"}):setTimeout(k,500);})();</script>
  </body>
</html>
]]></description>
    <pubDate>No date found.</pubDate>
    <guid>http://dekokun.github.io/posts/2012-12-16.html</guid>
</item>
<item>
    <title>PHPにおいてstaticメソッドの呼び出し元クラスを動的に変更</title>
    <link>http://dekokun.github.io/posts/2013-01-14.html</link>
    <description><![CDATA[<!doctype html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7" lang="ja"> <![endif]-->
<!--[if IE 7]>    <html class="no-js lt-ie9 lt-ie8" lang="ja"> <![endif]-->
<!--[if IE 8]>    <html class="no-js lt-ie9" lang="ja"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="ja"> <!--<![endif]-->
  <head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# article: http://ogp.me/ns/article#">
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <title>PHPにおいてstaticメソッドの呼び出し元クラスを動的に変更</title>
    <meta name="description" content>
    <meta name="author" content>

    <meta name="viewport" content="width=device-width">
    <meta property="fb:app_id" content="351187098330864">
    <meta property="og:type" content="article">
    <meta property="og:image" content="http://dekokun.github.com/img/dekokun.png">
    <meta property="og:title" content="PHPにおいてstaticメソッドの呼び出し元クラスを動的に変更">
    <meta property="og:description" content="@dekokunの技術日記">
    <meta property="og:site_name" content="でこてっくろぐ">
    <meta name="twitter:widgets:csp" content="on">

    <link rel="stylesheet" href="../css/bootstrap.css">
    <link rel="stylesheet" href="../css/bootstrap-responsive.css">
    <link rel="stylesheet" href="../css/style.css">
    <style>
    body {
      padding-top: 60px;
      padding-bottom: 40px;
    }
    </style>
    <link href="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.css" type="text/css" rel="stylesheet">
    <script src="../js/libs/modernizr-2.5.3-respond-1.1.0.min.js"></script>
    <script>
      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

      ga('create', 'UA-39650556-1', 'auto');
      ga('send', 'pageview');
    </script>
  </head>
  <body>
  <!--[if lt IE 7]><p class=chromeframe>Your browser is <em>ancient!</em> <a href="http://browsehappy.com/">Upgrade to a different browser</a> or <a href="http://www.google.com/chromeframe/?redirect=true">install Google Chrome Frame</a> to experience this site.</p><![endif]-->
    <div id="fb-root"></div>
    <script>(function(d, s, id) {
      var js, fjs = d.getElementsByTagName(s)[0];
      if (d.getElementById(id)) return;
      js = d.createElement(s); js.id = id;
      js.src = "//connect.facebook.net/ja_JP/all.js#xfbml=1&appId=351187098330864";
      fjs.parentNode.insertBefore(js, fjs);
      }(document, 'script', 'facebook-jssdk'));
    </script>
    <header>
      <nav class="navbar navbar-fixed-top">
        <div class="navbar-inner">
          <div class="container">
            <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
            </a>
            <a class="brand" href="../index.html">でこてっくろぐ</a>
            <div class="nav-collapse">
              <ul class="nav">
                <li><a href="../index.html">ほーむ</a></li>
                <li><a href="../posts.html">あーかいぶ</a></li>
                <li><a href="../aboutme.html">あばうとみー</a></li>
              </ul>
            </div><!--/.nav-collapse -->
          </div>
        </div>
      </nav>
    </header>

    <div class="container">
      <div class="row">
        <article class="span9">
          <h1>PHPにおいてstaticメソッドの呼び出し元クラスを動的に変更</h1>

<p>by <em><a href="https://twitter.com/dekokun">@dekokun</a></em> on <strong>2013/01/14 20:33</strong></p>

<p>Tagged as: <a href="../tags/PHP.html">PHP</a>.</p>

<p>staticメソッドを含むクラスをDIしたかったため、クラスを動的に変更してstaticメソッドを呼び出す方法を調べました。</p>
<h2 id="呼び出し方">呼び出し方</h2>
<pre><code>&lt;?php
class ClassName {
  public static function method() {
  }
}</code></pre>
<p>のようなstaticメソッドの呼び出し元を動的に変更できるようクラス名から呼び出せるようにしたいですね。</p>
<p>以下のようにすればよいです。</p>
<pre><code>$className = 'ClassName';
$className::method();</code></pre>
<p>以上、めでたしめでたし。</p>
<p>クラス名の文字列からnewできることは知っている人も多いかと思いますが、staticメソッドも同様に呼び出せるのでした。</p>
<h2 id="注意事項">注意事項</h2>
<p>この注意事項は、クラス名を動的に指定する場合全般に当てはまります。staticメソッドだからどうこうというわけではありません。</p>
<h3 id="変数に格納しなくてはいけません">変数に格納しなくてはいけません</h3>
<p><code>new 'ClassName'</code>とか<code>'ClassNeme'::method()</code>とかはできません。パースエラーです。</p>
<h3 id="完全修飾名を使ってください">完全修飾名を使ってください</h3>
<pre><code>namespace Hoge\Fuga

class Fuga {
  public static method() {
  }
}</code></pre>
<p>のようなクラスがあった場合、</p>
<pre><code>use Hoge\Fuga

$className = 'Fuga';
$className::method();</code></pre>
<p>のようにエイリアスを使用したアクセスはできません。</p>
<pre><code>$className = 'Hoge\Fuga';
$className::method();</code></pre>
<p>のように完全修飾名を使用しアクセスしましょう。</p>
<p>本件について、詳しくは以下PHPマニュアル参照</p>
<ul>
<li><a href="http://php.net/manual/ja/language.namespaces.dynamic.php">名前空間と動的言語機能</a></li>
</ul>
<h2 id="まとめ">まとめ</h2>
<p>文字列からnewできることを知っている人はよく知っていることばかりだったかもしれませんね。</p>
<p>動的にクラス名を指定できるようにしてレッツエンジョイDIライフ！</p>

<div id="disqus_thread"></div>
<script type="text/javascript">
    /* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */
    var disqus_shortname = 'dekokun'; // required: replace example with your forum shortname

    /* * * DON'T EDIT BELOW THIS LINE * * */
    (function() {
        var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
        dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js';
        (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
    })();
</script>
<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
<a href="http://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a>

          <ul class="social">
            <li class="kindle"><div class="kindleWidget"><img style="vertical-align:middle;" src="https://d1xnn692s7u6t6.cloudfront.net/white-15.png" /><span style="vertical-align:middle;margin-left:3px;">Send to Kindle</span></div></li>
            <li class="facebook"><div class="fb-like" data-send="false" data-layout="button_count" data-width="100" data-show-faces="true" data-font="arial"></div></li>
            <li class="twitter"><a href="https://twitter.com/share" class="twitter-share-button" data-via="dekokun" data-lang="ja">ツイート</a></li>
            <li class="hatena-bookmark"><a href="http://b.hatena.ne.jp/entry/" class="hatena-bookmark-button" data-hatena-bookmark-layout="standard" title="このエントリーをはてなブックマークに追加"><img src="http://b.st-hatena.com/images/entry-button/button-only.gif" alt="このエントリーをはてなブックマークに追加" width="20" height="20" style="border: none;"></a><script type="text/javascript" src="http://b.st-hatena.com/js/bookmark_button.js" charset="utf-8" async="async"></script></li>
            <li><a data-pocket-label="pocket" data-pocket-count="horizontal" class="pocket-btn" data-lang="en"></a>
            <script type="text/javascript">!function(d,i){if(!d.getElementById(i)){var j=d.createElement("script");j.id=i;j.src="https://widgets.getpocket.com/v1/j/btn.js?v=1";var w=d.getElementById(i);d.body.appendChild(j);}}(document,"pocket-btn-js");</script></li>
          </ul>

        </article>
        <aside class="span3">
          <div class="sidebar-module">
            <div class="title">プロフィール</div>
            <p class="id"><a href="https://twitter.com/dekokun">dekokun</a></p>
            <p><a href="https://twitter.com/dekokun"><img src="../img/dekokun.png" alt="dekokun"></a></p>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.io/";
              Hatena.BookmarkWidget.title = "人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 200;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.com/";
              Hatena.BookmarkWidget.title = "旧人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 0;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module visible-desktop">
            <div class="title">twitter</div>
            <a class="twitter-timeline" data-dnt="true" href="https://twitter.com/dekokun" data-widget-id="306408547573440513">@dekokun からのツイート</a>
            <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
          </div>
          <div class="sidebar-module hidden-phone">
            <div class="title">RSS</div>
            <p><a href="../rss.xml"><img src="../img/rss.gif" alt="rss"></a></p>
          </div>
        </aside> <!-- /span3 -->
      </div> <!-- /row -->
      <footer>
        <p>©<script type="text/javascript">$y=2012;$ny=new Date().getFullYear();document.write($ny>$y?$y+'-'+$ny:$y);</script> <a href="https://twitter.com/dekokun">dekokun</a></p>
      </footer>
    </div> <!-- /container -->

    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script>window.jQuery || document.write('<script src="../js/libs/jquery-1.7.2.min.js"><\/script>')</script>
    <!-- /ツイートボタン -->
  <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>

    <script src="../js/libs/bootstrap/bootstrap.min.js"></script>

    <script src="../js/script.js"></script>
    <script>
      var _gaq=[['_setAccount','UA-XXXXX-X'],['_trackPageview']];
      (function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
      g.src=('https:'==location.protocol?'//ssl':'//www')+'.google-analytics.com/ga.js';
      s.parentNode.insertBefore(g,s)}(document,'script'));
    </script>
    <!-- Code syntax highlight -->
    <script type="text/javascript" src="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.js"></script>
    <script type="text/javascript">
    $(function(){ 
        $('pre').css({
            'overflow-x': 'scroll',
            'background-color': '#f6f6f6',
            'border': '1px dotted #ccc',
            'padding': '0.8em'
        });
        $('pre code').addClass('prettyprint');
        prettyPrint();
    });
    </script>
    <script type="text/javascript" src="https://d1xnn692s7u6t6.cloudfront.net/widget.js"></script>
    <script type="text/javascript">(function k(){window.$SendToKindle&&window.$SendToKindle.Widget?$SendToKindle.Widget.init({"content":"article"}):setTimeout(k,500);})();</script>
  </body>
</html>
]]></description>
    <pubDate>No date found.</pubDate>
    <guid>http://dekokun.github.io/posts/2013-01-14.html</guid>
</item>
<item>
    <title>「第7回 スタートHaskell2(最終回)」行ってきた</title>
    <link>http://dekokun.github.io/posts/2013-01-20.html</link>
    <description><![CDATA[<!doctype html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7" lang="ja"> <![endif]-->
<!--[if IE 7]>    <html class="no-js lt-ie9 lt-ie8" lang="ja"> <![endif]-->
<!--[if IE 8]>    <html class="no-js lt-ie9" lang="ja"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="ja"> <!--<![endif]-->
  <head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# article: http://ogp.me/ns/article#">
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <title>「第7回 スタートHaskell2(最終回)」行ってきた</title>
    <meta name="description" content>
    <meta name="author" content>

    <meta name="viewport" content="width=device-width">
    <meta property="fb:app_id" content="351187098330864">
    <meta property="og:type" content="article">
    <meta property="og:image" content="http://dekokun.github.com/img/dekokun.png">
    <meta property="og:title" content="「第7回 スタートHaskell2(最終回)」行ってきた">
    <meta property="og:description" content="@dekokunの技術日記">
    <meta property="og:site_name" content="でこてっくろぐ">
    <meta name="twitter:widgets:csp" content="on">

    <link rel="stylesheet" href="../css/bootstrap.css">
    <link rel="stylesheet" href="../css/bootstrap-responsive.css">
    <link rel="stylesheet" href="../css/style.css">
    <style>
    body {
      padding-top: 60px;
      padding-bottom: 40px;
    }
    </style>
    <link href="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.css" type="text/css" rel="stylesheet">
    <script src="../js/libs/modernizr-2.5.3-respond-1.1.0.min.js"></script>
    <script>
      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

      ga('create', 'UA-39650556-1', 'auto');
      ga('send', 'pageview');
    </script>
  </head>
  <body>
  <!--[if lt IE 7]><p class=chromeframe>Your browser is <em>ancient!</em> <a href="http://browsehappy.com/">Upgrade to a different browser</a> or <a href="http://www.google.com/chromeframe/?redirect=true">install Google Chrome Frame</a> to experience this site.</p><![endif]-->
    <div id="fb-root"></div>
    <script>(function(d, s, id) {
      var js, fjs = d.getElementsByTagName(s)[0];
      if (d.getElementById(id)) return;
      js = d.createElement(s); js.id = id;
      js.src = "//connect.facebook.net/ja_JP/all.js#xfbml=1&appId=351187098330864";
      fjs.parentNode.insertBefore(js, fjs);
      }(document, 'script', 'facebook-jssdk'));
    </script>
    <header>
      <nav class="navbar navbar-fixed-top">
        <div class="navbar-inner">
          <div class="container">
            <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
            </a>
            <a class="brand" href="../index.html">でこてっくろぐ</a>
            <div class="nav-collapse">
              <ul class="nav">
                <li><a href="../index.html">ほーむ</a></li>
                <li><a href="../posts.html">あーかいぶ</a></li>
                <li><a href="../aboutme.html">あばうとみー</a></li>
              </ul>
            </div><!--/.nav-collapse -->
          </div>
        </div>
      </nav>
    </header>

    <div class="container">
      <div class="row">
        <article class="span9">
          <h1>「第7回 スタートHaskell2(最終回)」行ってきた</h1>

<p>by <em><a href="https://twitter.com/dekokun">@dekokun</a></em> on <strong>2013/01/20 19:26</strong></p>

<p>Tagged as: <a href="../tags/Haskell.html">Haskell</a>, <a href="../tags/勉強会.html">勉強会</a>.</p>

<h2 id="イベント概要">イベント概要</h2>
<ul>
<li>PARTAKE <a href="http://partake.in/events/60b9a21c-8282-4abe-8820-099d65f69a62">第7回 スタートHaskell2(最終回)</a></li>
<li>月に1度くらいのペースで<a href="http://www.amazon.co.jp/すごいHaskellたのしく学ぼう-Miran-Lipovača/dp/4274068854">すごいHaskell楽しく学ぼう</a>をテキストに、セミナーと演習で進んでいく</li>
<li>去年の5月くらいから続いているこの回もついに今回が最終回だったわけです。私としては、初めて、1時間という長時間の発表をした勉強会かつ、初めての最初から最後まですべて参加した連続の勉強会になりますので、感慨深いです。</li>
</ul>
<h2 id="今回の内容">今回の内容</h2>
<ul>
<li>「すごいHaskell楽しく学ぼう」の第14章(もうちょっとだけモナド)と第15章(Zipper)でした。</li>
<li>演習問題はこちらですよ <a href="http://wiki.haskell.jp/Workshop/StartHaskell2/exercise14#readerモナドを使ってみよう">『もうちょっとだけモナド』　練習問題</a>
<ul>
<li>私は逆ポーランド記法で書かれた式を計算する関数solveRPNにWriterモナドでログ追加する問題にハマり続けギョッとしました。Haskell力の低さを思い知らされた…</li>
</ul></li>
<li>私もLiterate HaskellとMarkdownで発表資料作ってみたいです。</li>
<li><code>a -&gt; b</code> を<code>((-&gt;) a) b</code>と書けばモナドっぽさがわかるでしょ♪♪</li>
<li>モナドの導入には以下を読むとよいそうですよ。Maybeモナドより簡単なIdentityモナドから考えて行きましょう。
<ul>
<li><a href="http://d.hatena.ne.jp/kazu-yamamoto/20090826/1251258560">例題で比較する状態系のモナド</a></li>
</ul></li>
<li>RubyistのかたがHaskellの会合では自虐ネタを話すようになるということが分かったし、PHPerの私は身分を明かし辛い世の中になったものだと思いました(嘘です。最近PHPを使っていることにに対して誇りを持ち始めました)</li>
<li>LiveReloadとHakyllの連携で快適ブログ記述生活(このブログもHakyll製だし導入せねば！)</li>
<li>アクセスする度に木の形が変わるスプレー木
<ul>
<li>アクセスしたノードがルートになり、次回以降の検索が早くなる</li>
<li>アクセスすればするほどバランスしていく</li>
</ul></li>
<li>詳しくは、他の方がブログ書いてくれるのではないでしょうか。</li>
</ul>
<h2 id="最初から最後まで参加してhaskellについての感想とか">最初から最後まで参加してHaskellについての感想とか</h2>
<ul>
<li>Haskellは純粋ですね</li>
<li>型システムって素敵ですね。動的言語しか書いたことなかったから、コンパイル時点でエラーとなるのは大変ありがたいなぁというのを強く感じました。
<ul>
<li>型システムのない言語を書いた際の恐怖心が格段にあがり、動的言語を書く際のテストの大切さをより強く感じたという副作用も(静的言語でもテストは大切ですが、動的言語はそれとは比べ物にならないほどテストが大切ですね)</li>
</ul></li>
<li>いろいろあってHaskellと一緒にJavaも学んだりして、オブジェクト指向とは何かというのもよく学べました。</li>
<li>60人くらいの前で初めて1時間という長時間に渡るHaskellについての発表(発表資料：<a href="http://dekokun.github.com/StartHaskell2-Chapter10/?theme=beige&amp;transition=page#/">スタートHASKELL 2 関数型問題解決法</a>)を行いました。「ゆっくり話す」ということだけ意識して発表し、ゆっくり話せました。</li>
</ul>
<h2 id="これから">これから</h2>
<ul>
<li>実際に業務で使っているPHPに対して、「Haskellで何かを作る」というのはまだおこなっていないため、何か作らねばならぬと考えております。
<ul>
<li>やはり、実際に何かを作ってみないと何が良くて何が悪いのかわからない</li>
<li>今のままでは、ただ「Haskellマンセー。純粋じゃない言語使ってるなんてプギャー」というだけでなんの進歩もない</li>
</ul></li>
<li>以前のブログで書きましたが(<a href="http://dekokun.github.com/posts/2012-12-16.html">DevLOVE Conference 2012 に参加した後、これからの私にとって最も大切なこと</a>)、「yesodでWebアプリを作って公開」したいですね。</li>
<li>まずはチュートリアル(<a href="https://github.com/seizans/yesod-tutorial">yesod-tutorial</a>)から(2ヶ月前にやってたけど途中でやらなくなってしまっている)</li>
<li>「この勉強会に最後まで参加した人は優秀なHaskellerだと思っているので、是非Haskellを広めていってください」とのことなので、広めて行きたいですね(どうすれば…)</li>
</ul>
<h2 id="最後に">最後に</h2>
<ul>
<li>運営の皆さん、ありがとうございました。</li>
<li>プログラミングを何も書いたこともない私の彼女に「彼女とペアプロするのが夢だったし一緒にHaskellやらない？」って言ってこの勉強会に第2回からモナドに入ったあたりまで4回ほど参加してもらいました。ありがとうございました。あまり予習復習に時間を割けなくてすみませんでした。</li>
</ul>

<div id="disqus_thread"></div>
<script type="text/javascript">
    /* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */
    var disqus_shortname = 'dekokun'; // required: replace example with your forum shortname

    /* * * DON'T EDIT BELOW THIS LINE * * */
    (function() {
        var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
        dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js';
        (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
    })();
</script>
<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
<a href="http://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a>

          <ul class="social">
            <li class="kindle"><div class="kindleWidget"><img style="vertical-align:middle;" src="https://d1xnn692s7u6t6.cloudfront.net/white-15.png" /><span style="vertical-align:middle;margin-left:3px;">Send to Kindle</span></div></li>
            <li class="facebook"><div class="fb-like" data-send="false" data-layout="button_count" data-width="100" data-show-faces="true" data-font="arial"></div></li>
            <li class="twitter"><a href="https://twitter.com/share" class="twitter-share-button" data-via="dekokun" data-lang="ja">ツイート</a></li>
            <li class="hatena-bookmark"><a href="http://b.hatena.ne.jp/entry/" class="hatena-bookmark-button" data-hatena-bookmark-layout="standard" title="このエントリーをはてなブックマークに追加"><img src="http://b.st-hatena.com/images/entry-button/button-only.gif" alt="このエントリーをはてなブックマークに追加" width="20" height="20" style="border: none;"></a><script type="text/javascript" src="http://b.st-hatena.com/js/bookmark_button.js" charset="utf-8" async="async"></script></li>
            <li><a data-pocket-label="pocket" data-pocket-count="horizontal" class="pocket-btn" data-lang="en"></a>
            <script type="text/javascript">!function(d,i){if(!d.getElementById(i)){var j=d.createElement("script");j.id=i;j.src="https://widgets.getpocket.com/v1/j/btn.js?v=1";var w=d.getElementById(i);d.body.appendChild(j);}}(document,"pocket-btn-js");</script></li>
          </ul>

        </article>
        <aside class="span3">
          <div class="sidebar-module">
            <div class="title">プロフィール</div>
            <p class="id"><a href="https://twitter.com/dekokun">dekokun</a></p>
            <p><a href="https://twitter.com/dekokun"><img src="../img/dekokun.png" alt="dekokun"></a></p>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.io/";
              Hatena.BookmarkWidget.title = "人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 200;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.com/";
              Hatena.BookmarkWidget.title = "旧人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 0;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module visible-desktop">
            <div class="title">twitter</div>
            <a class="twitter-timeline" data-dnt="true" href="https://twitter.com/dekokun" data-widget-id="306408547573440513">@dekokun からのツイート</a>
            <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
          </div>
          <div class="sidebar-module hidden-phone">
            <div class="title">RSS</div>
            <p><a href="../rss.xml"><img src="../img/rss.gif" alt="rss"></a></p>
          </div>
        </aside> <!-- /span3 -->
      </div> <!-- /row -->
      <footer>
        <p>©<script type="text/javascript">$y=2012;$ny=new Date().getFullYear();document.write($ny>$y?$y+'-'+$ny:$y);</script> <a href="https://twitter.com/dekokun">dekokun</a></p>
      </footer>
    </div> <!-- /container -->

    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script>window.jQuery || document.write('<script src="../js/libs/jquery-1.7.2.min.js"><\/script>')</script>
    <!-- /ツイートボタン -->
  <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>

    <script src="../js/libs/bootstrap/bootstrap.min.js"></script>

    <script src="../js/script.js"></script>
    <script>
      var _gaq=[['_setAccount','UA-XXXXX-X'],['_trackPageview']];
      (function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
      g.src=('https:'==location.protocol?'//ssl':'//www')+'.google-analytics.com/ga.js';
      s.parentNode.insertBefore(g,s)}(document,'script'));
    </script>
    <!-- Code syntax highlight -->
    <script type="text/javascript" src="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.js"></script>
    <script type="text/javascript">
    $(function(){ 
        $('pre').css({
            'overflow-x': 'scroll',
            'background-color': '#f6f6f6',
            'border': '1px dotted #ccc',
            'padding': '0.8em'
        });
        $('pre code').addClass('prettyprint');
        prettyPrint();
    });
    </script>
    <script type="text/javascript" src="https://d1xnn692s7u6t6.cloudfront.net/widget.js"></script>
    <script type="text/javascript">(function k(){window.$SendToKindle&&window.$SendToKindle.Widget?$SendToKindle.Widget.init({"content":"article"}):setTimeout(k,500);})();</script>
  </body>
</html>
]]></description>
    <pubDate>No date found.</pubDate>
    <guid>http://dekokun.github.io/posts/2013-01-20.html</guid>
</item>
<item>
    <title>GREE Tech Talk #2 へ行って来ました</title>
    <link>http://dekokun.github.io/posts/2013-01-28.html</link>
    <description><![CDATA[<!doctype html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7" lang="ja"> <![endif]-->
<!--[if IE 7]>    <html class="no-js lt-ie9 lt-ie8" lang="ja"> <![endif]-->
<!--[if IE 8]>    <html class="no-js lt-ie9" lang="ja"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="ja"> <!--<![endif]-->
  <head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# article: http://ogp.me/ns/article#">
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <title>GREE Tech Talk #2 へ行って来ました</title>
    <meta name="description" content>
    <meta name="author" content>

    <meta name="viewport" content="width=device-width">
    <meta property="fb:app_id" content="351187098330864">
    <meta property="og:type" content="article">
    <meta property="og:image" content="http://dekokun.github.com/img/dekokun.png">
    <meta property="og:title" content="GREE Tech Talk #2 へ行って来ました">
    <meta property="og:description" content="@dekokunの技術日記">
    <meta property="og:site_name" content="でこてっくろぐ">
    <meta name="twitter:widgets:csp" content="on">

    <link rel="stylesheet" href="../css/bootstrap.css">
    <link rel="stylesheet" href="../css/bootstrap-responsive.css">
    <link rel="stylesheet" href="../css/style.css">
    <style>
    body {
      padding-top: 60px;
      padding-bottom: 40px;
    }
    </style>
    <link href="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.css" type="text/css" rel="stylesheet">
    <script src="../js/libs/modernizr-2.5.3-respond-1.1.0.min.js"></script>
    <script>
      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

      ga('create', 'UA-39650556-1', 'auto');
      ga('send', 'pageview');
    </script>
  </head>
  <body>
  <!--[if lt IE 7]><p class=chromeframe>Your browser is <em>ancient!</em> <a href="http://browsehappy.com/">Upgrade to a different browser</a> or <a href="http://www.google.com/chromeframe/?redirect=true">install Google Chrome Frame</a> to experience this site.</p><![endif]-->
    <div id="fb-root"></div>
    <script>(function(d, s, id) {
      var js, fjs = d.getElementsByTagName(s)[0];
      if (d.getElementById(id)) return;
      js = d.createElement(s); js.id = id;
      js.src = "//connect.facebook.net/ja_JP/all.js#xfbml=1&appId=351187098330864";
      fjs.parentNode.insertBefore(js, fjs);
      }(document, 'script', 'facebook-jssdk'));
    </script>
    <header>
      <nav class="navbar navbar-fixed-top">
        <div class="navbar-inner">
          <div class="container">
            <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
            </a>
            <a class="brand" href="../index.html">でこてっくろぐ</a>
            <div class="nav-collapse">
              <ul class="nav">
                <li><a href="../index.html">ほーむ</a></li>
                <li><a href="../posts.html">あーかいぶ</a></li>
                <li><a href="../aboutme.html">あばうとみー</a></li>
              </ul>
            </div><!--/.nav-collapse -->
          </div>
        </div>
      </nav>
    </header>

    <div class="container">
      <div class="row">
        <article class="span9">
          <h1>GREE Tech Talk #2 へ行って来ました</h1>

<p>by <em><a href="https://twitter.com/dekokun">@dekokun</a></em> on <strong>2013/01/28 23:30</strong></p>

<p>Tagged as: <a href="../tags/GitHub.html">GitHub</a>, <a href="../tags/勉強会.html">勉強会</a>.</p>

<p>GREE Tech Talk #2に参加し、GitHub Enterprise(以下、GHEと表記)の運用についてのお話を聞いて来ました。 開催からだいぶ日がたちましたが、感想など。 「GHE、気軽に導入できるのかなぁ」と軽く考えておりましたが、まだその段階には至ってないようでした。</p>
<h2 id="イベント概要">イベント概要</h2>
<ul>
<li><a href="http://techtalk2.labs.gree.jp/">GREE Tech Talk#2</a></li>
<li><a href="http://togetter.com/li/443950">GitHub Enterprise イベントまとめ #greetech02</a></li>
<li><a href="http://diary.sorah.jp/post/41286744473/github-enterprise-casual-talk-greetech02">GitHub:Enterprise Casual Talk に参加した #greetech02</a></li>
<li><a href="http://subtech.g.hatena.ne.jp/secondlife/20130124/1358987688">GitHub Enterprise TechTalk に見る、各社の運用法</a></li>
</ul>
<h2 id="感想">感想</h2>
<ul>
<li>GitHubエンタープライズの運用は現状では一筋縄ではいかないですね。</li>
<li>github.comが落ちていても諦められるかつセキュリティ的に問題なければgithub.com使ったほうがよいですね。</li>
<li>github.com使ってようが、GHE使ってようが、どちらも普通のGitサーバとくらべて格段に落ちやすいしクックパッド社やはてな社がやっているように、別のGitサーバを用意しそちらにミラーリングしてデプロイはそちらを参照するほうがいいですね。</li>
<li>gitlabは私も検証中なのですが、中身を改造しないと使いづらいです。。
<ul>
<li>ドリコムさんみたいにRailsで開発している会社ならまだいいですが、その他の会社はGitHubの代わりにgitlabというのは難度が高いのではないかと…</li>
<li>「金があるならGHEを使え」</li>
</ul></li>
<li><a href="http://www.harding.motd.ca/autossh/">autossh</a>便利ですね</li>
<li>「GitHubはアイコンが出るため、視覚的に誰のコメントかなどがわかりやすくてよい」「絵文字が使えるのがコミュニケーションに役立つ」という意見は、なるほどと思いました。</li>
</ul>

<div id="disqus_thread"></div>
<script type="text/javascript">
    /* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */
    var disqus_shortname = 'dekokun'; // required: replace example with your forum shortname

    /* * * DON'T EDIT BELOW THIS LINE * * */
    (function() {
        var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
        dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js';
        (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
    })();
</script>
<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
<a href="http://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a>

          <ul class="social">
            <li class="kindle"><div class="kindleWidget"><img style="vertical-align:middle;" src="https://d1xnn692s7u6t6.cloudfront.net/white-15.png" /><span style="vertical-align:middle;margin-left:3px;">Send to Kindle</span></div></li>
            <li class="facebook"><div class="fb-like" data-send="false" data-layout="button_count" data-width="100" data-show-faces="true" data-font="arial"></div></li>
            <li class="twitter"><a href="https://twitter.com/share" class="twitter-share-button" data-via="dekokun" data-lang="ja">ツイート</a></li>
            <li class="hatena-bookmark"><a href="http://b.hatena.ne.jp/entry/" class="hatena-bookmark-button" data-hatena-bookmark-layout="standard" title="このエントリーをはてなブックマークに追加"><img src="http://b.st-hatena.com/images/entry-button/button-only.gif" alt="このエントリーをはてなブックマークに追加" width="20" height="20" style="border: none;"></a><script type="text/javascript" src="http://b.st-hatena.com/js/bookmark_button.js" charset="utf-8" async="async"></script></li>
            <li><a data-pocket-label="pocket" data-pocket-count="horizontal" class="pocket-btn" data-lang="en"></a>
            <script type="text/javascript">!function(d,i){if(!d.getElementById(i)){var j=d.createElement("script");j.id=i;j.src="https://widgets.getpocket.com/v1/j/btn.js?v=1";var w=d.getElementById(i);d.body.appendChild(j);}}(document,"pocket-btn-js");</script></li>
          </ul>

        </article>
        <aside class="span3">
          <div class="sidebar-module">
            <div class="title">プロフィール</div>
            <p class="id"><a href="https://twitter.com/dekokun">dekokun</a></p>
            <p><a href="https://twitter.com/dekokun"><img src="../img/dekokun.png" alt="dekokun"></a></p>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.io/";
              Hatena.BookmarkWidget.title = "人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 200;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.com/";
              Hatena.BookmarkWidget.title = "旧人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 0;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module visible-desktop">
            <div class="title">twitter</div>
            <a class="twitter-timeline" data-dnt="true" href="https://twitter.com/dekokun" data-widget-id="306408547573440513">@dekokun からのツイート</a>
            <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
          </div>
          <div class="sidebar-module hidden-phone">
            <div class="title">RSS</div>
            <p><a href="../rss.xml"><img src="../img/rss.gif" alt="rss"></a></p>
          </div>
        </aside> <!-- /span3 -->
      </div> <!-- /row -->
      <footer>
        <p>©<script type="text/javascript">$y=2012;$ny=new Date().getFullYear();document.write($ny>$y?$y+'-'+$ny:$y);</script> <a href="https://twitter.com/dekokun">dekokun</a></p>
      </footer>
    </div> <!-- /container -->

    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script>window.jQuery || document.write('<script src="../js/libs/jquery-1.7.2.min.js"><\/script>')</script>
    <!-- /ツイートボタン -->
  <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>

    <script src="../js/libs/bootstrap/bootstrap.min.js"></script>

    <script src="../js/script.js"></script>
    <script>
      var _gaq=[['_setAccount','UA-XXXXX-X'],['_trackPageview']];
      (function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
      g.src=('https:'==location.protocol?'//ssl':'//www')+'.google-analytics.com/ga.js';
      s.parentNode.insertBefore(g,s)}(document,'script'));
    </script>
    <!-- Code syntax highlight -->
    <script type="text/javascript" src="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.js"></script>
    <script type="text/javascript">
    $(function(){ 
        $('pre').css({
            'overflow-x': 'scroll',
            'background-color': '#f6f6f6',
            'border': '1px dotted #ccc',
            'padding': '0.8em'
        });
        $('pre code').addClass('prettyprint');
        prettyPrint();
    });
    </script>
    <script type="text/javascript" src="https://d1xnn692s7u6t6.cloudfront.net/widget.js"></script>
    <script type="text/javascript">(function k(){window.$SendToKindle&&window.$SendToKindle.Widget?$SendToKindle.Widget.init({"content":"article"}):setTimeout(k,500);})();</script>
  </body>
</html>
]]></description>
    <pubDate>No date found.</pubDate>
    <guid>http://dekokun.github.io/posts/2013-01-28.html</guid>
</item>
<item>
    <title>GitLabにGitoliteが必要なくなるよ いいことばかりじゃないけど</title>
    <link>http://dekokun.github.io/posts/2013-02-19.html</link>
    <description><![CDATA[<!doctype html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7" lang="ja"> <![endif]-->
<!--[if IE 7]>    <html class="no-js lt-ie9 lt-ie8" lang="ja"> <![endif]-->
<!--[if IE 8]>    <html class="no-js lt-ie9" lang="ja"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="ja"> <!--<![endif]-->
  <head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# article: http://ogp.me/ns/article#">
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <title>GitLabにGitoliteが必要なくなるよ いいことばかりじゃないけど</title>
    <meta name="description" content>
    <meta name="author" content>

    <meta name="viewport" content="width=device-width">
    <meta property="fb:app_id" content="351187098330864">
    <meta property="og:type" content="article">
    <meta property="og:image" content="http://dekokun.github.com/img/dekokun.png">
    <meta property="og:title" content="GitLabにGitoliteが必要なくなるよ いいことばかりじゃないけど">
    <meta property="og:description" content="@dekokunの技術日記">
    <meta property="og:site_name" content="でこてっくろぐ">
    <meta name="twitter:widgets:csp" content="on">

    <link rel="stylesheet" href="../css/bootstrap.css">
    <link rel="stylesheet" href="../css/bootstrap-responsive.css">
    <link rel="stylesheet" href="../css/style.css">
    <style>
    body {
      padding-top: 60px;
      padding-bottom: 40px;
    }
    </style>
    <link href="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.css" type="text/css" rel="stylesheet">
    <script src="../js/libs/modernizr-2.5.3-respond-1.1.0.min.js"></script>
    <script>
      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

      ga('create', 'UA-39650556-1', 'auto');
      ga('send', 'pageview');
    </script>
  </head>
  <body>
  <!--[if lt IE 7]><p class=chromeframe>Your browser is <em>ancient!</em> <a href="http://browsehappy.com/">Upgrade to a different browser</a> or <a href="http://www.google.com/chromeframe/?redirect=true">install Google Chrome Frame</a> to experience this site.</p><![endif]-->
    <div id="fb-root"></div>
    <script>(function(d, s, id) {
      var js, fjs = d.getElementsByTagName(s)[0];
      if (d.getElementById(id)) return;
      js = d.createElement(s); js.id = id;
      js.src = "//connect.facebook.net/ja_JP/all.js#xfbml=1&appId=351187098330864";
      fjs.parentNode.insertBefore(js, fjs);
      }(document, 'script', 'facebook-jssdk'));
    </script>
    <header>
      <nav class="navbar navbar-fixed-top">
        <div class="navbar-inner">
          <div class="container">
            <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
            </a>
            <a class="brand" href="../index.html">でこてっくろぐ</a>
            <div class="nav-collapse">
              <ul class="nav">
                <li><a href="../index.html">ほーむ</a></li>
                <li><a href="../posts.html">あーかいぶ</a></li>
                <li><a href="../aboutme.html">あばうとみー</a></li>
              </ul>
            </div><!--/.nav-collapse -->
          </div>
        </div>
      </nav>
    </header>

    <div class="container">
      <div class="row">
        <article class="span9">
          <h1>GitLabにGitoliteが必要なくなるよ いいことばかりじゃないけど</h1>

<p>by <em><a href="https://twitter.com/dekokun">@dekokun</a></em> on <strong>2013/02/19 23:28</strong></p>

<p>Tagged as: <a href="../tags/GitLab.html">GitLab</a>, <a href="../tags/git.html">git</a>.</p>

<p>プライベートGitHubが構築できる(<a href="http://d.hatena.ne.jp/dkfj/20130212/1360676224">Amazon Linux AMIにGit + Gitolite + Gitlabをインストールして、プライベートGitHubを構築する</a>)などとして絶賛話題沸騰中、「<a href="http://www.slideshare.net/takafumionaka/is-there-anynecessityofusinggithubenterprise/9">貧者のGItHub Enterprize</a>」であるところの<a href="https://github.com/gitlabhq/gitlabhq">GitLab</a>ですが、次のメジャーバージョンアップでGitoliteが不要になるという大ニュースが数日前に発表されたにもかかわらず、日本語の情報が全くないのでそれではわたくしめがと思いましてブログを執筆させていただく次第です。 あ、あと、私事で恐縮ですが今度結婚することになりました。</p>
<h2 id="はじめに">はじめに</h2>
<p>皆さん、<a href="http://d.hatena.ne.jp/dkfj/20130212/1360676224">Amazon Linux AMIにGit + Gitolite + Gitlabをインストールして、プライベートGitHubを構築する</a>を読んで「GitLabの構築はなんと面倒くさいんだ」とは思いませんでしたか(実際のところ、例えば他のGitHubクローンであるところのGitoriousの構築のほうがもっと大変らしいですが)。 Ruby製のGitLabをインストールするにはPerl製のGitolite環境が必要だなんてなんて面倒極まりないですね。</p>
<p>しかし、会社の先輩から「GitLab 5.0からGitolite使わなくなるらしいっすよ」と聞いて<a href="http://blog.gitlabhq.com/">GitLab Blog</a>を見ましたら、確かに「Yeap GitLab 5.0 will be without gitolite」(訳：GitLab 5.0からGitoliteいらなくなるよ)と書いてあるではないですか。</p>
<p>以下、GitLab Blogの重要な部分を訳していきます。</p>
<h2 id="gitoliteを使用したgitlabのこれまでの問題">Gitoliteを使用したGitLabのこれまでの問題</h2>
<p>これまでのGitoliteを使用したGitLabの問題は以下のとおりだそうです。</p>
<ul>
<li>GitLabとGitoliteで不整合起きちゃうよ</li>
<li>リポジトリ数が増えてくるとGitoliteは遅くなるよ</li>
<li>GitLabをセットアップするのに2ユーザ(GitoliteのユーザとGitLabのユーザ)が必要で面倒だよね</li>
<li>GitoLiteのせいでコードが複雑になって簡単にミスをするようになってるよ</li>
<li>Gitoliteはリポジトリやキーの作成をサポートしてくれないよ</li>
</ul>
<h2 id="解決法">解決法</h2>
<p>というわけで、GitLabの代わりに<a href="https://github.com/gitlabhq/GitLab-shell">GitLab Shell</a>なるものを使用することにしたそうです。</p>
<p>これにより上記の不満点は解消するとのこと。 ついでに、GitLab Shellはgit pullするだけでGitLabの再起動なしでアップデートできて簡単だよとのこと。</p>
<h2 id="gitolite廃止に対する海外の反応">Gitolite廃止に対する海外の反応</h2>
<p>かなり雑に紹介します</p>
<ul>
<li>GitLab ShellはGitLabが動いてないと動かないんだよね？パッチあてたりでGitLabが一時的にダウンする時でもGitoliteの時はリポジトリにはアクセスできてたのにできなくなるのかー。
<ul>
<li>そうそう！これでメンテナンスが難しくなるよね！GitLabを止めることにしてもGitoliteによってリポジトリサービスを提供できるからGitLabを選んだというのも大きいというのに！</li>
<li>その他、Gitoliteからの脱却に反対がいくつか。「他のサービスを使うことを考え始めるよ」という意見も</li>
<li>GitLagのメンテナさんの回答：GitLab ShellはGitLabがないと動かないよ！よりよい安定性とパフォーマンスのためには仕方ないよね！</li>
</ul></li>
</ul>
<h2 id="終わりに">終わりに</h2>
<p>私も職場でGitLabのメンテナンスしてますが、GitLabが動いてないときでもGitoliteによってリポジトリが使えるというのは魅力だったわけですし、なかなか難しいところですね。まぁ、「Gitoliteのコンフィグをパースするのに1000行のコードと1つのライブラリを使ってるけど、GitLab Shellなら150行で済むよ」っていうんだし、確かに今後の安定性を考えるとGitoliteからの決別も仕方ないのかなと思います。</p>
<p>この件、発表からすでに数日経ってますが日本語の反応が見当たらないってことは、日本人はあまり興味のない話題だったのかなー。</p>
<p>どうでもいいが、GitHub Enterprize欲しいです。</p>

<div id="disqus_thread"></div>
<script type="text/javascript">
    /* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */
    var disqus_shortname = 'dekokun'; // required: replace example with your forum shortname

    /* * * DON'T EDIT BELOW THIS LINE * * */
    (function() {
        var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
        dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js';
        (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
    })();
</script>
<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
<a href="http://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a>

          <ul class="social">
            <li class="kindle"><div class="kindleWidget"><img style="vertical-align:middle;" src="https://d1xnn692s7u6t6.cloudfront.net/white-15.png" /><span style="vertical-align:middle;margin-left:3px;">Send to Kindle</span></div></li>
            <li class="facebook"><div class="fb-like" data-send="false" data-layout="button_count" data-width="100" data-show-faces="true" data-font="arial"></div></li>
            <li class="twitter"><a href="https://twitter.com/share" class="twitter-share-button" data-via="dekokun" data-lang="ja">ツイート</a></li>
            <li class="hatena-bookmark"><a href="http://b.hatena.ne.jp/entry/" class="hatena-bookmark-button" data-hatena-bookmark-layout="standard" title="このエントリーをはてなブックマークに追加"><img src="http://b.st-hatena.com/images/entry-button/button-only.gif" alt="このエントリーをはてなブックマークに追加" width="20" height="20" style="border: none;"></a><script type="text/javascript" src="http://b.st-hatena.com/js/bookmark_button.js" charset="utf-8" async="async"></script></li>
            <li><a data-pocket-label="pocket" data-pocket-count="horizontal" class="pocket-btn" data-lang="en"></a>
            <script type="text/javascript">!function(d,i){if(!d.getElementById(i)){var j=d.createElement("script");j.id=i;j.src="https://widgets.getpocket.com/v1/j/btn.js?v=1";var w=d.getElementById(i);d.body.appendChild(j);}}(document,"pocket-btn-js");</script></li>
          </ul>

        </article>
        <aside class="span3">
          <div class="sidebar-module">
            <div class="title">プロフィール</div>
            <p class="id"><a href="https://twitter.com/dekokun">dekokun</a></p>
            <p><a href="https://twitter.com/dekokun"><img src="../img/dekokun.png" alt="dekokun"></a></p>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.io/";
              Hatena.BookmarkWidget.title = "人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 200;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.com/";
              Hatena.BookmarkWidget.title = "旧人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 0;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module visible-desktop">
            <div class="title">twitter</div>
            <a class="twitter-timeline" data-dnt="true" href="https://twitter.com/dekokun" data-widget-id="306408547573440513">@dekokun からのツイート</a>
            <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
          </div>
          <div class="sidebar-module hidden-phone">
            <div class="title">RSS</div>
            <p><a href="../rss.xml"><img src="../img/rss.gif" alt="rss"></a></p>
          </div>
        </aside> <!-- /span3 -->
      </div> <!-- /row -->
      <footer>
        <p>©<script type="text/javascript">$y=2012;$ny=new Date().getFullYear();document.write($ny>$y?$y+'-'+$ny:$y);</script> <a href="https://twitter.com/dekokun">dekokun</a></p>
      </footer>
    </div> <!-- /container -->

    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script>window.jQuery || document.write('<script src="../js/libs/jquery-1.7.2.min.js"><\/script>')</script>
    <!-- /ツイートボタン -->
  <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>

    <script src="../js/libs/bootstrap/bootstrap.min.js"></script>

    <script src="../js/script.js"></script>
    <script>
      var _gaq=[['_setAccount','UA-XXXXX-X'],['_trackPageview']];
      (function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
      g.src=('https:'==location.protocol?'//ssl':'//www')+'.google-analytics.com/ga.js';
      s.parentNode.insertBefore(g,s)}(document,'script'));
    </script>
    <!-- Code syntax highlight -->
    <script type="text/javascript" src="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.js"></script>
    <script type="text/javascript">
    $(function(){ 
        $('pre').css({
            'overflow-x': 'scroll',
            'background-color': '#f6f6f6',
            'border': '1px dotted #ccc',
            'padding': '0.8em'
        });
        $('pre code').addClass('prettyprint');
        prettyPrint();
    });
    </script>
    <script type="text/javascript" src="https://d1xnn692s7u6t6.cloudfront.net/widget.js"></script>
    <script type="text/javascript">(function k(){window.$SendToKindle&&window.$SendToKindle.Widget?$SendToKindle.Widget.init({"content":"article"}):setTimeout(k,500);})();</script>
  </body>
</html>
]]></description>
    <pubDate>No date found.</pubDate>
    <guid>http://dekokun.github.io/posts/2013-02-19.html</guid>
</item>
<item>
    <title>SQLアンチパターンを読みました</title>
    <link>http://dekokun.github.io/posts/2013-02-24.html</link>
    <description><![CDATA[<!doctype html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7" lang="ja"> <![endif]-->
<!--[if IE 7]>    <html class="no-js lt-ie9 lt-ie8" lang="ja"> <![endif]-->
<!--[if IE 8]>    <html class="no-js lt-ie9" lang="ja"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="ja"> <!--<![endif]-->
  <head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# article: http://ogp.me/ns/article#">
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <title>SQLアンチパターンを読みました</title>
    <meta name="description" content>
    <meta name="author" content>

    <meta name="viewport" content="width=device-width">
    <meta property="fb:app_id" content="351187098330864">
    <meta property="og:type" content="article">
    <meta property="og:image" content="http://dekokun.github.com/img/dekokun.png">
    <meta property="og:title" content="SQLアンチパターンを読みました">
    <meta property="og:description" content="@dekokunの技術日記">
    <meta property="og:site_name" content="でこてっくろぐ">
    <meta name="twitter:widgets:csp" content="on">

    <link rel="stylesheet" href="../css/bootstrap.css">
    <link rel="stylesheet" href="../css/bootstrap-responsive.css">
    <link rel="stylesheet" href="../css/style.css">
    <style>
    body {
      padding-top: 60px;
      padding-bottom: 40px;
    }
    </style>
    <link href="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.css" type="text/css" rel="stylesheet">
    <script src="../js/libs/modernizr-2.5.3-respond-1.1.0.min.js"></script>
    <script>
      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

      ga('create', 'UA-39650556-1', 'auto');
      ga('send', 'pageview');
    </script>
  </head>
  <body>
  <!--[if lt IE 7]><p class=chromeframe>Your browser is <em>ancient!</em> <a href="http://browsehappy.com/">Upgrade to a different browser</a> or <a href="http://www.google.com/chromeframe/?redirect=true">install Google Chrome Frame</a> to experience this site.</p><![endif]-->
    <div id="fb-root"></div>
    <script>(function(d, s, id) {
      var js, fjs = d.getElementsByTagName(s)[0];
      if (d.getElementById(id)) return;
      js = d.createElement(s); js.id = id;
      js.src = "//connect.facebook.net/ja_JP/all.js#xfbml=1&appId=351187098330864";
      fjs.parentNode.insertBefore(js, fjs);
      }(document, 'script', 'facebook-jssdk'));
    </script>
    <header>
      <nav class="navbar navbar-fixed-top">
        <div class="navbar-inner">
          <div class="container">
            <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
            </a>
            <a class="brand" href="../index.html">でこてっくろぐ</a>
            <div class="nav-collapse">
              <ul class="nav">
                <li><a href="../index.html">ほーむ</a></li>
                <li><a href="../posts.html">あーかいぶ</a></li>
                <li><a href="../aboutme.html">あばうとみー</a></li>
              </ul>
            </div><!--/.nav-collapse -->
          </div>
        </div>
      </nav>
    </header>

    <div class="container">
      <div class="row">
        <article class="span9">
          <h1>SQLアンチパターンを読みました</h1>

<p>by <em><a href="https://twitter.com/dekokun">@dekokun</a></em> on <strong>2013/02/26 8:15</strong></p>

<p>Tagged as: <a href="../tags/SQL.html">SQL</a>, <a href="../tags/書籍.html">書籍</a>.</p>

<p><a href="http://event.shoeisha.jp/detail/1/">デプサミ2013</a>で<a href="http://www.slideshare.net/t_wada/sql-antipatterns-devsumi-2013">和田さんのSQLアンチパターンの講演</a>を聞けなかった腹いせに<a href="http://www.oreilly.co.jp/books/9784873115894/">SQLアンチパターン</a>を購入して読んでおりましたが読み終わりましたので投稿。</p>
<h2 id="だいたいの内容">だいたいの内容</h2>
<p>世のシステムのかなりの割合で使用されているとおもわれるRDBMSを使用したシステムを作る際に開発者(DBAなど含む)が陥りがちなアンチパターンがまとまっている本です。</p>
<p>「インデックスショットガン(無闇やたらとインデックスを貼りまくる)」などの「そりゃ当然やっちゃいけないよね」と誰しもが納得するものから、「IDリクワイアド(すべてのテーブルにID列をつける)」など、一部の人には「あれ、それって何がダメなんだっけー」というもの、「リーダブルパスワード(パスワードの値を読める状態でDBに保存)」などの、いわゆる「DB設計についての本」にはあまり載っていないようなものまで、幅広いアンチパターンが記載されています。</p>
<p>上記のようにそれぞれのアンチパターンには名前がついているのも「アンチパターンの広まりやすさ、会話への出しやすさが高まる」という点でうれしいところです。</p>
<h2 id="一読した際の全体的な感想">一読した際の全体的な感想</h2>
<ul>
<li>「このアンチパターンはここがだめ。代替策にはこれとこれとこれがある。ただ、この代替策をとると今度はここを注意しなくてはいけない」という例が豊富で、更にほとんどの場合に「アンチパターンを用いてもよい場合」が記述されているため、単純なアンチパターン集というよりは、「様々な解決したい問題に対しての策が複数提示され、それらの利点欠点がよく分かる本」というイメージが強い。</li>
<li>今後「この方法を取りたいがこの方法にはどんな利点欠点があり、代替策にはどんなのがあるんだっけ」という際に手にとる時に最高の力を発揮すると思われる。</li>
<li>また、アンチパターンに名前がついているので、あとはみんながこの本を読みさえすれば「これはポリモーフィック関連になってるし直したいよね」とかいう会話ができるようになるし楽しいなぁ。この用語達浸透しないかなぁ。「私はIDリクワイアドが問題だとは思っていませんがあなたはどうですか」とか議論できたらいいなぁ。</li>
<li>「はじめに」にも書いてあるが、「本書を読むことで、データベース管理者はソフトウェア開発者がどのような考えでミスを犯してしまうのかがわかります。」はまさにそのとおりだと思います。素敵です。</li>
<li>シュードキー・ニートフレークの最後にアンチパターンを使用しないように上司を説得方法が記載されているなど、この本は現実と向き合うことを重視していると感じられる。</li>
</ul>
<h2 id="新たに知ったことや強く感じたことなど">新たに知ったことや強く感じたことなど</h2>
<p>この本を読んで新たに知ったことや、強く感じるものがあった部分を説明。すでにSQLアンチパターンを読んだことのある人以外は理解できない文章</p>
<h3 id="章-idリクワイアド">3章 IDリクワイアド</h3>
<ul>
<li>本書を読む直前に<a href="http://www.amazon.co.jp/達人に学ぶDB設計-徹底指南書-初級者で終わりたくないあなたへ-ミック/dp/4798124702">達人に学ぶDB設計 徹底指南書 初級者で終わりたくないあなたへ</a>を読んでいまして「サロゲートキーは撤廃しろ」という主張を見て頭をガーンとやられた気分になっていたのですが、SQLアンチパターンにも同様の主張が見られるとは！！！</li>
<li>IDリクワイアドに関しては、かなりの数の技術者が「問題はない。むしろこうするべきだ」と言って実践しているだろうなと思います。実践するのはいいとして、少なくとも「自然キーの代わりにID列を作成してプライマリキーとすることによって重複行を許可するようになってしまう」というあたりは押さえておかないといけない部分ですね。</li>
</ul>
<h3 id="章-アンビギュアスグループ">14章 アンビギュアスグループ</h3>
<ul>
<li>単一値の原則(Single-Value Rule)という単語は初めて知った</li>
<li>私は基本的にPostgreSQLからDBを学んできたために、group byなどを使用した際に集約関数を使用しない列が許容される場合があるのかと驚いた。MySQLやSQLiteはゆるふわちゃんで怖いわ…</li>
</ul>
<h3 id="章-スパゲッティクエリ">17 章 スパゲッティクエリ</h3>
<ul>
<li>P193のCASE式とSUM関数を組み合わせて条件ごとに集計する方法すごい！！便利！！！！！</li>
</ul>
<h3 id="章-リーダブルパスワード">19章 リーダブルパスワード</h3>
<ul>
<li>最近、「パスワードにはソルトをつけてハッシュ関数にかける」とか「ストレッチングをする」とか以前に「パスワードを不可逆な形で暗号化して保存しておく」ということすら知らない人の数が我々の想定よりははるかに多いのではないかという不安がよく押し寄せるのですが、「アンチパターン：リーダブルパスワード」という言葉が広まれば少しはマシになるのではないかなと思いました。</li>
</ul>
<h3 id="章-sqlインジェクション">20章 SQLインジェクション</h3>
<ul>
<li>プリペアドステートメントを使用することによってクエリオプティマイザがおかしな判断をする場合があるのですね。なんという罠…</li>
<li>テーブルの識別子や列識別子、SQL予約後などのプリペアドステートメントを使用できない場合の解決策としての「ユーザの入力をコードから隔離する」方法、超便利ですね。</li>
</ul>
<h3 id="章-シュードキーニートフレーク">21章 シュードキー・ニートフレーク</h3>
<ul>
<li>GUIDなんて知りませんでした。</li>
</ul>
<h3 id="章-マジックビーンズ">24章 マジックビーンズ</h3>
<ul>
<li>モデルがアクティブレコードを持つようにするの、とても便利じゃないですか。</li>
</ul>
<iframe src="http://rcm-jp.amazon.co.jp/e/cm?lt1=_blank&amp;bc1=000000&amp;IS2=1&amp;bg1=FFFFFF&amp;fc1=000000&amp;lc1=0000FF&amp;t=dekokun-22&amp;o=9&amp;p=8&amp;l=as1&amp;m=amazon&amp;f=ifr&amp;ref=qf_sp_asin_til&amp;asins=4873115892" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"></iframe>
<iframe src="http://rcm-jp.amazon.co.jp/e/cm?lt1=_blank&amp;bc1=000000&amp;IS2=1&amp;bg1=FFFFFF&amp;fc1=000000&amp;lc1=0000FF&amp;t=dekokun-22&amp;o=9&amp;p=8&amp;l=as4&amp;m=amazon&amp;f=ifr&amp;ref=ss_til&amp;asins=4798124702" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"></iframe>


<p>初めてAmazonのリンクをはった。</p>
<h2 id="初めて読んだ本についてのブログを書いての感想">初めて、読んだ本についてのブログを書いての感想</h2>
<ul>
<li>書籍についてのブログ記事を書くのは初めてですが、今後は技術書を読み終わったら書いていこうかなと思います。</li>
<li>ブログを書く際に強制的にもう一度読み直すことになるのでとてもよいですね。</li>
<li>本を読んで何を感じたかの記録になるのも良いです。</li>
</ul>

<div id="disqus_thread"></div>
<script type="text/javascript">
    /* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */
    var disqus_shortname = 'dekokun'; // required: replace example with your forum shortname

    /* * * DON'T EDIT BELOW THIS LINE * * */
    (function() {
        var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
        dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js';
        (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
    })();
</script>
<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
<a href="http://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a>

          <ul class="social">
            <li class="kindle"><div class="kindleWidget"><img style="vertical-align:middle;" src="https://d1xnn692s7u6t6.cloudfront.net/white-15.png" /><span style="vertical-align:middle;margin-left:3px;">Send to Kindle</span></div></li>
            <li class="facebook"><div class="fb-like" data-send="false" data-layout="button_count" data-width="100" data-show-faces="true" data-font="arial"></div></li>
            <li class="twitter"><a href="https://twitter.com/share" class="twitter-share-button" data-via="dekokun" data-lang="ja">ツイート</a></li>
            <li class="hatena-bookmark"><a href="http://b.hatena.ne.jp/entry/" class="hatena-bookmark-button" data-hatena-bookmark-layout="standard" title="このエントリーをはてなブックマークに追加"><img src="http://b.st-hatena.com/images/entry-button/button-only.gif" alt="このエントリーをはてなブックマークに追加" width="20" height="20" style="border: none;"></a><script type="text/javascript" src="http://b.st-hatena.com/js/bookmark_button.js" charset="utf-8" async="async"></script></li>
            <li><a data-pocket-label="pocket" data-pocket-count="horizontal" class="pocket-btn" data-lang="en"></a>
            <script type="text/javascript">!function(d,i){if(!d.getElementById(i)){var j=d.createElement("script");j.id=i;j.src="https://widgets.getpocket.com/v1/j/btn.js?v=1";var w=d.getElementById(i);d.body.appendChild(j);}}(document,"pocket-btn-js");</script></li>
          </ul>

        </article>
        <aside class="span3">
          <div class="sidebar-module">
            <div class="title">プロフィール</div>
            <p class="id"><a href="https://twitter.com/dekokun">dekokun</a></p>
            <p><a href="https://twitter.com/dekokun"><img src="../img/dekokun.png" alt="dekokun"></a></p>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.io/";
              Hatena.BookmarkWidget.title = "人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 200;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.com/";
              Hatena.BookmarkWidget.title = "旧人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 0;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module visible-desktop">
            <div class="title">twitter</div>
            <a class="twitter-timeline" data-dnt="true" href="https://twitter.com/dekokun" data-widget-id="306408547573440513">@dekokun からのツイート</a>
            <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
          </div>
          <div class="sidebar-module hidden-phone">
            <div class="title">RSS</div>
            <p><a href="../rss.xml"><img src="../img/rss.gif" alt="rss"></a></p>
          </div>
        </aside> <!-- /span3 -->
      </div> <!-- /row -->
      <footer>
        <p>©<script type="text/javascript">$y=2012;$ny=new Date().getFullYear();document.write($ny>$y?$y+'-'+$ny:$y);</script> <a href="https://twitter.com/dekokun">dekokun</a></p>
      </footer>
    </div> <!-- /container -->

    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script>window.jQuery || document.write('<script src="../js/libs/jquery-1.7.2.min.js"><\/script>')</script>
    <!-- /ツイートボタン -->
  <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>

    <script src="../js/libs/bootstrap/bootstrap.min.js"></script>

    <script src="../js/script.js"></script>
    <script>
      var _gaq=[['_setAccount','UA-XXXXX-X'],['_trackPageview']];
      (function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
      g.src=('https:'==location.protocol?'//ssl':'//www')+'.google-analytics.com/ga.js';
      s.parentNode.insertBefore(g,s)}(document,'script'));
    </script>
    <!-- Code syntax highlight -->
    <script type="text/javascript" src="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.js"></script>
    <script type="text/javascript">
    $(function(){ 
        $('pre').css({
            'overflow-x': 'scroll',
            'background-color': '#f6f6f6',
            'border': '1px dotted #ccc',
            'padding': '0.8em'
        });
        $('pre code').addClass('prettyprint');
        prettyPrint();
    });
    </script>
    <script type="text/javascript" src="https://d1xnn692s7u6t6.cloudfront.net/widget.js"></script>
    <script type="text/javascript">(function k(){window.$SendToKindle&&window.$SendToKindle.Widget?$SendToKindle.Widget.init({"content":"article"}):setTimeout(k,500);})();</script>
  </body>
</html>
]]></description>
    <pubDate>No date found.</pubDate>
    <guid>http://dekokun.github.io/posts/2013-02-24.html</guid>
</item>
<item>
    <title>Composerからプロジェクト内にインストールしたPhingをJenkinsで実行</title>
    <link>http://dekokun.github.io/posts/2013-03-06.html</link>
    <description><![CDATA[<!doctype html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7" lang="ja"> <![endif]-->
<!--[if IE 7]>    <html class="no-js lt-ie9 lt-ie8" lang="ja"> <![endif]-->
<!--[if IE 8]>    <html class="no-js lt-ie9" lang="ja"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="ja"> <!--<![endif]-->
  <head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# article: http://ogp.me/ns/article#">
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <title>Composerからプロジェクト内にインストールしたPhingをJenkinsで実行</title>
    <meta name="description" content>
    <meta name="author" content>

    <meta name="viewport" content="width=device-width">
    <meta property="fb:app_id" content="351187098330864">
    <meta property="og:type" content="article">
    <meta property="og:image" content="http://dekokun.github.com/img/dekokun.png">
    <meta property="og:title" content="Composerからプロジェクト内にインストールしたPhingをJenkinsで実行">
    <meta property="og:description" content="@dekokunの技術日記">
    <meta property="og:site_name" content="でこてっくろぐ">
    <meta name="twitter:widgets:csp" content="on">

    <link rel="stylesheet" href="../css/bootstrap.css">
    <link rel="stylesheet" href="../css/bootstrap-responsive.css">
    <link rel="stylesheet" href="../css/style.css">
    <style>
    body {
      padding-top: 60px;
      padding-bottom: 40px;
    }
    </style>
    <link href="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.css" type="text/css" rel="stylesheet">
    <script src="../js/libs/modernizr-2.5.3-respond-1.1.0.min.js"></script>
    <script>
      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

      ga('create', 'UA-39650556-1', 'auto');
      ga('send', 'pageview');
    </script>
  </head>
  <body>
  <!--[if lt IE 7]><p class=chromeframe>Your browser is <em>ancient!</em> <a href="http://browsehappy.com/">Upgrade to a different browser</a> or <a href="http://www.google.com/chromeframe/?redirect=true">install Google Chrome Frame</a> to experience this site.</p><![endif]-->
    <div id="fb-root"></div>
    <script>(function(d, s, id) {
      var js, fjs = d.getElementsByTagName(s)[0];
      if (d.getElementById(id)) return;
      js = d.createElement(s); js.id = id;
      js.src = "//connect.facebook.net/ja_JP/all.js#xfbml=1&appId=351187098330864";
      fjs.parentNode.insertBefore(js, fjs);
      }(document, 'script', 'facebook-jssdk'));
    </script>
    <header>
      <nav class="navbar navbar-fixed-top">
        <div class="navbar-inner">
          <div class="container">
            <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
            </a>
            <a class="brand" href="../index.html">でこてっくろぐ</a>
            <div class="nav-collapse">
              <ul class="nav">
                <li><a href="../index.html">ほーむ</a></li>
                <li><a href="../posts.html">あーかいぶ</a></li>
                <li><a href="../aboutme.html">あばうとみー</a></li>
              </ul>
            </div><!--/.nav-collapse -->
          </div>
        </div>
      </nav>
    </header>

    <div class="container">
      <div class="row">
        <article class="span9">
          <h1>Composerからプロジェクト内にインストールしたPhingをJenkinsで実行</h1>

<p>by <em><a href="https://twitter.com/dekokun">@dekokun</a></em> on <strong>2013/03/06 7:34</strong></p>

<p>Tagged as: <a href="../tags/Composer.html">Composer</a>, <a href="../tags/PHP.html">PHP</a>, <a href="../tags/Phing.html">Phing</a>, <a href="../tags/Jenkins.html">Jenkins</a>.</p>

<p>皆さん、<a href="http://ant.apache.org/">Apache Ant</a>をベースとしたPHPのプロジェクトビルドシステム、<a href="http://www.phing.info/">Phing</a>を使ってますか？</p>
<p>今日はComposerでインストールしたPhingをJenkinsから起動する方法について</p>
<h2 id="概要">概要</h2>
<p>Jenkinsからのビルド中に<code>php composer.phar install</code>でvendorディレクトリ下にインストールしたPhingを使用しビルドを行う方法について。 ついでに、JenkinsのPhingプラグインのハマりどころなど(今回の解決策ではPhingプラグインを使ってないけど)</p>
<h2 id="解答">解答</h2>
<p>ジョブの設定の「シェルの実行」から</p>
<p><code>vendor/bin/phing -logger phing.listener.DefaultLogger</code></p>
<p>-loggerの部分を指定しないとJenkinsの「コンソール出力」上で確認できるログに、ターミナル上で色をつけるための制御文字が出力され表示が崩れます。</p>
<p>めでたしめでたし。…こんな誰でも思いつく方法ですみませんすみません＞＜</p>
<p>結論としては、JenkinsのPhingプラグインの現在の挙動では要件を満たせないという話なのでした。</p>
<h2 id="jenkinsのphingプラグインについて">JenkinsのPhingプラグインについて</h2>
<ul>
<li>今回はプロジェクト内にビルドの一環でインストールするPhingを相対パス指定で実行したかったわけですが、Phingプラグインは絶対パスでの指定かつ、すでに存在しているPhingでないと実行してくれなかったため使うのはやめました。これはこれで妥当な挙動だとは思うので、pull requestを送るかどうかは要検討(Jenkinsのプラグインがどのようにできているかを知らないため、その勉強の意味でやってみようかしら)。</li>
<li>今回の記事とは関係ないですが、JenkinsのPhingプラグインの設定のPHING_HOME欄の入力は間違えやすいので注意。Phingの実行ファイルを指定するのではなく、Phingのclassesとbinディレクトリが存在するディレクトリを指定する必要があります。phingの実行ファイルを指定しても、“/hoge/fuga/phing/bin/phingが存在しません。”というエラーが出ます。ググったところ同じような現象で悩んでいる人がちらほらいるようですね。</li>
</ul>
<h2 id="あとがき">あとがき</h2>
<p>どうでもいいですが、Phing使ってるPHPユーザってどれくらいいるんだろうか…</p>
<p>Phingのプロジェクトを作成しながら、「2013年にもなってなぜAntのことを調べているんだ私は」という思いがひしひしとしました。</p>
<p>みんな<a href="http://www.php-maven.org/">Maven for PHP</a>使ってたりするのかな。</p>

<div id="disqus_thread"></div>
<script type="text/javascript">
    /* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */
    var disqus_shortname = 'dekokun'; // required: replace example with your forum shortname

    /* * * DON'T EDIT BELOW THIS LINE * * */
    (function() {
        var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
        dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js';
        (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
    })();
</script>
<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
<a href="http://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a>

          <ul class="social">
            <li class="kindle"><div class="kindleWidget"><img style="vertical-align:middle;" src="https://d1xnn692s7u6t6.cloudfront.net/white-15.png" /><span style="vertical-align:middle;margin-left:3px;">Send to Kindle</span></div></li>
            <li class="facebook"><div class="fb-like" data-send="false" data-layout="button_count" data-width="100" data-show-faces="true" data-font="arial"></div></li>
            <li class="twitter"><a href="https://twitter.com/share" class="twitter-share-button" data-via="dekokun" data-lang="ja">ツイート</a></li>
            <li class="hatena-bookmark"><a href="http://b.hatena.ne.jp/entry/" class="hatena-bookmark-button" data-hatena-bookmark-layout="standard" title="このエントリーをはてなブックマークに追加"><img src="http://b.st-hatena.com/images/entry-button/button-only.gif" alt="このエントリーをはてなブックマークに追加" width="20" height="20" style="border: none;"></a><script type="text/javascript" src="http://b.st-hatena.com/js/bookmark_button.js" charset="utf-8" async="async"></script></li>
            <li><a data-pocket-label="pocket" data-pocket-count="horizontal" class="pocket-btn" data-lang="en"></a>
            <script type="text/javascript">!function(d,i){if(!d.getElementById(i)){var j=d.createElement("script");j.id=i;j.src="https://widgets.getpocket.com/v1/j/btn.js?v=1";var w=d.getElementById(i);d.body.appendChild(j);}}(document,"pocket-btn-js");</script></li>
          </ul>

        </article>
        <aside class="span3">
          <div class="sidebar-module">
            <div class="title">プロフィール</div>
            <p class="id"><a href="https://twitter.com/dekokun">dekokun</a></p>
            <p><a href="https://twitter.com/dekokun"><img src="../img/dekokun.png" alt="dekokun"></a></p>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.io/";
              Hatena.BookmarkWidget.title = "人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 200;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.com/";
              Hatena.BookmarkWidget.title = "旧人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 0;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module visible-desktop">
            <div class="title">twitter</div>
            <a class="twitter-timeline" data-dnt="true" href="https://twitter.com/dekokun" data-widget-id="306408547573440513">@dekokun からのツイート</a>
            <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
          </div>
          <div class="sidebar-module hidden-phone">
            <div class="title">RSS</div>
            <p><a href="../rss.xml"><img src="../img/rss.gif" alt="rss"></a></p>
          </div>
        </aside> <!-- /span3 -->
      </div> <!-- /row -->
      <footer>
        <p>©<script type="text/javascript">$y=2012;$ny=new Date().getFullYear();document.write($ny>$y?$y+'-'+$ny:$y);</script> <a href="https://twitter.com/dekokun">dekokun</a></p>
      </footer>
    </div> <!-- /container -->

    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script>window.jQuery || document.write('<script src="../js/libs/jquery-1.7.2.min.js"><\/script>')</script>
    <!-- /ツイートボタン -->
  <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>

    <script src="../js/libs/bootstrap/bootstrap.min.js"></script>

    <script src="../js/script.js"></script>
    <script>
      var _gaq=[['_setAccount','UA-XXXXX-X'],['_trackPageview']];
      (function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
      g.src=('https:'==location.protocol?'//ssl':'//www')+'.google-analytics.com/ga.js';
      s.parentNode.insertBefore(g,s)}(document,'script'));
    </script>
    <!-- Code syntax highlight -->
    <script type="text/javascript" src="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.js"></script>
    <script type="text/javascript">
    $(function(){ 
        $('pre').css({
            'overflow-x': 'scroll',
            'background-color': '#f6f6f6',
            'border': '1px dotted #ccc',
            'padding': '0.8em'
        });
        $('pre code').addClass('prettyprint');
        prettyPrint();
    });
    </script>
    <script type="text/javascript" src="https://d1xnn692s7u6t6.cloudfront.net/widget.js"></script>
    <script type="text/javascript">(function k(){window.$SendToKindle&&window.$SendToKindle.Widget?$SendToKindle.Widget.init({"content":"article"}):setTimeout(k,500);})();</script>
  </body>
</html>
]]></description>
    <pubDate>No date found.</pubDate>
    <guid>http://dekokun.github.io/posts/2013-03-06.html</guid>
</item>
<item>
    <title>ブログにSend to Kindleボタンを追加してKindleでブログを読めるようにしよう</title>
    <link>http://dekokun.github.io/posts/2013-03-21.html</link>
    <description><![CDATA[<!doctype html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7" lang="ja"> <![endif]-->
<!--[if IE 7]>    <html class="no-js lt-ie9 lt-ie8" lang="ja"> <![endif]-->
<!--[if IE 8]>    <html class="no-js lt-ie9" lang="ja"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="ja"> <!--<![endif]-->
  <head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# article: http://ogp.me/ns/article#">
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <title>ブログにSend to Kindleボタンを追加してKindleでブログを読めるようにしよう</title>
    <meta name="description" content>
    <meta name="author" content>

    <meta name="viewport" content="width=device-width">
    <meta property="fb:app_id" content="351187098330864">
    <meta property="og:type" content="article">
    <meta property="og:image" content="http://dekokun.github.com/img/dekokun.png">
    <meta property="og:title" content="ブログにSend to Kindleボタンを追加してKindleでブログを読めるようにしよう">
    <meta property="og:description" content="@dekokunの技術日記">
    <meta property="og:site_name" content="でこてっくろぐ">
    <meta name="twitter:widgets:csp" content="on">

    <link rel="stylesheet" href="../css/bootstrap.css">
    <link rel="stylesheet" href="../css/bootstrap-responsive.css">
    <link rel="stylesheet" href="../css/style.css">
    <style>
    body {
      padding-top: 60px;
      padding-bottom: 40px;
    }
    </style>
    <link href="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.css" type="text/css" rel="stylesheet">
    <script src="../js/libs/modernizr-2.5.3-respond-1.1.0.min.js"></script>
    <script>
      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

      ga('create', 'UA-39650556-1', 'auto');
      ga('send', 'pageview');
    </script>
  </head>
  <body>
  <!--[if lt IE 7]><p class=chromeframe>Your browser is <em>ancient!</em> <a href="http://browsehappy.com/">Upgrade to a different browser</a> or <a href="http://www.google.com/chromeframe/?redirect=true">install Google Chrome Frame</a> to experience this site.</p><![endif]-->
    <div id="fb-root"></div>
    <script>(function(d, s, id) {
      var js, fjs = d.getElementsByTagName(s)[0];
      if (d.getElementById(id)) return;
      js = d.createElement(s); js.id = id;
      js.src = "//connect.facebook.net/ja_JP/all.js#xfbml=1&appId=351187098330864";
      fjs.parentNode.insertBefore(js, fjs);
      }(document, 'script', 'facebook-jssdk'));
    </script>
    <header>
      <nav class="navbar navbar-fixed-top">
        <div class="navbar-inner">
          <div class="container">
            <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
            </a>
            <a class="brand" href="../index.html">でこてっくろぐ</a>
            <div class="nav-collapse">
              <ul class="nav">
                <li><a href="../index.html">ほーむ</a></li>
                <li><a href="../posts.html">あーかいぶ</a></li>
                <li><a href="../aboutme.html">あばうとみー</a></li>
              </ul>
            </div><!--/.nav-collapse -->
          </div>
        </div>
      </nav>
    </header>

    <div class="container">
      <div class="row">
        <article class="span9">
          <h1>ブログにSend to Kindleボタンを追加してKindleでブログを読めるようにしよう</h1>

<p>by <em><a href="https://twitter.com/dekokun">@dekokun</a></em> on <strong>2013/03/21 1:30</strong></p>

<p>Tagged as: <a href="../tags/Kindle.html">Kindle</a>, <a href="../tags/日記改造.html">日記改造</a>.</p>

<p><a href="http://jp.techcrunch.com/2013/03/20/20130319amazon-launches-send-to-kindle-button-for-web-developers-wordpress-blogs/">Amazonが[Send to Kindle]（コンテンツをKindleへ送る）ボタンをローンチ</a>を読み、昨日あたりからブログ記事にSend to Kindleボタンを置けるようになったことがわかりましたので、早速ブログにボタンをつけてみました。</p>
<p>これまでも、<a href="http://www.amazon.com/gp/sendtokindle/chrome">Chrome拡張</a>や<a href="http://www.amazon.com/gp/sendtokindle/firefox">Firefox拡張</a>、<a href="http://www.amazon.com/gp/sendtokindle/email">E-mailを使用した方法</a>などでWebサイトをKindleに送ることはできていたようですが(全く知らなかった)、ブログ側に専用のボタンを設置することで、ユーザが頑張らなくても簡単にKindleにブログ記事を送ることができるようになるわけです。</p>
<h2 id="方法">方法</h2>
<p>今回は、WordPress以外の場合の説明をします。 WordPress上のブログにSend to Kindleボタンを作成する場合は専用のプラグインがあるようですので、どうぞ</p>
<ul>
<li><a href="http://wordpress.org/extend/plugins/send-to-kindle/">Send to Kindle</a></li>
</ul>
<p>それでは、以下、簡単な説明。</p>
<ol style="list-style-type: decimal">
<li><a href="http://www.amazon.com/gp/sendtokindle/developers/button">The Send to Kindle Button for Websites</a>に行く
<ul>
<li>“Choose your button style”で見た目を選択</li>
<li>“How do you mark the title, author, and publication date on your pages?”の部分は、facebookボタンなどでOGP設定を行なっている場合は“Open Graph”を選択し、それ以外の場合は“Custom CSS Selectors”を選択しタイトルや作者の名前を、CSSセレクタ形式で選択
<ul>
<li>scheme.org, hNewsの方法で指定することもできるが、私は両形式に詳しくないため割愛</li>
<li>私の場合はすでにOGP設定を行なっていたため“Open Graph”で</li>
</ul></li>
<li>“How do you mark the main body of content on your pages?”の部分は、実際に配信したい部分をCSSセレクタ形式で選択
<ul>
<li>こちらもscheme.org, hNewsの方法で指定することもできるが、私は両形式に詳しくないため割愛</li>
<li>私の場合はarticleタグ内を全て配信したかったため、“article”で</li>
</ul></li>
<li>“Do you sell a periodicals subscription on Kindle?”は“No”で
<ul>
<li>Kindle Storeで定期刊行物を販売している際にYesを選択すると、定期刊行物にブログ記事を含ませることができるっぽい。<a href="http://www.amazon.com/dp/B000HC48T0">The Washington Post for Kindle (Ad-Free)</a>とかがそうしているそうな。</li>
</ul></li>
</ul></li>
<li>“Generate widget code”ボタンを押下</li>
<li>生成されたコードを自分のブログに貼り付ける
<ul>
<li>“Step 1”のJavaScriptは、bodyタグの最後に貼り付ける</li>
<li>“Step 2”のHTMLは、“Send to Kindle”ボタンを置きたい場所に貼り付ける</li>
</ul></li>
</ol>
<p>完了。めでたしめでたし。</p>
<h2 id="注意点">注意点</h2>
<ul>
<li><a href="https://www.amazon.com/gp/help/customer/display.html?nodeId=200767340#usb">対応しているKindleクライアント</a>に対してしか送ることができません</li>
<li>amazon.comのアカウントに紐付いたKindleクライアントにしか送ることができません(amazon.co.jpのアカウントには送れません)
<ul>
<li><a href="http://www.amazon.co.jp/gp/help/customer/display.html/?nodeId=201049300">アカウント統合</a>していれば可能なようですが、実際どれくらいの人がアカウント統合しているのだろうか…</li>
<li>ちなみに、私はamazon.comのアカウントでSend to Kindleボタンのテストを行いましたが、統合したアカウントではテストをおこなっていないため本当にアカウント統合でいけるのかどうかは知りません。誰か教えてください。</li>
<li>これじゃ日本のブログに「Send to Kindle」ボタンをつけても恩恵にあずかることのできる読者はほとんどいないのでは、というかただの害悪である場合のほうが多いかもしれないですね
<ul>
<li>読者A「おっ、[Send to Kindle]だって。Kindleに送れるのか！ポチッとな」…「あれ、対応デバイスが無いって出てる。死ね」みたいな</li>
</ul></li>
</ul></li>
<li>amazon.comのアカウントに紐づく対応クライアントがない場合は、Send to Kindleボタンを押した際に以下のようなメッセージが表示される</li>
</ul>
<blockquote>
<p>You don’t have a supported Kindle device or reading app. For a list of supported devices, click <a href="https://www.amazon.com/gp/help/customer/display.html?nodeId=200767340#usb">here</a>.</p>
</blockquote>
<h2 id="何が便利なんですか">何が便利なんですか</h2>
<p><a href="https://twitter.com/imarikaratsu/statuses/314263521561047040">“あとで読むサービスに近い”</a>とおっしゃっているかたがいて、確かにそうかもしれないなと思いました。</p>
<p>Chrome拡張とかをいれなくてもそれができるようになったってのは嬉しいんじゃないですかね。</p>
<p>他に、どんな嬉しいことがあるのかな。誰か教えてください。</p>
<p>まぁ、そもそも、amazon.co.jpのアカウントに対応したKindleで読めなくちゃほとんど嬉しくないですけどね…</p>
<p>以上、めでたしめでたし</p>
<h2 id="追記">2013/03/21 1:41 追記</h2>
<p>あ、すでに同様の記事を書いているかたがいらっしゃった。こちらは写真入りだー！</p>
<p>こちらのタイトルなどの指定方法は、schema.org方式ですね。</p>
<ul>
<li><a href="http://www.kaoritter.com/archives/2013/0320_211756.html">早速ブログに Send to Kindle ボタンを導入してみたのだが・・・</a></li>
</ul>

<div id="disqus_thread"></div>
<script type="text/javascript">
    /* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */
    var disqus_shortname = 'dekokun'; // required: replace example with your forum shortname

    /* * * DON'T EDIT BELOW THIS LINE * * */
    (function() {
        var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
        dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js';
        (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
    })();
</script>
<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
<a href="http://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a>

          <ul class="social">
            <li class="kindle"><div class="kindleWidget"><img style="vertical-align:middle;" src="https://d1xnn692s7u6t6.cloudfront.net/white-15.png" /><span style="vertical-align:middle;margin-left:3px;">Send to Kindle</span></div></li>
            <li class="facebook"><div class="fb-like" data-send="false" data-layout="button_count" data-width="100" data-show-faces="true" data-font="arial"></div></li>
            <li class="twitter"><a href="https://twitter.com/share" class="twitter-share-button" data-via="dekokun" data-lang="ja">ツイート</a></li>
            <li class="hatena-bookmark"><a href="http://b.hatena.ne.jp/entry/" class="hatena-bookmark-button" data-hatena-bookmark-layout="standard" title="このエントリーをはてなブックマークに追加"><img src="http://b.st-hatena.com/images/entry-button/button-only.gif" alt="このエントリーをはてなブックマークに追加" width="20" height="20" style="border: none;"></a><script type="text/javascript" src="http://b.st-hatena.com/js/bookmark_button.js" charset="utf-8" async="async"></script></li>
            <li><a data-pocket-label="pocket" data-pocket-count="horizontal" class="pocket-btn" data-lang="en"></a>
            <script type="text/javascript">!function(d,i){if(!d.getElementById(i)){var j=d.createElement("script");j.id=i;j.src="https://widgets.getpocket.com/v1/j/btn.js?v=1";var w=d.getElementById(i);d.body.appendChild(j);}}(document,"pocket-btn-js");</script></li>
          </ul>

        </article>
        <aside class="span3">
          <div class="sidebar-module">
            <div class="title">プロフィール</div>
            <p class="id"><a href="https://twitter.com/dekokun">dekokun</a></p>
            <p><a href="https://twitter.com/dekokun"><img src="../img/dekokun.png" alt="dekokun"></a></p>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.io/";
              Hatena.BookmarkWidget.title = "人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 200;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.com/";
              Hatena.BookmarkWidget.title = "旧人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 0;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module visible-desktop">
            <div class="title">twitter</div>
            <a class="twitter-timeline" data-dnt="true" href="https://twitter.com/dekokun" data-widget-id="306408547573440513">@dekokun からのツイート</a>
            <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
          </div>
          <div class="sidebar-module hidden-phone">
            <div class="title">RSS</div>
            <p><a href="../rss.xml"><img src="../img/rss.gif" alt="rss"></a></p>
          </div>
        </aside> <!-- /span3 -->
      </div> <!-- /row -->
      <footer>
        <p>©<script type="text/javascript">$y=2012;$ny=new Date().getFullYear();document.write($ny>$y?$y+'-'+$ny:$y);</script> <a href="https://twitter.com/dekokun">dekokun</a></p>
      </footer>
    </div> <!-- /container -->

    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script>window.jQuery || document.write('<script src="../js/libs/jquery-1.7.2.min.js"><\/script>')</script>
    <!-- /ツイートボタン -->
  <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>

    <script src="../js/libs/bootstrap/bootstrap.min.js"></script>

    <script src="../js/script.js"></script>
    <script>
      var _gaq=[['_setAccount','UA-XXXXX-X'],['_trackPageview']];
      (function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
      g.src=('https:'==location.protocol?'//ssl':'//www')+'.google-analytics.com/ga.js';
      s.parentNode.insertBefore(g,s)}(document,'script'));
    </script>
    <!-- Code syntax highlight -->
    <script type="text/javascript" src="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.js"></script>
    <script type="text/javascript">
    $(function(){ 
        $('pre').css({
            'overflow-x': 'scroll',
            'background-color': '#f6f6f6',
            'border': '1px dotted #ccc',
            'padding': '0.8em'
        });
        $('pre code').addClass('prettyprint');
        prettyPrint();
    });
    </script>
    <script type="text/javascript" src="https://d1xnn692s7u6t6.cloudfront.net/widget.js"></script>
    <script type="text/javascript">(function k(){window.$SendToKindle&&window.$SendToKindle.Widget?$SendToKindle.Widget.init({"content":"article"}):setTimeout(k,500);})();</script>
  </body>
</html>
]]></description>
    <pubDate>No date found.</pubDate>
    <guid>http://dekokun.github.io/posts/2013-03-21.html</guid>
</item>
<item>
    <title>Python製デプロイツール Fabricを初めて使う際に役立つTips</title>
    <link>http://dekokun.github.io/posts/2013-04-07.html</link>
    <description><![CDATA[<!doctype html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7" lang="ja"> <![endif]-->
<!--[if IE 7]>    <html class="no-js lt-ie9 lt-ie8" lang="ja"> <![endif]-->
<!--[if IE 8]>    <html class="no-js lt-ie9" lang="ja"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="ja"> <!--<![endif]-->
  <head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# article: http://ogp.me/ns/article#">
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <title>Python製デプロイツール Fabricを初めて使う際に役立つTips</title>
    <meta name="description" content>
    <meta name="author" content>

    <meta name="viewport" content="width=device-width">
    <meta property="fb:app_id" content="351187098330864">
    <meta property="og:type" content="article">
    <meta property="og:image" content="http://dekokun.github.com/img/dekokun.png">
    <meta property="og:title" content="Python製デプロイツール Fabricを初めて使う際に役立つTips">
    <meta property="og:description" content="@dekokunの技術日記">
    <meta property="og:site_name" content="でこてっくろぐ">
    <meta name="twitter:widgets:csp" content="on">

    <link rel="stylesheet" href="../css/bootstrap.css">
    <link rel="stylesheet" href="../css/bootstrap-responsive.css">
    <link rel="stylesheet" href="../css/style.css">
    <style>
    body {
      padding-top: 60px;
      padding-bottom: 40px;
    }
    </style>
    <link href="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.css" type="text/css" rel="stylesheet">
    <script src="../js/libs/modernizr-2.5.3-respond-1.1.0.min.js"></script>
    <script>
      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

      ga('create', 'UA-39650556-1', 'auto');
      ga('send', 'pageview');
    </script>
  </head>
  <body>
  <!--[if lt IE 7]><p class=chromeframe>Your browser is <em>ancient!</em> <a href="http://browsehappy.com/">Upgrade to a different browser</a> or <a href="http://www.google.com/chromeframe/?redirect=true">install Google Chrome Frame</a> to experience this site.</p><![endif]-->
    <div id="fb-root"></div>
    <script>(function(d, s, id) {
      var js, fjs = d.getElementsByTagName(s)[0];
      if (d.getElementById(id)) return;
      js = d.createElement(s); js.id = id;
      js.src = "//connect.facebook.net/ja_JP/all.js#xfbml=1&appId=351187098330864";
      fjs.parentNode.insertBefore(js, fjs);
      }(document, 'script', 'facebook-jssdk'));
    </script>
    <header>
      <nav class="navbar navbar-fixed-top">
        <div class="navbar-inner">
          <div class="container">
            <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
            </a>
            <a class="brand" href="../index.html">でこてっくろぐ</a>
            <div class="nav-collapse">
              <ul class="nav">
                <li><a href="../index.html">ほーむ</a></li>
                <li><a href="../posts.html">あーかいぶ</a></li>
                <li><a href="../aboutme.html">あばうとみー</a></li>
              </ul>
            </div><!--/.nav-collapse -->
          </div>
        </div>
      </nav>
    </header>

    <div class="container">
      <div class="row">
        <article class="span9">
          <h1>Python製デプロイツール Fabricを初めて使う際に役立つTips</h1>

<p>by <em><a href="https://twitter.com/dekokun">@dekokun</a></em> on <strong>2013/04/07 19:30</strong></p>

<p>Tagged as: <a href="../tags/Python.html">Python</a>, <a href="../tags/Fabric.html">Fabric</a>, <a href="../tags/デプロイツール.html">デプロイツール</a>.</p>

<p>2013/04/09 追記 意外と反響があるようなので、Tips追加しました。 2013/05/10 追記 並列実行について調べたのでついでに追記</p>
<p>「次のプロダクトはシンプルなデプロイツールだと噂の<a href="http://d.hatena.ne.jp/naoya/20130118/1358477523">Cinnamon</a>でも使ってみるかー」と言っていたら、「Cinnamonは使ってるユーザ数が少なそうだし同様のことが行えるFabricのほうがいいんじゃないですかね。」というツッコミをいただき、今回はPerlのプロジェクトでもないためFabricを使用することにしました。</p>
<p>初めて触るFabric、やはり初学者にはいろいろとよくわからない部分があったため、はまって解決したことや便利なTipsなどをつらつらと列挙していきます。</p>
<p>なお、以下情報はPython2.7及びFabric1.6でのみ検証しています。</p>
<p>以下、Tipsです。</p>
<h2 id="日本人がはじめの一歩を踏み出すには">日本人がはじめの一歩を踏み出すには</h2>
<p>以下を参考にするといいでしょう。バージョンが古いですが、特に問題ないかと。私もpipでインストールしました。</p>
<ul>
<li><a href="http://skitazaki.github.io/python-school-ja/cmdline/cmdline-6.html">Python School 1.5.0 documentation</a></li>
</ul>
<p>英語でもいいなら、以下本家のドキュメントがいいんじゃないですかね。</p>
<ul>
<li><a href="http://docs.fabfile.org/en/1.6/tutorial.html">Overview and Tutorial</a></li>
</ul>
<h2 id="run関数を呼んだ際リモートサーバ側では実際にどのように実行されているんですか">run関数を呼んだ際、リモートサーバ側では実際にどのように実行されているんですか</h2>
<p>わざと失敗してみるとわかりますが、以下のようにbash -l -cで実行しています。</p>
<pre><code>from fabric.api import run

def exittest():
  run('exit 1')

## Requested: exit 1
## Executed: /bin/bash -l -c &quot;exit 1&quot;</code></pre>
<h2 id="scpがしたい">SCPがしたい</h2>
<p>デプロイの際など、ローカルのファイルをリモートに送りたい場合などありますよね。local(‘scp hoge fuga@host:…’)などしてもいいですが、もっといい方法があります。</p>
<p>(2013/04/13 追記) コメントいただきました。fabricのputはSCPではなくSFTPなのですね(参照：fabric/operations.py 及び fabric/sftp.py)。ありがとうございます。</p>
<h3 id="解決策">解決策</h3>
<p>put関数を使いましょう。</p>
<pre><code>from fabric.api import put

def scp():
  put('local path', 'remote path')</code></pre>
<p>local pathの部分はワイルドカードも使えますよ。もちろんディレクトリも送ることができます。</p>
<ul>
<li><a href="http://docs.fabfile.org/en/1.4.3/api/core/operations.html#fabric.operations.put">fabric.operations.put</a></li>
</ul>
<h2 id="実行される際の環境変数を変更したい">実行される際の環境変数を変更したい</h2>
<p>ローカル実行、リモート実行共に、環境変数を規定して何かを実行したい場合がありますよね。</p>
<h3 id="解決策-1">解決策</h3>
<p>shell_env関数を使いましょう</p>
<pre><code>from fabric.api import local, shell_env, run

def envtest():
  with shell_env(HOGE='fuga'):
    local('env')
    run('env')</code></pre>
<p>上記のように、同じ環境変数をローカルとリモート両方で使用できます。</p>
<p>上記だと、export HOGE=“fuga”が呼ばれた後に後続のコマンドが実行されます。</p>
<h2 id="どこかにcdしてコマンドを実行させたい">どこかにcdしてコマンドを実行させたい</h2>
<p>デプロイの際にcd repo_path &amp;&amp; git fetch &amp;&amp; git checkoutみたいなことしたいこともありますよね</p>
<h3 id="解決策-2">解決策</h3>
<p>リモートでcdする場合はcd関数、ローカルでcdする場合はlcd関数を実行しましょう。</p>
<p>with構文を抜けると、cd, lcdの効果はなくなります。</p>
<pre><code>from fabric.api import run, local, cd, lcd

def cdtest():
  local('mkdir -p hoge')
  run('mkdir -p hoge')
  with cd('hoge'):
    local('pwd')
    run('pwd')

  with lcd('hoge'):
    local('pwd')
    run('pwd')</code></pre>
<h2 id="開発環境と本番環境用にデプロイ先を分けたい">開発環境と本番環境用にデプロイ先を分けたい</h2>
<p>まぁ、デプロイツールであれば当然の要求ですよね</p>
<h3 id="解決策-3">解決策</h3>
<p>方法がいくつか考えられます。デプロイ先毎にタスクを分ける方法と、デプロイ先を定義するタスクを作り、そのタスクを呼ぶことでデプロイ先を切り替える方法。(その他もろもろ)</p>
<pre><code>from fabric.api import env

# デプロイ先毎にタスクを分ける方法
def dev_deploy():
  deploy('devserver')

def production():
  deploy('prodserver')

def deploy(server):
  env.hosts = [server]
  ...

# タスクのなかでデプロイ先を定義
# $ fab develop deploy など、デプロイ先を定義するタスクを呼ぶことでデプロイ先を制御
def develop():
  env.user = 'devuser'
  env.hosts = ['dev']

def production():
  env.user = 'produser'
  env.hosts = ['prod.server.com', 'prod2.server.com']

def deploy():
  ...</code></pre>
<p>とにかく、なんらかの方法でenv.hostsやenv.userを書き換えればよいです。</p>
<p>他にも$ fab deploy:devserver など、コマンドラインでデプロイ先をタスクに直接与える方法や、デフォルトの$ fab -Hでデプロイ先を指定する方法など、いろいろ考えられますね。</p>
<p>私は、fabfileでデプロイ先をバージョン管理したいかつ、一番柔軟な方法を取りたいという思いがあり、上記の「タスクのなかでデプロイ先を定義」を採用しています。</p>
<h2 id="ロールを分けたい">ロールを分けたい</h2>
<p>デプロイツールであれば、「本番環境のなかにもWebサーバとツールサーバがあり、それぞれデプロイする内容が違う」ということを行いたい欲求は確実に出てきます。Ruby製デプロイツールのCapistranoにあるロールのようなものが欲しいですよね。</p>
<h3 id="解決策-4">解決策</h3>
<p>roledefsでロールを定義し、デコレータを使用してタスクにロールを紐付けることができます。</p>
<pre><code>from fabric.api import env
from fabric.decorators import roles

def production(user='vagrant'):
    env.user = user
    env.roledefs.update({
        'webservers': ['host1', 'host2'],
        'toolservers': ['host3'],
        })

def develop(user='vagrant'):
    env.user = user
    env.roledefs.update({
        'webservers': ['host4'],
        'toolservers': ['host2'],
        })

@roles('webserver')
def webserver_deploy
    ...

# $ fab develop webserver_deploy とすれば、develop環境のWebサーバに対して対象のタスクが実行されます。</code></pre>
<h2 id="fabfileに関数を作成したいけどタスクとして実行できないようにしたい">fabfileに関数を作成したいけどタスクとして実行できないようにしたい</h2>
<p>fabファイルの中で普通に関数を定義するとタスクとして実行可能になってしまい気持ちが悪いので、補助用の関数はタスクとしてコマンドラインから実行できないようにしたいですね。</p>
<h3 id="解決策-5">解決策</h3>
<p>サブタスクにしたい関数名の初めにアンダーバーを入れろ。以上(疲れてきた)</p>
<h2 id="引数指定したい">引数指定したい</h2>
<p>タスクに引数を渡したい場合がありますよね。</p>
<h3 id="解決策-6">解決策</h3>
<p>$ fab hoge:fuga</p>
<p>でhoge関数の第一引数に’fuga’を渡すことができます。</p>
<p>$ fab hello:name=Jeff とかね。最初に提示したチュートリアル(<a href="http://docs.fabfile.org/en/1.6/tutorial.html">Overview and Tutorial</a>)に載っているから詳しくはそっち参考にしてね。</p>
<h2 id="ssh_configの設定を使用したい">ssh_configの設定を使用したい</h2>
<p>何もせずに.ssh/configの設定を使用しようとしても、.ssh/configを使用せずにsshで接続しようとしてしまいます。<code>Fatal error: Name lookup failed for server1</code>とかエラーメッセージが出たりしますよね。</p>
<h3 id="解決策-7">解決策</h3>
<p>以下1行を書いておけば、.ssh/configを使用してsshで接続してくれます。</p>
<pre><code>env.use_ssh_config = True</code></pre>
<h2 id="タスク内でホスト名を取得">タスク内でホスト名を取得</h2>
<p>なんでホスト名を取得したくなったのか忘れたが、とにかく取得したいと思ったことがあったのです。</p>
<h3 id="解決策-8">解決策</h3>
<p>env.hostを使えば良い感じです</p>
<p>以下で、タスクが各ホストに対して順番に実行されている様子が観察できます。</p>
<pre><code>env.hosts = ['host1', 'host2']

def hosttest():
  print env.host</code></pre>
<h2 id="タスク内で各ホストに対して並列実行したい">タスク内で各ホストに対して並列実行したい</h2>
<p>ホストが増えたら並列実行できないとお話になりませんよね。</p>
<h3 id="解決策-9">解決策</h3>
<p>$ fab -Pで、全てのタスクの中を並列実行にすることが可能です。</p>
<p>タスク毎に並列実行か直列実行かを指定したい場合は、以下のようにデコレータを使用してください。</p>
<pre><code>from fabric.api import env, run
from fabric.decorators import parallel

@parallel
def sleeptest():
  run('sleep 3')</code></pre>
<h2 id="タスク毎に同時並列最大数を規定したい">タスク毎に同時並列最大数を規定したい</h2>
<p>一気に全部並列実行はやばいけどチマチマserial実行は時間がかかりすぎるよねって時。capistranoのmax_hostで設定するのと同じようなことをしたいことってありますよね。</p>
<h3 id="解決策-10">解決策</h3>
<p>上記のparallelデコレータにpool_size=で最大同時実行数を指定しましょう</p>
<pre><code>from fabric.api import env, run
from fabric.decorators import parallel

@parallel(pool_size=2)
def sleeptest():
  run('sleep 3')</code></pre>
<h2 id="全タスクから見える変数を定義したい">全タスクから見える変数を定義したい</h2>
<p>まぁ、したいことありますよね。リポジトリのURLを定義したり、途中で状態を変えたり</p>
<h3 id="解決策-11">解決策</h3>
<p>envに値をセットすることでどこからでも取り出すことが可能になります。</p>
<p>ここ、本当にこれでいいんですかね。私はもっと定数的なものが欲しいんですけども。Fabric使いの人からのツッコミをお待ちしております。</p>
<pre><code>from fabric.api import env

env.test = 'hoge'

def envtest():
  print env.test
  env.test = 'fuga'

def envtest2():
  print env.test

# $ fab envtest envtest2
# hoge
# fuga

# Done.</code></pre>
<hr></hr>
<p>以下、2013/04/09追記</p>
<hr></hr>
<h2 id="コンフィグファイルを使いたい">コンフィグファイルを使いたい</h2>
<p>コンフィグファイルに設定を記載し、その情報を使ってデプロイをしたいことってありますよね。</p>
<h3 id="解決策-12">解決策</h3>
<p>.ini形式のファイルをfab -cオプションで指定することが可能です。-cオプションがない場合は$HOME/.fabricrcを読みにいきます。文字列しか指定できないため、配列で指定しなくてはいけないenv.hostsはコンフィグファイルに書けないのであまりうれしさはないけども。</p>
<p>fabricrc:</p>
<pre><code>user = vagrant
hoge = fuga</code></pre>
<p>fabfile.py:</p>
<pre><code>from fabric.api import env, run

env.hosts = ['server1', 'server2']

def deploy():
  run('deploy.sh')

def printenv():
  print(env.hoge)

# $ fab -c fabricrc deploy
# 上記で、fabricrcに指定したvagrantユーザに対してrunが走る
# $ fab -c fabricrc printenv
# 上記で'fuga'と出力される</code></pre>
<h2 id="env.hostsを別ファイルに切り出したい">env.hostsを別ファイルに切り出したい</h2>
<p>fabricをデプロイツールとして見た際に、やはりデプロイ先は別ファイルとして切り出したい感じありますよね。実際、<a href="https://twitter.com/ume3_/status/321304849612423168">そのような内容のツイートをいただきました</a>。productionとdevelopそれぞれに1ファイルずつあるとわかりやすいのではないかと。</p>
<h3 id="解決策-13">解決策</h3>
<p>力技で行きます。ファイルを行で分割して配列に格納します。本当にこの方法しかないのかな…過去にgithubのfabricのリポジトリ上で「env.hostsは設定ファイルで指定したい」「yamlがいいんじゃないか」等と議論していたのですが、特にその辺りの成果は出ていないようです。</p>
<p>以下でも力技の解決策で人々が頑張っている姿がみうけられます。</p>
<ul>
<li><a href="http://stackoverflow.com/questions/10391377/setting-fabric-hosts-list-from-an-external-hosts-file">Setting fabric hosts list from an external hosts file</a></li>
</ul>
<p>production.conf:</p>
<pre><code>server1
server2</code></pre>
<p>development.conf</p>
<pre><code>server3</code></pre>
<p>fabfile.py:</p>
<pre><code>from fabric.api import env, run

def product():
  env.user = 'pro_user'
  env.hosts = _get_servers('production.conf')

def develop():
  env.user = 'dev_user'
  env.hosts = _get_servers('development.conf')

def deploy():
  run('deploy.sh')

def _get_servers(file_name):
  servers = map((lambda x: x.rstrip()), open(file_name, 'r').readlines())
  while(True):
    try:
      servers.remove(&quot;&quot;)
    except ValueError:
      break
  return servers
# fab product deploy でserver1, server2にデプロイ</code></pre>
<h2 id="感想">感想</h2>
<p>Fabric、シンプルでいいですね。やりたいことが簡単にできます。 最近、Pythonを書く機会がじわじわと増えてきており、今年はへび年だしそういうものなのかなと感じております。 私自体初心者であるため、もしかしたらもっといい方法があるかもしれません。ツッコミお願い致します。</p>
<h2 id="その他雑感">その他雑感</h2>
<p>このブログが運用されているGithub Pagesのドメインがgithub.comからgithub.ioに変わっちゃいましたね。 はてブとかtwitterの言及数とかfacebookのいいね数とかが全部0になっちゃいましたね。引き継げないんですかね。</p>
<p>Pythonつながりの話ですが、<a href="http://ansible.cc/">Ansible</a>という構成管理ツールが少し話題になっていましたね。私はChefでknife-soloを使ってリモートからchef-solo実行みたいなことしかしていなかったため、Ansibleでもいいんじゃないかと思いました。 あとは、Chefの豊富なresourceとrecipe達に太刀打ちできるかですかね。使ってみなくては。</p>

<div id="disqus_thread"></div>
<script type="text/javascript">
    /* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */
    var disqus_shortname = 'dekokun'; // required: replace example with your forum shortname

    /* * * DON'T EDIT BELOW THIS LINE * * */
    (function() {
        var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
        dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js';
        (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
    })();
</script>
<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
<a href="http://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a>

          <ul class="social">
            <li class="kindle"><div class="kindleWidget"><img style="vertical-align:middle;" src="https://d1xnn692s7u6t6.cloudfront.net/white-15.png" /><span style="vertical-align:middle;margin-left:3px;">Send to Kindle</span></div></li>
            <li class="facebook"><div class="fb-like" data-send="false" data-layout="button_count" data-width="100" data-show-faces="true" data-font="arial"></div></li>
            <li class="twitter"><a href="https://twitter.com/share" class="twitter-share-button" data-via="dekokun" data-lang="ja">ツイート</a></li>
            <li class="hatena-bookmark"><a href="http://b.hatena.ne.jp/entry/" class="hatena-bookmark-button" data-hatena-bookmark-layout="standard" title="このエントリーをはてなブックマークに追加"><img src="http://b.st-hatena.com/images/entry-button/button-only.gif" alt="このエントリーをはてなブックマークに追加" width="20" height="20" style="border: none;"></a><script type="text/javascript" src="http://b.st-hatena.com/js/bookmark_button.js" charset="utf-8" async="async"></script></li>
            <li><a data-pocket-label="pocket" data-pocket-count="horizontal" class="pocket-btn" data-lang="en"></a>
            <script type="text/javascript">!function(d,i){if(!d.getElementById(i)){var j=d.createElement("script");j.id=i;j.src="https://widgets.getpocket.com/v1/j/btn.js?v=1";var w=d.getElementById(i);d.body.appendChild(j);}}(document,"pocket-btn-js");</script></li>
          </ul>

        </article>
        <aside class="span3">
          <div class="sidebar-module">
            <div class="title">プロフィール</div>
            <p class="id"><a href="https://twitter.com/dekokun">dekokun</a></p>
            <p><a href="https://twitter.com/dekokun"><img src="../img/dekokun.png" alt="dekokun"></a></p>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.io/";
              Hatena.BookmarkWidget.title = "人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 200;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.com/";
              Hatena.BookmarkWidget.title = "旧人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 0;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module visible-desktop">
            <div class="title">twitter</div>
            <a class="twitter-timeline" data-dnt="true" href="https://twitter.com/dekokun" data-widget-id="306408547573440513">@dekokun からのツイート</a>
            <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
          </div>
          <div class="sidebar-module hidden-phone">
            <div class="title">RSS</div>
            <p><a href="../rss.xml"><img src="../img/rss.gif" alt="rss"></a></p>
          </div>
        </aside> <!-- /span3 -->
      </div> <!-- /row -->
      <footer>
        <p>©<script type="text/javascript">$y=2012;$ny=new Date().getFullYear();document.write($ny>$y?$y+'-'+$ny:$y);</script> <a href="https://twitter.com/dekokun">dekokun</a></p>
      </footer>
    </div> <!-- /container -->

    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script>window.jQuery || document.write('<script src="../js/libs/jquery-1.7.2.min.js"><\/script>')</script>
    <!-- /ツイートボタン -->
  <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>

    <script src="../js/libs/bootstrap/bootstrap.min.js"></script>

    <script src="../js/script.js"></script>
    <script>
      var _gaq=[['_setAccount','UA-XXXXX-X'],['_trackPageview']];
      (function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
      g.src=('https:'==location.protocol?'//ssl':'//www')+'.google-analytics.com/ga.js';
      s.parentNode.insertBefore(g,s)}(document,'script'));
    </script>
    <!-- Code syntax highlight -->
    <script type="text/javascript" src="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.js"></script>
    <script type="text/javascript">
    $(function(){ 
        $('pre').css({
            'overflow-x': 'scroll',
            'background-color': '#f6f6f6',
            'border': '1px dotted #ccc',
            'padding': '0.8em'
        });
        $('pre code').addClass('prettyprint');
        prettyPrint();
    });
    </script>
    <script type="text/javascript" src="https://d1xnn692s7u6t6.cloudfront.net/widget.js"></script>
    <script type="text/javascript">(function k(){window.$SendToKindle&&window.$SendToKindle.Widget?$SendToKindle.Widget.init({"content":"article"}):setTimeout(k,500);})();</script>
  </body>
</html>
]]></description>
    <pubDate>No date found.</pubDate>
    <guid>http://dekokun.github.io/posts/2013-04-07.html</guid>
</item>
<item>
    <title>デプロイツール比較 CapistranoとFabric</title>
    <link>http://dekokun.github.io/posts/2013-05-21.html</link>
    <description><![CDATA[<!doctype html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7" lang="ja"> <![endif]-->
<!--[if IE 7]>    <html class="no-js lt-ie9 lt-ie8" lang="ja"> <![endif]-->
<!--[if IE 8]>    <html class="no-js lt-ie9" lang="ja"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="ja"> <!--<![endif]-->
  <head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# article: http://ogp.me/ns/article#">
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <title>デプロイツール比較 CapistranoとFabric</title>
    <meta name="description" content>
    <meta name="author" content>

    <meta name="viewport" content="width=device-width">
    <meta property="fb:app_id" content="351187098330864">
    <meta property="og:type" content="article">
    <meta property="og:image" content="http://dekokun.github.com/img/dekokun.png">
    <meta property="og:title" content="デプロイツール比較 CapistranoとFabric">
    <meta property="og:description" content="@dekokunの技術日記">
    <meta property="og:site_name" content="でこてっくろぐ">
    <meta name="twitter:widgets:csp" content="on">

    <link rel="stylesheet" href="../css/bootstrap.css">
    <link rel="stylesheet" href="../css/bootstrap-responsive.css">
    <link rel="stylesheet" href="../css/style.css">
    <style>
    body {
      padding-top: 60px;
      padding-bottom: 40px;
    }
    </style>
    <link href="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.css" type="text/css" rel="stylesheet">
    <script src="../js/libs/modernizr-2.5.3-respond-1.1.0.min.js"></script>
    <script>
      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

      ga('create', 'UA-39650556-1', 'auto');
      ga('send', 'pageview');
    </script>
  </head>
  <body>
  <!--[if lt IE 7]><p class=chromeframe>Your browser is <em>ancient!</em> <a href="http://browsehappy.com/">Upgrade to a different browser</a> or <a href="http://www.google.com/chromeframe/?redirect=true">install Google Chrome Frame</a> to experience this site.</p><![endif]-->
    <div id="fb-root"></div>
    <script>(function(d, s, id) {
      var js, fjs = d.getElementsByTagName(s)[0];
      if (d.getElementById(id)) return;
      js = d.createElement(s); js.id = id;
      js.src = "//connect.facebook.net/ja_JP/all.js#xfbml=1&appId=351187098330864";
      fjs.parentNode.insertBefore(js, fjs);
      }(document, 'script', 'facebook-jssdk'));
    </script>
    <header>
      <nav class="navbar navbar-fixed-top">
        <div class="navbar-inner">
          <div class="container">
            <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
            </a>
            <a class="brand" href="../index.html">でこてっくろぐ</a>
            <div class="nav-collapse">
              <ul class="nav">
                <li><a href="../index.html">ほーむ</a></li>
                <li><a href="../posts.html">あーかいぶ</a></li>
                <li><a href="../aboutme.html">あばうとみー</a></li>
              </ul>
            </div><!--/.nav-collapse -->
          </div>
        </div>
      </nav>
    </header>

    <div class="container">
      <div class="row">
        <article class="span9">
          <h1>デプロイツール比較 CapistranoとFabric</h1>

<p>by <em><a href="https://twitter.com/dekokun">@dekokun</a></em> on <strong>2013/05/21 23:46</strong></p>

<p>Tagged as: <a href="../tags/Capistrano.html">Capistrano</a>, <a href="../tags/Fabric.html">Fabric</a>.</p>

<p>最近、<a href="http://docs.fabfile.org/en/1.6/">Fabric</a>, <a href="https://github.com/capistrano/capistrano/wiki">Capistrano</a>と立て続けに2種類のデプロイツールを使ってデプロイ環境を構築する機会がありましたので、その際に感じた両者の利点を書いてみたいと思います。</p>
<h2 id="両者の簡単な解説">両者の簡単な解説</h2>
<p>そもそもCapistrano, Fabricについて、「片方は知っているけど片方は知らないよ」という人がいるかと思いますので、簡単な説明をします。</p>
<p>両方とも何かを知らない人は…「自動デプロイ」とかそのあたりで検索してみるといいんじゃないですかね。</p>
<h3 id="capistranoとは">Capistranoとは</h3>
<p>Ruby製のFabricみたいなものです</p>
<h3 id="fabricとは">Fabricとは</h3>
<p>Python製のCapistranoみたいなものです</p>
<p>Fabricは私の中ではデプロイツールという認識なのですが、最近Chefと比較されることが多い気がします。<a href="http://cuisine.readthedocs.org/en/latest/">Cuisine</a>の登場によって冪等性を保証した操作もできるようになったからでしょうか。</p>
<p>個人的には、Chefと比較されるべきPythonツールはAnsibleなのではないかという気がしていますが、どうなんですかね。</p>
<h2 id="capistranoの利点">Capistranoの利点</h2>
<ul>
<li>デフォルトのデプロイタスクが存在する
<ul>
<li>これはRails使いにはたまりませんね。ほんの少し設定を行うだけでRailsのデプロイが可能になります</li>
<li>Railsにかぎらず、設定を適切にすればPHPなど多言語のデプロイにも使えますしね</li>
<li>Capistranoのデフォルトのデプロイタスクで私は「シンボリックリンクを使用したデプロイ」という概念を初めて知り感動したのでした</li>
<li>デフォルトのデプロイタスクを使わない場合も、デフォルトのデプロイタスクはデプロイタスクを書く上で非常に参考になりますね</li>
</ul></li>
<li>日本語のドキュメントが多い
<ul>
<li>やはり、日本はPythonよりRubyのほうが強いイメージがありますね</li>
<li>最近、VagrantやChefなどのRubyツールの勢い強いですよね</li>
<li>私はPython製のAnsible, Fabricを陰ながら応援しています。今年はへび年ですしね</li>
</ul></li>
<li><s>ストリームが簡単に扱える</s>
<ul>
<li>ごめんなさい、こちら、CapistranoだけではなくFabricのほうでも普通にrun関数で実施可能でした</li>
<li>Capistranoはstreamメソッドで簡単に<code>tail -f</code>の結果を一箇所で見たりすることが可能ですよね</li>
<li><s>Fabricで同様のことを行いたい場合はどうすればいいんでしょうか。私が方法を知らないだけですかね…</s></li>
<li>デプロイツールという意味ではこの機能は不要ですが、せっかくデプロイツールで大量のサーバに対して色々できる環境が整ったのであれば、デプロイ以外でも使うべきですよね</li>
</ul></li>
<li>全体的に細かい機能が充実している
<ul>
<li>cap shellとかすごく便利ですよね</li>
<li>便利な機能が多すぎて迷ってしまうイメージはありますが</li>
</ul></li>
</ul>
<h2 id="fabricの利点">Fabricの利点</h2>
<ul>
<li>Capistranoとくらべて薄いフレームワークであるため動きを把握しやすい
<ul>
<li>テストを除いたコードの行数を比較すると、Capistranoが9000行くらいでFabricが7000行くらいでした。コード行数だけでは一概に比較できないですが…(行数に思ったより差がついてなくて驚いた)</li>
<li>Fabricのほうが圧倒的に「わかりやすい」というイメージが強いんですよね。CapistranoはDSLを提供してくれていたりデフォルトのdeployタスクがあったりして、「覚えることが多い」というイメージが強い</li>
<li>「Capistranoを使う場合でもデフォルトdeployタスクを使わなければ分かりやすさには大差ないのでは」という話はもちろんある</li>
</ul></li>
<li>DSLを覚えなくても普通にPythonを書く感覚で書ける
<ul>
<li>「関数がタスクになるよ」「run関数使おうね」くらいを知っていればひとまず使えるイメージ</li>
<li>Capistranoは、「まず、taskでタスクを登録して…」「勝手に作られているこのデプロイタスクはなんですか」と、最初の導入の際に知るべきことが少し多い</li>
</ul></li>
<li><a href="http://cuisine.readthedocs.org/en/latest/">Cuisine</a>によりChef的に使える
<ul>
<li>このあたり、話には聞くんですけども、よく知らないです</li>
</ul></li>
<li>世界全体ではこちらのほうが人気
<ul>
<li>Googleトレンドの結果をご確認ください <a href="http://www.google.co.jp/trends/explore?q=Ruby+capistrano#q=Ruby%20Capistrano%2C%20Python%20Fabric&amp;cmpt=q">Ruby Capistrano, Python Fabric</a></li>
<li>2011年あたりからFabricがCapistranoを追い抜き、現在では圧倒的にFabricの検索数のほうが多いですね</li>
</ul></li>
</ul>
<h2 id="その他感じたこと">その他感じたこと</h2>
<ul>
<li>Fabricのputはファイルをアップロードするのに対して、Capistranoのputは引数の文字列が中身のファイルを作成するのですね。驚きました。Capistranoでのファイルアップロードはuploadですね</li>
<li>Fabricが基本的に直列実行であるのに対してCapistranoは基本的に並列実行ですよね。まぁ、どちらも、直列/並列を切り替えることが可能ですが
<ul>
<li>Fabricの同時並列実行数の指定はデコレータの引数で行うのに対して、Capistranoの同時並列実行数の指定はメソッドのオプションを使うというのが、それぞれの言語っぽさがあって素敵だなと思いました。</li>
</ul></li>
</ul>
<h2 id="まとめ">まとめ</h2>
<p>ちゃんと、両方ともロールが扱えたり、少し手を加えればプロダクション環境やデベロップ環境の使い分けも可能ですし、デプロイのための最低限の機能は両方共に揃っていると思います。</p>
<p>まぁ、PythonやRubyのプロダクトを扱っているのであればそれぞれの言語のデプロイツールを使えばいいんじゃないんですかね知らんけど。PerlだったらCinnamonもありますしね。</p>
<p>問題はPHPのデプロイですよ。Phingを使うためにXMLを書きたくないなという感じなのですよ(あぁ、<a href="http://kohkimakimoto.hatenablog.com/entry/2013/03/12/201330">Altax</a>をちゃんと触っていない私がこんなことを言っていていいのだろうか)</p>
<p>眠くなってきた。正直、「ハマった時にソースを読むもしくは英語で解決する能力があればFabric, 日本語でググって解決したいのであればCapistrano」とかそんな感じで適当に決めればいいんじゃないですか。</p>
<p>「デコレータ？よくわからんしそういう知らない言語の謎機能は使えません」とか言うバカはcapistranoを使っていればいいんじゃないですかね。</p>
<p>なお、以下の理由でこの記事はCapistrano推しに寄っている可能性があります</p>
<ol style="list-style-type: decimal">
<li>私はFabricよりもCapistranoのデプロイ構築経験のほうが多い(人生初のデプロイ自動化はCapistranoを使ったものでした)</li>
<li>私はPythonよりもRubyを書いた経験のほうが多い(昔はRuby大好きっ子だったのです)</li>
</ol>
<p>あ、ちなみに現在の私はPHP書きです。</p>

<div id="disqus_thread"></div>
<script type="text/javascript">
    /* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */
    var disqus_shortname = 'dekokun'; // required: replace example with your forum shortname

    /* * * DON'T EDIT BELOW THIS LINE * * */
    (function() {
        var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
        dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js';
        (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
    })();
</script>
<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
<a href="http://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a>

          <ul class="social">
            <li class="kindle"><div class="kindleWidget"><img style="vertical-align:middle;" src="https://d1xnn692s7u6t6.cloudfront.net/white-15.png" /><span style="vertical-align:middle;margin-left:3px;">Send to Kindle</span></div></li>
            <li class="facebook"><div class="fb-like" data-send="false" data-layout="button_count" data-width="100" data-show-faces="true" data-font="arial"></div></li>
            <li class="twitter"><a href="https://twitter.com/share" class="twitter-share-button" data-via="dekokun" data-lang="ja">ツイート</a></li>
            <li class="hatena-bookmark"><a href="http://b.hatena.ne.jp/entry/" class="hatena-bookmark-button" data-hatena-bookmark-layout="standard" title="このエントリーをはてなブックマークに追加"><img src="http://b.st-hatena.com/images/entry-button/button-only.gif" alt="このエントリーをはてなブックマークに追加" width="20" height="20" style="border: none;"></a><script type="text/javascript" src="http://b.st-hatena.com/js/bookmark_button.js" charset="utf-8" async="async"></script></li>
            <li><a data-pocket-label="pocket" data-pocket-count="horizontal" class="pocket-btn" data-lang="en"></a>
            <script type="text/javascript">!function(d,i){if(!d.getElementById(i)){var j=d.createElement("script");j.id=i;j.src="https://widgets.getpocket.com/v1/j/btn.js?v=1";var w=d.getElementById(i);d.body.appendChild(j);}}(document,"pocket-btn-js");</script></li>
          </ul>

        </article>
        <aside class="span3">
          <div class="sidebar-module">
            <div class="title">プロフィール</div>
            <p class="id"><a href="https://twitter.com/dekokun">dekokun</a></p>
            <p><a href="https://twitter.com/dekokun"><img src="../img/dekokun.png" alt="dekokun"></a></p>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.io/";
              Hatena.BookmarkWidget.title = "人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 200;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.com/";
              Hatena.BookmarkWidget.title = "旧人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 0;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module visible-desktop">
            <div class="title">twitter</div>
            <a class="twitter-timeline" data-dnt="true" href="https://twitter.com/dekokun" data-widget-id="306408547573440513">@dekokun からのツイート</a>
            <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
          </div>
          <div class="sidebar-module hidden-phone">
            <div class="title">RSS</div>
            <p><a href="../rss.xml"><img src="../img/rss.gif" alt="rss"></a></p>
          </div>
        </aside> <!-- /span3 -->
      </div> <!-- /row -->
      <footer>
        <p>©<script type="text/javascript">$y=2012;$ny=new Date().getFullYear();document.write($ny>$y?$y+'-'+$ny:$y);</script> <a href="https://twitter.com/dekokun">dekokun</a></p>
      </footer>
    </div> <!-- /container -->

    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script>window.jQuery || document.write('<script src="../js/libs/jquery-1.7.2.min.js"><\/script>')</script>
    <!-- /ツイートボタン -->
  <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>

    <script src="../js/libs/bootstrap/bootstrap.min.js"></script>

    <script src="../js/script.js"></script>
    <script>
      var _gaq=[['_setAccount','UA-XXXXX-X'],['_trackPageview']];
      (function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
      g.src=('https:'==location.protocol?'//ssl':'//www')+'.google-analytics.com/ga.js';
      s.parentNode.insertBefore(g,s)}(document,'script'));
    </script>
    <!-- Code syntax highlight -->
    <script type="text/javascript" src="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.js"></script>
    <script type="text/javascript">
    $(function(){ 
        $('pre').css({
            'overflow-x': 'scroll',
            'background-color': '#f6f6f6',
            'border': '1px dotted #ccc',
            'padding': '0.8em'
        });
        $('pre code').addClass('prettyprint');
        prettyPrint();
    });
    </script>
    <script type="text/javascript" src="https://d1xnn692s7u6t6.cloudfront.net/widget.js"></script>
    <script type="text/javascript">(function k(){window.$SendToKindle&&window.$SendToKindle.Widget?$SendToKindle.Widget.init({"content":"article"}):setTimeout(k,500);})();</script>
  </body>
</html>
]]></description>
    <pubDate>No date found.</pubDate>
    <guid>http://dekokun.github.io/posts/2013-05-21.html</guid>
</item>
<item>
    <title>httpdでconfigtestが成功しても起動できない時の切なさ</title>
    <link>http://dekokun.github.io/posts/2013-06-23.html</link>
    <description><![CDATA[<!doctype html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7" lang="ja"> <![endif]-->
<!--[if IE 7]>    <html class="no-js lt-ie9 lt-ie8" lang="ja"> <![endif]-->
<!--[if IE 8]>    <html class="no-js lt-ie9" lang="ja"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="ja"> <!--<![endif]-->
  <head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# article: http://ogp.me/ns/article#">
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <title>httpdでconfigtestが成功しても起動できない時の切なさ</title>
    <meta name="description" content>
    <meta name="author" content>

    <meta name="viewport" content="width=device-width">
    <meta property="fb:app_id" content="351187098330864">
    <meta property="og:type" content="article">
    <meta property="og:image" content="http://dekokun.github.com/img/dekokun.png">
    <meta property="og:title" content="httpdでconfigtestが成功しても起動できない時の切なさ">
    <meta property="og:description" content="@dekokunの技術日記">
    <meta property="og:site_name" content="でこてっくろぐ">
    <meta name="twitter:widgets:csp" content="on">

    <link rel="stylesheet" href="../css/bootstrap.css">
    <link rel="stylesheet" href="../css/bootstrap-responsive.css">
    <link rel="stylesheet" href="../css/style.css">
    <style>
    body {
      padding-top: 60px;
      padding-bottom: 40px;
    }
    </style>
    <link href="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.css" type="text/css" rel="stylesheet">
    <script src="../js/libs/modernizr-2.5.3-respond-1.1.0.min.js"></script>
    <script>
      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

      ga('create', 'UA-39650556-1', 'auto');
      ga('send', 'pageview');
    </script>
  </head>
  <body>
  <!--[if lt IE 7]><p class=chromeframe>Your browser is <em>ancient!</em> <a href="http://browsehappy.com/">Upgrade to a different browser</a> or <a href="http://www.google.com/chromeframe/?redirect=true">install Google Chrome Frame</a> to experience this site.</p><![endif]-->
    <div id="fb-root"></div>
    <script>(function(d, s, id) {
      var js, fjs = d.getElementsByTagName(s)[0];
      if (d.getElementById(id)) return;
      js = d.createElement(s); js.id = id;
      js.src = "//connect.facebook.net/ja_JP/all.js#xfbml=1&appId=351187098330864";
      fjs.parentNode.insertBefore(js, fjs);
      }(document, 'script', 'facebook-jssdk'));
    </script>
    <header>
      <nav class="navbar navbar-fixed-top">
        <div class="navbar-inner">
          <div class="container">
            <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
            </a>
            <a class="brand" href="../index.html">でこてっくろぐ</a>
            <div class="nav-collapse">
              <ul class="nav">
                <li><a href="../index.html">ほーむ</a></li>
                <li><a href="../posts.html">あーかいぶ</a></li>
                <li><a href="../aboutme.html">あばうとみー</a></li>
              </ul>
            </div><!--/.nav-collapse -->
          </div>
        </div>
      </nav>
    </header>

    <div class="container">
      <div class="row">
        <article class="span9">
          <h1>httpdでconfigtestが成功しても起動できない時の切なさ</h1>

<p>by <em><a href="https://twitter.com/dekokun">@dekokun</a></em> on <strong>2013/06/23 23:20</strong></p>

<p>Tagged as: <a href="../tags/httpd.html">httpd</a>.</p>

<p>今回は技術的に大したネタではないですが切なさが募ったので投稿</p>
<p>Apacheなんですが、configtestではステータスコード0が返ってきているのに再起動が失敗すると切ないですよね。</p>
<p>デプロイの際にcapistranoでhttpd.confを書き換えてconfigtestを行い成功したらhttpdの再起動を行なっていたのですが、configtestはステータスコード0で成功したのにhttpdの起動が失敗してヒヤリとしました。</p>
<p>capistranoで並列実行数を絞ってhttpdを再起動していたため影響は全台には及ばなかったのでそんなに問題はないですけども(テスト環境と本番環境で完全に異なるvirtual host設定を適用していたのが今回最大の敗因)</p>
<p>少し試してみたら、いろいろなパターンでhttpdが起動したりしなかったりconfigtestが成功したりしなかったりしますね。</p>
<p>なお、以下はApacheの2.2.23での挙動ですよ</p>
<p>例1： ログディレクトリが存在しない場合</p>
<pre><code># service httpd configtest; echo $?; service httpd restart
Syntax OK
0
Stopping httpd:                                            [  OK  ]
Starting httpd:                                            [FAILED]</code></pre>
<p>configtestは成功したにもかかわらず死亡</p>
<p>例2：ドキュメントルートが存在しない場合</p>
<pre><code># service httpd configtest; echo $?; service httpd restart
Warning: DocumentRoot [/var/www/htmls] does not exist
Syntax OK
0
Stopping httpd:                                            [  OK  ]
Starting httpd: Warning: DocumentRoot [/var/www/htmls] does not exist
                                                       [  OK  ]</code></pre>
<p>ドキュメントルートが存在しない場合はconfigtestの際にWarningは出してくれるがステータスは成功でhttpdは起動しますね。この挙動はどうなんだろうね。</p>
<p>例3:ドキュメントルートにファイルを指定したりドキュメントルートにしたディレクトリの親ディレクトリがそもそも存在しなかった場合</p>
<pre><code># service httpd configtest; echo $?; service httpd restart
Syntax error on line 292 of /etc/httpd/conf/httpd.conf:
DocumentRoot must be a directory
1
Stopping httpd:                                            [  OK  ]
Starting httpd: Syntax error on line 292 of /etc/httpd/conf/httpd.conf:
DocumentRoot must be a directory
                                                           [FAILED]</code></pre>
<p>configtestで失敗し、もちろん起動もしない。まぁ、この挙動は自然ですね。</p>
<p>(このあたり、詳しくはhttpdのソースのserver/core.c内のset_document_rootあたりを読むといいと思いますよ多分) このページとか参考にしながら。 <a href="http://dsas.blog.klab.org/archives/50596409.html#s28">ディレクティブの処理と設定値の利用 (apache module 開発事初め その3)</a></p>
<p>まぁ、なんというか、今回、初めてhttpdのソースを読みました。めでたしめでたし。</p>

<div id="disqus_thread"></div>
<script type="text/javascript">
    /* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */
    var disqus_shortname = 'dekokun'; // required: replace example with your forum shortname

    /* * * DON'T EDIT BELOW THIS LINE * * */
    (function() {
        var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
        dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js';
        (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
    })();
</script>
<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
<a href="http://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a>

          <ul class="social">
            <li class="kindle"><div class="kindleWidget"><img style="vertical-align:middle;" src="https://d1xnn692s7u6t6.cloudfront.net/white-15.png" /><span style="vertical-align:middle;margin-left:3px;">Send to Kindle</span></div></li>
            <li class="facebook"><div class="fb-like" data-send="false" data-layout="button_count" data-width="100" data-show-faces="true" data-font="arial"></div></li>
            <li class="twitter"><a href="https://twitter.com/share" class="twitter-share-button" data-via="dekokun" data-lang="ja">ツイート</a></li>
            <li class="hatena-bookmark"><a href="http://b.hatena.ne.jp/entry/" class="hatena-bookmark-button" data-hatena-bookmark-layout="standard" title="このエントリーをはてなブックマークに追加"><img src="http://b.st-hatena.com/images/entry-button/button-only.gif" alt="このエントリーをはてなブックマークに追加" width="20" height="20" style="border: none;"></a><script type="text/javascript" src="http://b.st-hatena.com/js/bookmark_button.js" charset="utf-8" async="async"></script></li>
            <li><a data-pocket-label="pocket" data-pocket-count="horizontal" class="pocket-btn" data-lang="en"></a>
            <script type="text/javascript">!function(d,i){if(!d.getElementById(i)){var j=d.createElement("script");j.id=i;j.src="https://widgets.getpocket.com/v1/j/btn.js?v=1";var w=d.getElementById(i);d.body.appendChild(j);}}(document,"pocket-btn-js");</script></li>
          </ul>

        </article>
        <aside class="span3">
          <div class="sidebar-module">
            <div class="title">プロフィール</div>
            <p class="id"><a href="https://twitter.com/dekokun">dekokun</a></p>
            <p><a href="https://twitter.com/dekokun"><img src="../img/dekokun.png" alt="dekokun"></a></p>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.io/";
              Hatena.BookmarkWidget.title = "人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 200;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.com/";
              Hatena.BookmarkWidget.title = "旧人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 0;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module visible-desktop">
            <div class="title">twitter</div>
            <a class="twitter-timeline" data-dnt="true" href="https://twitter.com/dekokun" data-widget-id="306408547573440513">@dekokun からのツイート</a>
            <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
          </div>
          <div class="sidebar-module hidden-phone">
            <div class="title">RSS</div>
            <p><a href="../rss.xml"><img src="../img/rss.gif" alt="rss"></a></p>
          </div>
        </aside> <!-- /span3 -->
      </div> <!-- /row -->
      <footer>
        <p>©<script type="text/javascript">$y=2012;$ny=new Date().getFullYear();document.write($ny>$y?$y+'-'+$ny:$y);</script> <a href="https://twitter.com/dekokun">dekokun</a></p>
      </footer>
    </div> <!-- /container -->

    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script>window.jQuery || document.write('<script src="../js/libs/jquery-1.7.2.min.js"><\/script>')</script>
    <!-- /ツイートボタン -->
  <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>

    <script src="../js/libs/bootstrap/bootstrap.min.js"></script>

    <script src="../js/script.js"></script>
    <script>
      var _gaq=[['_setAccount','UA-XXXXX-X'],['_trackPageview']];
      (function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
      g.src=('https:'==location.protocol?'//ssl':'//www')+'.google-analytics.com/ga.js';
      s.parentNode.insertBefore(g,s)}(document,'script'));
    </script>
    <!-- Code syntax highlight -->
    <script type="text/javascript" src="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.js"></script>
    <script type="text/javascript">
    $(function(){ 
        $('pre').css({
            'overflow-x': 'scroll',
            'background-color': '#f6f6f6',
            'border': '1px dotted #ccc',
            'padding': '0.8em'
        });
        $('pre code').addClass('prettyprint');
        prettyPrint();
    });
    </script>
    <script type="text/javascript" src="https://d1xnn692s7u6t6.cloudfront.net/widget.js"></script>
    <script type="text/javascript">(function k(){window.$SendToKindle&&window.$SendToKindle.Widget?$SendToKindle.Widget.init({"content":"article"}):setTimeout(k,500);})();</script>
  </body>
</html>
]]></description>
    <pubDate>No date found.</pubDate>
    <guid>http://dekokun.github.io/posts/2013-06-23.html</guid>
</item>
<item>
    <title>Chef Server 11系にてadminのパスワードがわからなくなった場合の対処法</title>
    <link>http://dekokun.github.io/posts/2013-06-24.html</link>
    <description><![CDATA[<!doctype html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7" lang="ja"> <![endif]-->
<!--[if IE 7]>    <html class="no-js lt-ie9 lt-ie8" lang="ja"> <![endif]-->
<!--[if IE 8]>    <html class="no-js lt-ie9" lang="ja"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="ja"> <!--<![endif]-->
  <head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# article: http://ogp.me/ns/article#">
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <title>Chef Server 11系にてadminのパスワードがわからなくなった場合の対処法</title>
    <meta name="description" content>
    <meta name="author" content>

    <meta name="viewport" content="width=device-width">
    <meta property="fb:app_id" content="351187098330864">
    <meta property="og:type" content="article">
    <meta property="og:image" content="http://dekokun.github.com/img/dekokun.png">
    <meta property="og:title" content="Chef Server 11系にてadminのパスワードがわからなくなった場合の対処法">
    <meta property="og:description" content="@dekokunの技術日記">
    <meta property="og:site_name" content="でこてっくろぐ">
    <meta name="twitter:widgets:csp" content="on">

    <link rel="stylesheet" href="../css/bootstrap.css">
    <link rel="stylesheet" href="../css/bootstrap-responsive.css">
    <link rel="stylesheet" href="../css/style.css">
    <style>
    body {
      padding-top: 60px;
      padding-bottom: 40px;
    }
    </style>
    <link href="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.css" type="text/css" rel="stylesheet">
    <script src="../js/libs/modernizr-2.5.3-respond-1.1.0.min.js"></script>
    <script>
      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

      ga('create', 'UA-39650556-1', 'auto');
      ga('send', 'pageview');
    </script>
  </head>
  <body>
  <!--[if lt IE 7]><p class=chromeframe>Your browser is <em>ancient!</em> <a href="http://browsehappy.com/">Upgrade to a different browser</a> or <a href="http://www.google.com/chromeframe/?redirect=true">install Google Chrome Frame</a> to experience this site.</p><![endif]-->
    <div id="fb-root"></div>
    <script>(function(d, s, id) {
      var js, fjs = d.getElementsByTagName(s)[0];
      if (d.getElementById(id)) return;
      js = d.createElement(s); js.id = id;
      js.src = "//connect.facebook.net/ja_JP/all.js#xfbml=1&appId=351187098330864";
      fjs.parentNode.insertBefore(js, fjs);
      }(document, 'script', 'facebook-jssdk'));
    </script>
    <header>
      <nav class="navbar navbar-fixed-top">
        <div class="navbar-inner">
          <div class="container">
            <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
            </a>
            <a class="brand" href="../index.html">でこてっくろぐ</a>
            <div class="nav-collapse">
              <ul class="nav">
                <li><a href="../index.html">ほーむ</a></li>
                <li><a href="../posts.html">あーかいぶ</a></li>
                <li><a href="../aboutme.html">あばうとみー</a></li>
              </ul>
            </div><!--/.nav-collapse -->
          </div>
        </div>
      </nav>
    </header>

    <div class="container">
      <div class="row">
        <article class="span9">
          <h1>Chef Server 11系にてadminのパスワードがわからなくなった場合の対処法</h1>

<p>by <em><a href="https://twitter.com/dekokun">@dekokun</a></em> on <strong>2013/06/24 06:24</strong></p>

<p>Tagged as: <a href="../tags/Chef Server.html">Chef Server</a>.</p>

<p>昨日に引き続き本日も小ネタ。</p>
<p>本日は朝早くからAWS上にてChef Serverを構築してみたりしておりました。</p>
<p>adminのパスワードがわからなくなったのでリセットとかしたくなったけどググってもChef Server10でDBがまだCouch DBだった頃の情報ばかりでChef Server11系の情報があまりなかった(まぁ、結局頑張ってググってたら見つかったしこのブログはそれを参考に書いているんだけれども)ためここに書き残す。</p>
<p>具体的には、PostgreSQLにログインしユーザの情報を削除して新たなユーザを作成する。</p>
<p>以下は、adminユーザにて<strong>hogehogeというパスワードでログイン</strong>できるようにする場合</p>
<p>まず、一旦、Chef Serverが動いているサーバの/etc/chef-server/chef-server-running.jsonのchef-server-webui-&gt;web_ui_admin_default_passwordに記載してあるパスワードでログインできないか確かめてみましょう。それがダメだったら以下手順でどうぞ</p>
<pre><code>Chef Serverが起動しているサーバにて
# /opt/chef-server/embedded/bin/psql -U opscode_chef opscode_chef

BEGIN;

UPDATE osc_users
SET hashed_password = '$2a$12$lNDCQ37UteDUyj0qwK55b.o2tnZeD.XptoekgUHAlItYHEnTIUQKq',
    salt = '$2a$12$lNDCQ37UteDUyj0qwK55b.',
    hash_type = 'erlang-bcrypt-0.5.0'
WHERE username = 'admin';

COMMIT;</code></pre>
<p>なお、このコードはChef Server 11.0.8で動作確認を行なっております。</p>
<p>以下やり取りを参考にさせていただきました。 (今ググったら、「Chef Server 11 password reset」では検索に引っかからないが、「Chef 11 password reset」ならすぐに出てきた。google先生、難しいですね。)</p>
<ul>
<li><a href="http://lists.opscode.com/sympa/arc/chef/2013-03/msg00279.html">[chef] how to reset webui password in chef 11</a></li>
</ul>

<div id="disqus_thread"></div>
<script type="text/javascript">
    /* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */
    var disqus_shortname = 'dekokun'; // required: replace example with your forum shortname

    /* * * DON'T EDIT BELOW THIS LINE * * */
    (function() {
        var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
        dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js';
        (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
    })();
</script>
<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
<a href="http://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a>

          <ul class="social">
            <li class="kindle"><div class="kindleWidget"><img style="vertical-align:middle;" src="https://d1xnn692s7u6t6.cloudfront.net/white-15.png" /><span style="vertical-align:middle;margin-left:3px;">Send to Kindle</span></div></li>
            <li class="facebook"><div class="fb-like" data-send="false" data-layout="button_count" data-width="100" data-show-faces="true" data-font="arial"></div></li>
            <li class="twitter"><a href="https://twitter.com/share" class="twitter-share-button" data-via="dekokun" data-lang="ja">ツイート</a></li>
            <li class="hatena-bookmark"><a href="http://b.hatena.ne.jp/entry/" class="hatena-bookmark-button" data-hatena-bookmark-layout="standard" title="このエントリーをはてなブックマークに追加"><img src="http://b.st-hatena.com/images/entry-button/button-only.gif" alt="このエントリーをはてなブックマークに追加" width="20" height="20" style="border: none;"></a><script type="text/javascript" src="http://b.st-hatena.com/js/bookmark_button.js" charset="utf-8" async="async"></script></li>
            <li><a data-pocket-label="pocket" data-pocket-count="horizontal" class="pocket-btn" data-lang="en"></a>
            <script type="text/javascript">!function(d,i){if(!d.getElementById(i)){var j=d.createElement("script");j.id=i;j.src="https://widgets.getpocket.com/v1/j/btn.js?v=1";var w=d.getElementById(i);d.body.appendChild(j);}}(document,"pocket-btn-js");</script></li>
          </ul>

        </article>
        <aside class="span3">
          <div class="sidebar-module">
            <div class="title">プロフィール</div>
            <p class="id"><a href="https://twitter.com/dekokun">dekokun</a></p>
            <p><a href="https://twitter.com/dekokun"><img src="../img/dekokun.png" alt="dekokun"></a></p>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.io/";
              Hatena.BookmarkWidget.title = "人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 200;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.com/";
              Hatena.BookmarkWidget.title = "旧人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 0;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module visible-desktop">
            <div class="title">twitter</div>
            <a class="twitter-timeline" data-dnt="true" href="https://twitter.com/dekokun" data-widget-id="306408547573440513">@dekokun からのツイート</a>
            <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
          </div>
          <div class="sidebar-module hidden-phone">
            <div class="title">RSS</div>
            <p><a href="../rss.xml"><img src="../img/rss.gif" alt="rss"></a></p>
          </div>
        </aside> <!-- /span3 -->
      </div> <!-- /row -->
      <footer>
        <p>©<script type="text/javascript">$y=2012;$ny=new Date().getFullYear();document.write($ny>$y?$y+'-'+$ny:$y);</script> <a href="https://twitter.com/dekokun">dekokun</a></p>
      </footer>
    </div> <!-- /container -->

    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script>window.jQuery || document.write('<script src="../js/libs/jquery-1.7.2.min.js"><\/script>')</script>
    <!-- /ツイートボタン -->
  <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>

    <script src="../js/libs/bootstrap/bootstrap.min.js"></script>

    <script src="../js/script.js"></script>
    <script>
      var _gaq=[['_setAccount','UA-XXXXX-X'],['_trackPageview']];
      (function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
      g.src=('https:'==location.protocol?'//ssl':'//www')+'.google-analytics.com/ga.js';
      s.parentNode.insertBefore(g,s)}(document,'script'));
    </script>
    <!-- Code syntax highlight -->
    <script type="text/javascript" src="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.js"></script>
    <script type="text/javascript">
    $(function(){ 
        $('pre').css({
            'overflow-x': 'scroll',
            'background-color': '#f6f6f6',
            'border': '1px dotted #ccc',
            'padding': '0.8em'
        });
        $('pre code').addClass('prettyprint');
        prettyPrint();
    });
    </script>
    <script type="text/javascript" src="https://d1xnn692s7u6t6.cloudfront.net/widget.js"></script>
    <script type="text/javascript">(function k(){window.$SendToKindle&&window.$SendToKindle.Widget?$SendToKindle.Widget.init({"content":"article"}):setTimeout(k,500);})();</script>
  </body>
</html>
]]></description>
    <pubDate>No date found.</pubDate>
    <guid>http://dekokun.github.io/posts/2013-06-24.html</guid>
</item>
<item>
    <title>「Gitの使用には免許が必要。危険だから初心者に使わせるな」とか思っちゃいますよね。そんな人に向けて</title>
    <link>http://dekokun.github.io/posts/2013-07-31.html</link>
    <description><![CDATA[<!doctype html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7" lang="ja"> <![endif]-->
<!--[if IE 7]>    <html class="no-js lt-ie9 lt-ie8" lang="ja"> <![endif]-->
<!--[if IE 8]>    <html class="no-js lt-ie9" lang="ja"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="ja"> <!--<![endif]-->
  <head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# article: http://ogp.me/ns/article#">
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <title>「Gitの使用には免許が必要。危険だから初心者に使わせるな」とか思っちゃいますよね。そんな人に向けて</title>
    <meta name="description" content>
    <meta name="author" content>

    <meta name="viewport" content="width=device-width">
    <meta property="fb:app_id" content="351187098330864">
    <meta property="og:type" content="article">
    <meta property="og:image" content="http://dekokun.github.com/img/dekokun.png">
    <meta property="og:title" content="「Gitの使用には免許が必要。危険だから初心者に使わせるな」とか思っちゃいますよね。そんな人に向けて">
    <meta property="og:description" content="@dekokunの技術日記">
    <meta property="og:site_name" content="でこてっくろぐ">
    <meta name="twitter:widgets:csp" content="on">

    <link rel="stylesheet" href="../css/bootstrap.css">
    <link rel="stylesheet" href="../css/bootstrap-responsive.css">
    <link rel="stylesheet" href="../css/style.css">
    <style>
    body {
      padding-top: 60px;
      padding-bottom: 40px;
    }
    </style>
    <link href="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.css" type="text/css" rel="stylesheet">
    <script src="../js/libs/modernizr-2.5.3-respond-1.1.0.min.js"></script>
    <script>
      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

      ga('create', 'UA-39650556-1', 'auto');
      ga('send', 'pageview');
    </script>
  </head>
  <body>
  <!--[if lt IE 7]><p class=chromeframe>Your browser is <em>ancient!</em> <a href="http://browsehappy.com/">Upgrade to a different browser</a> or <a href="http://www.google.com/chromeframe/?redirect=true">install Google Chrome Frame</a> to experience this site.</p><![endif]-->
    <div id="fb-root"></div>
    <script>(function(d, s, id) {
      var js, fjs = d.getElementsByTagName(s)[0];
      if (d.getElementById(id)) return;
      js = d.createElement(s); js.id = id;
      js.src = "//connect.facebook.net/ja_JP/all.js#xfbml=1&appId=351187098330864";
      fjs.parentNode.insertBefore(js, fjs);
      }(document, 'script', 'facebook-jssdk'));
    </script>
    <header>
      <nav class="navbar navbar-fixed-top">
        <div class="navbar-inner">
          <div class="container">
            <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
            </a>
            <a class="brand" href="../index.html">でこてっくろぐ</a>
            <div class="nav-collapse">
              <ul class="nav">
                <li><a href="../index.html">ほーむ</a></li>
                <li><a href="../posts.html">あーかいぶ</a></li>
                <li><a href="../aboutme.html">あばうとみー</a></li>
              </ul>
            </div><!--/.nav-collapse -->
          </div>
        </div>
      </nav>
    </header>

    <div class="container">
      <div class="row">
        <article class="span9">
          <h1>「Gitの使用には免許が必要。危険だから初心者に使わせるな」とか思っちゃいますよね。そんな人に向けて</h1>

<p>by <em><a href="https://twitter.com/dekokun">@dekokun</a></em> on <strong>2013/07/31 09:30</strong></p>

<p>Tagged as: <a href="../tags/Git.html">Git</a>.</p>

<p>会社などでの開発において、「Gitをよく知らない人にmasterブランチを破壊されるのが怖い」「初心者にはまずブランチの詳しい動きを勉強させないといけないなぁ…大変だ…」という文脈でそういっているのであれば、GITLABでも導入してmasterブランチへの書き込み権限を制限させ、pull request(GITLABでは「merge request」と言う)のワークフローでも使えばいいんじゃないですか。</p>
<p>pull requestのワークフローは「とにかくブランチを切ってそこに対してpushをし、質問したいときとかマージしてほしいときにWeb UIからpull requestをしてね」くらいで全く問題なく動くため、非常に簡単に、そして「変なマージをしづらい」という意味で危険なく使えますし。</p>
<p>「GITLABは貧者のGitHub Enterpriseだ」と馬鹿にしている人もいますが(<a href="http://dekokun.github.io/posts/2013-02-19.html">昔の私もそんなこと言ってましたが…</a>)、GITLABはブランチ毎に書き込み権限を制限できるという点においてGitHubよりも圧倒的に優れていると私は思いますし、もう一度GITLABをみ直してみてもいいんじゃないですかね。 (GitHub Enterpriseを使っているなら「forkさせてpull requestを投げる」ようなワークフローにすればいいしブランチ毎に権限を付与する必要はないという意見もあるかもしれませんが)</p>
<p>最近会社での開発では主にGITLABを使用しているのですが、とても便利です、という話だったのでした。</p>

<div id="disqus_thread"></div>
<script type="text/javascript">
    /* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */
    var disqus_shortname = 'dekokun'; // required: replace example with your forum shortname

    /* * * DON'T EDIT BELOW THIS LINE * * */
    (function() {
        var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
        dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js';
        (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
    })();
</script>
<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
<a href="http://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a>

          <ul class="social">
            <li class="kindle"><div class="kindleWidget"><img style="vertical-align:middle;" src="https://d1xnn692s7u6t6.cloudfront.net/white-15.png" /><span style="vertical-align:middle;margin-left:3px;">Send to Kindle</span></div></li>
            <li class="facebook"><div class="fb-like" data-send="false" data-layout="button_count" data-width="100" data-show-faces="true" data-font="arial"></div></li>
            <li class="twitter"><a href="https://twitter.com/share" class="twitter-share-button" data-via="dekokun" data-lang="ja">ツイート</a></li>
            <li class="hatena-bookmark"><a href="http://b.hatena.ne.jp/entry/" class="hatena-bookmark-button" data-hatena-bookmark-layout="standard" title="このエントリーをはてなブックマークに追加"><img src="http://b.st-hatena.com/images/entry-button/button-only.gif" alt="このエントリーをはてなブックマークに追加" width="20" height="20" style="border: none;"></a><script type="text/javascript" src="http://b.st-hatena.com/js/bookmark_button.js" charset="utf-8" async="async"></script></li>
            <li><a data-pocket-label="pocket" data-pocket-count="horizontal" class="pocket-btn" data-lang="en"></a>
            <script type="text/javascript">!function(d,i){if(!d.getElementById(i)){var j=d.createElement("script");j.id=i;j.src="https://widgets.getpocket.com/v1/j/btn.js?v=1";var w=d.getElementById(i);d.body.appendChild(j);}}(document,"pocket-btn-js");</script></li>
          </ul>

        </article>
        <aside class="span3">
          <div class="sidebar-module">
            <div class="title">プロフィール</div>
            <p class="id"><a href="https://twitter.com/dekokun">dekokun</a></p>
            <p><a href="https://twitter.com/dekokun"><img src="../img/dekokun.png" alt="dekokun"></a></p>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.io/";
              Hatena.BookmarkWidget.title = "人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 200;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.com/";
              Hatena.BookmarkWidget.title = "旧人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 0;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module visible-desktop">
            <div class="title">twitter</div>
            <a class="twitter-timeline" data-dnt="true" href="https://twitter.com/dekokun" data-widget-id="306408547573440513">@dekokun からのツイート</a>
            <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
          </div>
          <div class="sidebar-module hidden-phone">
            <div class="title">RSS</div>
            <p><a href="../rss.xml"><img src="../img/rss.gif" alt="rss"></a></p>
          </div>
        </aside> <!-- /span3 -->
      </div> <!-- /row -->
      <footer>
        <p>©<script type="text/javascript">$y=2012;$ny=new Date().getFullYear();document.write($ny>$y?$y+'-'+$ny:$y);</script> <a href="https://twitter.com/dekokun">dekokun</a></p>
      </footer>
    </div> <!-- /container -->

    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script>window.jQuery || document.write('<script src="../js/libs/jquery-1.7.2.min.js"><\/script>')</script>
    <!-- /ツイートボタン -->
  <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>

    <script src="../js/libs/bootstrap/bootstrap.min.js"></script>

    <script src="../js/script.js"></script>
    <script>
      var _gaq=[['_setAccount','UA-XXXXX-X'],['_trackPageview']];
      (function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
      g.src=('https:'==location.protocol?'//ssl':'//www')+'.google-analytics.com/ga.js';
      s.parentNode.insertBefore(g,s)}(document,'script'));
    </script>
    <!-- Code syntax highlight -->
    <script type="text/javascript" src="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.js"></script>
    <script type="text/javascript">
    $(function(){ 
        $('pre').css({
            'overflow-x': 'scroll',
            'background-color': '#f6f6f6',
            'border': '1px dotted #ccc',
            'padding': '0.8em'
        });
        $('pre code').addClass('prettyprint');
        prettyPrint();
    });
    </script>
    <script type="text/javascript" src="https://d1xnn692s7u6t6.cloudfront.net/widget.js"></script>
    <script type="text/javascript">(function k(){window.$SendToKindle&&window.$SendToKindle.Widget?$SendToKindle.Widget.init({"content":"article"}):setTimeout(k,500);})();</script>
  </body>
</html>
]]></description>
    <pubDate>No date found.</pubDate>
    <guid>http://dekokun.github.io/posts/2013-07-31.html</guid>
</item>
<item>
    <title>PostgreSQLのhstoreを触ってみた</title>
    <link>http://dekokun.github.io/posts/2013-08-06.html</link>
    <description><![CDATA[<!doctype html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7" lang="ja"> <![endif]-->
<!--[if IE 7]>    <html class="no-js lt-ie9 lt-ie8" lang="ja"> <![endif]-->
<!--[if IE 8]>    <html class="no-js lt-ie9" lang="ja"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="ja"> <!--<![endif]-->
  <head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# article: http://ogp.me/ns/article#">
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <title>PostgreSQLのhstoreを触ってみた</title>
    <meta name="description" content>
    <meta name="author" content>

    <meta name="viewport" content="width=device-width">
    <meta property="fb:app_id" content="351187098330864">
    <meta property="og:type" content="article">
    <meta property="og:image" content="http://dekokun.github.com/img/dekokun.png">
    <meta property="og:title" content="PostgreSQLのhstoreを触ってみた">
    <meta property="og:description" content="@dekokunの技術日記">
    <meta property="og:site_name" content="でこてっくろぐ">
    <meta name="twitter:widgets:csp" content="on">

    <link rel="stylesheet" href="../css/bootstrap.css">
    <link rel="stylesheet" href="../css/bootstrap-responsive.css">
    <link rel="stylesheet" href="../css/style.css">
    <style>
    body {
      padding-top: 60px;
      padding-bottom: 40px;
    }
    </style>
    <link href="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.css" type="text/css" rel="stylesheet">
    <script src="../js/libs/modernizr-2.5.3-respond-1.1.0.min.js"></script>
    <script>
      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

      ga('create', 'UA-39650556-1', 'auto');
      ga('send', 'pageview');
    </script>
  </head>
  <body>
  <!--[if lt IE 7]><p class=chromeframe>Your browser is <em>ancient!</em> <a href="http://browsehappy.com/">Upgrade to a different browser</a> or <a href="http://www.google.com/chromeframe/?redirect=true">install Google Chrome Frame</a> to experience this site.</p><![endif]-->
    <div id="fb-root"></div>
    <script>(function(d, s, id) {
      var js, fjs = d.getElementsByTagName(s)[0];
      if (d.getElementById(id)) return;
      js = d.createElement(s); js.id = id;
      js.src = "//connect.facebook.net/ja_JP/all.js#xfbml=1&appId=351187098330864";
      fjs.parentNode.insertBefore(js, fjs);
      }(document, 'script', 'facebook-jssdk'));
    </script>
    <header>
      <nav class="navbar navbar-fixed-top">
        <div class="navbar-inner">
          <div class="container">
            <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
            </a>
            <a class="brand" href="../index.html">でこてっくろぐ</a>
            <div class="nav-collapse">
              <ul class="nav">
                <li><a href="../index.html">ほーむ</a></li>
                <li><a href="../posts.html">あーかいぶ</a></li>
                <li><a href="../aboutme.html">あばうとみー</a></li>
              </ul>
            </div><!--/.nav-collapse -->
          </div>
        </div>
      </nav>
    </header>

    <div class="container">
      <div class="row">
        <article class="span9">
          <h1>PostgreSQLのhstoreを触ってみた</h1>

<p>by <em><a href="https://twitter.com/dekokun">@dekokun</a></em> on <strong>2013/08/05 22:38</strong></p>

<p>Tagged as: <a href="../tags/PostgreSQL.html">PostgreSQL</a>, <a href="../tags/hstore.html">hstore</a>.</p>

<p>PostgreSQLにはhstoreなる、キーと値の集合を単一の列に保持できる型があると聞き及びまして、普段MySQLな私ですがこれは一度触ってみなくてはいかんと触ってみたのでした。</p>
<p>普通のselectとの非常に簡単(かつ不正確)な速度比較とインデックス作成くらいしかやってませんが。</p>
<h2 id="導入">導入</h2>
<p>今回、AWSのm1.small上に構築したCentOS6.3を使用しています。PostgreSQLのバージョンは最新のStableバージョンである9.2を使用。</p>
<p><a href="http://yum.postgresql.org/">PostgreSQL RPM Building Project - Yum Repository</a>からstableバージョンをダウンロードし、</p>
<p>インストール</p>
<pre><code># rpm -ivh pgdg-centos92-9.2-6.noarch.rpm
# rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-PGDG-92
# yum -y install postgresql92-server
# yum -y install postgresql92-contrib.x86_64</code></pre>
<p>初期化</p>
<pre><code># service postgresql-9.2 initdb</code></pre>
<p>デーモンスタート</p>
<pre><code># service postgresql-9.2 start
# su - postgres
$ psql</code></pre>
<p>hstoreの有効化</p>
<pre><code>postgres=# CREATE EXTENSION hstore;</code></pre>
<h2 id="計測">計測</h2>
<pre><code>postgres=# \timing
Timing is on.</code></pre>
<p>テーブル作成</p>
<pre><code>postgres=# CREATE TABLE hstore_tbl AS
postgres-#     SELECT
postgres-#         ('&quot;hoge&quot;=&gt;' || RANDOM() || ' , &quot;fuga&quot;=&gt;2')::hstore AS hstore, cast(RANDOM() as text) AS fuga
postgres-#     FROM
postgres-#         generate_series(1,1000000)
postgres-#     ;
SELECT 1000000
Time: 5500.272 ms
postgres=# SELECT * FROM hstore_tbl LIMIT 1;
                  hstore                   |       fuga
-------------------------------------------+-------------------
 &quot;fuga&quot;=&gt;&quot;2&quot;, &quot;hoge&quot;=&gt;&quot;0.0839038179256022&quot; | 0.392216250766069
(1 row)

Time: 0.605 ms</code></pre>
<p>hstoreなカラムの検索</p>
<pre><code>postgres=# select * from hstore_tbl where hstore-&gt;'hoge' = '0.0839038179256022';
                  hstore                   |       fuga
-------------------------------------------+-------------------
 &quot;fuga&quot;=&gt;&quot;2&quot;, &quot;hoge&quot;=&gt;&quot;0.0839038179256022&quot; | 0.392216250766069
(1 row)

Time: 302.522 ms</code></pre>
<p>速度比較のための普通のカラムの検索</p>
<pre><code>postgres=# select * from hstore_tbl where fuga = '0.392216250766069';
                  hstore                   |       fuga
-------------------------------------------+-------------------
 &quot;fuga&quot;=&gt;&quot;2&quot;, &quot;hoge&quot;=&gt;&quot;0.0839038179256022&quot; | 0.392216250766069
(1 row)
Time: 205.692 ms</code></pre>
<p>やはりhstoreな検索よりは早いですねぇ(一回実施した時の時間だけじゃなんとも言えないというのが正しい見方ですが、まぁ、何回か同じクエリを流してみてこんな感じだったので、雰囲気hstoreのほうが少し遅い、といっても速度比1.5倍ですが、まぁ。。という感じでいいでしょう)</p>
<p>インデックスを貼ってみた</p>
<pre><code>postgres=# CREATE INDEX hstore_index ON hstore_tbl ((hstore-&gt;'hoge'));
CREATE INDEX
Time: 18843.262 ms
postgres=# CREATE INDEX text_index ON hstore_tbl (fuga);
CREATE INDEX
Time: 53691.437 ms
postgres=# select * from hstore_tbl where fuga = '0.392216250766069';
                  hstore                   |       fuga
-------------------------------------------+-------------------
 &quot;fuga&quot;=&gt;&quot;2&quot;, &quot;hoge&quot;=&gt;&quot;0.0839038179256022&quot; | 0.392216250766069
(1 row)

Time: 0.756 ms
postgres=# select * from hstore_tbl where hstore-&gt;'hoge' = '0.0839038179256022';
                  hstore                   |       fuga
-------------------------------------------+-------------------
 &quot;fuga&quot;=&gt;&quot;2&quot;, &quot;hoge&quot;=&gt;&quot;0.0839038179256022&quot; | 0.392216250766069
(1 row)

Time: 0.604 ms</code></pre>
<p>hstore型なカラムの検索、ド派手に遅くなるんじゃないかと思っておりましたが意外とそんなことはないんですね。</p>
<p>インデックスも貼れますし、今後使用を検討してもいいかもしれませんね。</p>
<p>最後に、<a href="https://twitter.com/r_rudi">@r_rudy</a>さんとのやり取り</p>
<blockquote class="twitter-tweet"><p>
<a href="https://twitter.com/dekokun">@dekokun</a> かなり便利ですよ。indexも貼れますし。ただ、データの取り出しがちょっと遅いので、普段使う分には問題ないですが、速度がものすごく重要なところには使わないほうがいいかと思います。
</p>
— しろう (@r_rudi) <a href="https://twitter.com/r_rudi/statuses/364370906103033858">August 5, 2013</a>
</blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>

<blockquote class="twitter-tweet"><p>
<a href="https://twitter.com/dekokun">@dekokun</a> 遅いのは内部実装がTextという文字列で持っているからなのですが、そこをmsgpackにするという試験実装をされた方がいまして、数倍速くなったそうです。PostgreSQLにはほかにもいろいろ便利な機能があるのでぜひ使ってください！
</p>
— しろう (@r_rudi) <a href="https://twitter.com/r_rudi/statuses/364372885256671232">August 5, 2013</a>
</blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>

<p>FDWとかも私、興味あります</p>

<div id="disqus_thread"></div>
<script type="text/javascript">
    /* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */
    var disqus_shortname = 'dekokun'; // required: replace example with your forum shortname

    /* * * DON'T EDIT BELOW THIS LINE * * */
    (function() {
        var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
        dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js';
        (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
    })();
</script>
<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
<a href="http://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a>

          <ul class="social">
            <li class="kindle"><div class="kindleWidget"><img style="vertical-align:middle;" src="https://d1xnn692s7u6t6.cloudfront.net/white-15.png" /><span style="vertical-align:middle;margin-left:3px;">Send to Kindle</span></div></li>
            <li class="facebook"><div class="fb-like" data-send="false" data-layout="button_count" data-width="100" data-show-faces="true" data-font="arial"></div></li>
            <li class="twitter"><a href="https://twitter.com/share" class="twitter-share-button" data-via="dekokun" data-lang="ja">ツイート</a></li>
            <li class="hatena-bookmark"><a href="http://b.hatena.ne.jp/entry/" class="hatena-bookmark-button" data-hatena-bookmark-layout="standard" title="このエントリーをはてなブックマークに追加"><img src="http://b.st-hatena.com/images/entry-button/button-only.gif" alt="このエントリーをはてなブックマークに追加" width="20" height="20" style="border: none;"></a><script type="text/javascript" src="http://b.st-hatena.com/js/bookmark_button.js" charset="utf-8" async="async"></script></li>
            <li><a data-pocket-label="pocket" data-pocket-count="horizontal" class="pocket-btn" data-lang="en"></a>
            <script type="text/javascript">!function(d,i){if(!d.getElementById(i)){var j=d.createElement("script");j.id=i;j.src="https://widgets.getpocket.com/v1/j/btn.js?v=1";var w=d.getElementById(i);d.body.appendChild(j);}}(document,"pocket-btn-js");</script></li>
          </ul>

        </article>
        <aside class="span3">
          <div class="sidebar-module">
            <div class="title">プロフィール</div>
            <p class="id"><a href="https://twitter.com/dekokun">dekokun</a></p>
            <p><a href="https://twitter.com/dekokun"><img src="../img/dekokun.png" alt="dekokun"></a></p>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.io/";
              Hatena.BookmarkWidget.title = "人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 200;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.com/";
              Hatena.BookmarkWidget.title = "旧人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 0;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module visible-desktop">
            <div class="title">twitter</div>
            <a class="twitter-timeline" data-dnt="true" href="https://twitter.com/dekokun" data-widget-id="306408547573440513">@dekokun からのツイート</a>
            <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
          </div>
          <div class="sidebar-module hidden-phone">
            <div class="title">RSS</div>
            <p><a href="../rss.xml"><img src="../img/rss.gif" alt="rss"></a></p>
          </div>
        </aside> <!-- /span3 -->
      </div> <!-- /row -->
      <footer>
        <p>©<script type="text/javascript">$y=2012;$ny=new Date().getFullYear();document.write($ny>$y?$y+'-'+$ny:$y);</script> <a href="https://twitter.com/dekokun">dekokun</a></p>
      </footer>
    </div> <!-- /container -->

    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script>window.jQuery || document.write('<script src="../js/libs/jquery-1.7.2.min.js"><\/script>')</script>
    <!-- /ツイートボタン -->
  <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>

    <script src="../js/libs/bootstrap/bootstrap.min.js"></script>

    <script src="../js/script.js"></script>
    <script>
      var _gaq=[['_setAccount','UA-XXXXX-X'],['_trackPageview']];
      (function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
      g.src=('https:'==location.protocol?'//ssl':'//www')+'.google-analytics.com/ga.js';
      s.parentNode.insertBefore(g,s)}(document,'script'));
    </script>
    <!-- Code syntax highlight -->
    <script type="text/javascript" src="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.js"></script>
    <script type="text/javascript">
    $(function(){ 
        $('pre').css({
            'overflow-x': 'scroll',
            'background-color': '#f6f6f6',
            'border': '1px dotted #ccc',
            'padding': '0.8em'
        });
        $('pre code').addClass('prettyprint');
        prettyPrint();
    });
    </script>
    <script type="text/javascript" src="https://d1xnn692s7u6t6.cloudfront.net/widget.js"></script>
    <script type="text/javascript">(function k(){window.$SendToKindle&&window.$SendToKindle.Widget?$SendToKindle.Widget.init({"content":"article"}):setTimeout(k,500);})();</script>
  </body>
</html>
]]></description>
    <pubDate>No date found.</pubDate>
    <guid>http://dekokun.github.io/posts/2013-08-06.html</guid>
</item>
<item>
    <title>git ls-remoteコマンドの終了ステータスがデフォルトでは期待するものと違う件とその対策</title>
    <link>http://dekokun.github.io/posts/2013-08-26.html</link>
    <description><![CDATA[<!doctype html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7" lang="ja"> <![endif]-->
<!--[if IE 7]>    <html class="no-js lt-ie9 lt-ie8" lang="ja"> <![endif]-->
<!--[if IE 8]>    <html class="no-js lt-ie9" lang="ja"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="ja"> <!--<![endif]-->
  <head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# article: http://ogp.me/ns/article#">
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <title>git ls-remoteコマンドの終了ステータスがデフォルトでは期待するものと違う件とその対策</title>
    <meta name="description" content>
    <meta name="author" content>

    <meta name="viewport" content="width=device-width">
    <meta property="fb:app_id" content="351187098330864">
    <meta property="og:type" content="article">
    <meta property="og:image" content="http://dekokun.github.com/img/dekokun.png">
    <meta property="og:title" content="git ls-remoteコマンドの終了ステータスがデフォルトでは期待するものと違う件とその対策">
    <meta property="og:description" content="@dekokunの技術日記">
    <meta property="og:site_name" content="でこてっくろぐ">
    <meta name="twitter:widgets:csp" content="on">

    <link rel="stylesheet" href="../css/bootstrap.css">
    <link rel="stylesheet" href="../css/bootstrap-responsive.css">
    <link rel="stylesheet" href="../css/style.css">
    <style>
    body {
      padding-top: 60px;
      padding-bottom: 40px;
    }
    </style>
    <link href="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.css" type="text/css" rel="stylesheet">
    <script src="../js/libs/modernizr-2.5.3-respond-1.1.0.min.js"></script>
    <script>
      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

      ga('create', 'UA-39650556-1', 'auto');
      ga('send', 'pageview');
    </script>
  </head>
  <body>
  <!--[if lt IE 7]><p class=chromeframe>Your browser is <em>ancient!</em> <a href="http://browsehappy.com/">Upgrade to a different browser</a> or <a href="http://www.google.com/chromeframe/?redirect=true">install Google Chrome Frame</a> to experience this site.</p><![endif]-->
    <div id="fb-root"></div>
    <script>(function(d, s, id) {
      var js, fjs = d.getElementsByTagName(s)[0];
      if (d.getElementById(id)) return;
      js = d.createElement(s); js.id = id;
      js.src = "//connect.facebook.net/ja_JP/all.js#xfbml=1&appId=351187098330864";
      fjs.parentNode.insertBefore(js, fjs);
      }(document, 'script', 'facebook-jssdk'));
    </script>
    <header>
      <nav class="navbar navbar-fixed-top">
        <div class="navbar-inner">
          <div class="container">
            <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
            </a>
            <a class="brand" href="../index.html">でこてっくろぐ</a>
            <div class="nav-collapse">
              <ul class="nav">
                <li><a href="../index.html">ほーむ</a></li>
                <li><a href="../posts.html">あーかいぶ</a></li>
                <li><a href="../aboutme.html">あばうとみー</a></li>
              </ul>
            </div><!--/.nav-collapse -->
          </div>
        </div>
      </nav>
    </header>

    <div class="container">
      <div class="row">
        <article class="span9">
          <h1>git ls-remoteコマンドの終了ステータスがデフォルトでは期待するものと違う件とその対策</h1>

<p>by <em><a href="https://twitter.com/dekokun">@dekokun</a></em> on <strong>2012/08/26 1:30</strong></p>

<p>Tagged as: <a href="../tags/git.html">git</a>.</p>

<p>なんらかの要因で、自前でデプロイスクリプトを構築していたとします。</p>
<p>タグやブランチ名を指定したデプロイを可能にしたかったとします。</p>
<p>リモートリポジトリに存在しないタグやブランチをデプロイ対象として指定されたらエラーにしたいため、リモートリポジトリにそのタグやブランチが存在するかどうかを知りたいとします。</p>
<p>そんなことはgit ls-remoteにてできそうだったので試してみたら、イマイチだったという話とその解決策。</p>
<h2 id="説明">説明</h2>
<p>git ls-remoteコマンドは、リポジトリの場所とリファレンスを引数に渡すとそのコミットIDを取得してくれるコマンドなのです。 私のリポジトリのmasterのコミットIDを取得しようとすると、こんな感じ。</p>
<pre><code>git ls-remote git@github.com:dekokun/dekokun.github.com_data.git master
d4e508e59b4fb38f41489d7bef8aa1be8e1bd9ec        refs/heads/master</code></pre>
<p>これを使えば、存在しないブランチやらタグの取得は、git ls-remoteの終了ステータスコードを利用して</p>
<pre><code># 注：このコードは想定通りに動きません
git ls-remote git@github.com:dekokun/dekokun.github.com_data.git hogehogefugafuga &gt;/dev/null 2&gt;&amp;1
if [ $? -ne 0 ]; then
  echo '存在するブランチを指定してね〜'
  usage
  exit 1
fi</code></pre>
<p>みたいなことできそうじゃないですか。しかし残念ながらそれは無理なんです。なぜなら、git ls-remoteはそのリファレンスが存在しなくても終了ステータスは0(正常終了)を返してくれてしまうからなのですね。</p>
<pre><code>git ls-remote git@github.com:dekokun/dekokun.github.com_data.git not-exists-branch; echo $?
0</code></pre>
<p>あらあらどうしましょうという感じだったので、解決策を2点ほど。</p>
<h2 id="解決策">解決策</h2>
<h3 id="オプションを変えるgit-1.7.6以降">オプションを変える(git 1.7.6以降)</h3>
<p>exit-codeオプションをつけると、存在しないリファレンスを指定した際の終了コードは2が返ってきます。</p>
<pre><code>git ls-remote --exit-code git@github.com:dekokun/dekokun.github.com_data.git not-exists; echo $?
2</code></pre>
<p>これなら以下が使えますね。</p>
<pre><code>git ls-remote --exit-code git@github.com:dekokun/dekokun.github.com_data.git hogehogefugafuga &gt;/dev/null 2&gt;&amp;1
if [ $? -ne 0 ]; then
  echo '存在するブランチを指定してね〜'
  usage
  exit 1
fi</code></pre>
<p>ただし、git 1.7.6以降…</p>
<h3 id="力技">力技</h3>
<p>存在しないリファレンスを指定した際は出力が0行であることを利用します。</p>
<pre><code>if [ $(git ls-remote $git_url $version | wc -l) -eq 0 ]; then
  echo '存在するブランチを指定してね〜'
  usage
  exit 1
fi</code></pre>
<h2 id="まとめ">まとめ</h2>
<p>git 1.7.6以降を使おう。 git ls-remote以外を使ったもっと簡単な方法あるかなぁ。</p>

<div id="disqus_thread"></div>
<script type="text/javascript">
    /* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */
    var disqus_shortname = 'dekokun'; // required: replace example with your forum shortname

    /* * * DON'T EDIT BELOW THIS LINE * * */
    (function() {
        var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
        dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js';
        (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
    })();
</script>
<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
<a href="http://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a>

          <ul class="social">
            <li class="kindle"><div class="kindleWidget"><img style="vertical-align:middle;" src="https://d1xnn692s7u6t6.cloudfront.net/white-15.png" /><span style="vertical-align:middle;margin-left:3px;">Send to Kindle</span></div></li>
            <li class="facebook"><div class="fb-like" data-send="false" data-layout="button_count" data-width="100" data-show-faces="true" data-font="arial"></div></li>
            <li class="twitter"><a href="https://twitter.com/share" class="twitter-share-button" data-via="dekokun" data-lang="ja">ツイート</a></li>
            <li class="hatena-bookmark"><a href="http://b.hatena.ne.jp/entry/" class="hatena-bookmark-button" data-hatena-bookmark-layout="standard" title="このエントリーをはてなブックマークに追加"><img src="http://b.st-hatena.com/images/entry-button/button-only.gif" alt="このエントリーをはてなブックマークに追加" width="20" height="20" style="border: none;"></a><script type="text/javascript" src="http://b.st-hatena.com/js/bookmark_button.js" charset="utf-8" async="async"></script></li>
            <li><a data-pocket-label="pocket" data-pocket-count="horizontal" class="pocket-btn" data-lang="en"></a>
            <script type="text/javascript">!function(d,i){if(!d.getElementById(i)){var j=d.createElement("script");j.id=i;j.src="https://widgets.getpocket.com/v1/j/btn.js?v=1";var w=d.getElementById(i);d.body.appendChild(j);}}(document,"pocket-btn-js");</script></li>
          </ul>

        </article>
        <aside class="span3">
          <div class="sidebar-module">
            <div class="title">プロフィール</div>
            <p class="id"><a href="https://twitter.com/dekokun">dekokun</a></p>
            <p><a href="https://twitter.com/dekokun"><img src="../img/dekokun.png" alt="dekokun"></a></p>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.io/";
              Hatena.BookmarkWidget.title = "人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 200;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.com/";
              Hatena.BookmarkWidget.title = "旧人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 0;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module visible-desktop">
            <div class="title">twitter</div>
            <a class="twitter-timeline" data-dnt="true" href="https://twitter.com/dekokun" data-widget-id="306408547573440513">@dekokun からのツイート</a>
            <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
          </div>
          <div class="sidebar-module hidden-phone">
            <div class="title">RSS</div>
            <p><a href="../rss.xml"><img src="../img/rss.gif" alt="rss"></a></p>
          </div>
        </aside> <!-- /span3 -->
      </div> <!-- /row -->
      <footer>
        <p>©<script type="text/javascript">$y=2012;$ny=new Date().getFullYear();document.write($ny>$y?$y+'-'+$ny:$y);</script> <a href="https://twitter.com/dekokun">dekokun</a></p>
      </footer>
    </div> <!-- /container -->

    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script>window.jQuery || document.write('<script src="../js/libs/jquery-1.7.2.min.js"><\/script>')</script>
    <!-- /ツイートボタン -->
  <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>

    <script src="../js/libs/bootstrap/bootstrap.min.js"></script>

    <script src="../js/script.js"></script>
    <script>
      var _gaq=[['_setAccount','UA-XXXXX-X'],['_trackPageview']];
      (function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
      g.src=('https:'==location.protocol?'//ssl':'//www')+'.google-analytics.com/ga.js';
      s.parentNode.insertBefore(g,s)}(document,'script'));
    </script>
    <!-- Code syntax highlight -->
    <script type="text/javascript" src="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.js"></script>
    <script type="text/javascript">
    $(function(){ 
        $('pre').css({
            'overflow-x': 'scroll',
            'background-color': '#f6f6f6',
            'border': '1px dotted #ccc',
            'padding': '0.8em'
        });
        $('pre code').addClass('prettyprint');
        prettyPrint();
    });
    </script>
    <script type="text/javascript" src="https://d1xnn692s7u6t6.cloudfront.net/widget.js"></script>
    <script type="text/javascript">(function k(){window.$SendToKindle&&window.$SendToKindle.Widget?$SendToKindle.Widget.init({"content":"article"}):setTimeout(k,500);})();</script>
  </body>
</html>
]]></description>
    <pubDate>No date found.</pubDate>
    <guid>http://dekokun.github.io/posts/2013-08-26.html</guid>
</item>
<item>
    <title>トランザクションが存在しないDBにてその弱点をどのようにカバーするか</title>
    <link>http://dekokun.github.io/posts/2013-09-30.html</link>
    <description><![CDATA[<!doctype html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7" lang="ja"> <![endif]-->
<!--[if IE 7]>    <html class="no-js lt-ie9 lt-ie8" lang="ja"> <![endif]-->
<!--[if IE 8]>    <html class="no-js lt-ie9" lang="ja"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="ja"> <!--<![endif]-->
  <head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# article: http://ogp.me/ns/article#">
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <title>トランザクションが存在しないDBにてその弱点をどのようにカバーするか</title>
    <meta name="description" content>
    <meta name="author" content>

    <meta name="viewport" content="width=device-width">
    <meta property="fb:app_id" content="351187098330864">
    <meta property="og:type" content="article">
    <meta property="og:image" content="http://dekokun.github.com/img/dekokun.png">
    <meta property="og:title" content="トランザクションが存在しないDBにてその弱点をどのようにカバーするか">
    <meta property="og:description" content="@dekokunの技術日記">
    <meta property="og:site_name" content="でこてっくろぐ">
    <meta name="twitter:widgets:csp" content="on">

    <link rel="stylesheet" href="../css/bootstrap.css">
    <link rel="stylesheet" href="../css/bootstrap-responsive.css">
    <link rel="stylesheet" href="../css/style.css">
    <style>
    body {
      padding-top: 60px;
      padding-bottom: 40px;
    }
    </style>
    <link href="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.css" type="text/css" rel="stylesheet">
    <script src="../js/libs/modernizr-2.5.3-respond-1.1.0.min.js"></script>
    <script>
      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

      ga('create', 'UA-39650556-1', 'auto');
      ga('send', 'pageview');
    </script>
  </head>
  <body>
  <!--[if lt IE 7]><p class=chromeframe>Your browser is <em>ancient!</em> <a href="http://browsehappy.com/">Upgrade to a different browser</a> or <a href="http://www.google.com/chromeframe/?redirect=true">install Google Chrome Frame</a> to experience this site.</p><![endif]-->
    <div id="fb-root"></div>
    <script>(function(d, s, id) {
      var js, fjs = d.getElementsByTagName(s)[0];
      if (d.getElementById(id)) return;
      js = d.createElement(s); js.id = id;
      js.src = "//connect.facebook.net/ja_JP/all.js#xfbml=1&appId=351187098330864";
      fjs.parentNode.insertBefore(js, fjs);
      }(document, 'script', 'facebook-jssdk'));
    </script>
    <header>
      <nav class="navbar navbar-fixed-top">
        <div class="navbar-inner">
          <div class="container">
            <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
            </a>
            <a class="brand" href="../index.html">でこてっくろぐ</a>
            <div class="nav-collapse">
              <ul class="nav">
                <li><a href="../index.html">ほーむ</a></li>
                <li><a href="../posts.html">あーかいぶ</a></li>
                <li><a href="../aboutme.html">あばうとみー</a></li>
              </ul>
            </div><!--/.nav-collapse -->
          </div>
        </div>
      </nav>
    </header>

    <div class="container">
      <div class="row">
        <article class="span9">
          <h1>トランザクションが存在しないDBにてその弱点をどのようにカバーするか</h1>

<p>by <em><a href="https://twitter.com/dekokun">@dekokun</a></em> on <strong>2013/09/30 23:30</strong></p>

<p>Tagged as: <a href="../tags/NoSQL.html">NoSQL</a>.</p>

<p>NoSQL系のDBをメインDBとして使用する場合、最もネックになってくるのはトランザクション周りかと思います。 DBとしてトランザクション機能が提供されていない中でその弱点をどのようにソフトウェアでカバーするかをまとめます。</p>
<p>なお、以下は机上の空論である部分が多く、これから知見を得る度に追記していこうかと思います。</p>
<p>なお、基本的にMongoDB, DynamoDBあたりのドキュメント指向DBを想定した記事です。完全なるKVS系(memcachedとか)では、以下記事があてはまらない場合もあるかと思います。</p>
<h2 id="カバーすべきトランザクションの性質">カバーすべきトランザクションの性質</h2>
<p>トランザクションの持つべき性質として、「ACID」と呼ばれる以下4つの性質があります。</p>
<p>参考：<a href="http://ja.wikipedia.org/wiki/ACID_(コンピュータ科学)">ACID (コンピュータ科学) - Wikipedia</a></p>
<h3 id="原子性">原子性</h3>
<ul>
<li>トランザクションに含まれるタスクが全て実行されるか全く実行されないかを保証する性質</li>
<li>「書き込み失敗したりしたらロールバックすればデータが中途半端に残らなくていいやー」というアレ。これがあると極めて楽ですね。</li>
</ul>
<h3 id="一貫性">一貫性</h3>
<ul>
<li>常にデータベースの整合性が保たれていることを保証する性質</li>
<li>これについてはイマイチ私はよくわかってないのですが、トランザクションの前後で外部制約やユニーク制約などが満たされているという認識でいいのかな。</li>
</ul>
<h3 id="独立性">独立性</h3>
<ul>
<li>トランザクション中に行われる過程が他の操作から隠蔽されること</li>
<li>「デッドロック以外は、他のスレッドからどのようにDB更新されるかあまり気にしなくていいよ〜」という感じ。楽ですね。まぁ、実際に左記のような態度で開発に望むと色々と大変なことになりますが。ロック待ちから開放されないとか、ファントム・リードが発生しておかしなことになるとか。</li>
<li>たいていのDBは性能とのトレードオフから完全な独立性は保証しない設定になっている
<ul>
<li>トランザクション分離レベルの変更によってどの程度独立性を保つか規定が可能</li>
<li>ちなみに最近知ったのだが、MySQLとPostgreSQL及びOracleでデフォルトの分離レベルが異なる。MySQLはデフォルトがREPEATABLE READであるのに対して他の2つはREAD COMMITTED</li>
</ul></li>
</ul>
<h3 id="永続性">永続性</h3>
<ul>
<li>トランザクションが完了した操作は、永続的になることが確定していること</li>
<li>一度トランザクションが完了したら、旧にDBが落ちたりした後に復旧させたりしても対象の操作をした結果はDBに反映されている状態となっているものですね。便利ですね。</li>
<li>たいていのRDBMSは、トランザクション完了時のトランザクションログ(MySQLでいうところのバイナリログ)への書き込みとロールフォワードでこれを実現していますね。</li>
</ul>
<h2 id="トランザクションをソフトウェアでどのようにある程度実現するか">トランザクションをソフトウェアでどのように(ある程度)実現するか</h2>
<p>今回は、上記の機能をソフトウェアでどのように実現するかを考えていきます。</p>
<p>なお、以下の文章はどのDBについてなのか規定していませんが、RDBMSでいうところの「テーブル、レコード」(ドキュメント系のDBでは「コレクション、ドキュメント」など)のことは、一律「テーブル」、「レコード」と呼ぶことにします。</p>
<h3 id="原子性の対策">原子性の対策</h3>
<h4 id="どの操作が成功したか失敗したかを記録し失敗した操作が1つでもあった場合は他の成功した操作を巻き戻す">どの操作が成功したか、失敗したかを記録し、失敗した操作が1つでもあった場合は他の成功した操作を巻き戻す</h4>
<ul>
<li>王道ですね。</li>
<li>弱点
<ul>
<li>実装が複雑</li>
<li>「2をたす」のを巻き戻す場合は「2を引く」でいいと思いますが、例えば「名前を太郎から二郎に変更」などを行った場合、巻き戻す場合に「二郎」にしていいかどうかというのは議論がわかれるところ。別スレッドが「太郎から三郎に変更」など行っていた場合は巻き戻しによってその変更が消えてしまうことに</li>
<li>以下に全体的に言える話として、「」</li>
</ul></li>
</ul>
<h4 id="操作の冪等性を担保しながら失敗した際は再実行する">操作の冪等性を担保しながら失敗した際は再実行する</h4>
<ul>
<li>Version Numberパターンなどの、「そのレコードが、特定の条件を満たせば更新(以前読み込んだデータとバージョン番号が同じだったら更新)」というような楽観的ロックを使用して操作の冪等性を担保した形で1つ1つの操作を規定し、まとまった操作の中の1つでも失敗したら全ての操作をもう一度再実行する</li>
<li>弱点
<ul>
<li>「(主キー以外の)条件を指定して更新を行う」ことができないDBでは実施できない</li>
<li>常に失敗するような操作が操作のまとまりの中に存在すると、下手すりゃ無限ループになる。かといって「◯◯回やっても失敗したら再実行をやめる」とすると、中途半端に操作されたままの状態になってしまうし…</li>
<li>Version Numberパターンを使用した場合、他のスレッドなどから対象のレコードを操作されるてバージョンが変化すると、対象の行が更新できずに、整合性が失われる</li>
</ul></li>
</ul>
<h4 id="トランザクションが1行の更新のみになるように設計する">1トランザクションが1行の更新のみになるように設計する</h4>
<ul>
<li>これならそもそも1回の更新が成功するか失敗するかのみであるので、原子性を考える必要がない</li>
<li>弱点
<ul>
<li>1つのレコードの更新がアトミックにできないDBでは実施できない</li>
<li>そもそも、全てのデータ更新を、1行の更新だけにすることは不可能</li>
</ul></li>
</ul>
<h4 id="トランザクションテーブルを使用した多相コミット">トランザクションテーブルを使用した多相コミット</h4>
<ul>
<li>トランザクション用のテーブルを使用して、まぁ頑張る方法。</li>
<li>詳細な方法は複雑なので、まぁ「多相コミット」とかで検索してください</li>
<li>なんらかの原因により処理が途中で終わってしまっても、「どの処理が完了していないか」「その処理の中で完了していないのはどのレコードか」というのが分かる</li>
<li>弱点
<ul>
<li>1つのレコードの更新がアトミックにできないDBでは実施できない</li>
<li>実装が複雑</li>
</ul></li>
</ul>
<h3 id="一貫性の対策">一貫性の対策</h3>
<p>要検討。「ソフトウェア側でバリデーションを行う」くらいですか？</p>
<h3 id="独立性の対策">独立性の対策</h3>
<h4 id="楽観ロック">楽観ロック</h4>
<ul>
<li>Version Numberパターンなどを使用した楽観ロックを使用し、書き込み件数が0件だったらバージョン番号の取得部分から再実行(もしくは書き込み失敗としてエラーを返す)</li>
<li>弱点
<ul>
<li>「(主キー以外の)条件を指定して更新を行う」ことができないDBでは実施できない</li>
<li>書き込みが何件行われたかが分からないDBでは実施できない</li>
</ul></li>
</ul>
<h3 id="永続性の対策">永続性の対策</h3>
<p>こちらに関しては、完全にDBの機能に依存しますかねぇ。自前でディスクに書き込んでいくという手はあるかもしれないが…性能面でも実装面でも難しいでしょうね。そんなことするくらいなら素直にRDBMS使うべきですね。</p>
<h4 id="トランザクションログ的な機能を有効にする">トランザクションログ的な機能を有効にする</h4>
<ul>
<li>そういう機能があるなら有効にしましょう</li>
<li>弱点
<ul>
<li>トランザクションログ的な機能がないDBでは実施できない</li>
<li>自動フェイルオーバー機能を備えて複数マスターになりうるようなDBの場合、1台が落ちたら他のDBがマスターになり、新しいマスターに反映されていないデータは消失する</li>
</ul></li>
</ul>
<h4 id="書き込みの際にディスクに書き込まれたことを保証するようなオプションをつける">書き込みの際に、「ディスクに書き込まれたことを保証する」ようなオプションをつける</h4>
<ul>
<li>そういう機能があるなら有効にしましょう</li>
<li>弱点
<ul>
<li>そのような機能がないDBでは実施できない</li>
<li>自動フェイルオーバー機能を備えて複数マスターになりうるようなDBの場合、1台が落ちたら他のDBがマスターになり、新しいマスターに反映されていないデータは消失する
<ul>
<li>RiakやMongoDBでは、スレーブに書き込まれたことを保証する書き込みもありましたね</li>
</ul></li>
</ul></li>
</ul>
<h2 id="まとめ">まとめ</h2>
<ul>
<li>基本的にはトランザクションを考えなくてもいい部分と必要な部分に分け、必要な部分だけ上記対策を施しましょう</li>
<li>上記を全部実施するくらいならRDBMS使ったほうが幸せなのではないかなとは思います
<ul>
<li>トランザクション及び高可用性が必要だったら、MySQL Clusterを使うとか(MySQL Clusterのこと、全然詳しくないですが)</li>
</ul></li>
</ul>

<div id="disqus_thread"></div>
<script type="text/javascript">
    /* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */
    var disqus_shortname = 'dekokun'; // required: replace example with your forum shortname

    /* * * DON'T EDIT BELOW THIS LINE * * */
    (function() {
        var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
        dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js';
        (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
    })();
</script>
<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
<a href="http://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a>

          <ul class="social">
            <li class="kindle"><div class="kindleWidget"><img style="vertical-align:middle;" src="https://d1xnn692s7u6t6.cloudfront.net/white-15.png" /><span style="vertical-align:middle;margin-left:3px;">Send to Kindle</span></div></li>
            <li class="facebook"><div class="fb-like" data-send="false" data-layout="button_count" data-width="100" data-show-faces="true" data-font="arial"></div></li>
            <li class="twitter"><a href="https://twitter.com/share" class="twitter-share-button" data-via="dekokun" data-lang="ja">ツイート</a></li>
            <li class="hatena-bookmark"><a href="http://b.hatena.ne.jp/entry/" class="hatena-bookmark-button" data-hatena-bookmark-layout="standard" title="このエントリーをはてなブックマークに追加"><img src="http://b.st-hatena.com/images/entry-button/button-only.gif" alt="このエントリーをはてなブックマークに追加" width="20" height="20" style="border: none;"></a><script type="text/javascript" src="http://b.st-hatena.com/js/bookmark_button.js" charset="utf-8" async="async"></script></li>
            <li><a data-pocket-label="pocket" data-pocket-count="horizontal" class="pocket-btn" data-lang="en"></a>
            <script type="text/javascript">!function(d,i){if(!d.getElementById(i)){var j=d.createElement("script");j.id=i;j.src="https://widgets.getpocket.com/v1/j/btn.js?v=1";var w=d.getElementById(i);d.body.appendChild(j);}}(document,"pocket-btn-js");</script></li>
          </ul>

        </article>
        <aside class="span3">
          <div class="sidebar-module">
            <div class="title">プロフィール</div>
            <p class="id"><a href="https://twitter.com/dekokun">dekokun</a></p>
            <p><a href="https://twitter.com/dekokun"><img src="../img/dekokun.png" alt="dekokun"></a></p>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.io/";
              Hatena.BookmarkWidget.title = "人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 200;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.com/";
              Hatena.BookmarkWidget.title = "旧人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 0;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module visible-desktop">
            <div class="title">twitter</div>
            <a class="twitter-timeline" data-dnt="true" href="https://twitter.com/dekokun" data-widget-id="306408547573440513">@dekokun からのツイート</a>
            <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
          </div>
          <div class="sidebar-module hidden-phone">
            <div class="title">RSS</div>
            <p><a href="../rss.xml"><img src="../img/rss.gif" alt="rss"></a></p>
          </div>
        </aside> <!-- /span3 -->
      </div> <!-- /row -->
      <footer>
        <p>©<script type="text/javascript">$y=2012;$ny=new Date().getFullYear();document.write($ny>$y?$y+'-'+$ny:$y);</script> <a href="https://twitter.com/dekokun">dekokun</a></p>
      </footer>
    </div> <!-- /container -->

    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script>window.jQuery || document.write('<script src="../js/libs/jquery-1.7.2.min.js"><\/script>')</script>
    <!-- /ツイートボタン -->
  <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>

    <script src="../js/libs/bootstrap/bootstrap.min.js"></script>

    <script src="../js/script.js"></script>
    <script>
      var _gaq=[['_setAccount','UA-XXXXX-X'],['_trackPageview']];
      (function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
      g.src=('https:'==location.protocol?'//ssl':'//www')+'.google-analytics.com/ga.js';
      s.parentNode.insertBefore(g,s)}(document,'script'));
    </script>
    <!-- Code syntax highlight -->
    <script type="text/javascript" src="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.js"></script>
    <script type="text/javascript">
    $(function(){ 
        $('pre').css({
            'overflow-x': 'scroll',
            'background-color': '#f6f6f6',
            'border': '1px dotted #ccc',
            'padding': '0.8em'
        });
        $('pre code').addClass('prettyprint');
        prettyPrint();
    });
    </script>
    <script type="text/javascript" src="https://d1xnn692s7u6t6.cloudfront.net/widget.js"></script>
    <script type="text/javascript">(function k(){window.$SendToKindle&&window.$SendToKindle.Widget?$SendToKindle.Widget.init({"content":"article"}):setTimeout(k,500);})();</script>
  </body>
</html>
]]></description>
    <pubDate>No date found.</pubDate>
    <guid>http://dekokun.github.io/posts/2013-09-30.html</guid>
</item>
<item>
    <title>ISUCON予選にPHP実装で参加して3位になりましたーやったことなどまとめ</title>
    <link>http://dekokun.github.io/posts/2013-10-06.html</link>
    <description><![CDATA[<!doctype html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7" lang="ja"> <![endif]-->
<!--[if IE 7]>    <html class="no-js lt-ie9 lt-ie8" lang="ja"> <![endif]-->
<!--[if IE 8]>    <html class="no-js lt-ie9" lang="ja"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="ja"> <!--<![endif]-->
  <head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# article: http://ogp.me/ns/article#">
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <title>ISUCON予選にPHP実装で参加して3位になりましたーやったことなどまとめ</title>
    <meta name="description" content>
    <meta name="author" content>

    <meta name="viewport" content="width=device-width">
    <meta property="fb:app_id" content="351187098330864">
    <meta property="og:type" content="article">
    <meta property="og:image" content="http://dekokun.github.com/img/dekokun.png">
    <meta property="og:title" content="ISUCON予選にPHP実装で参加して3位になりましたーやったことなどまとめ">
    <meta property="og:description" content="@dekokunの技術日記">
    <meta property="og:site_name" content="でこてっくろぐ">
    <meta name="twitter:widgets:csp" content="on">

    <link rel="stylesheet" href="../css/bootstrap.css">
    <link rel="stylesheet" href="../css/bootstrap-responsive.css">
    <link rel="stylesheet" href="../css/style.css">
    <style>
    body {
      padding-top: 60px;
      padding-bottom: 40px;
    }
    </style>
    <link href="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.css" type="text/css" rel="stylesheet">
    <script src="../js/libs/modernizr-2.5.3-respond-1.1.0.min.js"></script>
    <script>
      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

      ga('create', 'UA-39650556-1', 'auto');
      ga('send', 'pageview');
    </script>
  </head>
  <body>
  <!--[if lt IE 7]><p class=chromeframe>Your browser is <em>ancient!</em> <a href="http://browsehappy.com/">Upgrade to a different browser</a> or <a href="http://www.google.com/chromeframe/?redirect=true">install Google Chrome Frame</a> to experience this site.</p><![endif]-->
    <div id="fb-root"></div>
    <script>(function(d, s, id) {
      var js, fjs = d.getElementsByTagName(s)[0];
      if (d.getElementById(id)) return;
      js = d.createElement(s); js.id = id;
      js.src = "//connect.facebook.net/ja_JP/all.js#xfbml=1&appId=351187098330864";
      fjs.parentNode.insertBefore(js, fjs);
      }(document, 'script', 'facebook-jssdk'));
    </script>
    <header>
      <nav class="navbar navbar-fixed-top">
        <div class="navbar-inner">
          <div class="container">
            <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
            </a>
            <a class="brand" href="../index.html">でこてっくろぐ</a>
            <div class="nav-collapse">
              <ul class="nav">
                <li><a href="../index.html">ほーむ</a></li>
                <li><a href="../posts.html">あーかいぶ</a></li>
                <li><a href="../aboutme.html">あばうとみー</a></li>
              </ul>
            </div><!--/.nav-collapse -->
          </div>
        </div>
      </nav>
    </header>

    <div class="container">
      <div class="row">
        <article class="span9">
          <h1>ISUCON予選にPHP実装で参加して3位になりましたーやったことなどまとめ</h1>

<p>by <em><a href="https://twitter.com/dekokun">@dekokun</a></em> on <strong>2013/10/06 20:15</strong></p>

<p>Tagged as: <a href="../tags/contest.html">contest</a>.</p>

<p>今日(10/6)は<a href="http://isucon.net/">ISUCON3</a>の予選2日目に参加しました。</p>
<p>「予選落ちだろうなー」と思いながら挑んだら、意外と3位(暫定。運営の方が提出したAMIを起動しベンチマーク実行し、提出したスコアと比べてあまりにもスコアが低かった場合は失格となる)で本選進出が決まったので嬉しくてブログ書いてます。</p>
<p>スコアは14379で、予選1日目と合わせて9位。</p>
<p>「チームたこやき」という名前で後輩2人と参加しました。</p>
<p>題名に「PHP実装で」と入れたのは、ディスられがちなPHP書きへのエールを込めてです。</p>
<h2 id="基本的にやってたこと">基本的にやってたこと</h2>
<p>以下、恒常的にやってたこと一覧と、その効果を。</p>
<h3 id="xhprofでのプロファイリング">xhprofでのプロファイリング</h3>
<p>効果：圧倒的</p>
<ul>
<li>facebook謹製プロファイリングツール、xhprof様でございます</li>
<li>session_startが異様に遅い(memcachedの罠)とか、preg_split使いすぎとか、「今はDBネックだし他のことやってもあまり意味ないよね」とか、いろいろなことがわかりました</li>
<li>ベンチかけながらブラウザでxhprofの結果をみて遅い場所を判断するということの繰り返しでしたね</li>
</ul>
<h3 id="スロークエリログの解析">スロークエリログの解析</h3>
<p>効果：圧倒的</p>
<ul>
<li>mysqldumpslowを使ってスロークエリを解析していました</li>
<li>遅いクエリを見つけてはindexをはったりアプリケーションを書き換えたり</li>
<li>xhprof同様、ベンチかけては解析結果を見て を繰り返していました</li>
</ul>
<h3 id="dstatの使用">dstatの使用</h3>
<p>効果：普通(私に使いこなせなかった)</p>
<ul>
<li>あーCPU使用率高いわーIO高いわー。以上。みたいなそんな感じだった</li>
<li>せっかくグラフィカルだったし、1枚のディスプレイに表示させてみんなで見ながらやるとよかったなと思いました</li>
</ul>
<h3 id="topの使用">topの使用</h3>
<p>効果：いい感じ</p>
<ul>
<li>topはいいですねぇ</li>
</ul>
<h2 id="最終的なミドルウェア構成">最終的なミドルウェア構成</h2>
<ul>
<li>DB: MySQL リバースプロキシ: nginx アプリサーバ: Apache2.4(Prefork MPM) + mod_php</li>
<li>PHPらしい構成ですね</li>
<li>Apacheだけでいいかなーと思っていたら後輩がnginxを入れて静的ファイルはそちらから配信するようにしてくれていました</li>
<li>memcachedは使用しておりません</li>
<li>せっかくApache2.4だったので、Event Mpm + PHP-FPMも試そうかと思っていたのですが、最後までDBネックから抜けだせなかったため「PHP-FPMにしても今は意味ないだろうな」という感じでそのまま終了</li>
</ul>
<h2 id="開発環境">開発環境</h2>
<ul>
<li>各人に別々のポートで立ち上げた開発環境を用意し、そこで開発して特にエラーが起きなかったらデプロイするという感じ</li>
<li>git pullによるデプロイ</li>
<li>isuコマンドという、いろいろなもののラッパースクリプトを作成したりもしました。“isu deploy”とか“isu slow-show(mysqldumoslowを使ってスロークエリを見る)”とか</li>
</ul>
<h2 id="覚えている範囲で実際に行った作業">覚えている範囲で実際に行った作業</h2>
<p>以下、特にPHPのロジック変更周りは基本的に後輩2人がやってくれたので私はあまり関与していませんが、記憶している限り書きます</p>
<h3 id="ベンチマークのworkloadオプションを変更">ベンチマークのworkloadオプションを変更</h3>
<ul>
<li>Lingrを見ていた後輩がworkloadオプションの変更を提案。スコアが上がったため変更</li>
<li>情報収集力の大切さを感じました</li>
</ul>
<h3 id="セッションにmemcacheを使用しない">セッションにmemcacheを使用しない</h3>
<ul>
<li>プロファイリングの結果、session_startに異様に時間がかかっていたことが判明したために、サーバ1台だけで動いていることもあってファイルを使ったセッション管理に切り替えた</li>
<li>知らず知らずのうちに運営のはった罠(純正のmemcachedではなくMySQL 5.6.14のInnoDB Memcached Pluginが使われていた)を抜けていた感じですね</li>
</ul>
<h3 id="markdownコマンドを表示時ではなく記事投稿時に実施するように変更">markdownコマンドを表示時ではなく記事投稿時に実施するように変更</h3>
<ul>
<li>子プロセスの起動はクソほど重いですからね…</li>
<li>Markdown作成処理をPHPに行わせることはしていません</li>
<li>ベンチマークがうまく動いていない時に実施した施策なので、この施策による実際の効果のほどはイマイチわからないが、良かったのではないかと</li>
</ul>
<h3 id="ユーザ名を記事毎にselectしている部分の撤去">ユーザ名を記事毎にselectしている部分の撤去</h3>
<ul>
<li>悪名高き N + 1クエリ問題</li>
<li>inner joinして解決</li>
<li>memosテーブルにユーザ名を持てばよいのではという話もありましたが、「アプリケーション初期化の際にどうすればいいんだ」という話になってボツに</li>
</ul>
<h3 id="apcの使用">APCの使用</h3>
<ul>
<li>Opcodeキャッシュは重要ですよね</li>
<li>これをやってかなりスコアが伸びた記憶が</li>
</ul>
<h3 id="タイトルを記事投稿時に保存するように変更">タイトルを記事投稿時に保存するように変更</h3>
<ul>
<li>プロファイリングによりトップ画面表示時のタイトル生成のためにpreg_splitが呼び出されまくっていたため、タイトルは投稿時に作成しDBに保存するようにした</li>
<li>効果があったらしい(この頃、私はDBにインデックスはったりDBのパラメータチューニングしたりしていて、記憶にない)</li>
</ul>
<h3 id="countテーブルの作成">countテーブルの作成</h3>
<ul>
<li>is_privateではないmemosの全件をcountしている部分が遅かったため、専用のcountテーブルを作成し、insertする度に件数をupdateするなどした</li>
</ul>
<h3 id="unixドメインソケットを使用した接続">Unixドメインソケットを使用した接続</h3>
<ul>
<li>同じサーバなのでわざわざTCPを使用することもないなと思いソケットファイルを使用した通信に</li>
<li>実施が簡単なので実施したが、特に効果はみられなかった</li>
</ul>
<h3 id="ログインしてもdbは更新しない">ログインしてもDBは更新しない</h3>
<ul>
<li>last_accessカラムを更新していましたが、不要ですね。ということで更新しなくした。運営からのサービスポイントだったようですね。</li>
</ul>
<h3 id="mysqlのクエリキャッシュを有効に">MySQLのクエリキャッシュを有効に</h3>
<ul>
<li>query_cache_sizeだけ設定しquery_cache_typeを設定せず、「あれ、キャッシュヒット数が0から増えないなぁ」などとやっておりました。</li>
<li>クエリキャッシュを実施しても特にスコアの上昇はなかった</li>
</ul>
<h2 id="所感">所感</h2>
<ul>
<li>とにかく、地道に、プロファイリングしてはボトルネック部分を直してを繰り返したのが良かった</li>
<li>今回、KVSなど使用せず非常に古典的にMySQLとWebサーバのみで如何に遅い部分を潰すかをプロファイル見ながら普通に実施していただけですが、これだけでは本選は戦えないだろうなぁとは思っており、一層の奮闘が必要。</li>
<li>後輩2人がすごく頑張ってくれていた。後半は、私は「クエリが早くならないなぁ」というだけの係になっていた感があった</li>
<li>インデックスを作成したらオプティマイザがバグってexplainの結果にusing filesortとか出てきたためしょうがなくstraight_joinを使用したりした。joinとsortが混じるようなSQLはオプティマイザがバグりやすくて要注意</li>
<li>今回、トップページを高速化すれば全体のスコアが上がるようなアプリだったため、「トップページのxhprofを見る」-&gt;「遅いところを直す」だけで良かったが、本来ならアクセスログから遅いページを割り出すなどする必要があったなぁ。と思っております。アクセスログにかかった時間をマイクロ秒単位で出力するようにしたものの最後までそれが使われることはなかった…</li>
<li>ISUCON応募締め切り10分前くらいに後輩にISUCONのこと話したら後輩も乗り気だったため締め切り3分前くらいに応募を完了したんだけど、出てよかったなと思いました</li>
<li>NHN選抜チームを抜けそうだったので、本選では抜きたいと思います</li>
<li>白金動物園を抜けて結構うれしい</li>
<li>運営の追試によって失格にならないか怖くて仕方がない</li>
</ul>

<div id="disqus_thread"></div>
<script type="text/javascript">
    /* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */
    var disqus_shortname = 'dekokun'; // required: replace example with your forum shortname

    /* * * DON'T EDIT BELOW THIS LINE * * */
    (function() {
        var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
        dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js';
        (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
    })();
</script>
<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
<a href="http://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a>

          <ul class="social">
            <li class="kindle"><div class="kindleWidget"><img style="vertical-align:middle;" src="https://d1xnn692s7u6t6.cloudfront.net/white-15.png" /><span style="vertical-align:middle;margin-left:3px;">Send to Kindle</span></div></li>
            <li class="facebook"><div class="fb-like" data-send="false" data-layout="button_count" data-width="100" data-show-faces="true" data-font="arial"></div></li>
            <li class="twitter"><a href="https://twitter.com/share" class="twitter-share-button" data-via="dekokun" data-lang="ja">ツイート</a></li>
            <li class="hatena-bookmark"><a href="http://b.hatena.ne.jp/entry/" class="hatena-bookmark-button" data-hatena-bookmark-layout="standard" title="このエントリーをはてなブックマークに追加"><img src="http://b.st-hatena.com/images/entry-button/button-only.gif" alt="このエントリーをはてなブックマークに追加" width="20" height="20" style="border: none;"></a><script type="text/javascript" src="http://b.st-hatena.com/js/bookmark_button.js" charset="utf-8" async="async"></script></li>
            <li><a data-pocket-label="pocket" data-pocket-count="horizontal" class="pocket-btn" data-lang="en"></a>
            <script type="text/javascript">!function(d,i){if(!d.getElementById(i)){var j=d.createElement("script");j.id=i;j.src="https://widgets.getpocket.com/v1/j/btn.js?v=1";var w=d.getElementById(i);d.body.appendChild(j);}}(document,"pocket-btn-js");</script></li>
          </ul>

        </article>
        <aside class="span3">
          <div class="sidebar-module">
            <div class="title">プロフィール</div>
            <p class="id"><a href="https://twitter.com/dekokun">dekokun</a></p>
            <p><a href="https://twitter.com/dekokun"><img src="../img/dekokun.png" alt="dekokun"></a></p>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.io/";
              Hatena.BookmarkWidget.title = "人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 200;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.com/";
              Hatena.BookmarkWidget.title = "旧人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 0;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module visible-desktop">
            <div class="title">twitter</div>
            <a class="twitter-timeline" data-dnt="true" href="https://twitter.com/dekokun" data-widget-id="306408547573440513">@dekokun からのツイート</a>
            <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
          </div>
          <div class="sidebar-module hidden-phone">
            <div class="title">RSS</div>
            <p><a href="../rss.xml"><img src="../img/rss.gif" alt="rss"></a></p>
          </div>
        </aside> <!-- /span3 -->
      </div> <!-- /row -->
      <footer>
        <p>©<script type="text/javascript">$y=2012;$ny=new Date().getFullYear();document.write($ny>$y?$y+'-'+$ny:$y);</script> <a href="https://twitter.com/dekokun">dekokun</a></p>
      </footer>
    </div> <!-- /container -->

    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script>window.jQuery || document.write('<script src="../js/libs/jquery-1.7.2.min.js"><\/script>')</script>
    <!-- /ツイートボタン -->
  <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>

    <script src="../js/libs/bootstrap/bootstrap.min.js"></script>

    <script src="../js/script.js"></script>
    <script>
      var _gaq=[['_setAccount','UA-XXXXX-X'],['_trackPageview']];
      (function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
      g.src=('https:'==location.protocol?'//ssl':'//www')+'.google-analytics.com/ga.js';
      s.parentNode.insertBefore(g,s)}(document,'script'));
    </script>
    <!-- Code syntax highlight -->
    <script type="text/javascript" src="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.js"></script>
    <script type="text/javascript">
    $(function(){ 
        $('pre').css({
            'overflow-x': 'scroll',
            'background-color': '#f6f6f6',
            'border': '1px dotted #ccc',
            'padding': '0.8em'
        });
        $('pre code').addClass('prettyprint');
        prettyPrint();
    });
    </script>
    <script type="text/javascript" src="https://d1xnn692s7u6t6.cloudfront.net/widget.js"></script>
    <script type="text/javascript">(function k(){window.$SendToKindle&&window.$SendToKindle.Widget?$SendToKindle.Widget.init({"content":"article"}):setTimeout(k,500);})();</script>
  </body>
</html>
]]></description>
    <pubDate>No date found.</pubDate>
    <guid>http://dekokun.github.io/posts/2013-10-06.html</guid>
</item>
<item>
    <title>Chef Serverにてクックブックの実行時間が長いとForbiddenエラーが出る件</title>
    <link>http://dekokun.github.io/posts/2013-10-19.html</link>
    <description><![CDATA[<!doctype html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7" lang="ja"> <![endif]-->
<!--[if IE 7]>    <html class="no-js lt-ie9 lt-ie8" lang="ja"> <![endif]-->
<!--[if IE 8]>    <html class="no-js lt-ie9" lang="ja"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="ja"> <!--<![endif]-->
  <head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# article: http://ogp.me/ns/article#">
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <title>Chef Serverにてクックブックの実行時間が長いとForbiddenエラーが出る件</title>
    <meta name="description" content>
    <meta name="author" content>

    <meta name="viewport" content="width=device-width">
    <meta property="fb:app_id" content="351187098330864">
    <meta property="og:type" content="article">
    <meta property="og:image" content="http://dekokun.github.com/img/dekokun.png">
    <meta property="og:title" content="Chef Serverにてクックブックの実行時間が長いとForbiddenエラーが出る件">
    <meta property="og:description" content="@dekokunの技術日記">
    <meta property="og:site_name" content="でこてっくろぐ">
    <meta name="twitter:widgets:csp" content="on">

    <link rel="stylesheet" href="../css/bootstrap.css">
    <link rel="stylesheet" href="../css/bootstrap-responsive.css">
    <link rel="stylesheet" href="../css/style.css">
    <style>
    body {
      padding-top: 60px;
      padding-bottom: 40px;
    }
    </style>
    <link href="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.css" type="text/css" rel="stylesheet">
    <script src="../js/libs/modernizr-2.5.3-respond-1.1.0.min.js"></script>
    <script>
      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

      ga('create', 'UA-39650556-1', 'auto');
      ga('send', 'pageview');
    </script>
  </head>
  <body>
  <!--[if lt IE 7]><p class=chromeframe>Your browser is <em>ancient!</em> <a href="http://browsehappy.com/">Upgrade to a different browser</a> or <a href="http://www.google.com/chromeframe/?redirect=true">install Google Chrome Frame</a> to experience this site.</p><![endif]-->
    <div id="fb-root"></div>
    <script>(function(d, s, id) {
      var js, fjs = d.getElementsByTagName(s)[0];
      if (d.getElementById(id)) return;
      js = d.createElement(s); js.id = id;
      js.src = "//connect.facebook.net/ja_JP/all.js#xfbml=1&appId=351187098330864";
      fjs.parentNode.insertBefore(js, fjs);
      }(document, 'script', 'facebook-jssdk'));
    </script>
    <header>
      <nav class="navbar navbar-fixed-top">
        <div class="navbar-inner">
          <div class="container">
            <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
            </a>
            <a class="brand" href="../index.html">でこてっくろぐ</a>
            <div class="nav-collapse">
              <ul class="nav">
                <li><a href="../index.html">ほーむ</a></li>
                <li><a href="../posts.html">あーかいぶ</a></li>
                <li><a href="../aboutme.html">あばうとみー</a></li>
              </ul>
            </div><!--/.nav-collapse -->
          </div>
        </div>
      </nav>
    </header>

    <div class="container">
      <div class="row">
        <article class="span9">
          <h1>Chef Serverにてクックブックの実行時間が長いとForbiddenエラーが出る件</h1>

<p>by <em><a href="https://twitter.com/dekokun">@dekokun</a></em> on <strong>2013/10/19 15:33</strong></p>

<p>Tagged as: <a href="../tags/Chef Server.html">Chef Server</a>.</p>

<p><a href="http://connpass.com/event/3420/">怖くないScala勉強会</a>の休憩時間にこんなの書いてます。</p>
<p>表題の件ですが、Chef Serverを使用していると、デフォルト状態では1つのクックブックの実行に15分以上かかるとエラーになります。 気をつけましょう。</p>
<p>どうにかしたい場合は、Chef Server上で/etc/chef-server/chef-server.rb を作成し、</p>
<pre><code>erchef['s3_url_ttl'] = 3600</code></pre>
<p>と記述した後に、 chef-server-ctl reconfigureしましょう。これで、制限時間が15分から1時間まで伸びます。</p>
<p>なお、私はOpscodeから提供されているChef自体のクックブックでChefサーバを作成したりしているのですが、それの実行時のアトリビュートを以下のように設定することで対処することもできますよ。</p>
<pre><code>    &quot;chef-server&quot;: {
  &quot;configuration&quot;: {
    &quot;erchef&quot;: {
      &quot;s3_url_ttl&quot;: 3600
    }
  }
}</code></pre>
<p>以上。休憩時間がそろそろ終わるので簡潔に。</p>
<p>参考：</p>
<ul>
<li><a href="http://linkis.com/tickets.opscode.com/uQ7r">long running recipes cause Forbidden errors</a></li>
</ul>

<div id="disqus_thread"></div>
<script type="text/javascript">
    /* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */
    var disqus_shortname = 'dekokun'; // required: replace example with your forum shortname

    /* * * DON'T EDIT BELOW THIS LINE * * */
    (function() {
        var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
        dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js';
        (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
    })();
</script>
<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
<a href="http://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a>

          <ul class="social">
            <li class="kindle"><div class="kindleWidget"><img style="vertical-align:middle;" src="https://d1xnn692s7u6t6.cloudfront.net/white-15.png" /><span style="vertical-align:middle;margin-left:3px;">Send to Kindle</span></div></li>
            <li class="facebook"><div class="fb-like" data-send="false" data-layout="button_count" data-width="100" data-show-faces="true" data-font="arial"></div></li>
            <li class="twitter"><a href="https://twitter.com/share" class="twitter-share-button" data-via="dekokun" data-lang="ja">ツイート</a></li>
            <li class="hatena-bookmark"><a href="http://b.hatena.ne.jp/entry/" class="hatena-bookmark-button" data-hatena-bookmark-layout="standard" title="このエントリーをはてなブックマークに追加"><img src="http://b.st-hatena.com/images/entry-button/button-only.gif" alt="このエントリーをはてなブックマークに追加" width="20" height="20" style="border: none;"></a><script type="text/javascript" src="http://b.st-hatena.com/js/bookmark_button.js" charset="utf-8" async="async"></script></li>
            <li><a data-pocket-label="pocket" data-pocket-count="horizontal" class="pocket-btn" data-lang="en"></a>
            <script type="text/javascript">!function(d,i){if(!d.getElementById(i)){var j=d.createElement("script");j.id=i;j.src="https://widgets.getpocket.com/v1/j/btn.js?v=1";var w=d.getElementById(i);d.body.appendChild(j);}}(document,"pocket-btn-js");</script></li>
          </ul>

        </article>
        <aside class="span3">
          <div class="sidebar-module">
            <div class="title">プロフィール</div>
            <p class="id"><a href="https://twitter.com/dekokun">dekokun</a></p>
            <p><a href="https://twitter.com/dekokun"><img src="../img/dekokun.png" alt="dekokun"></a></p>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.io/";
              Hatena.BookmarkWidget.title = "人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 200;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.com/";
              Hatena.BookmarkWidget.title = "旧人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 0;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module visible-desktop">
            <div class="title">twitter</div>
            <a class="twitter-timeline" data-dnt="true" href="https://twitter.com/dekokun" data-widget-id="306408547573440513">@dekokun からのツイート</a>
            <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
          </div>
          <div class="sidebar-module hidden-phone">
            <div class="title">RSS</div>
            <p><a href="../rss.xml"><img src="../img/rss.gif" alt="rss"></a></p>
          </div>
        </aside> <!-- /span3 -->
      </div> <!-- /row -->
      <footer>
        <p>©<script type="text/javascript">$y=2012;$ny=new Date().getFullYear();document.write($ny>$y?$y+'-'+$ny:$y);</script> <a href="https://twitter.com/dekokun">dekokun</a></p>
      </footer>
    </div> <!-- /container -->

    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script>window.jQuery || document.write('<script src="../js/libs/jquery-1.7.2.min.js"><\/script>')</script>
    <!-- /ツイートボタン -->
  <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>

    <script src="../js/libs/bootstrap/bootstrap.min.js"></script>

    <script src="../js/script.js"></script>
    <script>
      var _gaq=[['_setAccount','UA-XXXXX-X'],['_trackPageview']];
      (function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
      g.src=('https:'==location.protocol?'//ssl':'//www')+'.google-analytics.com/ga.js';
      s.parentNode.insertBefore(g,s)}(document,'script'));
    </script>
    <!-- Code syntax highlight -->
    <script type="text/javascript" src="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.js"></script>
    <script type="text/javascript">
    $(function(){ 
        $('pre').css({
            'overflow-x': 'scroll',
            'background-color': '#f6f6f6',
            'border': '1px dotted #ccc',
            'padding': '0.8em'
        });
        $('pre code').addClass('prettyprint');
        prettyPrint();
    });
    </script>
    <script type="text/javascript" src="https://d1xnn692s7u6t6.cloudfront.net/widget.js"></script>
    <script type="text/javascript">(function k(){window.$SendToKindle&&window.$SendToKindle.Widget?$SendToKindle.Widget.init({"content":"article"}):setTimeout(k,500);})();</script>
  </body>
</html>
]]></description>
    <pubDate>No date found.</pubDate>
    <guid>http://dekokun.github.io/posts/2013-10-19.html</guid>
</item>
<item>
    <title>#isucon 本選惨敗！！！！</title>
    <link>http://dekokun.github.io/posts/2013-11-09.html</link>
    <description><![CDATA[<!doctype html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7" lang="ja"> <![endif]-->
<!--[if IE 7]>    <html class="no-js lt-ie9 lt-ie8" lang="ja"> <![endif]-->
<!--[if IE 8]>    <html class="no-js lt-ie9" lang="ja"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="ja"> <!--<![endif]-->
  <head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# article: http://ogp.me/ns/article#">
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <title>#isucon 本選惨敗！！！！</title>
    <meta name="description" content>
    <meta name="author" content>

    <meta name="viewport" content="width=device-width">
    <meta property="fb:app_id" content="351187098330864">
    <meta property="og:type" content="article">
    <meta property="og:image" content="http://dekokun.github.com/img/dekokun.png">
    <meta property="og:title" content="#isucon 本選惨敗！！！！">
    <meta property="og:description" content="@dekokunの技術日記">
    <meta property="og:site_name" content="でこてっくろぐ">
    <meta name="twitter:widgets:csp" content="on">

    <link rel="stylesheet" href="../css/bootstrap.css">
    <link rel="stylesheet" href="../css/bootstrap-responsive.css">
    <link rel="stylesheet" href="../css/style.css">
    <style>
    body {
      padding-top: 60px;
      padding-bottom: 40px;
    }
    </style>
    <link href="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.css" type="text/css" rel="stylesheet">
    <script src="../js/libs/modernizr-2.5.3-respond-1.1.0.min.js"></script>
    <script>
      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

      ga('create', 'UA-39650556-1', 'auto');
      ga('send', 'pageview');
    </script>
  </head>
  <body>
  <!--[if lt IE 7]><p class=chromeframe>Your browser is <em>ancient!</em> <a href="http://browsehappy.com/">Upgrade to a different browser</a> or <a href="http://www.google.com/chromeframe/?redirect=true">install Google Chrome Frame</a> to experience this site.</p><![endif]-->
    <div id="fb-root"></div>
    <script>(function(d, s, id) {
      var js, fjs = d.getElementsByTagName(s)[0];
      if (d.getElementById(id)) return;
      js = d.createElement(s); js.id = id;
      js.src = "//connect.facebook.net/ja_JP/all.js#xfbml=1&appId=351187098330864";
      fjs.parentNode.insertBefore(js, fjs);
      }(document, 'script', 'facebook-jssdk'));
    </script>
    <header>
      <nav class="navbar navbar-fixed-top">
        <div class="navbar-inner">
          <div class="container">
            <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
            </a>
            <a class="brand" href="../index.html">でこてっくろぐ</a>
            <div class="nav-collapse">
              <ul class="nav">
                <li><a href="../index.html">ほーむ</a></li>
                <li><a href="../posts.html">あーかいぶ</a></li>
                <li><a href="../aboutme.html">あばうとみー</a></li>
              </ul>
            </div><!--/.nav-collapse -->
          </div>
        </div>
      </nav>
    </header>

    <div class="container">
      <div class="row">
        <article class="span9">
          <h1>#isucon 本選惨敗！！！！</h1>

<p>by <em><a href="https://twitter.com/dekokun">@dekokun</a></em> on <strong>2013/11/09 15:33</strong></p>

<p>Tagged as: <a href="../tags/contest.html">contest</a>.</p>

<p>今日はISUCON本選でした！！！！！</p>
<p>後輩二人(<a href="https://twitter.com/jyegan">@jyegan</a>, <a href="https://twitter.com/Altsencturel://twitter.com/Altsencturely">@Altsencturely</a>)と参加してきました！！！</p>
<p>今回は私のせいで相当時間をロスさせてしまい、最終的にfailして懺悔懺悔です！！！！(懺悔内容は最下部に記載)</p>
<p>が、まぁ、今回もやったことなどをまとめていきたいと思います。今回は、私が発生させた謎のエラーにハマり続けたのであまりいろいろできなかったのですが…</p>
<p>failしなかったチームは7チームでして、一応順位としては8位(まぁ、8位かつ最下位なわけだが)になるんですかね</p>
<h2 id="今回のお題アプリケーションについて">今回のお題アプリケーションについて</h2>
<ul>
<li>画像投稿版Twitterみたいなもの</li>
<li>公開範囲を決めて画像投稿可能
<ul>
<li>これにより、安易に画像の静的配信はできませんよ</li>
</ul></li>
<li>サーバが1台あたり100Mbpsに絞られているという話だったため、画像投稿サイトということもあり、そこがボトルネックになるかなぁと思っておりましたがそれ以前の問題だった(ように見えるがそもそも通信量とかみてなかったのでなんとも)</li>
</ul>
<h2 id="基本的にやっていたこと">基本的にやっていたこと</h2>
<h3 id="xhprofでのプロファイリング">xhprofでのプロファイリング</h3>
<p>今回も素晴らしい効果を発揮する…はずでしたが、最初に「execが圧倒的に遅い」というところが判明した以降は、そのボトルネックを最後まで解消せずに終わってしまいました…</p>
<h3 id="new-relicでのプロファイリング">New Relicでのプロファイリング</h3>
<p>New Relicのおかげで画像表示部分が圧倒的に遅いですね！ということがわかりました。xhprofでの結果と併せて、execが遅いせいですね！という結論が出た以降状態が変わらず終わりました。 New RelicといえばRubyで注目されがちですが、本来はPHPでもめちゃくちゃ便利なツールなんですけどね。今回はボトルネックの再確認ツールというくらいの活躍ぶりでした。</p>
<p>ルーティング判別部分は<a href="http://sssslide.com/www.slideshare.net/MiuraKatsu/ss-26186401">FuelPHPで３種のprofilerを使ってみた</a>を参考に、設定しました。</p>
<h3 id="スロークエリログの解析">スロークエリログの解析</h3>
<p>「DBが全くボトルネックじゃないね」ということがわかった以降何も進まず終わった</p>
<h2 id="その他やったこと">その他やったこと</h2>
<p>ある程度時系列順に</p>
<ul>
<li>全グループメンバーから全サーバ及び全サーバから他の全サーバに対してsshのパスワードなしで接続できるように設定</li>
<li>各自の開発環境を同じサーバ上の別ポートで立ち上げ、git管理した</li>
<li>git pullによる各サーバへのデプロイ環境を構築した(“isu deploy”コマンドを打つことによって開発環境からpushして全サーバへのデプロイ可能に)
<ul>
<li>が、結局サーバは1台だけしか使えず終わった…</li>
</ul></li>
<li>上記“isu deploy”以外にも予選から使用していた“isu”コマンドの機能拡充
<ul>
<li>“isu allcommand”で全ホストにコマンドをばらまくとか、isu currentで前回のベンチマーク結果を取得できるとか、“isu slow-show”でmysqldumpslowの結果を出力して見られるとか</li>
</ul></li>
<li>my.cnfを編集し、127.0.0.1以外からもアクセス可能なように修正
<ul>
<li>「mysqlDBの中のuserテーブルの中ではちゃんと設定されているのになぁ」などと若干ハマった…</li>
</ul></li>
<li>上記各種プロファイリングの設定</li>
<li>思えばここまではまだ順調だった…</li>
<li>画像にアクセスが来る度に画像生成していたため、一度生成した画像はディレクトリに置いて次からのアクセスはそれを返すようにした</li>
<li>このあたりから、以下懺悔しているような状態が発生しベンチマークが失敗し続けいろいろ巻き戻したりが始まった。ラスト1時間くらいまでベンチマークが失敗し続けていた。辛かった</li>
<li>最終的に、ラスト30分くらいで、「DBではなくexecがネックなので他のサーバを使用すれば使用した分だけスケールするのはわかりきったこと！！スケールアウトしよう！ローカルに保存している画像はMemcachedにしよう！」という実装をガツッとやりましたが、一部うまくいかず結局スケールアウトはできず</li>
<li>最終的にfailして終了</li>
<li>なお、Memcachedが1キーに対してデフォルト1MBまでしか保存できないのは知らなかった
<ul>
<li>この辺りはいい勉強になりましたね</li>
</ul></li>
</ul>
<h2 id="感想">感想</h2>
<ul>
<li>前回予選でちょっと良い成績だったからと言って色々調子乗った発言(「LINE選抜を抜けそうだったが抜けなかった。次は抜く」だとか「白金動物園に勝てて嬉しい」とか)を繰り返していましたが今回ダメだった。めちゃくちゃ悔しい</li>
<li>「くらげとみかんと江戸幕府」チームが前回PHPで出場していたため、「PHP仲間だー」と思っていたら今回PHP実装は我々だけだった
<ul>
<li>これに伴い(?)最後までApacheで戦ったのも我々のチームだけでしたね</li>
<li>PHPの威光を世に知らしめたかったが全くもって力及ばず</li>
<li>「くらげとみかんと江戸幕府」は今回はRubyだったとのこと</li>
</ul></li>
<li>優勝チームのtagomorisさんとお話しまして、「最初の一時間半くらいはひたすら戦略をねっていた」という話を聞き、最後に勝つのはちゃんと最初に戦略をたててチームかという思いが強く残った</li>
<li>来年(あれば)必ずリベンジしたい</li>
<li>問題作成、運営、会場及び賞金提供、サーバや食料提供の皆様ありがとうございました！！</li>
<li>私はいつも基本的にぼっちなのですが、今日は懇親会で積極的に皆さんとお話出来てよかったです
<ul>
<li>くらげとみかんと江戸幕府の皆さんとか、山形組のかたとか、LINEやCOOKPADの方々など</li>
</ul></li>
</ul>
<h2 id="チームメイトへの懺悔">チームメイトへの懺悔</h2>
<p>ベンチマークスクリプトのオプションを誤り(サーバ指定するオプションとワークロード指定するオプションを逆にみていた)、「よし、ワークロードを2に増やそう」と言ってワークロードではなくアクセス先のサーバIDのほうを編集してしまい、その後、その変更によってまだアプリケーションが動いていないサーバ2に対してベンチマークが走りベンチマークが失敗し続け原因解明に2~3時間くらいかかってしまったのではないでしょうか…</p>
<p>ベンチマーク実施した瞬間になぜか正しいサーバにもアクセスが来ていたように見えていた(原因は不明。UAはちゃんとISUCONのベンチマークツールだったように思っていたが。まぁ当時は焦っていたからあまり記憶はあてになりませんね…)ため、全然きづけなかった　…「何度やってもfailし続ける！しかもログ上では200番を返している！！！gitで最初の状態にアプリケーションを巻き戻してもダメ！！！！」という感じだった。</p>
<p>すみませんすみません。。。これのせいでかなりの時間を無駄にしてしまいましたね。。。</p>
<h3 id="懺悔からわかる反省点">懺悔からわかる反省点</h3>
<ul>
<li>ベンチマークをラップするようなコマンドを作成しており、それが誤っていたせいでベンチマークが失敗し続けていましたのですが、ラップするものを皆が見られる状態にあまりしていなかったのが良くなかった - 一応、“isu vi”コマンドでラップスクリプト自体を編集できる機能はあったが、若干周知不足
<ul>
<li>それ以外でも、isuコマンドは機能追加してもあまり周知することができていなかった</li>
</ul></li>
<li>ベンチマークのラップコマンドを編集したことを周りに伝えなかったのが一番悪かった</li>
<li>ベンチマークのラップコマンドをWebUIと一緒にバージョン管理していればよかった。そうしていなかっったため周りが変更に気づく土壌がなかった</li>
<li>他のサーバのアクセスも監視していれば間違えに気づけた</li>
<li>オプションを変更したらちゃんと動きを確認しましょう</li>
</ul>
<p>一日一日を大切に、反撃の牙を磨くのです！！！！！！</p>

<div id="disqus_thread"></div>
<script type="text/javascript">
    /* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */
    var disqus_shortname = 'dekokun'; // required: replace example with your forum shortname

    /* * * DON'T EDIT BELOW THIS LINE * * */
    (function() {
        var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
        dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js';
        (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
    })();
</script>
<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
<a href="http://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a>

          <ul class="social">
            <li class="kindle"><div class="kindleWidget"><img style="vertical-align:middle;" src="https://d1xnn692s7u6t6.cloudfront.net/white-15.png" /><span style="vertical-align:middle;margin-left:3px;">Send to Kindle</span></div></li>
            <li class="facebook"><div class="fb-like" data-send="false" data-layout="button_count" data-width="100" data-show-faces="true" data-font="arial"></div></li>
            <li class="twitter"><a href="https://twitter.com/share" class="twitter-share-button" data-via="dekokun" data-lang="ja">ツイート</a></li>
            <li class="hatena-bookmark"><a href="http://b.hatena.ne.jp/entry/" class="hatena-bookmark-button" data-hatena-bookmark-layout="standard" title="このエントリーをはてなブックマークに追加"><img src="http://b.st-hatena.com/images/entry-button/button-only.gif" alt="このエントリーをはてなブックマークに追加" width="20" height="20" style="border: none;"></a><script type="text/javascript" src="http://b.st-hatena.com/js/bookmark_button.js" charset="utf-8" async="async"></script></li>
            <li><a data-pocket-label="pocket" data-pocket-count="horizontal" class="pocket-btn" data-lang="en"></a>
            <script type="text/javascript">!function(d,i){if(!d.getElementById(i)){var j=d.createElement("script");j.id=i;j.src="https://widgets.getpocket.com/v1/j/btn.js?v=1";var w=d.getElementById(i);d.body.appendChild(j);}}(document,"pocket-btn-js");</script></li>
          </ul>

        </article>
        <aside class="span3">
          <div class="sidebar-module">
            <div class="title">プロフィール</div>
            <p class="id"><a href="https://twitter.com/dekokun">dekokun</a></p>
            <p><a href="https://twitter.com/dekokun"><img src="../img/dekokun.png" alt="dekokun"></a></p>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.io/";
              Hatena.BookmarkWidget.title = "人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 200;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.com/";
              Hatena.BookmarkWidget.title = "旧人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 0;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module visible-desktop">
            <div class="title">twitter</div>
            <a class="twitter-timeline" data-dnt="true" href="https://twitter.com/dekokun" data-widget-id="306408547573440513">@dekokun からのツイート</a>
            <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
          </div>
          <div class="sidebar-module hidden-phone">
            <div class="title">RSS</div>
            <p><a href="../rss.xml"><img src="../img/rss.gif" alt="rss"></a></p>
          </div>
        </aside> <!-- /span3 -->
      </div> <!-- /row -->
      <footer>
        <p>©<script type="text/javascript">$y=2012;$ny=new Date().getFullYear();document.write($ny>$y?$y+'-'+$ny:$y);</script> <a href="https://twitter.com/dekokun">dekokun</a></p>
      </footer>
    </div> <!-- /container -->

    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script>window.jQuery || document.write('<script src="../js/libs/jquery-1.7.2.min.js"><\/script>')</script>
    <!-- /ツイートボタン -->
  <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>

    <script src="../js/libs/bootstrap/bootstrap.min.js"></script>

    <script src="../js/script.js"></script>
    <script>
      var _gaq=[['_setAccount','UA-XXXXX-X'],['_trackPageview']];
      (function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
      g.src=('https:'==location.protocol?'//ssl':'//www')+'.google-analytics.com/ga.js';
      s.parentNode.insertBefore(g,s)}(document,'script'));
    </script>
    <!-- Code syntax highlight -->
    <script type="text/javascript" src="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.js"></script>
    <script type="text/javascript">
    $(function(){ 
        $('pre').css({
            'overflow-x': 'scroll',
            'background-color': '#f6f6f6',
            'border': '1px dotted #ccc',
            'padding': '0.8em'
        });
        $('pre code').addClass('prettyprint');
        prettyPrint();
    });
    </script>
    <script type="text/javascript" src="https://d1xnn692s7u6t6.cloudfront.net/widget.js"></script>
    <script type="text/javascript">(function k(){window.$SendToKindle&&window.$SendToKindle.Widget?$SendToKindle.Widget.init({"content":"article"}):setTimeout(k,500);})();</script>
  </body>
</html>
]]></description>
    <pubDate>No date found.</pubDate>
    <guid>http://dekokun.github.io/posts/2013-11-09.html</guid>
</item>
<item>
    <title>初心者向け タイプヒンティングとはなんなのかというお話</title>
    <link>http://dekokun.github.io/posts/2013-12-14.html</link>
    <description><![CDATA[<!doctype html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7" lang="ja"> <![endif]-->
<!--[if IE 7]>    <html class="no-js lt-ie9 lt-ie8" lang="ja"> <![endif]-->
<!--[if IE 8]>    <html class="no-js lt-ie9" lang="ja"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="ja"> <!--<![endif]-->
  <head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# article: http://ogp.me/ns/article#">
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <title>初心者向け タイプヒンティングとはなんなのかというお話</title>
    <meta name="description" content>
    <meta name="author" content>

    <meta name="viewport" content="width=device-width">
    <meta property="fb:app_id" content="351187098330864">
    <meta property="og:type" content="article">
    <meta property="og:image" content="http://dekokun.github.com/img/dekokun.png">
    <meta property="og:title" content="初心者向け タイプヒンティングとはなんなのかというお話">
    <meta property="og:description" content="@dekokunの技術日記">
    <meta property="og:site_name" content="でこてっくろぐ">
    <meta name="twitter:widgets:csp" content="on">

    <link rel="stylesheet" href="../css/bootstrap.css">
    <link rel="stylesheet" href="../css/bootstrap-responsive.css">
    <link rel="stylesheet" href="../css/style.css">
    <style>
    body {
      padding-top: 60px;
      padding-bottom: 40px;
    }
    </style>
    <link href="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.css" type="text/css" rel="stylesheet">
    <script src="../js/libs/modernizr-2.5.3-respond-1.1.0.min.js"></script>
    <script>
      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

      ga('create', 'UA-39650556-1', 'auto');
      ga('send', 'pageview');
    </script>
  </head>
  <body>
  <!--[if lt IE 7]><p class=chromeframe>Your browser is <em>ancient!</em> <a href="http://browsehappy.com/">Upgrade to a different browser</a> or <a href="http://www.google.com/chromeframe/?redirect=true">install Google Chrome Frame</a> to experience this site.</p><![endif]-->
    <div id="fb-root"></div>
    <script>(function(d, s, id) {
      var js, fjs = d.getElementsByTagName(s)[0];
      if (d.getElementById(id)) return;
      js = d.createElement(s); js.id = id;
      js.src = "//connect.facebook.net/ja_JP/all.js#xfbml=1&appId=351187098330864";
      fjs.parentNode.insertBefore(js, fjs);
      }(document, 'script', 'facebook-jssdk'));
    </script>
    <header>
      <nav class="navbar navbar-fixed-top">
        <div class="navbar-inner">
          <div class="container">
            <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
            </a>
            <a class="brand" href="../index.html">でこてっくろぐ</a>
            <div class="nav-collapse">
              <ul class="nav">
                <li><a href="../index.html">ほーむ</a></li>
                <li><a href="../posts.html">あーかいぶ</a></li>
                <li><a href="../aboutme.html">あばうとみー</a></li>
              </ul>
            </div><!--/.nav-collapse -->
          </div>
        </div>
      </nav>
    </header>

    <div class="container">
      <div class="row">
        <article class="span9">
          <h1>初心者向け タイプヒンティングとはなんなのかというお話</h1>

<p>by <em><a href="https://twitter.com/dekokun">@dekokun</a></em> on <strong>2013/12/14 15:33</strong></p>

<p>Tagged as: <a href="../tags/PHP.html">PHP</a>.</p>

<p>どうも、<a href="http://qiita.com/advent-calendar/2013/php">PHP Advent Calendar 2013</a>の14日目の記事です。</p>
<p>昨日は<a href="https://twitter.com/ockeghem">@ockeghem</a>の<a href="http://blog.tokumaru.org/2013/12/php12sql.html">PHPとセキュリティの解説書12種類を読んでSQLエスケープの解説状況を調べてみた</a>でしたね。</p>
<p>最近、仕事を一緒にし始めた後輩がPHPに慣れておらず、PHPのタイプヒンティングのことを知らなかったので(そして、さっき一緒にお酒を飲んだ別の後輩もタイプヒンティングを知らなかったので)、彼らに向けて、タイプヒンティングとはなにか、なぜタイプヒンティングを使うのかを解説する記事となります。</p>
<p>PHPのことをよく知っている皆様におかれましては特に得るものはないお話なのかなと思います。ご了承ください。なお、下記のような流れを経て、このブログの内容は当初の予定から変遷しました。</p>
<blockquote class="twitter-tweet" lang="ja"><p>
「returnとrequireでファイル間で値を受け渡しできるよ、でもonce系を使う場合は注意な」ってAdvent Calendarで書こうとしていたんだけど既にHirakuさんが全く同じこと書いてた。 <a href="http://t.co/FMhGllrYJz">http://t.co/FMhGllrYJz</a>
</p>
— でこくん (@dekokun) <a href="https://twitter.com/dekokun/statuses/405917922805047296">2013, 11月 28</a>
</blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>

<h2 id="タイプヒンティングとは">タイプヒンティングとは</h2>
<p>関数及びメソッドが受け取る引数がどのオブジェクトなのか(もしくはなんのインターフェースを備えるか)、配列なのか、コールバックなのかなどを指定することが出来る機能です。</p>
<h3 id="具体例">具体例</h3>
<p>こんな感じ</p>
<pre><code>&lt;?php
// この&quot;Iterator $a&quot;の&quot;Iterator&quot;部分がタイプヒンティング
// ここで、$aはIteratorと同様のインターフェースを備えていることが保証される
function func(Iterator $a) {
    return $a-&gt;next();
}</code></pre>
<p>上記の “Iterator”部分がタイプヒンティングとなります。</p>
<h3 id="違反するとどうなるの">違反するとどうなるの？</h3>
<p>例えば、タイプヒンティングでクラスを指定したにもかかわらずスカラー値を指定された場合はエラーになります。</p>
<pre><code>&lt;?php

function func(TestClass $a) {
    return $a;
}

func(1);</code></pre>
<p>上記のようなコードは以下のようなFatal errorが投げられます</p>
<pre><code>PHP Catchable fatal error:  Argument 1 passed to func() must be an instance of TestClass, integer given, called in /private/var/folders/hy/xc91_vr542z40knyzs4h9n2r0000gn/T/vHqWMFW/2 on line 8 and defined in /private/var/folders/hy/xc91_vr542z40knyzs4h9n2r0000gn/T/vHqWMFW/2 on line 4

Catchable fatal error: Argument 1 passed to func() must be an instance of TestClass, integer given, called in /private/var/folders/hy/xc91_vr542z40knyzs4h9n2r0000gn/T/vHqWMFW/2 on line 8 and defined in /private/var/folders/hy/xc91_vr542z40knyzs4h9n2r0000gn/T/vHqWMFW/2 on line 4</code></pre>
<p>このエラーをコード中で捕捉したい場合は、エラーハンドラの中で“E_RECOVERABLE_ERROR”を捕捉しましょうね。</p>
<h2 id="何が嬉しいの">何が嬉しいの？</h2>
<ul>
<li>エラーを早めに検知可能</li>
<li>(コメントなどと比べて)検証可能、腐ることのない形(=メソッドのドックコメントなどとは違うのですよ)でメソッドの前提条件を指定可能</li>
<li>そもそも、変なことが起きた時にエラーが起きて死ぬというのは、エラーを返り値で返しがちなPHPにとっては非常に重要なことだと思います</li>
</ul>
<h2 id="どんな時に使うの">どんな時に使うの？</h2>
<p>少なくとも、現世利益的なことを話しますと、タイプヒンティングによって、期待しないクラス(とか配列とかコールバックとか)が引数にわたってこないことが保証されるため、バリデーションを減らすことができます。</p>
<p>たとえば、以下のようなコードの場合、</p>
<pre><code>&lt;?php

function func(array $a) {
    return $a;
}</code></pre>
<p>$aは配列であることが保証されるため、func関数の中で</p>
<pre><code>if(! is_array($a)) {
    throw new \InvalidArgumentException;
}
// do_something();</code></pre>
<p>などのチェックを行う必要はなくなります。</p>
<h3 id="ライブラリなどの作者の意図をプログラムで伝えやすくなります">ライブラリなどの作者の意図をプログラムで伝えやすくなります</h3>
<p>以下のようなコードがあった際に、それを使う側は引数に配列が期待されているかどうかは実装を読まないと(もしくはコメントなどを読むことでしか)判断できません。使う側に実装を読ませるのはライブラリの敗北ですし、コメントで意図を伝えると、そのコメントのメンテナンスコストが以降発生します。</p>
<p>更に、間違えて配列以外を突っ込んでしまった際も、以下だとWarningのエラーが発生するだけでプログラムが落ちないために使い方を誤っていることに気づかない危険が高まります。</p>
<pre><code>function func($a) {
    return array_shift($a);
}</code></pre>
<p>しかし以下のように記述すれば、使う側はインターフェースを見るだけで、引数に配列が期待されていることがわかるだけです。そして、誤った使い方をすれば、プログラムが死ぬため、すぐに気づくことができます(これは、ヴァリデーションでも同様のことは可能ですが、それならタイプヒンティング使ったほうが圧倒的に楽ですよね)</p>
<pre><code>function func(array $a) {
    return array_shift($a);
}</code></pre>
<h3 id="コールバック">コールバック</h3>
<p>以下のような引数にコールバックを期待している関数に文字列を渡すと、非常にわかりづらいエラーになります。 引数にコールバックを受け取る関数では、確実にcallableタイプヒントをつけるようにしましょう(PHP5.4~)</p>
<pre><code>function fuga($a) {
    return $a();
}</code></pre>
<p>以下、非常にわかりづらいエラー。</p>
<pre><code>$variable = 'c';
fuga($variable);
PHP Fatal error:  Call to undefined function c() in php shell code on line 2

Fatal error: Call to undefined function c() in php shell code on line 2</code></pre>
<h3 id="とあるメソッドを持っているかどうかの検査">とあるメソッドを持っているかどうかの検査</h3>
<p>タイプヒンティングにインターフェースを使うなどして、ストラテジーパターンなどを行いやすいですね。</p>
<pre><code>interface runnable
{
    public function run();
}

function test(runnable $a) {
    // タイプヒンティングを行っているので、引数がrunメソッドを持っていることを検証せずに使うことができる
    $a-&gt;run();
}</code></pre>
<h2 id="最後">最後</h2>
<p>つまり、タイプヒンティングのおかげで、簡単に早い段階でにわかりやすくエラーを検知できるのがとても素晴らしいということですね！そんなこと言っていると「それなら静的型付け言語を使えよ」と言われそうですが、PHPのタイプヒンティングは、固くいきたいところは固く、動的型付けの柔軟さ、生産性の高さ(?)を積極的に使っていきたいところはタイプヒンティングなしで書けるというわけで、そのどっちでも選択できる感じが素敵だなと思います。</p>
<p>便利だから積極的に使って行こったほうがいいと思います。後輩たちにおかれましても、少なくともライブラリのコードを読んで「ここはタイプヒンティングを使っているんだ！！」ということをわかるようになっていればと思います。</p>
<p>というか、なんか色々骨抜きなブログだ！！！！！</p>
<p>他にも、「名前空間の使い方」とか「composerをなぜ使うのか」とか、「migrationをなぜ使うのか」とか、伝えたいことは非常にたくさんあるのですが、本日は時間もないですしこのあたりで筆を置きます。</p>
<p>酔っ払ってるしね。</p>
<p>次回は<a href="http://qiita.com/k-motoyan">k-motoyan</a>による「FWに依存しないDBマイグレーションツール」ですね。楽しみですね</p>

<div id="disqus_thread"></div>
<script type="text/javascript">
    /* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */
    var disqus_shortname = 'dekokun'; // required: replace example with your forum shortname

    /* * * DON'T EDIT BELOW THIS LINE * * */
    (function() {
        var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
        dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js';
        (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
    })();
</script>
<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
<a href="http://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a>

          <ul class="social">
            <li class="kindle"><div class="kindleWidget"><img style="vertical-align:middle;" src="https://d1xnn692s7u6t6.cloudfront.net/white-15.png" /><span style="vertical-align:middle;margin-left:3px;">Send to Kindle</span></div></li>
            <li class="facebook"><div class="fb-like" data-send="false" data-layout="button_count" data-width="100" data-show-faces="true" data-font="arial"></div></li>
            <li class="twitter"><a href="https://twitter.com/share" class="twitter-share-button" data-via="dekokun" data-lang="ja">ツイート</a></li>
            <li class="hatena-bookmark"><a href="http://b.hatena.ne.jp/entry/" class="hatena-bookmark-button" data-hatena-bookmark-layout="standard" title="このエントリーをはてなブックマークに追加"><img src="http://b.st-hatena.com/images/entry-button/button-only.gif" alt="このエントリーをはてなブックマークに追加" width="20" height="20" style="border: none;"></a><script type="text/javascript" src="http://b.st-hatena.com/js/bookmark_button.js" charset="utf-8" async="async"></script></li>
            <li><a data-pocket-label="pocket" data-pocket-count="horizontal" class="pocket-btn" data-lang="en"></a>
            <script type="text/javascript">!function(d,i){if(!d.getElementById(i)){var j=d.createElement("script");j.id=i;j.src="https://widgets.getpocket.com/v1/j/btn.js?v=1";var w=d.getElementById(i);d.body.appendChild(j);}}(document,"pocket-btn-js");</script></li>
          </ul>

        </article>
        <aside class="span3">
          <div class="sidebar-module">
            <div class="title">プロフィール</div>
            <p class="id"><a href="https://twitter.com/dekokun">dekokun</a></p>
            <p><a href="https://twitter.com/dekokun"><img src="../img/dekokun.png" alt="dekokun"></a></p>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.io/";
              Hatena.BookmarkWidget.title = "人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 200;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.com/";
              Hatena.BookmarkWidget.title = "旧人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 0;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module visible-desktop">
            <div class="title">twitter</div>
            <a class="twitter-timeline" data-dnt="true" href="https://twitter.com/dekokun" data-widget-id="306408547573440513">@dekokun からのツイート</a>
            <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
          </div>
          <div class="sidebar-module hidden-phone">
            <div class="title">RSS</div>
            <p><a href="../rss.xml"><img src="../img/rss.gif" alt="rss"></a></p>
          </div>
        </aside> <!-- /span3 -->
      </div> <!-- /row -->
      <footer>
        <p>©<script type="text/javascript">$y=2012;$ny=new Date().getFullYear();document.write($ny>$y?$y+'-'+$ny:$y);</script> <a href="https://twitter.com/dekokun">dekokun</a></p>
      </footer>
    </div> <!-- /container -->

    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script>window.jQuery || document.write('<script src="../js/libs/jquery-1.7.2.min.js"><\/script>')</script>
    <!-- /ツイートボタン -->
  <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>

    <script src="../js/libs/bootstrap/bootstrap.min.js"></script>

    <script src="../js/script.js"></script>
    <script>
      var _gaq=[['_setAccount','UA-XXXXX-X'],['_trackPageview']];
      (function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
      g.src=('https:'==location.protocol?'//ssl':'//www')+'.google-analytics.com/ga.js';
      s.parentNode.insertBefore(g,s)}(document,'script'));
    </script>
    <!-- Code syntax highlight -->
    <script type="text/javascript" src="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.js"></script>
    <script type="text/javascript">
    $(function(){ 
        $('pre').css({
            'overflow-x': 'scroll',
            'background-color': '#f6f6f6',
            'border': '1px dotted #ccc',
            'padding': '0.8em'
        });
        $('pre code').addClass('prettyprint');
        prettyPrint();
    });
    </script>
    <script type="text/javascript" src="https://d1xnn692s7u6t6.cloudfront.net/widget.js"></script>
    <script type="text/javascript">(function k(){window.$SendToKindle&&window.$SendToKindle.Widget?$SendToKindle.Widget.init({"content":"article"}):setTimeout(k,500);})();</script>
  </body>
</html>
]]></description>
    <pubDate>No date found.</pubDate>
    <guid>http://dekokun.github.io/posts/2013-12-14.html</guid>
</item>
<item>
    <title>PHP書きが久しぶりにRubyの言語仕様を詳しく思い出して抱いた感想たち</title>
    <link>http://dekokun.github.io/posts/2013-12-15.html</link>
    <description><![CDATA[<!doctype html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7" lang="ja"> <![endif]-->
<!--[if IE 7]>    <html class="no-js lt-ie9 lt-ie8" lang="ja"> <![endif]-->
<!--[if IE 8]>    <html class="no-js lt-ie9" lang="ja"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="ja"> <!--<![endif]-->
  <head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# article: http://ogp.me/ns/article#">
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <title>PHP書きが久しぶりにRubyの言語仕様を詳しく思い出して抱いた感想たち</title>
    <meta name="description" content>
    <meta name="author" content>

    <meta name="viewport" content="width=device-width">
    <meta property="fb:app_id" content="351187098330864">
    <meta property="og:type" content="article">
    <meta property="og:image" content="http://dekokun.github.com/img/dekokun.png">
    <meta property="og:title" content="PHP書きが久しぶりにRubyの言語仕様を詳しく思い出して抱いた感想たち">
    <meta property="og:description" content="@dekokunの技術日記">
    <meta property="og:site_name" content="でこてっくろぐ">
    <meta name="twitter:widgets:csp" content="on">

    <link rel="stylesheet" href="../css/bootstrap.css">
    <link rel="stylesheet" href="../css/bootstrap-responsive.css">
    <link rel="stylesheet" href="../css/style.css">
    <style>
    body {
      padding-top: 60px;
      padding-bottom: 40px;
    }
    </style>
    <link href="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.css" type="text/css" rel="stylesheet">
    <script src="../js/libs/modernizr-2.5.3-respond-1.1.0.min.js"></script>
    <script>
      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

      ga('create', 'UA-39650556-1', 'auto');
      ga('send', 'pageview');
    </script>
  </head>
  <body>
  <!--[if lt IE 7]><p class=chromeframe>Your browser is <em>ancient!</em> <a href="http://browsehappy.com/">Upgrade to a different browser</a> or <a href="http://www.google.com/chromeframe/?redirect=true">install Google Chrome Frame</a> to experience this site.</p><![endif]-->
    <div id="fb-root"></div>
    <script>(function(d, s, id) {
      var js, fjs = d.getElementsByTagName(s)[0];
      if (d.getElementById(id)) return;
      js = d.createElement(s); js.id = id;
      js.src = "//connect.facebook.net/ja_JP/all.js#xfbml=1&appId=351187098330864";
      fjs.parentNode.insertBefore(js, fjs);
      }(document, 'script', 'facebook-jssdk'));
    </script>
    <header>
      <nav class="navbar navbar-fixed-top">
        <div class="navbar-inner">
          <div class="container">
            <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
            </a>
            <a class="brand" href="../index.html">でこてっくろぐ</a>
            <div class="nav-collapse">
              <ul class="nav">
                <li><a href="../index.html">ほーむ</a></li>
                <li><a href="../posts.html">あーかいぶ</a></li>
                <li><a href="../aboutme.html">あばうとみー</a></li>
              </ul>
            </div><!--/.nav-collapse -->
          </div>
        </div>
      </nav>
    </header>

    <div class="container">
      <div class="row">
        <article class="span9">
          <h1>PHP書きが久しぶりにRubyの言語仕様を詳しく思い出して抱いた感想たち</h1>

<p>by <em><a href="https://twitter.com/dekokun">@dekokun</a></em> on <strong>2013/12/15 20:47</strong></p>

<p>Tagged as: <a href="../tags/Ruby.html">Ruby</a>.</p>

<p>どうも、<a href="http://www.adventar.org/calendars/198">パーフェクトRuby Advent Calendar 2013</a>の15日目の記事です。</p>
<p>昨日は<a href="https://twitter.com/Shindo200">@Shindo200</a>の<a href="http://shindolog.hatenablog.com/entry/2013/12/14/235211">-&gt; { “Perfect Ruby Advent Calendar” }.call</a>でしたね。</p>
<p>昨日はPHPのアドベントカレンダーを書き、今日はRuby系のアドベントカレンダーを書く、因果なものですね。</p>
<h2 id="私とパーフェクトrubyの因縁">私とパーフェクトRubyの因縁</h2>
<blockquote class="twitter-tweet" lang="ja"><p>
すがさんと一緒に合コンした身としては、パーフェクトRubyは買わなくてはいけないなと思っているわけですよ。まだ買ってないけど。
</p>
— でこくん (@dekokun) <a href="https://twitter.com/dekokun/statuses/373461858990043136">2013, 8月 30</a>
</blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>

<p>上記のようなツイートをしておきながらずっとパーフェクトRubyを買ってなかったのですが、パーフェクトRubyアドベントカレンダーが存在すると聞いて買ってみたのでした。</p>
<blockquote class="twitter-tweet" lang="ja"><p>
アドベントカレンダー登録したのでパーフェクトRubyを購入した。RubyはChefのレシピ作成に使っているのでもっと深く知りたいですね☆ パーフェクトRuby Advent Calendar 2013 <a href="http://t.co/VA8ZleGSer">http://t.co/VA8ZleGSer</a> <a href="https://twitter.com/search?q=%23adventar&amp;src=hash">#adventar</a>
</p>
— でこくん (@dekokun) <a href="https://twitter.com/dekokun/statuses/405656020019458049">2013, 11月 27</a>
</blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>

<p>その後、会社の行き帰りで頭から読んでいたのですが、残念ながら全部読み終われませんでした。具体的には、5章まで(1/3もいってない!!!)しか読めませんでした。ですので、5章までで、普段書いているPHPとくらべて、面白いなぁと思ったところを記載します。</p>
<h2 id="本題">本題</h2>
<p>なお、以下にはパーフェクトRubyのページ数も記載していますが、これは初版の際のページ数です。</p>
<h3 id="定数の再代入p49">定数の再代入(p49)</h3>
<ul>
<li>再代入可能というのは面白いんですが、なぜそんな設計にしたんでしたっけ。再代入可能なことによってどのような利点があるんですかね。</li>
</ul>
<h3 id="モジュールp57">モジュール(p57)</h3>
<ul>
<li>PHPでいうところの、traitと名前空間を組み合わせたようなものですね</li>
<li>昔はPHPにはtraitも名前空間もなく、単一継承のみ可能な言語であったためRubyのモジュールがうらやましかったのですが、最近はtraitや名前空間が出てきて、PHPもいい感じですね</li>
</ul>
<h3 id="記法p62">%記法(p62)</h3>
<ul>
<li>純粋に便利。Chefのレシピ書く際にも非常にお世話になっています</li>
<li>PHPでは、PHP5.4で「配列がRubyみたいに“[]”で宣言できるようになった！マジ便利！」と言っている感じで、%記法の存在するRubyと比べると、配列の初期化の容易さでは一歩負けているなと思う次第</li>
</ul>
<h3 id="擬似変数たちp70">擬似変数たち(p70)</h3>
<ul>
<li>true, false, nilって擬似変数っていうものだったのか。それぞれがTrueClass, FalseClass, NilClassの唯一のインスタンス。</li>
</ul>
<p>インスタンスつくろうとしたら怒られた。</p>
<pre><code>[1] pry(main)&gt; true_val = TrueClass.new
NoMethodError: undefined method `new' for TrueClass:Class
from (pry):1:in `__pry__'</code></pre>
<ul>
<li>PHPでは__DIR__は__FILE__と同じ、「<a href="http://www.php.net/manual/ja/language.constants.predefined.php">自動的に定義される定数</a>」なのですが、Rubyでは__dir__はKernelモジュールのメソッドであり、__FILE__は擬似変数であるという違いがある</li>
</ul>
<h3 id="数々の組み込み変数p71">数々の組み込み変数(p71)</h3>
<ul>
<li>Perlやシェルスクリプトもそうだけど、これらのググらビリティの低さは異常であり、ちょっとどうにかしてほしい</li>
<li>でも、便利なことは間違いない。いいですね</li>
</ul>
<h3 id="演算子がメソッドとして定義p74">演算子がメソッドとして定義！！！(p74)</h3>
<ul>
<li>これは昔からRubyの羨ましかったところ</li>
<li>1+1が 1.+(1)のシンタックスシュガーであるとか、やばい</li>
<li>全てがオブジェクトであるRuby(注：<a href="http://d.hatena.ne.jp/shunsuk/20100407/1270642620">Rubyでは、すべてがオブジェクト。じゃないよ！</a>)だからこそこういうことがしやすいんですよねと思いました。関係ないですが、このブログを書いて以下名言が生まれました。
<blockquote class="twitter-tweet" lang="ja"><p>
Ruby 「なんでもはオブジェクトじゃないわよ。オブジェクトであるものだけ。」
</p>
— でこくん (@dekokun) <a href="https://twitter.com/dekokun/statuses/412213551046983680">2013, 12月 15</a>
</blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script></li>
<li>ただ、一つ疑問なのは、Rubyはオープンクラスであることもあり、こういう基本的な演算子系をモンキーパッチとして書き換えたりもできるわけだ。Ruby書き達はその誘惑にどのように打ち勝っているのだろうか。(まぁ、この辺りの問題と我々がどうすればいいかはMatzの「<a href="http://www.atmarkit.co.jp/news/201009/13/spell.html">Rubyは君を信頼する。Rubyは君を分別のあるプログラマとして扱う。Rubyはメタプログラミングのような強力な力を与える。ただし、大いなる力には、大いなる責任が伴うことを忘れてはいけない</a>」という言葉が端的に表してますね)</li>
</ul>
<h3 id="case-..-whenp77">case .. when(p77)</h3>
<ul>
<li>一般的な他の言語のswitchと違い、fall throughできないのがとても良い。fall throughはバグの温床</li>
<li>一方で、明示的にfall throughしたい場面は存在すると思うので、Goのように明示的にfall throughを指定できる感じだとより嬉しかったとは思う</li>
<li>なお、全く関係ないがPythonにはswitch系の構文が存在しない</li>
<li>これも特に関係ないが、昔読んだブログを思い出した <a href="http://melborne.github.io/2013/02/25/i-wanna-say-something-about-rubys-case/">Rubyのcaseを〇〇(言語名)のswitch文だと思っている人たちにぼくから一言ガツンと申し上げたい</a></li>
</ul>
<h3 id="メソッドやクラスモジュール定義で例外を捕捉p88">メソッドやクラス/モジュール定義で例外を捕捉(p88)</h3>
<ul>
<li>なんだこれ便利すぎる。知らなかった。</li>
<li>いつも、PHPを書く際にメソッドごとtry{}でくくってネストが1段階下がるのにイライラしていたのでとても嬉しい感じですね</li>
<li>ついでに言うと、retryも便利すぎるんだが。えっbeginからもう一回やり直してくれるのなにそれ。</li>
</ul>
<p>そろそろ時間もきているのでこれ以上列挙するのはやめておこう。</p>
<h3 id="ところで">ところで</h3>
<p>なんか、Rubyをひたすら褒めているだけな感じがしてきて、PHP書きとして面白くなくなってきたので、最後にPHPがRubyに対して圧倒的に優れていると思う点を書いておこう</p>
<p><strong>PHPのインターフェース及びタイプヒンティングはとても優れています！！！！！！</strong></p>
<p>いえ、まぁ、Rubyはダックタイピングな言語ですもんね。</p>
<h2 id="最後に">最後に</h2>
<h3 id="私とruby">私とRuby</h3>
<p>私のプログラミングの歴史はRubyから始まっております(大学の講義でRubyを習い、その後<a href="http://projecteuler.net/">Project Euler</a>の問題をひたすらRubyで解いていた記憶が)。そして、会社でPHPを書きながら「PHPのようなクソ言語は好かん。やはり全てがオブジェクトであるRubyかっこいいよRuby」といって、たまにあるバッチ処理をちょろっとRubyで書いたりRailsで忘年会用のWebサイトを作成するくらいで「俺は時代の先端のRubyを使いこなすプログラマだぜ」と言っているような痛い感じのプログラマでした。</p>
<p>そんな私が、今では毎日PHPを書いてすっかりPHPの魅力に魅せられ、Rubyのことは完全に忘れて今ではChefのレシピをRuby上のDSLで書いているだけになっていました。</p>
<h3 id="今後">今後</h3>
<p>昔の私は所詮Rubyを手慰み程度でしか触っていなかったし、もっと何かRubyで作りたいですね。</p>
<p>ただ、現在PHPばかり書いているので、Rubyのような動的型付け言語ではなくもっとPHPと離れた言語を触りたいと思う今日このごろ。やはりこの前某氏にオススメされたAgdaか。証明！！！</p>

<div id="disqus_thread"></div>
<script type="text/javascript">
    /* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */
    var disqus_shortname = 'dekokun'; // required: replace example with your forum shortname

    /* * * DON'T EDIT BELOW THIS LINE * * */
    (function() {
        var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
        dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js';
        (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
    })();
</script>
<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
<a href="http://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a>

          <ul class="social">
            <li class="kindle"><div class="kindleWidget"><img style="vertical-align:middle;" src="https://d1xnn692s7u6t6.cloudfront.net/white-15.png" /><span style="vertical-align:middle;margin-left:3px;">Send to Kindle</span></div></li>
            <li class="facebook"><div class="fb-like" data-send="false" data-layout="button_count" data-width="100" data-show-faces="true" data-font="arial"></div></li>
            <li class="twitter"><a href="https://twitter.com/share" class="twitter-share-button" data-via="dekokun" data-lang="ja">ツイート</a></li>
            <li class="hatena-bookmark"><a href="http://b.hatena.ne.jp/entry/" class="hatena-bookmark-button" data-hatena-bookmark-layout="standard" title="このエントリーをはてなブックマークに追加"><img src="http://b.st-hatena.com/images/entry-button/button-only.gif" alt="このエントリーをはてなブックマークに追加" width="20" height="20" style="border: none;"></a><script type="text/javascript" src="http://b.st-hatena.com/js/bookmark_button.js" charset="utf-8" async="async"></script></li>
            <li><a data-pocket-label="pocket" data-pocket-count="horizontal" class="pocket-btn" data-lang="en"></a>
            <script type="text/javascript">!function(d,i){if(!d.getElementById(i)){var j=d.createElement("script");j.id=i;j.src="https://widgets.getpocket.com/v1/j/btn.js?v=1";var w=d.getElementById(i);d.body.appendChild(j);}}(document,"pocket-btn-js");</script></li>
          </ul>

        </article>
        <aside class="span3">
          <div class="sidebar-module">
            <div class="title">プロフィール</div>
            <p class="id"><a href="https://twitter.com/dekokun">dekokun</a></p>
            <p><a href="https://twitter.com/dekokun"><img src="../img/dekokun.png" alt="dekokun"></a></p>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.io/";
              Hatena.BookmarkWidget.title = "人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 200;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.com/";
              Hatena.BookmarkWidget.title = "旧人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 0;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module visible-desktop">
            <div class="title">twitter</div>
            <a class="twitter-timeline" data-dnt="true" href="https://twitter.com/dekokun" data-widget-id="306408547573440513">@dekokun からのツイート</a>
            <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
          </div>
          <div class="sidebar-module hidden-phone">
            <div class="title">RSS</div>
            <p><a href="../rss.xml"><img src="../img/rss.gif" alt="rss"></a></p>
          </div>
        </aside> <!-- /span3 -->
      </div> <!-- /row -->
      <footer>
        <p>©<script type="text/javascript">$y=2012;$ny=new Date().getFullYear();document.write($ny>$y?$y+'-'+$ny:$y);</script> <a href="https://twitter.com/dekokun">dekokun</a></p>
      </footer>
    </div> <!-- /container -->

    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script>window.jQuery || document.write('<script src="../js/libs/jquery-1.7.2.min.js"><\/script>')</script>
    <!-- /ツイートボタン -->
  <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>

    <script src="../js/libs/bootstrap/bootstrap.min.js"></script>

    <script src="../js/script.js"></script>
    <script>
      var _gaq=[['_setAccount','UA-XXXXX-X'],['_trackPageview']];
      (function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
      g.src=('https:'==location.protocol?'//ssl':'//www')+'.google-analytics.com/ga.js';
      s.parentNode.insertBefore(g,s)}(document,'script'));
    </script>
    <!-- Code syntax highlight -->
    <script type="text/javascript" src="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.js"></script>
    <script type="text/javascript">
    $(function(){ 
        $('pre').css({
            'overflow-x': 'scroll',
            'background-color': '#f6f6f6',
            'border': '1px dotted #ccc',
            'padding': '0.8em'
        });
        $('pre code').addClass('prettyprint');
        prettyPrint();
    });
    </script>
    <script type="text/javascript" src="https://d1xnn692s7u6t6.cloudfront.net/widget.js"></script>
    <script type="text/javascript">(function k(){window.$SendToKindle&&window.$SendToKindle.Widget?$SendToKindle.Widget.init({"content":"article"}):setTimeout(k,500);})();</script>
  </body>
</html>
]]></description>
    <pubDate>No date found.</pubDate>
    <guid>http://dekokun.github.io/posts/2013-12-15.html</guid>
</item>
<item>
    <title>Nodeの複数バージョン管理のお供にnをどうぞ</title>
    <link>http://dekokun.github.io/posts/2014-01-01.html</link>
    <description><![CDATA[<!doctype html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7" lang="ja"> <![endif]-->
<!--[if IE 7]>    <html class="no-js lt-ie9 lt-ie8" lang="ja"> <![endif]-->
<!--[if IE 8]>    <html class="no-js lt-ie9" lang="ja"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="ja"> <!--<![endif]-->
  <head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# article: http://ogp.me/ns/article#">
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <title>Nodeの複数バージョン管理のお供にnをどうぞ</title>
    <meta name="description" content>
    <meta name="author" content>

    <meta name="viewport" content="width=device-width">
    <meta property="fb:app_id" content="351187098330864">
    <meta property="og:type" content="article">
    <meta property="og:image" content="http://dekokun.github.com/img/dekokun.png">
    <meta property="og:title" content="Nodeの複数バージョン管理のお供にnをどうぞ">
    <meta property="og:description" content="@dekokunの技術日記">
    <meta property="og:site_name" content="でこてっくろぐ">
    <meta name="twitter:widgets:csp" content="on">

    <link rel="stylesheet" href="../css/bootstrap.css">
    <link rel="stylesheet" href="../css/bootstrap-responsive.css">
    <link rel="stylesheet" href="../css/style.css">
    <style>
    body {
      padding-top: 60px;
      padding-bottom: 40px;
    }
    </style>
    <link href="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.css" type="text/css" rel="stylesheet">
    <script src="../js/libs/modernizr-2.5.3-respond-1.1.0.min.js"></script>
    <script>
      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

      ga('create', 'UA-39650556-1', 'auto');
      ga('send', 'pageview');
    </script>
  </head>
  <body>
  <!--[if lt IE 7]><p class=chromeframe>Your browser is <em>ancient!</em> <a href="http://browsehappy.com/">Upgrade to a different browser</a> or <a href="http://www.google.com/chromeframe/?redirect=true">install Google Chrome Frame</a> to experience this site.</p><![endif]-->
    <div id="fb-root"></div>
    <script>(function(d, s, id) {
      var js, fjs = d.getElementsByTagName(s)[0];
      if (d.getElementById(id)) return;
      js = d.createElement(s); js.id = id;
      js.src = "//connect.facebook.net/ja_JP/all.js#xfbml=1&appId=351187098330864";
      fjs.parentNode.insertBefore(js, fjs);
      }(document, 'script', 'facebook-jssdk'));
    </script>
    <header>
      <nav class="navbar navbar-fixed-top">
        <div class="navbar-inner">
          <div class="container">
            <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
            </a>
            <a class="brand" href="../index.html">でこてっくろぐ</a>
            <div class="nav-collapse">
              <ul class="nav">
                <li><a href="../index.html">ほーむ</a></li>
                <li><a href="../posts.html">あーかいぶ</a></li>
                <li><a href="../aboutme.html">あばうとみー</a></li>
              </ul>
            </div><!--/.nav-collapse -->
          </div>
        </div>
      </nav>
    </header>

    <div class="container">
      <div class="row">
        <article class="span9">
          <h1>Nodeの複数バージョン管理のお供にnをどうぞ</h1>

<p>by <em><a href="https://twitter.com/dekokun">@dekokun</a></em> on <strong>2014/01/01 16:13</strong></p>

<p>Tagged as: <a href="../tags/Node.html">Node.js</a>.</p>

<p>新年早々、去年全く使っていなかったNodeのブログを。</p>
<h2 id="初めに">初めに</h2>
<p>2年ほど前にNodeを使っていた時は、複数バージョン管理には<a href="https://github.com/creationix/nvm">npm</a>及び<a href="https://github.com/isaacs/nave">nave</a>が二大巨頭だった感じがありますが、調べたら<a href="https://github.com/visionmedia/n">n</a>というのがあったので使ってみました</p>
<p>(2014/01/02 追記 nは、半年ほど前に開発が止まっているようだし、ちょっとイマイチなのかな…)</p>
<h2 id="雰囲気">雰囲気</h2>
<p>以下Readmeのトップにある動画を見ればわかるのではないかと。この、対話的にバージョンを選択する感じ、素敵ですね。</p>
<ul>
<li><a href="https://github.com/visionmedia/n/blob/master/Readme.md">Readme.md</a></li>
</ul>
<p>作者はexpressやjadeを作っている安心のvisionmediaさん。</p>
<h2 id="インストール">インストール</h2>
<ul>
<li>なんらかの方法によってNode.js及びnpmをインストールし、<code>npm install n -g</code>
<ul>
<li>これが、Nodeなしでインストール可能なnvmやnaveと違う点なのですね。</li>
<li>右記質問がイカしている。<a href="http://stackoverflow.com/questions/19451851/install-node-js-to-install-n-to-install-node-js">Install Node.js to install n to install Node.js?</a></li>
<li>ただ、そもそもnpm install nでインストールされるのはシェルスクリプト1個だけであるため、別にnpm installを行うのが必須であるわけではありません。</li>
<li><a href="https://github.com/visionmedia/n">リポジトリ</a>にはMakefile(これも、シェルスクリプトを/usr/local/下に展開しているだけというお手軽実装)も存在しますので、そっちでのインストールも可能</li>
</ul></li>
</ul>
<p>以上、終わりです。内部の実装が、/usr/local/下のファイルをごそっと置き換えるという驚きの実装であるため、PATHの設定も必要ありません。</p>
<p>上記のような/usr/local下ファイルをごそっと入れ替える(正確には<code>/usr/local/n/versions/バージョン番号</code>下ファイルの全てを/usr/local下にコピーする)という驚きの実装が嫌な場合は環境変数<code>N_PREFIX</code>に、インストールしたいディレクトリを指定し、<code>${N_PREFIX}/bin</code>下にPATHを通してあげた後に、nを使ってください</p>
<h2 id="使い方">使い方</h2>
<p><code>n latest</code>や<code>n stable</code>や<code>n 0.11.10</code>のようにバージョンを指定して切り替えます。(もしくは、上記動画のように、<code>n</code>コマンドの後に対話的に選択。</p>
<p>対象のバージョンが存在しない場合は勝手にインストールしてくれます。</p>
<h2 id="注意点">注意点</h2>
<ul>
<li>上記記載しましたように、初期設定では<code>/usr/local/n/versions/バージョン番号/*</code>を全て/usr/local/下に展開するという強烈な作りをしているため、ちゃんとその挙動を理解して使いましょう。
<ul>
<li>嫌な場合は、上記あるように環境変数<code>N_PREFIX</code>を設定して使いましょう</li>
</ul></li>
<li>上記のような動きをするため、1台のサーバ上で動くのは1台のバージョンのみです。ですので、rbenvのように、「1台のサーバでも複数のアプリケーションで別バージョン使えるよ！」というような売りはありません。</li>
</ul>
<h2 id="利点">利点</h2>
<ul>
<li>PATHの切り替えなどではなく、実行ファイルが直接上書きされるという仕様であるため、nodeを使う側はnの存在を全く気にすることなく使うことができます(例えば、nvmなどを使っている時のように“cronで使うにはゴニョゴニョしなくちゃいけない”とか、そういうことを考える必要がありません。)</li>
<li>新しいバージョンのインストールが素早くていいですね。バイナリを落としているだけなのか。
<ul>
<li>昔、nvm installを行う際は、コンパイルを行うため結構な時間を覚悟しなくてはいけないものだったが。</li>
<li>今調べたら、nvmも、オプションによってバイナリを直接落とすことができるようになっていますね。いいですね。</li>
</ul></li>
</ul>
<h2 id="あとがき">あとがき</h2>
<p>サーバ上のバイナリを直接書き換えることによってバージョンを切り替えているため、1台のサーバ上では常に1つのバージョンを使うことしかできず、nvmの求めている用途とは少し異なるねと思いました。 開発環境ではnvmを使い、商用サーバでのバージョンアップにnを使うなどの使い分けが必要ですね。</p>
<p>先ほど、<a href="http://www.moongift.jp/2014/01/dat-データ版git。データを分散管理、解析/">Dat – データ版Git。データを分散管理、解析</a>という、Node製のソフトウェアのブログを読み、試してみようと思ったのですが、最近新調したMacにはNode環境が整っておらず、まずNode環境を整えることからスタートしたのでした。</p>
<p>Dat、面白いですね。</p>

<div id="disqus_thread"></div>
<script type="text/javascript">
    /* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */
    var disqus_shortname = 'dekokun'; // required: replace example with your forum shortname

    /* * * DON'T EDIT BELOW THIS LINE * * */
    (function() {
        var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
        dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js';
        (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
    })();
</script>
<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
<a href="http://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a>

          <ul class="social">
            <li class="kindle"><div class="kindleWidget"><img style="vertical-align:middle;" src="https://d1xnn692s7u6t6.cloudfront.net/white-15.png" /><span style="vertical-align:middle;margin-left:3px;">Send to Kindle</span></div></li>
            <li class="facebook"><div class="fb-like" data-send="false" data-layout="button_count" data-width="100" data-show-faces="true" data-font="arial"></div></li>
            <li class="twitter"><a href="https://twitter.com/share" class="twitter-share-button" data-via="dekokun" data-lang="ja">ツイート</a></li>
            <li class="hatena-bookmark"><a href="http://b.hatena.ne.jp/entry/" class="hatena-bookmark-button" data-hatena-bookmark-layout="standard" title="このエントリーをはてなブックマークに追加"><img src="http://b.st-hatena.com/images/entry-button/button-only.gif" alt="このエントリーをはてなブックマークに追加" width="20" height="20" style="border: none;"></a><script type="text/javascript" src="http://b.st-hatena.com/js/bookmark_button.js" charset="utf-8" async="async"></script></li>
            <li><a data-pocket-label="pocket" data-pocket-count="horizontal" class="pocket-btn" data-lang="en"></a>
            <script type="text/javascript">!function(d,i){if(!d.getElementById(i)){var j=d.createElement("script");j.id=i;j.src="https://widgets.getpocket.com/v1/j/btn.js?v=1";var w=d.getElementById(i);d.body.appendChild(j);}}(document,"pocket-btn-js");</script></li>
          </ul>

        </article>
        <aside class="span3">
          <div class="sidebar-module">
            <div class="title">プロフィール</div>
            <p class="id"><a href="https://twitter.com/dekokun">dekokun</a></p>
            <p><a href="https://twitter.com/dekokun"><img src="../img/dekokun.png" alt="dekokun"></a></p>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.io/";
              Hatena.BookmarkWidget.title = "人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 200;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.com/";
              Hatena.BookmarkWidget.title = "旧人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 0;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module visible-desktop">
            <div class="title">twitter</div>
            <a class="twitter-timeline" data-dnt="true" href="https://twitter.com/dekokun" data-widget-id="306408547573440513">@dekokun からのツイート</a>
            <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
          </div>
          <div class="sidebar-module hidden-phone">
            <div class="title">RSS</div>
            <p><a href="../rss.xml"><img src="../img/rss.gif" alt="rss"></a></p>
          </div>
        </aside> <!-- /span3 -->
      </div> <!-- /row -->
      <footer>
        <p>©<script type="text/javascript">$y=2012;$ny=new Date().getFullYear();document.write($ny>$y?$y+'-'+$ny:$y);</script> <a href="https://twitter.com/dekokun">dekokun</a></p>
      </footer>
    </div> <!-- /container -->

    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script>window.jQuery || document.write('<script src="../js/libs/jquery-1.7.2.min.js"><\/script>')</script>
    <!-- /ツイートボタン -->
  <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>

    <script src="../js/libs/bootstrap/bootstrap.min.js"></script>

    <script src="../js/script.js"></script>
    <script>
      var _gaq=[['_setAccount','UA-XXXXX-X'],['_trackPageview']];
      (function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
      g.src=('https:'==location.protocol?'//ssl':'//www')+'.google-analytics.com/ga.js';
      s.parentNode.insertBefore(g,s)}(document,'script'));
    </script>
    <!-- Code syntax highlight -->
    <script type="text/javascript" src="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.js"></script>
    <script type="text/javascript">
    $(function(){ 
        $('pre').css({
            'overflow-x': 'scroll',
            'background-color': '#f6f6f6',
            'border': '1px dotted #ccc',
            'padding': '0.8em'
        });
        $('pre code').addClass('prettyprint');
        prettyPrint();
    });
    </script>
    <script type="text/javascript" src="https://d1xnn692s7u6t6.cloudfront.net/widget.js"></script>
    <script type="text/javascript">(function k(){window.$SendToKindle&&window.$SendToKindle.Widget?$SendToKindle.Widget.init({"content":"article"}):setTimeout(k,500);})();</script>
  </body>
</html>
]]></description>
    <pubDate>No date found.</pubDate>
    <guid>http://dekokun.github.io/posts/2014-01-01.html</guid>
</item>
<item>
    <title>Zabbixで「○回のうち○回失敗したら」というトリガー設定</title>
    <link>http://dekokun.github.io/posts/2014-01-30.html</link>
    <description><![CDATA[<!doctype html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7" lang="ja"> <![endif]-->
<!--[if IE 7]>    <html class="no-js lt-ie9 lt-ie8" lang="ja"> <![endif]-->
<!--[if IE 8]>    <html class="no-js lt-ie9" lang="ja"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="ja"> <!--<![endif]-->
  <head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# article: http://ogp.me/ns/article#">
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <title>Zabbixで「○回のうち○回失敗したら」というトリガー設定</title>
    <meta name="description" content>
    <meta name="author" content>

    <meta name="viewport" content="width=device-width">
    <meta property="fb:app_id" content="351187098330864">
    <meta property="og:type" content="article">
    <meta property="og:image" content="http://dekokun.github.com/img/dekokun.png">
    <meta property="og:title" content="Zabbixで「○回のうち○回失敗したら」というトリガー設定">
    <meta property="og:description" content="@dekokunの技術日記">
    <meta property="og:site_name" content="でこてっくろぐ">
    <meta name="twitter:widgets:csp" content="on">

    <link rel="stylesheet" href="../css/bootstrap.css">
    <link rel="stylesheet" href="../css/bootstrap-responsive.css">
    <link rel="stylesheet" href="../css/style.css">
    <style>
    body {
      padding-top: 60px;
      padding-bottom: 40px;
    }
    </style>
    <link href="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.css" type="text/css" rel="stylesheet">
    <script src="../js/libs/modernizr-2.5.3-respond-1.1.0.min.js"></script>
    <script>
      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

      ga('create', 'UA-39650556-1', 'auto');
      ga('send', 'pageview');
    </script>
  </head>
  <body>
  <!--[if lt IE 7]><p class=chromeframe>Your browser is <em>ancient!</em> <a href="http://browsehappy.com/">Upgrade to a different browser</a> or <a href="http://www.google.com/chromeframe/?redirect=true">install Google Chrome Frame</a> to experience this site.</p><![endif]-->
    <div id="fb-root"></div>
    <script>(function(d, s, id) {
      var js, fjs = d.getElementsByTagName(s)[0];
      if (d.getElementById(id)) return;
      js = d.createElement(s); js.id = id;
      js.src = "//connect.facebook.net/ja_JP/all.js#xfbml=1&appId=351187098330864";
      fjs.parentNode.insertBefore(js, fjs);
      }(document, 'script', 'facebook-jssdk'));
    </script>
    <header>
      <nav class="navbar navbar-fixed-top">
        <div class="navbar-inner">
          <div class="container">
            <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
            </a>
            <a class="brand" href="../index.html">でこてっくろぐ</a>
            <div class="nav-collapse">
              <ul class="nav">
                <li><a href="../index.html">ほーむ</a></li>
                <li><a href="../posts.html">あーかいぶ</a></li>
                <li><a href="../aboutme.html">あばうとみー</a></li>
              </ul>
            </div><!--/.nav-collapse -->
          </div>
        </div>
      </nav>
    </header>

    <div class="container">
      <div class="row">
        <article class="span9">
          <h1>Zabbixで「○回のうち○回失敗したら」というトリガー設定</h1>

<p>by <em><a href="https://twitter.com/dekokun">@dekokun</a></em> on <strong>2014/01/30 00:45</strong></p>

<p>Tagged as: <a href="../tags/Zabbix.html">Zabbix</a>.</p>

<p>忘れがちなので</p>
<pre><code>アイテム名.count(直近何回から取得するか, 値, &quot;gtとかeqとか&quot;)&gt;回数

例：
{Template OS Linux:system.cpu.util[,iowait].count(#5, 30, &quot;gt&quot;)}&gt;3

上記は、直近5回の計測でiowaitが30よりも大きい場合が3回より多くあったらトリガー発動
</code></pre>
<p>それだけ。</p>

<div id="disqus_thread"></div>
<script type="text/javascript">
    /* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */
    var disqus_shortname = 'dekokun'; // required: replace example with your forum shortname

    /* * * DON'T EDIT BELOW THIS LINE * * */
    (function() {
        var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
        dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js';
        (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
    })();
</script>
<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
<a href="http://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a>

          <ul class="social">
            <li class="kindle"><div class="kindleWidget"><img style="vertical-align:middle;" src="https://d1xnn692s7u6t6.cloudfront.net/white-15.png" /><span style="vertical-align:middle;margin-left:3px;">Send to Kindle</span></div></li>
            <li class="facebook"><div class="fb-like" data-send="false" data-layout="button_count" data-width="100" data-show-faces="true" data-font="arial"></div></li>
            <li class="twitter"><a href="https://twitter.com/share" class="twitter-share-button" data-via="dekokun" data-lang="ja">ツイート</a></li>
            <li class="hatena-bookmark"><a href="http://b.hatena.ne.jp/entry/" class="hatena-bookmark-button" data-hatena-bookmark-layout="standard" title="このエントリーをはてなブックマークに追加"><img src="http://b.st-hatena.com/images/entry-button/button-only.gif" alt="このエントリーをはてなブックマークに追加" width="20" height="20" style="border: none;"></a><script type="text/javascript" src="http://b.st-hatena.com/js/bookmark_button.js" charset="utf-8" async="async"></script></li>
            <li><a data-pocket-label="pocket" data-pocket-count="horizontal" class="pocket-btn" data-lang="en"></a>
            <script type="text/javascript">!function(d,i){if(!d.getElementById(i)){var j=d.createElement("script");j.id=i;j.src="https://widgets.getpocket.com/v1/j/btn.js?v=1";var w=d.getElementById(i);d.body.appendChild(j);}}(document,"pocket-btn-js");</script></li>
          </ul>

        </article>
        <aside class="span3">
          <div class="sidebar-module">
            <div class="title">プロフィール</div>
            <p class="id"><a href="https://twitter.com/dekokun">dekokun</a></p>
            <p><a href="https://twitter.com/dekokun"><img src="../img/dekokun.png" alt="dekokun"></a></p>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.io/";
              Hatena.BookmarkWidget.title = "人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 200;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.com/";
              Hatena.BookmarkWidget.title = "旧人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 0;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module visible-desktop">
            <div class="title">twitter</div>
            <a class="twitter-timeline" data-dnt="true" href="https://twitter.com/dekokun" data-widget-id="306408547573440513">@dekokun からのツイート</a>
            <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
          </div>
          <div class="sidebar-module hidden-phone">
            <div class="title">RSS</div>
            <p><a href="../rss.xml"><img src="../img/rss.gif" alt="rss"></a></p>
          </div>
        </aside> <!-- /span3 -->
      </div> <!-- /row -->
      <footer>
        <p>©<script type="text/javascript">$y=2012;$ny=new Date().getFullYear();document.write($ny>$y?$y+'-'+$ny:$y);</script> <a href="https://twitter.com/dekokun">dekokun</a></p>
      </footer>
    </div> <!-- /container -->

    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script>window.jQuery || document.write('<script src="../js/libs/jquery-1.7.2.min.js"><\/script>')</script>
    <!-- /ツイートボタン -->
  <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>

    <script src="../js/libs/bootstrap/bootstrap.min.js"></script>

    <script src="../js/script.js"></script>
    <script>
      var _gaq=[['_setAccount','UA-XXXXX-X'],['_trackPageview']];
      (function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
      g.src=('https:'==location.protocol?'//ssl':'//www')+'.google-analytics.com/ga.js';
      s.parentNode.insertBefore(g,s)}(document,'script'));
    </script>
    <!-- Code syntax highlight -->
    <script type="text/javascript" src="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.js"></script>
    <script type="text/javascript">
    $(function(){ 
        $('pre').css({
            'overflow-x': 'scroll',
            'background-color': '#f6f6f6',
            'border': '1px dotted #ccc',
            'padding': '0.8em'
        });
        $('pre code').addClass('prettyprint');
        prettyPrint();
    });
    </script>
    <script type="text/javascript" src="https://d1xnn692s7u6t6.cloudfront.net/widget.js"></script>
    <script type="text/javascript">(function k(){window.$SendToKindle&&window.$SendToKindle.Widget?$SendToKindle.Widget.init({"content":"article"}):setTimeout(k,500);})();</script>
  </body>
</html>
]]></description>
    <pubDate>No date found.</pubDate>
    <guid>http://dekokun.github.io/posts/2014-01-30.html</guid>
</item>
<item>
    <title>Lang-8はiOSエンジニアを募集しているとのことです！ #lang8_sushi_karaage 及びささたつさんとお話しした技術的なこと</title>
    <link>http://dekokun.github.io/posts/2014-02-12.html</link>
    <description><![CDATA[<!doctype html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7" lang="ja"> <![endif]-->
<!--[if IE 7]>    <html class="no-js lt-ie9 lt-ie8" lang="ja"> <![endif]-->
<!--[if IE 8]>    <html class="no-js lt-ie9" lang="ja"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="ja"> <!--<![endif]-->
  <head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# article: http://ogp.me/ns/article#">
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <title>Lang-8はiOSエンジニアを募集しているとのことです！ #lang8_sushi_karaage 及びささたつさんとお話しした技術的なこと</title>
    <meta name="description" content>
    <meta name="author" content>

    <meta name="viewport" content="width=device-width">
    <meta property="fb:app_id" content="351187098330864">
    <meta property="og:type" content="article">
    <meta property="og:image" content="http://dekokun.github.com/img/dekokun.png">
    <meta property="og:title" content="Lang-8はiOSエンジニアを募集しているとのことです！ #lang8_sushi_karaage 及びささたつさんとお話しした技術的なこと">
    <meta property="og:description" content="@dekokunの技術日記">
    <meta property="og:site_name" content="でこてっくろぐ">
    <meta name="twitter:widgets:csp" content="on">

    <link rel="stylesheet" href="../css/bootstrap.css">
    <link rel="stylesheet" href="../css/bootstrap-responsive.css">
    <link rel="stylesheet" href="../css/style.css">
    <style>
    body {
      padding-top: 60px;
      padding-bottom: 40px;
    }
    </style>
    <link href="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.css" type="text/css" rel="stylesheet">
    <script src="../js/libs/modernizr-2.5.3-respond-1.1.0.min.js"></script>
    <script>
      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

      ga('create', 'UA-39650556-1', 'auto');
      ga('send', 'pageview');
    </script>
  </head>
  <body>
  <!--[if lt IE 7]><p class=chromeframe>Your browser is <em>ancient!</em> <a href="http://browsehappy.com/">Upgrade to a different browser</a> or <a href="http://www.google.com/chromeframe/?redirect=true">install Google Chrome Frame</a> to experience this site.</p><![endif]-->
    <div id="fb-root"></div>
    <script>(function(d, s, id) {
      var js, fjs = d.getElementsByTagName(s)[0];
      if (d.getElementById(id)) return;
      js = d.createElement(s); js.id = id;
      js.src = "//connect.facebook.net/ja_JP/all.js#xfbml=1&appId=351187098330864";
      fjs.parentNode.insertBefore(js, fjs);
      }(document, 'script', 'facebook-jssdk'));
    </script>
    <header>
      <nav class="navbar navbar-fixed-top">
        <div class="navbar-inner">
          <div class="container">
            <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
            </a>
            <a class="brand" href="../index.html">でこてっくろぐ</a>
            <div class="nav-collapse">
              <ul class="nav">
                <li><a href="../index.html">ほーむ</a></li>
                <li><a href="../posts.html">あーかいぶ</a></li>
                <li><a href="../aboutme.html">あばうとみー</a></li>
              </ul>
            </div><!--/.nav-collapse -->
          </div>
        </div>
      </nav>
    </header>

    <div class="container">
      <div class="row">
        <article class="span9">
          <h1>Lang-8はiOSエンジニアを募集しているとのことです！ #lang8_sushi_karaage 及びささたつさんとお話しした技術的なこと</h1>

<p>by <em><a href="https://twitter.com/dekokun">@dekokun</a></em> on <strong>2014/02/12 22:51</strong></p>

<p>Tagged as: <a href="../tags/Lang-8.html">Lang-8</a>.</p>

<p>本日は、Lang-8がオフィス移転をした記念ということで、<a href="http://www.zusaar.com/event/3497004">Lang-8 Sushi Karaage</a>が開かれました。私は参加してきました！！</p>
<p>最初に、Lang-8はiOSエンジニアを募集しているそうですよ！<a href="https://www.wantedly.com/projects/5123">wantedly 本当にグローバルなアプリを作りたいiOSエンジニア募集!</a></p>
<h2 id="お話ししたこと">お話ししたこと</h2>
<p><a href="https://kitchhike.com/">KitchHike</a>というサービスを運営している方とお話をしました。 旅行客(主に外国人？)に向けたサービスで、家庭料理を有償で振る舞っていいよという人とをマッチングするサービスとのことでした。こういう、料理をシェアする系のサービスはいいなぁと思いました。ちょっとこのサービスの文脈とは外れてしまうかもしれませんが、料理を提供できる人たち(子どもと一緒に住んでいない親とか！)と、料理を欲する人たち(私とその妻のような、地方出身のワーカホリック気味な家庭とか！)のマッチングとかあるととても幸せだなと思いました。</p>
<p><a href="https://twitter.com/2celeb">@2celeb</a>さんとそのお知り合い（Lang-8で働いているとのことでしたがアカウントがわからない&gt;&lt; 追記：<a href="https://twitter.com/suginoy">@suginoy</a>さんとのことでした！Twitterでフォローしていた！）の方と、Ruby及びRails周りのバージョンアップやMongoDBなどに関して話を聞きました！ hogehoge.rbなどでRailsの低いバージョンを使っているとガンガンdisられるみたいな話を聞いて、Ruby界隈は楽しげだなぁという感想をいだきました。</p>
<p>そして、私的に一番うれしかったのは、<a href="https://twitter.com/sasata29://twitter.com/sasata299">@sasata299</a>さんとたくさん話せたことです！！！！！！</p>
<p>sasata299さんのブログとか読んでて、すごいなーと思っていたので、とても嬉しかった！ちゃんと個人的に話せたのは初めてですし！！！！</p>
<h2 id="sasata299さんと話したこと達">sasata299さんと話したこと達</h2>
<h3 id="pt-online-schema-changeの失敗の件">pt-online-schema-changeの失敗の件</h3>
<ul>
<li>sasata299さんの書いたブログを参考にpt-online-schema-changeを使ったら盛大に失敗したという話</li>
<li>同じレコードを使ったテスト環境では成功したのになー</li>
<li>こういう失敗談を共有できるような文化があんまり無いですよねーというお話をしました。
<ul>
<li>「失敗談は、原因を追求しないと公表しづらい」</li>
<li>「有識者に『そんなことも知らなかったのかカスが』と言われそうで怖い」</li>
<li>というわけで、匿名で失敗談を共有するようなもの欲しいねという話でした。</li>
</ul></li>
</ul>
<h3 id="テストの文化を醸成するのが難しいとのこと">テストの文化を醸成するのが難しいとのこと</h3>
<ul>
<li>結構話したけど比較的忘れた</li>
<li>まぁ、チーム全体でテストを書くのは非常に難しいですよねという感じの話をしました</li>
<li>Lang-8では、ブラウザ側のテストもガリガリ書いているようで、ブラウザ側のようなテストが比較的もろくなりがちな環境でも頑張っているんだなぁという感じがありました。APIのテストで「仕様変更でガンガンテストが落ちていきます！！！」という感じで音を上げがちなうちのチームは(というか私は)まだまだですね。</li>
</ul>
<h3 id="migrationどうよという話">migrationどうよという話</h3>
<ul>
<li>主に以前ツイートした以下のような話</li>
</ul>
<blockquote class="twitter-tweet" lang="ja"><p>
実際に開発者全員がmigrationを駆使して開発するとカオスになるということがよくわかってきているところ。事前に設計をすりあわせたとしても。
</p>
— でこくん (@dekokun) <a href="https://twitter.com/dekokun/statuses/428513025587298305">2014, 1月 29</a>
</blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
<blockquote class="twitter-tweet" lang="ja"><p>
そもそも、migrationについては、git checkoutに追従できない(downのSQLを発行するためのファイル自体が消滅する)ため、まぁ、最初に設計して共有しなくちゃいけませんねという話ですね。
</p>
— でこくん (@dekokun) <a href="https://twitter.com/dekokun/statuses/428516408121507840">2014, 1月 29</a>
</blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
<blockquote class="twitter-tweet" lang="ja"><p>
migrationとrollbackを行い、DBが元の形に戻っているかを検出するというCIが求められている。
</p>
— でこくん (@dekokun) <a href="https://twitter.com/dekokun/statuses/428529335117443073">2014, 1月 29</a>
</blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>

<h3 id="pull-requestを1人でさばくことのアンチパターン感">pull requestを1人でさばくことのアンチパターン感</h3>
<ul>
<li>pull requestをさばく（≒レビューをする）のを一人でやるのってかなり時間がかかってアンチパターン感ありますよね！！！！！！！</li>
<li>でもある程度しかたない側面もあって難しいところ</li>
</ul>
<h2 id="最後に">最後に</h2>
<p>なお、私とLang-8の関わりは、大学時代にインターンとして携帯サイト(ガラケーですよ！ガラケー！！！)の画面遷移図を作成していたことにさかのぼります。当時はLang-8も京都にありましたし、私も京都にいました。そこから、私もLang-8も東京にきて、更にLang-8はオフィス移転なんですね！ おめでとうございます！！！</p>
<p>そして昔は社会人になってもガラケー担当だった気がする私もいつの間にかスマートフォンアプリのサーバサイド開発担当になっているわけです。時代は変わるものなのですねぇ。</p>
<p>先日送った透明な感じのデスクと電源タップをがんがん使い倒していっていただけたらと思います！！！</p>
<p>最後に、Lang-8はiOSエンジニアを募集しているとのことでした！！！！！われこそはと思うエンジニアは是非！！！</p>
<p><a href="https://www.wantedly.com/projects/5123">wantedly 本当にグローバルなアプリを作りたいiOSエンジニア募集!</a></p>

<div id="disqus_thread"></div>
<script type="text/javascript">
    /* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */
    var disqus_shortname = 'dekokun'; // required: replace example with your forum shortname

    /* * * DON'T EDIT BELOW THIS LINE * * */
    (function() {
        var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
        dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js';
        (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
    })();
</script>
<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
<a href="http://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a>

          <ul class="social">
            <li class="kindle"><div class="kindleWidget"><img style="vertical-align:middle;" src="https://d1xnn692s7u6t6.cloudfront.net/white-15.png" /><span style="vertical-align:middle;margin-left:3px;">Send to Kindle</span></div></li>
            <li class="facebook"><div class="fb-like" data-send="false" data-layout="button_count" data-width="100" data-show-faces="true" data-font="arial"></div></li>
            <li class="twitter"><a href="https://twitter.com/share" class="twitter-share-button" data-via="dekokun" data-lang="ja">ツイート</a></li>
            <li class="hatena-bookmark"><a href="http://b.hatena.ne.jp/entry/" class="hatena-bookmark-button" data-hatena-bookmark-layout="standard" title="このエントリーをはてなブックマークに追加"><img src="http://b.st-hatena.com/images/entry-button/button-only.gif" alt="このエントリーをはてなブックマークに追加" width="20" height="20" style="border: none;"></a><script type="text/javascript" src="http://b.st-hatena.com/js/bookmark_button.js" charset="utf-8" async="async"></script></li>
            <li><a data-pocket-label="pocket" data-pocket-count="horizontal" class="pocket-btn" data-lang="en"></a>
            <script type="text/javascript">!function(d,i){if(!d.getElementById(i)){var j=d.createElement("script");j.id=i;j.src="https://widgets.getpocket.com/v1/j/btn.js?v=1";var w=d.getElementById(i);d.body.appendChild(j);}}(document,"pocket-btn-js");</script></li>
          </ul>

        </article>
        <aside class="span3">
          <div class="sidebar-module">
            <div class="title">プロフィール</div>
            <p class="id"><a href="https://twitter.com/dekokun">dekokun</a></p>
            <p><a href="https://twitter.com/dekokun"><img src="../img/dekokun.png" alt="dekokun"></a></p>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.io/";
              Hatena.BookmarkWidget.title = "人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 200;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.com/";
              Hatena.BookmarkWidget.title = "旧人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 0;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module visible-desktop">
            <div class="title">twitter</div>
            <a class="twitter-timeline" data-dnt="true" href="https://twitter.com/dekokun" data-widget-id="306408547573440513">@dekokun からのツイート</a>
            <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
          </div>
          <div class="sidebar-module hidden-phone">
            <div class="title">RSS</div>
            <p><a href="../rss.xml"><img src="../img/rss.gif" alt="rss"></a></p>
          </div>
        </aside> <!-- /span3 -->
      </div> <!-- /row -->
      <footer>
        <p>©<script type="text/javascript">$y=2012;$ny=new Date().getFullYear();document.write($ny>$y?$y+'-'+$ny:$y);</script> <a href="https://twitter.com/dekokun">dekokun</a></p>
      </footer>
    </div> <!-- /container -->

    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script>window.jQuery || document.write('<script src="../js/libs/jquery-1.7.2.min.js"><\/script>')</script>
    <!-- /ツイートボタン -->
  <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>

    <script src="../js/libs/bootstrap/bootstrap.min.js"></script>

    <script src="../js/script.js"></script>
    <script>
      var _gaq=[['_setAccount','UA-XXXXX-X'],['_trackPageview']];
      (function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
      g.src=('https:'==location.protocol?'//ssl':'//www')+'.google-analytics.com/ga.js';
      s.parentNode.insertBefore(g,s)}(document,'script'));
    </script>
    <!-- Code syntax highlight -->
    <script type="text/javascript" src="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.js"></script>
    <script type="text/javascript">
    $(function(){ 
        $('pre').css({
            'overflow-x': 'scroll',
            'background-color': '#f6f6f6',
            'border': '1px dotted #ccc',
            'padding': '0.8em'
        });
        $('pre code').addClass('prettyprint');
        prettyPrint();
    });
    </script>
    <script type="text/javascript" src="https://d1xnn692s7u6t6.cloudfront.net/widget.js"></script>
    <script type="text/javascript">(function k(){window.$SendToKindle&&window.$SendToKindle.Widget?$SendToKindle.Widget.init({"content":"article"}):setTimeout(k,500);})();</script>
  </body>
</html>
]]></description>
    <pubDate>No date found.</pubDate>
    <guid>http://dekokun.github.io/posts/2014-02-12.html</guid>
</item>
<item>
    <title>PHPのMockeryでメソッドが特定の引数を受け取った時のみ動作を変えるモック作成方法</title>
    <link>http://dekokun.github.io/posts/2014-03-08.html</link>
    <description><![CDATA[<!doctype html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7" lang="ja"> <![endif]-->
<!--[if IE 7]>    <html class="no-js lt-ie9 lt-ie8" lang="ja"> <![endif]-->
<!--[if IE 8]>    <html class="no-js lt-ie9" lang="ja"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="ja"> <!--<![endif]-->
  <head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# article: http://ogp.me/ns/article#">
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <title>PHPのMockeryでメソッドが特定の引数を受け取った時のみ動作を変えるモック作成方法</title>
    <meta name="description" content>
    <meta name="author" content>

    <meta name="viewport" content="width=device-width">
    <meta property="fb:app_id" content="351187098330864">
    <meta property="og:type" content="article">
    <meta property="og:image" content="http://dekokun.github.com/img/dekokun.png">
    <meta property="og:title" content="PHPのMockeryでメソッドが特定の引数を受け取った時のみ動作を変えるモック作成方法">
    <meta property="og:description" content="@dekokunの技術日記">
    <meta property="og:site_name" content="でこてっくろぐ">
    <meta name="twitter:widgets:csp" content="on">

    <link rel="stylesheet" href="../css/bootstrap.css">
    <link rel="stylesheet" href="../css/bootstrap-responsive.css">
    <link rel="stylesheet" href="../css/style.css">
    <style>
    body {
      padding-top: 60px;
      padding-bottom: 40px;
    }
    </style>
    <link href="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.css" type="text/css" rel="stylesheet">
    <script src="../js/libs/modernizr-2.5.3-respond-1.1.0.min.js"></script>
    <script>
      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

      ga('create', 'UA-39650556-1', 'auto');
      ga('send', 'pageview');
    </script>
  </head>
  <body>
  <!--[if lt IE 7]><p class=chromeframe>Your browser is <em>ancient!</em> <a href="http://browsehappy.com/">Upgrade to a different browser</a> or <a href="http://www.google.com/chromeframe/?redirect=true">install Google Chrome Frame</a> to experience this site.</p><![endif]-->
    <div id="fb-root"></div>
    <script>(function(d, s, id) {
      var js, fjs = d.getElementsByTagName(s)[0];
      if (d.getElementById(id)) return;
      js = d.createElement(s); js.id = id;
      js.src = "//connect.facebook.net/ja_JP/all.js#xfbml=1&appId=351187098330864";
      fjs.parentNode.insertBefore(js, fjs);
      }(document, 'script', 'facebook-jssdk'));
    </script>
    <header>
      <nav class="navbar navbar-fixed-top">
        <div class="navbar-inner">
          <div class="container">
            <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
            </a>
            <a class="brand" href="../index.html">でこてっくろぐ</a>
            <div class="nav-collapse">
              <ul class="nav">
                <li><a href="../index.html">ほーむ</a></li>
                <li><a href="../posts.html">あーかいぶ</a></li>
                <li><a href="../aboutme.html">あばうとみー</a></li>
              </ul>
            </div><!--/.nav-collapse -->
          </div>
        </div>
      </nav>
    </header>

    <div class="container">
      <div class="row">
        <article class="span9">
          <h1>PHPのMockeryでメソッドが特定の引数を受け取った時のみ動作を変えるモック作成方法</h1>

<p>by <em><a href="https://twitter.com/dekokun">@dekokun</a></em> on <strong>2014/03/08 11:55</strong></p>

<p>Tagged as: <a href="../tags/PHP.html">PHP</a>, <a href="../tags/Mockery.html">Mockery</a>.</p>

<p>テスト、モック使用が重要ですね。</p>
<p>DIとモックで快適なテストライフを送りましょう。</p>
<p>さて、現在、モックライブラリとしてMockeryを使っております。</p>
<p>先日、ある引数が渡ってきた時だけ動作を変更するようなモックを作りたかったのですが軽く調べただけでは出てこないような情報だったためこちらに記載しておきます。</p>
<p>具体的には、withで引数指定してshouldReturnで返り値を決定し、その後passthruを指定することにより、それ以外の引数の際は元のメソッドの動作を行わせることができます。</p>
<p>ただし、以下でテストしているようにpassthruの後にwithで引数指定を行った場合は指定が効きませんのでご注意。</p>
<p>ただ、一点、上記のようなテストはテストが実装の内部に依存しすぎた脆いテストになりがちであり、そもそも上記のようなモックが必要だと思った時点で設計に敗北している可能性が高いのでそこだけ注意。</p>
<pre><code>&lt;?php

use \Mockery as m;

class MockeryTest extends PHPUnit_Framework_TestCase
{
    private $mock;

    public function setUp()
    {
        $mock = m::mock('\HOGE', ['a', 'b']);
        // 引数がhogeだったら&quot;mock : hoge&quot;を返す
        $mock-&gt;shouldReceive('get')-&gt;with('hoge')-&gt;andReturn('mock : hoge');
        // 引数がfugaだったら&quot;mock : fuga&quot;を返す
        $mock-&gt;shouldReceive('get')-&gt;with('fuga')-&gt;andReturn('mock : fuga');
        // それ以外の引数の場合は元のクラスの動作をさせる
        $mock-&gt;shouldReceive('get')-&gt;passthru();
        // 引数がfooだったら&quot;mock : foo&quot;を返す ?
        $mock-&gt;shouldReceive('get')-&gt;with('foo')-&gt;andReturn('mock : foo');
        $this-&gt;mock = $mock;
    }

    /**
    * @test
    */
    public function Mockeryが特定の引数の時だけちゃんと動く()
    {
        $this-&gt;assertEquals('mock : hoge', $this-&gt;mock-&gt;get('hoge'));
    }

    /**
    * @test
    */
    public function withでの指定が2個目でも成功する()
    {
        $this-&gt;assertEquals('mock : fuga', $this-&gt;mock-&gt;get('fuga'));
    }

    /**
    * @test
    */
    public function withで指定されていなかった場合は元のメソッドと同じ動きをする()
    {
        $this-&gt;assertEquals('original : piyoab', $this-&gt;mock-&gt;get('piyo'));
    }

    /**
    * @test
    */
    public function passthruの後の指定は無効()
    {
        // with('foo')-&gt;andReturn('mock : foo') としたはずだが…
        $this-&gt;assertEquals('original : fooab', $this-&gt;mock-&gt;get('foo'));
    }
}

class HOGE
{

    protected $a;
    protected $b;

    public function __construct($a, $b)
    {
        $this-&gt;a = $a;
        $this-&gt;b = $b;
    }
    public function get($str)
    {
        return 'original : ' . $str . $this-&gt;a . $this-&gt;b;
    }
}</code></pre>
<p>上記を実行すると、テストは全部通ります。めでたしめでたし。</p>
<pre><code>$ vendor/bin/phpunit test.php
PHPUnit 4.0.3 by Sebastian Bergmann.

....

Time: 36 ms, Memory: 3.25Mb

OK (4 tests, 4 assertions)</code></pre>
<h2 id="まとめ">まとめ</h2>
<ul>
<li>mockeryを使った際に、メソッドがある引数を受け取った時だけモックの動きを変え、それ以外の引数の時は元のメソッドの動きをさせる場合はwithとpassthruを組み合わせて使いましょう</li>
</ul>

<div id="disqus_thread"></div>
<script type="text/javascript">
    /* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */
    var disqus_shortname = 'dekokun'; // required: replace example with your forum shortname

    /* * * DON'T EDIT BELOW THIS LINE * * */
    (function() {
        var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
        dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js';
        (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
    })();
</script>
<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
<a href="http://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a>

          <ul class="social">
            <li class="kindle"><div class="kindleWidget"><img style="vertical-align:middle;" src="https://d1xnn692s7u6t6.cloudfront.net/white-15.png" /><span style="vertical-align:middle;margin-left:3px;">Send to Kindle</span></div></li>
            <li class="facebook"><div class="fb-like" data-send="false" data-layout="button_count" data-width="100" data-show-faces="true" data-font="arial"></div></li>
            <li class="twitter"><a href="https://twitter.com/share" class="twitter-share-button" data-via="dekokun" data-lang="ja">ツイート</a></li>
            <li class="hatena-bookmark"><a href="http://b.hatena.ne.jp/entry/" class="hatena-bookmark-button" data-hatena-bookmark-layout="standard" title="このエントリーをはてなブックマークに追加"><img src="http://b.st-hatena.com/images/entry-button/button-only.gif" alt="このエントリーをはてなブックマークに追加" width="20" height="20" style="border: none;"></a><script type="text/javascript" src="http://b.st-hatena.com/js/bookmark_button.js" charset="utf-8" async="async"></script></li>
            <li><a data-pocket-label="pocket" data-pocket-count="horizontal" class="pocket-btn" data-lang="en"></a>
            <script type="text/javascript">!function(d,i){if(!d.getElementById(i)){var j=d.createElement("script");j.id=i;j.src="https://widgets.getpocket.com/v1/j/btn.js?v=1";var w=d.getElementById(i);d.body.appendChild(j);}}(document,"pocket-btn-js");</script></li>
          </ul>

        </article>
        <aside class="span3">
          <div class="sidebar-module">
            <div class="title">プロフィール</div>
            <p class="id"><a href="https://twitter.com/dekokun">dekokun</a></p>
            <p><a href="https://twitter.com/dekokun"><img src="../img/dekokun.png" alt="dekokun"></a></p>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.io/";
              Hatena.BookmarkWidget.title = "人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 200;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.com/";
              Hatena.BookmarkWidget.title = "旧人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 0;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module visible-desktop">
            <div class="title">twitter</div>
            <a class="twitter-timeline" data-dnt="true" href="https://twitter.com/dekokun" data-widget-id="306408547573440513">@dekokun からのツイート</a>
            <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
          </div>
          <div class="sidebar-module hidden-phone">
            <div class="title">RSS</div>
            <p><a href="../rss.xml"><img src="../img/rss.gif" alt="rss"></a></p>
          </div>
        </aside> <!-- /span3 -->
      </div> <!-- /row -->
      <footer>
        <p>©<script type="text/javascript">$y=2012;$ny=new Date().getFullYear();document.write($ny>$y?$y+'-'+$ny:$y);</script> <a href="https://twitter.com/dekokun">dekokun</a></p>
      </footer>
    </div> <!-- /container -->

    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script>window.jQuery || document.write('<script src="../js/libs/jquery-1.7.2.min.js"><\/script>')</script>
    <!-- /ツイートボタン -->
  <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>

    <script src="../js/libs/bootstrap/bootstrap.min.js"></script>

    <script src="../js/script.js"></script>
    <script>
      var _gaq=[['_setAccount','UA-XXXXX-X'],['_trackPageview']];
      (function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
      g.src=('https:'==location.protocol?'//ssl':'//www')+'.google-analytics.com/ga.js';
      s.parentNode.insertBefore(g,s)}(document,'script'));
    </script>
    <!-- Code syntax highlight -->
    <script type="text/javascript" src="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.js"></script>
    <script type="text/javascript">
    $(function(){ 
        $('pre').css({
            'overflow-x': 'scroll',
            'background-color': '#f6f6f6',
            'border': '1px dotted #ccc',
            'padding': '0.8em'
        });
        $('pre code').addClass('prettyprint');
        prettyPrint();
    });
    </script>
    <script type="text/javascript" src="https://d1xnn692s7u6t6.cloudfront.net/widget.js"></script>
    <script type="text/javascript">(function k(){window.$SendToKindle&&window.$SendToKindle.Widget?$SendToKindle.Widget.init({"content":"article"}):setTimeout(k,500);})();</script>
  </body>
</html>
]]></description>
    <pubDate>No date found.</pubDate>
    <guid>http://dekokun.github.io/posts/2014-03-08.html</guid>
</item>
<item>
    <title>PHPのarray_searchが全く見当違い(に見える)値を出力する件について(ちゃんとstrictフラグ立てよう)</title>
    <link>http://dekokun.github.io/posts/2014-04-26.html</link>
    <description><![CDATA[<!doctype html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7" lang="ja"> <![endif]-->
<!--[if IE 7]>    <html class="no-js lt-ie9 lt-ie8" lang="ja"> <![endif]-->
<!--[if IE 8]>    <html class="no-js lt-ie9" lang="ja"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="ja"> <!--<![endif]-->
  <head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# article: http://ogp.me/ns/article#">
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <title>PHPのarray_searchが全く見当違い(に見える)値を出力する件について(ちゃんとstrictフラグ立てよう)</title>
    <meta name="description" content>
    <meta name="author" content>

    <meta name="viewport" content="width=device-width">
    <meta property="fb:app_id" content="351187098330864">
    <meta property="og:type" content="article">
    <meta property="og:image" content="http://dekokun.github.com/img/dekokun.png">
    <meta property="og:title" content="PHPのarray_searchが全く見当違い(に見える)値を出力する件について(ちゃんとstrictフラグ立てよう)">
    <meta property="og:description" content="@dekokunの技術日記">
    <meta property="og:site_name" content="でこてっくろぐ">
    <meta name="twitter:widgets:csp" content="on">

    <link rel="stylesheet" href="../css/bootstrap.css">
    <link rel="stylesheet" href="../css/bootstrap-responsive.css">
    <link rel="stylesheet" href="../css/style.css">
    <style>
    body {
      padding-top: 60px;
      padding-bottom: 40px;
    }
    </style>
    <link href="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.css" type="text/css" rel="stylesheet">
    <script src="../js/libs/modernizr-2.5.3-respond-1.1.0.min.js"></script>
    <script>
      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

      ga('create', 'UA-39650556-1', 'auto');
      ga('send', 'pageview');
    </script>
  </head>
  <body>
  <!--[if lt IE 7]><p class=chromeframe>Your browser is <em>ancient!</em> <a href="http://browsehappy.com/">Upgrade to a different browser</a> or <a href="http://www.google.com/chromeframe/?redirect=true">install Google Chrome Frame</a> to experience this site.</p><![endif]-->
    <div id="fb-root"></div>
    <script>(function(d, s, id) {
      var js, fjs = d.getElementsByTagName(s)[0];
      if (d.getElementById(id)) return;
      js = d.createElement(s); js.id = id;
      js.src = "//connect.facebook.net/ja_JP/all.js#xfbml=1&appId=351187098330864";
      fjs.parentNode.insertBefore(js, fjs);
      }(document, 'script', 'facebook-jssdk'));
    </script>
    <header>
      <nav class="navbar navbar-fixed-top">
        <div class="navbar-inner">
          <div class="container">
            <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
            </a>
            <a class="brand" href="../index.html">でこてっくろぐ</a>
            <div class="nav-collapse">
              <ul class="nav">
                <li><a href="../index.html">ほーむ</a></li>
                <li><a href="../posts.html">あーかいぶ</a></li>
                <li><a href="../aboutme.html">あばうとみー</a></li>
              </ul>
            </div><!--/.nav-collapse -->
          </div>
        </div>
      </nav>
    </header>

    <div class="container">
      <div class="row">
        <article class="span9">
          <h1>PHPのarray_searchが全く見当違い(に見える)値を出力する件について(ちゃんとstrictフラグ立てよう)</h1>

<p>by <em><a href="https://twitter.com/dekokun">@dekokun</a></em> on <strong>2014/04/26 20:40</strong></p>

<p>Tagged as: <a href="../tags/PHP.html">PHP</a>.</p>

<p>どうも。来月結婚する@dekokunです。タイトルで言いたいことは全て言っているのですが、まぁ詳細書きます。</p>
<h2 id="導入-array_searchとは">導入 array_searchとは</h2>
<blockquote>
<p>指定した値を配列で検索し、見つかった場合に対応するキーを返す</p>
</blockquote>
<p>参照：<a href="http://www.php.net/manual/ja/function.array-search.php">array_search</a></p>
<pre><code>&lt;?php
array_search(1, [2, 3, 4, 1]); // =&gt; 3
// インデックス3の値が1なので、3が返ってきた
array_search(1, [2, 1, 4, 1]); // =&gt; 1
// 複数マッチした場合は最初にマッチした値を返す</code></pre>
<p>という感じですね。</p>
<h2 id="本題">本題</h2>
<p>では、タイトルにあるように“array_searchが全く見当違い(に見える)値を出力する”というのはどういうことか見て行きましょう。</p>
<pre><code>&lt;?php

function test() {
  // 'hoge'なんて引数の配列の中に存在しないのでfalseが返るよね！
  if (array_search('hoge', [1, 2, 3, 0])) {
    echo 'match!';
    return;
  }
  echo 'not match!';
}

test();
// =&gt; &quot;match!&quot;が出力される！！！</code></pre>
<p>何が起きているかわかりますかね。私は最初わかりませんでしたよ。ま、そもそも上記のように配列の中に値があるかどうか調べたい場合はin_arrayを使うべきではありますが、まぁ。</p>
<p>REPLを使ってもう少し詳しく確かめてみましょう(余談ですが、PHPのREPLとしては私はpsyshを使ってます。便利ですね。他の人のPC上で実施するときはphp -a使いますが、結構だるいですよね。)</p>
<pre><code>$ psysh
&gt;&gt;&gt; array_search('hoge', [1, 2, 3, 0])
=&gt; 3</code></pre>
<p>上記、なぜか3が出力されてますね。配列の中のインデックスが3の値は…0 !!!</p>
<p>はい、PHPによく慣れている方はもうわかったかもしれませんね。array_searchはデフォルトでは“==”による比較を行うため、‘hoge’ == 0の比較を行ってtrueになってしまったということだったのでした。ちょっとぎょっとしますよねこれは。</p>
<h2 id="解決策">解決策</h2>
<p>array_searchにはstrictフラグという、値の比較の際に型の一致(及びオブジェクトの一致)をチェックするフラグがあるのでそちらを使いましょう。</p>
<pre><code>$ psysh
// strictモードfalse(デフォルト値)版
&gt;&gt;&gt; array_search('hoge', [1, 2, 3, 0])
=&gt; 3
// strictモードfalseを明示的に指定版
&gt;&gt;&gt; array_search('hoge', [1, 2, 3, 0], false)
=&gt; 3
// strictモードtrue版
&gt;&gt;&gt; array_search('hoge', [1, 2, 3, 0], true)
=&gt; false
// やった！これからはちゃんとstrictにしよう！！！</code></pre>
<p>めでたしめでたしなのでしたー！！！</p>
<h2 id="本題とは関係ないけどarray_searchについて">本題とは関係ないけどarray_searchについて</h2>
<p>array_searchについて学んだついでに、上記の他に「array_searchのバグじゃないか」としてよく言われる挙動を見ておきましょう。</p>
<pre><code>&lt;?php

function test() {
  // 1は引数の配列の中に存在するし&quot;match&quot;が出力されるよね
  if (array_search(1, [1, 2, 3])) {
    echo 'match!';
    return;
  }
  echo 'not match!';
}

test();
// =&gt; &quot;not match!&quot;が出力される！！！</code></pre>
<p>上記、PHPによく慣れている方は、すぐに「あ、検索する値が配列の0番目にあったのでarray_searchの返り値が0になりfalse判定されたんですね」とわかるかと思います。 まぁ、こちらはわかりやすいですかね。PHPを書いていればあまりにも普通のことです。</p>
<p>ま、上記のようにマッチしているかどうかを取りたいだけなら問答無用でin_arrayを使えという話ではありますが(なお、in_arrayもstrictフラグを使わないとarray_searchと同様文字列が0にマッチしたりするので要注意です。)</p>
<h2 id="あとがき">あとがき</h2>
<p>PHPの曖昧さとうまく付き合っていく方法が未だによくわかっていない。というか、‘hoge’ == 0というのはあまりにも直感的じゃなさすぎてさすがに無理がある。‘1a’ == 1とかも まぁ、とにかく厳密にできるところは一歩ずつ厳密にしていきましょう。</p>
<p>あ、「来月結婚する」って書いたけど正確には入籍は一年くらい前に終わっていて、来月あるのは挙式です。</p>
<p>1年半前から毎月1記事は書こうと頑張っていたが結婚準備でかなりバタバタしており、「4月は頑張らないと」と思っていたのですが、まぁブログは予定通り書けてよかったです。</p>
<h2 id="このブログを140文字で伝えると">このブログを140文字で伝えると</h2>
<p>以下私のツイート</p>
<blockquote class="twitter-tweet" lang="ja"><p>
PHPの array_searchですが、返り値が0になりうるのでfalseと判定されて云々という話ばかりでてくるが本当にやばいのはheystackの中に0などが入っている時にneedleが文字列の場合ですよね。0でマッチしちゃう。strictフラグ立てましょう。
</p>
— でこくん (@dekokun) <a href="https://twitter.com/dekokun/statuses/460018910545203200">2014, 4月 26</a>
</blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>





<div id="disqus_thread"></div>
<script type="text/javascript">
    /* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */
    var disqus_shortname = 'dekokun'; // required: replace example with your forum shortname

    /* * * DON'T EDIT BELOW THIS LINE * * */
    (function() {
        var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
        dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js';
        (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
    })();
</script>
<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
<a href="http://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a>

          <ul class="social">
            <li class="kindle"><div class="kindleWidget"><img style="vertical-align:middle;" src="https://d1xnn692s7u6t6.cloudfront.net/white-15.png" /><span style="vertical-align:middle;margin-left:3px;">Send to Kindle</span></div></li>
            <li class="facebook"><div class="fb-like" data-send="false" data-layout="button_count" data-width="100" data-show-faces="true" data-font="arial"></div></li>
            <li class="twitter"><a href="https://twitter.com/share" class="twitter-share-button" data-via="dekokun" data-lang="ja">ツイート</a></li>
            <li class="hatena-bookmark"><a href="http://b.hatena.ne.jp/entry/" class="hatena-bookmark-button" data-hatena-bookmark-layout="standard" title="このエントリーをはてなブックマークに追加"><img src="http://b.st-hatena.com/images/entry-button/button-only.gif" alt="このエントリーをはてなブックマークに追加" width="20" height="20" style="border: none;"></a><script type="text/javascript" src="http://b.st-hatena.com/js/bookmark_button.js" charset="utf-8" async="async"></script></li>
            <li><a data-pocket-label="pocket" data-pocket-count="horizontal" class="pocket-btn" data-lang="en"></a>
            <script type="text/javascript">!function(d,i){if(!d.getElementById(i)){var j=d.createElement("script");j.id=i;j.src="https://widgets.getpocket.com/v1/j/btn.js?v=1";var w=d.getElementById(i);d.body.appendChild(j);}}(document,"pocket-btn-js");</script></li>
          </ul>

        </article>
        <aside class="span3">
          <div class="sidebar-module">
            <div class="title">プロフィール</div>
            <p class="id"><a href="https://twitter.com/dekokun">dekokun</a></p>
            <p><a href="https://twitter.com/dekokun"><img src="../img/dekokun.png" alt="dekokun"></a></p>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.io/";
              Hatena.BookmarkWidget.title = "人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 200;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.com/";
              Hatena.BookmarkWidget.title = "旧人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 0;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module visible-desktop">
            <div class="title">twitter</div>
            <a class="twitter-timeline" data-dnt="true" href="https://twitter.com/dekokun" data-widget-id="306408547573440513">@dekokun からのツイート</a>
            <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
          </div>
          <div class="sidebar-module hidden-phone">
            <div class="title">RSS</div>
            <p><a href="../rss.xml"><img src="../img/rss.gif" alt="rss"></a></p>
          </div>
        </aside> <!-- /span3 -->
      </div> <!-- /row -->
      <footer>
        <p>©<script type="text/javascript">$y=2012;$ny=new Date().getFullYear();document.write($ny>$y?$y+'-'+$ny:$y);</script> <a href="https://twitter.com/dekokun">dekokun</a></p>
      </footer>
    </div> <!-- /container -->

    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script>window.jQuery || document.write('<script src="../js/libs/jquery-1.7.2.min.js"><\/script>')</script>
    <!-- /ツイートボタン -->
  <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>

    <script src="../js/libs/bootstrap/bootstrap.min.js"></script>

    <script src="../js/script.js"></script>
    <script>
      var _gaq=[['_setAccount','UA-XXXXX-X'],['_trackPageview']];
      (function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
      g.src=('https:'==location.protocol?'//ssl':'//www')+'.google-analytics.com/ga.js';
      s.parentNode.insertBefore(g,s)}(document,'script'));
    </script>
    <!-- Code syntax highlight -->
    <script type="text/javascript" src="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.js"></script>
    <script type="text/javascript">
    $(function(){ 
        $('pre').css({
            'overflow-x': 'scroll',
            'background-color': '#f6f6f6',
            'border': '1px dotted #ccc',
            'padding': '0.8em'
        });
        $('pre code').addClass('prettyprint');
        prettyPrint();
    });
    </script>
    <script type="text/javascript" src="https://d1xnn692s7u6t6.cloudfront.net/widget.js"></script>
    <script type="text/javascript">(function k(){window.$SendToKindle&&window.$SendToKindle.Widget?$SendToKindle.Widget.init({"content":"article"}):setTimeout(k,500);})();</script>
  </body>
</html>
]]></description>
    <pubDate>No date found.</pubDate>
    <guid>http://dekokun.github.io/posts/2014-04-26.html</guid>
</item>
<item>
    <title>MySQL5.6.5からDATETIME型で行生成時刻と更新時刻を自動でセットすることができるようになりましたよ</title>
    <link>http://dekokun.github.io/posts/2014-05-31.html</link>
    <description><![CDATA[<!doctype html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7" lang="ja"> <![endif]-->
<!--[if IE 7]>    <html class="no-js lt-ie9 lt-ie8" lang="ja"> <![endif]-->
<!--[if IE 8]>    <html class="no-js lt-ie9" lang="ja"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="ja"> <!--<![endif]-->
  <head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# article: http://ogp.me/ns/article#">
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <title>MySQL5.6.5からDATETIME型で行生成時刻と更新時刻を自動でセットすることができるようになりましたよ</title>
    <meta name="description" content>
    <meta name="author" content>

    <meta name="viewport" content="width=device-width">
    <meta property="fb:app_id" content="351187098330864">
    <meta property="og:type" content="article">
    <meta property="og:image" content="http://dekokun.github.com/img/dekokun.png">
    <meta property="og:title" content="MySQL5.6.5からDATETIME型で行生成時刻と更新時刻を自動でセットすることができるようになりましたよ">
    <meta property="og:description" content="@dekokunの技術日記">
    <meta property="og:site_name" content="でこてっくろぐ">
    <meta name="twitter:widgets:csp" content="on">

    <link rel="stylesheet" href="../css/bootstrap.css">
    <link rel="stylesheet" href="../css/bootstrap-responsive.css">
    <link rel="stylesheet" href="../css/style.css">
    <style>
    body {
      padding-top: 60px;
      padding-bottom: 40px;
    }
    </style>
    <link href="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.css" type="text/css" rel="stylesheet">
    <script src="../js/libs/modernizr-2.5.3-respond-1.1.0.min.js"></script>
    <script>
      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

      ga('create', 'UA-39650556-1', 'auto');
      ga('send', 'pageview');
    </script>
  </head>
  <body>
  <!--[if lt IE 7]><p class=chromeframe>Your browser is <em>ancient!</em> <a href="http://browsehappy.com/">Upgrade to a different browser</a> or <a href="http://www.google.com/chromeframe/?redirect=true">install Google Chrome Frame</a> to experience this site.</p><![endif]-->
    <div id="fb-root"></div>
    <script>(function(d, s, id) {
      var js, fjs = d.getElementsByTagName(s)[0];
      if (d.getElementById(id)) return;
      js = d.createElement(s); js.id = id;
      js.src = "//connect.facebook.net/ja_JP/all.js#xfbml=1&appId=351187098330864";
      fjs.parentNode.insertBefore(js, fjs);
      }(document, 'script', 'facebook-jssdk'));
    </script>
    <header>
      <nav class="navbar navbar-fixed-top">
        <div class="navbar-inner">
          <div class="container">
            <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
            </a>
            <a class="brand" href="../index.html">でこてっくろぐ</a>
            <div class="nav-collapse">
              <ul class="nav">
                <li><a href="../index.html">ほーむ</a></li>
                <li><a href="../posts.html">あーかいぶ</a></li>
                <li><a href="../aboutme.html">あばうとみー</a></li>
              </ul>
            </div><!--/.nav-collapse -->
          </div>
        </div>
      </nav>
    </header>

    <div class="container">
      <div class="row">
        <article class="span9">
          <h1>MySQL5.6.5からDATETIME型で行生成時刻と更新時刻を自動でセットすることができるようになりましたよ</h1>

<p>by <em><a href="https://twitter.com/dekokun">@dekokun</a></em> on <strong>2014/05/31 20:46</strong></p>

<p>Tagged as: <a href="../tags/MySQL.html">MySQL</a>.</p>

<p>どうも。先日結婚式を挙げました。二次会のために手作りの巨大くす玉を作るノウハウを手に入れましたのでそのあたりもいずれブログに書きたいですね。</p>
<h2 id="概説">概説</h2>
<p>MySQL5.6.5から、DATETIME型でも行の生成時刻と更新時刻を自動更新できるようになりましたよ。</p>
<h2 id="方法">方法</h2>
<p>作成時刻は DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP で</p>
<p>更新時刻は DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP で宣言しましょう</p>
<p>参照：<a href="http://localhost/posts/2014-05-31.html">How do you set a default value for a MySQL Datetime column?</a></p>
<p>以下、MySQL5.6.17で検証</p>
<h3 id="テーブル生成">テーブル生成</h3>
<pre><code>mysql&gt; CREATE TABLE foo (
         `id` INT(11),
         `creation_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
         `modification_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
         PRIMARY KEY (id)
       );
Query OK, 0 rows affected (0.12 sec)</code></pre>
<h3 id="生成時刻自動挿入のテスト">生成時刻自動挿入のテスト</h3>
<pre><code>mysql&gt; insert into foo (id) VALUES (1);
Query OK, 1 row affected (0.00 sec)

mysql&gt; select * from foo;
+----+---------------------+---------------------+
| id | creation_time       | modification_time   |
+----+---------------------+---------------------+
|  1 | 2014-05-31 21:25:09 | 2014-05-31 21:25:09 |
+----+---------------------+---------------------+
1 row in set (0.00 sec)</code></pre>
<h3 id="更新時刻自動挿入のテスト">更新時刻自動挿入のテスト</h3>
<pre><code>mysql&gt; update foo set id = 2;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql&gt; select * from foo;
+----+---------------------+---------------------+
| id | creation_time       | modification_time   |
+----+---------------------+---------------------+
|  2 | 2014-05-31 21:25:09 | 2014-05-31 21:25:59 |
+----+---------------------+---------------------+
1 row in set (0.00 sec)</code></pre>
<h2 id="注意">注意</h2>
<p>この設定が性能面にどのような影響をあたえるかは検証しておりません。</p>
<p>あれ、以前MySQL5.6.13くらいで検証した時はDEFAULT CURRENT_TIMESTAMPを2カラムに設定できなかったような記憶があるが5.6.17ではできているな。</p>

<div id="disqus_thread"></div>
<script type="text/javascript">
    /* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */
    var disqus_shortname = 'dekokun'; // required: replace example with your forum shortname

    /* * * DON'T EDIT BELOW THIS LINE * * */
    (function() {
        var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
        dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js';
        (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
    })();
</script>
<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
<a href="http://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a>

          <ul class="social">
            <li class="kindle"><div class="kindleWidget"><img style="vertical-align:middle;" src="https://d1xnn692s7u6t6.cloudfront.net/white-15.png" /><span style="vertical-align:middle;margin-left:3px;">Send to Kindle</span></div></li>
            <li class="facebook"><div class="fb-like" data-send="false" data-layout="button_count" data-width="100" data-show-faces="true" data-font="arial"></div></li>
            <li class="twitter"><a href="https://twitter.com/share" class="twitter-share-button" data-via="dekokun" data-lang="ja">ツイート</a></li>
            <li class="hatena-bookmark"><a href="http://b.hatena.ne.jp/entry/" class="hatena-bookmark-button" data-hatena-bookmark-layout="standard" title="このエントリーをはてなブックマークに追加"><img src="http://b.st-hatena.com/images/entry-button/button-only.gif" alt="このエントリーをはてなブックマークに追加" width="20" height="20" style="border: none;"></a><script type="text/javascript" src="http://b.st-hatena.com/js/bookmark_button.js" charset="utf-8" async="async"></script></li>
            <li><a data-pocket-label="pocket" data-pocket-count="horizontal" class="pocket-btn" data-lang="en"></a>
            <script type="text/javascript">!function(d,i){if(!d.getElementById(i)){var j=d.createElement("script");j.id=i;j.src="https://widgets.getpocket.com/v1/j/btn.js?v=1";var w=d.getElementById(i);d.body.appendChild(j);}}(document,"pocket-btn-js");</script></li>
          </ul>

        </article>
        <aside class="span3">
          <div class="sidebar-module">
            <div class="title">プロフィール</div>
            <p class="id"><a href="https://twitter.com/dekokun">dekokun</a></p>
            <p><a href="https://twitter.com/dekokun"><img src="../img/dekokun.png" alt="dekokun"></a></p>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.io/";
              Hatena.BookmarkWidget.title = "人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 200;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.com/";
              Hatena.BookmarkWidget.title = "旧人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 0;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module visible-desktop">
            <div class="title">twitter</div>
            <a class="twitter-timeline" data-dnt="true" href="https://twitter.com/dekokun" data-widget-id="306408547573440513">@dekokun からのツイート</a>
            <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
          </div>
          <div class="sidebar-module hidden-phone">
            <div class="title">RSS</div>
            <p><a href="../rss.xml"><img src="../img/rss.gif" alt="rss"></a></p>
          </div>
        </aside> <!-- /span3 -->
      </div> <!-- /row -->
      <footer>
        <p>©<script type="text/javascript">$y=2012;$ny=new Date().getFullYear();document.write($ny>$y?$y+'-'+$ny:$y);</script> <a href="https://twitter.com/dekokun">dekokun</a></p>
      </footer>
    </div> <!-- /container -->

    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script>window.jQuery || document.write('<script src="../js/libs/jquery-1.7.2.min.js"><\/script>')</script>
    <!-- /ツイートボタン -->
  <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>

    <script src="../js/libs/bootstrap/bootstrap.min.js"></script>

    <script src="../js/script.js"></script>
    <script>
      var _gaq=[['_setAccount','UA-XXXXX-X'],['_trackPageview']];
      (function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
      g.src=('https:'==location.protocol?'//ssl':'//www')+'.google-analytics.com/ga.js';
      s.parentNode.insertBefore(g,s)}(document,'script'));
    </script>
    <!-- Code syntax highlight -->
    <script type="text/javascript" src="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.js"></script>
    <script type="text/javascript">
    $(function(){ 
        $('pre').css({
            'overflow-x': 'scroll',
            'background-color': '#f6f6f6',
            'border': '1px dotted #ccc',
            'padding': '0.8em'
        });
        $('pre code').addClass('prettyprint');
        prettyPrint();
    });
    </script>
    <script type="text/javascript" src="https://d1xnn692s7u6t6.cloudfront.net/widget.js"></script>
    <script type="text/javascript">(function k(){window.$SendToKindle&&window.$SendToKindle.Widget?$SendToKindle.Widget.init({"content":"article"}):setTimeout(k,500);})();</script>
  </body>
</html>
]]></description>
    <pubDate>No date found.</pubDate>
    <guid>http://dekokun.github.io/posts/2014-05-31.html</guid>
</item>
<item>
    <title>composer installをproduct環境で使う際はoptimize-autoloaderオプションを使おう</title>
    <link>http://dekokun.github.io/posts/2014-06-22.html</link>
    <description><![CDATA[<!doctype html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7" lang="ja"> <![endif]-->
<!--[if IE 7]>    <html class="no-js lt-ie9 lt-ie8" lang="ja"> <![endif]-->
<!--[if IE 8]>    <html class="no-js lt-ie9" lang="ja"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="ja"> <!--<![endif]-->
  <head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# article: http://ogp.me/ns/article#">
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <title>composer installをproduct環境で使う際はoptimize-autoloaderオプションを使おう</title>
    <meta name="description" content>
    <meta name="author" content>

    <meta name="viewport" content="width=device-width">
    <meta property="fb:app_id" content="351187098330864">
    <meta property="og:type" content="article">
    <meta property="og:image" content="http://dekokun.github.com/img/dekokun.png">
    <meta property="og:title" content="composer installをproduct環境で使う際はoptimize-autoloaderオプションを使おう">
    <meta property="og:description" content="@dekokunの技術日記">
    <meta property="og:site_name" content="でこてっくろぐ">
    <meta name="twitter:widgets:csp" content="on">

    <link rel="stylesheet" href="../css/bootstrap.css">
    <link rel="stylesheet" href="../css/bootstrap-responsive.css">
    <link rel="stylesheet" href="../css/style.css">
    <style>
    body {
      padding-top: 60px;
      padding-bottom: 40px;
    }
    </style>
    <link href="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.css" type="text/css" rel="stylesheet">
    <script src="../js/libs/modernizr-2.5.3-respond-1.1.0.min.js"></script>
    <script>
      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

      ga('create', 'UA-39650556-1', 'auto');
      ga('send', 'pageview');
    </script>
  </head>
  <body>
  <!--[if lt IE 7]><p class=chromeframe>Your browser is <em>ancient!</em> <a href="http://browsehappy.com/">Upgrade to a different browser</a> or <a href="http://www.google.com/chromeframe/?redirect=true">install Google Chrome Frame</a> to experience this site.</p><![endif]-->
    <div id="fb-root"></div>
    <script>(function(d, s, id) {
      var js, fjs = d.getElementsByTagName(s)[0];
      if (d.getElementById(id)) return;
      js = d.createElement(s); js.id = id;
      js.src = "//connect.facebook.net/ja_JP/all.js#xfbml=1&appId=351187098330864";
      fjs.parentNode.insertBefore(js, fjs);
      }(document, 'script', 'facebook-jssdk'));
    </script>
    <header>
      <nav class="navbar navbar-fixed-top">
        <div class="navbar-inner">
          <div class="container">
            <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
            </a>
            <a class="brand" href="../index.html">でこてっくろぐ</a>
            <div class="nav-collapse">
              <ul class="nav">
                <li><a href="../index.html">ほーむ</a></li>
                <li><a href="../posts.html">あーかいぶ</a></li>
                <li><a href="../aboutme.html">あばうとみー</a></li>
              </ul>
            </div><!--/.nav-collapse -->
          </div>
        </div>
      </nav>
    </header>

    <div class="container">
      <div class="row">
        <article class="span9">
          <h1>composer installをproduct環境で使う際はoptimize-autoloaderオプションを使おう</h1>

<p>by <em><a href="https://twitter.com/dekokun">@dekokun</a></em> on <strong>2014/06/22 23:34</strong></p>

<p>Tagged as: <a href="../tags/PHP.html">PHP</a>, <a href="../tags/composer.html">composer</a>.</p>

<h2 id="概要">概要</h2>
<p>composer installには–optimize-autoloaderオプションつけたほうが若干アプリケーションの性能が上がるよ。 もしくは、composer installした後にcomposer dumpautoload -oするか。</p>
<h2 id="なぜか">なぜか</h2>
<p>composerが自動生成するautoloaderは、以下の順番でクラスファイルを探していくんですね。</p>
<ol style="list-style-type: decimal">
<li>vendor/composer/autoload_classmap.php(以下、classmapファイルと記載)ファイルの中にクラス及びそのファイルの定義があればそのファイルをinclude</li>
<li>上記なければそのファイルをまぁいろいろ検索してファイルの存在まで確認して存在すればinclude</li>
</ol>
<p>というわけでclassmapファイルにいろいろ書いてあるとファイルの検索部分が省略され基本的に高速化される模様なのですが、classmapファイルは、普通にcomposer installを行っただけでは空の配列を返す感じになっているのです。</p>
<p>以下のような感じです。</p>
<pre><code>&lt;?php

// autoload_classmap.php @generated by Composer

$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);

return array(
);</code></pre>
<p>ではどうすればいいかというと、表題のようにcomposer install時に –optimize-autoloaderオプションをつければいいのです。つけると以下のように、クラス名とファイル名を対応させる記述が増えます。</p>
<pre><code>&lt;?php

// autoload_classmap.php @generated by Composer

$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);

return array(
    'Acme\\DemoBundle\\AcmeDemoBundle' =&gt; $baseDir . '/src/Acme/DemoBundle/AcmeDemoBundle.php',
    'Acme\\DemoBundle\\Command\\HelloWorldCommand' =&gt; $baseDir . '/src/Acme/DemoBundle/Command/HelloWorldCommand.php',
    'Acme\\DemoBundle\\Controller\\DemoController' =&gt; $baseDir . '/src/Acme/DemoBundle/Controller/DemoController.php',
    'Acme\\DemoBundle\\Controller\\SecuredController' =&gt; $baseDir . '/src/Acme/DemoBundle/Controller/SecuredController.php',
    'Acme\\DemoBundle\\Controller\\WelcomeController' =&gt; $baseDir . '/src/Acme/DemoBundle/Controller/WelcomeController.php',
    'Acme\\DemoBundle\\DependencyInjection\\AcmeDemoExtension' =&gt; $baseDir . '/src/Acme/DemoBundle/DependencyInjection/AcmeDemoExtension.php',

    ...以下略 なお、こちらはSymfonyの初期状態でテストしています</code></pre>
<h2 id="実際の効果">実際の効果</h2>
<ul>
<li>上記最適化を行うことでMoufというフレームワークでhello worldするWebアプリのレスポンスが37%早くなったという話
<ul>
<li><a href="http://mouf-php.com/optimizing-composer-autoloader-performance">Optimizing Composer’s autoloader performance</a></li>
</ul></li>
</ul>
<p>実際に自分でもやってみました。</p>
<ul>
<li>OS: Mac</li>
<li>言語: PHP5.5</li>
<li>Web server: PHPのビルトインサーバ</li>
<li>Apache Bench: Mac上から自分自身に対してApache Bench実施</li>
</ul>
<p>クラスファイルを1万ほど生成し(参考までに、素のSymfonyをインストールした際にvendorディレクトリ以下は6000ファイルほどとなっています)、そのクラスのスタティックメソッドをひたすら呼び出すアプリケーションを作ってApache Benchをかけてみました。 (もろもろキャッシュに載せた結果を確認するため、2回同じことを行い、2回目の結果を採用しています)</p>
<pre><code>composer install 
Time per request:       788.825 [ms] (mean)

composer install --optimize-autoloader
Time per request:       731.721 [ms] (mean)</code></pre>
<p>はい、少し早くなりましたね。</p>
<p>何回かやりましたが全部こんなかんじでしたので、まぁある程度正しいんでしょうが、かなり適当に計測しているというのはご了承ください。</p>
<p>なお、2014/06/23時点で、Composerが生成するautoloaderにおいてクラス名の最初の一文字というのは非常に重要(クラス名の一文字目を検索の最初のフィルタリングのキーとして使っている)なのですが、今回全てTestから始まるクラス名だったため、あまりにもこの計測は実態から乖離しまくっているなとは思いました。</p>
<h2 id="結論">結論</h2>
<p>composer install –optimize-autoloader をしよう ただ、まぁ、若干composer installにかかる時間が長くなる</p>
<h2 id="自分が行ったテストについて">自分が行ったテストについて</h2>
<p>Apache Benchとサーバを同じPC上で行っていたり、100リクエスト程度しかしてなかったり、まぁかなり適当な感じのテストではある。</p>
<p>アプリケーションは以下。</p>
<pre><code>&lt;?php

require_once __DIR__ . '/../vendor/autoload.php';

for($i = 1; $i &lt; 10000; $i++) {
  $className = &quot;Test&quot; . $i;
  $a = $className::hoge();
}

echo 'hoge';</code></pre>
<p>composer.json</p>
<pre><code>{
    &quot;name&quot;: &quot;dekokun/hoge&quot;,
    &quot;description&quot;: &quot;hoge demo&quot;,
    &quot;repositories&quot;: [
    ],
    &quot;autoload&quot;: {
        &quot;psr-0&quot;: {&quot;&quot;: &quot;lib&quot;}
    }
}</code></pre>
<p>libディレクトリの下は以下</p>
<pre><code>$ ll | more
total 80016
-rw-r--r--  1 dekokun  staff    71B  6 22 23:14 Test1.php
-rw-r--r--  1 dekokun  staff    72B  6 22 23:14 Test10.php
-rw-r--r--  1 dekokun  staff    73B  6 22 23:14 Test100.php
-rw-r--r--  1 dekokun  staff    74B  6 22 23:14 Test1000.php
…以下略</code></pre>
<p>各クラスファイルは以下</p>
<pre><code>&lt;?php

class Test1 {
  static function hoge()
  {
    return 1;
  }
}</code></pre>

<div id="disqus_thread"></div>
<script type="text/javascript">
    /* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */
    var disqus_shortname = 'dekokun'; // required: replace example with your forum shortname

    /* * * DON'T EDIT BELOW THIS LINE * * */
    (function() {
        var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
        dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js';
        (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
    })();
</script>
<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
<a href="http://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a>

          <ul class="social">
            <li class="kindle"><div class="kindleWidget"><img style="vertical-align:middle;" src="https://d1xnn692s7u6t6.cloudfront.net/white-15.png" /><span style="vertical-align:middle;margin-left:3px;">Send to Kindle</span></div></li>
            <li class="facebook"><div class="fb-like" data-send="false" data-layout="button_count" data-width="100" data-show-faces="true" data-font="arial"></div></li>
            <li class="twitter"><a href="https://twitter.com/share" class="twitter-share-button" data-via="dekokun" data-lang="ja">ツイート</a></li>
            <li class="hatena-bookmark"><a href="http://b.hatena.ne.jp/entry/" class="hatena-bookmark-button" data-hatena-bookmark-layout="standard" title="このエントリーをはてなブックマークに追加"><img src="http://b.st-hatena.com/images/entry-button/button-only.gif" alt="このエントリーをはてなブックマークに追加" width="20" height="20" style="border: none;"></a><script type="text/javascript" src="http://b.st-hatena.com/js/bookmark_button.js" charset="utf-8" async="async"></script></li>
            <li><a data-pocket-label="pocket" data-pocket-count="horizontal" class="pocket-btn" data-lang="en"></a>
            <script type="text/javascript">!function(d,i){if(!d.getElementById(i)){var j=d.createElement("script");j.id=i;j.src="https://widgets.getpocket.com/v1/j/btn.js?v=1";var w=d.getElementById(i);d.body.appendChild(j);}}(document,"pocket-btn-js");</script></li>
          </ul>

        </article>
        <aside class="span3">
          <div class="sidebar-module">
            <div class="title">プロフィール</div>
            <p class="id"><a href="https://twitter.com/dekokun">dekokun</a></p>
            <p><a href="https://twitter.com/dekokun"><img src="../img/dekokun.png" alt="dekokun"></a></p>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.io/";
              Hatena.BookmarkWidget.title = "人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 200;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.com/";
              Hatena.BookmarkWidget.title = "旧人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 0;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module visible-desktop">
            <div class="title">twitter</div>
            <a class="twitter-timeline" data-dnt="true" href="https://twitter.com/dekokun" data-widget-id="306408547573440513">@dekokun からのツイート</a>
            <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
          </div>
          <div class="sidebar-module hidden-phone">
            <div class="title">RSS</div>
            <p><a href="../rss.xml"><img src="../img/rss.gif" alt="rss"></a></p>
          </div>
        </aside> <!-- /span3 -->
      </div> <!-- /row -->
      <footer>
        <p>©<script type="text/javascript">$y=2012;$ny=new Date().getFullYear();document.write($ny>$y?$y+'-'+$ny:$y);</script> <a href="https://twitter.com/dekokun">dekokun</a></p>
      </footer>
    </div> <!-- /container -->

    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script>window.jQuery || document.write('<script src="../js/libs/jquery-1.7.2.min.js"><\/script>')</script>
    <!-- /ツイートボタン -->
  <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>

    <script src="../js/libs/bootstrap/bootstrap.min.js"></script>

    <script src="../js/script.js"></script>
    <script>
      var _gaq=[['_setAccount','UA-XXXXX-X'],['_trackPageview']];
      (function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
      g.src=('https:'==location.protocol?'//ssl':'//www')+'.google-analytics.com/ga.js';
      s.parentNode.insertBefore(g,s)}(document,'script'));
    </script>
    <!-- Code syntax highlight -->
    <script type="text/javascript" src="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.js"></script>
    <script type="text/javascript">
    $(function(){ 
        $('pre').css({
            'overflow-x': 'scroll',
            'background-color': '#f6f6f6',
            'border': '1px dotted #ccc',
            'padding': '0.8em'
        });
        $('pre code').addClass('prettyprint');
        prettyPrint();
    });
    </script>
    <script type="text/javascript" src="https://d1xnn692s7u6t6.cloudfront.net/widget.js"></script>
    <script type="text/javascript">(function k(){window.$SendToKindle&&window.$SendToKindle.Widget?$SendToKindle.Widget.init({"content":"article"}):setTimeout(k,500);})();</script>
  </body>
</html>
]]></description>
    <pubDate>No date found.</pubDate>
    <guid>http://dekokun.github.io/posts/2014-06-22.html</guid>
</item>
<item>
    <title>xhprofって実行時間だけじゃなくてメモリとかCPU使用率のプロファイリングとかもしてくれるんだね知らなかった</title>
    <link>http://dekokun.github.io/posts/2014-07-01.html</link>
    <description><![CDATA[<!doctype html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7" lang="ja"> <![endif]-->
<!--[if IE 7]>    <html class="no-js lt-ie9 lt-ie8" lang="ja"> <![endif]-->
<!--[if IE 8]>    <html class="no-js lt-ie9" lang="ja"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="ja"> <!--<![endif]-->
  <head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# article: http://ogp.me/ns/article#">
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <title>xhprofって実行時間だけじゃなくてメモリとかCPU使用率のプロファイリングとかもしてくれるんだね知らなかった</title>
    <meta name="description" content>
    <meta name="author" content>

    <meta name="viewport" content="width=device-width">
    <meta property="fb:app_id" content="351187098330864">
    <meta property="og:type" content="article">
    <meta property="og:image" content="http://dekokun.github.com/img/dekokun.png">
    <meta property="og:title" content="xhprofって実行時間だけじゃなくてメモリとかCPU使用率のプロファイリングとかもしてくれるんだね知らなかった">
    <meta property="og:description" content="@dekokunの技術日記">
    <meta property="og:site_name" content="でこてっくろぐ">
    <meta name="twitter:widgets:csp" content="on">

    <link rel="stylesheet" href="../css/bootstrap.css">
    <link rel="stylesheet" href="../css/bootstrap-responsive.css">
    <link rel="stylesheet" href="../css/style.css">
    <style>
    body {
      padding-top: 60px;
      padding-bottom: 40px;
    }
    </style>
    <link href="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.css" type="text/css" rel="stylesheet">
    <script src="../js/libs/modernizr-2.5.3-respond-1.1.0.min.js"></script>
    <script>
      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

      ga('create', 'UA-39650556-1', 'auto');
      ga('send', 'pageview');
    </script>
  </head>
  <body>
  <!--[if lt IE 7]><p class=chromeframe>Your browser is <em>ancient!</em> <a href="http://browsehappy.com/">Upgrade to a different browser</a> or <a href="http://www.google.com/chromeframe/?redirect=true">install Google Chrome Frame</a> to experience this site.</p><![endif]-->
    <div id="fb-root"></div>
    <script>(function(d, s, id) {
      var js, fjs = d.getElementsByTagName(s)[0];
      if (d.getElementById(id)) return;
      js = d.createElement(s); js.id = id;
      js.src = "//connect.facebook.net/ja_JP/all.js#xfbml=1&appId=351187098330864";
      fjs.parentNode.insertBefore(js, fjs);
      }(document, 'script', 'facebook-jssdk'));
    </script>
    <header>
      <nav class="navbar navbar-fixed-top">
        <div class="navbar-inner">
          <div class="container">
            <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
            </a>
            <a class="brand" href="../index.html">でこてっくろぐ</a>
            <div class="nav-collapse">
              <ul class="nav">
                <li><a href="../index.html">ほーむ</a></li>
                <li><a href="../posts.html">あーかいぶ</a></li>
                <li><a href="../aboutme.html">あばうとみー</a></li>
              </ul>
            </div><!--/.nav-collapse -->
          </div>
        </div>
      </nav>
    </header>

    <div class="container">
      <div class="row">
        <article class="span9">
          <h1>xhprofって実行時間だけじゃなくてメモリとかCPU使用率のプロファイリングとかもしてくれるんだね知らなかった</h1>

<p>by <em><a href="https://twitter.com/dekokun">@dekokun</a></em> on <strong>2014/07/01 00:28</strong></p>

<p>Tagged as: <a href="../tags/PHP.html">PHP</a>, <a href="../tags/xhprof.html">xhprof</a>.</p>

<h2 id="概要">概要</h2>
<p>xhprof_enable関数の引数にいろいろ指定できた</p>
<h2 id="詳細">詳細</h2>
<p>xhprof_enableの引数に、XHPROF_FLAGS_NO_BUILTINS | XHPROF_FLAGS_CPU | XHPROF_FLAGS_MEMORYとか指定してあげて色々動きが変わる</p>
<ul>
<li>XHPROF_FLAGS_NO_BUILTINSは、ビルトイン関数がプロファイルに出力されない</li>
<li>XHPROF_FLAGS_CPUは、CPU使用率のプロファイルが出力される
<ul>
<li>どうやって計測しているんだろうか</li>
<li>DBにクエリを投げたりするメソッドはやはりTimeが高くてもこの値は低くなったりするんだろうなぁ。検証が必要</li>
</ul></li>
<li>XHPROF_FLAGS_MEMORYは、メモリ使用率のプロファイルが出力される
<ul>
<li>こちらは、メソッド呼び出し前後のメモリ使用量を測定して計算しているということかな？</li>
</ul></li>
</ul>
<p>なお、第二引数で、無視する関数を指定したりできるらしい。</p>
<p>詳細は以下</p>
<p><a href="http://www.php.net/manual/ja/function.xhprof-enable.php">xhprof_enable</a></p>
<h3 id="xhprof_flags_no_builtinsの効果">XHPROF_FLAGS_NO_BUILTINSの効果</h3>
<p>before (ビルトイン関数のfile_existsがグラフに出てきていますね)</p>
<div class="figure">
<img src="../img/2014-07-01-file_exists-before.png" alt="XHPROF_FLAGS_NO_BUILTINS前" /><p class="caption">XHPROF_FLAGS_NO_BUILTINS前</p>
</div>
<p>after(ビルトイン関数のfile_existsがグラフに出てこなくなりました)</p>
<div class="figure">
<img src="../img/2014-07-01-file_exists-after.png" alt="XHPROF_FLAGS_NO_BUILTINS後" /><p class="caption">XHPROF_FLAGS_NO_BUILTINS後</p>
</div>
<h3 id="xhprof_flags_cpu-xhprof_flags_memoryの効果">XHPROF_FLAGS_CPU | XHPROF_FLAGS_MEMORYの効果</h3>
<p>before(まぁ、よく見る普通の光景)</p>
<div class="figure">
<img src="../img/2014-07-01-memory-cpu-before.png" alt="XHPROF_FLAGS_CPU | XHPROF_FLAGS_MEMORY前" /><p class="caption">XHPROF_FLAGS_CPU | XHPROF_FLAGS_MEMORY前</p>
</div>
<p>after(カラムがゴサっと色々増えた！！)</p>
<div class="figure">
<img src="../img/2014-07-01-memory-cpu-after.png" alt="XHPROF_FLAGS_CPU | XHPROF_FLAGS_MEMORY後" /><p class="caption">XHPROF_FLAGS_CPU | XHPROF_FLAGS_MEMORY後</p>
</div>
<h2 id="雑談">雑談</h2>
<p>これまでxhprofは実行時間の計測のためだけに使っていた(というか、他も計測できるの知らなかった)のですが、マニュアル見たらそれだけじゃなかったのでビビってやってみたらいろいろでてきた。ビビった。</p>
<p>ただ、CPUのプロファイルの部分など、もうちょっと検証は必要。</p>
<blockquote class="twitter-tweet" lang="ja"><p>
getrusageで使用するユーザー時間がとれるからそこからCPUの部分を取得している感じなのかな。
</p>
— でこくん (@dekokun) <a href="https://twitter.com/dekokun/statuses/483646255055110145">2014, 6月 30</a>
</blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>

<p>このブログで画像をちゃんと管理するために久しぶりにHaskell書いた(コピペ)</p>

<div id="disqus_thread"></div>
<script type="text/javascript">
    /* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */
    var disqus_shortname = 'dekokun'; // required: replace example with your forum shortname

    /* * * DON'T EDIT BELOW THIS LINE * * */
    (function() {
        var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
        dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js';
        (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
    })();
</script>
<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
<a href="http://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a>

          <ul class="social">
            <li class="kindle"><div class="kindleWidget"><img style="vertical-align:middle;" src="https://d1xnn692s7u6t6.cloudfront.net/white-15.png" /><span style="vertical-align:middle;margin-left:3px;">Send to Kindle</span></div></li>
            <li class="facebook"><div class="fb-like" data-send="false" data-layout="button_count" data-width="100" data-show-faces="true" data-font="arial"></div></li>
            <li class="twitter"><a href="https://twitter.com/share" class="twitter-share-button" data-via="dekokun" data-lang="ja">ツイート</a></li>
            <li class="hatena-bookmark"><a href="http://b.hatena.ne.jp/entry/" class="hatena-bookmark-button" data-hatena-bookmark-layout="standard" title="このエントリーをはてなブックマークに追加"><img src="http://b.st-hatena.com/images/entry-button/button-only.gif" alt="このエントリーをはてなブックマークに追加" width="20" height="20" style="border: none;"></a><script type="text/javascript" src="http://b.st-hatena.com/js/bookmark_button.js" charset="utf-8" async="async"></script></li>
            <li><a data-pocket-label="pocket" data-pocket-count="horizontal" class="pocket-btn" data-lang="en"></a>
            <script type="text/javascript">!function(d,i){if(!d.getElementById(i)){var j=d.createElement("script");j.id=i;j.src="https://widgets.getpocket.com/v1/j/btn.js?v=1";var w=d.getElementById(i);d.body.appendChild(j);}}(document,"pocket-btn-js");</script></li>
          </ul>

        </article>
        <aside class="span3">
          <div class="sidebar-module">
            <div class="title">プロフィール</div>
            <p class="id"><a href="https://twitter.com/dekokun">dekokun</a></p>
            <p><a href="https://twitter.com/dekokun"><img src="../img/dekokun.png" alt="dekokun"></a></p>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.io/";
              Hatena.BookmarkWidget.title = "人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 200;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.com/";
              Hatena.BookmarkWidget.title = "旧人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 0;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module visible-desktop">
            <div class="title">twitter</div>
            <a class="twitter-timeline" data-dnt="true" href="https://twitter.com/dekokun" data-widget-id="306408547573440513">@dekokun からのツイート</a>
            <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
          </div>
          <div class="sidebar-module hidden-phone">
            <div class="title">RSS</div>
            <p><a href="../rss.xml"><img src="../img/rss.gif" alt="rss"></a></p>
          </div>
        </aside> <!-- /span3 -->
      </div> <!-- /row -->
      <footer>
        <p>©<script type="text/javascript">$y=2012;$ny=new Date().getFullYear();document.write($ny>$y?$y+'-'+$ny:$y);</script> <a href="https://twitter.com/dekokun">dekokun</a></p>
      </footer>
    </div> <!-- /container -->

    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script>window.jQuery || document.write('<script src="../js/libs/jquery-1.7.2.min.js"><\/script>')</script>
    <!-- /ツイートボタン -->
  <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>

    <script src="../js/libs/bootstrap/bootstrap.min.js"></script>

    <script src="../js/script.js"></script>
    <script>
      var _gaq=[['_setAccount','UA-XXXXX-X'],['_trackPageview']];
      (function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
      g.src=('https:'==location.protocol?'//ssl':'//www')+'.google-analytics.com/ga.js';
      s.parentNode.insertBefore(g,s)}(document,'script'));
    </script>
    <!-- Code syntax highlight -->
    <script type="text/javascript" src="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.js"></script>
    <script type="text/javascript">
    $(function(){ 
        $('pre').css({
            'overflow-x': 'scroll',
            'background-color': '#f6f6f6',
            'border': '1px dotted #ccc',
            'padding': '0.8em'
        });
        $('pre code').addClass('prettyprint');
        prettyPrint();
    });
    </script>
    <script type="text/javascript" src="https://d1xnn692s7u6t6.cloudfront.net/widget.js"></script>
    <script type="text/javascript">(function k(){window.$SendToKindle&&window.$SendToKindle.Widget?$SendToKindle.Widget.init({"content":"article"}):setTimeout(k,500);})();</script>
  </body>
</html>
]]></description>
    <pubDate>No date found.</pubDate>
    <guid>http://dekokun.github.io/posts/2014-07-01.html</guid>
</item>
<item>
    <title>PHPにおけるタイプヒンティングでのClosureとcallableの違い</title>
    <link>http://dekokun.github.io/posts/2014-07-25-2.html</link>
    <description><![CDATA[<!doctype html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7" lang="ja"> <![endif]-->
<!--[if IE 7]>    <html class="no-js lt-ie9 lt-ie8" lang="ja"> <![endif]-->
<!--[if IE 8]>    <html class="no-js lt-ie9" lang="ja"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="ja"> <!--<![endif]-->
  <head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# article: http://ogp.me/ns/article#">
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <title>PHPにおけるタイプヒンティングでのClosureとcallableの違い</title>
    <meta name="description" content>
    <meta name="author" content>

    <meta name="viewport" content="width=device-width">
    <meta property="fb:app_id" content="351187098330864">
    <meta property="og:type" content="article">
    <meta property="og:image" content="http://dekokun.github.com/img/dekokun.png">
    <meta property="og:title" content="PHPにおけるタイプヒンティングでのClosureとcallableの違い">
    <meta property="og:description" content="@dekokunの技術日記">
    <meta property="og:site_name" content="でこてっくろぐ">
    <meta name="twitter:widgets:csp" content="on">

    <link rel="stylesheet" href="../css/bootstrap.css">
    <link rel="stylesheet" href="../css/bootstrap-responsive.css">
    <link rel="stylesheet" href="../css/style.css">
    <style>
    body {
      padding-top: 60px;
      padding-bottom: 40px;
    }
    </style>
    <link href="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.css" type="text/css" rel="stylesheet">
    <script src="../js/libs/modernizr-2.5.3-respond-1.1.0.min.js"></script>
    <script>
      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

      ga('create', 'UA-39650556-1', 'auto');
      ga('send', 'pageview');
    </script>
  </head>
  <body>
  <!--[if lt IE 7]><p class=chromeframe>Your browser is <em>ancient!</em> <a href="http://browsehappy.com/">Upgrade to a different browser</a> or <a href="http://www.google.com/chromeframe/?redirect=true">install Google Chrome Frame</a> to experience this site.</p><![endif]-->
    <div id="fb-root"></div>
    <script>(function(d, s, id) {
      var js, fjs = d.getElementsByTagName(s)[0];
      if (d.getElementById(id)) return;
      js = d.createElement(s); js.id = id;
      js.src = "//connect.facebook.net/ja_JP/all.js#xfbml=1&appId=351187098330864";
      fjs.parentNode.insertBefore(js, fjs);
      }(document, 'script', 'facebook-jssdk'));
    </script>
    <header>
      <nav class="navbar navbar-fixed-top">
        <div class="navbar-inner">
          <div class="container">
            <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
            </a>
            <a class="brand" href="../index.html">でこてっくろぐ</a>
            <div class="nav-collapse">
              <ul class="nav">
                <li><a href="../index.html">ほーむ</a></li>
                <li><a href="../posts.html">あーかいぶ</a></li>
                <li><a href="../aboutme.html">あばうとみー</a></li>
              </ul>
            </div><!--/.nav-collapse -->
          </div>
        </div>
      </nav>
    </header>

    <div class="container">
      <div class="row">
        <article class="span9">
          <h1>PHPにおけるタイプヒンティングでのClosureとcallableの違い</h1>

<p>by <em><a href="https://twitter.com/dekokun">@dekokun</a></em> on <strong>2014/07/25 00:26</strong></p>

<p>Tagged as: <a href="../tags/PHP.html">PHP</a>, <a href="../tags/タイプヒンティング.html">タイプヒンティング</a>.</p>

<h2 id="概要">概要</h2>
<p>Closureとcallable、どちらも無名関数に使えるタイプヒンティングなのですが、callableは無名関数以外でも関数名とかでもいけるけどClosureはそういうのいけないよという話。</p>
<p>@do_aki氏に感謝</p>
<h2 id="詳細">詳細</h2>
<blockquote class="twitter-tweet" lang="ja"><p>
PHPのタイプヒンティングで。
</p>
— でこくん (@dekokun) <a href="https://twitter.com/dekokun/statuses/491446139527233536">2014, 7月 22</a>
</blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
<blockquote class="twitter-tweet" lang="ja"><p>
<a href="https://twitter.com/dekokun">@dekokun</a> 5.5 あたりから、Closure ベースで良いよって事になってたはず。
</p>
— どぅーあき (@do_aki) <a href="https://twitter.com/do_aki/statuses/491447179337150465">2014, 7月 22</a>
</blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
<blockquote class="twitter-tweet" lang="ja"><p>
<a href="https://twitter.com/dekokun">@dekokun</a> <a href="http://t.co/mZdkKiY3EH">http://t.co/mZdkKiY3EH</a>
</p>
— どぅーあき (@do_aki) <a href="https://twitter.com/do_aki/statuses/491447723892015106">2014, 7月 22</a>
</blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
<blockquote class="twitter-tweet" lang="ja"><p>
<a href="https://twitter.com/dekokun">@dekokun</a> うんにゃ。 callable だと、文字列(関数名)や array (クラス名/インスタンスとメソッド名) も受け付けるよ。
</p>
— どぅーあき (@do_aki) <a href="https://twitter.com/do_aki/statuses/491468144959975424">2014, 7月 22</a>
</blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>


<pre><code>&lt;?php

function callableTest(callable $func) {
}
function closureTest(\Closure $func) {
}

callableTest('printf'); // 問題なし
// closureTest('printf'); // PHP Catchable fatal error:  Argument 1 passed to closureTest() must be an instance of Closure, string given

class Hoge {
  public function hoge() {
  }
}

$hoge = new Hoge();

callableTest([$hoge, 'hoge']); // 問題なし
// closureTest([$hoge, 'hoge']); // PHP Catchable fatal error:  Argument 1 passed to closureTest() must be an instance of Closure, array given,

callableTest(function() {}); // 問題なし
closureTest(function() {}); // 問題なし</code></pre>
<h2 id="あとがき">あとがき</h2>
<p>@do_akiさんありがとう</p>
<p>Twitterさんありがとう</p>

<div id="disqus_thread"></div>
<script type="text/javascript">
    /* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */
    var disqus_shortname = 'dekokun'; // required: replace example with your forum shortname

    /* * * DON'T EDIT BELOW THIS LINE * * */
    (function() {
        var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
        dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js';
        (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
    })();
</script>
<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
<a href="http://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a>

          <ul class="social">
            <li class="kindle"><div class="kindleWidget"><img style="vertical-align:middle;" src="https://d1xnn692s7u6t6.cloudfront.net/white-15.png" /><span style="vertical-align:middle;margin-left:3px;">Send to Kindle</span></div></li>
            <li class="facebook"><div class="fb-like" data-send="false" data-layout="button_count" data-width="100" data-show-faces="true" data-font="arial"></div></li>
            <li class="twitter"><a href="https://twitter.com/share" class="twitter-share-button" data-via="dekokun" data-lang="ja">ツイート</a></li>
            <li class="hatena-bookmark"><a href="http://b.hatena.ne.jp/entry/" class="hatena-bookmark-button" data-hatena-bookmark-layout="standard" title="このエントリーをはてなブックマークに追加"><img src="http://b.st-hatena.com/images/entry-button/button-only.gif" alt="このエントリーをはてなブックマークに追加" width="20" height="20" style="border: none;"></a><script type="text/javascript" src="http://b.st-hatena.com/js/bookmark_button.js" charset="utf-8" async="async"></script></li>
            <li><a data-pocket-label="pocket" data-pocket-count="horizontal" class="pocket-btn" data-lang="en"></a>
            <script type="text/javascript">!function(d,i){if(!d.getElementById(i)){var j=d.createElement("script");j.id=i;j.src="https://widgets.getpocket.com/v1/j/btn.js?v=1";var w=d.getElementById(i);d.body.appendChild(j);}}(document,"pocket-btn-js");</script></li>
          </ul>

        </article>
        <aside class="span3">
          <div class="sidebar-module">
            <div class="title">プロフィール</div>
            <p class="id"><a href="https://twitter.com/dekokun">dekokun</a></p>
            <p><a href="https://twitter.com/dekokun"><img src="../img/dekokun.png" alt="dekokun"></a></p>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.io/";
              Hatena.BookmarkWidget.title = "人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 200;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.com/";
              Hatena.BookmarkWidget.title = "旧人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 0;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module visible-desktop">
            <div class="title">twitter</div>
            <a class="twitter-timeline" data-dnt="true" href="https://twitter.com/dekokun" data-widget-id="306408547573440513">@dekokun からのツイート</a>
            <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
          </div>
          <div class="sidebar-module hidden-phone">
            <div class="title">RSS</div>
            <p><a href="../rss.xml"><img src="../img/rss.gif" alt="rss"></a></p>
          </div>
        </aside> <!-- /span3 -->
      </div> <!-- /row -->
      <footer>
        <p>©<script type="text/javascript">$y=2012;$ny=new Date().getFullYear();document.write($ny>$y?$y+'-'+$ny:$y);</script> <a href="https://twitter.com/dekokun">dekokun</a></p>
      </footer>
    </div> <!-- /container -->

    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script>window.jQuery || document.write('<script src="../js/libs/jquery-1.7.2.min.js"><\/script>')</script>
    <!-- /ツイートボタン -->
  <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>

    <script src="../js/libs/bootstrap/bootstrap.min.js"></script>

    <script src="../js/script.js"></script>
    <script>
      var _gaq=[['_setAccount','UA-XXXXX-X'],['_trackPageview']];
      (function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
      g.src=('https:'==location.protocol?'//ssl':'//www')+'.google-analytics.com/ga.js';
      s.parentNode.insertBefore(g,s)}(document,'script'));
    </script>
    <!-- Code syntax highlight -->
    <script type="text/javascript" src="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.js"></script>
    <script type="text/javascript">
    $(function(){ 
        $('pre').css({
            'overflow-x': 'scroll',
            'background-color': '#f6f6f6',
            'border': '1px dotted #ccc',
            'padding': '0.8em'
        });
        $('pre code').addClass('prettyprint');
        prettyPrint();
    });
    </script>
    <script type="text/javascript" src="https://d1xnn692s7u6t6.cloudfront.net/widget.js"></script>
    <script type="text/javascript">(function k(){window.$SendToKindle&&window.$SendToKindle.Widget?$SendToKindle.Widget.init({"content":"article"}):setTimeout(k,500);})();</script>
  </body>
</html>
]]></description>
    <pubDate>Fri, 25 Jul 2014 00:00:00 UT</pubDate>
    <guid>http://dekokun.github.io/posts/2014-07-25-2.html</guid>
</item>
<item>
    <title>FuelPHPの脆弱性への攻撃を再現出来たけど公開していいものなんだっけ</title>
    <link>http://dekokun.github.io/posts/2014-07-25.html</link>
    <description><![CDATA[<!doctype html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7" lang="ja"> <![endif]-->
<!--[if IE 7]>    <html class="no-js lt-ie9 lt-ie8" lang="ja"> <![endif]-->
<!--[if IE 8]>    <html class="no-js lt-ie9" lang="ja"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="ja"> <!--<![endif]-->
  <head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# article: http://ogp.me/ns/article#">
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <title>FuelPHPの脆弱性への攻撃を再現出来たけど公開していいものなんだっけ</title>
    <meta name="description" content>
    <meta name="author" content>

    <meta name="viewport" content="width=device-width">
    <meta property="fb:app_id" content="351187098330864">
    <meta property="og:type" content="article">
    <meta property="og:image" content="http://dekokun.github.com/img/dekokun.png">
    <meta property="og:title" content="FuelPHPの脆弱性への攻撃を再現出来たけど公開していいものなんだっけ">
    <meta property="og:description" content="@dekokunの技術日記">
    <meta property="og:site_name" content="でこてっくろぐ">
    <meta name="twitter:widgets:csp" content="on">

    <link rel="stylesheet" href="../css/bootstrap.css">
    <link rel="stylesheet" href="../css/bootstrap-responsive.css">
    <link rel="stylesheet" href="../css/style.css">
    <style>
    body {
      padding-top: 60px;
      padding-bottom: 40px;
    }
    </style>
    <link href="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.css" type="text/css" rel="stylesheet">
    <script src="../js/libs/modernizr-2.5.3-respond-1.1.0.min.js"></script>
    <script>
      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

      ga('create', 'UA-39650556-1', 'auto');
      ga('send', 'pageview');
    </script>
  </head>
  <body>
  <!--[if lt IE 7]><p class=chromeframe>Your browser is <em>ancient!</em> <a href="http://browsehappy.com/">Upgrade to a different browser</a> or <a href="http://www.google.com/chromeframe/?redirect=true">install Google Chrome Frame</a> to experience this site.</p><![endif]-->
    <div id="fb-root"></div>
    <script>(function(d, s, id) {
      var js, fjs = d.getElementsByTagName(s)[0];
      if (d.getElementById(id)) return;
      js = d.createElement(s); js.id = id;
      js.src = "//connect.facebook.net/ja_JP/all.js#xfbml=1&appId=351187098330864";
      fjs.parentNode.insertBefore(js, fjs);
      }(document, 'script', 'facebook-jssdk'));
    </script>
    <header>
      <nav class="navbar navbar-fixed-top">
        <div class="navbar-inner">
          <div class="container">
            <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
            </a>
            <a class="brand" href="../index.html">でこてっくろぐ</a>
            <div class="nav-collapse">
              <ul class="nav">
                <li><a href="../index.html">ほーむ</a></li>
                <li><a href="../posts.html">あーかいぶ</a></li>
                <li><a href="../aboutme.html">あばうとみー</a></li>
              </ul>
            </div><!--/.nav-collapse -->
          </div>
        </div>
      </nav>
    </header>

    <div class="container">
      <div class="row">
        <article class="span9">
          <h1>FuelPHPの脆弱性への攻撃を再現出来たけど公開していいものなんだっけ</h1>

<p>by <em><a href="https://twitter.com/dekokun">@dekokun</a></em> on <strong>2014/07/25 00:11</strong></p>

<p>Tagged as: <a href="../tags/PHP.html">PHP</a>, <a href="../tags/FuelPHP.html">FuelPHP</a>.</p>

<h2 id="概要">概要</h2>
<p>FuelPHPの脆弱性への攻撃を再現出来て嬉しいんだけど、こういうのって公開していいものなの？</p>
<h2 id="詳細">詳細</h2>
<p><a href="http://codezine.jp/article/detail/79209">JVN#94791545 FuelPHP において任意のコードが実行される脆弱性</a>に書かれている脆弱性を突く攻撃を再現できそうだったので再現に努めた。</p>
<p>無事再現出来たんだけど、こういう攻撃方法って、あんまり外に出しちゃいけないんですか。どうなんですか。</p>
<ol style="list-style-type: decimal">
<li>公開したら攻撃したい人が喜ぶだろ</li>
<li>公開して危険さを広めることで皆のバージョンアップを促そう</li>
</ol>
<p>という２つの立ち位置がある感じがする。</p>
<p>まぁ、そもそも今回の脆弱性への攻撃はやり方を公開したところで普通の人はどうにもできない感はある。攻撃相手サーバの通信先に、攻撃コードを埋め込む必要があるので…</p>
<h2 id="結論">結論</h2>
<p>serializeされて渡された文字列をデフォルトでunserializeするような実装にしているのはさすがにもっとちゃんとしてくださいという気持ち。まぁ、私もちゃんと気をつけたいです。</p>
<p>FuelPHP、この脆弱性対応で、1.7.1と1.7.2というマイナーバージョンアップにもかかわらずRequest系クラスのインターフェースが結構変わってしまった感あるのだが大丈夫なのだろうかという気持ち。</p>

<div id="disqus_thread"></div>
<script type="text/javascript">
    /* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */
    var disqus_shortname = 'dekokun'; // required: replace example with your forum shortname

    /* * * DON'T EDIT BELOW THIS LINE * * */
    (function() {
        var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
        dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js';
        (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
    })();
</script>
<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
<a href="http://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a>

          <ul class="social">
            <li class="kindle"><div class="kindleWidget"><img style="vertical-align:middle;" src="https://d1xnn692s7u6t6.cloudfront.net/white-15.png" /><span style="vertical-align:middle;margin-left:3px;">Send to Kindle</span></div></li>
            <li class="facebook"><div class="fb-like" data-send="false" data-layout="button_count" data-width="100" data-show-faces="true" data-font="arial"></div></li>
            <li class="twitter"><a href="https://twitter.com/share" class="twitter-share-button" data-via="dekokun" data-lang="ja">ツイート</a></li>
            <li class="hatena-bookmark"><a href="http://b.hatena.ne.jp/entry/" class="hatena-bookmark-button" data-hatena-bookmark-layout="standard" title="このエントリーをはてなブックマークに追加"><img src="http://b.st-hatena.com/images/entry-button/button-only.gif" alt="このエントリーをはてなブックマークに追加" width="20" height="20" style="border: none;"></a><script type="text/javascript" src="http://b.st-hatena.com/js/bookmark_button.js" charset="utf-8" async="async"></script></li>
            <li><a data-pocket-label="pocket" data-pocket-count="horizontal" class="pocket-btn" data-lang="en"></a>
            <script type="text/javascript">!function(d,i){if(!d.getElementById(i)){var j=d.createElement("script");j.id=i;j.src="https://widgets.getpocket.com/v1/j/btn.js?v=1";var w=d.getElementById(i);d.body.appendChild(j);}}(document,"pocket-btn-js");</script></li>
          </ul>

        </article>
        <aside class="span3">
          <div class="sidebar-module">
            <div class="title">プロフィール</div>
            <p class="id"><a href="https://twitter.com/dekokun">dekokun</a></p>
            <p><a href="https://twitter.com/dekokun"><img src="../img/dekokun.png" alt="dekokun"></a></p>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.io/";
              Hatena.BookmarkWidget.title = "人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 200;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.com/";
              Hatena.BookmarkWidget.title = "旧人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 0;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module visible-desktop">
            <div class="title">twitter</div>
            <a class="twitter-timeline" data-dnt="true" href="https://twitter.com/dekokun" data-widget-id="306408547573440513">@dekokun からのツイート</a>
            <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
          </div>
          <div class="sidebar-module hidden-phone">
            <div class="title">RSS</div>
            <p><a href="../rss.xml"><img src="../img/rss.gif" alt="rss"></a></p>
          </div>
        </aside> <!-- /span3 -->
      </div> <!-- /row -->
      <footer>
        <p>©<script type="text/javascript">$y=2012;$ny=new Date().getFullYear();document.write($ny>$y?$y+'-'+$ny:$y);</script> <a href="https://twitter.com/dekokun">dekokun</a></p>
      </footer>
    </div> <!-- /container -->

    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script>window.jQuery || document.write('<script src="../js/libs/jquery-1.7.2.min.js"><\/script>')</script>
    <!-- /ツイートボタン -->
  <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>

    <script src="../js/libs/bootstrap/bootstrap.min.js"></script>

    <script src="../js/script.js"></script>
    <script>
      var _gaq=[['_setAccount','UA-XXXXX-X'],['_trackPageview']];
      (function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
      g.src=('https:'==location.protocol?'//ssl':'//www')+'.google-analytics.com/ga.js';
      s.parentNode.insertBefore(g,s)}(document,'script'));
    </script>
    <!-- Code syntax highlight -->
    <script type="text/javascript" src="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.js"></script>
    <script type="text/javascript">
    $(function(){ 
        $('pre').css({
            'overflow-x': 'scroll',
            'background-color': '#f6f6f6',
            'border': '1px dotted #ccc',
            'padding': '0.8em'
        });
        $('pre code').addClass('prettyprint');
        prettyPrint();
    });
    </script>
    <script type="text/javascript" src="https://d1xnn692s7u6t6.cloudfront.net/widget.js"></script>
    <script type="text/javascript">(function k(){window.$SendToKindle&&window.$SendToKindle.Widget?$SendToKindle.Widget.init({"content":"article"}):setTimeout(k,500);})();</script>
  </body>
</html>
]]></description>
    <pubDate>No date found.</pubDate>
    <guid>http://dekokun.github.io/posts/2014-07-25.html</guid>
</item>
<item>
    <title>CEDEC AI CHALLENGE 決勝に参加して来ます</title>
    <link>http://dekokun.github.io/posts/2014-08-31.html</link>
    <description><![CDATA[<!doctype html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7" lang="ja"> <![endif]-->
<!--[if IE 7]>    <html class="no-js lt-ie9 lt-ie8" lang="ja"> <![endif]-->
<!--[if IE 8]>    <html class="no-js lt-ie9" lang="ja"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="ja"> <!--<![endif]-->
  <head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# article: http://ogp.me/ns/article#">
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <title>CEDEC AI CHALLENGE 決勝に参加して来ます</title>
    <meta name="description" content>
    <meta name="author" content>

    <meta name="viewport" content="width=device-width">
    <meta property="fb:app_id" content="351187098330864">
    <meta property="og:type" content="article">
    <meta property="og:image" content="http://dekokun.github.com/img/dekokun.png">
    <meta property="og:title" content="CEDEC AI CHALLENGE 決勝に参加して来ます">
    <meta property="og:description" content="@dekokunの技術日記">
    <meta property="og:site_name" content="でこてっくろぐ">
    <meta name="twitter:widgets:csp" content="on">

    <link rel="stylesheet" href="../css/bootstrap.css">
    <link rel="stylesheet" href="../css/bootstrap-responsive.css">
    <link rel="stylesheet" href="../css/style.css">
    <style>
    body {
      padding-top: 60px;
      padding-bottom: 40px;
    }
    </style>
    <link href="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.css" type="text/css" rel="stylesheet">
    <script src="../js/libs/modernizr-2.5.3-respond-1.1.0.min.js"></script>
    <script>
      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

      ga('create', 'UA-39650556-1', 'auto');
      ga('send', 'pageview');
    </script>
  </head>
  <body>
  <!--[if lt IE 7]><p class=chromeframe>Your browser is <em>ancient!</em> <a href="http://browsehappy.com/">Upgrade to a different browser</a> or <a href="http://www.google.com/chromeframe/?redirect=true">install Google Chrome Frame</a> to experience this site.</p><![endif]-->
    <div id="fb-root"></div>
    <script>(function(d, s, id) {
      var js, fjs = d.getElementsByTagName(s)[0];
      if (d.getElementById(id)) return;
      js = d.createElement(s); js.id = id;
      js.src = "//connect.facebook.net/ja_JP/all.js#xfbml=1&appId=351187098330864";
      fjs.parentNode.insertBefore(js, fjs);
      }(document, 'script', 'facebook-jssdk'));
    </script>
    <header>
      <nav class="navbar navbar-fixed-top">
        <div class="navbar-inner">
          <div class="container">
            <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
            </a>
            <a class="brand" href="../index.html">でこてっくろぐ</a>
            <div class="nav-collapse">
              <ul class="nav">
                <li><a href="../index.html">ほーむ</a></li>
                <li><a href="../posts.html">あーかいぶ</a></li>
                <li><a href="../aboutme.html">あばうとみー</a></li>
              </ul>
            </div><!--/.nav-collapse -->
          </div>
        </div>
      </nav>
    </header>

    <div class="container">
      <div class="row">
        <article class="span9">
          <h1>CEDEC AI CHALLENGE 決勝に参加して来ます</h1>

<p>by <em><a href="https://twitter.com/dekokun">@dekokun</a></em> on <strong>2014/08/31 12:56</strong></p>

<p>Tagged as: <a href="../tags/PHP.html">PHP</a>.</p>

<h2 id="概要">概要</h2>
<ul>
<li>日本最大のゲーム開発者向けカンファレンスであるところのCEDECにて、AIコンテストが開かれる</li>
<li>インターネット予選を勝ち抜いた16名で争われる</li>
<li>インターネット予選、19位だったので決勝出場の16位に入れなかったと思ってたけど、決勝に参加できない人が何名かいたようで繰り上がり参加できるようになった模様</li>
</ul>
<h2 id="使ってる言語や作戦など">使ってる言語や作戦など</h2>
<ul>
<li>決勝については詳しくはまだ明かさないが、予選はPHP + モンテカルロシミュレーションを使用して戦った</li>
<li>上記組み合わせだと、動的言語PHPの弱点(実行速度の遅さ)をもろに晒す戦い方になるので、決勝では言語か戦略をガラッと変えていく予定。多分
<ul>
<li>まぁ、9/1日中にAIを提出しなくてはいけなくてあまり時間ないですが</li>
</ul></li>
<li>詳しくは決勝終わってから解説します</li>
</ul>
<h2 id="モンテカルロシミュレーションについて">モンテカルロシミュレーションについて</h2>
<p>人生初のモンテカルロシミュレーションだったが、以下学びがあった</p>
<ul>
<li>なぜ強いのかわからんけど強い、みたいな不思議な気分に包まれる。AIって多分全体的にそんな感じなのだろうが</li>
<li>バグなくちゃんと動いているかを検証するのが極めて難しい</li>
</ul>
<h2 id="その他作戦">その他作戦</h2>
<ul>
<li>AI開発の集中力を高めるために<a href="http://floatcenter.jp/">アイソレーションタンク</a>とやらに行って来た
<ul>
<li>プカプカ浮かんできた</li>
<li>実にクリアな気分になれた。これならAI CHALLNGE、いけそう</li>
</ul></li>
<li>ついでに、HHKBを購入した
<ul>
<li>実に素晴らしい。これならいけそう</li>
<li>という予定だったのだが、近くのヤマダ電機にはHHKBがなかった。普通にあるものだと思っていたが違った</li>
</ul></li>
</ul>

<div id="disqus_thread"></div>
<script type="text/javascript">
    /* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */
    var disqus_shortname = 'dekokun'; // required: replace example with your forum shortname

    /* * * DON'T EDIT BELOW THIS LINE * * */
    (function() {
        var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
        dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js';
        (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
    })();
</script>
<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
<a href="http://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a>

          <ul class="social">
            <li class="kindle"><div class="kindleWidget"><img style="vertical-align:middle;" src="https://d1xnn692s7u6t6.cloudfront.net/white-15.png" /><span style="vertical-align:middle;margin-left:3px;">Send to Kindle</span></div></li>
            <li class="facebook"><div class="fb-like" data-send="false" data-layout="button_count" data-width="100" data-show-faces="true" data-font="arial"></div></li>
            <li class="twitter"><a href="https://twitter.com/share" class="twitter-share-button" data-via="dekokun" data-lang="ja">ツイート</a></li>
            <li class="hatena-bookmark"><a href="http://b.hatena.ne.jp/entry/" class="hatena-bookmark-button" data-hatena-bookmark-layout="standard" title="このエントリーをはてなブックマークに追加"><img src="http://b.st-hatena.com/images/entry-button/button-only.gif" alt="このエントリーをはてなブックマークに追加" width="20" height="20" style="border: none;"></a><script type="text/javascript" src="http://b.st-hatena.com/js/bookmark_button.js" charset="utf-8" async="async"></script></li>
            <li><a data-pocket-label="pocket" data-pocket-count="horizontal" class="pocket-btn" data-lang="en"></a>
            <script type="text/javascript">!function(d,i){if(!d.getElementById(i)){var j=d.createElement("script");j.id=i;j.src="https://widgets.getpocket.com/v1/j/btn.js?v=1";var w=d.getElementById(i);d.body.appendChild(j);}}(document,"pocket-btn-js");</script></li>
          </ul>

        </article>
        <aside class="span3">
          <div class="sidebar-module">
            <div class="title">プロフィール</div>
            <p class="id"><a href="https://twitter.com/dekokun">dekokun</a></p>
            <p><a href="https://twitter.com/dekokun"><img src="../img/dekokun.png" alt="dekokun"></a></p>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.io/";
              Hatena.BookmarkWidget.title = "人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 200;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.com/";
              Hatena.BookmarkWidget.title = "旧人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 0;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module visible-desktop">
            <div class="title">twitter</div>
            <a class="twitter-timeline" data-dnt="true" href="https://twitter.com/dekokun" data-widget-id="306408547573440513">@dekokun からのツイート</a>
            <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
          </div>
          <div class="sidebar-module hidden-phone">
            <div class="title">RSS</div>
            <p><a href="../rss.xml"><img src="../img/rss.gif" alt="rss"></a></p>
          </div>
        </aside> <!-- /span3 -->
      </div> <!-- /row -->
      <footer>
        <p>©<script type="text/javascript">$y=2012;$ny=new Date().getFullYear();document.write($ny>$y?$y+'-'+$ny:$y);</script> <a href="https://twitter.com/dekokun">dekokun</a></p>
      </footer>
    </div> <!-- /container -->

    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script>window.jQuery || document.write('<script src="../js/libs/jquery-1.7.2.min.js"><\/script>')</script>
    <!-- /ツイートボタン -->
  <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>

    <script src="../js/libs/bootstrap/bootstrap.min.js"></script>

    <script src="../js/script.js"></script>
    <script>
      var _gaq=[['_setAccount','UA-XXXXX-X'],['_trackPageview']];
      (function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
      g.src=('https:'==location.protocol?'//ssl':'//www')+'.google-analytics.com/ga.js';
      s.parentNode.insertBefore(g,s)}(document,'script'));
    </script>
    <!-- Code syntax highlight -->
    <script type="text/javascript" src="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.js"></script>
    <script type="text/javascript">
    $(function(){ 
        $('pre').css({
            'overflow-x': 'scroll',
            'background-color': '#f6f6f6',
            'border': '1px dotted #ccc',
            'padding': '0.8em'
        });
        $('pre code').addClass('prettyprint');
        prettyPrint();
    });
    </script>
    <script type="text/javascript" src="https://d1xnn692s7u6t6.cloudfront.net/widget.js"></script>
    <script type="text/javascript">(function k(){window.$SendToKindle&&window.$SendToKindle.Widget?$SendToKindle.Widget.init({"content":"article"}):setTimeout(k,500);})();</script>
  </body>
</html>
]]></description>
    <pubDate>No date found.</pubDate>
    <guid>http://dekokun.github.io/posts/2014-08-31.html</guid>
</item>
<item>
    <title>PHPを使ったり4000円課金したりしてCEDEC AI CHALLENGE 準優勝に至るまでの軌跡</title>
    <link>http://dekokun.github.io/posts/2014-09-07.html</link>
    <description><![CDATA[<!doctype html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7" lang="ja"> <![endif]-->
<!--[if IE 7]>    <html class="no-js lt-ie9 lt-ie8" lang="ja"> <![endif]-->
<!--[if IE 8]>    <html class="no-js lt-ie9" lang="ja"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="ja"> <!--<![endif]-->
  <head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# article: http://ogp.me/ns/article#">
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <title>PHPを使ったり4000円課金したりしてCEDEC AI CHALLENGE 準優勝に至るまでの軌跡</title>
    <meta name="description" content>
    <meta name="author" content>

    <meta name="viewport" content="width=device-width">
    <meta property="fb:app_id" content="351187098330864">
    <meta property="og:type" content="article">
    <meta property="og:image" content="http://dekokun.github.com/img/dekokun.png">
    <meta property="og:title" content="PHPを使ったり4000円課金したりしてCEDEC AI CHALLENGE 準優勝に至るまでの軌跡">
    <meta property="og:description" content="@dekokunの技術日記">
    <meta property="og:site_name" content="でこてっくろぐ">
    <meta name="twitter:widgets:csp" content="on">

    <link rel="stylesheet" href="../css/bootstrap.css">
    <link rel="stylesheet" href="../css/bootstrap-responsive.css">
    <link rel="stylesheet" href="../css/style.css">
    <style>
    body {
      padding-top: 60px;
      padding-bottom: 40px;
    }
    </style>
    <link href="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.css" type="text/css" rel="stylesheet">
    <script src="../js/libs/modernizr-2.5.3-respond-1.1.0.min.js"></script>
    <script>
      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

      ga('create', 'UA-39650556-1', 'auto');
      ga('send', 'pageview');
    </script>
  </head>
  <body>
  <!--[if lt IE 7]><p class=chromeframe>Your browser is <em>ancient!</em> <a href="http://browsehappy.com/">Upgrade to a different browser</a> or <a href="http://www.google.com/chromeframe/?redirect=true">install Google Chrome Frame</a> to experience this site.</p><![endif]-->
    <div id="fb-root"></div>
    <script>(function(d, s, id) {
      var js, fjs = d.getElementsByTagName(s)[0];
      if (d.getElementById(id)) return;
      js = d.createElement(s); js.id = id;
      js.src = "//connect.facebook.net/ja_JP/all.js#xfbml=1&appId=351187098330864";
      fjs.parentNode.insertBefore(js, fjs);
      }(document, 'script', 'facebook-jssdk'));
    </script>
    <header>
      <nav class="navbar navbar-fixed-top">
        <div class="navbar-inner">
          <div class="container">
            <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
            </a>
            <a class="brand" href="../index.html">でこてっくろぐ</a>
            <div class="nav-collapse">
              <ul class="nav">
                <li><a href="../index.html">ほーむ</a></li>
                <li><a href="../posts.html">あーかいぶ</a></li>
                <li><a href="../aboutme.html">あばうとみー</a></li>
              </ul>
            </div><!--/.nav-collapse -->
          </div>
        </div>
      </nav>
    </header>

    <div class="container">
      <div class="row">
        <article class="span9">
          <h1>PHPを使ったり4000円課金したりしてCEDEC AI CHALLENGE 準優勝に至るまでの軌跡</h1>

<p>by <em><a href="https://twitter.com/dekokun">@dekokun</a></em> on <strong>2014/09/08 00:07</strong></p>

<p>Tagged as: <a href="../tags/PHP.html">PHP</a>, <a href="../tags/contest.html">contest</a>.</p>

<h2 id="概要">概要</h2>
<p>日本で最大のゲーム開発者向けカンファレンスであるところのCEDECにて、AIのプログラミングコンテストが開かれました。</p>
<p>その名も<a href="http://www.ai-comp.net/cedec2014/">CEDEC AI CHELLENGE</a>。</p>
<p>そこで、PHPを使って参戦したら見事準優勝したので何を行ったかを書きます</p>
<p>なお、この大会はオンラインで行われる予選と、実際にCEDECの会場で行われる本選の2段階で行われました。 上記「見事準優勝」等と言っておりますが、予選はともかく本選の方はほとんど運によって全てが支配されていたため、準優勝ってなんぼのもんなのかと言われると、「最低限瞬殺されないくらいの強さ」というくらいの話でしかないです。はい。</p>
<p>参加者は、去年は11人だったようですが今年は5倍以上の60人。来年はもっと増えるんですかね。来年も参加したいですね。</p>
<p>なお、タイトルに「PHP」と付けたのは、日々disられがちなPHP使いへのエールを込めてです(去年のISUCONブログでも同じ事を書いたよね <a href="http://dekokun.github.io/posts/2013-10-06.html">ISUCON予選にPHP実装で参加して3位になりましたーやったことなどまとめ</a>)</p>
<h2 id="簡単なルール">簡単なルール</h2>
<ul>
<li>詳細はこちら <a href="http://www.ai-comp.net/cedec2014/#game-rules">Game Rules</a></li>
<li>一回の対戦は4人で行われます。8人のバーチャルな女の子がいて、平日は5回、休日は2回、それぞれ誰かとデートをします</li>
<li>平日に誰が誰とデートをしたかの情報は開示されるのですが、休日は、どの女の子がデートをしたかだけが開示され、誰とデートしかかは不明です</li>
<li>それらの情報を元により多くの女の子の好感度をあげよう！</li>
<li>女の子には一人ひとりに情熱度が付与され公開されていて、情熱度が高い女の子の好感度を上げるほど勝利は近いぞ！</li>
<li>さて、他の人の情報が中途半端にわかっている状態で君は誰とデートする？！</li>
<li>みたいなざっくりとしたルールはそんな感じです</li>
<li>使用言語は、C, C++, Java, C#, Scala, Ruby, Python, Perl, PHP, Haskell, JavaScriptです
<ul>
<li>今回私はPHPを使いました。最近disられがちなPHPの復権を望んでそんなことをしましたが、動的言語が遅いのはわかりきった話ではあるので、次はScalaで戦います</li>
<li>多分、今回本選に参加したメンバーの中でPHP使ってたの私だけだろうなぁ</li>
<li>別のところでGoが使わせてもらえるのならGoで書く</li>
</ul></li>
</ul>
<h2 id="戦略概要">戦略概要</h2>
<ul>
<li>ルールベースAIとモンテカルロなAIの組み合わせ</li>
<li>最初は「ただのルールベースAIで行くぞ」と思ってルールベースの土台を作ったが、結局「基本ははモンテカルロ法ルール。前半と後半でちょっとパラメータを変化させるためにルールベースAIを使った」という感じだったため、ルールベースAIを導入した意味はほとんどなかった</li>
<li>どのようにモンテカルロ法を使ったか
<ul>
<li>自分の取りうる全ての手に対して、その後自分と相手がランダムに全ての手を打ったと仮定した際に誰が勝つかを計算し、その中で自分の勝率が最も良かった手を打つ</li>
<li>情報の不完全性を最大限利用して頭のいいAIに情報を与えないためにために、前半は休日の際は1ターンの中では2日とも同じ相手に点を入れるようにしてある</li>
<li>上記を前半だけにしたのは、前半に混乱させれば後々それが効いてくるだろうというのと、後半はお互いの今後の可能性が減りより精緻なよみができるようになるのでその中でちゃんと最善の手を打たせたかったから</li>
</ul></li>
</ul>
<h2 id="なぜモンテカルロ">なぜモンテカルロ？</h2>
<p>意思決定の流れを時系列順に</p>
<ul>
<li>「このAI,モンテカルロが向いているんちゃいますか？」という後輩の進言によってモンテカルロ法のAIについて調べる</li>
<li>調べたところ「どのような手を打っても確実にゲームは終了する」というゲームの特徴がモンテカルロ法にぴったりだった</li>
<li>唯一の懸念点は、PHPを選択していることで「Scala等のコンパイル型の言語を選んだ参加者と比べて計算量が圧倒的に少なく試行回数が稼げない」ところ</li>
<li>以下『工夫したところ』『反省点』にあるように、今回の問題はモンテカルロ法を選択した際に収束を早める工夫が色々できそうだったのでまぁ、他の参加者を出し抜くことも可能だろう</li>
<li>モンテカルロに決定</li>
<li>私はこの時まで、モンテカルロに対して「なんか確率的な手法なんでしょーよく知らんけど」みたいな感じだったため、後輩がいなかったら「AIにモンテカルロ法を使用する」という発想が出てくることは絶対になかったと思われる。後輩に感謝</li>
</ul>
<h2 id="aiで工夫したところ">AIで工夫したところ</h2>
<ul>
<li>自分が取りうる手は状況によって変わらないためプログラム内に自分の打ち得る手を最初に列挙しておいたところ
<ul>
<li>こちら、実は手打ちでやっており、やばかった。700超通りの配列を延々手打ちで作成したのはものすごくプログラマとしてダメなことしてるなと思いながら延々手打ちをした</li>
</ul></li>
<li>過去のデート回数については、1ターン毎の各ヒロインのデート回数を、そのターンでの全デート回数で割った数を、自分以外の各プレイヤが取得した好感度として計算 &lt;- この考えを入れることで明らかに勝率が上がった</li>
<li>今回、「敵がランダムに行動する」という仮定をとった際、自分がとった手は全く相手の手に影響を与えないため（例えば囲碁の場合、自分が打った場所には敵は打てないが、今回はそのような制約はない）、ランダムな、全プレイヤーが取りうる手の中で、自分がとる手を入れ替えていくことで計算量を減らすという戦略をとった</li>
<li>このゲームでは、「敵がランダムに行動する」という仮定をとった際、「ある手を打つことが決まっているのであれば、それがどのタイミングだとしても最終結果は変わらない」ため、あるプレイヤーが今後取りうる手を計算する際に、「全45ポイントをどのヒロインに割り振るか」だけを計算することで、収束を早めることができた
<ul>
<li>これによって、一人のプレイヤーが取りうる手の組み合わせ結果が 8^45(ものすごくたくさん) から 52C8(752538150) まで減った(と思う。計算が間違っていなければ)</li>
<li>ただ、この方法での敵のポイント分布は実際にランダムに敵が行動した場合のポイント分布と異なるという欠点はあるが収束を早めるためにやってよかったと思っている</li>
</ul></li>
</ul>
<h2 id="aiの中身以外で良かった点">AIの中身以外で良かった点</h2>
<ul>
<li>Jenkinsを構築しGithubにコードがPUSHされたタイミングで、過去の自分と300回ほど対戦して極端に勝率が低くなっていないかを確認するCIを回していた
<ul>
<li>これを実現するためにはCPUぶんまわしの並列実行バリバリできるサーバが必要であり、AWSのc3.8xlargeというかなり最強に近いインスタンスを使用し、2日で4000円ほどが吹き飛んだ</li>
<li>勝率のグラフ化、plotプラグインが便利だった</li>
<li>提出直前は、「ある施策を打つ」「JenkinsのCIで極端に勝率が落ちる」「revertする」の繰り返しで、弱いAIを提出しちゃわなかったという点で圧倒的に役に立った</li>
</ul></li>
<li>ライバルと一緒に参加したこと
<ul>
<li>まぁ、ライバルというか会社の後輩なんだけど、二人で励まし合ったり情報交換したりして頑張れた</li>
<li>なお、彼は予選の「最後に提出したAIが採用される」というルールを把握しておらずそんなに強くないAIで戦い死んだ</li>
</ul></li>
<li>予選終了後にライバルとの反省会
<ul>
<li>予選が終わった後すぐにお互いがどのような戦略をとっていたのかをまじえつつ反省会を行った</li>
<li>その結果は決勝のAIにフィードバックされております</li>
</ul></li>
<li>プロファイラでボトルネックを測定した
<ul>
<li>PHPには、最強のプロファイリングツールであるxhprofがありまして、こいつのお陰でボトルネックらくらく特定でしたね</li>
</ul></li>
</ul>
<h2 id="行おうとしたけどしなかった施策達">行おうとしたけどしなかった施策達</h2>
<p>邪悪なものから、普通に実現できなかったものまで</p>
<h3 id="並列実行">並列実行</h3>
<ul>
<li>そもそもPHPでは並列実行周り非常に弱いのだが、新しいプロセスを起動し自分自身を実行して標準出力でデータを受け渡すなどしてなんとかすれば並列実行できるしそちら頑張ってみようかなと思った
<ul>
<li>そもそもコア数が1だったら意味が無いので計測した。具体的には、 予選サーバの/proc/cpuinfoファイルの中身をAI実行ファイルから覗き見た</li>
<li>結果、コア数が1だとわかったため並列実行は断念</li>
<li>後で運営の方に確認したところ、DigitalOceanの一番安いインスタンスを使用していたとのことだった</li>
<li>事前にインスタンス情報も与えられていなかったし計測するのは本当に大切なことだ！</li>
</ul></li>
</ul>
<h3 id="外部のサーバに頑張らせる">外部のサーバに頑張らせる</h3>
<ul>
<li>外部の超いいインスタンスを用意し、そのAPIを叩くことで高性能な外部のサーバに計算させることを考えた
<ul>
<li>が、PHPから外部のサーバを叩こうとしたらエラーだったため「さすがに運営が止めているか。そりゃそうだよな」とすぐに諦めた</li>
<li>運営によると「外部への通信は制限していなかったはず」と言っていたので何か間違えたかも</li>
</ul></li>
</ul>
<h3 id="事前に計算結果を持っておく">事前に計算結果を持っておく</h3>
<ul>
<li>今回PHPを使ったわけだが最大の弱点として「遅い」という問題があるため、それを事前計算で解決しようとした</li>
<li>具体的には、試行回数を増やしたモンテカルロ法で、事前にあらゆる手に対しての最善手を計算してファイルに格納しておき、実際の戦いでは現状から答えを読み取るだけで済むようにする</li>
<li>ファイルアップロードの容量制限があるのは知っていたため、前半の手だけでも格納できないかなと考えていた</li>
<li>実装時間がたりなさすぎてできなかった</li>
</ul>
<h3 id="複数aiの協調動作邪悪">複数AIの協調動作(邪悪)</h3>
<ul>
<li>複数アカウントを作成し、序盤はそれぞれのAIがある法則にしたがって自分の手を打ち他のAIにメッセージを投げる</li>
<li>それぞれのAIが、序盤のメッセージを受け戦いの中に味方がいることを察すると、後はそれぞれが事前に決められたあるAIを勝たせるために協調動作する
<ul>
<li>具体的には、勝たせるAIが狙っている女の子に対しては自分は一位の好感度を得ないようにし、他のAIが勝ちそうな女の子の好感度を上げて他のAIにポイントをとらせないみたいな</li>
</ul></li>
<li>この方法は予選突破にしか使えず、そもそも実装がかなり複雑になるため予選突破するためなら普通に頑張ったほうが早いと思ってやめた。そもそも発想が邪悪すぎる</li>
</ul>
<h2 id="感想">感想</h2>
<ul>
<li>アイデアをくれた後輩に感謝</li>
<li>モンテカルロ法、実行結果をみても正しく動いているかがよくわからないためデバッグが著しく困難
<ul>
<li>その反省を活かして決勝にJenkinsを導入したのはとてもよかった</li>
</ul></li>
<li>PHPの「division by zero エラーでもプログラムが止まらない」という特性を知った
<ul>
<li>予選では上記エラーが出まくるプログラムを提出していました。動いていたから気付かなかった。恐ろしいですね</li>
</ul></li>
<li>懇親会の中華、おいしかったです</li>
</ul>
<h2 id="最後に">最後に</h2>
<ul>
<li>運営の方が、この対戦に使用される絵(<a href="http://www.ai-comp.net/cedec2014/#screenshots">スクリーンショット</a>)を描いていただける絵師さんを募集しているそうです</li>
<li>コードはこちら https://github.com/dekokun/CEDECAI</li>
<li>このブログ、めちゃ長いな</li>
</ul>

<div id="disqus_thread"></div>
<script type="text/javascript">
    /* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */
    var disqus_shortname = 'dekokun'; // required: replace example with your forum shortname

    /* * * DON'T EDIT BELOW THIS LINE * * */
    (function() {
        var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
        dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js';
        (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
    })();
</script>
<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
<a href="http://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a>

          <ul class="social">
            <li class="kindle"><div class="kindleWidget"><img style="vertical-align:middle;" src="https://d1xnn692s7u6t6.cloudfront.net/white-15.png" /><span style="vertical-align:middle;margin-left:3px;">Send to Kindle</span></div></li>
            <li class="facebook"><div class="fb-like" data-send="false" data-layout="button_count" data-width="100" data-show-faces="true" data-font="arial"></div></li>
            <li class="twitter"><a href="https://twitter.com/share" class="twitter-share-button" data-via="dekokun" data-lang="ja">ツイート</a></li>
            <li class="hatena-bookmark"><a href="http://b.hatena.ne.jp/entry/" class="hatena-bookmark-button" data-hatena-bookmark-layout="standard" title="このエントリーをはてなブックマークに追加"><img src="http://b.st-hatena.com/images/entry-button/button-only.gif" alt="このエントリーをはてなブックマークに追加" width="20" height="20" style="border: none;"></a><script type="text/javascript" src="http://b.st-hatena.com/js/bookmark_button.js" charset="utf-8" async="async"></script></li>
            <li><a data-pocket-label="pocket" data-pocket-count="horizontal" class="pocket-btn" data-lang="en"></a>
            <script type="text/javascript">!function(d,i){if(!d.getElementById(i)){var j=d.createElement("script");j.id=i;j.src="https://widgets.getpocket.com/v1/j/btn.js?v=1";var w=d.getElementById(i);d.body.appendChild(j);}}(document,"pocket-btn-js");</script></li>
          </ul>

        </article>
        <aside class="span3">
          <div class="sidebar-module">
            <div class="title">プロフィール</div>
            <p class="id"><a href="https://twitter.com/dekokun">dekokun</a></p>
            <p><a href="https://twitter.com/dekokun"><img src="../img/dekokun.png" alt="dekokun"></a></p>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.io/";
              Hatena.BookmarkWidget.title = "人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 200;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.com/";
              Hatena.BookmarkWidget.title = "旧人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 0;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module visible-desktop">
            <div class="title">twitter</div>
            <a class="twitter-timeline" data-dnt="true" href="https://twitter.com/dekokun" data-widget-id="306408547573440513">@dekokun からのツイート</a>
            <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
          </div>
          <div class="sidebar-module hidden-phone">
            <div class="title">RSS</div>
            <p><a href="../rss.xml"><img src="../img/rss.gif" alt="rss"></a></p>
          </div>
        </aside> <!-- /span3 -->
      </div> <!-- /row -->
      <footer>
        <p>©<script type="text/javascript">$y=2012;$ny=new Date().getFullYear();document.write($ny>$y?$y+'-'+$ny:$y);</script> <a href="https://twitter.com/dekokun">dekokun</a></p>
      </footer>
    </div> <!-- /container -->

    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script>window.jQuery || document.write('<script src="../js/libs/jquery-1.7.2.min.js"><\/script>')</script>
    <!-- /ツイートボタン -->
  <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>

    <script src="../js/libs/bootstrap/bootstrap.min.js"></script>

    <script src="../js/script.js"></script>
    <script>
      var _gaq=[['_setAccount','UA-XXXXX-X'],['_trackPageview']];
      (function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
      g.src=('https:'==location.protocol?'//ssl':'//www')+'.google-analytics.com/ga.js';
      s.parentNode.insertBefore(g,s)}(document,'script'));
    </script>
    <!-- Code syntax highlight -->
    <script type="text/javascript" src="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.js"></script>
    <script type="text/javascript">
    $(function(){ 
        $('pre').css({
            'overflow-x': 'scroll',
            'background-color': '#f6f6f6',
            'border': '1px dotted #ccc',
            'padding': '0.8em'
        });
        $('pre code').addClass('prettyprint');
        prettyPrint();
    });
    </script>
    <script type="text/javascript" src="https://d1xnn692s7u6t6.cloudfront.net/widget.js"></script>
    <script type="text/javascript">(function k(){window.$SendToKindle&&window.$SendToKindle.Widget?$SendToKindle.Widget.init({"content":"article"}):setTimeout(k,500);})();</script>
  </body>
</html>
]]></description>
    <pubDate>No date found.</pubDate>
    <guid>http://dekokun.github.io/posts/2014-09-07.html</guid>
</item>
<item>
    <title>PHPカンファレンス2014でLTしてきました</title>
    <link>http://dekokun.github.io/posts/2014-10-14.html</link>
    <description><![CDATA[<!doctype html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7" lang="ja"> <![endif]-->
<!--[if IE 7]>    <html class="no-js lt-ie9 lt-ie8" lang="ja"> <![endif]-->
<!--[if IE 8]>    <html class="no-js lt-ie9" lang="ja"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="ja"> <!--<![endif]-->
  <head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# article: http://ogp.me/ns/article#">
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <title>PHPカンファレンス2014でLTしてきました</title>
    <meta name="description" content>
    <meta name="author" content>

    <meta name="viewport" content="width=device-width">
    <meta property="fb:app_id" content="351187098330864">
    <meta property="og:type" content="article">
    <meta property="og:image" content="http://dekokun.github.com/img/dekokun.png">
    <meta property="og:title" content="PHPカンファレンス2014でLTしてきました">
    <meta property="og:description" content="@dekokunの技術日記">
    <meta property="og:site_name" content="でこてっくろぐ">
    <meta name="twitter:widgets:csp" content="on">

    <link rel="stylesheet" href="../css/bootstrap.css">
    <link rel="stylesheet" href="../css/bootstrap-responsive.css">
    <link rel="stylesheet" href="../css/style.css">
    <style>
    body {
      padding-top: 60px;
      padding-bottom: 40px;
    }
    </style>
    <link href="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.css" type="text/css" rel="stylesheet">
    <script src="../js/libs/modernizr-2.5.3-respond-1.1.0.min.js"></script>
    <script>
      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

      ga('create', 'UA-39650556-1', 'auto');
      ga('send', 'pageview');
    </script>
  </head>
  <body>
  <!--[if lt IE 7]><p class=chromeframe>Your browser is <em>ancient!</em> <a href="http://browsehappy.com/">Upgrade to a different browser</a> or <a href="http://www.google.com/chromeframe/?redirect=true">install Google Chrome Frame</a> to experience this site.</p><![endif]-->
    <div id="fb-root"></div>
    <script>(function(d, s, id) {
      var js, fjs = d.getElementsByTagName(s)[0];
      if (d.getElementById(id)) return;
      js = d.createElement(s); js.id = id;
      js.src = "//connect.facebook.net/ja_JP/all.js#xfbml=1&appId=351187098330864";
      fjs.parentNode.insertBefore(js, fjs);
      }(document, 'script', 'facebook-jssdk'));
    </script>
    <header>
      <nav class="navbar navbar-fixed-top">
        <div class="navbar-inner">
          <div class="container">
            <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
            </a>
            <a class="brand" href="../index.html">でこてっくろぐ</a>
            <div class="nav-collapse">
              <ul class="nav">
                <li><a href="../index.html">ほーむ</a></li>
                <li><a href="../posts.html">あーかいぶ</a></li>
                <li><a href="../aboutme.html">あばうとみー</a></li>
              </ul>
            </div><!--/.nav-collapse -->
          </div>
        </div>
      </nav>
    </header>

    <div class="container">
      <div class="row">
        <article class="span9">
          <h1>PHPカンファレンス2014でLTしてきました</h1>

<p>by <em><a href="https://twitter.com/dekokun">@dekokun</a></em> on <strong>2014/10/14 7:54</strong></p>

<p>Tagged as: <a href="../tags/PHP.html">PHP</a>.</p>

<h2 id="概要">概要</h2>
<p>国内最大のPHPイベントである<a href="http://phpcon.php.gr.jp/w/2014/">PHPカンファレンス2014</a>でLTしてきました。</p>
<p>プログラムの最後のLT無差別級の中でも一番最後のLTということで緊張しましたが、結構いい感じに発表できたと思います。ウケて良かった。</p>
<h2 id="発表資料">発表資料</h2>
<iframe src="//www.slideshare.net/slideshow/embed_code/40222955" width="427" height="356" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC; border-width:1px; margin-bottom:5px; max-width: 100%;" allowfullscreen> </iframe> <div style="margin-bottom:5px"> 
<strong> <a href="https://www.slideshare.net/shintarokurachi/phpai" title="PHPでAIプログラミングコンテスト準優勝するまでの軌跡" target="_blank">PHPでAIプログラミングコンテスト準優勝するまでの軌跡</a> </strong> from <strong><a href="http://www.slideshare.net/shintarokurachi" target="_blank">Shintaro Kurachi</a></strong>
</div>

<h2 id="発表内容について">発表内容について</h2>
<ul>
<li>当日手元の資料を見なおしたらデグれっており、慌ててそれを修正したのだが発表の時に更に前のバージョンまでデグれっていることに気付いてバイナリのバージョン管理のできて無さに驚いたのであった
<ul>
<li>例えば、17ページ目の外部サーバに計算させようとしていたところなどは、時間の都合上抜かしていたのだが入っていた</li>
<li>まぁ、デグれったバージョンでも特に問題なく発表できたのでよかった。早口になっていたのか、特に時間が足りなくなることもなかった</li>
<li>iCloudをiCloud DriveにほいほいバージョンアップしたらMarvericsからアクセスできなくなったのが辛かったです</li>
</ul></li>
<li>8ページ目「PHPの立ち位置」の中の「並列実行が苦手」については、あくまで1プロセスの中の話しであり、もちろんApache等の力を借りれば並列処理は特に問題ない感じではある
<ul>
<li>「並行処理」という記述のほうが適切だったかなと思っている</li>
</ul></li>
<li>「PHPの立ち位置」の中の「柔軟な配列」については、プログラムを書く上で便利ではあるが、AIプログラミングという観点からは、むしろデータ構造を選べる方がいいよねという話は確実にある</li>
</ul>
<h2 id="ltについて">LTについて</h2>
<ul>
<li>当日は後輩2人も発表し、それぞれ新卒1年目、2年目にしては非常に堂々とした発表でとてもよかった</li>
<li>社内で定期的にLTイベントが開かれているのが良かったよねという思い
<ul>
<li>もちろん、本人たちのもともとの素養が優れているというのは間違いないが</li>
</ul></li>
</ul>
<h2 id="php愛について">PHP愛について</h2>
<ul>
<li>タイプヒンティングは本当に素晴らしいと思う</li>
<li>それなら静的片付け言語を使えばいいのではと言われそうだが、まぁ、ある程度そのとおりなんだけど、動的言語の中に一部だけ混ぜられるというのがいいと思う</li>
<li>まぁ、タイプヒンティング以外は、特筆すべきところはあまりないかなという感じはあるが…
<ul>
<li>xhprofは便利だけど</li>
</ul></li>
</ul>

<div id="disqus_thread"></div>
<script type="text/javascript">
    /* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */
    var disqus_shortname = 'dekokun'; // required: replace example with your forum shortname

    /* * * DON'T EDIT BELOW THIS LINE * * */
    (function() {
        var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
        dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js';
        (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
    })();
</script>
<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
<a href="http://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a>

          <ul class="social">
            <li class="kindle"><div class="kindleWidget"><img style="vertical-align:middle;" src="https://d1xnn692s7u6t6.cloudfront.net/white-15.png" /><span style="vertical-align:middle;margin-left:3px;">Send to Kindle</span></div></li>
            <li class="facebook"><div class="fb-like" data-send="false" data-layout="button_count" data-width="100" data-show-faces="true" data-font="arial"></div></li>
            <li class="twitter"><a href="https://twitter.com/share" class="twitter-share-button" data-via="dekokun" data-lang="ja">ツイート</a></li>
            <li class="hatena-bookmark"><a href="http://b.hatena.ne.jp/entry/" class="hatena-bookmark-button" data-hatena-bookmark-layout="standard" title="このエントリーをはてなブックマークに追加"><img src="http://b.st-hatena.com/images/entry-button/button-only.gif" alt="このエントリーをはてなブックマークに追加" width="20" height="20" style="border: none;"></a><script type="text/javascript" src="http://b.st-hatena.com/js/bookmark_button.js" charset="utf-8" async="async"></script></li>
            <li><a data-pocket-label="pocket" data-pocket-count="horizontal" class="pocket-btn" data-lang="en"></a>
            <script type="text/javascript">!function(d,i){if(!d.getElementById(i)){var j=d.createElement("script");j.id=i;j.src="https://widgets.getpocket.com/v1/j/btn.js?v=1";var w=d.getElementById(i);d.body.appendChild(j);}}(document,"pocket-btn-js");</script></li>
          </ul>

        </article>
        <aside class="span3">
          <div class="sidebar-module">
            <div class="title">プロフィール</div>
            <p class="id"><a href="https://twitter.com/dekokun">dekokun</a></p>
            <p><a href="https://twitter.com/dekokun"><img src="../img/dekokun.png" alt="dekokun"></a></p>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.io/";
              Hatena.BookmarkWidget.title = "人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 200;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.com/";
              Hatena.BookmarkWidget.title = "旧人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 0;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module visible-desktop">
            <div class="title">twitter</div>
            <a class="twitter-timeline" data-dnt="true" href="https://twitter.com/dekokun" data-widget-id="306408547573440513">@dekokun からのツイート</a>
            <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
          </div>
          <div class="sidebar-module hidden-phone">
            <div class="title">RSS</div>
            <p><a href="../rss.xml"><img src="../img/rss.gif" alt="rss"></a></p>
          </div>
        </aside> <!-- /span3 -->
      </div> <!-- /row -->
      <footer>
        <p>©<script type="text/javascript">$y=2012;$ny=new Date().getFullYear();document.write($ny>$y?$y+'-'+$ny:$y);</script> <a href="https://twitter.com/dekokun">dekokun</a></p>
      </footer>
    </div> <!-- /container -->

    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script>window.jQuery || document.write('<script src="../js/libs/jquery-1.7.2.min.js"><\/script>')</script>
    <!-- /ツイートボタン -->
  <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>

    <script src="../js/libs/bootstrap/bootstrap.min.js"></script>

    <script src="../js/script.js"></script>
    <script>
      var _gaq=[['_setAccount','UA-XXXXX-X'],['_trackPageview']];
      (function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
      g.src=('https:'==location.protocol?'//ssl':'//www')+'.google-analytics.com/ga.js';
      s.parentNode.insertBefore(g,s)}(document,'script'));
    </script>
    <!-- Code syntax highlight -->
    <script type="text/javascript" src="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.js"></script>
    <script type="text/javascript">
    $(function(){ 
        $('pre').css({
            'overflow-x': 'scroll',
            'background-color': '#f6f6f6',
            'border': '1px dotted #ccc',
            'padding': '0.8em'
        });
        $('pre code').addClass('prettyprint');
        prettyPrint();
    });
    </script>
    <script type="text/javascript" src="https://d1xnn692s7u6t6.cloudfront.net/widget.js"></script>
    <script type="text/javascript">(function k(){window.$SendToKindle&&window.$SendToKindle.Widget?$SendToKindle.Widget.init({"content":"article"}):setTimeout(k,500);})();</script>
  </body>
</html>
]]></description>
    <pubDate>No date found.</pubDate>
    <guid>http://dekokun.github.io/posts/2014-10-14.html</guid>
</item>
<item>
    <title>#isucon 2014で11位でした</title>
    <link>http://dekokun.github.io/posts/2014-11-08.html</link>
    <description><![CDATA[<!doctype html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7" lang="ja"> <![endif]-->
<!--[if IE 7]>    <html class="no-js lt-ie9 lt-ie8" lang="ja"> <![endif]-->
<!--[if IE 8]>    <html class="no-js lt-ie9" lang="ja"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="ja"> <!--<![endif]-->
  <head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# article: http://ogp.me/ns/article#">
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <title>#isucon 2014で11位でした</title>
    <meta name="description" content>
    <meta name="author" content>

    <meta name="viewport" content="width=device-width">
    <meta property="fb:app_id" content="351187098330864">
    <meta property="og:type" content="article">
    <meta property="og:image" content="http://dekokun.github.com/img/dekokun.png">
    <meta property="og:title" content="#isucon 2014で11位でした">
    <meta property="og:description" content="@dekokunの技術日記">
    <meta property="og:site_name" content="でこてっくろぐ">
    <meta name="twitter:widgets:csp" content="on">

    <link rel="stylesheet" href="../css/bootstrap.css">
    <link rel="stylesheet" href="../css/bootstrap-responsive.css">
    <link rel="stylesheet" href="../css/style.css">
    <style>
    body {
      padding-top: 60px;
      padding-bottom: 40px;
    }
    </style>
    <link href="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.css" type="text/css" rel="stylesheet">
    <script src="../js/libs/modernizr-2.5.3-respond-1.1.0.min.js"></script>
    <script>
      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

      ga('create', 'UA-39650556-1', 'auto');
      ga('send', 'pageview');
    </script>
  </head>
  <body>
  <!--[if lt IE 7]><p class=chromeframe>Your browser is <em>ancient!</em> <a href="http://browsehappy.com/">Upgrade to a different browser</a> or <a href="http://www.google.com/chromeframe/?redirect=true">install Google Chrome Frame</a> to experience this site.</p><![endif]-->
    <div id="fb-root"></div>
    <script>(function(d, s, id) {
      var js, fjs = d.getElementsByTagName(s)[0];
      if (d.getElementById(id)) return;
      js = d.createElement(s); js.id = id;
      js.src = "//connect.facebook.net/ja_JP/all.js#xfbml=1&appId=351187098330864";
      fjs.parentNode.insertBefore(js, fjs);
      }(document, 'script', 'facebook-jssdk'));
    </script>
    <header>
      <nav class="navbar navbar-fixed-top">
        <div class="navbar-inner">
          <div class="container">
            <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
            </a>
            <a class="brand" href="../index.html">でこてっくろぐ</a>
            <div class="nav-collapse">
              <ul class="nav">
                <li><a href="../index.html">ほーむ</a></li>
                <li><a href="../posts.html">あーかいぶ</a></li>
                <li><a href="../aboutme.html">あばうとみー</a></li>
              </ul>
            </div><!--/.nav-collapse -->
          </div>
        </div>
      </nav>
    </header>

    <div class="container">
      <div class="row">
        <article class="span9">
          <h1>#isucon 2014で11位でした</h1>

<p>by <em><a href="https://twitter.com/dekokun">@dekokun</a></em> on <strong>2014/11/08 23:48</strong></p>

<p>Tagged as: <a href="../tags/contest.html">contest</a>.</p>

<h2 id="概要">概要</h2>
<p><a href="http://isucon.net/">第4回 ISUCON</a>の本選に、参加しました。去年に引き続き予選突破しての本選出場でした。去年の本選は0点での敗北だったのですが、今年は30組中11位で、まぁ、去年よりは良かったよねという感じになりました。</p>
<p><a href="https://twitter.com/ikemonn">@ikemonn</a> と<a href="https://twitter.com/MiuraKatsu">@MiuraKatsu</a>の3人チームでの出場でした。</p>
<h2 id="やったこと">やったこと</h2>
<ul>
<li>フロントのサーバを2台にして、redisに突っ込んでいた動画ファイルはフロントのファイルとして起き、nginxに直接配信させる</li>
<li>残り1台(1コアだったやつ)を、動画以外のデータを保存するためのredisサーバとして使用</li>
<li>他にもいろいろやって、そのおかげでアプリケーション内の遅い部分はどんどん移り変わっていったのですが、何しろボトルネックは別に存在したため、ただ単にどんどんCPUを食わなくなっていっただけでした
<ul>
<li>クライアント側のキャッシュについては全く気付かず、まぁ、なんというか…1位の1/80ほどの得点だったのでした…</li>
</ul></li>
</ul>
<h2 id="思ったこと">思ったこと</h2>
<ul>
<li>ベンチマークにキャッシュさせてリクエスト自体を発生させなくしないとスコアが全然伸びない件、意識の外側から刈り取られた感じがすごかった
<ul>
<li>まさかベンチマークツールがブラウザ同様にキャッシュ機構を持っているとは…</li>
</ul></li>
<li>思考に枠をはめていたなぁと強く思わされた</li>
<li>非常に悔しくて悔しくて…</li>
<li>AMI公開されたら、自分のやった変更をあてた状態でクライアント側のキャッシュ部分だけ書きなおしてどれだけ変わるのか試してみます</li>
</ul>
<h2 id="phpの復権を賭けた戦い">PHPの復権を賭けた戦い</h2>
<p>チーム名は「PHPに花束を」です。</p>
<blockquote class="twitter-tweet" lang="ja"><p>
PHPに花束を、暫定一位をとってます！！！！キテマスキテマス！！！！！！！！！ ドローンゲットだぜ！！！！！ <a href="https://twitter.com/hashtag/isucon?src=hash">#isucon</a>
</p>
— でこくん (@dekokun) <a href="https://twitter.com/dekokun/status/530972038140157953">2014, 11月 8</a>
</blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>

<blockquote class="twitter-tweet" lang="ja"><p>
まだ暫定一位だ！！！PHPに花束を捧げたい！！！！ <a href="https://twitter.com/hashtag/isucon?src=hash">#isucon</a>
</p>
— でこくん (@dekokun) <a href="https://twitter.com/dekokun/status/530985894753206273">2014, 11月 8</a>
</blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>

<blockquote class="twitter-tweet" lang="ja"><p>
よっしゃーなんか知らんが一位に返り咲いた！！！ <a href="https://twitter.com/hashtag/isucon?src=hash">#isucon</a>
</p>
— でこくん (@dekokun) <a href="https://twitter.com/dekokun/status/531002260440903680">2014, 11月 8</a>
</blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>

<blockquote class="twitter-tweet" lang="ja"><p>
暫定一位が「PHPに花束を」だ…これはもしやPHPの復権の時？ <a href="https://twitter.com/hashtag/isucon?src=hash">#isucon</a>
</p>
— Mr. Fiber (@repeatedly) <a href="https://twitter.com/repeatedly/status/531003537375784960">2014, 11月 8</a>
</blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>

<blockquote class="twitter-tweet" lang="ja"><p>
我々のチーム、PHP復権を狙っております。 <a href="https://twitter.com/hashtag/isucon?src=hash">#isucon</a>
</p>
— でこくん (@dekokun) <a href="https://twitter.com/dekokun/status/531009166916067328">2014, 11月 8</a>
</blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>

<blockquote class="twitter-tweet" lang="ja"><p>
PHPの復権ならず…！！
</p>
— でこくん (@dekokun) <a href="https://twitter.com/dekokun/status/531061960196907009">2014, 11月 8</a>
</blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>

<blockquote class="twitter-tweet" lang="ja"><p>
辛すぎてレゴで名前を作った。 <a href="http://t.co/IYo0MdLrZj">pic.twitter.com/IYo0MdLrZj</a>
</p>
— でこくん (@dekokun) <a href="https://twitter.com/dekokun/status/531061395098312704">2014, 11月 8</a>
</blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>

<h2 id="次回">次回</h2>
<ul>
<li>次こそは優勝したいです</li>
</ul>
<blockquote class="twitter-tweet" lang="ja"><p>
まぁ、去年の本戦の結果は0点だったし、無限倍の成長をしたということでここはひとつ…
</p>
— でこくん (@dekokun) <a href="https://twitter.com/dekokun/status/531073933227728896">2014, 11月 8</a>
</blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>




<div id="disqus_thread"></div>
<script type="text/javascript">
    /* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */
    var disqus_shortname = 'dekokun'; // required: replace example with your forum shortname

    /* * * DON'T EDIT BELOW THIS LINE * * */
    (function() {
        var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
        dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js';
        (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
    })();
</script>
<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
<a href="http://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a>

          <ul class="social">
            <li class="kindle"><div class="kindleWidget"><img style="vertical-align:middle;" src="https://d1xnn692s7u6t6.cloudfront.net/white-15.png" /><span style="vertical-align:middle;margin-left:3px;">Send to Kindle</span></div></li>
            <li class="facebook"><div class="fb-like" data-send="false" data-layout="button_count" data-width="100" data-show-faces="true" data-font="arial"></div></li>
            <li class="twitter"><a href="https://twitter.com/share" class="twitter-share-button" data-via="dekokun" data-lang="ja">ツイート</a></li>
            <li class="hatena-bookmark"><a href="http://b.hatena.ne.jp/entry/" class="hatena-bookmark-button" data-hatena-bookmark-layout="standard" title="このエントリーをはてなブックマークに追加"><img src="http://b.st-hatena.com/images/entry-button/button-only.gif" alt="このエントリーをはてなブックマークに追加" width="20" height="20" style="border: none;"></a><script type="text/javascript" src="http://b.st-hatena.com/js/bookmark_button.js" charset="utf-8" async="async"></script></li>
            <li><a data-pocket-label="pocket" data-pocket-count="horizontal" class="pocket-btn" data-lang="en"></a>
            <script type="text/javascript">!function(d,i){if(!d.getElementById(i)){var j=d.createElement("script");j.id=i;j.src="https://widgets.getpocket.com/v1/j/btn.js?v=1";var w=d.getElementById(i);d.body.appendChild(j);}}(document,"pocket-btn-js");</script></li>
          </ul>

        </article>
        <aside class="span3">
          <div class="sidebar-module">
            <div class="title">プロフィール</div>
            <p class="id"><a href="https://twitter.com/dekokun">dekokun</a></p>
            <p><a href="https://twitter.com/dekokun"><img src="../img/dekokun.png" alt="dekokun"></a></p>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.io/";
              Hatena.BookmarkWidget.title = "人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 200;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.com/";
              Hatena.BookmarkWidget.title = "旧人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 0;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module visible-desktop">
            <div class="title">twitter</div>
            <a class="twitter-timeline" data-dnt="true" href="https://twitter.com/dekokun" data-widget-id="306408547573440513">@dekokun からのツイート</a>
            <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
          </div>
          <div class="sidebar-module hidden-phone">
            <div class="title">RSS</div>
            <p><a href="../rss.xml"><img src="../img/rss.gif" alt="rss"></a></p>
          </div>
        </aside> <!-- /span3 -->
      </div> <!-- /row -->
      <footer>
        <p>©<script type="text/javascript">$y=2012;$ny=new Date().getFullYear();document.write($ny>$y?$y+'-'+$ny:$y);</script> <a href="https://twitter.com/dekokun">dekokun</a></p>
      </footer>
    </div> <!-- /container -->

    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script>window.jQuery || document.write('<script src="../js/libs/jquery-1.7.2.min.js"><\/script>')</script>
    <!-- /ツイートボタン -->
  <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>

    <script src="../js/libs/bootstrap/bootstrap.min.js"></script>

    <script src="../js/script.js"></script>
    <script>
      var _gaq=[['_setAccount','UA-XXXXX-X'],['_trackPageview']];
      (function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
      g.src=('https:'==location.protocol?'//ssl':'//www')+'.google-analytics.com/ga.js';
      s.parentNode.insertBefore(g,s)}(document,'script'));
    </script>
    <!-- Code syntax highlight -->
    <script type="text/javascript" src="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.js"></script>
    <script type="text/javascript">
    $(function(){ 
        $('pre').css({
            'overflow-x': 'scroll',
            'background-color': '#f6f6f6',
            'border': '1px dotted #ccc',
            'padding': '0.8em'
        });
        $('pre code').addClass('prettyprint');
        prettyPrint();
    });
    </script>
    <script type="text/javascript" src="https://d1xnn692s7u6t6.cloudfront.net/widget.js"></script>
    <script type="text/javascript">(function k(){window.$SendToKindle&&window.$SendToKindle.Widget?$SendToKindle.Widget.init({"content":"article"}):setTimeout(k,500);})();</script>
  </body>
</html>
]]></description>
    <pubDate>No date found.</pubDate>
    <guid>http://dekokun.github.io/posts/2014-11-08.html</guid>
</item>
<item>
    <title>宣言すればコンピューターがいい感じに解決してくれる未来を目指して~理想の世界と現実の壁~</title>
    <link>http://dekokun.github.io/posts/2014-12-25.html</link>
    <description><![CDATA[<!doctype html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7" lang="ja"> <![endif]-->
<!--[if IE 7]>    <html class="no-js lt-ie9 lt-ie8" lang="ja"> <![endif]-->
<!--[if IE 8]>    <html class="no-js lt-ie9" lang="ja"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="ja"> <!--<![endif]-->
  <head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# article: http://ogp.me/ns/article#">
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <title>宣言すればコンピューターがいい感じに解決してくれる未来を目指して~理想の世界と現実の壁~</title>
    <meta name="description" content>
    <meta name="author" content>

    <meta name="viewport" content="width=device-width">
    <meta property="fb:app_id" content="351187098330864">
    <meta property="og:type" content="article">
    <meta property="og:image" content="http://dekokun.github.com/img/dekokun.png">
    <meta property="og:title" content="宣言すればコンピューターがいい感じに解決してくれる未来を目指して~理想の世界と現実の壁~">
    <meta property="og:description" content="@dekokunの技術日記">
    <meta property="og:site_name" content="でこてっくろぐ">
    <meta name="twitter:widgets:csp" content="on">

    <link rel="stylesheet" href="../css/bootstrap.css">
    <link rel="stylesheet" href="../css/bootstrap-responsive.css">
    <link rel="stylesheet" href="../css/style.css">
    <style>
    body {
      padding-top: 60px;
      padding-bottom: 40px;
    }
    </style>
    <link href="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.css" type="text/css" rel="stylesheet">
    <script src="../js/libs/modernizr-2.5.3-respond-1.1.0.min.js"></script>
    <script>
      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

      ga('create', 'UA-39650556-1', 'auto');
      ga('send', 'pageview');
    </script>
  </head>
  <body>
  <!--[if lt IE 7]><p class=chromeframe>Your browser is <em>ancient!</em> <a href="http://browsehappy.com/">Upgrade to a different browser</a> or <a href="http://www.google.com/chromeframe/?redirect=true">install Google Chrome Frame</a> to experience this site.</p><![endif]-->
    <div id="fb-root"></div>
    <script>(function(d, s, id) {
      var js, fjs = d.getElementsByTagName(s)[0];
      if (d.getElementById(id)) return;
      js = d.createElement(s); js.id = id;
      js.src = "//connect.facebook.net/ja_JP/all.js#xfbml=1&appId=351187098330864";
      fjs.parentNode.insertBefore(js, fjs);
      }(document, 'script', 'facebook-jssdk'));
    </script>
    <header>
      <nav class="navbar navbar-fixed-top">
        <div class="navbar-inner">
          <div class="container">
            <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
            </a>
            <a class="brand" href="../index.html">でこてっくろぐ</a>
            <div class="nav-collapse">
              <ul class="nav">
                <li><a href="../index.html">ほーむ</a></li>
                <li><a href="../posts.html">あーかいぶ</a></li>
                <li><a href="../aboutme.html">あばうとみー</a></li>
              </ul>
            </div><!--/.nav-collapse -->
          </div>
        </div>
      </nav>
    </header>

    <div class="container">
      <div class="row">
        <article class="span9">
          <h1>宣言すればコンピューターがいい感じに解決してくれる未来を目指して~理想の世界と現実の壁~</h1>

<p>by <em><a href="https://twitter.com/dekokun">@dekokun</a></em> on <strong>2014/12/25 00:00</strong></p>

<p>Tagged as: <a href="../tags/ポエム.html">ポエム</a>.</p>

<p><a href="http://qiita.com/advent-calendar/2014/cybird">CYBIRDエンジニア Advent Calendar 2014</a>最終日の<a href="https://twitter.com/dekokun">@dekokun</a>です。 昨日は<a href="http://qiita.com/gotyoooo">@gotyoooo</a>くんの<a href>サーバ障害時のトラブルシューティング ~クリスマスイブでも早く帰ろう~</a>でしたね。彼は新卒2年目なんですけど、新卒2年目でこんな感じで障害要因の絞りこみできているのを見ると、私の若いころとくらべてモノが違うなって思いますね。すごいですね。</p>
<h2 id="今日の内容">今日の内容</h2>
<p>人間は「◯◯がしたい」って願うだけで後は全てコンピュータに任せたい。その未来はどんどん迫ってきている。以下、その例をいくつか挙げます。</p>
<h2 id="ルンバ系の掃除機">ルンバ系の掃除機</h2>
<ul>
<li>ルンバみたいなの買いました。東芝製のトルネオロボっていう名前です。可愛いです。</li>
</ul>
<iframe src="http://rcm-fe.amazon-adsystem.com/e/cm?t=dekokun-22&amp;o=9&amp;p=8&amp;l=as1&amp;asins=B00N2O3KJE&amp;ref=qf_sp_asin_til&amp;fc1=000000&amp;IS2=1&amp;lt1=_blank&amp;m=amazon&amp;lc1=0000FF&amp;bc1=000000&amp;bg1=FFFFFF&amp;f=ifr" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"></iframe>

<ul>
<li>電源を入れてリモコンで「自動で掃除」ボタンを押すだけで部屋全体を勝手にいい感じに掃除してくれます。</li>
<li>もちろん、「どのように動け」みたいなプログラミングを行う必要はないです。ただ「自動で掃除して」とお願いするだけで部屋全体がいい感じに掃除されるのでとてもいいかんじです。</li>
<li>「隅から隅まで圧倒的に綺麗な部屋じゃないとやばい」みたいな人以外は、こいつがいれば基本的にあんまり掃除しなくていいんだろうなと思いました。</li>
</ul>
<h2 id="sql">SQL</h2>
<ul>
<li>SQLは「どんな方法でデータをとってきて」って言わなくても「どんなデータが欲しい」っていうだけでデータをくれます。</li>
<li>上記のように作られているのに「インデックスはってないカラムにクエリ投げるな」とか「どっちが駆動表だと意識しろ」とか、結局DBMSがどのようにデータをとってきているのかを考えなくちゃいけないの完全に人類の知性の敗北っぽいと思います。
<ul>
<li>と言っても実際のところは「小さいデータであればどのようにデータをとってきているかを意識する必要はないが大きいデータではそれは難しかったりして、まぁ程度問題」というのが正しい話ではありますね。</li>
<li>まぁ、Oracleとかの賢いDBMS使って「程度問題の『程度』」のレベルをあげたらいいんじゃないっすか〜みたいな話でもあります。</li>
</ul></li>
<li>多分普通の人が(普通の人って何？という話はあるが)普通にDBを使う分には、十分にいい感じに「どんなデータが欲しい」に答えてくれているようです
<ul>
<li>弊社でSQL書いたりORMでDBアクセスする際は、ちゃんと「どのようにデータを取ってきているか」を意識してくださいね</li>
</ul></li>
</ul>
<h2 id="ライブラリとかそういうの">ライブラリとかそういうの</h2>
<blockquote class="twitter-tweet" lang="ja"><p>
コードの速度は本当に遅いと分かるまで最適化しないみたいなの、理想論ではそういう世界であるべきなんだが結局ORMを適切に使わずN+1問題大量発生とかforの中でinnerHTML変更しまくるとかそういうのはやはり事前に潰さないとねと思うわけですよ。
</p>
— でこくん (@dekokun) <a href="https://twitter.com/dekokun/statuses/502378200467382273">2014, 8月 21</a>
</blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
<blockquote class="twitter-tweet" lang="ja"><p>
ライブラリやフレームワークをより賢くしていく方向で「素直に書くと勝手にその辺りが潰される」という理想の世界を我々が作っていかなくてはいけないとは思っている。
</p>
— でこくん (@dekokun) <a href="https://twitter.com/dekokun/statuses/502378607944028160">2014, 8月 21</a>
</blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
<blockquote class="twitter-tweet" lang="ja"><p>
宣言型がまさに宣言型として動く世の中を。
</p>
— でこくん (@dekokun) <a href="https://twitter.com/dekokun/statuses/502378737405403136">2014, 8月 21</a>
</blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>

<ul>
<li>上記で言っているようなことは、まだまだ人間が頑張らないといけないところ多めだよねって思いますね。ただ、ORMがDBへのアクセスからその結果をオブジェクトに突っ込むまでやってくれてるの、やっぱすごいですよねって思います。</li>
<li>最初の「innerHTML変更しまくるとかそういうのはやはり事前に潰さないとね」とかも、<a href="http://qiita.com/mizchi/items/4d25bc26def1719d52e6">Virtual DOM</a>等の流れや、そもそものブラウザのDOM操作の最適化、高速化などによってそういうことをそこまで考えなくても良い世界が一歩ずつ近づいているなぁとは感じますね。</li>
</ul>
<h2 id="宣言型プログラミング">宣言型プログラミング</h2>
<ul>
<li>手続き型プログラミングと対比されるやつですね</li>
<li>「どのように行うか」ではなく、「何をしたいか」を記述する感じのプログラミングスタイルです。</li>
<li>宣言型プログラミングのスタイル及びそのプログラミングスタイルを支援するためのライブラリやら言語やらが最近熱いようです
<ul>
<li>ただ、例えばfoldlとfoldrとfoldl’の使い分けは？どういう時にfoldl’使うの？え？foldlを使ったほうがいい場面はほぼないって？なんで？「どう動くかを考えれば当然だろ！」みたいな話を考えるにつけ、人生ってのは私が思っていたよりも圧倒的に複雑なものだなぁという思いを新たにしますね。</li>
<li>上記はHaskellを例に出しちゃいましたが、別にHaskellだからどうこうという話ではなく、どのような実装でもある程度のレベルだと何がどう動いているかは考えないといかんよね〜みたいな話でした。</li>
<li>遅延評価の思想とか、初めて知った時には本当に感動したし、その分理想と現実の落差を(どこで何が起きているか全然わからんぞ。みたいな。どこで何が起きているのかも全然わからなくても問題ないようにするのが一番の理想なのだろうが)どう埋めるかの絶望感も高い</li>
</ul></li>
</ul>
<h2 id="結論">結論</h2>
<ul>
<li>今でもある程度理想の世界は現世に現れてきている
<ul>
<li>現代の私達は、たいていの場合において<a href="http://togetter.com/li/675599">マシン語が見えたりCPUの歓声が聞こえたり</a>しなくてもほぼ問題なくプログラミングができる時代に生きているし、ルンバは勝手にある程度綺麗に掃除をしてくれるし、SQLは小さいデータなら中を知らなくてもいい感じに欲しいデータをくれるし、etcetc</li>
</ul></li>
<li>ただ、改良の余地はどれだけでもあるので、我々はそれを更に改良していかなくては！って思います。人間の判断で色々指示を出すとどうしても間違えちゃうので、指示出しは極限までコンピュータに任せたいです。</li>
</ul>
<p>最終的に我々のしごとが全てコンピュータに奪われてくれないかな〜って思います。</p>
<h2 id="cybird-advent-calendar">CYBIRD Advent Calendar</h2>
<ul>
<li>「やりたい」って言ったらみんな賛同してくれて、いい感じにできました。嬉しいです</li>
<li>ブログ書く人、25人集まるかなっていうのもすごく不安だったんだけど、みんな書いてくれて嬉しいです
<ul>
<li>集まらなかったら、「しょうがないから自分たちでブログ書きまくるしかないよね〜」っていう話をしていたけどそんな必要は全くなくて嬉しかったです</li>
<li>私が2回書いてますが、メンバーが集まらなかったというよりは、私が2回書きたかったってだけですね</li>
</ul></li>
<li>たくさんの人が自分の書いたものを世に出す経験をしたっていうのが死ぬほど重要なんだろうなぁと思っている。が、実際のところ、これが弊社にとってどれくらいいい影響を与えるかはよくわかっていないです
<ul>
<li>このブログ群をみて、弊社を知っている人が少しでも増えたのであれば嬉しいです</li>
</ul></li>
<li>弊社CYBIRDは、一緒に働く仲間、コンピュータに人間の仕事をどんどん奪わせたい仲間を絶賛募集しています！！
<ul>
<li>http://www.cybird.co.jp/recruit/</li>
<li>せっかく会社の名前出してブログ書いてるし、どうせなら宣伝入れてみようと思って宣伝入れてみました
<ul>
<li><a href="http://phpcon.php.gr.jp/w/2014/">PHPカンファレンス2014</a>で社名を出して発表してから、なんかもうひたすら社名とアカウントを紐付けまくる感じになっている。いいことも悪いこともたくさんあるだろうなって思います</li>
</ul></li>
</ul></li>
</ul>

<div id="disqus_thread"></div>
<script type="text/javascript">
    /* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */
    var disqus_shortname = 'dekokun'; // required: replace example with your forum shortname

    /* * * DON'T EDIT BELOW THIS LINE * * */
    (function() {
        var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
        dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js';
        (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
    })();
</script>
<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
<a href="http://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a>

          <ul class="social">
            <li class="kindle"><div class="kindleWidget"><img style="vertical-align:middle;" src="https://d1xnn692s7u6t6.cloudfront.net/white-15.png" /><span style="vertical-align:middle;margin-left:3px;">Send to Kindle</span></div></li>
            <li class="facebook"><div class="fb-like" data-send="false" data-layout="button_count" data-width="100" data-show-faces="true" data-font="arial"></div></li>
            <li class="twitter"><a href="https://twitter.com/share" class="twitter-share-button" data-via="dekokun" data-lang="ja">ツイート</a></li>
            <li class="hatena-bookmark"><a href="http://b.hatena.ne.jp/entry/" class="hatena-bookmark-button" data-hatena-bookmark-layout="standard" title="このエントリーをはてなブックマークに追加"><img src="http://b.st-hatena.com/images/entry-button/button-only.gif" alt="このエントリーをはてなブックマークに追加" width="20" height="20" style="border: none;"></a><script type="text/javascript" src="http://b.st-hatena.com/js/bookmark_button.js" charset="utf-8" async="async"></script></li>
            <li><a data-pocket-label="pocket" data-pocket-count="horizontal" class="pocket-btn" data-lang="en"></a>
            <script type="text/javascript">!function(d,i){if(!d.getElementById(i)){var j=d.createElement("script");j.id=i;j.src="https://widgets.getpocket.com/v1/j/btn.js?v=1";var w=d.getElementById(i);d.body.appendChild(j);}}(document,"pocket-btn-js");</script></li>
          </ul>

        </article>
        <aside class="span3">
          <div class="sidebar-module">
            <div class="title">プロフィール</div>
            <p class="id"><a href="https://twitter.com/dekokun">dekokun</a></p>
            <p><a href="https://twitter.com/dekokun"><img src="../img/dekokun.png" alt="dekokun"></a></p>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.io/";
              Hatena.BookmarkWidget.title = "人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 200;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.com/";
              Hatena.BookmarkWidget.title = "旧人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 0;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module visible-desktop">
            <div class="title">twitter</div>
            <a class="twitter-timeline" data-dnt="true" href="https://twitter.com/dekokun" data-widget-id="306408547573440513">@dekokun からのツイート</a>
            <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
          </div>
          <div class="sidebar-module hidden-phone">
            <div class="title">RSS</div>
            <p><a href="../rss.xml"><img src="../img/rss.gif" alt="rss"></a></p>
          </div>
        </aside> <!-- /span3 -->
      </div> <!-- /row -->
      <footer>
        <p>©<script type="text/javascript">$y=2012;$ny=new Date().getFullYear();document.write($ny>$y?$y+'-'+$ny:$y);</script> <a href="https://twitter.com/dekokun">dekokun</a></p>
      </footer>
    </div> <!-- /container -->

    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script>window.jQuery || document.write('<script src="../js/libs/jquery-1.7.2.min.js"><\/script>')</script>
    <!-- /ツイートボタン -->
  <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>

    <script src="../js/libs/bootstrap/bootstrap.min.js"></script>

    <script src="../js/script.js"></script>
    <script>
      var _gaq=[['_setAccount','UA-XXXXX-X'],['_trackPageview']];
      (function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
      g.src=('https:'==location.protocol?'//ssl':'//www')+'.google-analytics.com/ga.js';
      s.parentNode.insertBefore(g,s)}(document,'script'));
    </script>
    <!-- Code syntax highlight -->
    <script type="text/javascript" src="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.js"></script>
    <script type="text/javascript">
    $(function(){ 
        $('pre').css({
            'overflow-x': 'scroll',
            'background-color': '#f6f6f6',
            'border': '1px dotted #ccc',
            'padding': '0.8em'
        });
        $('pre code').addClass('prettyprint');
        prettyPrint();
    });
    </script>
    <script type="text/javascript" src="https://d1xnn692s7u6t6.cloudfront.net/widget.js"></script>
    <script type="text/javascript">(function k(){window.$SendToKindle&&window.$SendToKindle.Widget?$SendToKindle.Widget.init({"content":"article"}):setTimeout(k,500);})();</script>
  </body>
</html>
]]></description>
    <pubDate>No date found.</pubDate>
    <guid>http://dekokun.github.io/posts/2014-12-25.html</guid>
</item>
<item>
    <title>2014年振り返り</title>
    <link>http://dekokun.github.io/posts/2014-12-31.html</link>
    <description><![CDATA[<!doctype html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7" lang="ja"> <![endif]-->
<!--[if IE 7]>    <html class="no-js lt-ie9 lt-ie8" lang="ja"> <![endif]-->
<!--[if IE 8]>    <html class="no-js lt-ie9" lang="ja"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="ja"> <!--<![endif]-->
  <head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# article: http://ogp.me/ns/article#">
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <title>2014年振り返り</title>
    <meta name="description" content>
    <meta name="author" content>

    <meta name="viewport" content="width=device-width">
    <meta property="fb:app_id" content="351187098330864">
    <meta property="og:type" content="article">
    <meta property="og:image" content="http://dekokun.github.com/img/dekokun.png">
    <meta property="og:title" content="2014年振り返り">
    <meta property="og:description" content="@dekokunの技術日記">
    <meta property="og:site_name" content="でこてっくろぐ">
    <meta name="twitter:widgets:csp" content="on">

    <link rel="stylesheet" href="../css/bootstrap.css">
    <link rel="stylesheet" href="../css/bootstrap-responsive.css">
    <link rel="stylesheet" href="../css/style.css">
    <style>
    body {
      padding-top: 60px;
      padding-bottom: 40px;
    }
    </style>
    <link href="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.css" type="text/css" rel="stylesheet">
    <script src="../js/libs/modernizr-2.5.3-respond-1.1.0.min.js"></script>
    <script>
      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

      ga('create', 'UA-39650556-1', 'auto');
      ga('send', 'pageview');
    </script>
  </head>
  <body>
  <!--[if lt IE 7]><p class=chromeframe>Your browser is <em>ancient!</em> <a href="http://browsehappy.com/">Upgrade to a different browser</a> or <a href="http://www.google.com/chromeframe/?redirect=true">install Google Chrome Frame</a> to experience this site.</p><![endif]-->
    <div id="fb-root"></div>
    <script>(function(d, s, id) {
      var js, fjs = d.getElementsByTagName(s)[0];
      if (d.getElementById(id)) return;
      js = d.createElement(s); js.id = id;
      js.src = "//connect.facebook.net/ja_JP/all.js#xfbml=1&appId=351187098330864";
      fjs.parentNode.insertBefore(js, fjs);
      }(document, 'script', 'facebook-jssdk'));
    </script>
    <header>
      <nav class="navbar navbar-fixed-top">
        <div class="navbar-inner">
          <div class="container">
            <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
            </a>
            <a class="brand" href="../index.html">でこてっくろぐ</a>
            <div class="nav-collapse">
              <ul class="nav">
                <li><a href="../index.html">ほーむ</a></li>
                <li><a href="../posts.html">あーかいぶ</a></li>
                <li><a href="../aboutme.html">あばうとみー</a></li>
              </ul>
            </div><!--/.nav-collapse -->
          </div>
        </div>
      </nav>
    </header>

    <div class="container">
      <div class="row">
        <article class="span9">
          <h1>2014年振り返り</h1>

<p>by <em><a href="https://twitter.com/dekokun">@dekokun</a></em> on <strong>2014/12/31 20:15</strong></p>

<p>Tagged as: <a href="../tags/ポエム.html">ポエム</a>.</p>

<p>紅白見ながら今年をまとめてみた</p>
<h2 id="年の抱負">2014年の抱負</h2>
<p>得に何も決めていなかったので、明日(2015/1/1)はちゃんと新年の抱負をブログに書こうと思います。</p>
<h2 id="仕事">仕事</h2>
<h3 id="社内のltイベント">社内のLTイベント</h3>
<ul>
<li>参考(後輩が書いてくれたブログ)：<a href="http://qiita.com/megadreams14/items/5134329738101fd4cea9">CYBIRDの技術者社内交流イベントについて</a></li>
<li>去年から社内で始めたLTイベントの運営トップ的な立場を後輩に禅譲した(禅譲したの、去年の話だったかもしれない)
<ul>
<li>なかなか続かない社内イベント達の中で、継続的に続ける素地を作れてたらいいなと思う</li>
<li>継続的に続くための第一歩として、運営トップ的な立場を後輩に移していくような環境ができたというのは非常に良かったんじゃないかと勝手に自画自賛している</li>
<li>後輩たちが積極的に運営に絡んできてくれたの嬉しかった</li>
</ul></li>
<li>っていうか、そのLTイベント自体、後輩達が最初に盛り上がっていて、その勢いにおされて始まった感じが強いと思っている。弊社の後輩たち、勢いもすごいしエンジニアリング的にもすごいし全体的にすごすぎると思う。私はすぐに負けそう(ってか負けてる部分も多々あると感じる)なので私も頑張ろうと思う</li>
</ul>
<h3 id="去年からやってたプロジェクト">去年からやってたプロジェクト</h3>
<ul>
<li>ひたすらPHPでAPIを作っていた</li>
<li>使用するDBMSの決定、DB設計や使用フレームワークの決定、サーバの自動構築機構等、最初の最初から全て設計をしていった感じで学びが多かった</li>
<li>まぁ、プロジェクトがいろいろあっていろいろあったのだが、いい経験だった</li>
</ul>
<h3 id="今年中盤からやってるプロジェクト">今年中盤からやってるプロジェクト</h3>
<ul>
<li>初めて仕事でブラウザサイドJSを扱うプロジェクトだった</li>
<li>使用するフレームワーク選定等から携わり、いきなり学びばかりであった
<ul>
<li>Backbone.Marionetteを使っている
<ul>
<li>AngularとVueとBackbone.Marionetteをメインに他のもろもろも併せて比較して選んだ</li>
</ul></li>
</ul></li>
<li><a href="http://qiita.com/dekokun/items/598ce49bfac84460d956">なぜBackbone.Modelのchangeイベントが発火しないかについての2つの陥っていがちなパターン</a>のポエム部分に詳しく書いているんだけど、人生初のGUIプログラミングとなり、非常に学びが多い
<ul>
<li>状態管理の複雑さが激しい</li>
</ul></li>
<li>10人ほどの開発要員がいるプロジェクトで設計するというのが初めての経験で、これについての学びが多い。設計とはなにかを考えさせられるいい契機となった</li>
<li>現在進行中のプロジェクトなので、来年も頑張りたいです</li>
<li>このプロジェクトによってJSのもろもろに強く興味が出て、React.jsを触ったりするきっかけもなり、ブログを書いたりもできたので非常に良かったと思う
<ul>
<li><a href="http://qiita.com/dekokun/items/abaaf731c738698016e4">PHPでReact.jsのサーバサイドレンダリング</a></li>
</ul></li>
<li>なお、CSS周りの設計は後輩が全てやっており、私はCSSはほぼ書くことができない</li>
</ul>
<h3 id="会社のadvent-calendar">会社のAdvent Calendar</h3>
<ul>
<li><a href="http://qiita.com/advent-calendar/2014/cybird">CYBIRDエンジニア Advent Calendar 2014</a></li>
<li>やりたいって言ったらいい感じに周りの皆さんも賛同してくれて、やることができた</li>
<li>お祭り感あって良かった</li>
<li>普段技術ブログを書いていないメンバーがたくさんブログ書いてくれたのがすごく嬉しかった</li>
<li>弊社、最近外に発表したりしていく人が増えてきているけど、その勢いをよりつけることができてたらいいなと思う
<ul>
<li>来年は、皆で色々なAdvent Calendarに出陣しくメンバーがたくさん出るといいな〜</li>
</ul></li>
<li>非常に様々なテーマについてのブログが集まり、バラエティ豊かで面白かった</li>
</ul>
<h2 id="仕事以外の技術的な対外活動">仕事以外の技術的な対外活動</h2>
<ul>
<li>今年は去年ほどは勉強会等に参加しなかった感じがある
<ul>
<li>結婚式周り、プロジェクトが忙しいのもあって精神的に廃人に近かったというのもあったな…</li>
</ul></li>
<li>思い入れの強いものだけ紹介</li>
</ul>
<h3 id="cedec-ai-challenge">CEDEC AI CHALLENGE</h3>
<ul>
<li>AIコンテストなんだけど、なんか準優勝して嬉しかった。決勝はかなりの運ゲーだった感じはあるが、まぁ、結果は結果ということで、今後もこういう方面でも頑張って行きたい</li>
<li><a href="http://dekokun.github.io/posts/2014-09-07.html">PHPを使ったり4000円課金したりしてCEDEC AI CHALLENGE 準優勝に至るまでの軌跡</a></li>
<li>似たようなAIプログラミングコンテストが始まっているので、PHP以外の言語で参加したい
<ul>
<li><a href="http://samuraicoding.info/index-jp.html">SamurAI Coding 2014-15</a></li>
<li>決勝進出して我が母校であるところの京大に久しぶりに行きたいですね</li>
</ul></li>
</ul>
<h3 id="isucon2014">ISUCON2014</h3>
<ul>
<li>決勝には進出できたけど11位だった</li>
<li>去年も決勝進出したんだけど、決勝では0点だった。今年はそれよりは進歩を感じる</li>
<li>悔しいし来年こそは勝つ
<ul>
<li>100万円欲しい</li>
</ul></li>
<li>「優勝してDisられがちなPHP使いへのエールにしたい」とかそんなことばかり言っていたがエールはおくれなかった</li>
</ul>
<h3 id="phpカンファレンス2014">PHPカンファレンス2014</h3>
<ul>
<li>LTした</li>
<li>slide: <a href="http://www.slideshare.net/shintarokurachi/phpai">PHPでAIプログラミングコンテスト準優勝するまでの軌跡</a></li>
<li>youtube: <a href="https://www.youtube.com/watch?v=xhssgM_Kpgw&amp;index=8&amp;list=PL55Rz5TsPc_f0Z0Gyj8YErkIobxkVpMrz">LT無差別級 - PHPカンファレンス2014 (メイントラック)</a> 最後の5分間が私</li>
<li>予想外にウケが良くて嬉しかった。社内のLTイベントのおかげで、LTがうまくなっているんだなぁと感じた</li>
<li>妻に見せたら、「普段と比べて早口で普段の良さが出てない」って言われたし、ゆっくり話すのも意識してみてどっちがいいか比べてみたい</li>
</ul>
<h3 id="aws-summit-tokyo-2014">AWS Summit Tokyo 2014</h3>
<ul>
<li>私はなにかをしたわけじゃないんだけど弊社後輩2人が発表してた。すごいなと思った</li>
<li><a href="http://www.slideshare.net/megadreams14/aws-summit-tokyo-2014-tc09">AutoScale×ゲーム ~運用効率化への取り組み</a></li>
<li>そういえば最近Immutable Infrastructureって聞かないなって思います</li>
</ul>
<h3 id="ctmcp勉強会">CTMCP勉強会</h3>
<ul>
<li>http://www.zusaar.com/event/7517008
<ul>
<li>輪読形式の読書会</li>
</ul></li>
<li>初期に何回かと、中期に何回か参加したのだが、一瞬仕事のプロジェクトが大変なことになって半分以上参加できなかった</li>
<li>一旦仕事は一瞬一段落ついたのでまた来年から参加する。発表もする</li>
</ul>
<h2 id="日々の思い">日々の思い</h2>
<ul>
<li>人間が何かを宣言したらコンピュータがなんとかしてくれる世界を目指したい
<ul>
<li><a href="http://dekokun.github.io/posts/2014-12-25.html">宣言すればコンピューターがいい感じに解決してくれる未来を目指して<sub>理想の世界と現実の壁</sub></a></li>
</ul></li>
<li>設計の力で人間を動かしていかなくてはいけない
<ul>
<li>プログラミングとかチームビルディングとかもそうだし、それ以外に、管理会計の力とかそういうのも含めて、人類の目指すべき道だ</li>
</ul></li>
</ul>
<h2 id="私事">私事</h2>
<ul>
<li>5月に結婚式
<ul>
<li>直径50センチほどのくす玉を作るノウハウが身についた。素晴らしい</li>
</ul></li>
<li>5月に新婚旅行でモルディブへ
<ul>
<li>良すぎた。2年に1度くらいは行けるような環境を整えなくてはいけないなという感じがした。金銭的、仕事の休み的に</li>
</ul></li>
</ul>
<h2 id="思い">思い</h2>
<ul>
<li>今年の中頃まで、PHP芸人っぽくなってた
<ul>
<li>来年は別の言語をもっと頑張りたいです</li>
</ul></li>
<li>なんか色々あったけど全体的にいい感じだったと思う
<ul>
<li>年初に「どうしたい」というのを決めていなかったのでこんな適当な振り返りしかできない感</li>
</ul></li>
<li>来年(明日)は抱負を決めよう</li>
</ul>
<p>紅白のゴールデンボンバー、すごかった</p>

<div id="disqus_thread"></div>
<script type="text/javascript">
    /* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */
    var disqus_shortname = 'dekokun'; // required: replace example with your forum shortname

    /* * * DON'T EDIT BELOW THIS LINE * * */
    (function() {
        var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
        dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js';
        (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
    })();
</script>
<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
<a href="http://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a>

          <ul class="social">
            <li class="kindle"><div class="kindleWidget"><img style="vertical-align:middle;" src="https://d1xnn692s7u6t6.cloudfront.net/white-15.png" /><span style="vertical-align:middle;margin-left:3px;">Send to Kindle</span></div></li>
            <li class="facebook"><div class="fb-like" data-send="false" data-layout="button_count" data-width="100" data-show-faces="true" data-font="arial"></div></li>
            <li class="twitter"><a href="https://twitter.com/share" class="twitter-share-button" data-via="dekokun" data-lang="ja">ツイート</a></li>
            <li class="hatena-bookmark"><a href="http://b.hatena.ne.jp/entry/" class="hatena-bookmark-button" data-hatena-bookmark-layout="standard" title="このエントリーをはてなブックマークに追加"><img src="http://b.st-hatena.com/images/entry-button/button-only.gif" alt="このエントリーをはてなブックマークに追加" width="20" height="20" style="border: none;"></a><script type="text/javascript" src="http://b.st-hatena.com/js/bookmark_button.js" charset="utf-8" async="async"></script></li>
            <li><a data-pocket-label="pocket" data-pocket-count="horizontal" class="pocket-btn" data-lang="en"></a>
            <script type="text/javascript">!function(d,i){if(!d.getElementById(i)){var j=d.createElement("script");j.id=i;j.src="https://widgets.getpocket.com/v1/j/btn.js?v=1";var w=d.getElementById(i);d.body.appendChild(j);}}(document,"pocket-btn-js");</script></li>
          </ul>

        </article>
        <aside class="span3">
          <div class="sidebar-module">
            <div class="title">プロフィール</div>
            <p class="id"><a href="https://twitter.com/dekokun">dekokun</a></p>
            <p><a href="https://twitter.com/dekokun"><img src="../img/dekokun.png" alt="dekokun"></a></p>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.io/";
              Hatena.BookmarkWidget.title = "人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 200;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.com/";
              Hatena.BookmarkWidget.title = "旧人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 0;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module visible-desktop">
            <div class="title">twitter</div>
            <a class="twitter-timeline" data-dnt="true" href="https://twitter.com/dekokun" data-widget-id="306408547573440513">@dekokun からのツイート</a>
            <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
          </div>
          <div class="sidebar-module hidden-phone">
            <div class="title">RSS</div>
            <p><a href="../rss.xml"><img src="../img/rss.gif" alt="rss"></a></p>
          </div>
        </aside> <!-- /span3 -->
      </div> <!-- /row -->
      <footer>
        <p>©<script type="text/javascript">$y=2012;$ny=new Date().getFullYear();document.write($ny>$y?$y+'-'+$ny:$y);</script> <a href="https://twitter.com/dekokun">dekokun</a></p>
      </footer>
    </div> <!-- /container -->

    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script>window.jQuery || document.write('<script src="../js/libs/jquery-1.7.2.min.js"><\/script>')</script>
    <!-- /ツイートボタン -->
  <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>

    <script src="../js/libs/bootstrap/bootstrap.min.js"></script>

    <script src="../js/script.js"></script>
    <script>
      var _gaq=[['_setAccount','UA-XXXXX-X'],['_trackPageview']];
      (function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
      g.src=('https:'==location.protocol?'//ssl':'//www')+'.google-analytics.com/ga.js';
      s.parentNode.insertBefore(g,s)}(document,'script'));
    </script>
    <!-- Code syntax highlight -->
    <script type="text/javascript" src="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.js"></script>
    <script type="text/javascript">
    $(function(){ 
        $('pre').css({
            'overflow-x': 'scroll',
            'background-color': '#f6f6f6',
            'border': '1px dotted #ccc',
            'padding': '0.8em'
        });
        $('pre code').addClass('prettyprint');
        prettyPrint();
    });
    </script>
    <script type="text/javascript" src="https://d1xnn692s7u6t6.cloudfront.net/widget.js"></script>
    <script type="text/javascript">(function k(){window.$SendToKindle&&window.$SendToKindle.Widget?$SendToKindle.Widget.init({"content":"article"}):setTimeout(k,500);})();</script>
  </body>
</html>
]]></description>
    <pubDate>No date found.</pubDate>
    <guid>http://dekokun.github.io/posts/2014-12-31.html</guid>
</item>
<item>
    <title>2015年の抱負</title>
    <link>http://dekokun.github.io/posts/2015-01-01.html</link>
    <description><![CDATA[<!doctype html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7" lang="ja"> <![endif]-->
<!--[if IE 7]>    <html class="no-js lt-ie9 lt-ie8" lang="ja"> <![endif]-->
<!--[if IE 8]>    <html class="no-js lt-ie9" lang="ja"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="ja"> <!--<![endif]-->
  <head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# article: http://ogp.me/ns/article#">
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <title>2015年の抱負</title>
    <meta name="description" content>
    <meta name="author" content>

    <meta name="viewport" content="width=device-width">
    <meta property="fb:app_id" content="351187098330864">
    <meta property="og:type" content="article">
    <meta property="og:image" content="http://dekokun.github.com/img/dekokun.png">
    <meta property="og:title" content="2015年の抱負">
    <meta property="og:description" content="@dekokunの技術日記">
    <meta property="og:site_name" content="でこてっくろぐ">
    <meta name="twitter:widgets:csp" content="on">

    <link rel="stylesheet" href="../css/bootstrap.css">
    <link rel="stylesheet" href="../css/bootstrap-responsive.css">
    <link rel="stylesheet" href="../css/style.css">
    <style>
    body {
      padding-top: 60px;
      padding-bottom: 40px;
    }
    </style>
    <link href="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.css" type="text/css" rel="stylesheet">
    <script src="../js/libs/modernizr-2.5.3-respond-1.1.0.min.js"></script>
    <script>
      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

      ga('create', 'UA-39650556-1', 'auto');
      ga('send', 'pageview');
    </script>
  </head>
  <body>
  <!--[if lt IE 7]><p class=chromeframe>Your browser is <em>ancient!</em> <a href="http://browsehappy.com/">Upgrade to a different browser</a> or <a href="http://www.google.com/chromeframe/?redirect=true">install Google Chrome Frame</a> to experience this site.</p><![endif]-->
    <div id="fb-root"></div>
    <script>(function(d, s, id) {
      var js, fjs = d.getElementsByTagName(s)[0];
      if (d.getElementById(id)) return;
      js = d.createElement(s); js.id = id;
      js.src = "//connect.facebook.net/ja_JP/all.js#xfbml=1&appId=351187098330864";
      fjs.parentNode.insertBefore(js, fjs);
      }(document, 'script', 'facebook-jssdk'));
    </script>
    <header>
      <nav class="navbar navbar-fixed-top">
        <div class="navbar-inner">
          <div class="container">
            <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
            </a>
            <a class="brand" href="../index.html">でこてっくろぐ</a>
            <div class="nav-collapse">
              <ul class="nav">
                <li><a href="../index.html">ほーむ</a></li>
                <li><a href="../posts.html">あーかいぶ</a></li>
                <li><a href="../aboutme.html">あばうとみー</a></li>
              </ul>
            </div><!--/.nav-collapse -->
          </div>
        </div>
      </nav>
    </header>

    <div class="container">
      <div class="row">
        <article class="span9">
          <h1>2015年の抱負</h1>

<p>by <em><a href="https://twitter.com/dekokun">@dekokun</a></em> on <strong>2014/01/04 11:37</strong></p>

<p>Tagged as: <a href="../tags/ポエム.html">ポエム</a>.</p>

<p><a href="http://dekokun.github.io/posts/2014-12-31.html">12/31に紅白見ながら書いたブログ</a>に「明日(2015/1/1)はちゃんと新年の抱負をブログに書こうと思います」などと書きましたが1/2になってしまいました。お正月っていろいろな行事が多いですね。頑張って書きます。 その後、1/4になってしまいました。仕事が始まる前には書き上げる</p>
<h2 id="仕事">仕事</h2>
<h3 id="去年からやってるプロジェクト">去年からやってるプロジェクト</h3>
<ul>
<li>リリースする</li>
</ul>
<h3 id="みんなが情報共有するように頑張る">みんなが情報共有するように頑張る</h3>
<ul>
<li>チームメンバーが日報の良さを認識して日報を書くようになる</li>
<li>外を通じての情報共有も皆がすると楽しいので、そっちでも積極的にいい感じになるようやっていきたい。去年のAdvent Calendarみたいな</li>
</ul>
<h3 id="収入を増やす">収入を増やす</h3>
<p>今後子どもを産んだりすることを考えると収入の重要さを痛感するので収入は増やす</p>
<ul>
<li>幸い、最近は会社から求められているものと自分が行いたい方向が一致している感じがするし、とにかく時間はかけずに頑張る</li>
<li>具体的には、社内で勉強会を開いたりする
<ul>
<li>技術への感度も忘れずに</li>
</ul></li>
<li>あと、下にも書いているが、会計への興味が強くなってきていて、これもそのうち役に立つかもなぁと思っている</li>
</ul>
<h3 id="自由な時間を増やす仕事時間を減らす">自由な時間を増やす(仕事時間を減らす)</h3>
<p>最近、かなり仕事一辺倒な生活をしていて、こんなんじゃ人生ダメだという思いが強いのでなんとかする</p>
<ul>
<li>まずは、早起きをして早く会社に行って決まった時間に早く帰るというのを繰り返して早く帰る癖をつけながら徐々に出社時間を遅くしていって勤務時間を減らしていきたい</li>
<li>ポモドーロ・テクニックを使う(ただ、これ、使っているときは非常に調子がいいのに1~2ヶ月経つといつの間にか使わなくなっていっちゃっていて、その理由がまだ良くつかめていないんだよな…何を変えればポモドーロを何ヶ月も続けられるのか…)</li>
</ul>
<h2 id="その他技術とか学びとか系">その他、技術とか学びとか系</h2>
<h3 id="samurai-coding-2014-15"><a href="http://samuraicoding.info/index-jp.html">SamurAI Coding 2014-15</a></h3>
<ul>
<li>決勝進出して我が母校であるところの京大に久しぶりに行きたいですね</li>
</ul>
<h3 id="isucon">ISUCON</h3>
<ul>
<li>今年こそ優勝</li>
<li>ISUCONは優勝するために具体的に何をやるっていうのはあんまりないですが、まぁ、いろいろなものの積み重ねとして優勝したい</li>
</ul>
<h3 id="ctmcp勉強会">CTMCP勉強会</h3>
<ul>
<li>http://www.zusaar.com/event/7517008</li>
<li>前に立って解説する人やる</li>
</ul>
<h3 id="その他外部発表">その他外部発表</h3>
<ul>
<li>3回くらいは外部の勉強会で発表したいです</li>
<li>回数は適当に決めた</li>
</ul>
<h3 id="会計">会計</h3>
<ul>
<li>「設計の力で人間の意思判断を正しくしていく」というのを強く意識し始めた私にとって、管理会計の考え方は非常に強く「学びたい」と思わせるものであった</li>
<li>ものすごい長い歴史を持つ会計学の一旦に触れることは今後の私にとっていい影響を与えるだろうと思われる</li>
<li>手始めに、妻が持っていた「経理以外の人のための日本一やさしくて使える会計の本」を読んだ。門外漢でも非常にわかりやすくて良かった <iframe src="http://rcm-fe.amazon-adsystem.com/e/cm?lt1=_blank&amp;bc1=000000&amp;IS2=1&amp;bg1=FFFFFF&amp;fc1=000000&amp;lc1=0000FF&amp;t=dekokun-22&amp;o=9&amp;p=8&amp;l=as4&amp;m=amazon&amp;f=ifr&amp;ref=ss_til&amp;asins=488759836X" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"></iframe></li>
<li>簿記3級を少し学んでみて、良さそうだったら取得したいと思っている</li>
</ul>
<h3 id="新しい言語">新しい言語</h3>
<ul>
<li>goかscalaで何かを作る</li>
</ul>
<h3 id="ossへのコミット">OSSへのコミット</h3>
<ul>
<li>なんでもいいから30コミットがなんらかのOSSに取り込まれることを目標とする
<ul>
<li>30という数字はなんの根拠もない</li>
</ul></li>
<li>自分で適当にソフトウェア作れば30コミットなんて一瞬やんという話はあるが、まぁそれはそれでいいか…</li>
</ul>
<h2 id="私事">私事</h2>
<h3 id="実家を大切にする">実家を大切にする</h3>
<p>去年結婚して、「隔年でお互いの実家に帰る」みたいにしたけど、なんかそれだと実家が寂しい気がしたので、以下をしたいなと思いました</p>
<ul>
<li>妻は出張などで実家に帰るタイミングが結構あり、そのタイミングで私も実家に帰る</li>
<li>実家は兼業農家なのだが、稲刈りやら田植えの人が必要なタイミングで実家に帰る</li>
<li>父の日、母の日にプレゼントを送る</li>
</ul>
<h3 id="旅行">旅行</h3>
<p>妻が行きたがっているのに去年は私が出不精でそんなに行っていなかったので今年は行く</p>
<ul>
<li>台湾</li>
<li>九州</li>
</ul>
<h2 id="漠然とした思い">漠然とした思い</h2>
<ul>
<li>設計の力で人間を正しい判断に導いていかなくてはならない
<ul>
<li>プログラミングの設計とかチームビルディングとかもそうだし、それ以外に、管理会計の力とかそういうのも含めて、人類の目指すべき道だ</li>
<li>正しい設計というのは、常に変化していくという、設計の設計に関する考えも忘れてはいけない(というかそっちのほうが大切)</li>
</ul></li>
<li>人間が何かを宣言したらコンピュータがなんとかしてくれる世界を目指したい
<ul>
<li><a href="http://dekokun.github.io/posts/2014-12-25.html">宣言すればコンピューターがいい感じに解決してくれる未来を目指して<sub>理想の世界と現実の壁</sub></a></li>
</ul></li>
<li>ただ、Web系で現在必要なソフトウェアについての知識を得てるだけだと悲しいので、なんかWeb以外の何かにも取り組みたい感じはあるが…何か一つくらいWeb系以外の何かに取り組みたいなぁという思い</li>
</ul>
<h2 id="最後に">最後に</h2>
<p>なんかモリモリ多すぎる気はするが、来年の振り返りがどうなるかですね</p>
<h2 id="やらないこと">やらないこと</h2>
<p>2015/05/28 追記</p>
<ul>
<li>Tumblrをみる</li>
<li>アプリゲームをする</li>
</ul>

<div id="disqus_thread"></div>
<script type="text/javascript">
    /* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */
    var disqus_shortname = 'dekokun'; // required: replace example with your forum shortname

    /* * * DON'T EDIT BELOW THIS LINE * * */
    (function() {
        var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
        dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js';
        (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
    })();
</script>
<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
<a href="http://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a>

          <ul class="social">
            <li class="kindle"><div class="kindleWidget"><img style="vertical-align:middle;" src="https://d1xnn692s7u6t6.cloudfront.net/white-15.png" /><span style="vertical-align:middle;margin-left:3px;">Send to Kindle</span></div></li>
            <li class="facebook"><div class="fb-like" data-send="false" data-layout="button_count" data-width="100" data-show-faces="true" data-font="arial"></div></li>
            <li class="twitter"><a href="https://twitter.com/share" class="twitter-share-button" data-via="dekokun" data-lang="ja">ツイート</a></li>
            <li class="hatena-bookmark"><a href="http://b.hatena.ne.jp/entry/" class="hatena-bookmark-button" data-hatena-bookmark-layout="standard" title="このエントリーをはてなブックマークに追加"><img src="http://b.st-hatena.com/images/entry-button/button-only.gif" alt="このエントリーをはてなブックマークに追加" width="20" height="20" style="border: none;"></a><script type="text/javascript" src="http://b.st-hatena.com/js/bookmark_button.js" charset="utf-8" async="async"></script></li>
            <li><a data-pocket-label="pocket" data-pocket-count="horizontal" class="pocket-btn" data-lang="en"></a>
            <script type="text/javascript">!function(d,i){if(!d.getElementById(i)){var j=d.createElement("script");j.id=i;j.src="https://widgets.getpocket.com/v1/j/btn.js?v=1";var w=d.getElementById(i);d.body.appendChild(j);}}(document,"pocket-btn-js");</script></li>
          </ul>

        </article>
        <aside class="span3">
          <div class="sidebar-module">
            <div class="title">プロフィール</div>
            <p class="id"><a href="https://twitter.com/dekokun">dekokun</a></p>
            <p><a href="https://twitter.com/dekokun"><img src="../img/dekokun.png" alt="dekokun"></a></p>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.io/";
              Hatena.BookmarkWidget.title = "人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 200;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.com/";
              Hatena.BookmarkWidget.title = "旧人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 0;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module visible-desktop">
            <div class="title">twitter</div>
            <a class="twitter-timeline" data-dnt="true" href="https://twitter.com/dekokun" data-widget-id="306408547573440513">@dekokun からのツイート</a>
            <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
          </div>
          <div class="sidebar-module hidden-phone">
            <div class="title">RSS</div>
            <p><a href="../rss.xml"><img src="../img/rss.gif" alt="rss"></a></p>
          </div>
        </aside> <!-- /span3 -->
      </div> <!-- /row -->
      <footer>
        <p>©<script type="text/javascript">$y=2012;$ny=new Date().getFullYear();document.write($ny>$y?$y+'-'+$ny:$y);</script> <a href="https://twitter.com/dekokun">dekokun</a></p>
      </footer>
    </div> <!-- /container -->

    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script>window.jQuery || document.write('<script src="../js/libs/jquery-1.7.2.min.js"><\/script>')</script>
    <!-- /ツイートボタン -->
  <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>

    <script src="../js/libs/bootstrap/bootstrap.min.js"></script>

    <script src="../js/script.js"></script>
    <script>
      var _gaq=[['_setAccount','UA-XXXXX-X'],['_trackPageview']];
      (function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
      g.src=('https:'==location.protocol?'//ssl':'//www')+'.google-analytics.com/ga.js';
      s.parentNode.insertBefore(g,s)}(document,'script'));
    </script>
    <!-- Code syntax highlight -->
    <script type="text/javascript" src="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.js"></script>
    <script type="text/javascript">
    $(function(){ 
        $('pre').css({
            'overflow-x': 'scroll',
            'background-color': '#f6f6f6',
            'border': '1px dotted #ccc',
            'padding': '0.8em'
        });
        $('pre code').addClass('prettyprint');
        prettyPrint();
    });
    </script>
    <script type="text/javascript" src="https://d1xnn692s7u6t6.cloudfront.net/widget.js"></script>
    <script type="text/javascript">(function k(){window.$SendToKindle&&window.$SendToKindle.Widget?$SendToKindle.Widget.init({"content":"article"}):setTimeout(k,500);})();</script>
  </body>
</html>
]]></description>
    <pubDate>No date found.</pubDate>
    <guid>http://dekokun.github.io/posts/2015-01-01.html</guid>
</item>
<item>
    <title>Erlang書きはじめた</title>
    <link>http://dekokun.github.io/posts/2015-04-26.html</link>
    <description><![CDATA[<!doctype html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7" lang="ja"> <![endif]-->
<!--[if IE 7]>    <html class="no-js lt-ie9 lt-ie8" lang="ja"> <![endif]-->
<!--[if IE 8]>    <html class="no-js lt-ie9" lang="ja"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="ja"> <!--<![endif]-->
  <head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# article: http://ogp.me/ns/article#">
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <title>Erlang書きはじめた</title>
    <meta name="description" content>
    <meta name="author" content>

    <meta name="viewport" content="width=device-width">
    <meta property="fb:app_id" content="351187098330864">
    <meta property="og:type" content="article">
    <meta property="og:image" content="http://dekokun.github.com/img/dekokun.png">
    <meta property="og:title" content="Erlang書きはじめた">
    <meta property="og:description" content="@dekokunの技術日記">
    <meta property="og:site_name" content="でこてっくろぐ">
    <meta name="twitter:widgets:csp" content="on">

    <link rel="stylesheet" href="../css/bootstrap.css">
    <link rel="stylesheet" href="../css/bootstrap-responsive.css">
    <link rel="stylesheet" href="../css/style.css">
    <style>
    body {
      padding-top: 60px;
      padding-bottom: 40px;
    }
    </style>
    <link href="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.css" type="text/css" rel="stylesheet">
    <script src="../js/libs/modernizr-2.5.3-respond-1.1.0.min.js"></script>
    <script>
      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

      ga('create', 'UA-39650556-1', 'auto');
      ga('send', 'pageview');
    </script>
  </head>
  <body>
  <!--[if lt IE 7]><p class=chromeframe>Your browser is <em>ancient!</em> <a href="http://browsehappy.com/">Upgrade to a different browser</a> or <a href="http://www.google.com/chromeframe/?redirect=true">install Google Chrome Frame</a> to experience this site.</p><![endif]-->
    <div id="fb-root"></div>
    <script>(function(d, s, id) {
      var js, fjs = d.getElementsByTagName(s)[0];
      if (d.getElementById(id)) return;
      js = d.createElement(s); js.id = id;
      js.src = "//connect.facebook.net/ja_JP/all.js#xfbml=1&appId=351187098330864";
      fjs.parentNode.insertBefore(js, fjs);
      }(document, 'script', 'facebook-jssdk'));
    </script>
    <header>
      <nav class="navbar navbar-fixed-top">
        <div class="navbar-inner">
          <div class="container">
            <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
            </a>
            <a class="brand" href="../index.html">でこてっくろぐ</a>
            <div class="nav-collapse">
              <ul class="nav">
                <li><a href="../index.html">ほーむ</a></li>
                <li><a href="../posts.html">あーかいぶ</a></li>
                <li><a href="../aboutme.html">あばうとみー</a></li>
              </ul>
            </div><!--/.nav-collapse -->
          </div>
        </div>
      </nav>
    </header>

    <div class="container">
      <div class="row">
        <article class="span9">
          <h1>Erlang書きはじめた</h1>

<p>by <em><a href="https://twitter.com/dekokun">@dekokun</a></em> on <strong>2015/04/26 22:26</strong></p>

<p>Tagged as: <a href="../tags/Erlang.html">Erlang</a>.</p>

<p>すごいErlang本を1ヶ月くらいかけてひと通り読み終わったので、何か作らにゃいかんと思っていたら社内でWebSocketのリアルタイムほげほげ系開発ツールの話が出てきたため、一旦作ってみるかという感じでまずはWebSocketを使って云々なやつをさっきから作り始めた。</p>
<p>まだ1時間くらいの進捗だけ(というよりは、ほとんど何も進んでいない)だが、かなり雑にハマったことを以下に記述する。</p>
<h2 id="参考にしたもの">参考にしたもの</h2>
<ul>
<li><a href="http://www.google.co.jp/url?sa=t&amp;rct=j&amp;q=&amp;esrc=s&amp;source=web&amp;cd=1&amp;ved=0CB8QFjAA&amp;url=http://www.amazon.co.jp/%E3%81%99%E3%81%94%E3%81%84Erlang%E3%82%86%E3%81%8B%E3%81%84%E3%81%AB%E5%AD%A6%E3%81%BC%E3%81%86-Fred-Hebert/dp/4274069125&amp;ei=5Og8Vc_zM4K5mwWB0oHQCA&amp;usg=AFQjCNEZHrq06TFgh4Ojj7sx8dPQRjKtbQ&amp;sig2=73m-9UP9uLSPkri56S7d5g&amp;bvm=bv.91665533,d.dGY">すごいErlangゆかいに学ぼう!</a></li>
<li><a href="http://clina.jp/blog/cowboy-websocket.html">Erlang WebサーバCowboy - WebSocket編</a></li>
</ul>
<p>すごいErlang本、すごいHaskell本と比べても非常に情報量が多く、実践的な内容が大量にあって素敵だった。</p>
<iframe src="http://rcm-fe.amazon-adsystem.com/e/cm?lt1=_blank&amp;bc1=000000&amp;IS2=1&amp;bg1=FFFFFF&amp;fc1=000000&amp;lc1=0000FF&amp;t=dekokun-22&amp;o=9&amp;p=8&amp;l=as1&amp;m=amazon&amp;f=ifr&amp;ref=qf_sp_asin_til&amp;asins=4274069125" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"></iframe>

<h2 id="ハマった点">ハマった点</h2>
<p>初めてのErlangなのですが、なんかよくわからんところでよくコケている</p>
<p>参考URL(<a href="http://clina.jp/blog/cowboy-websocket.html">Erlang WebサーバCowboy - WebSocket編</a>)にweb socketのサンプルの作り方があったのでそれ通りプログラムを作成したんだけど、makeしても参考URLに記載の実行コマンド、<code>./_rel/message_wall_release/bin/message_wall_release</code>なぞというファイルは存在しない。何が起きているのかよくわからんかったのですが、しょうがないので以下のように起動していた。 <code>erl -pa message_wall/ebin message_wall/deps/*/ebin</code> -&gt; <code>{ok, _} = application:ensure_all_started(message_wall).</code></p>
<p>なお、最初はmessage_wallディレクトリ内で上記erlコマンドを実行したりしていたんだけど、“priv_dirが存在しねぇぜ”エラー(Can’t resolve the priv_dir of application message_wall)が出てて、そういえばディレクトリ構造大切だったねと思い出して一つ上のディレクトリで起動したらうまくいった。デバッグの過程で<code>code:priv_dir/1</code>を覚えた。</p>
<p>後でMakefile(erlang.mk)みてたらbootstrap-relターゲットがあったので<code>make bootstrap-rel</code>打ってみたらmakeで<code>./_rel/message_wall_release/bin/message_wall_release</code> ができてた。めでたい。</p>
<h2 id="感想">感想</h2>
<p>この雑な記事、感想も何もないのですが、まぁ、上記「WebSocketのリアルタイムほげほげ系開発ツールの話」が続く限りは今後も制作過程を書いていけたらと思います。多分。</p>
<p>ここ数週間は、は会社でひたすらChefのcookbookを書いてはサーバを構築していて、それも非常に楽しいのですがプログラムを書くのも好きです(まだこの段階では写経をして動く段階まで持っていっただけだけど)</p>

<div id="disqus_thread"></div>
<script type="text/javascript">
    /* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */
    var disqus_shortname = 'dekokun'; // required: replace example with your forum shortname

    /* * * DON'T EDIT BELOW THIS LINE * * */
    (function() {
        var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
        dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js';
        (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
    })();
</script>
<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
<a href="http://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a>

          <ul class="social">
            <li class="kindle"><div class="kindleWidget"><img style="vertical-align:middle;" src="https://d1xnn692s7u6t6.cloudfront.net/white-15.png" /><span style="vertical-align:middle;margin-left:3px;">Send to Kindle</span></div></li>
            <li class="facebook"><div class="fb-like" data-send="false" data-layout="button_count" data-width="100" data-show-faces="true" data-font="arial"></div></li>
            <li class="twitter"><a href="https://twitter.com/share" class="twitter-share-button" data-via="dekokun" data-lang="ja">ツイート</a></li>
            <li class="hatena-bookmark"><a href="http://b.hatena.ne.jp/entry/" class="hatena-bookmark-button" data-hatena-bookmark-layout="standard" title="このエントリーをはてなブックマークに追加"><img src="http://b.st-hatena.com/images/entry-button/button-only.gif" alt="このエントリーをはてなブックマークに追加" width="20" height="20" style="border: none;"></a><script type="text/javascript" src="http://b.st-hatena.com/js/bookmark_button.js" charset="utf-8" async="async"></script></li>
            <li><a data-pocket-label="pocket" data-pocket-count="horizontal" class="pocket-btn" data-lang="en"></a>
            <script type="text/javascript">!function(d,i){if(!d.getElementById(i)){var j=d.createElement("script");j.id=i;j.src="https://widgets.getpocket.com/v1/j/btn.js?v=1";var w=d.getElementById(i);d.body.appendChild(j);}}(document,"pocket-btn-js");</script></li>
          </ul>

        </article>
        <aside class="span3">
          <div class="sidebar-module">
            <div class="title">プロフィール</div>
            <p class="id"><a href="https://twitter.com/dekokun">dekokun</a></p>
            <p><a href="https://twitter.com/dekokun"><img src="../img/dekokun.png" alt="dekokun"></a></p>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.io/";
              Hatena.BookmarkWidget.title = "人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 200;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.com/";
              Hatena.BookmarkWidget.title = "旧人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 0;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module visible-desktop">
            <div class="title">twitter</div>
            <a class="twitter-timeline" data-dnt="true" href="https://twitter.com/dekokun" data-widget-id="306408547573440513">@dekokun からのツイート</a>
            <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
          </div>
          <div class="sidebar-module hidden-phone">
            <div class="title">RSS</div>
            <p><a href="../rss.xml"><img src="../img/rss.gif" alt="rss"></a></p>
          </div>
        </aside> <!-- /span3 -->
      </div> <!-- /row -->
      <footer>
        <p>©<script type="text/javascript">$y=2012;$ny=new Date().getFullYear();document.write($ny>$y?$y+'-'+$ny:$y);</script> <a href="https://twitter.com/dekokun">dekokun</a></p>
      </footer>
    </div> <!-- /container -->

    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script>window.jQuery || document.write('<script src="../js/libs/jquery-1.7.2.min.js"><\/script>')</script>
    <!-- /ツイートボタン -->
  <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>

    <script src="../js/libs/bootstrap/bootstrap.min.js"></script>

    <script src="../js/script.js"></script>
    <script>
      var _gaq=[['_setAccount','UA-XXXXX-X'],['_trackPageview']];
      (function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
      g.src=('https:'==location.protocol?'//ssl':'//www')+'.google-analytics.com/ga.js';
      s.parentNode.insertBefore(g,s)}(document,'script'));
    </script>
    <!-- Code syntax highlight -->
    <script type="text/javascript" src="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.js"></script>
    <script type="text/javascript">
    $(function(){ 
        $('pre').css({
            'overflow-x': 'scroll',
            'background-color': '#f6f6f6',
            'border': '1px dotted #ccc',
            'padding': '0.8em'
        });
        $('pre code').addClass('prettyprint');
        prettyPrint();
    });
    </script>
    <script type="text/javascript" src="https://d1xnn692s7u6t6.cloudfront.net/widget.js"></script>
    <script type="text/javascript">(function k(){window.$SendToKindle&&window.$SendToKindle.Widget?$SendToKindle.Widget.init({"content":"article"}):setTimeout(k,500);})();</script>
  </body>
</html>
]]></description>
    <pubDate>No date found.</pubDate>
    <guid>http://dekokun.github.io/posts/2015-04-26.html</guid>
</item>
<item>
    <title>Erlangで一旦何か作ってみた</title>
    <link>http://dekokun.github.io/posts/2015-05-10.html</link>
    <description><![CDATA[<!doctype html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7" lang="ja"> <![endif]-->
<!--[if IE 7]>    <html class="no-js lt-ie9 lt-ie8" lang="ja"> <![endif]-->
<!--[if IE 8]>    <html class="no-js lt-ie9" lang="ja"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="ja"> <!--<![endif]-->
  <head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# article: http://ogp.me/ns/article#">
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <title>Erlangで一旦何か作ってみた</title>
    <meta name="description" content>
    <meta name="author" content>

    <meta name="viewport" content="width=device-width">
    <meta property="fb:app_id" content="351187098330864">
    <meta property="og:type" content="article">
    <meta property="og:image" content="http://dekokun.github.com/img/dekokun.png">
    <meta property="og:title" content="Erlangで一旦何か作ってみた">
    <meta property="og:description" content="@dekokunの技術日記">
    <meta property="og:site_name" content="でこてっくろぐ">
    <meta name="twitter:widgets:csp" content="on">

    <link rel="stylesheet" href="../css/bootstrap.css">
    <link rel="stylesheet" href="../css/bootstrap-responsive.css">
    <link rel="stylesheet" href="../css/style.css">
    <style>
    body {
      padding-top: 60px;
      padding-bottom: 40px;
    }
    </style>
    <link href="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.css" type="text/css" rel="stylesheet">
    <script src="../js/libs/modernizr-2.5.3-respond-1.1.0.min.js"></script>
    <script>
      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

      ga('create', 'UA-39650556-1', 'auto');
      ga('send', 'pageview');
    </script>
  </head>
  <body>
  <!--[if lt IE 7]><p class=chromeframe>Your browser is <em>ancient!</em> <a href="http://browsehappy.com/">Upgrade to a different browser</a> or <a href="http://www.google.com/chromeframe/?redirect=true">install Google Chrome Frame</a> to experience this site.</p><![endif]-->
    <div id="fb-root"></div>
    <script>(function(d, s, id) {
      var js, fjs = d.getElementsByTagName(s)[0];
      if (d.getElementById(id)) return;
      js = d.createElement(s); js.id = id;
      js.src = "//connect.facebook.net/ja_JP/all.js#xfbml=1&appId=351187098330864";
      fjs.parentNode.insertBefore(js, fjs);
      }(document, 'script', 'facebook-jssdk'));
    </script>
    <header>
      <nav class="navbar navbar-fixed-top">
        <div class="navbar-inner">
          <div class="container">
            <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
            </a>
            <a class="brand" href="../index.html">でこてっくろぐ</a>
            <div class="nav-collapse">
              <ul class="nav">
                <li><a href="../index.html">ほーむ</a></li>
                <li><a href="../posts.html">あーかいぶ</a></li>
                <li><a href="../aboutme.html">あばうとみー</a></li>
              </ul>
            </div><!--/.nav-collapse -->
          </div>
        </div>
      </nav>
    </header>

    <div class="container">
      <div class="row">
        <article class="span9">
          <h1>Erlangで一旦何か作ってみた</h1>

<p>by <em><a href="https://twitter.com/dekokun">@dekokun</a></em> on <strong>2015/05/10 15:46</strong></p>

<p>Tagged as: <a href="../tags/Erlang.html">Erlang</a>, <a href="../tags/WebSocket.html">WebSocket</a>, <a href="../tags/Heroku.html">Heroku</a>.</p>

<p>前回のブログ「<a href="http://dekokun.github.io/posts/2015-04-26.html">Erlang書きはじめた</a>」で何か作っていたと思いますが、一旦雑ながらもそれっぽいものができたので公開します。</p>
<h2 id="何作ったの">何作ったの？</h2>
<p>Markdownを入力するとそれをレンダリングしたものが表示され、同じページを開いている他の人のところにも反映されて、同時編集っぽいことが出来る感じです。 まぁ、よくあるやつの超機能劣化バージョンっていう感じです。</p>
<ul>
<li>動いてるやつ: <a href="http://erl-editor.herokuapp.com/">erlang editor</a></li>
</ul>
<p>2つのタブで上記ページを開いて適当に編集するともうひとつのタブに即時反映されていくのが見えるはずです</p>
<ul>
<li>github: <a href="https://github.com/dekokun/erl_editor">dekokun/erl_editor</a></li>
</ul>
<p>サーバサイドはErlang + Cowboyで静的ページ配信及びWebsocketサーバとして動いており、クライアントサイドはReact.jsでマークダウン変換する感じです</p>
<h2 id="使っているもの-ライブラリとか言語とかpaasとか">使っているもの ライブラリとか言語とかPaaSとか</h2>
<h3 id="サーバサイド">サーバサイド</h3>
<ul>
<li>Erlang
<ul>
<li><a href="https://github.com/ninenines/cowboy">Cowboy</a></li>
</ul></li>
<li>Heroku</li>
</ul>
<h3 id="クライアントサイド">クライアントサイド</h3>
<ul>
<li>JavaScript
<ul>
<li><a href="https://github.com/facebook/react">React</a></li>
<li><a href="https://github.com/mizchi/md2react">md2react</a>
<ul>
<li>md2reactのplaygroundをほぼそのまま使わせてもらっています</li>
</ul></li>
<li><a href="http://browserify.org/">browserify</a></li>
<li><a href="http://coffeescript.org/">CoffeeScript</a>
<ul>
<li>md2reactのplaygroundがcoffeeで書かれていたので全部をそのままcoffeeで書きました</li>
<li>久しぶりに三項演算子の罠にハマった。coffeeには三項演算子はないのにエラーにならない。恐ろしい。if then elseを使おう</li>
</ul></li>
<li><a href="https://github.com/twada/licensify">licensify</a>
<ul>
<li>後から追加。browserifyで結合されたファイルの先頭にnpmでインストールされたライブラリのライセンスを埋め込んでくれる</li>
</ul></li>
</ul></li>
</ul>
<h2 id="大変だったところ">大変だったところ</h2>
<ul>
<li>HerokuでErlang動かすの、少し詰まると一気にどうやればいいのか全然わからなくなって大変だった。code:priv_dir/1が{error, bad_name}返すなぁとか、そもそもcompileできないなぁとか
<ul>
<li>結果、依存ライブラリの情報がrebar.configとMakefileに重複している…</li>
<li><a href="https://github.com/ninenines/erlang.mk">erlang.mk</a>ファイルを使っていて、そもそもErlangがどうやってcompileされてリリースまで行っているのかもよくわからず、すごいErlang本のリリースの章を読みなおしたりしていた</li>
<li>手元のforemanでは動くのにherokuでは動かんなぁとかもあって厳しかった。</li>
<li><a href="https://github.com/6/heroku-erlang-example">heroku-erlang-example</a>や<a href="http://voluntas.hatenablog.com/entry/20111218/1324167999">Heroku 上で WebMachine (Erlang) を動かす</a>を参考にさせていただきました。安心のvoluntasさんブログ</li>
</ul></li>
<li>erlang自体は、何も考えずに「とにかく動けばいい」というスタンスで全く以って大したことを行っていないためそんなに大変なことはなかった
<ul>
<li>コードをupdateする際にプロセスを殺さずにupdateするとかそういうことは一切やっていないため、まぁ、なんでErlang使っているのみたいなところはある</li>
<li>あと、負荷試験なども全くやっていないのでどんな問題が起き得るかも分かっていない</li>
</ul></li>
</ul>
<h2 id="herokuでの学び">Herokuでの学び</h2>
<ul>
<li>Procfileのデバッグにはforemanを使おう</li>
<li>複数のbuildpackを使用したいときは<a href="https://github.com/ddollar/heroku-buildpack-multi">buildpack-multi</a>を使おう</li>
</ul>
<h2 id="雑なところ">雑なところ</h2>
<ul>
<li>編集対象のルーム的なやつが1つしかない</li>
<li>Markdownを複数人で同時に編集した場合、他の人の編集内容を適用するアルゴリズムが「全てを送り、送られてきた全てをそのまま上書きする」というもののため、盛大に変更内容がバッティングしすぐにめちゃくちゃになる。ちゃんと差分を送るようにしないとダメだ
<ul>
<li>差分、せっかくReact使っているんだし、実はReactの差分DOMをおくればいいんじゃないかという気もしたがそれをちゃんと動かすとするとhtmlからmarkdownに変換するやつも必要になったりするよねー
<ul>
<li>そもそも差分を外から取り出せるのかとか、差分がJSONで表せるのかとかもまだ調べてないですが</li>
</ul></li>
</ul></li>
<li>他の人の編集によってMarkdownが変更された際にキャレット位置を保持するように少し頑張りましたが、雑なのでイマイチな動きをします。textareaの先頭からなん文字目かを保持してその位置に戻しているため、キャレット位置より手前を編集されると死ぬ</li>
<li>データはETSがメモリ上に保持しているだけなのでいとも簡単にデータが消える</li>
<li>あと、妻のAndroid端末で試してみたら動かなかった</li>
</ul>
<h2 id="感想">感想</h2>
<p>作っているものの先にはそんなに可能性が感じられないので、このプログラムはこれからは特に進展はないと思う。 差分解決アルゴリズムだけちょっとなんとかしたい感じはある</p>
<p>今日は結婚一年目です。八芳園で結婚式を挙げたのですが、アニュアルレターっていう、毎年夫婦がそれぞれお互いへのメッセージを書いていく本をもらったので今年も書きました。 50年分あります。50歳まで、いやもっと仲良く過ごせるといいですね。</p>
<p>これから、八芳園で夕ごはん食べていきます。</p>

<div id="disqus_thread"></div>
<script type="text/javascript">
    /* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */
    var disqus_shortname = 'dekokun'; // required: replace example with your forum shortname

    /* * * DON'T EDIT BELOW THIS LINE * * */
    (function() {
        var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
        dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js';
        (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
    })();
</script>
<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
<a href="http://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a>

          <ul class="social">
            <li class="kindle"><div class="kindleWidget"><img style="vertical-align:middle;" src="https://d1xnn692s7u6t6.cloudfront.net/white-15.png" /><span style="vertical-align:middle;margin-left:3px;">Send to Kindle</span></div></li>
            <li class="facebook"><div class="fb-like" data-send="false" data-layout="button_count" data-width="100" data-show-faces="true" data-font="arial"></div></li>
            <li class="twitter"><a href="https://twitter.com/share" class="twitter-share-button" data-via="dekokun" data-lang="ja">ツイート</a></li>
            <li class="hatena-bookmark"><a href="http://b.hatena.ne.jp/entry/" class="hatena-bookmark-button" data-hatena-bookmark-layout="standard" title="このエントリーをはてなブックマークに追加"><img src="http://b.st-hatena.com/images/entry-button/button-only.gif" alt="このエントリーをはてなブックマークに追加" width="20" height="20" style="border: none;"></a><script type="text/javascript" src="http://b.st-hatena.com/js/bookmark_button.js" charset="utf-8" async="async"></script></li>
            <li><a data-pocket-label="pocket" data-pocket-count="horizontal" class="pocket-btn" data-lang="en"></a>
            <script type="text/javascript">!function(d,i){if(!d.getElementById(i)){var j=d.createElement("script");j.id=i;j.src="https://widgets.getpocket.com/v1/j/btn.js?v=1";var w=d.getElementById(i);d.body.appendChild(j);}}(document,"pocket-btn-js");</script></li>
          </ul>

        </article>
        <aside class="span3">
          <div class="sidebar-module">
            <div class="title">プロフィール</div>
            <p class="id"><a href="https://twitter.com/dekokun">dekokun</a></p>
            <p><a href="https://twitter.com/dekokun"><img src="../img/dekokun.png" alt="dekokun"></a></p>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.io/";
              Hatena.BookmarkWidget.title = "人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 200;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.com/";
              Hatena.BookmarkWidget.title = "旧人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 0;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module visible-desktop">
            <div class="title">twitter</div>
            <a class="twitter-timeline" data-dnt="true" href="https://twitter.com/dekokun" data-widget-id="306408547573440513">@dekokun からのツイート</a>
            <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
          </div>
          <div class="sidebar-module hidden-phone">
            <div class="title">RSS</div>
            <p><a href="../rss.xml"><img src="../img/rss.gif" alt="rss"></a></p>
          </div>
        </aside> <!-- /span3 -->
      </div> <!-- /row -->
      <footer>
        <p>©<script type="text/javascript">$y=2012;$ny=new Date().getFullYear();document.write($ny>$y?$y+'-'+$ny:$y);</script> <a href="https://twitter.com/dekokun">dekokun</a></p>
      </footer>
    </div> <!-- /container -->

    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script>window.jQuery || document.write('<script src="../js/libs/jquery-1.7.2.min.js"><\/script>')</script>
    <!-- /ツイートボタン -->
  <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>

    <script src="../js/libs/bootstrap/bootstrap.min.js"></script>

    <script src="../js/script.js"></script>
    <script>
      var _gaq=[['_setAccount','UA-XXXXX-X'],['_trackPageview']];
      (function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
      g.src=('https:'==location.protocol?'//ssl':'//www')+'.google-analytics.com/ga.js';
      s.parentNode.insertBefore(g,s)}(document,'script'));
    </script>
    <!-- Code syntax highlight -->
    <script type="text/javascript" src="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.js"></script>
    <script type="text/javascript">
    $(function(){ 
        $('pre').css({
            'overflow-x': 'scroll',
            'background-color': '#f6f6f6',
            'border': '1px dotted #ccc',
            'padding': '0.8em'
        });
        $('pre code').addClass('prettyprint');
        prettyPrint();
    });
    </script>
    <script type="text/javascript" src="https://d1xnn692s7u6t6.cloudfront.net/widget.js"></script>
    <script type="text/javascript">(function k(){window.$SendToKindle&&window.$SendToKindle.Widget?$SendToKindle.Widget.init({"content":"article"}):setTimeout(k,500);})();</script>
  </body>
</html>
]]></description>
    <pubDate>No date found.</pubDate>
    <guid>http://dekokun.github.io/posts/2015-05-10.html</guid>
</item>
<item>
    <title>ここ半年の振り返り</title>
    <link>http://dekokun.github.io/posts/2015-06-01.html</link>
    <description><![CDATA[<!doctype html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7" lang="ja"> <![endif]-->
<!--[if IE 7]>    <html class="no-js lt-ie9 lt-ie8" lang="ja"> <![endif]-->
<!--[if IE 8]>    <html class="no-js lt-ie9" lang="ja"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="ja"> <!--<![endif]-->
  <head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# article: http://ogp.me/ns/article#">
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <title>ここ半年の振り返り</title>
    <meta name="description" content>
    <meta name="author" content>

    <meta name="viewport" content="width=device-width">
    <meta property="fb:app_id" content="351187098330864">
    <meta property="og:type" content="article">
    <meta property="og:image" content="http://dekokun.github.com/img/dekokun.png">
    <meta property="og:title" content="ここ半年の振り返り">
    <meta property="og:description" content="@dekokunの技術日記">
    <meta property="og:site_name" content="でこてっくろぐ">
    <meta name="twitter:widgets:csp" content="on">

    <link rel="stylesheet" href="../css/bootstrap.css">
    <link rel="stylesheet" href="../css/bootstrap-responsive.css">
    <link rel="stylesheet" href="../css/style.css">
    <style>
    body {
      padding-top: 60px;
      padding-bottom: 40px;
    }
    </style>
    <link href="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.css" type="text/css" rel="stylesheet">
    <script src="../js/libs/modernizr-2.5.3-respond-1.1.0.min.js"></script>
    <script>
      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

      ga('create', 'UA-39650556-1', 'auto');
      ga('send', 'pageview');
    </script>
  </head>
  <body>
  <!--[if lt IE 7]><p class=chromeframe>Your browser is <em>ancient!</em> <a href="http://browsehappy.com/">Upgrade to a different browser</a> or <a href="http://www.google.com/chromeframe/?redirect=true">install Google Chrome Frame</a> to experience this site.</p><![endif]-->
    <div id="fb-root"></div>
    <script>(function(d, s, id) {
      var js, fjs = d.getElementsByTagName(s)[0];
      if (d.getElementById(id)) return;
      js = d.createElement(s); js.id = id;
      js.src = "//connect.facebook.net/ja_JP/all.js#xfbml=1&appId=351187098330864";
      fjs.parentNode.insertBefore(js, fjs);
      }(document, 'script', 'facebook-jssdk'));
    </script>
    <header>
      <nav class="navbar navbar-fixed-top">
        <div class="navbar-inner">
          <div class="container">
            <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
            </a>
            <a class="brand" href="../index.html">でこてっくろぐ</a>
            <div class="nav-collapse">
              <ul class="nav">
                <li><a href="../index.html">ほーむ</a></li>
                <li><a href="../posts.html">あーかいぶ</a></li>
                <li><a href="../aboutme.html">あばうとみー</a></li>
              </ul>
            </div><!--/.nav-collapse -->
          </div>
        </div>
      </nav>
    </header>

    <div class="container">
      <div class="row">
        <article class="span9">
          <h1>ここ半年の振り返り</h1>

<p>by <em><a href="https://twitter.com/dekokun">@dekokun</a></em> on <strong>2015/06/01 15:46</strong></p>

<p>Tagged as: <a href="../tags/ポエム.html">ポエム</a>.</p>

<p>1月に<a href="http://dekokun.github.io/posts/2015-01-01.html">2015年の豊富</a>というブログを書いてからほぼ半年が経ちました。ので、半年たった現状を、目標と照らし合わせながらザクっと振り返ってみます。</p>
<h2 id="仕事">仕事</h2>
<h3 id="去年からやってたプロジェクト">去年からやってたプロジェクト</h3>
<ul>
<li>リリースできました。めでたい</li>
<li>ただ、その過程で、あまりにも心身をすり減らしすぎたみたいなのはありますね</li>
</ul>
<h3 id="みんなが情報共有するように頑張る">みんなが情報共有するように頑張る</h3>
<ul>
<li>チームの皆の協力もあり、チームの皆が日報を書くようになりました。めでたい</li>
<li>対外的な発表等については、去年のAdvent Calendar以降は特に私は何も働きかけてはいないですが、皆さんAWS Summitに登壇するなど、いろいろと発表されていましたね</li>
</ul>
<h3 id="収入を増やす">収入を増やす</h3>
<ul>
<li>上司の方が頑張ってくれて、収入も増えました。めでたい。</li>
</ul>
<h3 id="自由な時間を増やす仕事時間を減らす">自由な時間を増やす(仕事時間を減らす)</h3>
<ul>
<li>前半は自由時間らしきものがほとんどなかったですが、後半はその分たくさん休みをもらうなど、自由な時間が増えて良かったです</li>
<li>Tasukumaが結構時間管理に活躍している</li>
</ul>
<h2 id="その他技術とか学びとか系">その他、技術とか学びとか系</h2>
<h3 id="samurai-coding-2014-15">SamurAI Coding 2014-15</h3>
<ul>
<li>決勝進出できず。決勝進出できるのは確か上位12名で、私は19位でした…
<ul>
<li>http://arena.ai-comp.net/contests/11</li>
</ul></li>
</ul>
<h3 id="isucon">ISUCON</h3>
<ul>
<li>今年こそは優勝する</li>
</ul>
<h3 id="ctmcp勉強会">CTMCP勉強会</h3>
<ul>
<li>前半、仕事で精神及び生活がめちゃくちゃな状態になって、全く参加しなくなってしまったんですよね…残念…</li>
</ul>
<h3 id="その他外部発表">その他外部発表</h3>
<ul>
<li>まだ外部の勉強会、1度も発表してないな。やばいな</li>
</ul>
<h3 id="会計">会計</h3>
<ul>
<li>結局、「<a href="http://www.amazon.co.jp/gp/product/B00C67XWAU/ref=as_li_qf_sp_asin_tl?ie=UTF8&amp;camp=247&amp;creative=1211&amp;creativeASIN=B00C67XWAU&amp;linkCode=as2&amp;tag=dekokun-22">経理以外の人のための　日本一やさしくて使える会計の本 (ディスカヴァー携書)</a><img src="http://ir-jp.amazon-adsystem.com/e/ir?t=dekokun-22&amp;l=as2&amp;o=9&amp;a=B00C67XWAU" width="1" height="1" border="0" alt style="border:none !important; margin:0px !important;" />」以外の本を読んでない。</li>
<li><a href="http://anond.hatelabo.jp/20150512193300">会計オンチのはてな達へ</a>によれば、次は<a href="http://www.amazon.co.jp/gp/product/4813261612/ref=as_li_qf_sp_asin_tl?ie=UTF8&amp;camp=247&amp;creative=1211&amp;creativeASIN=4813261612&amp;linkCode=as2&amp;tag=dekokun-22">スッキリわかる 日商簿記2級 商業簿記 第7版 [テキスト&amp;問題集] (スッキリわかるシリーズ)</a><img src="http://ir-jp.amazon-adsystem.com/e/ir?t=dekokun-22&amp;l=as2&amp;o=9&amp;a=4813261612" width="1" height="1" border="0" alt style="border:none !important; margin:0px !important;" />なのかな</li>
</ul>
<h3 id="新しい言語">新しい言語</h3>
<ul>
<li>目標には「scalaかgo」と書いていたが、まさかErlang, Elixirを触ることになるとは。</li>
<li>作ったもの： http://erl-editor.herokuapp.com/</li>
</ul>
<h3 id="ossへのコミット">OSSへのコミット</h3>
<ul>
<li>少なくとも他の人が作った何かに対してpull requestを投げるなどしておらず、これは30コミット厳しいのではないか説がある</li>
<li>自分でOSSのライブラリを作るなどが必要</li>
<li>まぁ、上記erlangで作ったエディタもオープンソースではあるが、何か違う感</li>
</ul>
<h2 id="私事">私事</h2>
<h3 id="実家を大切にする">実家を大切にする</h3>
<ul>
<li>結構実家に帰っている。ただ、稲刈りに行こうかと提案したら、稲刈りは実際のところ特に人出が不要らしいのでいいと言われたので、今回は行かない</li>
<li>母の日、何も送っていないけど、その近くの、母の誕生日にはプレゼントした</li>
</ul>
<h3 id="旅行">旅行</h3>
<ul>
<li>日光行った。花粉すごすぎた</li>
</ul>
<h2 id="漠然とした思い">漠然とした思い</h2>
<ul>
<li>目標のところでは「設計の力で人間を正しい判断に導いていかなくてはならない 」という非常にかっこいいことを言っているが、最近の私は</li>
</ul>
<h2 id="やらないことリスト">やらないことリスト</h2>
<ul>
<li>Tumblrはしなかった</li>
<li>アプリゲームも、消しまくってそれからはしなくなった。良い
<ul>
<li>まぁ、仕事がアプリゲーム開発なので、やらないのもどうかとは思うが…</li>
</ul></li>
</ul>
<h2 id="最後に">最後に</h2>
<p>いろいろありましたね</p>

<div id="disqus_thread"></div>
<script type="text/javascript">
    /* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */
    var disqus_shortname = 'dekokun'; // required: replace example with your forum shortname

    /* * * DON'T EDIT BELOW THIS LINE * * */
    (function() {
        var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
        dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js';
        (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
    })();
</script>
<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
<a href="http://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a>

          <ul class="social">
            <li class="kindle"><div class="kindleWidget"><img style="vertical-align:middle;" src="https://d1xnn692s7u6t6.cloudfront.net/white-15.png" /><span style="vertical-align:middle;margin-left:3px;">Send to Kindle</span></div></li>
            <li class="facebook"><div class="fb-like" data-send="false" data-layout="button_count" data-width="100" data-show-faces="true" data-font="arial"></div></li>
            <li class="twitter"><a href="https://twitter.com/share" class="twitter-share-button" data-via="dekokun" data-lang="ja">ツイート</a></li>
            <li class="hatena-bookmark"><a href="http://b.hatena.ne.jp/entry/" class="hatena-bookmark-button" data-hatena-bookmark-layout="standard" title="このエントリーをはてなブックマークに追加"><img src="http://b.st-hatena.com/images/entry-button/button-only.gif" alt="このエントリーをはてなブックマークに追加" width="20" height="20" style="border: none;"></a><script type="text/javascript" src="http://b.st-hatena.com/js/bookmark_button.js" charset="utf-8" async="async"></script></li>
            <li><a data-pocket-label="pocket" data-pocket-count="horizontal" class="pocket-btn" data-lang="en"></a>
            <script type="text/javascript">!function(d,i){if(!d.getElementById(i)){var j=d.createElement("script");j.id=i;j.src="https://widgets.getpocket.com/v1/j/btn.js?v=1";var w=d.getElementById(i);d.body.appendChild(j);}}(document,"pocket-btn-js");</script></li>
          </ul>

        </article>
        <aside class="span3">
          <div class="sidebar-module">
            <div class="title">プロフィール</div>
            <p class="id"><a href="https://twitter.com/dekokun">dekokun</a></p>
            <p><a href="https://twitter.com/dekokun"><img src="../img/dekokun.png" alt="dekokun"></a></p>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.io/";
              Hatena.BookmarkWidget.title = "人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 200;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.com/";
              Hatena.BookmarkWidget.title = "旧人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 0;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module visible-desktop">
            <div class="title">twitter</div>
            <a class="twitter-timeline" data-dnt="true" href="https://twitter.com/dekokun" data-widget-id="306408547573440513">@dekokun からのツイート</a>
            <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
          </div>
          <div class="sidebar-module hidden-phone">
            <div class="title">RSS</div>
            <p><a href="../rss.xml"><img src="../img/rss.gif" alt="rss"></a></p>
          </div>
        </aside> <!-- /span3 -->
      </div> <!-- /row -->
      <footer>
        <p>©<script type="text/javascript">$y=2012;$ny=new Date().getFullYear();document.write($ny>$y?$y+'-'+$ny:$y);</script> <a href="https://twitter.com/dekokun">dekokun</a></p>
      </footer>
    </div> <!-- /container -->

    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script>window.jQuery || document.write('<script src="../js/libs/jquery-1.7.2.min.js"><\/script>')</script>
    <!-- /ツイートボタン -->
  <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>

    <script src="../js/libs/bootstrap/bootstrap.min.js"></script>

    <script src="../js/script.js"></script>
    <script>
      var _gaq=[['_setAccount','UA-XXXXX-X'],['_trackPageview']];
      (function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
      g.src=('https:'==location.protocol?'//ssl':'//www')+'.google-analytics.com/ga.js';
      s.parentNode.insertBefore(g,s)}(document,'script'));
    </script>
    <!-- Code syntax highlight -->
    <script type="text/javascript" src="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.js"></script>
    <script type="text/javascript">
    $(function(){ 
        $('pre').css({
            'overflow-x': 'scroll',
            'background-color': '#f6f6f6',
            'border': '1px dotted #ccc',
            'padding': '0.8em'
        });
        $('pre code').addClass('prettyprint');
        prettyPrint();
    });
    </script>
    <script type="text/javascript" src="https://d1xnn692s7u6t6.cloudfront.net/widget.js"></script>
    <script type="text/javascript">(function k(){window.$SendToKindle&&window.$SendToKindle.Widget?$SendToKindle.Widget.init({"content":"article"}):setTimeout(k,500);})();</script>
  </body>
</html>
]]></description>
    <pubDate>No date found.</pubDate>
    <guid>http://dekokun.github.io/posts/2015-06-01.html</guid>
</item>
<item>
    <title>TCP_NODELAYによるNagleアルゴリズム封じとTCP_CORKについて</title>
    <link>http://dekokun.github.io/posts/2015-06-03.html</link>
    <description><![CDATA[<!doctype html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7" lang="ja"> <![endif]-->
<!--[if IE 7]>    <html class="no-js lt-ie9 lt-ie8" lang="ja"> <![endif]-->
<!--[if IE 8]>    <html class="no-js lt-ie9" lang="ja"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="ja"> <!--<![endif]-->
  <head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# article: http://ogp.me/ns/article#">
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <title>TCP_NODELAYによるNagleアルゴリズム封じとTCP_CORKについて</title>
    <meta name="description" content>
    <meta name="author" content>

    <meta name="viewport" content="width=device-width">
    <meta property="fb:app_id" content="351187098330864">
    <meta property="og:type" content="article">
    <meta property="og:image" content="http://dekokun.github.com/img/dekokun.png">
    <meta property="og:title" content="TCP_NODELAYによるNagleアルゴリズム封じとTCP_CORKについて">
    <meta property="og:description" content="@dekokunの技術日記">
    <meta property="og:site_name" content="でこてっくろぐ">
    <meta name="twitter:widgets:csp" content="on">

    <link rel="stylesheet" href="../css/bootstrap.css">
    <link rel="stylesheet" href="../css/bootstrap-responsive.css">
    <link rel="stylesheet" href="../css/style.css">
    <style>
    body {
      padding-top: 60px;
      padding-bottom: 40px;
    }
    </style>
    <link href="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.css" type="text/css" rel="stylesheet">
    <script src="../js/libs/modernizr-2.5.3-respond-1.1.0.min.js"></script>
    <script>
      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

      ga('create', 'UA-39650556-1', 'auto');
      ga('send', 'pageview');
    </script>
  </head>
  <body>
  <!--[if lt IE 7]><p class=chromeframe>Your browser is <em>ancient!</em> <a href="http://browsehappy.com/">Upgrade to a different browser</a> or <a href="http://www.google.com/chromeframe/?redirect=true">install Google Chrome Frame</a> to experience this site.</p><![endif]-->
    <div id="fb-root"></div>
    <script>(function(d, s, id) {
      var js, fjs = d.getElementsByTagName(s)[0];
      if (d.getElementById(id)) return;
      js = d.createElement(s); js.id = id;
      js.src = "//connect.facebook.net/ja_JP/all.js#xfbml=1&appId=351187098330864";
      fjs.parentNode.insertBefore(js, fjs);
      }(document, 'script', 'facebook-jssdk'));
    </script>
    <header>
      <nav class="navbar navbar-fixed-top">
        <div class="navbar-inner">
          <div class="container">
            <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
            </a>
            <a class="brand" href="../index.html">でこてっくろぐ</a>
            <div class="nav-collapse">
              <ul class="nav">
                <li><a href="../index.html">ほーむ</a></li>
                <li><a href="../posts.html">あーかいぶ</a></li>
                <li><a href="../aboutme.html">あばうとみー</a></li>
              </ul>
            </div><!--/.nav-collapse -->
          </div>
        </div>
      </nav>
    </header>

    <div class="container">
      <div class="row">
        <article class="span9">
          <h1>TCP_NODELAYによるNagleアルゴリズム封じとTCP_CORKについて</h1>

<p>by <em><a href="https://twitter.com/dekokun">@dekokun</a></em> on <strong>2015/06/03 8:17</strong></p>

<p>Tagged as: <a href="../tags/TCP.html">TCP</a>.</p>

<p>こんな理解でいいんですか。教えてください。あと、Nagleアルゴリズムについて詳細は後で書く</p>
<blockquote class="twitter-tweet" lang="ja"><p lang="ja" dir="ltr">
NagleアルゴリズムとTCP遅延ACKとTCP CORK覚えた。 / “nginxのパフォーマンスチューニング // Speaker Deck” <a href="http://t.co/HbOKeoNQc8">http://t.co/HbOKeoNQc8</a>
</p>
— でこくん (@dekokun) <a href="https://twitter.com/dekokun/status/605820330729349121">2015, 6月 2</a>
</blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>

<blockquote class="twitter-tweet" lang="ja"><p lang="ja" dir="ltr">
さっきの資料にも載ってたけど、TCP_NODELAYとTCP_CORKの組み合わせ、コルクの抜くタイミングをいい感じにしながら、コルクを抜いてしまえば一気にフラッシュできますよってことだよね。コルクを抜くタイミングはどう制御されてる？
</p>
— でこくん (@dekokun) <a href="https://twitter.com/dekokun/status/605821565024870400">2015, 6月 2</a>
</blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>

<blockquote class="twitter-tweet" lang="ja"><p lang="ja" dir="ltr">
まぁ、そこはnginxがよしなにやってくれるわけなのかな。TCP_NODELAYとTCP_CORKの組み合わせは、パケット送信タイミングの最適化をカーネルに任せずにアプリケーション(今回はnginx)に任せるってことという理解でいいのかな。
</p>
— でこくん (@dekokun) <a href="https://twitter.com/dekokun/status/605823744972455939">2015, 6月 2</a>
</blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>

<h2 id="nagleアルゴリズム">Nagleアルゴリズム</h2>
<p>非常に雑に書いている。後でちゃんと書きたい</p>
<ul>
<li>なるべく複数のTCP通信を1回にまとめちゃおうというアルゴリズム</li>
<li>パケット数の減少によるヘッダ容量の削減及び輻輳の回避を狙っている模様</li>
</ul>

<div id="disqus_thread"></div>
<script type="text/javascript">
    /* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */
    var disqus_shortname = 'dekokun'; // required: replace example with your forum shortname

    /* * * DON'T EDIT BELOW THIS LINE * * */
    (function() {
        var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
        dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js';
        (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
    })();
</script>
<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
<a href="http://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a>

          <ul class="social">
            <li class="kindle"><div class="kindleWidget"><img style="vertical-align:middle;" src="https://d1xnn692s7u6t6.cloudfront.net/white-15.png" /><span style="vertical-align:middle;margin-left:3px;">Send to Kindle</span></div></li>
            <li class="facebook"><div class="fb-like" data-send="false" data-layout="button_count" data-width="100" data-show-faces="true" data-font="arial"></div></li>
            <li class="twitter"><a href="https://twitter.com/share" class="twitter-share-button" data-via="dekokun" data-lang="ja">ツイート</a></li>
            <li class="hatena-bookmark"><a href="http://b.hatena.ne.jp/entry/" class="hatena-bookmark-button" data-hatena-bookmark-layout="standard" title="このエントリーをはてなブックマークに追加"><img src="http://b.st-hatena.com/images/entry-button/button-only.gif" alt="このエントリーをはてなブックマークに追加" width="20" height="20" style="border: none;"></a><script type="text/javascript" src="http://b.st-hatena.com/js/bookmark_button.js" charset="utf-8" async="async"></script></li>
            <li><a data-pocket-label="pocket" data-pocket-count="horizontal" class="pocket-btn" data-lang="en"></a>
            <script type="text/javascript">!function(d,i){if(!d.getElementById(i)){var j=d.createElement("script");j.id=i;j.src="https://widgets.getpocket.com/v1/j/btn.js?v=1";var w=d.getElementById(i);d.body.appendChild(j);}}(document,"pocket-btn-js");</script></li>
          </ul>

        </article>
        <aside class="span3">
          <div class="sidebar-module">
            <div class="title">プロフィール</div>
            <p class="id"><a href="https://twitter.com/dekokun">dekokun</a></p>
            <p><a href="https://twitter.com/dekokun"><img src="../img/dekokun.png" alt="dekokun"></a></p>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.io/";
              Hatena.BookmarkWidget.title = "人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 200;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.com/";
              Hatena.BookmarkWidget.title = "旧人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 0;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module visible-desktop">
            <div class="title">twitter</div>
            <a class="twitter-timeline" data-dnt="true" href="https://twitter.com/dekokun" data-widget-id="306408547573440513">@dekokun からのツイート</a>
            <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
          </div>
          <div class="sidebar-module hidden-phone">
            <div class="title">RSS</div>
            <p><a href="../rss.xml"><img src="../img/rss.gif" alt="rss"></a></p>
          </div>
        </aside> <!-- /span3 -->
      </div> <!-- /row -->
      <footer>
        <p>©<script type="text/javascript">$y=2012;$ny=new Date().getFullYear();document.write($ny>$y?$y+'-'+$ny:$y);</script> <a href="https://twitter.com/dekokun">dekokun</a></p>
      </footer>
    </div> <!-- /container -->

    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script>window.jQuery || document.write('<script src="../js/libs/jquery-1.7.2.min.js"><\/script>')</script>
    <!-- /ツイートボタン -->
  <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>

    <script src="../js/libs/bootstrap/bootstrap.min.js"></script>

    <script src="../js/script.js"></script>
    <script>
      var _gaq=[['_setAccount','UA-XXXXX-X'],['_trackPageview']];
      (function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
      g.src=('https:'==location.protocol?'//ssl':'//www')+'.google-analytics.com/ga.js';
      s.parentNode.insertBefore(g,s)}(document,'script'));
    </script>
    <!-- Code syntax highlight -->
    <script type="text/javascript" src="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.js"></script>
    <script type="text/javascript">
    $(function(){ 
        $('pre').css({
            'overflow-x': 'scroll',
            'background-color': '#f6f6f6',
            'border': '1px dotted #ccc',
            'padding': '0.8em'
        });
        $('pre code').addClass('prettyprint');
        prettyPrint();
    });
    </script>
    <script type="text/javascript" src="https://d1xnn692s7u6t6.cloudfront.net/widget.js"></script>
    <script type="text/javascript">(function k(){window.$SendToKindle&&window.$SendToKindle.Widget?$SendToKindle.Widget.init({"content":"article"}):setTimeout(k,500);})();</script>
  </body>
</html>
]]></description>
    <pubDate>No date found.</pubDate>
    <guid>http://dekokun.github.io/posts/2015-06-03.html</guid>
</item>
<item>
    <title>バックエンドにAWS Lambdaを使ってサーバレスな動的サイトを作った</title>
    <link>http://dekokun.github.io/posts/2015-07-05.html</link>
    <description><![CDATA[<!doctype html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7" lang="ja"> <![endif]-->
<!--[if IE 7]>    <html class="no-js lt-ie9 lt-ie8" lang="ja"> <![endif]-->
<!--[if IE 8]>    <html class="no-js lt-ie9" lang="ja"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="ja"> <!--<![endif]-->
  <head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# article: http://ogp.me/ns/article#">
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <title>バックエンドにAWS Lambdaを使ってサーバレスな動的サイトを作った</title>
    <meta name="description" content>
    <meta name="author" content>

    <meta name="viewport" content="width=device-width">
    <meta property="fb:app_id" content="351187098330864">
    <meta property="og:type" content="article">
    <meta property="og:image" content="http://dekokun.github.com/img/dekokun.png">
    <meta property="og:title" content="バックエンドにAWS Lambdaを使ってサーバレスな動的サイトを作った">
    <meta property="og:description" content="@dekokunの技術日記">
    <meta property="og:site_name" content="でこてっくろぐ">
    <meta name="twitter:widgets:csp" content="on">

    <link rel="stylesheet" href="../css/bootstrap.css">
    <link rel="stylesheet" href="../css/bootstrap-responsive.css">
    <link rel="stylesheet" href="../css/style.css">
    <style>
    body {
      padding-top: 60px;
      padding-bottom: 40px;
    }
    </style>
    <link href="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.css" type="text/css" rel="stylesheet">
    <script src="../js/libs/modernizr-2.5.3-respond-1.1.0.min.js"></script>
    <script>
      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

      ga('create', 'UA-39650556-1', 'auto');
      ga('send', 'pageview');
    </script>
  </head>
  <body>
  <!--[if lt IE 7]><p class=chromeframe>Your browser is <em>ancient!</em> <a href="http://browsehappy.com/">Upgrade to a different browser</a> or <a href="http://www.google.com/chromeframe/?redirect=true">install Google Chrome Frame</a> to experience this site.</p><![endif]-->
    <div id="fb-root"></div>
    <script>(function(d, s, id) {
      var js, fjs = d.getElementsByTagName(s)[0];
      if (d.getElementById(id)) return;
      js = d.createElement(s); js.id = id;
      js.src = "//connect.facebook.net/ja_JP/all.js#xfbml=1&appId=351187098330864";
      fjs.parentNode.insertBefore(js, fjs);
      }(document, 'script', 'facebook-jssdk'));
    </script>
    <header>
      <nav class="navbar navbar-fixed-top">
        <div class="navbar-inner">
          <div class="container">
            <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
            </a>
            <a class="brand" href="../index.html">でこてっくろぐ</a>
            <div class="nav-collapse">
              <ul class="nav">
                <li><a href="../index.html">ほーむ</a></li>
                <li><a href="../posts.html">あーかいぶ</a></li>
                <li><a href="../aboutme.html">あばうとみー</a></li>
              </ul>
            </div><!--/.nav-collapse -->
          </div>
        </div>
      </nav>
    </header>

    <div class="container">
      <div class="row">
        <article class="span9">
          <h1>バックエンドにAWS Lambdaを使ってサーバレスな動的サイトを作った</h1>

<p>by <em><a href="https://twitter.com/dekokun">@dekokun</a></em> on <strong>2015/07/05 8:17</strong></p>

<p>Tagged as: <a href="../tags/AWS.html">AWS</a>.</p>

<p>どうも。<a href="http://dekolife.hatenablog.com/entry/2015/07/03/153402">もう一つのブログの方に書いていた</a>のですが、東京から京都まで歩いて行くことになりまして、私の位置情報が把握しやすいようにサイトを作りました。なお、明日(7/6)出発します</p>
<ul>
<li><a href="http://twittermap.dekokun.info/">京都まで歩こう</a></li>
</ul>
<p>このためだけにサーバを構築しサーバ代を払うのは馬鹿らしいと思いまして、なんとかサーバを構築せずにある程度安く済ませることはできないかと考えた結果、バックエンドをAWS Lambdaに任せてサイト自体はS3上に構築するという形にしました。</p>
<p>なお、「バックエンドをAWS Lambdaに任せた」といった場合、普通はクライアントのAWS SDKからLambda関数をキックするようなものになるかと思いますが、今回はLambda関数を無限ループのバッチ的に使い、クライアントはS3を経由してその結果を取得するような作りにしています。詳しくは以下。</p>
<p>あと、後述しますが「結局何かしらでLambdaを使いたかったネタ設計」みたいなところはありますのでご了承ください。</p>
<h2 id="構成">構成</h2>
<p>以下図をみてもらったほうが早いかもしれませんが、以下のとおりです。</p>
<h3 id="バックエンド">バックエンド</h3>
<p><a href="http://qiita.com/toritori0318/items/3ab95e94c5fc47530447">AWS Lambdaをcronの代わりに使ってみるよ</a>を参考にしています。</p>
<ol style="list-style-type: decimal">
<li>AWS Lambdaを最初に手動でキックする</li>
<li>登録してあるLambda関数が動きtwitterのAPIから私のtweetを取得、Web用のS3 bucketにjson形式でアップロードする</li>
<li>上記Lambda関数が最後にLambda用のS3 bucketにファイルをアップロードする</li>
<li>Lambda用のS3 bucketへのファイルアップロードイベントがLambdaに通知される (2. に戻る。無限ループ)</li>
</ol>
<h3 id="フロントエンド">フロントエンド</h3>
<ol style="list-style-type: decimal">
<li>ブラウザがS3からindex.htmlを取得</li>
<li>index.htmlのJSから定期的にLambdaによってアップデートされたjsonファイルを取得して地図に反映</li>
</ol>
<h3 id="構成図">構成図</h3>
<div class="figure">
<img src="../img/2015-07-05-aws-lambda.png" /><p class="caption"></p>
</div>
<h2 id="料金">料金</h2>
<p>大雑把に言うとS3のデータ転送量及びデータへのリクエスト数と、Route53のクエリ数、Lambda関数の実行回数と実行時間に対して料金がかかっていますが、Lambda関数は月の無料枠に収まるレベルになっておりまして、これからの転送量にもよりますが、現在はだいたい1日あたり0.05ドルな感じです。月に1.5ドルくらいでこんな環境ができるなんて嬉しいですね。</p>
<p>S3へのPUTリクエスト数による課金が比較的高いです。現在、tweets.jsonは以前と内容が同じでも毎回S3にtweets.jsonをPUTしているのですがそれをなくせば更に安くなる模様。もう明日の朝には京都に向けて出発するのでそちらを修正するのはやめておきます。</p>
<h2 id="lambdaで良かったこと">Lambdaで良かったこと</h2>
<h3 id="テストが結構簡単">テストが結構簡単</h3>
<p>例えばindex.jsのhandlerを登録しているような環境のテストがしたい場合は、手元の環境でLambda関数に渡しているロールとと同じ権限を付与して、以下みたいな形で簡単にテストできます。いいね！</p>
<pre><code>var main = require('./index');
var context = {done: function(var1, var2) {console.log(var1), console.log(var2)}}
main.handler('イベントデータ', context);</code></pre>
<h3 id="デプロイが結構簡単">デプロイが結構簡単</h3>
<p>以下のコマンドを実行するだけでデプロイできちまうので非常に簡単でした。</p>
<p><code>rm -f lamda.zip &amp;&amp; zip -r lambda.zip index.js node_modules &amp;&amp; aws lambda update-function-code --function-name 関数名どうぞ --zip-file fileb://./lambda.zip --region ap-northeast-1 | jq '.'</code></p>
<p><code>npm run deploy</code>で実行できるようにして超楽だった。npmのscripts便利。</p>
<h2 id="lambdaでハマったところ">Lambdaでハマったところ</h2>
<p>結構ハマりどころは多かったです。まぁ、一度わかると超便利ではあるのですが…なかなか…</p>
<h3 id="sourceを指定してなかった">sourceを指定してなかった</h3>
<p>Lambda関数を登録するだけ登録して、event sourceを追加せず、「自分でinvokeするとうまくうごくけどS3にファイルをアップロードしても動かないなぁ」「ってか、全てのS3へのイベントが全部通知されるのか！やばいな！！」と悩みました。そんなわけありませんでした。</p>
<p>Management ConsoleのLambdaのところからAction -&gt; Add event source で必要なイベントソース(今回だと、S3のlambda用bucketへのPUTの通知)を追加することで動くようになりました。</p>
<h3 id="zipにする際にフォルダごとzipにしてて怒られた">zipにする際にフォルダごとzipにしてて怒られた</h3>
<p>Lambda関数はzipをアップロードして登録することができるのですが、その際に、最初はindex.jsが存在しているディレクトリごとzipコマンドにかけてアップロード(例： <code>zip -r lambda.zip lambda_dir</code>)していたのですがそれではダメで、<code>zip -r lambda.zip index.js node_modules</code>みたいに、直接index.jsをzipしてあげる必要があります。</p>
<p>まぁ、そりゃ、アップロードされる側もzipされたディレクトリの名前なんて知らねぇでしょうし当然といえば当然なのですが、少し悩んだ。</p>
<h3 id="s3にputobjectする際にaclをいじろうとしたら失敗した">S3にputobjectする際にACLをいじろうとしたら失敗した</h3>
<p>Lambda関数、登録する時にその関数が動く際の権限をroleで付与するのですが、結構賢くて「S3に何かするならいい感じにロールを作ってやるよ」みたいな感じでロールを作ってくれます。</p>
<p>S3へのPUTとGETが行える権限(s3:PutObject及びs3:GetObject)はついてくるのですが、PUTする際にACLを付与する権限(s3:PutObjectAcl)はついてきません。</p>
<p>ですので、PUTする際にACLを指定する際は、ロールにs3:PutObjectAclを付与してあげる必要があります。</p>
<h2 id="注意">注意</h2>
<p>実際のところ、この無限ループによる擬似cronは信頼性が死ぬほど低い(変なところでcrashしたら最後、一生起動しない)ので、商用環境などでは絶対に使えません。というか、今回の私の目的に合致したものだったかどうかも怪しい。というか、合致していない。ま、楽しかったしいっか。</p>
<h2 id="想定される質問">想定される質問</h2>
<h3 id="これは本当に動的サイトと言えるものなのか">これは本当に「動的サイト」と言えるものなのか</h3>
<p>答：まぁ、静的サイトじゃないし…動的サイトなんじゃないかな！！！！</p>
<h3 id="こんなまわりくどいことしなくてもjsから直接dekokunのツイートを取得しにいけばいいのではないか">こんなまわりくどいことしなくてもJSから直接@dekokunのツイートを取得しにいけばいいのではないか</h3>
<p>答：東京から京都までの旅はだいたい15日〜20日くらい、その間にツイートする件数は何件になるか想像もつかない状態でJSからtwitterに問い合わせまくるよりも、こっちで一旦保持しておいたほうがいろいろと便利だろうと思ってこちらの構成にしております！！！</p>
<h3 id="tweetが累積した場合かつ上記サイトがたくさんの人に見られた場合定期的にそれをクロールされると通信料やばくなるんじゃ">tweetが累積した場合かつ上記サイトがたくさんの人に見られた場合、定期的にそれをクロールされると通信料やばくなるんじゃ…</h3>
<p>答：その通り！せめて、tweets.jsonはIDだけ保持して、それが変化したらさらに別の所に問い合わせるとかしたほうがよかった！！！が、まぁ、実際通信料が増大してきたらクロールの間隔を下げる方向で対応するしかないね…もう明日には出発だもんね</p>
<h3 id="cloudfront使わないの">CloudFront使わないの？</h3>
<p>答：tweets.jsonが更新されたタイミングでinvalidationするっていうのさえちゃんとすればCloudFrontいいですね！！！！！！今回は時間がなくてやってないけど！！！！</p>
<h3 id="擬似cronってaws-data-pipelineは使わないの">擬似cronって…AWS Data Pipelineは使わないの？</h3>
<p>答：Data Pipelineはcron的に使おうとすると15分に1回しか動かせないし、EC2経由で実行されるため結構お金がかかる</p>
<h3 id="この構成やろうとしていることに対してクソな構成なのでは">この構成、やろうとしていることに対してクソな構成なのでは？</h3>
<p>答：そのとおりですね！！JSONをS3を介して渡しているためWebSocketも使えず、前時代的なポーリングによる解決になってしまいましたし、上記あるようにcronの信頼性は著しく低いですし、無駄に構成が複雑になっている感ありますし…ま、仕事じゃないし、とにかくLambdaを使いたかったって感じですね！</p>
<h2 id="感想">感想</h2>
<p>明日から京都に向けて歩き始めるから早く寝ようと思っていたが結構遅くなりつつある。いかんいかん。</p>
<p>以下のブログで実況中継しているので、皆さん応援してね！！</p>
<p><a href="http://dekolife.hatenablog.com/">でこらいふろぐ http://dekolife.hatenablog.com/</a></p>
<p>応援してね！！応援してね！！！！</p>

<div id="disqus_thread"></div>
<script type="text/javascript">
    /* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */
    var disqus_shortname = 'dekokun'; // required: replace example with your forum shortname

    /* * * DON'T EDIT BELOW THIS LINE * * */
    (function() {
        var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
        dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js';
        (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
    })();
</script>
<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
<a href="http://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a>

          <ul class="social">
            <li class="kindle"><div class="kindleWidget"><img style="vertical-align:middle;" src="https://d1xnn692s7u6t6.cloudfront.net/white-15.png" /><span style="vertical-align:middle;margin-left:3px;">Send to Kindle</span></div></li>
            <li class="facebook"><div class="fb-like" data-send="false" data-layout="button_count" data-width="100" data-show-faces="true" data-font="arial"></div></li>
            <li class="twitter"><a href="https://twitter.com/share" class="twitter-share-button" data-via="dekokun" data-lang="ja">ツイート</a></li>
            <li class="hatena-bookmark"><a href="http://b.hatena.ne.jp/entry/" class="hatena-bookmark-button" data-hatena-bookmark-layout="standard" title="このエントリーをはてなブックマークに追加"><img src="http://b.st-hatena.com/images/entry-button/button-only.gif" alt="このエントリーをはてなブックマークに追加" width="20" height="20" style="border: none;"></a><script type="text/javascript" src="http://b.st-hatena.com/js/bookmark_button.js" charset="utf-8" async="async"></script></li>
            <li><a data-pocket-label="pocket" data-pocket-count="horizontal" class="pocket-btn" data-lang="en"></a>
            <script type="text/javascript">!function(d,i){if(!d.getElementById(i)){var j=d.createElement("script");j.id=i;j.src="https://widgets.getpocket.com/v1/j/btn.js?v=1";var w=d.getElementById(i);d.body.appendChild(j);}}(document,"pocket-btn-js");</script></li>
          </ul>

        </article>
        <aside class="span3">
          <div class="sidebar-module">
            <div class="title">プロフィール</div>
            <p class="id"><a href="https://twitter.com/dekokun">dekokun</a></p>
            <p><a href="https://twitter.com/dekokun"><img src="../img/dekokun.png" alt="dekokun"></a></p>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.io/";
              Hatena.BookmarkWidget.title = "人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 200;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.com/";
              Hatena.BookmarkWidget.title = "旧人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 0;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module visible-desktop">
            <div class="title">twitter</div>
            <a class="twitter-timeline" data-dnt="true" href="https://twitter.com/dekokun" data-widget-id="306408547573440513">@dekokun からのツイート</a>
            <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
          </div>
          <div class="sidebar-module hidden-phone">
            <div class="title">RSS</div>
            <p><a href="../rss.xml"><img src="../img/rss.gif" alt="rss"></a></p>
          </div>
        </aside> <!-- /span3 -->
      </div> <!-- /row -->
      <footer>
        <p>©<script type="text/javascript">$y=2012;$ny=new Date().getFullYear();document.write($ny>$y?$y+'-'+$ny:$y);</script> <a href="https://twitter.com/dekokun">dekokun</a></p>
      </footer>
    </div> <!-- /container -->

    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script>window.jQuery || document.write('<script src="../js/libs/jquery-1.7.2.min.js"><\/script>')</script>
    <!-- /ツイートボタン -->
  <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>

    <script src="../js/libs/bootstrap/bootstrap.min.js"></script>

    <script src="../js/script.js"></script>
    <script>
      var _gaq=[['_setAccount','UA-XXXXX-X'],['_trackPageview']];
      (function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
      g.src=('https:'==location.protocol?'//ssl':'//www')+'.google-analytics.com/ga.js';
      s.parentNode.insertBefore(g,s)}(document,'script'));
    </script>
    <!-- Code syntax highlight -->
    <script type="text/javascript" src="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.js"></script>
    <script type="text/javascript">
    $(function(){ 
        $('pre').css({
            'overflow-x': 'scroll',
            'background-color': '#f6f6f6',
            'border': '1px dotted #ccc',
            'padding': '0.8em'
        });
        $('pre code').addClass('prettyprint');
        prettyPrint();
    });
    </script>
    <script type="text/javascript" src="https://d1xnn692s7u6t6.cloudfront.net/widget.js"></script>
    <script type="text/javascript">(function k(){window.$SendToKindle&&window.$SendToKindle.Widget?$SendToKindle.Widget.init({"content":"article"}):setTimeout(k,500);})();</script>
  </body>
</html>
]]></description>
    <pubDate>No date found.</pubDate>
    <guid>http://dekokun.github.io/posts/2015-07-05.html</guid>
</item>
<item>
    <title>ブログ移設してた</title>
    <link>http://dekokun.github.io/posts/2015-09-09.html</link>
    <description><![CDATA[<!doctype html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7" lang="ja"> <![endif]-->
<!--[if IE 7]>    <html class="no-js lt-ie9 lt-ie8" lang="ja"> <![endif]-->
<!--[if IE 8]>    <html class="no-js lt-ie9" lang="ja"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="ja"> <!--<![endif]-->
  <head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# article: http://ogp.me/ns/article#">
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <title>ブログ移設してた</title>
    <meta name="description" content>
    <meta name="author" content>

    <meta name="viewport" content="width=device-width">
    <meta property="fb:app_id" content="351187098330864">
    <meta property="og:type" content="article">
    <meta property="og:image" content="http://dekokun.github.com/img/dekokun.png">
    <meta property="og:title" content="ブログ移設してた">
    <meta property="og:description" content="@dekokunの技術日記">
    <meta property="og:site_name" content="でこてっくろぐ">
    <meta name="twitter:widgets:csp" content="on">

    <link rel="stylesheet" href="../css/bootstrap.css">
    <link rel="stylesheet" href="../css/bootstrap-responsive.css">
    <link rel="stylesheet" href="../css/style.css">
    <style>
    body {
      padding-top: 60px;
      padding-bottom: 40px;
    }
    </style>
    <link href="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.css" type="text/css" rel="stylesheet">
    <script src="../js/libs/modernizr-2.5.3-respond-1.1.0.min.js"></script>
    <script>
      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

      ga('create', 'UA-39650556-1', 'auto');
      ga('send', 'pageview');
    </script>
  </head>
  <body>
  <!--[if lt IE 7]><p class=chromeframe>Your browser is <em>ancient!</em> <a href="http://browsehappy.com/">Upgrade to a different browser</a> or <a href="http://www.google.com/chromeframe/?redirect=true">install Google Chrome Frame</a> to experience this site.</p><![endif]-->
    <div id="fb-root"></div>
    <script>(function(d, s, id) {
      var js, fjs = d.getElementsByTagName(s)[0];
      if (d.getElementById(id)) return;
      js = d.createElement(s); js.id = id;
      js.src = "//connect.facebook.net/ja_JP/all.js#xfbml=1&appId=351187098330864";
      fjs.parentNode.insertBefore(js, fjs);
      }(document, 'script', 'facebook-jssdk'));
    </script>
    <header>
      <nav class="navbar navbar-fixed-top">
        <div class="navbar-inner">
          <div class="container">
            <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
            </a>
            <a class="brand" href="../index.html">でこてっくろぐ</a>
            <div class="nav-collapse">
              <ul class="nav">
                <li><a href="../index.html">ほーむ</a></li>
                <li><a href="../posts.html">あーかいぶ</a></li>
                <li><a href="../aboutme.html">あばうとみー</a></li>
              </ul>
            </div><!--/.nav-collapse -->
          </div>
        </div>
      </nav>
    </header>

    <div class="container">
      <div class="row">
        <article class="span9">
          <h1>ブログ移設してた</h1>

<p>by <em><a href="https://twitter.com/dekokun">@dekokun</a></em> on <strong>2015/09/09 22:17</strong></p>

<p>Tagged as: .</p>

<p>どうも。ブログ移設していたのでご連絡です。</p>
<p>移設先：<a href="http://dekotech.dekokun.info/">でこてっくろぐ ねお</a></p>
<p>どうぞ今後もよろしう</p>

<div id="disqus_thread"></div>
<script type="text/javascript">
    /* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */
    var disqus_shortname = 'dekokun'; // required: replace example with your forum shortname

    /* * * DON'T EDIT BELOW THIS LINE * * */
    (function() {
        var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
        dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js';
        (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
    })();
</script>
<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
<a href="http://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a>

          <ul class="social">
            <li class="kindle"><div class="kindleWidget"><img style="vertical-align:middle;" src="https://d1xnn692s7u6t6.cloudfront.net/white-15.png" /><span style="vertical-align:middle;margin-left:3px;">Send to Kindle</span></div></li>
            <li class="facebook"><div class="fb-like" data-send="false" data-layout="button_count" data-width="100" data-show-faces="true" data-font="arial"></div></li>
            <li class="twitter"><a href="https://twitter.com/share" class="twitter-share-button" data-via="dekokun" data-lang="ja">ツイート</a></li>
            <li class="hatena-bookmark"><a href="http://b.hatena.ne.jp/entry/" class="hatena-bookmark-button" data-hatena-bookmark-layout="standard" title="このエントリーをはてなブックマークに追加"><img src="http://b.st-hatena.com/images/entry-button/button-only.gif" alt="このエントリーをはてなブックマークに追加" width="20" height="20" style="border: none;"></a><script type="text/javascript" src="http://b.st-hatena.com/js/bookmark_button.js" charset="utf-8" async="async"></script></li>
            <li><a data-pocket-label="pocket" data-pocket-count="horizontal" class="pocket-btn" data-lang="en"></a>
            <script type="text/javascript">!function(d,i){if(!d.getElementById(i)){var j=d.createElement("script");j.id=i;j.src="https://widgets.getpocket.com/v1/j/btn.js?v=1";var w=d.getElementById(i);d.body.appendChild(j);}}(document,"pocket-btn-js");</script></li>
          </ul>

        </article>
        <aside class="span3">
          <div class="sidebar-module">
            <div class="title">プロフィール</div>
            <p class="id"><a href="https://twitter.com/dekokun">dekokun</a></p>
            <p><a href="https://twitter.com/dekokun"><img src="../img/dekokun.png" alt="dekokun"></a></p>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.io/";
              Hatena.BookmarkWidget.title = "人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 200;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module hidden-phone">
            <script language="javascript" type="text/javascript" src="http://b.hatena.ne.jp/js/widget.js" charset="utf-8"></script>
            <script language="javascript" type="text/javascript">
              Hatena.BookmarkWidget.url   = "http://dekokun.github.com/";
              Hatena.BookmarkWidget.title = "旧人気エントリー";
              Hatena.BookmarkWidget.sort  = "";
              Hatena.BookmarkWidget.width = 0;
              Hatena.BookmarkWidget.num   = 5;
              Hatena.BookmarkWidget.theme = "hatenadiary";
              Hatena.BookmarkWidget.load();
            </script>
          </div>
          <div class="sidebar-module visible-desktop">
            <div class="title">twitter</div>
            <a class="twitter-timeline" data-dnt="true" href="https://twitter.com/dekokun" data-widget-id="306408547573440513">@dekokun からのツイート</a>
            <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
          </div>
          <div class="sidebar-module hidden-phone">
            <div class="title">RSS</div>
            <p><a href="../rss.xml"><img src="../img/rss.gif" alt="rss"></a></p>
          </div>
        </aside> <!-- /span3 -->
      </div> <!-- /row -->
      <footer>
        <p>©<script type="text/javascript">$y=2012;$ny=new Date().getFullYear();document.write($ny>$y?$y+'-'+$ny:$y);</script> <a href="https://twitter.com/dekokun">dekokun</a></p>
      </footer>
    </div> <!-- /container -->

    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script>window.jQuery || document.write('<script src="../js/libs/jquery-1.7.2.min.js"><\/script>')</script>
    <!-- /ツイートボタン -->
  <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>

    <script src="../js/libs/bootstrap/bootstrap.min.js"></script>

    <script src="../js/script.js"></script>
    <script>
      var _gaq=[['_setAccount','UA-XXXXX-X'],['_trackPageview']];
      (function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
      g.src=('https:'==location.protocol?'//ssl':'//www')+'.google-analytics.com/ga.js';
      s.parentNode.insertBefore(g,s)}(document,'script'));
    </script>
    <!-- Code syntax highlight -->
    <script type="text/javascript" src="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.js"></script>
    <script type="text/javascript">
    $(function(){ 
        $('pre').css({
            'overflow-x': 'scroll',
            'background-color': '#f6f6f6',
            'border': '1px dotted #ccc',
            'padding': '0.8em'
        });
        $('pre code').addClass('prettyprint');
        prettyPrint();
    });
    </script>
    <script type="text/javascript" src="https://d1xnn692s7u6t6.cloudfront.net/widget.js"></script>
    <script type="text/javascript">(function k(){window.$SendToKindle&&window.$SendToKindle.Widget?$SendToKindle.Widget.init({"content":"article"}):setTimeout(k,500);})();</script>
  </body>
</html>
]]></description>
    <pubDate>No date found.</pubDate>
    <guid>http://dekokun.github.io/posts/2015-09-09.html</guid>
</item>

    </channel> 
</rss>
