INDEX
- 背景
- だからこのコードはクソなのだ!
- あとがき
背景
かなり攻撃的なタイトルを付けたが、要はクソコードと言われるものを引き継いだり、
生産者からアドバイスを求められたりレビューをせざるを得ない状況に追い込まれ徐々に精神崩壊を起こしそうになった気がするので脳内妄想を吐き出してみることにした。つまりフィクションだ。いいね?
クソコードにも色々誕生秘話があって確かに大多数がクソ認定するコードもあるとは思うが、レビュアの理解が追い付かない事でクソコード認定されてしまう事もある。
はたまた、かつては輝いていたけど幾多の苦難2に飲まれ、多くの兵どもの夢の跡3を見守った結果、技術的観点からグリーフシード4のようにクソコードとなってしまった悲しい経緯があるかもしれん。
変に稼働実績があるからリファクタリング出来ないし、しない方が良い類のものでもある。5
まあ、そんなことはどーでも良い。この記事は
肩の力を全力で抜いて「あるある!」と笑えばいいのだ!6
だからこのコードはクソなのだ!
以下、グダグダと続く。後から何か気が付いたら追記するかもしれない。
ちなみにサンプルコードは主にJava
で書いているが基本的に言語に依存する話ではない。
1. インデントにスペースとタブが混在している
if (hoge != null) {
for (int i = 0; i < hoge.length; i++) {
\t String str = hoge.get(i);
\t System.out.println(i + ": " + str);
}
}
- 何?お前、うち(レビュア)の事を騙したいの?
- 人間は欺けてもコンピュータは欺けないので当然バグが入り込む可能性がある。
- このコードだと、基本は4スペースインデントだが、
for
の中身に1段分タブインデントがある。あった…(Qiitaさんに削られたので\t
と書く)
-
Python
だと割と致命的。
2. インデントに全角スペースが混入している
if (hoge != null) {
for (int i = 0; i < hoge.length; i++) {
String str = hoge.get(i);
System.out.println(i + ": " + str);
}
}
- 何?お前、うち(レビュア)の事を騙したいの?(再)
- これでバグ出してみろ。お前はボスにも**「先輩にも見てもらいました」**って言い訳の報告をして、うちは連帯責任取らされるんだろ?…クソッ…クソッ…
- このコードだと、
println()
の箇所に全角スペースがある
-
LL(Lightweight Programing Language: 軽量プログラミング言語)だと、実行時に初めて気づく場合も…
- 要コンパイルな言語だったり、開発支援機能があるエディタなら事前にエラー等で分かる
-
JavaScript
等言語によって使える場合もあるが、統一するならともかく混在は嫌だなあ…- メリーさんのパロディ7とかあるくらいだし。
-
Python
はダメかもしれん。
3. カッコの位置がテキトー
if (hoge != null) {
for (int i = 0; i < hoge.length; i++) {
String str = hoge.get(i);
System.out.println(i + ": " + str);}
}
- 何?お前、うち(レビュア)の事を騙したいの?(祭)
- スコープが分かりにくいクセに動作はするもんだから、相手によっては検収通っちゃて後の祭になんだよ!
- このコードの改修依頼とか来てみろ。うちが発狂する未来しか見えないから請けないからな!(ボスへの意思表示。頼む、頼む…)
- っつーか、すんごいモヤモヤすんだよ。目が腐るから読む気しないんだよ。こんなん門前払いだよ。フォーマッター使えや!
- スコープが分かりにくいクセに動作はするもんだから、相手によっては検収通っちゃて後の祭になんだよ!
- そもそもお前、これどっからコピって来た?
- 派生形(かどうかは知らんけど)で、インデント位置ガン無視もある。スコープって何?
-
Python
だととても致命的。うちも致命的。
4. スペルミスを気にしない
/**
* 名前を取得する
* @return 名前
*/
public String getoName() {
return this.name;
}
- いや、確かに呼び出している箇所全部でスペルミスのまま実装すれば動くけどさ…
- こんなん検収通っちゃった日には恥ずかしくてしょうがないんですよ…
- だってお前、どうせこのクラスのサンプルとして、うちが@auther neonemo8とか書いてるクラスを丸ごとコピって来て、さらに**@autherは自分の名前に書き換えていない**んだろ?
- ハハッ、
get
すら書けない低能野郎だってこのコードを引き継いだ会社の社員とかたまたまソースを覗いたお客さんに思われるんだろうな…クソッ…クソッ…
- ハハッ、
-
Python
に限らず恥ずかしいから止めてくれ…。うちは自ら発した言霊9により致命傷。
5. フォーマットの足並みを揃えない
/**
* 名前を取得する。未設定時は"(未設定)"と返す
* @return 名前
*/
public String getName() {
if (StringUtils.isEmpty(this.name)) {
return "(未設定)";
}
return this.name;
}
// 名前を取得する。未設定時は"(未設定)"と返す
public String get_name()
{
if(StringUtils.isEmpty(this.name)) return "(未設定)";
return this.name;
}
- 既存ソースを無視して、独自フォーマットを使い始めてしまう
- たしかに動作に違いはないが、運用上パッチ当てがあるソースだったりすると汎用パッチじゃなくて専用が必要になるかもしれん
- 正直ソース解析する時に、変に気を使うので止めて欲しいし、仮にフォーマッタの使用指示が無かったとしてもこの辺の感覚は養って掴んで欲しい。
- むしろ気に入らない書き方でどうしても変えたかったら、その旨を上司に相談し、既存のフォーマットを自力で全部直して、チームメンバーに布教活動するくらいの気概を見せて欲しい。勝手に反乱軍10を作らないでくれ…頼む…orz
-
Python
でもこういうのは嫌だろう。
6. 似た処理を行うのに不必要に複数の書き方をする
for (int i = 0; i < hoge.length; i++) {
System.out.println(i + ": " + hoge[i]);
}
int i = 0;
for (String v : hoge) {
System.out.println(i + ": " + v);
i++;
}
- カウンタも出力したいんなら、カウンタ番号で回す
for
文で良いだろ。- 他の実装箇所はカウンタで書いてるじゃないか。何故変えた!?
- コレクション系の
forEach()
とかもかな。使いどころですよ。
- いいんですよ。基本は自由で。必要があればなおさら。ただ、特に理由もなく同じプロダクト内なのに場所によって書き方が違うのはNGだ!レビュアがそのコードに対するレビュー内訓練が出来ず、結果解析速度が落ちてしまう。
- もっとも、書いた本人だって1ヵ月もしたら読むの大変だと思う。細かな内容は忘れてると思うので。
- いわゆるクセの一種だと思うが、統一する事で構文解析にレビュアの脳のリソースを割かずに済み、他のコード解析にリソースを割けるのでレビューの品質が上がる。かもしれない。
-
Python
だと…どうなんだろ?
7. 周りと文字コードが違っている
Shift_JIS「もしかして・・・・・・」 UTF-8「私たち……」
二人「蜈・繧梧崛繧上▲縺ヲ繧具ス橸シ?シ」
- 5ch(https://hawk.5ch.net/test/read.cgi/livejupiter/1514990323/)より引用11
- 菴包シ溘♀蜑阪√≧縺。�シ医Ξ繝薙Η繧「�シ峨′隱ュ繧√↑縺�縺ィ縺ァ繧よ昴▲縺溘�ョ�シ滂シ医ラ繝、繧。�シ�
- 指定された開発環境を使っていなかったり、どこぞからコピーして来たファイルをそのまま入れた場合にまま起きる。主な副作用は次の通り。
- ビルドが通らない(UTF-8前提の所にSJISが混入してマルチバイト誤認したりとか)
- Windows版Maven等で日本語のバリデーションテストをする時に良く落ちる。
- プログラムから吐き出すテキストが文字化けしている。
- 間違った文字コードでエディタを開いているだけならまだしも、その状態で保存なんかした日にゃ正しいマルチバイドを復元する事は極めて困難だろう。
- 設定ファイルとか設定ファイルとか設定ファイルな!そういう意味ではネイティブなpropertiesファイル12は優秀かもしれん。
- つーか、それライセンスとかバグとか平気?中身理解してコピってる?
- ビルドが通らない(UTF-8前提の所にSJISが混入してマルチバイト誤認したりとか)
-
Python
縺倥c縺ェ縺上※繧ゅム繝。縺�繧阪≧縲�
8. 指定の改行コードから別のものに変えてしまう
- 何?お前、うち(レビュア)に目grep13でもしろと?(眼精疲労)
- Gitで改行コード変換無しで運用するってのは割とあると思う。上記のスクショはGitHubにて改行コードのみを変更した場合のバッチファイルの差分である。
-
LF
と言われているのにデフォルトのCRLF
で作業していました等。- ファイル全体が差分として検出されるね!やったねタエちゃん!!
- つーか、プログラム不具合起こされても嫌だから直してコミットしなおせ!
-
- これも
Python
とか関係なしにダメだろ…。
9. 設計通りではないが一見すると要件通りではある
サンプルなし
- 何?お前、うち(レビュア)とボスに、次はテストフェーズだって時期に仕様と設計を変えさせてくださいとお客さんに謝罪と説得に行けと?(胃痛)
-
Python
とか関係なs(ry
FINAL. でも、動いているからOKですよね?
サンプルなし
-
だからこのコードはクソなのだ!
- そんなわけあるか!動いているからOKってのは、障害復帰等のスピード重視な暫定対応とかの特殊な場合だけだ。初期開発や恒久対応でそれはない。…ないよな?
- こういうプログラム改修で生産者がギブアップしてしまい、うちの所に回って来た場合、身内なら嫌がるし外部からならゼロベース開発を模索してしまうと思う。
- 命令されたらやるとは思うけど、「このクソコード書いたの誰だよ!」16って脳内でディスる未来が見える。
-
Python
(ry
Ex1. ブーメラン
- 2021/02/13追記
- @sohsatohさん指摘ありがとうございます。
- 誤:
auther
⇒ 正:author
- 案の定、うちもクソでした。そんな気はしてた…知ってた…知ってた…orz
- フリのつもりはなかったんだけどなあ。やっちまったな!
- 元々ボケ多めなのに自分でオチまでつけてしまった。ネタ記事ですし直すのもあれなのでそのままにしておきます。
Ex2. Pythonのタブとスペースの混在ってエラーじゃないの?
- 2021/02/13追記
- マンガの方のツッコミがTwitterの方にあったのでネタ晴らしをすると、2.7では、1タブが8スペース換算で動きます。3.8は混ぜるな危険と怒られますがががg
TabError: inconsistent use of tabs and spaces in indentation
あとがき
どうだっただろうか。
今回はコード解析やレビュー時に脳内ツッコミしている点などを書いてみた。
やり玉に挙げているのは業務ロジックの話まで行けない門前払いなソースである。
最近はレビューやプロダクト引継ぎとして他人のソースを読むことが圧倒的に多くなった。
まあ、引き継いだ方はしょうがないので解析するが、レビューの場合、本来は業務ロジックとかそういった方に力を注ぎたいのだが、ソースが読みにくい事が多くてそっちに気が回らない。集中が分散するので、レビュー品質が落ちてしまう。
そんな鬱憤が溜まってて爆発したのがこの記事でした。orz
とりあえず、初心者を自覚している人はコードフォーマッタを使う所から始めると良いかと思う。
Visual Studio CodeやEclipse等にもフォーマッタが組み込まれているしカスタマイズも出来る。
人間はテキトーだからね。エディタで手動調整するくらいなら先人の知恵が入ったツールは使いこなせばいい。
それにしてもこんな記事書いて怒られないかな…(ドキドキ
(2021/2/14追記)やべぇ…デイリートレンドに載っていいねが増えまくってしまい、タグランキングがクソコードの弊社みたいになってる。ボスに目を付けられるかも…やべぇ、やべぇ…。17
以上!
-
誤:
printf(f'~')
⇒ 正:print(f'~')
記事を推敲しないと修正だらけになる良い反面教師 ↩ -
経営戦略とかそういうの。スマホの料金プラン辺りをイメージするといいかも。 ↩
-
この場合は経営戦略的無理難題吹っ掛けられた結果、仕様が複雑化したシステムに立ち向かうエンジニアというニュアンス。 ↩
-
マドマギのあれ。 - グリーフシード - ピクシブ百科事典 ↩
-
そうは言っても引き継ぐ方は溜まったもんじゃないので何とかならないもんか…。 ↩
-
これ(こんなログは嫌だ! - Qiita)と同系統の記事だしね ↩
-
私全角スぺース、今あなたのソースの中にいるの - このページ(https://corobuzz.com/archives/43674 )のNo.8。 ↩
-
JavaDocの一種で作成者を表すもののつもり。文中はtypoで本当は
@author
が正しい ↩ -
神「authorの綴りが間違えているのはツッコミ待ちですか...?」俺「ああああああッ!」 ↩
-
「のばら」「きさまら はんらんぐんだな!」って帝国兵に襲われるあたり帝国に情報漏洩しているのは明らかなので反乱軍の情報セキュリティのリテラシーは低い。 ↩
-
Shift-JIS⇔UTF-8間の文字化けのパロディ。実は文字化けしている方にも意味がある。興味があるなら文字化けを解消したものを調べてみて欲しい。消えた情報自体は戻らないが正しくデコードできれば読めるようになる事もある。手練れてくると「糸偏が多いから元がSJISでUTF-8にしちゃったか?」等の勘が働くようになる。 ↩
-
Javaのプロパティファイル(*.properties)は、ASCIIで書かれるので基本的に文字化けしない。 ↩
-
diff
やgrep
コマンドが役に立たない時に発揮するいぶし銀の業。老眼にはキツイ。目grepとは? - https://atuweb.net/201808_about-me-grep/ ↩ -
要件通りじゃなかった箇所orz ↩
-
JUnit
はJava
のテストツール。@Ignore
はテストケースを一時的に実施しないようにするアノテーション。 ↩ -
そしてそれは往々にしてブーメランにもなる。なった(記事内で実証済み) ↩
-
…とか書きつつ、こういうイレギュラーな奴もある程度取り込める組織なので居心地良いですよ。 ↩