Вам бонус- начислено 1 монета за дневную активность. Сейчас у вас 1 монета

Стили и парадигмы программирования и выбор языка программирования при разработке программного продукта. Примеры и презентация

Лекция



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

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

  • процедурный,
  • императивный
  • деларатичный
  • флаговый
  • функциональный,
  • логический
  • объектно-ориентированный.

Следует отличать понятие стиль и парадигму программирования. Парадигма программирования чаще относится к возможностям конкретного языка программирования.

Перечислим их с короткими пояснениями:

императивное программа = последовательность действий, связанных условными и безусловными переходами
процедурное программа = последовательность процедур, каждая из которых есть последовательность элементарных действий и вызовов процедур, структурированных с помощью структурных операторов if, for и while
объектно-ориентированное программа = несколько взаимодействующих объектов, функциональность (действия) и данные распределяются между этими объектами
функциональное прогамма = система определений функций, описание того, что нужно вычислить, а как это сделать — решает транслятор; последовательность действий не прослеживается
продукционное (логическое) программа = система определений и правил вида "условие => новый факт"
сентенциальное программа = система правил вида "шаблон => трансформирующее действие"
событийное программа = система правил вида "событие => новые события" + диспетчер событий
автоматное программа = конечный автомат или автомат специального типа

Морфологический ящик 2x2

Чтобы разобраться в этом мире живой природы была сделана попытка поместить все парадигмы программирования в морфологический ящик 2x2:

действия \ условия локальны глобальны
локальны императивное
глобальны сентенциальное

Эта простая классификация (Н.Н. Непейвода, " стили программирования ") уже может пролить свет на ключевые характеристики парадигм (стилей) программирования.

Классификация стилей программирования

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

Грубо говоря, эти признаки касаются способа организаций хранения данных и доступа к данным и способа организации и типа императивных данных (логики действий, зависимостей, правил обработки).

  • тип локализации (видимости) данных
    • (Global) данные глобальны
    • (Local) данные локальны
    • (Flow) данные передаются как аргументы функции
    • (NONE) данные отсутствуют
  • структура хранимых данных
    • хранилище фактов
    • храниище объектов (переменные, структуры данных, объекты)
    • состояние
  • принцип доступа к данным
    • именованный
    • адресный
    • сложный (по запросам)
      • SQL (Relational DBs)
      • Logical queries (Prolog)
    • линейный
      • FIFO (очередь)
      • FILO (стек)
  • тип императивных данных (метод описания логики работы программы)
    • действия + условные переходы
    • математические зависимости функций друг от друга
    • диаграмма переходов
    • правила вида "логическое условие -> изменение данных"
    • правила вида "шаблон -> изменение данных"
  • принцип взаимной организации имеративных и декларативных данных
    • инкапсуляция в одном (объектно-ориентированный подход)
    • декларативных данных как таковых нет, есть аргументы, поступающие на вход функциям (функциональный подход)
    • простая логика действий привязана к состояниям глобальных данных
    • ....

Примеры стилей программирования

1.Императивный стиль

Императивный стиль = последовательность команд + переходы

пример 1

Стили и парадигмы  программирования и выбор языка программирования при разработке программного продукта. Примеры и презентация

пример 2

Стили и парадигмы  программирования и выбор языка программирования при разработке программного продукта. Примеры и презентация

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

2. Процедурный стиль

Процедурный стиль = императивный + вызов других последовательностей команд (процедур)

 Стили и парадигмы  программирования и выбор языка программирования при разработке программного продукта. Примеры и презентация 

3.Флаговое программирование или флаговый стиль

В таком стиле программирования исользуюся флаги.

В программировании так называют переменные содержащие булевы значения.

 Стили и парадигмы  программирования и выбор языка программирования при разработке программного продукта. Примеры и презентация

Флаги, часто (но не всегда!), признак плохой архитектуры. Их количество часто увеличивается , условия пересекаются и накладываются друг на друга

увеличивается цикломатическая сложность.

При использовании комбинации разных флагов, усложняется анализ кода:

 Стили и парадигмы  программирования и выбор языка программирования при разработке программного продукта. Примеры и презентация

Такой стиль программирования имеет свое название: "флаговое программирование". Так говорят про код, в котором трудно разобраться из-за наличия логики, завязанной на комбинацию флагов. А наличие флагов почти наверняка к этому приведет. Все дело в том, что количество состояний у систем, как правило, больше чем две. То есть одного флага никогда не будет достаточно.

От флагов возможно уйти, введя все варианты явных состояний системы. (вместо их комбинаций)

4. Функциональный стиль

Функциональный стиль = императивный + процедуры принимают параметры и возвращают значения

  Стили и парадигмы  программирования и выбор языка программирования при разработке программного продукта. Примеры и презентация

Или второй пример аналогичного кода для п 1

Стили и парадигмы  программирования и выбор языка программирования при разработке программного продукта. Примеры и презентация

5. Объектно-ориентированный стиль

Объектно-ориентированный стиль = группировка кода в связанные классы

Стили и парадигмы  программирования и выбор языка программирования при разработке программного продукта. Примеры и презентация

6. Декларативный стиль


Декларативный стиль = Программист не отвечает за реализацию.

Стили и парадигмы  программирования и выбор языка программирования при разработке программного продукта. Примеры и презентация

7. Логический стиль

Логический стиль = Программист получает логический вывод информации на основе заданных фактов и правил вывода

пример 

Стили и парадигмы  программирования и выбор языка программирования при разработке программного продукта. Примеры и презентация

Стили и парадигмы  программирования и выбор языка программирования при разработке программного продукта. Примеры и презентация

Парадигмы программирования

Парадигма программирования — это совокупность идей и понятий, определяющих стиль написания компьютерных программ (подход к программированию). Это способ концептуализации, определяющий организацию вычислений и структурирование работы, выполняемой компьютером .

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

Также существующие парадигмы зачастую пересекаются друг с другом в деталях (например, модульное и объектно-ориентированное программирование), поэтому можно встретить ситуации, когда разные авторы употребляют названия из разных парадигм, говоря при этом, по сути, об одном и том же явлении.

Стили и парадигмы  программирования и выбор языка программирования при разработке программного продукта. Примеры и презентация

Императивное программирование

Императивное программирование характеризуется в основном:

  • в исходном коде программы записываются инструкции (команды);
  • инструкции должны выполняться последовательно;
  • каждая инструкция может изменять некое глобальное “состояние” программы

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

Практически все аппаратное обеспечение в основе своей императивное.

Декларативное программирование

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

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

К подвидам декларативного программирования также зачастую относят функциональное и логическое программирование — несмотря на то, что программы на таких языках нередко содержат алгоритмические составляющие.

“Чисто декларативные” компьютерные языки зачастую не полны по Тьюрингу — примерами служат SQL и HTML — так как теоретически не всегда возможно порождение исполняемого кода по декларативному описанию. Это иногда приводит к спорам о корректности термина “декларативное программирование”.

Неструктурное программирование

Характерно для наиболее ранних языков программирования.

В основном характеризуется:

  • строки как правило нумеруются
  • из любого места программы возможен переход к любой строке

Характерной особенностью неструктурного программирования является сложность реализации рекурсии.

Структурное программирование

В отличие от неструктурного программирования, характеризуется:

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

Концепция структурного программирования основана на теореме Бема-Якопини:

Любая вычислимая функция может быть представлена комбинацией трех управляющих структур:

  • Последовательности
  • Ветвления
  • Итерации

Последовательность – это выполнение сначала одной подпрограммы, затем другой.

Ветвление – это выполнение либо одной, либо другой подпрограммы в зависимости от значения некого булева (логического) выражения.

Итерация – это многократное выполнение подпрограммы пока некое булево выражение истинно.

Стили и парадигмы  программирования и выбор языка программирования при разработке программного продукта. Примеры и презентация

Стили и парадигмы  программирования и выбор языка программирования при разработке программного продукта. Примеры и презентация

Процедурное программирование


Программа на процедурном языке программирования состоит из последовательности операторов (инструкций), задающих процедуру решения задачи. Основным является оператор присваивания, служащий для изменения содержимого областей памяти. Концепция памяти как хранилища значений, содержимое которого может обновляться операторами программы, является фундаментальной в императивном программировании.Процедурное (императивное) программирование является отражением архитектуры традиционных компьютеров, которая была предложена фон Нейманом в 40-х годах. Теоретической моделью процедурного программирования служит алгоритмическая система под названием «машина Тьюринга».

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

Процедурные языки характеризуются следующими особенностями:

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

Процедурное программирование можно рассматривать как небольшую вариацию на тему структурного программирования, основанную на концепции вызова процедуры.

Основная идея заключается в том, чтобы сделать подпрограммы более модульными за счет:

  • локальных переменных
  • относительно простой рекурсии

Оба этих пункта реализуются за счет использования стека вызовов.

Одним из важнейших классификационных признаков процедурного языка является его уровень. Уровень языка программирования определяется семантической (смысловой) емкостью его конструкций и степенью его ориентации на программиста. Язык программирования частично ликвидирует разрыв между методами решения различного рода задач человеком и вычислительной машиной. Чем более язык ориентирован на человека, тем выше его уровень. Дадим краткую характеристику реализованным на компьютере языкам программирования в порядке возрастания их уровня.

Двоичный язык является непосредственно машинным языком. В настоящее время такие языки программистами практически не применяются.

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

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

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

Языки Ассемблера и Макроассемблера применяются системными программистами-профессионалами с целью использования всех возможностей оборудования ЭВМ и получения эффективной по времени выполнения и по требуемому объему памяти программы. На этих языках обычно разрабатываются относительно небольшие программы, входящие в состав системного программного обеспечения: драйверы, утилиты и другие.

Язык программирования С (Си) первоначально был разработан для реализации операционной системы UNIX в начале 70-х годов. В последующем приобрел высокую популярность среди системных и прикладных программистов. В настоящее время этот язык реализован па большинстве ЭВМ.

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

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

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

Basic (BeginnersAll-purposeSymbolicInstructionCode) — многоцелевой язык символических инструкций для начинающих) представляет собой простой язык программирования, разработанный в 1964 году для использования новичками. Он был разработан как простейший язык для непосредственного общения человека с вычислительной машиной. Поэтому первоначально работа велась в интерактивном режиме с использованием интерпретаторов. В настоящее время для этого языка имеются также и компиляторы.

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

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

Pascal является одним из наиболее популярных среди прикладных программистов процедурным языком программирования, особенно для ПЭВМ. Разработанный в 1970 году швейцарским специалистом в области вычислительной техники профессором Н. Виртом, язык назван в честь французского математика и по замыслу автора предназначался для обучения программированию. Однако язык получился настолько удачным, что стал одним из основных инструментов прикладных и системных программистов при решении задач вычислительного и информационно-логического характера. В 1979 году был подготовлен проект описания языка — Британский стандарт языка программирования PascalBS6192, который стал также и международным стандартом ISO 7185.

В языке Pascal реализован ряд концепций, рассматриваемых как основа «дисциплинированного» программирования и заимствованных впоследствии разработчиками многих языков. Одним из существенных признаков языка Pascal является последовательная и достаточно полная реализация концепции структурного программирования. Причем это осуществляется не только путем упорядочивания связей между фрагментами программы по управлению, но и за счет структуризации данных. Кроме того, в языке реализована концепция определения новых типов данных на основе уже имеющихся. Этот язык, в отличие от языка С, является строго типизированным. Pascal характеризуется:

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

Pascal реализован на ЭВМ различных типов, но наиболее распространен и развит для ПЭВМ. Об этом говорит сайт https://intellect.icu . В настоящее время широко используются такие версии этого языка для ПЭВМ, как BorlandPascalи TurboPascal.

Функциональное программирование


Роль основной конструкции в функциональных языках играет выражение. К выражениям относятся скалярные константы, структурированные объекты, функции, тела функций и вызовы функций. Функция трактуется как однозначное отображение из Х^ в X, где Х — множество выражений.Сущность функционального (аппликативного) программирования определена А. П. Ершовым как «... способ составления программ, в которых единственным действием является вызов функции, единственным способом расчленения программы па части является введение имени для функции, а единственным правилом композиции — оператор суперпозиции функции. Никаких ячеек памяти, ни операторов присваивания, ни циклов, ни, тем более, блок-схем, ни передачи управления».

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

Не менее жесткие решения приняты в других чистых парадигмах.

Но на практике же находят применения различные гибриды парадигм.

Аппликативный язык программирования включает следующие элементы:

  • -классы констант, которыми могут манипулировать функции;
  • -набор базовых функций, которые программист может использовать без предварительного объявления и описания;
  • -правила построения новых функций из базовых;
  • -правила формирования выражений на основе вызовов функций.

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

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

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

Основные концепции:

  • отсутствие неявных побочных эффектов
  • ссылочная прозрачность
  • отсутствие неявного состояния
  • данные и функции – это концептуально одно и то же

Основано на лямбда-исчислении

Аппликативное

Аппликативное программирование — один из видов декларативного программирования, в котором написание программы состоит в систематическом осуществлении применения одного объекта к другому. Результатом такого применения вновь является объект, который может участвовать в применениях как в роли функции, так и в роли аргумента и так далее. Это делает запись программы математически ясной. Тот факт, что функция обозначается выражением, свидетельствует о возможности использования значений-функций — функциональных объектов — на равных правах с прочими объектами, которые можно передавать как аргументы, либо возвращать как результат вычисления других функций.

Комбинаторное

Комбинаторное программирование (англ. function-level programming) — парадигма программирования, использующая принципы комбинаторной логики.

Является особой разновидностью функционального программирования, но, в отличие от основного его направления, комбинаторное программирование не использует λ-абстракцию.

На практике это выливается в отсутствие “переменных”, содержащих данные.

Сентенциальное программирование

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

Парадигма программирования проявляется не только в том, как организованы условия и действия, но также в том, как организованны данные в программе. Например, в сентенциальном программировании данные глобальны.

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

Если наоборот — глобальных переменных нет, и у функций нет никаких побочных эффектов, то скорее всего программист мыслил согласно парадигме функционального программирования.

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

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

Можно сказать, что функциональное и автоматное программирование дуальны по отношению к организации данных: в автоматном программировании данные глобальны, а в функциональном — локальны.

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

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

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

Логическое программирование

Новую область — логическое, или реляционное программирование, — открыло появление языка PROLOG {Пролог} (PROgramminginLOGic — программирование в терминах логики). Этот язык был создан французским ученым А. Кольмероэ в 1973 году. В настоящее время известны и другие языки, однако наиболее развитым и распространенным языком логического программирования является именно Пролог. Так, имеется свыше 15 различных его реализации на ПЭВМ. Языки логического программирования, в особенности Пролог, широко используются в системах искусственного интеллекта, рассматриваемых в данном учебном пособии.

Центральным понятием в логическом программировании является отношение. Программа представляет собой совокупность определений отношений между объектами (в терминах условий или ограничений) и цели (запроса). Процесс выполнения программы трактуется как процесс общезначимости логической формулы, построенной из программы по правилам, установленным семантикой используемого языка. Результат вычисления является побочным продуктом этого процесса. В реляционном программировании нужно только специфицировать факты, на которых алгоритм основывается, а не определять последовательность шагов, которые требуется выполнить. Это свидетельствует о декларативности языка логического программирования. Она метко выражена в формуле Р. Ковальского: «алгоритм = логика + управление». Языки логического программирования характеризуются:

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

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

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

Самым известным языком логического программирования является Prolog.

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


В основе объектно-ориентированного стиля программирования лежит понятие объекта, а суть его выражается формулой: «объект = данные + процедуры». Каждый объект интегрирует в себе некоторую структуру данных и доступные только ему процедуры обработки этих данных, называемые методами. Объединение данных и процедур в одном объекте называетсяинкапсуляцией и присуще объектно-ориентированному программированию.Прототипом объектно-ориентированного программирования послужил ряд средств, входящих в состав языка SIMULA-67. Но в самостоятельный стиль оно оформилось с появлением языка SMALLTALK, разработанного А. Кеем в 1972 году и первоначально предназначенного для реализации функций машинной графики.

Объектно-ориентированное программирование основано на концепции “объекта”.

Объекты могут содержать данные (поля, свойства, аттрибуты) и поведение (код, процедуры, методы).

Наиболее популярной формой ООП является ООП на основе классов. В данном подходе, все объекты являются экземплярами классов, и классы определяют так же тип объектов.

Одной из альтернатив является прототипное наследование. Прототипное наследование не использует классов. Вместо этого, одни объекты могут быть объявлены “прототипами” других объектов – при этом методы и поля прототипа становятся доступны как методы и поля нового объекта (если, конечно, новый объект их не переопределяет)

Стили и парадигмы  программирования и выбор языка программирования при разработке программного продукта. Примеры и презентация

Для описания объектов служат классы. Класс определяет свойства и методы объекта, принадлежащего этому классу. Соответственно, любой объект можно определить как экземпляр класса.

Программирование рассматриваемого стиля заключается в выборе имеющихся или создании новых объектов и организации взаимодействия между ними. При создании новых объектов свойства объектов могут добавляться или наследоваться от объектов-предков. В процессе работы с объектами допускается полиморфизм — возможность использования методов с одинаковыми именами для обработки данных разных типов.

К наиболее современным объектно-ориентированным языкам программирования относятся C++ и Java.

Язык C++ был разработан в начале 80-х годов Б. Страуструпом, сотрудником лаборатории Bell корпорации AT&T. Им была создана компактная компилирующая система, в которой за основу был взят язык С, дополненный элементами языков BCPL,Simula-67 и Algol-68. К июлю 1983 года появился язык С с классами, а чуть позднее — C++. К 1990 году была выпущена третья версия языка C++, принятая комитетом ANSI в качестве исходного материала для его стандартизации.

В 1990 году сотрудник корпорации Sun Д. Гослинг на основе расширения C++ разработал объектно-ориентированный язык Oak, основным достоинством которого было обеспечение сетевого взаимодействия различных по типу устройств. Новая интегрируемая в Internet версия языка, получила название Java. Первый броузер, который поддерживал язык Java, разработан программистом корпорации Sun П. Нафтоном и получил название HotJava. С января 1995 года Java получает распространение в Internet.

Согласно официальному определению авторов, Java является простым объектно-ориентированным и архитектурно-нейтральным языком интерпретирующего типа, обеспечивающим надежность, безопасность и переносимость, обладающим высокой производительностью в сочетании с многопоточностью и динамичностью.

Принципиальной разницей между Java и C++ является то, что первый из них является интерпретируемым, а второй — компилируемым. Синтаксис языков практически полностью совпадает.

С точки зрения возможностей собственно объектно-ориентированных средств язык Java обладает рядом преимуществ перед языком C++. Так, язык Java демонстрирует более гибкую и мощную систему инкапсуляции информации. Механизм наследования, реализованный в Java, обязывает к более строгому подходу к программированию, что улучшает надежность и понимаемость кода. Язык же C++ обладает сложной, неадекватной и трудной для понимания системой наследования. Возможности динамического связывания объектов одинаково хорошо представлены в обоих языках, однако, синтаксическая избыточность C++ заставляет и здесь отдать предпочтение языку Java.

В силу своей конструктивности идеи объектно-ориентированного программирования используются во многих универсальных процедурных языках. Так, например, в состав интегрированной системы программирования на языке PASCAL (корпорации BorlandInternational) версии 5.5 входит специальная библиотека объектно-ориентированного программирования TurboVision.

В последнее время многие программы, в особенности объектно-ориентированные, реализуются как системы визуального программирования. Отличительной особенностью таких систем является мощная среда разработки программ из готовых «строительных блоков», позволяющая создать интерфейсную часть программного продукта в диалоговом режиме, практически без кодирования программных операций. К числу объектно-ориентированных систем визуального программирования относятся: VisualBasic, Delphi, C++ Builder и Visual C++.

Презентация по стилям программирования

Стили и парадигмы  программирования и выбор языка программирования при разработке программного продукта. Примеры и презентация

Стили и парадигмы  программирования и выбор языка программирования при разработке программного продукта. Примеры и презентация

Стили и парадигмы  программирования и выбор языка программирования при разработке программного продукта. Примеры и презентация

Стили и парадигмы  программирования и выбор языка программирования при разработке программного продукта. Примеры и презентация

Стили и парадигмы  программирования и выбор языка программирования при разработке программного продукта. Примеры и презентация

Стили и парадигмы  программирования и выбор языка программирования при разработке программного продукта. Примеры и презентация

Стили и парадигмы  программирования и выбор языка программирования при разработке программного продукта. Примеры и презентация

Интегрированная модель системы

Стили и парадигмы  программирования и выбор языка программирования при разработке программного продукта. Примеры и презентация


Диаграмма вариантов использования используемая в мнтегрированной моделе системы

Стили и парадигмы  программирования и выбор языка программирования при разработке программного продукта. Примеры и презентация


Диаграмма классов в мнтегрированной моделе системы

Стили и парадигмы  программирования и выбор языка программирования при разработке программного продукта. Примеры и презентация

Отношения между классами

Стили и парадигмы  программирования и выбор языка программирования при разработке программного продукта. Примеры и презентация

Диаграмма кооперации в мнтегрированной моделе системы

Стили и парадигмы  программирования и выбор языка программирования при разработке программного продукта. Примеры и презентация

Сравнение стилией и парадигм программирования

Таблица: Типы входных данных в различных парадигмах

тип входных данных Парадигмы программирования
аргументы (flow) функциональное
глобальные (global) автоматное, сентенциальное, продукционное
локальные (local) (создание временных локальных объектов используется во многих стилях)
события (event) событийное

Для того, чтобы различить автоматное, сентенциальное, продукционное программирования, следует посмотреть на то, как устроены данные в глобальном хранилище данных и как устроена обработка данных (тип императива).

Таблица: Организация глобального хранилища

Парадигмы программирования структура хранимых данных тип императива
автоматное состояние диаграмма переходов
продукционное (логическое) факты (n-арные отношения) правила вида (логическое условие -> новые факты)
сентенциальное текст (произвольные данные, обычно записанные на некотором формальном языке) правила вида (шаблон -> трансформация)

Иногда рассматривают расширенное состояние автомата как прямое произведение макро-состояния (режимов) и состояния памяти (значений глобальных переменных). Вершины соответствуют режиму. Считывание входных данных в автоматном программировании может происходить в каждой вершине (в каждом режиме).

Например, телефон имеет следующие макро-состояния (режимы):

  • ожидание звонка
  • кто-то звонит
  • идет разговор, установлено соединение
  • просмотр телефонной книжки
  • навигация по меню

Поток входных данных — это последовательность нажимаемых клавиш и (параллельно!) принимаемые телефоном сигналы.

Глобальными переменными (памятью) являются все настройки, адресная книга, списки вызовов, SMS сообщения, флаги о пропущенных вызовах или полученных SMS сообщениях и др.

Множество состояний телефона = Множество режимов x Множество состояний памяти

Конечно, значение режима также отображается в виде значения какой-то ячейки памяти, но программистам часто удобно делить всю память (или множество бит, определяющих состояние телефона) на режим и память. Это деление условно и целиком определяется программистом.

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

Программа относится к автоматному стилю тогда, когда значительная часть логики программы заключена в диаграмме переходов между режимами.

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

Глобальные настройки телефона являются ярко выраженными глобальными данными. Остальные данные связаны с конкретными режимами.

И здесь мы подбираемся к объектно-ориентированному программированию.

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

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

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

Таблица базовых парадигм программирования

стили\признак Единица программы Входные декларативные данные Выходные декларативные данные Входные императивные данные Выходные императивные данные Модульность
Автоматное программирование transition_act dequeued token from global_queue changed global_state make transition (atom) none, {events}, {enqueue tokens to global_queues of other automats} Libraries:
automats
Функциональное программирование definition flow flow calculate calculate others (composite) Libraries:
functions
Процедурное программирование procedure flow,{global} flow,{global} execute execute others (composite) Libraries:
procedures
Сентенциальное программирование transform rule (pattern->transform action) global global query query subqueries Libraries:
transformation rules
Логическое программирование inference rule (logical condition->new fact) global global query query subqueries Libraries:
inference rules + facts

Таблица характеристик типичных парадигм программирования для базовых языков программирования

язык\признак Единица программы Декларативные данные Императивные данные Модульность
Assembler action_simple(Global:restricted) + data_simple Global:(named+addressed)_simple+FIFO Procedures:Local+Global Libraries:
Functions
Си action_macro(Flow+{Global}) + data_simple (Global + Local):(named+addressed)_simple+Flow Procedures:Local+Global Libraries:
Functions
Prolog Rule+Fact+Query Global:[d]named_relations Rules:Global Libraries:
(Rules+Facts)
Haskell Function(Flow) Flow Functions:Global Libraries:
Functions
Tcl Function(Flow+Global) (Global+Local):[d]named_structures Functions Namespace:
(Functions+Objects)
Java Class() (Global+Local):named_(simple+dobjects) Functions Namespace:
(Functions+Classes+Objects)

Другие характеристики языков

Остальные характеристи языков хотелось бы вынести за понятие парадигмы программирование. Их очень много, они касаются конкретных маленьких (но довольно важных) деталей.

Динамическое пространство имен

Если язык допускает именованние единиц данных, то возникает вопрос о возможности изменения имен и создания новых именованных единиц во время выполнения программы.

Скриптовые языки Tcl, Perl, ... позволяют это делать. Языки С, С++. Java, Pascal — нет. Имена переменных в этих языках задаются на этапе написания программы.

В языке Prolog хранимые данные есть множество фактов — n-арных отношений. Эти отношения имеют имена, а отдельные факты обычно не именуют (хотя потенциальная возможность есть). Таким образом, в Prolog есть возможность динамического именования отношений.

Наличие типизирования

Язык называется типизированным, если и к каждой единице данных привязан определенный тип данных (целое число, символ, строка, объект класса A, ...).

C, Pascal, Java, Ruby, ... — типизированные языки программирования.

Perl, Python, — нетипизированные (слаботипизированные) языки программирования. Типы в этих языках присутствуют -- они различают функции, хэштаблицы, скаляры, массивы. Про эти языки правильно говорить, что у них отсутствует типизация скалярных типов данных.

SQL — типизированный язык программирования, но без возможности именования отдельной единицы данных (ячейки таблицы).

Динамическое типизирование

Если для именованных единиц данных в типизированном языке программирования есть возможность менять тип данных в ходе выполнения программы, то говорят, что язык с динамическим типизированием.

Ярким примером является язык Ruby, где в случае, когда результат арифметической операции приводит к целому числу, большему 232, результат (и переменная, в которую он помещается) автоматически меняет тип с FixedInteger на BigInteger.

Полиморфизм сущностей

Если в языке программирования за одним и тем же именем могут скрываться различные сущности, то говорят, что в языке реализован полиморфизм объектов.

Какую из сущностей использовать в каждом конкретном случае, транслятор языка определяет из контекста, в котором встретилось имя.

Например, если программе на языке Perl если после имени стоит квадратная скобка, то используется массив с данным именем, а если стрелка (->) — то используется хэштаблица с данным именем. Это две сущности, которые содержать принципиально различные данные, но имеют одно и то же имя.

Полиморфизм функций

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

Обычно, какую именно функцию имел в ввиду программист, транслятор языка определяет из количества переменных и типов переданных аргументов.

Полиморфизм функций встречается в типизированных языках программирования, но бывают и исключения.

Можно считать, что полиморфизм функции есть частный случай полиморфизма сущностей.

Примеры программ с разными парадигмами

Здесь мы рассмотрим подробнее различные парадигмы программирования, и постараемся привести наиболее яркие демонстирующие их примеры программ.

Императивное программирование

Императивное программирование — программирование от "глаголов". Программы представляют собой последовательность действий с уловными и безусловными переходами. Программист мыслит в терминах действий и выстраивает последовательности действий в более сложные макро-действия (процедуры).

 Стили и парадигмы  программирования и выбор языка программирования при разработке программного продукта. Примеры и презентация

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

Кроме того, он знает входные условия (prerequisites) для каждого действия и старается им удовлетворить. Проверку этих условий полезно производить внутри самой процедуры в самом ее начале.

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

Это позволяет отловить многие ошибки на этапе тестирования программы.

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

Чем императивное программирование отличается от процедурного?

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

Что такое структурное программирование?

Термин структурное программирование ввел Э.Дейкстра в 1975 году:
  • Э.Дейкстра "Заметки по структурному программированию" (в составе сборника "Структурное программирование" / М.: "Мир", 1975.
  • Э.Йордан "Структурное проектирование и конструирование программ" / М.: "Мир", 1979.
Можно рассматривать структурное программирование как стиль написания программ, исключающий оператор go to.

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

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

Объектно-ориентированное и событийное программирование

Объектно-ориентированное программирование — это программирование от объектов. Программа представляет собой набор связанных объектов. Каждый объект представляет собой набор каких-то данных и набор действий, которые он умеет делать. Естественно с объектом связывать именно те действия, которые необходимы при выполнении привязанных к нему действий. Эти действия называют методами объекта.

Типы объектов называются классами объектов. Объектно-ориентированный-программист описывает именно классы, а не объекты. В объектно-ориентированной программе также присутствует процедура, запускаемая при инициализации, которая создает объект базового класса, а затем этот объект уже сам все что нужно делает — занимается порождением и уничтожением других объектов.

В примере про кипячение чайника объекты выделяются естественным образом — это плита и чайник.

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

Стили и парадигмы  программирования и выбор языка программирования при разработке программного продукта. Примеры и презентация

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

Действительно, плита у нас становиться управляющим объектом, который управляет четырьмя конфорками -- тоже объектами, решающими некоторую сложную "вычислительную" задачу "нагрева чайников". Все конфорки работают параллельно, независимо друг от друга, и плита контролирует их работу.

Такую независимость процесса жизни объектов друг от друга можно реализовать на современных компьютерах разными способами:

  • Во-первых, ее можно эмулировать — методы объектов исполняются в одном процессе, но каждый из них может считать, что живет независимо.
  • Каждому объекту можно выделять отдельный процесс, и передачу сообщений между процессами можно реализовать с помощью различных механизмов взаимодействия процессов (sockets, pipes, messages, shared memory ...). Процессы могут реально исполняться на различных процессорах многопроцессорного компьютера.
  • Объекты могут "жить" на разных компьютерах, и обмениваться сообщениями с помощью одного из возможных протоколов (sockets, TCP/IP, ...)

Таким образом, объектно-ориентированный подход видется достаточно удобных для реализации параллельных вычислений.

Поясним сказанное. Когда мы ставим чайник на плиту, вовсе не обязательно ждать 5 минут — вычислительное время дорого, и кроме того, мы не может предсказать сколько на самом деле продлится процесс "вычисления". Правильнее приделать к чайнику свисток и продолжить заниматься другими важными делами.

Объектно-ориентированный подход активно применяется при разработке графических интерфейсов: окошки, кнопки, текстовые надписи, чекбоксы и другие графические элементы интерфейса (graphical user interface controls) — все это объекты, вложенные друг в друга и посылающие друг другу сообщения. Например, когда главное окно получает сообщение закрыться, оно должно отправить аналогичные сообщения всем своим дочерним окнам (объектам).

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

Приведем реализацию структуры данных стэк на объектно-ориентированном языке C++.

Стек — это структура данных для хранения последовательности элементов с двумя операциями — добавить элемент (push) и извлечь элемент (pop). Причем извлекаются элементы в порядке, обратном порядку добавления (последний добавленный элемент — First In First Out (FIFO)).

Стили и парадигмы  программирования и выбор языка программирования при разработке программного продукта. Примеры и презентация

Обратите внимание на то, что пользователю этого класса не нужно думать о памяти — ни о выделении, ни об освобождении. Стэк сам "позаботиться" о том, чтобы выделить нужное количество памяти. Если операцией pop() в стэк будет помещаться очередной элемент, который уже не помещается в память, на текущий момент предоставленную стеку, стэк выделит (realloc) под себя бОльшее количество памяти. А при завершении работы функции, в которой стэк был объявлен, автоматически вызовется деструктор ~Stack() и освободит память, которая использовалась под элементы стэка.

Кроме того Stack ответственнен за консистентность хранимых данных. Он не допустит того, чтобы указатель стэка m_pt вышел за пределы допустимых значений из полуинтервала [0, m_size).

Итак, объекты — это сущности, которые содержат в себе некоторую группу данных, и предоставляют функциональность, связанную с этими данными. Они ответственны за их консистентность.

И из этого определения можно сразу же вывести все проблемы, которые поджидают объектно-ориентированных программистов:

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

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

ООП на C vs ООП на C++

Приведем, для примера два альтернативных подхода к организации кипячения чайников на кухне.

Стили и парадигмы  программирования и выбор языка программирования при разработке программного продукта. Примеры и презентация

Объектно-ориентированный стиль программирования — это веселый стиль, в котором можно писать много строчек кода на "Ура!", думая о красоте и естественности.

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

Вопрос: в каком из данных классов естественно поместить хэштаблицу вида "чайник -> (плита, конфорка)"?

Посмотрим на другой стиль реализации аналогичной функциональности.

Стили и парадигмы  программирования и выбор языка программирования при разработке программного продукта. Примеры и презентация

Предложенная реализация объектно-ориентированного подхода без C++ позволяет не думать об группировке данных и функций. Программист думает только о организации данных внутри отдельной "кухни", и о структурах данных, которые нужны для эффективной работы "кухни". Вся функциональность реализуется в виде набора глобальных функций, которые не распределяются между классами.

Такой подход позволяет экономить силы и на этапе проектирования и на этапе разработки. В случае зоопарка из нескольких классов (кухня, чайник, плита, конфорка, ..., — на практике их число может быть очень большим, порядка сотни) в разных классах начинают встречаться функции с одинаковым смыслом. Например, в классе Плита есть функция, определяющая, кипит ли чайник. И в классе чайник есть аналогичная функция. Эти функции должно быть как-то используют друг друга. Здесь общепринятого стиля нет. Некоторые помещают "внутрь" чайника ссылку на плиту, и о своем состоянии чайник узнает у плиты. Некоторые делают наоборот — плита опрашивает стоящий на ней чайник, кипит ли он.

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

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

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

Обычно делают так, что все функции возвращают код возврата, который равен 0, если все хорошо, и некоторому ненулевому значению errno — иначе. И также добавляют функцию для получения описания ошибок:

кухня_описание_ошибки(errno); // возвращает текстовое описание ошибки

Методология исключительных ситуация, существующая в С++ и Java, безусловно, заслуживает внимания. Она очень хороша. Плохо, что она позволяет программистам писать на начальных этапах код не думая — это может плохо сказаться на этапе созревания проекта.

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

Калькулятор

Язык арифметических выражений — это еще не язык программирования. Но на задаче разработки программы-калькулятора можно обозначить много ключевых моментов теории языков программирования вообще.

Калькулятор выражений в обратной польской нотации на языке C++ (событийное программирование)

Рассмотрим несколько необычную запись (нотацию) арифметических выражений, в которой сначала идут два операнда, разделенные пробелом, а затем знак арифметической операции. Например,

  Стили и парадигмы  программирования и выбор языка программирования при разработке программного продукта. Примеры и презентация

Эта нотация называется обратной польской нотацией. Заметьте, что во втором примере скобочки можно опустить


выражение по прежнему будет интерпретироваться однозначно.

Транслятор-вычислитель таких выражений естественно построить на основе стека. Каждое считываемое число помещается в стек, а как только встречается арифметическая операция, из стека считываются два элемента (a = pop(), b = pop()), над ними производится соответствующая операция и результат заносится в стэк (push(a * b)).

Ниже приведенеа программа, в которой используется class Stack, который мы определили выше.

Стили и парадигмы  программирования и выбор языка программирования при разработке программного продукта. Примеры и презентация

В основе этой программы лежит событийная парадигма, хотя кого-то это может и удивить.

Да, здесь имеется оператор while — представитель структурного программировния, также испольуется объект стек --- представитель объектно-ориентированного программирования.

Тем не менее, базовая логика программы событийная. Роль событий здесь играют входные символы. Программа устроена как бесконечный цикл обработки приходящих событий (пока не поступит сигнал конца входа EOF).

Результатом обработки события являются события, посылаемые объекту "стек" — это запросы pop и push.

Это не автоматный стиль по той причине, что здесь нет режимов (ярко выраженных, разнотиповых состояний) и какой-то сложной диаграммы переходов между этими режимами.

Нечестный калькулятор на языке Perl:

 Стили и парадигмы  программирования и выбор языка программирования при разработке программного продукта. Примеры и презентация

Калькулятор на Perl, написанный в сентенциальной парадигме

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

   Стили и парадигмы  программирования и выбор языка программирования при разработке программного продукта. Примеры и презентация

например

Стили и парадигмы  программирования и выбор языка программирования при разработке программного продукта. Примеры и презентация

По сути, данный калькулятор работает согласно пяти сентенциям:

  • если число окружено скобками, то скобки можно убрать
  • подвыражение вида "число * число" можно заменить результат умножения
  • подвыражение вида "число + число" можно заменить результат сложения
  • подвыражение вида "число - число" можно заменить результат вычитания

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

Пример:

Стили и парадигмы  программирования и выбор языка программирования при разработке программного продукта. Примеры и презентация 

В данном примере получается неверный результат. Близость сентенций к естественному языку мешает программисту видеть подводные камни.

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

Логику конвертации данных из одного формата в другой часто можно записать в виде сентенций. Например, при конвертации из LaTeX в HTML можно использовать сентенции:

  Стили и парадигмы  программирования и выбор языка программирования при разработке программного продукта. Примеры и презентация

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

Например, символ "тильда" при конвертации из LaTeX в HTML нужно заменять на " " только тогда, когда этот символ находится в тексте (а не в формуле) и когда перед ним не стоит символ "обратный слэш". Такую сентенцию сложно записать в виде регулярного выражения на Perl или на каком-либо другом языке сентенций.

Вау!! 😲 Ты еще не читал? Это зря!

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

Ответы на вопросы для самопроверки пишите в комментариях, мы проверим, или же задавайте свой вопрос по данной теме.

создано: 2016-05-01
обновлено: 2023-12-11
132458



Рейтиг 9 of 10. count vote: 2
Вы довольны ?:


Найди готовое или заработай

С нашими удобными сервисами без комиссии*

Как это работает? | Узнать цену?

Найти исполнителя
$0 / весь год.
  • У вас есть задание, но нет времени его делать
  • Вы хотите найти профессионала для выплнения задания
  • Возможно примерение функции гаранта на сделку
  • Приорететная поддержка
  • идеально подходит для студентов, у которых нет времени для решения заданий
Готовое решение
$0 / весь год.
  • Вы можите продать(исполнителем) или купить(заказчиком) готовое решение
  • Вам предоставят готовое решение
  • Будет предоставлено в минимальные сроки т.к. задание уже готовое
  • Вы получите базовую гарантию 8 дней
  • Вы можете заработать на материалах
  • подходит как для студентов так и для преподавателей
Я исполнитель
$0 / весь год.
  • Вы профессионал своего дела
  • У вас есть опыт и желание зарабатывать
  • Вы хотите помочь в решении задач или написании работ
  • Возможно примерение функции гаранта на сделку
  • подходит для опытных студентов так и для преподавателей



Комментарии


Оставить комментарий
Если у вас есть какое-либо предложение, идея, благодарность или комментарий, не стесняйтесь писать. Мы очень ценим отзывы и рады услышать ваше мнение.
To reply

Разработка программного обеспечения и информационных систем

Термины: Разработка программного обеспечения и информационных систем