トップ «前の日記(2004-03-18) 最新 次の日記(2004-03-20)» 編集

日々の破片

著作一覧

2004-03-19

_ 続変数名

というわけで、ローカル変数名のデフォルトを無意味1文字変数とすると、次のように論が進められる。

前提:ローカル変数は1文字か2文字で付ける。(実際は、もっとゆるいのだ。別にBook bkでもBook bookでも構わない。この場合、Book bokはありえないとは思うけど、それでも構わない)

例外:特に着目すべき変数についてはフルスペルやそれに準じた変数名をつける。たとえば、

Book myGrandFathersFavoriteBook

この方法論は、次の方法論より、有効だ。

前提:ローカル変数であってもフルスペルな変数名を付ける.

Book myGrandFathersFavoriteBook

Book myGrandMothersFavoriteBook

Book myFatersFavoriteBook

Book myMothersFavoriteBook

Book myBrothersFavoriteBook

Book mySistersFavoriteBook

Book mySonsFavoriteBook

(ふむ、さらに悪いことにコピペ地獄に陥ってるな)

例外:for文のiくらいは勘弁してやる。

なぜ有効かといえば、例外的な記述は違和感を持つからだ。そのためそれが注目すべきものだということが明らかになる。

ところが、後者の場合、せっかくの例外的な状況が、まったく有効に活用できない。

それは

極上の料理にハチミツをぶちまけるかのごとく甘い思想

――範馬勇次郎

であろう。

_ 参照

これはOASISのXML Common Biometric Format TC Public Documentsだったりするのだが、ここからCommon Biometric Formatを見ると、簡単に

biometricObject.biometricHeader.format.formatType.BindedPrimaryAccountNumberっていうようなオブジェクトが集約したオブジェクトが集約した……オブジェクトの属性名とかが出てくるわけだ。

で、BindedPrimaryAccountNumberっていうのが正式な属性名になるんだが、もし変数名としてaccountNumberってのをテンポラリに使おうとしたら(それでも死ぬほど長いが)、それは既に略してるんだよね。

で、まあ、手元にメソッドの引数としてbiometricObjectのインスタンスが渡されたとする。で、いちいち

biometricObject.getBiometricHeader().getFormat()....

なんて書くのは何がなんでもくだらないから、部分で切り分けることになる。

BiometricHeader h = biometricObject.getBiometricHeader();

で、ここで、hと書かずにbiometricHeaderと書くと

BiometricHeader biometricHeader = biometricObject.getBiometricHeader();

だ。

こんな行がずらずら並んだ、真っ黒なソースから問題点を探すのはばかげている。

というわけで、

BiometricHeader header = biometricObject.getBiometricHeader();

としてみたとする。

header.getFormat().getFormatType()....

と書いたほうが

h.getFormat().getFormatType()....

と書くより、「読みやすい」とか「理解が促進される」とか言い出す人がいたら、やはり何か変ですな。

プログラム書いたこともなければ、読んだこともないんじゃなかろうか?

すると、恣意的なルールを持ち出したくなったりするかも。

ゲッタが4個以上になる場合は〜とするが、2個ならば〜とか。

だが、ルールは少ないほうが覚え易いし、実効性を持つ。そうじゃなければ破られるだけだ。破りたくなるようなルールは間違っている。

ショウカの法三章ってやつだ。

というわけで、ブロック内での変数(だいたいオブジェクト指向言語で記述する以上、変数の役割はキャッシュか計算の中間結果の保持用だ)の名前なんて短くても問題なし。

#まあ、可能性としては、乏しい語彙の世界でしかプログラムを記述したことが無い人間がルールだとか言ってるんだろう。としか考えられん。

というわけで、豊富な語彙の世界でプログラムを記述したり読んだりしているおいらが言っておこう。

「変数名は短ければ短いほど良い。」

#追記:当然だが、スキーマ上の要素名が長いのはまったく問題ない。こっちを省略させたり短くしては本末転倒だ。

_ 簡潔な記述のためのキャッシュ

ここで言うキャッシュっていうのは、たとえば最適化とかを意識して行うことではなく、単に短くための道具のことだ。
a.getB().getC().getD().getE();
とある場合に、
b.getB().getC().getD().setE(a.getB().getC().getD().getE());
と書くかわりに、
b_d.setE(a_d.getE());
と書いてある方が、単純に読みやすい。それは、余白が多いからだというのはいい?
で、この時に、aがソース、bがデスティネーション(クラスは同じ)という場合に、
dst_d.setE(src_d.getE());
と書くとする。
で、ここで、
desination_d.setE(source_d.getE());
のほうが、本当に、dst_d.setE(src_d.getE());
より望ましいですか? (と、具体的な読み手が想像されると急に丁寧語になってみたり)
で、実際には、dとしているがこれが、AccountOfTheCustomerっていう要素名だと
dst_act.setE(src_act.getE());
というよりキャメルケースで、
dstAct.setE(srcAct.getE());
より、
destinationAccount.setE(sourceAccount.getE());
のほうが良い?
しかも、実際には、ここでAccountと略しているが、同じXMLの兄弟要素に、AccountOfThePublisherとかAccountOfTheShoppersとかが並列しているとする。
その場合、Accountという省略は、「わかりにくい」。なぜならば、どのAccountかが略されているからだ。
すると明晰さを求めるためには、
destinationAccountOfTheCustomer.setE(sourceAccountOfTheCustomer.getE());
で、こうなってしまえば、最初に行った「 ここで言うキャッシュっていうのは、たとえば最適化とかを意識して行うことではなく、単に短くための道具のことだ。」が無効化されてしまう。
というところで、落としどころとして、まあ、兄弟要素には目をつむって
destinationAccount.setE(sourceAccount.getE());
としたとする。
だったら、そんな「落としどころ」はやめてしまって、
dstAct.setE(srcAct.getE());
のほうが良いのではないか?
ってことなんだけど。
#あと、上じゃ忘れてるが、前提はスコープの狭さにあります。 #わざとクネクネカーブの道を住宅地に作り時速20Km制限を守らせようとするのに近いのかも知れない。
#変数名は短くて良いとすれば、よろこんでhとかsとかを使いまくるだろうと前提しているわけだ。
#反省略/フルスペル派は、やっぱり放っておけば、そうなって荒れると危惧してるだろうと想像できるから、この前提は良いと思う。
で、実際に書けば、よほどセンスが無ければともかく、iとかsとかnとかで100行もあるブロック作れば、いったいおれが使っているこのsはなんだったか? となるんじゃなかろうか。
つまり、短い変数名は狭いスコープを強制し、かつ、「放っておけば省略した短い変数名を使うんじゃ無かろうか」の危惧のもとになる人間精神の方向に沿ったルールだと思う。変数名をどうつけるかより、スコープを短くとり、実行している処理を局所分割してあるほうが、後からソースを読んだ場合の読みやすさは上だと考えるというか、実際に読みやすい。
しかし、ひねくれた人間はいるから、短い名前をつけろ、と言っているのに、昨日の最初の引用のような、どう考えてもメソッド名をコピペしたような変数を作って、しかもたった5行くらいのスコープで使われるとたまらんなぁ、ということだったり。 などとやっている間にも、1000行くらいのメソッドに変数名hだのを使ったソースが量産されているという罠。
にも、かかわらず、1000行も真っ黒なコードで埋められるよりは、スカスカしているほうが読みやすいから、短い名前のほうがやっぱり好きだ、となるんだけど。 (っていうか、1000行もあったら、変数への代入が出てきた時点でメソッド呼び出しに変更していくしかないだろうな)
#しかし、世の中にはインテリセンスとかメソッド補完といったおそろしいツールを装備した開発環境があるから、素直に記述させると、
b.getB().getC().getD().setE(a.getB().getC().getD().getE());
が編集画面の全体を覆ってしまうという罠。
それと同時に、兄弟Accountがいくつあろうが、順番に処理するのであれば、
AccountType accounts[] = getAccounts(a);
for (int i = 0; i < nrOfAccount; i++) { // nrOfは良く使うな
    accounts[i] = null;
}
の都合2カ所しか使われない変数のために、accountsなんて打ち込むのはあまり意味がないと思うのは事実。
そのいっぽうで、メリハリってことに関しては、
AccountType as[] = getAccounts(a);
for (int i = 0; i < nrOfAccount; i++) { // nrOfは良く使うな
    as[i] = null;
    if (i == PUBLISHER_ACCOUNT_INDEX) {
      publisherAccount = as[i];
      ....(publisherAccount);
      publisherAccount.xxxx(ssss);
      .... = publisherAccount.getxxx();
    }
}
のほうが良いと思うのだが、その瞬間に、この内容は、
AccountType as[] = getAccounts(a);
for (int i = 0; i < nrOfAccount; i++) { // nrOfは良く使うな
    as[i] = null;
    if (i == PUBLISHER_ACCOUNT_INDEX) {
      setupPublisherAccount(as[i]);
    }
}
というように、メソッド名によって吸収されてしまうのであった。 で、追加があって、setupPublisherAccountというか、最初の要素名にあわせればsetupAccountOfThePublisher()という名前になるわけだが、このメソッドは名前からいっても特定要素の関心空間だってのは自明だから
private void setupAccountOfThePublisher(AccountType a) {
      ....(a);
      a.xxxx(ssss);
      .... = a.getxxx();
}
となってしまう。これはイヤなんだろうなぁ、と想像できるが、ここで引数がAccountOfThePublisher以外の意味になることはありえないんだから、暗黙のselfが欲しいくらいでaと書くのさえばかばかしく感じるので、(AccountType account) { とはやはり書かない。
というか、自動生成じゃなければ、こんなメソッドはAccountTypeクラスに入れたいところだがよく考えてみればそれはおかしい(AccountOfThePublisherという特定の要素に関連)のでインスタンスの特異メソッドであるべきなんだろうがそんなものは無いから(たった1つの初期化メソッドのために無理矢理AccountTypeへのデコレータを作ってそこに入れるとはしない)、ここではコントローラに持たせてしまっているから仮引数なんていうものが必要になるのであった。
でも、copyAccount(AccountType source, AccountType destination);
くらいだとsrc,dstとする必要もないようには思うので(しても全然良い)、そのメソッドの処理範囲によって仮引数名の長さが決まる(が、こんなのは恣意的なルールだから、ローカル変数と異なり、メソッドレベルの命名規則の適用ということで、aは原則だめですなぁ、となる)。

_ ふむ。

適切な名前が付けられない、キャッシュ的なlocal変数を作るハメになったら、どこか、何か理解や設計の間違いがある。

実は同じことを言ってるように思える。

本来は、local変数というのは、パラメータやループのインデックスくらいしか出てこないものなのだ。これは同じ認識だと思う。

その出てこないほうがいいし、出ないようにもできるんだが、そこまでやり過ぎるのはかえって無駄であろうと判断した場合(たとえば、上のsetupAccountOfThePublisherメソッドをこの要素限定にするためにAccountOfThePublisherTypeというクラスを作るというようなこと)に、そうは言っても適切な代名詞を使うべし(って、srcはまさに3文字略語だと思うんだけど。だったらhdrでもいいじゃん)と考えるか、そんなの使い捨てなんだから短きゃ短いほど良し、と考えるかって「ここまで認識が異なる」ってほど重要な点かな(もちろん、重要なんだけど、後述)。

本質的にはどうも一致しているんだが、枝葉の部分で異なるってのがそんなに重要かと聞かれれば、「表現」ってのはまさにそれだ。

同一の内容を書いた文書であっても、ですます調、である調、2ch調、べらんめえ調で、全然、印象が異なる。当然だ。

で、おそらく、一般論としては「文語」であるべきだということなのであろう。ここが認識の相違で、僕は「口語」のほうが読みやすいと感じているのだ。厳密度は微妙に(スカスカすることは逆にノイジーである)口語のほうが落ちるのだが、そのかわりに文語には無い、リズムが生まれると感じているからだ。つまり、喋るように記述せよ、ということだ。

困ったことに、こと本質ではなくて表現にかかわる意見の相違ってのいうのは意見の一致を見ることは難しい。というか、あまり意味がない。だから仮に一緒に仕事する機会があったら、じゃんけんか多数決で「コーディング規約」を作って遵守するってことになるだろう。その時は、グーを出してください。僕はパーを出します。

本日のツッコミ(全18件) [ツッコミを入れる]
_ なひ (2004-03-20 00:36)

「ふむ」の段落を読んでもやはり、「ここまで認識が異なる」の気持ちはいや増すばかりでした。<br>上から下までいちいちひっかかってしまいます。<br><br>「本来は、local変数というのは、パラメータやループのインデックスくらいしか出てこないものなのだ」<br>→なひはメソッドの主題を明らかにするため、いきなりfinal local変数を置くことがあります。<br><br>「使い捨てなんだから短きゃ短いほど良し」→「使い捨てだから」という考えは悪いコードの証なので<br>常に避けろと指導しています。<br><br>「僕は『口語』のほうが読みやすいと感じているのだ。」→なひも口語のほうが読みやすいと感じます。<br>隠語は嫌い。<br><br>「喋るように記述せよ、ということだ」→御意。<br><br>面白いですね。似た分野の仕事だと思うんですけど、どこですれ違うのかな。

_ なひ (2004-03-20 00:37)

書き忘れました。りょーかい > ぐー :)

_ arton (2004-03-20 00:44)

1点。<br>>なひはメソッドの主題を明らかにするため<br>だって、主語はthisでしょ? と思ったら、「主題」か。主題はメソッド名だと思うけどな。<br>それはそれとして、いきなりfinal localに注目すべき変数を書くというのは良さそうなので場合によっては使わせていただきます。

_ arton (2004-03-20 00:46)

あと、隠語と口語は違います。たとえばオレは隠語ではありませんが、文語では主語として使ってはいけません。オレが主語になるのが口語です(もちろんワタシが主語の口語もあるけど)。

_ なひ (2004-03-20 01:12)

「34歳千葉在住既婚の会社員を〜」は×は同意できてますよね。<br>で、クラス・メソッド・ブロックにより適切にスコープを設定し、「男を」や「社員を」を使えと。「Aを」や「例のヤツを」は嫌。

_ arton (2004-03-20 02:00)

なるほど。それはうまい言い方ですね。その言い方だと僕はメソッドのレベルでは「男」、ただし特に注目すべき場合は「社員」から「既婚会社員」まで幅を持たせる、だが、ブロックの中では「それ(人なら「そいつ」」と呼べば良いという感じかな。「やつは34歳千葉在住既婚の会社員だ。やつにカバンを渡して金を受け取れ」って感じ。ハードボイルドプログラミングか。

_ なひ (2004-03-22 13:30)

ほとぼりが冷めた頃に。実はなひもsrcやdestなど、いくつかの略語は使います。「辞書用意しなきゃダメなほどの略語」は嫌いだ、と書くべきでした。<br>これについては1文字変数に関するセンスとは異なり、単に程度の問題かもしれませんね。

_ arton (2004-03-22 13:46)

辞書はねぇ、語彙数と管理上の問題です(きっぱり)。登録されている専門用語の数が100越えて、あと、忘れていたけど平均語長が15を越えるようなドメインでフルスペルに任せると、そこら中にスペルミスが今度は入り込むという罠もありますし。辞書+略語がいちばん、メンバー間での意思統一が楽ですな。

_ arton (2004-03-22 13:50)

スペルミスは、本当に、頭痛い。特に変数名だとミスっててもコンパイルエラーになるわけじゃないし、そこからコピペされて伝染していくって罠。

_ arton (2004-03-22 14:01)

思いつきというわけでもないけどスポンタナスにコメント入れてくと元発言が消える罠。僕も、headerとかcolorとかaccount程度は面倒だから綴っちゃうことのほうが多いけどね。実際は上だか前日だかに書いたけどそれの複合語になるから3×3でも9文字になったりするわけで、また複合させないと微妙なやつもいっぱいあるのも問題点。

_ arton (2004-03-22 14:16)

スポンタナス→スポンテイニアスらしい。

_ なひ (2004-03-22 15:21)

正しくはスポンタネオウスです。<br><br>専門用語の数が100超えて全てフラット(構造化でもオブジェクト化でもよいけとともあれ組織化できない)なんてのは、分析が甘いのです(きっぱり)。

_ arton (2004-03-22 15:47)

まあ、某団体に言ってほしいな、それについては。というよりも、どうも想定している単語の種類が違うような気もするけど(甘いも何も、そういう言葉だからね)、それ以上は職務上の秘密に属してくるからここまでですね。

_ arton (2004-03-22 16:10)

あと、なんか誤解しているみたいだから(フラットというやつ)付け加えておきますが、(どうしても例になってしまうのはしょうがない)元素を扱うとしても、フラットな空間(化合物になっていないやつ)だけでも水素とか酸素とか鉛とかたくさんありますね。これを英語で書けといったって、その時点で辞書はいずれにしろ必要です。

_ なひ (2004-03-22 16:51)

「サービス指向」とやらに乗じて、フラットに詰め込む設計をするやつが増えたと思いませんか。getFooOfBarWithBazメソッドとか、PairOfFooAndBar(Response)とか。<br><br>元素の例のほうは、「辞書」という言葉にひっぱられて違う話になってる気がします(なひから見れば)。この場合の辞書にはなんて書いてあるんでしょう。「鉛 ... plumbum」とか? それは仕方ないと思います。なひが言いたかったのは、3×3で9になるようなものは、独自に辞書に9エントリ作るのでなく、3分割して3ずつにできるんじゃないか、ということです。

_ arton (2004-03-22 17:26)

>辞書の件。言われている意味はわかりましたが、もちろん3ずつになってます。<br>たとえばありがちなのは、本日営業日(今日が日曜日なら実際は翌日)と昨日営業日の比較というような場合は、同一ブロック内に計算の結果求められた、「本日営業日」と「昨日営業日」の2つの変数が出てきます。しかも同一ブロック内に時間計算が必要になり、「本日暦日」と「昨日暦日」も出てきたりします。うんと簡単な例だと。これらは処理上はアトムですが、言葉としては複合語。で、かつ暦日、営業日および本日、昨日の区別も必要になります。同一ブロック内で。<br>で、bt, by, ct, cyですね、僕は。b=businessDate, t = today, y = yesterday, c = CalendarDate<br>>サービス指向」とやらに乗じて……<br> うーん、僕の業界だと強力過ぎて逆にフラットにしていかなければ現実味に乏しいデータモデルが先にあったりするので、良くわかんないです。

_ arton (2004-03-22 17:32)

変なこと書いたけど、辞書にbtとか出てるわけじゃありません。<br>営業日:BusinessDate: BusDay<br>日本語:要素名:略称<br>というような辞書になります。ブロック変数は別。

_ arton (2004-03-22 17:56)

あっ、SOAのやつもしかしたらかいま見えたかも。<br>それはメソッド名とかルートの要素名のことでは(と書いてあるし)。<br>それは粒度がサービスとしては細かすぎるのではないかと。とは言え、ユースケース上、しょうがない場合もあるかも知れないのでやっぱり判断は保留。


2003|06|07|08|09|10|11|12|
2004|01|02|03|04|05|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|09|10|11|12|
2007|01|02|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|04|05|06|07|08|09|10|11|12|
2009|01|02|03|04|05|06|07|08|09|10|11|12|
2010|01|02|03|04|05|06|07|08|09|10|11|12|
2011|01|02|03|04|05|06|07|08|09|10|11|12|
2012|01|02|03|04|05|06|07|08|09|10|11|12|
2013|01|02|03|04|05|06|07|08|09|10|11|12|
2014|01|02|03|04|05|06|07|08|09|10|11|12|
2015|01|02|03|04|05|06|07|08|09|10|11|12|
2016|01|02|03|04|05|06|07|08|09|10|11|12|
2017|01|02|03|04|05|06|07|08|09|10|11|12|
2018|01|02|03|04|05|06|07|08|09|10|11|12|
2019|01|02|03|04|05|06|07|08|09|10|11|12|
2020|01|02|03|04|05|06|07|08|09|10|11|12|
2021|01|02|03|04|05|06|07|08|09|10|11|12|
2022|01|02|03|04|05|06|07|08|09|10|11|12|
2023|01|02|03|04|05|06|07|08|09|10|11|12|
2024|01|02|03|04|05|06|07|08|09|10|11|12|

ジェズイットを見習え