Критика
Вам никогда не хотелось вернуться к уже законченному проекту и переделать его заново? Нет, дело даже не в том, что наш шаблон фильтра чем-то плох. Просто сейчас я оглядываюсь назад и думаю о том, что многое можно было сделать по-другому.
В целом шаблон получился вполне приличным, и я уже воспользовался им при написании нескольких программ, от самых примитивных до чрезвычай но полезного потокового редактора.
Пожалуй, требования к командной строке получились излишне строгими - все параметры должны указываться с помощью префиксов, не поддерживается работа с конфигурационными файлами. С одной стороны, это не так уж страшно, зато программирование заметно упрощается. С другой стороны, поддержка конфигурационных файлов была бы нелишней, и благодаря структуре нашей программы реализовать ее не так уж сложно. Единственное, что мне еще хотелось бы изменить (и то из чисто косметических соображений) - использование типа ShortString для строковых параметров и имен файлов. Вероятно, PString или PChar будет работать более эффективно.
С TFilterFile дело обстоит иначе. Этот класс реализует абсолютный минимум функций, необходимых для файлового ввода/вывода. Вероятно, вы уже заметили, что в нем отсутствует механизм блочного чтения/записи, а также возможность произвольного доступа к файлам1. Многие программы-фильтры используют одну или обе из этих возможностей. Блочные операции реализуются довольно просто - следует лишь воспользоваться нетипизиро ванным параметром var и счетчиком байтов по аналогии со стандартными процедурами BlockRead и BlockWrite. Эти процедуры должны выполнять блочный обмен данными между пользовательской структурой и буфером объекта. Не забудьте реализовать чтение и запись в файл в случае необходимости.
1Все перечисленные функции (кроме автоматической буферизации) реализованы в файловом потоке TFileStream, описанном в модуле Classes. - Примеч. ред.
Для операций GetByte и PutByte я воспользовался методами, а не свойства ми. С минимальными изменениями в TFilterFile можно было определить два свойства:
property InByte : byte read GetByte;
property OutByte : byte write PutByte;
а заодно превратить в свойство и Eof. Такое изменение выглядит привлека тельным в некоторых отношениях, но мне не понравилась перспектива остаться без кода возврата при вызове функции вывода. В итоге я решил оставить все три функции в виде методов. Кроме того, можно было организо вать обработку исключений ввода/вывода в блоке try/finally.
Лично меня огорчает, что байтовое значение, возвращаемое GetByte, приходится явно преобразовывать в символьный тип. Конечно, в класс TFilterFile можно было включить методы GetChar и PutChar, но черт побери! Символ - это байт, и я буду обращаться с ним, как с байтом 1. Это один из случаев, когда C ведет себя более разумно, а Object Pascal страдает излишними ограничения ми. Редко, но случается и такое. Наверное, в преобразовании типов нет ничего страшного, но я стараюсь избегать их, потому что в программировании они считаются моветоном. В сущности, вы говорите компилятору: «Да, я и сам знаю, что нарушаю правила. Заткнись и делай, что велено». Я предпочитаю избегать подобных ситуаций.
1Не следует только забывать, что на смену кодировкам OEM и ANSI постепенно приходит система Unicode, где символ - уже не байт, а слово (в Delphi - тип данных WideChar). - Примеч. ред.