2010年4月20日火曜日

ソフト開発への心がけ

  • 目的・目標をはっきり作る。
  • プログラムは小さく、シンプルに、分りやすく書く。
  • コピペしない。
  • 重複コードは書かない。
  • ツールを作る。
  • ツールを使う。
  • プログラムでテストする。
  • テストはもれなくする。
  • プロトタイプでこまめに納品。
  • ミス、失敗は必ず記録して、次回に活用する
  • 詳細に決めない。
  • 作り込まない。
  • 決まっていないことを前倒しで作らない。

2010年4月15日木曜日

逆転の発想

逆転の発想が好きである。
中学生の時には、電子工作が好きで、真空管やトランジスタでラジオを良く作っていた。
「初歩のラジオ」だったかに載っていた記事で、真空管は熱が出るので特性が安定しないという性質を逆手にとって、
金属ケースに真空管を入れて、熱するだけ熱せば良いという記事を読んで、「ああ、面白いこと考えるなあ」と思ったのが最初だと思う。

要するに普通の方法が駄目なら逆の方法も試してみるということである。
江崎ダイオードの江崎博士も当時は、半導体の不純物を少なくする方法を考えるという流れに逆らって、不純物いれちゃえー!みたいなノリで、トンネル効果を発見し、江崎ダイオードができた。
江崎博士そうとうなへそ曲がりだと思う。

プログラミングも常識的な一手を疑うことも大切である。
普通の計算方法なら、非常に時間がかかるが、逆にすればあっという間に計算が終わることもしばしばある。

たとえば、以前、ポリゴンの配列にデータを入れていく時に、既に同じデータがあれば、そのインデックスを参照するようなプログラムを作った。
データが少なければ直ぐに計算が終わるが、これが数十万から数百万頂点になると、何度も最初から配列を調べなくてはならないので計算量は指数的に増大して行く。
しかしインデックスを参照するような頂点データは、そもそも偏っていて、近くにあるものである。
毎回配列の最初から探す理由がない。
配列の最後から探す、たったこれだけで、計算量は極端に少なくなる。
画像処理だってそうである。ある画素に相関のあるのは、その画素の近傍だけである。
データの量が多くても、連続性や偏りなどの局所性に注目すれば良いのである。

2010年4月9日金曜日

コピペコード

自分は、コピペコードは禁止している。
手作業で似たような箇所を3カ所以上修正する場合には、プログラムで発生させることにしている。
プログラムで直すと、最初に手間はかかるけど、次の修正には時間がほとんどかからない。
何故そうしているかは、『修正が何度もあるから』である。
手で直している限りは、必ず同じ分の時間がかかる。
しかも、手作業ではミスが発生しやすい。
そして、コピペコードは間違えた場合に、極めて発見しにくいバグとなる。
たとえば、

ActiveWorkbook.Worksheets("header").Range("EA" & CStr(xlsRow)).Value = .Range("EA" & CStr(csvRow)).Value
ActiveWorkbook.Worksheets("header").Range("EB" & CStr(xlsRow)).Value = .Range("EB" & CStr(csvRow)).Value
ActiveWorkbook.Worksheets("header").Range("EC" & CStr(xlsRow)).Value = .Range("EC" & CStr(csvRow)).Value
ActiveWorkbook.Worksheets("header").Range("ED" & CStr(xlsRow)).Value = .Range("ED" & CStr(csvRow)).Value
ActiveWorkbook.Worksheets("header").Range("EE" & CStr(xlsRow)).Value = .Range("EE" & CStr(csvRow)).Value
ActiveWorkbook.Worksheets("header").Range("EF" & CStr(xlsRow)).Value = .Range("EE" & CStr(csvRow)).Value
ActiveWorkbook.Worksheets("header").Range("EG" & CStr(xlsRow)).Value = .Range("EG" & CStr(csvRow)).Value
ActiveWorkbook.Worksheets("header").Range("EH" & CStr(xlsRow)).Value = .Range("EH" & CStr(csvRow)).Value
ActiveWorkbook.Worksheets("header").Range("EI" & CStr(xlsRow)).Value = .Range("EI" & CStr(csvRow)).Value
ActiveWorkbook.Worksheets("header").Range("EJ" & CStr(xlsRow)).Value = .Range("EJ" & CStr(csvRow)).Value
ActiveWorkbook.Worksheets("header").Range("EK" & CStr(xlsRow)).Value = .Range("EK" & CStr(csvRow)).Value
ActiveWorkbook.Worksheets("header").Range("EL" & CStr(xlsRow)).Value = .Range("EL" & CStr(csvRow)).Value

この間違いが一見して分かるだろうか。
EFとするべきところが、EEになってしまっている。よーく見ても似ている字なのでなかなか見つけにくい。
そもそも連続しているのだから、ループにすれば良いと思う。
だが、エクセルは列は文字列なので、そのままできない。
列名を配列に入れる方法もあるが、ここは列名を数字に相互変換するメソッドを用意した方が色々と計算が簡単になる。

列名加算なるメソッドを追加して、次の様に書く。

Dim ws
Dim column
Set ws = ActiveWorkbook.Worksheets("header")

For i = 0 To 12
column = 列名加算("EA", i );
ws.Range(column & CStr(xlsRow)).Value = .Range(column & CStr(csvRow)).Value
Next

もっともRangeの設定を上手にすれば、そもそもループせんでも良いのでは?などという突っ込みもあるけど。一応参考例として。