*** ВНИМАНИЕ: Блог переехал на другой адрес - demin.ws ***

среда, 7 апреля 2010 г.

Jason Fried, David Heinemeier Hansson, "Rework"

Книга от создателей компании 37 signals и Ruby on Rails о том, как можно вести малый бизнес в IT, не разрывая зад по 10-12 часов в день, а только с 9 до 5, и при этом достойно и даже очень зарабатывать.

Jason Fried, David Heinemeier Hansson, "Rework"



Довольно пафосная книга, состоящая из мини глав, похожих на посты в блоге (эта книга и родилась из блога), но многие ее посылы стоит усвоить. С ними легче и приятнее жить, и во многом ранее скучном и нудном может появиться вдруг смысл. Также книга может подтолкнуть в мир самостоятельной работы на самого себя, например, написание shareware.

Но одна глава мне очень понравилась. Про резюме и сопроводительные письма.

Приведу ее целиком как есть и собственный вольный перевод, если кому надо.

Resumes are ridiculous

We all know resumes are a joke. They're exaggerations. They're filled with "action verbs" that don't mean anything. They list job titles and responsibilities that are vaguely accurate at best. And there's no way to verify most of what's on there. The whole thing is a face.

Worst of all, they're too easy. Anyone can create a decent-enough resume. That's why half-assed applicants love them so much. They can shotgun out hundreds at a time to potential employers. It's another form of spam. They don't care about landing your job; they just care about landing any job.

If someone sends out a resume to three hundred companies, that's a huge red flag right there. There's no way that applicant has researched you. There's no way he knows what's different about your company.

If you hire based on this garbage, you're missing the point of what hiring is about. You want a specific candidate who cares specifically about your company, your products, your customers, and your job.

So how do you find these candidates? First step: Check the cover letter. In a cover letter, you get actual communication instead of a list of skills, verbs, and years of irrelevance. There's no way an applicant can churn out hundreds of personalized letters. That's why the cover letter is a much better test than a resume. You hear someone's actual voice and are able to recognize if it's in tune with you and your company.

Trust you gut reaction. If the first paragraph sucks, the second has to work that much harder. If there's no hook in the first three, it's unlikely there's a match there. On the other hand, if your gut is telling you there's a chance at a real match, then move on to the interview stage.

Перевод:

Резюме – это недоразумение.

Всем известно, что резюме – это ерунда. Одни преувеличения. В них полно «правильных» глаголов, которые ничего не значат. В них перечисляются должности и обязанности, которые в лучшем случае сомнительны. И нет никакой возможности проверить, что за всем этим стоит. Сплошной фарс.

И хуже все то, что их очень просто сделать. Любой может написать приличное резюме. Вот почему недоразвитые кандидаты так их любят. Они могут наплодить их сотни для потенциальных работодателей. Это еще один тип спама. Им не важно получить работу у вас. Им нужна какая-то работа.

Если кто-то посылает резюме в три сотни компаний, это плохой знак. Такой кандидат не пытался ничего о вас узнать, и чем ваша компания отличается от других.

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

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

Доверяйте нутру. Если в первом параграфе все плохо, во втором шансов уже мало. Если первые три вас не зацепили, вряд ли это ваш случай. С другой стороны, если вы чувствуете, что-то тут есть – переходите к интервью.

От себя могу добавить. Всегда стоит писать cover letter, причем вдумчивые и персонализированные. В процессе их написания часто приходит понимание - "а хочу ли сам я там работать?"

Книгу после прочтения я продал назад через Амазон.

Bernard Girard, "The Google Way"

Было интересно почитать про историю Google, посему купил вот эту книгу.

Bernard Girard, The Google Way



Не могу сказать, что мне особо понравилось, хоть фактов в книге предостачно: и про самое начало, и про выход на IPO (работая сейчас в сфере finance, знаю, как обычно инвестиционные банкиры наживаются на процедуре IPO, но Гугл их сильно в этом плане разочаровал, не дав им кусок своего пирога), и про правило 20%, и про систему peer review, и про наличие технической иерархии и про многое другое.

Разок прочитать можно, но не более того. Книгу продал назад через Amazon Market Place.

Задача про гномов

Товарищ рассказал интересную задачку и был очень удивлен, что я ее не слышал.

Поймал людоед несколько гномов (количество в задаче не задается), и сказал, что завтра он всех выстроит в колонну один за другим и оденет всем на головы либо черную, либо белую шапку. Гномы будут стоять так, что каждый будет видеть шапки только тех, кто впереди (последний видит всех, кроме себя, а первый – никого). Свою собственную шапку гномы не видят. Количество черных и белых шапок произвольное (хоть все белые, хоть все черные). Далее людоед, начиная с последнего, будет каждого спрашивать, какая шапка у него на голове. Гном может ответить только одним из двух слов «черная» или «белая». Если ответ неверный, но гном съедается, иначе переходят к следующему. В процессе поедания все пока еще живые гномы слышат, что проиходит сзади, то есть хоть они и не видят товарищей сзади, но слышат – когда кого съели, а кого нет, и также их ответы.

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

Вопрос: что за стратегию придумали гномы?

Задача имеет очень красивое решение, имеющее прямое отношение к компьютерной науке.

Ответ будет позже, если кто вдруг не догадается.

пятница, 2 апреля 2010 г.

parsetInt() в JavaScript'e

Напоролся на совершенно замечательное поведение в parseInt()'e:

Я думал, что код ниже должен давать мне числа от 0 до 9:

<script>
var n = [ '00', '01', '02', '03', '04', '05', '06', '07', '08', '09' ];
for (var i = 0; i < n.length; ++i)
  document.writeln(parseInt(n[i]));
</script>

Но выводится:

0 1 2 3 4 5 6 7 0 0

И это поведение законно, так как лидирующие нули рассматриваются как признак восьмеричного числа, а 8 и 9 не являются восьмеричными знаками.

Правильно надо писать так:

<script>
var n = [ '00', '01', '02', '03', '04', '05', '06', '07', '08', '09' ];
for (var i = 0; i < n.length; ++i)
  document.writeln(parseInt(n[i], 10));
</script>
По хорошему, второй аргумент parseInt()'а, задающий систему исчисления, должен быть обязательным, чтобы исключить путаницу.

Общий виртуальный десктоп

В крупных конторах с множеством UNIX-программистов, работающих в основном через telnet/ssh/xterm, разумно сделать общий NFS-раздел, который виден всем, и также монтируется сразу на много машин. Во-первых, все имеют доступ практически ко всему в development пространстве, и во-вторых, содержимое моего home каталога всегда одно и то же на всех машинах (не надо вручную копировать файлы с машины на машину).

Минуту назад я не смог залогиниться xterm'ом из-за каких-то временных проблем в сети и попросил коллегу проверить, все ли работает. У него получилось, и он типа сказал в шутку, что жаль не может передать мне его телнетное окно.

Так вот, только родилась мысль -- а что, если все разработчики будут также "шарить" общий огро-о-о-мный виртуальный десктоп? Захотел что-то передать/показать коллеге -- просто перебросил окно в его "зону видимости".

Идея, конечно, утопичная, но красивая.

Веселые перестановки. Решение (сортировка перестановками соседних элементов)

Итак, мое решение вопроса о приведении одной последовательности к другой, когда можно только переставлять два элемента.

Нас просят привести одну последовательность (исходную) к другой (целевой). То есть логично предположить, что одна последовательность в нужном порядке (целевая), а вторая (исходная) - нет. Так надо просто отсортировать исходную последовательность "в целевую".

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

Теперь, а какой алгоритм сортировки использовать, чтобы для перемещения элементов использовать только обмен соседних элементов (функция swap())? Подходит сортировка вставками, когда на каждом шаге неотсортированный элемент последовательно "пропихивается" вниз к отсортированным. Тут как раз можно обойтись только обменом соседних элементов. Сама функция insertion_sort() является универальной и не зависит от компаратора is_less().

#include <stdlib.h>
#include <stdio.h>

void swap(int* a, int i) {
  int t = a[i];
  a[i] = a[i + 1];
  a[i + 1] = t;
}

#define N 8

const int etalon[] = { 1, 5, 7, 4, 2, 9, 8, 6 };
int from[N] = { 8, 1, 4, 2, 5, 6, 9, 7 };

void insertion_sort(int* a, int n, int (*is_less)(int, int)) {
  int i, j;
  for (i = 1; i < n; ++i) 
    for (j = i - 1; j >= 0 && is_less(a[j + 1], a[j]); j--)
      swap(a, j);
}

void print_array(const char* title, const int* a, int n) {
  int i;
  printf("%9s: ", title);
  for (i = 0; i < n; ++i)
    printf("%d ", a[i]);
  printf("\n");
}

int less(int a, int b) {
  int ia = -1, ib = -1;
  int i;
  for (i = 0; i < N; ++i) {
    if (etalon[i] == a) ia = i;
    if (etalon[i] == b) ib = i;
    if (ia >= 0 && ib >= 0) break;
  }
  return ia < ib;
}

int main() {
  int i, j;

  print_array("Original", from, N);
  insertion_sort(from, N, less);
  print_array("Converted", from, N);
  print_array("Etalon", etalon, N);

  return 0;
}

Запускаем:

 Original: 8 1 4 2 5 6 9 7 
Converted: 1 5 7 4 2 9 8 6 
   Etalon: 1 5 7 4 2 9 8 6 

Вроде работает.

Теперь что со сложностью. Принято считать, что сортировка вставками - это O(N^2) для худшего случая. Так как для сравнения элементов нам приходится искать линейно по эталонной последовательности на каждом шаге, то это еще O(N). В этоге: O(N^3).

Как вариант ускорения, можно изначально сделать отсортированную по значениям копию эталонной последовательности, и хранить не только значение, но его индекс. В этом случае поиск элемента будет уже занимать не O(N), а O(log(N)), и общая сложность будет O(log(N)*N^2).

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

Указание на эти два факта лично я счел бы на однозначно достаточный ответ.

среда, 31 марта 2010 г.

Продуктивные программисты

Не секрет, в сфере программирования работает много особей мужского пола. И также не секрет, что настоящие программисты обожают померяться п… знаниями, а конкретно, в плане чья программа круче! Лично я не являюсь крутанским мега крутаном в плане алгоритмов, и мне далеко до бойцов высшей лиги TopCoder’а, Google Code Jam’а и т.д., но алгоритмы люблю и ими интересуюсь.

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

Далее есть спецы по различным API – например, им не надо глядеть в man каждый раз при вызове socket (7), чтобы вспомнить, как там правильно подавить появление сигнала SIGPIPE и т.д.

Дальше идут знатоки проектирования. Всякие темы типа ООП, например, когда именно лучше применять агрегирование, а когда композицию и т.д.

За ними шагают апологеты тестирования – они во всех изматывающих подробностях знают, как правильно, например, написать конструктор класса, что класс было просто тестировать.

Может, есть и еще категории (если кто знает, прошу делиться).

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

У нас контора весьма крупная. Количество программистов более нескольких сотен. Есть из кого выбирать для интервьюирования. Многие не любят учувствовать в этом, но лично я люблю. По нескольким причинам. Во-первых, постоянно есть возможность глядеть на себя со стороны, так как если человек по телефону как орехи разделал все твои вопросы или поставил тебя в тупик встречным вопросом, то может ты как-то уже профессионально «засахарился»? Или если большинство коллег дали совершенно противоположную твоей оценку, может ты спрашиваешь какую-то ерунду и думаешь, что это важно? А во-вторых, есть появляется возможность быть в курсе, что вообще сейчас на рынке труда.

Теперь совсем к теме. Интересно слушать, как люди проводят интервью по телефону. Что они спрашивают, на чем делают акценты. Тут сразу становится видно, кто какой категории принадлежит человек (алгоритмист, языковед, API’ист, теоретик и т.д.)

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