суббота, 27 июня 2009 г.

[comp] Нет прогресса, говорите?

Возвращаясь к старой теме. Вот свеженький анонс новой версии среды Eclipse:

Release train comprises 33 projects and more than 24 million lines of code.

Так кто говорит, что в индустрии разработки ПО нет прогресса? Вышел проект с 24 миллионами(!) строк внутрях! Лет 25-30 назад проект подобного объема попробовали бы выпустить, обкакались бы, ей богу. 24 миллиона(!!!) строк – это ж офигеть сколько!

(Чуть в сторону) Есть у меня подозрение, что немалую роль в работоспособности такого монстра играет Java. Безопасная среда, сборка мусора и все такое. Но и для работы такого монстра нужно железо, которое 25-30 лет было, наверное, только в виде суперкомпьютеров :)

[life] Repeat after me: I am free

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

Возникает вопрос: какой херней я здесь страдаю?

пятница, 26 июня 2009 г.

[life] Ксения Симонова. Песочная анимация

Это не описать словами. Просто посмотрите.

[comp] Доверие к “правильному” коду

В очередном RSDN-новском флейме на тему unit-тестирования возникло противопоставление тестирования кода и разработки гарантированно корректного кода (с помощью “правильных”, т.е. функциональных языков программирования). Продемонстрировать это можно на примере, который я подкинул в это обсуждение. Итак, есть некий псевдо-C++ код для перевода денег с одного банковского счета на другой:

void transfer(
  Account & from,
  Account & to,
  const Money & amount )
  {
    // RAII в действии. Конструктор блокирует объект,
    // а деструктор разблокирует.
    AccountLock lock_from( from );
    AccountLock lock_to( to );

    from.debit( amount );
    to.credit( amount );
  }

Данный код является потенциально подверженным взаимным блокировкам. Например, если первая нить вызовет transfer(A,B,m), а вторая transfer(B,A,n).

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

LockPair< Account > transfer(
  Account & from,
  Account & to,
  const Money & amount )
  {
    // Этот объект гарантирует, что захват ресурсов
    // выполняется в нужном порядке.
    LockPair< Account > locks( lock_objects( from, to ) );

    from.debit( amount );
    to.credit( amount );

    return locks;
  }

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

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

Однако, не все так просто. Поскольку никто не застрахован от ошибок, и в реализацию transfer могла закрасться маленькая опечаточка:

LockPair< Account > locks( lock_objects( from, from ) );

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

К чему я это? Да к тому, что тестам по барабану, какие ошибки искать и в соответствии с какими принципами разрабатывался тестируемый код. Они просто показывают, есть ли ожидаемый результат или нет. Тогда как изначально задумывавшийся в качестве корректного код может оказаться проблемным из-за опечатки. И это не будет выявлено как раз из-за отсутствия тестов, поскольку разработчик посчитал, что его “правильный” код в тестировании не нуждается.

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

PS. Этот пример интересен еще и тем, во что может выливаться в коде попытка писать гарантированно корректный код. Так, возвращаемое значение для transfer теперь показывает наружу детали работы transfer. А что, если нам это не нужно? Ведь мы можем писать код, которому не важно, работает ли он в многопоточной или однопоточной программе. Но тем не менее, мы будем закладываться на то, что реализация transfer связана с блокировками. Далее, если уж мы начали пытаться что-то гарантировать, то нужно идти дальше, и гарантировать, что операции debit и credit не могут вызываться для незаблокированных объектов Account. А это значит, что спецификация этих операций должна измениться, например, на такую:

void debit(
  const Amount & money,
  const Lock & lock );

чтобы программист не мог вызвать debit/credit без предварительного блокирования счета. Хотя и это еще не гарантия правильной реализации transfer. Но это уже совсем другая история.

четверг, 25 июня 2009 г.

[life.idea] Способ борьбы с коррупцией :)

По следам статьи “Китай: взяточник платит за свою пулю” в “Аргументах и Фактах”.

Вместо того, чтобы казнить взяточников (как в Китае), в России (да и в Белоруссии), на мой взгляд, лучше поступать так:

  1. Немедленное увольнение с пожизненным запретом любой работы на предприятиях с любой долей государственной собственности. Т.е. даже дворником в акционерном обществе, в котором государству принадлежит хотя бы 0.1% акций – все равно нельзя.
  2. Работодателям разрешается немотивированно отказывать таким гражданам в приеме на работу и увольнять без выходного пособия и объяснения причин увольнения. Не понравился работодателю бывший взяточник – вылетел с работы без права голоса.
  3. На лицо взяточнику наносится татуировка “Взяточник” (например, на скулы под глазами) без права ее сведения. Вряд ли солидной коммерческой структуре захочется взять попавшегося на взятке чиновника, у которого в прямом смысле слова на лице будет написано, что он взяточник.

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

PS. Всегда легко рассуждать о том, в чем не разбираешься ;)

понедельник, 22 июня 2009 г.

[comp; life] Роботехника: вот так сказка становится былью

Вот так вот потихонечку, помаленечку… А там глядишь – поедешь на старости лет в Японию, а в забегаловке тебе стол сервировать будет робот.

[comp] SObjectizer – что-то странное…

В посление несколько дней статистика загрузки SObjectizer-проектов на SourceForge показывала что-то странное:

2009.06.22 0
2009.06.21 76
2009.06.20 261
2009.06.19 110
2009.06.18 76
2009.06.17 57
2009.06.16 27
2009.06.15 1
2009.06.14 6
2009.06.13 9
2009.06.12 0

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

Пока у меня есть всего три версии, которые могли бы объяснить происходившее:

  • какой-нибудь баг в системе сбора статистики SourceForge. Имхо, это самая вероятная версия, т.к. в последнее время качество SourceForge стремится к плинтусу;
  • кто-то DOS-ит SourceForge выкачивая более-менее большие пакеты (а Globe – это архив на 3Mb). Не очень верится в такую версию, но все же :)
  • кто-то выпустил какой-то продукт на основе SObjectizer и Gemont. И пользователи этого продукта вынуждены качать Globe.

Последняя версия самая маловероятная, но очень хочется верить именно в нее :)