Всем хорош язык Ада, да только нет для него нормальных библиотек для разработки GUI. Нормальные — это у которых соотношение времени разработка/геморрой хотя бы 60% на 40%. Так было...
Но вот, небольшая группа энтузиастов, озабоченная этой проблемой, взялась за портирование библиотеки Qt на Ada2005. И у них получилось! :) Что особенно приятно — ребята из России.
На данный момент библиотека поддерживает все фичи Qt 4.3.1. Возможно, релиз еще сыроват, но работа над библиотекой ведется непрерывно. Как бы там ни было, уже в текущей версии есть все, что нужно для разработки полноценного графического Qt-приложения.
Библиотека QtAda - http://qtada.sourceforge.net/
— Откуда вы знаете, что я ненормальная? — спросила Алиса.
— Потому что ты тут, — просто сказал Кот. — Иначе бы ты сюда не попала.
— Потому что ты тут, — просто сказал Кот. — Иначе бы ты сюда не попала.
4 сентября 2007 г.
31 августа 2007 г.
Расширяем возможности cleartool, ч. 2
Кроме отсутствия в cleartool команды status, мне совершенно не нравится семантика команды cleartool diff. Действительно, после простой и удобной команды
Но у меня есть волшебный скрипт, который неожиданно оказался вполне расширяемым :)
Итак, мне нужна простая команда diff, которая мне покажет локальные изменения для одного или нескольких файлов. Назовем ее
Теперь нужно создать функцию sdiff(), которая бы выводила изменения для всех переданных в командной строке имен файлов:
Ну, вот и все. Синтаксис новой команды такой:
где pname — имя файла или директории.
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 — имя файла или директории.
Теги:
программирование,
clearcase,
linux,
shell,
unix
29 августа 2007 г.
Адское программирование
Сейчас, вернувшись к 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. (Если такая команда все же есть, буду благодарен человеку, который мне ее покажет.)
В конце концов мне надоело выполнять множество однообразных и громоздких действий, чтобы решить довольно простую, на мой взгляд, задачу, и я решил как-то автоматизировать этот процесс и облегчить себе дальнейшую работу. В результате, родился некий скрипт, который я здесь и представляю.
Файл скрипта я назвал ct (сокращенно от cleartool) и положил в папку $HOME/bin, которая прописана у меня в системной переменной $PATH. Таким образом, я могу вызвать мой скрипт из любой директории.
Итак, зачем это. Скрипт построен таким образом, что все аргументы, указанные при запуске скрипта, передаются команде cleartool. Таким образом, скрипт ct является неким псевдонимом команды cleartool. Например, команда
эквивалентна вызову
Однако, ct — это не просто псевдоним, а псевдоним с дополнительными возможностями. Вызвав команду
где pname — имя папки или файла репозитория (может быть указано несколько имен). Если pname не указывать, команда будет выполнена для текущей директории. Ключ -r переводит команду в рекурсивный режим — команда status будет выполнена для всех вложенных поддиректорий.
Например, необходимо получить статус файлов и поддиректорий для папки /vob/myproject/someapp:
Результат выполнения команды показывает, что из репозитория были "вычекнуты" файлы file.c, file.h, main.c, types.h и ext.h, а изменены только file.c, main.c и types.h.
Получившийся скрипт, конечно, далеко не идеален. Но пока у меня с ним возникла только одна проблема: невозможно передать в качестве аргумента строку, состоящую из нескольких слов. Например, вот такая команда работать не будет:
При обработке аргументов скриптом качычки будут проигнорированы и каждое слово будет восприниматься, как отдельный параметр. Неудобно? Наверное, да. Но лично я не использую такой вариант check in. Я использую вариант с добавлением комментария после ввода команды, поэтому для меня это неудобство проблемой не является:
В 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>
Теги:
программирование,
clearcase,
linux,
shell,
unix
26 июля 2007 г.
Ящик без денег
Сегодня хотел снять немного денег со счета через банкомат. Выбрал пункт меню "Снять наличные", ввел пин-код. Появилась надпись "Введите желаемую сумму. Сумма должна быть кратна 50 руб." Набрал сумму 1950 руб, нажал ввод... "В банкомате отсутствует требуемый номинал", сообщил банкомат. Хм...
Попробовав несколько вариантов, понял, что в этом банкомате денег мне снять не удастся: "В банкомате отсутствует требуемый номинал", невозмутимо сообщала железная коробка с деньгами на все мои попытки снять требуемую мне сумму. "Ну, если денег не даёт, так хоть удовольствие получу", подумал я и приступил к тестированию (да, я ненормальный ;).
Какие у нас есть номиналы, кратные 50 рублям? 50, 100, 500, 1000, 5000. Ну что, поехали? "Снять наличные", пин-код, 50 — "В банкомате отсутствует требуемый номинал". "Снять наличные", пин-код, 100 — "В банкомате отсутствует требуемый номинал"... Уфф... Кнопки тугие, аж пальцы заболели.
Выяснилось, что в банкомате нет вообще никаких денежных номиналов. Для разработчиков банковского ПО эта ситуация, видимо, не является чем-то особенным, но для меня, как для обывателя, это приципиально важно — надпись о том, что в банкомате нет ни копейки, сэкономила бы мне уйму времени и нервов. Похоже, что тестирование на юзабилити банкомат не проходил... Жаль...
* * *
В случае данного банкомата я вижу сразу две проблемы. Первую я уже описал — при отсутствии в банкомате наличности нужно потратить достаточно много времени, чтобы понять, что железный ящик денег тебе не даст. Вторая проблема вытекает из текста, предлагающего ввести требуемую сумму — сумма должна быть кратна 50 руб. несмотря на то, что такого номинала нет.
Какие решения я тут вижу:
Если реализация этих двух вариантов по каким-то причинам невозможна (во что я слабо верю), то нужно просто сообщать об отсутствии денег в банкомате после первой же попытки снять деньги, а не заставлять пользователя догадываться об этом эмпирическим путем.
Попробовав несколько вариантов, понял, что в этом банкомате денег мне снять не удастся: "В банкомате отсутствует требуемый номинал", невозмутимо сообщала железная коробка с деньгами на все мои попытки снять требуемую мне сумму. "Ну, если денег не даёт, так хоть удовольствие получу", подумал я и приступил к тестированию (да, я ненормальный ;).
Какие у нас есть номиналы, кратные 50 рублям? 50, 100, 500, 1000, 5000. Ну что, поехали? "Снять наличные", пин-код, 50 — "В банкомате отсутствует требуемый номинал". "Снять наличные", пин-код, 100 — "В банкомате отсутствует требуемый номинал"... Уфф... Кнопки тугие, аж пальцы заболели.
Выяснилось, что в банкомате нет вообще никаких денежных номиналов. Для разработчиков банковского ПО эта ситуация, видимо, не является чем-то особенным, но для меня, как для обывателя, это приципиально важно — надпись о том, что в банкомате нет ни копейки, сэкономила бы мне уйму времени и нервов. Похоже, что тестирование на юзабилити банкомат не проходил... Жаль...
В случае данного банкомата я вижу сразу две проблемы. Первую я уже описал — при отсутствии в банкомате наличности нужно потратить достаточно много времени, чтобы понять, что железный ящик денег тебе не даст. Вторая проблема вытекает из текста, предлагающего ввести требуемую сумму — сумма должна быть кратна 50 руб. несмотря на то, что такого номинала нет.
Какие решения я тут вижу:
- При выборе пукта меню "Снять наличные" нужно сразу выводит сообщение "Извините, денег нет".
- При выводе текста о вводе требуемой суммы нужно предлагать ввести сумму, кратную тому номиналу, который имеется в наличии, а не какому попало.
Если реализация этих двух вариантов по каким-то причинам невозможна (во что я слабо верю), то нужно просто сообщать об отсутствии денег в банкомате после первой же попытки снять деньги, а не заставлять пользователя догадываться об этом эмпирическим путем.
17 марта 2007 г.
Задачи на собеседованиях: биты и байты
- Написать программу, которая переворачивает порядок бит в байте. То есть, из 0xE2 (11100010) нужно получить 0x47 (01000111).
- То же самое, но без использования циклов.
Подсказка:Если нас не интересуют циклы, то разумное объяснение этому - жесткие требования к производительности. Когда существуют требования к производительности, то всегда можно чем-то пожертвовать, например, памятью.
Теги:
задачи,
программирование,
собеседования
22 сентября 2006 г.
В поисках истины
Недавно, при создании небольшой утилитки, столкнулся с проблемой инициализации указателей на массивы
Проблема выглядела примерно так:
Если откомпилировать этот код и попытаться выполнить, то результат будет плачевным:
Хм, странно... Что-то не помню я, чтобы такая проблема у меня раньше возникала. А в чем же причина?
Похоже, что проблема в разнице объявления и инициализации переменных
Смотрим, что там получилось. Ага, вот оно:
При компиляции место для обеих строк резервируется в секции
Немного странно, что выражение
Интересно, что
Стоп. Раз уж я полез в другие системы, может быть и компилятор другой попробовать. Что у нас там в Windows есть? Компилятор
Ой... :-/ Это что такое? А где же "unexpected exception" или "memory access denied"?.. Неужели
Странно, но все то же самое — для первой строки в стек загоняется только указатель, а вторая полностью копируется в стек. Получается, что система тут не при чем? Все дело в компиляторе?
Пришлось лезть в MSDN и читать документацию. После недолгих поисков был найден некий ключ
А что же
Вот тут-то и пришла в голову идея заглянуть, наконец-таки, в стандарт языка Си. Параграф 6.7.8 стандарта гласит:
Эээ... И что?
Читаем внимательней — "behavior is undefined". Именно эти три слова являются причиной такого поведения моего кода под разными компиляторами. "Поведение неопределено" — этого должно быть вполне достаточно для нормальных людей, чтобы не использовать конструкции вида
Мда... Я зачем-то провел "масштабное исследование" проблемы, которое все равно меня привело туда, куда я должен был пойти в самом начале. К Стандарту. Стыдно? Да.
В чем мораль этого рассказа? Follow the standards.
char. Точнее, не с самой инициализацией, а последующим использованием такого указателя. Дело было под Linux Slackware, компилятором выступал gcc.Проблема выглядела примерно так:
#include <stdlib.h>
void myfunc (char *p)
{
*p = 'X';
}
int main ()
{
char *str0 = "Hello";
char str1[] = "Hello2";
printf("str1 => %s\n", str1);
myfunc(str1);
printf("str1 => %s\n", str1);
printf("str0 => %s\n", str0);
myfunc(str0);
printf("str0 => %s\n", str0);
return 0;
}Если откомпилировать этот код и попытаться выполнить, то результат будет плачевным:
> gcc a.c
> ./a.out
str1 => Hello2
str1 => Xello2
str0 => Hello
Segmentation fault
Хм, странно... Что-то не помню я, чтобы такая проблема у меня раньше возникала. А в чем же причина?
Похоже, что проблема в разнице объявления и инициализации переменных
str0 и str1. Первое, что пришло в голову, — посмотреть, во что превращается СИшный код на этапе ассемблирования:
> gcc -S a.c
> cat a.s
Смотрим, что там получилось. Ага, вот оно:
...
LC0:
.ascii "Hello\0"
LC1:
.ascii "Hello2\0"
...
movl $LC0, -12(%ebp)
movl LC1, %eax
movl %eax, -40(%ebp)
movzwl LC1+4, %eax
movw %ax, -36(%ebp)
movzbl LC1+6, %eax
movb %al, -34(%ebp)
...
При компиляции место для обеих строк резервируется в секции
.rdata. Но при инициализации указателя str0 в память стека просто записывается адрес размещения строки "Hello" (LC0), а при инициализации str1 в стеке резервируется нужное количество байт и туда полностью копируется содержимое второй строки (LC1). Когда мы пытаемся изменить вторую строку (которая скопирована в стек), то она без проблем меняется. А при попытке изменить первую — мы лезем в сегмент данных. Вот тут-то нас и поджидает Seqmentation fault. Неплохо...Немного странно, что выражение
char *str0 = "..." в результате дает константную строку. Ну, да ладно.Интересно, что
Seqmentation fault, как правило, возникает в системах с защитой памяти. А ну-ка, проверим, что там у нас в других системах: Solaris, gcc — то же самое; Windows, MSYS, gcc — то же... Ну, что ж, все понятно. Ура.Стоп. Раз уж я полез в другие системы, может быть и компилятор другой попробовать. Что у нас там в Windows есть? Компилятор
cl.exe от Microsoft:
> cl.exe a.c
> a.exe
str1 => Hello2
str1 => Xello2
str0 => Hello
str0 => Xello
Ой... :-/ Это что такое? А где же "unexpected exception" или "memory access denied"?.. Неужели
cl генерирует принципиально другой код? Ну-ка, cl, покажи, что там у тебя в ассемблере:
...
$SG829 DB 'Hello', 00H
ORG $+2
$SG831 DB 'Hello2', 00H
ORG $+1
...
mov DWORD PTR _str0$[ebp], OFFSET FLAT:$SG829
mov eax, DWORD PTR $SG831
mov DWORD PTR _str1$[ebp], eax
mov cx, WORD PTR $SG831+4
mov WORD PTR _str1$[ebp+4], cx
mov dl, BYTE PTR $SG831+6
mov BYTE PTR _str1$[ebp+6], dl
...
Странно, но все то же самое — для первой строки в стек загоняется только указатель, а вторая полностью копируется в стек. Получается, что система тут не при чем? Все дело в компиляторе?
Пришлось лезть в MSDN и читать документацию. После недолгих поисков был найден некий ключ
/GF, который, помимо прочего, заставляет компилятор размещать строковые константы в read-only memory. "If you try to modify strings under /GF, an application error occurs." Да, это обеспечит защиту строковых "констант" от модификации, но только если указать нужный ключ компилятора.А что же
gcc? Внимательно просмотрев документацию, обнаружил раздел "Incompatibilities of GCC", первый пункт которого гласил: "GCC normally makes string constants read-only." Вот так. То есть и gcc и cl могут сгенерировать код с одинаковым поведением, но первый делает это по умолчанию, а второй — только, если указать нужную опцию.Вот тут-то и пришла в голову идея заглянуть, наконец-таки, в стандарт языка Си. Параграф 6.7.8 стандарта гласит:
"...the declarationchar *p = "abc";definespwith type 'pointer to char' and initializes it to point to an object with type 'array of char' with length 4 whose elements are initialized with a character string literal. If an attempt is made to use p to modify the contents of the array, the behavior is undefined."
Эээ... И что?
Читаем внимательней — "behavior is undefined". Именно эти три слова являются причиной такого поведения моего кода под разными компиляторами. "Поведение неопределено" — этого должно быть вполне достаточно для нормальных людей, чтобы не использовать конструкции вида
char *p = "abc".Мда... Я зачем-то провел "масштабное исследование" проблемы, которое все равно меня привело туда, куда я должен был пойти в самом начале. К Стандарту. Стыдно? Да.
В чем мораль этого рассказа? Follow the standards.
16 сентября 2006 г.
Задачи на собеседованиях: строки и указатели
На собеседованиях частенько задают задачи на знание Си-строк и указателей.
Первый вариант. Нужно написать программу копирования строк без использования strcpy, strlen и прочих им подобным. Входные данные - только указатель на строку, оканчивающуюся нулем, и указатель на destination область.
Второй вариант: "развернуть" строку при копировании. То есть, если у нас есть "abcdef", то после выполнения программы мы должны получить "fedcba". В качестве входных данных - указатель на строку и можно воспользоваться strlen.
Третий вариант: "развернуть" строку на месте, не пользуясь дополнительными блоками памяти. Входные данные - как в варианте 2.
Подобные задачи советует задавать на собеседованиях Джоэль Спольски. Какими бы простыми не казались эти задачи, именно на них отсеиваются большинство кандидатов.
Подобные задачи советует задавать на собеседованиях Джоэль Спольски. Какими бы простыми не казались эти задачи, именно на них отсеиваются большинство кандидатов.
Теги:
задачи,
программирование,
собеседования,
cpp
9 июля 2006 г.
Немного о тестировании
В процессе изучения разных подходов к тестированию программного обеспечения и многолетних попыток их практического применения, в голове сформировались некоторые мысли. Попытаюсь их сформулировать, пока не убежали... Вернее, это даже не мысли, а мои убеждения, основанные на результатах применения тех или иных подходов.
Фух! Ну вот, вроде бы удалось изложить мысли не сильно сумбурно :)
- Тестирование в проекте должно быть. Если тестирования нет — на проекте можно ставить крест. Еще лучше — даже не начинать такие проекты :)
- Разработчики должны сами тестировать свой код. Причем, тесты должны создаваться разработчиками до того, как они напишут свою первую строку кода ("test first" — этот подход описан в книге Кента Бека "Test Driven Development" и применяется в экстремальном программировании). Для чего:
Во-первых, такой подход позволит создавать "чистый" код, то есть код, не содержащий ничего лишнего. Добавить в процессе кодирования пару-другую "кульных" фич, которые якобы обязательно будут использоваться — по-моему, этим болеют все разработчики. Пересилить себя и не делать этого очень трудно.
Во-вторых, тестируя свой код, разработчики начнут задумываться о том, как они будут это делать. Иногда проблема невозможности тестирования доходит до крайности, когда нужно все выбрасывать и начинать заново. Разумеется, наличие толкового архитектора должно свести такие проблемы к минимуму, но опыт показывает, что разработчики, которым наплевать на тестирование, могут свести на нет все благие начинания. Да и толковых архитекторов не так уж легко найти... Как, впрочем, и разработчиков. Но это совсем другая история :)
Третье, и самое главное достоинство этого подхода, — у разработчиков появится четкое понимание задачи, поставленной перед ними. Не редкость, когда разработчик приступает к реализации решения, не разобравшись толком, что же на самом деле требует ТЗ. Как результат — переделывание уже выполненной работы, иногда по нескольку раз, а значит, потеря драгоценного времени. - Наличие в проекте команды тестеров. Это совсем необязательно на ранних этапах проекта, но, как говорится, "must be" уже со следующей итерации. Чем они должны заниматься: анализ существующих тестов на предмет актуальности и полноты (например, на основе статического анализа кода можно выяснить, что покрытие кода тестами не приближается и к 15%, даже несмотря на то, что разработчики старательно выписывают тесты, как написано в предыдущем пункте); создание новых сценариев и тестов, которые еще не были реализованы; вообще, стремиться всячески поставить разрабатываемую систему в такую позу, чтобы она (система) с перепугу начала делать что-нибудь не то, или выдала какой-нибудь непотребный Segmentation fault. Также эти ребята должны проводить и другие виды тестирования, например, динамическое, нагрузочное и стрессовое тестирование. При этом наличие тестеров предполагает, что разработчики будут продолжать создавать часть тестов самостоятельно.
- Тестирование должно быть автоматизированным! Как говорят военные, у продукта должно быть только две кнопки — "вкл." и "пуск ракеты". Этот очень логичный подход должен применяться и здесь. Существует множество фреймворков, чтобы облегчить реализацию этого пункта. Например, семейство xUnit — эффективные и простые в обращении продукты, к тому же совершенно бесплатные. Казалось бы, автоматизация тестов — вполне логичный подход, но, к сожалению, с ужасающей регулярностью приходится наблюдать тестирование "в живую". Это когда разработчик пишет, например, функцию сложения двух чисел и вместо того, чтобы запускать набор тестов, он каждый раз запускает свою программу, вводит с клавиатуры разные числа и смотрит, что же там его программулина наскладывала... Жуть!
Фух! Ну вот, вроде бы удалось изложить мысли не сильно сумбурно :)
10 мая 2006 г.
2>&1
Я долго пытался понять правила перенаправления потоков вывода в юниксовой оболочке
Например, было непонятно, почему работает команда, перенаправляющая
Но при этом не работает вот так:
И уж совсем китайской грамотой казалась строка:
Да, мне понятно, что эта команда меняет местами потоки вывода
Всё оказалось не просто, а очень просто :) Спасибо замечательной книге "Unix Power Tools" издательства O'Reilly.
Дело в том, что оболочка, при разборе параметров командной строки, читает параметры строго слева направо. Этот факт кажется совсем неудивительным, но оказывается именно это правило оказывает влияние на результат обработки командной строки.
Разберем, как интерпретируется строка "
А как интерпретируется строка "
После этого совсем не трудно понять, как работает команда "
bash. Действительно, вроде всё понятно, но...Например, было непонятно, почему работает команда, перенаправляющая
stderr в stdout:ls *.txt *.err >file 2>&1Но при этом не работает вот так:
ls *.txt *.err 2>&1 >fileИ уж совсем китайской грамотой казалась строка:
cat file 3>&2 2>&1 1>&3Да, мне понятно, что эта команда меняет местами потоки вывода
stderr и stdout. То, что выводилось в stdout, теперь будет выводиться в stderr и наоборот. Но почему именно так и никак иначе?..Всё оказалось не просто, а очень просто :) Спасибо замечательной книге "Unix Power Tools" издательства O'Reilly.
Дело в том, что оболочка, при разборе параметров командной строки, читает параметры строго слева направо. Этот факт кажется совсем неудивительным, но оказывается именно это правило оказывает влияние на результат обработки командной строки.
Разберем, как интерпретируется строка "
ls *.txt *.err >file 2>&1":- параметр "
>file" — означает "перенаправить стандартный поток вывода (stdout) в файл c именемfile"; - параметр "
2>&1" — означает "перенаправить стандартный поток ошибок (2) в стандартный поток вывода (1). Но, так как стандартный поток вывода уже перенаправлен в файл, то и стандартный поток ошибок перенаправляется туда же.
А как интерпретируется строка "
ls *.txt *.err 2>&1 >file"?- параметр "
2>&1" — означает "перенаправить стандартный поток ошибок в стандартный поток вывода". На этот момент поток вывода (1) направляется в терминал, а значит, что поток ошибок тоже перенаправится в терминал. - параметр "
>file" — означает "перенаправить стандартный поток вывода (stdout) в файл c именемfile".
После этого совсем не трудно понять, как работает команда "
cat file 3>&2 2>&1 1>&3". Тут тоже все просто:- поток вывода 3 перенаправить туда же, куда выводится поток вывода 2 — в
stderr; - поток вывода 2 перенаправить туда же, куда выводится поток 1 — в
stdout; - поток вывода 1 перенаправить туда же, куда выводится поток 3 — в
stderr
stderr и stdout как будто меняются местами — поток 1 идет в stderr, а поток 2 идет в stdout.
Подписаться на:
Сообщения (Atom)