If a C programmer asks "do you want to see something cool?", run away.
--John Van Enk

Friday, May 23, 2008

О пользе открытого кода в учебном процессе

Прежде чем высказаться по теме, хочу поделиться несколькими ссылками, которые могут пригодиться. Первая - Sitepoint раздают за бесплатно книгу "The Photoshop Anthology: 101 Web Design Tips, Tricks & Techniques", загрузить можно в двух вариантах - print-ready (более высокого качества) и, очевидно, для чтения с монитора. Линк на загрузку присылают на мыло. Вторая - разработчик сетевой библиотеки для С++ Boost.Asio Chris Kohlhoff рассказывает об отличиях между Asio и Boost.Asio.

Ну а теперь по теме. Хоть она и обсуждалась уже почти где только можно, я же хочу рассказать о случае, которые произошел не далее как вчера. Вчера жена делала диплом, основную часть которого составляет куча расчетов газотурбинного двигателя. Эти расчеты производятся при помощи набора консольных приложений, которые изначально писались еще во времена, когда программы хранились на перфокартах, а с приходом DOS были адаптированны под новую платформу (правда я предполагаю, что до этого они были адаптированны еще и под ЕС ЭВМ, а уж потом под DOS). Исходные данные находятся в файлах, выходные данные также записываются в файл. Казалось бы это хорошо для конвеерной обработки данных, однако формат выходных данных одного расчета не соответствует формату входных данных другого расчета.

Но не это самое досадное. Изюминка данного программного комплекса состоит в том, что с некоторой вероятностью он не работает, и на одних и тех же входных данных может рапортовать как "domain error: Math error - sqrt()" так и "Program stopped". И если по поводу первой ошибки у меня еще и возникают некоторые догадки, то относительно второй я могу лишь руками развести. Руководство пользователя крайне краткое и подсказок не дает. А эти программы используются на протяжении всего времени обучения в университете для дипломного и курсового проектирования. "Эхх, был бы исходный код" - подумал я и махнул на это все рукой,- может завтра заработает. Дизасемблировать и выяснять алгоритм у меня не было ни времени не желания.

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

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

Monday, May 19, 2008

Designing and Building Portable Systems in C++. Part II - Solutions

....продожение. Начало.

Как нетрудно было догадаться из предыдущего поста, пожалуй единственным подходящим решением проблем, возникающих при разработке портабельных систем, является абстракция и обобщенное программирование - сильные стороны C++. Описание техник можно поискать в серии книг C++ In Depth, книгах Мейерса и прочих гуру, я же приведу некоторые мысли относительно моментов, на которые следует обратить внимание, если вы используете для разработки сторонние библиотеки/компоненты.

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

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

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

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

Четвертым - maintainable ли код? Насколько легко будет споровождать его (если он открыт) в случае, если разработчики "забьют" на компонент? Насколько легко сопровождать код, написанный с использованием этой библиотеки? (так как в большинстве случаев библиотека и язык, на котором она написана, диктуют стиль программирования). Насколько легко вы воспринимаете идиомы, используемые при написании такого кода?

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

Шестым фактором является наличие возможности локализации. Можно ли использовать библиотеку/компонент в другой временной/географической зоне? нужны ли изменения?

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

Велкам в камменты, как говориться ;-).

Thursday, May 15, 2008

Designing and Building Portable Systems in C++. Part I - Problems

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

Одной из основных проблем, при написании портируемого кода на С++, являются отличия компиляторов. Несмотря на то, что сам язык описан довольно детально в стандарте, трактовки самого стандарта в станах компиляторостроителей иногда различаются. Кроме того, C++ часто ругают (вполне заслуженно) за сложность, особенно когда дело касается шаблонов. Эта сложность по определению ну никак не может облегчить жизнь как разработчикам компиляторов, так и "обычным" программистам, которые эти компиляторы используют.

Однако не только сложность языка источник проблем. Стандарт - один из этих источников. Описывая поведение большинства (но не всех) элементов языка, он, вместе с тем, оставляет некоторые из них implementation-defined, unspecified или undefined. В тексте документа приводится такой пример:
void f(int a, int b, int c)
{
cout << "a = " << a << ", b = " << b << ", c = " << c << endl;
}

int main(int argc, char** argv)
{
int i = 0;
f(i++, i++, i++);
return 0;
}

И оговаривается, что на разных платформах результат выполнения программы будет разным

For example, on Mac OS X, using GCC 3.3, the program fragment yields the following output
a = 0, b = 1, c = 2

This is what one would intuitively expect, assuming left-to-right argument evaluation. Compiled with HP ANSI C++ A.03.57 on HP-UX 11.11, the result is the same. However,when compiled with Compaq C++ 6.5 on HP Tru64 5.1, the program yields:
a = 0, b = 0, c = 0

which may be surprising

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

"Расширения" языка, которыми зачастую грешат разработчики из обоих лагерей (MS и GNU), тоже мешают писать портируемый код. Особенно "грешат" на майкрософтовский компилер, у которого есть опция для отключения подобного рода расширений. Заодно автоматически у вас пропадает возможность использовать Platform SDK, так как его заголовочные файлы используют эти расширения. Меня самого когда-то возмущала необходимость использовать тип BOOL, вместо bool (сейчас уже правда не возмущает) и я до сих пор иногда забываю ставить новую строчку в конце файла, с раздражением наблюдая ворнинги компилятора.

Типы. На разных платформах фундаментальные типы могут иметь разный размер. Поэтому если в вашей программе необходимо 32 битное беззнаковое целое, то проще всего, наверное, определить свой тип в заголовочном файле сразу, чем потом по всему коду выискивать и менять unsigned на myint32_t. В стандарте языка С ISO/IEC 988:1999 к стати есть типы int8_t, int16_t, int32_t, int64_t, uint8_t, uint16_t, uint32_t, uint64_t, определенные в stdint.h, однако это тот случай, где С++ не обратно совместим с С. Может в следующем стандарте поправят. Там вроде как намечается соласовать стандарты. Про типы с плавающей запятой вообще отдельная сказка, ее лучше почитать в оригинале.

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

Выравнивание данных. На многих архитектурах данные обычно выравниваются на границу слова, что иногда может приводить к проблемам. В частности, приводится следующий пример:
struct Header
{
UInt32 size;
UInt32 checksum;
};
...
void handleData(void* pData)
{
Header* pHeader = reinterpret_cast<Header*>(pData);
for (int i = 0; i < pHeader->size; ++i)
...
}

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

Там где дело касается API операционных систем дела обстоят еще хуже - совсем недавно в одном из блогов наткнулся на замечания по поводу портирования софта linux -> windows (блог к стати мне понравился, жаль ссылку потерял). Для меня, к стати, оказалась сюрпризом информация о том, что Windows NT поддерживала POSIX, а с приходом WindowsXP ее убрали.

В общем, проблем вполне достаточно. В следующей части напишу про некоторые решения, призванные прийти на помощь в борьбе за чистое небо над головой программиста... Тфу! ну в общем вы поняли ))

Tuesday, May 13, 2008

Баги - страшные и ужастные

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

Еще некоторое время назад я совершенно не понимал зачем нужны все эти обновления, хотфиксы, патчи и пр., если в большинстве случаев ПО работает корректно. Однако информация (особенно ценная), будучи одним из самых востребованных товаров, зачастую страдает от недостатка внимания к ее защите. Вы думаете, что ваш компьютер полностью защищен? Тогда взгляните хотя бы сюда. С тем обилием нелицензионного софта на просторах нашей Родины велик риск поставить себе ОС или софт с уже "предустановленными" программами - троянами, вирусами, различными руткитами )), которые тут же примутся усердно работать, собирая информацию о вас и вашей деятельности и отсылая ее своим "хозяевам". Или же вы станете частью какого-нить ботнета. Перспектив масса, но ни одна из них особо не радует. Выход остается один - выдернуть сетевой кабель из системного блока, так как ни проприетарное ни открытое ПО не защищено от уязвимостей. Зачастую слышно, что для полноценной работы в Linux нужен инет, ну никак без него.... Для других ОС ситуация обстоит так же - все обновления ПО качаются из интернета.

Ну а если уязвима например библиотека? которая используется в сотнях государственных учереждений, университетов, частных и коммерческих организациях национального и международного масштаба? А если где-то до сих пор работает софт, саппорт для которого discontinued, и используется уязвимая версия? А если этот софт управляет вашей АТС или работает в сети сотовой связи и вы не сможете однажды набрать "03"? или управляет АЭС, расположенной неподалеку от вас? или...

В общем к чему я веду -"семь раз проверь, один раз закоммить". (C) Народная программистcкая мудрость.