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
四捨五入や切り捨てではなく偶数丸めになっているため、
このような挙動になります。
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
これは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人)
30000万以下はこっち
ちなみに全体をグラフにするとこんな感じ。
・・・って、あまりにも偏っているので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 これはひどい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
まとめ
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
で戻せる。
みにきゅん買ってみた
湘南地域で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入れ直しちゃいました。
<結論>