MacPortsのErlang/OTPでRiakをまともにうごかす

ぼく自信はもうソースから手でインストールする暮らしになっているので不要なのだが、最近closeされたらしいのでここに努力の結晶を書き残しておこう。ErlangがHiPE有効な状態でインストールされていると、RiakをHiPE有効な状態でコンパイルしてしまい、中のなんとかいうモジュールがスタックオーバーフローしてRiakがまともに動かなかった時期があった。まあHiPEなしのコンパイル

$ ./configure --disable-hipe

としておけばよいのだが、MacPortsだとこれを入れるためにはvariantを指定しないといけなかった:

$ sudo port install erlang +nohipe

これはMacPortsが + で始まるvariantしか受け付けなかった時代の名残りで、しかもあろうことかバグっていた(のを僕が報告した)。

これが気付いたらいつの間にか本体に入っていたらしいので、MacPorts使いの人は

$ sudo port install erlang -- -hipe

ってやって入れるとR16B02が入る?と思うよ。それにしても -- ってすごいな
Riakの1.4はR16B系だとコンパイルできないので2.0系(preリリースしかないけど)で試してみてください。

モダンErlang/OTP開発環境 2013

とりあえずモダン○○といっとけばいいかなと思ったが、モダニズムとか言ってた頃からモダンという言葉には「最近の」「ナウい」とかその程度の意味しかないのでそんなにありがたい話ではないことにご注意いただきたい。大正とか昭和初期のオバちゃんが「いや〜モダンやわぁ〜」とか言ってたのと同じだ。今ではもうばあちゃんだな。

エディタ

世間にはエディタを巡って宗教対立が発生し、場合によっては宗教戦争になるそうだがErlang/OTPの世界においてはそれは起き得ない。なぜならEmacsがデフォルトの開発環境として推奨されており、メジャーモードが処理系のディストリビューションに含まれているからだ。さまざまな便利ショートカットが用意されているので M-x tempo- と入れて補完されるものを眺めるとよいだろう。

パスを通して

(require 'erlang-start)
(require 'erlang-flymake)

してやるとよい。

ちなみにVimEclipseと同じくらいマイノリティだ。これらのマイノリティを採用する場合は、Emacsに比べて10〜100倍ほど生産性に差が出るレベルでないとやめた方がよい。

ソースコードを読むとき、ちゃんとしたい人はGTAGSか、erlcscopeがよいだろう。erlcscopeはcscopeとは別の実装だが、Emacsのcscope.elと相性がよいので僕もたまに使う。たまに使うが、普段はgrepだ。

OS

Erlang/OTPは現在、Linuxが最もメジャーなOSだろう。商用環境で次に多いのはSolaris系のOSだ。開発環境の場合はMacOSを使える場合もあるが、dtraceを使えるようになる代わりに本番環境との微妙な違いに悩むことが多いだろう。NIFなどのC拡張があると余計に面倒が増える。私は基本的にLinuxを使っている。ちなみにソースをみるとわかるが、他にもマニアックな*nix系OSに対応している。
BSD系もユーザーがいないことはない。Windowsでも動かないことはないが茨の道だろう。

コンパイラと処理系

Ericssonが出しているもの以外の処理系では、Triforkが公開しているErjangが有名だ。組み込み向けのものもあったように記憶している。真面目にErlang/OTPを使いたい場合はローカルで複数のバージョンを用意しておくことをすすめる。rbenvのようなものとしてはkerlがあるが、rbenvとちがってRubygemsのようなエコシステムはないので大して役に経たない。

最初はOSのディストリビューションが提供するものでもよいかもしれないが、本気で使うならソースから入れておくのがよいだろう。僕は /usr/local/erlang 以下に

$ ls /usr/local/erlang
R14B04  R15B01  R15B01.zdss  R15B03  R16B  R16B01  eqc

と、prefix指定したものをいろいろと入れている。PATHをbinに通すだけで使い分けられるので便利だ:

$ export PATH=/usr/local/erlang/R16B01/bin:$PATH

コンパイルオプションはいつもこんな感じだ:

MacOS

$ ./configure --enable-darwin-64bit --disable-hipe --enable-vm-probes --with-dynamic-trace=dtrace --prefix=/usr/local/erlang/R16B01

Linux

$ sudo aptitude install xsltproc fop libssl-dev
$ ./configure --enable-m64-build --disable-hipe  --prefix=/usr/local/erlang/R16B01

この過程でncurses-devなど必要なものを指摘されるので注意しておくこと。wxは別になくてもよいだろう。javaがないとwithout指定か何かが必要だった気がするが、特に気にしてないので記憶していない。

manpagesも、ソースから入れておくとよい。とんぷー氏のブログ記事が参考になるがここにも転載しておく。

$ make docs
$ make install-docs

これを動かすためにはfopやxsltprocなどいろいろと必要になるので都度インストールすること。

ビルドツール

ビルドツールの選定ほど面倒なことはない。しかしErlang/OTPではrebar一択だ。もしもautomakeなど、rebar以外のツールを使っているプロジェクトがあったら、それは少しあやしいので眉に唾をつけるとよいだろう。rebarをちいさなMakefileでラップするのが一般的だ。Makefileのサンプルもあるので参考にするとよい。

rebarは依存ライブラリをバージョンつきで指定することができる。これはとても便利だが、ダイヤモンド依存になったときに依存しているバージョンが異なる場合があるので注意すること。

VCS

rebarがそのサービスをサポートしているものを使うとよい。git, hgなどいくつかあるので、github, bitbucketなどのレポジトリを依存ライブラリとしてバージョン指定するとよいだろう。

テスト環境

ユニットテストはeunitかct(common tests)で書くのが一般的だ。テスト用のライブラリはmeck, properなどが代表的だ。Dialyzerという静的な型解析ツールもある。テストは分野によって書き方や使い方が全然違うので自分に合ったものを模索するしかない。

僕の会社ではeunitでQuickCheck (プロプラ)を流して、結合は riak_test というのを使っている。

人によってはTravis-CIやdrone.ioなども合わせて使うとよいだろう。この辺はErlang/OTPに独特ということはあまりない。

パッケージング

Erlang/OTPはそれ自体、パッケージングやリリースのための仕組みが沢山ある。交換機は無停止でシステムを更新する必要があったから、そういったところも処理系に組み込まれている…のだが、これが滅法使いにくい。なので、rebarがこれをサポートするコマンドを作って、tarball一発まで作れるようになっている。これが便利なのは、Erlangの処理系もリリースパッケージに一緒に入れてしまうので、本番環境で特に環境を作る必要がほとんどないためだ。Erlangを頑張ってインストールする必要はない(goみたいですごいでしょ!)。

しかし、これだけだとtarballなど独特の仕組みになってしまい、設定ファイルなどもまだ扱いにくい。そこで登場するのが、 node_package だ。これを使うことで、APT, yum, SmartOS, ports など様々な環境に向けたリリースパッケージを構築してくれる。設定ファイルやログの出力など、それぞれのOSの流儀に合ったものにしてくれる。コマンドひとつで.debパッケージを作るの、昔からの夢だったんだ…!

ライブラリ

これ!といった定番がいくつかあるので…とはいえ、いろいろありすぎて面倒なのでパス。

ドキュメント

edocというのがあり、これもrebarを使えば一発でHTMLを吐いてくれる。使っている人もいるし使っていない人もいる。たいていはREADME.mdで済ませてしまっている。

デバッガ

基本的には printf というデバッガが最もよく使われている。いちおう、C拡張などをテストするため gdb も使えたりするのだが… distel は emacs と相性がよく昔から使われている。また、最近では redbug というツールがとてもよい。これは予めプロダクションシステムに仕込んでおけば、サービスを止めずにコールフローを追ったりフックを仕掛けたりやめたりできる優れものなので使い方を覚えておくとよいだろう。

まとめ

erlang-users.jpというサイトを最近復活させたので、ヒマがあったらそちらを覗いてみると新しい情報がなにか出ているかも?!

ソフトウェアデザイン 10月号はRiakでの全文検索の話です

まだやっとるんかい、というツッコミをいただきそうですが、ソフトウェアデザイン10月号にRiakでまた記事を書きました。今回はRiakで全文検索をする、というか、JSONログを掘るはなしです*1…が、記事を書いた時と若干手順が変わっているので補足。

これを書いたときは0.8.0が最新版だったのですが、いまは0.9.0がリリースされていて、インストールの方法が変わっています。そして、年内に出る(と期待される)Riak 2.0の開発ブランチにすでにマージされていて、いくつか変わっています。

設定ファイルのフォーマットが変わった

こう、ものすごく…ふつうの.iniフォーマットっぽい感じになっています。どれくらいふつうかというと、ドット区切りになっていたりします!

 The enabled Yokozuna set this 'on'.
yokozuna = off

## The port number which Solr binds to.
yokozuna.solr_port = 8093

## The port number which Solr JMX binds to.
yokozuna.solr_jmx_port = 8985

## The arguments to pass to the Solr JVM.  Non-standard
## arguments, i.e. -XX, may not be portable across JVM
## implementations.  E.g. -XX:+UseCompressedStrings.
yokozuna.solr_jvm_args = -Xms1g -Xmx1g -XX:+UseStringCache -XX:+UseCompressedOops

## The data under which to store all Yokozuna related data.
## Including the Solr index data.
yokozuna.data_dir = ./data/yz

etc/app.config のかわりに etc/riak.conf というファイルになっているので適当にみつけてください。

パフォーマンスがよくなった

あとはパフォーマンス問題が解決されています。実は記事を書いているときに「スループット出ないなぁ、なんかおかしいなぁ…」と思いながら締切に追われて深く調べるヒマがなかったのであまり性能の話を書けなかったのですが、やはりボトルネックというかバグがあって、それが修正されています。なので、Yokozunaの性能を測りたい場合は0.9.0推奨です。

機能を知りたいだけなら0.8.0でも十分です。もし0.9.0のコンパイルでコケることがあったら、次の手順を試してみてください。

$ tar xzf riak-yokozuna-0.9.0.tar.gz
$ cd riak-yokozuna-0.9.0
$ ./rebar get-deps
$ ./rebar compile
$ ./rebar generate

どうもMakefileをはさむとCuttlefishあたりでおかしくなるので、まあ心配なときは deps というディレクトリを消すと最初からやり直すことができます。

それでは、Happy Databassing!!

*1:ちなみにふつうの全文検索もできるはずなので、調べたら書くつもりです

memcached API で Riak を叩けるようになりました

Deer

その名もダイコーン。まずはget, set, delete だけなんですが、とりあえず適当に作ってもMemcachedの速度の1/40くらい出ます。そのうちいろんなデータベースのAPI備えて、クライアント側を書き換えなくてもRiakを叩けるようにしたいなーと思っています。memslapの結果だと

$ ./clients/memslap --servers=localhost:11211 --non-blocking --concurrency=10

とすると

memcached dicorn/mem dicorn/riak
1.987 2.705 88.487

てな感じです(単位は秒)。

構成としては1プロセスで動くただのプロキシで、メモリもCPUもほとんど使いません。Memcachedがいたところに代わりに立ち上げて、Riakの場所を教えてあげるとそれだけでMemcachedとして動いて叩けるようになります。まだ試してませんが、複数のRiakのIPアドレスを指定できるので、Riakのノードが多少落ちたくらいだと自動的に他のとこに再接続に行ってくれます。

今回あたらしく試してみたのは、Goという言語で実装したところです。Goは軽量プロセス的なのがあってしかもネイティブコードで動くので、高速なTCPサーバーがわりと実装しやすいです(あとはバイナリパターンマッチがあれば完璧なのに…!!)。Goがすごいので、小さなコードなのにネイティブで動いてそこそこ性能もよいです。メモリもほとんど使わないし、Riakを叩くときのオーバーヘッドとしてはほとんど無視できるレベルなんじゃないかと思います。

Goなのでデプロイも簡単です。ビルドすると dicorn という名前のバイナリができるので、それをscpしてしまえばWindowsのバイナリみたいな感じで動きます。rbenvとかChefとか全く使えないぼくのような情弱にも嬉しいですね!

今後はMemcached APIもincrとかdecrを追加しつつ、CassandraとかHBase的なAPIを実装していきたいところです。インピーダンスミスマッチがすごいことになると思いますが、今後のロードマップを考えてもまあ割となんでもアリな感じでできそうな感じで、Riakが持ってるVector Clocks, CRDT, 2i, そしてこれから実装される予定のStrong Consistencyを使えば多分全部できます。これでまわりの皆さんを、Riakを使うしかない的な状況に追い込んでいきたいと思います。

Kyoto Tycoon使ってる人がいたら是非フィードバックください(チラチラ

技術書を読む読む詐欺

Books_0491

この手の「俺は今からこれを読んでログを残すぜー!」的宣言は過去に何度かやって当然失敗してきたのでそんなに期待しないで頂きたい。

Principles of Distributed Database Systems

これは御徒町と名乗るトランザクションおじさんが主導して僕も便乗させていただいている本。分散データベースの歴史をANSIの頃からちょいちょい触れながら、どういう風に最適なクエリを実行できるかにフォーカスしている感じの本。SQLとかクエリプランニングとか最適配置とか集合の分割とかそういう話が多く、CAP定理とかトランザクションとかはあまり出てこない。途中までしか読んでないのでそんな印象だけど、今後どうなるかな…?!

860p

Principles of Distributed Database Systems

Principles of Distributed Database Systems

Fault-Tolerant Agreement in Synchronous Message-Passing Systems

仲間内で同期本と呼ばれているやつ。分散調停問題とか分散合意問題について扱った二部作の一部で、同期な環境での分散合意に絞って解説している。このクエストをクリアすると非同期本クエストがオープンになり、非同期本クエストをクリアするとついにアトミックブロードキャストや高速レプリケーションが理論的な視点から見られるようになる…とはいうものの読書会の第一回に佐藤一郎先生が突然現れてひと通り分散システムの理論屋コミュニティの話をして去っていくという事件もありなかなか期待が持てそうな展開に今のところなっております。というか、同期な世界ってイマイチ現実から想像しにくくて要領を得ないものの、この分野の実践面では一日の長があることもあって、今はなんとかついていけてる状態。

190p

Fault-Tolerant Agreement in Synchronous Message-Passing Systems (Synthesis Lectures on Distributed Computing Theory)

Fault-Tolerant Agreement in Synchronous Message-Passing Systems (Synthesis Lectures on Distributed Computing Theory)

Communication and Agreement Abstractions for Fault-Tolerant Distributed Systems

こちらは分散合意シリーズ第二部。このシリーズは分散システムの権威Nancy Lynch女史のレビューを受けているとあって期待しているものの、…行き着くところはFLP impossibilityとPaxosだとは分かっているので、まあ焦らずじっくり理解していきたいところ。これが分かるとCAP定理の証明とかも理解できるようになるかも…?

274 p

Communication and Agreement Abstractions for Fault-Tolerant Distributed Systems (Synthesis Lectures on Distributed Computing Theory)

Communication and Agreement Abstractions for Fault-Tolerant Distributed Systems (Synthesis Lectures on Distributed Computing Theory)

Quorum Systems

これは分散合意本を買うときにうっかり密林社のレコメンデーションに乗って課金してしまったアイテム。Quorumについては、 N < R+W というのはよく語られる話ではありますがmutableなデータベースに限っていうと実はかなり奥が深いので期待している。 分散システム 第二版 のQuorumの記述だけだと、そりゃ狐につままれたような気分になりますって。

146p

Quorum Systems (Synthesis Lectures on Distributed Computing Theory)

Quorum Systems (Synthesis Lectures on Distributed Computing Theory)

Introduction to Reliable and Secure Distributed Programming

こちらも御徒町先生がどこからか見つけてきた本。タイトルに "Secure" と入っていたので、分散システムにおけるセキュリティの話だと思ってうっかりジャケ買いしてしまったものの目次見たら、単なる安定したシステムを作る分散プログラミングの話じゃねーか!!! とはいうものの切り口がほかとちょっと違ってr(x)とかw(x)とかいうのが見えたのでこれも期待できるかもしれない。 Webサイトも用意されてる。

320p

Introduction to Reliable and Secure Distributed Programming

Introduction to Reliable and Secure Distributed Programming

Guide to Reliable Distributed Systems

タイトルをみると( ´_ゝ`)フーンという印象しかないが、Prefaceを読むと「最近流行の分散技術っていうかクラウドコンピューティングが世界を変えたんだ、その要素技術を全部紹介するぜー!」というなんとも熱い筆者のノリが伝わってくる良著です。クラウドコンピューティングについて技術面から広く深く知りたい人(情報系の学生さんとか)には割とよい入門書だと思う。それぞれの技術については多くても10ページ程度なので、この中で興味持ったところを攻めていくとよいだろう。

752p

Concurrency Control and Recovery in Database Systems

どこかで見かけて僕の人生もリカバリと並行処理が必要だなと思って中古を買ったがPDFが公開されているので積ん読はいけないなとも思ったけどまあエキスは出ているだろう。

370p


Concurrency Control and Recovery in Database Systems

Concurrency Control and Recovery in Database Systems

The Art of the Start: The Time-Tested, Battle-Hardened Guide for Anyone Starting Anything

Guy Kawasakiのスタートアップ入門書。起業する人でなくとも、何かを始めるとはどういうことかの心構えが書かれている。じゃあ古い会社とか、大企業に勤めている人に不要かというとそうではない。愚者は経験に学ぶが賢者は歴史に学ぶのだ。自分の会社がどこから始まったのか、創業者が何をどう考えて物事を始め、なぜ成功できたのかを知るためにもよい本だ。途中までしか読んでないけど。

240p

The Art of the Start: The Time-Tested, Battle-Hardened Guide for Anyone Starting Anything

The Art of the Start: The Time-Tested, Battle-Hardened Guide for Anyone Starting Anything

Distributed Algorithms for Message-Passing Systems

これもProf. Micheal Reynal師による教科書。佐藤先生によると実装の話は嫌いな一方で理論の話はずーっと楽しそうにする人みたいだし、内容もよく網羅しているらしいので、iCarlyと一緒にポチってみた。まだ届いていないが積んでおこう。

410p

Distributed Algorithms for Message-Passing Systems

Distributed Algorithms for Message-Passing Systems

まとめると…

860 + 190 + 274 + 146 + 320 + 752 + 370 + 240 + 410 = 3562 ページもあります。100ページくらいは消化したけど、残りを週に50ページ読んでも61週間、つまり17ヶ月もかかります。私の読み様をとくとご覧あれ。

最近のネタまとめ(2)

Generating Precise Dependencies for Large Software

Googleさんの巨大なC, C++のコードベース、コンパイルとかリンクに時間がかかりすぎる問題はあちこちから聞こえてくる。その答えがいくつか(その1, その2)彼ら自身によって提案されているのだけど、やっぱりC++のコードは膨大にあるわけで既存のものもメンテナンスしないといけない。あまり依存していないライブラリとかをいつまでも残していると、ライブラリに不要な影響を受けたりリファクタリングが困難になったりする。だからなるべくスリムに保ちたい。ChromiumとかChromiumとかChromiumとか。。。もうBlinkになってしまったけどね。

依存性の解析はLLVM IRを使った。既存のASTベースのやり方だとオーバーロードされると大変だし、そもそも暗黙の関数(オペレータとかコピーコンストラクタとかデコンストラクタとか)も多いしなんといってもテンプレートがうまく扱えない。

structural dependencyとbehavioural dependencyという言葉が使われてるけどよくわからない。。。ともあれ、6MLOCあるChromiumをこれで解析してみたところ238コのモジュール、47万のシンボル、1391万のシンボル参照があり…それでunderutilizedなモジュールをいくつかみつけたよ!しかも2時間ちょいで!という内容。短いので是非よんでみるとよいかと。

Counting Server is Hard

Steve Ballmarが「ウチは100万台のサーバー持ってるぜ!!」と言ってるが…そもそもどこそこは何万台のサーバー持ってるぜ!ウチは何千台だぜ!!みたいな話どんだけ信用できるのかという話。全米の統計とか個々の値段からフェルミ推定的に想像して、100万台のサーバーを持つためには

  • 15~30くらいの大きめのデータセンター
  • 予算 $4.25B
  • 電力消費 300MW, 年間で: 2.6TWh 消費

だけ必要になる。できなくはないね、というところか*1

バグ予測は役に立ってるのか?(Googleの場合)

Does Bug Prediction Support Human Developers? Findings from a Google Case Study
バグ予測それ自体が目覚ましい成果を挙げたわけじゃないけど、Googleの中の開発のやり方とかが詳しく書かれていてとても面白かった

*1:どんだけハッタリかましてんだよ!という御大の声が俺には聞こえる

ウォーターフォールもろもろ用語について

新卒で会社に入って言葉の定義も教えてもらえず、クラスタによって用語や概念が全く違っていて混乱した人も多いと思う。僕もそうだったのでちょっと整理していきたい。このあたり、PMBOKだの難しい本を長々と読んだりしても*1どうせ役に立たないので僕の考え方を手短に書いておこうと思う。

瀬戸大橋

個人的にはV字モデルというやつはどうもよく分からんし、考えれば考えるほどやりにくいのであんまり好きじゃない。また、そもそも大前提なのだけどウォーターフォールは人間を機械だと思って統計の対象にするので、チームの規模が大きくないと(すくなくとも50人以上が関わる)個々人のばらつきが予測を壊してしまうので大規模開発(笑)が前提だ。

要求定義

そのソフトウェアやシステムで「やりたいこと」を定義する。

要件定義

そのソフトウェアやシステムの開発で検証可能な形でゴールを設定する。また、複数ある要件に矛盾があってはいけない。BIとかいったりする。もしも受発注があるなら、これが終わらないと見積りなんてできない。

基本設計

BDとかいったりする。◯◯機能とかいうのを並べるだけだと思いがちだが、実際にやるべき作業は問題を分割することだ。要件を複数の問題にブレークダウンすることによって分業したり、検討しやすくしたりするためだ。ここで出来上がるのが基本設計書で、開発を通じてのバイブルになる。
ここでのコツは適切な粒度にすること、分割された他の機能のことは知らんと言ってはいけない、実装の骨組みをほとんど決めてしまうこと、くらいかな。

詳細設計

基本設計で分割された問題に従って、ほとんど決めてしまったシーケンスやフローチャートを書き下す。このときあんまり考えてたらダメ。ただの作業なので、なるべくツールを使って効率化すべきなのだがDoxygenはわりと痛い目を見てきたのでアノ手のツールは使わない方がよい。

製造、ユニットテスト

このへんはみなさん得意ですよね、僕は苦手だけど。別にここでTDDってやつをやってもいいと思う。
この工程で出るバグは記録を残しておくとあとで役に立つ。

試験1

ぼくのところではDB1と呼んでたりした。基本設計のときに問題を分割したが、その個々の問題をちゃんと解けているか(各◯◯機能が正しく動いているか)をここで確認する。ここでテストをある程度書いてしまっておくと便利だと思う。
責任者はこの工程から、出てくるバグを全て理解しておかなければならない。

試験2

こっちはDB2だけど、まあシステムとしてトータルで動いているかを確認する。具体的には、要件定義のときに設定したゴールを達成できているかをテストする。わりと人力じゃないとツラいことが多いけど、ここで長安試験(エージング試験)とかをやったりする。
ここでセグフォとかRace Condition系の問題が出ると結構難しくて楽しい。

検収

まあどうせ短い期間しか用意できないので、形式的なものになりがちなのは避けられない。発注側の人がいるなら、発注側の人は最初から開発側と密接にやり取りをしておくべき。どうせ検収の試験で分かるのはわずかなことだけなので。また、受注側の人がいるなら、折をみてきちんと説明しておこう(発注側の信頼を勝ち取っておけば検収は大抵うまくいく)。

振り返り、メトリクス

まあソフトウェア工学いろいろあるので勉強してみるといいんじゃないかな。集計してみるとわりと面白いし失敗したとき上司にうまく説明できると思う。

うまく進めるコツは

  • ドキュメントに間違いが見つかったら容赦なく修正する
  • 各工程の終了条件を予め決めておくこと(バグ0とか仕様書が出来上がっているとか)。まあ決めておいても、場合によっては一部だけ他の工程に進むとかやってしまってもOK(斜め線表とか言ったりしてた)
  • 各工程で常にメトリクスを監視して、スケジュールが遅れそうな要因を早めに潰してしまうこと
  • スケジュールが遅れそうな場合、要件を削る(ここ重要、削るのは機能ではなく要件)
  • 要件を削れなそうなら容赦なくスケジュールを伸ばす(追加要員は、たとえば50%稼働でプロジェクトに入っていたひとを100%にするとかはアリだがそうじゃないなら意味がない)。ただし伸ばし方は「工程が進むに従って判明した情報をもとに、正しい見積もりをやり直す」
  • 上流工程でも重要なポイントなら容赦なく実装の議論をする

くらいだろうか。ちなみに個人的には「仕様書」という言葉はインターフェース定義にしか使ってはいけないと思っていて(◯◯仕様書とか見たら眉に唾をつけるべし)、理由はまあいろいろあるんだけど仕様という言葉が何を意味するかを一度じっくり考えてみないと理解できないのでここでは書かないことにしとく。

*1:読んだことない

ディスクフルについて

inspired by

個人的に好きなのはこれ。

この流れならRiakでどうやるかの詳しい話を僕も書ける…と思っていたら俺はもうすでに書いていたッ!!! ソフトウェアデザイン8月号、100〜101ページのRiak連載に書いていたッ!!

というわけで皆さん買ってください。