Hatena::ブログ(Diary)

やさしいデスマーチ このページをアンテナに追加 RSSフィード

札幌のWebエンジニアの綴る日常と開発の日々。
GoogleAppEngine/slim3/Django/NetBeans/Swing/JavaFXを中心にお届け。

2011-02-28

70-シングルトンパターンの誘惑に負けない

| 23:49 |  70-シングルトンパターンの誘惑に負けないを含むブックマーク

プログラマが知るべき97のこと」の70個目のエピソードは、シングルトンパターンに関する話です。シングルトンパターンはGoFデザインパターンの中でも最もよく知られ、使われているパターンかと思います。その理由はシンプルであり、かつ強力で、かつ解りやすいからではないでしょうか?しかし、シングルトンパターンは簡単に使える反面で、陥りやすい弊害も多くあります。このエピソードではそのような弊害をいくつか紹介しています。特にユニットテストしにくくなるのが最大の欠点です。

例えば、アプリケーションの設定などを保持するオブジェクトはシングルトンパターンにしがちなオブジェクトです。アプリケーションの中で「1つしかない」と考えるのは自然なことでしょう。しかし、ユニットテストの時やデバッグ時などは、設定オブジェクトを差し替えたいと考えます。シングルトンであるが故に差し替えできないという状況を生んでしまいます。

また、グローバル変数のような使い方をシングルトンオブジェクトに行うコードも見かけます。シングルトンオブジェクトが至るところから参照され、かつ状態を変更できるとしたら恐ろしいことです。それは、あの忌み嫌われているグローバル変数と同じです。参照されているところが増えていくと変更する事も難しくなりますし、マルチスレッド環境では問題はさらに深刻になります。ソースコードを読んでいてシングルトンパターンだらけのコードは非常に読みにくいものです。コードは至る所に依存関係を持ち、どうやっても引きはがせないほど癒着しいます。正直なところ、手遅れとなってしまうと、ユニットテストを諦めたり、多大な労力をさく必要になります。

勿論、気をつけてシングルトンパターンを適用すれば問題ありません。ただし、そのオブジェクトが1つしかないことが本当に妥当な判断かどうかを再確認した上で使うべきでしょう。また、欠点も持つということを認識すべきです。他のデザインパターンも同様ですが、適用する箇所を正しく判断し、デザインパターンを使いたいという事がデザインパターン適用する理由にならないように注意しましょう。

プログラマが知るべき97のこと

プログラマが知るべき97のこと

2011-02-27

69-車輪の再発明の効用

| 01:44 |  69-車輪の再発明の効用を含むブックマーク

プログラマが知るべき97のこと」の69個目のエピソードは、車輪の再発明に関する話です。プログラミングにおける「車輪の再発明」とは、既に作られたフレームワークライブラリがあるのにも関わらず、コストをかけて開発する事を指します。このような「車輪の再発明」をする事は、一般的にはネガティブな意味合いで使われます。つまり、「車輪の再発明をしない方が良い」というニュアンスです。十分にテストされ使えるものがあれば、既に存在するものを作るのは無駄であると考えるのは自然な事です。状況によっては、既存の「車輪」に不満があるため新しい車輪を作る、十分にテストされていない為にリスクを避ける意味で作る、必要な機能が足りないため作る、利用したい言語では実装されていないために作る、といったケースもあります。しかし、そうでないのであれば「車輪の再発明」を仕事としてのプログラミングですることはほとんどないでしょう。

ですが、「車輪の再発明」をあえて行う事はプログラマにとっては無駄どころか非常に有用な事です。優れたプログラマになる為には様々な経験が必要です。その為に、書籍を読んだりと様々な学習をする必要がありますが、最も重要なことはコードを書くことです。経験が浅い時は書籍を読みひたすらコードを写経をすることで十分な学習効果があります。それではある程度の基礎ができたプログラマはどのようにしてスキルをあげるのでしょうか?その1つの回答は「車輪の再発明」だと思います。

車輪の再発明」と「全く新しい事の発明」とを比べると「車輪の再発明」の方が簡単です。元になる「車輪」もそのソースコードも手に入るのであれば、それが何を目的としたライブラリであり、どのように実装されているかが理解しやすくなります。可能であれば自分なりの解釈をし、実装を変えたり、なんらかの工夫をすると「少しだけ良い車輪」が出来るかもしれません。単にソースコードを読み似たような実装を書くだけでも勉強になるでしょう。あまりにも難しく巨大な「車輪」を選択せず興味のあるちょっとしたライブラリを再発明することは、ある程度の基礎が出来たプログラマにとって非常に有効な学習です。業界にとっては貢献できないかもしれませんが、自分には大きなプラスになります。しかし、恐らくは自分の「車輪」は完成できません。「車輪」を「製品(プロダクト)」にするにはコーディング以外に非常に多くのスキルが必要なのです。それが、車輪を再発明することで学べるもう1つの効用です。

プログラマが知るべき97のこと

プログラマが知るべき97のこと

2011-02-26

68-「人間」を知る

| 10:05 |  68-「人間」を知るを含むブックマーク

プログラマが知るべき97のこと」の68個目のエピソードは、コミュニケーションに関する話です。きのこ本に書かれていることのほとんどは「当たり前」の事です。「あたり前」の事なのですが、すべてを実践できているプログラマは中々いないでしょう。きのこ本を読む事で、そのような「当たり前」の事を再認識し、自分で実践していないような箇所を見つめ直すことができます。このエピソードに関しても同様に「当たり前」の事が書かれているのですが、具体的に実践するアプローチについて強く学ぶ事が書かれていました*1

このエピソードで書かれているのはコミュニケーションです。コミュニケーションと言っても「上司と酒を飲みに行く」とか「空気を読んで先に帰らない」とか「くだらないギャグを言うのが得意」いった話ではありません。コミュニケーションとは、人と人との意識の伝達手段です。

つまり、人は、人とともに、そして人の為にソフトウェアを書くというわけです。

ソフトウェア開発では少なくとも2つのコミュニケーションが存在します。1つはチームメンバーであり、もう1つはユーザです*2。それぞれ全く異なる性質の人なので、同じようにコミュニケーションはとれません。プログラマ同士のコミュニケーションは同じような人が相手ですので比較的に簡単に行う事ができます。問題となるのはお互いのスキルが自分の考えを十分に表現できるレベルにあることでしょう。しかし、このエピソードでは、ユーザとのコミュニケーションでは、特にプログラマは論理的にカテゴライズしながら整理していく方法を自然に行う方法(カテゴライズ)が原因で失敗するという説が紹介されています。

私たちの思想、世界観には、いまだにアリストテレスの影響が強く残っています。アリストテレスのように物事を分類して考える習慣がいまだに残っているのです。

(中略)

人間は、「例」に基づいて物事を理解します。

(中略)

「アリストテレス的」な答えを求めている限り、私たちはユーザに対して、妥当な問を発することができないのです。ユーザの物の捉え方と相容れないからです。そのため、共通理解を得るのに大変な苦労を強いられることになります。

この考え方はちょっと意外でしたが、人間は論理的なカテゴライズではなく経験による共通認識(ナチュラルカテゴリ−)をベースに物事を理解しているという主張を読んで納得しました。本文にも書かれているように、「プロトタイプ」や「モック」を使ってのユーザとのコミュニケーションは非常に重要です。この点は自分も強く認識していましたが、それでもモックを提示した上でカテゴライズしようという思考で設計をしていました。勿論、ソフトウェアとして構成していくにはどこかでカテゴライズは必須ですが、ユーザとのコミュニケーションを行う時に頭を切り換えるようなアプローチをすれば、より「プロトタイプ」や「モック」の効果が高まるのでしょう。今後、実践していきたい方法です。

プログラマが知るべき97のこと

プログラマが知るべき97のこと

*1:人によっては「当たり前」かと思います

*2:その上にチーム外の上司とか元請けの人とかまで必要になるケースがありますが…

2011-02-25

67-コードを読む

| 01:03 |  67-コードを読むを含むブックマーク

プログラマが知るべき97のこと」の67個目のエピソードは、コードリーディングに関する話です。プログラマソースコードを読む場面は多くあります。開発中は期待通りに動作しないソフトウェアソースコードを読み、不具合を探します。ソフトウェアの機能拡張が行われるのであれば、既存のソースコードを読んでどこを修正するとよいかを検討します。利用しているライブラリフレームワークの知識を深めるため、一部をカスタマイズするためにソースコードを入手して読む事もあります。ソフトウェアの品質を計るためソースコードレビューとして読む事もあります。つまり、プログラマにとって、ソースコードを読む事は、ソースコードを書くことよりも多いのです。

しかし、自分の書いたコードもそうですが、他人の書いたコードは非常に読みにくいと感じる事があります。このエピソードでは、その原因が思考や問題解決の方法が自分と異なる事にあると書かれています。この傾向は柔軟なコードを記述できる性質のプログラミング言語で特に強いと感じます。

例えば、Rubyは柔軟な言語であり、「考えていることがそのままコードに記述できる」と言われた事があります。他の人がどう考えてコードを書いたが解り、人によってコードが全く異なるそうです。これはRubyのメリットでしょう。プログラマが書いた時の思考が多く残るようなコードであれば、それを読み取りながらコードを読むことが出来ます。しかし、自分はそこまでRubyを使えるわけではないため、他人のコードは非常に読みにくいと感じます。つまり、ホーム言語がRubyであると言えるほど慣れていれば楽なのですが、そうでない人にはかえって難しく感じる原因となる気がします。

一方、Pythonは「1つの事をコードに変換するならば同じコードになるべき」という思想で設計された言語です。プログラマ個人の考え方や解決方法に関してなるべく排除し、同じようなコードが生成される事を期待しています。言い換えれば、コードを書いたときの意図はコードに残りにくい事が欠点です。しかし、コードの型は同じような形になっていくため、形式的な読みやすさという点では大きなメリットになります。Javaも似た傾向があると思います。

このように言語の特徴によってコーディング時の意図が残りやすい言語も残りにくい言語もありますが、この辺は好みかと思います。自分はコーディング時の意図はコメントとして残すべきと考えていますので、Javaでもそのようにコーディングしています。また、それ以外にもコードを読みやすくするように常に工夫しています。

読みやすいコードを書けるようになる為にはコードを読むことです。世の中には多くのオープンなソースコードがありますが、綺麗で読みやすいコードもあれば、酷く読みにくいコードもあります。前者はお手本とし、後者は「どうして読みにくいのか?」と考える事が重要です。

プログラマが知るべき97のこと

プログラマが知るべき97のこと

Scenic3 0.4.0 リリース

| 08:16 |  Scenic3 0.4.0 リリースを含むブックマーク

Slim3を薄くラップし、T2Framework風に1つのページクラスに複数のコントローラメソッドを記述することのできるライブラリ「Scenic3」のバージョン0.4.0をリリースしました。

変更点は次の通りです。

  • REST風のページクラスのサポート
  • 不足していたControllerへの委譲メソッドの追加
  • @ActionPathに空パス("")を許可

尚、Scenic3はSlim3 1.0.7 / AppEngine 1.4.2 に対応しています。

詳細はプロジェクトサイトドキュメントサイトを確認して下さい。

REST風に記述する詳しい方法はこちらのエントリーもあわせてどうぞ。

調査員調査員 2011/02/28 12:35 こんにちは。
Scenic3 0.4.0 を早速使ってみたのですが気になった点を上げます。
・setUpについて
pageSetupがrunで実行されているため、setUpでreruest等がnullになっており参照できない
・downloadについて
showメソッドは追加されたのを確認したのですが、downloadが有りませんでした。

shuji_w6eshuji_w6e 2011/02/28 21:58 報告ありがとうございます。
確認しましたので修正してリリースしますね

2011-02-24

66-いったんコンピュータから離れてみる

| 23:31 |  66-いったんコンピュータから離れてみるを含むブックマーク

プログラマが知るべき97のこと」の66個目のエピソードは、プログラミング中の閃きに関する話です。このエピソードに書かれているような脳の論理的部分がどうこうという理由が正しいかどうかは解りませんが、根を詰めてプログラミングをしていてると効率が悪いものです。難しい問題や厄介なバグに悩まされ、あれこれと手を打つもいっこうに解決しません。しかし、諦めて帰宅してみると、帰宅途中や次の日の朝に何かが閃いてスラスラと解決する事はよくあります。

プログラマの仕事は知的労働です。そもそも6時間も8時間も集中してプログラミングすることはできませんし、5時間であってもずっと同じ集中力で効率を一定に保つ事はできません。嫌なことがあって気分が乗らなかったり、体調が悪かったりすれば自然と効率は下がります。それは認めなければならない事実です。したがって、プログラマとして、集中力をコントロールするスキルは高めていく必要があるでしょう。

集中力をなるべく長く持続させるにはテンポ良いプログラミングと適度な気分転換が不可欠です。プログラミング時にいらいらするような要素を減らし、小粒なタスクをテンポ良く消化している時はあっという間に時間が過ぎる感覚となります。集中している証拠でしょう。外に出てぐるりとオフィスの周囲を散歩してくるのも良い気分転換です。それでも夕方になってしまうと中々出夕出来ません。そのような時はドキュメントを書いたり、雑務をこなしたり、ちょっと勉強をしてみるなど仕事内容を変化させるのも効果的です。

決して良い効果が生まれないのは夜遅くまで根を詰めて作業することです。集中力が切れていると効率が悪いだけではなく、判断力の低下からミスが増えます。そのミスに早く気付けば良いのですが、気付かずに放置していると取り返しのつかない事態になることもあるでしょう。時間をかければ解決するという考え方は論外です。

解決策が見つからず夜遅くまで悩むよりも、諦めて帰宅することが重要です。

プログラマが知るべき97のこと

プログラマが知るべき97のこと

2011-02-23

65-バージョン管理システムを使う

| 00:12 |  65-バージョン管理システムを使うを含むブックマーク

プログラマが知るべき97のこと」の65個目のエピソードは、バージョン管理システムに関する話です。そろそろ都市伝説になってもいい気もしますが、バージョン管理システムが導入されていなかったり、導入していても適切に運用されていない開発現場は存在しています。自動的に履歴が残っているにも関わらずコードの削除を禁止しコメントアウトするルール、誰がいつ更新したかが解るメリットを捨てて共通のユーザ名での利用、システムテストが通り完成したコードしかコミットが許されないリポジトリバージョン管理システムを導入してながらソース(クラス)のリリースに関してリリース台帳と呼ばれるスプレッドシートと判子による管理など、それほど昔に経験した経験というわけではありません*1

バージョン管理は、モダンソフトウェア開発の3本柱の1本です。しかし、残り2本のユニットテストと自動化に関しては、バージョン管理ありきという側面もあります。ユニットテストが十分だとしてもそのコードがバージョン管理されていない開発やなんでも自動化が進んでいるがコードがバージョン管理されていない開発というのは考えられません。しかし、幸いにもバージョン管理システムの導入だけであればそれほど難しい事はありません。SubversionGitMercurialなどフリーで十分な機能を持ったソフトウェアがありますし、インストールして利用する事も簡単です。

また、バージョン管理システムを利用することも難しい事ではなく、アップデートコミットさえ学べば基本的な利用ができます。しかし、問題なのは適切に運用することです。バージョン管理システムを適切に運用するには、開発プロセスビルド・リリース管理などに関する知識と経験が必要になってきます。

例えばSubversionを使ったバージョン管理の運用の基本ルールは次の通りです。初めにtrunk, branches, tagsの3つのディレクトリリポジトリに作成します。開発のメインラインはtrunkを使ってコミットしていきます。そして、リリースを迎える段階になったならばbranchを作成します。そのリリースで残った作業やテストの不具合に関する修正はbranchにコミットしていき、同時に次のバージョンに向けた開発がtrunkにコミットされていきます。ここでbranchとtrunkに差分が発生してしまうため、適切にマージする作業が発生します。システムテストが終わりリリースが出来る段階になったならば、branchからtagを作成します。tagはある時点でのスナップショットです。通常はリリースタイミングでバージョンを付与したtagを作ります。その他なんらかの区切りでtagを作成する事もありますが、tagにはコミットしません。このような開発の流れとバージョン管理については知識として覚える事も重要ですが、実際に行うという経験が必要です。

ソースコードを書くプログラマにとって、バージョン管理は最も重要なスキルの1つです。書き捨てるコードもありますが、ソフトウェアとしてユーザに提供するならば、その元となるソースコードを適切に管理する事は当然のことです。適切に管理されている事で安心してコードを書き、それを修正していく事ができます。そして、リリースを適切に管理する事も必要とされます。つまり、バージョン管理なくしてソフトウェア開発は成り立たないのです。利用するならば誰にでも簡単にできますが、真に求められるのは適切な管理スキルです。

プログラマが知るべき97のこと

プログラマが知るべき97のこと

*1:全て3−7年以内の実話

2011-02-22

64-プロのプログラマとは

| 23:04 |  64-プロのプログラマとはを含むブックマーク

プログラマが知るべき97のこと」の64個目のエピソードは、プログラマが知るべきことに関する話です。

プロフェッショナルプログラマの最大の特徴は「自分が責任を取る」という態度、責任感です。プロのプログラマは、まず自分のキャリアに責任を持ちます。責任の取れない見積もりやスケジューリングは決してせず、作る製品の質にも責任を持ちます。ミスがあれば、必ず自ら対応します。他人に責任を押しつけるようなことは一切しない、それがプロです。

このエピソードは一言一言が重く響きます。「プログラマが知るべき97のこと」の中で最も大切で基本的な心構えです。他のエピソードもそれぞれ重要な事が書かれていますが、すべてはこのエピソードに繋がってきているのではないでしょうか?

プロであることはどういうことか考えると、スキル・プライド・拘り・品質などをあげる人が多いのでしょう。勿論、それらもプロとして重要な要素です。自分はその中でもプライドと品質が重要な部分と考えていました。しかし、このエピソードを読んでからは、はっきりと「責任」であると答えます。

プライドや品質に関しても重要です。しかし、プロとして仕事をしていくのであれば、納期や予算など何処かで妥協するシーンがあります。そんな時に品質に拘りつつ付けて納品できなかったり、納品はしたものの品質が酷いものであったりするならば、プロの仕事ではありません。バランスが重要であるということは解ってはいるのですが、自分を納得させながら仕事をしてきました。

しかし、それらのモヤモヤはこのエピソードで道が見えたと感じました。プロのプログラマとしてとるべきは、「責任をもって仕事に臨むこと」なのです。「やる」と言ったからには例えどんな事があろうとやり遂げる、それだけの事だったのです。それは、根性論で「やる」という事ではありません。自分の判断で「やれる」と判断したものに対して責任を持ってやり遂げるという事です。それだけの事ですが、決して簡単な事ではありません。

責任を持って「やれる」と宣言する事は覚悟の必要な事です。初めから無理な事を「やる」と宣言するのは無謀で愚かなことでしかありません。責任を持って「やれる」と判断する為には自分とチームの力量を正確に知る必要があります。日々の学習を積み重ねスキルを高めていかなければ「やれる」レベルは高くなりません。予期せぬ問題や不測の事態をリスクとして管理し、リスクが現実のものとなったとしても適切に対応し、完遂しなければならないのです。プロジェクトが失敗したならば腹を切る覚悟で「やる」と宣言するという事です。

最後にこのエピソードで書かれている心がけを箇条書きに引用しておきます。

・キャリアに責任を持つというのは、自分の力で自分の価値を高め、成長していくということです。

・プロのプログラマは、自分の書いたコードに責任を持ちます。

・プロのプログラマはチームプレイヤーです。一人一人が自分の仕事だけでなく、チーム全体のアウトプットに責任を持ちます。

・プロのプログラマは、バグリストが一定以上の規模にならないよう、常に注意を怠りません。

・プロのプログラマは、絶対に、間に合わせのいい加減な仕事はしません。

自分が「プロのプログラマ」であると自信を持って言えるようになる為、これらの格言を心に刻み、修練していく事を誓います。

プログラマが知るべき97のこと

プログラマが知るべき97のこと

2011-02-21

63-ユーザの操作ミスを防止する

| 23:34 |  63-ユーザの操作ミスを防止するを含むブックマーク

プログラマが知るべき97のこと」の63個目のエピソードは、ユーザビリティに関する話です。残念な事ですが、画面デザインに関して自分の仕事ではないと考えているプログラマは少なくありません。勿論、すべての分野のプログラマに必要なスキルではないかと思いますが、ユーザビリティを考慮したインターフェイスを設計する事はプログラマに求められるスキルの1つです。アイコンや画像を描くようなデザイナの仕事と考えてはいけません。情報の入力フォームであれば、入力値の妥当性のチェックはプログラマの仕事です。ユーザの操作が迷わないように誘導したり、不正な操作をすることを防止する手を打つのもプログラマの仕事です。論理的に考えた上で最適な形を提供する必要があります*1

このエピソードでは、そんなユーザビリティに関する内容で特にエラーチェックに関する事が書かれています。

「入力して欲しいのはあくまで情報であり、データではない」ということを考慮すべきでしょう。

この言葉はきのこ本の中でも、最も衝撃を受けた言葉の1つです。自分もユーザビリティに関しては拘りが強く、重要性も説く機会が多いのですが、説得するのは難しいと感じていました。ユーザビリティを高くすることでユーザの満足度が高くなることは確かなのですが、プログラマが意識する必要があるのか?という点は説明しにくい部分です。しかし、この言葉は一言でそれを説明しています。我々プログラマが必要としているのはデータです。仕様としては入力データの妥当性をチェックする必要があります。これについては反論はないでしょう。ですが、業務アプリケーションであってもたいていの場合、ユーザはデータを入力していないのです。それは情報であり、ソフトウェアとは情報をデータとして処理するツールなのです。したがって、ユーザの情報を的確にデータに変換する事は大きな価値があるわけです。ユーザにデータを求めていると、入力フォーマットなどをガチガチに堅めがちですが、情報を求めているならば違う価値観で入力インターフェイスを設計できるかと思います。

しかし、文章で長々と説明されても理解は難しいものです。実際に使ってみなければわからないこともあります。

ユーザビリティを意識する場合に重要な事です。紙芝居では解らない操作感覚を伝えるには、実際に動くモックアップを作る必要があります。どれだけ完璧に画面遷移図と画面項目定義を書いたとしても、動かしてみなければ違和感を感じることができません。また、実際にエンドユーザに使って貰い、感想をフィードバックしてもらう事が重要です。プログラマが自分のために作っているわけではありません。使うのはユーザです。

その原因に関係なく、システムはユーザの操作ミスに対し寛容であるべきです。

なんでもエラーにしてしまうシステムにイライラしたことは誰でもあるでしょう。どうして、入力に半角数字を強制する必要があるのでしょうか?漢数字を変換する必要はないかと思いますが、全角数値を半角数字に変換するプログラムと全角数字をエラーとするプログラムで大きく実装コストが変わるとは思えません。同じコストをかけるならば、よりユーザに優しい仕様を心がけることで、ソフトウェアプログラマの価値は大きくなるのです。

どういう種類のシステムであっても、ユーザのミスには一定の傾向があるものです。多くの場合、ミスはユーザとソフトウェアがお互いを誤解した結果として生じるのです。そうしたミスを防ぐには、ユーザがデータを入力する際、どのように考え、情報をどのように解釈し、どのように判断を下しているかを知ることが重要なのです。

プログラマは常にユーザの視点でソフトウェアを評価する必要があります。自分が使って使いにくいと思ったり、訳がわからないようなソフトウェアを作っているならば心が痛むはずです。プログラマソフトウェアをリリースすることで対価を得ます。対価を得る以上はソフトウェアに価値がある必要があるのです。

自分も言われたままの使いにくいソフトウェアを作る事を求められる職場を何度も経験してきました。矛盾があろうとも上司・元請けの言う仕様は絶対であり、その通りに作る事で対価を貰う仕事だったのです。自分はそんな開発は二度としたくありません。

エラーメッセージは、ユーザとシステムの間の重要なコミュニケーション手段です。エラーメッセージが出るのは,ユーザとシステムの間のコミュニケーションに危機が生じている時である、とも言えます。

この言葉はしっかりと胸に刻んでいこうと思います。

プログラマが知るべき97のこと

プログラマが知るべき97のこと

*1:一方でウェブデザイナのようなデザインの専門家もまたユーザビビりティを意識した論理的な画面構成を造る必要もある

2011-02-20

Javaのチェック例外はクソ仕様

| 00:40 |  Javaのチェック例外はクソ仕様を含むブックマーク

Java言語のチェック例外は本当にGood Partなのか?というエントリーを読んで自分の考え方を簡単にまとめておこうと思う。

続きを読む

62-プリミティブ型よりドメイン固有の型を

| 23:51 |  62-プリミティブ型よりドメイン固有の型をを含むブックマーク

プログラマが知るべき97のこと」の62個目のエピソードは、ドメイン型に関する話です。このエピソードでは1999年の火星探査機「マーズ・クライメイト・オービター」の事故を例にあげ、プリミティブ型と暗黙で利用している単位に関する問題を提起しています。この事故の原因は宇宙船プログラムにありました。推力を計算する演算処理が宇宙船と地上の両方のプログラムに含まれていたようです。どちらのプログラム演算にも不具合は恐らくなかったのでしょう。しかし、それぞれのプログラムを書いたプログラマ文化圏が異なり、自然に使う計算の単位が異なったため、数百億円が燃え尽きたのです。

Javaで次のようなコードがあったとします。

float speed = 10f;

この単純なコードは「浮動小数点数speedを定義して値を10」と定義しているコードです。このコード自体の意味はどんな国の人がコードを読もうと不変です。Javaプログラミング言語に採用しているという事さえ共通に認識していれば、万国共通です。しかし、speedの単位という情報が欠落しているのです。この情報はプログラム仕様書に記述されるべき情報であるかもしれませんが、そこに強制力はありません。

例えば、次のようにコメントを残したとしても、うっかり見落としてしまう可能性はまだ残ります。

// speed in kots
float speed = 10f;

一方、次のように型を定義した上で、speedを定義したとします。

class SpeedInKots {
  final float value;
  SpeedInKots(float value) {
    this.value = value;
  }
}
SpeedInKots speed = new SpeedInKots(10f);

こう記述することで、speedが『ノット』という単位であることが明確になります。ソースコードで最も重要な要素である「読みやすさ」が格段に向上し、他のプログラマが読む時に誤解を受ける事が少なくなるのです。

また、このようなドメイン固有の型を利用する事で、単なるfloatという数値に意味を持たせることができます。テストという観点で考えれば、速度にどんな値が入るかを考慮する必要がありますが、マイナス値はこの場合に妥当でしょうか?どんな乗り物のノットを考慮するでしょうか?一般的な船舶を対象としたアプリケーションを開発しているのであれば、とりえる値は0〜100までで十分でしょう*1。すると次のように制限することができます。

class SpeedInKots {
  final float value;
  SpeedInKots(float value) {
    if (value < 0f || 100f < value) throw new IllegalArgumentException("Out of range.");
    this.value = value;
  }
}

ソフトウェア株式の注文数が異常な値の時に注文を確定させた事についてソフトウェアの不具合かどうかが問題となった事件もありました。単なるプリミティブ型でなく適切な範囲と単位を持ったドメイン型を用いることでより高品質なソフトウェアとなるのです。

コンピュータ演算能力が十分な現代であれば、ドメイン型を使う事によるパフォーマンス上のデメリットはほとんどないでしょう。全ての状況でドメイン型を使うべきかどうかは実装コストと品質(安全性)のトレードオフとなるかと思います。プログラマとしては、プリミティブ型ではなくドメイン固有の型を利用するという選択肢を自然とできるようにはなっておくべきです。間違っても注文数にマイナスを入力すると在庫が増えるようなソフトウェアを出荷してはなりません。

プログラマが知るべき97のこと

プログラマが知るべき97のこと

*1:一般的な船舶の速度は22ノット程度だそうです

2011-02-19

61-ビルドをおろそかにしない

| 21:24 |  61-ビルドをおろそかにしないを含むブックマーク

プログラマが知るべき97のこと」の61個目のエピソードは、ビルドに関する話です。これまで仕事で様々な開発現場を経験してきましたが、ビルドプロセスに関して真剣に取り組んでいる所はほとんどありませんでした。下請けで開発を行っている所が多かったのも理由かもしれません。元請けにソースコードだけを納品した結果、本番環境で動かない(ビルドも出来ない)という経験もあります*1ビルドプロセスや環境構築に対して作業を見積もっていないケースもよくある話です。開発には、開発環境を用意し作成したコードをビルドする事が必要不可欠です。それなのに、各機能に関する見積もりだけというのも珍しい話ではありません。明らかにビルドプロセスが軽視されています。

ソフトウェア開発は実体が見えにくいものですが、ビルドプロセスはその中でも更に実体の見えにくい部分です。それが原因でビルドプロセスが軽視されていると思われます。ソースコードは質や量については測りにくいもののある程度の定量化は可能です。しかし、ビルドプロセスがどれだけ大変な作業かは経験してみないと解らないのです。少なくともコードすら書いたことないPMには想像できません。そして、これは一部のプログラマにも言える事です。ビルドプロセスは「魔法」という認識でいます。魔法と感じるのは知識や経験がないからです。

勿論、新人プログラマビルドプロセスまで勉強する必要があるとは思いません。ですが、3−4年も経験を積めばホーム言語について一通り操れる段階になっているはずです。その時こそビルドプロセスを学ぶタイミングだと思います。ビルドプロセスはそれほど簡単なものでもありません。少なくとも1つのライブラリフレームワークを学習する程度の学習コストはかかります。片手間に学ぶのではなくしっかりと腰を据えて学ばなければなりません。

最近のJavaの開発現場ではCIツールとしてJenkins(Hudson)を導入するところが増えています。そして、十分な効果をあげています。しかし、Jenkinsを使うには幾つもの前提となる技術が必要です。Jenkinsを設置するにはウェブアプリケーションサーバの設置ができなければなりません。SubversionなどのSCMと連携しなければメリットは低いので、SCMに関するスキルも必要です。Tracなどのチケット管理システムと連動することでさらに効果は高くなります。自動的にビルドさせるにはAntMavenといたビルドツールを使えなければなりません。ユニットテストを行っていないならばCIのメリットを感じることも少ないでしょう。このように、Jenkinsを自然に導入できて活用できている現場は、様々な技術を少しずつ習得してきているのです。しかし、学習を怠っていた現場では10年前の開発スタイルが今も続けられています。そして、今後も変わらないのでしょう。

コードを書くことができればプログラマです。しかし、それだけではプロのプログラマではありません。周辺の技術も含め、ソフトウェア開発をトータルに推進できる必要があります。コーディングは楽しいものですが、ビルドプロセスや開発環境の整備など裏方の仕事にもっと興味をもって学習してみましょう。

プログラマが知るべき97のこと

プログラマが知るべき97のこと

*1:不安でしたがやる必要がないと上司が判断してました

KazKaz 2011/02/21 11:48 Javaではないんですが, 手元では正常にビルドできるのに, 客先ではエラーになるということが以前ありました。結局客先では開発ツールの自動アップデートをしていなかっただけ (ネット接続の制限のため) ということで, ソース上でエラーにならないように書き換える羽目になったんですが, すでに解決されているはずの開発ツールのバグに対応するのは気が滅入ります。

2011-02-18

60-真実を語るのはコードのみ

| 21:25 |  60-真実を語るのはコードのみを含むブックマーク

プログラマが知るべき97のこと」の60個目のエピソードは、コードの可読性に関する話です。可読性に関する話題は何度も登場しています。プログラムは実行できることが全てですが、保守をしていくなかで、ソースコードを読む比重は高くなっていきます。新しい機能を追加するにしても、不具合を修正するにしても、既存のソースコードを読む事が必要不可欠です。そして、継続的なプロジェクトでは「ソースコードを読む」時間が大きな比重をしめるでしょう。従って、生きたコメントやシンプルで読みやすいコードである事に価値があるのです。

コードを書くことは、誌やエッセイ、不特定多数の人に見せるブログ、あるいは大切な要件を伝えるメールなどを書くのと同じようなものと考えるべきです。表現を工夫し「このプログラムはどう動くものなのか」ということが、コードの読み手にストレートに伝わるようにするのです。

こんな事を会社で話したら気持ち悪い奴扱いされるかもしれません。しかし、プログラムが動く事は当たり前であり、プログラマスキルが問われるのは如何にコード自身に語らせることができるかです。読みにくい難解なコードを書く事よりも、誰にでも読みやすいコードを書く方が難しいのです。コードの可読性に関するネタも尽きてきたので、読みやすく美しいコードを書くために自分が心がけている事を幾つか紹介します。

1つ目は、常に人に読まれるという意識でコードを書くと言うことです。メールやブログのエントリーと同じように、コードを書いたならば読み直します。コンパイルが通ったとしても、テストが通ったとしても、もう1回読んでみます。その時、「変数の名前はこっちのがいいな」「宣言の順番としてはこっちを先にしよう」「ここはメソッドを抽出しておくか」「このループは拡張forのほうが読みやすいだろう」という感じでちょっとした修正をします。この時には必ず読まれるということを意識しています。

2つ目はコードを晒す事です。オープンソースのプロジェクトやブログでコードを晒します。そのコードにツッコミが入ることなどはまずありませんが、自分の書いたコードを公開する事は勇気がいる行為です。緊張します。怖い事もあります。ミスをしてどこかで晒されたらどうしようと思います。ですが、公開することの緊張感は確実にコードの可読性を高める効果を期待できます。これは技術的なエントリーを書く場合も同様です。知識を伝えることで自分の成長に繋がります。

3つ目はとにかく書く事です。ブログのエントリーでもそうですが、訓練して書き慣れる事が最大の学習です。書かなければ綺麗なコードは書くことができないでしょう。写経も効果はありますが、可能な限り綺麗なコードを写経してください。反復練習に勝る学習はありません。

コーディングプログラマにとって最も基本的なスキルです。自分もまだまだ修練が足りません。他の人の参考になるようなコードを書けるようになるのが目標です。

だから、ブログを書き、コードも公開しています。

プログラマが知るべき97のこと

プログラマが知るべき97のこと

2011-02-17

59-バイナリは常に1つ

| 21:47 |  59-バイナリは常に1つを含むブックマーク

プログラマが知るべき97のこと」の59個目のエピソードは、ビルドバイナリに関する話です。自分の経歴の7割以上はJavaによるソフトウェア開発であることもあり、バイナリにまつわる問題はほとんど経験した事がありません。ソフトウェアのほとんど同じだけど少しだけ違っているバージョンを作らざるを得ない状況も数えるほどしかありませんでした。Javaが実現しようとしていた「Write once, Run anywhere」のポリシーがあるからでしょう。Javaを使っている以上は、悩まされるのは環境に依存した改行コード・文字コード・ファイルの区切り文字程度であり、それらも少しだけ注意を払うことで実装を変更する必要はほとんどありません。

ですが、Javaや他の言語でのウェブアプリケーション開発などでも共通するような事はあります。開発環境がWindowsで実行環境がLinuxというケースであれば、環境に依存しないコードであることが望ましいでしょう。開発時から本番で使うバイナリと同じものを使う事は問題の発生を多く減らせるという実感もあります。

また、最近のウェブアプリケーションフレームワークビルドツールでは、環境毎に設定ファイルを読み込ませる機能が提供されています。開発用の設定やステージング環境用の設定が外部ファイルとして記述され、アプリケーション本体では可能な限り環境を意識しないようなコードを記述します。デプロイプロセスも自動化しておけば、同じコードをそのまま幾つかの環境に間違えなくデプロイすることも出来ます。

自分にとってはバイナリはあまり身近な問題ではありません。しかし、「皆が常に同一のバイナリを使用するようにする」という事と「環境に関する情報もバージョン管理の対象とする」という2つのルールは、スクリプト言語による開発であってもJavaの開発であっても共通して重要な事だと思います。それらの事を実現するためにはそれなりのノウハウが必要ですが、学習する価値は高いでしょう。ビルドプロセスの自動化までは基本スキルです。

プログラマが知るべき97のこと

プログラマが知るべき97のこと

2011-02-16

Scenic3 によるRESTサポート

| 23:46 |  Scenic3 によるRESTサポートを含むブックマーク

Scenic3はSlim3のController層を薄くラップした拡張ライブラリです。Slim3では1アクション(URL)に対して1つのControllerを作成するシンプルなデザインですが、どうしてもControllerの数が多くなってしまいます。関連するアクションは1つのクラスにまとめ、アクションメソッドを複数定義する設計を好む人にとってはやや窮屈な仕様です。Scenic3ではそんな人達のために、複数のControllerクラスを1つのPageクラスに定義する手段を提供しています。

一方、REST風のAPIを設計する場合は同一URLに対して異なるHTTPメソッドを割り当てる事になります。例えば、あるモデルに対する取得と削除は次のような同じURLとなります。

http://yourdomain/item/{id}

idにはモデルを識別する一意の値が指定されます。同一のモデルに対する操作は同じURLとなり、HTTPメソッドがGET/POST/DELETE/PUTのどれであるかにより振る舞いが変わるようになります。

このようなREST風のAPISlim3で実装するには、Controllerのrunメソッド内で、isGet, isPut, isPost, isDeleteメソッドを利用して条件分岐を行えば実現できます。Scenic3を使った場合でもisGet, isPut, isPost, isDeleteが利用できるので同様です。

Scenic3の目的は「見通しの良いコード」を実現することです。0.4.0で実装されるRESTサポートを利用する事で、アクションメソッド毎に、呼び出されるHTTPメソッドを宣言的に指定できるようになります。

続きを読む

58-テスト担当者はプログラマの友人

| 23:33 |  58-テスト担当者はプログラマの友人を含むブックマーク

プログラマが知るべき97のこと」の58個目のエピソードは、テストに関する話です。このエピソードにおけるテストはユニットテストではなく、QA(Quality Assurance:品質保証)やQC(Quality Control:品質管理)と呼ばれる部署が行うようなテストです。会社の規模やプロジェクトの規模がそれほど大きくない場合は、テスト専門の部署がない事が多いですが、プロジェクトの後半にて品質を担保するためのシステムテストや負荷テストは必要不可欠でしょう。そのような品質を保証するテスト担当者とプログラマとが良い関係を保てない状況は珍しい事ではありません。似たような問題として、プログラマと営業担当者の問題もあります。どちらの問題も、それぞれの立場ではお互いに正論を述べる一方で、利害関係が一致しないことに起因します。最終的な利益はユーザの価値であるはずなのですが、何故か上手くいきません。

プログラマはユーザのためにソフトウェアを開発します。困難な問題を様々なソリューションを使って解決する事に価値を見いだします。一方、テスト担当者はユーザのためにソフトウェアの不具合を探します。不具合があるソフトウェアをリリースすることによりユーザの価値が減ることを防止します。それは、プログラマに対して嫌がらせをしているのではありません。勿論、プログラマもテスト担当者が悪意を持って不具合を報告していると思う人はいません。

規模も納期も小さくなりつつあるソフトウェア開発では、どのように品質管理やテストと向き合うかはもう1つの課題です。最近は、品質保証のキーはユーザマニュアルであると考えるようになりました。そのユーザマニュアルの元となるのはユースケースシナリオであり、ユーザマニュアルを元にシステムテストが行われる事が理想です。ポイントは基本設計の頃からユーザマニュアルシステムテスト項目と変化していく事を想定したユースケースシナリオの作成です。ユースケースはユーザとの契約上は重要なものかと思いますが、最終的にユーザ価値をもたらすのはシステムとマニュアルです。そして、それを担保するのはテストであり、設計書ではありません。したがって、最終的に「動くソフトウェア」と「知りたいことの書いてあるマニュアル」を目指すのが最短コースと考えます。作成はフェイズ毎に区切ることはしない方がいいでしょう。開発を進めながらマニュアルとテストを作成していくことで、実装漏れや考慮漏れに気付くことになります。

テスト担当者が独立しているような開発でも同じと思います。なるべく早い段階でソフトウェアを知り、プログラマと同じ環境で開発に参加するべきではないでしょうか?

プログラマが知るべき97のこと

プログラマが知るべき97のこと

2011-02-15

57-ポリモーフィズムの利用機会を見逃さない

| 22:04 |  57-ポリモーフィズムの利用機会を見逃さないを含むブックマーク

プログラマが知るべき97のこと」の57個目のエピソードは、ポリモーフィズムに関する話です。ポリモーフィズムオブジェクト指向プログラミングにおいて最も重要な概念の1つです。日本語で多態性と呼ばれるこの技術は、実装レベルで考えれば方が同じで振る舞いが異なるクラスを定義できるということです。その事による恩恵としては、冗長なif文を減らすことができる事でしょう。例えば次のようなif文を含むメソッドがあるとします。

class Controller {
  void run(Request req) {
     if (req.isGet()) {
        // GETの場合の処理
     } else if (req.isPost()) {
        // POSTの場合の処理
     } else {
       throw new AssersionErrror();
     }
  }
}
class Client {
  void invoke(Request req) {
    Controller controller = new Controller();
    controller.run(req);
  }
}

このクラスはHTTPのリクエストを処理するクラスですが、GETとPOSTを判別して別の処理を実行しています。次のようなポリモーフィズムを利用したコードでは、POSTまたはGETの場合に呼び出されるという前提でロジックを書く事ができます。

abstract class Controller {
  void run(Request req);
}
class GetController extends Controller {
  void run(Request req) {
    // GETの場合の処理
  }
}
class PostController extends Controller {
  void run(Request req) {
     // POSTの場合の処理
  }
}
class Client {
  void invoke(Request req) {
    Controller controller = createController(req);
    controller.run(req);
  }

  Controller createController(Request req) {
     if (req.isGet()) {
        return new GetController();
     } else if (req.isPost()) {
        return new PostController();
     } else {
       throw new AssersionErrror();
     }
  }
}

ポリモーフィズムを使う事で、クライアントのコードはControllerの実装がPOST用なのかGET用なのかを意識しないコードになりました。しかし、if文が全くなくなったというわけではありません。createControllerのメソッドの実装にifが移動しているだけです。

勿論、リフレクションなどの動的な生成方法を使う事でif文を完全に排除することもできますが、分岐そのものがなくなるわけではないことに注意すべきです。また、コード量だけを考えれば、ポリモーフィズムを使わない方がコード量・クラス数も少ないでしょう。こうなってくると、本当にポリモーフィズムは有効なテクニックなのか怪しくなってきました。「未来へのメッセージ」にもあるように、難しいソリューションを使う事で何となく凄い事をしていると錯覚しているのかと思えてきます。

実は、ポリモーフィズムを使ったコードの最大のメリットは単純に条件分岐が減る事ではありません。条件分岐を行う場所をメインの処理から切り離すことができることなのです。上記の例では、リクエストがPOSTとGETで処理を分岐していましたが、それがメインのロジックの中に分散してしまうと、非常に読みにくいコードになります。1本の主シナリオを記述しているのではなく、幾つかの主シナリオが混在する状況です。一方で、それぞれのControllerを作成した場合、それぞれのロジックは完全に分けて考える事ができるのです。分岐部分は別のレイヤーで行い、一旦GET/POSTと判定されたならばそのコンテキストで処理が行われます。だから読みやすいコードとなるのです。読みやすさに対してコストと複雑性を払う意味はあるのです。

とはいえ、ポリモーフィズム麻疹のようなもので、何でもかんでもポリモーフィズムを使いたくなる時期は誰にでもあります。しかし、ちょっとやりすぎたかな?という経験が、どの程度でセーブすれば最適化という経験に繋がるので、怖がる必要はありません。多少無理して使ってみようと検討することは重要な事です。ただし、流行病なので治す事を忘れずに。

プログラマが知るべき97のこと

プログラマが知るべき97のこと

2011-02-14

56-未来へのメッセージ

| 23:03 |  56-未来へのメッセージを含むブックマーク

プログラマが知るべき97のこと」の56個目のエピソードは、コミュニケーションに関する話です。

「取り組む問題が難しければ、そのソリューションも難しく、わかりにくいものになるのが当然」そう考えている人がどうも多いようです。問題が難しいのだから、それに対応するソリューションは理解しにくく、保守も難しいもにになって当たり前と思っているようなのです。

このエピソードは、きのこ本の中でも特に考えさせられたエピソードです。シンプルに解釈するのであれば、「コードを書く時には未来の誰かが保守をする時の事を考慮して解りやすく美しいコードを書くことが重要」という話でしょう。しかし、これまでの自分の経験などから振り返りながら読んでいると、自分にはコミュニケーション、特に発信側に関するエピソードと映りました*1

「賢い人」は難しい事を簡単に実現することができる人です。難解なソリューションを多く理解し、専門用語を簡単に使いこなします。彼らは有能な一方でチーム開発が苦手なケースを多くみかけます。自分がまだ新人だった頃の話ですが、技術的に凄い人はいましたが、エンジニアとして尊敬できるような人とは出会えませんでした。その技術的に凄い人は、技術力が非常に高く、社内でも信頼が置かれ、話す言葉1つ1つが難しかったものです。そして、自分にとっては理解できないことでした。自分も経験を積んでいったので、その人が話してた内容が少しづつ解るようになったわけですが、学習を続けていなければ生涯解らなかったでしょう。

厳しい見方をすれば、努力しないならば道は開けないと考えることができます。しかし、もっと初学者に対して適切なコミュニケーションをしていたならば、違う結果になったのではないかとも考えることができます。デザインパターンフレームワーク、難解なアルゴリズムなど難しいソリューションを身につけてスキルを高めていくことは重要です。自分で使いこなす事も重要なのですが、それ以上にその技術を誰かに伝えるスキルをもっと高めていくべきだと自分は考えています。

幸いにも最近は、コミュニティ主催の勉強会ブログなどを通じて自分から情報を発信することは非常に簡単です。勿論、発信することは本当に面倒なことです。ブログのエントリーを書くよりも本を読んだりコーディングをする方が有用であると考える事もできます。ですが、情報を発信するスキルは、難解なソリューションと同等以上の価値を持つでしょう。

情報の発信は、現在・過去・未来へのメッセージです。難解な論文を書くこともひとつの選択肢ですがそれは学者肌の人に任せ、自分はプログラムでもブログでもコミュニティでも誰もが共感できるようなメッセージを発信していきたいと思います。

プログラマが知るべき97のこと

プログラマが知るべき97のこと

*1:解釈は人それぞれです。

2011-02-13

Slim3 に Scenic3 と PirkaEngineを使う方法

| 23:55 |  Slim3 に Scenic3 と PirkaEngineを使う方法を含むブックマーク

ここの所、随分とAppEngineへの関心が高まってきているようです。Slim3の周辺も活発になってきている事もあり、Scenic3に注目していただく方もチラホラと出てきました。注目されるということは非常にモチベーションが高まります。

今回は前回に予告した通り、Scenic3にPirkaEngineを組み合わせる方法の紹介です。Slim3GAE上で動作するフルスタックのMVCフレームワークですが、その大部分の機能はModelに相当するDatastore周りです。View層はJSPに幾つかのヘルパが用意されており、Controller部分はシンプルな1コントローラクラス=1URLのパターンになっています。この組み合わせでも、十分に機能するのですが、JSPを使いたくない場合や1クラスに複数のアクションメソッドを記述したいスタイルとは相性が悪くなります。後者についてはScenic3が解決する領域ですが、どうせならばJSPも使わない方法を提案します。

PirkaEngineとは?

PirkaEngineはJava6を用いたXHTMLテンプレートエンジンです。プレビューを崩さないように考慮されたXML属性を用いてループや条件分岐等を扱うことができます。また、依存ライブラリがないため、GAEとは相性が良くなっています。

ゴール

このエントリーでのゴールはPirkaEngineをViewに採用し、HTMLに近いテンプレートのメリットを伝えることです。Scenic3とPirkaEngineを組み合わせれば、ViewとControllerに不安はなくなるでしょう。

続きを読む

55-並列処理に有効なメッセージパッシング

| 22:44 |  55-並列処理に有効なメッセージパッシングを含むブックマーク

プログラマが知るべき97のこと」の55個目のエピソードは、並列処理に関する話です。並列処理に関する関心は日々に高まっています。プロセッサのクロック速度の向上はやや頭打ちになってきており、高速に処理を行う為にはコアを増やす傾向なのです。家庭用のPCでもデュアルコアは最低限のスペックですから、家庭で使うようなちょとしたフリーソフトであっても、並列処理を考慮する価値は十分にある時代です。しかし、並列処理は非常に難しい技術です。タイミングやデッドロックの問題、メモリのアトミック性に伴う問題などたくさんのことを学ぶ必要があります。Javaであれば、「Java並行処理プログラミング」は必読書と言えるでしょう。一時期は絶版状態でしたが、復刊運動の結果、入手もできるようになりました。

このエピソードでは、そんな並列処理の1つの技法であるメッセージパッシングについて書かれています。メッセージパッシングについては深く勉強をしているわけではないので大まかなことしか知りませんが、簡単に言えば共有メモリを使わずに独立したプロセス間でメッセージを送受信しながら処理を行う方法です。並列処理の難しい点は共有したメモリへのアクセスです。これは同じ素材に対して、複数人で作業しているような状態です。それぞれがタイミングを間違えて作業を行ってしまったり、お互いにお互いが始めるのを待っている状態になるなど、様々な複雑な状況を想定しなくてはなりません。しかし、素材を2つに分けてしまい、お互いに独立して作業ができるのであれば、少なくとも前述のような問題は起きないのです。必要に応じて両者は会話(メッセージ)をします。作業状況を確認しつつ、お互いの作業に集中できるのです。メッセージパッシングを使った仕組みはまさにそんなイメージです。お互いが独立しているので、リモートマシン間での並列処理も簡単になります。ただし、うまくタスクを分割できなければなりません。お互いの作業を後からマージできるような処理であれば、安全で分散がしやすいメッセージパッシングは有効な選択肢でしょう。

ただ、まずは基本的な並列処理をもっと学ぶべきだと思います。メッセージパッシングのような1つ上位のレイヤーにある仕組みを使いこなすには、並列処理の難しさを知った上でどうしてそのような仕組みなっているかを理解して使うべきでしょう。メモリの揮発性や不変オブジェクトの価値などは並列処理プログラミングを学ばなければあまりピンとくるものではありません。共有メモリをどう扱うと安全な並列処理が実装できるのかを学ぶべきです。その上でメッセージパッシングを選択する方がずっと有用です。

ちょっとしたソフトウェアでも並列処理に関するニーズは高まっています。自分のホーム言語ならば、並列処理を自然に書く事ができるようにしましょう。

プログラマが知るべき97のこと

プログラマが知るべき97のこと

2011-02-12

54-見えないものを見えるように

| 23:14 |  54-見えないものを見えるようにを含むブックマーク

プログラマが知るべき97のこと」の54個目のエピソードは、ソフトウェア開発の可視化に関する話です。ソフトウェア開発において可視化見える化)はマネージャ層にとっては特に興味のある話題です。本文でも書かれているように、ソフトウェア開発の難しさの本質は、ソースコードや設計と言ったものが実体を持っているようで持っていない為、定量化・可視化が難しい所にあります。

ソフトウェア開発の定量化や可視化については、様々な方法が考えられ、試されてきました。ソフトウェアが複雑になればなるほどソースコードの量は増える傾向があるため、ステップ数という定量化手法が生まれ、ステップ数に対してどの程度の不具合が含まれているかの傾向を分析した結果、バグ率といった手法が生まれたわけです。また、エンジニア1人当たりの生産性をすステップ数で割れば正確に工数も計算できる、そんな方法は誰もが聞いたことあるでしょう。これらの手法は、忌み嫌われ、現在のソフトウェア開発の効率を下げる原因と言われます。しかし、それらの手法は、現代のソフトウェア開発に適していないだけです。過去はその手法でそれなりに正確に定量化・可視化できていたので間違いではありません。

それでは、どのようにして現代のソフトウェア開発を定量化・可視化するべきでしょうか?まず、過去の定量化手法は一旦リセットすることが重要でしょう。現代のソフトウェア開発においてステップ数が意味をなさないことは誰にも明らかなことです。過去の経験やノウハウを捨てるには勇気がいることですが、ソフトウェア開発に携わる以上は時代の進化に対応しなければなりません。自分も某開発においてはリファクタリングを行いコード量を減らした事が大問題になったことがあります。ステップ数が減る事は受け容れられなかったようです…。結果としてその会社は辞める事になりましたが、説得しても無駄と言うことはよく解りました。

次にタスクを細分化して見える形にすることです。タスクはプロジェクトの規模にもよりますが、数ヶ月程度のプロジェクトまたはイテレーションであれば、半日から数日で完了する粒度にするのが良いでしょう。それ以上細かいとタスクが多くなりすぎて管理しきれませんし、大きすぎると見積もりが難しくなる上に正確性が失われるからです。タスクの管理はissue管理システムやチケット管理システムを使えば簡単に行う事ができます。慣れていないと導入に抵抗がありますが、強引にでも導入し慣れさせる事が重要でしょう。また、システムよりもより形として見えるようにタスクかんばんを作り、ポストイットで手書きする事も効果があります。ブラウザを開いて確認するよりも常に誰の目にも見える事で、プロジェクト外の人にも確認しやすく、なにより意識が高まります。

そしてユニットテストは実体の見えにくいコードを色々な視点で可視化します。ユニットテストのないソースコードは実行することにより「ある」という実感を与えます。しかし、そのボリュームや仕様に関する部分について実感する事はありません。コードの動きが目に見えるようになり、テストしやすいかどうかも浮き彫りにします。ちょっとした修正であっても大量のユニットテストコードに影響を与えるならば、それはちょっとした修正ではないのです。逆に大きな修正であってもユニットテストに影響がないのであれば大きな修正ではありません。コードの修正量ではなくユニットテストも含めた修正量を計ることで現代のソフトウェア開発に適した作業量を知ることができます。

GUIなどユニットテストの難しいコードであるならば、ユースケースシナリオやユーザマニュアルが鍵となります。そのGUIを動かすための事前条件・ユーザシナリオなどがスクリーンショット付きで用意されているならば、誰もが何が正しいかを正確に知ることができるでしょう。ユースケースシナリオやマニュアルを最後まで着手しなかったら、誰も何が正しいのかを把握できません。細かい画面仕様書や詳細設計書はあれば有用かもしれませんが、ユーザの価値を重視する現代のソフトウェア開発では正確な記述よりも実用的なマニュアルの方が適している筈です。

残る問題はプロジェクトメンバーのスキルと意識です。メンバーが言われた事をやれば十分と感じているチームでは実現できません。うまく文化を形成していく事が重要ですが、変えられないならば諦めて新しい環境を探すべきと思います。

ソフトウェア開発プロジェクトを進める際はいつでも、目に見える証拠がたくさんあるという状態を維持すべきでしょう。目にみえる証拠があれば、進捗状況も正確に把握できます。決して思い込みで判断はしなくなります。

目に見える証拠を揃えるにはプロジェクトを正確に把握することが重要です。その為にはプロジェクトに関連する技術的なスキルだけでなく、見積もりの技術が不可欠だと思います。49-見積りとは何かにあるように、プログラマは技術的スキルだけでなくプロジェクトを俯瞰できるスキルを身につけてください。まずは「アジャイル見積りと計画づくり」を読むべきです。

プログラマが知るべき97のこと

プログラマが知るべき97のこと

2011-02-11

53-正しい使い方を簡単に、誤った使い方を困難に

| 23:47 |  53-正しい使い方を簡単に、誤った使い方を困難にを含むブックマーク

プログラマが知るべき97のこと」の53個目のエピソードは、インターフェイスに関する話です。ソフトウェア開発のスキルを身につけていく中で、インターフェイスバウンダリ(境界)に関することは、最も悩まされる事の1つです。一言でインターフェイスと言っても、ユーザインターフェイスのような抽象度が高くシステムの中でもエンドユーザに近いインターフェイスもあれば、クラス内での関数の呼び出しのような抽象度の低くプログラマに近いインターフェイスもあります。共通する点は、複数の領域を橋渡しする為の窓口となっているという事です。使う側からすれば、窓口の反対側でどのような事が行われるかよりも窓口を通じて受け取れる結果や効果について興味があります。極端な例をあげれば、自動販売機の中でどのような処理が行われていたとしても、自動販売機を利用する人はお金を投入した結果として商品が入手できる事が重要なのです。窓口での手続きは簡単である方が望ましいのです。このエピソードでは、そんなインターフェイスを設計していく時に重要な事を2つ紹介しています。

正しく使用する方が操作ミスをするより簡単

自然に正しく使えるようになっていれば、操作ミスを未然に防止できます。言い換えれば、正しく使用する方法が解らないから操作ミスが発生するのです。最も良く利用し最も価値の高い機能を使う為のボタンが、特定の条件を満たし、解りにくい場所に表示されるとしたら、その機能を試す前にユーザーは心が折れてしまいます。ある処理をするためにたくさんのクラスを初期化し、組み合わせて実行するとしたならば、どこかで設定し忘れて正しく実行できない可能性が高くなります。見やすい場所のボタン1つ、ユーティリティメソッド1回の呼び出しで済むのであれば、操作ミスをするよりも簡単に利用できます。

誤った使い方をすることが困難

操作ミスの原因自体がなければ、操作ミスは起こりえません。操作できないボタンが押すことが出来てしまうとそれだけで操作ミスが発生する原因となります。一手間かけてボタンを非活性にすることで、操作ミス自体が起きないようにすることが出来ます。関数であれば、複数の引数は指定順番を間違える可能性があります。しかし、1つしかなければ順番を間違えることはできません。

使いやすいインターフェイスを設計する場合は、必ず利用者側の視点に立って設計することです。インターフェイスAPIは利用者のために存在するのです。その為には、自分自身が利用者となり、使いにくくないか?間違えやすくないか?について検討するべきです。自己満足インターフェイスを作ってはいけません。ユーザが満足するようなインターフェイスを作るのです。APIであればテスト駆動開発を導入して最初に自分がユーザとなってください。テストが可能で使いやすいかを確認してください。GUIであれば、モックを作り実際に操作してください。GUIの場合は実際に使うユーザと同じ程度のコンピュータ知識を持った人が使うのがベストでしょう。どちらにせよ、使ってみて感じる事が大切です。

プログラマが知るべき97のこと

プログラマが知るべき97のこと

2011-02-10

52-「その場しのぎ」が長生きしてしまう

| 21:53 |  52-「その場しのぎ」が長生きしてしまうを含むブックマーク

プログラマが知るべき97のこと」の52個目のエピソードは、暫定ソリューションに関する話です。暫定ソリューション(その場しのぎ)とは、本来は遵守すべき規約やプロセスに従わずに急ごしらえで作成したソリューションのことです。時間に追われ不具合を直すために行儀の良くないパッチを当てる事もそうですが、設計の段階で捨てる予定のモックがいつの間にか採用されて使わざるをえなくなるような事も含むでしょう。暫定ソリューションが生まれる要因は時間が十分に確保できない事にあります。言い換えれば、暫定ソリューションは十分な時間をかけて満足するレベルに達していない事が多く、結果として改修や拡張が困難になるのです。

暫定ソリューションの最大の問題は既成事実化することです。「とりあえず作ったもの」であっても、ユーザにとって役に立つのであれば、無理に変更する価値はほとんどありません。先が見えない中での暫定ソリューションは、さらなる暫定ソリューションを生みだします。そして、気付くと巨大なレガシーコードとなり、最終的にはレジェンドコードとなるのです。こうなってくると設計の問題を認識できるようになりますが、それでも「その場しのぎで良いから対応してくれ」と言われるのが現実です。

それではどのようにして暫定ソリューションを回避すべきでしょうか?このエピソードで紹介されている3つの方法の中では2番目の暫定ソリューション修正の優先度が上がる体勢作りが現実的で理想的なスタンスだと思います。暫定ソリューションを全く作らないことは現実的ではありません。特に売り込みをかけている段階では、必要以上に時間もお金もかけることができません。問題はそのソフトウェアが認められ開発も軌道に乗り始めた時期です。タイミングが難しいですが、早い段階で再設計やリファクタリングをしなかった為に破綻したプロジェクトというのは良く耳にします。作った負債はなるべく早く返済し、借金をゼロに近づけるのが理想です。

また、「その場しのぎ」の続く文化は成長を阻害します。毎度「その場しのぎ」が続くと、「どうせ、今後もその場しのぎで対応するんだから、設計しても意味がない」という空気が生まれます。そんな開発チームが良い物を作れるでしょうか?品質への高い意識は、結果としてプログラマスキルを高めます。各プログラマ負債を早く返す意識と、それを後押しするような開発体制をひくことが重要なのです。

技術的負債の話にもありましたが、暫定ソリューションは返さなくてはならない借金であるという事を忘れないようにしましょう。借金ですから利子もあることも忘れずに。

プログラマが知るべき97のこと

プログラマが知るべき97のこと

調査員調査員 2011/02/11 10:56 こんにちは
またまたScenic3について質問等があります。

1.ファイルのダウンロード、表示について
Slim3のControllerにはdownload、showメソッドが実装されていますがScenicPageにはありません。
ダウンロードするファイル名の実装がややこしく、できればSlim3のControllerのメソッドをそのまま使いたいですが、委譲メソッド等の実装を検討していただけませんでしょうか。

2.setUpメソッドについて
Slim3のControllerのsetUpは戻り値がNavigationですがScenicPageのsetUpはvoidになっています。
できればSlim3のControllerと同じ動きをさせたいので、ScenicPageのsetupPageの実行をController#runからController#setUpに変更し、setupPageで実行していたPage#setUpをScenicControllerで実行し戻り値を返すようにしてはどうでしょう?

3.tearDownについて
これも実装されていませんので2と同様に、Controller#tearDownからPage#tearDownを実行するようにしてはどうでしょう?


試しにソースをチェックアウトして上記変更を加えたScenic3を試してみましたが、問題なく使用できています。
もし、検討していただけるのであればご迷惑でなければパッチをお送りします。

shuji_w6eshuji_w6e 2011/02/11 23:48 コメント有り難うございます。
指摘いただいた部分を含め、修正を進めていますのでもう暫くお待ちください。

KazKaz 2011/02/14 16:46 現実に「その場しのぎ」を繰り返さざるを得ない現状が目の前にあるので, 正論には返す言葉もありませんね。継続開発で受けているので, 一つ動くものを見せてしまうと次のリクエストが来てしまって, 結局書き直す時間が取れないという悪循環を経験中であります。

2011-02-09

51-プロジェクト自身にしゃべらせる

| 23:52 |  51-プロジェクト自身にしゃべらせるを含むブックマーク

プログラマが知るべき97のこと」の51個目のエピソードは、ソフトウェア開発の自動化に関する話です。先日のTDDBCでもid:t-wada氏は「近代ソフトウェア開発の三本柱はテスト・バージョン管理・自動化」と話していましたが、自動化は興味深く重要なテーマの1つです。最近は、Huds○n*1の普及によってCI(継続的結合:Continuous Integration)サーバも自然に使われるようになってきました。継続的なビルド以外でも、静的なメトリクス測定・テストの自動実行・カバレッジ測定・その他様々な定型処理を自動化する流れがあります。そして、自動化を行うツールも整備されてきています。自動化をするメリットは、時間のかかる面倒な処理を任せてしまうことにより時間を有効に使えることと思われがちです。しかし、それ以上に実感するメリットは、問題等を早い段間で検知できることです。

テストを例にあげましょう。テストをJUnitCIで自動化してない場合、テストは手作業で行われます。手作業で行う場合、何度もやることは現実的ではありません。したがって、開発フェイズの最終段階で行うのが一般的です。すると、最後の最後まで問題が発覚しにくいのです。一方、テストが自動化されており、毎日実行されていれば、遅くとも次の日の朝には問題が検知できています。検知が早ければ早いほど対処も簡単になりますし、他の箇所への影響も最小限に抑えることができるのです。

CIサーバは導入していくのが一番大切です。導入には様々な障害があると思いますが、導入してみないとそのメリットは感じられません。ユニットテストと同様にソフトウェア開発の精神的な不安を軽減する効果が高いでしょう。勿論、導入にはコストがかかりますし、設定やノウハウの蓄積にもコストがかかります。まずは、自分自身の勉強のために導入して運用すると良いでしょう。そうすれば、業務で導入する場合でも最小限のコストで導入できます。

また、導入は他のメンバーにも良い影響を与えます。自分の今抱えている業務では初めて本格的にCIを導入しました。すると、自然とユニットテストビルドエラーに対する意識が向上します。初めは「良くわからないけど便利らしい」と感じていたメンバーかもしれませんが、Hudsonが裏側で堅実に仕事を行っている安心感を感じています。そして、自分のコミットに責任を感じるようになっています。

尚、このエピソードでは、更に楽しんで開発を行う為にXFD(eXtreme Feedback Device)が紹介されています。タスクの結果に応じてランプやちょっとしたギミックが反応する、ちょっとした遊び心です。くだらないことと感じるかもしれませんが、このような遊び心が生まれるということは余裕があるという事です。ある程度のスキルを持ったメンバーが集まって、楽しみながらチームで開発を行うというのは理想でしょう。全員が日々学習し、スキルを身につけ、余裕が出てきたならば遊び心を加えていく、そんな仕事を目指しています。

プログラマが知るべき97のこと

プログラマが知るべき97のこと

*1:商標に考慮

2011-02-08

JavaScriptによるEtupirkaCMSのアップデートプログラム

| 23:28 |  JavaScriptによるEtupirkaCMSのアップデートプログラムを含むブックマーク

EtupirkaCMS絡みでちょっとネタになりそうなプログラムを作ったので紹介します。内容としては、JSR223(スクリプト言語サポート)を使いJavaScriptランチャープログラムSwingアプリ)の更新を行う仕組みの解説です。

動機

EtupirkaCMSのウリとしてJavaだとかGAEだとかを意識せずに使って貰えるようなユーザビリティを目指しています。昨今のアプリでは自動アップデートなんて当たり前ですから、EtupirkaCMSも自動アップデートが出来る必要があります。しかし、Javaスタンドアローンプログラムなど珍しいこの時代、WindowsアプリやWebStartのようにちょとしたAPIを使えば自動アップデートが出来るというわけにはいきません。そこでほとんどを自分で実装するわけですが、色々と課題もあります。

続きを読む

50-Hello, Worldから始めよう

| 00:02 |  50-Hello, Worldから始めようを含むブックマーク

プログラマが知るべき97のこと」の50個目のエピソードは、プログラミングの原点に関する話です。長くプログラミングを続けていたり、マネジメントやその他の業務が多くなってくると、基本的な事を忘れがちです。焦って自分を見失っている時などは、原点、すなわちHello Worldテキストエディタで入力する事に戻ってみようという話が書かれています。

この事はどんな時にでも重要な事です。ちょっと実装で詰まったとき、設計がどうも納得できないとき、交渉事がウマくいかないとき、様々な困難に当たったとき、疲れた頭でより複雑に考えていても中々解決することはありません。よく、「今日は帰ろう。明日の朝には解決するさ」という会話を同僚としますが、これは問題を放棄して早く帰りたいわけではないです。煮詰まったときはより複雑な方に思考が行くだけでなく、夕方から夜では既に集中力はありません。頭をリフレッシュしてシンプルに整理してみると、あっさり解決することは経験的にも多いです。

このエピソードに書かれているように、たまにはIDEを閉じてテキストエディタでコードを書くのも良いでしょう。

public class HelloWorld {
  public static void main(String[] args) {
    System.out.println("Hello, World");
  }
}

・・・・せめてScalaJavaScriptあたりにしておきます。そういえば、初心者だった頃はこの長ったらしいHello Worldを書くのに何度タイポしたものか。

プログラマが知るべき97のこと

プログラマが知るべき97のこと

QQ 2011/05/17 16:02 こんにちは、はじめまして。
どちらに書かせていただこうか迷ったのですが、etupirkaタグのついているこちらに失礼します。
ローカルでのappengine-java-sdkのインストールがうまくいかないようで、ご意見いただければ幸いです。
当方の環境はWindoes XPで、JAVAは現在最新のVer6-25です。
EtupirkaCMS-0.2.0.zipを解凍し、ガイドサイトの手順のとおりetupirka.exe(EtupirkaCMS.exe)をダブルクリックしたところ、appengine-java-sdkフォルダは作成されるのですが、ダウンロードが始まりません。
一瞬窓が表示されるのですがすぐに閉じてしまっています。
チェックすべき項目はありますでしょうか。よろしくお願いします。

shuji_w6eshuji_w6e 2011/05/22 07:42 確認しました。
サーバ移行時にミスしたようです。
これから対応します

shuji_w6eshuji_w6e 2011/05/22 10:55 対応しました。
ご迷惑おかけして申し訳ありません。

QQ 2011/05/23 23:04 sdkのダウンロードもはじまり、無事起動できました。
これからローカルでページを作ってからGAEにアップロードしてみようと考えています。
ローカルのデータ→GAE上に反映や、また逆もやりやすいとのことで、
こういった使い方ができるというのはとても楽しみです。
対応どうもありがとうございました。

2011-02-07

49-見積りとは何か

| 22:16 |  49-見積りとは何かを含むブックマーク

プログラマが知るべき97のこと」の49個目のエピソードは、見積りに関する話です。見積に関するこのエピソードは日頃よく思う部分です。しかし、残念な事に本当に読んで理解して欲しいのはプロジェクトマネージャです。そして、プロジェクトをリードしていく事になるプログラマも知るべき内容です。

このエピソードではあるプロジェクトマネージャプログラマとのありがちな会話を例にして、見積りの定義を再確認しています。大辞林で「見積もり(る)」を調べると次のように書かれています。

1. 目分量や心づもりではかっておおよその見当をつける。目算する。「入場者数を―○る」

2. 工事や製品などの、原価・日数・経費などを前もって計算して出す。「経費を―○る」「工事を―○る」

ソフトウェア開発では、現実として1の「おおよそ見当をつける」事しかできません。工業製品などと異なり、プログラマスキルに依存する部分が多いこと、要求が変化する可能性があること、見積りの時点で全ての情報が揃うことはほとんどないことなどが理由です。工業製品の生産だけに限るのであれば、原材料のコスト・原材料の調達時間・加工時間・ラインの稼働状況などを計算することで、2の「計算して出す」事が可能ですが、ソフトウェア開発には適用できません。しかし、実際のソフトウェア開発の現場では、2の「計算して出す」として使われているのが現状です。この問題を解決するには、「見積り」と「コミットメント」の違いを知る事が出発点になります。

見積り」とは、何かの価値、数字、量、程度などについて概算、あるいはおおまかな判断をすることを指します。

見積り」では、正確な数値を出すことはできません*1。「見積り」は信頼できるデータや経験から基づく予想でしかないため、幅がある方が自然です。例えば、「xyz機能について、特に大きな問題も発生せずに順調に実装ができれば3日程度でできると思いますが、xxの部分で気になるところがあり最大で5日かかる可能性があります」と言ったように大雑把な数値で幅が出るのが自然です。言い換えれば、正確な値を出すことができないのです。

コミットメント」とは、「約束」と言い換えても良いでしょう。

コミットメント」は文字通り「約束」です。別の会話はよくある会話ですが、プログラマであれば似たような違和感を感じたことがあるでしょう。

  • PM 「機能xyzはまだ出来ていないようだが、開発期間の見積もりは5日と言っていたはずでは?」
  • プログラマ 「はい、思った以上に手こずっていまして、最終的には6ー7日になるかと思います。明後日には完成するかと」
  • PM 「それでは(私が/WBS上で)困る。5日と見積つもった以上、5日で終わらせるのが仕事だろう」
  • プログラマ 「・・・・」

このありがちなケースではプロジェクトマネージャは完全に「見積り」を「コミットメント(約束)」として捉えています。日本語の「見積り」には「計算して出す」というコミットメントに近い意味と2つの意味があるのが問題なのです。しかし、はじめからプログラマとプロジェクトマネージャの間で言葉の定義を合わせておけばトラブルは避けられました*2

プログラマとしては、言葉の定義を正確に行いコミュニケーションを行う必要があります。

1つ目として、チームメンバーやステークホルダから「見積り」を依頼された場合は、それがコミットメントかどうかを確認するべきです。コミットメントであれば、見積りにリスクを加味した上で自分がやり遂げる自信のある数値を呈示するのがプロの見積もりです。例えば、コミットメントとして7日と提示する場合でも、「実装自体は5日程度の見込みですが、一部の機能に調査が必要な部分があり最大で2日程度使うかもしれません。7日あれば終わらせます」という具合です。勿論、5日の根拠もあると望ましいですが、それが見積もりでなく約束になる事を踏まえて伝えなくてはなりません。そして、不可能なコミットメントを要求されてもそれを簡単に受け容れてはなりません。

2つ目として、細かい単位でのコミットメントは避ける事です。例えば、おおよそ3−5日で終わる見込みの機能を1つ実装する為にはどうしても5日をコミットメントとする必要があるでしょう。しかし、同じボリュームの機能を10個実装する時に最大値である50日をコミットメントにする必要はないと思うはずです。勿論、最悪のケースでは50日かかるわけですが、最短で30日ということを考え、40日程度をコミットメントとする事は可能だと思います。実際には、3日よりももっと早く終わらせる事の出来る機能もあれば、5日以上かかる機能もあるでしょう。しかし、全体として調整できる余地が残ります。これは、見積額を出す場合は行っているでしょう。言い換えると、1−3日程度の個々のタスクコミットメントを求めるのはナンセンスということです。金額の見積りについて補足ですが、初めはリスクコミットメントを加味せずに見積りを行う事が重要です。初めから納期がx月だからとか予算がxxx万円だからというコミットメントを意識して見積りを行うと、単純な引き算になってしまい、現実と乖離するだけです。現実に見積もりを行い、適切なリスク係数などを加味して見積額を算出しましょう。

ソフトウェア開発には変化が付きものです。正確な見積もりや正確なスケジュールを立てようとしてもコスト的に見合うことはほとんどありません。「アジャイル見積りと計画づくり」には、どのようにして変化に向き合ってソフトウェア開発を進めていくかが書かれていますので必読です。

プログラマが知るべき97のこと

プログラマが知るべき97のこと

*1見積額はかなり正確である事が求められるので語弊されやすいです

*2:まあ、コミットメントできない納期を要求される事はあるかもしれません:p

2011-02-06

48-いろいろな言葉を学ぶ

| 23:02 |  48-いろいろな言葉を学ぶを含むブックマーク

プログラマが知るべき97のこと」の48個目のエピソードは、コミュニケーションに関する話です。エピソードのタイトルになっている「言葉」にはプログラミング言語も含みます。プログラマコンピュータと対話する職業である以上は、コンピュータと対話するための言語、つまりプログラミング言語を習得することは大切なことです。そして、1つの言語ではなく幾つかの言語を習得し、よりコンピュータと密なコミュニケーションが取れることはより望ましいことです。複数の言語を習得した方が良いという話題は、43-プログラミング言語は複数習得すべきなどでも語られている重要な事です。このエピソードでは、プログラミング言語を習得する事に加えてプログラマが習得すべきコミュニケーション能力について記述されています。

1つ目は、プログラマ間のコミュニケーションに関してです。ほとんどのプログラマは1人ではなく複数のメンバーでプログラムを行います。したがって、チーム内でコミュニケーションが発生しないことはまずありません。例えば、設計の話、使用に関する認識の話、テスト方針の話、不具合の話などチーム内で意識を合わせていく事はソフトウェア開発では最も重要で最も難しい部分です。そこにはプログラミングスキルだけでなくUMLデザインパターンなどの特有の「言葉」があり、抽象的概念をコミュケーションを成り立たせています。

2つ目は、QA・セールス・マーケティングといったプログラマとは違うレイヤーの開発者とのコミュニケーションです。彼らはプログラマではありませんので、プログラマの「言葉」をそのまま使ってしまっては会話が成り立たないでしょう。彼らの立場に立ち、可能な限り彼らの「言葉」を使ってコミュニケーションをする必要があります。勿論、共に開発を行っているのですから、彼らもまたプログラマの「言葉」を使えるような努力は必要でしょう。

最後は、顧客などドメインの違う相手とのコミュニケーションです。彼らは開発者ですらありませんから、彼らのドメインの「言葉」をどれだけ知っているかはコミュニケーションを行う為に必要不可欠な要素です。プロジェクトの全員が専門家になる事は難しいでしょうが、何人かは顧客の言葉を聞き話す事ができる必要があります。ただ、顧客のドメインに詳しい開発者はそれが強みである一方で、他のドメインの仕事につくことが難しくなる事もあるのが難しい所です。

ここ1−2年の間で、このエピソードに関係する事について多くのことを学びました。プログラマ以外の人と話すときの「言葉」が重要な事は何回も実感しています。例えば、セールスやマーケティングの立場の人との会話では、プログラマの視点だけでは論点がずれてしまいます。少しでもお互いに「言葉」を理解する事で、ずっとコミュニケーションがやりやすくなることを知りました。また、プログラマ間のコミュニケーションについて、よくコミュニケーション能力不足が原因と言われます。しかし、自分は疑問を感じていました。そもそもソフトウェア開発のチーム内コミュニケーションは難しいものです。自分で理解できる事と、それを表現できることでは求められる理解度に大きな差があります。さらに問題なのは、どれだけ伝えたとしても、理解しようとしない人には永遠に理解して貰えないのです。つまり、チーム内でのコミュニケーションが円滑に行えるためには、チームのメンバーが一定のレベルでスキルを有している事が前提となっているのです。そこにコミュニケーション能力という不可解な能力などは存在せず、存在するのは理解力と表現力というスキルです。

幸いな事にこれらの「言葉」は努力すれば習得する事ができます。努力しようとすれば、かならずあなたの仲間の誰かはしっかりとあなたに教えてくれる師匠になるはずです。コミュニケーション能力とかいうインチキ能力に惑わされず、地に足を付けて地道に「言葉」を学びましょう。

プログラマが知るべき97のこと

プログラマが知るべき97のこと

2011-02-05

47-大量のデータはデータベースで

| 23:30 |  47-大量のデータはデータベースでを含むブックマーク

プログラマが知るべき97のこと」の46個目のエピソードは、データベースに関する話です。

アプリケーションで大量の永続データを扱う必要がある場合やデータが相互に関係し合う場合は、迷うことなくRDB(リレーショナルデータベース)にデータを保存すべきでしょう。

時代の差なのでしょうか?自分が仕事としてプログラミングを始めたのは2003年頃なので、その頃にはデータベースの利用はごく一般的な事でした。まだ、MySQLなどのフリーで信頼性のあるRDBはなかった為、ほとんどの業務でOracleなどを利用してたと記憶しています。なのでピンと来ないエピソードなのですが、自分のデータースにまつわるエピソードを紹介しておきます。

1つ目は最近の案件で実感した事ですが、組込RDBは思った以上に高性能で使いやすいという事です。あるアプリケーションの改修を行う際に性能要件を大きくあげて欲しいとの要望がありました。それまではインメモリでデータを格納しても十分なデータ量だったのですが、要件を満たすためにはメモリがどうやっても足りません。そこで、組込RDBとしてH2 Databaseを使用しました。合わせてDomaをO/Rマッパーとし、全文検索エンジンとしてLuceneを組み合わせた形になります。MySQLなどは自然に利用していましたが、組込DBということで初めは戸惑ったものです。でも、調査をしてみると意外に簡単に実現できました。

2つ目はマスターテーブルに関する話です。世の中には不思議なアプリケーションも多いもので、「性別区分」や「都道府県コード」のようなものまで全てマスターテーブルに管理するアプリケーションがあります。明らかに不変なものまでRDBで管理するのはオカシイ話なのですが、もっとオカシイ事に全てのテーブルにマスターメンテ画面も付属するのです。こんな不毛な機能にクライアントは幾ら払っているのだろうと考えるわけです。

自分にとって、RDB+SQLはごく自然なスキルとして身につけてきました。それはJava案件、特にウェブアプリケーションに多く携わっていたからだと思います。ですが、人によってはRDBとは縁のない領域でプログラムをしているかと思います。もし、RDBについてあまり詳しくないようであれば、最低限のスキルは持つべきです。あちらこちらで応用の利く便利な技術だと思います。

プログラマが知るべき97のこと

プログラマが知るべき97のこと

2011-02-04

46-すべきことは常に明確に

| 00:55 |  46-すべきことは常に明確にを含むブックマーク

プログラマが知るべき97のこと」の46個目のエピソードは、仕事の進め方に関する話です。特に仕事でプログラミングをしている人にとって非常に有用なエピソードで、きのこ本の中でも特に感銘を受けました。

プログラミングに限ることではありませんが、仕事をどのように効率良く行っていくかは重要なテーマです。仕事を始めて間もない人は、自分が何をやったらばいいか右も左も解りません。先輩から細分化されたタスクを割り当てられ、ある程度の経験を積んでいくことで小さなタスクとしての仕事は出来るようになります*1。そして、次のステップとして全体を俯瞰してみることが出来る事が求められます。残念なことに、このステップに進めないで成長が止まる人も多いのが事実であり、チームリーダーなどチームを統括するポジションにつく人のみが全体を俯瞰できているのが現実でしょう。すると、仕事の進め方として、全体を俯瞰できる人がWBSなどを使い細かいタスクに分割していき、それをチームメンバーに割り当てながら仕事を進めていく方法が取られます。つまり、全体を俯瞰して見る事の出来ればプログラマとしてプロジェクトを回すための十分なスキルなのです。少なくとも自分はそう思っていました。

ですが、このエピソードでは全体を俯瞰できるのは当たり前で、その中で自分が何をすべきかを明確にするのがプロの仕事として語られています。プログラミングならではのやり方かと思いますが、ある時間で出来なかったならば破棄するという方法を提案しています。実際に開発をしていて煮詰まったとき、そこまで書いたコードを破棄するには相当の勇気が必要です。苦労して書いたコードであればなおさら、それを破棄して作り直したくないと思うのは当然です。しかし、本当に詰んだときにコードを破棄して書き直すことは珍しいことではありません。そして、詰まるまでに蓄積された思考まだは破棄されないので、作り直してみたら意外に簡単に片付いたということもよくあります。ですが、破棄するための判断基準が難しく、破棄した方が良いかもしれないけどもう少し頑張ってみようとなるのです。

このエピソードではそんなジレンマに関して解決策を教えて貰いました。それは時間です。何をするかを決めたならばそのタスクを完了するための期限を決めるのです。その期限を越えそうであれば、その時点で破棄を判断します。もしくはタスクの作業時間の再見積や細分化をします。時間で区切ることにより、客観的な基準を設定するのです。

大事なのは、常に自分が何をすればいいを明確にするということです。完了する期限も必ず決めます。もし、期限内に予定の作業が終わらないようであれば、その間に書いたコード、コードに加えた変更はすべて破棄します。再度、小目標を立て直して作業内容を検討し、はじめからやり直すのです。

時間を区切って仕事をする事といえば、アジャイル系の開発におけるタイムボックスが思い浮かびますね。

プログラマが知るべき97のこと

プログラマが知るべき97のこと

*1ペアプロを導入すればこの部分はもっと効率化できます

2011-02-03

45-限界を知る

| 08:39 |  45-限界を知るを含むブックマーク

プログラマが知るべき97のこと」の45個目のエピソードは、リソースに関する話です。このエピソードは、アルゴリズムと計算量に関する記述が目立ちますが、冒頭にあるようにリソースの限界を知ることが重要であるという主張です。

ソフトウエア開発には様々なリソースがあります。ハードウェアの性能、アルゴリズム、作業に費やせる時間、お金、プログラミング言語の制約・性能などです。これらのリソースプログラマが個人ではどうにもならないものと、何とかできるものに分けられます。例えば、プロジェクトに投入するお金やハードウェアに関しては、ある程度はともかく完全にコントロールできません。限られたリソースでどれだけの効果を出せるかが求められます。一方で作業に費やせる時間やプログラミング言語の制約などはプログラマが自分でコントロールできるリソースです。限界はありますが、訓練をしてスキルをあげていくことで、リソースの限界を大幅に引き上げられます。エキスパートには訓練をすることで誰でもなれるのです。

どのリソースも正確に、特に限界を知るには訓練をしてスキルを磨かなくてはなりません。例えば、プロジェクトの予算を引き上げることは難しくとも、スキルを高めることにより見積の精度は高まるでしょう。見積の精度が高まれば、お金というリソースの限界も見えてきます。また、自分のスキルの限界も見えるようになります。この規模のプロジェクトであれば自分の限界に比べてどの程度の難易度かが客観的に判断できるようになるでしょう。

このエピソードで書かれている計算量とアルゴリズムの話もその1つです。最適なアルゴリズムを選択するためには1つのアルゴリズムを知っているだけではなく、幾つかのアルゴリズムの特性を知っている必要があります。要件を実現するだけであれば1つのアルゴリズムを知っているだけで充分ですが、最適なアルゴリズムを選択するのがプロの仕事です。プログラミングスキルなどは学習により限界を知り、お金などのリソースよりも簡単に限界をあげることができます。

自分の持つ戦力を把握することは戦いにおいて最も基本的なことです。戦力を把握すると言うことは、限界を知ると言うことです。限界を知るには学習するしかありません。学習し、経験することで本当の力になるでしょう。

プログラマが知るべき97のこと

プログラマが知るべき97のこと

2011-02-02

44-IDEを知る

| 23:48 |  44-IDEを知るを含むブックマーク

プログラマが知るべき97のこと」の44個目のエピソードは、IDEに関する話です。きのこ本には幾つかのIDEに関するエピソードがあります。プログラマにとってIDEテキストエディタは最も重要な道具なので当然でしょう。それらのエピソードで共通する主張は、IDEを活用することで生産性をあげることができるがUNIXツールやコマンドラインツールも重要という事です。さて、IDEに関するネタは尽きてきました。今回は、自分がEclipseJavaを操る時の感覚について書こうと思います。

最近流行の言語に比べれば、Javaは冗長な構文のプログラミング言語です。Rubyなどの言語に比べてタイプ数は遙かに多く、考えていることをそのまま記述できるような柔軟性はありません。ですが、情報量が多いため、コードを読む時のヒントは多いとも言えます。また、コードを書くときには「型」を強く意識します。「型」とはイディオムテンプレートとも言い換えることができます。ある種のことがやりたい場合、「このように書く」と言う型が明確です。

Javaをホーム言語としている人はこの「型」のボキャブラリーが豊富と言えます。プログラミングをする時に型を意識して思考します。勿論、他の言語であっても同様なことは言えます。しかし、パターンを認識したり、応用したりする場合、簡潔すぎると覚えにくい事があります。言い換えると、ある程度の冗長な構文がパターンの認識を手助けしており、応用的な使い方も想像しやすいのではないでしょうか?勿論、そのコーディングに手間がかかるのであればメリットよりもデメリットのほうが大きいでしょう。しかし、Eclipseを使えば、そのコーディングの手間は大幅に減少します。頭の中で「こう書きたい」とイメージしたならば、数タッチでそれが実現可能なのです。

自分の場合、Javaプログラミングをしている時、コードのイメージを思い浮かべ、それを形にしていくような感覚でEclipseを叩きます。例えば、文字列のリストを作成したいと思ったならば、完成形のコードを思い浮かべながら「new Array」とまで入力し、Ctrl+Spaceで自動補完をかけます。するとEclipseは「ArrayList?」と聞いてきますので「Yes」と答えるのです。さらに型パラメータを聞いてきますので「String」と入力します。続けて、Ctrl + 1を叩き「ローカル変数に代入する?」とEclipseに提案することを誘導します。最後に型がArrayListでなくてListがいいのでは?とEclipseは聞いてくるので「Yes」と入力するわけです。このようにイメージ(型)を浮かべたならば、後はEclipseと対話的にプログラミングしています。自分にとってJavaの冗長な構文はロジックの構造を確認し、安心するために必要な要素です。

このエピソードで書かれているように、IDEの習得曲線は非常に緩やかです。ですが、手足のように使えるようになるには、十分な訓練が必要なのはテキストエディタと変わりません。そして、正確に早くプログラミングするにはエディタの性能ではなくプログラマスキルが重要です。IDEエディタは思考を妨げないレベルでの性能を持てば良いでしょう。幸いにもPCの性能が向上した今、IDEが重くて動かないこともなくなりました。Javaをホーム言語とするならば、もっともっとEclipseを使いこなせるように勉強してみましょう。

プログラマが知るべき97のこと

プログラマが知るべき97のこと

2011-02-01

43-プログラミング言語は複数習得すべき

| 23:36 |  43-プログラミング言語は複数習得すべきを含むブックマーク

プログラマが知るべき97のこと」の43個目のエピソードは、プログラミング言語の習得に関する話です。26-言語だけではなく文化も学ぶでも書いたように達人プログラマーには「毎年、新たなプログラミング言語を1つは学ぶこと」と書かれています。新しいプログラミング言語を習得していくことにより、新しい視点や思考を出来るようになります。このエピソードでは、新しい言語を学ぶ場合でも、可能な限りパラダイムの異なる言語を選択していくのが効果的であると書かれています。

ですが、実際に新しい言語を学ぶという事はどの程度現実的でしょうか?2つ目の言語を学び始める時期に関しては才能や素質による部分が大きいと思います。22-1万時間の訓練で書いたように誰もが適切な訓練を積み重ねる事でエキスパートとなれと思いますが、誰もが同じようなペースで訓練できるわけではありません。自分の場合、20代前半ではほぼ100%の仕事や学習はJavaでした。Javaを6年ほど続けた上でRubyPHPPythonなどを経験し、趣味ではJavaFX Script, Scalaなどを触っています。今、考えるとその配分は良かった点も悪かった点もあると感じています。

学習意欲のある新人がプロのプログラマを目指すのであれば、最初の3年程度は浮気をせずに1つの言語に絞って学習する方が良いと思います。1つの言語に絞る前の段階で、幾つかの言語をつまみ食いして、自分にあいそうな言語を探すのもいいでしょう。しかし、ある程度の経験を積むまでは1つの言語に打ち込んだ方が良いと思います。ある言語をそれなりに理解しているならば新しい言語の習得の時に新しく覚える事が減りますし、比較しながら学習することができます。また、ホーム言語に別の言語で得た経験を適用して、ホーム言語のスキルをさらに伸ばすこともできるのです。

現実的には最初のホーム言語として適しているのは、JavaPHPVB.netあたりかと思います。何より仕事として選択がある程度可能ですので、仕事外の時間だけで習得するよりも早いペースで習得可能です。また、十分な書籍も揃っています。そして十分なコミュニティも形成されています。したがって、マイナーな言語を選択するよりも楽にスキルが伸ばせるでしょう。勿論、自分がやりたいと心に決めた言語があるならばそれを選んでください。

また、プログラミング言語だけではなく、周辺の技術や開発手法なども学ぶべきです。実際の開発現場では、どんな言語でも使いこなすエキスパートプログラマはそれほど価値はありません。3つ4つの言語をそれなりのレベルで使えれば十分です。それだけの数の言語を使えれば、新しい言語が業務で要求されても、覚えながら仕事が可能だからです。それよりも、ネットワークの基礎知識、Linuxを扱うスキルUMLを使った設計方法、ユースケースの書き方、テスト駆動開発の進め方など周辺技術や設計手法を幅広く使いこなせる人に価値が高くなります。近年の開発では短納期・少人数で行う事が多くなっているため、要件定義から運用までカバーできる人は価値が高いのです。

「新しい言語を学ぶ」のは重要です。それはプログラマとして幅広い知識と考え方を習得するためです。その為には言語だけでなく周辺技術にも目を向けると良いでしょう。さらに全く異なる分野の事を学ぶのも違った効果があるでしょう。

なにはともあれ、学習を続けることしかありませんね。

プログラマが知るべき97のこと

プログラマが知るべき97のこと