当前位置:  开发笔记 > 编程语言 > 正文

什么是意大利面条代码?

如何解决《什么是意大利面条代码?》经验,为你挑选了9个好方法。

你能发一个真实的,过度的意大利面条代码的简短例子,可能会说它的作用是什么?你能告诉我一个小调试器的噩梦吗?

我不是指IOCCC代码,那是科幻小说.我的意思是发生在你身上的现实生活例子......

更新

重点已从"发布一些意大利面条代码"到"什么是改变究竟面条代码?".从历史的角度来看,目前的选择似乎是:

旧的Fortran代码大量使用compute gotos

使用ALTER语句的旧Cobol代码

Brian Genisi.. 19

对我来说,一个更现代的意大利面条代码示例是当你有20个dll并且每个DLL以某种方式相互引用时.你的依赖图看起来像一个巨大的blob,你的代码在没有真正顺序的地方跳过.一切都是相互依赖的.



1> Brian Genisi..:

对我来说,一个更现代的意大利面条代码示例是当你有20个dll并且每个DLL以某种方式相互引用时.你的依赖图看起来像一个巨大的blob,你的代码在没有真正顺序的地方跳过.一切都是相互依赖的.



2> 小智..:

我不会把这个从头脑中拉出来.这是我必须使用的,虽然简化了.让我们说基本上你有一个需要枚举的程序:

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的代码来完成的:


  
  
  

并插入哈希表.但代码是"优化的",因此它不会读取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> Joris Timmer..:

还有Ravioli Code,相反.漂亮的小块功能,干净的界面整齐地包裹着肉质的美味,都坐在一个漂亮的框架酱.



4> Diomidis Spi..:

从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


上面有很多东西,但它实际上非常清楚他们在做什么,所以这不会得到我对意大利面的投票.
非常清楚?转到G2Q_QUIN?转到G2Q_LP?
..因为这是内核模式驱动程序,性能很重要!在这些情况下,意大利面条代码更受CPU限制,性能更强.GOTO只解决了一个ASM JMP/LJMP.所以我完全可以使用这段代码.
是的-使用while语句不能有效地完成那些繁忙的等待循环。(这对任何不知道的人都是讽刺的)。
我确信代码可以用结构化的更易读的方式编写,而不会遭受任何重大开销.

5> S.Lott..:

真正的意大利面条代码在COBOL中完成并使用了ALTER语句.

这是一个例子,虽然列出了一个"幽默",但我已经看到了这种事情.因为注意到任何带有Alter声明的程序显然都处于犯罪状态,所以几乎被解雇了一次.我拒绝"维护"该程序,更换它比理解它更快.



6> 小智..:

别忘了提到面向对象的意大利面条.这是当你尝试使用书中的所有设计模式时,即使它们没有意义.这导致概念级别的意大利面条代码,这比传统的基于goto的意大利面条代码更不利于质量.



7> Nils Pipenbr..:

你问过它,你会得到它:

这是播放蓝色多瑙河华尔兹的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


这不算数,汇编语言依赖于跳转 - 你基本上不能写非意大利语汇编程序.
代码被重用为数据,你确定你的名字不是Mel吗?
作为数据重用的代码也不计算在内.这是真正的巧妙,但它不是意大利面条代码.意大利面条代码是几乎不可能遵循控制流程的代码.

8> JacquesB..:

真正的意大利面条代码需要大量的非本地代码.遗憾的是,使用大多数现代语言是不可能的.

编辑:有人建议将例外和longjmp作为GOTO的替代品.但这些都远远有限和结构,因为它们只允许您返回了调用堆栈.真正的GOTO允许您跳转到程序中任何位置的任何行,这是创建真正的意大利面条所必需的.


你真的是"悲伤地"吗?
令人遗憾的是,我们再也无法写出模糊不清,令人困惑的东西.那是我小时候真正的工作保障.无法外包支持无法穿透的东西.Futurama引用:"你有额外的转到10吗?"

9> 小智..:

简单来说,意大利面条代码是任何编程语言中的任何代码,其中不可能跟踪下一个执行的帖子,或者至少难以确定下一个点在一个动作的响应中的位置.

推荐阅读
mobiledu2402851323
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有