Перерыв на обед – нет!
В одной известной компании свёл меня случай с одним коллегой по офису. Звали его Джон. С первого взгляда очень солидный мужчина, умный вид, семейный, уже растут дети. Биоритмы мои с ним совпадали, порою я даже умудрялся приходить раньше его на офис и даже уходить раньше, что для рядового сотрудника было бы настоящим состязанием. По утрам он имел привычку делать себе мюсли: в принесённую на офис тарелку он засыпал мохнатые хлопья, заливал волшебным молоком и аппетитно хрумкал минут пять. После этого Джонни делал себе ароматный чай, который непременно дополнял вафлями или печеньем. Всё это утреннее время мне работалось не шибко сильно. Его же завтрак, я так думаю, проходил за чтением утренних новостей, поскольку ничем другим решительно невозможно заниматься с ложкой в одной руке и кружкой – в другой. Спустя некоторое время после опустошения и осушения нахлынивало рабочее настроение, и мы погружались в работу. В перерывах между завтраком и обедом в ход шли хрустящие яблоки и бананы, которые обязательно присутствовали на полке для головных уборов, превращённую безапелляционно в мини-склад фруктового магазина. На обед он ходил когда-как, видимо, пытаясь чутка сэкономить: всё-таки бремя ипотеки (может даже не одной) давало о себе знать. Вместо этого он покупал экспресс-суп наподобие Ролтона, заливал его водой и подогревал в микроволновке на кухне. Но вместо того, чтобы присесть за столиком тут же, на кухне (где ему никто и слова наперекор бы не сказал), и насладиться вкусом сего мессива, он (нетрудно догадаться) нёс его в наш офис, в котором через мгновение по расплывался приятный запах макарон, шампиньонов и чего-то-там (запах производителям продукта удалось синтезировать "на пять"). Вот скажите мне, почему я должен нюхать это весь следующий час?Унылая муторная работа в послеобеденное время очень быстро понижала жизненный тонус Джон и тогда он открывал сайт с анекдотами и читал их, едва сдерживая смех сквозь зубы, иногда прихихикивая и прикрывая рот кулаком. Подкрепление желудка в послеобеденное время всегда проходило под лозунгом "съешь ещё этих божественных хрустящих сухариков", причём так как эти ненавистные мне сухарики были к тому же расфасованы в небольшенькие фольгированные пакетики, то весь ритуал начинался с шумного разрывания одного-двух таких пакетиков, высыпания в освободившуюся после завтрака тарелку, затем пакетики комкались и находили упокоение в мусорке. Всё это, сами понимаете, происходило настолько "абсолютно беззвучно", что кроме грома и молний в своём собственном мозгу ничего слышно не было.
Возвращение бумеранга
Мой коллега любил забирать свой рабочий ноут с собой уходя из офиса. Конечно, это не запрещено правилами, но что-то подсказывало мне, что он откроет его дома на своём диване совсем не для того, чтобы закончить отчёт. Просто этот жмот не мог выделить из своего бюджета каких-то $200, которые бы, воплощённые в БУшный ноут, с лихвой покрыли бы все его потребности. Однажды утром, приволоча с собой этот затасканный рабочий ноут, Джон обнаружил, что он не включается. Точнее, на экран выскакивает та самая надпись, от которой прошибает в пот: "Operating system not found". Это был уже второй аналогичный случай за последний месяц, когда у него слетел винт. Ситуация малоприятная в принципе, поскольку всё приходилось начинать сначала, а бакупов он вряд ли делал. На этот раз мой коллега не поленился поинтересоваться у менеджера, за какое время должна отработать служба поддержки и принести ему новый винт. После часа ничегонеделания, он позвонил в службу поддержки дабы сообщить им, что из-за их, мягко говоря, нерасторопности, он не может выполнять свою наивысочайшую функцию в компании. А просто книжку почитать или газетку у него не возникало желания. Когда же наконец в нашей комнате появился несчастный одинокий технарь, Джон строгим голосом спросил:— Ты можешь показать мне винт, что ты принёс?
Тот протягивает винт.
— Почему он не в упаковке? Где тут дата изготовления?
Оба начинают рассматривать винт в поисках желанной маркировки.
— Так ты мне юзаный винт принёс. Конечно они через месяц выходят из строя!
— У нас такая политика: мы не выбрасываем винты, мы их переформатируем и возвращаем в оборот.
— Если он опять упадёт, что мне делать?
— Послушайте, коллега. Я лишь делаю свою маленькую работу. Если вы не довольны тем, как я её делаю, вы можете сообщить об этом моему менеджеру.
После непродолжительной перепалки на повышенных тонах, технарь всё-таки смог заменить винт и ушёл. Но Джон не мог оставить всё это на самотёк, и решил преподать неказистому технарю урок, а именно, пойти и пожаловаться. Но стоило ему переступить порог, как его споймал наш менеджер и сообщил, что только что ему позвонил начальник технического отдела и сказал, что Джон был груб в беседе и не давал другим выполнять свои обязанности. Технарь, холера, сработал на опережение.
Солдат спит, а служба идёт
Семья моего коллеги не жила с ним в той же стране, где он работал. Джон снимал квартиру для ночлега недалеко от офиса, и почти на каждые выходные уезжал домой, в свою страну. Машины у него своей не было и денег на билет на самолёт тоже. Вариант его был самый экономный: посредством форума находить водилу, который едет в нужном ему направлении, и за небольшую договорную цену составлять ему компанию. Понятно, что часть рабочего времени на неделе уходило на прозвонку дальнобойщиков и выяснения того, когда отправляется машина, где его смогут подобрать и где лучше выбросить. График на пятницу у Джона напрямую зависел от машины и частенько в пятницу его не было, что не могло нравится нашему менеджеру. Гибкий график работы в офисе позволял работать overtime, и при некоторой усидчивости и доступности интернета можно было продержаться лишние два часа на работе с понедельника по четверг, что как раз и накручивало нужные восемь пятничных часов. Это не нравилось нашему менеджеру ещё больше, и тот в связи с этим ввёл ограничения на overtime (абсурд для менеджеров в некоторых других компаниях, в которых мне довелось работать, но с другой стороны приятно, что о твоём состоянии заботятся):- Если ты честно отработал 40 часов в неделею, то тебе положено 5 часов overtime
- Если ты отработал 32 часа, то только 3.
- ... и далее по убывающей
Алё, Асисяй?!
Джону с завидной периодичностью на рабочий телефон звонила его жена. Иногда он ей звонил, несмотря на то, что звонок, в общем-то, международный. Но однажды я непроизвольно стал пассивным свидетелем весьма неприятного разговора. Один прекрасным утром Джон звонит в свой банк (а банк его был в его родной стране), и разговор идёт приблизительно в таком русле (ответов из трубки я не слышал, поэтому пофантазирую):Джон: — Здравствуйте. Есть ли у вас для меня новости, касательно денег, пропавших с моего счёта?
Банк: — Здравствуйте. Пока новостей нет, но мы выясняем причину.
— Я вам сообщил об этом ещё на прошлой неделе. Имеет место финансовое преступление. Надо звонить в полицию, а вы ничего не сделали!
— Мистер, мы делаем всё, что в наших силах.
— Скажите мне ваше имя и фамилию и дайте мне телефон вашего менеджера. Я хочу разговаривать с вашим начальством касательно сложившейся ситуации.
— Да, меня зовут Ребекка Смит. Номер телефона менеджера я вам дать не могу, это против наших правил. Но я могу вас на него переключить. Желаете?
— Да, переключайте.
Возникает пауза на несколько минут, в течение которой Джонни напрасно посылает сигналы своим мозгом на тот конец провода: трубку никто не берёт. Он с досадой бросает свою трубку и говорит мне: "Совсем эти клерки распоясались. Их просто некому поставить на место!"
Мастер-ломастер
Уж не знаю, насколько Джону удавалось удовлетворять запросы нашего менеджера, но в плане какой он талантливый программист мне пришлось проверить на собственном опыте. А дело было так. Моему коллеге нужно было получить некоторые данные из RESTful сервиса, который возвращал ответ в XML формате. Тот наваял какую-то Java программулинку, которая работала в 99 случаях и в одном почему-то накрывалась с исключением SaxParseException "Invalid UTF-8 character at position X". Сервис, к которому он обращался, был написал давно и откатан хорошо, поэтому вероятность того, что именно мой коллега был претендентом на приз "лучший баголов недели" была крайне мала. Практически ничтожна. Когда он уже занёс руку над телефоном, чтобы звонить в службу поддержки этого сервиса и жаловаться, что у них сервис работает из рук вон плохо, как меня передёрнуло от одной только мысли, что история-то повторяется и мне придётся быть волей-неволей свидетелем новой истории. Я, как истинный коллега, предложил свою помощь с решением проблемы. Когда я подошёл к его монитору, меня несколько всколыхнуло, как от удара звуковой волны. Во-первых, мой коллега, каким-то чудом всё-таки сумевший скачать и поставить себе Eclipse, подключил в проект только JRE (искать у него JDK у меня не было никакой охоты), а следовательно, ни исходников ни Javadoc у него не было. "В таком режиме работают лишь истинные профессионалы" подумал я и взглянул на код. А предстало перед моими очами следующее:и далее по коду было жёстокое порно с участием getChildNodes() и doc.getElementsByTagName("..."). Ошибка тут очевидна: DOM парсеру надо было передавать "сырой" InputStream, а не выворачивать его в строку. Рассказав это тут же, я, не заметив зачем же ему всё-таки понадобилась эта строка, спросил, а нельзя ли обойтись без StringBuffer? В ответ получил, что хотелось бы выдать ответ сервиса на экран. Ну что делать: раз хочешь, то хочешь. Я уже ничего не говорил о многоэкранной мастурбации с DOM-деревом, которую можно было заменить на xPath (для моего коллеги это явно была инопланетная технология). По идее самым простым решением было бы задать кодовую страницу new BufferedReader(new InputStreamReader(is), "UTF-8"), поскольку, как известно, по умолчанию используется кодовая страница файловой системы ОС, что в нашем мелкомягком случае было "CP-1252". Но мой мозг всё-таки приучен мыслить "как правильно", а не "как быстрее" и поэтому моим решением "на скорую, но более адекватную руку" было создать массив подходящего размера "на глаз", зачитать в него весь ответ, вывести на экран и скормить парсеру:InputStream is = serviceUrl.openStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuffer sb = new StringBuffer();
String line;
while (line = reader.readLine() != null) {
sb.append(line);
}
System.out.println("XML: " + sb.toString());
Document doc = documentBuilder.parse(new InputSource(new StringReader(sb.toString())));
Node node = doc.getChildNodes().item(5);
URL serviceUrl = null;Мой фатальной ошибкой в этом коду было то, что я, как и Билли, повёлся на то, что "64K ought to be enough for everyone", а именно, размер буфера может оказаться маловат. Но я об этом сказал коллеге, что, по хорошему, надо зачитывать ответ кусками, и что не нужно изобретать велосипед, а взять IOUtils.toByteArray(is). Сейчас, глядя на этот код, вижу ещё одну, на мой взгляд малозначительную непринципиальную ошибку (напиши о ней в комментарии, дорогой мой читатель), во всяком случае, с парсингом всё в порядке. На следующий день я как-бы ненавязчиво спросил Джонни, а дописал ли он свой мега-код, на что он повёл себя неадекватно, взъерепенился и буркнул, что это не моё дело, сколько времени он будет писать этот код. Я совсем не против, путь пишет его хоть неделю. "Просто помочь хотел", – ответил я ему. На что он ответил, что не упала ему такая помощь: [я] простоял у его спины вчера целых 15 минут, а работающего кода не написал. Оказалось, что для части запросов буфера всё-таки не хватило, но я ему напомнил, что я сказал об этом ещё вчера. Далее и без того натянутый разговор завернулся в сторону, которую я совсем не ожидал: мой коллега спросил меня, а сколько лет я в IT? Я ответил, что пять (хотя на самом деле больше, но я же скромный). И тут Джонни, торжествуя, выложил: "А я – 15", что лично я расценил как "заткнись, и смотри в свой монитор", что я и сделал, не имея никакого желания объяснять человеку, не понимающего разницу между SOAP и REST, что такое буфер и что такое UTF-8. Вот такое вот "спасибо" я получил взамен на свой (бесспорно не работающий) код.
InputStream is = serviceUrl.openStream();
byte[] buf = new byte[20 * 1024];
int len = is.read(buf);
System.out.println("XML: " + new String(buf, 0, len));
Document doc = documentBuilder.parse(new InputSource(new ByteArrayInputStream(buf, 0, len)));
new String(buf, 0, len) -> new String(buf, 0, len, "UTF-8")
ReplyDeleteТаки +1 :)
DeleteГнать таких джонов сраной метлой из профессии!
ReplyDelete