« 2008年9月 | トップページ | 2008年11月 »

2008年10月29日 (水)

「変数のスコープは狭いほど良い」

「goto文禁止令」の類の話かと。

中途半端に優秀なプログラマが「正しいプログラミングテクニック」だと妄信しがちな3つポイント

比較的簡単なので1番目の「変数のスコープ」だけ。

その変数はどのくらい「変数」なのか?

「変数」の最大のポイントは、「代入」にあると思います。

public class Test {

  public static void main(String[] args) {
    if (args.length > 0) {
      String x = args[0];
      new Foo().bar(x);
    }
  }

}

上のソースで変数 x (つまり args[0]) って、どのくらい代入操作されますかね?

マルチスレッドなのか?

はてなブックマーク コメント よりお題をいただきました。

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class TestServlet
  extends javax.servlet.http.HttpServlet
  implements javax.servlet.Servlet {

  static final long serialVersionUID = 1L;
  static HttpServletRequest request_;

  public TestServlet() {
    super();
  }

  protected void doGet(
    HttpServletRequest request,
    HttpServletResponse response)
    throws ServletException, IOException {

    request_ = request;
    try {
      Thread.sleep(5000);
    } catch (InterruptedException e) {
    }
    response.getWriter().println(request_.getParameter("p0"));
  }
}

2つのブラウザから、以下のリクエストを連続して投げること(5秒以内)。

GET /ServletTest/TestServlet?p0=A
GET /ServletTest/TestServlet?p0=B

一時期、この手のバグが話題になっていましたね。

とはいえ、 Servlet のユーザから見ると、 HttpServletRequest が「定数」に見えるのも確かです。 Servlet コンテナから見ると、「変数」なわけですけどね。

これは Servlet の仕様でしょうね。もともと、「軽量さ」が Servlet の売りであったことを思えば、意図的なデザインでしょう。

そのコードはどの程度「再利用」されるか?

使い捨てにするコードなら、別に気にしなくて良いですよね。広汎に使われるとなると、「想定外」の使われ方をする可能性が増えますので、より「防衛的に」プログラミングする必要があるかと。

| | コメント (0) | トラックバック (0)

2008年10月19日 (日)

固定小数点演算

基数変換誤差が問題となるのは、固定小数点だからなんですよね。浮動小数点演算では、計算値に対する精度が十分に大きければ、基数変換誤差を気にする必要はないわけでして。そう考えると、固定小数点と10進数演算は、常にセットで考えるものなのでしょう。2進固定小数点を見かけない理由でもあるわけですね。

さて、 Java の 固定小数点数 java.math.BigDecimal ではソースコードはこんな感じになります。

import java.math.*;

public class BigDecimalTest {

  public static void main(String[] args) {
    float fa = 0.4f;
    float fb = 0.3f;
    float fc = 0.1f;

    System.out.println(fa - fb - fc);

    final BigDecimal xa = new BigDecimal("0.4");
    final BigDecimal xb = new BigDecimal("0.3");
    final BigDecimal xc = new BigDecimal("0.1");
    final BigDecimal xd = xa.subtract(xb).subtract(xc);

    System.out.println(xd);
  }

}

実行結果:

-7.4505806E-9
0.0

確かに、うざったい感じですね。

精度、スケール、丸めの方向を java.math.MathContext 、および java.math.RoundingMode で細かく指定できるのは、良いと思いますけど。

忘れていましたが、 Microsoft .NET では、組み込み型で固定小数点がサポートされています。

ソースコードは以下のようになります。

using System;

namespace DecimalTest
{
    class Program
    {
        static void Main(string[] args)
        {
          float fa = 0.4f;
          float fb = 0.3f;
          float fc = 0.1f;

          Console.WriteLine(fa - fb - fc);

          decimal xa = 0.4m;
          decimal xb = 0.3m;
          decimal xc = 0.1m;

          Console.WriteLine(xa - xb - xc);

        }
    }
}

実行結果:

-7.450581E-09
0.0

精度は 128 ビットで固定されているようです。スケールを明示的に指定する方法はなさそうですね。丸めの方向も指定できなさそう。

組み込み型なのは良いのですが。 Java と良い点・悪い点が、ちょうど反対になっているのが面白いといいますか。

しかし、この .NET Framework マニュアルの説明はわけわからないですね。どこかでも話題になっていましたが。

Decimal 値型は、多数の有効な整数桁と小数桁を必要とし、丸め誤差を使用しない財務計算に適しています。

10 進数は、符号、値の各桁の範囲が 0 から 9 までの数値、数値の整数部と小数部を分ける浮動小数点の位置を示すスケール ファクタで構成される浮動小数点値です。

Decimal 構造体 (System)

「整数部と小数部を分ける ... スケール ファクタ」があるわけですから、固定小数点と呼ぶべきなのではないでしょうか。浮動小数点とは呼ばないのではないかと思うのですけど。

A decimal number is a floating-point value that consists of a sign, a numeric value where each digit in the value ranges from 0 to 9, and a scaling factor that indicates the position of a floating decimal point that separates the integral and fractional parts of the numeric value.

Decimal Structure (System)

小数点の桁位置を変えられることを、 ”floating-point value”, "floating decimal point" と言っているのですかね。かえって判りにくいような。

| | コメント (0) | トラックバック (0)

2008年10月17日 (金)

FORTRAN と COBOL の代替言語はないかも

以下の記事を読んでの感想。

「COBOLは現役バリバリだ。"COBOLは化石"などと口にするのはITとエンタープライズシステムが何たるかをわかっていない証拠」

「30年システムに携わっているが,COBOLは規格として長期間安定し,ビジネスロジックの書きやすさにおいては右に出る言語はない」

「COBOLは現役バリバリ」,東京海上日動がシステム全面再構築でCOBOLを選んだワケ (ITPro)

COBOL を使う最大の理由といえば、10進固定小数点演算が言語組み込みでサポートされている点がまず思い浮かびました。

事務処理用及び管理分野用とされるCOBOLにおいては会計・経理処理などのように通貨を対象とした正確な数値計算が特に要求されるため、数値に対する10進数から2進数への基数変換時に計算誤差の発生しない2進化10進数による数値型(固定小数点数)を用いることができる。

COBOL (Wikipedia)

会計計算では、計算規則は、人間が手で計算することを前提に作られているはずですから、10進固定小数点で計算しなければ、計算結果は「正しく」ならないでしょうね。保険関係の計算を行なうのに COBOL を使うのは、合理的な選択に思えます。プログラミング言語の組み込み型に、10進固定小数点がなければ、プログラムを書くのは、かなりつらくなるでしょう。

他方、浮動小数点演算はどうかといえば、未だ FORTRAN がデファクト・スタンダードであったりします。

十数年前、C言語 が普及し始めた当時、C言語の浮動小数点演算機能について、確か以下のようなことが言われていたと思います。

  1. 式を評価する際、浮動小数点数が double にキャストされる仕様がふざけている
  2. 標準ライブラリの数学関数の引数がすべて double になっているのがふざけている
  3. 複素数型がないのは馬鹿にしている

C言語 は、 FORTRAN より退化している、という評価がもっぱらであったかと思います。

以下の数を扱える。

  • 整数(範囲は機種依存、4バイトであればその範囲)
  • 単精度実数(整数部+小数部、指数表示可能、精度は機種依存)
  • 倍精度実数(単精度の倍の精度を持つ)
  • 複素数(単精度または倍精度の実数の組み合わせ。2つの数字を()でくくる)

    ......

    組込み関数

    組込み関数は、同じ機能でも引数の型と関数の型によって名前が異なる。関数名の先頭がI〜Nのものが整数型、Dが倍精度実数型、Cが複素数型、それ以外が実数型である。

    FORTRAN (Wikipedia)

なお、 C言語 浮動小数点で批判が多かった、 「式がすべて double になる」は、その後改善されています。

ここで注意すべきは、式の中の float が自動的に double に変換されるのではないことである。これは C のもとの定義に比べて代わった点の一つになっている。しかし一般に <math.h> にあるような数学関数では倍精度が使われよう。 float を使う主な理由は、大きな配列の記憶容量を減らすことであり、またそうあることではないが、倍精度の算術がとくに高くつくような計算機で計算時間を短くする点にある。

B.W.カーニハン/D.M.リッチー著, 石田晴久訳, 『プログラミング言語C 第2版』, 共立出版, 1989, p.55

単精度を使う理由が効率の問題でしかない、というのは少し乱暴な話ですね。

Java言語では、このC言語の仕様を、ほぼそのまま受け継いでいます。

Conversions and Promotions (Java Language Specification Third Edition)

Math (Java 2 Platform SE 5.0)

で、やっぱり批判されていると。

Java's floating-point arithmetic is blighted by five gratuitous mistakes:

  1. Linguistically legislated exact reproducibility is at best mere wishful thinking.
  2. Of two traditional policies for mixed precision evaluation, Java chose the worse.
  3. Infinities and NaNs unleashed without the protection of floating-point traps and flags mandated by IEEE Standards 754/854 belie Java's claim to robustness.
  4. Every programmer's prospects for success are diminished by Java's refusal to grant access to capabilities built into over 95% of today's floating-point hardware.
  5. Java has rejected even mildly disciplined infix operator overloading, without which extensions to arithmetic with everyday mathematical types like complex numbers, intervals, matrices, geometrical objects and arbitrarily high precision become extremely inconvenient.

    W. Kahan and Joseph D. Darcy, "How Java's Floating-Point Hurts Everyone Everywhere"1

C言語のときからすると、要求のハードルは大分高くなっているようにも思えますけど。5番目は、10進固定小数点演算 java.math.BigDecimal についても当てはまりますね。

FORTRAN と COBOL というのは、コンピュータが「計算機」であった時代に生まれたプログラミング言語であるわけでして、数値計算に関しては、未だこれに代わる言語というのは存在していないように思いますね。C言語がプログラミング言語のメインストリームになってからは、数値計算というのはプログラミング言語の進化から忘れられた存在なのかもしれません。


1. http://www.cs.berkeley.edu/~wkahan/JAVAhurt.pdf

| | コメント (0) | トラックバック (0)

2008年10月 8日 (水)

工事完成基準でも同じです

工事進行基準では、ベンダの恣意的な売上計上がいくらでも可能である、といった話。

... そもそも工事進行基準は会計操作の余地がてんこ盛りの危ない会計処理方法だ。ITベンダーの事業実態を決算書に正確に反映するために、そうしたリスクを背負い込んだ。その分、他業種以上に堅牢な内部統制制度が要るし、会計士や監査法人のチェックも厳しくなると覚悟しなければならない。

工事進行基準の売上計上でSI料金を請求できますか (東葛人的視点 ITpro)

いくらなんでも、受注額を超える売上高を計上する、なんてことはないでしょう。すると、「会計操作」として現実に可能なのは売上計上の時点を「操作」することでしょうね。

極端な例を考えます。たとえば、契約締結の翌日が決算締め日で、その日に受注総額の半額に相当する売上高が計上されている、とかですかね。

工事完成基準で売上高を計上している場合でも、似たような例は考えられますよね。

たとえば、開発現場に契約書が営業から渡されて、みると納期が明日になっている、なんて話です。で、なぜか、一週間後に検収書が発行されて、顧客から入金がなされている...

工事完成基準というのは、システムが現実に完成した時点をもって売上を計上するわけでして、検収書発行時点でもなければ、顧客から入金があった時点でもないのですよね。書類上、システムが完成していることになっているだけではだめでして、現実にシステムが完成したといえる状況になければなりません。

企業会計原則では、売上高は、実現主義の原則に従うこととされており、通常、実現主義とは、(1)商品等の財またはサービスの提供、(2)その対価の獲得という2つの要件を満たしたときに収益を計上することとされています。

太陽ASG監査法人編, 『ソフトウエアビジネスの会計実務』, 中央経済社, 2008, p.133

実現主義の原則というそうです。

同書では、受注制作のソフトウエアに関しては、以下の3点の要件を満たしたときに、売上高を計上するのが適切である、としています。

(1) ソフトウエアの完成

 ソフトウエアの受注制作を請け負った企業における品質管理上のルールに合致したソフトウエアとして完成していることが確かめられていること。

(2) ソフトウエアの納品・検査

 完成したソフトウエアを顧客に納品し、顧客の検査を受けることによって実際に稼動し機能することが確かめられていること。

(3) ソフトウエア成果物の検収

 契約書によって顧客への引渡しが定められているソフトウエア成果物(例えば、設計書、仕様書、マニュアル、プログラムを記録したCD−ROM等)が引き渡され、その内容が顧客によって確かめられていること。

同書, P.136

日本公認会計士協会 が、平成17年に出した、「情報サービス産業における監査上の諸問題について」という報告書では、「収益の認識時点の問題」として、「我が国の会計基準では明確ではなく」とした上で、米国基準を紹介しています。この報告書が、前年のIT業界の一連の会計不祥事を受けて出されたものであることは周知のとおりと思います。

こうした流れからしますと、受託ソフトウエア開発に対する、工事進行基準の適用は、工事完成基準を厳格に適用することで、売上高を計上できない事態に陥る、ということに対し、逃げ道を用意した、とみることもできるのではないですかね。

工事進行基準ばかりがクローズアップされていますが、つまるところ、IT業界が会計処理を適切に行なうよう求められている、ということでしょう。この点、工事完成基準を使う場合でも同じことだと思います。

| | コメント (0) | トラックバック (0)

2008年10月 7日 (火)

請負契約の成立するとき

深沢隆司氏の『SEの教科書2』(技評SE新書017, 2008) を読みました。システム開発について、おおよそ以下のような主張がなされていまして、興味深いと感じたのですが。

営業段階・受注段階で作成されたスケジュール(初期計画)に従っていては、システム開発プロジェクトを成功させることはできない。 業務分析、要求定義が完了した段階で、開発計画を改めて作成する必要がある。にもかかわらず、ベンダは初期計画を絶対視して変更をしようとせず、そのままプロジェクトを進めようとしている。だから、システム開発のほとんどは、失敗に終わる。

ソフトウエア受託開発では、受注金額と納期だけが決まっていて、開発要件は不明確、という形で、「請負契約」が締結され、契約書が交わされる、ということが往々にしてありますね。

しかし、法的には、請け負う仕事の内容が不明確な状態では、請負契約というのは成立しません。何を請け負うのかわからないのに、請負契約が締結される、というのは奇妙な話です。契約書の内容にもよるでしょうが、開発計画がまともに立てられないような契約書というのは、紙くずでしかないわけです。

名古屋地裁平成16年1月28日判決

本件総合システムの導入に際して締結されるような,業務用コンピューターソフトの作成やカスタマイズを目的とする請負契約は,業者とユーザ間の仕様確認等の交渉を経て,業者から仕様書及び見積書などが提示され,これをユーザが承認して発注することにより相互の債権債務の内容が確定したところで成立するに至るのが通常であると考えられる。

システム開発をめぐる法律問題(3)個別契約で上流工程の不払いリスクを回避する (ITPro)

日経BP社 ITPro の連載記事『システム開発をめぐる法律問題』では、名古屋地裁の判例をひいて、「外部設計相当の内容について合意が得られている」時点を請負契約成立の時点と考えるのが良い、と提示しています。

ベンダの営業、経営層が、受注時点の「初期計画」をもって、「請負契約成立」とみなそうとするのは、売上を早期に計上したいというインセンティブがあるからでしょう。

深沢隆司氏によれば、

たいていの場合、開発計画は初期計画の2・3倍程度になる

とのことですが、これは、ベンダの営業・経営層にとっては都合がよいわけです。本来必要な工期の 1/2 ・ 1/3 の時点で、キャッシュが手に入るわけですから。

顧客側は、契約書にある納期に従って入金の事務処理を進めたいでしょうから、実態としてシステム開発が完了していなくとも、検収書発行、入金が行なわれる可能性が高いです。また、顧客も初期計画の予算・納期で開発を進めてもらいたいわけでして、そこをベンダに付け込まれている面もあるでしょう。

もちろん、これらは開発現場にとっては最悪なわけでして。もともと達成不可能な計画を押し付けられ、最後はプロジェクト失敗の責任を負わされますからね。

上の名古屋地裁判例の判決文は、裁判所の判例データベース内に登録されていて、読むことができるのですが、読んでいると、こうした構図が透けてみえます。顧客側(原告)敗訴の判決ですけど、少々この顧客には同情してしまいますね。顧客の契約管理が甘かったのは確かのようですが(契約書すら存在しない)、ベンダにうまくやられた、という印象も受けます。

| | コメント (0) | トラックバック (0)

2008年10月 5日 (日)

工事進行基準の対象となる会社

「上場企業だけの話」という声もありますが。ソフトウエア受託開発を業務としている、全ての株式会社が対象じゃないですかね。

第四百三十一条  株式会社の会計は、一般に公正妥当と認められる企業会計の慣行に従うものとする。

会社法(平成十七年七月二十六日法律第八十六号)

会社法431条にいう、「一般に公正妥当と認められる企業会計の慣行」というのは、企業会計基準委員会の定める会計基準のことを指すのだそうですから(微妙なところもあるらしいですが)、 企業会計基準第15号「工事契約に関する会計基準」 もこれに含まれるのでしょうね。

4 本会計基準は、工事契約に関して、施工者における工事収益及び工事原価の会計処理並びに開示に適用される。

 本会計基準において「工事契約」とは、仕事の完成に対して対価が支払われる請負契約のうち、土木、建築、造船や一定の機械装置の製造等、基本的な仕様や作業内容を顧客の指図に基づいて行なうものをいう。

5 受注制作のソフトウエアについても、前項の工事契約に準じて本会計基準を適用する。

「工事契約に関する会計基準」 4, 5

請負プロジェクトの収益計上については、工事完成基準または工事進行基準の選択適用となっています。どちらを選択するかについて定めがありまして。

 工事契約に関して、工事の進行途上においても、その進捗部分について成果の確実性が認められる場合には工事進行基準を適用し、この要件を満たさない場合には工事完成基準を適用する。

 成果の確実性が認められるためには、次の各要素について、信頼性をもって見積もることができなければならない。

 (1) 工事収益総額

 (2) 工事原価総額

 (3) 決算日における工事進捗度

「工事契約に関する会計基準」 9

「成果の確実性」がある場合には、工事進行基準を適用する、となっています。通常のプロジェクトでは、成果の確実性がない、とするのは説明が難しいでしょうね。プロジェクトが期をまたぐ場合、工事進行基準で売上と費用を計上する、ということになりそうです。

| | コメント (0) | トラックバック (0)

« 2008年9月 | トップページ | 2008年11月 »