你能发一个真实的,过度的意大利面条代码的简短例子,可能会说它有什么作用?你能告诉我一个小调试器的噩梦吗?
我不是指IOCCC代码,即科幻小说。我的意思是发生在你身上的真实例子......
重点从“发布一些意大利面条代码”变为“什么正好意大利面条代码?”。从历史的角度来看,目前的选择似乎是:
答案 0 :(得分:18)
对我而言,意大利面条代码的一个更强大的现代示例是当你有20个dll并且每个DLL以某种方式相互引用时。你的依赖图看起来像一个巨大的blob,你的代码在没有真正顺序的地方跳过。一切都是相互依赖的。
答案 1 :(得分:14)
还有Ravioli Code,这是相反的。漂亮的小块功能,干净的界面整齐地包裹着肉质的美味,都坐在一个漂亮的框架酱。
答案 2 :(得分:12)
我不会把它从脑子里拉出来。这是我必须使用的,虽然简化了。让我们说基本上你有一个需要枚举的程序:
enum {
a, b, c;
} myenum;
但我们拥有的是
HashTable t;
t["a"] = 0;
t["b"] = 1;
t["c"] = 2;
但是当然,没有哈希表的实现是足够好的,所以有一个哈希表的本地实现,其中包含的代码大约是平均开源实现的10倍,其中一半的功能和错误数量加倍。 HashTable实际上是虚拟定义的,并且有一个工厂HashTableFactory来创建HashTables的实例,但是HashTableFactory模式也是虚拟的。为了防止虚拟类的infite级联,有一个函数
HashTableFactory *makeHashTableFactor();
因此,代码需要 myenum 的所有地方都会引用HashTable和HashTableFactory的实例,以防你想要制作更多的HashTable。但等等,这不是全部!这不是哈希表的初始化方式,而是通过编写读取XML的代码来完成的:
<enum>
<item name="a" value="0"/>
<item name="b" value="1"/>
<item name="c" value="2"/>
</enum>
并插入哈希表。但代码是“优化的”,因此它不会读取ascii文件myenum.xml,而是有一个编译时脚本生成:
const char* myenumXML = [13, 32, 53 ....];
来自myenum.xml的和哈希表由函数初始化:
void xmlToHashTable(char *xml, HashTable *h, HashTableFactory *f);
被称为:
HashTableFactory *factory = makeHashTableFactory();
HashTable *t = facotry.make();
xmlToHashTable(myenumXML, t, f);
好的,我们有很多代码来获取枚举结构。它基本上用在一个函数中:
void printStuff(int c) {
switch (c) {
case a: print("a");
case b: print("b");
case c: print("c");
}
}
并在以下情况下调用:
void stuff(char* str) {
int c = charToEnum(str);
printStuff(c);
}
所以我们实际拥有的不是
void stuff(char *str) {
printf(str);
}
我们已经生成了数千行代码(私有新的,错误的,复杂的,哈希表的实现,以及xml阅读器和编写器)来代替上面的3个。
答案 3 :(得分:9)
从Linux SCSI驱动程序(它应保持无名以保护有罪):
wait_nomsg:
if ((inb(tmport) & 0x04) != 0) {
goto wait_nomsg;
}
outb(1, 0x80);
udelay(100);
for (n = 0; n < 0x30000; n++) {
if ((inb(tmport) & 0x80) != 0) { /* bsy ? */
goto wait_io;
}
}
goto TCM_SYNC;
wait_io:
for (n = 0; n < 0x30000; n++) {
if ((inb(tmport) & 0x81) == 0x0081) {
goto wait_io1;
}
}
goto TCM_SYNC;
wait_io1:
inb(0x80);
val |= 0x8003; /* io,cd,db7 */
outw(val, tmport);
inb(0x80);
val &= 0x00bf; /* no sel */
outw(val, tmport);
outb(2, 0x80);
TCM_SYNC:
/* ... */
small_id:
m = 1;
m <<= k;
if ((m & assignid_map) == 0) {
goto G2Q_QUIN;
}
if (k > 0) {
k--;
goto small_id;
}
G2Q5: /* srch from max acceptable ID# */
k = i; /* max acceptable ID# */
G2Q_LP:
m = 1;
m <<= k;
if ((m & assignid_map) == 0) {
goto G2Q_QUIN;
}
if (k > 0) {
k--;
goto G2Q_LP;
}
G2Q_QUIN: /* k=binID#, */
我是如何找到这颗宝石的?
find /usr/src/linux -type f -name \*.c |
while read f
do
echo -n "$f "
sed -n 's/^.*goto *\([^;]*\);.*/\1/p' $f | sort -u | wc -l
done |
sort +1rn |
head
输出是一系列行,列出按照不同标签的数量排序的文件,如下所示:
kernel/fork.c 31
fs/namei.c 35
drivers/infiniband/hw/mthca/mthca_main.c 36
fs/cifs/cifssmb.c 45
fs/ntfs/super.c 47
答案 4 :(得分:9)
真正的意大利面条代码是在COBOL中完成的,并使用了ALTER语句。
这是一个example,虽然列出了一个“幽默”,但我已经看到了这种事情。因为注意到任何带有Alter声明的程序显然都处于犯罪状态,所以几乎被解雇了一次。我拒绝“维护”该程序,更换它比理解它更快。
答案 5 :(得分:8)
别忘了提到面向对象的意大利面条。 这是当你尝试使用书中的所有设计模式时,即使它们没有意义。这导致概念层面的意大利面条代码,这比传统的基于goto的意大利面条代码更不利于质量。
答案 6 :(得分:7)
你已经要求了,你会得到它:
这是播放蓝色多瑙河华尔兹的DOS .com文件的来源。可执行文件的大小只有176个字节。代码重新用作数据,反之亦然。
.286
.model tiny
g4 equ 55-48 ; removed note-decoding !
a4 equ 57-48 ; now: storing midi-notes for octaves 0..2 and convert
h4 equ 59-48 ; to 4..6 with a simple add 48.
c5 equ 60-48
d5 equ 62-48
e5 equ 64-48
g5 equ 67-48
h5 equ 71-48
c6 equ 72-48
d6 equ 74-48
e6 equ 76-48
g6 equ 79-48 ; = 00011111b
pp equ 0 ; c4 is not used in the walz, using it as play-pause.
EOM equ 1 ; c#4 is also available... End Of Music
; warning: experts only beyond this point !
pau1 equ 00100000b ; bitfield definitions for note-compression
pau2 equ 01000000b ; you can or a pau to each note!
pau3 equ 01100000b
;rep1 equ 01000000b ; rep1 is history (only used once).
;rep3 equ 11000000b ; rep3 was never used.
rep2 equ 10000000b ; or a rep2 to a note to play it 3 times.
drumsize equ 5
.code
org 100h
start:
mov ah,9
mov dx,offset msg
int 21h ; print our headerstring
mov dx,0330h ; gus midi megaem -port
mov si,offset music_code ; start of music data
mainloop:
; get new note (melody)
xor bp,bp ; bp= repeat-counter
lodsb ; get a new note
cmp al, EOM ; check for end
jne continue
ret
continue:
jns no_rep2 ; check for rep2-Bit
inc bp
inc bp ; "build" repeat-counter
no_rep2:
push ax ; save the note for pause
; "convert" to midi-note
and al,00011111b
jz skip_pp ; check pp, keep it 0
add al,48 ; fix-up oktave
skip_pp:
xchg ax,bx ; bl= midi-note
play_again:
mov cl,3
push cx ; patch program (3= piano)
push 0c8h ; program change, channel 9
; wait (cx:dx) times
mov ah,86h ; wait a little bit
int 15h
; prepare drums
dec di ; get the current drum
jns no_drum_underflow
mov di,drumsize
no_drum_underflow:
; play drum
push dx ; volume drum
push [word ptr drumtrk+di] ; note drum
mov al,99h
push ax ; play channel 10
; play melody
push dx ; volume melody
push bx ; note melody
dec ax ; replaces dec al :)
push ax ; play channel 9
; send data to midi-port
mov cl,8 ; we have to send 8 bytes
play_loop:
pop ax ; get the midi event
out dx,al ; and send it
loop play_loop
; repeat "bp" times
dec bp ; repeat the note
jns play_again
; check and "play" pause
xor bx,bx ; clear the note, so we can hear
; a pause
; decode pause value
pop ax
test al,01100000b
jz mainloop ; no pause, get next note
; decrement pause value and save on stack
sub al,20h
push ax
jmp play_again ; and play next drum
; don't change the order of the following data, it is heavily crosslinked !
music_code db pp or rep2
db g4 or rep2 or pau1
db h4 or pau1, d5 or pau1, d5 or pau3
db d6 or pau1, d6 or pau3, h5 or pau1, h5 or pau3
db g4 or rep2 or pau1
db h4 or pau1, d5 or pau1, d5 or pau3
db d6 or pau1, d6 or pau3, c6 or pau1, c6 or pau3
db a4 or rep2 or pau1
db c5 or pau1, e5 or pau1, e5 or pau3
db e6 or pau1, e6 or pau3, c6 or pau1, c6 or pau3
db a4 or rep2 or pau1
db c5 or pau1, e5 or pau1, e5 or pau3
db e6 or pau1, e6 or pau3, h5 or pau1, h5 or pau3
db g4 or rep2 or pau1
db h4 or pau1, g5 or pau1, g5 or pau3
db g6 or pau1, g6 or pau3, d6 or pau1, d6 or pau3
db g4 or rep2 or pau1
db h4 or pau1, g5 or pau1, g5 or pau3
db g6 or pau1, g6 or pau3, e6 or pau1, e6 or pau3
db a4 or rep2 or pau1
db c5 or pau1, e5 or pau1, e5 or pau3, pp or pau3
db c5 or pau1, e5 or pau1, h5 or pau3, pp or pau3, d5 or pau1
db h4 or pau1, h4 or pau3
db a4 or pau1, e5 or pau3
db d5 or pau1, g4 or pau2
; db g4 or rep1 or pau1
; replace this last "rep1"-note with two (equal-sounding) notes
db g4
db g4 or pau1
msg db EOM, 'Docking Station',10,'doj&sub'
drumtrk db 36, 42, 38, 42, 38, 59 ; reversed order to save some bytes !
end start
答案 7 :(得分:6)
真正的意大利面条代码需要大量的非本地色彩。遗憾的是,使用大多数现代语言是不可能的。
编辑:有人建议将例外和longjmp作为GOTO的替代品。但这些远有限且结构化,因为它们只允许您返回callstack。真正的GOTO允许你跳转到程序中任何行 的行,这是创建真正的意大利面条所必需的。
答案 8 :(得分:6)
简单来说,意大利面条代码是任何编程语言中的任何代码,在这些代码中,无法跟踪下一个执行帖子,或者至少很难确定下一个点在一个操作的响应中的位置。
答案 9 :(得分:4)
这是我前一段时间写过的MIDI解析器。这是一个快速而肮脏的概念证明,但是,我将承担其丑陋的责任:4级嵌套条件加上可怕的多重回报。此代码用于比较2个MIDI事件,以便在写入文件时按优先级对它们进行排序。虽然很丑陋,但它确实做得不错。
internal class EventContainerComparer : IComparer {
int IComparer.Compare(object a, object b) {
MIDIEventContainer evt1 = (MIDIEventContainer) a;
MIDIEventContainer evt2 = (MIDIEventContainer) b;
ChannelEvent chanEvt1;
ChannelEvent chanEvt2;
if (evt1.AbsoluteTime < evt2.AbsoluteTime) {
return -1;
} else if (evt1.AbsoluteTime > evt2.AbsoluteTime) {
return 1;
} else {
// a iguar valor de AbsoluteTime, los channelEvent tienen prioridad
if(evt1.MidiEvent is ChannelEvent && evt2.MidiEvent is MetaEvent) {
return -1;
} else if(evt1.MidiEvent is MetaEvent && evt2.MidiEvent is ChannelEvent){
return 1;
// si ambos son channelEvent, dar prioridad a NoteOn == 0 sobre NoteOn > 0
} else if(evt1.MidiEvent is ChannelEvent && evt2.MidiEvent is ChannelEvent) {
chanEvt1 = (ChannelEvent) evt1.MidiEvent;
chanEvt2 = (ChannelEvent) evt2.MidiEvent;
// si ambos son NoteOn
if( chanEvt1.EventType == ChannelEventType.NoteOn
&& chanEvt2.EventType == ChannelEventType.NoteOn){
// chanEvt1 en NoteOn(0) y el 2 es NoteOn(>0)
if(chanEvt1.Arg1 == 0 && chanEvt2.Arg1 > 0) {
return -1;
// chanEvt1 en NoteOn(0) y el 2 es NoteOn(>0)
} else if(chanEvt2.Arg1 == 0 && chanEvt1.Arg1 > 0) {
return 1;
} else {
return 0;
}
// son 2 ChannelEvent, pero no son los 2 NoteOn, el orden es indistinto
} else {
return 0;
}
// son 2 MetaEvent, el orden es indistinto
} else {
return 0;
}
}
}
}
答案 10 :(得分:3)
以下是Duff's Device,来自Matt对this question的回答:
int n = (count + 7) / 8;
switch (count % 8) {
case 0: do { *to = *from++;
case 7: *to = *from++;
case 6: *to = *from++;
case 5: *to = *from++;
case 4: *to = *from++;
case 3: *to = *from++;
case 2: *to = *from++;
case 1: *to = *from++;
} while (--n > 0);
}
答案 11 :(得分:1)
意大利面条代码:起源于意大利60年代早期,作为某些意大利面食的替代配方,意大利面条代码由一位餐馆企业家烹饪,他们试图自动创建一个防呆的主菜。由于缺乏完成设计的时间,工程师/厨师偷工减料,这在早期引入了配方中的问题。在一个疯狂的尝试,以纠正一个好主意变坏,各种香料迅速添加到混合物,因为配方失去控制。结果是一连串,曲折,但可能是美味的文本堆,后来成为世界各地的开发人员所珍视的实践。
答案 12 :(得分:0)
您是否曾查看过Flex / Bison扫描仪和生成器生成的代码?过多的标签和预处理器指令。
绝对不可能理解里面是什么......并且绝对不可能遵循程序的流程。
这是定义意大利面条代码。