пятница, 25 марта 2011 г.

Новый проект - новая команда. Какая она?

При поиске нового места работы важна компания, предметная область, компенсация, перспективы и все такое. Мне же кажется что после компании как таковой на второе место по важности в выборе нового места работы выходит команда и продукт который она делает. Чем больше компания, тем больше внутри нее команд - как следствие корреляция между компанией и успехом/неудачей конкретных разработчиков в ней исчезает. Ну за редкими исключениями, когда компания сама по себе гарантирует интересный и реальный проект (ну-у-у кроме: раз два три). В остальных же случаях мне кажется очень важным распознать проект / продукт / команду в которой открыта вакансия.

Итак, когда в команде открываются вакансии?

1. Команда расширяется революционно

При численности N набирает A ~ N сотрудников. Выделится среди коллег легко, что больше больше подходит для самостоятельных и проактивных личностей.
Если используемые технологии вам знакомы - то все карты в вам руки, так как времени заниматься вами особо ни у кого не будет. А если последовательно начнете выполнять задачи (причем даже в том ключе который нравится вам, а не тот который принят в команде) - потом может оказаться что ваш подход имеет наибольшее покрытие в коде. Таким образом вы закроете своей экспертизой большой кусок функциональности - а это всегда очень ценится.
Если технологии незнакомы - то либо вы их срочно изучаете в процессе работы (и тогда см. выше), либо долго вы там не продержитесь потому что быстро окажетесь в аутсайдерах среди новичков.





2. Команда расширяется итерационно

При численности N набирает A < < N новых специалистов. Грубо говоря вы будете одним из немногих (если не единственным) новичком. Это значит что на первых порах команда сможет уделять вам достаточно много времени чтобы обучить и поделится опытом / технологиями / традициями / лучшими практиками. Так у вас всегда будет более опытный коллега который подстрахует в случае чего - то есть ваш уровень ответственности будет невысок. Идеальное место для изучения новых технологий и/или предметной области.
В то же время выделится будет очень непросто на фоне более опытных коллег и для этого нужно будет серьезно поработать - возможно лучшим вариантом было бы найти пробел в какой-нибудь области и начать его устранять собственными силами.


3. Команда стагнирует


Численность постоянна N = N. Вы претендуете как замена ушедшего [на повышение?] члена команды. Здесь важно знать контекст.
Если команда / продукт достаточно старые и уже прошли стадию "дойной коровы" - то скорее всего она сейчас находится в состоянии, когда хорошие спецы из нее уходят. При этом поддержка все равно нужна - как следствие набираются смена. В долгосрочной перспективе - уровень экспертизы в команде падает, звезды даже если в команду и попадают - достаточно быстро ее покидают ибо стагнирующий проект им не интересен. В общем, надо быть осторожным.
Возможен конечно вариант когда участник команду ушел на повышение/уволился - а проект вполне себе перспективный. Наверное, первое от второго можно отличить вопросом "сколько лет проекту?" Возможно, вполне честно ответят на вопрос "какие дальнейшие шаги по развитию проекта?". Идеальным вариантом было бы иметь инсайдера, который сможет рассказать историю проекта с самого начала.


4. Команда регрессирует

При начальной численности N, какое-то количество специалистов уходит, новый же размер команды M <>
Ну регресс понятен - это сжатие размеров проекта - как следствие увеличение доли поддержки в общем объеме работ. Если же ушедшим был тим лид - еще и деградация (по-крайней мере на первое время) руководящей / лидирующей функции. Сложно сказать что привлекательного в такой команде кроме разве что достаточно спокойной жизни - никаких серьезных встрясок во взрослом/старом проекте не будет.

воскресенье, 23 января 2011 г.

Java: Вызов переопределенных методов в конструкторе

Подобная проблема, по-моему описывалась Блохом, но я изложу ее на русском и со своей стороны. Имеем родительский класс с полем, значение которого инициализируется в конструкторе (логика обычно простая). По правилам хорошего тона эта логика вынесена в отдельный метод. Поле после инициализации больше не используется для записи и поэтому final.
Спустя какое-то время появляется наследник класса у которого логика инициализации поля field другая. Для этого модификатор доступа меняется на protected, чтобы дать возможность наследнику заложить туда свою логику. Итак, получаем:
  1. static class Parent {
  2.         private final String field;
  3.  
  4.         Parent() {
  5.             field = createField();
  6.         }
  7.  
  8.         protected String createField() {
  9.             return "Parent-impl";
  10.         }
  11.  
  12.         @Override
  13.         public String toString() {
  14.             return getClass().getSimpleName() + field;
  15.         }
  16.     }
  17.  
  18.  
  19.     static class Child extends Parent {
  20.         private final String leftPart, rightPart;
  21.  
  22.         Child(String left, String right) {
  23.             leftPart = left;
  24.             rightPart = right;
  25.         }
  26.  
  27.         @Override
  28.         protected String createField() {
  29.             return leftPart + rightPart;
  30.         }
  31.     }
  32.  
  33.     public static void main(String[] args) {
  34.         System.out.println(new Child("AB", "CD"));

По результатам кажется что main должен вернуть ABCD. Однако это не так. Проблема в том, что в логике переопределенного метода createField() не должны участвовать состояния как наследника, так и родителя. Проще говоря можно использовать только константы (statiс final), хотя и с ними надо быть осторожным. Почему? Дело в том, что на момент вызова метода поля его + родительские поля создаваемого экземпляра еще не до конца созданы. В данном примере в момент вызова Child.createField() поля leftPart и rightPart ещё не проинициализированы (хотя они и final) и равны null.

Как теперь это исправить?
Есть несколько способов, я предпочитаю работать вместо поля с методом и как следствие вынести инициализацию в "ленивую" секцию. Как-то так:
  1. static class Parent {
  2.         private final String field;
  3.  
  4.         Parent() {
  5.             field = createField();
  6.         }
  7.  
  8.         private String createField() {
  9.             return "Parent-impl";
  10.         }
  11.  
  12.         protected String getField() {
  13.             return field;
  14.         }
  15.  
  16.         @Override
  17.         public String toString() {
  18.             return getClass().getSimpleName() + getField();
  19.         }
  20.     }
  21.  
  22.  
  23.     static class Child extends Parent
  24.  
  25.     {
  26.         private final String leftPart, rightPart;
  27.  
  28.         Child(String left, String right) {
  29.             leftPart = left;
  30.             rightPart = right;
  31.         }
  32.  
  33.         @Override
  34.         protected String getField
  35.                 () {
  36.             return leftPart + rightPart;
  37.         }
  38.     }
  39.  
  40.     public static void main(String[] args) {
  41.         System.out.println(new Child("AB", "CD"));

вторник, 18 января 2011 г.

GSM 5G что хотелось бы иметь

Что бы я добавил в стандарт сотовой связи GCM 5G.


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

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


3. Способность GSM модулям телефонов связываться напрямую друг с другом если они в пределах досягаемости одной соты. Такой peer-2-peer для соседей. Телефон тогда бы отсылал на соту только тарификационные данные - поговорил с абонентом таким-то столько-то минут и секунд. Это бы решило проблему связи в большой толпе когда все друг другу звонят. Ну и конечно снизило нагрузку на соты в какой-то мере.

4. В адресной книге - статусы абонентов как в аське / скайпе. Чтобы не звонить и слышать "абонент временно недоступен" - видеть сразу что человека нет в сети. В статусе также можно было бы писать имя оператора, местоположение, в роуминге ли абонент или нет, ну и много чего еще интересного.

5. Ну и то, что уже наверняка есть на Android - автоподключение к халявным Wi-Fi сетям поблизости. Иметь базу городских точек с бесплатным Wi-Fi и просто определать их по местоположению.

четверг, 30 декабря 2010 г.

Ленты RSS: фильтрация и полное содержание

Копался и сортировал свои подписки (которые RSS). Попутно решил пару сопутствующих проблем. Хочу поделиться.

Фильтрация

Есть ленты, в которых нет разбиения на какие-либо подразделы / темы. Собственно, почти все они такие. А если тематизация и существует, то достаточно строгая (например, можно подписаться на новости "Политика", но нельзя на новости "Путин" или "Путин или Медведев"). Как следствие, приходится либо просматривать большое количество обновлений такой ленты, либо отказаться от нее совсем (я выбрал второе - придерживаюсь принципа, что рассылка должна иметь большую точность).

Альтернатива - настроить правила подписки самому или фильтровать общий канал на основе своих фильтров. Для решения задачи прошерстил с десяток сайтов, вот что получилось:

  1. http://re.rephrase.net/filter  - просто и со вкусом. Скармливаем оригинальный фид, задаем логическое правило пропуска фидов - и вуаля! (новости согласно моим музыкальным вкусам). Проблема только одна, правда серьезная - фильтрация по русским словам не работает. Отсюда второй ресурс.
  2. Yahoo.Pipes - вагон и маленькая тележка сил и средств по работе с лентами (и не только). Можно делать действительно всё и это достаточно просто. Правда, требует регистрации, но получившийся фид может быть общедоступным (моё Хабра-избранное). Странно, что Google ещё подобный набор не добавил в свой feedburner и/или reader. 

Было еще много других, но их с легкостью выдает поисковик по фразе "rss filter". Они либо не работали с русскими фидами, либо портили html-содержание ленты, либо просто мне не понравились.

Полнотекстовые RSS-обновления

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

Ресурсы, которые решают эту проблему обычно выкусывают содержимое статьи из соответствующей html-страницы. Нужно только дать ссылку (чуть ли не в XPath) на элемент в HTML-элемент в дереве.

  1. feedex.net - принцип "нажал-и-готово". Распознает дерево сам, поэтому частенько глючит. Мне подошел только в половине случаев (удачный пример).
  2. RSS-farm - кажется один из первых отечественных ресурсов для мануального создания полнотекстовых лент. Требует установку .NET 3.5
  3. Readbox - проект хабраюзера. Делает тоже, что и RSS-farm, но требует наличия только Firefox + Firebug (плагин к лисе). Им я смог докрутить оставшиеся ленты до их полнотекстовой версии (тот же удачный пример).


среда, 22 декабря 2010 г.

Deadlock на МКАДе

Очень злободневная тема с московскими (да и не только) пробками. Не высказался только ленивый. А так как я не ленивый, то тоже черкану пару строк. Но интересна конечно не столько сама проблема, сколько её решение. Если оно конечно есть. Взять к примеру такую простую вещь, как пересечение дорог. Выясняется, что неверно "развязанные" пересечения сводят на нет и ширину дороги, и её качество. С какой бы скоростью и во сколько бы рядов поток не двигался - ему всё равно стоять на/в/перед перекрестком.

Для визуализации воспользуюсь OpenTTD. Здесь и далее одна ж/д колея может рассматриваться как от 1 до N полос для автотранспорта. Важно направление. Итак, самый примитивный перекресток с 4-мя светофорными парами:

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

Улучшаем конструкцию. Цель - сделать прямой проезд в пересекающихся направлениях неблокирующим друг друга. Блокирующим может быть только поворот направо/налево. Получаем текущие развязки на МКАД в виде 88:

Великолепно работает если основной поток идет по прямым направлениям или, максимум, поворачивает направо. Поворот налево все также сложен - он потенциально блокирует направление с которого сворачивает. Более того, очень легко достижим deadlock (4 поезда поворачивают налево одновременно).

Причем раскрутить такой deadlock очень тяжело - "отвести" в сторону какое-нибудь транспортное средство невозможно - ему в затылок "дышит" другое... Кроме того, поворот налево достаточно трудоемкий - это фактически разворот на 270 градусов вместо 90. Т.е. требует сильного снижения скорости или достаточной площади для большого радиуса. Также при таком повороте в 2х случаях из 4х требуется еще и "взбираться" на уровень вверх...

Эти проблемы решены в новой версии предыдущей развязки. Суть та же, но поворот налево теперь 90-градусный и располагается на том же уровне, что и основная дорога до пересечения. Правда, для пересекающихся направлений теперь нужны туннель (одно направление) и мост (другое).

Под мостами развязка выглядит так:

Смотрится немного громоздко, но запас прочности для deadlock'а теперь больше. Сам он теперь не образуется - а только с помощью внешних факторов - например поломки (на примере поезд на Северо-Запад сломался и перекрыл все повороты налево).

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

Это была развязка уже на трех уровнях. Что же будет если использовать 4? Возможно ли сделать развязку, в которой поворот налево не пересекается с другим поворотом налево? Да:

Или вот так с прозрачными мостами:

Требуется 4 туннеля и 4 моста. Самый дорогой вариант (что неудивительно). Проезд в одном направлении идет практически по прямой (и на том же уровне). На другом направлении - тоже по прямой, но на -1 уровне. А вот для поворота налево нужно сначала "взобраться" на +1 уровень, на котором проехать под двумя мостами, "взобраться" на другой мост и затем съехать с моста и с холма до начального уровня. Поворот налево снова 90-градусный, что есть несомненный плюс.

Как видно, сама развязка с точки зрения транспортного средства представляет из себя сначала развилку, а потом слияние. Примерно так это работает:

А так это уже делают в реале:

Ничего, когда-нибудь и у нас так будет.

P.S. для тайкуноводов. Как построить последнюю развязку - алгоритм: