
Все примерно представляют, что такое говнокод. На этом замечательном сайте собрана целая коллекция.
Что делает код говнокодом — никто точно не знает. Точного определения нет. Часто то, что одни считают очевидным говнокодом, другим кажется лаконичным и эффективным решением.
Примеры
Примеры говнокода варьируются от избыточных до откровенного хардкода. Самые любмые примеры — такие, говнокодистость которых очевидна для всех:
Boolean b = new Boolean( is_admin );
if( b.toString().length() == 4 ) {
// something...
}
// something
Но знаете, что я скажу? Осуждать говнокод легко, но написать его не так-то легко!
Не верите? Давайте попробуем!
UPD Ниже добавлен анализ поступивших решений.
Задание
Вот простое задание: Напечатать на экране следующее:
1
2-1
1-2-3
4-3-2-1
1-2-3-4-5
6-5-4-3-2-1
(Естественно, вместо 6 может быть любое число).
Попробуйте написать два решения на любом языке:
1. Максимально лаконичное/красивое/читабельное
2. Максимально говнокодистое (но не слишком много. Скажем, ограничение в один экран. И конечно, решение должно работать!)
Можете писать свои варианты в комментарии (для длинных кусков рекомендуется pastebin). Помимо развлекательной составляющей, это может оказаться и полезным упражнением, потому что возможно, оно приблизит вас к понимаю, как получается плохой код и как с ним бороться.
Дайте волю своей фантазии!
UPDATE: Анализ решений
Спасибо всем, кто прислал свои варианты. Так много комментариев я ещё не видел. Стало быть, тема актуальна.
Попробуем проанализировать поступившие решения.
Хорошие решения
«Хорошие» решения, как и полагается, все однотипные, то есть примерно такие:
$n = 6;
for($i = 1; $i <= $n; $i++) {
$array = $i % 2 ? range(1, $i) : range($i, 1);
echo join('-', $array), PHP_EOL;
}
Среди них выделяются два решения на Руби и Хаскеле, которые, на мой взгляд, хороши тем, что они написаны в одну строчку, но при этом сохраняют читабельность. Достигается это, очевидно, засчёт языка.
Руби от Arion:
(6 + 1).times{|i| p (1..i).to_a.send((i%2 == 0)? :to_a: :reverse).join('-')}
Хаскель от pechlambda:
main = mapM_ (putStrLn . foo) [1..6]
foo n = concat $ intersperse "-" $ (if odd n then id else reverse) $ take n $ map show [1..]
Что ещё раз доказывает, что Руби рулит!
Если говорить серьёзно, то у всех этих решений есть один недостаток: они жрут много ресурсов при больших N (создают много временных массивов и строк). Следующее решение от rPman отчасти решает эту проблему (интересно, что сам автор представил его как говнокод):
<?php
define('LENGTH',6);
define('nl',"\n");
$right='1';
$left='1';
echo '1'.nl; // <== это он
for($i=2;$i<=LENGTH;$i++)
{
$left=$i.'-'.$left;
$right=$right.'-'.$i;
echo ($i%2?$right:$left).nl;
}
?>
Плохие решения
Меня изначально интересовали, конечно, именно «плохие» решения. Надо сказать, что хабровчане смогли-таки меня удивить и придумал больше говновариантов, чем я ожидал.
Добротный треш
Решение от runcore пытается в одной строчке совместить цикл 1..N и N..1, что надёжно обфускирует изначальное предназначение этого кода:
$is_reverse = false;
for($i=1; $i<=6; ++$i) {
for($is_reverse?$j=$i:$j=1; $is_reverse?$j>=1:$j<=$i; $is_reverse?--$j:++$j) {
echo (($is_reverse)?($j.($j>1?'-':'')):($j.($j<$i?'-':'')));
}
$is_reverse = (($is_reverse) ? false : true);
if (in_array($is_reverse, array(true,false))) {
echo '<br />';
}
}
Комментарии рулят
AHDPEu в своём решении активно использует комментарии. Получилось классно. Что ещё раз доказывает, что комментирование кода — от лукавого.
Premature optimization
Говнокод на Perl у youlose получается засчёт попыток чего-то там оптимизировать. Что ещё раз доказывает, что преждевременная оптимизация — зло.
Обработка ошибок
Решение на JavaScript от azproduction, хоть и несколько преувеличенно, показывает, к чему приводит чрезмерная забота об ошибках и нестандартных ситуациях.
Говноязыки
- Доставило решение sledopit на языке bash:
#!/bin/bash i=1;m=7;while [ $i -lt $m ];do seq 1 $(($i%$m))|tr '\n' ' '|sed 's/ /-/g;s/-$//';((i++));echo;done|while read line; do [ $((${line/*-/}%2)) -eq 1 ]&&echo $line||echo $line|rev;done
Думаю, все согласятся с тем, что оно ни разу не читабельное. Похоже, это тот случай, когда сам язык обязывает программиста писать говнокод. То же подтверждает и целая череда решений на brainfuck.
- Решение pechlambda на Хаскеле: codepad.org/NQUSqcjc доказывает, что каким бы хорошим язык ни был, на нём всегда можно добротно наговнокодить.
- Спасибо огромное Next_Alex за то, что напомнил нам про старые добрые goto.
- А вот Levsha100, совершенно зря наговаривает на своё решение на ассемблере. По-моему, ничего читабельнее я тут не встречал. :)
- Решения на Лиспе, по-моему, оба нечитабельные. Впрочем, позже S2nek исправился.
Школы говнокода
- Решение на PHP от reinventer демонстрирует беспощадный китайский стиль.
- Решение на C от Wyrd демонстрирует старую добрую школу C. Честно говоря, я даже не пытался понять, что там написано.
- Можно ли считать этот шедевр от Levsha100 русским стилем?
- Классическое решение на Java от barker лишний раз показывает, что Ява вербозна, увы.
barker представил решение в стиле Enterprise Java — это круто! Ещё один enterprise от AlexanderYastrebov.
Классика
Но самый классический говнокод, похоже, вышел у SnakeSolid: pastebin.com/rdCtf2j5
Вроде бы ничего особенно лишнего: комментарии, и парочка лишних проверок — да, это всё немножко лишнее, но без криминала. Начнёшь придираться — автор наверняка сможет всё это защитить. Но кода получилось на целую страницу вместо пары строчек. Именно так оно в жизни и бывает.
Подводя итоги
Надеюсь, это нехитрое упражнение заставило вас лишний раз задуматься о том, что такое хорошо и что такое плохо, или хотя бы размять старые косточки.
Всем спасибо!
Пишите чисто!