18 декабря 2007 г.

MDA: ловушка для разработчиков

Основной смысл MDA (Model Driven Architecture) заключается в том, чтобы вся разработка программного обеспечения выполнялась на уровне модели. То есть, грубо говоря, разработчик вносит все изменения в продукт посредством рисования квадратиков, стрелочек и прочих графических элементов. А дальнейшее преобразование из схемы в конкретную реализацию для конкретной платформы должно выполняться некими автоматизированными инструментами практически без вмешательства человека.

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

Частично эта проблема решается путем спекуляции терминами типа "самодокументирующийся код", хотя на самом деле, самодокументирующийся код — это миф. Однако, я признаю, что с помощью жесткого(!) контроля над соблюдением стандартов кодирования, возможно попытаться свести к минимуму проблемы документирования изменений.

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

Теперь вернемся к MDA. Как правило, для моделирования структуры и поведения ПО обычно используется язык UML или подобные ему. На текущий момент существует довольно много инструментов, которые позволяют сгенерировать из UML-модели некий код на каком-нибудь языке программирования. И уже довольно много команд используют эти инструменты для разработки своего ПО. Это, конечно, еще ненастоящий MDA, но суть не в этом.

Суть в том, что при использовании UML-моделей проблема отсутствия документирования изменений никуда не уходит. Но в отличие от текстовых файлов, сравнение двух UML-моделей превращается в нетривиальную задачу.

Да, некоторые UML-инструменты позволяют выполнять сравнение моделей и представлять результат в каком-то читаемом виде. Однако, каждый производитель пытается сделать это своим неповторимым способом, и на сегодняшний день работоспособность, мягко говоря, оставляет желать лучшего. И что, на мой взгляд, более важно, совместимость UML-инструментов различных производителей практически равна нулю. Даже стандарт XMI каждый производитель умудряется трактовать по-своему, хотя сама цель существования стандарта — облегчить импорт/экпорт UML-моделей между инструментами различных производителей.

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

Мое мнение. На текущий момент, за отсутствием других средств, поддерживать MDA-проекты в контролируемом состоянии поможет только тщательное документирование изменений, как бы скучно это не звучало. Иного способа я пока не вижу.

29 ноября 2007 г.

Двойная загрузка grub

После установки Linux с загрузчиком grub захотелось сделать возможность двойной загрузки — Linux и Windows XP с разных физических дисков (hd0 и hd1, соответственно). В доках по установке Ubuntu и Gentoo был обнаружен пример текста grub.conf для загрузки Windows с одного из логических разделов:

title=Windows XP
rootnoverify (hd0,5)
makeactive
chainloader +1

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

title=Windows XP
rootnoverify (hd1,0)
makeactive
map (hd0,0) (hd1,0)
map (hd1,0) (hd0,0)
chainloader +1

Теперь все работает правильно :) Кстати, в процессе также обнаружил, что в Ubuntu 7, в отличие от Gentoo, можно вызывать root (hd1,0) вместо rootnoverify (hd1,0).

27 октября 2007 г.

Восхитительное чтиво

Сегодня ковырялся в Сети в поисках наилучшего перевода на русский язык сказки "Алиса в Стране Чудес". И совершенно случайно наткнулся на незнакомый мне доселе текст "Восемь или девять мудрых слов о том, как писать письма". О, какое удовольствие я получил от прочтения этой небольшой, но очень интересной статьи!.. :)

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

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

Я советую всем, кто еще не знаком с этим текстом, обязательно прочитать. Хотя бы как художественное произведение :)

24 октября 2007 г.

Искусство интервью от gamedeff

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

Читать статью на blog.gamedeff.com

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

23 октября 2007 г.

Команды bg, fg и jobs

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

Но, как говорится, век живи, век учись. Так уж получилось, что последнее время пришлось много работать по ssh на удаленных серверах. А там и редактирование, и сборка, и запуск... В общем, несколько терминалов с ssh открыть, конечно, можно, да только слишком уж неудобно. Пришлось читать букварь :)

16 октября 2007 г.

QtAda: поддержка Mac OS + скриншоты

Теперь библиотека QtAda поддерживает Mac OS X помимо MS Windows и Linux.

Кроме этого, появились первые скриншоты. Вот, например, один из них:


P.S. Плохо, что сайт библиотеки в сыром состоянии. К сожалению, ссылка download с сайта работает неправильно. Поэтому скачать последнюю версию библиотеки QtAda всегда можно с http://sourceforge.net/project/showfiles.php?group_id=193547.

28 сентября 2007 г.

QtAda 0.2.0

Сегодня вышла новая версия библиотеки QtAda — 0.2.0.

На подробный отчет у разработчиков времени пока нет, но мне дали эксклюзивный анонс, который я и публикую :)

1) Добавлена поддержка около десятка классов вокруг QTextEdit, им теперь можно пользоваться.

2) Добавлен работающий пример main_windows/dock_widgets.

3) Исправлено множество потерь памяти. Заодно оптимизировано создание, копирование и освобождение временных объектов. Как результат, на 27% уменьшилось количество выделений и освобождений памяти под временные объекты.

4) Но самое главное - это введение поддержки MS Windows! Инструкция в файле INSTALL.Windows. Работа с библиотекой под Windows требует установленных MinGW и MSYS.

Кстати, на днях ожидается появление бинарного дистрибутива библиотеки для Windows. Ждем! :)

http://qtada.sourceforge.net

Искусственный разум: кто нажмет "reset"?

Автор: Джеймс Бах (James Bach)
Оригинал: "The Future Will Need Us to Reboot It"


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

Я думаю, что ни один тестировщик не был приглашен на обсуждение этого проектного плана. Если мы даже не можем дать толковое определение разуму, то как мы можем создать нечто человекоподобное? Попытки создать машины, которые заставят людей поверить, что они очень-очень умны, мне кажутся похожими на попытки сделать Феррари из фанеры. Нет, кого-то одурачить у вас, конечно, получится, но это все равно будет не Феррари. Вера и желание никогда не превратят фанерную поделку в настоящий спортивный автомобиль.

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

В качестве примера можно привести Google Grid, показанный в видео "Epic 2014". Один из основных моментов этого видео — некий "алгоритм", который автоматически создает новости, используя отрывки информации, найденной в сети. Системы, генерирующие текст, существуют уже сегодня. Например, Racter, которому уже 25 лет. Разумеется, гугловцы думают о создании чего-то более продвинутого, но тут есть небольшая проблема. Создание осмысленного текста — это не просто манипуляция словами, не копирование случайных словосочетаний и перемешивание их в случайном порядке. Человек, пишущий для других, представляет себе своего читателя и его мир, ставит целью донести информацию и придумывает способ сделать это. Написать — означает выразить точку зрения. Добиться этого в автоматически сгенерированных текстах пока еще не удалось. Поэтому людей дурачат, предлагая суррогат вместо осмысленных текстов.

Я думаю, единственный способ создания настоящего искусственного разума — попытаться обеспечить такие условия для отдельных его свойств, при которых может произойти самообразование какой-то более высокоуровневой сетевой субстанции, подобной скоплению нейронов. Но мы никогда не узнаем может ли эта субстанция называться разумом, кроме как после длительного тестирования. Причем процесс тестирования будет очень долгим, нетривиальным и полным ошибок, ведь чем сложнее программа, тем больше в ней ошибок. Очень похоже на компьютер HAL 9000 из "Космической Одиссеи 2001" — может быть, он действительно умен, а может быть, он сошел с ума и все время врет. Никто не знает. Вызывайте тестеров.

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

Вы не согласны? Вы соберете триллионы простейших компонентов и предоставите природе сделать из этого "разум"? Да, именно так и работает эволюция, и посмотрите, сколько ошибок! Посмотрите, насколько длителен этот процесс! И как мало разумного при этом создается! Если элементарным компонентам поставить задачу создать интеллект, почему мы считаем, что результат будет положительным?

Несмотря на то, что люди создают программы, еще не одна программа не создала человека. И на это есть причины. Человек намного сложнее, чем программа. Программе, которая бы угрожала порабощением человечества, понадобилась бы еще более умная программа, чтобы исправлять в ней ошибки. А "еще более умной программе" понадобилась бы другая программа... И так далее.

Так что, мне кажется, что точка Сингулярности никогда не будет достигнута из-за того, что мы не сможем преодолеть барьер сложности. Увеличение сложности технологии неизбежно ведет к снижению ее надежности. Рост технологического прогресса требует постоянного увеличения квалифицированных специалистов. Я предполагаю, что количество энергии и ресурсов, требуемых для преодоления барьера сложности, стремится к бесконечности.

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

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

Публикуется с разрешения автора.

24 сентября 2007 г.

Причины быть тестером

На Real World Software Development опубликовали с заметку "10 Reasons Why It's Better to Be a Software Tester". Хорошая идея, но, на мой взляд, слишком уж размазано получилось. Описанные 10 причин могли бы быть сокращены до 3-4 пунктов. А так — выглядит попыткой высосать из пальца недостающие причины, чтобы дотянуть до круглого числа 10.

Вообще, тон статьи кажется слишком уж деструктивным. Ведь, цель тестировщиков совсем не "break the software developer's code". У команды тестировщиков должна быть общая цель с командой разработчиков — добиться выпуска качественного релиза, найти и исправить максимум ошибок до того, как эти ошибки обнаружит заказчик. Это выгодно всем — и тестировщикам, и разработчикам, и даже заказчику, как бы смешно это не звучало :) Поэтому, цель - это сотрудничество, а не война с разработчиками.

Еще есть странный пункт номер 6 - "You don't need to deal with marketing gurus changing requirements". Ха-ха. Как будто тестировщиков вовсе не касается что изменяется в требованиях, кем производятся изменения и с какой целью это делается? Например, в моей практике был случай, когда упущенный контроль проектного лидера над процессом постоянных изменений в требованиях привел к тому, что команда тестирования узнавала об изменениях только тогда, когда приступала к тестированию нового release candidate. В результате, тестировщикам приходилось напрямую общаться с заказчиком, чтобы выяснить, что и зачем было изменено в требованиях.

Конечно, описанный случай — это не проблема тестировщиков или разработчиков. Это, скорее, проблема управления. Но даже при более правильном управлении, изменения в требованиях часто либо вообще не отражаются в документации, либо документируются настолько скудно, что приходится прилагать усилия, чтобы получить дополнительную информацию. А от кого можно получить такую информацию? Только от заказчика, от этих самых "marketing gurus"...

Но на самом деле с двумя пунктами не могу не согласиться.

"You get to touch more areas of the application than the developer" Как это не печально, но это правда. Я все чаще сталкиваюсь с ситуациями, когда область знаний и опыта представителей команд тестирования гораздо больше, чем у обычных разработчиков. Сложно сказать, с чем это связано. Думаю, не последнюю роль в этом играет отношение к тестерам, как полу-программистам...

"If you do make the switch to software developer, you will be 10 times better than the software developers that have not been testers" Да! Да! И еще раз — да! Проверено неоднократно. Это одна из причин, почему я обеими руками за то, чтобы разработчики сами создавали unit-тесты к своему коду — окунувшись хоть на немного в процесс тестирования, разработчик изменяет свое мышление. В лучшую сторону. Даже простая мысль "как я буду тестировать этот код" ставит разработчика на ступеньку выше тех программеров, которые не задумываются об этом.

Мне кажется, что именно эти две причины нужно выписать золочеными буквами и поставить на первые два места. Остальные пункты можно выкинуть :)

7 сентября 2007 г.

Пример плохого кода

Сегодня гоняли тесты компонентов и обнаружили в логах "memory allocation error". Ну что ж, надо локализовывать... Анализ логов показал, что проблема возникает в MyClass::onInit. Решили начать с осмотра кода. Код, конечно, упрощен, но основной смысл остался:

bool MyClass::onInit(State state)
{
  if(!someObject.isReady())
  {
    std::cerr << "Can't register SomeObject."
      << std::endl;
    return false;
  }
  return BaseClass::onInit(state);
}

Похоже, что дальше нужно лезть в BaseClass::onInit(), потому как isReady() проверяет состояние объекта... Стоп! А что значит "Can't register SomeObject"? Причем тут регистрация? А ну-ка, что там в isReady()?..

...И обнаружили вот такой шедевр:

bool SomeObject::isReady()
{
  if(tryToRecover)
  {
    deinit();
    state = init(origin);
  }
  else if(!state)
  {
    state = init(origin);
  }
  return state;
}

Ошибка возникала при вызове init() — функции инициализации объекта. Но дело-то уже не в ошибке.

У меня нет слов... Засунуть в функцию проверки состояния объекта вызовы инициализации и деинициализации — это что-то. Я, конечно, понимаю, что это не конец света, но именно из таких мелочей складывается общая некрасивая картина.

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

4 сентября 2007 г.

QtAda — такого Qt мы еще не видели

Всем хорош язык Ада, да только нет для него нормальных библиотек для разработки GUI. Нормальные — это у которых соотношение времени разработка/геморрой хотя бы 60% на 40%. Так было...

Но вот, небольшая группа энтузиастов, озабоченная этой проблемой, взялась за портирование библиотеки Qt на Ada2005. И у них получилось! :) Что особенно приятно — ребята из России.

На данный момент библиотека поддерживает все фичи Qt 4.3.1. Возможно, релиз еще сыроват, но работа над библиотекой ведется непрерывно. Как бы там ни было, уже в текущей версии есть все, что нужно для разработки полноценного графического Qt-приложения.

Библиотека QtAda - http://qtada.sourceforge.net/

31 августа 2007 г.

Расширяем возможности cleartool, ч. 2

Кроме отсутствия в cleartool команды status, мне совершенно не нравится семантика команды cleartool diff. Действительно, после простой и удобной команды svn diff file.c, предназначенной для просмотра локальных изменений в файле file.c, строка cleartool diff -pre -dif file.c кажется слишком неудобной. И что самое главное — командой cleartool diff нельзя просмотреть изменения в нескольких файлах одновременно.

Но у меня есть волшебный скрипт, который неожиданно оказался вполне расширяемым :)

Итак, мне нужна простая команда diff, которая мне покажет локальные изменения для одного или нескольких файлов. Назовем ее sdiff и добавим в парсер аргументов скрипта:

case "$1" in
  sdiff) shift; sdiff $*;;
  status) shift; status $*;;
  *) $CT $*;;
esac

Теперь нужно создать функцию sdiff(), которая бы выводила изменения для всех переданных в командной строке имен файлов:

sdiff()
{
  if [ 0 = $# ]; then
    echo "ERROR: at least one argument should be passed."
    exit 1
  fi

  for T in $*; do
    echo "Index: $T"
    echo "---------------------------------------------"
    $CT diff -dif -pre $T
    echo
  done
}

Ну, вот и все. Синтаксис новой команды такой:

ct sdiff pname [pname ...]

где pname — имя файла или директории.

29 августа 2007 г.

Адское программирование

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

Сейчас, вернувшись к C и C++, я часто ловлю себя на мысли, что мне очень недостает адских возможностей. Но, как оказалось, по этому языку скучаю не я один :) Ричард Херрик так соскучился по возможностям языка Ада, что решил создать свою собственную реализацию адских ограниченных типов данных на C++, которую и предлагает нашему вниманию. И на мой взгляд, вполне достойную реализацию. К сожалению, пока речь идет только о целочисленных типах, но лиха беда начало :)

Читать статью "Ada-style Ranged Types in C++"

10 августа 2007 г.

Расширяем возможности cleartool

Так получилось, что по воле объективных причин недавно пришлось сменить систему контроля версий. До этого я использовал Subversion, и, надо признаться, с удовольствием использовал. Еще раньше был CVS, но, мне кажется, это все-таки прошлый век, и Subversion мне нравится гораздо больше. Однако, проблема Subversion в том, что в больших проектах его очень трудно использовать. Частично из-за его ограниченной производительности, частично из-за отсутствия средств автоматизации и интеграции с другими продуктами. И вот, пришлось пересесть за ClearCase, этого необъятного монстра. Говорят, много в нем хорошего, но и плохого — тоже немало. Точнее, не плохого, а неудобного. Хотя, возможно, это просто с непривычки...

В Subversion есть замечательная команда status, которая показывает все локальные изменения, произведенные с репозиторием. И хотя возможности этой команды достаточно широки, в подавляющем большинстве случаев я использовал эту команду, чтобы получить список измененных мной файлов, а также добавленных или удаленных. Обычно это делалось перед занесением изменений в репозиторий. В CVS для этих целей применялась команда update.

Используя cleartool, — консольный инструмент для работы с репозиторием ClearCase, — я обнаружил, что не могу найти простого и легкого способа получить список измененных мной файлов. Возможно, я плохо искал, но перерыв man и документацию по cleartool, я не нашел команды, аналогичной svn status. (Если такая команда все же есть, буду благодарен человеку, который мне ее покажет.)

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

#!/bin/sh

CT=cleartool

show_status()
{
  for T in $*; do
    PRE=" "
    $CT diff -pre -opt "-sta" $T || PRE="M"
    echo "$PRE $T" | tr -s "//" "/"
  done
}

status()
{
  CT_LSCO="$CT lsco -s -cvi -me"
  show_status `$CT_LSCO $*`
}

case "$1" in
  status) shift; status $*;;
  *) $CT $*;;
esac

Файл скрипта я назвал ct (сокращенно от cleartool) и положил в папку $HOME/bin, которая прописана у меня в системной переменной $PATH. Таким образом, я могу вызвать мой скрипт из любой директории.

Итак, зачем это. Скрипт построен таким образом, что все аргументы, указанные при запуске скрипта, передаются команде cleartool. Таким образом, скрипт ct является неким псевдонимом команды cleartool. Например, команда

ct ls -r /vob/myproject/somelib

эквивалентна вызову

cleartool ls -r /vob/myproject/somelib

Однако, ct — это не просто псевдоним, а псевдоним с дополнительными возможностями. Вызвав команду ct status, можно получить список "вычекнутых" из репозитория папок и файлов текущим пользователем для текущего view. Файлы, которые были изменены, будут помечены буквой M, как и при выполнении svn status. Общий формат вызова ct status такой:

ct status [-r] [pname ... ]

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

Например, необходимо получить статус файлов и поддиректорий для папки /vob/myproject/someapp:

$> ct status -r /vob/myproject/someapp

M /vob/myproject/someapp/file.c
  /vob/myproject/someapp/file.h
M /vob/myproject/someapp/main.c
M /vob/myproject/someapp/include/types.h
  /vob/myproject/someapp/include/ext/ext.h

Результат выполнения команды показывает, что из репозитория были "вычекнуты" файлы file.c, file.h, main.c, types.h и ext.h, а изменены только file.c, main.c и types.h.

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

ct ci -c "Some text here." file.c

При обработке аргументов скриптом качычки будут проигнорированы и каждое слово будет восприниматься, как отдельный параметр. Неудобно? Наверное, да. Но лично я не использую такой вариант check in. Я использую вариант с добавлением комментария после ввода команды, поэтому для меня это неудобство проблемой не является:

$> ct ci file.c
Some text here.
.
<Ctrl+E>

26 июля 2007 г.

Ящик без денег

Сегодня хотел снять немного денег со счета через банкомат. Выбрал пункт меню "Снять наличные", ввел пин-код. Появилась надпись "Введите желаемую сумму. Сумма должна быть кратна 50 руб." Набрал сумму 1950 руб, нажал ввод... "В банкомате отсутствует требуемый номинал", сообщил банкомат. Хм...

Попробовав несколько вариантов, понял, что в этом банкомате денег мне снять не удастся: "В банкомате отсутствует требуемый номинал", невозмутимо сообщала железная коробка с деньгами на все мои попытки снять требуемую мне сумму. "Ну, если денег не даёт, так хоть удовольствие получу", подумал я и приступил к тестированию (да, я ненормальный ;).

Какие у нас есть номиналы, кратные 50 рублям? 50, 100, 500, 1000, 5000. Ну что, поехали? "Снять наличные", пин-код, 50 — "В банкомате отсутствует требуемый номинал". "Снять наличные", пин-код, 100 — "В банкомате отсутствует требуемый номинал"... Уфф... Кнопки тугие, аж пальцы заболели.

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

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

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

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

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

17 марта 2007 г.

Задачи на собеседованиях: биты и байты


  1. Написать программу, которая переворачивает порядок бит в байте. То есть, из 0xE2 (11100010) нужно получить 0x47 (01000111).

  2. То же самое, но без использования циклов.

    Подсказка:
    Если нас не интересуют циклы, то разумное объяснение этому - жесткие требования к производительности. Когда существуют требования к производительности, то всегда можно чем-то пожертвовать, например, памятью.