Lex Kravetski (lex_kravetski) wrote,
Lex Kravetski
lex_kravetski

Category:

Кой-чего про говнокод

Тут гражданин в комментах посетовал, что, дескать, у отечественных программистов нет базовых знаний, когда у зарубежных они, напротив, есть. Поэтому у местных весь код состоит из попытки взломать сейф консервным ножом, хотя зарубежные умеют его открывать ключом. Лично я считаю, главная проблема отечественных программистов (преимущественно, начинающих, само собой) как раз не в отсутствии базовых знаний, а в отсутствии практики. Базовые знания-то в вузах как раз дают, только эти знания связаны с реальной работой примерно как алфавит с журналистикой, если не хуже. Однако об этом будет следующая статья. А эта — о говнокоде.

Так вот, лет эдак десять назад я тоже пребывал в иллюзиях, будто кривой код пишут только у нас. А на Западе, обратно, программисты — профессионалы своего дела, дисциплинированные такие, хорошо подкованные и всё такое. Потом, когда начал работать, с зарубежным кодом неизбежно пришлось познакомиться. И я с удивлением выяснил, что и на Западе тоже пишут преимущественно говнокод. Нет-нет, не индусы и китайцы для Запада. Именно что западные программисты.

С другой стороны, не говнокод там тоже пишут. И у нас, что характерно, тоже. Я не уверен, что в процентах количество говнокода тождественно, однако проценты сравнимы — это точно. Что наш, что не наш — примерно одни и те же распределения. Тут надо понимать: в США программистов минимум раз в десять больше, чем в России. Поэтому хорошего кода тоже примерно минимум раз в десять будет больше. И плохого. Запад при этом одними только США не ограничивается, и количество западных программистов в сравнении с российскими — мега-огромно.

Говнокода я видел много разного. И все эти «индусские» проверки разных там условий видел. И архитектурные решения вида «всё передаётся через глобальные переменные». И попытки заоптимизировать на низком уровне, сопровождённые мега-затратными операциями в ключевых местах. Однако самый-самый говнокод из мной виденного всё-таки принадлежит руке белого человека. Причём, европейского.

Этот код прилагался к книжке Мастерса (такой маститый специалист по методам искусственного интеллекта и прочей обработки данных). Писал ли он его сам — не знаю. Скорее всего подрядил студентов написать. Но студенты наверняка местные, а не индусы на аутсорсе.

Код завораживал своей аккуратностью — видно, что при копи-пасте разработчики были крайне внимательны. Всё форматирование сохранено, все доп. условия проверены. Отлично. Но вот структура…

void MyCalculator::calculateSomething(int n){
	float* xxx = new float[n];
	
	// Что-то делаем
	
	if (что-то пошло не так) {
		delete[] xxx;
		return;
	}
	
	float* yyy = new float[n];
	
	// Снова что-то делаем
	
	if (блин, опять что-то не так) {
		delete[] xxx;
		delete[] yyy;
		return;
	}
	
	float* zzz = new float[n];
	
	// Раз с исками и игреками получилось, попробуем с зэтами
	
	if (не сработало) {
		delete[] xxx;
		delete[] yyy;
		delete[] zzz;
		return;
	}
	
	// А у нас есть вдобавок aaa, bbb, ccc, ddd и ещё много всего вкусного
	
	if (но если случится беда…){
		delete[] xxx;
		delete[] yyy;
		delete[] zzz;
		delete[] aaa;
		…
		…
		return;
	}
	
	// Ура, у нас получилось!!!

	delete[] xxx;
	delete[] yyy;
	delete[] zzz;
	delete[] aaa;
	…
	…
	
	return;
}


И это, пацаны, не просто одна функция. Все функции такие. Во все функции скопипасчен вот такой вот код — с вариациями по количеству икс-икс-исков и игрек-игрек-игреков.

Быть может, их труд оплачивали построчно?

Многим наверно интересно, а куда девается результат? Куда, на хрен, делось то, что мы так долго считали? Признаюсь, я по началу тоже был весьма заинтригован — долго вычисляли какую-то хрень, отслеживали ошибки, зачищали память, а в конце return и до свидания? Однако оказалось, что результат не потерян, нет, он аккуратно сложен в некий глобальный контейнер и в некую глобальную переменную заботливо проставлен индекс результата в этом контейнере.

Контейнер, граждане, не простой. Контейнер хранит все результаты, да. Он — массив массивов. Когда мы что-то посчитали, то создаётся массив на один элемент больше (да, прямо руками — фигли там, мы ж не лохи какие, мы сами такую штуку написать сможем) и все элементы из старого массива копируются в новый. Некоторые могут подумать, что копируются ссылки на прежние массивы, но нет, зачем? Копируются именно все элементы. А последним добавляется новый массив — только что посчитанный (наверно, когда удаляется что-то, то оно работает примерно так же). Теперь заказавший расчёт может полезть в глобальную переменную и узнать, под каким номером сохранён результат. А потом из глобального массива его по номеру извлечь. Если он по глупости своей следом заказал второй расчёт — сам дурак, надо было сначала порядковый номер предыдущего результата запомнить. Вычисляй теперь, где он, о глупый кто-то.

Код при этом не на С, а на С++. То есть, вся вот эта мутотень обёрнута в объекты, потому что на С++ надо писать с объектами — это базовое знание. Кроме того, базовое знание: массивы работают быстрее. Поэтому вместо тормозных векторов, связных списков и всего прочего использован быстрый и эффективный массив. Ведь там не три числа обрабатываются, а десятки тысяч за раз — вектор наверняка будет снижать скорость работы. Теперь же всё надёжно сохранено в быстром массиве, который, — чтобы сэкономить память, — всего один. И если кто-то захочет из него получить один результат — не вопрос, ему этот результат быстро и эффективно из двумерного массива скопируют в одномерный. Ну или, как вариант, он может сам ходить по двумерному глобальному массиву — ему же всё предоставлено в глобальных переменных. А глобальные переменные, они чтобы не усложнять код. Знания — сила. Базовые европейские.

Не знаю, быть может, в последующих изданиях они всё поправили — не проверял. Но вот этот вариант потряс меня до глубины души. До сих пор он — лидер моего личного рейтинга.
Tags: программирование, философия
Subscribe
  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    default userpic

    Your reply will be screened

    Your IP address will be recorded 

  • 219 comments
Previous
← Ctrl ← Alt
Next
Ctrl → Alt →
Previous
← Ctrl ← Alt
Next
Ctrl → Alt →