bash.im ithappens.me zadolba.li

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

10317

Рубикон говнокода

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

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

Открываю её код и вижу:

boolean bound=false;
boolean granitza=true;

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

9848

Обезжиренный жир под майонезом

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

<li class="bold-segoe-V"><span style="font-weight: normal;"><strong>пункт_списка</strong></span></li>

Вот кто так делает? Русские? Индусы? Инопланетяне?

9824

Да прольётся кровь программистов

Расскажу ещё о софте для медучреждений.

Работаю на станции переливания крови по контракту. Устанавливали известную в этих кругах информационную систему, написанную отечественными программистами. За десять месяцев работы с этой системой выявился список весёлых моментов.

Программа внедряется на все станции переливания крови по сей день. Фирма, написавшая её аж в лохматом 1998 году, уже перестала существовать. Поддержкой занимаются не создатели, а люди, увидевшие программу впервые какое-то время назад.

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

В программе используется классификатор адресов, который мало того, что автоматически не подключается полностью (каждый новый населённый пункт, улицу и дом надо вручную вытаскивать из него), но и не соответствует общепринятому российскому КЛАДРу.

Фамилия, имя, отчество в базе хранятся в одном столбце таблицы, а день, месяц и год рождения — каждый в своём. Также в отдельном столбце таблицы хранится количество полных лет.

При повторном приёме доноров приходится заново проставлять группу крови и резус-фактор (хотя они хранятся в электронной карте), иначе врач, направляющий донора на сдачу крови, просто не увидит результаты его анализов.

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

О таких косяках можно писать бесконечно. Может, кто объяснит, почему за 14 лет существования программного продукта не были доработаны даже простейшие вещи, которые требуются абсолютно всем пользователям? Зачем покупать и устанавливать софт, который уже шесть лет как не поддерживается его разработчиками? И это на фоне того, что существует минимум три схожих бесплатных программных продукта, которые за последние пять лет уже прошли серьёзную обкатку и учли сотни пожеланий пользователей.

9797

У семи кодеров дитя без глазу

Не могу не поделиться чудесами интерфейса одной небезызвестной стоматологической программы.

Выхожу из истории болезни кнопкой «Отмена». Программа задаёт вопрос: «Отказаться от изменений?» Жму «Да» — и сразу второй вопрос: «Сохранить результаты?» Ага, может, передумал уже.

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

При нажатии кнопки «Сохранить» тоже иногда задается вопрос а-ля «Может, передумаешь?»

Названия кнопки «ОК»: «Продолжить», «Сохранить», «Да», «Назначить», «Выбрать», «Печать», «Обновить».

Названия кнопки «Отмена»: «Выход», «Отказ», «Отменить», «Закрыть», «Нет».

Расположение кнопок «ОК» и «Отмена»: справа вверху, слева вверху, справа внизу, вверху посередине, в центре.

Даже галочки у «ОК» где синие, а где зелёные, где слева от надписи, а где снизу.

База данных — вообще отдельная песня. Русско-английские сочетания типа «UDERGSPRAV», «kodoper», «ordercod», длиннющие названия таблиц типа «TREATSCHGROUPSPARAMSLINKS», «GRIDLAYOUTSETTINGSBIN». Все таблицы зарплаты именованы с префиксом «SAL_», но одна названа просто «SHTATVAR» (опять языки вперемешку).

В окне «О программе» не умещается логотип.

Программа 8-й версии имеет значок с цифрой 7.

При работе на незарегистрированной программе просто выдается ошибка SQL. Учитывая, что регистрация иногда слетает, новичкам на техподдержке очень весело.

Про глюки уж я молчу. Наверное, я счастлив, что мне не довелось увидеть исходного кода.

9715

Бетон на языке RGB

Есть два типа программистов. Первые сначала читают, потом программируют. Вторые сразу рвутся программировать, а читают только тогда, когда у них ничего не получается, и то не всё и не до конца. Решения, которые предлагают программисты второго типа, иногда просто изумительны!

Есть бетонная плита метр на метр, покрашенная краской. Задача: определить цвет, в который она покрашена. Что делает программист второго типа? Он берёт плиту и тащит её в лабораторию. Там он устанавливает напротив неё очень яркую лампу и три фоторезистора. Фоторезисторы он закрывает светофильтрами красного, зелёного и синего цветов. Включает лампу и регистрирует показания, снятые с фоторезистров. Дальше он бежит в библиотеку, берёт каталог со всеми возможными цветами и начинает искать среди них тот, компоненты которого наиболее точно соответствуют его данным. Его абсолютно не интересует, что его метод занимает половину дня, что он работает, только если плита имеет яркий цвет и не грязная, что в каталоге может и не быть искомого цвета… Но самое главное, он не знает, что цвет можно определить мгновенно, просто посмотрев на плиту.

Работать с такими программистами мне доводится довольно часто. На днях один такой программист два часа писал функцию перемешивания массива. Не знал он, что в PHP есть такая штука, как shuffle. И самое главное — не хотел знать! Другой быстренько набросал на JS функцию, которая перебирает все элементы массива и на каждом делает только одно действие: увеличивает значение переменной на единицу… Верно, ему нужно было узнать размер массива.

Программисты, читайте перед тем, как что-нибудь делать! Этим вы сэкономите и ваше время, и чужие нервы.

9563

Синий зуб звонит бревну

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

— Отсутствует 301-й редирект. Сайт работает только с WWW.
— Работает только под «ослом». Пришлось запускать через Wine.
— Отсутствует поиск.
— Имеется русская локализация, но переведённая в стиле «Синий зуб — Позвонить бревну».
— В некоторых местах русский язык вообще отсутствует, текст написан на английском.

И как тут не вспомнить бородатый анекдот, как программисты строили дом?

9560

Жизнь, Вселенная, индусы и всё такое

Последних лет десять я занимаюсь SAP. Практически вся прикладная часть системы доступна разработчикам конечного пользователя в исходных кодах. Язык программирования ABAP/4, правда, несколько специфический. Говорят, похож на Кобол. Если сравнивать с популярными ныне языками, то у меня он более всего ассоциируется с Бейсиком.

Есть в ABAP два вида подпрограмм: формы и функции. Форма имеет локальную область видимости (хотя её можно вызвать извне, но тогда нужно указать имя главной программы, в которой размещён код формы). Функции имеют глобальную область видимости, но должны быть обязательно приписаны к какой-нибудь группе функций. SAP может поставляется в разной комплектации. Набор установленных компонент (и, соответственно, доступных групп функций) может отличаться. Из-за этого имя вызываемой функции передаётся как литерал и, если оно указано неправильно или в системе не установлен компонент, содержащий нужную группу функций, выяснится это только в процессе вызова. Разработчики различных модулей вынуждены делить между собой общее пространство имён функций, а также других объектов. Наверное, они как-то координируют имена всех создаваемых функций. Но, скажем так, у них с этим есть некоторые трудности, потому очень часто в разных модулях есть функции, выполняющие схожие действия, а имя функции содержит посторонние символы. К слову, у конечного пользователя тоже есть возможность разрабатывать свои функции. И чтобы хотя бы устранить проблемы с пересечением имён с объектами клиентов, SAP не создаёт свои объекты с именами, начинающимися на букву Z — такие имена зарезервированы для разработчиков конечного пользователя, а клиентам не рекомендует создавать объекты, начинающиеся не на букву Z.

Конкретный пример. Во многих случаях необходимо определить количество дней в данном месяце (ну или последнюю дату в данном месяце). Похоже, что для каждого модуля SAP разработчики пишут эту функцию отдельно, причём не по одному разу. Беглый поиск дал сорок два различных варианта от SAP плюс ещё, конечно, ZMONTH_LAST_DATA — вариант от разработчиков конечного пользователя. Система SAP изначально немецкая, но индусский код попадается и тут. Вот несколько примеров.

Функция CBIH_RP02_GET_END_MONTH.

Через конструкцию CASE анализирует номер месяца. Для всех месяцев, кроме февраля, присваивает своей локальной переменной end_month1 соответствующее значение 30 или 31. Для февраля вызывает форму CHECK_DATE, передаёт ей дату и анализирует возвращаемую переменную L_ERROR. В зависимости от её значения устанавливает своей переменной end_month1 значение 28 или 29. Из исходного года и месяца и вычисленного дня формирует возвращаемую дату. Форма CHECK_DATE у переданной даты меняет число на 29, эта новая дата передаётся функции DATE_CHECK_PLAUSIBILITY, по возвращении из которой форма анализирует код возврата (была ли ошибка) и возвращает эту информацию в вызвавшую функцию. Функция DATE_CHECK_PLAUSIBILITY тщательно проверяет дату на корректность по григорианскому календарю (71 строчка исходного кода) и генерирует ошибку, если дата неправильная.

Функция FIMA_END_OF_MONTH_DETERMINE.

Ничего особенного — честно проверяет для февраля високосность года по григорианскому календарю. Впечатлило использование констант. Видимо, автору кто-то сказал, что хороший стиль программирования — никогда не использовать константы напрямую, а всегда их описывать в отдельно отведённом месте. Идея, конечно, здравая, но доведена до абсурда. Все необходимые группе функций константы описаны в отдельном инклюде FIMA_CONSTANTS (135 строк исходного кода). Я ещё понимаю описание констант для номера месяца типа CON_FEBRUARY(2) TYPE N VALUE '02'. Но это скорее исключение. Типичное описание:

CON_FIRST_DAY_OF_MONTH(2) TYPE N VALUE '01',
CON_DAYS_OF_MONTH_27(2) TYPE N VALUE '27',
CON_SBERFIMA_TLRA TYPE SBEWFIMA VALUE 'TLRA',

А код для присвоения числа, соответственно, такой:

CASE I_DATE+4(2).
WHEN CON_JANUARY. E_DAYS_OF_MONTH = CON_DAYS_OF_MONTH_31.

Функции, начинающиеся на «FKK».

Две из них, FKK_DTE_DAYS_PER_MONTH и FKK_DTE_GET_LASTDAY_OF_MONTH, находятся в одной группе FKDATE, причём рядом. В группе всего семь функций — трудно не заметить существующую тому, кто писал позже. Однако детали реализации отличаются — похоже, что каждой автор писал сам, хотя концептуально алгоритмы одинаковые. За исключением того, что вторая функция для дат до 1582 года вычисляет високосность года по юлианскому календарю. В обеих честно анализируются компоненты даты. Есть отличия в формате вызова.

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

Третья функция FKK_GET_LAST_DAY_OF_MONTH находится в группе FKB3A. Вычисляет последний день месяца с использованием встроенной операции над датами — прибавления и вычитания дней. Сначала она формирует дату на 28 число того же месяца и года, потом прибавляет к ней 4, получает дату заведомо в следующем месяце, устанавливает там день в «01» и вычитает единицу из всей даты. Простенько и со вкусом. Для дат в декабре 9999 года будет ошибка из-за переполнения года по ходу вычислений. Ну да кого это сейчас волнует?

Четвёртая функция FKK_LAST_DAY_OF_MONTH находится в третьей группе FKKPERIOD. Алгоритм компромиссный. Номер следующего месяца и года вычисляется «честно», потом формируется дата на первое число этого месяца и уже от неё отнимается единица. Функция корректно обрабатывает даты в декабре 9999 года, специально анализируя этот случай и возвращая константу «31.12.9999». Но при этом все даты до 1800 года считает некорректными и генерит на них исключения, как и на даты с неправильным месяцем. Если передана дата с неправильным днём, не замечает этого.

Функция HR_RU_DAQ_GET_DAYS_IN_MONTH.

Имеет 8 входных параметров, 2 выходных и 2 одновременно входных и выходных. При этом состоит всего из 58 строк кода (из них 26 выполняемых). Алгоритм вполне аскетичный, как у FKK_GET_LAST_DAY_OF_MONTH, только прибавляет не 4 к двадцать восьмому числу, а 31 к первому. Некоторые входные параметры помечены как необязательные и никак не участвуют в алгоритме. В некоторых функциях, не вошедших в этот краткий обзор, использовались вариации — например, к первому числу прибалялось 35 или 32. Видимо, 31 побоялись прибавлять — а вдруг не хватит? 32 и 35 — надёжнее. Или, может, они так округляли? Разницы-то действительно нет, сколько конкретно прибавлять, лишь бы попало куда-нибудь в следующий месяц.

Две замечательные функции END_OF_MONTH_DETERMINE и END_OF_MONTH_DETERMINE_2.

Находятся в группах FV03 и FV02 соответственно. При этом алгоритм практически повторяется. Видно, что вторая тупо списана с первой. Но автор второй, вероятно, решил не полагаться на автора первой, а иметь такую важную функцию под собственным контролем. Обе честно вычисляют високосность года, но только по юлианскому календарю. А чего заморачиваться — на ближайшие 90 лет-то хватит, а там пусть потомки решают «проблему 2100»…

Самая аккуратная реализация оказалась у разработчика конечного пользователя. Лаконичная, эффективная и снабжённая исчерпывающими комментариями. Это и понятно — он ведь заведомо не индус.

9463

Армия дятлов-индусов

К различным глюкам госзаказного софта, выдаваемым за фичи, мы все уже привыкли. Но последний случай не вызвал никаких эмоций, кроме идиотской ухмылки с тянущейся из угла рта каплей слюны и нечленораздельного «Ы-ы-ы».

Программа «Декларант-Алко», банальная алкогольная отчётность. Десяток полей ввода, база данных, выгрузка в XML — ничего сложного, казалось бы, многие в своё время на коленке варганили и не такое.

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

Нет, конечно, на решение этой проблемы мне потребовалось секунд пятнадцать — опыт сказывается, — но это ведь уже клиника. Людям, допускающим такое в примитивной проге, недостаточно оторвать жопу, чтобы решить проблемы с руками на корню. Цивилизацию от этой армии дятлов-индусов спасет только огонь. Причем термоядерный.

9432

Дни Индии в Корее

Тут все ругают индийский код. Я вам скажу, корейцы не лучше.

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

Сайтов с аналогичным интерфейсом — тысячи в мировой паутине. Но только корейцам удалось написать сайт, который работает:

— только под IE и никак иначе;
— строго на одной версии Java;
— только если в системе стоит полная поддержка корейского языка, хотя сайт полностью англоязычный.

Как? Как они это сделали?!