肉とビールとパンケーキ by @sotarok

少し大人になった「肉とご飯と甘いもの」

Behat でメソッド定義して正規表現にもマッチしているはずなのに「未定義」と言われてハマった件

原因が分かったときに死ぬほど悲しかったが、ひとまず記録しておく。

    ...
    When I run "git daily init"
    ...

とか書いてて、メソッドも

<?php

    // ...

    /*
     * @When /^I run "git daily(?: ([^"]*))?"$/
     *
     * @param   string  $args
     */
    public function iRunGitDaily($args = '') // {{{
    {
       // ...   
    }

と定義してあって、これで間違いなく正規表現にマッチしているはずなのに、

未定義のステップを、次のスニペットで実装できます:

    /**
     * @When /^I run "([^"]*)"$/
     */
    public function iRun($argument1)
    {
        throw new PendingException();
    }

などと言われ、やたらハマってたんだけど、落ちついてドキュメントをもう一度読んでいたら、

Notice the comment block starts with /**, and not the usual /*. This is important for Behat to be able to parse such comments as annotations!

Defining Reusable Actions - Step Definitions — Behat 2 documentation

。。。oh ... なるほど ...

メソッドの定義を

<?php

    // ...

    // ↓ここが ** じゃなくて * になってた
    /**
     * @When /^I run "git daily(?: ([^"]*))?"$/
     *
     * @param   string  $args
     */
    public function iRunGitDaily($args = '') // {{{
    {
       // ...   
    }

これで解決。
初歩的?

  • (追記) ソースまで追っかけてないけどこの仕様は多分 PHP の ReflectionMethod の getDocComment() メソッドの仕様によるものとおもわれる

「Pull Request」 はオープンソースに限らず使える優れた開発フローだ

チーム開発において、「チケット/Issue」「TDD」「コードレビュー」など、ソースコードの変更に対する効果的な開発フローについてよく考えるのだけど、なんにしてもこのあたりは非常に課題が多く、各社各コミュニティで色々なやり方が模索されているポイントだと思う。

で、まぁご多分に漏れず僕もよく考えるわけだけど、現状その過程で Pull Request こそが非常に効果的なのではないか、と思うので、ちょっとまとめてみようかと思う。
もちろん、言うまでもないようなことだよ、という人もいるかもしれないけど、そういう人がたくさんいると、非常に喜ばしいことだね。

Pull Request とは

GitHub でこう呼ばれているので、こう呼ぶことにするが、ここでは、複数のリポジトリ/ブランチ間でのオープンな patch のやりとりのことだと考える。
あと、自分が使っているのが Git なので、ここでは Git について扱うけど、Git 以外の分散VCSでも当てはまる議論だと思う。

前提条件
  • 複数人で1つのソフトウェアを開発する
  • 分散型VCS (Git。もちろん Mercurial などでも良いと思う) で、各自がリポジトリを保持している。
  • チーム開発なので全員が同じものを開発していて、リリースマネジメントの過程では、どこかに「マスター」的なものが存在する
    • つまり、ここからリリースしますよ、という大元。
    • Linux などでは Linus が持っているリポジトリ、なのかもしれないけど、大抵の場合はGitサーバ (e.g. GitHub) などのようなものが存在しているよね?
  • 各自は自分のリポジトリで、開発ブランチまたは開発ブランチから派生したブランチで開発を行う
Pull Request

フローを手順化すると、概ねこういうことになる:

  • あるリポジトリ A の develop ブランチから fork したリポジトリ A' の develop ブランチがあり、そこに変更を加えたコミットが存在する。
  • リポジトリ A の管理者 (あるいは、その変更箇所に対する責任者) に、「A' の develop ブランチに変更おいてあるので pull してくれ」と要求する
    • それが Issue (チケット) 化される
  • A の責任者がそれを確認し、A' -> A に merge を行う。


ちなみに、GitHub では、fork して変更して push し、元のリポジトリのページを開き、Pull Request というボタンを押して、どのブランチをどのブランチに Pull Requset をするか、という確認をし、確定すると完了。Request された人は、diff を確認したり、その変更されたブランチをチェックアウトしてテストを行ったりして、問題がなければ merge 、というフローとなる(fast-forward 可能であればウェブ上からもボタン1つで merge できる)。

ソースコードに対する責任とカオス化

複数人での開発で必ず伴うのは「人が書いたコードでは足りない機能を実現する」ことだ。

ここに登場するのは、ある機能を提供するサービス *1 と、それを書いた Alice さんがいるとする。

このとき、ソースコードに対する責任は、Alice さんにある (とする)。これは、よくあることだと思う。*2

そして、そのサービスを利用した機能を実装していた Bob さんが、このサービスで提供されている機能だけでは足りないことに気づいたとする。そうしたときに、いくつかのやり方があると思うけど、それをちょっと書きだしてみようかと思う。

変更・対応を依頼する

ひとつは、Alice さんに「こういう機能が足りないんだけど、追加してほしい」と依頼することだ。これは、縦割りになった会社や、そもそも会社が違ったり、クローズドなライブラリを利用している場合にはよくあることだと思う。

ただ、 オーバーヘッドが大きいという問題がある。Alice さんがいつ対応してくれるか、という問題 *3。変更の依頼・対応は、コミュニケーションコストが大きいし、「今すぐ欲しいのに」にはどうしても対応できない。さらに、コミュニケーションミスで、変更されたのに依頼された機能が提供されない場合もある。そしたら差し戻しだし、さらにコストはかさむ。

しかし、ある程度これは、業務形態とか色々な要因 (外部サービスを利用する場合など) によって、たとえオーバーヘッドが大きくても、こうせざるを得ない場合も多いね。まぁそれは仕方がないけど..

変更し、確認をとりコミットする


よくコミュニケーションのとれたチームではこれが出来ると思う。
Bob さんも、ある機能を追加したい場所を探し当て、そこに変更を加える。diff を見せて、「こういう変更をしたいんだけど」と Alice さんに確認をとる。Alice さんは、「大丈夫だ問題ない」と答え、Bob さんはそれをコミットする。

変更せずに解決する方法を探す


当該箇所には変更せずに自分の希望する機能が提供されるようにする。
これは、Aliceさんの責任範囲には影響しない自分の責任でコードを追加するというイメージ。

しかし、こういうことを繰り返すと、謎のオプションが増えたり、似た様なメソッドが増えたりして、後述のカオス化が完成する。

勝手に変更する



最も悪いのはこのパターン。勝手に変更してしまう。あとから Aliceさんが「おいちょっと何この変更」となることは目に見えている。
テストでこけてくれればまだ良いが、気づかずにバグが混入している場合もある。

カオス化

一番ツライのは、「変更せずに解決する方法を探す」と「勝手に変更する」だ。
Alice さんが作ったらしき機能に変更を加えずに自分の欲しい機能を追加していったり、あるいはAliceさんの意図とは別の意図がコードにどんどん追加されたりすると、そういったものが積み重なって、例えば「似た様な機能を提供するメソッドが別名でたくさんある、しかもいたるところで両方が使われているしどっちも消せない手が出せない」みたいなことがおこってしまいにはちょっと違うことをやる似た様な機能について更に同じようなことが繰り返される。カオスである。

こうなると誰も手を付けられないので「あーそこは樹海だからさわらないで」みたいなものが完成する。おめでとう。

Pull Request がもたらす「小さなパッチ」とコードレビューとリファクタの機会

そもそも、Git の利点として、自分の元にリポジトリを持てる、気軽にブランチを切り気軽にマージできる、というのがあるけど、Pull Request こそ、これを最大限生かした理想的な開発フローなのではないか。

上述のやりとりを Pull Request に置き換えると、次のようになる。

  • Alice さんが責任をもつ箇所について、Bob さんが変更し、patch をつくる (小さなパッチ)
  • Pull Request を送る
  • Alice さんがそれを確認する (レビューとリファクタ)
  • 変更を取り込む

上述でいうところの「変更し、確認をとりコミットする」によく似ているけど、

  • Git の分散性、ブランチ機能を生かした効率的なフローがシステムよって提供され、
  • オープンにやりとりされる、

という点が異なる。

小さなパッチを繰り返すこと

ソースコードへの変更は、大きければ大きいほど影響範囲やバグの混入する確率も大きくなるので、パッチは小さければ小さい方が良い。
できれば単一機能についてその都度パッチがあるのが良い。

だから、小さな変更でも、自分の責任下で済まないソースコードの変更は、すべて Pull Request になっているべきだ。小さな diff であればあるほど、小さなコストで確認ができる。それを繰り返すことが重要だ。

コードレビューの機会を設けること

コードレビュー会のようなものが開かれるチームもあると思うけど、色々な変更が含まれた大きな diff や、複数人が責任をもったソースコードについて、いっぺんにたくさんのコードをレビューするのは非常に大変だし、コストが大きい。その点、Pull Request であれば、小さな patch ごとにレビューが入るため、コストが小さく、議論が1点に集中できるため質も高い。

また、防げるべきことが防げる、という利点もある。
Bob さんは、その変更の影響範囲はわかっていたつもりで、それに対応したつもりだけど、想定できていなかった影響範囲について、Aliceさんのチェックが入る。これは非常に大きなことだ*4。「勝手に変更された」場合、あとからこの変更を知り「ちょっとなんでこういう変更になってるの?」となってしまうし、できるだけそれは避けたい。

コードに対するチェックの目は多ければ多いほうが良いが、とはいえ毎回全員の変更を誰かがあるいは全員がチェックし合うのは非常に大変。自分が書いたことのある単一機能に対して他の人が変更加えたいときに、どう変更されるかをチェックできる、という仕組みが Pull Request によって、コストの低い形で提供される。

リファクタされる

Bob さんが欲しい機能についての変更がレビューされるということは、Aliceさんが、それがその機能を提供するための変更にとって良い変更なのか、がチェックされることになる。
あるいは、「このメソッドはこういう意図で使われるからこの変更はココじゃないほうがいいなあ、こっちのメソッドにオプションを作ろう」のような提案ができるかもしれない。

小さなdiffでリファクタされることは、カオスになりきった大きなコードをあとからリファクタすることよりもコストが非常に小さく済む。

オープンであること

Alice さんと Bob さんが、こういうやり取りをしてこの変更が加えられたのだ、ということが他の人に分かる形で残る、というも非常に良い。

上記の「変更し、確認をとりコミットする」では、Alice さんと Bob さんの間では共通認識の確認がとれるが、そこに Charlie さんがまた変更したいと思った場合に、その時のやり取りがわかるかわからないかで、考えられることが違うと思う。その機能を提供するコードが、どういう意図で書かれているのか両人の意図がすぐにわかるはずだ。

まとめ

  • ちいさなパッチを常々レビューしよう
  • そのために、仕事でも Pull Request を使おう。
    • 「GitHub を仕事で使う」はモチロンOKだと思います。
      • お金のあるところは GitHub Enterprise が手っ取り早い。まじ高いです。
      • そうでないなら Organization で有料プランを使うのがよさげ
    • GitHub はちょっと... という人は Gitlab オススメ。Merge Request という機能があります。 *5


ちなみに、Redmine で Pull Request 的なことを何度かやってみたけど、チケット化して当人同士で管理するのはできるけど、どのブランチからどのブランチへどの diff を? のような記録を明示的に残すのが難しいなーと感じた。


繰り返しになるが、patch のやり取りやコードレビューを、システムによって効率的に低コストで行うことができるようになったことが、Git の、GitHub の革命であり、これを開発フローに取り込むというのは非常に有効な手段だと思う。


(追記) :

すいません、すいません、本当に忘却してました。
メールでのやりとりで、request-pull / am でパッチのやりとりをする機能が Git にはありますね。


オススメ:
入門Git (濱野 純(Junio C Hamano)) - Amazon

*1:とここでは呼ぶけど、MVCでいうところのモデル的な場所のこととか、リポジトリクラスとか、まぁだいたいそういうイメージ。

*2:ちなみに、ちょっと横道にそれるけど、自分が書いたコードに対する責任をちゃんと持つようにしましょう

*3:Aliceさんがすぐ対応してくれる場合もある。だけど、その場合Aliceさんにとっては差し込みの仕事だし、これはAliceさんにとってのコストが増大する

*4:テストが書いてある、というのも重要だけど、それは別の話になるので今回は割愛

*5:そういや横道にそれるけど、何度も Twitter などで言っているけど、GitHub クローンなどと称されるプロダクトはちょいちょいでてきてるのだけど、Pull Request こそが GitHub が起こした革命だと思うので、これが無いものは GitHub クローンなどではなく、ただの Git リポジトリビューワーですね。

いつも忘れて頑張って検索して名前を思い出すのでメモしておくスティーブン・キング原作のホラー「ランゴリアーズ」

「ランゴリアーズ」

f:id:sotarok:20120214001853j:plain

NHK で深夜にやっていたのを姉だか母だかといっしょに見ていたんだけど、飛行機に乗っていた人たちが何人かを残して消えてしまい、謎の世界?へいってしまう。そこで迫り来る危機と、飛行機で人が消えた理由(というか自分たちが残った理由)を考えながら生還を目指す的な内容だったきがする。
結構怖かった。

自分の記憶が正しいのかわからないけど面白かったような記憶があるので一度DVD借りてきて見ようかなーと思っている。

pecl install hoge でインストールしたとき、インストール先が extension_dir じゃないディレクトリになってしまう場合

Debain での話。

  • 手元で色々 PHP いじってて環境が微妙なことになってしまったとき
  • まぁ、こういうことになる人ってあんまいないと思うけど
$ sudo pecl install hoge

でインストールすると、

...
checking for PHP includes... -I/usr/include/php -I/usr/include/php/main -I/usr/include/php/TSRM -I/usr/include/php/Zend -I/usr/include/php/ext -I/usr/include/php/ext/date/lib
checking for PHP extension directory... /usr/lib/php/20100525-debug
checking for PHP installed headers prefix... /usr/include/php
...

おや?
で、当然 /etc/php5/conf.d/http.ini とかに

extension=http.so

とか書いても、

$ php -v
PHP Warning:  PHP Startup: Unable to load dynamic library '/usr/lib/php5/20090626/http.so' - /usr/lib/php5/20090626/http.so: cannot open shared object file: No such file or directory in Unknown on line 0
...

とかいわれる。
extension のインストールされたディレクトリと、phpの設定がもってる extension dir が違うようだ。

$ php -i | grep extension_dir
extension_dir => /usr/lib/php5/20090626 => /usr/lib/php5/20090626

となるから当然で。

あれ、じゃあなんで pecl install するときにここに入らないのだ、と思い一応 pecl config-show で確認。

$ pecl config-show
...
PHP extension directory        ext_dir          /usr/lib/php5/20090626
...

ちゃんとなっている。

ビルドのときには /usr/bin/php-config が使われるのでそれも確認

$ which php-config
/usr/bin/php-config
$ php-config
...
  --libs              [-lcrypt   -lz -lcrypt -lonig -lcrypto -lssl -lcrypto -ldb-4.8 -lqdbm -lbz2 -lz -lcrypto -lssl -lcrypto -lrt -lm -ldl -lnsl  -lxml2 -lgssapi_krb5 -
lkrb5 -lk5crypto -lcom_err -lxml2 -lxml2 -lxml2 -lcrypt -lxml2 -lxml2 -lxml2 -lxml2 -lcrypt ]
  --extension-dir     [/usr/lib/php5/20090626-debug]
  --include-dir       [/usr/include/php5]
...

あれ。

php-config は誰によってインストールされるか、

$ dpkg -S php-config
php5-dev: /usr/share/man/man1/php-config5.1.gz
php5-dev: /usr/bin/php-config5

php5-dev。だけど /usr/bin/php-config5 ってことは多分 /usr/bin/php-config は symlink にしてるんだな、と確認してみると、

$ ls -la /usr/bin/php-config
-rwxr-xr-x 1 root root 4570 2012-02-03 08:36 /usr/bin/php-config

あれ。実体だ。

つまり原因は、

  • 何かしらのタイミングで php-config が実体になっちゃった
  • php5-dev をインストールしなおしても、update alternatives が働かない
  • 何かしらのタイミングで実体になっちゃったものがずっとつかわれちゃってる
  • pecl install のときにおかしくなる

ということなので、 /usr/bin/php-config を削除して php5-dev のインストールしなおし

$ sudo rm /usr/bin/php-config
$ sudo apt-get remove php5-dev
$ sudo apt-get install php5-dev

...

php5-dev (5.3.10-1~dotdeb.1) を設定しています ...
update-alternatives: /usr/bin/php-config (php-config) を提供するために 自動モード で /usr/bin/php-config5 を使います。
update-alternatives: /usr/bin/phpize (phpize) を提供するために 自動モード で /usr/bin/phpize5 を使います。m

で、再度確認

$ ls -la /usr/bin/php-config
lrwxrwxrwx 1 root root 28 2012-02-06 11:47 /usr/bin/php-config -> /etc/alternatives/php-confi

$ php-config
...
  --libs              [-lcrypt   -lz -lcrypt -lonig -lcrypto -lssl -lcrypto -ldb-4.8 -lqdbm -lbz2 -lz -lcrypto -lssl -lcrypto -lrt -lm -ldl -lnsl  -lxml2 -lgssapi_krb5 -
lkrb5 -lk5crypto -lcom_err -lxml2 -lxml2 -lxml2 -lcrypt -lxml2 -lxml2 -lxml2 -lxml2 -lcrypt ]
  --extension-dir     [/usr/lib/php5/20090626]
  --include-dir       [/usr/include/php5
...

OK。
で、 pecl install してめでたし。

追記

最初の php-config のときに

  --version           [5.4.0beta1-dev]
  --vernum            [50400]

が出てたので自分で作ってた php5.4 の .deb をインストールしたときだなー間違いなく。

ますますこの問題おこるひとほとんどいないきがするよ。。
起こるとしたら、debian標準のaptから dotdeb に切り替えたとか、何かしら環境を変えた時とか。

KnpPaginatorBundle で Twitter Bootstrap でうまいこといくやつを出す

小ネタ。

Symfony2 つかってるとページング処理どうしようかってのに KnpLabs が公開してる KnpPaginatorBundle を使うことが多い。KnpPaginatorBundle は 2.0 系から Zend_Paginator に依存しなくなって使いやすくなりましたね。 *1

そして、最近特に管理画面系をサクっと仕上げるのに欠かせないのが Twitter Bootstrap なわけだけど、つまり、KnpPaginatorBundle が吐き出すページング用の HTML を、Twitter Bootstrap の、navigation でうまくいくやつを出力したいと思うわけです。

これね:

テンプレートファイルを用意して parameters.ini に設定

Twitter Bootstrap 用に変更している点は、現在のページを active ってクラスにしている点とかその他なんだっけもろもろです。

これを自分で作ってるアプリの適当な Bundle の Resouces/views な場所に入れます。(今回は、 Pagination:pagination.html.twig にいれた。)
で、KnpPaginatorBundle が使うテンプレートを指定するのが parameters.ini で:

[parameters]
...
    knp_paginator.template.pagination=MyAppBundle:Pagination:pagination.html.twig

的なかんじ。

追記: なぜ parameters.ini なのか質問されたので追記。こういう設定は普通 config.yml 的なところで knp_paginator: template: pagination ... なんじゃ?とも思ったんですけど、ソース読んだら parameters から取ってたので、parameters.ini に書きました。勘違いしてたりして...!

追記の追記。 parameters.ini → config.yml に設定変わってた。

この内容つくったとき、最新のソースでソース読んでつくったんだけど、今度ブログ書こー、とおもって1ヶ月くらい経過してたせいで、その後テンプレート指定の方法が変わってたw
32c5c3c 時点では、parameters.ini でOKです。最新のソースでは 06dc809d で設定方法がかわってるので、 config.yml に書けば良いっぽいですね。

と、いうことで多分 config.yml に以下のように記述すればいいとおもいます。

knp_paginator: template: pagination: MyAppBundle:Pagination:pagination.html.twig

※ブログ書く前に最新版で確認しましょうという話。

でなんかする

なんちゃら Controller:

<?php
// in some action

        $qb = $this->get('doctrine')->getEntityManager()->createQuery('...');
        $paginator = $this->get('knp_paginator');
        $posts = $paginator->paginate(
            $qb,
            $this->getRequest()->query->get($pageQueryName, 1), # page number
            $itemCount # items per page
        );

        return $this->render('MyAppBundle:Internal:Hoge/fuga.html.twig', array(
            'posts' => $posts
        )); 

なんちゃら .html.twig

{{ posts.render()|raw }}
  • それだけなのでとくにオチとかもないです
  • KnpPaginatorBundle 使うと 各 column での sort とかも簡単に実装できるので楽ですね

*1:というか KnpLabs は謎の日本語サイトがあったりして面白いですね。日本でもがんばるつもりなんですかね?

node.js で Redmine の REST API を扱う node-redmine つくりました

RedmineAPI をごにょごにょしたいことが多いんだけど、毎回 PHP ってのも芸が無いので年始の休みのときに遊びはじめてみた node.js / JavaScript のモジュールにしてみた。


何でもある npm になかったので、node.js の練習がてら作ってみました感じです。この記事ではバージョン0.2.0 です。
まだ作ってみたばっかで全然使ってないから API とかは変わるかもしれません。すいません。

インストール

npm だと、

$ npm install redmine

です。それ以外の方法はよく知りません。

使い方

example においてあるけど、

var Redmine = require('redmine');

var redmine = new Redmine({
  host: 'vivid-winter-3808.heroku.com',
  apiKey: 'xxxxxxxxxxxxxxxxx',
});

redmine.getIssues({project_id: 1}, function(err, data) {
  if (err) {
    // error
    console.log("Error: " + err.message);
    return;
  }

  console.log(data);

  // { offset: 0,
  //   total_count: 3,
  //   issues:
  //    [ { updated_on: '2012/01/13 03:18:30 +0900',
  //        priority: [Object],
  //        status: [Object],
  //        tracker: [Object],
  //        project: [Object],
  //        description: 'Test issue description',
  //        subject: 'This is test issue on 1326392307929',
  //        done_ratio: 0,
  //        created_on: '2012/01/13 03:18:30 +0900',
  //        start_date: '2012/01/13',
  //        author: [Object],
  //        id: 3 },
  // ...
});

的な感じ。
久々に Redmine の REST API 調べてたら Issues 以外にも API 増えてたから必要に応じて対応しようかな。
とりあえず Issues しか対応してないです。

APIとか

Redmine.getIssues(criteria, callback)
Redmine.postIssue(issue, callback)
Redmine.updateIssue(id, issue, callback)
Redmine.deleteIssue(id, callback)

いやこれやすいか微妙だからすぐかえるかも。なんたって 0.2.0 だから...。

なんとなく、

Redmine.issue.get(criteria, callback)
...
Redmine.issue.delete(id, callback)

とかのほうが使いやすいのでは(というか他のAPIに対応するため)、という気がしている。

まぁ適当にアップデートします。

その他

  • RedmineAPI テスト用に初めて heroku 使ってみたけど、すごいですね。やっぱりよくできてますね。
    • テスト用サイトはこちらですが、添付ファイルの永続化とかしてないし本番用に使う気はないのけど、とりあえずうごいている
  • node.js のパッケージもはじめて作ったけど簡単ですね。
    • npm publish で公開できるのはすごい。PHP でもこういう感じに簡単にしたいなあ。
  • test は見よう見まねで書き始めたけどちゃんと書きます書きます
  • node.js 楽しいです


参考にしたものたち:

いち早く70%〜80%程度の完成度で人に見せられるものを作ることがいかに重要か、という話

去年の年末、Facebookで以下の様な画像が流れてきて自分もついついシェアしたんだけど、久々に、というか、自分にとってのここ最近の課題をドンピシャで突かれたような気がして、しばらく頭から離れなかった。


「プロ」か「アマチュア」か、というのはこの際どうでも良くて、この図の、上の曲線が、目指すべきところだなって話なだけなので、とりあえずその話をまとめてみることにする。

けど、まぁ、だいたい、こういう話をまとめるのは苦手だし途中で面倒になってしまうので、以下サブセクションだけ先に作ってみたものの、ちゃんと書くかどうかわからない... が、まあ、いい!あと、なんかグダグダ書いてしまいそうだけど、結局、サブセクションのタイトルにしたことをこねくりまわしているだけです。

作ってみるまでわからない

何にも言えることだけど作ってみるまで、それがどんなものかわからない。人間はその場に無いものがどんなものか評価することはできない。多分、よほどの何かを持った一握りの人でない限り。だから、まずモノが無いと議論が始まらない。

アイデアに価値はない、というのは多くの人が言っていて、僕もそう思ってる。
でも、実際にモノを作るにはアイデアが必要だ。で、アイデアはどんどん湧き出てくる、そして僕らはそれを話しあう。あれもいいね、これもいいね、という話は年中している。で、作り始めるときは、そりゃもちろん「いいね」と思ったものを作る。よくないね、と思ったものは、強要されてるんだ!でない限りは、まぁ作らない。


ところが、いいね、と思って作り始めたモノなのに、作ってみると、よくなかったりする。逆に、よくないね、と思ったものも、強要されて作ってみたら実はいいね、だったりもする。



アイデアレベルで良し悪しを判断することは、絶対にできない。アイデアは、モノになって初めて価値のある何かになって、そこで初めて議論ができる。

だから、要するに作ってみるまでわからない。

手戻るなら早ければ早いほうが良い

もうひとつ、ウェブサービスにしても何か他のプロダクトにしても、「手戻り」は必ず発生する。作ってみなければわからない、の次の話だ。

実際に作ってみたら「やっぱコレ違うな...」なんてことはめちゃくちゃ頻繁に起こることだし、というか、まあ、絶対に起こる。一人でサービスを作ったら、だいたい、コツコツつくって、それで、デキた、それで公開、だいたいまあそれでOKだろう。でもそれでも、実際に他の人に使ってもらったら「いややっぱこうだったな」ということは、起こる。数人〜多くの人が関わるプロダクトだったら、なおさら、それは絶対に起こる。 *1

で、作ってみなければわからないもので、「よくなかった」ものができてしまった、そうしたら、良いものにするために議論をする、そして、修正する、もしくは、最悪、作りなおす。
細部にこだわって全体に手をつけずに時間をかけて作り込んできたものが、ようやく出来上がったとして、そこからの手戻りは、すごくパワーがいる。スケジュールが自由にできない場合、パワーが要るでは済まされず、そもそも、手戻りできない可能性もある。


だから、出来る限りこのサイクルを、早く・短くしたいわけだ。


赤いのが目指すべきライン、青いのがダメパターンってことです。 適当な絵だけど、だいたいこういうことだよw

実践することの難しさ

だけど、この話をすすめるうえで非常に難しい点が、「いち早く70%〜80%程度の完成度で人に見せられるものを作ろう」なんてことは、意識してれば出来るというモノでもない、というコト。

というのは、

  • 見た目・細部にこだわる作業はテンションがあがる。
    • たとえば、ウェブサービスで言えば、モックつくる、と言って、スタイルをあてずに真っ白に黒字で作ってるとテンションがあがらないよね。
  • 早い段階で全体像を見せる、というのは、必ずしも「とりあえず動けば良いで実装を進めれば良い」というわけではない。
    • 細かいトコロやリファクタは後回しにしたとしても「後々ココはこうなるなー」などと想像しながら、ある程度柔軟に対応可能なように作らないと、絶対後々つらくなる
    • で、それをするには、設計・プログラミングの技術や経験をかなり求められる

なんてことがあるからだ。


だから、ココまでの話を実践するには、ザックリいうと「実力」が必要になる。それを実践するだけの力。
さらにいえば、自分があまりできていないのでなんともいえないけど、「細かいところをとりあえず後回しにしつつ全体が見えるようなものを早い段階でつくりあげる」を実践するには、それ自体を意識し続ける訓練と経験が必要だと思う。

  • 日々それを意識して感覚を鍛える
  • 細かいトコロはとりあえず捨てる勇気を持つ
  • 全体像をつくりあげる実力をつける *2
    • 経験
    • 問題に対する解決方法を日々蓄積しておく

なんか当たり前の話に落ち着きつつあるんだけどまあそいういうことなんだろう。。

今年の目標としようと思う点。タイトルに戻るけど、

  • 「いち早く70%〜80%程度の動くものを人に見せる」を頑張る


もうちょっと細かくいうと、

  • それはつまり、サービス・ソフトウェアライブラリ・何か、に関わらず、自分が今やっている作業が「細かいところ」ではないか、その作業を続けることによって全体が見えるようになるのかを考える。
    • もし細かいトコロをやってしまっていることがわかったら、それが楽しいことでも、とりあえず、やめる。


ということで、またしても全然具体的じゃないけど、今年も頑張っていきます。

おまけ。ある程度のものを作るのに役に立つかもしれないと思っているもの

最終的にウェブサービスに限った話になってきたけど、最近でいえば、以下のツールは、やっぱり、ある程度のモノを早い段階で人に見せるために役に立つと思う。

*1:ただし、どのくらいの手戻りが発生するか、というのは、そもそものセンスが関わっている可能性はあるとは思う。センスってなんだよって話だけど

*2:自分の場合で言えば、プログラミングの能力や、設計・ミドルウェアの知識、オブジェクト指向の知識、などです

*3:でも、とりあえずこれでもいいから出しちゃって、あとで見た目綺麗にすればいいや、というアプローチもゼンゼンアリだと思う