2010年8月23日月曜日

灼熱アイランドのExcel

CollectionオブジェをMap的に使用する際の注意事項

VBAのCollectionオブジェクトは、Key-Value形式で値を格納でき、Map的な使い方が可能。
ところが、キーの有無を確かめるAPIが無い(JavaでいうところのMap#containsKeyみたいな)。
その上、存在しないキーを指定すると、落ちる。
以下の例では「mapModoki.Item("キー2")」で落ちている。

ちなみに利用可能メソッドはたった4つ(仕様は名称から大体分かるよね)。

VBAの内部文字コードはUnicodeで、エンコーディングはUCS-2

※Office2000以降。参考:EXCELのVBAでLenB関数について

あまり聞いた事がない符号化方式だが、これって何と全角も半角も2バイト。
'以下はすべて「10」と表示される
MsgBox LenB("12345")
MsgBox LenB("abcde")
MsgBox LenB("12345")
MsgBox LenB("ABCDE")
MsgBox LenB("あいうえお")

Shift-jisで扱いたい場合は、StrConv関数使って変換すべし。
LenB(StrConv("文字列", vbFromUnicode))

Javaでいうところのcontinue文は無し

次ループに処理スキップするcontinue的な構文は何と用意されておらず、ラベルとGoto文使用するしかないとのこと。使えね~
参考:VBAのループ構文にnext(Perl)やらcontinue(C)やらの機能がない件

セル内改行の検索方法

「Alt + Enter」で入力できるセル内改行。これを検索したい場合は、「Ctrl + J」を使うんだってさ。
以下、セル内改行を「\n」に置換した例。ご覧の通り、「Ctrl + J」の値は検索ボックス上には見えない。


ちなみにOpenOfficeのセル内改行は「Ctrl + Enter」。OpenOfficeの場合の検索方法は不明。

ワークシート一覧表示隠しコマンド

シート移動矢印部分を右クリックすると、シート一覧が表示されることを最近知った。
これでシートが数十あるような場合の移動が楽になる(てかブック分けろ)。

え?みんな知ってたって?

2010年8月22日日曜日

真夏の夜のWindows

リモートデスクトップ接続:接続先のPCをシャットダウンする方法

リモートデスクトップで接続した場合、スタートメニューに「ログオフ」「切断」はあるが「シャットダウン」が無い。
まあコマンドプロンプトでshutdownコマンド実行すれば済む話なのだが、GUIどっぷり世代としては、マウスクリックでシャットダウンする方法も知っておきたい所だ。
調べたらすぐに見つかったので、ここに記す。
by GUI:「ロック」やら「タスクマネージャ…」ボタン等が並んだあのダイアログから
PCフリーズ時の御用達である「Ctrl + Alt + Delete」。この操作で出現するダイアログ(※1)には「シャットダウン」ボタンがある。接続先PCも同じWindowsなので、このダイアログを利用してやればいい。

では早速「Ctrl + Alt + Delete」ポチッとな…ダメだ。接続元PCに対してダイアログが表示されてしまう。

正解は「Ctrl + Alt + End」でした。
by CUI:shutdownコマンドの使い方も
オプション無しで実行した場合はヘルプが表示されるだけ。
シャットダウンを実行する場合は「/s」オプションが必要。
C:\>shutdown /s
「いもうとデスクトップ」と空耳ったあの日は快晴だった
はい、既出ですね:検索結果


コマンドプロンプト:カレントドライブの移動

「cd」だけだと移動できないということを時々ど忘れする。
ここに記すことを以て焼きつけるんだ、俺。
方法1:cdなんていらない
ドライブ名だけでOK。
C:\>D:
方法2:やっぱりcdが恋しい
「/d」オプションを使用。
C:\>cd /d D:


※1
WindowsXPで「ようこそ画面を使用する」設定の場合、ダイアログは表示されずタスクマネージャが起動する。しかし、この場合タスクマネージャに「シャットダウン」メニューが追加されており、そこからシャットダウン可能。
試したことないですけど、もし接続先PCが「ようこそ画面を使用する」設定だった場合、同じ挙動なんですかね?

2010年8月16日月曜日

オラ、焼け野原しんのすけだゾ! その5(完) Trac横転

炎上プロジェクト記録、完結編。

Trac、稟議通らず

当プロジェクトの作業場所は客先。よって、ハードウェアは客先のものを利用することになるので、Tracのようなサーバソフトウェアのインストールには申請が必要(※1)。セキュリティに五月蠅い企業なので、こういった申請のフローは複雑・面倒で時間がかかり、散々待たされた挙げ句NGということが屡々。しかし、Tracに関しては、別会社主導のプロジェクトで利用実績があったので、すんなり通るだろうと皆高を括っていた。それでも申請してすぐOK出るかというと流石に厳しいので、それまでは僕のPCにインストールして利用することとなった。

結果…何とNG。情報共有ならグループウェアNがあるし、タスクリストはExcelでいいじゃないですかとのこと。Excelで情報共有する事の愚かしさなんて過去に語り尽くされたし、グループウェアNは全文検索ができない(※2)。今時、Webで情報検索する時、カテゴリ辿りますか?キーワード検索でしょ?キーワード検索の方が遙かに楽でしょ?
上記の事を(勿論大人の対応で)伝えて頑張ってみたが、玉砕。某社はOKだったのに…会社力の違いか?それとも俺の力不足か?
一応、現状の環境(僕のPC上で稼働)を利用する許可は頂けたのだが…何だかなぁ…(※3

Trac < Excel

今年の1月の私。
・仕事が楽しくなってきた。『Trac Lightning』を利用して開発プロセスのChange(死語)に取り組んでいるからだ。
・懸念していた「面倒くせ~」といった反発もなく、むしろ積極的に利用してくれており…
・非常に充実している
この頃はまだ平和だったからなぁ…

プロジェクト序盤は、上記の通りそれなりに利用されていた。しかし火を噴いた中盤以降、
「Excelの方が記入楽。チケット登録するのって面倒臭い。」
「口頭の方が速い」
「チケットだと集計がしづらい。Excelならマクロが使える。」
等の難癖をつけだし(上も下も)、殆ど利用されなくなった。
人間の本質は、やはり追い込まれてから現れる。

「チケット登録の手間とExcel記入のそれの間に大きな差があるとは思えない。」
「Tracには集計に利用できるクエリ機能というものが備わっている。SQLを使えるので、マクロ組むよりは絶対簡単。どうしてもExcelで欲しいという場合でも、Excel形式でダウンロードできるので、チケット登録しておいて損はない。」
「今回、Tracによる管理に取り組んでいる第一の目的は、ノウハウ蓄積。やり方戻したら、今まで通り何にも残りませんよ!」
そしてここでもExcelで情報共有することの愚かしさと共に、上記事項を伝えて頑張ったが、再び玉砕。中盤以降は、質問は殆ど『口頭』、Excel管理すらされていない状況。バグ一覧表とかは流石にExcel作っていたが(それこそTracの役割なのに…)。てか、あんだけ「Excelじゃないと集計できない」とか言ってた癖に、出来上がったExcelファイル見た限り、集計なんてしてる気配が全くない。あの啖呵は一体何だったのだ?

口頭至上主義

その2その3でお伝えした、DBアクセスロジックの仕様分裂問題。この問題の対応がどうしても納得いかず、はらわた煮えくりかえっていたので、プロジェクト完了後に改めて直訴した。こちらの最大の主張は、
「『意見があれば言ってください』と伝えており、さらに使えない旨を伝えて向こうは『了解した』と言ったにもかかわらず、勝手なことをしていた」
という点。ちなみにこの遣り取りのメールは、本文冒頭に「マネージャー陣も含めて全員必ず読んでください」という一文を赤太字で含めていた(レビュー時のリアクションを考えると、ここまでしても読んでなかったようだが)。
するとマネージャーは
「口頭で遣り取りしなかったからだ。」
…わからん。世の中、そういうものなのか?その時も、こうして文書書いている今も、これに対して何て返事していいかわからない。
「読字障害をお持ちなんですか?」という言葉が危うく喉から出かけた。
てか、フロアが結構離れてるっつーの。一々口頭でなんて、非効率すぎる。

まあ、殆どのメンバーはその『口頭』方式を実践してましたが…
うちの会社、分散開発は絶対無理だなと実感した次第。それとノウハウの蓄積・見える化も。
「どんなにすぐれたツール・システムを導入した所で、使う人間に使う意志が無ければ…」という、ありがちな台詞がこの身を貫く。

※1
ちなみに、PCの場合は「Vector・窓の杜で公開されている『フリーウェア』は自由にインストールしてよいが、それ以外はNG」という、厳しいんだか厳しくないんだかよく分からんというもの。とにかく、どんなに有名・信頼のおけるツールであろうと、上記サイトで公開されてなければNG。秀丸もATOKもNG。ギークがキレる職場。

※2
或いは備わっていたのかもしれないが、少なくともその顧客は利用していなかった。

※3
僕のPCのパフォーマンス悪化を懸念していたが、後述する通りTracは殆ど利用されなかったので、それ程支障は無かった。嬉しいような悲しいような…


ガキの頃よく唄ってた初代オープニング、唄うは亀田誠治の嫁。

2010年8月15日日曜日

オラ、焼け野原しんのすけだゾ! その4 プログラミング力≒片付け力

気がつけば本日は終戦記念日。そんな日にこんなタイトルのエントリ、不謹慎か?



さて、これまで3回に分けて行ってきた、炎上プロジェクトの1人ふりかえり(その1 その2 その3)。致命的レベルの問題のふりかえりは粗方完了した。私の仕事力・文章力不足もあり、Tryの内容・表現がショボかったり、そもそもエントリ自体が愚痴っぽくなっているかもしれないが、それは追々改善していこうと思う。

当エントリからは、プロジェクトに対するその他の考察・感想・愚痴などを記す。

プログラミング力≒片付け力

プログラマに対して、私はある偏見を抱いている。それは
「デスクトップやブックマークが汚い者は、総じてソースコードも汚い」
というものだ。
プログラミングは、結局は『整理整頓』作業の連続だ。固定値の定数化、何度も使用するロジックの関数化・クラス化、関数化・クラス化する際はどのように分割するのがベストか、無駄・冗長な記述を如何に抑えるかetc…。よって、僕が思うに、プログラミングで一番必要なのは、『整理整頓力』とか『片付け力』とでも言う力だと思う(※1)。
そしてこの力の有無を如実に露わにしてくれるのが、デスクトップやブックマークだ。『片付け力』の無い者は、フォルダやタグで系統立てて整理することを碌に行わず、混沌と化している(フォルダの命名も分かりにくかったり…)。

『片付け力』という力。この力は、向上させるといういう意識を持って取り組まなければ、向上するものでは無い。人生経験、仕事のキャリアを積んでいけば自動的に向上するというものではないのだ。皆も今までたくさん見てきたことであろう、部屋を『片付けられない大人たち』を。
プログラミングも同じで、整理整頓された綺麗なコード書いてやるぞ!という意識が無い者は、いくらプログラミング経験を積んだところで、生み出すコードは汚いままだ(※2)。

以上より、『Problem6:技術力はキャリアの長さに比例するという認識』には、大いに異を唱えたい。

上記偏見、僕の少ないキャリアで見てきた限りでは大体当たっていると思うが、皆さんの周りではどうだろうか?


※1
この理屈だと、「ソースコードが汚い人間は、デスク周りや部屋も汚い」という事になる。確かにその通りの者は多い。そうでは無い者、つまりソースコードの割にデスク周りなどは綺麗な者は、得てして『八方美人』が多いというのが僕のもう一つの偏見だ。現在のプロジェクトにもそういう輩がいる。目に付く範囲ではきちんとする、普段は遅刻してる癖に、マネージャーがいる日だけは遅刻しないという…それも1人だけではない…鼻折りたい。

※2
経験を積むことで、既存のライブラリだけでどれだけの事ができるかという知識が蓄積され、所謂『車輪の再発明』をやってしまう可能性は減少し、「無駄・冗長な記述を抑える」に繋がる事は確かにある。
が、根本的に『片付け力』が備わっていなければ、焼け石に水だろう。

2010年8月14日土曜日

オラ、焼け野原しんのすけだゾ! その3 技術力∝キャリア?(後)

前回のあらすじ。
DBアクセスロジックに関して、どのように実装するかの方針を開発者全員で打合せを行い合意形成。その後に意見は何も出なかったのでフィックスし、製造フェーズが開始された。
製造フェーズが開始されて数日後、メンバーの1人から「DBアクセスの仕組みを作った」との連絡が。内容を確認した所、致命的な問題も含まれており、そもそもフィックス済みの方針と異なるので、採用できない旨を伝える。その後、了承した旨の返事を受け取る。これで一件落着かと思われたが…
メールの遣り取りがあった次の週、コードレビューが実施された。内容は、コーディング・命名規約等が遵守されているかどうかをチェックするというもので、「ここはこう実装した方がいいんじゃない?」というようなリファクタ目的ではない。
※ちなみにコードレビューは結局この1回限りだけだった。何だかなぁー…

今回のシステムは、大きく分けて画面系とバッチ系に分かれていた。プログラマは全6名で、その内2名がバッチ系担当、その他4名が画面系担当だ。全てのソースコードをレビューする時間的余裕は無かったので、画面系・バッチ系それぞれから代表して1つの機能を抜粋し、それに対してレビューを実施した。画面系の代表は私が製造した機能だ。まず私のコードのレビューを行い、つづいてバッチ代表の番となった。途中まで淡々と進んでいたが、DBアクセスロジック部分で問題発覚。バッチ側のコードが、開発者間で合意形成した決定事項を遵守していない。 先週のメールで遣り取りした「採用できない」仕組みのままだ。
同席していたリーダー(以下、L)が

L「何で分裂しているの?統一してください。」

とごもっともな一言。いや、ごもっともじゃないな、ここは違反している側に対して「規約を遵守してください」じゃないのか?
「統一せよ」ではなくて「違反している側は遵守せよ」が正当である旨と、そもそもこの仕組みは「採用できない」旨を伝えたところ、その仕組みを作った人物(以下、X)曰く

X「致命的な問題は修正したので問題無い。」

との事。どうやら、SQL文実行クラスを、Java標準のものから、フレームワーク標準のDBアクセスクラスに変更した、これで要件満たせるとの事。いや、もうそう言う問題じゃ無いんですけど。約束事を守っていないんですよ。
すると、

L「何でちゃんと話し合っておかないの!とにかく統一してください。」

私「こちらはその話し合った末の結論に従っています。それに、結論出た後も度々『意見があれば言ってください』って伝えてましたが、このような仕組みを作っている事に関して、何も連絡ありませんでした。致命的な問題の修正に関してもそうです。」

約束事は度々破るわ、技術的にも使えるものでは無いわ…折衷案があるような問題でも無いし、こちらとしては全く譲歩する気は無い。その旨伝えた所、

X「こっちの修正は無理。もう大分作り込んであるから。」

…わからん。何ですか、この威風堂々っぷりは。
しかし、もっとわからないのは、リーダー陣はどうもXの方を支持しているらしいという現実だ。
その心は、前回エントリで挙げた
Problem6:技術力はキャリアの長さに比例するという認識。つまり、キャリアが短い者の言うことよりは、長い者の方が正しいという価値観。によるものだ。
5年目の若造よりも、10年以上の付き合いがあって仕事も速く(※1)て信頼できるベテランの方が正しいと考えてる感がひしひしと伝わってくる。「Xさんが言うなら間違いない!」という台詞を何度聞いたことか。実は、「致命的な問題は修正した」と言っておきながら、相変わらずPreparedStatement使ってなかったので(※2)、この点に関して突っ込んだのだが、ここでも終始「Xさんが言ってるんだから…」という感じだった(※3)。

結局、約束事を守っていたのは画面チームの3人で、画面の1人とバッチチームは例の「採用できない」仕組みを利用していた。再度話し合って決定しろという事になったが、そこでの遣り取り・雰囲気を考えると、「話し合え」なんて只のポーズであることは明らかだ。結論なんて、既に決まっている…結局、約束事を守っていた3人が、血を吐く羽目となった。



後で聞いた話だが、バッチチームが独自の仕組みを作ったのは、マネージャーの命令だったとのこと。バッチ系プログラムは、将来的にフレームワークを変更した場合も利用できるように、フレームワークに依存しない作りにしたかったそうだ。
…いやいや、それなら、画面系と統一させる必要なんてないじゃないか…ったく、リーダーは偉そうに「ちゃんと話し合え!」と言っていたが、そっちだってマネージャーと意思疎通できてないじゃないか。
それに、「フレームワークに依存しない作り」なんてものは、顧客は望んでいなかった。一応、プログラマ・リーダーという立場のため、クラス構成の説明等を顧客に説明しなければならない機会があったのだが、
「何でこんなややこしい作りにしてるんですか?」
「フレームワークに依存しない作り?でも結局フレームワークのライブラリ使ってますよね?」
「ハッキリ言って非常にわかりづらくて、保守しづらいです。」
と、散々だった。はい、全く仰る通りです…
マネージャーはその旨伝えてあると言っていたが、この時の遣り取りを鑑みるに、全然伝わってないことは明確だ。YAGNIの原則について勉強してください。




さて、今回のProblemをおさらい。
  • Problem5:開発者間で決定するように指示した事項に関して、その決定事項の内容確認、及びそれらが遵守されているかどうかを確認しなかった。
  • Problem6:技術力はキャリアの長さに比例するという認識。つまり、キャリアが短い者の言うことよりは、長い者の方が正しいという価値観。
これらを解決するためにTryしなければならないことは?
  • Try5:
    …わからん。確認してもらったところで、Problem6が存在する限り、覆る可能性は常に存在する。
  • Try6:
    価値観を変えさせるのは非常に困難。よって、「技術力がある」と思われるようになるしかない…のか?

※1
確かに仕事は速い。だが質はどうかというと…↓

※2
PreparedStatement使わない理由を尋ねると、「SQLがキャッシュされると、大量のSQL実行した場合、サーバーのメモリ食い尽くして落ちる」とのお答えが。いやいや、キャッシュしない(使い回さない)方がメモリ食い尽くすと思うが?それ以前に、メモリ食い尽くす程の量のSQLをPreparedStatement使わないで実行してたら、パフォーマンスの面を絶対クリアできない。
ちなみに、SQLインジェクション脆弱性に関しては、「エスケープ処理は(パラメータ)渡す側の仕事」だそうだ。絶対間違っている。PreparedStatement使う方が、遙かに簡単・安全・確実だ。

※3
この遣り取りで、開発チームの誰もがSQLインジェクションを知らないらしいという事実が判明。



懐かし。『ESCAPE』よりは『アネモネ』の方が好きだったなー

2010年8月13日金曜日

オラ、焼け野原しんのすけだゾ! その2 技術力∝キャリア?(前)

「燃えるゴミのほうに燃えないゴミ入れたらダメですよ。
でも燃えないゴミのほうに燃えるゴミ入れるのは別にエエやん」
~ by 松本人志 at 松紳とか放送室とか
松ちゃん、それは屁理屈だ。

さて、前回に引き続き、ふりかえりを行う…って、1ヶ月近く経ってるじゃねぇか。この間一体何してたのかというと、ロシア状態ですわ、また…
  • Problem5:開発者間で決定するように指示した事項に関して、その決定事項の内容確認、及びそれらが遵守されているかどうかを確認しなかった。
  • Problem6:技術力はキャリアの長さに比例するという認識。つまり、キャリアが短い者の言うことよりは、長い者の方が正しいという価値観。
詳細設計フェーズも終盤に差し掛かった頃、DBアクセスロジックの実装の規約・方針を決めておくように上から指示された。

Java言語(というよりオブジェクト指向言語)でDBアクセスといえば、DAO・DTOと呼ばれるクラス群(+ORマッパー)で行うのが一般的だ。開発を何年も行っていれば、どこの会社も大抵はプチフレームワークとでも言うような仕組み・パターンを構築しているものだろうが…うちの会社はさにあらず、全社標準の規約というようなものは存在しない。コーディングは疎か、仕様書のフォーマットなども、プロジェクトによってまちまちだ。外部から参画している1人のメンバーは「(全社標準規約的なもの)無いの!?駆け出しの会社じゃあるまいし、普通作るよね…」と呆れ顔だ。
※規約が無い事もさることながら、その現実に対して何ら疑問を持ったり改善しようとしてこなかった古参社員にはもっと…

閑話休題。さて、話し合い、今回のプロジェクトではどうするか…ぶっちゃけ、特に話し合うことなどは無かった。どういう事かというと、
  1. 当プロジェクトで利用するフレームワークのライブラリに、DBアクセスクラスは用意されている。
    ※SELECT・FROMといったSQLの要素をプロパティとしてセットし、それを元にSQL文を生成し、SELECT文であれば検索結果をHashMap的なオブジェクト(の配列)で返すといったクラス。
  2. このフレームワークのシステムでは、1.のクラスを用いるのが一般的というか当然。
    同じフレームワークで構築した他のシステムにおいても、勿論上記クラスを使用している。
  3. 1.のクラス使用すると、ログ出力・主キーにセットするシーケンスの採番等、『おまけ』処理も自動で行ってくれる。
  4. 3.のおまけ処理に関して、顧客から要望が挙がっている。つまり、顧客も1.のクラスを使用するものだとの認識でいる。つまり、「1.のクラスを利用する」ことは、暗黙的ではあるが顧客の要件である。
  5. 作ったシステムを保守するのは顧客自身。顧客(情シス部門)はSIerと異なり、保守的なスタンスであり、あまり新しい事にチャレンジしたり覚えたりしたがらない。
    よって、2.で述べた他の既存システムとあまり外れた方法をとるべきではない。むしろ揃えるべき。
と、言うわけで、選択の余地など無い。DAOやらDTOやらクラス設計どうするというような大規模な取り決めなど不要。こちらで出来ることと言えば、上記DBアクセスクラスをラッピングすることくらい。
結局、上記5項目を全員に伝えた上で、どういう単位でラッピングするかという事だけで終了。話し合いは意見が衝突するようなこともなく、「意見は?」の問いに誰も挙手せず。話し合い終了後も意見は出ることもなかったので、フィックスし、数日後に製造フェーズは開始となった。

製造フェーズが始まって数日、あるベテランプログラマから連絡が入った。
「DBアクセスを行う仕組みを作った、概要・使い方を説明したいので、時間取れないか?」と。
…はて、フィックス済みだが。ユーティリティー的なものを作りましたってことなのか?でもそれにしては「時間取れないか?」って大袈裟だよな。
この時点で進捗に遅れが発生していたこともあり、あまり時間をかけたくなかったので、とりあえずソースコードを見せてもらった。

…結果、絶句。 本当に仕組みを0から作ってやがる。
SELECT・FROMといったSQLの要素を引数で渡し、それを元にJava標準のStatementやResultSetを使用してDBアクセス、SELECT文であれば検索結果をHashMap(の配列)で返すといった仕組みだ。
前述の1.のDBアクセスクラスと、内容どんがぶりである。激しく無意味だ。そして、無意味なだけでなく、致命的な問題点も含んでいる。
  • 致命的な問題
    • 顧客の要件を満たせない(ログ出力等)
    • PreparedStatement使用していないので、SQLインジェクション脆弱性が存在!
  • 致命的では無いが…
    • インターフェイスをテーブル単位で作成する必要があるなど、クラス数が増大する。 今までのやり方と異なる事もあり、顧客からクレームが来る可能性大。
      ※フレームワーク標準のDBアクセスクラスは、DB情報は設定ファイルから取得するので、このような余計なクラスは不要。
    • SQLの要素を渡す手段が引数だと、その組合せの数だけ引数違いのメソッドを用意しなければならない。
      ※SELECT、FROM以外は必須じゃないからね。必要無い場合はNULLで渡すなんてイケてないし。
    • そもそも、この仕組みで行えることは、フレームワーク標準のDBアクセスクラスで全て実現可能。しかも、より簡単かつスマートに。
PreparedStatement使ってないのは本当にビックリした。『いろはのい』だぞ?何年やってんだ…
上述の通り、採用できないのは明らか。加えて、そもそも既にこれに関してはフィックス済みで、その決定内容で製造フェーズが開始されてしまっている。このような案があるなら、何故事前に連絡をくれなかったのか?
そのような事も添えて、この仕組みは採用できない旨をメール送信。ここでも「意見があれば言ってください。」の一文と共に。結果、「了解した」との素っ気ない返事。ちょっとイラっとしたが、取り敢えず一件落着…と思っていた…

そのような遣り取りがあった次の週、我が社では珍しく(というか恐らく初の)コードレビューが実施された。 そこで明らかされたのは、開発者間打合せ、上記のようなメールの遣り取りを経たにもかかわらず、決定事項が守られていないという現実…しかも、6人中3人も。

思ってた以上に長くなったので、エントリ分ける。つづく。


ちなみにCoccoで一番好きな曲は『寓話。』です。