Swingで変数数縛りプレイ

コードを読みやすくするにはどうしたら良いか?
この疑問に対する答えについて、最近の僕のスタンスは
「頭のワーキングメモリ(レジスタの本数)を使わなくて済むコード」
だと考えるようになっている。*1
ワーキングメモリ削減を実現するサブミッションとして、
「分かりやすい変数名にしましょう」とか
「変数のスコープは出来るだけ狭くしましょう」とか
「変数を出来るだけ減らしましょう」といったアプローチが
どんな言語でも取り組みやすい対策だと思う。


そんなわけで最近は変数削減史上主義に走っている僕ですが、
GUI絡みのコードはどうしても変数数が多くなってしまいがちだった。
そこで無理やり削ってみたらどこまで減らせるかチャレンジしてみたくなった。

以下はID/PASS/ボタンの3点セットのよくあるログインフォーム

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class NonUseVariant {
    public static void main(String[] args) {
        new JFrame(){
            public void $() {
                setTitle("変数削減縛りプレイ");
                setBounds(100, 100, 320, 120);
                setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS));
                add(new JPanel(){
                    public JPanel $() {
                        setLayout(new BorderLayout());
                        add(new JLabel("UserName"), BorderLayout.WEST);
                        add(new JTextField(), BorderLayout.CENTER);
                        return this;
                    }
                }.$());
                add(new JPanel(){
                    public JPanel $() {
                        setLayout(new BorderLayout());
                        add(new JLabel("Password"), BorderLayout.WEST);
                        add(new JPasswordField(), BorderLayout.CENTER);
                        return this;
                    }
                }.$());
                add(new JButton("ログイン"){
                    public JButton $(){
                        if(getActionListeners().length >= 1) return this;
                        
                        addActionListener(new ActionListener() {
                            @Override
                            public void actionPerformed(ActionEvent e) {
                                System.out.println(
                                    ((JTextField)((JPanel)$().getParent().
                                    getComponent(0)).getComponent(1)).getText()
                                );
                            }
                        });
                        return this;
                    }
                }.$());
                setDefaultCloseOperation(EXIT_ON_CLOSE);
                this.setVisible(true);
            }
        }.$();
    }
}

どうしてもないと困る2つ(mainメソッドの引数とActionListener#actionPerformedをオーバーライドしたときの引数)以外は削減することができた。保守性や見た目は犠牲になりました。

*1:テストしやすいコードや、変更・保守に強いコードはまた別のスタンスがあるが

他言語プログラマ向けのExcelVBA 10の落とし穴

プロジェクトのメイン言語はイマドキのものを使っていたり、
チーム内ではBTSやWeb上での進捗管理をしていても、
顧客とのやり取りや事務処理になんだかんだでExcelやり取りしているところは、
結構あるんじゃないかなと思います。


けど、いざ作業自動化のためにVBAを使おうにも、
今更VBAの本をわざわざ買うってほどではないし、
かといってググってみてもプログラミング初心者向けサイトや、
類似サイトばかりヒットして疲弊するということがあるかもしれません。


というわけで、今回は既に2〜3言語以上は習得しているプログラマが、
初めてExcelマクロを書いたときに躓きやすいポイントをまとめてみました。

Integerは16bitである

範囲は-32768〜32767です。
意図して範囲を狭めているのでなければ32bitのLongを使用しましょう。

整数の割り算で / を使用すると偶数丸めになる

Sub test()
    Dim a As Integer, b As Integer
    a = 5 / 2
    b = 7 / 2
    Debug.Print "a=" & a & ",b=" & b
End Sub

上記のコードを実行すると、結果はa=2,b=4になります。


四捨五入や切り捨てではなく偶数丸めになっているため、
このような挙動になります。
wikipediaによると

端数が0.5より小さいなら切り捨て、端数が0.5より大きいならは切り上げ、端数がちょうど0.5なら切り捨てと切り上げのうち結果が偶数となる方へ丸める

という仕様だそうで、金融界隈ではよく使われているそうです。
ですが、C言語の / と同じような結果を期待している人にとっては、
躓きポイントになりやすいので要注意。
C言語と同じような結果(切り捨て)を求めるのなら、 / ではなく \(円マーク)を
使いましょう。

AndやOrは&&や||相当ではなく&や|相当だ

VBAのAndやOrは多くの言語にある&&や||相当ではありません。
またPythonのAnd,Orとも違います。
どこが違うかというと、Andを使用した場合、
前者の評価がFalseでも後者まで評価してしまう点が異なります。
つまり、他言語では可能だった

if (obj != null && obj.getHoge() > 4)

のような最初にNullチェックをしてその後中身の評価といった
書き方ができません。


以下のコードを実行するとエラーダイアログが表示されます。

Sub test()
    Dim a As Range
    ' セルaの値が1でないときに出力したい
    If Not a Is Nothing And a.Value <> 1 Then
        Debug.Print a.Value
    End If
End Sub


またOrについては、前者がTrueでも後者まで評価してしまいます。
三項演算子相当のIIfの場合はtruePartとfalsePartの両方を評価してしまいます。
VB6ではAndAlsoやOrElseといった構文が新たに用意されているので、
そのうちVBAでも使えるようになるかもしれないです。(Excel2007では使えませんでした)

Forループの終了値指定部は都度評価されるけど再計算はされない

For文のto直後に書く終了値指定ですが、これは繰り返し判定としては評価されますが、
値については最初の1回しか計算されないようです。
これについては日本語で説明するよりもコードを読んだ方が理解が早いと思います。

Sub hoge()
    Dim i As Integer
    For i = 0 To 3
        Debug.Print i
        i = i + 1
    Next i
End Sub

上記コードを実行した場合は、0,2が出力されます。

これはiが3を超えるかをループの都度チェックしているからです。

しかし、以下の例を見てみましょう。

Sub test()
    Dim s As String
    s = "abc"
    Dim i As Integer
    For i = 0 To Len(s)
        Debug.Print i
        s = "abcdefghi"
    Next i
End Sub

上記のコードを実行した場合は、0,1,2,3が出力されます。

これは都度Len(s)を評価しているわけではないためです。

On Errorを同じ関数内で2度使用しない

VBAではファイルアクセスに失敗した時などのために、
エラー処理構文としてOn Error文が用意されています。


しかしこのOn Error、同じ関数内で2度使用すると2回目のエラーはキャッチしてくれません。
以下の例は、処理Aでチャレンジしてみてダメだったら処理Bで試してみる。
それでもダメだったら諦めるといったパターンです。

Sub test()
    Dim a As Range, b As Range
    On Error GoTo 処理スキップA
    MsgBox a.Value
    Exit Sub
処理スキップA:
    MsgBox "処理A失敗のため処理Bでチャレンジ"
    On Error GoTo 処理スキップB
    MsgBox b.Value
    Exit Sub
処理スキップB:
    MsgBox "処理B終了のため、諦める"
End Sub

aとbに何も設定していないため、エラーになるのですが、
2回目は「処理スキップB」に飛ばずにVBAの実行時エラーになってしまいます。

対処としては関数を分けるか、
Resumeを使っていったんエラー情報をリセットしてあげましょう。



今回は文法編だけで終わってしまったので、次回はライブラリ操作の
落とし穴についてピックアップしていきます。
と思ったのですが、もしかしたら飽きてしまい趣味のJava7のネタか、
本業のLinux/C++周りの話を書いているかもしれないです。

お近くのふぁぼり数について調べてみた

ふぁぼられ数じゃなくてふぁぼり数について調べてみた。
Twitter新参者は片思いの有名人よりも、ふぁぼ魔と友達になれば
たくさんふぁぼってもらえてfollowing自然と増えるんじゃないかな!という魂胆です。

母数 26568ユーザ (totteのfollowingと followingのfollowing)
集計日 2009/08/01の夜〜早朝にかけて
集計方法 http://twitter.com/users/show/SCREEN_NAME.xml内のfavourites_countを集計

3万ふぁぼ以上の人(82人)

id ふぁぼ数
katoyuu 168268
yamifuu 110489
maybowjing 106723
Wing_of_Blood 98924
breeziness 98376
shy_azusa 94392
barekichi 94307
Uchimata 90977
ta_boP 90676
fune 88656
uinyun 79441
kegelstatt 78394
ynk 76323
myu65 76221
denimu 75417
yuiseki 71910
zeppel 69668
zero_zaki_ 68078
phji 67402
tyoro 65450
miru 62770
sagittarius72 62037
harsch 60661
ngtn310 57284
chch 56458
fuba 55620
ravi2beat 54794
sahiro 54742
mio_sakamoto 53824
yuzupepper 52613
shikaikilyou 51389
llcheesell 50999
myrmecoleon 49987
wyinoue 49163
Palpha 48849
kckm 48708
tato256 47663
onodera_sf 47277
a_halka 45788
0nasu 45561
kiwofusi 45544
isbsh 44742
rurero 43253
hironao 43215
VoQn 42419
yomayoma 42229
s1tutu985 41205
mizuami 41037
flashingwind 40693
syochin 40553
todesking 40430
wideangle 40084
sachi_volta 39575
seaki 38209
kossie89 38050
sween 38016
long_voyager 37776
watarumode 36770
c_cha 36696
balanco 36658
aotako 36547
GUMIMI 36495
saeko 36443
yisual 35585
jumitaka 35308
hironica 35083
ryukaiy 34740
Erl_ 34626
96neko 34590
nezike 33901
n_3 33786
halciondaze 33574
hawelka 32810
garandou 32759
maccolli 32660
shikachanman 32236
R_Kakolog003 31426
h_hiro 30900
tengennsui 30817
f_jiro 30672
Eccentricer 30541

30000万以下はこっち

favcount.txt


ちなみに全体をグラフにするとこんな感じ。

・・・って、あまりにも偏っているので3万ふぁぼり以上の人をピックアップすると

こんな感じになった。

ソース→FavCounter.java(やっつけだからきちゃない)

調べようと思った経緯

Twitterって新参者にとってどんどん敷居が高くなるよねぇといったことを考えていた。
理由はfollowerが増えれば増えるほど読み切れない可能性が高くなって、
ツールで抽出したりふぉろー返ししない人が増えていくから。

そこで新参者でも手っとり早くfollower増やす方法について考えていた矢先、
僕が最近面白いなーと憧れてた山田にーちさんがfollow契機の集計をしていた。


          http://favotter.matope.com/status.php?id=2891546982


やはり、ふぁぼったーの影響力は強いようだ。
ふぁぼられ数によってタイムラインの文字の色/大きさが変わるグリモンも出てくるし、
有名人がふぁぼりんこって言葉を使いだす時代ですし。
けれどふぁぼりんこって発言で400favられてる有名人は自分からは5favしかしてないので、
ふぁぼったークロール対象外。
これじゃあTwitter始めたばかりの人が
「とりあえず有名人をふぉろーしたけど、一方通行になってTwitter飽きて辞めてしまう」
なんてことになってしまいそう。
有名人の発言を読みたい目的でTwitterやってる人はfavられ数が多い人をfollowすればいいけど、
自分の発言が読まれたい人はたくさんfavってくれる人をfollowすればいいんじゃないかな!
って思いクロールしてみた。

考察

  • ふぁぼ数上位者は色んな人のPOST読んでるなーって普段思っていた人たちが多かった。
  • followingのfollowingが26000人いるのに驚いた。3か月ぐらい前に日本のTwitterアカウント数は8万程度ってTwitterクロールしてる人たちが言ってたからなんか色々すごい。

Stringで今日やったミス

以前にも同じミスをしたことあるので戒めも込めて投稿。

for(String animal : Arrays.asList("fox dog wolf horse sheep deer cat nyaa".split("\\s")))
    System.out.println(animal);


・・・と書いていて、リストが長くなってきたので、Eclipseでリストの途中を改行してみた。

for(String animal : Arrays.asList("fox dog" +
       		" wolf horse sheep deer cat nyaa".split("\\s")))
    System.out.println(animal);

実行結果

fox dog[Ljava.lang.String;@1546e25

文字列の途中で改行加えただけで、結果が変わってしまった><

"fox dog" + " wolf horse sheep deer cat nyaa".split("\\s");

は、

"fox dog" + 文字列配列

を連結したことになってしまう。対処として、

("fox dog" + " wolf horse sheep deer cat nyaa").split("\\s");

のように括弧でくくればおk

修正後

for(String animal : Arrays.asList(("fox dog" +
   		" wolf horse sheep deer cat nyaa").split("\\s")))
    System.out.println(animal);

実行結果

fox
dog
wolf
horse
sheep
deer
cat
nyaa

他のStringメソッドでも同様の注意をしないといけない

String hoge = "ふぉくすけのしっぽかわいいよ".substring(6);
System.out.println(hoge);  // しっぽかわいいよ
String hoge = "ふ" +
        "ぉくすけのしっぽかわいいよ".substring(6);
System.out.println(hoge);  // ふっぽかわいいよ

まとめ

見やすさのために文字列改行することよくあるけど、
改行するとどの文字列に対してメソッドが実行されるのかを間違えやすいので要注意。

作業記録

作業メモなので、頭の中に思いついた順に書いていっているので文章のまとまりはないでs

5/3

今年のGWは GoogleAppEngineでなんかするぞーとは決めていたものの、
何をやるかは決めていなかったので、周りでTwitter-bot作りが流行っていたので、
Twitter4j使ってbot動かそうとする。

⇒ローカルでは動くのに、サーバからcronで叩くと動かない
⇒cronの設定うまくいってないのかな? と思いとりあえず断念。
(実はcronはうまく動いてたけど、別問題だったことが後で判明する

5/5

botいまさら作っても、もう既存に優秀なbotがたくさんあるし、使わないだろうなーと思う。
⇒よしじゃあ、携帯向けのクライアント作ろっか!と思い立つ。
(mtwitter.comはページ遷移で挙動おかしいところあるし、何よりもAPI制限なし&&アイコンがあるクライアントが欲しい!
んでAPI制限ひっかからないやつを使いたい

⇒途中 JDOの設定で結構手こずる(JDO使うの初めてだったので

⇒さっそくパケットキャプチャしながらスクレイピングのクライアント作る
⇒ HttpURLConnection.setFollowRedirects(false)でSecurityManager()でエラー
      ⇒GAEは色々制限あるらしいと聞いていたけどこれか!
      ⇒Googleが推奨してきてる方法 (URLFetchでアクセス)とやらを試す
⇒こちらではリダイレクトがうまくいく
⇒ローカルで動いた!

当時のPOST

自作くらいあんt
2:09 AM May 6th mobile webで

@nezike セッション情報知っちゃうけど。。
2:14 AM May 6th webで nezike宛

@nezike DMおくた
2:16 AM May 6th webで

動かないw これはひどい
2:20 AM May 6th webで

ローカルだといけるんだけどな、、
2:31 AM May 6th webで

GAEからアクセスすると403…
3:11 AM May 6th mobile webで

というわけで、ローカルで動くけど、GAEからアクセスするとだめぽ。

5/6

5/6 Google App Engine 対応 の Twitter4J 2.0.1 リリース

きゃーーー、5/3に動かなかったのはこれなのかー。
というわけで、

  • クッキーセッションを手打ちして自分で登録
  • 取得系はスクレイピング / 投稿系はTwitterAPI

にすればAPI制限を回避しつつ動かせることは判明。確認済み。
(でもクッキーセッションを手打ちはさすがに微妙w


まとめ

  • GAE/JのセキュリティマネージャーはGoogleオリジナルのものを積んでいる模様。
  • Twitterスクレイピングは、ローカルで可能だがGAEからアクセスするとダメ(原因はhostかUser-Agentかなぁ(確認とれず))
  • TwitterAPI使えばいけるっぽい

今後

人のパスワードを(GAEのサーバとはいえ)保存するのは嫌なので、携帯版Twitterはやらないかなぁ。。
(自分専用クライアントなら作るかもしれんが、スクレイピングでない携帯版Twitterクライアントは
既にいくつか素晴らしいのがあるので、車輪の再開発は嫌だから)
(それOAuthでできるよ?なのかな、わからにゃー

なので、他のプログラム書いていこうかしらん。

mini9/UbuntuでEMOneモデム接続する

うぶんつことUbuntuでEMOneをモデム代わりにしてお外でネットしようと考え、ここら辺→ukai's blog: Linux で emone modem参考にしながらまずは自室で接続試していたのだがどうもうまくいかにゃー。んで、調べた結果「無線LANとEMOneのモデムでNICが二つ」
みたいな現象に陥ってたよ!というのが分かったので同じところでつまづいてる人いるかもしれないので、書き残してみる。ひょっとしたらアドエスモデムでも起こり得るかも。

まず、EMoneとみにきゅんをUSBで繋いできちんと認識できてるかチェック

$ sudo -s
# lsusb

で実行結果にSharp Corpって文字が見えたら認識はOK.
つづいてmini9側のモデムの設定をする為に、pppconfigを入れる。GUIライク(Linuxインスコするときに出てくるブルーバックな画面のやつ)なので初心者でもタブとスペース押してけば設定容易だよ。

# apt-get install pppconfig
# pppconfig

設定項目は下記のような感じ。

user: em
pass: em
DNS: dynamic
電話番号: *99***1#
method: PAP
Com: /dev/ttyUSB0

で、保存を押して終了。
pppconfigで設定した設定名でPPP接続する

# pon emone

・・・とここまで他所参考にしながらやったのですが、ponして確認くんで調べてみても無線LAN経由のプロバイダのアドレスのままだった。

なので

# ifconfig eth1 down

無線LAN止めてみる。

そうすると今度はネットに接続できなくなってしまった。#route で見てみると挙動がおかしくなってたので、route書き換えて、カーネル無線LAN経由じゃなくてイモバモデム経由にするよう設定する。

# route del default dev eth1
# route add default gw <イモバのIP> dev ppp0

そしたら動いた!

イモバ辞めて無線LAN繋ぎたい時、

# poff emone(pppconfigで設定した名前)
# ifconfig eth1 up
# route add default gw 192.168.<家のルータのIP> dev eth1

で戻せる。

まとめ

  • 無線LAN使いでモデム使うとちょっとroute設定の知識必要そう。(多分事前に調べた方がよさげ)
  • Windowsでいうブリッジ機能みたいなのもLinuxであるっぽいのでそっちの方が便利そうなので今後の課題としたい
  • というか多分このやり方は非効率なので、「とりあえず!」ていうレベル


はぁ、これでどこでもネット環境は整ったので、あとは外に出るだけですね!

みにきゅん買ってみた

湘南地域でDellのmini9が流行っていたので、湘南に入ろうとやたら必死に頑張っている平塚に住んでいる自分もみにきゅん欲しいなーと思っていたところ、ちょうど1日限定で安売りキャンペーンをやっていたのでポチってみました。

¥38000+Eで以下のスペック

  • Ubuntu 8.04 (DELL カスタマイズ版)
  • SSD 32G
  • 2GB DDR2
  • Atom N270 (1.6GHz, 512KB L2キャッシュ, 533MHz FSB)
  • 1024x600 WSVGA光沢液晶ディスプレイ
  • GMA950


<感想>

  • 初めてのdellだったんだけど届いたダンボールは思っていたより小さかった。レッツノート12インチのダンボールと比べて半分以下。んで、うまいなーと思ったのがPCの入れ方。2段弁当式。裁縫箱的。本を開くみたいにダンボールを開けると発砲スチロールがあってそれを開くと1段目にみにきゅんが登場。2段目に簡易取説,CD格納。AppleといいDellといいそこらへんがうまいよなーと思いました。レッツノートダイナブックは細長いダンボールから発泡スチロールをミシミシ音たてながらスライドしていって取り出す形だったと思う、確か。
  • 液晶が綺麗。光沢なので明るいです。光沢は反射するのかなと思っていて今まで使ってこなかったけれどそんなことはなかった。あと他デバイスでたまに聞こえる液晶特有の高周波音もしません。
  • 特に調べないで買っちゃった端子周りは、しっかり欲しいものが装備されていて良かった。USB*3(右側面1、左側面2)、モニタ出力、マイク、イヤホン、SD/MS/Pro-MMS、LANポート
  • キー配置は微妙かも。半角全角が右側なのでIMの設定変更で半角全角切り替えにSHIFT+SPACEを追加しました。 |\キーが十字キーの左側にあるのはパイプ処理書いたりするときにまだ探してしまう。F1〜F10がFn+A〜Fn++、F11がFn+Z、F12がFn+X
  • 気になっていたバッテリーは今のところ公称と同じかそれ以上になる。4時間〜5時間。Skypeとかのチャット群つけてると短くなるかも。
  • ウィンドウの縦幅が768じゃなくて600になってるのは全画面にしまくればいけるかも。必要な時以外は全画面。
  • 初めてのうぶんつだったのですが、root権限ないんですね。sudo susudo -sで対応(thx. limitusus)。passは今使ってるユーザのPASS
  • 最初から入っているブラウザはWebBrowserとか書いてあってしかもヤフーツールバーが画面占領してたり、きつねアイコンじゃなかったのでFirefox入れ直しちゃいました。

<結論>

  • おでかけ、ゴロ寝ネットにはかなりよさげ。
  • 文字を打ちまくる作業には微妙かなぁ。mini9使っていてその後他のキーボードを使おうとするとキーピッチからtypoが増える。
  • SSDファンレスなので鯖用途にもいいかも!って思っていたけれど、sudoしないとroot使えない等うぶんつはやっぱデスクトップ向けかなぁ。