|
Почему именно Clipper, а не что-нибудь другоеДавайте рассмотрим Clipper, как язык и средство разработки, не обращая внимания на его конкретную реализацию под названием CA-Clipper 5.x, с точки зрения "на чем писать информационные системы". Рассмотрим основные характеристики и требования к ИС:
В данном случае, мы не претендуем на полноту списка требований, нам просто хочется показать, насколько тесно связаны требования к ИС и к языку. Любой из перечисленных параметров напрямую зависит от способностей системы разработки, на основе которой была создана ИС. Так или иначе, достоинства и недостатки средства разработки будут унаследованы в готовом конечном продукте. Хотелось бы отдельно прояснить вопрос о "надежности". У многих программистов и пользователей существует предвзятое мнение, что DBF - это очень ненадежно, что системы, построенные на xBase, подвержены разрушениям данных и индексов. Соответственно требования к средству разработки:
Можно сказать, что это общие параметры, которые собственно ничего не дают
при выборе системы разработки. И Clipper как язык вполне удовлетворяет этим
требованиям - более мощного препроцессора, чем у Clipper я не видел (разве что
fort?), RDD, OO, C-API это все имеется в наличии и очень даже хорошего
качества.
Байт код (псевдокод) или машинныйКак показывает история развития популярных ИС, практически все они имеют в том или ином виде интерпретаторы "бухязыка" для расширения ИС без изменения некоторого ядра ИС. И причем новые версии выходят со все большим использованием "бухязыков", т.е. большая часть работы ИС перекладывается на скриптовые, интерпретирующие или виртуальные машины. В качестве ярких примеров можно привести 1C, perl, rexx, php, Java, VB. Т.е. как сказал бы чукча - "тенденция, однако". К чему бы проявляется такая тенденция ? Все очень просто - на интерпретируемых языках гораздо легче выполнить требования по функциональной расширяемости и обеспечить простоту сопровождения ИС в отличие от ИС, построенных на машинных языках С/С++, ASM, Pascal и т.п. Разумеется, в рамках интерпретатора тяжело организовать алгоритмы по обработке больших массивов данных или быстродействующих программ. И для такого рода алгоритмов должна быть предусмотрена возможность подключать код, написанный на "системных" языках. Как это реализовано в том или ином языке, обсуждать не будем, только упомянем, что C-API у Clipper достаточно продвинутое для подключения практически всего, что можно написать на Си. ТипизацияВ результате переписки и споров с Maxim.Friedental@f105.n5010.z2.fidonet.org ( maxim@polyot.ru ) получился вот такай текст, добавлять и править не буду, приведу "как есть". Тест полностью написан Максимом и в большей части мы с ним согласны. Для начала определимся с терминами. Имеем сложную предметную область. Для снижения сложности мы моделируем ее путем разбиения на взаимодействующие сущности. Сущность имеет свойства. Свойство может быть либо информацией в определенном формате, либо операцией, определенной над этой информацией. Тип - это совокупность _всех_ свойств сущности. Типизация - это явное указание в тексте программы типа каждой сущности. При этом используется имя типа - идентификатор, который однозначно определяет собственно тип. При этом обычно компилятор берет на себя работу по проверке типов, т.к. типы переменных ему известны уже на этапе компиляции. Недостатки типизации таковы: 1. Недостаточная гранулированность. Например, функция на С int foo (int a, int b) { return a + b; }может принимать только аргументы типа int и приводящиеся к ним. Тем самым она накладывает ИЗБЫТОЧНЫЕ ограничения на свои аргументы. Действительно, int означает, что для a и b должны быть определены операции -, /, *, %, <, ==, >, >>, << и уйма других. Но ведь они не используются в теле функции! Сравним с той же функцией на нетипизированном Smalltalk: foo: a and: b ^ a + b.У объекта a будет вызван метод '+' и ему передан аргумент b. Функция правильно работает при ЛЮБЫХ объектах a, для которых определена операция '+' и любых объектах b. Никаких других ограничений на объекты не накладывается. Однако при этом не производится статическая проверка, и все возможные проблемы вылезают во время выполнения. Единственным на сегодняшний день решением для типизированных языков (C++, Java) является определение большого количества интерфейсов, состоящих из одного/двух методов и формирование типа каждой сущности путем множественного наследования. Это неприемлемо. 2. Статичность типизации. Весь смысл типизации заключается в статической проверке ДО выполнения программы. Если по тем или иным соображениям переменная должна менять свой тип, возникают определенные проблемы - либо язык вообще не позволяет делать такое (и такие языки уже мертвы), либо позволяет, но при этом выключаются все механизмы статической проверки типа! А учитывая то, что в типизированных языках традиционно не развита run-time поддержка информации о типах, возникает вопрос о целесообразности применения типизированного языка в данном конкретном случае. 3. Смех и грех - эквивалентность типов определяется по эквивалентности их идентификаторов, а не свойств. Например, C++ в ситуации class A { public: int var; }; class B { public: int var; };считает классы A и B - идентификаторами разных типов, хотя тип-то один и тот же. Это тоже самое, как если бы автомастерская бралась ремонтировать только желтые Жигули, и отказывалась от Жигулей всех других цветов :-) 4. Необоснованное увеличение количества ручной писанины для программиста. Это скорее проблемы неразвитости конкретных IDE, нежели типизированных языков. Например, OCAML способен догадаться из записи let x = 10, что тип x - int.Но это скорее счастливое исключение из правил. В большинстве языков тип приходится указывать вручную, более того, приходится указывать его многократно. Рассмотрим пример: int max (int a, int b) { return (a > b) ? a : b; }Здесь тип указан трижды, хотя ДОЛЖЕН был быть указан только один раз - и так понятно из назначения функции, что тип второго аргумента и возвращаемое значение будут такими же, что и тип первого аргумента. В некоторых языках (Eiffel) есть специальные конструкции для этого, но особой экономии при этом не получается. Синтаксический мусор, возникающий при типизации, существенно сказывается в основном не на затратах на написание программы, а на времени ее модификации. Это не дает полноценно применить некоторые современные методики разработки программ, например Extreme Programming (www.extremeprogramming.org). 5. Существует ряд мифов, связанных с типизацией.
Например, что
существенный процент ошибок в программе связан с ошибками, которые можно
отловить типизацией. Или что отлаживать run-time-овые ошибки типов очень
сложно. Любой пользователь Clipper-а знает, что это не так (при
нормальных средствах написания и отладки).
В настоящее время единственный аргумент ЗА статические проверки, который я нахожу разумным - это невозможность оттестировать все возможные варианты вызова всех ветвей кода. Грубо говоря, ветвь аварийного гашения реактора может в реальности никогда не быть вызванной и не протестированной, а статические проверки все-таки хоть что-то, да проверят. Максим закончил. Мне бы хотелось еще добавить один фактор - о какой типизации может идти речь при обработке данных из БД (хоть DBF, хоть результатов SQL-запроса)! Что можно проверить на этапе компиляции, если типы получаемых данных заранее неизвестны? Ну, если кому-то хочется иметь побольше проблем, то пусть обрабатывает БД на Си, до тех пор пока не надоест. Процедурная или объектная ориентацияА почему, собственно, вообще возникает такой вопрос? Почему язык не может быть одновременно и тем и другим, а может еще и чем-то третьим? Я еще понимаю, что "типизация" это принципиально. Потому, как создать типизированный run-time язык - это просто нонсенс (описание чуть выше), как и нетипизированный без run-time - что-то из области сумасшедших идей. Вопрос должен звучать несколько иначе - какой синтаксис и модель лучше использовать, чтобы не было конфликтов в компиляторе и тормозов при выполнении ? А политический выбор "ОО или неОО" пусть остается на совести писателей. Особо интересующиеся могут прочитать сравнение ОО-моделей нескольких популярных языков программирования. Собственно говоря, этот анализ прямого отношения к Clipper не имеет, но зато проясняет недостатки некоторых подходов к ОО-программированию. А вот ОО-модель Clipper даже назвать таковой стыдно. Тем более что как такого ОО и не существует, если не считать недокументированные возможности, на которые накручены через C-API несколько разных библиотек поддержки ОО. В данном случае важно только одно - компилятор Clipper поддерживает ОО-синтаксис и позволяет за счет средств расширения формировать и управлять объектами. И еще один интересный вопрос - какая ОО-модель лучше подходит для управления объектами, хранящимися в БД? Особенно, если хранилище неОО, а обычные таблицы или результаты SQL-запросов. Получается, что объекты должны наследовать структуру таблицы, а она неизвестна до ее использования, я даже не упоминаю про этап компиляции, структура становится известной лишь после открытия_БД/получения_ответа_от_SQL_сервера. Вот и получается, что структура объекта должна генерироваться в run-time, причем структура не является постоянной за время жизни объекта. И много языков таких существует ? ..... И все они скриптовые! Файл-сервер, клиент-сервер, терминал-сервер, CORBA, Active-X, GUI...Собственно говоря, никаких языковых проблем для использования всех этих технологий у Clipper не существует, есть проблемы с наличием/отсутствием нужных библиотек или Clipper-совместимых компиляторов под нужные платформы.ЗаключениеТак почему собственно Clipper, а не что-нибудь другое ?Потому что мы не знаем другого языка, который умеет столько же, сколько и clipper. |