オブジェクトをそのままで送受信するPipe

IPCの中でもPipeはTCPとかのネットワーク系の基礎になったもので、結構使いやすくて個人的に好きな機能です。
特にスレッドを使うと、スレッド間通信用に多用します。
自分でリングバッファとか作るのも1つの手なのですが、自前でこういうの作るとブロッキングが出来なくsleepとかいれざるを得ないのでちょっと厄介なので特別な理由がない場合使いません。


さて、これを今回Rubyで使おうと思ったのですがRubyの場合IO#pipeで作りwrite/readを使うので文字列でしか通信できないのがネック。
送受信したいのはあくまでもRubyのオブジェクト。Cだと、どうせ同一プロセス内なので型を統一してポインタをwrite、readしたらキャストすればOKなのですがこの技が使えない。
http://docs.ruby-lang.org/ja/2.1.0/class/IO.html#S_PIPE
http://docs.ruby-lang.org/ja/2.1.0/class/IO.html#I_WRITE
http://docs.ruby-lang.org/ja/2.1.0/class/IO.html#I_READ


諦めるのも嫌だし仕方がないので、悩んだのですがMarshalを使うことにして動作するのを確認しました。
http://docs.ruby-lang.org/ja/2.1.0/class/Marshal.html

class ObjctPipe   
  def initialize  
    pipe = IO.pipe
    @rp = pipe[0]
    @wp = pipe[1]
  end

  def write(obj)
    objs = Marshal.dump(obj)

    len = objs.length
    lens = [len].pack('L!')
    @wp.syswrite(lens)

    @wp.syswrite(objs)
  end

  def read
    lens = @rp.sysread(8)
    len = lens.unpack('L!')[0]
    objs = @rp.sysread(len) 
    obj = Marshal.load(objs)
    return obj
  end
end


# 使い方はこうなります
pipe = ObjctPipe.new

# read側はスレッドで行う
Thread.new do
  while true
    obj = pipe.read
  end
end

# write側
while true
  # データを作成しておく
  pipe.write("なにかobject")
end


いくつかポイント

  • write側スレッドとread側スレッドで同じ'pipe'オブジェクトを使いますが、Mutexは使っていない
    • これは、実質同じデータにアクセスしないのでスレッド特有の問題は発生しないからです
  • 送信するobjectをMarshalしておく
    • 当然Marshalの制限がかかります
  • objectを送信する前にオブジェクトサイズを送る
    • サイズはpackで'unsigned long'にしておき、'オブジェクトサイズ'自体の大きさを固定しておく
    • これはread時のバッファやブロッキング動作が絡むからです
  • write/readではなくsyswrite/sysreadを使う
    • これは文字コードが絡んできてデータによってはwriteでエラーになるから


Rubyってobj.__id__でオブジェクトIDは作れるのですが、IDからオブジェクトの復活方法が分からないのでこの方法を取りました。
Marshalやpack/unpackが入るのでCに比べて無駄が多いのですが、まあ許容範囲内でしょう。
意外と便利に使えています。

会社での開発体制改善中

ここ5年程はWeb業界で働いていてWeb業界で現在2社目。
前職の最後の方ではそこそこ業界で有名になった企業。現職は上場している企業なわけですが、両方とも開発体制、手法がひどい。


端的に言えばいきあたりばったり開発です。
ディレクタに当たる人たちが、まともに仕様書を作れないから仕様書を作らない or 作っても要望書というか夢リストになるだけの書類しか作れない、でも自主的に勉強もしない。
そしてそういう人たちだけが出世する会社。
でもエンジニアはそれなりにスキルがある人たちが多いという現場なので、エンジニアが空気を読まされて、なんとか物をつくってリリースするという最悪な状況。
当然エンジニアの仕事もドキュメントは少なくというかほぼ存在しない、テストコードもほとんど書いていない。
最近はDevOpsとかも取り入れていますが、それはエンジニアだけの改善策であってディレクタが変わらない。
マジで最悪。


とはいっても、現在の職場の人たちはそれでも知りたいという気持ちはあって、エンジニアが勉強会を開くと参加もしてくれる。
最近だと会社のサービスを例に1からサーバ構成とか、Rails(うちはRailsが基本です)の仕組みを教える勉強会を開催すると参加はするし、質問ももらえる。
つまり、少なくとも現職勉強しないのではなくて、勉強方法が分からないのだと思う。意欲はあるのだから。


さて、最近自分は完全に新規のプロジェクトを担当している。しかも会社としては初のチャレンジ部分だ。
当然ながら仕様はきちんと決める必要があるし、テストも大事だ。エンジニアよりもディレクタの人数が多く、相変わらず夢物語も多い。
ここいらで何とかしたいし、何とかして良い効果がでれば開発手法も横展開したい。
で、どうするかだが、悩んだ結果大まかな部分はウォーターフォール型で開発すると宣言して、実際の開発ではスクラム開発を採用するという、かなり変則的な方法をとった。


ウォーターフォールとはいっても話は簡単で、はじめにきちんと仕様書をつくる。仕様書を作る段階では何回もチェックをいれて修正を行ってもらう。その次に開発を進めて、最後に一斉にテストだ。ウォーターフォールっぽい。
もちろんこれがきちんとしたウォーターフォールだとは思っていないが、目的はきちんと仕様書を書かせることにあってそのための方便として'ウォーターフォール'という言葉を使わせてもらった。
ここをきっちりしないと、開発が進まないので彼らからしたらかなり厳しい要求をした。仕様書はダメ出ししまくり上司だろうが関係なし。
結果出来たのは仕様書とは言えないが、仕様書になりかけの要望書と言ったところ。
前職合わせても、ここ数年のWeb業界で見たなかでは確実に良い出来でしょう。


でもこのままウォーターフォールで開発を行うとテスト段階でバグが出まくるし、そもそも開発時間が少ない。そこでスクラム開発の出番だ。
今回入ってもらうスクラムマスタに当たる人と相談して、時間がないので出来るだけスクラムそのもので余計な時間を取らないように相談した。また、がっちりスクラム開発の枠にはめてもいない。
結果、今回はこうなった。

  • 基本エンジニアのみにスクラム開発を適応させる
  • スプリントは1週間
  • ディリースクラム
  • 日報、これは少しから導入しているので継続中
  • KPT
  • 週末の振り返りなどのMTG
    • これだけはディレクタも参加する
  • ホワイトボードでタスク管理
    • 反対が多いのでPivotal Trackerなどのツールは使わない
  • エンジニア側では別途仕様書を作成する
  • Rdoc/YARD等で細かい部分のドキュメントを作成する
  • Rspec等でのテストコード作成
  • Jenkinsでの自動テストを実施する


まだまだ走りだしたプロジェクトだが、そこそこ前には進んでいると思う。
すでにいくつか良い意見ももらったり、効果も出てきていると思う。

  • 仕様書のレビューして修正という形は、しんどいが良い効果がある
  • ディリースクラムは横で聞いていたディレクタには悪くない印象
  • 作った物のレビューは良い反応


個人的にはアジャイルスクラム開発は両手を上げて賛成はしていない。
だって、OSSとかだとこんなことしなくても開発できているプロジェクトもあるし。そもそもこの業界にいてエンジニアではないにしろ勉強しない奴がいる事自体がおかしい。
もちろんテストコードを書いたり、Jenkinsでの自動テストとか好きな部分もあるのは確かだ。TDDは精神力を多大に浪費するのでしんどいけどw
良い結果が出始めている事なのは確かなので、開発の管理が出来ていないと悩んでいる方たちはこういうフレームワークをうまく取り入れれば良いとおもう。

謹賀新年

さて、年が明けました。


昨年はWebサービスを1つ作りましたが、結局先日中止しました。
http://khondalit.hatenablog.com/entry/2013/07/07/024922
仕事で忙しくなり結局停止。
時間がない中での複数人での開発は厳しいなぁというのが今の素直な気持ち。
ただ、仕事ではいくつもWebサイトを作って来ましたが、個人でも作るのは問題ないのを実感できたのが大きい。
ということで、今年の目標は真面目にWebサービスを1つは作ります。


あと、どこかで http://linuxc.info/ の更新も少しずつします。
ただ、仕事で新規プロジェクト(しかも結構無茶なの)を担当することになったので、今年前半は厳しいかもです。

バッチのテストの難しさ

さてかなり久しぶりの投稿です。


自分はかなり詰めが甘いほうで良く下らないバグをだします。ですので最近はテストコードの信者になりつつあります。
おそらく、RailsというかRubyがテストが良く書かれる文化だとは感じていますが、バッチが一番の曲者。
View側も最近はCapybaraをはじめとして受け入れテストも可能になり、またJavaScriptのテストツールも整いつつあります。
これにより以前ではかなりテストし辛い部分までテストコードを書くことが可能になっています。またJenkinsにより自動テストの環境が整い、さらにはVagrantなどでDevOpsも可能になり、私がエンジニアになった約10年ほど前とは根本的に異なる時代になって来ました。


ところが、個人的に難しいと考えているのがバッチです。
このバッチのテストが非常に難しい。自動テストを正しく行おうとすれば、現実の全データでテストを行うのが理屈上正しいのですが、バッチの実行を行うと、数日から1週間は必要という開発としてはまずありえない時間が必要になります。
Factorygirlを使ってダミーデータを用意すれば良い? それはそうなのですが、ダミーデータと言えども正常パターン、異常パターンを作成するのはまず無理。用意出来るならばすでに用意してテストもしています。


また、バッチは長年の経験を集めた実装で、また実装がテストしやすいようにはなっていない。必要な環境変数が多々必要だったり、特定の順番で複数のバッチを動作させることが前提だったり。また、リファクタリングも難しくテストコードも非常に書きづらい。
言語に限らずバッチはどこの環境でもこのような難しさを秘めている場合がほとんどな気がします。
ここ最近始めた方法として、バッチの中にtestというメソッドを用意して、最低限の動作を行う処理を書いておきテストを行う、という非常にいい加減な事をしてお茶を濁しています。


良い方法がないかこれからも探していきますが、私程度では解決方法は見つからず...。
どうしたものでしょうかね。

新規サービス公開

最終更新から1年ほど。
ここ最近色々ありまして更新できていませんでしたが、またちょっとづつ更新していこうかと思います。


最近の出来事。
色々あって、転職をしました。
今回もWeb系の会社。前職と違うのは今回のほうがユーザの生活に役に立ている点だと思います。
前職は会社としては利益がありましたが、目の前の稼ぎに対してしか見れずユーザを満足させていたかというとかなり疑問が残りました。
ここもそれなりに忙しいですが、堅実ですし良い雰囲気の会社だと思います。
さて、プライベートで開発する時間が取れるかは不安ですが、会社にだけ頼るのもちょっと問題かと思いますし頑張って行きたいです。

新サービス "2chまとめストリーム"公開!

もうすぐ1ヶ月ほど立ちますが、Railsの練習で前職の中の良い方と2人で作成しました。
http://www.2chstream.com/


よくある2ch記事のまとめサイトのまとめです。
勉強するにあたって、まずは簡単なサービスが良いと判断しました。
このサイトのようなタイプの良い所は、データを集めてそれを公開するだけです。
ユーザ管理や大量のデータを扱う必要は無く、デザインもシンプルに出来ます。

LinuxCの更新

LinuxCの更新。
忙しく手付かずになっていたLinuxCをまた少しづつですが、記事を増やしています。
その効果があったのか多少ではありますがPVが増えているようです。有難い話ですね。
IPを見るとユーザは大学や企業が多いようで、平日のアクセスが多く土日になるとガクッとPVが下がるようです。

今後

LinuxCはまだまだ書く内容はあるので少しづつ更新はしていきます。
また、個人で何か新しい開発をしていきたいですね。

HTML5メモ

最近気になるのがHTML5
そこで色々情報をメモしてみます。
JavaScriptHTML5と必須の知識ですがそれは次回ということで。

入門 HTML5

入門 HTML5

最近中古で入手した本です。
HTML5までのHTMLの流れから、文章の構造や意味に焦点を置いた点、videoやcanvasをはじめとした目新しい機能の紹介等、広く浅く紹介といった内容です。

リンク

入門用
http://html5.imedia-web.net/
http://w3g.jp/blog/studies/html5report

色々情報がまとまっています。
http://hyper-text.org/archives/2009/11/html5_resources.shtml

ブラウザの対応状況など最新の情報が公開されています。
http://html5please.us/
http://caniuse.com/
http://mobilehtml5.org/

SlideShare

SlideShareHTML5で検索して目についたのをメモ

HTML5について基礎から色々情報がまとまっています
http://www.slideshare.net/shumpei/what-is-html5-at-css-nite-osaka

こっちも同じように基礎の説明です。
http://www.slideshare.net/myakura/html5-2480964

これも基礎系
http://www.slideshare.net/futomihatano/html5-9066829

Web Intentsについて。Webのパイプのようなイメージです。
http://www.slideshare.net/shumpei/web-intents

HTML5について最新の仕様についてまとまっています。
http://www.slideshare.net/shumpei/html5api-10703643

nanocを使って静的サイトを作ろう2

前回の続きになります。


今回は新しいページの作成に挑戦します。

ディレクトリとファイルの解説

まずは前回と少し被りますが、ディレクトリの構成です。

$ ls -F
Rakefile  Rules  config.yaml  content/  layouts/  lib/  output/  tmp/
$ ls -F layouts/
default.html
$ ls -F content/
index.html  stylesheet.css

まず、layouts/default.htmlが全体で使われるテンプレートになります。
次に、content/index.htmlがトップページです。
処理としては、layouts/default.htmlにcontent/index.htmlが埋め込まれます。結果はoutput/に作成されます。


layouts/default.htmlの中身を見てみます。

$ cat layouts/default.html 
<!DOCTYPE HTML>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>A Brand New nanoc Site - <%= @item[:title] %></title>
    <link rel="stylesheet" type="text/css" href="/style.css" media="screen">
    <meta name="generator" content="nanoc 3.2.3">
  </head>
  <body>
    <div id="main">
      <%= yield %>
    </div>
    <div id="sidebar">
      <h2>Documentation</h2>
      <ul>
        <li><a href="http://nanoc.stoneship.org/docs/">Documentation</a></li>
        <li><a href="http://nanoc.stoneship.org/docs/3-getting-started/">Getting Started</a></li>
      </ul>
      <h2>Community</h2>
      <ul>
        <li><a href="http://groups.google.com/group/nanoc/">Discussion Group</a></li>
        <li><a href="irc://chat.freenode.net/#nanoc">IRC Channel</a></li>
        <li><a href="http://projects.stoneship.org/trac/nanoc/">Wiki</a></li>
      </ul>
    </div>
  </body>
</html>

"<%= yield %>" という部分があります。ここにcontent/index.htmlが埋め込まれます。
この記法はERBというRubyのデフォルトのライブラリとして実装されていて、任意のテキストファイルにRubyスクリプトを埋め込む書式です。

新規ページの作成

簡単な動作を理解したところで実際に新規ページを作成します。

手っ取り早く行うためにindex.htmlをコピーして使います

$ cp content/index.html content/test.html


ちなみにページを1から作成したい場合は"create_item"オプションがあります。

$ nanoc create_item test
      create  content/test.html
An item has been created at /test/.


これが修正した内容です。

$ cat content/test.html 
---
title: Test <!-- 修正部分 -->
---

<h1>Test Page</h1> <!-- 修正部分 -->

<p>You've just created a new nanoc site. The page you are looking at right now is the home page for your site. To get started, consider replacing this default homepage with your own customized homepage. Some pointers on how to do so:</p>

<ul>
  <li><p><strong>Change this page's content</strong> by editing the "index.html" file in the "content" directory. This is the actual page content, and therefore doesn't include the header, sidebar or style information (those are part of the layout).</p></li>
  <li><p><strong>Change the layout</strong>, which is the "default.html" file in the "layouts" directory, and create something unique (and hopefully less bland).</p></li>
</ul>

<p>If you need any help with customizing your nanoc web site, be sure to check out the documentation (see sidebar), and be sure to subscribe to the discussion group (also see sidebar). Enjoy!</p>


修正部分をコメントで示しています。"Home"を"Test"に、"A Brand New nanoc Site"を"Test Page"に変更しました。


この修正を表示するために"compile"オプションを使用してhtmlを作成します。

$ nanoc compile
Loading site data...
Compiling site...
   identical  [0.02s]  output/index.html
   identical  [0.00s]  output/style.css
      create  [0.00s]  output/test/index.html

Site compiled in 0.10s.

output/test/index.htmlが作成されているのが分かります。


新しいファイルが作成されたので表示をしてみます。
この状態でブラウザから"http://localhost:3000/test/"にアクセスしてください。修正した内容が表示されれば成功です。

$ nanoc view
[2012-01-24 23:16:22] INFO  WEBrick 1.3.1
[2012-01-24 23:16:22] INFO  ruby 1.9.3 (2011-10-30) [x86_64-linux]
[2012-01-24 23:16:22] INFO  WEBrick::HTTPServer#start: pid=25689 port=3000

HTML上の階層

content/test.htmlを作成しましたが、これがHTML上の位置でどのようになるかを説明します。
これを理解していないと、サイト内リンクが作成出来ない状態のままになります。

単体ファイル

"content/hoge.html"の場合、"output/hoge/index.html"として作成されます。
このようになっている理由を想像すると、2つ理由があります。
1つ目の理由は、"content/hoge.html"にアクセスするために、"http://localhost:3000/content/hoge/"だけでアクセスできるようにという配慮だと思われます。
2つ目の理由は、複数ファイルへの対処です。これは次で説明します。

複数ファイル

"http://localhost:3000/hoge/*.html"という形で、サブディレクトリを作り複数のファイルをまとめて管理する場合の方法です。
この場合、content/hoge/というディレクトリを作成しその下にファイルを作っていく流れになります。
当初、"content/hoge.html"を作成していたが、ページが増えてきて1つのページを複数に分けたいという欲求が出てきた場合、"content/hoge/"を作成し、次に"content/hoge.html"を"content/hoge/index.html"にするだけで対応ができます。


最初からこのようにサブディレクトリを作成したい場合は"create_item"オプションで一度に作成できるようになっています。

$ nanoc create_item hoge/index
      create  content/hoge/index.html
An item has been created at /hoge/index/.

あとはhoge/index.htmlを修正し、新しいファイルが欲しければ"create_item"オプションを使えば良いのです。

URLはどうなるか?

"content/test.html"の場合、"http://localhost:3000/test/index.html"というリンクになります。


これを確かめるために"content/index.html"にこのように"test/"へのリンクを作成してみます。

$ cat content/index.html 
---
title: Home
---

<h1>A Brand New nanoc Site</h1>

<a href="test/">test page<a> <!-- 追加 -->

<p>You've just created a new nanoc site. The page you are looking at right now is the home page for your site. To get started, consider replacing this default homepage with your own customized homepage. Some pointers on how to do so:</p>

<ul>
  <li><p><strong>Change this page's content</strong> by editing the "index.html" file in the "content" directory. This is the actual page content, and therefore doesn't include the header, sidebar or style information (those are part of the layout).</p></li>
  <li><p><strong>Change the layout</strong>, which is the "default.html" file in the "layouts" directory, and create something unique (and hopefully less bland).</p></li>
</ul>

<p>If you need any help with customizing your nanoc web site, be sure to check out the documentation (see sidebar), and be sure to subscribe to the discussion group (also see sidebar). Enjoy!</p>


compileを行うとリンクが作成されてリンクをクリックすると正しく移動する事が分かります。



いかがだったでしょうか? nanocを使うと空ページのテンプレートの作成やディレクトリ構成を深く考える必要が無く、簡単にHTMLを作成できる事ができました。
次回は、コンパイル時のルール修正について解説します。