Главная

Ликбез

Главная
SINT
Ликбез
Уровни
Монитор
Код

Карта

Зачем это всё?




Назад...   Далее...

Система SINT создавалась и использовалась довольно много лет, причём круг решаемых задач сильно различался в разные моменты времени, а сами алгоритмы обработки данных не раз претерпевали заметные изменения. Туда в разное время входили (и выходили) модули обеспечения диалога, графика, средства для работы с внешними устройствами, обработка прерываний, инструментарий для работы в объектах и событиях, файловая система, диспетчер памяти... в общем, какого только дерьма туда не попадало, несмотря ни на каких Оккамов и несколько крупных ревизий, во время каждой из которых общий объём кода обычно уменьшался в полтора-два раза. Поэтому я даже не буду и пытаться сформулировать, что такое SINT - всё равно не получится. Пусть будет "среда программирования". Или, как когда-то сказал один мой хороший знакомый: "SINT - это универсальный интерпретатор ВСЕГО"! Я же попробую перечислить несколько отличительных признаков, на что эта штуковина похожа. Создать что-то типа фоторобота.

Язык

С языком всё просто - как говорил Генри Форд: "Любой модуль SINT может быть написан на любом языке программирования при условии, что это язык C". И это почти не шутка: эффективность C сравнима с ассемблером, он пригоден для решения подавляющего большинства задач, поддерживается всеми платформами, удобен для программиста - удобен настолько, что зная этот язык ничего лучшего искать просто не хочется! Причём именно C, но не C++, который был отвергнут из-за крайне неудачной реализации (я бы даже сказал "дискредитации") идей объектного программирования. В своё время я пару лет вёл на форуме ixbt ветку C vs C++, где утверждал, что я на чистом C сделаю всё, что можно сделать на C++, а вот повторить на "плюсах" то, что я сделаю на чистом C не сможет никто. Того же мнения я придерживаюсь и сейчас.

К сожалению, даже такой язык, как C несколько ограничен по функциональным возможностям: затруднена инициализация неоднородных массивов, отсутствует возможность создания меток в массивах или меток межпрограммного перехода (тривиальные задачи для любого языка ассемблера). Кроме того, стандарты ANSI, UNIX или K&R не поддерживают строчных комментариев, что крайне неудобно. Поэтому в SINT допускается использование модулей на языках ассемблера (по возможности, выполненных как вставки в текст на C и транслируемых компиляторами C/C++). Мы также активно используем строчные комментарии, поскольку все зарегистрированные на сегодняшний момент компиляторы их понимают. В крайнем случае, комментарии несложно удалить программно.

Мнемоника

В SINT используется собственная мнемоника имён функций, переменных, структур, массивов. Более того: использование стандартной мнемоники запрещено (кроме операторов языка, хотя и для них можно задавать нестандартные обозначения). Это, парадоксальное на первый взгляд, требование имеет серьёзное обоснование: любой стандартный элемент может быть, при необходимости, переопределён и заменён элементом собственной разработки, чтобы наиболее полно учитывать специфические особенности реализации этого элемента для конкретного приложения. Пример: метод выдачи сообщения TypeMessage в программе, работающей в пакетном режиме может представлять собой обычную printf (хотя это не рекомендуется, поскольку может вызвать потенциальные проблемы - скажем, с поддержкой мультиязычности). Та же функция в диалоговой сборке может иметь расширенные возможности (специализированные форматы выдачи, настройку палитры), и вообще быть не функцией, а строкой событий или объектом иного класса. Примечательно, что программист прикладного уровня об этих особенностях может даже не подозревать.

Написание кода программы обычно предполагает частичное использование мнемоники производителей трансляторов, что мешает унификации синтаксиса. Но более серьёзным доводом в пользу нестандартных определений является возможность писать программы для компилятора, который в системе вообще (пока) не зарегистрирован. Кроме того, нередко условную трансляцию выгодно делать не по стандартным определениям, а по групповым, типа WINDOWS (WIN3X, WIN95, WINNT), мнемонику которых легко узнать в заголовочных файлах. Аналогичными причинами вызвано требование определения собственных типов данных, кодов клавиатуры, кодов ошибок, битовых полей, полная спецификация которых определена в заголовочных файлах и доступна после подключения файла include.h. Так, тип данных I16 всегда имеет длину 16 бит при использовании любого компилятора. Адресная переменная типа TDP (Type of Data Pointer) может быть определена для разных задач как near (2 байта), far (4 байта, сегмент и смещение) или flat (4 байта, абсолютный адрес). Аналогично определяются тип вызова функции описанием TFC (Type of Function Call) и другие специальные типы: TOH (Type of Object's Handle), OMD (Object's Model Data pointer), и т.д. Коды клавиатуры включают описание как обычных (скажем, Ctrl_F12), так и виртуальных (реально не существующих) клавиш: знаменитая k_ANY, k_DrawDesktop, k_QuitMenu - эти клавиши используют для программирования в событиях.

Организация труда программиста

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

Каждый программист работает лишь с одним (временным) файлом, где он производит отладку своих программных компонентов. Этот файл располагается в текущем каталоге программиста и изначально содержит лишь одну строчку: #include <include.h>, обеспечивающую подключение всего инструментария SINT для компилируемой программы (мнемоника, макросы, структуры данных, глобальные описания). Там же размещаются копия файла проекта, осуществляющая компиляцию и сборку SINT-программы и копия файла настройки параметров условной трансляции, в которой программист имеет возможность определить некоторые константы препроцессора и разрабатываемый им программный модуль (СУБД, текстовый редактор, шахматная программа и т.п.). Такое соглашение позволяет использовать все выполненные ранее наработки, не опасаясь разрушить уже отлаженные объекты, а также разрабатывать несколько проектов одновременно или вести параллельную разработку компонентов одного проекта разными программистами. После отладки и документирования, модули из временных файлов переносятся в SINT программистом, ответственным за проект в целом, одновременно выполняющим при этом функции ОТК. Он же предварительно регистрирует проект в среде SINT.

Регистрация состоит в перечислении требуемых приложению необходимых инструментальных модулей: звук, графика, обработка прерываний, и т.д. Полная спецификация инструментария не требуется: система в большинстве случаев уже "знает", какие именно модули необходимо подгрузить. Так, если указана необходимость работы с файлами в диалоговой программе, SINT добавит в проект средства работы с каталогами и дисками, меню выбора файла, необходимую контекстную помощь, а для задач, работающих в пакетном режиме, этот набор не будет включен. При регистрации программы указывается и используемый язык сообщений. Если языков указано более одного, формируется мультиязычная версия программы. Определение текущей версии операционной системы, как правило, осуществляется автоматически, в зависимости от выбранного для трансляции компилятора. Например, один и тот же проект будет скомпонован как Windows-приложение (при использовании компилятора MSVC++), либо как DOS-задача (BC3++).

Обработка ошибок

Описанный подход чрезвычайно облегчает работу программиста прикладного уровня и снижает требования к его квалификации, поскольку даже серьёзные ошибки в коде обычно выявляет сама система. Реальный случай: после аварийного завершения программы, в диагностическом сообщении я увидел: Функция [не помню какая] ещё не написана, обратитесь к... да-да, эта скотина нагло посоветовала мне обратиться к Владимиру Рыбинкину! Несмотря на то, что этот модуль тоже писал я сам, и много лет уж прошло, впечатление от диагностики незабываемое!

Как известно, за всё приходится платить, и недостатком данного подхода (хотя можно отнести и к достоинствам!) можно назвать резко возросшие требования к объектам системного уровня в плане их функциональности и надёжности. Именно они обрабатывают ошибки других уровней (если в состоянии с ними справиться) или выполняют корректное завершение работы программы. Кроме того, мы отказались от размещения объектов (за исключением локальных переменных) на стеке программы, что создавало бы гигантские трудности в аварийной ситуации. Да и вообще, размещение объектов в стеке (пусть не программном) нежелательно хотя бы потому, что хочется иметь произвольный порядок их освобождения. Поэтому даже в случае порчи памяти программного стека особых проблем не возникает: пользуясь информацией паспортов (статических структур данных) системного уровня, почти всегда удается восстановить информацию, необходимую для корректного завершения задачи, даже если она содержится в локальных переменных или параметрах вышестоящих по стеку функций. Очень важна также последовательность действий в аварийной ситуации: закрыть файловые буферы, затем файлы, попытаться выдать "предсмертную" диагностику, освободить ОЗУ (вначале прикладное, затем системное), восстановить вектора прерываний и т.п.

Объектное программирование

Программное обеспечение - это не только код, но и данные (классы, структуры, файлы конфигурации). Можно даже сказать, не столько код, сколько данные. Объектное программирование резко упрощает разработку и сопровождение, и в SINT этой технологии уделено особое внимание - настолько, что в настоящее время набор инструментальных средств, позволяющих программировать не только в операторном стиле, но и в объектах и/или событиях, вообще выполнен неотключаемым. Для приложений, работающих с файлами, доступно также и программирование в шаблонах, что исключительно важно при проектировании диалога или работе с базой данных.

С точки зрения программиста объектного стиля (обычно это прикладной уровень), любой объект (даже функция) есть не что иное, как данные. Поэтому, за счёт некоторого замедления выполнения операций вследствие необходимости интерпретации данных, обеспечивается высокая надежность и скорость разработки, компактность кода, лёгкость его модификации. Объём самого программирования минимален, требования к квалификации разработчика относительно невысоки. Программирование в объектах предоставляет также возможность динамического конструирования необходимых утилит даже во время работы программы (run-time), а программирование в шаблонах может перенастроить уже скомпилированную программу, заставить её выполнять действия, не предусмотренные разработчиком.

При создании любого объекта система возвращает его дескриптор (имя), и вся дальнейшая работа осуществляется только по имени. Например, программист может написать: CloseObj (Handle); При этом он имеет право ничего не знать ни о классе объекта, ни о методах реализации нужных ему действий, ни даже об их наличии. Объект зарегистрирован в системе - пусть она с ним и разбирается! Сама должна знать, что это: файл, база данных, массив ОЗУ или соединение с Интернет, сама должна уметь выполнить поставленную задачу или корректно обработать нештатную ситуацию. А программист должен знать о любом зарегистрированном в SINT методе лишь его имя, входные и выходные параметры. Эта обезличенность позволяет для каждой конкретной задачи исполнять функционально эквивалентные методы наиболее удобным для неё способом. Упомянутый выше TypeMessage не только может быть реализован объектами разных классов, но и заменён даже на этапе выполнения программы, при этом взаимодействующие с ним внешние объекты просто не заметят подмены. Вызов метода также может производиться тем способом, который наиболее удобен программисту в данный момент: функцией, событием, объектом, шаблоном.

Пример: любая SINT-программа определена нами как строка методов, и её код (кстати, единый для всех программ) настолько прост, что его можно привести прямо здесь:
I16 MainSO[] = { StartInit, StartEvents, MenuVirt, Exit, EndSO };

Как видим, программа состоит из четырёх (пятый - признак конца строки) вложенных объектов. Все разные: StartInit - строка методов (инициализирует структуры, заказывает ОЗУ, разбирается с файлом конфигурации и т.п.). StartEvents - строка событий, которые должны быть сгенерены при старте, а MenuVirt - меню, которое (первым) начнет эти события обрабатывать. Наконец, Exit - функция, завершающая работу программы. При этом визуально определить класс объекта по его имени практически невозможно (да и не нужно).

Оформление

Тексты (вместе с комментариями) не должны выходить за пределы экрана (80 символов). Строчные комментарии располагаются с 33 позиции курсора в строке. Все строки, позволяющие разместить строчный комментарий, должны его иметь. При необходимости, в теле программы могут быть глобальные комментарии, располагающиеся с первой позиции курсора. Строки после операторов if, for, switch и первый оператор после окрывающей фигурной скобки смещаются вправо на один символ относительно предыдущего текста. Длинная строка (перенос) смещается на два символа. При описании процедуры (функции) в комментариях указывается её назначение, входные и выходные параметры, имена разработчиков (соавторов) с указанием даты начала и окончания работы над модулем (любого принятого изменения - даже если это была единственная запятая, даже если изменение впоследствии было отменено).

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

Исходные коды

Несколько раз я публиковал тексты того или иного модуля SINT в разных дискуссиях, но, поскольку это всё-таки не классический C, а действительно некая среда программирования, воспринимались они примерно так:

  • Если Вы скажете, какое отношение эта абракадабра имеет к моему примеру, я буду весьма признателен.
  • Эта абракадабра делает в точности то же, что и Ваш пример - на мой взгляд, проще и элегантнее.
  • Простите, а этот код человек писал? То есть руками? Таких программистов надо выгонять с работы. Без разговоров.
  • Так я же не поленился, скопировал код и отформатировал его. Клянусь - readability не на грамм не повысилась. Как не понимал ни бельмеса в том, что там творится, так и не понял.

Одим словом, хотя тексты особой тайной не являются, публиковать из здесь не вижу особого смысла. Более правильным, видимо, будет изложение ключевых алгоритмов и других концептуальных вещей на обычном, "человеческом" языке, время от времени подкрепляя сказанное фрагментами кода. Я также не вижу смысла обсуждать протоколы обмена данными, внешние устройства (возможно, кроме самых необходимых - клавиатура, мышь, экран, файловая система) и вообще аппаратный уровень - тем более, что это скорее проблемы операционки. А вот алгоритмически интересные подходы SINT - в первую очередь, не прикладные, а системные - я и постараюсь изложить на этих страницах.
Назад...   Далее...

08.12.2017 20:43
 
`