bash.im ithappens.me zadolba.li

Программизмы

11486

И молодая не узнает, какой у файла был конец

Знакомо ли вам сообщение программы «Не могу открыть файл» с последующим выходом? Мне — да. И это уже расстрел. Расстрел того программиста, который так написал. Потому что не написано, где именно программа ищет файл, и не указано, почему именно она этого не может сделать.

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

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

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

11478

Тест на вшивость

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

Работаю в довольно крупной компании, занимающейся в числе прочего QA (обеспечением качества). Мне таки есть что сказать об автоматизированном тестировании. Большинство решений в кровавом энтерпрайзе — лютый ад. Конечно же, поскольку автотесты — тот же программный продукт, то для них характерны всё те же проблемы, что и для ПО, только всё ещё печальнее.

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

1) Бывшие функциональные тестировщики. Эти ребята обычно хорошо понимают процессы QA, но плохо понимают, как этого добиться с помощью имеющегося инструментария, а уж тем более как этот самый инструментарий подобрать исходя из задач. Хуже всего — когда они примеряют на себя роль «очень-крутого-парня-который-теперь-лучше-других».

2) Технические специалисты, уровня знаний которых достаточно, чтобы делать грамотные решения автотестов, но недостаточно для разработки. Как правило, далеки от QA и мечтают вырасти или в менеджеров, или в разработчиков.

3) Автоматизатор-единорог: технически подкован, чётко понимает процессы и задачи QA. В природе практически не встречается.

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

4) Индусы и примкнувшие к ним. Люди, умудряющиеся сделать предположение, что KDT — это Keyboard Driven Testing, рисующие XPath-локаторы вроде //*[@id='some_id'] и т. п.

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

В-третьих, есть неслабая мода устраивать псевдо-agile, когда тесты пишутся по новой функциональности, а подход в разработке не BDD/TDD (или банально не выделяется времени на поддержку тестов в актуальном состоянии).

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

Может, коллеги меня поправят, и всё не так грустно где-нибудь в другом месте. Пожалуйста…

11475

За мишурой методов

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

Программисты — не исключение. Те, кому посчастливилось поработать в крупной софтверной компании, начинают мыслить категориями проектов, дедлайнов, тест-кейсов и так далее.

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

Просто не забывайте об этом за мишурой методов разработки — никому, кроме вас самих, они не интересны.

11451

Не грози козой

Добавлю свою ложку сахара в приторный уже чай из холиваров на тему сравнения компьютеров (сайтов, сетей, юзеров и прочего) с холодильниками (автомобилями, стиралками). На эту тему пела известная до сих пор певица: «Сделать хотел грозу, а получил козу…»

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

Действительно, почему бы таким «разработчикам» и «админам» не сесть за компьютер рядового пользователя? Так сказать, поработать в полевых условиях. Может, тогда другим профессионалам в своём деле работалось бы полегче.

11445

Дюк Глюкем 3D

Вспомню и я свою молодость. БК-0010, прыгающие шарики, синусоиды, самодельные игры и даже некое подобие цветомузыки — на экране прыгало нечто при наличии любого сигнала на входе с магнитофона. Затем появился доступ к 386, под руку попалась очень интересная книга «Как написать компьютерную игру» — по сути, отличный учебник по ассемблеру. Жаль, что там не рассматривался защищённый режим, его я так и не осилил. И понеслось… С приятелями писали вирусы наперегонки, меняли синий Нортон на зелёный, приятель реализовал анимацию огня на загрузочном секторе дискеты — 512 байт!

Как-то в начале 2000-х попался мне в руки первый «пень» с EGA-видеокартой и монитором — 16 цветов! В те времена любили мы с другом гонять Дюка 3D по сетке (звонили по модему). Не обращая внимания на EGA-карту, Дюк спокойно запускался: то ли карта была хитрая, то ли проверки не было. На экране была цветная каша, ибо в EGA цвет кодировался непосредственно самим байтом (или полубайтом — не помню), то есть по такому же принципу, как и в нынешних видеокартах, а в режиме VGA с 256 цветами байт в видеопамяти — это индекс, который ссылался на 18-битный (если не ошибаюсь) регистр, в котором уже кодировался сам цвет. А поиграть хочется!

Что делаем? Распаковываем GRP-файл из Дюка — получаем кучу BMP-спрайтов. Пишем на ассемблере программу, которая открывает указанный в командной строке BMP и округляет цвет каждой точки до палитры EGA. Запускаем Windows 98, вписываем соответствующую команду в реестр, выделяем в проводнике все BMP — правой кнопкой — наша команда. Идём пить чай, ибо по лени программу я не оптимизировал и закрывал файл после конвертации каждой точки, а для каждой следующей точки открывал снова. Знаю, убить меня мало за такое издевательство над компьютером. Но хорошо, что это был ассемблер, и в конце концов все файлы были обработаны. Пакуем GRP, запускаем игру. Картинка ужасная, но, по крайней мере, играть уже можно!

11441

Цокот кованых сапог

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

Взял первую попавшуюся локализацию сборки — немецкую. Кнопки и настройки-то там же расположены. Поставил, запустил. Непонятные надписи смущают, но «на скорость не влияет». Собрал логи, скриншоты, отправляю тимлиду.

— Картинки-то не изменились. Хотя дико неудобно.

Unabhänglich von den Gewährleistungsverpflichtungen! Слышен прямо цокот кованых сапог.

11406

Я тебя породил — я тебя не убью

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

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

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

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

«Не страшно, — думаю. — Ctrl+Alt+Del я-то не заблокировал». Хотя были мысли и эту комбинацию заблокировать, так как не завершать работу аварийно, когда им что-то непонятно, я так и не научил.

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

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

11371

Блок-наволочка

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

Загрузил экзешник в IDA, он вроде как нормально распотрошился в автоматическом режиме. Поначалу всё оказалось просто: получение дескрипторов консольного ввода/вывода, определение режима работы по ключу запуска, загрузка драйвера программатора, проверка подключения. В конце концов дело дошло до самого криптоалгоритма, а именно до формирования открытого ключа. В его состав входили как константы, так и параметры, получаемые в ходе выполнения программы (например, дата и время). Всё это набивалось в стек для передачи в качестве параметров процедуре, которая должна была сварганить готовый ключ. Вот как раз на передаче такого большого числа разнотипных параметров меня и заклинило: я понял, что окончательно запутался, что, где и откуда берётся. Так как дело было в субботу, решил на работе не засиживаться и пошёл домой.

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

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

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

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

11340

А стул догорал подо мной

Занимаюсь программированием PLC Siemens. Есть такая возможность — передать со SCADA целых 4 КБ данных за один цикл, пусть байтовым массивом — но можно же! А при объёме оперативной памяти 128 КБ и под хранение программы 512 — это ой-ой-ой. Решил заняться этим вопросом, благо рецептурная база в пищёвке — вещь необходимая. Вышел я из отпуска — и понеслась…

Шаг первый: скачал пример. Работает, но выворачивает байты наизнанку. Моторола же ж. Ладно, выкурил учебник по C, пристрелял его к реалиям извращённой логики скрипта. Приходит случайно сгенерированный массив в нужном виде.

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

Шаг третий: теперь полученный массив надо перевести в должный вид, чтобы булевы переменные стали булевыми. А что вы хотели? Нельзя просто так взять и сразу выдать булевыми: хитрая система всё, что отлично от нуля, считает априори трушным. На каком языке проще всего перебирать два массива в трёх циклах? Конечно же, STL.

Шаг четвертый (стул начал тлеть): два массива перебираются в трёх циклах по типу переменных — переменная времени, булева, real. Всё хорошо, но при переборе массива число итераций не увеличивается, что приводит к падению в стоп. Левый глаз дёргается, правый судорожно читает срач на форуме. Умный человек советует скурить книгу Бергера. Слава ему и честь, указывает главу. Смысл в том, что если ты собираешься вызывать один функциональный блок несколько раз, то тебе не надо ничего делать, но второй адресный регистр забирает компилятор под статпеременные, в которых лежат счётчики итераций. Эту возможность можно отключить только при создании блока. Но после — уже никак не изменить судьбу, быть ему навечно мультиэкземплярным.

Шаг пятый: всё, заработало, перебирает и шуршит. Самое время перебраться с симулятора на реальное железо. Из заказанного шкафа выдирается контроллер — и-и-и… Фейл! Эта фича работает или на старшем поколении, или всего на трёх из младшего по мощности, у которых есть порт Profinet.

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