Что такое запутанный код? [закрытый]

Как будто вы пытаетесь получить доступ к объекту, который является null. Рассмотрим ниже пример:

TypeA objA;

. В это время вы только что объявили этот объект, но не инициализировали или не инициализировали. И всякий раз, когда вы пытаетесь получить доступ к каким-либо свойствам или методам в нем, он будет генерировать NullPointerException, что имеет смысл.

См. Также этот пример:

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
25
задан Federico A. Ramponi 28 October 2010 в 01:38
поделиться

12 ответов

Мне больше современный пример запутанного кода - когда у Вас есть 20 dlls и каждый DLL ссылки друг друга так или иначе. Ваш граф зависимостей похож на огромный блоб и Ваши транзитные участки кода повсеместно без реального порядка. Все взаимозависимо.

19
ответ дан Brian Genisio 28 November 2019 в 17:41
поделиться

Существует также Код Равиолей , который является противоположным. Миленькие блоки функциональности, чистый интерфейс аккуратно перенес мясистое совершенство, все находились в хорошем соусе платформы.

14
ответ дан Joris Timmermans 28 November 2019 в 17:41
поделиться

От драйвера SCSI Linux (который должен остаться неназванным для защиты виновного):

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

вывод является серией строк, перечисляющих файлы, заказанные количеством gotos к отличным маркировкам, как следующее:

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
9
ответ дан Diomidis Spinellis 28 November 2019 в 17:41
поделиться

Реальный запутанный код был сделан в КОБОЛе и использовал оператор ALTER.

Вот пример , в то время как перечислено "юмор", я видел такого рода вещь. Почти был уволен однажды за замечание, что любая программа с оператором Alter была, очевидно, в состоянии греха. Я отказался "поддерживать" ту программу, это было более быстро для замены его, чем понимают его.

9
ответ дан onurozgurozkan 28 November 2019 в 17:41
поделиться

Не забывайте упоминать Объектно-ориентированные спагетти. Это - когда Вы пытаетесь использовать все шаблоны разработки в книге, даже когда они не имеют смысла. Это приводит к запутанному коду на концептуальном уровне, который намного более вреден для качества, чем классический находящийся в goto запутанный код.

8
ответ дан 28 November 2019 в 17:41
поделиться

Вы попросили его, Вы получите его:

Это - источник 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
ответ дан Thomas L Holaday 28 November 2019 в 17:41
поделиться

Реальный запутанный код требует множества нелокального gotos. Печально это не возможное использование наиболее современные языки.

Редактирование: Некоторые предлагают исключения и longjmp как замены для GOTO. Но это далеко к ограниченному и структурированному, так как они только позволяют Вам возвращать стек вызовов. Реальный GOTO позволяет Вам переходить к любой строка где угодно в программе, которая необходима для создания реальных спагетти.

6
ответ дан JacquesB 28 November 2019 в 17:41
поделиться

Это из синтаксического анализатора 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;
            }
        }
    }
}
4
ответ дан Juan Pablo Califano 28 November 2019 в 17:41
поделиться

Вот Устройство Вареного пудинга от ответа Matt до этот вопрос :

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);
}
3
ответ дан Community 28 November 2019 в 17:41
поделиться

Запутанный код: Происходя в начале 60-х в Италии как альтернативный рецепт приготовления определенных блюд из пасты, запутанный код был приготовлен одним предпринимателем ресторана, который попытался автоматизировать создание надежного входа. Нажатый отсутствием времени для завершения дизайна углы сокращения инженера/шеф-повара, которые представили проблемы в рецепте вначале. В безумной попытке исправить хорошую идею разложенные, различные специи были быстро добавлены к смеси, поскольку рецепт вышел из-под контроля. Результатом была волокнистая, извилистая, все же потенциально вкусная груда текста, который позже вырастет, чтобы быть практикой, которую заветный разработчики во всем мире.

1
ответ дан Cliff 28 November 2019 в 17:41
поделиться

Вы когда-нибудь смотрели на код, сгенерированный сканером и генератором Flex / Bison? Множество меток и директив препроцессора.

Абсолютно невозможно понять, что внутри ... и абсолютно невозможно следить за ходом программы.

Это определенно спагетти-код.

0
ответ дан 28 November 2019 в 17:41
поделиться

Я не вытаскиваю это из головы. Это то, с чем мне пришлось работать, хотя и в упрощенном виде. Предположим, что в основном у вас есть программа, которой требуется перечисление:

enum {
   a, b, c;
} myenum;

Но вместо этого у нас есть

HashTable t;
t["a"] = 0;
t["b"] = 1;
t["c"] = 2;

Но, конечно, никакая реализация хеш-таблицы не является достаточно хорошей, поэтому существует локальная реализация хеш-таблиц, которая содержит примерно в 10 раз больше кода, чем в средней реализации с открытым исходным кодом, вдвое меньше функций и вдвое больше ошибок. HashTable фактически определен как виртуальный, и есть фабрика HashTableFactory для создания экземпляров HashTables, но, как и шаблон, HashTableFactory также является виртуальным.Чтобы предотвратить бесконечный каскад виртуальных классов, существует функция

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.

15
ответ дан 28 November 2019 в 17:41
поделиться
Другие вопросы по тегам:

Похожие вопросы: