9565

До 16, не старше

Я задолбался жить в хрущёвке. Долго копил деньги и в итоге таки смог переехать в уютненький домик в пригороде Екатеринбурга. Думаете, жизнь пошла спокойно? Ага, сейчас же! Одна-единственная заноза в заднице мешает жить спокойно, и имя ей — интернет.

Сперва подключил ADSL от известного всем оператора в жёлтую полосочку. Я закрыл глаза на то, что за вдвое большие деньги скорость была в полтора раза меньше, чем в хрущёвке. Я со вздохом смог принять, что выходной канал раз в пять ýже входного: в конце концов, рейтинг на торрент-трекерах уже не мейнстрим, а фотки можно и на ночь оставить выкладываться. А то, что цифрового ТВ нет и не предвидится, меня вообще не задело: я его не смотрю. В общем, интернет нормально работал до первого осеннего дождя. После него связь исчезла. Техподдержка ответила просто шедеврально: «У нас этот, как его… свитч водой заливает! Подождите недельку, он высохнет, и интернет появится». Все попытки пробиться сквозь железнолобый первый эшелон успехом не увенчались. В итоге я неделю докачивал свои торренты, сидя в кафе с халявным вайфаем.

Зима прошла. Наступила весна. Снег начал таять. Свитч по-прежнему затапливало. Будучи не в силах платить за отсутствие интернета, я расторг договор и обратил свой взор к точно независимому от погоды 3G-модему красно-белой яйценосной компании. На коробочке гордо красовалась надпись: «До 14,4 Мбит/с!» Подключил, пару часов поковырявшись, чтобы завести модем под линуксом. Интернет появился. От радости даже ограничение в 8 ГБ не показалось большим. Малина, как всегда, быстро кончилась при попытке измерить скорость. Наивысшим достигнутым показателем были 1,5 Мбит/с, — и это при вышке в паре сотен метров! Саппорт поверг все мои аргументы в прах железобетонной фразой: «Полтора мегабита замечательно укладываются в ограничение до 14,4 мегабит».

9564

Голенькие одноклассники

Кодирую в PhpStorm. Пишу «NULL», промахиваюсь и печатаю «NU::».

Смотрю. Жму Ctrl+Space. Жду. Думаю, почему автокомплит IDE ничего не показывает. И что вообще за класс такой — «NU»?

Чувствую, что пора сделать перерыв на кофе.

9563

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

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

— Отсутствует 301-й редирект. Сайт работает только с WWW.

— Работает только под «ослом». Пришлось запускать через Wine.

— Отсутствует поиск.

— Имеется русская локализация, но переведённая в стиле «Синий зуб — Позвонить бревну».

— В некоторых местах русский язык вообще отсутствует, текст написан на английском.

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

9562

Коробочка с интернетом

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

По приходе домой достал замученный бывшим владельцем известный 320-й роутер с горелыми портами. Восстановил бутлоадер через JTAG, прошил в DD-WRT, нашёл полудохлые банки ноутбучных аккумуляторов и притащил утром на работу. Питание роутера завёл от аккумов, с коммуникатора попытался поднять беспроводной линк. Жутко неудобно и хреново выходит.

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

Озарение пришло дома. Выйдя покурить на балкон, зацепился взглядом за разбитый китайский радиоуправляемый вертолёт. Снял приёмник-контроллер, из 3310-й «нокии» выкорчевал моторчик, взял пульт. На работе приступил к сборке. К моторчику припаял лопасть из полоски латуни, кнопку в роутере перепаял на 180 градусов, рядом закрепил моторчик, прицепил ограничительный резистор и аккумы. Вместе с контроллером и ранее изготовленной биквадратной антенной смонтировал внутри роутера. На пульте нажимаю рычаг газа — моторчик хлопает лопастью по кнопке и держит, пока не отпустишь рычаг. Шикарно!

Шайтан-девайс закинул на шкаф у окна, растянул метра три провода от приёмника. Не вставая с рабочего места, быстро настроил беспроводной мост и оставшуюся пару рабочих часов провёл уже в интернете, почитывая свежие вести с IT happens.

Со временем о точке узнали молодые коллеги. В обмен на пароль обязались заряжать девайс по окончании рабочего дня. Я же, помимо кнопки ресета, внедрил возможность включения и выключения питания с того же пульта, но через релюшку. Красота!

9561

Драная, дырявая

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

— Где наклейка?

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

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»…

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

9559

Оскорбление корпоративной этики

Лежит у меня 40-мегабайтный хард от WD с серийником 0000016. Года три назад была у него обнаружена интересная привычка: всуе обругаешь WD — не включается неделю, потом нормально. До следующего оскорбления корпоративной этики.

Наводки? Нет, он лежал на дощечке, так как компьютер был занят комбо-приводом под 5,25" и 3,5" дискеты. Единственное соединение — шлейф и питание от БП. БП работает до сих пор без нареканий. Обитатели дома? Нет, диск стоял в сторонке, пыль никто не протирал.

Единственное объяснение — мистика. Винт старый, из первой партии. От возраста у него настолько ослабли некоторые контакты, что поддерживались только квантовой связью, намоленной радостными мотивированными сотрудниками завода в первый день работы, и при её ослаблении он «глох». Мысли о том, что компания плоха, преобразовывались в радиоволны и улавливались чем-то в устройстве, внося помехи в нежные квантовые связи. Они нарушались, хард вис.

Может, вся суть «мистики» и «эффекта присутствия» в плохих контактах и маломощных резонансных наводках, «ремонтирующих» их?

9558

Прикинься шлангом

Году в двухтысячном писал систему управления RAID-контроллером. Контроллер попался солидный — железка с форм-фактором CD-ROM, управляемая через COM-порт. Софт этот повёз на выставку в Тайбэй этакий клерк-администратор от IT, по доброй традиции ни хрена не понимающий ни в софте, ни в железе, ни в IT вообще. Кому же ещё можно доверить руководить программистами?

Софт, естественно, не заработал. За последующие 13 часов было выполнено следующее:

— скачан и установлен Visual C++;

— скачаны и откомпилированы исходники софта;

— скачан, откомпилирован и запущен самопальный дебаггер RAID-команд;

— проведена отладка всего софта.

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

Я настропалился кидать в асю команды типа «F7 → Alt+O → смотрим последнюю строку» или «мышь на текст comStatus → Ctrl+F9 — что выдало?». Работа под конец шла довольно быстро; создавалось впечатление, что багу всё же найдем.

Финал был сплошным разочарованием. Наш клерк забыл воткнуть шланг от COM-порта в контроллер.

9557

Таких не берут в пилоты

Стоят в кабинете DECT-аппараты. Два из них включены в один «пилот». Одна девочка в целях экономии электроэнергии «пилот» выключила: дескать, лампочка зазря горит, тратится ток.

Началось: «Не работает!» Выяснить, что не работает, не удалось. Пришёл инженер, включил «пилот». Поругался на девок. В это время «экономная» выходила из кабинета. Пришла, увидела лампочку — опять «пилот» выключила. Опять телефон не работает. Пришёл инженер, включил «пилот». Сказал, что выключать нельзя, что телефоны от него питаются. Девушка сказала, что инженер врун, что телефоны от розетки не питаются! Пришлось показывать и рассказывать.

9556

Не зная броду, не суйся в воду

Есть организация, которой я настраивал линуксовый сервер: 1С 8.1 + файлопомойка. По мере необходимости они просят сделать то одно, то другое. Я не отказываюсь, но беру за это некоторые деньги. Зеркало нужно? Пожалуйста. Ещё одну базу 1С на сервере? Без проблем. Хотите два сервера 1С (8.1 и 8.2) на одной машине? Пожалуйста, N рублей.

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

Конкурент:

1. Не сделал архивные копии боевых баз работающего сервера, а архивирование почему-то остановил неделю назад.

2. Переустановил зачем-то СУБД PostgreSQL с инициализацией, то бишь все базы стёр к монахам.

3. Два сервера одновременно запустить не смог.

4. Постоянно названивал мне с консультациями: «А как пароль к БД восстановить? А как подключиться к БД без пароля? А как…»

5. Вчера в час дня пришёл к главбуху, сказал, что ничего не получается, так как «диски посыпались и базы пропали», и пропал. На звонки не отвечает.

Короче, с дисками там всё в порядке оказалось — не зря зеркало настраивал. Да и диски новые, полгода им всего. Установил я им два сервера 8.1 и 8.2 на одну машину. Восстановил базы недельной давности, взял деньги и ушёл.

Но в душе у меня остался вопрос: на фига так делать? Не умеешь — не берись. Не умеешь, но очень хочется? Возьми тестовый комп, потренируйся «на кошках».