bash.im ithappens.me zadolba.li

Индийский код

13432

Fair dice roll

Великий корейский рандом, говорите? Всего лишь особенности работы генератора псевдослучайных чисел. Это очень хорошо, что вы только IP с его помощью формируете и ничего более, куда печальней дела обстоят в геймдеве, я вам скажу.

Уже более пятнадцати лет я наблюдаю пляски разработчиков игр вокруг рандомизаторов, и мне слегка несмешно временами, такое ощущение, что матчасть даже не пытались изучать:

  • if (rand(10000)==1) и прочие подобные глупости при использовании генератора с нормальным распределением.

  • Выбор по таблице добычи при помощи генератора с нормальным распределением. Если сюда добавить ещё разный шанс трофеям, то для некоторых позиций вырисовывается совсем запредельная схема.

  • Генерация энтропии на основе данных игрока/сессии/сервера. Обычно легко прослеживается и явно заметна.

  • Выборка случайного элемента из некоторой части списка для придания «большей случайности». За пределами добра и зла. В одной известной игрушке про убийство монстров это привело к тому, что можно было сутками пытаться выбить шмотку, которой просто не может выпасть в текущей сессии.

  • Скрытая манипуляция выборкой под видом случайного выбора.

  • ...и даже сочетание всего вышеперечисленного.

Самое смешное, что когда пользователи жалуются на симптомы подобных решений или вычисляют примерный алгоритм работы рандомизатора, начинается тотальное отрицание всего и вся. В крайнем случае, проверки алгоритма за пределами возможного матожидания, например: «Вот, смотрите, мы протестировали алгоритм на выборке из 300 выстрелов, всё чудесно». После этой фразы уже объяснять, что если сократить количество итераций до 30, картина меняется в корне, абсолютно бесполезно.

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

13427

Неуловимый Джо

Индусы, индусы, индусы… Пару часов назад столкнулся с тем, что коренные американцы способны накосячить не хуже индусов.

Вставляем в программу проверку входных бинарных данных (_fpclass) — вдруг нам NaN пришёл (или ещё какой мусор). И неожиданно для себя получаем три жирных бага в совсем других местах: зависание, некорректное отображение данных, движение времени «большими рывками».

Пара часов отладки — и становится понятно, что дело в том, что _fpclass портит режим сопроцессора. И вместо long double у нас сопроцессор считает всё как float.

Открываем сорцы. Ну странно же, когда стандартная подпрограмма из системной библиотеки не восстанавливает регистры оборудования. Гм, она восстанавливает. Угу, восстанавливает. Но с перепутанным порядком параметров в вызове _control87.

Дата написания кода — © 1998, 2000. Версия библиотеки 10.0. Как этот баг прожил 15 лет? 15 лет, Карл!

13333

Самопроизвольное индоизвержение

А я теперь официально признаюсь быдлокодером.

Дело в том, что мне приспичило написать обёртку на Go для сишного API Eggdrop. Всё было хорошо до тех пор, пока я не попытался реализовать подобие Tcl-функции bind для C-функций. Полдня я потратил на исследование исходников, так как всемогущий поисковик мне не помог, но не нашёл ничего, кроме функций добавления и бинда Tcl-функций. В результате у меня получился такой механизм: генерируется имя вида eapi:bind_xxx, затем под этим именем добавляется привязываемая функция, затем получившаяся Tcl-функция привязывается как обычно. Возвращаемым значением этого монстра является номер бинда (то самое xxx в названии функции).

Простите меня, оно само.

13132

Джанго, освобождённый от быдлокода

Коллеги! Выбирайте технологии. Выбирайте так, чтобы потом не жаловаться, что приходится поддерживать за кем-то код «не очень красивого цвета», который ещё и пахнет соответственно.

Поделюсь немного своим опытом. Я веб-разработчик, программист, в основном бэкэнд.

До относительно недавних пор я работал преимущественно с широко известной в России CMS, отличающейся агрессивным маркетингом (вплоть до упоминания жёлтой программы в своём названии), низким порогом вхождения и широкими возможностями нарушения архитектуры. Точно так же, как и многие любители чистого и красивого кода, плакал кровью, глядя на некоторые конструкции, особенно написанные «золотыми сертифицированными партнёрами», осилившими эпический труд «PHP за 24 часа для чайников». Компонент (почти аналог контроллера в традиционных системах), который не содержит логики, а только подключает тот или иной шаблон в зависимости от входного параметра — нормально! А вся логика в шаблоне. Вплоть до обращения к БД. Да, прямыми SQL-запросами, несмотря на то, что система имеет хоть и своеобразный, но всё же ORM. А что? В учебниках для начинающих же действительно есть такие примеры, и возможность обратиться в БД прямо из HTML-файла преподносится как преимущество и неоспоримое достоинство PHP. Но ладно. Сами авторы системы тоже не ангелы. Кто-то про классы жаловался? Так вот, классы — это, по мнению авторов замечательной (без иронии) CMS, всего лишь способ логически объединить несколько функций. Большинство методов класса статические. Но в некоторых случаях нужно создавать объект класса, который будет использован только для вызова одного метода, и нигде и никогда больше. Такое своеобразное видение ООП.

Беда? Однозначно беда. Копаться в таком быдлокоде — приятного мало. Надо было что-то делать. Я изучил альтернативы и остановился на приятном фреймворке Django, с помощью которого теперь и разрабатываю сайты. Возможно, вы не поверите, но проблема чужого кода исчезла. Во-первых, оформление кода. Оно всегда и у всех одинаковое. Синтаксис языка Python предъявляет жёсткие требования. Питоновская идеология также гласит, что для решения задачи должен быть один очевидный способ. В Django эта идея поддерживается. И это помогает, экономит время и нервы. Кто бы ни писал до меня, я заранее знаю, где искать нужный код, даже если проект впервые вижу.

Порог вхождения намного выше. То есть нельзя, просмотрев один 15-минутный видеоурок, сразу начать клепать «визиточки». Нужно иметь некоторую базовую подготовку и потратить время на изучение. Это отсекает случайных людей: средний уровень разработчика на Django намного выше, чем средний уровень широко рекламируемых решений с низким порогом вхождения. А значит, и качество кода выше.

И ещё один бонус, который не сразу очевиден: повышается качество заказчиков. Довольно легко убедить в преимуществах своего предложения заказчика, которому важен результат, нацеленного на долгосрочное сотрудничество. И практически невозможно склонить на свою сторону тех, чья главная цель — снять с себя ответственность: всяких менеджеров по просиживанию штанов.

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

13129

Нет предела безобразию

Прочитал тут про страдания одного программиста. Слёзы наворачиваются. Хочу в этот санаторий, там, где функция в 400 строк — предел безобразий. Видимо, у всех болевой порог разный, а у меня болевые рецепторы на заднице стёрлись давно. Итак, что у меня.

Есть программы на Фортране. Язык весёлый. Констант в нём нет, а параметры в программу передаются исключительно по ссылке. То есть вызов call subr(1) на самом деле передаёт в подпрограмму адрес переменной, в которой лежит единица. Значение переменной в подпрограмме можно изменить. Так я узнал, что в любой фортрановской программе есть как минимум четыре единицы (и четыре нуля, кстати), в общем случае не равные между собой. То, что print *, 0 выдаст именно «0», не гарантируется.

Есть программы на Паскале. Все пользовательские типы там именуются по простой схеме: Т1, T2, T3, T4… T55. Что вы, конечно же, есть распечатанный документ, где эти типы подробно описаны, для чего и как, но его потеряли. А переменные экономили, поэтому в разные моменты времени переменная используется для вычисления и хранения совершенно различных по смыслу значений. Поэтому называют их А1, А2, А3. Это не обфускатор. Люди реально так писали.

И, наконец, любимый С++. Реальная программа, которая лет десять назад неплохо продавалась по всему миру. Там есть три функции. Первые две содержат 45 и 35 тысяч строк. Раньше это была одна функция, но Visual C++ отказался компилировать файл больше 65К строк, и автор разбил функцию на две. Третья функция поменьше — 20 тысяч. Практически все 20 тысяч строк запиханы в отрисовку окна. Инициализация программы, парсинг DXF-файла с картой Земли, расчёт всякой астрономической фигни и, собственно, отрисовка.

Есть ещё 16 файлов машинно-генерённого С++ по мегабайту каждый, которые иногда приходится править вручную.

Могу продолжить, но мне уже грустно. А вы над 300 строками плачете…

13123

Валерьянки за вредность

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

Один класс (имя не отражает сущность — кого это волнует?) и сотня функций. Казалось бы, нормально. Нормально?! Ни хрена это не нормально, когда поля класса расположены случайным образом между функциями. Именование переменных, бизнес-правила? Да ну их в большой сочный болт! Метод, внутри которого переменные t, p, x, а некоторые и глобальные — вот что здесь норма.

Вы думаете, это всё? Да я молился, чтоб этом было «всем». Это творение подключалось к базе Аксесса. Банально через датасеты. Банально? Ну да, слишком банально. Один датагрид, пять таблиц, поэтому что? Правильно: надо пять датасетов! Имена… А что имена? Имя как имя: 50 символов, начинается латиницей, продолжается русским капсом (тысяча блудниц!) и заканчивается цифролатиницей. И их пять. Пять таких датасетов в одной форме. На один датагрид. А знаете, какой запрос в каждом из пяти датасетов? Глаза вытекают: SELECT * FROM [dataTableName];.

Про форматирование кода после предыдущего даже писать как-то мелочно.

Функция. Да-да, именно так: Функция. Особая примета: входной параметр — y, выходной — x. 150 строк. Шта? Ладно. Следующая. 230. Шта-а-а? А дальше скромная ФУНКЦИЯ. 320 строк. Мои глаза невозможно было представить, пока я не увидел следующую (правда, всю закомментированную однострочными комментариями) на 400 строк. Я не знаю, как про это говорить.

Похоже, я должен требовать ящик валерьянки в неделю как расходные материалы.

12990

Код и небрежный обормот

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

Мне попадались дизайнеры, ухитрившиеся сделать главную страницу весом в 20 мегабайт. Художники, не имевшие понятия об анатомии и перспективе. Системные администраторы, которые при копировании данных ухитрились потерять все файлы .htaccess и после трёх напоминаний всё равно забывшие, что нужно установить определённый набор библиотек, но выпустившие все это в продакшн.

И, наконец, мои коллеги-программисты, писавшие if на пятнадцати строках с десятком вызовов функций с невменяемыми названиями и параметрами внутри без единого комментария ко всему блоку кода. Программисты, делавшие SELECT * на таблице с сотней миллионов записей (на тестовом сервере было всего тысяч десять, так что всё работало, а вот в продакшне…) Программисты, презирающие ссылки и пересылающие в подпрограмму массивы по миллиону элементов. Программисты, считающие, что ссылки вида parent.parent.parent.parent["funcRecalc"](a,b,c) — это нормально. Программисты, считающие, что defensive programming — пустая трата времени даже при разработке биллинговой системы.

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

12559

Честный просвещённый индус

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

Почитал инструкцию об общем устройстве этих процессов, нашёл статью на Хабре о подводных камнях и недокументированных возможностях этой системы. Разобрал библиотеку, которая с ней взаимодействует, её процедуры и параметры…

И потом, как честный просвещённый индус, вставил себе этот неведомый кусок чужого кода.

12535

Жёлтая плохая: я её не знаю

Сменилось руководство, притащило своих программистов кодить 1С. Не знаю, кто они, но точно не программисты жёлтой. И начали они кодить…

«Что такое ссылка? Я не понимаю!» — восклицал их начальник. Он же в запросе ставил условие ЭтоГруппа = 2. В этот момент мне вспомнился фрагмент из «Футурамы», когда Бендеру снится кошмар, где всплывают единицы и нули, и он просыпается с криком: «Кажется, я видел двойку!» При моей поправке, что нужно поставить 0 или 1, мне ответили тоном мудреца: «Не надо! У нас тут своё». Естественно, ничего не выполнялось и указывало ошибку на это условие. И все эти эксперименты — на рабочей базе.

Дальше — больше. Был показан крутой отчёт, над которым ребята трудились месяц. Параметров нет, отборов нет, группировок нет, поля поменять местами или убрать нельзя: всё жёстко забито в коде и выполняется только при открытии. Чтобы посмотреть данные, нужно переоткрыть отчёт. Функциональность на высоте: запросы написаны на T-SQL и к базе обращаются через ADO в обход RLS и всего остального «ненужного». Пофиг, что теперь все смогут увидеть информацию, которую не положено; пофиг на то, что мы полгода потратили на разборку, что и кому показывать…

Появляется второй отчёт. Нет, теперь 1С не нужна. Они из Экселя макросом дёргают инфу из базы. Ага, с полными правами и открытым паролем, вписанным в код (безопасники рукоплещут). 1С же «тупит», так быстрее. А ещё информацию можно менять напрямую.

Прошло время, база стала тупить ещё больше. Блокировками уже никого не удивишь. Стало ещё хуже, чем было. Печально, что из-за действий вот таких людей и формируется отношение к программе конечных пользователей.

12429

Отставить неопределённость!

«Отменить» и «Отмена» — можно ли это переплюнуть? Авторы одного андроидного калькулятора переплюнули. «Division by zero» — и три кнопки: «OK», «Cancel», «Help». Реакция при нажатии любой из них одинакова: выскакивает помощь.