bash.im ithappens.me zadolba.li
9568

DRY me a river

15 июля 2012, 07:45

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

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

Специфичные для России бизнес-процессы зачастую реализуют иностранные отделения, которые знают о том, что нужно сделать, только из спецификации, которую тоже писали не в России, пытаясь прочитать результаты трудов отечественных законотворцев.

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

9567

Нелогично, но работает отлично

15 июля 2012, 07:15

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

Надо рисовать на карте трассу спутника. Если верить формуле, трасса начинается на каком-то значении долготы, вырисовывает загогулины, причём иногда весьма интересные, и завершается на той же долготе плюс 360 градусов. Проблема состоит в том, что при рисовании надо ловить переходы через границу карты, завершать рисование справа и начинать рисовать трассу на карте слева. Сколько было визуальных глюков вокруг перехода через эту границу… Проблема исчезла, когда стали рисовать трассу три раза — со сдвигом −360, 0 и 360 градусов. Ненужное отсекалось само, нужные куски при рисовании стыковались сами. И не надо точки разрыва трассы искать.

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

9566

Это как роутер, да?

Я работаю инженером в NOC крупного магистрального провайдера. Основная задача — фиксация аварий, их локализация, устранение и ещё куча всего по мелочи. Приходится работать в том числе и с оборудованием SDH.

Фиксирую на мультиплексоре по потоку E1 аварийную индикацию. Стандартно открываю трабл-тикет, оповещаю свой саппорт, что по такому-то клиенту со стольких-то лежит канал, и звоню субпровайдеру, обеспечивающему последнюю милю в городе. Трубку поднимает девушка. Объясняю ситуацию. Девушка достаточно быстро понимает, про какой канал идёт речь.

— Да, по этому направлению у нас была авария, но всё восстановилось.
— Авария по каналу сохраняется.
— Перезагрузите ваше оборудование.
— Магистральный мультиплексор? (Время ребута — более пяти минут.)
(Уверенным голосом.) Да.

Я не выдержал и распрощался, скисая от хохота. Всё понимаю, техподдержка, на ней не инженеры работают, но она ведь для корпоративных лиц, не для физиков! Базовые вещи должны всё-таки знать.

9565

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

15 июля 2012, 07:15

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

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

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

9564

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

14 июля 2012, 07:15

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

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

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

9563

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

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

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

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

9562

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

14 июля 2012, 07:15

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

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

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

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

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

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

9561

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

14 июля 2012, 07:15

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

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

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

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