воскресенье, февраля 08, 2009

Программизмы

Только что друг показал мне одну интересную страницу:

http://www.sjbaker.org/wiki/index.php?title=Cruel_Code_list

На ней расположен архив самых ужасных кусков кода,которые только может выдать человеческий мозг. Осмыслить и понять эти куски человеческий мозг уже способен с большим трудом. Код написан на C++ и в нём сможет разобраться каждый, даже без уморительных английских вставок автора архива, поэтому я не возьмусь переводить статью на русский. Интересно другое.

Я вылез в Гугл и нашёл реального автора одной из программ. Я даю ссылку на ветку одного форума... Угадайте, на каком языке написана программа? На Java.

http://forums.sun.com/thread.jspa?threadID=5224563

Читать рекомендую тред целиком,на второй странице выложены не меньшие перлы. Люди, не начинайте знакомство с программированием с лёгких языков вроде Бейсика, Явы и PHP\Perl! Они слишком легки, чтобы программист вообще задумывался над своей программой.

Приведу рассуждение одного из героев треда:

"Если (a>b) ложно,то логически следует, что b должно быть больше а. <..>"

Классно. Просто замечательно. От автора ускользнула мелкая деталь: a=b. Я не придираюсь, просто пытаюсь найти ту последовательность мыслей, тот корень в логике, провал мозга, который породил столь интересное творение:

if(a > b && b > c) {
// a is greatest
} else if(b > c) {
// note there is no b>a
// b is greatest
} else {
// note there is no test at all
// c is greatest
}


Заметьте - это функция выбора наибольшего элемента. Для трёх элементов. А теперь представьте,что элементов 5, 7, 10, 100...
Ему не жалко стирать пальцы.

Есть три вида ошибок. Первый - это обычные опечатки, вроде следующей для Си:

if ($value = $some_value) {
// тут какой-то код
}


такое случается спросонья,и никто от этого не застрахован. К тому же, компилятор в большинстве случаев вас спасёт.

Второй вид - это непродуманность, вроде хранения числа -333 в типе unsigned char или написания цикла if (password=='password'). Это лечится с опытом, хотя может и обрушить\помешать работе пары систем.

Наконец,третий вид - это именно такие программизмы. Перлы индийского кода. Те творения, авторов которых назвать "быдлокодерами" даже сложно.

Я сам писал нечто подобное лишь раз: это моя функция смены регистра с верхнего на нижний или наоборот; она кочует по моим прогам по одной хорошей причине: я сижу на разных компьютерах и компилю проги на разных системах. Дома у меня стоит Linux, в универе - Винда. Кодировки русского на обеих системах разные, это может быть KOI8-R, CP1251, UTF-8 или (о ужас, кто такое придумал в нашем универе) ISO 8859-5. Как следствие, обычный сдвиг ASCII\UTF значения попросту не работает, когда я конвертирую код в другую кодировку. Именно так в моих программах можно встретить:


char tolower(const char input){
switch (input){
case ('А'): return ('а');break;//надо же с чего-нибудь начинать
case 'Й': return ('й');break;//йцукенг удобнее абв
case 'Ё': return ('ё');break;//не забудем родную буковку
case 'Ц': return ('ц');break;//дети учат эту буковку первой.Кто сказал "А"?Вы всегда читает книгу с начала?
case 'У': return ('у');break;//Ни один порядочный ребёнок не будет читать книгу с начала
case 'К': return ('к');break;//Вместо этого он будет смотреть картинки
case 'Е': return ('е');break;//Причём все и без порядка
case 'Н': return ('н');break;//От У до Г
case 'Г': return ('г');break;//а потом обратно
case 'Ш': return ('ш');break;//от Ш до Г
case 'Щ': return ('щ');break;//да,он посмотрит Г два раза
case 'З': return ('з');break;//надо с детских лет приучать ребёнка уделять большое внимание всякой гадости
case 'Х': return ('х');break;//потому что он потом всю жизнь только этим и будет заниматься
case 'Ъ': return ('ъ');break;//так,сейчас у нас твёрдый знак
case 'Ф': return ('ф');break;//на Олимпийских играх в китае он получил медаль за твёрдость
case 'Ы': return ('ы');break;//Что не значит,что эта медаль была российской
case 'В': return ('в');break;
case 'П': return ('п');break;//помните,мы с чего-то начинали?
case 'Р': return ('р');break;//наверняка помните
case 'О': return ('о');break;//это - О.Познакомьтесь.Очень приятно.
case 'Л': return ('л');break;//здесь слишком много комментов
case 'Д': return ('д');break;//ненавижу комменты
case 'Ж': return ('ж');break;//люблю комменты
case 'Э': return ('э');break;//один из комментов лжёт
case 'Я': return ('я');break;//любимая буковка
case 'Ч': return ('ч');break;//два коммента лгут
case 'С': return ('с');break;//здесь вообще сборище борцов за правду
case 'М': return ('м');break;//думайте над этой логической задачей
case 'И': return ('и');break;//в этих комментах нет смысла..давайте закончим
case 'Т': return ('т');break;//держись,Саня,ещё немного и мы закончим эту муть...
case 'Ь': return ('ь');break;//ну ещё чуть-чуть...
case 'Б': return ('б');break;//ещё немного...
case 'Ю': return ('ю');break;//ДА!!!Закончили.
}
return input;
}



Люди,если вы тратите на подобное 100 килобайт - у вас должна быть причина. Если вы тратите 500 килобайт - весомая причина. Наконец, у вас должна быть просто КЛЯТВЕННАЯ УВЕРЕННОСТЬ в том,что вы знаете,что делаете, если вы тратите на это два мегабайта.

Напоследок, немного ещё интересных строчек.

public string GetUsername (string userName)
{
User user = DbLookup.GetUser(userName);
return user.Username;
}


Есть лишь два логичных объяснения такому: либо прогрев базы данных, либо надо выяснить, существует ли такой юзер. В любом случае, решения этих проблем занимают в 4 раза меньше строк.

string @string = @"new @string()".ToString();
@string = @string == @"string" ? @string : @"Hello World!";


Я не могу понять до конца глубину этих двух строк.
Возможно,в них есть какой-то тайный смысл.
В любом случае, если автор хотел просто потренироваться в эзотеричности, опробовать новый финт ушами или хотя бы просто проверить компилятор - он выполнил это самым остроумным способом.

if 1 <> 1 then
// <..>
end if


Классический пример творчества наших братьев по разуму. Действительно,а вдруг?
Это даже круче следующего:

if (someVariable == someVariable) {
// <..>
}


Это уже просто образец паранойи. Есть только одно логическое объяснение подобному: someVariable=NULL, так что такой код может иметь под собой какую-то почву. Но опять же, зачем городить эзотерику?

Чувствую,что я немного сбавляю темп, это всё равно что представлять публике сакраментальное #define NUMBER_1 1. Что же,исправлюсь. Проверка булевой переменной:

if (boolean.toString().length()<5){...}

if (value && System.Convert.ToBoolean("false")){...} else{...}

if (b.toString.substring(0, 1).equals("t")) {...}

Небольшая вариация:

if (b.ToString().ToLower()[0].Equals(Convert.ToChar("t"))){...}

Окончание парада - вычисление 1% от числа:

a=abs(b-(b*1.01));

Ей-богу,когда у меня что-то глючит, тормозит или просто плохо работает,я вспоминаю о таких перлах...

2 комментария:

  1. Кстати вот этот блок

    if 1 <> 1 then
    // <..>
    end if

    может использоваться для отключения временного отладочного кода. В Си для этого обычно используют ifdef и ifndef.

    ОтветитьУдалить
  2. Именно что. В Си для этого обычно используют ifdef и ifndef. Логичны,простой, а главное - удобный способ - это писать #define DEBUG 1 в начале программы и в дальнейшем уже смотреть на эту опцию. В любом языке можно сделать что-то подобное, и не придётся бегать по коду чтобы менять всё,что можно на if 1<>1.
    Я не говорю,что все программизмы здесь являются чудовищными - их возможно объяснить, их зачем-то писали. Просто их объединяет одна фраза: ЭТО МОЖНО СДЕЛАТЬ ПРОЩЕ.

    ОтветитьУдалить

Постоянные читатели

Архив