2011年2月28日月曜日

投稿間隔の妙

何にも考えずにブログを更新してきましたが、
先月とほぼ同じ投稿数であることに気がついた今日この頃。

ただの偶然か、
これが自然のペースってことなのか…

まあ昼休みにブログが更新できなくなったら状況は一変するでしょうけどね。
スマートフォンでは更新できない!できにくい!

おっと、もう時間だっと…

2011年2月26日土曜日

スマートフォンから投稿

特に意味もなく、
スマートフォンから書きこめるか実験してみました。

結果はこの通りです。
だけど書きにくい…
キーボードはフィルコFILCOを愛する自分は特に…

そういえばヨドバシで見かけなくなったけど…
撤退してないよね?

2011年2月25日金曜日

本当にすごいこと

前に“本当にまずいこと”を書いたので、
今度はその逆について考えてみようかと思いました。

まあ技術系なら色々知っていること≒すごいことなわけですが…

本当にすごいことは
「必要な概念を使いこなせる」
ってことなんだと思います。

結局プログラミングの歴史は抽象化の歴史です。
参考書に書いてあることは、抽象化の例として具象化されたものです。

そこから抽象化された概念の本質を見極め、
実際に使いこなせる(ソフトウェアにできる)ことがすごいことなんだと思います。

オブジェクト指向で動物を例にすることが酷評されているのが見受けられますが、
抽象化のレベルで言えばより本質に近い説明ではないかと思います。
実際の業務コードで説明されるよりも本質の概念に近い位置に見えます。
そしてそれは著者にとっての正しいガイドなのではないでしょうか?

つまり少し抽象的な説明は一定のレベル以下を蹴落しはしますが、
一定のレベル以上の理解を助けてもいるとも言えるわけです。
(そのレベルが先天的なのか後天的なのかは永遠のテーマということで。)

そういう意味では、
絵画の技法集より親切かつ残酷といえるかもしれません。

…相変わらずのイミフ文ですが、まあ誰も見てないしいいか。

2011年2月23日水曜日

Stack Overflowで活躍したい!

別に障害の切り分けが上手くなりたいとかでは無いです。
そういう名前のサイトがあって、そこで活躍したいという意味です。

とりあえずいくつかの質問に答え、
カルマ値を51にまで上げることができました。

そのうちブログにプロフィールのリンクを貼りつけようと思います。
(その前にPixivかな…)

2011年2月21日月曜日

スマートフォン購入

手持ちの携帯のバッテリーが限界だったので、
この機にスマートフォンへ移行しました。

…タッチパネルって高速連打には向かないか。
でもこれってvi使いがeclipseに否定的なのと同じ理由なような気がします。
総合的な観点で見ないといけないですね。

とりあえずスプレッドシートの使い心地次第では、
家計簿アプリを作らないといけないかな?

2011年2月19日土曜日

XMLの落とし穴…

myBatisのXMLをWindows-31Jに変更したらパースエラー
なんと"を超"という2文字を連続させるとダメらしい…

スタックトレースはJDK6標準のパース使っているような感じだから…
もしかしてJavaとしてのバグ?

もう少し調べる必要があるよな…これ…


追記:
自作のXML読み込みでは起こらない…
ということはmyBatis特有の話か…

2011年2月18日金曜日

Log4jのエラーハンドラ

Log4jでよく、
「ログ書き込みの成否を取得したい」
って依頼を受けます。

通知されないのがLog4jの魅力なのですが…
まあ仕方ありません。
(成否が分からないだって!?そんなことが本当にあるのか?)

Log4jのErrorHandlerを継承して適当なクラスを作り、
アペンダには<errorhandler>を使って使用を宣言します。

あとはそのまま使えば…とはなりません。
ErrorHandlerのインターフェースは例外を返す仕様とはなっていないからです。
(RuntimeException系の例外クラスなら…
いやよそう、自分の勝手な想像でみんなを混乱させたくない。)

エラーハンドラのインスタンスへ干渉するには、
ロガーからgetAppenderでアペンダを取得して、
さらにgetErrorHandlerすればインスタンスに到達できます。

ただこれどう考えても単一のインスタンスなので、
相当排他処理を頑張らないとまずいことになりそうです。
あまりに使いにくいので、
サンプルとして紹介する価値もありません。

あれ?なんか霧が出てきたような…

追記:RuntimeExceptionでどうにかしたのはこちら

2011年2月17日木曜日

1行1処理の嘘

よくコーディング規約で、
if文を最低3行にしなければならないようなルールを見かけます。

つまり、
if (flag) testValue = 0;
みたいに書ける場合でも、
if (flag) { 
    testValue = 0; 
}
として書かなければならない規約です。
(もう少し詳しい人が規約を書いたなら、
三項演算子の禁止もセットでしょうか?)

その理由としては、
“1行1処理”とすることが好ましいからだそうです。

まあ { } を省略するのは下品かもしれませんが、
その理由は違うんじゃないでしょうか?

適当な例ですが、
型変換や四則演算の組み合わせだけでも平気でその原則は崩れます。
Integer.valueOf("123456".substring(1, 3)) + 1000;

逐一行を分けていたら、
自分なら気が滅入ってしまいます。

だから多少省略しても許してもらえませんかねぇ?
三項演算子も使わせてもらえませんかねぇ?

※ただしコーダーばかりの開発現場を除く

2011年2月16日水曜日

本当にまずいこと

仕事でプログラミングをしていると、
1000行に近い関数のソースなんていうのものを当たり前に書く人をたくさん見かけます。
数値に意味があるとは思えないマジックナンバーも当たり前のように書き、
オブジェクト指向ではクラスの継承すらろくに使いこなせません。
(挙げ句の果てには業務では必要じゃないとまで言われたり…悲しいけどこれ実話なのよね。)

まあそれはそれで致命的にまずいのですが、
本当にまずいのはそれがまずいということが感覚的に分からないことです。

とりあえずまずい点を10個ぐらい指摘してはみたのですが、
どうにも腑に落ちていない様子でした。
本当に一から丁寧に順を追ってゆっくりと説明しないと納得してもらえないのです。
(それでも感覚的な理解は得られませんでしたけど…)

確かに彼(彼女)らが学習している教材を覗き見してみると、
関数をだらだらと書くことがまずいとは明記されていません。

そりゃ自分も入門書で見たことはありません。
まあでも、自分からは見た目が汚いからすぐに分かるとしか言えないですが…
実際ソースコードの*美しさ*と表現しているくらいですから、
それは知識によるものではなく、
感覚によって判断しているものだからです。

仮に知識としてまずい事項を伝えることはできても、
まずい事項はそれは山のようにあり、
別のところでまた伝えなおすことになります。
結局はそのまずさそのものを理解してもらえないと、
根本的な解決にはならないのです。

この概念・感覚を人に教えるにはどうするべきなのでしょうか。
まるで"数"って何?と聞かれている気分です。

今のところ世界レベルのプログラマーでも、
このあたりは*全員に*上手く教えることができないそうです。
プログラミングで才能って言われている部分は、
そんなあたりになるのでしょうか?
(MITの6.001をプログラマーの必須要件にしたい…)

2011年2月15日火曜日

統計でニヤニヤ(・∀・)

ろくにリンクも貼らず、
参照なし街道を快走中のことブログですが…
ごくわずかながら引っかかることもあるようです。

やはりlog4jやmyBatisの話題は調べる方がいるようです。
googleの検索結果に引っかかったという情報が統計に寄せられました。

…ブログの中身は見てないでしょうけどね。

2011年2月14日月曜日

DBCPを取り戻せ!

myBatisを適当にインストール(libフォルダに投下)、
適当にDBCPへせつぞ…くできない(泣)

JNDI経由なら問題ありませんが、
直接DBCPを利用する手段が消えているようです。

ソースにも痕跡が無い…
というわけで何とかするとしましょう。

とりあえずDataSourceFactoryを実装すれば拡張可能だと判明したので、
適当にBasicDataSourceFactoryからDataSourceを作成するようにクラスを作成しました。

public class DbcpDataSourceFactory implements DataSourceFactory {

    private DataSource datasource = null;

    @Override
    public DataSource getDataSource() {
        return datasource;
    }

    @Override
    public void setProperties(final Properties property) {
        try {
            datasource = BasicDataSourceFactory.createDataSource(property);
        } catch (Exception e) {
            throw new DataSourceException("DBCPの設定に失敗しました。", e);
        }
    }
}

あとは設定用(configuration)XMLのdataSourceタグのtype属性に、
作成したクラス名を*パッケージ名も含めて*入力しておきます。

配下のpropertyタグにDBCPの設定をガンガン入れればいいはずです。

こんなの需要なさそうだけど、
やらなきゃならない人は苦労するだろうな…

2011年2月7日月曜日

プログラマーズハイ

最近ではあまり体験できなくなりましたが、
プログラマーズハイ(?)になったことがあります。

何のことかと言いますと、
目の前の風景が全てコードに変換されて見える(ような幻覚が見える)現象です。

マトリックスでネオが覚醒した状態が近いですかね?
あれは意外にリアルじゃないかと思います。

まあ半分トリップしているようなものなので、
望んでなるものではないと思います。

2011年2月4日金曜日

なぜ精神論ははびこる?

世の中には、
努力すればどうにかなるとか、
常に注意していればどうにかなるとか、
理屈が一切入っていない精神論が多く見受けられます。

それを何年も叫んでいても状況は改善されてはいないのに、
なぜ引き続き叫ぼうとするのかは分かりません。

確かに、
スポーツで最後に頼りになるのは精神力というのは分かります。

ですが、
いきなりその最後を頼りにするのは無謀すぎやしないでしょうか?
少なくとも優先順位が違います。
1の手法は100の精神に勝ります。
(まあ1000なら勝てるかもしれませんが)

ここで普通なら、
その手法としてのシステムを…とか話すところですが、
今回は別の視点で考えてみることにします。

今回の要旨は、
その脆弱性が理解されずに精神論が振りかざされる理由についてです。

それは、
(ま~ったく根拠はないですが、)
心理学が甘く見られすぎているからではないでしょうか。

ユーザーインターフェースを設計していると分かりますが、
心理学が参考になることが多くあります。
人間の習性について(作業を中断したら続きを忘れることがあるなど)もそうですが、
操作性を実際に測定してみるなんてのも、
心理学では基本的な考え方です。
(よく心理学の実験とか聞きますよね?)

とにかく、
精神論に代わるヒントが多く散りばめられています。

その上で精神論を語られ続けるのであれば、
自分には学習が足りないようにしか思えません。
(特にセキュリティについてなんですけどね)

学習に学習を重ね、
対策に対策を重ねた上で、
始めて最後は精神論でと締められるような行動を心がけたいものです。

おしまい

2011年2月3日木曜日

プログラマーのレベル測定

プログラマーのレベルが低いだと高いだと議論することはよくありますが、
一体レベルの高低はどうやって測るのでしょうか?

もしプログラミング能力を客観的に測定する方法があるのなら、
レベルの低いプログラマーがはびこるのを防ぐことができます。



…と言っておいてなんですが、
おそらくこれは(まさに)絵に描いた餅と言えます。

プログラマーはクリエイター業なので、
客観的な測定は極めて難しいからです。

例えるならば、
絵描きのレベルを測定しようと言っているようなものです。

「でもあからさまに下手な絵は分かりますよね?」
という質問があるかもしれませんが、
これはプログラミング能力の上では成り立たないのではないでしょうか。

少なくともスケッチであれば、
実際の風景と見比べて似ているかどうか見ればよいだけです。
※味のある表現とかは今は抜きにさせてください。それ以前のレベルの話です。

しかしプログラミング能力は別です。
前提となる知識や概念が無数に存在します。
・変数
・配列
・関数
・ポインタ
・再帰
・クロージャ
・アルゴリズム
・データ構造
・構造化プログラミング
・ガベージコレクション
・オブジェクト指向
・λ計算 …etc
少なくとも、知らないものについてはその良し悪しは判断できません。

つまり、
上級プログラマーは下級プログラマーたちのレベル差が分かりますが、
下級プログラマーは上級プログラマーたちのレベル差が分からないのです。

そしてこれはこう言い換えられます。
「素人はプログラマーのレベルを一切区別できない」
…と。

ここに鶏と卵の問題が発生しています。
レベルの高いプログラマーを雇うためには、
レベルの高いプログラマーが必要となるわけです。

さあ、どうやって解決しましょうか?

追記:Paul Grahamも同じこと言っているし、あながち間違いではないはず。

2011年2月1日火曜日

経路問題はウロボロスの香り

経路のパターンを洗い出す問題にて、
仕事場のプログラマーがいつまで経っても作れない…
ループする経路がないという限定条件なはずなんだけど…

というわけでサンプルを15分で書いて、
もう15分できれいにしたのがこちらです。
ハッシュテーブルに格納しているのは、
この方が実際に使うデータ構造に近かったからです。

public class Sandbox {

    public static void main(String[] args) {
        HashMap<String, Node> map = new HashMap<String, Node>();
        // ノードの作成
        map.put("A", new Node("A"));
        map.put("B", new Node("B"));
        map.put("C", new Node("C"));
        map.put("D", new Node("D"));
        map.put("E", new Node("E"));
        map.put("F", new Node("F"));
        map.put("G", new Node("G"));
        map.put("H", new Node("H"));
        map.put("I", new Node("I"));
        map.put("J", new Node("J"));
        map.put("K", new Node("K"));

        // ノードの連結
        map.get("A").addChildren(new Node[]{map.get("B"), map.get("C")});
        map.get("B").addChildren(new Node[]{map.get("D")});
        map.get("C").addChildren(new Node[]{map.get("D"), map.get("E")});
        map.get("D").addChildren(new Node[]{map.get("H"), map.get("I")});
        map.get("E").addChildren(new Node[]{map.get("F"), map.get("G")});
        map.get("F").addChildren(new Node[]{map.get("J")});
        map.get("G").addChildren(new Node[]{map.get("J")});
        map.get("H").addChildren(new Node[]{map.get("K")});
        map.get("I").addChildren(new Node[]{map.get("K")});
        map.get("J").addChildren(new Node[]{map.get("K")});
        map.get("K").addChildren(new Node[]{});

        // 走査を開始する
        preorder(map.get("A"), map.get("A").getValue());
    }

    public static void preorder(Node node, String message) {
        // 子供がいない場合
        if (node.getChildren().size() == 0) {
            System.out.println(message);
        }
        // 子供がいる場合
        for (Node t : node.getChildren()) {
            preorder(t, message + ":" + t.getValue());
        }
    }

    public static class Node {
        private String value = null;
        private ArrayList<Node> children = new ArrayList<Node>();

        public Node(String value) {
            this.value = value;
        }

        public String getValue() {
            return value;
        }

        public ArrayList<Node> getChildren() {
            return children;
        }

        public void addChildren(Node[] nodes) {
            for (Node n : nodes) {
                children.add(n);
            }
        }
    }
}

追記:TreeModelクラスなんてものが…見なかったことにしよう。