суббота, 17 апреля 2010 г.

[life.flame] LetItBit по-белоруски… А не спампаваць ли мне пару-тройку файлов? :/

Сервис LetItBit по моему IP-шнику определил, что я из Белоруссии и заговорил со мной по-белоруски:

Я долго не мог врубиться в термин “Спампаваць”…

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

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

Лично для меня белорусский язык – как красная тряпка. Поэтому, когда ко мне какой-то иностранный ресурс обратился по-белоруски, то я был, мягко говоря, шокирован.

А вот слово “спампаваць”, определенно войдет в мой обиход. Буду им что-нибудь обзывать.

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

[prog.work] (не)большой производственный лытдыбр

Последние три дня прошли в приключениях при портировании большого C++ного проекта под Linux. Точнее говоря, приключения были не столько с портированием, сколько с Linux-ом. Хотя и с портированием было интересно и поучительно :)

Linux я себе на “голое железо” зарекся ставить уже очень давно. Поскольку работаю на ноутбуках, а Linux-ы на ноутбуках – это отдельная песня. Поэтому на ноутбуки я ставлю Windows с родными драйверами от производителей, а Linux-ы держу под виртуалками. Очень удобно.

Последний Linux, который у меня был – это Kubuntu 8.04. Но я его не запускал, наверное, с прошлого года. Как пересел на новый ноутбук, так даже виртуальную машину не устанавливал. А тут понадобилось и, как всегда, в условиях цейтнота :) Поэтому поставил себе VirtualBox 3.1.6. Новый VirtualBox старый образ Kubuntu поднял, но оказалось, что я там чего-то начал переделывать, но не доделал и оставил систему в полуразобранном состоянии. Ну и чтобы не заниматься восстановлением старой системы, решил поставить себе Kubuntu 9.10.

К сожалению, решил делать я это в офисе, где доступ в Интернет через прокси. А инсталлятор Kubuntu, как мне показалось, этого очень не любит, даже не смотря на то, что параметры прокси в инсталляторе выставить можно. Поэтому Kubuntu стала как-то криво. Вроде бы и работала, но с помощью шаманских плясок и бубнов. Например, захотел я заменить Ruby 1.8 на Ruby 1.9, проинсталлировал пакет ruby1.9, но ruby не запускался. Хотя KPackageKit упорно показывал, что пакет есть. Какие-то странные вещи были с g++ – изначально в системе его не было, пришлось ставить пакет g++-4.4.1. Поставил, но g++ не запускался.

Случайно выяснилось, что все устанавливалось, но под странными именами: ruby назывался не ruby, а ruby1.9 и запускать его нужно было как ruby1.9. Аналогично и с g++ – вместо команды g++ была команда g++4.4. Но апофеозом всего этого стала попытка проинсталлировать rubygems через KPackageKit и apt-get. KPackageKit просто говорил, что нет зависимостей, но даже не сообщал, каких именно. Apt-get указывал, что нет RDoc, Irb, и еще чего-то, вплоть до readline5. А вот где взять readline5 я вообще не смог понять, поскольку в системе стоял readline6, а следов readline5 не было вообще.

Кое как настроил все это дело вручную, сказав много матерных слов в адрес самых разных людей :) Процесс портирования начался. Но вскоре началась новая беда – стоило чему-то произойти с сетевым окружением на host-машине, как guest-система в виртуалке переставала видеть svn-репозиторий. А потом и еще одна напасть – виртуальная машина не всегда стартовала при перезагрузках. То VirtualBox упадет, то сам Kubuntu где-то на середине загруки повиснет. В общем, хотел все сделать за один день, но пришлось отложить на следующий.

А на следующий день, с утреца, посмотрев на все это безобразие, решил установить Kubuntu заново. И правильно сделал. Повезло, что инсталляцию я проводил дома, где нормальный Интернет без проксей. Поскольку при инсталляции Kubuntu что-то увлеченно качала из Интернета и потом все встало как надо. И KPackageKit работает, и пакеты нормально устанавливаются, и с сетью проблемы нет, и при перезагрузках ничего не падает. Лепота, в общем.

Впечатления от Kubuntu 9.10 самые благоприятные. Аналогично и от VirtualBox-а. Тем, кто будет ставить Linux под VirtualBox-ом в первый раз, маленький совет: после установки Linux будет работать в разрешении 800x600. Чтобы его увеличить, нужно подмонтировать в качестве CD-ROM-а образ VBoxGuestAdditions.iso из VirtualBox-а, а потом запустить оттуда в guest-системе соответствующий файлик (VBoxLinuxAdditions-x86.run). После этого и разрешение в Linux-е станет больше, и появится очень удобная интеграция мыши.

После того, как Kubuntu нормально задышал, начался, собственно, процесс портирования моего большого проекта. В качестве компилятора использовался GCC 4.4.1. Был приятно поражен тем, что GCC сейчас анализирует форматные строки в sprintf-е и предупреждает, если спецификатор формата не соответствует переданному типу значения (попробуйте, например, указать “%02d” и передать значение long int).

Нашел у себя один серьезный баг, который сидел в программе не пойми сколько времени, и никогда не проявлялся ни под VC++ 7.1, ни под GCC 3.4.*. Но основная часть проблем заключалась в двух вещах:

  1. Для функций из стандартных C-шных библиотек, вроде sprintf и strcmp, не подключались соответствующие заголовочные файлы. Т.е. когда работаешь под VC++, то <cstdio> загружается где-нибудь в <iostreams> или <string>, поэтому функция sprintf оказывается в области видимости и без явной загрузки <cstdio>. А вот в GCC 4.4.1 стандартные заголовочные файлы загружают себя по другому и компилятор ругается на то, что символ sprintf не определен.
  2. Я постоянно забываю при определении своих классов исключений писать в деструкторе throw(). VC++ 7.1 это фиолетово, а вот GCC ругается, т.к. у std::exception деструктор имеет спецификатор throw().

В общем, сильно пожалел о том, что не делал периодического портирования этого проекта под Linux в течении последнего года. Раньше я это делал – и по производственной необходимости, и просто так – для профилактике. Поэтому такие ошибки выявлялись быстрее и в меньшем количестве. А тут их сразу несколько десятков, и все в разных модулях из разных подпроектов… Так что совет: если есть возможность, то гоняйте свои проекты под разными компиляторами, от разных производителей. C++, конечно, переносим на уровне исходников, но за эту переносимость приходится платить.

Еще одна штука, связанная с портированием. Меньше всего возни было со сторонними проектами, для которых мы сами сделали обвязки для нашей системы сборки и поместили их исходники в свой репозиторий. Такие проекты просто разворачивались самим svn через свойство svn:externals, а потом естественным образом компилировались в рамках всего большого проекта. А вот с libiconv и openssl-ем пришлось потрудится – ставить их отдельно и компилировать вручную (кстати, не понятно, почему в Kubuntu не оказалось пакетов для этих библиотек – чего-нибудь вроде libiconv-dev, openssl-dev). Так что еще один раз убедился в том, насколько удобно держать точные версии всех зависимостей в собственном репозитории.

Кстати еще о зависимостях и больших проектах. Сейчас нужно раздербанить проект на несколько разных частей, каждая из которых получит самостоятельное развитие. Плюс, в дебрях этого проекта скопилось несколько удобных и почти универсальных вещей, которые следует оформить в виде повторно-используемых самостоятельных компонентов. Т.е. большой проект начинает выглядеть как сборник не сильно связанных между собой пакетов. Вести их все в рамках одной ветки репозитория уже не кажется разумным. Хочется каждый из них выделить в отдельную ветку. И каким-то образом прописать между ними зависимости. А здесь уже напрашивается и следующий шаг – какая-то система пакетов, с манифестами и GUI-инструментом для выбора нужного их сочетания. Нестареющий велосипедостроитель внутри меня настойчиво уговаривает взяться за реализацию такой штуки :) Но, может быть уже есть готовые кроссплатформенные решения для C++? Вроде бы в CMake есть что-то связанное с пакетами – может кто-то знаком?

Еще есть небольшие подвижки на SObjectizer-овском фронте. Подружил SObjectizer 4.4.0-b6 с ACE-5.7.*. Оказалось, правда, что в ACE-5.7 нет проектных файлов для VC++7.1, поэтому с ACE 5.7.* SObjectizer будет работать только в VC++8 и VC++9. Но пока не удалось решить проблему с рестартом дефолтного реактора. Зараза, не работает с асинхронными сокетами при перезапуске SObjectizer Run-Time. И не понятно пока, мой ли это косяк, или же в ACE-овском реакторе есть баги. Буду разбираться. Получится или нет – не знаю, но хочу к концу апреля выкатить очередной патч для SObjectizer, чтобы на ACE 5.6.* не сидеть больше.

На неделе скачал себе ISO-шный образ с VisualStudio 2010 Express Edition. В котором C++ный компилятор с частичной поддержкой C++0x. Но не было времени поставить. А хочется уже познакомиться лично с лямбдами и rvalue references. Тем более, что на днях и GCC 4.5.0 вышел. Так что в двух мейнстримовых С++ных компиляторах лямбды уже есть, а у меня были связаны с ними большие надежды в плане сокращения многословности для SObjectizer-5. Еще хочется поскорее с VC++10 разобраться, чтобы в MxxRu новый тулсет добавить – vc10, в компанию к vc7, vc8 и vc9. Нужно только время найти для этого :/

Такие дела. В планах еще две-три заметки для блога по поводу моих впечатлений от Java. Stay tunned, в общем ;)

[prog.work] Mxx_ru и счетчик на Gemcutter: рубеж в 1000 взят!

С ноября прошлого года статистику инсталляций RubyGem-ов (через команду gem install) ведет сайт gemcutter.org. И вот сегодня сделал для себя приятное открытие: общее количество загрузок Mxx_ru по показателям Gemcutter-а превысило 1000. С чем себя и поздравляю :)

На самом деле я хочу поблагодарить всех пользователей Mxx_ru – спасибо вам большое!

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

В ближайшее время хочу добавить в Mxx_ru тулсет для Visual C++ 10, так что версия 1.5.1 должна появится вот-вот (ну т.е. как только, так сразу).

Еще хочется сделать объявление переменной среды MXX_RU_CPP_TOOLSET необязательной. Т.е., чтобы человек сделал gem install и все, больше ему ничего не нужно. В принципе, под Linux-ом можно смело считать, что используется тулсет gcc_linux. А вот под Windows сложнее – нужно как-то анализировать доступный компилятор – а это могут быть и разные версии VC++, и GCC. Но, наверняка, что-то можно придумать.

Еще хочется улучшить поддержку больших проектов. Например, если я компилирую какой-то проектик с “тяжелыми” зависимостями (вроде ACE), то утомляют постоянные проверки необходимости перекомпиляции всего и вся. Сейчас в Mxx_ru есть ключик –mxx-cpp-1, но это не совсем то. Хотелось бы либо запретить компиляцию конкретных подпроектов в командной строке, либо же ввести в Mxx_ru какую-то эмпирику, чтобы анализировалась дата/время изменений в каталоге подпроектов. Но чтобы в типичных сценариях тяжелые зависимости компилировались только один раз, а потом перестраивались лишь при изменениях настроек и/или полных ребилдах.

Еще хотелось бы добавить в Mxx_ru какие-то заготовки для поддержки сторонних проектов. Например, какой-нибудь libiconv под Linux собирается через обычную последовательность из config;make;make install. Было бы полезно, если бы в Mxx_ru была возможность поддержки этой последовательности, чтобы не приходилось много вручную напильником работать при продключении проектов вроде libiconv и pcre в собственные проекты.

Так что Mxx_ru еще не мертв. Скорее он пока собирается с силами для нового рывка :)

четверг, 15 апреля 2010 г.

[prog.flame] Попрограммировал на Java, делюсь впечатлениями. Часть II. Какую бы Java хотелось иметь (минимальный вариант).

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

Здесь описываются, на мой взгляд, минимальные изменения языка. Т.е., при желании, их можно было бы реализовать в препроцессоре (что-то вроде старого Cfront-а), который бы генерировал обычный Java-исходник. В следующей заметке я попробую описать более серьезные изменения.

Итак, в первую очередь в Java мне нужны typedef-ы. Чтобы вместо:

private Map<com.intervale.someprj.customproto.Uid, com.intervale.someprj.customproto.Pdu> parseStream(java.nio.channels.ReadableByteChannel from) {...}

public void handleStreamContent(java.nio.channels.ReadableByteChannel from) {
   Map<com.intervale.someprj.customproto.Uid, com.intervale.someprj.customproto.Pdu> pdus =
      parseStream(from);
   ...
}

можно было бы написать:

typedef Map<com.intervale.someprj.customproto.Uid,
            com.intervale.someprj.customproto.Pdu>
      PduByUidContainer;
typedef java.nio.channels.ReadableByteChannel ByteChannel;

private PduByUidContainer parseStream(ByteChannel from) {...}

public void handleStreamContent(ByteChannel from) {
   PduByUidContainer pdus = parseStream(from);
   ...
}

Использование typedef-ов не только уменьшает объем кода, но еще и скрывает часть деталей реализации. Так, если со временем заменить в определении ByteChannel тип ReadableByteChannel на что-нибудь другое, то изрядную часть кода даже не придется переписывать (про автоматические рефакторинги в Java я в курсе, но это несколько другое).

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

В-третьих, в Java очень не хватает перегрузки операторов. Не знаю, возможно ли в Java повторить C++ный синтакис перегрузки операторов (т.е. запись вида operator+ или operator<<), но вполне подойдет и подход языка D: функции со специальными именами. Чтобы можно было написать:

class TrickyByteStream {
   ...
   public TrickyByteStream opLShift(byte b) {...}
   public TrickyByteStream opLShift(byte[] a) {...}
   public TrickyByteStream opLShift(short s) {...}
   ...
}

TrickyByteStream bs = new TrickyByteStream();
bs << byteValue << byteArray << shortValue << intValue;

В совокупности со свободными функциями перегрузка операторов может дать важный эффект – возможность расширять функциональность чужих классов. Например, я написал TrickyByteStream, а кто-то написал собственный класс UserInfo. И сделал оператор сдвига UserInfo в TrickyByteStream в виде свободной функции. В результате, объекты UserInfo смогут сохраняться в TrickyByteStream точно так же, как если бы я сам встроил в класс TrickyByteStream эту функциональность.

В-четвертых, очень бы хотелось видеть в Java автоматический вывод типов для переменных. То, что есть в C# 3.0, что добавили в C++0x с помощью ключевого слова auto и то, что планируется в Java 7 (если мне мой склероз не изменяет). Все-таки двадцать первый век на дворе. Хочется уже просто писать:

public void handleStreamContent(ByteChannel from) {
   auto pdus = parseStream(from);
   ...
}

В-пятых, в Java не хватает lambda-функций. Анонимные классы, по сути, тоже самое и есть, но уж очень большой у них синтаксический оверхед :) А еще было бы здорово, чтобы в качестве lambda-функций можно было передавать свободные функции. Вот это было бы действительно удобно – нужно отсортировать список – вызываешь java.util.Collections.sort и вместо объекта-компаратора передаешь свободную функцию. Эффект такой же, как от использования объектов-компараторов, но телодвижений и строчек кода в программе будет меньше.

В-шестых, в Java следует заменить checked exceptions на спецификатор nothrow. Т.е. вместо того, чтобы тупо перечислять исключения, который может выбросить метод (что, в конце-концов ведет к простым конструкциям вида throws Exception или throws MyLibraryBasicException), нужно просто явно говорить – вот здесь исключений не будет (зуб даю!), а здесь – сколько угодно. Поскольку тема эта большая и говорить о ней можно много, то не буду ее развивать. Скажу только, если если делать препроцессор в обычную Java, то спецификатор nothrow не должен вызвать затруднений. Те методы, которые не имеют nothrow транслируются в методы со спецификацией throws Exception. Методы с nothrow транслируются в методы без спецификации throws.

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

В-седьмых, в Java необходимы что-то вроде using из C# или scope(*) из D. Писать очистку ресурсов в случае исключения в блоках finally не правильно, поскольку она оказывается далеко от места захвата ресурсов. Раз уж C++ных деструкторов, которые гарантированно вызываются при выходе из области видимости, нет, то помогли бы специализированные средства. Вряд ли конструкцию using из C# удалось бы сделать через препроцессинг – ведь требуется еще и поддержка идиомы IDisposable в стандартной библиотеке. А вот конструкция scope(exit) из D, да еще в сочетании со свободными функциями и lambda-функциями, пришлась бы в тему:

auto cf = (JmsConnectionFactory) context.lookup(connectionFactoryFromJndi);

auto destination = (JmsDestination) context.lookup(destinationFromJndi);

auto connection = cf.createConnection();
scope(exit) { safeCloseConnection(connection); }

auto session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
scope(exit) { safeCloseSession(session); }

auto producer = session.createProducer(destination);
scope(exit) { safeCloseProducer(producer); }

Для сравнения, вот так бы этот код выглядел через finally:

JmsConnectionFactory cf = null;
JmsDestination destination = null;
Connection connection = null;
Session session = null;
MessageProducer producer = null;
try {
   cf = (JmsConnectionFactory) context.lookup(connectionFactoryFromJndi);

   destination = (JmsDestination) context.lookup(destinationFromJndi);

   connection = cf.createConnection(); 

   session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); 

   producer = session.createProducer(destination);
   ...
} catch( ... ) {
} finally {
   if(null != producer)
      safeCloseProducer(producer);
   if(null != session)
      safeCloseSession(session);
   if(null != connection)
      safeCloseConnection(connection);
}

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

Еще одна штука меня раздражала и которую, имхо, следует устранить. Допустим, есть пакет com.intervale.customproto. В котором есть класс Pdu. И в котором есть класс BasicPduFormatter:

class BasicPduFormatter {
   public String format(Pdu what) { ... }
}

Так вот, если я в другом пакете захочу унаследоваться от BasicPduFormatter и перекрыть его метод format, то я не смогу работать с классом Pdu, пока не сделаю его импорт к себе в пакет. Т.е. я наследуюсь от BasicPduFormatter (т.е. он импортируется в мой пакет), но необходимое ему определение Pdu автоматически не импортируется. Что не правильно, я считаю. Да и исправить это, имхо, не так сложно.

По-минимуму, пожалуй, и все. Существуй такой язык для JVM здесь и сейчас, я бы сильно задумался, а стоит ли дальше оставаться на C++ ;)

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

[prog] Проверка моего прогноза относительно Scala 2.8.0

В конце января 2010 вышла первая бета-версия Scala 2010, о чем я написал в своем блоге. Там же я сделал прогноз о том, что Scala 2.8.0 стабилизируется только месяцев через 5-6. И вот, сегодня ночью было объявлено о выходе первого релиз-кандидата. Т.е. прошло 2.5 месяца и бета превратилась в релиз-кандидат. Еще через месяц стоит ожидать стабильного релиза, а потом еще один-два корректирующих релиза (2.8.1 и 2.8.2) – и мой прогноз относительно 5-6 месяцев может сбыться :)

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

[prog] Еще одна презентация про использование Erlang: Макс Лапшин о Erlyvideo

Сама презентация:

Её обсуждение в ЖЖ автора: http://levgem.livejournal.com/285670.html

Из того, что там изложено я не могу спорить только с тем, что в Erlang есть возможность “горячей” замены кода “из коробки”.

Есть так же несколько вещей, которые я понять не могу:

  • ладно в C++ной программе легко пройтись по чужой памяти и уронить таким образом все приложение. Но зачем подобные страшилки о Java рассказывать?
  • зачем в приложениях на Erlang вручную управлять памятью?

А еще мне очень не нравится, когда между C и C++ ставят знак равенства (во всей презентации речь идет то об C++, то о C, как будто это одно и то же).

PS. И нефиг серьезные вещи на Objective-C делать ;)

вторник, 13 апреля 2010 г.

[prog.flame] Попрограммировал на Java, делюсь впечатлениями. Часть I. Общие слова.

Несколько недель назад довелось попрограммировать на Java, а до этого в последний раз я писал на Java 2001-м году. Впечатлений много. Нашлось время часть из них описать.

Впечатление первое. Теперь я понимаю, почему Java-программисты такое большое значение придают IDE. Без продвинутой IDE в Java очень сложно. Сам язык такой многословный, что одно и то же в нем приходится повторять по нескольку раз. Например, если мне нужна локальная переменная типа StringBuilder, то имя StringBuilder мне придется писать дважды:

StringBuilder sb = new StringBuilder();

Тогда как в C++, за счет такой вещи, как создаваемые на стеке переменные, объявление требовало бы всего одного имени типа.

Другое проявление многословности и очень существенной помощи IDE – это директивы import. Насколько я понял, сейчас уже не принято импортировать все содержимое пакета. Т.е. вместо:

import javax.naming.*;

модно стало писать так:

import javax.naming.Context;
import javax.naming.InitialContext;

Не могу себе представить, как без помощи IDE делать import отдельных классов.

Еще одна сторона многословности: checked exceptions. Даже если оставить за рамками данной заметки сам смысл существования checked exceptions, то перечисление исключений в собственных методах, а так же перехват чужих исключений для того, чтобы преобразовать их в собственные исключения – все это, мягко говоря, тупая и механическая работа, которая с удовольствием отдается на откуп IDE.

Впечатление второе. Однопарадигменность языка после C++ и Ruby сильно… как бы это сказать… огорошивает. В C++ у  меня есть выбор – использовать ООП или старый добрый структурный подход, или же сделать решение через шаблоны и функторы. А в Java нет такого многообразия. Там есть только кастрированный ООП (по сравнению с тем же C++, не говоря об Eiffel или Ruby/Python). И все. Если тебе нужно что-то простое сделать – делай это через наследование. Даже если это потребует в полтора-два раза больше строк кода. Все равно делай через наследование. И как бы лично меня не раздражала такая ограниченность, я думаю, что именно в ней и запрятана сила Java. Но об этом позже.

Впечатление третье. По сравнению с тем языком, который я изучал и эпизодически использовал в конце девяностых, современная Java стала приятнее. Autoboxing, generics, цикл for для обхода контейнеров – вроде бы мелочи, но с ними Java стала сильно удобнее. Просто удивительно. Желание продолжить программировать на Java у меня, разумеется, не возникло, но плеваться приходилось меньше :)

Ну а теперь впечатление четвертое, оно же главное. Появилась у меня еще одна версия ответа на вопрос “В чем сила брат Java?”

Продвинутые IDE и огромное количество библиотек для Java – это да, этого у Java не отнимешь. Но это, я бы сказал, верхушка айсберга. Это следствие, на мой взгляд, главного качества языка – его примитивизма и сильно ограниченного множества выразительных средств. Да, та самая однопарадигменность на основе кастрированного ООП и есть главная положительная характеристика Java. Именно она позволила Java стать одним из самых успешных и широко применяемых языков программирования в истории.

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

Определенно, язык Java создавался для того, чтобы код одного разработчика был как две капли воды похож на код другого разработчика. И скудость возможностей языка этому очень сильно способствует – какие бы оригинальные идеи не рождались в голове программиста, после реализации они все равно будут сильно “усреднены”. Именно поэтому на Java не создают аналогов Boost.Lambda – язык просто не позволяет разработчику заниматься подобной ерундой.

В заключение выскажу пятое впечатление, пророческое. Поскольку от мира Java я держался в стороне, то по-наивности считал, что у Scala есть шансы со временем стать главным мейнстрим языком на платформе JVM. Оказалось, что нет шансов. Ничего Scala не светит в этом смысла.

Перед тем, как мне пришлось засесть за Java, я пытался читать книгу Programming Scala издательства O’Reilly. Я прочел почти 100 страниц книги, но так и не понял, как написать на Scala что-то сложнее “Hello, World” и очередного факториала. И это я – профессиональный программист с 16-ти летним стажем, который когда-то Scala изучал. Не могу себе представить, чтобы Scala успешно освоил какой-нибудь чайник, которому нужно быстро написать что-то специфическое для себя.

Тогда как из 100 страниц нормальной книги по Java можно не только узнать почти все о самом языке, но и много всего полезного о наиболее употребительных частях JDK. Т.е. я вполне могу себе представить студента-второкурсника, который за пару месяцев осваивает Java, после чего успешно подрабатывает в какой-нибудь аутсорсинговой шараге. Я могу себе представить какого-нибудь физика, которому нужно написать какую-нибудь программку для сохранения результатов эксперимента в БД. Или я сам за два-три дня узнал о Java достаточно, чтобы написать библиотеку для поддержки TLV-формата.

Это все потому, что Java, как язык программирования, налагает минимальные требования на новичков. А потом ее возможностей (с учетом IDE и библиотек) хватает с головой. От добра добра не ищут :)

Поэтому Scala не будет заменой Java. Уж если что-то и станет заменой Java на JVM, так это какой-то очень-очень близкий Java язык, который добавит в Java совсем немного новых хороших вещей (как это произошло с for-ами и generic-ами). Но при этом не будет тянуть груз синтаксической совместимости со старыми версиями Java. Но о том, какой лично мне хотелось бы видеть “новую Java” – в следующий раз.

понедельник, 12 апреля 2010 г.

[prog.work] “Что? Зачем?” vs “Как? Почему?”

На работе потихоньку трансформируюсь из разработчика в эдакую помесь тимлида и архитектора. В связи с чем стал замечать, что основными вопросами у меня становятся “Что?” (“Что разрабатывать?”) и “Зачем” (“Зачем разрабатывать именно это?”). Тогда как раньше меня волновали вопросы “Как?” (“Как это запрограммировать?”) и “Почему?” (“Почему именно так?”). Специфика работы меняется. Сейчас, чтобы кого-то озадачить, нужно точно знать, что именно я жду от него. Иначе озадачивание не произойдет :)

Подозреваю, что у менеджеров доминирующими вопросами являются “Кому?” (“Кому эту задачу поручить?”) и “Когда?” (“Когда задача будет решена?”). Впрочем, выяснять так это или нет, пока не хочется. Не чувствую в себе желания быть менеджером :)

воскресенье, 11 апреля 2010 г.

[life.photo] “Птичьи” фотографии Вадима Морозова

Фотограф Вадим Морозов привлек мое внимание потрясающими снимками птиц.

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

Вот серьезная птица:

Пардону просим

Па берегись

Хмурое небо

Обнимая небо

Реверс

Закат

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

Сурьёзный разговор

Посадобль!

[prog.wow] Гослинг ушел из Oracle!

Новость из разряда “ох*еть просто”: Джеймс Гослинг, тот самый создатель Java, уволился из Oracle!

Произошло сие событие 2-го апреля, а написал он об этом своем блоге позавчера.

Фиг знает, какую роль в разработке Java он играл в последние годы, и играл ли вообще. Так что не имеет смысла строить какие-либо предположения о том, что будет с Java после его ухода. Однако думаю, причина ухода наверняка связана с планами Oracle на будущее Java.

Но все равно… Сложно представить себе Java без Гослинга. Грустно стало почему-то.

[life.work] О графике работы во время авралов, причинах авралов и вообще…

Очередная заметка, которая начиналась как комментарий, но быстро доросла до самостоятельного блог-поста. Отвечаю на вопрос ув.тов.Alex к предыдущей заметке:

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

В 2004-м график был приблизительно такой: подъем в 4:45, потом работа до 8 (как раз пока жена и дочка спали), потом завтрак и все остальное, где-то с 10:00-11:00 до 19:00-20:00 работа в офисе.

Сейчас уже здоровье не то. Поэтому подъем часов в 6, потом 2 или 3 часа работы, завтрак. Если нужно быть в офисе с утра, то еду в офис после завтрака. Если есть возможность поработать дома, то где-то до 13:00-14:00 работаю дома, обедаю и еду в офис. В офисе нахожусь до 19:30-20:00. Благо у нас город маленький, и до работы я добираюсь из дома за 35-40 минут.

Нужно здесь отдельно сказать, что пребывание в офисе – это рабочее время, но оно далеко не всегда полностью посвящается именно работе. Офис – это целая куча отвлекающих факторов. Даже если тебе нужно сделать большой объем работы, нельзя в офисе зашиться в свой угол и ни с кем не разговаривать. Офис – это коллектив, в коллективе нужно поддерживать хорошие отношения. Просто пообщаться с кем-то из коллег на отвлеченные темы минут 30-40 в день – это не столько отвлечение, сколько инвестиции в нормальный социальный климат. Но, с другой стороны, напряженная работа требует полной концентрации и отсутствия раздражающих факторов. Поэтому, если мне предстоит запрограммировать большой и/или ответственный кусок, то я стараюсь делать это дома, с отключенными средствами коммуникации. В прошлом году был случай, когда я неделю в офисе не появлялся, чтобы успеть закончить важный кусок к намеченному сроку.

Отбой – когда как. Если есть интересный фильм или идет матч Лиги Чемпионов, то где-то в 23:30-24:00, если нет – то в районе 23:00.

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

В отпуске был уже не помню когда.

По натуре я жаворонок, довольно ярко выраженный. Но, жизнь показала, что могу сильно изменять своим привычкам. Когда родилась дочка, я работал по вечерам и ночью часов до 3-4, чтобы покормить дочку в 4:00 и потом уже завалиться спать. Тогда я был типичной совой :)

Вообще, хочу сказать, что работа по 10-12 часов – это ненормально. Ее можно выдержать на протяжении 3-4 недель вполне спокойно, от 2-х до 3-х месяцев с большим напряжением. Больше 3-х месяцев, думаю, без ущерба уже обойтись.

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

Поддержание физической формы в время авралов – это очень важно (без фанатизма). Если каждый день отжиматься/подтягиваться, то можно выдержать аврал в пару месяцев. Но если этого не делать, а вести “растительный” образ жизни, то уже через пару недель сильно снизится работоспособность и начнутся различные неприятные симптомы. Еще очень важно нормально питаться – не переедать, и не сидеть в проголодь, не злоупотреблять печеньем и шоколадками :)

Кроме физической усталости есть и психологическая, что намного хуже. Становишься раздражительным, сложно себя сдерживать (особенно с моим взрывным характером). На работе тяжело относишься к двум вещам – разгильдяйству и пофигизму коллег/подчиненных, а так же к внезапно сваливающимся на тебя от руководства новым задачам. Но самые большие сложности дома – родные не хотят видеть тебя дома всего по 1-2 часа в день, да и то со спины. Тут полный обертюр, поскольку на работе еще находятся силы как-то сдерживаться в разговорах с коллегами, не переходить на крик и не заниматься рукоприкладством. А вот дома уже сил нет, поэтому начинашь на всех рычать, а потом самому от этого хреново.

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

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

Раз уж пошла такая пьянка, то в разговоре об авралах нужно обязательно затронуть еще две вещи.

Во-первых, почему авралы возникают и можно ли их предотвратить?

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

В моем же случае есть еще один фактор. Я могу порвать на британский флаг любую задачу. Но для этого мне нужно захотеть это сделать. Что происходит лишь в двух случаях: либо эта задача мне самому очень интересна (как это было с SObjectizer и so_4_book), либо если отступать уже некуда. Так как на работе приходится решать, зачастую, задачи из разряда “надо, но уж очень не хочется”, то получается так: сначала я долго хожу вокруг да около, рисую какие-то схемки на бумаге, отвлекаюсь на всякое разное, а потом, когда отступать уже некуда, стартует аврал. Тогда адреналин и огромное желание “поиметь” задачу. Тогда она внезапно становиться очень и очень интересной и привлекательной ;)

А по поводу авралов в области разработки ПО я думаю, что они никогда не исчезнут. Программирование – это творческая профессия, а в творчестве авралы являются нормальным явлением. Не важно, будь то программирование, литература или разработка артиллерийских орудий (достаточно почитать, как работало КБ Грабина).

Во-вторых, почему я соглашаюсь работать в авральном режиме, а не посылаю все на три буквы?

В моем случае это совокупность факторов. Упомянутый выше способ “мотивировать” самого себя. Плюс “менталитет морского корпуса” (из книги “Путь камикадзе” Йордана) – стремление забежать босиком на Эверест. Плюс с детства усвоенная истина, что большие достижения требуют большого труда. Плюс понимание того, что все это, в конечном итоге, работает на мое благосостояние. Ну и плюс к тому: все, что нас не убивает, делает нас сильнее :) Наличие в прошлом случаев, когда я напрягался и создавал сложные вещи, дает мне уверенность в том, что я смогу повторить такие же достижения и сейчас, и в будущем.

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


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

И в отличии от старой Apple-овской гвардии, я редко работаю по 80 часов в неделю, а когда работаю так, то это мне не нравится :)