トップ «前の日記(2004-03-26) 最新 次の日記(2004-03-28)» 編集

日々の破片

著作一覧

2004-03-27

_ J2EE プロジェクトの問題

こんな資料があったとは(JDCSDCの会員登録が多分必要)。

問題 8: 開発工程が古い

プロジェクトフェーズ:

開発

影響のあるプロジェクトフェーズ:

安定化、本稼動

影響のあるシステム要素:

保守、コーディング品質

徴候:

プロジェクト計画が、直下型 (Waterfall) 方式をとっている。つまり、システム を最初から設計し、コーディングなどに大量の時間を費やしている。

構築工程が存在しないため、構築品質が低い

構築を行っている間は何も作業できず、構築の遅れが開発の遅れにつながっている

コンポーネントを統合する前に十分にテストしていない。つまり、2 つのコンポーネントを安定しないうちに統合し、そのスタックトレースを検証している

解決策:

優れたソフトウェア技術を採り入れる必要があります。XP についてはすでに言及しましたが、XP の詳細については最後の「参照情報」から関連サイトを参照してください。

注:

単体テストを行うときは JUnit、構築するときは Ant を使用することをお勧めします。JUnit および Ant は、XP 方法論を支援する無料のツールです。JUnitおよび Ant の詳細については、「参照情報」を参照してください

サンの公式な技術情報で、アンチパターンになってるよ>ウォーターフォール

_ ちょっと読解

ツッコミに書いたことは別として、あの文書の内容がどこまで有効かの議論とは別に、読解しておく。

問題は、「徴候」のパートで、これは4つの異なる徴候を示している。

1. 直下型の問題として、最初から設計し、コーディングに時間をかける。

訳が変なんじゃないかと思うが、原文を探す気にはならないので、かってに逆翻訳してから再翻訳して、最初に設計してからコーディングするので時間がかかるというふうに読み取った。

解決策:XP

2. 構築工程がない

そんなバカな。ということで、おそらくここで想定している状況は、どっかにクラスツリーが非管理レポジトリとして用意してあって、メンバーが別々にjavacした出力をコピーするというようなことを指しているのだと思う。

解決策:仕事やめろと思うが、ここではantくらい使えということ。

追記:構築工程ではなく、これは構成管理のことではないかな?

3. 構築に時間がかかる

2.はさすがにバカげていると気付いたので、ソースのツリーを作り、誰かがソースをコピーしてから、全体をコンパイルする。だから、誰かがコンパイル中はほかのことが(テスト実行を含み)できない

解決策:仕事やめろと思うが、ここではantくらい使えということ。

4. ユニットテストがバータリー

解決策:JUnit使って順に検証し、新たな実装の追加が、元の実装の破壊を生むこと無いように確認してから、統合テストのフェーズに移れ

2と3はさすがに考えにくいが、僕には、1.と4.は有意な提言だと思う。

ちなみに、500人のプロジェクトでXPは使えるか、について、使えるとこないだ気付いた。

最初の時点できちんとアーキテクチャを構築すれば、500人分の作業といっても50の異なるサブドメインに分割可能なはずだ。各サブドメインは別にWebサービスで結合する必要はないが、SOAの考えを流用してきちんとブラックボックス化したサービスとして相互に結合可能なアーキテクチャだ。

であれば、10人1プロジェクトとなるのだから、そこでXPすれば良い。

500人のうち、優秀なのが20人(そのくらいはいるだろう)いれば、その20人から1番出来の良いのを1〜2人、喧嘩になるようなら3人の合議制で、アーキテクチャを決めさせる。まあ、出来が良いんだから、スケジュールは守るだろう。次にその20人を重要度の高い20のプロジェクトに配分すれば、50のサブプロジェクトのうち2/5は確実にまかなえるはずだ。実際には500人もいれば優秀なのは100人以上はいるはずだから、その配置をきちんとやり、週1ペースでサブプロジェクトのリーダーによる相互の進捗ミーティングを行いサブプロジェクトの重要度に応じたメンバー移動などを行っていけば良い。

間違ってるかな?

_ 真似るということ

そういや、子供を見てたり、自分のことを振り返ったり、その他いろいろな見聞から考えると、最初はマネするもんだな。

マンガを見ればマンガを書き、病気になれば看護婦や医者になりたがり、小説を読めば小説を書く。

子供は金を稼ぐためのシノギとして考えないから素直なもんだ。自分がそれによって何か、心が動かされれば、同じように、心を動かすためのものを自分の手で作りたくなる。

プログラマがシノギのための学習項目であるならば、まず読むまず観るなんて面倒なことがなおざりになるのも、効率ってやつに焦点を当てれば無理もなかろう。

しかし、その無理のなさが、世に腐れプログラムが垂れ流される元凶なんだとしたら、それは良くない。

「仕事は趣味ではない」

というのは、フツーの文脈では、「遊びじゃないんだから真剣にやれ」という意味であるとか「遊びじゃないんだから規約を守れ」というどちらかといえば積極的にプラス方向へモノゴトを進めるために使うべきものなのだが、ことプログラムに関して言えば、「手を抜け」であるとか「後先を考えちゃおしまいよ」とか「目先の利益優先」とか「形式さえ合っていれば内容は問わない」とマイナス方向へ進めるために利用されているのではなかろうか。

っていうか、「形式」が2種類の意味を持ってるのがまず問題だろう。ドキュメントの整形式ってのが、数合わせだったりするわけだし、コーディングルールが目先の見易さだったりするようなことだ。

かくして、やはり「文芸的」と訳すのが正解なのだ(プログラミングは理系作業ではなく、文系作業。レトリック重要)とここでひとまず結論をおいてみる。

_ レトリック重視プログラミング

というわけで、そのプログラムが非常に無意味なバータリーなためにあると感じたら、正しいプログラムは、
/**
 * とりあえず、データベースを指定されたキーで読み込んで中に入れて返す。
 * 各フィールドの並び順は運任せ。
 */
public class A {
 public static DataSource dataSource;
 public int a1; // バータリーなんだから命名もいい加減。
 public int a2;
  ...
 public int a259;
 /**
  * 指定されたキーで読み取った内容を格納したインスタンスを生成。
  * 事前条件: {@link #dataSource}に有効なデータソースを設定しておく。
  * @param key SQLを指定する
  * @throws IllegalArgumentException エラーの時に投げる。エラーになるのはいつだって引数が変だからである。
  */
 public A(String key) {
   assert dataSource != null;
 
   Connection connection = null;
   PreparedStatement preparedStatement = null;
   ResultSet resultSet = null;
   try {
     connection = dataSource.getConnection();
     preparedStatement = conneciton.prepareStatement(key); // インジェクションOK!
     resultSet = prepraedStatemet.executeQuery();
     resultSet.next();
     for (int i = 1; i < 259; i++) {
         String fieldName = "a" + i;
         Filed field = getClass().getDeclardField(filedName);
         field.setInt(this, resultSet.getInt(i);
     }
   } catch (Exception e) {
     throw new IllegalArgumentException(e);
   } finally {
     close(resultSet);
     close(prepraedStatement);
     close(connection);
   }
 }
 /**
  * なんでもクローズする。
  * @param object クローズしたいオブジェクト。nullの場合は既にクローズ済みとみなし、何も行わない。
  */
 public void close(Object object) {
   if (object == null) {
       return;
   }
   try {
     Method method = object.getClass().getMethod("close");
     method.invoke(object, null);
   } catch (Exception e) {
   }
 }
 /**
  * a1を返す。いちいちゲッタメソッドを呼ぶと面倒だから、直接
  * {@link #a1}を操作すること。
  * @return ない
  * @throws IllegalStateException このメソッドは呼ぶためにあるわけではない
  * @deprecated
  */
 public void getA1(int x) { throws IllegalStateException("呼ぶな"); }
}
 
とか。 コードによって表現されている内容。
  • フィールドは配列ではなく、きわめて抽象的なフィールド名によって示されているのは、抽象化こそ人間精神の発露であるという自己表現。
  • なぜか、intで決定となっているのは、すべての事象は数値的に表現できる(しかし32ビット以内)という明確な意思の表現。
  • SQLがなんであろうが受け止めてしまうのは柔軟な精神の表現。
  • どんなエラーであっても引数が悪いことにしている(データベースが落ちていた時に呼び出したやつ=引数を与えたやつが悪いという含意も)、悪意に満ちた眼差し。
  • 意味無くリフレクションを使用してコード量を削減して省力化をアピール。
  • Javadocは嫌味っぽくそれなりに記述してあるのは、底意地の悪さと嫌々やっていることの意思表示。
など。
それから見逃してはいけないのは、クラス名のAというのが、どんなSQLでも受け付ける=どのようなロウのインスタンス化も引き受けるという点から、AnonymousやAliasのA、すなわち匿名のAという極めて意味付けされた名前だという点。当然、フィールド名もその文脈において(A社の従業員a1, a2, ...)という極めて正しい命名則に則っていると言う点。ここを見逃すと重要な意味が理解できなくなる。
すなわちコメントの記述(// バータリーなんだから命名もいい加減。)は、韜晦であって事実ではないという点。わざわざコードに韜晦的なコメントを入れると言うのは、バータリーな作業なためウンザリしているという心理状態を反映している。すなわち、「非常に無意味でバータリーな」作業だと感づいているということを示している。
これだけの意味を読み取れましたか?
本日のツッコミ(全7件) [ツッコミを入れる]
_ WR (2004-03-27 01:07)

Waterfallがまずいのではなく、極端な工期圧縮によりコーディング→単体テスト→結合テストの流れのなかで単体テストが省かれてしまい、結果としてデスマーチになっているということかと思います。おそらくTestDrivenDevelopment的な小規模で機敏な構築&検証の実現が求められているのでしょう。って、はずしてます?<br>余談:MSのDOAセミナー最終回行かれました?

_ arton (2004-03-27 01:29)

いや、行けませんでした。残念>DOAセミナー<br>多分、指摘されている1番の問題は「最初から設計し」ではないかと思います。実際問題として、大雑把な部分まではあらかじめモデル化できますが、実装詳細でどのようなクラスが必要になるかはわからないと思います。わからないからこそのTDDです。もちろん、実装するのと同程度の検討を加えれば可能ですが、それは無駄だという発想が根底にあるはずです。<br> 僕は(「も」だとは思うけど)、開発工程の中抜きが必要だと思います。要件定義―機能定義の次は実装であるべきだということです。すなわち詳細の設計は不要です。大きな設計(アーキテクチャと必要に応じたフレームワーク)はあらかじめ決定可能だとは思いますが。<br> ただし、スキルセットの問題、ドメイン分析をどこまで委譲できるかといった(技術的なものだけではなく政治的なものも含む)判断、が必要ですし、それをどこまでプロジェクトメンバーに与えることが可能かといった点(教育とかも。ペアプログラミングは1つの解決策でしょうが完全ではないし、土地が狭い=机が狭い日本の状況も考えるべきでしょう)まで考えなければならないので、事は単純では無いとは思います。したがって、すべてのプロジェクトでXPを採用するわけにはいかないかも知れないし、必要であれば、構造化設計をして1インスタンスシングルスレッドというか全部staticの最低プロジェクトもありだとは思います(が、そんなものはごめんですけど)。<br> 設計からユニットテスト完了までのフェーズについては、10人のプロジェクトで3人が設計し6人が設計を待って実装するのではなく、同時に9人が設計/実装を行うというのが、中抜きの理想です。計算通りなら、ボトルネックが生まれません。

_ arton (2004-03-27 01:30)

長い……本文に書くべきだった。

_ WR (2004-03-27 01:48)

>要件定義―機能定義の次は実装であるべき<br>DOAセミナーの影響をカナリ受けているので、差し引いて考えてほしいのですが(笑)データモデルがキチンと定義でき、アーキテクチャが決まっていれば(J2EE+サポートするフレームワーク or .NET)いきなり実装はOKだと思います。<br>> ただし、スキルセットの問題、ドメイン分析をどこまで委譲 ・・・<br>すみませんが、ここら辺は、ちょっとパスさせてください。難しい・・<br>> ボトルネックが生まれません。<br>TDDなら、結合テストでのバグ検出待ちが出にくい(ちょっといいすぎ?)ので、さらにスループットを増すことがみこめると思います。(http://member.nifty.ne.jp/yamazaki/doc/code_design/vol11.htmlのイメージです)<br><br>徒然気味のツッコミですみません。

_ arton (2004-03-27 01:56)

>TDDなら<br>同意します。<br>>DOA<br>プラットフォームの移行プロジェクトといった場合、データは既存のものの再利用となるので、まさにそんな感じですね。<br> まあ、最初のツッコミのは期間が最初から短いという前提なので、どうあがいてもだめではないかと。

_ uno (2004-03-28 05:58)

ソース先頭の「とりあえず、」が強烈。

_ (2004-03-29 12:56)

ひとふで書きでコーディングすることを目指すことないのにね。> 最初に設計


2003|06|07|08|09|10|11|12|
2004|01|02|03|04|05|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|09|10|11|12|
2007|01|02|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|04|05|06|07|08|09|10|11|12|
2009|01|02|03|04|05|06|07|08|09|10|11|12|
2010|01|02|03|04|05|06|07|08|09|10|11|12|
2011|01|02|03|04|05|06|07|08|09|10|11|12|
2012|01|02|03|04|05|06|07|08|09|10|11|12|
2013|01|02|03|04|05|06|07|08|09|10|11|12|
2014|01|02|03|04|05|06|07|08|09|10|11|12|
2015|01|02|03|04|05|06|07|08|09|10|11|12|
2016|01|02|03|04|05|06|07|08|09|10|11|12|
2017|01|02|03|04|05|06|07|08|09|10|11|12|
2018|01|02|03|04|05|06|07|08|09|10|11|12|
2019|01|02|03|04|05|06|07|08|09|10|11|12|
2020|01|02|03|04|05|06|07|08|09|10|11|12|
2021|01|02|03|04|05|06|07|08|09|10|11|12|
2022|01|02|03|04|05|06|07|08|09|10|11|12|
2023|01|02|03|04|05|06|07|08|09|10|11|12|
2024|01|02|03|

ジェズイットを見習え