2010年8月16日月曜日

javaのsqlアクセスメソッドgetStringで文字化け(2)?

以前にjavaプログラミングで、MSAccessデータベースにアクセスする際の文字化けについてお話しました。どのようにコーディングするのかコメントがありましたので、私がYawdbaで使用しているコードの抜粋を説明します。

◆以下のコーディングでODBCデータソースにアクセスします。
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); 
cnn = DriverManager.getConnection("jdbc:odbc:" + "データソース");

◆取得したODBCデータソースコネクション(cnn)クラスのcreateStatementメソッドを呼び出し、SQL文を実行するStatementインタフェースを以下のように取得します。

stmt = cnn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY);

◆StatementインタフェースのexecuteQueryメソッドにより、SQL Query文を実行します。
rset =stmt.executeQuery("SELECT * From myTable"); 

◆SQL文が実行したら、取得したResultSetインタフェースオブジェクト(rset)を使って取得するレコード行を設定した後、レコード内のカラム位置(1~)を指定してデータを取得します。
このとき、このデータの型によって動作が異なります。

> データ型がVARCHAR以外なら、通常のgetStringメソッドを使ってデータを取得します。
val = rset.getString(カラム位置);


>データ型がVARCHARなら、ストリームを使ってデータを取得します。
/* データ取得するためのリーダー(myReader)をgetCharacterStreamメソッドで取得します */
Reader              myReader = rset.getCharacterStream(カラム位置);
/* 取得するデータの表示サイズをgetColumnDisplaySizeメソッドで取得し、そのサイズ分のStringBufferを確保しておきます */
StringBuffer       sb = new StringBuffer(該当フィールド表示サイズ);

try    {
        int    c;
        /* 取得したmyReaderを使ってreadメソッドで1文字づつ取得します。*/
        while((c = myReader.read()) != -1) {
        if(c != 0)  /* c == 0の場合には、文字列データとして不正なのでスキップ */
                       sb.append((char)c); /* 取得した文字列をStringBufferに追加します */
                }
        }
        catch (Exception e)
               エラー処理
        }
        val = (sb.length() == 0)?null:sb.toString(); /* StringBufferを文字列に変換します。 */
}


現在開発しているYawdbaもある程度形になれば、Yawdbaのサイトで公開したいと思いますが、暫く時間をください。

2010年8月4日水曜日

構造化プログラミングと抽象化について

私は、プログラミングを始めてから長い間、構造化プログラミングによる設計を行ってきました。この経験のなかで、処理の抽象化による設計が大切であることが分かってきました。今回は、これについて話したいと思います。おそれく、処理の抽象化とオブジェクト指向プログラミングは、近い関係にあるかと思います。
入社後、2年程たってサンディエゴに出張してUCSD-pSystemlの内部構造を勉強することになりました。UCSD-pSystemには、Pascalコンパイラーだけでなく、ファイルシステムやプログラム実行環境、スクリーンエディターが用意されていました。プログラミングに関して勉強になったのは、そのファイルシステムのモジュールの作り方でした。詳しくはこのリソースをご覧ください。
下位のモジュール(では、フロッピーのディスク内のシリンダー番号やセクター番号から物理セクターを読み込んで、メモリ内に読み込むだけにし、この下位モジュールを呼び出す上位モジュールでは、実際に物理セクターを読み出す下位モジュールを使ってファイルシステムが使用する論理ブロック(ブロック長は固定の512バイト?)を実現していました。さらに、その上のモジュールでファイル名の管理などを行う実際のファイルシステムを構築しています。このような構造は、通常のオペレーティングシステムの開発方法としては一般的ですが、下位モジュールに行くに従って実施のディスクアクセスを物理動作を行っています。
この方法のメリットとしては、仮にセクターの管理するバイト数が変更されたとしても、下位モジュールを修正するだけで上位モジュールに手を加えることなく動作できることにあります。同様のシステム構成としては、プロトコルレイアの階層として一般的なOSI参照モデルがあります。このOSI参照モデルの下位層である物理層やデータリンク層から上位に行くに従って、データにやり取りが抽象化されています。
このように、処理やデータを抽象化することにより、仕様変更に強いシステムの構築が可能となります。
なお、私が尊敬する「ニクラウス・ヴィルト」も、プログラミングに関する抽象化の大切さを著しています。

2010年7月23日金曜日

クラスの作り方

Javaプログラミングでは、まず、クラスが必要となります。それでは、クラスを設計する上での基準などあるのでしょうか?。これが、正しいかはわかりませんが、私が考えるクラス設計方法について述べたいと思います。
私は非常に長い間、構造化プログラミングに従ってプログラム設計を行っていましたが、システムプログラム分野では、データの関連をポインターを使ったツリーやノードで表現するデータ構造が決まるとほとんど、プログラム構造が決まってくることがわかってきました。その結果、プログラミングの多くの時間はデータ構造の設計に費やすようになりました。データ構造の設計では、今後、想定される仕様変更や機能追加に対応できるかが大きなポイントとなります。
オブジェクト指向の設計方法でも、クラスを単位を決定するには、今後、どのような仕様変更があるか、作成したクラスが他のモジュールで再利用できるかを観点に決める必要があると思います。
高速性が必要とされるサブルーチンや仕様変更が発生することが想定されないサブルーチンに迄、クラス化する必要はないと思います。

Yawdbaでは、クライアントからWebリクエストから、クライアントのブラウザやパラメータなどを内部データに持つクラスインスタンスを作成し、その後の処理では、このクラスインスタンスのみを使用して処理します。もし、クライアントからの呼び出し方法が変更された場合には、このクラスインスタンスを拡張するだけで、後続の処理に影響を与えないことが可能にしています。

構造化プログラミング

わたしが、プログラマーになったころ(1978年頃)、大量のソースコードを開発する方法として構造化プログラミング手法が確立したころでした。それまでのアセンブラやFortranなどのプログラムロジックには、プログラムを開発する手法がなく、ロジックを記述する手法としてフローチャートがあったのみでした。
構造化プログラミング手法では、 順次繰り返し分岐を組み合わせて論理構造を作り上げるものです。このように論理構造を限定化することにより、大量のソースコードの品質を向上することが可能となりました。最近のプログラム言語では、このような構造化プログラミング技法での順次・繰り返し・分岐をif文やwhile文などの構文として組み込まれています。
したがって、CやJava,VisualBasicなどを使ってgoto文を使わずにコーディングすれば、まずは、構造化プログラミング手法に準じたプログラムとなります。
私の知っている人で、ロジックを従来の方法で設計してフローチャートで記述した後、このフローチャートから順次・繰り返し・分岐の構造を作り出した人がいました。しかし、このモジュールの非常に分かり難く、デバッグが非常に困難になってしまいました。このような方法は、構造化プログラミングとは言えません。

2010年7月18日日曜日

Cプログラマーから見たJava

私は、長くC言語(約20年くらい)プログラミングを行ってきました。当初、C言語は、CobolやFortranには無かった構造化設計が可能な上に、PL/IやPascalで可能であったポインタが利用できる点において、システム開発では有効であったと思います。(PL/Iは、コンパイラーが非常に重くIBMコンピュータでしか完全には利用できませんでしたし、Pascalでは、ビット演算など小回りの効くコーディングができなかったり、オブジェクトモジュール別の開発が面倒でした。)
その後、SmallTalkなどの成功によりオブジェクト指向プログラミングが流行るようになると、C言語でも同様の処理系が開発できないかと言うことが検討されC++が開発されました。しかし、C++を利用せずに、C言語でオブジェクト指向風のコーディングでできないかというアプローチも行われました。なぜ、オブジェクト指向プログラミングが大切かお話するまえに、C言語でオブジェト志向風プログラミングを行うコーディングにつてお話しましょう。これが、分かるとJava処理系の動作について分かるかと思います。

クラスには、インスタンスとメソッドがありますが、これは、C言語での構造体で定義します。インスタンスについては、構造体内の一般の変数、メソッドは、関数へのアドレスを格納します。

例えば、次のように書きます。
struct {
  int  instance;
  int  (*get_method)(void);
}  myClass;

instanceフィールドは、このクラスのインスタンス変数を格納するフィールドであり、get_methodフィールドは、get_method関数ポインターが格納されます。オブジェクト指向は、それぞれのオブジェクト毎に内部インスタンスとメソッドがありますが、このようにすることで、C構造体に付随するインスタンスとメソッドを定義します。あとは、この構造体を通じて、メソッドを通じて操作することでオブジェクト指向を実現します。

しかし、この構造体では、get_methodフィールドは、単に関数ポインターが格納されると宣言しているだけで、実際の関数アドレスが可能されている訳ではありません。そこで、これらの構造体に関数アドレスを事前に設定する必要があります。これらの初期設定する部分を関するにして、上記構造体のアドレスを返却する関数を以下のように用意します。
  myClass *handle = Create();

このCreate関数で、get_method関数アドレズを設定したります。このようにすると、次のように利用できます。
  thisValue =(* handle->get_method)();

Javaでもオブジェクトをクラスから作り出す際に、newオペレーターを使っていますが、内部的には、クラス特有に存在している構造体に、メソッド関数などを定義したり、各クラス内のインスタンス関数を実行しているものと思われます。この方法で、擬似的にオブジェクト指向風のプログラムを作成することができますが、クラスのインヘリタンス(継承)機能をC言語で記述することはできません。

2010年7月11日日曜日

Excelって印刷のことを考えていないと思う

みなさんは、Excelを使って印刷するケースが多いと思いますが、実は、Excelからの印刷では注意すべき点が沢山あります。
Wordなどでは、Wordのファイルメニューにあるページ設定で用紙サイズを指定すると、この用紙で印刷されます。プリンタドライバーの印刷設定に「用紙サイズ」や「原稿サイズ」などの設定がありますが、この用紙サイズを変えても、Wordで設定した用紙サイズで印刷され、印刷レイアウトはあまり変化しません。つまり、Wordでは、Wordで指定された用紙サイズで印刷のレイアウトが決定され、プリンタドライバによって変化することはありません。
一方、Excelでは、印刷指示を行った際に、プリンタドライバで設定した用紙サイズやExcelの[ページ設定]で指定した「用紙サイズ」に合わせて、Excelで印刷できる行数や桁数を計算して印刷します。Excelのページ設定で印刷領域から印刷ページ数を指定してレイアウトを決定する方法もありますが、印刷レイアウトは、プリンタドライバの能力(解像度・印刷可能領域サイズ・搭載フォント種類)によって自動的に変化します。
このため、プリンタドライバを変えてしまうと、思ったように印刷されないなどの現象が発生します。
Excelは、基本的にセルで計算するためのソフトであり、印刷に向いていないことを十分知っておく必要があります。

2010年7月4日日曜日

コンピュータ昔話(PC起動をなぜブートと言うか)

みなさんは、PCを立ち上げる際にブート(Boot)するといいますが、なぜかご存知でしょうか?昔のコンピュータでは、ハードウェアリソースが限られており、そのためにシステムを立ち上げるために必要なプログラムをROMに書き込んでおくことができませんでした。
そこで、最低限の入出力を行う処理だけがコンピュータハードウェアとして用意されており、PCを立ち上げるプログラムをメモリにロードする手順(ブートストラップローダー)を行った後、立ち上げ少しずつ機能を加えながら立ち上げを繰り返しました。まるで、靴紐を編み上げるようにコンピュータを起動するために、コンピュータの立ち上げをBootStrap(靴紐)と言いました。ブートストラップからストラップが無くなり、現在では、PCを立ち上げるのにブートと言うようになりました。