プログラミング雑談

メインページに戻る

VS2008 Express Editionで遊ぶ

最近はWindowsのプログラムも書いて遊んでいます。
昔々Visual C++ 5.0を買ったことがあり、チュートリアル本を見ながらWindowsのプログラミングの勉強をしたことがありますし、MFCで簡単なプログラムを書いたこともあります。でもWindowsのアプリケーション開発を職業にしているわけでもないのでほぼ素人です。
いわゆるNetBookでしたっけ。安いノートPCを買ってVisual Studio 2008 Express EditionのVC++をインストールして、無料の環境でどこまで作れるのか身をもって実験しています。
とりあえず外付けモニタを使わないとはかどりません。SDKのドキュメントを表示しながらVisual Studioのエディタ画面(?)に関数を書こうにも画面が狭すぎてSDKのドキュメントを参照できません。
でも外付けモニタさえつけてしまえば結構使えます。
面倒な事を考えたく無かったのでSTLも使っています。まだstringとかwstringとかしか使っていませんが、一から処理を書かなくてもよいので楽ですね。
一応アプリケーションとして当たり前のことを実現しようとするといろいろな事をやらなくてはならないのですね。普通にテキストエディタで書いたファイルを読み込んで処理しようとするとcharからwchar_tへの変換が必要になったり、前回の設定を復元するためにiniファイルにアクセスしたり。
作っているのはちっちゃいプログラムなんです。年賀状の宛名印刷です。凝ったことは何もしないで、CSVファイルの住所録を読み込んで印刷するだけ。世間にフリーソフトがたくさんあるのは知っています。私も過去3年くらい使っています。えと、作ることに意義があるということで。
今の感じだと当初作りたかったものが出来上がるとリソースを除いて100KB位のexeになるんだろうな。

2008年11月07日 プログラミング雑談

作りたいアプリはあるけど構想中

プログラミングの勉強がてらWindowsで私専用のwebページ作成アプリを書いてみようかなと思い始めてかれこれ半年。年末に年賀状宛名印刷ソフトを作って、完成しないまま無理やり宛名だけ印刷できたところで時間切れ。webページ作成アプリはどんなアプリを作れば便利なのか構想すら曖昧なままだったりして。

2009年01月17日 プログラミング雑談

連休中はプログラムのひとつも書けるかな

5月の大型連休の間に何かプログラムでも書きたいなぁと思う今日この頃。
去年、年賀状印刷プログラムが作りかけなので完成させたいところですが、まとまった時間が取れそうにありません。プログラミング関連では「Advanced Windows Debugging」など読んでいるのでLeakDiag.exeとかをいじってみたり。LeakDiagってautodiag.iniをきちんと書けばアプリの起動から終了までのリークが検出できそうな雰囲気なのですが、どうしてもアプリの立ち上げでSleep()して、その隙にLeakDiagを設定しなくてはならない感じ。無料で入手できるツールでリークの発生するGlobalAllocの行が特定できるのは実にありがたいので、活用したいのですが・・・・。
わけあってWindows Mobileのプログラミングも調べ始めました。古いバージョンのWindows CE向けの開発ツールは無料で入手できるそうで。Win32のサブセットが使えるのかな。WILLCOMのPHSであるところのzero3[es]を使っていますが、最近はフルキーボードは外付けでよいから厚ぼったい筐体をスマートにできないものかと思ったり。NTTドコモのケータイも家にあるけど、ケータイにはフルキーボードを接続できないのでiモードのメールで長い文章を書こうという気にならないし。あ、違った。キーボードの話題ではなかった。zero3[es]にキーボードをつないで、このページを更新するのも良いなと思ったもので、簡単webページ作成ソフトとか作れたら面白いだろうなと。まだCEのプログラミングに入門すらしていないのでたぶん実現しないのですけど。
まずWindows上で実現させたいなぁ。ブログなら自動でできてしまうようなことを全て手動でhtmlを書いていると、時々文章を書くことすら面倒になってくることがあるんだよね。

2009年05月03日 プログラミング雑談

サイトリニューアル(どこが?)

しばらく更新していませんでしたが生きています。
ADSLをフレッツからイーアクセスに切り替えて、最悪2週間くらいアクセスできなくなるかなと思いましたが意外とすぐに切り替え工事が済んで、結局一晩使えなかっただけでした。
これで毎月の通信費が3,000円近く安くなるはず。
そういえば、今はメールのためにWILLCOMのPHSを使っているけれど、ドコモ携帯電話もメールの利用料が基本料金に含まれるコースができるのでWILLCOMを解約するという手もアリになってきたんですよね。そうすると2,900円位通信費がまた安くできる・・・かも。ドコモのiモードはパケ放題にしてもパケット料金0.08円と馬鹿高だけど、WILLCOMはパケ割にすると0.01円位だからパケットをたくさん使うならWILLCOMが断然安いという利点はまだあるのだけれど、私ってパケット使わないからなぁ。

さてさて、話がそれましたが、表題の「サイトリニューアル」は別にADSLを切り替えたことではなくて、このページの作成環境を切り替えていました。
ということで、このページを作るだけのためのプログラムを書いていました。Windowsベースのコンソールアプリです。そういうプログラムを作りたいなぁと思い始めて1年、具体的にどう作ろうか考え始めて3日。まだ構想の1割もできていないのですが、完成までがんばっちゃうと年内の更新はなくなってしまうので、試運転がてら。
見た目はぜんぜん変わっていませんが、多分左側に見えているカレンダーとカテゴリーのリンクは自動生成になりました。まだカレンダーにリンクをつけるのは手作業なので、この部分は今後の実装。
構想としては「これより古い独り言」のページを自動生成したいんだけどなぁ。これも後日。

2009年11月03日 プログラミング雑談

Test Firstでなくてもcppunitは便利かも

今夜もcppunitでこのページの生成プログラムのテストコードを書いていました。
簡単なコードの部分からテストを書き始めて、徐々にテストしにくい、現実にバグが入っているだろうと思う部分のテストコード作成に移ってきています。cppunitって使ったことがあまり無かったので、どういうテストを書くのかいちいち考えながらやっているので面白いです。
今は「大体動くプログラム」があって、それに合わせてテストを書いていますが、それでもテストを書きながらプログラム本体を修正しますし、テストするためにプログラム本体を設計しなおしたくなったりします。そんなことをしながら今日思ったのは、プログラムを修正するときに直し間違えたときにcppunitを使っていると発見が早いということと、テストコードをプログラム本体と同時に作成すると、プログラムの怪しい部分をテストコードですぐに確かめられるので便利だということ。
しばらくは「このページの生成プログラム」と「テストコード」で遊べそうです。

2009年11月16日 プログラミング雑談

プログラムは完成していないのに次の野望

htmlを手で書かなくてもサイトが更新できるようになったもので、少し欲が出てきたのかRSSにも対応したいなぁと思いはじめました。
まだ私のwebページ自動生成プログラムは完成していないというのに・・・。
あと実働で数日あれば今作っているwebページ生成プログラムは一段落するだろうから、その後windowsアプリ化とかRSS対応とか手を出すのも良いかも。
そういえば年賀状宛名印刷プログラムも昨年の年賀状シーズンが終わったら放置していた・・・。windowsの表示関連でいろいろ遊んではいましたが、ウインドウの再表示処理がどうも不完全(クライアント領域ではなくてタイトルバーなどで再表示されない部分かある)というあたりで止まってます。
年賀状宛名印刷という点ではタイトルバーの再表示が欠けても問題ないから再開しようか・・・。
そういえば今年も写真の年賀状にしようとしているので写真を選んで写真屋に注文しないと・・・。
年末はやっぱりプログラムを書いている場合ではないかも。

2009年11月20日 プログラミング雑談

忘れる前に今回作っているプログラムについてメモ

ここしばらくの間作成していたプログラムもようやく最初の段階に達して使えるところまで来たので、つまづいたところをメモしておきます。
(1) C++の標準出力について
普通に次のようなプログラムを書きました。

#include <stdio.h>
#include <tchar.h>
#include <iostream>
#include <windows.h>
int main(int argc, char* argv[])
{
    std::wcout << TEXT("Hello world! あいうえお") << std::endl;
    return 0;
};

今回作るのはコンソールプログラムですが、Visual Studio 2008 Express Editionを使っていますので、一応最近のWindowsプログラムっぽくテキストはTEXT("")マクロを使おうかなと思っちゃったわけです。
このプログラムの出力は
Hello world!
です。「あいうえお」以降の部分が出力されません。最後のstd::endl;も出力されていません。

std::wcoutをstd::coutにすると、"Hello world!"すら出力されず、ポインタのアドレスらしいものが出力されます。  
    std::cout << TEXT("1 Hello world! あいうえお") << std::endl;
    std::wcout << TEXT("2 Hello world! あいうえお") << std::endl;
    std::cout << "3 Hello world! あいうえお" << std::endl;
    std::wcout << "4 Hello world! あいうえお" << std::endl;

とすると、期待通りに出力されるのは3だけです。
・・・・と、ここまでがVisual Studio 2008 Express EditinのC++でコンソールプログラムのデフォルトなんですが、プロジェクトのプロパティの全般設定で文字セットを「マルチバイト文字セットを使用する」設定にすると1から4まで全て期待通りに出力されます。
今回私が作っているプログラムではユニコードを使用する設定なのですが、なぜか上記4の形式で期待通りに出力できています。理由はわかりません。この問題で半日くらいあれこれ設定をいじったときに何かあったのかもしれません。

2009年11月24日 プログラミング雑談

忘れる前にCppUnitについてメモ

今回作成しているプログラムではCppUnitを使って単体テストしながら作成しました。
昨日は(1)でしたので今日は(2)
(2) CppUnitのランタイムライブラリを使うときのランタイムライブラリ設定について
コマンドラインプログラムですので、DLLとか使うのは何だか変な気がしたんですよね。理屈ではコマンドラインプログラムでもWindowsのGUIプログラムと同様に普通に使えば良いというのはわかります。
私の好みとして、VC++のランタイムDLLってPCによってインストールされていたりされていなかったりするので、exeのサイズを特に小さくしたい欲求がなければランタイムライブラリは使いたくないという気持ちはあります。というわけで、ランタイムライブラリは使わずに静的にリンクするためにプロジェクトのプロパティのC/C++コード生成のランタイムライブラリは「マルチスレッド」としました。「マルチスレッドDLL」は使いませんでした。
そうしたところ、CppUnitがうまくリンクできなくなりました。
結局、CppUnitを使うのはデバッグ時だけですので、デバッグ時のランタイムライブラリを「マルチスレッド デバッグDLL」と、リリースビルド時を「マルチスレッド」としました。
私はCppUnitの使い方はまだ初心者ですので、@ITのチュートリアル記事を参考に環境を作っています。最初「マルチスレッド デバッグ」でコードを生成するときにはcppunitd.lib、「マルチスレッド デバッグDLL」でコード生成するときにはcppunitd_dll.lib、cppunitd_dll.dllを使えば良いのかなと思っていたのですが、どうもこれは関係なくて、常に「マルチスレッド デバッグDLL」でコードを生成して、cppunitはスタティックリンクしてcppunitd.libを使えばよさそうです。
※2009年12月13日訂正
CppUnitを@ITの記事を見ながらビルドしたのがかなり昔だったので忘れていましたが、冷静になってよく思い出せばCppUnitを「マルチスレッド デバッグDLL」でビルドしたからテスト対象コードも「マルチスレッド デバッグDLL」にしなくてはならないだけでした。
CppUnitのライブラリを「マルチスレッド」としてリリースビルドしたら、リリースビルド時もCppUnitのライブラリをリンクしてビルドできるようになりました。バグって、そんなものだよね・・・。

気が向いたら、明日は(3) sizeofについて・・・初歩的なことなのですが、いつも混乱してしまうので。

2009年11月25日 プログラミング雑談

忘れる前にsizeofについてメモ

プログラミングは本をしっかり読んで勉強するというよりはプログラムを実際に作って覚えるというスタイルの私はsizeofがよく理解できていませんでした。
構造体などのポインタをsizeofすると構造体のサイズが取れるのかポインタのサイズが取れるのか、いつもわからなくなっていました。
char strTest[256];
と宣言するとsizeof(strTest)で256がとれるらしい。
でも関数の引数でfunction(strTest);などとやると、function(char* strTest)の関数内でsizeof(strTest)するとポインタのサイズである4がとれたりします。
要はsizeofする場所で変数がどう見えるかが問題なんですね。
sizeof(strTest[0])とすれば1がとれるのは私にもわかるんですけどね。

2009年11月27日 プログラミング雑談

WindowsのDLLで共有メモリを使ってプロセス間データ交換

Windowsのプログラムを作っていまして、プログラム間でデータのやり取りをしたくなりました。
いろいろな方法があるようですが、今回はDLLにデータ交換用のメモリ(変数)を確保して、そこで交換するという方法。
DLL中で

#pragma comment(linker, "/section:.myseg,rws")
#pragma data_seg (".myseg")
    INT i = 0;
#pragma data_seg()

とかすれば、変数iはこのDLLをリンクするプログラムで共有できるようになる。
変数iに初期値を入れないとセグメントがuninitialized dataになって、data_segではなくbss_segになるとかで、もしかしてdata_segをbss_segとかに書き換えればよいのかな? 試してみたらbss_segでいいみたい。でもiを初期化するタイミングはどうすればいいのだろう。調べればわかるだろうけど。
それはともかく、最近C++でプログラムを書く練習をしていますので、なんとなくこの共有領域の変数iが裸で外に出ているのが怖くて、クラスで包んでprivateにして、そのクラスを共有領域に置いて、メソッドを公開したいと思ったのですが、どうもWindowsではそのようなことは危ないらしいです。メモリマップドファイルを使うと良いらしい。
やっぱり初期化の問題はあるけれど、

class MyDllClass {
private:
    INT i;
public:
    MyDllClass(){ i = 0;}
    ~MyDllClass(){}
    int Add(){
        i++;
        return i;
    }
};
#pragma comment(linker, "/section:.myseg,rws")
#pragma bss_seg (".myseg")
MyDllClass _cc;
#pragma bss_seg()

とかやればとりあえず動いたけれど、やっぱり初期化をどうするかという問題が。最初にLoadLibraryした人が初期化すれば良いのだろう。
初期化の問題が解決したとしても、文脈は少し違うのですが「DLL内のデータをアプリケーションまたはほかのDLLと共有する方法」というMicrosoftのページで「(前略)Micorosoftではプロセス間でのC++オブジェクトの共有をお勧めできません。(中略)クラス インスタンス自体は共有しないでください」とありますので、結局使えないのですけど。ここでは全文はコピーしていませんが、このMSのページからは仮想関数さえ使わなければ自己責任で使って良さそうな感じにも読めます。まあWindowsの挙動がわかっていない私のような素人Windowsプログラマがやっていい技でもなさそう。

2009年12月06日 プログラミング雑談

ASP.NET入門中

なぜか突然ASP.NETの入門書を読んでいます。
そうだよねぇ。きっと自分のwebページを自動生成するアプリを書くなら本当はこういうツールを使うのでしょうね。
一応C++まで使うプログラマですのでC#を使いたい人向けのASP.NETの入門書を読んでいます。
1年位前にVisual C#の入門書を途中まで読んで飽きちゃった私ですが、このときの飽きちゃった原因はVisual StudioとC#と.NETがごちゃごちゃになった本だったのが原因だったような気がします。今回のASP.NETの入門書はその辺が別々になっていてとても読みやすい感じです。まあ、Visual StudioやC#のページが本の最初のほうにあるので、いまだにASP.NET関連のページに到達していないのですけどね。

2010年01月23日 プログラミング雑談

久々にプログラムをいじる気に

システム手帳の用紙を印刷するプログラムを作っています。
仕事ではなくて趣味で。
多分私の仕事はプログラマだったと思うけど、最近仕事でプログラムを書いていないなぁ。
あ、いきなり話がそれた。
見開きで一週間になっていて、その日の時刻毎の予定と、その週のToDoと、その日のToDoと、ちょっとしたメモが少し書ければよいという感じのページです。
雰囲気としては「7つの習慣」の第三の習慣のところに出てくるような週間予定表からミッションステートメント的なところを削除した感じで作っています。えと、7つの習慣がベースなのではなくて、「気がつくと机がぐちゃぐちゃになっているあなたへ」とかいう本のスケジュール表がベースです。思えばこの本が私のスケジュール管理の入門書でした。その後「7つの習慣」とか読んだりして方向修正したりします。
ああ、今度どっちの本もきちんと読み直そう。

また話がそれた。
システム手帳用のスケジュール表を印刷する話でしたね。
超手抜き版ですが、適当に罫線を引いて、時刻を書いて、日付を書いて、印刷するというプログラムは新年早々に作ったんですよね。
昔はWindows98でExcel95で作ったスケジュール表だったのですが、さすがにWindowsXPのPCにExcel95をインストールするのも気が引けたし、個人でExcel2007を買うほどの富豪でもないし、OpenOffice.Orgとかでスケジュール表を作っても良かったけど、せっかく一応職業プログラマ(だった?)わけだしプログラムを書いて見ようと思ったので。
どのくらい手抜きで作ったかというと、日付は全部コード中にベタベタに書いてあるというすばらしい手抜きぶり。プログラマなら日付をインクリメントするプログラムを書いたほうが早いし間違いがないだろうとツッコミたくなるような出来栄え。言い訳すると、私は職業プログラマだったけどUI付近には縁がなかったので文字列関数とか日付関数とかのランタイムライブラリって趣味でしか使ったことがないので、なんとなく日付の処理がめんどくさかったのです。
で、今日は超手抜き版に日付関数を入れて、日付をプログラムに書かせるように直していたというわけでした。さっきやっとできました。なかなか充実した夜だったと思い込むことにしよう。
それにしても、_localtime64_sで、どうして月だけ1月が0って感じで1ずれるんだろう。

2010年03月10日 プログラミング雑談

Windowsのコンソールプログラム

Windowsのコマンドラインのプログラムを作っていて、どうして文字コードにUnicodeを使うとstd::coutとかstd::wcoutとかがうまく使えないのだろうと思っていましたが、もしかしてコマンドのシェルが間抜けだからダメだったのか。
Unicodeを標準出力に出そうとしても出せないみたい。
半年くらい前からどうしてダメなのかずっと引っかかっていたのですが、私としてはやっと解決です。満足いく解決ではないのですけど。
コンソールアプリではShift-JISでいくしかないのか。なんだか残念。標準出力を使わないように作り直すのも面倒だなぁ

2010年05月01日 プログラミング雑談

システム手帳印刷プログラムの残作業

ふと気がつけば5月15日。毎週1回は更新するつもりがすっかり間が開いていました。
ま、アクセスカウンタもあまり動いていないようなので、更新を期待している人もそもそもいないだろうということで。
・・・と、何を書こうか考える前に書き始めてしまいました。
自分用の、システム手帳を印刷するプログラムをしばらく前から作っていましたが、使い勝手をあれこれ言わなければ使えるところまで出来ました。あとは使い勝手を改善して、プログラム内部のつくりをきれいにして・・・というところが当面の課題です。
まずやりたいのがツールバーの追加。今は何でもメニューで操作するようにしてるけどシステム手帳のページを印刷するだけの単機能のアプリなんだからツールバーをマウスでカチカチっと操作すると印刷が完了するくらいの手軽さが欲しいです。
Visual Studio 2008のVCでネイティブWin32アプリなんですけどどうやってツールバーを作るんだろう・・・と思って何週間か手が止まっていました。ツールバー自体はコモンコントロールなんですね。ボタンのイメージ(ビットマップ)も手元の古い本を見ていたら作れそうな気がしてきたし。ビットマップは何種類かの大きさを作らないといけないみたいだけどその辺の作り方は後で調べよう。
次にやりたいのは印刷中断用のダイアログ作成、その次にやりたいのはCppUnitのテストコードを作ること。
どうせいつものように自分専用のちっちゃなアプリですのでそこまでで良いかな。
あとは次にプログラムを書くときに再利用しやすいように何かしたいのだけれど、毎日プログラムを書いているわけではないので、きっと次に作るときって何年も先で、今回何かプログラム用に部品を作っても部品の使い方を忘れているに違いない。あ、そっか、プログラムのドキュメント代わりにDoxygen形式のコメントを入れてDoxygenにかけておくか・・・。

2010年05月15日 プログラミング雑談

久しぶりにプログラムを書こうという気に

自分用のシステム手帳印刷プログラムは一応できたのですが、せっかくなので公開できるようにきちんと作り直してこのwebページで公開しようかなと。
以前このwebページを生成するプログラムを公開したいとかいった記憶がありますが、あまりにこのページ専用のアプリになってしまったので公開しても需要が全くなさそうで公開をしようという構想をこっそり取り下げてしまった前科のある私ですので、果たして公開までたどり着けるか不明。

2010年06月02日 プログラミング雑談

みんなどうやってプログラムを書くんだろ

システム手帳の印刷プログラムとか年賀状宛名印刷プログラムとかここのサイトの更新プログラムとか、一応造って使っているプログラムはあるけれど、毎回スクラッチから作っているような気がして非効率的。
せめてWindowsの標準的な処理・・・スクロールバーとかツールバーとか、ウインドウの再描画とか印刷とかという、プログラムの中身に関係ない処理くらい自前のライブラリにしてしまいたいと思い始めてかれこれ何年だろう。年賀状宛名印刷プログラムを考えていた頃からだから・・・何年だかわからない(笑)
この手のことを考えて、実行に移そうと思ったときにいつも考えるのは「MFCや.NETでいいじゃん」ということ。でも私、MFCのランタイムをインストールしなくてはならないとか.NET3.0をインストールしなくてはならないとか、そういう面倒なことが嫌いなんですよね。そういうのを全部スタティックリンクしてしまえば良いのかもしれませんが、それではつまらない単機能のプログラムなのにexeのサイズが数メガバイトとかいうみっともないことになるし。
スマートフォンとかクラウドとかいうのが流行っている時代だからDOSコマンドプロンプトアプリやWin32ネイティブアプリなんて書いてもどうしようもないという気がするし、そもそもそこまでMicrosoftが好きではないしなぁ。こんなことを考えていても私は幸せになれないので、今のところWin32で自前のちっちゃな共通処理の実現に励もうか。

2010年06月13日 プログラミング雑談

Document-Viewアーキテクチャってどうやるんだろ

相変わらずこりもせずWin32ネイティブの簡単なアプリを書いています。
ここ数日はちょっと中断。せっかく作るのならば力の及ぶ範囲で美しく作りたい。ということで、せっかくWin32アプリなんだからMFCではないけれどMFCでは必須らしいDocument-Viewとやらでやってみたい。でもDocument-Viewってどうやるの?
MVCパターンをM-VCにしたものみたい。
そこまではなんとなくわかったような気がする。
今回はDocumentが入れ子になってるCompositパターンで作ろうとしていたのですが、このときはView側でGetDocumentするときにどうしたらよいのだろう。View側で入れ子になったDocumentを展開していくのかな。それともDocument側からViewを呼び出すように組めばよいのかな。後者のほうが実装は簡単になりそうな気がするけど、なんだかDocument-Viewっぽく無いような気がする。
Document側に入れ子のDocumentを返すようなメソッドを作って、View側でそれを呼び出して入れ子データを展開するのがよさそうだなぁ。
DocumentはどのViewから呼び出されてるか知っている必要はないんだよね。って事は、Documentを取り出してから対応するViewを探すのは難しそうだ。Abstruct FactoryパターンをView毎に適用する感じなのかなぁ。それはそれで面倒そうだ。

2010年06月18日 プログラミング雑談

CompositパターンとDocument-Viewアーキテクチャ

ここしばらくプライベートの時間が確保できなかったので、思い切って有給休暇を取得して時間を確保。自分用のシステム手帳印刷プログラムの骨格部分の試作を実施。
この前から悶々としてたのが、Compositパターンでページ内のオブジェクトを入れ子にしたときにDocumentとViewの関連付けをどうしようかということ。
Document-ViewのDocument側はとりあえずCompositパターンでこんな感じかと。
Document側クラス図
適当なUMLエディタがなかったので手書き・・・
ページと線と文字の関係はこんな感じ
ページが線と文字を所有
一方、Document-ViewのView側はCompositパターンとかにしないで普通に継承してみただけ。
描画オブジェクトViewクラスにDrawメソッドを作る
ここでDocumentとViewをどうやって結びつけるのかで悶々としていました。
描画オブジェクトViewクラスにページオブジェクトを渡してDraw()すると、ページオブジェクト内に入れ子になっている線や文字もDraw()できるというのを目指したのですが、ページViewクラスのDrawで線オブジェクトや文字オブジェクトを取り出しても対応するViewがわからないのです。
ViewはどのDocumentを使うか知っているけれど、DocumentはどのViewから描画されているか知らないのがDocument-Viewらしいので、Drawメソッド内で子のDocument(線とか文字とか)を取り出しても対応するViewが取り出せないのです。

結局、今回はFactoryメソッドを使って、Documentに対応する描画オブジェクトViewを生成してみることにしました。プリンタに出力するViewと画面に表示するViewは違うFactoryで生成するということになります。
なんとなくあまりシンプルではないような気がしてます。きちんとしたDocument-Viewって違うんだろうなという不安が・・・。
でもこれで試作は動いたし、正しいDocument-ViewになっていなくてもDocumentとViewの分離は出来たような気がしますので、今回の骨組みで完成まで持っていこうかなと思っています。

2010年06月28日 プログラミング雑談

バイブルサイズの手帳印刷プログラム試作中

春頃に試作していたバイブルサイズの手帳印刷プログラムは単に試作でしたので「とにかく動けばよい」という感じでつくりました。
画面はこんな感じ。
手帳印刷プログラム画面
見ての通り、クラシカルなWin32アプリです。
Visual Studio 2008 Express Editionで作りましたので、Windows 2000以降で動くようです。
実行ファイルはこれです。
ソースファイルはこんな感じ。
このバージョンを公開するつもりはそもそもなかったので、いろいろWin32アプリとしてやるべきことをやっていません。例えば印刷中止用ダイアログが出ないので、印刷開始したら中断できないとか、ツールバーがメインのウインドウ座標上にあって、redrawのメッセージをツールバーに送っていないのでメインのウインドウをリサイズするとツールバーの表示が変になるとか。
スクロールバーもつけたかったけれどまだつけていません。
・・・などなど、数多くの問題がありながらもこのプログラムはこれでオシマイ。
この試作を捨てて、C++っぽく全面書き換えを始めました。
拡張子がcppだけど、クラスを一つも使っていないなんて・・・という感じでしたし。
Compositパターンを使ってページオブジェクトを作ってその中に線オブジェクトと文字オブジェクトがあって・・・Document-View構造にしたいなぁ・・・とか考えているのは楽しいのですが、やってみると一歩毎に壁がある感じ。なかなか進みません。
まずはこの試作と同等レベルで画面表示するところまで行きたいと思っています。
今はこんな感じ。
改良版手帳印刷プログラム画面
オブジェクト指向っていいなぁと思ったのは、ちゃんと設計すればあとはページオブジェクトに部品を追加いるだけで他のモジュールに手を加えなくて良いこと。線を増やしたり文字を増やしたりしても、表示ルーチンは全然いじらなくて良いというのは楽です。
楽だと言っておきながら、日曜プログラマなもので、このペースだとプログラムが出来るのは夏休み頃かなぁ。でも、このプログラムならばその後改良して、以前から作りながら中途半端で挫折していた年賀状宛名印刷プログラムに応用するのも簡単になりそう。
懸念事項が一つ。右手が痛いです。
整形外科とかに行ったほうがいいかなぁ。この界隈だとどこにあるんだろ。内科や皮膚科は行くけど整形外科って知らない。

2010年07月03日 プログラミング雑談

手帳印刷プログラム進捗

最近、XPエクストリーム・プログラミング入門とかいう本を読みました。
著者の趣旨とは違うかもしれないけれど、最初からきれいに実装しようとして手が止まるくらいならば汚くてもプログラムを書いたほうが良いのだ!という気がしました。
ということで、今日もちょっとだけプログラムを書きました。
Windowsプログラミングでは殆どの場合は画面表示の処理を書いていますが、プリンタの場合はページの余白の分のオフセット処理が必要なんですよね。最近の家庭用プリンタは余白なしで印刷できるので画面と同じように書いてもずれずに印刷できてしまうのでバグにちょっとだけ気がつきにくいです。
GetDeviceCaps(hdc, PHYSICALOFFSETX)、GetDeviceCaps(hdc, PHYSICALOFFSETY)で余白分のピクセル数を取得してずらさなくてはなりません。ということで、昨日公開した試作のプログラムから印刷処理をコピーして、多分印刷できるようになりました。まだ1ページ分の印刷しか出来ませんので、複数ページのオブジェクトを印刷する処理に成長させなくては・・という状況です。
複数ページ印刷に対応したらスクロールバーをつけたいなぁ。スクロールバーの前にタスクバーかな。

2010年07月04日 プログラミング雑談

プログラムは毎日作らなくては・・・

昨日から久しぶりに作りかけのプログラムをいじり始めました。
いじり始めたと言っても昨日と今日でまた中断期間に入ると思います。
作っているのは相変わらずシステム手帳の印刷プログラムです。一応印刷できるようになりましたので使い始めているのですが、WYSIWYG(What You See Is What You Get)の画面表示が出来ていませんし、春頃作ったバージョンで実現していたUIが全く入っていないのでまだまだ完成までは時間がかかりそうです。
昨日はリソースのリークのデバッグをしていました。
CreateFontIndirect()で失敗するのでDeleteObject()し忘れているのだろうと思ってデバッグしてもなかなか原因が見つからない。CreateFontしたあとはきちんとDeleteしているのに・・・ということで2時間ほど。結局Fontはリークしていなくて、penをCreateしたあとDeleteしていないことが発覚。まあバグってこんな感じで入り込むのですよね。
まだ小さいプログラムのうちに問題が見つかってよかった。
それにしてもこの前いじったときから1ヶ月くらい経ったようで、どんなコードを書いていたか殆ど記憶にありません。やっぱり毎日毎日継続して作っていかないとダメですね。
今日はスクロールバーをつけようとしています。
デザインパターン的にはDecoratorのはず。でもまだWin32プログラミングでデザインパターンに合わせるのに慣れていなくてはかどりません。精進しなくては。
今日中にスクロールバーをつけてしまわないと次に取り掛かれるのはいつになるかわからないのでちょっと気合を入れてがんばろー。

関係ないけど、この夏のジブリの映画のアリエッティだっけ、の設定を聞いていたら「あおいちゃんパニック」の「きぴきゃぴ」を連想していました。「アリエッティ "きぴきゃぴ"」でググったら2件ヒット。私だけではなかった・・・でもたった2件とは。
そのうち1件はTwitter で、発言者のサイトを見たりして、「伺か」とかいうツール?を知りました。昔Microsoft Officeでイルカのカイルとか居ましたけど、あれよりはかなり役に立ちそうなデスクトップ用のアシスタントのようです。無機質なツールも良いけれど、萌えキャラのツールも癒されるかもしれない。長く付き合うツールなら無機質なのが好みだけど。

2010年08月11日 プログラミング雑談

システム手帳印刷プログラム(作り直し版)

7月3日頃にC++で作り直し始めたシステム手帳印刷プログラムも一応自分で使うことが出来るレベルに到達しました。
現時点のシステム手帳印刷プログラム
前回作ったバージョンよりも垂直スクロールバーが使えるところと、複数ページ表示に対応したところが新しいです。
あとはツールバーをつければ前回作ったバージョンと同等、さらに水平スクロールバーをつければ当初作ろうと思っていた機能が一通り入るというところまで来ました。Document - Viewアーキテクチャの自己流の解釈で作ってましたがクラスの機能がおかしな割り当てになってしまった部分がありますし、Windowsメッセージの処理がViewに入っていないので、機能が一通り入ったらそのあたりの修正に取り掛かりたいと思います。
あ、そうだ。印刷中ダイアログも表示しなくちゃいけなかったんだ。
ゆっくりプログラムを書く時間がまた暫くとれなくなるので当初作りたかったものが完成するのはいつになることやら。年内には完成させたいのですが・・・。
疲れた。でもプログラムを書くのって楽しいですね。

2010年08月13日 プログラミング雑談

システム手帳印刷プログラム 残作業がいっぱい

日曜が終わって明日は仕事。
とりあえず一週間はほとんど趣味のプログラミングは進まない見込みです。
一区切りまで作りこみたかったのは

なのですが、ツールバーはちょっと面倒なことがわかったので、後日取り掛かることにしました。その代わりに

を先に作らなくてはならないようです。
垂直スクロールバーをつけてツールバーをつけたらツールバーがクライアント領域内なので垂直スクロールでツールバーもスクロールされてしまうというのに気がついて、ツールバーの部分はスクロール対象外にしようか、ツールバーを別ウインドウにしようか思案していました。
結局どちらの方法をとるにしても子ウインドウを作らなくてはならないわけで、設計とか考えずにガリガリ書いてしまえば実現は出来るでしょうが、今回はC++っぽくクラスを作っていきたいのでそのあたりの設計をしたいなぁと思っています。
そんなわけでツールバーをきちんと作ろうとすると考える時間が必要なので、ツールバーは無くても支障がないというわけで先送り。当面は

を優先して、その後子ウインドウの設計、作りこみ という順でとりかかり、その後ツールバーの組み込みをすることにします。

きちんと設計して作って、ライブラリを再利用したいと思っていますが、この次にプログラムを書くのは何年か先のことで、その時にはWin32のアプリは仕様が大幅に変わっていたりして。そうでなくてもどんな仕様でライブラリを作ったか忘れて、また最初からアプリを書きそうな気がする。

2010年08月15日 プログラミング雑談

WindowsのCrypt API

先週から一週間ほど、楽しい仕事をしてました。
本当は私が自分でするべき仕事ではなかったのかもしれませんが、納期に間に合いそうにない気配が濃厚になってきたので手出ししてしまいました。
あまり詳細を書くと職場の人に見つかってしまうので(見つかっても別にヤバイ事は無いのですが、(そうではない人から見て)アニメオタクな話題も書いているので隠れていたいので)概略だけ。

指定されたアルゴリズムでハッシュ値を計算して、そのハッシュ値をキーにしてAES暗号化するプログラムを書く仕事で、Microsoftのサンプルプログラムをベースに試作しました。サンプルにはMD5でパスワードをハッシュして、それをキーにして任意のファイルをRC4で暗号化し、別のサンプルプログラムで復号するというのがありましたので、RC4の部分をAESにしたら簡単に動作させることが出来ました。
ところが、そのようにして作成した暗号が、試験用のツールでエラーになるのです。
なぜ?
先週4日間、職場でも自宅でもそればっかり考えていました。指定されたアルゴリズムを何度も何度も繰り返し読み直しましたし、Windows SDKのCrypt関数の説明も読み直しました。今回はポピュラーなものを作ろうとしていましたので、同じ事をして苦労した話がないかググッたりもしました。
ポピュラーな題材だと思うのですが、今回の開発ターゲットのC言語でのネタはwebでは見つけることが出来ず、JavaやC#のコードをそれぞれ一つずつ見かけました。うーん、私がCで実装したのと同じに見えるなぁ・・・
3日目位に、Windows SDKのCryptDeriveKey()の説明の下のほうに「ハッシュ計算がSHA-2じゃなくて、かつ、暗号化に使うアルゴリズムがAESの場合は計算したハッシュ値をさらに勝手に加工しちゃうよ」(意訳)という記述に気がついた。なんてこったい。RC4で作った暗号は試験用ツールにパスしたので、アルゴリズムだけAESにすればそのまんま動くと信じてたよ。ハッシュ計算は指定されたアルゴリズムでなくてはならないので、勝手にいじられたら困るんですけど。だまされた。
こんなトラブルがなければ1日でできる試作だったのに4日もかかってしまった・・・
[今回の教訓]CryptDeriveKey()には気をつけろ

2010年09月08日 プログラミング雑談

手帳印刷プログラム

そろそろ年末だしなぁと思って、春だったか夏だったかに作っていた手帳印刷プログラムをいじり始めました。
確か、印刷中ダイアログを表示して印刷が中止できるようにするのと、ツールバーを表示するようにするのが当面の課題だったはず。
どちらもチュートリアル本のサンプルの通り作れば直ぐに入れることが出来る機能だったのですが、調べて実装するのが億劫で今日まで延ばしてきました。
とりあえずツールバーはこんな感じ。
スクロールしてもツールバーが消えない
スクロールしてもツールバーが消えないのが当たり前のことなんだけどいざ実現するのが面倒でした。技術的にはチュートリアル本にあるようなレベルなので簡単なはずですが、取り掛かるのが面倒でした。
ただし本当にチュートリアル本レベルで汚く試作した感じですので、あとはきれいに書きなおしてテストプログラムも書いて・・・というところで完成ということにしてしまいたいです。

2010年12月13日 プログラミング雑談

プログラムを書いてみた

プログラムを書いてみたって言っても、ちっちゃいプログラム。
コメントと空行込みで70行くらいの。
プログラムのロジック自体はすぐに書けたけれど、strcpyではなくて_tcscpy_sとかいうところの書き換えと、VS2015だとexeが128KBになるのが気に食わなくて、ビルド方法を調べてたりしたら2日くらいかかってしまった。
趣味だから許されるのんきなスケジュール感だなぁ。
実行ファイルとソースファイル

2016年07月30日 プログラミング雑談

CppUTestと戯れる

このwebページは2008年頃だったかにテキストからhtmlを生成するプログラムを書いて、以降ずっと使い続けています。
最初のうちはcppunitで単体テストを書いてました。このあたりで話題にしていましたね。
最近、また単体テストを書こうかなと思って、前回cppunitを使った時にはmockとか使っていなかったので、mockってのを使ってみたいなぁと思っていろいろググっていました。
どうもcppunitは長い間更新されていないようですね。
google testとかCppUTestとか、新しめのテストツールもいろいろあるようです。
ってことで、CppUTestで単体テストを書くための試作というか練習をしていました。
このページを見ながら右往左往。
何日か費やして、やっと到達したのがこのレベルのソースファイル
なかなか充実した日々だった。

2017年01月08日 プログラミング雑談

mockppと戯れる

mockpp-1.16.6のソースをダウンロードしてmsvc8\mockppの下にmockpp.slnがあるのでこれでVS2015を開いてビルドしてみるとmockppでmockpp_production_44d.libが見つからないと言ってくるのでリンカーの追加の依存ファイルからmockpp_production_44d.libを削除すると、とりあえずビルドが通るみたい。追加の依存ファイル名をmockpp_production.libに変更するのも良さそう。それにしても$(Outdir)がTEMP以下にできるのが面倒だな。

2017年01月29日 プログラミング雑談

プログラムって書かないと忘れてしまうのね

ライフログ的な意味で、レシートをスキャナで取り込んでみた。いや、半年くらい前からぼちぼち取り込んでる。
ファイルのタイムスタンプは当然取り込んだ日付になってしまうけれど、レシートなんだからファイル名くらいはレシートが発行された日付にしたい。
ずっとバッチでrenameしていたけれど、なんか面倒。些細な事なんだけど面倒。
面倒だからこそプログラムの出番だ!ってことで、ちょっと調べたら、最近はC++でも普通に正規表現で検索や置換ができるのですね。それならチョイチョイとファイルをリネームするプログラム位書けそうじゃん!
・・・と、軽い気持ちで書き始めたのだけれど、スキャナのOCRが出力したファイルがUTF-8だったあたりから不穏な空気が流れ始め、ググりまくり。WindowsでC++でUTF-8のテキストファイルを読み込んで、コンソールに出力するのって面倒だということを知りました。imbueって、何?
せっかくC++の標準的な機能で書くのだから、ファイル一覧の取得もできるだけ標準的な方法でやりたいよね・・・と思い、ググると#include <dirent.h>して云々。でもVisualStudio2017のC++で使えません。結局おととし位に書いたWin32ベタベタのコードを引っ張り出してきました。残念。

入力ファイルのUTF-8問題やdirent.h問題を経て、次はregexのパターン指定の型。どうして一致させる方の文字列がstd::wregexで置換する文字列がstd::wstringなんだ? どっちも同じwstringじゃないんかい?とかいう問題にぶちあたり、このあたりだけで3日程度消費。
今日は、javadocみたいなことをしたいなーって思ったので昔だったらDoxygenだったけど、最近は何かあるのかなと思ってググったら出てきたSandcastleっておもしろそう・・あれ?でもこれ、C++はManagedしか使えないんだ? 普通にjavadoc風のコメントならいくらでも書くつもりでいたのに。
最後は、レシートのOCRの変換精度がいまいちなので、日付の検索パターンをいくつか持っていた方が良さそうなのでvectorとかtupleとか使おうとしたら、2年ぶりぐらいなものですっかり忘れていてショック。
一応当初目標にしていたツールはできたから良いことにしよう。
メソッド一つ書くだけならばロジックに閉じた話だから簡単だけど、コマンドラインとはいえユーザーインターフェースがあり、最終的な入出力ファイルがあるアプリとして一通り入ったものって純粋ロジックではないから面倒。
ソースファイルはこんな感じ。
ワイルドカードで指定したUTF-8テキストファイルに書かれた日付を抽出して、ファイルをrenameするバッチファイルをつくるつもりのファイル。標準出力に出力しておいて、後処理で*.txtを*.pngに書き換えて、スキャナで取り込んだイメージファイルもまとめてrenameするの。

2018年12月15日 プログラミング雑談

このwebページのメンテ

毎年一度のこのwebページのメンテナンス。
過去ログのページの2019年分を作成して、2019年のページに飛ぶリンクを追加する。
今はテキストファイルを書くとhtmlを生成するようにしていますので、テキストエディタでちょこちょこっと飛び先をコピペするだけなので簡単・・・なはず。
でもめんどくさいなー。年末のテンション上昇期ならばここも自動化するプログラムを書く元気があったかな?
でもこの件はこのwebページの原稿を自動生成するって話だから、どういう仕様にするか決めないといけないからめんどくさい。って言うか、どういう原稿フォーマットにすればいいのか思いつかない。

2019年01月12日 プログラミング雑談

久しぶりにcurlなど使ってみた

東京電力のくらしTEPCO、スマートホームプランだと時間毎の電力使用量がダウンロードできるのだけれど、いちいち一日分ずつダウンロードするのが面倒なので、昔ちょっと遊んだことがあるcurlでバッチ化にトライ。
こんな感じのバッチファイルになりました。

@echo on
set user=ユーザーネーム
set password=パスワード
.\bin\curl -c cookie.txt -d "ACCOUNTUID=%user%" -d "PASSWORD=%password%" -d "HIDEURL=/pf/ja/pc/mypage/home/index.page?" -d "LOGIN=EUAS_LOGIN" -v "https://www.kurashi.tepco.co.jp/kpf-login"
.\bin\curl -b cookie.txt "https://www.kurashi.tepco.co.jp/pf/ja/pc/mypage/home/index.page?" -o "_111.html"
.\bin\curl -b cookie.txt "https://www.kurashi.tepco.co.jp/pf/ja/pc/mypage/learn/comparison.page?" -o "_112.html"
.\bin\curl -b cookie.txt -c cookie.txt -d "termRadio=time" "https://www.kurashi.tepco.co.jp/pf/ja/pc/mypage/learn/comparison.page?" -o "_115.html"
.\bin\curl -b cookie.txt "https://www.kurashi.tepco.co.jp/pf/ja/pc/mypage/learn/comparison.page?ReqID=CsvDL&year=2019&month=2&day=10" -o "20190210_comparison.csv"

これで最後の行の一日分のファイルをダウンロードする行を延々とコピペして日付だけ進めていっても良いですし、forみたいなループを書いても良いし、色々楽しめるのではないかと。

2019年03月29日 プログラミング雑談

デジカメ写真からカメラ名を取り出す

初めてデジカメを買ったのがどうも2003年末らしいので、かれこれ15年以上。
数えてみると20,000枚以上あるみたい。
この間、デジカメは6台。ケータイ、スマホも含めるとどれだけのデジカメを使ってきたのやら。
撮影したその場で撮影の失敗に気が付いて削除した場合を除いて一通りの写真はPCに保存してあるのだけれど、ふとデジカメごとにファイル名を変えようかなとか思ってしまった。
今はほとんどの写真がIMG_数字.jpgという形式のファイル名なのを、カメラごとにIMGの部分を変えようという発想。
カメラごとにファイル名を変えたら何か嬉しいことがあるわけでもないけれど、同じファイル名の写真が6枚とかあるのも気持ち悪い。
だいたいは写真の撮影時期でどのカメラか見当はつくのだけれど、写真一枚一枚、右クリック→プロパティ→詳細 でカメラ名を確認するのは20,000枚という枚数を前にするとやる気にならない。
ふと思い立って、JPEGファイルのExifからカメラ名を取り出すコマンドラインプログラムを書いてみた。
C++のifstreamってJPEGファイルをバイナリで読もうとするとちょっとだけ面倒。
最初はググってファイルの先頭からExifがある前提で書いてたけれど、デバッグ用にgimpで小さいjpgファイルを作ったらJFIFが先に来るファイルが出てきたので、それに対応しなきゃ、とか、昔スキャナで取り込んだ写真はなぜかExifにカメラ名が入っていないのでその対応とか、ちょっとはC++っぽいコードにしたい・・・とか、いじっているうちに土曜と日曜が終わってしまいました。
実行ファイルはこれです。
Windowsのコマンドラインから、ExifList jpegファイル名 で実行すると、指定したファイル名とカメラ名が表示される、というもの。
dir /s /bで取り出したファイル名からjpegファイルだけ抽出して、一つ一つこのプログラムでカメラ名をとりだせば、20,000枚のファイルも10分くらいで完了。
今までPowerShot G7では1000枚くらいしか写真を撮っていないと思っていたけれど、途中でファイル番号をリセットしていて、リセット前の写真が追加で1000枚以上あることが判明。これはちょっと予想外。

2019年06月02日 プログラミング雑談

ファイル分割ツールなど作ってみる

こんどはWindowsで動くファイル分割ツールなど作ってました。
最近のWindows界隈のGUI環境について疎いので、ググったところ、C++の場合はC++/WinRTというのがよいらしい。ってことで、VisualStudioでC++/WinRT関連モジュールをインストールしよう・・・あれ? C++/CXとかいうのはあるけれど、C++/WinRTってのがないぞ。
結局はVisualStudioインストーラーではなく、VisualStudioのIDEのメニューの拡張機能からインストールするらしい。
で、インストールしてみたのだけれど、WinRT拡張を入れるとVisualStudioが非常に重くなるみたい。メモリー8GBでは足りないというのか!でもこのPCの最大メモリーは8GBだった気がするし。あ、調べてみたらノートPCは8GBだけれど、古い方のミニタワーの方は16GB載るみたい。でも今使っている8GBを捨てて新規に8GBメモリーを2枚買わなくてはならないのがもったいない。
そのうえWinRTって実行ファイルをコピーしてきてダブルクリックで実行という手軽さがなくて、いちいち配置(インストールのことらしい)をしなくては実行もできない模様。面倒だなぁー
ってことで、重いのと面倒なのでWinRTはアンインストールすることにしました。
で、半日WinRTと戯れた後、ファイル分割ツールの作成にとりかかりました。
最初はいつもの通りWindowsのコマンドライン版で。
ハードコードしたファイル名を使用。コマンドライン引数でもよいのだけれど。
最初はファイルのコピーのプログラムを作って、その後に分割するように仕様変更。
ファイルを分割したら結合用のバッチファイルも作りたいなぁ。
やっぱりGUIがあったほうがいいよね。Windowsのコモンダイアログで分割するファイルを選択すると楽だよね・・・とかやってました。GUI版は結局WinRTではなく、古典的なWin32APIを使用。
結局土曜と日曜の合計2日間をこれに費やしてしまった・・・。充実した週末だった。ということにしておこう。
プログラムを作るという点では、機能の本体であるところのファイル分割はすぐにできた感じがするのですが、WindowsのGUI部分・・・最初はモーダルダイアログで作ろうとしたのですが、メインウインドウが消せない、いや、モーダルダイアログと同時にメインウインドウを終了させる方法がわからないので、ダイアログボックスで作成。
ボタンを押すとファイル分割開始なのだけれど、2〜3分ダイアログボックスが操作不能になるのが気になる。
スレッドにするとよいらしい・・・でもボタンが押されたらスレッドを作るとスレッドの変数的な意味でのスコープが狭くなるので変なエクセプションが出るとか、ファイルの分割が完了したことをダイアログボックスを見ててもわからないとか、そういう当たり前の使い勝手の実現にとても時間がかかりました。
ファイルの分割中に中断したくなったらどうする? とか。
結局こんな感じになりました。
実行ファイルはこれです。
7月7日版はこれです。
コードはスパゲッティなので秘密。まだ記憶があるうちにDoxygenコメント書いたり、設計を見直したりしたい。

2019年06月30日 プログラミング雑談

ファイル分割ツール、Vectorにアップしてみる

ファイル分割ツール、たまにアプリっぽいのを作っていたら面白かったので、公の場に公開してみようかなってことで、Vectorにアップしてみました。最近は既に窓の杜とかVectorは廃れている感じもしますが、Sourceforgeってなんか敷居が高い。
Vectorの作者登録して、さっきアプリをアップしてきましたが、公開は数日後らしいです。人間が審査しているのかしら。
たかがファイルを分割するだけのアプリなのに、公開しようかなと思った途端にエラーメッセージやその他あれこれ使い勝手の改善をやらなくてはという感じがして、ファイル分割機能は1日で作ったのに使い勝手の改善で3週間って感じ。なんか疲れた。
作りこみでいろいろ勉強させていただきましたわ。書籍 プログラミング言語C++に書いてあったこれは、こういうところで使うんだ!という事とか、単体テストフレームワークとしてBoost_Testを使ってみたりとか、OpenCppCoverageとかいうC0カバレッジ測定ツールまで使ってしまいましたよ。

そんないろいろなツールの中で、びっくりしたのはOpenCppCoverageの簡単さ。
Boost_Testで単体テストを書き始めていたので、そこからカバレッジを見るまでがあまりに簡単でびっくりしました。ツールをインストールして、コマンドラインから実行するだけで、html形式のレポートページが出来上がりました。カバレッジツールの出力って面白いですよね。ここを通すにはこういうテスト条件が必要だけれど、テストを書くのがなんかめんどくさい・・・とかネガティブな事を思いながらも、なんかカバレッジ100%を目指さなくてはならないような気分になります。
でも、今日は疲れたのでまた今度。
カバレッジを通すのも面白そうだけど、Doxygenコメントを先に書いてしまいたい。それと、設計の見直し。
設計の見直しとかする前に、まだ21章までしか読んでないプログラミング言語C++を読み終わったほうがいいかなぁ。

2019年07月14日 プログラミング雑談

MFCで遊ぶ

2020年ですね。すっかり更新をさぼっていました。
だいたいツイッターでつぶやいていると、ここに書くまでもないかな、と思ってしまうのですよね。
さてさて、3連休のようです。世間では新型肺炎の話題で持ちきりで、こんな時にあちこち散歩などして普通に風邪をひくだけでいろいろ面倒な状況になりそうなので、比較的天気が良かったにもかかわらず部屋でおとなしくしていました。
ヒキコーモリな三連休、なんかプログラムを書こうという気になりましたので、半年前に作ったファイル分割プログラム、UIがダメダメなので、作り直すことにしました。
ググった感じだとfltkとかWin32++とかwxWidgetsとかWindowsで使えるUIライブラリがあるようですので、それでUIを作り直そうかなとも思ったのですが、一応MFC位知っていた方が良いかなって思ってMFCで作ってみました。
大昔、C++もWin32APIも知らない時に学ぼうとしたMFCはハードルが高すぎて全然使えませんでしたが、今ならばなんとか使えなくもない・・・。
ってことで、2日くらいべったり作成してました。
MFCでUIを全面作り直ししたものはこんな感じ
デバッグ中に、半年前に作ったバージョンでメッセージを取り違えていたバグを発見。それも修正してベクターに登録申請して、アイコンも作りたいなぁと思ってググりながら悪戦苦闘。結局gimpでpngの24bit、1alphaチャンネルで作成すると大きなアイコンも使えるみたい・・・。レイヤーごとにイメージのサイズを変えなければならないとか、罠が多すぎ。
近いうちに備忘録を残す予定。

2020年02月23日 プログラミング雑談

WinAppDriverってWin32アプリもUIテストできるのね

アプリを書きながら、UIを含むテストってめんどくさいなって思っていました。
UIのテストもお手軽に自動化できないかなとずっと思っていましたが、UIテストって自動化した経験が無いですし、VisualStudioでUIのテストって有料のエディションでしか使えないと思っていました。
UWSCみたいな操作ツールの存在は知っていましたが、バッチみたいにGUIアプリを操作できてもそれとテストの結合ってどうやるのか見当もつきません。
で、GUIのテストについてググったら、WinAppDriverってのがヒットしました。これって.NET環境が必要だし、面倒そうだったのでスルーしていました。
今日、ちょっと気分がよかったのでダウンロードしてサンプルを動かしてみました。
なるほど、C#でWin32アプリのテストを書けるってことですね。C#以外でもjavaでもWin32アプリのテストが書けるみたいですね。
VisualStudioの統合環境でロジックの単体テストとUIの自動テストがまとめて管理できるのは魅力的かもしれない。
ノウハウを身に着けるまで大変かもしれないけれど、使いこなすことができれば使えるツールなんでしょうね。

2020年02月24日 プログラミング雑談

WinAppDriverでWin32 MFCアプリのテストとか

新型コロナウイルス騒動で休日も外出を自粛しておりますです。
休日は部屋にこもってファイル分割アプリのMFC化したものをWinAppDriverで自動テスト化に取り組んでおりました。
C#を知らないのでそっちの方がいろいろ面倒。
C#アプリからファイルにアクセスしたり、exeファイルを実行したりというやり方をググったりしていました。
今のところC#はWinAppDriverでSelenuimのI/FでMFCのGUIを操作する、という事に使っているのですが、エディットボックスに文字を入力するのが遅い。いや、手で入力するのに比べれば格段に速いのですが、いわゆる単体テストでルーチンをたくさんテストしても1秒とかで完了しますし、コマンドラインアプリをいろいろ引数を切り替えて何度も呼んでも数秒で完了するのに、GUIアプリでエディットボックスにフルパスでファイル名を入力するだけで2秒とか3秒とかかかるのがちょっと遅いなぁって。
SendKeys()が遅いのならばクリップボード経由でファイル名をコピペすればいいじゃない?
ってことで、C#でクリップボードにファイル名を入れるにはどうすればいいかググったところ、System.Windows.Clipboardとかいうクラスだか何だかがある模様。なんだか煮え切らない書き方なのは、C#のUnitTestプロジェクトではこのクラスだか何だかが使えないらしいから。Windows formアプリとかそういったGUIアプリのプロジェクトなら使えるんだけど・・・
ググっても同じ悩みが見つからないので、きっとC#が使える人にとっては容易に解決できる問題なのに違いない。でも、私のターゲットはとりあえずC++方面なので、新にC#を勉強する優先順位は高くない。
んー、ファイル名をクリップボードに入れるだけならそういうコマンドラインアプリを書いて、C#から呼び出しちゃえばいいじゃん
ってことで、そういうプログラムを書きました。20行くらい。ああ短い。
クリップボードに送り込む文字列を入れるメモリーをGlobalAllocしてGlobalLockしてmemcpyなりwcscpyなりしてGlobalUnlockしてOpenCLipboardしてSetClipboardDataしてCloseClipboardするだけ。
なんでもGlobalFreeはシステム側でやってくれるのでアプリ側ではGlobalFreeしてはいけないらしい。
確かにVisualStudioでデバッグモードで動かすとExceptionが出る。
ああ、でもGlobalFreeしなくてもアプリをreturnした後にExceptionが出てしまう(涙)。これはきっとデバッグさえしなければ問題ないに違いない。

Windowsにはclipコマンドなるものがあることは存じております。
でも、toClip.exe ファイル名 みたいなコマンド一発でファイル名をクリップボードに登録できるとあとはSendKiys(Keys.Control + "v");で完了って世界も捨てがたい。
そんなこんなで、今週末もきっと私は引きこもってプログラムを書いているに違いない。

2020年03月27日 プログラミング雑談

eclipseでselenideのチュートリアルをやってみた

本当はデジカメ写真をスマホやデジカメからPCに転送するアプリを書かなきゃと思っているのですが、なんかやる気にならないので現実逃避。
仕事でブラウザで表示するドキュメントがあるのですけれど、そのドキュメントの自動テストってできるのかなぁ?ってあたりを調べてみてました。
sikuliとかいうのがあると聞いたことはあります。半年くらい前からPCのダウンロードフォルダにsikuliのインストーラーは入っています。でも、なんか取り掛かる気分になれないままです。
今回は、「web ui テスト」などのキーワードでググったらselenideとかいうのがヒットして、なんか面白そうだと何故か思ってしまったのでeclipseでselenideのチュートリアルが書いてあるサイトを見ながらチュートリアルに入門していました。
私はeclipseの初心者だという自覚はありますので、手取り足取りって感じの粒度で記載されているところを見ながらやってみました。
結論から申し上げますと、土曜日が一日つぶれましたが、それでやっとチュートリアルを動かすことができました。
eclipse初心者ですので、実は、Mavenって知りませんでした。あと、自動テストなんてかっこいい事言っていますが、junitすらチュートリアルサイトを見ながら、よちよち書いた程度の知識しか持ち合わせていませんでしたので、selenideはとってもハードルが高かったです。
何が大変って、selenideのチュートリアルサイトに書いてある通りMavenでライブラリを準備しようとしても、謎のエラーが消えない。
私が今まで見てきたチュートリアルレベルのサイトであれば、だいたい書いてある通りやれば解決するものですが、こればっかりはダメでした。
selenideのチュートリアルっぽいサイトをいくつか渡り歩きましたが、解決せず。
結局eclipseのエラーメッセージを見ながらjarの取得に失敗するものに対して「Mavenキャッシュ削除:.m2以下にmavenキャッシュがあり、それを削除。」を繰り返し、やっと環境が作れました。
あとは「open("/calc.html");」とかしれっと書いてあるのですが、calc.htmlが開けないのでこれも困りました。こちらは結局「Configuration.baseUrl =」でhtmlが置いてあるフォルダを指定すれば良さそう。
あとはInternet Explorerで動かすための設定もググりまくりでした。
結局土曜日の夜11時くらいにやっとチュートリアルが動きました・・・長かった。チュートリアルってサイトに書いてある通りタイプして操作すれば1時間くらいでできるんちゃうの?って感じの一日でした。
でも、結局動いたからなかなか充実感がありました。

2020年05月17日 プログラミング雑談

eclipseでselenideでリンク切れチェック

先週Selenideってのが面白そうだなと思ってチュートリアルのサンプルを動かすところまで試して、今週は少し自分で何か書けるところまで行きたいなと思ってました。
そして、なぜか、土日の休みが終わった段階で、このwebページの、ローカルファイルの段階のリンク切れチェッカーを書いていました。
暫定アップしておきます
あれ、ここに書いていないかな。ちょっと衝動的にPCのモニターを1920x1200の24インチから、4Kの24インチに買い換えました。
マザーボードのグラフィックが4Kに対応していませんでしたので、グラボも買いました。安いやつ。
eclipseやVisualStudioでゴシック体はゴシック体っぽく、明朝体は明朝体っぽく表示されるのって素敵。とか思っていたら、なんと、先週チュートリアルのサンプルが動いていたはずのSelenideが動かなくなっていました。ググること2時間ちょっと。なんと、私はモニターを買い換えて、画面表示を200%拡大にしていたのですが、このモードではSelenideでIEが使えない模様。
しばらく100%表示の小さな文字と200%のSelenideが使えないモードを切り替えながら使っていましたが、もう無理ってことで、firefoxやchormeでSelenideを使うことにしました。
4Kモニター化はこの他にも自作ツールのchmファイルの文字が小さくなって、文字の大きさを直すために試行錯誤してたり、思わぬところでトラブルがポコポコ出てます。まあ最大のトラブルは前述のSelenide動かない事件だったりするのですが。

2020年05月24日 プログラミング雑談

隠しファイルや空フォルダをリストする

VisualStudioのC++でWin32コマンドラインでちっちゃい道具を必要に応じて作ってたり。
昔のSTLのFIlesystemって絶対パスと相対パスの変換が出来なくて、文字列的につなげたりして回避してましたが、最近は普通にできるようになったのですね。
ってことで、隠しファイルや空フォルダをリストするコマンドラインexeをお試しで書いてみました。

2021年07月03日 プログラミング雑談

Playwrightでリンク切れチェック

以前、Selenideというツールでこのサイトのリンク切れチェックを書いたことがあるけれど、最近はPlaywrightというツールがあるそうなので使ってみました。
Node.jsやjavaやPythonや.netで使えるみたいで、きっと最近の若い人ならばPythonなのだろうなと思いながら、今回は.netのC#でやってみました。
codegenが非常に便利で、とても入門しやすい感じですね。
で、リンク切れチェックを書いてみたわけですが、リンク切れUrlを踏んだ時に、どのUrlがリンク切れだったか取得するのにpage.Uriでとれるのは"chrome-error://chromewebdata/"という文字列になってしまってUrlがとれない。
はて困ったということでPlaywrightのサイトをあちこち見ながら数時間。結局、page.Uriで"chrome-error://chromewebdata/"が返ってきたらpage.TitleAsync();でブラウザのタイトルに入っている文字列を取得すれば良いみたい。
他のブラウザを使う時には書き換えだな・・・・

2022年03月05日 プログラミング雑談

Selenium.WebDriverは新しくしすぎないように

休みなので何かしなきゃ!ってことで、特にやりたいことも無いけれどVisualStudioを起動。
boostもアップデートされたみたいなので入れ替えたり、NuGetで新しい依存パッケージに入れ替えてみたり。
そしたらWindowsWebDriverを使ったテストがビルドエラーになってしまいました。
WindowsDriver<WindowsElement> m_AppSession; がダメと言われてしまうとどう直せばいいのやらって感じ。
ググった結果、Selenium.WebDriverは新しくしすぎてはいけないみたい。今は4.4.0とか出ていますが、4未満にしなくてはならないみたい。3.141.0に戻したらとりあえずエラーは消えました。

そういえばWindowsWebDriverからWindows.Automationに切り替えようと思ったけれど動かし方を確認したところで中断していました。今動いているテストを別のプラットフォームで作り変えるというモチベーションが無くて。

2022年08月11日 プログラミング雑談

久しぶりに昔書いたプログラムをコンパイルしたらテストがこける

競馬、先週の阪神のメインレース、ジュベナイルフィリーズでキタウイングが95.0秒で負けて春の新潟開催まで競馬はお休みしようかなと思い始めた今日この頃。
久しぶりに昔書いたプログラムをメンテしたり開発環境をアップデートしたりしようかなと思ってPCの前に座っていました。
いくつかトラブルに出くわしたので備忘録

1.Doxygen

Doxygen 1.9.5ってのが出てたので1.9.4からアップデート。1.9.4はファクトリーメソッドでunique_ptrを使うとcall graphに出ないから、そのあたり出るようになってたらいいなぁと思ったけれど、1.9.5でそのあたりを確認する前にUML形式のクラス図が変になっていたので1.9.4に戻しました。
GraphVizも一緒に7.0.4にアップデートしてたのでどっちが悪いのか調べるのがちょっとめんどくさかった。

2.UI Automation

Win32のUIアプリケーションをテストするためにUI Automationを使っていて、MSTest.TestAdapterとかMSTest.TestFrameworkとか使っていますが、3.0.0にアップデートしたら「実行プログラム 'executor://mstestadapter/v2' の呼び出し中に例外が発生しました」とか出てきてテストが動かなくなってました。ググったところ3.0.1で直る模様。とりあえず2.2.10に戻して直るのを待つことにします。

3.Windowsの「開く」コモンダイアログ

Win32のUIアプリケーションのテストで、テスト対象のアプリケーションはファイルを開くので、ファイルを「開く」のコモンダイアログを使っています。
このダイアログの「開く」ボタンが最近新しくなったようで、テストで「開く」ボタンが押せなくなっていました。
「開く」ボタン
隣の「キャンセル」ボタンとは違う方法で押さなくてはならない模様。恒久的なテストの修正方法は未定ですけど、とりあえずテストが動くように修正しました。

4.Playwright実行後のコンソールの文字コード

PlaywrightでJRAサイトの馬柱データをcsvに出力しているのですが、そのplaywrightのプログラムを1回動かすと起動したコンソールのロケールなのか文字コードなのかわかりませんが、何かが変わってしまってバッチがエラーになる問題が発生。
とりあえずplaywrightの処理を呼び出した後はchcp 932してコンソールをSHIFT_JISに戻して回避することにしました。
あ、playwrightのせいみたいな書き方をしてしまいましたが、.NET Frameworkのコンソールプログラムの文字コードの話ですね。これは。

2022年12月18日 独り言

JRAサイトから出馬表データを持ってくるプログラム書いてた

競馬、12月のジュベナイルフィリーズでキタウイングが負けて春まで競馬はお休みと思っていたけれど新年のフェアリーステークスで勝っていたので春までお休みできませんでした。
まあ馬券は穴狙いなので全然当たらず、というところ。
細々とJRAの出馬表データをローカルのPCに持ってくるプログラムを書いていたりしてます。
3月末からちょっと気合い入れて、C#からjavaに書き換えたり、出力をCSVではなくてXLSXファイルにしたり、1レースの処理に25秒くらいかかっていたのでPlaywrightでパースするのをやめてJsoupに置き換えたり、SQLiteのデータファイルの読み書きができるように試作したり・・・・で、月日はどんどん流れていきます。
2〜3年前に買ったような気がするノートPCも私の手元に帰ってきましたので、このPCには開発環境はインストールせずに普通のクライアントPCとして競馬場に持っていけるように環境をいじっていました。
JREはインストールしてもいいけど.netは何となくインストールしたくなかったのでC#からjavaに書き換えていたわけですが、いろいろ勉強させていただきました。
C++とc#とjavaでコンテナの使い方、宣言とか初期化とかメソッドとかがいろいろ違ったような気がします。どう違ったかはほとんど記憶に残っていないのが年寄りの困ったところ。
playwrightでパースすると遅いのであの手この手を試作してみましたが、htmlのwebページはDOMやXPathではエラーになってしまうことを知ってちょっとびっくりしたりもしました。
いろいろなライブラリをリンクしたら実行ファイルのjarは巨大になってしまいました。
ソースファイルはこんな感じ。

2023年04月22日 プログラミング雑談

Jsoupの使い方がよくわかんない

このWebページを生成するプログラムをC++11以前の古いC++で作っていたのをjavaでjsoupを使って書き換えようという気分になって書き換え始めたのだけれど、jsoup自体初心者なので細かい問題にぶつかってばかり。
最初はjsoupでnodeとかdocumentとかelementとかの使い分けがわからないところからスタートしているのでjavadocっぽいドキュメントを頑張って読んでいました。
その後はxmlヘッダーやドキュメントヘッダーの付け方に悩み、今は改行の付け方に悩んでいます。
一応このページはXHTML 1.0 Strictで作っているので、改行は<br />なのですが、appendElement("br /")だと閉じタグが生成されて<br /></br />になってしまうんですよね。
appendElement("br")ならばならば閉じタグが作られず<br>だけが生成されるのに。
もしかしてjsoupでこれはxhtmlだとかhtml5だとか教えることができて、その辺の設定ができるとうまいことやってくれるのかしら?
(追記)やっとわかった。XHTMLだから、jsoupをhtmlモードではなくxmlモードで動かさなければならない模様。

doc.outputSettings().syntax(Document.OutputSettings.Syntax.xml);

してからdoc.outerHtml();すれば良いんだ!
とりあえずXHTMLの骨組みはこんな感じで生成できそう

doc = new Document("");
XmlDeclaration xmlDecl = new XmlDeclaration("xml", false);
 
xmlDecl.attr("version", "1.0");
xmlDecl.attr("encoding", doc.charset().displayName());
DocumentType docType = new DocumentType("html", 
"-//W3C//DTD XHTML 1.0 Strict//EN", "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd");
 
doc.appendChild(xmlDecl);
doc.appendChild(docType);
 
Element html = doc.appendElement("html");
html.attr("xmlns","http://www.w3.org/1999/xhtml");
html.attr("xml:lang","ja");
html.attr("lang","ja");
Element head = html.appendElement("head");
head.append("<meta name=\"viewport\" content=\"width=device-width,initial-scale=1.0\" />");
head.append("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />");
head.append("<meta http-equiv=\"Content-Style-Type\" content=\"text/css\" />");
doc.title("MyPage");
Element body = html.appendElement("body");
 
Element ddd = body.appendElement("div");
ddd.appendChild(new Comment("Comment Node"));
ddd.appendChild(new TextNode("TextNode"));
ddd.appendElement("br");
ddd.appendText("&");
 
doc.outputSettings().indentAmount(0);
doc.outputSettings().syntax(Document.OutputSettings.Syntax.xml);
 
doc.outerHtml();

誰かのお役に立てれば。

2024年01月13日 プログラミング雑談

VSCodeでmavenでJUnitとかjacocoとか

割と最近までVisualStudioでC++の人だったのでjavaとかVSCodeとか、何かしようとするたびに壁にぶつかる今日この頃。
ググりまくりなのだけれど、右も左もわからない初心者なのでググるキーワードが多分不適切なのでしょう。全然情報が見つかりません・・・(涙)
VSCodeでExtension Pack for JavaとかMaven for Javaを入れて、簡単なコードを書いて、JUnitのテストコードを書いて実行してみてます。
コマンドパレットで"Maven Execute Commands..."で"install"を実行すると多分実行jarを作ってくれて、JUnitのテストを実行してくれて、カバレッジまで測ってくれるようです。ステキ。
そしたら間もなく
[WARNING] Rule violated for method com.segu.Index.addText(org.jsoup.nodes.Element, java.lang.String): complexity total count is 7, but expected maximum is 5
とか言われ始めました。
悪かったね! どうせ私のコードはスパゲッティだよ! とか思いながら、とりあえずcomplexityのmaximumを8とかにすれば良いんでしょ?ってことで、VSCodeのsettings.jsonとかに何か書けばいいんだろうなと思いながらググること何時間?。結局解決策がわからず、
[ERROR] Failed to execute goal org.jacoco:jacoco-maven-plugin:0.8.4:check
で"install"がエラーになってから手動でJUnitのテストを実行してました。
pom.xmlを見ると

<maximum>${jacoco.unit-tests.limit.method-complexity}</maximum>

という行があったので、method-complexityというパラメタ名でググったけれどわからず。
あきらめてcomlexityのチェック行をpom.xmlから全削除するという暴挙に出てERRORを回避して何日か過ごしました。
で、
別件でpom.xmlを見てたら

<jacoco.unit-tests.limit.method-complexity>5</jacoco.unit-tests.limit.method-complexity>

なんて行があるではないですか。なんだ、pom.xmlの中で上限値を設定してたのかよ!ってことで、ここで上限値を8とかにしたらWARNINGもERRORも消えてすっきり

で、さらに私の前に(多分客観的には低い)壁が出現するわけですよ
JUnitのテストはlog4jで何のテストを実行したかログを出力したいので、log4j2.xmlが見えるようにクラスパスを設定したいのだけれど、どうやったら設定できるかわからずに半日ググった結果、このサイトを見つけました。
いや、見つけたってなんだよ。VSCodeのMavenプラグインが設定してくれたpom.xmlにmaven-surefire-pluginって書いてあんだから、surefireのオフィシャル見に行くのは当然だろ!って気もしますが、わかんないことばかりでどこを見に行って何を読めばいいかわかんないんですよ....と言い訳しておきます。
私はプロジェクトのルートにlog4j2.xmlを置いているのでpom.xmlに次のように書けばよいみたいです。

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-surefire-plugin</artifactId>
  <version>${maven-surefire-plugin.version}</version>
  <configuration>
    <additionalClasspathElements>
      <additionalClasspathElement>./</additionalClasspathElement>
    </additionalClasspathElements>
  </configuration>
</plugin>

数日経つと忘れちゃうんだろうなという事で記録を残してみます。備忘録かよっ

2024年01月20日 プログラミング雑談

javaで正規表現

このページをテキスト形式からhtmlに変換するプログラムはC++で2009年に書いたものです。
これをjavaでjsoupを使って書き換えようと思い始めて多分2週間。
機能実現検証用の試作が動きました・・・。
もう若くないので夜更かしはできないし、平日昼間は仕事だし、このwebページをjava版の変換プログラムで作るのは2月に入ってからかなぁ。
秀丸の置換とかsedとかgawkで正規表現を便利に使っていますがjavaの場合のやり方を少しメモ。

Pattern pattern = Pattern.compile("^[ \t]*&([^:]+):") ;
Matcher matcher = pattern.matcher(inLine);
if(matcher.find()) {
    if(matcher.group(1).equals("end")) {

とかすると、"&end:"が検出できる模様。Patternの行からfindの行までは1行で書けるので、それなりにすっきり書くこともできるのですね。
はまったポイントは数字とマッチする"\d"は"\"自身がエスケープ文字なので"\\d"と書かねばならないとか、find()まで実行しないとgroupが使えないところですかね。

2024年01月21日 プログラミング雑談

java版のこのwebページ生成ツール 仮運用開始

正月が明けてからテレビアニメも見ずにプログラムを書いていました。
タイトルの通り、今日からこのwebページのhtmlはjavaで作り直したプログラムで生成を開始しました。
ページの見た目はcssファイルの方なのであまり変わっていないはず。個々のアーティクルへのリンクは極力従来通りに生成できるようにコードを書いたので、htmlの方もhtml自体をテキストエディタなどで見比べない限り(見比べても)わからないのではないかな。
もちろん何もないところからwebページのhtmlが出てくるわけではないので原稿があります。原稿はテキストファイルです。今回java版を作って従来の原稿を流すまで気が付きませんでしたが、これまでShift-JISファイルを使っていましたが、今回はUTF-8 BOM無しのテキストファイルを原稿の文字コードにしました。
その他、原稿のリンクや箇条書きなどはマークダウン風の記法にしました。今まではいくつかの独自記法でコード記載ブロックを切り分けていましたが、その他は原稿にhtmlタグを書くというweb黎明期でもほとんどはやらなかったであろう地味な作業をしていましたが、これももう不要です。改行のbrタグすら手書きだったものなぁ。
今回取り入れたマークダウン風の記法は

あたりです。
いままでコード記載ブロックの処理にバグがあって空行が表示されていませんでしたが、これも表示されるようになったはず。しばらく気が付きませんでしたが、気が付いた時に空行ではなくスペース一つ入力して回避してたりしました。
htmlのエスケープ文字もjsoupが自動で変換してくれるはず。
コーディング上は、15年前のC++版でも途中まで単体テストを入れていましたが、コーティングが進むにつれてメソッドの複雑度が上がってテストを書くのを断念してしまっていました。それだけでなく15年の歳月の間に流行りのc++テストツールが世間的に交代してしまったようで、その意味でもテストを書いて動かし続けるのが困難な状態でした。
今回はメソッドのコード複雑度(サイクロマチック)5以下でここまで作り切っていますので、今度こそ単体テストを後付けで作っていけるはず。
たくさんコードを書いたようなつもりだったけれどかぞえチャオで数えたら1,500ステップもなかった

2024年01月29日 プログラミング雑談 このページのリフォーム

サイクロマチック数 max 5の世界

久しぶりにプログラムを書くといろいろ勉強になりますね。
今回の一番の収穫はメソッドのサイクロマチック数をmax 5で作るのも良いものだ、という事を実感したことかもしれません。
最初はmavenの環境をチュートリアル見ながら構築したらデフォルトでそのような設定になっていたというだけなのですが、これがデフォルトという事は何か意味があるに違いないと思ってmax 5縛りで作ってみました。
最初に影響が出たのがswitch文。こんなの使うとあっという間にサイクロマチック数5を超えてしまいます。ファクトリーメソッドで処理を切り分けるようにしました。ファクトリーメソッドでもファクトリー部分で分岐が出ないようにArrayListとかに選択肢を詰め込んでおいてget(key)で探したりforeachで探したり。
次にif文の使用。メソッドの責務をシンプルにして、メソッドの上から下まで条件分岐なしでいかに流しきるか考えるようになりました。今回作っていたプログラムは、テキストファイルを読み込んでhtmlに変換して書き出すというシンプルなコマンドラインプログラムでした。メソッドの入り口で「入力ファイルを確認する」みたいなメソッドでチェックして、NGならエラーリターンし、その後の処理は余計なことは考えずに上から下まで一気に流す、みたいなスタイルになっていきました。

そのうちメソッドのサイクロマチック数 max 5はまあ普通に守れるようになってきましたが、次にクラスでmax 20という条件で引っかかるようになりました。メソッドが1つあればサイクロマチック数も最低1あるという数え方ですので、クラスのメンバー変数がいくつかあってsetter、getterを書き始めるとたちまち超えます。setter、getterは今回はあまり書かないで作ってみました。これが正しい対処法かどうかわかりませんが、
それよりも「もし入力ファイルが無かったら」はFileReaderクラスの責務、「もし入力ファイルの記載が間違っていたら」は処理するクラスの責務、みたいにクラスの責務を整理して、一つのクラスで処理しなければならないメソッドを減らすことに注力してました。
テキストファイルを読み込んだり、htmlをファイルに書き込んだりするのはhtmlを生成するクラスの責務ではないよね、ということで、ファイル読み書きは別クラスに切り出したり。

おかげで単体テストコードも書きやすいです。まだあまり書けていませんが、これまでコードの構造のせいでテストが書きにくいといった事には出くわしていません。
まだ単体テストを一通り書いていないのにこんなことを言うのもなんですが、単体テストってプログラマーの意図通りコードが書けているかどうかのテストなのだなぁと実感していました。単体テストが通っているのに出力されたhtmlファイルが意図通りではないことが頻発しています。これはplaywrightみたいなツールで結合テストするしかないのかもしれないですね

そうそう、サイクロマチック数とは関係ないかもですが、今回は(今回こそ)設計書をちゃんと書くぞと(まだ)思っています。DoxygenとかplantUMLとか使ってちまちま書いています。
私が飽きるのが先か、テストや設計書を作り切るのが先か、どうなるんでしょうね?

2024年02月04日 プログラミング雑談

jsoupで最初つまづいたところ

今度のお休みに書こうと思っていることをメモ
jsoupで私のwebページを書こうとして結構ずっと混乱していたのがappendChild()とappendElement()の使い方。

Element ddd = new Element("body");
ddd.appendElement("div").attr("name", "segu");

と書くことはできるけれど

Element ddd = new Element("body");
ddd.appendChild(new Element("div")).attr("name", "segu");

と書くと多分思ってたのと違う結果になる。
前者は<body><div name="segu">で
後者は<body name="segu"><div>になるはず。
jsoupのAPIリファレンスに書いてある通りだし、今考えるとこれが当然の挙動なのだけれど、その辺が理解できるまで思ったようなhtmlにならなくてだいぶ混乱してました

2024年02月08日 プログラミング雑談

3日なんてあっという間

jsoupについて何か書こうと思っていたけれど、gradleとかgroovyとかkotlinとか調べてたら土日が終わって、sonarQubeとかいうのの存在を知って使い方を調べて今回書いたコードをみてもらったら指摘がドバドバあって、月曜も終わってしまいました。

2024年02月12日 プログラミング雑談

javaの本

C++がある程度わかってきたら、書籍 プログラミング言語C++で勉強しなおすとすごくためになると思っています。
同様にjavaの場合にプログラミング言語Javaを読めばいいのかというと、なんか違う気がします。おとといの土曜まで知りませんでしたが、この本はJava 1.5までの内容しか書かれていないそうじゃないですか。せめて1.8のラムダとかメソッド参照とかstreamとか書かれていないといまどきのプログラミング言語として物足りないと思います。どおりでこの本をいくら調べてもメソッド参照について書かれていないわけだ!
昨日いろいろ書籍をググっていましたが、多分Effective Javaあたりから読むとよいのかなと。またはJavaによる関数型プログラミングかな。
他の言語も同様ではあるのですが、入門書はたくさんあるのですが、例えばif文を極力使わないでプログラミングしようとか、Exceptionをどのようなケースで使うのが良いのかとか、ファクトリーメソッドでどのタイミングでインスタンス生成すると良いのかとか、疑問は尽きません.
今からjavaを勉強しても勉強したことを生かしてプログラミングすることももう無さそうなんだけど。

2024年02月19日 プログラミング雑談

デザインパターンを勉強せずになんとなく使っているので説明できない

C++とかJavaとかで継承を学ぶと使いたくなるのがFactory Method。
その時はわかったような気分になるのですが、時々こんがらがってくるのでメモ。
「乗り物」を作る「工場」がある
「乗り物」は「自転車」もあれば「三輪車」もある。
「自転車」を作る「自転車工場」や「三輪車」を作る「三輪車工場」がある。

「乗り物」がProduct、「自転車」や「三輪車」がConcreteProduct
「工場」がCreator、「自転車工場」や「三輪車工場」がConcreteCreator

で、ここから先の正しい定義がいまだによくわからないのです。動的に、その時作りたい乗り物をswitch文などで切り分ける処理は何と呼べばいいのでしょう?
GoFの実装例ではCreatorクラスのCreator::Create()でMINEとかYOURESとかに応じて適切なProductをnewしているようです。
やっぱりちゃんとGoFのデザインパターンをちゃんと勉強しなきゃだな。もしかしてFactory Methodは適切なProductをnewするところまでで、どのように「乗り物」を作るかはAbstruct Factoryとかなのかしら。デザインパターンはつまみ食い状態だから全体像がつかめていない・・・

2024年02月23日 プログラミング雑談

Java AutoValueの私的なメモ

Effective Javaで今更ながらJavaを勉強中
最初の方の章でdataクラスを作るならequalとかちゃんとやらなきゃだめだよとか書いてあるみたい。自分で定義した値クラスを比較してないなら問題ないんでしょ? と思いながら、ちょっとお試し。
githubのAutoValue
detailed documentationをまるっとコピーしてしまうと、コード側の使い方はこんな感じらしい。@AutoValueというアノテーションを書くこととabstractクラスにすることがポイントらしい。インスタンス生成するためにabstractじゃないクラス名が必要だからcreateメソッドも必要ってことかな。

import com.google.auto.value.AutoValue;

@AutoValue
abstract class Animal {
  static Animal create(String name, int numberOfLegs) {
    return new AutoValue_Animal(name, numberOfLegs);
  }

  abstract String name();
  abstract int numberOfLegs();
}

mavenの場合pom.xmlには次のように書くみたい。${auto-value.version}は適切なバージョンに置き換える。

<dependencies>
  <dependency>
    <groupId>com.google.auto.value</groupId>
    <artifactId>auto-value-annotations</artifactId>
    <version>${auto-value.version}</version>
  </dependency>
</dependencies>

これだけだとAutoValue_Animalなんてクラス知らないって言われるので次の記載も必要みたい

<build>
  <plugins>
    <plugin>
      <artifactId>maven-compiler-plugin</artifactId>
      <configuration>
        <annotationProcessorPaths>
          <path>
            <groupId>com.google.auto.value</groupId>
            <artifactId>auto-value</artifactId>
            <version>${auto-value.version}</version>
          </path>
        </annotationProcessorPaths>
      </configuration>
    </plugin>
  </plugins>
</build>

これでビルドするとtarget/generated-sourcesの下にAutoValue_Aminal.javaが作られる。
私はたいしてjavaのコードを書いていないからこれまでこういうことを知らなくても実害はなかったけれど、コンテナに自作クラス(のインスタンス)を入れて何かさせる場合はequalとかちゃんと作らなきゃならないようなので、今は実害が無くてもちゃんと作る習慣を今からつけていかないと将来発見が難しいエラーを作りこんでしまうって事だろうな。

2024年02月24日 プログラミング雑談

匍匐前進

今年作っていたjavaのプログラム、VSCodeでMavenを使っていましたが、gradleも使ってみたくて。

VSCodeなのでGradle for Javaのプラグインを入れて、コマンドパレットで"Create a Gradle Java Project"でKotlinでJUnit5だったかな、そんな感じで選んでプロジェクトを作成。
もう一歩進むたびにやり方をググって・・・
依存パッケージの設定はbuild.gradle.ktsに

dependencies {
    // This dependency is used by the application.
    implementation("org.jsoup:jsoup:1.17.2")
    implementation("org.apache.logging.log4j:log4j-api:2.22.0")
    implementation("org.apache.logging.log4j:log4j-core:2.22.0")
}

とか書いて、VSCodeの左の象のアイコン→Tasks→build→buildしたらエラー。
どうやらbuild.gradleを更新したらUpdateする必要があるみたい。Mavenの時はpom.xmlを更新すると更新しますかみたいなメッセージボックスか何かが出てUpdateされていたみたいですが、まだ私の環境はbuild.gradleを更新しますかみたいなメッセージボックスか何かが出ているのですが反映されていないみたい。(追記)JDKとJREをインストールしなおしたら解決しました
とりあえずVSCodeを終了して立ち上げなおせば反映される。

Javaのソースファイルとテスト用データファイルを一式コピーしてbuild。今度はコンパイルが通ったけれど今度はテストでエラー。Webページのhtmlファイルを作るプログラムなので、生成したファイルの中の文字をチェックするのだけれど、UTF-8の文字列にもかかわらずShift-jisのつもりで比較している模様。UTF-8のソースファイルなのにShift-JISとしてコンパイルされているみたい。文字コードが誤認識されていてもビルドが通るとは恐るべし
VSCodeのエクステンションの設定かしらと思ってEncodeとか頑張って探すけれど設定する箇所が見つからない。
いろいろググってたらbuild.gradleで設定するらしい。このサイトの記載をそのまま使わせていただきました。

tasks.withType<JavaCompile>().configureEach {
    options.encoding = "UTF-8"
}

すっかり忘れていたけれど、Mavenの時はpom.xmlに

  <properties>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

みたいなのを書いた気がします。

VSCodeのjavaのプラグイン(?)でCreate Java Project→Maven→archetype-quickstart-jdk8とかで入ってくるcheckstyleとかjacocoとかはまだどうやったら使えるのかわからないし、log4jもまだlog4j2.xmlにパスが通っていないみたいでログが出てこないし、しばらくは前途多難な匍匐前進なのだな
でもググれば何かわかるというのは実に助かります。良い時代ですね。

2024年03月02日 プログラミング雑談

javaでifを使わずにnullじゃなかったら実行する

javaでもC++でも良いのですけれど、コードを書いているとnullチェックのif文が並んで、なんだかなぁ、と思うことが多いです。
例えばjavaで次のような感じ。クラスAaa、Bbbなどは省略します。

public class App {
    public static void main(String[] args) {
        for (int i = 0; i < args.length; i++) {
            create(args[i]);
        }
    }

    private static void create(String devName) {
        Map<String, Supplier<Xxx>> factory = new HashMap<>();
        factory.put("A", Aaa::new);
        factory.put("B", Bbb::new);
        Supplier<Xxx> sup = factory.get(devName);
        if (sup != null) { // ★
            Xxx xxx = sup.get();
            System.out.println(xxx.getProduct());
        }
    }
}

factory.get()のところをgetOrDefault()使ってnullが返らないようにする手もありますが、このケースでは本来エラーになるケースでsup.get()で無駄なインスタンスを生成してしまうのでいやだなぁと。
もう20世紀じゃない。javaでNullじゃなければ実行する、みたいなスマートな方法があるはず。どう調べればよいかわからないのでたどり着くのに時間がかかりましたが、こんな方法があるようです

    private static void create(String devName) {
        Map<String, Supplier<Xxx>> factory = new HashMap<>();
        factory.put("A", Aaa::new);
        factory.put("B", Bbb::new);
        Optional<Supplier<Xxx>> optxxx = Optional.ofNullable(factory.get(devName));
        optxxx.ifPresent(sup -> System.out.println(sup.get().getProduct())); // supにoptxxxが入る
    }

java.util.Optionalを使ってofNullableで「この変数、nullかもしれない」と申告しておいて、ifPresentで「もしnullじゃなかったらヨロシク」ってことらしい。
このコードではifPresentで実行までしていますが、生成したインスタンスを返して戻り先で実行させるならこんな感じ。「nullかもしれない」値をOptionalに入れて処理して、最後にorElseでインスタンスを取り出すみたい。

        Optional<Supplier<GenHtml>> maker = Optional.ofNullable(factory.get(htmlMode.toLowerCase(Locale.getDefault())));
        Optional<GenHtml> makerMethod = maker.map(zz -> zz.get());
        return makerMethod.orElse(null);

最初の方の例はこのページに書くためにでっち上げたコードだったけれど、こっちは自分のコードからコピペ。
多分読み慣れればifでnullチェックするよりも読みやすくなるのでしょうね。

問題というほどの問題ではないのですが、ifPresentやmapの中でラムダ式を使うのでjacocoではサイクロマチック数を一つ使ってしまうのですよね。Optionalの処理をメソッドにして追い出してしまうとかいう使い方を想定しているのでしょうかねぇ。

2024年03月10日 プログラミング雑談

どこまでも文字コードが付きまとう

javaでgradle使ってプログラム作るの第2弾。poiでexcelファイルを作る。

cell.setCellValue("日本語文字列");

ってやったら文字化けした。
poi側で何か文字コード設定があるのかと思ってググるのだけれどあまりヒットしない。日本語フォントを設定すれば文字化けが直るとか書いてあるサイトもあったけれどフォントを指定しても直らない。
しばらく悩んで

System.out.println("日本語文字列");

したらこっちも文字化けした(笑)
そうだった、build.gradle.ktsに

tasks.withType<JavaCompile>().configureEach {
    options.encoding = "UTF-8"
}

って書いてUTF-8でビルドしなきゃならないんだった

引き続き、
Excelのxlsxファイルを読み込んで条件付きで文字色を変更して別ファイルに保存させるプログラムを書こうと四苦八苦。OPCPackageってなんだかわからないけれどpoiのサイトのサンプルのコピペで

OPCPackage pkg = OPCPackage.open(new File("indata.xlsx"));

って書いてファイルを読むと読み出ししたいだけなのにファイルが何か更新されてしまうみたい。結局

XSSFWorkbook wb_r = (XSSFWorkbook) WorkbookFactory.create(new File("indata.xlsx"), null, true);

って書いて解決。create()の3番目の引数がread onlyにするフラグらしい。
でもなんか別ファイルを作って保存ってpoiではセル一つ一つを別ファイルにコピーする必要があるみたいで面倒らしい。poiの新しめのバージョンではメソッド一つでシートごとコピーできたりしないのかな・・・。後で調べてみる。

2024年03月20日 プログラミング雑談

Valid XHTML 1.0!Valid CSS!