2009年9月5日
北陸Scala勉強会の会場が決定しましたのでお知らせします。
9/26(土) 富山県民会館 303号室
定員 講師含め18名
13:30 - 17:30 を予定しています。
- 13:00 - 13:30 開場・設営
- 13:30 - 13:55 セッション 「Scala概説」
- 14:00 - 14:25 セッション 「副作用」
- 14:30 - 15:50 ディスカッション 「副作用の理解を深める」
- 16:00 - 17:30 ディスカッション 「既存言語への応用を考える」
- 17:30 - 18:00 後片付け
第一回のテーマは「副作用」です。Scalaスケーラブルプログラミングでは、3章5節あたりの話題です。Scalaではどのような言語的サポートがあるのか、副作用のない設計をするにはどうしたらよいか、副作用を抑えることで何が得られるのかを学びたいと思います。
簡単なセッションで副作用について学んだ後に、実際のソースを見ながら副作用を考慮した設計についてディスカッションしたいと思います。対話して理解を深める狙いです。
申込はこちら。
2009年6月30日
7/4(土)に富山でFlex3勉強会第73回@北陸が開かれます。北陸地方のFlex勉強会は隔月開催、北陸3県持ち回りとなっています。
今回が北陸の3回目で福井、石川に続き富山開催なわけですね。
公式ページはこちら
バーを借りきってまったりと進行の予定。ぜひ懇親会までご参加ください。きっと面白い話が聞けますよ。
2009年6月8日
第二回チキチキ 日本ペアプログラミングの会java-ja支部会(仮)に参加してきました。会場を提供してくださった株式会社ドワンゴ様、本当にありがとうございました。
TDD(test-driven development)での開発ってどんな感じ?というセッションをまずt_wada氏がやって、
踏まえたうえでペアプログラミングで実践して体感するという流れ。
ペアプロの相手を探すフェーズがさながら合コンかお見合いパーティといった風情。私は@yamashiro氏とペアを組みました。
@yamashiro氏はTDD慣れしているんだけど、僕のLet'sノートのキーボードと相性が悪かったのが残念。僕らのペアプロ姿はUst中継で放映されていましたよ。
セッション内容は@monjudoh氏がリアルタイムにblogに上げた奴とかたくさんあるので割愛。
成果物
テーマはプライオリティキューを作ろう、というもの。ぶっちゃけてしまえば、Java5からあるPriorityQueue
を自作しましょうというネタです。
作業のステップは以下のような感じ。記憶を元に書いているので怪しいです。実際にはもっと細かいステップもいろいろあります。Ust中継を見ていた人はわかったんじゃないかな。
- まず単なるキューを実装する方針にしよう
- ひとつのオブジェクトを入れて出すところまでをまず作る
- まずはテストを書いてJUnit(※自動テスト用ツール)を実行してバーをレッド(※自動テストが失敗した状態)にしないといけない
- キューに入れるテストコードをまず書く
- コンパイルエラーになるのでCtrl+1 (※エディタはEclipse3.4)を使って実装をCtrl+1で補完
- とりあえずJUnitのテストが通過してグリーンになる(pushは値を返さないので空実装でも関係ない)
- キューから取り出す部分のテストコードをまず書く
- コンパイルが通るように実装コードを補完して、JUnitを実行して失敗、バーが赤くなる
- Object型フィールド変数を作って格納してget()で返すという簡単な作り
- JUnitを実行して成功、バーがグリーンになる
- 次に複数個の入れれるようにしてちゃんとキューにしよう
- テストケースを書き足して、2個入れて2個出すようにする
- バーがレッドになる
- フィールドをList型に変更
- get()の実装は return this.data.remove(0); でいいよね(List#remove(int)を利用)
- バーがグリーンになる
- ジェネリクス対応させちゃいたいんでここで入れちゃおう
- コンストラクタに型変数を渡すようにテストコードを修正。コンパイルエラー
- コンストラクタに型変数を追加
- あー。このへんのリファクタリングで自動でやれないんだよなー。(2009年6月現在)
- 手動で実装を載せるしかない
- さて、プライオリティを渡せるようにしますか。コンストラクタで渡すでいいよね
- Comparatorを渡すようにして順序付けを外から指定できるのがいいよね
- コンストラクタにComparatorを渡して比較をするテストケースを書く
- コンパイルエラーになるので実装をCtrl+1で補完
- バーがレッド。さて、グリーンにするにはどうしようか?
- ちょっと小さい手ごろなステップが思い浮かばないので一気に実装しちゃう
- ThreeSetを使って実装しちゃえば速いんじゃない?
- 実装できた。テストを実行すると…あれ、レッド?
- あー。同じ値を入れたらTreeSetだとひとつにまとめられちゃうからか
- ダメだ、TreeSet方式は却下
- ちゃんとダメなケースをはじけたわけだからTDDがうまく機能したね
- Listにケツから突っ込んで、比較しながら手前に向かって追い越しをやる方法でどうだろう?
- push()時点でキューの中の状態を正しい状態に保つ感じ
- まずはTreeSet方式を差し戻す。Subversion使っておけばよかった orz (現地の環境がトラブル多そうだったので避けたのが敗因)
- ただのListにしよう
- 後ろから順に比較しないといけないから逆順にループしないと
- Collections#reverse()を使う?
- 挿入するときにループカウンタ必要になるから拡張for文つかうのはあきらめよう
- compare()の結果ってどっちが大きいときに正だっけ?w
- 出来上がり。なんか拡張するテーマ決めよう
- SQLのorder by みたいな感じで複数のキーを優先度設定できるようなのどう?
- よしそれで行こう…って時間切れか!
ソースコード
ソースをそのままで張ろうかとも思ったんだけど、コメントないなー orz 普段はjavadocとかコメントがりがり書く派なんだけど、なんかすっかり忘れてました。
上で時間切れになった後、「各自の荷物片付けてー」とか言われている最中に実装をやっちゃったので、実装完了版にコメントを追記したソースを載せます。
package queue;
import static org.junit.Assert.*;
import java.awt.Point;
import java.util.Comparator;
import org.junit.Test;
public class PriorityQueueTest
{
@Test
public void testname() throws Exception {
PriorityQueue<String> queue = new PriorityQueue<String>();
String expectedObj1 = new String();
String expectedObj2 = new String();
queue.push(expectedObj1);
queue.push(expectedObj2);
assertEquals(expectedObj1, queue.get());
assertEquals(expectedObj2, queue.get());
}
@Test
public void プライオリティを設定できる() throws Exception {
PriorityQueue<String> queue = new PriorityQueue<String>(new Comparator<String>(){
@Override
public int compare(String o1, String o2) {
return o2.compareTo(o1);
}});
String expectedObj1 = new String("b");
String expectedObj2 = new String("a");
queue.push(expectedObj1);
queue.push(expectedObj2);
assertEquals(expectedObj2, queue.get());
assertEquals(expectedObj1, queue.get());
}
@Test
public void 複数の優先度を設定できる() throws Exception {
PriorityQueue<Point> queue = new PriorityQueue<Point>(
new Comparator<Point>() {
@Override
public int compare(Point o1, Point o2) {
return o2.x - o1.x;
}},
new Comparator<Point>() {
@Override
public int compare(Point o1, Point o2) {
return o2.y - o2.y;
}});
Point p1 = new Point(1,4);
Point p2 = new Point(1,3);
queue.push(p1);
queue.push(p2);
assertEquals(p1, queue.get());
assertEquals(p2, queue.get());
Point p3 = new Point(2,2);
queue.push(p1);
queue.push(p3);
assertEquals(p1, queue.get());
assertEquals(p3, queue.get());
}
}
package queue;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
/**
* 2009.06.06 第二回チキチキ 日本ペアプログラミングの会java-ja支部会(仮)
* TDDでプライオリティキューの実装をした成れの果て。
* TDDで作ったものは複数優先度がやりかけだったので、お片づけ時間中にnagiseが完成させ、
* blog掲載時に読む人を考慮してnagiseが解説のコメントを足したもの。
*
* @author yamashiro, nagise
*
* @param <T> 格納するデータ型
*/
public class PriorityQueue<T> {
List<T> data = new ArrayList<T>();
List<Comparator<T>> comparators;
/** 自然順序付けによるプライオリティのキューを作成する */
public PriorityQueue() {
this.comparators = new ArrayList<Comparator<T>>();
this.comparators.add(new Comparator<T>() {
@SuppressWarnings("unchecked")
@Override
public int compare(T o1, T o2) {
Comparable c1 = (Comparable) o1;
return c1.compareTo(o2);
}
});
}
/**
* 指定したComparatorをプライオリティ判定に用いるキューを作成する
* @param comparator プライオリティ判定に用いるキュー
*/
public PriorityQueue(Comparator<T> comparator) {
this.comparators = new ArrayList<Comparator<T>>();
this.comparators.add(comparator);
}
/**
* 複数優先度を持つキューを作成する
* @param comparators 第一優先度判定用Comparator、第二優先度判定用Comparatorといった形で並べる
*/
public PriorityQueue(Comparator<T> ... comparators) {
this.comparators = new ArrayList<Comparator<T>>();
for (Comparator<T> c : comparators) {
this.comparators.add(c);
}
}
public T get() {
Iterator<T> iterator = data.iterator();
if (iterator.hasNext()) {
T next = iterator.next();
this.data.remove(next);
return next;
}
return null;
}
public void push(T obj) {
// 挿入時に末尾から前に向かって順に優先度判定をして、しかるべき位置に挿入する
int i = this.data.size();
// 第一優先度からループして、等しい値が現れたら次の優先度で比較
comparatorLoop: for (Comparator<T> c : this.comparators) {
// 末尾から前に向かって湯鮮度判定するから逆ループ
for (;i > 0; i--) {
T target = this.data.get(i -1);
// 現在の優先度が等しければ、次の優先度での比較に移行
if (c.compare(obj, target) == 0) {
continue comparatorLoop;
}
// 優先度を超えそうな境目を見つけたら、そこが安住の地
if (c.compare(obj, target) <= 0) {
break comparatorLoop;
}
}
}
this.data.add(i, obj);
}
}
2009年5月19日
Kanazawa.processではテスト駆動開発入門を読んで、テスト駆動開発を学びました。その本でのテスト駆動開発のサンプルとして挙がっていたテーマは複数通貨のMoneyを作るというものでした。
Dollarという米ドルを表現するオブジェクトを作り、Francというスイス・フランを表すオブジェクトを作り、そしてMoneyというオブジェクトに統合していくというリファクタリングの過程を経ています。
これをジェネリクスを使って設計したらどうなるでしょうか。
public abstract class Money<T extends Money<T>> {
public abstract T add(Money<?> m);
}
Moneyオブジェクトに演算用のメソッドadd()を定義します。引き算や掛け算など要求に合わせて各種用意するといいでしょう。
Money<T extends Money<T>>
という型変数の宣言方法は自己言及するジェネリクスの稿で
取り上げた手法です。add()の戻り型をTとしておくことで具象型自身の型を返させることができます。
これをDollarやFrancでオーバーライドして実装します。
public class Dollar extends Money<Dollar> {
@Override
public Dollar add(Money<?> m) {
// ...
}
}
こうすることで、Dollarのadd()はDollar型で返るわけです。
しかし、これだけだとDollarやFrancといった通貨単位ごとにadd()の実装を施さねばなりません。
protectedなファクトリーメソッドを用意して、オブジェクトの生成を具象型に委譲することで
スーパークラスであるMoney型で統一的にadd()を記述することができます。
public abstract class Money<T extends Money<T>> {
/** 為替レート */
Map<Class<? extends Money<?>>, Map<Class<? extends Money<?>>, Double>> rateMap;
/** 値 */
protected double value;
/** 加算メソッドの共通実装 */
public T add(Money<?> m) {
double rate = rateMap.get(this.getClass()).get(m.getClass());
return getInstance(this.value + m.value * rate);
}
/** 具象型の生成 */
protected abstract T getInstance(double value);
/** コンストラクタ */
protected Money(double value) {
this.value = value;
}
}
こうした手法で通貨単位ごとに型を作って何が嬉しいかと言えば、ドル建てである場所にスイス・フランの型が紛れ込んだ場合に
コンパイルエラーにすることができるという点です。
設計にはいろんな手法がありますし、それぞれにメリット、デメリットがあるので要求に合わせて柔軟に選べるようにしたいものですね。
Kanazawa.processというテスト駆動開発の勉強会が開催されたので参加してきました。話題に上がったネタの技術的な部分をいくつか補足しておきます。
副作用
この勉強会ではテキストとしてテスト駆動開発入門を用いました。
第一章で出てくる「副作用」という表現。あまりにも一般用語然としていますが、プログラミングの専門用語として「副作用」と言う場合、
状態の変更によって得られる結果が変わることを言います。
wikipediaにも
副作用 (プログラム)という項がありますね。変数の破壊的代入というような言い方もします。
関数型言語では関数が副作用を持たない、つまり、同じオブジェクトを引数に渡したとしても、オブジェクトの状態が変わったことによって
メソッドの呼び出し結果が異なる、といったことが起きません。そのために変数への代入は初期化のみが許されて、
再代入(破壊的代入)は許されないという特色があります。
その利点にあやかるべく、値を表すオブジェクト(バリューオブジェクト)には
Immutableパターン
というデザインパターンが適用されることが多くあります。
Javaの標準APIでは、Integerなどのプリミティブ型に対するラッパー型や、BigDecimal型などがこうした設計になっています。
これらは不変オブジェクトと表現されることもあります。
今のJavaには破壊的代入をコンパイラにチェックさせる機構がありませんが、JavaVM上で動作するScalaなど、
関数型の流れも汲み入れた新しい言語ではこれをサポートする機構が存在します。
Scalaの場合は変数宣言にvarとvalというキーワードで再代入可能な変数と再代入不可の変数を使い分けることができます。
IT Proの記事がわかりやすいでしょうか。
また、Java7での拡張に含まれる予定のJSR 305では
バグを根絶するための各種アノテーションの提案がされています。
マイコミの記事が詳しいですね。
この候補として@Immutableというものも候補に挙がっており、Java7ではコンパイラでチェックできるようになるかもしれません。
不変オブジェクトとGC
Javaの理論と実践: パフォーマンスの都市伝説
でも述べられているように、不変オブジェクトを用いることによって目に見えるようなパフォーマンスの劣化が起こることはありません。
90%のオブジェクトは作られてすぐに廃棄されると言われており、近年のGC(ガーベッジコレクション)は世代管理をして
こうしたライフサイクルの短いオブジェクトの回収を効率的に行えるように設計されています。
オブジェクトの再利用を行う機構を作ったとしても、不変オブジェクトの生成と破棄を行うスタイルと
目に見えるほどのパフォーマンスの改善を得ることはなかなかできません。
下手に頑張ったところで残るのは再利用や修正のしにくい醜い設計のプログラムだけです。
ソフトウェア品質の12の属性で取り上げたとおり、
パフォーマンスチューニングによる効率性の向上のためには、柔軟性、相互接続性、保守性、移植性、信頼性、堅牢性、試験性、使用性が犠牲になります。
そこまでの多大な犠牲と、パフォーマンスチューニングにかける時間、労力、そしてわずかばかりの効率性が釣り合うのかを冷静に判断してください。
大規模開発と静的解析
大規模特有の難しさと言うのは「人」が増えることによる開発の難しさなんですよね。
多くの人が関わって作業をすると言ったときに、メンバーの技術的ばらつきは大きくなる。
作業のやり方を統一することも難しいし、何より人間はヒューマンエラーを起こすのです。
これを漏れなく拾うことの難しさ、そしてフィードバックして個々人をレベルアップさせることの難しさがあります。
まぁ、ぶっちゃけて言えば手が回らない。なので、人海戦術はやめにして、機械化しましょう。
システム開発を機械化で高生産にするわけです。ビバ産業革命!
技術を持った人が注意深く作業する必要のある単純作業なんてのは、機械にやらせてしまいましょう。
そう、リファクタリング機能です。EclipseやNetBeansには高度で信頼できるリファクタリング機能が搭載されています。
静的な構文解析に裏打ちされた安定した機械的なリファクタリングを活用しましょう。
FindBugsプラグインなどの静的解析ツールによる機械的なコードレビューを活用しましょう。
命名規約やフォーマットのチェックなんてのはCheckStyleプラグインで機械的にチェックしてしまいましょう。
データ型の不一致をあぶり出す机上デバッグなんてやめて、ジェネリクスを使ってコンパイラでの静的型チェックをしましょう。
技術を持った人が注意深く、ヒューマンエラーと戦いながら退屈な単純作業をやらなきゃいけないなんて
そんな低生産なやり方はガーベッジコレクションに回収させてしまいましょう。
もっとも、頭の固いエライヒトがいつまでもそのやり方を参照しているとリークしていつまでも回収できないのですけどね。
2009年4月5日
4/4(土)に第十四回java-ja勉強会 - 第1回チキチキ 地方巡業withひがやすを飲み会in富山を開催しました。遠路はるばる富山までスピーカーしにきてくださった
ひがさん、
矢野さん、
米林さん、
ヨシオリさん、本当にありがとうございました。
凪瀬のジェネリクスの話
わんくま大阪でやったのと同じネタなんですが、時間を切り詰めてたので伝えたいところをうまく伝えられなかったかなぁと反省。
Javaのジェネリクスのややこしい部分は座学ですんなりわかるものじゃなくて、自分で四苦八苦してコード書いてみないと分からない
わけですが、苦労してジェネリクスを学んだ先にはより設計の幅が広がって幸せになれるから是非学ぼうという話をしようという
目論見だったのですけども、サンプルコードとかの説明とかがうまくやれなかったな、と。
テーマの取捨選択が難しいですね。変な切り落とし方しちゃったかなぁ…。
矢野さんのアニメーションの話
詳しいメモを取っていなかったのだけど、たぶんこのへんの奴。Timing Framework。
具体的にどれとかって話はきっと矢野さんがエントリを書いてくれるでしょう。
アニメーションの移動開始、終了間際の加速度の制御みたいな部分とか地味に面倒で難しいテーマ。書籍
Filthy Rich Clientsの第三部あたりの話題。
矢野さんが言うには「あの本にはアニメーションは難しいから俺の作ったフレームワークを使え的なことが書いてある」
とかなんとか。まぁ確かに。
自前で頑張ってチューニングを試みたらむしろ遅くなった、今のSwingはチューニングが凄いから
下手に頑張るよりそのまま何も考えずに描画した方が速い、みたいな話をしていて最近の画像処理にはついていけないやと思った次第。
自分はポリゴンとかの描画アルゴリズムとか勉強したことはあるけどパフォーマンスチューニングに凝ったことがないしなぁ。
あちこちで聞くけども本当に近年のSwingは速いらしいよ。
ひがさんのAOPの話
今回はひがやすを飲み会(東京都、仙台市、札幌市に続く第4回目。
参考記事)
も兼ねているわけで、真打登場といった感じ。
Slim3あたりのAOPのえらくマニアックな話をして頂きました。自分は大喜びで食いついていたけど、
他の参加者の人は大丈夫だったかしら。
AOPでのパフォーマンス向上のためのいろいろな工夫を聞いて感心することしきり。
実行時に通るAOPのための仕掛けをいかに薄くするかという話で、
実装方法論の部分で話題に上がってたのは確かClassLoader#defineClass()
あたりでロード時に書き換える話とか、Javassist
で継承クラスを作るとかの話かな。自分で実装してみたことないので間違ってるかもしれません。
自分はClassLoader#defineClass()でクラスロード時にウィービングする手法と、
コンパイル時でのウィービングする手法ぐらいしか理解していなかったのでこのテーマの深遠さが覗けて興奮しましたね。
よねさんの1つめの話
JavaとAIRの間で通信したりする話。あとはJavaFXとかJavaScriptとかもあって相互に通信しまくり。
こういう部分で何が可能なのかを知っておくことはトータルのシステム構成を考える上での重要な前提知識だと思うので
非常に興味深く聞いていました。
そうそう、よねさんのAppletは起動が超速かったデスヨー(棒読み
ヨシオリさんのTDDの話
テスト駆動開発 (test-driven development; TDD)の話。テスト手法とかはコレという正解が確立されていない感じで
みんながいろいろと模索しているようなテーマだから議論が盛り上がる、盛り上がる。ust中継してたので
和田さんのツッコミとかもあって面白かった。
僕もテスト駆動のテストって品質を担保するテストだと思っていたクチなので、
そういうテストじゃないんだという話に目から鱗。
「テスト駆動開発は宗教である」「コード=神」とか名言が飛び交う面白いセッションでした。
今日も誰かがモニタに向かって邪神を生み出そうとしてたりするのかな。
よねさんの2つめの話
T2とかの話。今日は相方の片山さんはいなかったけども
SeasarConference2009Whiteのときの
の話。僕はSeasarConのときに聞いてたのでテーマを復習した感じでしたね。
今回の失敗点
ust中継をやっていたのですが、Webカメラで写すとプロジェクタの文字が白飛びして見えない!
その上、マイクが中継機になってたヨシオリさんのノートPCのマイクになってて音が凄く拾いにくい!
ustでの中継だと空間的な場を伝えるには便利なんだけど、勉強会とかでの資料とかは解像度的に全然読めないのが常。
この辺どうにかならないんですかね。次会には機材としてマイクを準備しておきたいところです。
2009年3月22日
春分の日に大阪勉強会#28でセッションやってきました。
今回はジェネリクスということで難度の高いネタなんですが、狙いとしてはジェネリクスを使えるようになった先の世界はこんな感じだよ、というのが伝えられたらいいなということで、細かいところはおいておいて設計とかでこんな感じで役立つよという話をメインにしていました。後半部分ですね。
僕としては自重なしにマニアックなネタをしゃべったんですっきり。セッション聞いてもやもやした人は勉強してすっきりさせてください(鬼
ジェネリックメソッド
ジェネリックメソッドについては意図的にスルーしていたのですが、知りたいと言う人のためにさらっと説明しておくと、型変数がメソッドになっただけです。型変数にまつわる制約などはジェネリッククラスの場合の型変数と変わりませんね。
Javaのジェネリックメソッドで特記するべき点は型推論が効くと言う点なのですが、これがまたえらいややこしい話題なのでこれまたセッションではちょっと説明しきれない代物ですね。もっとも私もジェネリクスの型推論については語れるほど理解できていませんし。
キャストのシンタックスシュガー
ジェネリクスを「キャストのシンタックスシュガー」と言った人がいたと記憶していますが、この表現では大事なことを見落としています。確かにキャストの発生する場所全てで漏れなく確実にキャストを入れれるのであれば、ジェネリクスを使った場合と同じ動きをするプログラムになるのですが、「漏れなく確実に」がとても難しいのですね。
このキャストという横断的関心事、つまるところアスペクト指向的なテーマをコンパイル時の全走査で解決しているというのがJavaのジェネリクスです。大事なのは「漏れなく確実に」という部分。「キャストのシンタックスシュガー」という表現ではこの一番肝心なところが伝わらないので表現としてはイマイチではないでしょうか。
ソースコードとか
サンプルのソースコードとかはやっつけで作ってたんで綺麗にまとめてWeb化したいところですね。C#版とかScala版とかを手伝ってくれる人がいたら歓迎します。
ジェネリクス関連エントリ
過去に書いたジェネリクス関連エントリがありますので参考にしてください。
2009年3月2日
今日はまったバグ。
Map<Long, String> map = new HashMap<Long, String>();
map.put(1L, "1");
System.out.println(map.get(1));
System.out.println(map.get(1L));
キーに1 (ボクシング変換でIntegerになる)を渡した場合と1Lを渡した場合で挙動が異なるというオチ。Map.get()の引数がObjectなので両方受け付けちゃうんですね。
2009年2月23日
最近OFF充な凪瀬です。先日はFlex3勉強会第60回@北陸に参加してきました。
地方での勉強会は開催数が少ないですね。居住地域近辺の勉強会にはできるだけ参加したいと考えています。
とりあえず、今後のスケジュールとしては
といったところですね。
わんくま同盟 大阪勉強会 #28
今回はジェネリクスを使った設計の話をしたいと考えています。コードサンプルはJavaメインですが、C#版もできるだけ書くつもりです。
コレクションぐらいでしかジェネリクス使えてないやという人はぜひ。
わんくま同盟の勉強会ではすっかり恒例になっていますがustreamによるネット中継もありますので現地にこれない方も見てくださいね。
java-ja 第十四回 第1回チキチキ 地方巡業withひがやすを飲み会in富山
わんくま同盟 富山勉強会 #01に続く勉強会地方誘致シリーズです。
スピーカーは、
ひがやすを氏、
矢野勉氏、
米林正明氏と豪華です。
私も僭越ながらジェネリクスの話をば(使い回しというツッコミはなしの方向で)
参加登録はこちらでお願いします。
java-ja温泉
温泉に泊まってコードをひたすら書く企画。私も参加します。
どうも参加費が…という理由で躊躇している若きプログラマに援助をするのが流行っている
(矢野氏、
太一氏、
文殊堂氏)
ので、私も北陸近辺から参加したい人のために往復交通費+宿泊費を援助したいと思います。
応募枠は2名まで。応募条件は北陸近辺に在住の学生ないし25歳ぐらいまでの若いプログラマでやる気のある人。
代わりに北陸地域の勉強会開催のときのスタッフをやってもらいます。
左上の「連絡をする」のフォームから応募してください。
応募の際は住所、氏名、電話番号を記入の上、プログラムに対する熱い思いを伝えてください。
選考は独断と偏見でやる気のありそうな人を選びます。
2009年2月3日
システム開発において「品質の向上」という標語がしばしば掲げられますが、
「品質の属性」については無頓着なケースが多いのではないでしょうか。
ひとくちに品質といっても多様な属性があります。
顧客と品質の話で揉めたことはありませんか?
品質には多様な属性があり、単一の軸で良しあしを決められないという側面があります。
そのため、単に「品質」と言ってしまうと認識に齟齬が生じるのです。
Karl E. Wiegers氏が著書
「ソフトウェア要求」
で挙げた、すべてのプロジェクトが検討すべき12の属性は以下のとおりです。
| 可用性 | availability |
動作可能時間の指標。システム故障までの平均時間MTTF(Mean Time To Failure)を
平均修復時間MTTR(Mean Time To Repair)とMTTFの合計で割った値。稼働率とも呼ばれる。 |
| 効率性 | efficiency |
同じ処理性能を出すのにどのぐらいのハードウェアのスペックが必要か。 |
| 柔軟性 | flexibility |
機能拡張への柔軟性。順次拡張していくアジャイル開発を可能にするためには
ある程度の柔軟性を備えた設計にする必要がある。 |
| 完全性 | integrity |
データが正確で完全であること。改ざんなどされておらず、正しく動作すること。
情報セキュリティの目標事項のひとつとして挙げられる。 |
| 相互接続性 | interoperability |
他システムとのデータ連携の容易さ。 |
| 保守性 | maintainability |
バグの修正や仕様変更の容易性。 |
| 移植性 | portability |
ある稼働環境から、別の稼働環境へ移行させるために要する工数など。
JavaなどにみられるVM方式など高レイヤでの稼働システムは移植性が高いとも言える。 |
| 信頼性 | reliability |
特定の期間、故障なしでソフトウェアを実行できる可能性。 |
| 再利用性 | reusability |
プログラムコードの再利用性。オブジェクト指向などによるモジュール化によって高めることができる。
もっとも、日本だとソースコードが納品先の所有になる契約となることが多くライセンスの問題で再利用性が低い。 |
| 堅牢性 | robustness |
耐障害性。異常データなどの入力に対する耐性。 |
| 試験性 | testability |
テストのしやすさ。 |
| 使用性 | usability |
ユーザビリティ。使いやすさ。 |
これらは多くのプロジェクトに共通する属性ですが、もちろんこれで全てと言うわけではなく
特定ジャンルではさらに追加の品質属性を考慮する必要が出てきます。同じ本から引用すると
「組み込みシステムに重要な品質属性としてはさらに安全性、導入容易性、サービス能力があります。
スケータビリティは、インターネットアプリケーションに重要なもう一つの属性です。」
ということになるでしょう。
これらの品質属性は、すべてを同時に上げることができません。トレードオフが発生するのです。
品質属性のトレードオフ
これら品質の属性は、相互に作用し合っています。
ある属性を高めれば他の属性も高まる、あるいは低くなるということがおきます。
以下の表は左側の属性を上げた場合に上側のどの属性が高く、あるいは低くなるかを表しています。
(追記:引用元「ソフトウェア要求」228ページ)
|
可 用 性 |
効 率 性 |
柔 軟 性 |
完 全 性 |
相 互 接 続 性 |
保 守 性 |
移 植 性 |
信 頼 性 |
再 利 用 性 |
堅 牢 性 |
試 験 性 |
使 用 性 |
| 可用性 | | | | | | | | + | | + | | |
| 効率性 | | | - | | - | - | - | - | | - | - | - |
| 柔軟性 | | - | | - | | + | + | + | | | + | |
| 完全性 | | - | | | - | | | | - | | - | - |
| 相互接続性 | | - | + | - | | | + | | | | | |
| 保守性 | + | - | + | | | | | + | | | + | |
| 移植性 | | - | + | | + | - | | | + | | + | - |
| 信頼性 | + | - | + | | | + | | | | + | + | + |
| 再利用性 | | - | + | - | + | + | + | - | | | + | |
| 堅牢性 | + | - | | | | | | + | | | | + |
| 試験性 | + | - | + | | | + | | + | | | | + |
| 使用性 | | - | | | | | | | | + | - | |
まずは品質には属性があることを顧客に伝えましょう。
そして属性にトレードオフが発生することを理解してもらいましょう。
ソフトウェア工学と品質属性
ソフトウェア工学の数々の成果はこれらの品質属性にどう影響を与えたのでしょうか?
構造化プログラミング
試験性 - 適切なモジュール分割は試験性を高めます。より高めるにはステートレスな機能を意識的に分割することです。
ステートレスな関数は引数と戻り値によって容易にテストでき、自動テストなどによる自動化も行いやすくなります。
再利用性 - 構造化によりある程度、再利用性が高まりました。
契約に基づくプログラミング
完全性・堅牢性 - モジュール間での「契約に基づくプログラミング」のほつれに対して
適切にエラー処理を施すことで完全性・堅牢性を高めることができます。
オブジェクト指向
柔軟性・保守性 - オブジェクト指向によって動的なフローチャートになるプログラムを容易に制御できるようになりました(ポリモフィズム)。
これを活用することで、既存箇所に手を入れることなく追加のクラスを作成するだけでの拡張が可能になります。
再利用性 - 構造化プログラミングよりさらに再利用性を高めることができます。
ポリモフィズムを活用したプログラミングは再利用性の点でも優れています。
VM技術、仮想化技術
移植性 - Javaの標榜する"Write once, run anywhere"は究極の移植性と言えます。
現在のJava開発は主にWindows機上で行われており、そのままUnix系のOSで稼働する本番機で動作させる
ようなことが行われています。携帯電話におけるJavaMEの採用もこの点を活用してのことです。
O/Rマッピング
移植性 - O/RマッピングもDBを特定製品に縛らないという意味で移植性を高める効果があります。
DIコンテナ
柔軟性・保守性 - DIコンテナによる設計は柔軟性・保守性を高めます。
試験性 - DIコンテナによる疎結合は試験性をより高めます。DBなどを伴うシステムですら、
スタブによって自動テスト化することが容易になりました。
ここでは目立つ特徴をピックアップしましたが、もちろん品質属性への影響はここに挙げただけにはとどまりません。
各種パラダイムを眺める際に、品質属性への影響と言う点でみつめるとまた違ったものが見えてくるかもしれません。