Суровые будни релиз-инженера. Захожу в туалет. В диспенсер заряжены бумажные полотенца низкого качества. Кто-то до меня вырвал из торчащего полотенца середину — остальное, видно, достать не смог. Хватаюсь с двух сторон за огрызки, дёргаю. Повреждённое полотенце в руках, из устройства снова торчит целое новое. В голове мысль: «Jenkins build is back to normal».
Истории с тегом: программизмы
Всего историй: 900
Полное оно
Работаем в интернациональной команде — из тридцати пяти разработчиков русских всего пятеро. Пишем очень интересный и большой проект. Задумались о том, что иногда нужно оставлять такие комменты, которые были бы понятны только нам пятерым, но обязательный язык документирования — английский, и отклоняться от этого правила нельзя.
Провели мозговой штурм. В результате получился следующий коммент, который изредка встречается перед «нашими» блоками кода:
// Following code is unreal who it are.
Яркий, насыщенный прозрачный
Помню я свой первый проект. Писался он под Adobe AIR. Команда состояла из меня (девелопера), девочки-дизайнера и менеджера, который должен был руководить ходом разработки и общаться с заказчиком.
Надобно нам было реализовать функцию ластика. Рассказываю и поясняю нашему менеджеру, что обычно ластик просто зарисовывает картинку цветом фона, а нам так сделать нельзя, ибо фон — графическое изображение. Описываю проблему, говорю, сколько времени уйдёт на реализацию, совета спрашиваю, как у старшего.
— А нельзя ли как-то зарисовать прозрачным цветом?
Перекус, перекур, перефраг
Давным-давно в одном южном городе зарабатывал я свой первый миллион. Как раз перед деноминацией дело было. Работал я в конторе, которая занималась рекламой и приборостроением, в частности, разрабатывала прибор для изучения нефтяных скважин методом межскважинной томографии.
Суть метода проста. В земле бурятся две дырки, в одну спускают микрофоны, в другую кидают бомбу. Бомба бахает, микрофоны записывают колебания и передают их наверх. По скорости прохождения сигнала можно узнать много интересного о породах.
Миллион мне предлагали за программу, которая принимает данные с прибора на компьютер. Начальник, так случилось, считал, что понимает в программировании. Его понимания, однако, хватало ровно на то, чтобы в приказном порядке определить инструментом разработки ассемблер, ибо он и только он даст необходимую производительность.
Программа была написана и ловко принимала данные, записывая их в файл и попутно отображая в виде гистограммы на экране. Заняло это прилично времени (ассемблер же), но более всего запомнился один эпизод отладки.
В какой-то момент программа начала глючить вполне так конкретно; после того, как её удавалось закрыть, глючило всё остальное, пока комп не перегружался. Код, команда за командой, перебирался долго и вдумчиво. Просчитывались на пальцах сохранения регистров в стеке и корректное их оттуда извлечение. Перепроверялись отдельные куски и логика в целом. Что-то менялось и правилось.
На отладку ушли минимум три рабочих дня, в течение которых с утра до позднего вечера я искал, правил, делал контрольные запуски. Лишь когда в процессе сделали перерыв, и обнаружилось, что комп глючит и сам по себе, без запуска программы, нашлась истинная причина беды.
Кулер на процессоре сдох, сволочь.
А ведь если бы работал не спеша, с перерывами на поиграть, всё бы выяснилось в первый же день.
25-й, но не кадр
Контора занимается аутсорсингом. Наблюдаю диалог ведущего программиста проекта с младшим коллегой:
— Саня, пропиши часы для логов.
— Какие часы?
— Ну, обычные человеческие суточные часы. От 0 часов до 24.
Проходит два дня, тестирую логи. 0:00, 1:00… 23:00, 24:00.
В качестве наказания Саня вторую неделю ходит с беджиком: «Привет, земляне!»
Затычка по-Гоблински
Как-то раз меня попросили показать заказчику бета-версию некоей программы, и я пошла к программистам, чтобы узнать, что готово, а где стоят заглушки. Мне всё подробно показали и объяснили, предупредив, в частности, что на кнопку вызова определённой процедуры нажимать не нужно. Когда я понимающим тоном уточнила: «Что, не готово ещё?», кнопку нажали. Процедура всё рассчитывала должным образом, только вот после окончания работы выдавала пользователю сообщение: «Процедура завершена с особым цинизмом».
Powered by magic
Пишу проект на Delphi. В работе использую нестандартные компоненты из набора AlphaControls. Есть там такой симпатичный TFramebar — панель со сворачивающимися вкладками, на которых размещаются фреймы. И удобно, и красиво.
И было бы всё тихо-мирно, не понадобись мне воплотить следующую идею. Есть два фрейма, реализующих пользовательские интерфейсы для поиска и сортировки в БД. Эти фреймы помещаются на вкладки упомянутого фреймбара. Получается очень кошерная менюшка для манипуляции данными. А в приложении несколько таблиц, и каждой такую менюшку нужно прикрутить. Как это сделать? Ну конечно — кинуть саму менюшку на новый фрейм и разместить его экземпляры везде, где понадобится. Получится фрейм, на котором находится контейнер фреймов, в котором лежит два других фрейма (фрейм на фрейме и фреймом погоняет), но выглядит идея здраво. Начинаю воплощать.
Оказалось, что фреймы на фреймбарe нельзя просто взять и разместить (как, например, на привычном TPageControl — накидал, и готово). Здесь у каждой панельки прописывается событие OnFrameCreate, в котором нужно указать тип создаваемого фрейма. Только в runtime экземпляр будет создан и размещён на вкладке.
И вот тут-то подкрался капец. Привычный механизм наследования, когда потомок имеет доступ к свойствам и методам предка, у этого компонента почему-то сбойнул. То есть экземпляры моего фреймоконтейнера понятия не имели, что где-то там, в родительском модуле, у TFramebar прописаны обработчики и типы для фреймов на вкладках. При запуске я лицезрел пустые панельки с надписью: «Frame creation event has not been defined».
Когда гугление, медитация и маты не помогли, в дело вступил метод научного тыка. Я попробовал создать обработчик уже для экземпляра фрейма-контейнера. Он создался, при этом обязательный в таких случаях вызов соответствующей процедуры из родительского класса в нём не прописался, что подтвердило предположение о том, что этот потомок своих предков не помнит. Попробовал прописать вызов вручную — куда там, не знает оно о его существовании. Ладно, тупо скопировал код из родительского обработчика — при запуске словил невнятный эксепшн. Убрал обработчик — снова «has not been defined». Плюнул, создал событие обратно, поставил внутри комментарий (чтобы Delphi не удаляла пустой обработчик) и запустил. Моё долгожданное меню сортировки смотрело на меня со вкладки контейнера.
Я не поверил. Повторил все пройденные пункты — та же фигня. Создал пустой обработчик с одним только комментарием внутри для второй вкладки — менюшка поиска встала в строй. Минут пять я медитировал на это дело. Потом вздохнул — и пошёл лепить эти костыли во всех экземплярах контейнера.
Теперь в нескольких модулях красуются потрясающие по глубине и содержанию фрагменты вида:
{ powered by magic }
procedure TfrQuoteView.sfrmbrDBmenuItems0CreateFrame(Sender: TObject; var Frame: TCustomFrame);
begin
//
end;
procedure TfrQuoteView.sfrmbrDBmenuItems0FrameDestroy(Sender: TObject; var Frame: TCustomFrame; var CanDestroy: Boolean);
begin
//
end;
И такая пара для каждой вкладки контейнера.
Не раз уже сталкивался, казалось бы, с мистическими глюками в работе, но причина всё же находилась. А здесь — увы… Powered by magic, в общем.
Поиписькапосчитайка
Не интереса ради, а работы для нужно было поставить скрипт багтрекера, написанного в нашей конторе. Проблема была: не хотел он заводиться. Пришлось ковырять движок.
Видно, что код не быдлокодер писал: красиво, с чувством, толком, интонацией и документацией. Только со странностями небольшими. Автор, видимо, очень любил покурить или покушать чего весёлого. Так, например, обнаружились стандартные настройки идентификатора статьи, который был объявлен так:
// Поиписькапосчитайка *_*
$this->art_id = 0-1+11-111+101-1-101-1-101-11-1-11-111+11-1-0;
В качестве солей для хешей использовались фразы: «Потцан_с_района», «Билли Гейтс», «Пельмени», «Хочу смотреть Дом-2».
Но самое весёлое ждало меня дальше. Обнаруженные строки окунули меня в неописуемое чувство гордости за собратьев.
$желаемая_оплата = "1000 баксов";
$мне_обещали = "300 баксов";
if($желаемая_оплата != $мне_обещали) {
// Немножко индусской логики
$a = 0;
$b = 0;
$a = $b;
}
Старший научный сотрупник
Текущий проект нашей компании — программа для контроля исполнения документов сотрудниками, работающая на основе базы данных.
В ничем не примечательный день звонит заказчик и говорит, что хочется ему увидеть бета-версию. На доводы типа «Ещё далеко не всё работает» отвечает: «Ну, хоть какую-нибудь». В спешке на неработающие функции ставятся заплатки, сборка делается уже в день показа. Начальник и один из коллег в суматохе собираются на встречу с заказчиком и случайно путают папки с базами данных: вместо контрольного примера берут с собой тестовую базу, на которой отлаживался код. Но это всё мы узнали уже потом.
Показ прошёл успешно. Сотрудник, возивший программу к заказчику, потом травил байки о том, с каким удивлением заказчик обнаружил в списке должности «Суперперец», «Аццкий перец», «Йа криведко» и «Рядовой сотрупник». Самое же неизгладимое впечатление на заказчика произвели должность «Хрен моржовый» и личная карточка сотрудника с ФИО «Косяков Дофига Нахваталович».
Лубрикант для активного рефакторинга
Есть очень показательный тест. Вопрос звучит так:
Рабочий орган программиста? Четыре буквы, вторая — «О».
Проверял у себя на фирме. Электронщики и радиомонтажники ответили правильно. Ни один программист не догадался, что это мозг.