どのようなコードをエレガントだと感じる? 124
ストーリー by headless
コード鑑賞 部門より
コード鑑賞 部門より
本家/.「Ask Slashdot: What Do You Consider Elegant Code?」より
コンピューターが使われるようになってから、失敗したプロジェクトや決して修正されないバグ、機密情報の漏洩、スパゲッティコード、その他日々使用する重要な機器やシステムを操作するプログラムの欠陥なども数多い。一方、よく設計され、完璧にコーディングされた知的に高度なプログラムを読み解いていくのは面白いものだ。自分ではポータブルGPSユニットが衛星を見つけて位置情報を計算するコードを見るのが好きだ。そこで、コードの公開されているコンパクトでエレガントなプログラムの例があれば教えてほしい。
万能細胞のようなコード (スコア:4, おもしろおかしい)
#include "/dev/tty"
これはあらゆるプログラムと成り得る万能コードです。
コンパイルする人に「じゃ、よろしく」とプレッシャーをかけることで発動します。
但しコンパイルする人のスキルに影響するのと再現性が意外と低いという問題があります。
コンパイルする際に適当なコードをコピペするだけで批判の対象となる問題もあります。
アルゴリズムのエレガントさと、コードのエレガントさ (スコア:3, すばらしい洞察)
アルゴリズムのエレガントさと、コードのエレガントさでは異なるわけですが、どちらを求めてるのでしょうか。
GPSの位置計算などとかかれていることから、元投稿者の求めているものはアルゴリズムとしてのエレガントさではないかと推測するのですが。
Re:アルゴリズムのエレガントさと、コードのエレガントさ (スコア:1)
データ構造のエレガントさです。
ダメなデータ構造を取るシステムはいくらコードを弄り回してもどうにもなりません。
dcraw.c (スコア:2)
汎用のデジカメRaw現像ソフト。
デコード部分のコードにコンパクトでパズルチックなものが多い。
富豪的プログラミングの名のもとに直接的なコードしか書けない自分には,
なかなか参考には出来ないもののこういう世界もあるんだなと考えさせられる。
ちなみに,外部ライブラリを除けば単一ファイルで完結するソフトで,最新版の行数は9,519行と異常に長いのも特徴的。
Re:dcraw.c (スコア:3, 興味深い)
今を去ること数十年前、アセンブラ(というよりマシン語)で
事故^h^h自己書き換えをする処理を見たときとか
レジスタに0代入より、自レジスタとXORの方が1クロック速いとか見たとき
ちょっと感動した記憶があります
Re:dcraw.c (スコア:3)
クロックは同じで、命令が短いっていう印象。
xorというとビット反転に使うけど、プログラミングを始めた頃、BASICでA=1-Aとして0と1を切り替えていたのを見たとき
ちょっと感動した記憶があります
Re:dcraw.c (スコア:2)
ええ、初めは命令長の短さから使われ出したと思います。ところが、今時のx86 CPUだとxorでの0クリアは特別扱いされるので実際に速くなるはずです、こういう例もあるということで。
ASCII.jp:インテルCPU進化論 細かく変わって性能向上Sandy Bridge (5/5)|ロードマップでわかる!当世プロセッサー事情 [ascii.jp]
Re:dcraw.c (スコア:1)
これかな?
http://www.amazon.co.jp/dp/4434046683 [amazon.co.jp]
http://www.hackersdelight.org/ [hackersdelight.org]
Re:dcraw.c (スコア:1)
レジスタに0代入より、自レジスタとXORの方が1クロック速い
クロックは同じで、命令が短いっていう印象。
Z80あたりの8bit CPUだと、
は4クロック、
は7クロックで、実際にXOR Aの方が速い。
その理由は、命令が1バイト短いから。パイプラインも無いしねえ。
Re:dcraw.c (スコア:1)
マシン語が想像できれば、応用が利きますよね。インストラクションセットによって違いますが、一般的には
1)「値」を使うとコードに値が埋め込まれるのでコードが長くなる。当然、フェッチにもサイクルが増える。
2)算術命令でも論理命令でもオペコードが少ない方が速い
3)フラグが変化する命令はサイクルが長い場合もあるので、できればフラグ変化なしの命令を選ぶ
ぐらいは通用しそう。
実際は、コンパイラがどんなコード吐いてるか調べるのは実効速度に効くループの一番底ぐらいですけど。
Re:dcraw.c (スコア:1)
> 1)「値」を使うとコードに値が埋め込まれるのでコードが長くなる。当然、フェッチにもサイクルが増える。
ところがどっこい。RISC系のアーキテクチャだと、即値ロード命令はその即値がオペコードに埋め込まれたものになってたりしますので、「コードが長くなる」ことはありません。
ただし、「レジスタは32bit」「オペコードも全命令32bit」「即値代入で指定できるのは16bit」といった感じなので、その範囲を超えた値の即値代入は、複数回のロードに分割する必要があったりしますが…
以下MIPSの例ですが、
MIPSには即値ロード命令はありません。そのかわり、「値がゼロ固定のレジスタ0」なんてのもあったり(読み込みとして即値ゼロの代わり。書き込み先に使えば結果は保存されずフラグチェックだけができる)するので、R0との即値演算という形で
R1クリアは、「R1 = R0 + 即値0」と記述したりします。
なんか回りくどい命令記述ですが、でもそれでも1ワードの1命令で実行1クロック、とかになったりしますからねえ。
#そういう即値指定ができるから、INCもDECも独立した命令は存在せず、通常の即値加算命令が使えたりとか。
Z80でアセンブラでコードをゴリゴリ書いて「XOR A が常識だろ」なんて考えていた身からすると、ちょっとカルチャーショックなアーキテクチャですね。
Re:dcraw.c (スコア:2)
整数変数×整定数だと今でもいろいろやるよ。 x86_64 の gcc で -O2 を付けてコンパイルしたら、シフトやら加減算やら LEA [mztn.org] やらに展開される。
Re:dcraw.c (スコア:1)
lea命令って便利だよね。
a = a * 5; が lea eax,[eax+eax*4] になったりする。
Re:dcraw.c (スコア:2)
これを便利と呼ぶか、 5 倍はできるけど 6 倍はできないなんて不便と呼ぶかは人による気がする……。
Re:dcraw.c (スコア:1)
この手のコード自体は悪くないけどさ、こういうのを多用すると見通しが良くなくなるからなあ。
バカがコードに目を通すこともあるわけでさ。
Re:dcraw.c (スコア:1)
Re:dcraw.c (スコア:2)
C で 0 か 1 が入っている int 型の変数の 0 と 1 を入れ替えたいときに、スピード優先 (?) で A = 1 - A とか A ^= 1 とかなら意図は理解できる (本当に速いかどうかは知らない) けど、見通しを良くするのが目的なら A = !A 一択じゃないの? 三項演算子を使うべき場面じゃないと思う。
Re:dcraw.c (スコア:2)
難しい上に乗算が出てきそうだから、テーブルから引けばいいやって思ってしまう。
(´・ω・`)
C言語で書いたJSONパーザ (スコア:2)
コメントなし、700行の関数。でもエレガント。
https://github.com/udp/json-parser [github.com]
自分意外が書いたコード (スコア:2)
は全てエレガントなんです
Re:自分意外が書いたコード (スコア:1)
なるほど、確かに意外だ
Re:自分意外が書いたコード (スコア:1)
この間ハードディスクの整理をしていたら,10年前に書いたコードが出てきて,
へぇ~俺こんなエレガントなコードが書けたんだ~(過去形)ってちょっと意外だった。
分岐が少ない (スコア:2)
高級言語であれニモニックレベルであれ、分岐が少ないとエレガントに感じる。
Re:分岐が少ない (スコア:2)
分岐というか、深いネストがあると汚らしく感じる。
Re:分岐が少ない (スコア:2)
あまり良い例を思い付かないけど、例えば
int16_t x; if (x > 100) s++;
な場合に、
s += uint16_t(100-x)>>15;
みたいな感じで、『評価を計算式に組み込む』とか。
#例に限定する突っ込みは禁止の方向でひとつ
他には、ある値に応じて、別の数を掛けたり足したり、或いは関数を呼びたい場合にテーブルを引くとか。
Re:分岐が少ない (スコア:1)
Re:分岐が少ない (スコア:1)
誤: case ~ switch
正: switch ~ case
Re:分岐が少ない (スコア:1)
個人的に (スコア:2)
・問題が適切に定義されている
・それに則って分かりやすいマインドモデルが作られている
・マインドモデルが適切にコード化されている
無理なく相手に伝わるコードがエレガントだと感じます
エレガントと言えば (スコア:2)
#以下略
永世小学六年生神アイドル支持者(バランス取らなくっちゃなぁっ!!)
Re:エレガントと言えば (スコア:1)
「お前は今まで何行のコードを書いてきた!」とか言われちゃったわけですかw
変更に強いやつ (スコア:1)
関心事の分離がキチンとされて、そこそこのカバレッジの単体テストとスモークテストがしっかりあるヤツがいいです
Re:変更に強いやつ (スコア:1)
それはもう完璧に近いな。
計算量のオーダー (スコア:1)
自分が書いたものよりも、計算量のオーダーが小さいものを見たとき。
もっとお手軽に、ループの数や使用メモリが少ないだけでもエレガントだと感じます。
オブジェクト指向 (スコア:1)
クラスの構造定義(インスタンス変数とかクラス階層の定義)を見ただけで、その機能を彷彿とさせるもの。
扱うデータの対象がきちんと整理されていれば、データ構造もわかりやすくなるはず。
一片の陰り無く (スコア:1)
白が美しいと。
http://compsoc.dur.ac.uk/whitespace/ [dur.ac.uk]
#基本は踏襲
マクロの基本は検索置換(by y.mikome)
ネーミングセンス (スコア:1)
センス以前に変数とかの名前が揃ってる
といってもVF00Aみたいな変なルールで揃えてるやつじゃないよ
m_ ではじまるやつとかハンガリアン記法とか頭大文字とか小文字の_繋ぎとか、そういうのが入り混じってると嫌。
全く凄さを感じない何の変哲も無いコード (スコア:1)
若い奴から見たら、この程度でいいのかよって思われるぐらいの何の変哲も無いコードが
結局一番良いコードだと思う。
それと似てるけど、チーム内で既知のパターン(というかイディオムというか)をちゃんと理解して
使ってることだね。
どうにも納得行かないところは、チーム内で連携して改善案を提案してみんなに使ってもらう。
みんながそういう意識で作業していけば、自ずと(少なくともチーム内では)エレガントなコードに
なると思われる。
なにしろ、コードは1人で書くわけじゃないから悲しいことに1人だけ気を付けてもしょうがないんだよね…。
非常に声が小さく (スコア:1)
黒魔術にはまっていて、よく似た妹が格闘技をしている。
#それはエレガントなお嬢様
らじゃったのだ
誰が見てもわかるコード (スコア:0)
コメントが丁寧に書いてあって、無駄に過去の変更点が残されたりしてないコード
特に、実装中に仕様変更が入ったりして、ドキュメントからは漏れてるような、ビジネスロジック上の特異なものがコメントされてる事
Re:誰が見てもわかるコード (スコア:1)
>誰が見てもわかるコード
そんなものはない。
一方で「作った本人以外には読めないコード」というのも確かにあるんだけどね。
Re:誰が見てもわかるコード (スコア:1)
何がしたくてどんな過程でなぜこう実装したのか意図がわかるコード
要件や挙動は察しがついても
「どーしてこーした」がさっぱりわからんソースがある
コメントはそっちを補足しろよと言いたくなる
難読は我慢しても
正解がどうにも追えないのはキツすぎる
Re: (スコア:0)
なぜこうしたのかって普通Redmineとかそっちに書かない?
Re:誰が見てもわかるコード (スコア:1)
>「作った本人以外には読めないコード」
作った本人にも読めないコードが一番エレガントかも。
# ある意味、最適化の極だから。。。
notice : I ignore an anonymous contribution.
Re: (スコア:0)
そして、納品間際にドキュメントがメンテされて...
なかったりして、どつぼにハマって...
# そして、へたれプラグラマは、呪詛の呪文にたけていくのでした...
Boid (スコア:0)
力業でプログラムは書けても、Boidとかライフゲームとか、そういう発想は模倣こそ可能でも自分から生み出すのは無理だと思うわけです。
間延びしない (スコア:0)
変数の宣言と使用箇所が近い
と、ぱっと見でもまともな人が書いたようにみえる
Re:間延びしない (スコア:1)
C99から、任意の場所で変数宣言できるようになってますよ、
Re:「(仕様通りに)動けばOK」という人がいるけれども (スコア:1)
解った。ソースを削除しよう。
ただしその前に、仕様を100%反映したテストを書いてくれ。
もちろん、テストにバグがあってはダメだぞ。
それにしたって、「仕様のバグ」は救えないよな。
Re:底辺プログラマーにエレガントさなんて.. (スコア:1)
もうちょっと言えば、実用的な速度で動いて欲しいな……