Файл: Классификация языков программирования.Критерии выбора среды и языка разработки программ.pdf

ВУЗ: Не указан

Категория: Курсовая работа

Дисциплина: Не указана

Добавлен: 31.03.2023

Просмотров: 423

Скачиваний: 2

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.

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

Например, язык программирования содержит три элементарных типа данных (целый, вещественный с плавающей точкой и символьный), а также две конструкции данных (массив и указатель).[41] Если обе конструкции могут применяться к этим типам и самим себе, то говорят об их ортогональности, обеспечивающей создание большого количества структур данных.

Когда конструкции языка ортогональны, язык легче выучить и использовать для чтения и создания программ, ведь в нём меньше исключений и специальных случаев, требующих запоминания.[42]

В некоторых языках наблюдается недостаток ортогональности. В языке Pascal функции могут возвращать значения только скалярного или указательного типа, а в языках С и С++ – значения всех типов, за исключением массивов (трактовка массивов в этих языках отличается от трактовки остальных типов).

В языке C локальные переменные могут быть определены только в начале блока (составного оператора), а в C++ переменные определяются в любом месте блока (но, конечно, перед использованием).

В языке Java величины скалярных типов (символьного, целого, вещественного и т. д.) не являются объектами, а величины всех остальных типов считаются объектами.[43] Скалярные типы называют примитивными типами, а типы объектов — ссылочными типами. Примитивные типы используют семантику значения (значение копируется во время присваивания). Ссылочные типы используют семантику ссылки (присваивание формирует две ссылки на один и тот же объект). Кроме того, в языке Java коллекции объектов и коллекции примитивных типов трактуются по-разному. Среди коллекций в Java только массивы могут содержать примитивные значения. Примитивные значения могут вставляться в коллекции других типов лишь в капсулах объектов оболочек. В языках Smalltalk и Python, напротив, все величины являются объектами, а все типы — ссылочными типами.[44] Таким образом, в этих языках применяется лишь семантика ссылки и все коллекции объектов создаются в ортогональном стиле.

Если ортогональности слишком много, то это может стать источником проблем. Например, из-за разрешения полной ортогональности в ходе компиляции программы не генерируются ошибки, даже при наличии комбинаций, которые логически не согласованы или крайне неэффективны при выполнении.[45]


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

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

Следующий критерий – это легкость создания программ. Она отражает удобство языка для написания программ в конкретной предметной области. Поскольку в каждой предметной области программы имеют свою специфику, очень важно выбирать язык, который ее учитывает.[46] К примеру, если это – исследование искусственного интеллекта, то тогда следует использовать язык Prolog или LISP, а при решении задач научных вычислений применять язык Fortran.

Вполне ожидаемо, что характеристики, от которых зависит этот показатель, во многом пересекаются с характеристиками читабельности, ведь чтение текста является неотъемлемым атрибутом и процесса создания, и процесса понимания программы.[47]

Составляющей легкости создания программ является концептуальная целостность языка. Она включает в себя три взаимосвязанных аспекта: простоту, ортогональность и единообразие понятий.[48] Простота языка предполагает использование минимального числа понятий. Ортогональность позволяет комбинировать любые языковые конструкции по определенным правилам. Единообразие понятий требует согласованного, единого подхода к описанию и использованию всех понятий.[49]

Простота достигается путём устранения случайных ограничений на их использование. Так, например, при реализации массивов следует разрешить их объявление для любого типа данных, допускаемого языком. Если же, наоборот, запретить массивы некоторого типа, то язык окажется усложненным, поскольку проще изучить и запомнить основные правила языка, чем связанные с ними ограничения.

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

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


Еще раз важно отметить, что ортогональность приемлема в разумных пределах. Её чрезмерная степень усложняет применение языка. Если разрешена любая комбинация элементарных конструкций, то логические ошибки программы могут просто остаться незамеченными, их не сможет выявить компилятор.[50]

При рассмотрении критерия лёгкости создания программ, важно упомянуть естественность для приложений. Синтаксис языка должен способствовать легкому и прозрачному отображению в программах алгоритмических структур предметной области. Любой из типовых алгоритмов (последовательный, разветвляющийся, циклический, параллельный) имеет естественную структуру, которая должна поддерживаться программными операторами реализующего языка. Язык должен предоставлять структуры данных, операции и структуры управления, адекватные решаемой задаче. Естественность — это одна из важнейших причин популярности того или иного языка.[51] Язык, который ориентируется на характерные черты предметной области, может сильно упростить создание для нее программных приложений. Приведем примеры языков с очевидной направленностью на решение конкретных классов задач: Prolog (поддерживает дедуктивные рассуждения), Perl (предназначен для записи различных сценариев).[52]

В критерии лёгкости создания программ нужно не забывать о поддержке абстракций. Абстракция является инструментом определения сложных структур данных и действий, при использовании которого гарантируется простота, а также игнорируются многие второстепенные детали. Абстракция устраняет пробел между структурами данных и операциями, характерными для решения задачи, и конкретными структурами данных и операциями, встроенными в язык программирования.[53] К примеру, при написании информационной системы института требуются абстрактные структуры данных студент, курс, профессор, расписание и абстрактные операции записать студента на курс и спланировать расписание для курса. Программист должен создать программные реализации этих абстракций с использованием реального языка программирования, в котором изначально они отсутствуют. После этого программные абстракции можно использовать как новые элементы и в других частях программы, не вникая в их фактическую реализацию. Язык должен обеспечивать такую возможность. Например, в языке С++ поддержка абстракций существенно выше, чем в языке С.[54]


Следующее, что рассматривается в критерии лёгкости создания программ, – это выразительность. Она может характеризовать две возможности. С одной стороны, она означает наличие очень мощных средств для представления структур данных и действий, описывающих большой объем вычислений с помощью очень маленькой программы (языки APL, Snobol, Icon, SETL).[55] С другой стороны, выразительность позволяет записывать вычисления в более удобной и компактной форме. Например, в языке С запись х++ удобнее и короче представлять в виде х = х + 1. Аналогично, булевы операции «and then» и «or else» в языке Ada позволяют указать сокращенное вычисление булевых выражений. В языке Pascal циклы с известным количеством повторений проще создавать с помощью оператора «for», чем с помощью оператора «while». Нет сомнений в том, что все эти возможности облегчают разработку программ.

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

Рассмотрим факторы, которые оказывают сильное влияние на надежность программ.

Первый фактор – проверка типов. Принципиальным средством достижения высокой надежности языка является система типизации данных.[57] В ходе проверки типов анализируется совместимость типов в программе. Разные языки обеспечивают разную полноту проверки типов. Достаточно слабой считают проверку типов в языке С. Языки с динамической типизацией вообще относят эту проверку только к периоду выполнения программы. Наиболее полную проверку гарантирует языка Ada: в процессе компиляции программы проверяются типы практически всех переменных и выражений. Такой подход фактически устраняет ошибки типов при выполнении программы. В языках Pascal, Ada и Java диапазон изменения индексов является частью объявления массива и тоже подвергается проверке.[58] Данная проверка очень важна для обеспечения надежности программы, поскольку индексы, которые выходят за пределы допустимого диапазона, часто создают серьезные проблемы.


Ещё один фактор – обработка исключений. Исключением называют аварийное событие, которое обнаруживается во время выполнения программы (аппаратом исключений). В результате авария устраняется, и программа продолжает работу. Подобный механизм значительно повышает надежность вычислений. Языки Ada, C++, C# и Java позволяют обрабатывать исключения, хотя во многих других языках этот механизм отсутствует.[59]

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

В завершение рассмотрения критерия надежности стоит отметить, что на неё прямо влияют читабельность и легкость создания. Чем выше значения этих показателей, тем надежнее будет программа.[60]

Далее рассмотрим критерий стоимости. Суммарная стоимость языка программирования складывается из нескольких составляющих.[61]

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

Вторая составляющая – это размер стоимости трансляции программы, которая зависит от возможностей используемого компилятора.[62] Чем совершеннее методы оптимизации, тем дороже стоит трансляция. В итоге создается эффективный код: резко сокращается размер программы и/или возрастает скорость ее работы.[63]