суббота, 5 декабря 2009 г.

[comp.prog.bugs] Вальтер Брайт исправил баг, которому более 18 лет

Сегодня вышли новые версии компиляторов DMD – 1.053 и 2.047. В новых версиях большое количество баг-фиксов. Среди которых и исправление бага 3521. В news-группе digitalmars.D.announce Вальтер Брайт сказал, что этот баг, вероятно, прожил более 18 лет. Он срабатывал очень и очень редко. И для его поимки пришлось модифицировать C++ компилятор и прогнать большое количество тестов.

Такие дела. Что-то в последнее время баги вокруг возникают просто в невообразимых количествах. То на бажную обертку для libcurl наткнешься, то на баги в Poco. Наш новый клиент буквально вчера нашел у меня баг, которому если не пять лет, то года четыре точно. Прямо эпидемия какая-то, сезонная ;)

PS. Забавно, что в DMD 2.047 опять появилось много нововведений. В частности, некий opDispatch, назначение которого я с ходу понять не смог.

[life.auto.crash] Автомобильная авария в Иркутске

Однажды ехал в поезде с мужиком, который рассказал, как он попал в ДТП. Они шли по тротуару с женой, когда с проезжей части выскочил здоровенный джип. У жены ни одной царапины, мужика впечатало в стену, почти всего переломало и он больше полугода пролежал в больнице. Видимо, происходило это так же, как в Иркутске:

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

PS. Ссылка на видео найдена в Тупичке Goblin-а.

пятница, 4 декабря 2009 г.

[comp.humour] Портрет Стива Балмера из BSOD

Этот портрет составлен из фотографий компьютеров, на которых висит “Синий экран смерти” (BSOD):

Первоисточник.

[comp.robots] Автономный летающий робот из MIT

Есть, оказывается, такая организация: Association for Unmanned Vehicle Systems International. Которая регулярно проводит различные соревнования для роботов: перенести металлический диск с одного места на другое, проехать 3 мили с одной точки в другую. Главное, чтобы роботы делали это самостоятельно, без дистанционного управления. В этом году на подобном соревновании было поставлено условие: робот должен был проникнуть через окно в лабиринт, имитирующий коридор эвакуированного здания, найти комнату управления, распознать там датчики радиации, сфотографировать их и передать снимки по радио. В данном соревновании было запрещено использовать GPS-навигацию.

Впервые за историю проведения таких соревнований, задание было выполнено в первый же год. Это сделала команда из лаборатории Robust Robotics Group знаменитого Массачусетского Технологического Университета (он же MIT). А вот и их робот:

(в разделе Video на сайте лаборатории есть и другие ролики)

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

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

четверг, 3 декабря 2009 г.

[comp.prog.flame] И еще одно сравнение C++ с Erlang (британскими учеными на этот раз)

На RSDN-е проскочила ссылка на очередное сравнение C++ и Erlang, на этот раз выполненное в Motorola Labs совместно с университетом Heriot-Watt из Эдинбурга. Вот презентация этого сравнения:

При просмотре презентации я обратил внимание на один подозрительный момент – там где идет сравнение объемов кода на слайде 27. Чтобы убедиться в их обоснованности, я нашел PDF-ку с описанием этой работы – вот она: High-Level Distribution for the Rapid Production of Robust Telecoms Software: Comparing C++ and Erlang. А вот эти фрагменты крупным планом. На erlang-е:

sz_dme_dmtx:cast(device_info)

И оригинальный фрагмент на C++, который, якобы, делает тоже самое:

void DataMobilityRxProcessor::processUnsupVer(void)
{
  MSG_PTR msg_buf_ptr;
  MM_DEVICE_INFO_MSG *msg_ptr;
  RETURN_STATUS ret_status;
  UINT16 msg_size;

  // Determine size of ici message
  msg_size = sizeof( MM_DEVICE_INFO_MSG);

  // Create ICI message object to send to DMTX so it sends a Device Info
  // message to Q1 and Q2 clients
  IciMsg ici_msg_object( MM_DEVICE_INFO_OPC, ICI_DMTX_TASK_ID, msg_size);

  // Retrieve ICI message buffer pointer
  msg_buf_ptr = ici_msg_object.getIciMsgBufPtr();

  // Typecast pointer from (void *) to (MM_DEVICE_INFO_MSG *)
  msg_ptr = (MM_DEVICE_INFO_MSG *)msg_buf_ptr;

  // Populate message buffer
  SET_MM_DEVICE_INFO_DEVICE_TYPE( msg_ptr, SERVER);
  SET_MM_DEVICE_INFO_NUM_VER_SUPPORTED( msg_ptr, NUM_VER_SUPPORTED);
  SET_MM_DEVICE_INFO_FIRST_SUP_PROTO_VERS( msg_ptr, PROTO_VERSION_ONE);

  // Send message to the DMTX task
  ret_status = m_ici_io_ptr->send(&ici_msg_object);

  // Check that message was sent successfully
  if (ret_status != SUCCESS)
  {
    // Report problem when sending ICI message
    sz_err_msg( MAJOR, SZ_ERR_MSG_ERR_OPCODE, __FILE__, __LINE__,
      "DataMobilityRxProcessor processUnsupVer: failure sending "
      " device info message to DMTX");

Оставим сейчас в стороне логическое соответствие этих двух фрагментов (действительно, пусть в Erlang программе сущность device_info сразу рождается полностью корректно сформированной и в C++ сделать тоже самое ну никак нельзя). Достаточно просто взглянуть на C++ный код и ужаснуться.

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

void DataMobilityRxProcessor::processUnsupVer(void)
{
  // Create ICI message object to send to DMTX so it sends a Device Info
  // message to Q1 and Q2 clients
  IciMsg ici_msg_object( MM_DEVICE_INFO_OPC, ICI_DMTX_TASK_ID,
      sizeof( MM_DEVICE_INFO_MSG ) );

  // Retrieve ICI message buffer pointer and
  // Typecast pointer from (void *) to (MM_DEVICE_INFO_MSG *)
  MM_DEVICE_INFO_MSG * msg_ptr =
      (MM_DEVICE_INFO_MSG *)ici_msg_object.getIciMsgBufPtr();

  // Populate message buffer
  SET_MM_DEVICE_INFO_DEVICE_TYPE( msg_ptr, SERVER);
  SET_MM_DEVICE_INFO_NUM_VER_SUPPORTED( msg_ptr, NUM_VER_SUPPORTED);
  SET_MM_DEVICE_INFO_FIRST_SUP_PROTO_VERS( msg_ptr, PROTO_VERSION_ONE);

  // Send message to the DMTX task
  const RETURN_STATUS ret_status = m_ici_io_ptr->send(&ici_msg_object);

  // Check that message was sent successfully
  if (ret_status != SUCCESS)
  {
    // Report problem when sending ICI message
    sz_err_msg( MAJOR, SZ_ERR_MSG_ERR_OPCODE, __FILE__, __LINE__,
      "DataMobilityRxProcessor processUnsupVer: failure sending "
      " device info message to DMTX");

Уже получается 27 строк вместо 35 (сокращение на 22%, если пародировать подобные отчеты). А если поступить нормально и вынести все манипуляции с msg_ptr во вспомогательную функцию, то получится еще компактнее:

void DataMobilityRxProcessor::processUnsupVer(void)
{
  // Create ICI message object to send to DMTX so it sends a Device Info
  // message to Q1 and Q2 clients
  IciMsg ici_msg_object( MM_DEVICE_INFO_OPC, ICI_DMTX_TASK_ID,
      sizeof( MM_DEVICE_INFO_MSG ) );

  // Populate message buffer
  populateMessageBuffer(
      (MM_DEVICE_INFO_MSG *)ici_msg_object.getIciMsgBufPtr() );

  // Send message to the DMTX task
  const RETURN_STATUS ret_status = m_ici_io_ptr->send(&ici_msg_object);

  // Check that message was sent successfully
  if (ret_status != SUCCESS)
  {
    // Report problem when sending ICI message
    sz_err_msg( MAJOR, SZ_ERR_MSG_ERR_OPCODE, __FILE__, __LINE__,
      "DataMobilityRxProcessor processUnsupVer: failure sending "
      " device info message to DMTX");

Почти в два раза меньше исходного варианта. Я бы пошел еще дальше, и повыбрасывал бы эти дебильные комментарии вида “Ща мы проверим успешность операции”, да и количество пустых строк подсократил бы. Конечно, однострочного “аналога” на Erlang-е не получилось бы, но процентов из 60% от исходного индусокода можно было бы выбросить смело.

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

Эдинбург находится в Великобритании ;)

[comp.prog] Ссылки от читателей: Relacy Race Detector

Сейчас ссылки от Дмитрия Вьюкова (aka remark):

Relacy Race Detector – инструмент для поиска ошибок в многопоточных алгоритмах.

Интервью с Дмитрием Вьюковым по поводу RRD в Dr.Dobb’s. И вариант этого интервью на русском языке.

PS. Публиковать ссылку на RRD особенно приятно, поскольку каким-то чудом я там упомянут в разделе Acknowledgment :)

[comp.prog] Ссылки от читателей: анализаторы C++ кода

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

CppCheck – бесплатный статический анализатор C/C++ кода.

PVS-Studio – инструмент для проверки 64-битных и параллельных программ от российской компании “СиПроВер” (включает в себя инструменты Viva64 и VivaMP).

PolySpace – инструменты для верификации C/C++ и Ada кода от MathWorks.

Parasoft C++ Test – инструмент для статического анализа С++ кода, проведения code review, автоматического unit- и component-тестирования, определения степени покрытия тестами и регрессионного тестирования.

Parasoft Insure++ – инструмент для поиска run-time ошибок при работе с памятью.

PC-lint for C/C++ и FlexeLint for C/C++ от Gimpel Software -- статические анализаторы кода для C/C++.

Daikon – бесплатный инструмент для динамической проверки инвариантов в программе.

Frama-C – бесплатный инструмент для анализа C-шного кода с возможностями его проверки на соответствие формальным спецификациям.

От себя добавлю еще ссылочку на каталог подобных продуктов в Wikipedia.

[life.photo] Красный Христос над Рио

Статуя Христа была подсвечена красным цветом по поводу международного дня борьбы со СПИДом.

Найдено в WSJ’s Picture of the Day.

[life.phone] Мой слон – моя субмарина

Снимок сделан на Андаманских островах: некоторые слоны любят купаться и таких слонов, когда они не работают, специально приводят на пляж для привлечения туристов.

Найдено здесь (с подачи Uma Barzy).

среда, 2 декабря 2009 г.

[comp.prog.wow] Счетчик секунд до релиза

Оказывается, на сайте проекта International Components for Unicode (ICU в просторечии) присутствует обратный отсчет времени до очередного релиза:

Это мне напоминает один из способов борьбы с курением – даешь публичное обещание не курить. И попробуй потом его нарушить! Вот так и здесь – публично пообещали, а теперь остается доказать, что “мужик сказал, мужик сделал” :)

[comp.prog.thoughts] Мысли о больших библиотеках, навеянные выходом Qt 4.6

Исторически сложилось так, что в свои C++ проекты мы стараемся подключать сторонние C++ библиотеки в виде исходников. Чтобы библиотеки собирались и пересобирались вместе с самим проектом. Так у нас к проектам подключаются, например, ACE, Poco, PCRE, Crypto++. Отдельная песня с библиотеками вроде libiconv, openssl и Qt (хотя мысль о том, чтобы таки подключать libiconv и openssl в исходниках меня периодически терзает).

Но вот с большими библиотеками, вроде Qt или Boost, такой фокус, увы, вряд ли пройдет. Уж очень они большие. Даже ACE – и тот напрягает. Хотя он в разы меньше объемов Qt и Boost-а… :(

У включения сторонних библиотек к себе в проект в виде исходников есть несколько очень важных для меня достоинств.

Во-первых, сильно упрощается настройка рабочей среды под проект. Так, у меня на рабочей машине, обычно, несколько окружений под разные компиляторы (несколько версий MS VC++, автономный MinGW, cygwin). В идеале, мне не нужно настраивать в каждом из этих окружений пути к конкретным версиям ACE и Poco. Я просто делаю checkout проекта из репозитория, захожу в нужное мне окружение, запускаю компиляцию и получаю конкретную версию конкретного проекта под конкретный компилятор.

Во-вторых, появляется возможность без проблем держать кучу разных версий одной и той же библиотеки. Например, в каких-то проектах у нас используется ACE 5.6.5, в каких-то 5.6.8. В одном проекте – Poco 1.3.3p1, в другом – 1.3.5, в третьем 1.3.5 с одним нашим баг-фиксом, в четвертом 1.3.5 со вторым баг-фиксом. Где-то внешняя библиотека компилируется как статическая либа, где-то как динамическая. Где-то в Release-режиме, где-то в Debug-режиме. Все это элементарно разруливается на уровне проекта. Но гораздо сложнее все это было бы, если бы пришлось прописывать пути к различным версиям сторонних библиотек через переменные среды INCLUDE, LIB и PATH.

В-третьих, очень легко восстановить какой-то старый проект в какой-то конкретной версии. Скажем, отдали мы заказчику три года назад версию, скомпилированную на ACE 5.4.7 и PCRE 4.3, а теперь нужно разобраться с каким-то странным ее поведением. За это время и разработчики проекта сменились, и сами эти версии стали преданиями старины глубокой. Как настраивать среду для компиляции проекта? Очень просто – делается checkout версии из репозитория. И все!

Все эта лепота работает до тех пор, пока сторонние библиотеки небольшие и их легко интегрировать в наш процесс компиляции. Но вот монстры вроде Qt, Boost или ICU в эту красивую схему не укладываются. А жаль… Нужно думать…

PS. Подробнее о нашей схеме подключения подпроектов в проект с помощью svn:externals я рассказывал когда-то в RSDN Magazine.

вторник, 1 декабря 2009 г.

[life.work] Настоящие программисты не нуждаются в еде, сне и зарплате!

Данный афоризм вспомнился благодаря чтению вот этого объявления о вакансии (фиг знает, как я на него попал). Точнее говоря, вот этому фрагменту вот этого объявления:

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

(выделение мое).

В принципе, цинично, но честно – нафига наемному рабочему платить больше того, за что он согласен работать? Не понятно только, почему не сделан завершающий логический шаг – найм программистов за еду?

[life.work] Юрий Норнштейн: технология должна быть неудобной…

Понравилась цитата из интервью Юрия Норнштейна телеканалу НТВ:

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

Юрий Норнштейн – художник-мультипликатор, автор (среди прочего) мультика “Ёжик в тумане”.

Имхо, эта фраза может быть применена не только к мультипликации, но и к программированию. Развилась, например, мощь компьютеров неимоверно – появились монстры вроде Chromium OS, с декстопными приложениями на JavaScript ;)

Хотя, с учетом очень сильной специфичности того самого “Ёжика в тумане”, может и не следует уделять этим словам Норнштейна серьезного внимания? ;)

[comp.prog] Ссылки от читателей: OCaml => JavaScript

Иногда в комментариях читатели блога дают интересные ссылки. Чтобы эти ссылки не потерялись, буду выносить их наверх отдельными заметками. Вдруг со временем пригодятся.

Cсылки на трансляторы из OCaml в JavaScript от ув.тов.Rustam:

ocamljs – транслятор OCaml-а в JavaScript (при этом используется стандартный фронт-энд компилятора OCaml-а, поэтому со временем можно ожидать полной поддержки языка).

O’Browser – виртуальная машина OCaml-а, написанная на JavaScript. Позволяет, как я понимаю, запускать в Web-страничке написанные на OCaml скрипты. В самом руководстве есть примеры того, как это выглядит – можно запустить OCaml скрипт и можно посмотреть, как он выглядит:

(как по мне, так OCaml в виде скрипта еще менее читаемый, чем в виде автономной программы ;)

понедельник, 30 ноября 2009 г.

[comp.prog; management] Субъективность при оценке чужого дизайна программы

Хорошо обучать вытачиванию деталей – сделал ученик слишком тонкую, нагрузили ее как следует – сломалась. Сделал слишком толстую, показали разницу с нормальной деталью и спросили – зачем лишний металл расходовать?

В каратэ технике обучать так же удобно: выпрямил в майя-гири опорную ногу, сенсей по ней шлепнул слегка, ласково приговаривая при этом “что прямое, то ломается” – и запомнишь урок на всю жизнь ;)

А вот в живописи уже гораздо сложнее. Еще хорошо, когда учитель говорит – здесь тени неправильно лежат при таком источнике. В крайнем случае можно ученика заставить натурный эксперимент поставить, чтобы доказать это. А вот как быть, когда недостатки формулируются как “передний план перегружен” или “тона в левом верхнем углу слишком яркие”? Есть здесь какие-то объективные критерии проверить правильность претензий учителя? По-моему, нет. Либо веришь и набираешься ума-разума. Либо не веришь и идешь к другому учителю. Ну или пытаешься доказывать всему миру, что твое видение предмета правильное :) В конце-концов, у Винсента ван Гога и Поля Гогена получилось. После смерти…

Программирование же в этом смысле является чем-то средним между слесарным ремеслом (или каратэ, если хотите) и живописью. С одной стороны, написана программа, которая работает – т.е. выполняет то, что от нее требуется. Но смотришь на ее исходник, и понимаешь, что “передний план-то перегружен”. Что можно сделать проще. Или чуть сложнее, но гибче. Понимать-то понимаешь, но когда дело доходит до объяснения… Тут-то и начинаются сложности.

Хорошо, когда буквально на пальцах можно объяснить, как сделать проще. Например, было:

int get_multiply() {
  int result = SINGLE_FACTOR;
  if( some_condition() )
    result = DOUBLE_FACTOR;
  return result;
}

а можно было бы сделать:

int get_multiply() {
  return some_condition() ? DOUBLE_FACTOR : SINGLE_FACTOR;
}

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

Хуже, когда дело касается “вкусовых” пристрастий, ведь любую более-менее серьезную задачу можно решить несколькими способами. Кто-то делает ее решение с использованием классов A, B, C и D. Мне кажется, что можно было бы обойтись классами C и D, но добавив общего предка E. Работать будет и так, и так. Но какое решение лучше? Мне на основании собственного опыта и набитых шишек может казаться, что моим способом. Моему подчиненному может так не казаться.

Аргументы “Поверь моему опыту, у тебя передний план перегружен” или “Передний план перегружен, я сказал!” не проходят. Программа работает. Как она будет расширяться в будущем – это гадание. Может как я говорю, может не так. Худшее, что здесь может произойти – это долгая и бессмысленная перепалка на тему того, какая вероятность больше (еще одна вариация соревнования “у кого длиннее”).

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

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

В общем, жалко, что аргументы “Потому, что я так сказал!” не канают… :(

PS. С программами-то еще ладно. Там хоть какие-то объективные критерии могут быть найдены. А вот с документацией куда хуже. “Этот абзац непонятен” – “Как непонятен? Я же здесь все подробно написал.” – “А мне, как читателю, непонятен.” – “Ну не знаю, я все понимаю!”

PPS. Любые совпадения с реальными персонажами, фрагментами программ и диалогов являются случайными и непредумышленными. Я описал сборный портрет молодого программиста. Сам был таким в районе 1992-1999 годов, особенно в части документации.

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

[comp.prog.ace] Библиотека ACE обновилась до версии 5.7.5

Новость для тех, кто интересуется: вышла версия 5.7.5 библиотеки ACE (так же обновились TAO и CIAO). Из изменений заявлены поддержка MaxOS X Snow Leopard, улучшение поддержки LynxOS и Interix, добавлена обертка для strsignal() (но я могу и ошибаться). Плюс несколько баг-фиксов.

Сам я на ветку 5.7.* так и не перешел пока. В одном проекте мы используем модифицированную версию 5.6.5 (там мы доработали ACE-овский класс для работы с COM-портами, но наши изменения в сам ACE до сих пор не приняты), в остальных проектах, если не ошибаюсь, версия 5.6.8. Работает стабильно, глюков не наблюдается, переходить на 5.7.* стимулов нет :)

воскресенье, 29 ноября 2009 г.

[life.photo] Морские фотографии Дмитрия Виноградова

Просматривая сегодня Photoline.ru нашел ссылку на фотографии Дмитрия Виноградова. Некоторые из них очень понравились.

Стая

Полет валькирий

Portrait of one old lady

Жизнь в океане

Стеллс

Andaman Sky

Молитва (Средиземное море, Мальта. Статуя Христа, установленная Ж.И.Кусто на глубине 36 метров в 1995г.)

И в завершении не морской, но очень хороший и выразительный черно-белый снимок под названием “Старик” (сразу Эрнест Хемингуэй вспоминается почему-то):

[life.cinema] Очередной кинообзор

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

Во имя чести. Очень мощный фильм. Сцены боев, пожалуй, самые внушающие из всего виденного (похоже, в этом смысле он переплюнул и “Спасти рядового Райана” и “38-ю параллель”). Сильные впечатления остаются после просмотра. Похожие на те, которые были после наших "Они сражались за Родину" и "Батальоны просят огня".

Добро пожаловать в Zомбиленд. Динамичная черная комедия. Пока смотришь – прикольно. После просмотра вспомнить можно разве что Билла Мюррэйя в роли Билла Мюррэйя. Но на один раз любителям жанра вполне сойдет.

Пандорум. Средней руки фантастика. Один раз посмотреть вполне можно, но не шедевр.

2012. Фантастически впечатляющие сцены разрушений. Но сюжет – полнейшая галиматья.

Элитный отряд. Очень мощный и суровый фильм. Особое звучание он получает в связи с тем, что очередные Олимпийские Игры пройдут как раз в Рио-де-Жанейро. После просмотра задумываешься – а степень коррупции в наших МВД сравнима с показанным в кино?

Джони Д. Хороший фильм. Любителям ретро-боевиков про 1930-е год в США может понравится. По-моему, и Джонни Депп, и Кристиан Бэйл отлично справились со своими ролями. Отдельно я бы отметил операторскую работу – временами создается впечатление, что это ты сам двигаешься с камерой.

28 дней спустя. Хотя фильм и не новый, но посмотрел его впервые. Понравилось. Очень неожиданный подход к рассказу очередной истории на тему "смертельного вируса, превращающего людей в зомби". И если похожий чем-то по сюжету "28 недель спустя" берет своим экшеном, то этот фильми – психологизмом.