ドメイン駆動設計読んだ

エリック・エヴァンスのドメイン駆動設計 (IT Architects’Archive ソフトウェア開発の実践)

エリック・エヴァンスのドメイン駆動設計 (IT Architects’Archive ソフトウェア開発の実践)


ドメイン駆動設計読み終った。ドメインを中心に据えてソフトウェアを設計するための方法を教えてくれる本だった。設計の話なので、抽象度が高く、なかなか読み辛いけど、良い話がたくさんでてくる。この本で例にでてくるソフトウェアが経理システムだとか貨物の配送システムなどのエンタープライズよりだったので、はじめは自分のようなWebエンジニアとっては参考にしにくいかと思っていたのだけど、まったくそういうことはなく、たいへん参考になった。

ドメイン駆動設計でいうドメインとはソフトウェアが価値を生み出す問題領域のことだ。ドメイン駆動設計手法では、開発チームがドメインエキスパートと継続的に議論してドメインモデルをつくりあげ、ソフトウェア中でも同じドメインモデルを利用することで、チーム全体がドメインに対する知識を深めることを可能にし、理想的にはドメインを良くモデリングした有用かつ変化に強いソフトウェアが効率良く開発できる。(すごい)

この本が良かったのは、詳細レベルの設計テクニックではなく、アプリケーション全体をどのように設計するべきか、ということについてかなり詳細に説明してくれているところだ。これまでソフトウェアを設計するときにぼんやりとして捉えられていなかったところが、とてもよく整理されていて勉強になった。

例えば、第2部の”モデル駆動設計の構成要素”ではモデルをエンティティ、値オブジェクト、サービスなどの種類のオブジェクトに分類し、それらのライフサイクルはファクトリやリポジトリによって管理するという構成について教えてくれる。自分が設計しているコードのモデルが、それぞれどういった役割を意図していたものか、より整理された見方ができるようになった。

他にもドメインモデルをうまく取り扱えるように、継続的にリファクタリングする方法や、より複雑なシステムにおける設計戦略について紹介されている。ドメイン駆動開発の利点を分析するために、実例に基づいたアンチパターンが、都度、紹介されるのだけど、多くに心当たりあってなかなかつらい。しかし、なぜ悪いのか説明してくれるので、とても役立つ。

理想的な話に終始していないのもよい。時代はドメイン駆動設計や!とかいって、急激に設計を変えても良い設計にはならず、少しづつおかしなところを継続的にリファクタリングしていかなければならないという話や、もはや設計を変えることができないレガシーシステムになんとか対処する方法などについてもくわしく言及されていて、現実の問題に対応している。

自分がソフトウェアをつくる中で感じたり、これまでチームで議論してきた、設計上の難しい部分が、ドメインモデルを軸に次々と整理されて、目からうろこという感じだった。自分のように、これまでWebアプリケーションの設計をしてきた人にとっても、これまでうまくいった(あるいはうまくいかなかった)設計についての評価がたぶん見つかるので、ためしに読むと参考になると思う。急にすべての設計パターンを実際のプロジェクトに反映するのは難しいし、それこそ急激な設計変更になってうまくいかないだろうから、少しづつ実際の開発に生かしていきたい。

レジでの支払いのはなし

レジとかでお金を払うときに、支払う紙幣/硬貨の枚数が少なくて、かつ、お釣りの紙幣/硬貨の枚数が少ない、かっこいい支払いというのがある(適当)。あわよくば、かっこいい支払いをしようと思っていつもねらってる。なんか適当に言ってるけど、451円払う時に、適当に500円玉を渡すと10円x4枚+5円x1枚+1円x4円がお釣りになるのはイヤなので、501円を渡してお釣りを50円x1枚にしたりする、よくあるやつです。

451円請求されているときには、だいたい501円はらったら良さそうなのはわかる。では、例えば771円請求されている場合は、どうすれば最適な支払いになるかと考えると、801円か1001円か1021円かそのあたりかなーという感じですこし丁寧にしらべる必要がある。

小銭が関係する1000円以下の最適な支払いパターンくらいだと、機械的に全パターン調べられそうだったのでプログラムを書いてみた。以下のフォームに金額をいれると、どう支払ったら最適な支払いができるかわかる。ここで言ってる最適な支払いとは、レジの人に支払う紙幣/硬貨の枚数とおつりの紙幣/硬貨の枚数の合計が最小になるような支払いのことだ。お財布の中には、すべての種類の小銭が十分に入っているという前提で計算してる。(100円支払うのに1円玉100枚つかったりしない)

レジで771円請求された場合、おつりがないように771円払うのと、1001円払っておつりをもらうのと、1021円払ってお釣りをもらうのとでは、どれも同じ枚数だけの硬貨/紙幣がやりとりされる。支払う硬貨/紙幣の枚数とおつりの枚数はちがうので、あとは好みの問題ということになる。801円払う場合は、1021円と比べると支払い枚数が多くなってしまうわりに、お釣り枚数は変わらなく、最適とはいえない。なるほど〜

実際には、レジの前で支払いパターンの計算とかしてたら迷惑だし、財布のなかに入ってる小銭との兼ね合いを考えないといけない。そもそも、直感的な判断でだいたいなんとかなってるし、レジでの支払いでやりとりされる硬貨/紙幣の枚数が多少ちがったところで、だれも困らないので、まじでどうでもいい話だった。

金額をいれると、レジのまえでよくやってるお支払い行為に対応した数字が出てくるのはちょっとおもしろい。評価関数を変えれば最適の基準もいじれるので、とにかく財布の中の小銭を減らすストラテジーとか、モデルの改善の余地はある。がとにかくどうでもいい感じではある。

unite-scriptがUnite.vim本体に取り込まれました

ずいぶん前につくった unite-script が、先日リリースされた Unite.vim の ver 6からscript sourceとして本体に取り込まれました。今後は、別にunite-scriptをインストールすることなく、script sourceが利用できます。

unites-scriptはずいぶん長い間メンテナンスが滞っていて、ご迷惑をおかけしていたのですが、今後は本体機能として安心してご利用いただけます。取り込みなどほとんどの作業は、Unite.vimの作者の@Shougo さんにやっていただきました。ありがとうございました!!

そもそも、unite-scriptは、unite.vim の source をお好きなスクリプト言語で書ける unite-script - はこべブログ ♨ という記事ではじめて登場した、Unite.vimのsourceの1つです。自由なスクリプトを実行し、その実行結果をUnite.vimに表示してアクションを実行できます。

例えば、以下の様なスクリプトを準備することで、Githubの通知をvimから表示することができます。

このscriptを実行すると以下のように、項目名と、選択されたときのアクションがTAB区切りで一行ごとに標準出力に表示されます。この場合はgithubからの通知の内容と、スクリプト自身にURLを渡して起動するアクションがTAB区切りで一行ごとに表示されています。

$ ruby /path/to/github-notify.rb list
[htmlcatgo Issue] 色付けに対応	call unite#util#system('ruby /path/to/github-notify.rb open https://api.github.com/repos/hakobe/htmlcatgo/issues')
[unite-script-examples Issue] CPANモジュール依存を取り除く	call unite#util#system('ruby /path/to/github-notify.rb open https://api.github.com/repos/hakobe/unite-script-examples/issues/7')
[unite-script-examples Issue] 売りになりそうなおもしろいscriptを思いつく	call unite#util#system('ruby /path/to/github-notify.rb open https://api.github.com/repos/hakobe/unite-script-examples/issues/6')

このスクリプトをUnite.vimのscript sourceで利用するには以下のようなコマンドを実行します。

:Unite script:ruby:/path/to/github-notify.rb list

これで 以下のようにvimからGithubの通知を確認できるようになりました。自分のPullRequestのレビューが進んだかどうかなどがvimからすぐに確認できるので大変便利です。

f:id:hakobe932:20140220213732p:plain

このスクリプトを動作させるには、~/.unitescriptrcにyamlで設定を記述する必要があります。くわしくはscript内のコメントを御覧ください。Github Enterpriseにも対応しています。

こういう調子で、仕様にしたがって出力を組み立てるだけで、いろいろなものをUnite.vimに表示できて便利です。ぜひお試しください。これまで公開されていた以下のようなスクリプトも利用できます。(ありがとうございます > 公開いただいていた方々)

script sourceがUnite.vimで利用できることになったのに伴い、unite-scriptのリポジトリはunite-script-example として、script source用の便利なスクリプトをあつめるリポジトリにしましたので、おもしろscriptができましたらぜひPull Requestしてみてください。


個人的には itunes.pl が便利で気に入ってます。(Macでしか使えません)

f:id:hakobe932:20140220210614p:plain

どうぞご利用ください。

2014/02/14 追記

Shougoさんから教えていただいたところによりますと、Unite.vimのscript sourceに指定できるコマンドは、vimのruntimepathからの想定パスで指定できるそうです。

ですので、.vimrcに

NeoBundle 'hakobe/unite-script-examples'

のように書くと、.vim/bundle/unite-script-examplesがruntimepathにはいるので、.vim/bundle/unite-script-examples/examplesにはるスクリプトを以下のように利用できます。

:Unite script:ruby:examples/github-notify.rb

パスの解決をする必要がなくて、大変便利ですね。

すごいHaskellたのしく学ぼう! を読んだ

すごいHaskellたのしく学ぼう!

すごいHaskellたのしく学ぼう!

読み終わった。すごく丁寧にHaskellの考え方を教えてくれる本。じわじわ概念を教えてもらえて、最終的にはモナド便利やん! というところまで到達できて、とても良い本だった。

いっしょに働いている同僚のmechairoiさんがHaskellに詳しくて、Scalaでコードを書いていると「implicit は型クラスを定義するのに便利なんだよ」とか「for式っていうのは、Haskellでいうdoだから便利」ということを教えてくれる。どうやら便利そうな概念なのだけど、型クラスとかモナドなんかをちゃんと理解できていなくて良くないので、この本を読んで入門してみることにした。

この本は、教えてくれる順番がすごくよく出来ていて、難しい概念も前半のほうから、気づかないうちにすこしづつ小出しされていって、だいたい理解した頃に、今まで行ってきたのはじつはこれのことでしたというふうな展開になるので、納得しながら読み進められる。

具体的には、7章くらいでファンクタという概念が説明されて、そのあと練習問題をはさんで理解が深まった11章あたりで、ファンクタの強化版という触れ込みでアプリカティブファンクタの話がでてくる。MaybeやリストやIOあたりがアプリカティブファンクタであることを説明されたり、文脈を維持したまま計算を組み立てるのに慣れてきたころに、実はモナドというのがあるという話になる。この頃にはMaybeがモナドだとか言われても、話の流れで自然に理解できるし、ファンクタ則とかも勉強してきているので、モナド則が現れても特にこわくない。

圏論とかよくわからないけど、実用的にはモナドをどう使えばよいか、何が便利かは理解できたような気がする。強い型付けのあるHaskellのような言語でのプログラミングスタイルも見ることができた。めっちゃHaskellを書きまくるという予定はないけど、学んだことはScalaではすぐに役立ちそうだし、それ以外の言語を使う時にも計算の扱うときの考え方の道具が増えて役立ちそうという感じだった。

Dockerでgoのテストを実行する環境をつくる

1つのJenkinsの環境で複数のプロジェクトのテストが実行されることは、ままあると思う。Jenkins上で動作するすべてのプロジェクトが同時に動作するようにJenkins環境を整えるのは難しいことがある。あるプロジェクトのためにライブラリのバージョンを更新したことで、別のプロジェクトのテストが落ちるとか。

Ruby なら Bundler やrbenvを使って環境を切り替えるとだいたい解決するけど、libhogeみたいな共有ライブラリやBundlerやrbenv自体の更新とか、どうしても共有される部分はあって、だいたい普段は問題はないが、まれに困ると言う感じだと思う。

そこで、テストごとにDockerのコンテナを立ち上げてその中でテストを実行するようにすれば、環境を独立させることができるので、環境をこわさないように丁寧に設定するみたいなことに気を使わなくてよくなるので便利。

miyagawaさんのdocker-plenv-vanillaを使うとplenv環境がととのったDokcer imageを作ったりできる。こういう感じでgoが動くDocker imageを作ってgoのテストを動かしてみたので、ご紹介します。

Dockerfile になんか以下のように書く

FROM ubuntu
RUN apt-get -y update
RUN apt-get -y install curl sudo git build-essential

RUN mkdir -p /opt/local
RUN curl https://go.googlecode.com/files/go1.2.linux-amd64.tar.gz -o /tmp/go.tar.gz
RUN tar -C /opt/local -xzf /tmp/go.tar.gz

RUN mkdir -p /gobuild/src
RUN mkdir -p /gobuild/go/src/example.com/hakobe
RUN ln -sf /gobuild/src /gobuild/go/src/example.com/hakobe/goproject

RUN echo 'export GOPATH="/gobuild/go"' >> /gobuild/env
RUN echo 'export GOROOT="/opt/local/go"' >> /gobuild/env
RUN echo 'export PATH="/opt/local/go/bin:$PATH"' >> /gobuild/env

以下のようにしてimageを作る。

$ docker build -t gobuild .

テストは以下の様なスクリプトを用意しておいて実行する

docker run \
    -name gotest \
    -v "/path/to/goproject:/gobuild/src" \
    gobuild \
    sh -c 'cd /gobuild; . /gobuild/env; go test -v ./...'
result="$?"
docker rm gotest
exit $result

ポイントは以下の様な感じです。

  • /path/to/goprojectにあるソースコードはdocker run するときに /gobuild/src にmountされる
  • goがパッケージ名を解決できるように、/gobuild/srcから /gobuild/go/src/example.com/hakobe/goproject にシンボリックリンクを張っておく
    • パッケージ名が go get できる感じになっている場合は、こんなことする必要ないと思う
    • 直接 $GOPATH/src以下にmountしてもいいかもしれない
  • goの実行環境はバイナリのtarball持ってきて展開すれば作れる
  • 実行用の環境変数は /gobuild/env にとっておいて、テスト実行時に source する
    • /etc/bashrc? とかで勝手に読み込まれるようにしといても良いかもしれない
  • 最後にdocker rm しないとテストを実行するたびにコンテナがmountされたままになる
    • コンテナのmountはカーネルプロセスがやっていて、メモリを消費するので、ほうっておくとDockerのホストが爆発する
  • Jenkins上でdocker buildしているような体だけど、実際はdocker repositoryとかを活用したら良いと思う

今期アニソンの様子

気に入ってるアニメに基づいて以下あたりを聞いてます。ほかにも良い今期アニソンあったら教えて欲しい。

秘密の扉から会いにきて

秘密の扉から会いにきて

  • 田村ゆかり
  • アニメ
  • ¥250
  • provided courtesy of iTunes
ビジュメニア

ビジュメニア

  • 悠木碧
  • アニメ
  • ¥250
  • provided courtesy of iTunes
Be mine!

Be mine!

  • 坂本真綾
  • アニメ
  • ¥250
  • provided courtesy of iTunes
SAVED.

SAVED.

  • 坂本真綾
  • アニメ
  • ¥250
  • provided courtesy of iTunes
今日に恋色

今日に恋色

  • May'n
  • アニメ
  • ¥250
  • provided courtesy of iTunes
CLICK

CLICK

  • ClariS
  • アニメ
  • ¥250
  • provided courtesy of iTunes
本命アンサー

本命アンサー

  • 桐崎千棘・小野寺小咲(東山奈央・花澤香菜)
  • アニメ
  • ¥250
  • provided courtesy of iTunes
VOICE

VOICE

  • ZAQ
  • アニメ
  • ¥250
  • provided courtesy of iTunes
Van!shment Th!s World

Van!shment Th!s World

  • Black Raison d'être
  • アニメ
  • ¥250
  • provided courtesy of iTunes

IntelliJでvimキーバインドを使う

  • IdeaVimを使う
    • index.txtに何ができるか書いてある
    • TextObject的な操作もできて高機能
  • IdeaVimの利用に関係なくIntelliJはキーボードショートカットの入力時のキーボード種類がUS固定になってるらしく、JISキーボードを使ってると、押したキーと違う値が入力されたりする(マジか
    • この影響で Ctrl-[ が Ctrl-] とみなされてしまい ESC が入力しずらい
    • 以下のように Ctrl-] がつねにESCになるようにしておくと概ねよいけど雑な感じ

http://cdn-ak.f.st-hatena.com/images/fotolife/h/hakobe932/20140203/20140203224338.png


まじかって感じだけど、せっかく良いIDEがあるんだしということで、上のような設定をしてだましだまし使ってみることにした。

追記

参考になるアドバイスをいただいた