Глава 2. Почему мы переписываем программы

Станислав Иевлев

Содержание

ncursesxx/ndk++ vs. ncurses++
osec vs. AIDE, tripwire, mtree
alternatives vs. update-alternatives
csed vs. color-gcc

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

Мы же хотим от приложений: высокой масштабируемости (адекватного соответствия функциональности и имеющихся ресурсов) и максимально возможного использования готовых решений из системных библиотек, хорошей поддерживаемости кода и лёгкой адаптируемости к новым условиям.

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

Как писать хорошо масштабируемые приложения? Аккуратное разделение на слои и организация конвейеров, удачный выбор структур данных, протокола, конфигурационного файла. UNIX предоставляет готовые примитивы для организации конвейеров, и если приложения будут ими пользоваться, то будут содержать меньше ненужного кода. Почему-то зачастую библиотеки пытаются собрать в себе всю возможную функциональность, когда как проще разделить одну библиотеку на несколько небольших. Очень хорошо, если библиотека верхнего уровня не будет использовать недокументированные функции библиотеки нижнего уровня, ибо тогда будет легко изменять/заменять её по частям.

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

ncursesxx/ndk++ vs. ncurses++

curses — отличный пример неудачно спроектированной библиотеки. C++ bindings к ncurses отражают всю громоздкость и неразбериху этой библиотеки, пытаясь охватить сразу всё, что только возможно. Мы предлагаем свой вариант. Это пример правильного разделения библиотеки на слои, ncurses++ предоставляет только базовую функциональность: работа с окнами (изменение размера, перемещение, рисование) и терминалами (ввод/вывод, изменение атрибутов). ndk++ — поддержка событий и сложных виджетов. Что ещё в самом ncurses планируется переделать в том же ключе: terminfo — пример смешения вывода и получение информации из базы, ncurses — смешение ввода и вывода данных в окна.