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

[life] Участвую в акции против «Эхо Москвы»

Хоть я сейчас далеко от Москвы, но в акции поучаствую.

Поддержать акцию

Поскольку вот такое прощать нельзя:

В. Новодворская (журналист, постоянный гость радиостанции): «То есть страна стоит на вранье и тонет в этом вранье, и это называется “День победы”. У нас не было никакой победы...в стране, которая, якобы, победила фашизм».

А.Даниэль (член правления общества «Мемориал», правозащитник): «А ведь была попытка отменить, по-моему, в начале 90-х эти парады победы, да? И это было, по-моему, правильно».

В. Шендерович: «Это плохо [празднование Великой Отечественной  войны], потому что это не должно быть предметом празднования. 9 мая не праздник.»

А. Венедиктов: «Но на самом деле, конечно, «Майн Кампф» должен изучаться историками, и выдержки из «Майн Кампфа», на мой взгляд, должны быть в школьных учебниках».

[life.whiskey] Алкогольное. Шотландский виски против ирландского

В проведенном вчера соревновании-дегустации, на мой взгляд, безоговорочную победу одержал продукт компании Jameson (конкурентами были White&Mackey и Black Label (12-ти летний)):

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

Продегустированные вчера виски были представителями самого простого и массового вида виски – blended whiskey. Т.е. когда односолодовый ячменный виски разбавляется разными сортами зернового виски.  (Хотя с Jameson-ом, судя по всему, все не так однозначно, но, исходя из цены, это был явно не односолодовый).

Очень хочется попробовать именно односолодового виски (который single melt) и виски с острова Islay (говорят у него очень специфический вкус). Только у нас в городе single malt виски сейчас, похоже, днем с огнем не найдешь. Не говоря уже об Islay-виски. Ну ничего, будем доставлять с оказией из других городов и весей :)

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

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

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

Часть I
Часть II

В этот раз я расскажу о том, что хотелось бы иметь в языке Java, если бы его более-менее серьезно переработать (как язык, так и саму JVM).

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

Итак, сначала о том, что я себе хорошо представляю.

1. Мне пришлось в своем проекте на Java перепаковывать биты в байты и обратно – после C++ без unsigned char-ов и unsigned int-ов было непривычно. Приходилось делать лишнюю работу, мелкую и нудную. Поэтому очень хотелось бы видеть в Java хотя бы unsigned byte. Чтобы можно было писать так:

class ByteTest {
   static public void main(String[] args) {
      ubyte v = 0x83;
      ubyte b = v >> 1;
   }
}

Насколько я понимаю, беззнаковые целые не поддерживаются на уровне JVM. Зря они так.

2. Очень бы не помешали туплы для того, чтобы из методов можно было возвращать несколько значений. Этого и в C++ нынешнем нет, но в C++ хотя бы есть возможность передавать аргументы по неконстантным ссылкам/указателям. Поэтому в C++ возврат нескольких int-ов из функции/метода гораздо проще, чем в Java. Так что, имхо, в Java туплы даже нужнее, чем в C++.

Очевидно, что туплы – это штука неоднозначная (как и автоматический вывод типов). Сегодня одному разработчику будет удобно возвращать из метода тупл. А через год другой разработчик будет гадать – такой же смысл имеет третий элемент возвращенного тупла. Поэтому использование туплов можно было бы ограничить: например, запретить их возврат из public-методов классов. Тогда бы и разработка на Java упростилась бы, и сопровождаемость кода не пострадала бы. Лично мне было бы приятнее писать так:

class Demo {
   public void doSomething() {
      int min;
      int max;
      (min, max) = findMinAndMax();
      ...
   }

   private (int, int) findMinAndMax() {
      int min = someInternalData[0];
      int max = someInternalData[0];
      for( int item : someInternalData ) {
         if( item < min ) min = item;
         if( item > max ) max = item;
      }
      return (min, max);
   }

   ...
}

а не так, как сейчас:

class Demo {
   public void doSomething() {
      MinAndMax minMax = findMinAndMax();
      ...
   }

   private (int, int) findMinAndMax() {
      MinAndMax result = new MinAndMax( someInternalData[0], someInternalData[0] );

      for( int item : someInternalData ) {
         if( item < result.min ) result.min = item;
         if( item > result.max ) result.max = item;
      }
      return result;
   }

   ...
}

private class MinAndMax {
   int min;
   int max;

   MinAndMax(int min, int max) {
      this.min = min;
      this.max = max;
   }
}

3. В Java очень сильно не хватает константности объектов. В C++ я к этому привык. Бывало, что компилятор бил разработчика по рукам, предупреждая ошибки. Да и в связи с hype вокруг функционального программирования и многоядерных процессоров, языки без константности для объектов уже выглядят опасными.

За основу я бы взял вариант из языка D, но без хвостовой константности. Разделил бы все ссылки на три типа: обычные, readonly и immutable. Если есть обычная ссылка на объект, то у объекта можно вызывать любые методы. Если есть readonly-ссылка или immutable-ссылка, то можно вызывать только immutable-методы.

Соответственно, объекты в программе делятся на обычные (изменяемые) и immutable (изменить которые нельзя). Обычные объекты можно передавать по обычным или readonly ссылкам, но нельзя передавать по immutable-ссылке.

Смысл у readonly-ссылок такой же, как у const-ссылок и указателей в C++: мы не можем модифицировать объект, но эта модификация может быть разрешена для кого-то другого. Например:

class UserInfo {
   private String name;

   UserInfo(String name) { this.name = name; }

   immutable public String name() { return this.name; }
   public String setName(String name) { this.name = name; }
}

class UserObserver {
   readonly private UserInfo user;

   UserObserver(readonly UserInfo user) { this.user = user; }

   public void print() { System.out.println(user.name()); }
}

class Demo {
   static public void main(String[] args) {
      UserInfo ui = new UserInto("John Smith");
      UserObserver observer = new UserObserver(ui);

      observer.print(); // => John Smith

      ui.setName("John Woo");

      observer.print(); // => John Woo
   }
}

А вот смысл immutable в том, что компилятор гарантирует, что объект никогда не изменится. Если есть immutable ссылка на объект A, то компилятор разрешает вызывать только те методы объекта A, которые помечены как immutable. И компилятор следит за тем, чтобы внутри immutable-методов состояние объекта не изменялось.

Представим, что в примере выше в классе UserObserver хранилась бы не readonly, а immutable ссылка на UserInfo. В этом случае UserObserver был бы защищен от “внезапных” модификаций объекта UserInfo где-то в других местах программы.

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

class ChangeLogStreamNotify { 
   public LogStream stream;

   ChangeLogStreamNotify(LogStream stream) { this.stream = stream; }
}

Сам объект сообщения поступает подписчикам в виде immutable объекта. Поэтому подписчики не смогут заменить в нем значение stream. Т.е. при доступе к экземпляру ChangeLogStreamNotify из разных потоков не нужно никакой синхронизации.

Однако, ссылка на LogStream внутри ChangeLogStreamNotify является обычной ссылкой. Поэтому для объекта LogStream можно вызывать любые методы:

class WorkThread {
   public void onChangeLogStreamNotify(
         immutable ChangeLogStreamNotify notify) {
      notify.stream.debug("log stream changed");
   }
}

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

1. В Java не хватает хоть какого-то подобия нормального множественного наследования или же каких-то механизмов подмешивания общего кода в разные классы. Что-то типа механизма mixin-ов из Ruby или trait-ов из Scala. Хотя в Scala, имхо, trait-ы переусложнили. Нужно бы чего-нибудь попроще.

Например, был у меня интерфейс TlvCompoundItem с одним методом tlvFields.

public interface TlvCompoundItem extends TlvItem {
    TlvFieldInfo[] tlvFields();
}

Этот интерфейс реализует базовый класс для PDU (элементов прикладного протокола):

abstract public class Pdu implements TlvCompoundItem {
    @Override
    abstract public TlvFieldInfo[] tlvFields();
    ...
}

И затем каждый наследник Pdu должен определять у себя tlvFields одним и тем же способом:

public class SomeConcretePdu extends Pdu {
    ...
    @Override
    public TlvFieldInfo[] tlvFields() {
        return tlvFieldsDecription;
    }

    static private TlvFieldInfo[] tlvFieldsDescription = ...;
}

Т.е. в каждом наследнике Pdu есть статический атрибут с описанием TLV-полей, и всегда он имеет имя tlvFieldsDescription. И реализация метода tlvFields всегда возвращает этот атрибут.

Вот это дублирование одинакового кода tlvFields и не нравится. Можно было бы поступить как-то так (это только набросок):

mixin PduFieldsGetter requires(TlvFieldInfo[] fields) {
   public TlvFieldInfo[] tlvFields() {
      return fields;
   }
}

public class SomeConcretePdu
   extends Pdu
   uses PduFieldsGetter(tlvFieldsDescription)
{
   ... // Здесь уже не нужно объявлять tlvFields().

   static private TlvFieldInfo[] tlvFieldsDescription = ...;
}

2. Хотелось бы иметь в Java ссылки, которые гарантированно не могут быть нулевыми. Т.е., чтобы Java предлагала бы решение проблемы нулевых ссылок, как это сейчас делает Eiffel.

Только вот как это делать – это вопрос. Либо же в язык вводится понятие ненулевой ссылки (например, String! вместо String) и компилятор будет отслеживать действия с этой ссылкой (так попытались сделать в языке Nice). Либо же нужно добавлять в язык что-то вроде типа Option (с сопутствующими ему вариантами None и Some) и паттерн-матчинга, чтобы нужно было явно разделять ситуации с нулевыми и ненулевыми ссылками.

Я бы предпочел вариант без паттерн-матчинга и типа Option. Запись String! более привычна для императивного программиста. Да и гигатонны уже написанного Java кода в таком случае было бы гораздо проще переиспользовать.


Вот такие у меня мысли о том, как сделать из Java нормальный ;) язык. Если собрать эти предложения и то, о чем я писал раньше, то получится неплохой, прагматичный язык. На который я бы лично перешел бы с C++. Наверное :)

[life.photo] Вспышка на Солнце

Красиво.

Снимок сделан новым спутником NASA. Фото найдено в очередном выпуске WSJ’s Picture of the Day.

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

[prog.c++] Слайды Solid C++ Code by Example с конференции ACCU 2010

Некоторые докладчики конференции ACCU 2010 уже выложили в сеть слайды своих докладов. Например, Olve Maudal опубликовал слайды своего выступления Solid C++ Code by Example.

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

В Интернете так же есть презентация того же автора на ту же тему, но от 2008 года: C++ Idioms by Example, lesson 1.

Но, поскольку я в C++ не новичок и многое из изложенного в презентациях я делаю уже на автопилоте, то ряд моментов вызвал у меня некоторое недоумение.

Начну с презентации от 2008 года.

Рекомендация первая: не делать using namespaces (стр.24). Спорная штука. Я сам стараюсь избегать using namespace, особенно в заголовочных файлах. Но иногда эта инструкция избавляет от изрядного геморроя и сильно повышает читабельность текста.

Рекомендация вторая: при определении тела свободной функции из какого-то пространства имен, не нужно открывать это пространство имен (ст.65). Т.е. вместо:

// bar.hpp
#if !defined( BAR_HPP )
#define BAR_HPP

namespace bar {
   void print();
}

// bar.cpp
#include <bar.hpp>

namespace bar {
   void print() {
      ...
   }
}

нужно поступать в файле bar.cpp вот так:

// bar.cpp
#include <bar.hpp>

void bar::print() {
   ...
}

Интересно, что он прикажет мне делать, когда у меня пространства имен носят названия вида: aag_3::utils::rdbms::odbc_multi::otl_connect_factory?

Но больше всего в презентации 2008-го года меня убила последняя рекомендация на стр.74: настоящие, мол, профессионалы делают отступ в 4 пробела. Она как! :)

Теперь к новой презентации от 2010-го. Здесь есть моменты, которые (как и в случае с 4-мя пробелами) являются не столько рекомендациями, сколько “доколупыванием”. Нужно было до чего-то доколупаться, вот и доколупались.

Вот здесь (стр.69):

const std::size_t data_offset(to.end() - to.begin());

автору не понравилось, что data_offset инициализируется в синтаксисе конструктора, а не присваиванием. Там же ниже по коду:

std::vector<uint8_t> buffer(prefix, prefix + sizeof(prefix));

он требует убрать скобки в выражении sizeof.

Интереснее на странице 63. Там приведен конструктор класса, в котором атрибуты domain_ и workstation_ не перечислены в списке инициализаторов. Т.е. конструктор имеет вид:

pal::type3_message::type3_message(
   const std::vector<uint8_t> & lm_response,
   const std::vector<uint8_t> & nt_response,
   const std::string & user,
   uint32_t ssp_flags)
   :
   lm_response_(lm_response),
   nt_response_(nt_response),
   user_(user),
   ssp_flags_(ssp_flags)
   session_key_(session_key_size)
{...}

А автору хочется, чтобы он имел вид:

pal::type3_message::type3_message(
   const std::vector<uint8_t> & lm_response,
   const std::vector<uint8_t> & nt_response,
   const std::string & user,
   uint32_t ssp_flags)
   :
   lm_response_(lm_response),
   nt_response_(nt_response),
   domain_(),
   user_(user),
   workstation_(),
   session_key_(session_key_size)
   ssp_flags_(ssp_flags)
{...}

Атрибуты domain_ и workstation_ имеют тип std::string. У этого типа есть нормальный конструктор по умолчанию. Зачем демонстрировать факт этого в списке инициализаторов я не понимаю. А автор не объясняет.

Еще на странице 74 автор доколупался до метода debug_print. Метод этот писал значения атрибутов класса в указанный std::ostream. С багами, но писал. На странице 87 приведен модифицированный вариант этого метода, устраивающий автора. Новый debug_print не пишет в std::ostream. Он использует внутри себя std::stringstream и возвращает std::string.

Я не понял, зачем потребовалось заменять печать в ostream на возврат строки. Но зато автор выступления сам попался в собственные сети – почему у debug_print-а осталось старое название? Смысл-то поменялся. Нужно было дать название, например, to_debug_string или make_debug_string :/

Резюмирую. В обоих презентациях есть изрядное число полезных советов. Но нет ни одного объяснения, почему нужно поступать именно так. Человек с опытом понимает почему, а вот новичку остается только верить на слово. При этом следовать некоторым советом Olve Maudal я бы не рекомендовал.

PS. Это тот самы Olve Maudal, который написал главу в книгу 97 Things Every Programmer Should Know, о которой я уже писал. Глава называется Hard Work Does Not Pay Off и содержит, на мой взгляд, набор банальностей о том, как плохо много работать.

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

[prog.flame] Тихо и незаметно разговорам о новой multi/many-core эре в программировании исполнилось пять лет

Причем исполнилось не сегодня, а еще первого марта – именно первого марта 2005 года вышла знаменитая статья Герба Саттера “A Fundamental Turn Toward Concurrency in Software”.

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

Такое впечатление, что разговоры ведутся, какие-то результаты периодически возникают (вроде Intel TBB)… А вот революции нет. И задумываешься: либо она зреет-зреет и таки разразиться со временем, либо же ее не будет вовсе.

[prog.flame; humour] Откуда же тогда берутся плохие программисты? Да еще в таком количестве?

Многие из программистов считают себя хорошими программистами. Некоторые говорят, что они считают себя средними программистами. Но очень мало кто заявляет о том, что он считает себя плохим программистом. Тем не менее, очевидно, что плохих программистов вокруг полно (иначе не понятно, почему качество программ все время снижается) ;)

Так вот вопрос: если все считают себя хорошими программистами (ну средними в крайнем случае), тогда откуда берется такое количество плохих программистов? ;)

PS. Я хороший программист. Хотя считаю себя очень хорошим программистом :)))

PPS. На самом деле это просто стеб в догонку к предыдущей заметке. Я не серьезно (на 80% это шутка) ;)

[prog.flame] Пример программерского снобизма

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

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

Не задерживайте свое мышление на низком уровне абстракции и будет вам счастье.

Забавно вспоминать, но лет пятнадцать назад я и сам таким был – я-то уже освоил ООП, тогда как уровень среднего программиста не мог угнаться за мной. Да и шансов у среднего программиста не было – против него не кто-нибудь, а я, весь такой супер-пупер и самый лучший программист на Земле вааще.

Но прошло совсем немного времени, гормонов в крови поубавилось, изрядная доля сил, направленных на доказательство своего доминирования (по проф.Савельеву), уже истрачена. И оказалось, что я, такой весь из себя в белом и самый-самый вааще, уже всего лишь средненький программист, просравший задержавший свое мышление на низком уровне абстракции. Ну как же – пришла молодая шпана, которая сметет нас с лица земли :)

Когда-то комментатор с НТВ (не помню фамилию, к сожалению) сказал, что у комментаторов есть всего три правила:

  • во-первых, нельзя считать, что ты самый умный;
  • во-вторых, нельзя считать, что ты самый умный,
  • ну и, в-третих, ни в коем случае нельзя считать, что ты самый умный.

За годы занятия программированием я убедился, что это очень важные правила и программисты должны им следовать.

PS. Всегда с подозрением относился к участникам форумов, которые не открывали своего настоящего имени. Есть в этом что-то подозрительное. Вот тот же gandjustas на форумах настоящий орел, но кто он по жизни? Легко быть анонимным героем.

[life.photo] Молнии вулкана Эйяфьятлайокудль

Говорят, что изредка при извержении вулкана появляются молнии. Т.е. они точно появляются, поскольку их хорошо видно на нижеследующих фотографиях. Но говорят, что это редкое явление, а потому и неисследованное. Зато очень красивое:

Вся эта красота была найдена здесь.

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

[life.humour] Мы вам нальем виски онлайн, а вы нам отправите деньги по факсу…

…такой каламбур родился у меня в голове, когда я увидел название раздела на сайте производителя виски Jameson:

PS. На самом деле там видео, на котором какой-то эксперт проводит реальную дегустацию виски. Но крючок для цепляния внимания хороший – онлайн-дегустация – это вам не хухры-мухры :)

[prog.c++] Пример использования указателей на методы в C++

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

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

void
a_cp_service_t::do_all_periodic_actions()
   {
      measure_duration(
            m_monitors.m_avg_time_save_outgoing_pkg,
            this,
            &a_cp_service_t::handle_received_outgoing_packages );

      measure_duration(
            m_monitors.m_avg_time_handle_SR,
            this,
            &a_cp_service_t::handle_received_send_results );

      measure_duration(
            m_monitors.m_avg_time_handle_SR_pkg_ack,
            this,
            &a_cp_service_t::handle_received_SR_package_acks );

Где measure_duration – это очень простая функция-шаблон:

template< class T >
inline void
measure_duration(
   monitor_t & monitor,
   T * object,
   void (T::*method)() )
   {
      ACE_Time_Value s = ACE_OS::gettimeofday();
      (object->*method)();
      ACE_Time_Value f = ACE_OS::gettimeofday();

      monitor.add_time_slice( f - s );
   }

Т.е. указатели на методы в C++ позволили обойтись без определения каких-либо интерфейсов (к чему пришлось бы прибегнуть в Java), либо лямбда-функций-делегатов (C#/D/Scala), либо рефлексии (опять же Java, если интерфейсы не нравятся), либо макросов (если не знать, что такое указатели на методы в C++). А так все просто, прозрачно и эффективно.

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

[prog.d] Язык D обзавелся плагином для Visual Studio

Плагин называется Visual D. Написан на D.

Впечатляет скриншот, который показывает отладку D-шного кода в Visual Studio:

Не могу удержаться, и не спошлить: осталось только нормальный компилятор сделать… :/

[work] Вакансии C++ разработчиков закрыты

Закрыл все вакансии C++ программистов в своей команде. Ура! Нас ждут великие дела! :)))

Еще бы хорошего технического писателя найти…

[prog.c++] Презентация Concurrency in the Real World от Энтони Уильямса

Энтони Уильямс (Anthony Williams, один из активных разработчиков C++0x и автор библиотеки just::thread) опубликовал слайды своего доклада Concurrency in the Real World с прошедшей недавно конференции ACCU 2010.

Это 56-ти страничная PDF-ка весом в 2.5Mb. Интересная в первую очередь 100% ориентацией на возможности C++0x. Но мне показалось, что для такого названия, материала и примеров в ней должно было бы быть побольше.

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

[work.humour] Дотуп к тестовому…

От клиента сегодня пришло письмо с просьбой уточнить параметры подключения к нашей тестовой системе. Заголовок письма начинался с “Дотуп к тестовому…”

Хорошее такое слово – дотуп. Актуальное :)

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

[life.photo] Подводные фотографии Марины Кочетовой

В сегодняшнем выпуске рубрики “Знакомство с фотомастером” фотографии Марины Кочетовой.

Контакт

Знакомство с гигантом

"Гюльчатай, покажи личико!"

Краски моря

Китовая акула

портрет белухи

взгяд

..купаясь в солнечных лучах

Тянутся руки..

геометрия

Портрет креветки

Танцующая медуза

Летающая тарелка

Под сводами

С другими работами Марины Кочетовой можно познакомиться на photosight.ru и photoline.ru. Рекомендую это сделать, т.к. среди ее снимков есть очень приличные фотографии в жанрах “Пейзаж” и “Путешествия”.