Технология структурного программирования

  • Лекции
  • docx
  • 17.03.2026
Публикация на сайте для учителей

Публикация педагогических разработок

Бесплатное участие. Свидетельство автора сразу.
Мгновенные 10 документов в портфолио.

Иконка файла материала РПМ Тема 2.docx

Тема 2. Технология структурного программирования

 

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

 

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

 

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

 

Парадигмы — это не строгие законы, а скорее стили написания кода и использования языковых возможностей. Работа в рамках парадигмы означает, что разработчик придерживается использования определённой архитектуры и инструментов языка. Таким образом, парадигма программирования указывает не столько на то, что нужно делать, сколько на то, чего делать не следует (или крайне не рекомендуется).

 

Существуют два ключевых определения парадигмы:

 

  1. По Томасу Куну (историк и философ): парадигма программирования — устоявшаяся система взглядов и подходов, в рамках которых ведётся разработка.

 

  1. По Роберту Мартину (инженер и программист): парадигма — это запрет на определённые действия внутри кода программы, ограничения на языковые конструкции, которые вынуждают использовать определённый стиль.

 

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

 

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

 

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

 

Одна и та же задача может быть решена по-разному: каждая парадигма подразумевает своё решение. (Рис.)

 

Рис.

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

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

 

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

 

 

Императивная парадигма.

 

Императивная парадигма - первая появившаяся из парадигм сформировалась, когда программы записывались на машинном языке. Написанный в соответствии с этой парадигмой код будет отвечать на вопрос: «Как именно должна работать программа и что она должна делать?»

 

Для императивного программирования характерны следующие черты:

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

 

Чистый императивный код — машинный язык,  неудобный для написания программ из-за сложности восприятия, дублирования фрагментов и частого использования операторов присваивания. Как правило, императивное программирование решает небольшие подзадачи для поддержания работы основной программы.

Эту парадигму (но не ограничиваясь ею) можно использовать почти во всех современных языках: C, C#, C++, Python, Java, Ruby.

 

К императивной парадигме относятся следующие виды программирования:

 

- процедурное (примеры языков: C, Pascal, COBOL, ALGOL, BASIC, Fortran.)

- структурное;

- модульное

- аспектно-ориентированное;

- объектно-ориентированное и другие (Java, Python, C++, Ruby, C#, Objective-C, PHP.).

 

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

 

 

Декларативная парадигма.

 

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

 

Она отвечает на вопрос: «Что делает программа и что должно получиться в итоге?»

 

Как это выглядит:

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

 

Декларативный подход существенно облегчает работу. Его преимущества можно свести к двум основным:

 

  1. Точная адаптация под конкретные задачи. Декларативное программирование создаёт высокоуровневый слой функциональности, который выполняет заранее продуманные инструкции.
  2. Защита от ошибок. Скрытая реализация не даёт что-то поломать в системе. Например, мы можем неправильно использовать запросы SQL, но не можем испортить сами запросы.

 

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

 

- функциональное программирование (Haskell, Erlang, Scala, F#, OCaml, ELM, Lisp.)

-  логическое программирование (Prolog).

 

Сравнение и выбор парадигмы

 

Зачем использовать императивное программирование, если декларативное позволяет писать гораздо меньше кода?  Есть несколько причин.

 

Во-первых, декларативное программирование — это обёртка для императивного. Компьютер не может сам ппонять, чего хочет программист, поэтому для него нужно написать конкретные инструкции, что и в каком порядке делать.

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

 

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

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

 

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

 

Каждая парадигма подходит для определённых задач:

  • Императивная — для работы с анимацией, графическими интерфейсами, скриптами, играми.
  • Декларативная — для вычислений и работы с данными.

 

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

 

Простое сравнение:

Критерий

Императивный подход

Декларативный подход

Фокус

Как сделать?

Что получить?

Контроль

Полный контроль над выполнением

Контроль делегирован системе

Пример

Цикл для перебора массива

SQL-запрос SELECT * FROM users

Плюсы

Гибкость, эффективность

Краткость, надёжность, читаемость

Минусы

Много кода, сложность

Меньше контроля, не для всех задач

 

Задание 1.  Дать определение и писать суть:

 

Основные модели программирования

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

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

- Реактивное программирование

- Параллельное и распределённое программирование

 

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

o Компонентно-ориентированное программирование

o Прототипно-ориентированное программирование

o Агентно-ориентированное программирование

 

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

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

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

‒ Обобщённое программирование

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

- Метапрограммирование

‒ Порождающее программирование

‒ Аспектно-ориентированное программирование

‒ Агентно-ориентированное программирование

‒ Контрактное программирование

‒ Рекурсия

‒ Автоматное программирование

‒ Событийно-ориентированное программирование

‒ Компонентно-ориентированное программирование

‒ Грамотное программирование

‒ Вайб-кодинг

 

 

 

Основные модели программирования:

 

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

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

Ключевые принципы:

  • Чистые функции: Функции без побочных эффектов, всегда возвращающие одинаковый результат для одинаковых входных данных
  • Неизменяемость данных: Данные не изменяются после создания, создаются новые структуры
  • Функции первого класса: Функции можно передавать как аргументы, возвращать из функций, хранить в переменных
  • Рекурсия вместо циклов: Использование рекурсии для итеративных процессов
  • Каррирование и частичное применение: Преобразование функции с несколькими аргументами в последовательность функций с одним аргументом

Особенности:

  • Высокий уровень абстракции
  • Упрощение тестирования и отладки
  • Естественная поддержка параллельных вычислений
  • Мощные возможности композиции

Языки: Haskell, Lisp, Scheme, Erlang, Scala, F#, OCaml, Clojure
Применение: Обработка данных, математические вычисления, финансовые системы, компиляторы


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

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

Ключевые принципы:

  • Декларативность: Описание того, что должно быть вычислено, а не как
  • Единство данных и программы: Программа и данные имеют одинаковую структуру
  • Автоматический поиск решений: Система самостоятельно ищет решение на основе заданных правил
  • Резолюция и унификация: Механизмы логического вывода

Особенности:

  • Программа = база знаний + запросы
  • Поддержка недетерминированных вычислений
  • Обратный ход вычислений (backtracking)
  • Естественное представление для задач искусственного интеллекта

Языки: Prolog, Mercury, Datalog
Применение: Экспертные системы, искусственный интеллект, базы знаний, лингвистический анализ, формальная верификация


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

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

Ключевые принципы:

  • Потоки данных (Observables): Представление данных как временных последовательностей событий
  • Асинхронность: Неблокирующая обработка событий
  • Распространение изменений: Автоматическое обновление зависимых данных при изменении источников
  • Функциональные преобразования: Использование функций map, filter, reduce для обработки потоков

Особенности:

  • Event-driven архитектура
  • Упрощение работы с асинхронными операциями
  • Избегание состояния гонки в многопоточных приложениях
  • Деларативный стиль описания зависимостей

Языки/библиотеки: RxJS (JavaScript), ReactiveX, Akka Streams (Scala), Reactor (Java), Combine (Swift)
Применение: Веб-интерфейсы (Angular, React), мобильные приложения, обработка событий в реальном времени, IoT


Параллельное и распределённое программирование

Суть: Модели и техники для одновременного выполнения нескольких вычислений на нескольких процессорах или компьютерах.

Параллельное программирование:

  • Многопоточность: Несколько потоков в рамках одного процесса
  • Многопроцессорность: Несколько процессов на многопроцессорной системе
  • Модели: Модель разделяемой памяти, модель передачи сообщений

 

Распределённое программирование:

  • Сетевое взаимодействие: Вычисления на нескольких машинах в сети
  • Координация: Синхронизация и согласованность данных
  • Отказоустойчивость: Обработка сбоев отдельных узлов

Ключевые подходы:

  • Actor-модель: Независимые акторы с изолированным состоянием, общающиеся сообщениями
  • CSP (Communicating Sequential Processes): Процессы с явными каналами связи
  • MapReduce: Модель для обработки больших данных
  • Data Parallelism: Одинаковые операции над разными данными

Особенности:

  • Сложность синхронизации и координации
  • Проблемы гонки данных, deadlock, livelock
  • Обеспечение консистентности данных
  • Масштабируемость и отказоустойчивость

Языки/платформы: Erlang/Elixir (Actor), Go (goroutines и channels), MPI (C/Fortran), Hadoop/Spark, CUDA (GPU)
Применение: Высокопроизводительные вычисления, Big Data, веб-серверы, научные симуляции, блокчейн


Объектно-ориентированное программирование (ООП)

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

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

  • Инкапсуляция: Скрытие внутренней реализации и защита данных
  • Наследование: Создание новых классов на основе существующих
  • Полиморфизм: Возможность объектов обрабатываться как объекты родительского класса
  • Абстракция: Сокрытие сложности через создание простых интерфейсов

 

Компонентно-ориентированное программирование

Суть: Расширение ООП, где компоненты — это независимые, повторно используемые модули с чётко определёнными интерфейсами.

Особенности:

  • Чёткое разделение интерфейса и реализации
  • Поддержка композиции компонентов
  • Независимое развёртывание и версионирование
  • Межъязыковая совместимость (например, COM/.NET)

Примеры: COM/DCOM, CORBA, .NET Components, JavaBeans, EJB
Применение: Корпоративные системы, распределённые приложения, плагинные архитектуры

 

Прототипно-ориентированное программирование

Суть: Объекты создаются не из классов, а путём клонирования существующих объектов-прототипов.

Особенности:

  • Отсутствие понятия "класс" в классическом понимании
  • Динамическое наследование через цепочку прототипов
  • Гибкость и динамизм во время выполнения
  • Делегирование вместо классического наследования

Языки: JavaScript, Lua, Self, Io
Применение: Веб-разработка (JavaScript), скриптовые языки, гибкие динамические системы

 

Агентно-ориентированное программирование

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

Особенности:

  • Автономность: Агенты работают самостоятельно
  • Реактивность: Реагируют на изменения среды
  • Проактивность: Имеют цели и проявляют инициативу
  • Социальность: Взаимодействуют с другими агентами
  • Адаптивность: Учатся и адаптируются к среде

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


 

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

 

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

Суть: Программа представляется как последовательность процедур (подпрограмм), которые могут вызывать друг друга.

Особенности:

  • Иерархическая структура вызовов процедур
  • Использование глобальных и локальных переменных
  • Пошаговая детализация алгоритма
  • Предшественник структурного программирования

Языки: C, Pascal, Fortran, BASIC

Применение: Системное программирование, научные вычисления, обучение основам программирования


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

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

Особенности:

  • Композиция функций как основной метод построения программ
  • Использование функций высшего порядка
  • Каррирование и частичное применение
  • Минимизация явного управления потоком выполнения

Обобщённое программирование

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

Ключевые техники:

  • Шаблоны (C++): Параметрический полиморфизм во время компиляции
  • Дженерики (Java, C#): Параметрический полиморфизм с проверкой типов
  • Утиный полиморфизм (Python): "Если что-то ходит как утка и крякает как утка..."

Преимущества:

  • Повторное использование кода
  • Типобезопасность
  • Повышение производительности (специализация шаблонов в C++)

Применение: Контейнеры (векторы, списки), алгоритмы (сортировка, поиск), библиотеки


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

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

Техники:

  • Инварианты циклов: Условия, истинные перед и после каждой итерации
  • Пред- и постусловия: Спецификации для функций и методов
  • Теоремы и леммы: Формальные доказательства свойств программ
  • Верификация: Проверка соответствия программы спецификации

Языки/инструменты: Coq, Agda, Isabelle, TLA+
Применение: Критически важные системы (авионика, медицина), компиляторы, криптография


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

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

Формы метапрограммирования:

  1. Макросы (Lisp, C): Генерация кода во время препроцессинга или компиляции
  2. Шаблоны C++: Вычисления во время компиляции (TMP)
  3. Рефлексия (Java, C#): Интроспекция и модификация программы во время выполнения
  4. Генерация кода: Автоматическое создание кода из моделей или DSL

Применение:

  • Генераторы кода
  • ORM-системы
  • Сериализация/десериализация
  • Контейнеры зависимостей
  • Доменно-специфичные языки (DSL)

Порождающее программирование

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

Подходы:

  • Генерация кода из моделей (MDA/MDD)
  • Программирование на основе шаблонов
  • Автоматическая оптимизация и специализация кода
  • Генерация тестовых данных и сценариев

Инструменты: UML-генераторы кода, Yeoman, Cookiecutter, шаблоны проектов
Применение: Быстрая разработка приложений, создание каркасов проектов, кодогенерация для повторяющихся задач


Аспектно-ориентированное программирование (АОП)

Суть: Разделение сквозной функциональности (логирование, безопасность, транзакции) в отдельные модули — аспекты.

Ключевые концепции:

  • Аспект: Модуль, инкапсулирующий сквозную функциональность
  • Совет (Advice): Дополнительное поведение, применяемое в точках соединения
  • Точка соединения (Join Point): Точка в выполнении программы (вызов метода, доступ к полю)
  • Срез (Pointcut): Набор точек соединения

Языки/фреймворки: AspectJ (Java), Spring AOP, PostSharp (C#)
Применение: Логирование, безопасность, управление транзакциями, кэширование, обработка ошибок


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

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

Элементы контракта:

  • Предусловия (Preconditions): Что должно быть истинно перед вызовом метода
  • Постусловия (Postconditions): Что будет истинно после выполнения метода
  • Инварианты (Invariants): Что остаётся истинным на протяжении жизни объекта

Языки с поддержкой: Eiffel, D, Spec#; библиотеки для Java, C++, Python
Преимущества:

  • Чёткая документация поведения
  • Обнаружение ошибок на ранних этапах
  • Упрощение тестирования и отладки
  • Самодокументирующийся код

Рекурсия

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

Типы рекурсии:

  1. Прямая рекурсия: Функция вызывает саму себя
  2. Косвенная рекурсия: Функция A вызывает B, B вызывает A
  3. Хвостовая рекурсия: Рекурсивный вызов — последняя операция в функции
  4. Древовидная рекурсия: Функция делает несколько рекурсивных вызовов

Применение:

  • Обработка рекурсивных структур данных (деревья, графы)
  • Разделяй и властвуй алгоритмы
  • Математические вычисления (факториал, числа Фибоначчи)
  • Парсинг и обработка языков

Проблемы: Риск переполнения стека, неэффективность при глубокой рекурсии


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

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

Ключевые элементы:

  • Состояния: Дискретные режимы работы программы
  • События: Внешние воздействия, вызывающие переходы
  • Переходы: Изменения состояния при наступлении событий
  • Действия: Операции, выполняемые при переходе или в состоянии

Реализации:

  • Табличный подход: Таблицы состояний и переходов
  • Switch-case: Вложенные операторы switch
  • State pattern: Шаблон проектирования "Состояние"
  • Специализированные языки: Statecharts, UML state machines

Применение: Протоколы связи, пользовательские интерфейсы, игровые AI, бизнес-процессы


Событийно-ориентированное программирование

Суть: Архитектура, в которой поток выполнения программы определяется событиями.

Ключевые механизмы:

  • Цикл событий (Event Loop): Бесконечный цикл, обрабатывающий события из очереди
  • Обработчики событий (Event Handlers): Функции, вызываемые при наступлении событий
  • Публикация-подписка (Pub/Sub): Механизм распределения событий
  • Асинхронность: Неблокирующая обработка

Применение:

  • GUI приложения (клики мыши, нажатия клавиш)
  • Веб-серверы (HTTP-запросы)
  • Игровые движки
  • Системы реального времени

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

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

Особенности:

  • Чередование кода и объяснений на естественном языке
  • Акцент на понятность и объяснимость
  • Генерация документации и кода из одного источника
  • Литературный стиль изложения

Инструменты: Knuth's WEB (Pascal), CWEB (C), noweb, Jupyter Notebooks
Применение: Образовательные материалы, научные вычисления, сложные алгоритмические задачи


Вайб-кодинг

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

Характеристики:

  • Атмосфера: Музыка, освещение, окружение, способствующие концентрации
  • Поток (Flow): Состояние глубокой вовлечённости в процесс кодинга
  • Эстетика кода: Стремление к красивому, элегантному коду
  • Сообщество: Совместное программирование, стримы, обмен опытом
  • Инструменты: Настраиваемые редакторы, темы, плагины для улучшения опыта

Проявления:

  • Программирование под lo-fi музыку
  • Настройка IDE с тёмными темами и пастельными цветами
  • Виртуальные "кофейни" для совместной работы
  • Стримы на Twitch/YouTube с программированием
  • Эстетичные репозитории и README файлы

Значение: Смещение фокуса с чистой продуктивности на удовольствие от процесса, творчество и благополучие разработчика.

 

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

 

Структу́рное программи́рование — парадигма программирования, в основе которой лежит представление программы в виде иерархической структуры блоков.

 

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

 

При этом разработка программы ведётся пошагово, методом «сверху вниз».

 

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

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

 

Структурное программирование основывается на фундаменте теоремы Бёма-Якопини, математически обосновывающей возможность структурной организации программ, и работы Эдсгера Дейкстры «О вреде оператора goto» (англ. Goto considered harmful).

 

Таким образом структурное программирование стало основой всего, что сделано в последующих методологиях программирования, включая и объектное программирование».

 

2.2.1 История

 

Идея структурного программирования зародилась в связи с сомнениями в целесообразности использования оператора goto.

Впервые эти сомнения высказал Хайнц Земанек в 1959 году, но они не получили тогда развития.

Ситуация изменилась в 1968 году, когда Эдсгер Дейкстра опубликовал статью «Оператор Go To считается вредным» (первоначально — «Доводы против оператора GO TO»). Этот документ оказал значительное влияние на развитие программирования.

 

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

 

Проблемы использования goto:

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

Доводы оказались настолько весомыми, что goto стал рассматриваться как крайне нежелательный. Это отразилось в новых языках: например, goto запрещён в Java и Ruby, хотя в некоторых языках (как Ада) сохранён для редких случаев, где он оправдан по соображениям эффективности.

 

2.2.2 Цель

 

Цель структурного программирования — повысить производительность труда программистов, особенно при разработке больших и сложных программных комплексов. Оно направлено на сокращение числа ошибок, упрощение отладки, модификации и сопровождения программного обеспечения. Эта цель стала актуальной в 1960–1970-е годы из-за стремительного роста сложности программ и неспособности разработчиков управлять этой сложностью традиционными методами.

 

2.2.3 Спагетти-код

 

Структурное программирование призвано устранить беспорядок и ошибки, вызванные трудностью чтения и анализа неструктурированного кода, часто называемого «спагетти-код».

 

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

Название отражает извилистый и запутанный ход выполнения, похожий на миску спагетти. Иногда такой код называют «кенгуру-код» из-за обилия инструкций прыжков (jump).

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

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

 

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

 

 Теорему сформулировали и доказали итальянские математики Коррадо Бём и Джузеппе Якопини (Giuseppe Jacopini). Они опубликовали её в 1965 году на итальянском языке и в 1966 году на английском.

Наряду с теоремой, в статье Бёма и Якопини описывались методы преобразования неструктурных алгоритмов в структурные на примере созданного Бёмом языка программирования P′′. Язык P′′ — первый полный по Тьюрингу язык программирования без оператора goto.

 

В современной терминологии теорема Бёма-Якопини утверждает:

 

Любая программа, заданная в виде блок-схемы, может быть представлена с помощью трёх управляющих структур:

 

 • последовательность — обозначается: f THEN g,  (сначала выполняется f, затем g)

 • ветвление — обозначается: IF p THEN f ELSE g,

 • цикл — обозначается: WHILE p DO f,

 

где f, g — блок-схемы с одним входом и одним выходом,

            русловие, THEN,

           IF, ELSE, WHILE, DO — ключевые слова.

 

Пояснение. Формула f THEN g означает следующее: сначала выполняется программа f, затем выполняется программа g.

 

 Данная теорема резко контрастирует с обычной (в 1960—1970 годы) практикой программирования, когда наблюдалось массовое использование операторов перехода goto.

 

Бём и Якопини не употребляли термин «структурное программирование». Тем не менее, доказанную ими теорему (и её последующие вариации у разных авторов) впоследствии стали называть «теоремой о структурном программировании», «структурной теоремой», «теоремой о структурировании».

 

2.2.5 Принципы структурного программирования

 

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

 

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

 

Принцип 1. Следует отказаться от использования оператора безусловного перехода goto.

 

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

 

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

‒ Ветвление — однократное выполнение одной из двух или более операций, в зависимости от выполнения заданного условия.

 ‒ Цикл — многократное исполнение одной и той же операции до тех пор, пока выполняется заданное условие (условие продолжения цикла).

 

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

 

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

 

 В этом случае в тексте основной программы, вместо помещённого в подпрограмму фрагмента, вставляется инструкция «Вызов подпрограммы». При выполнении такой инструкции работает вызванная подпрограмма. После этого продолжается исполнение основной программы, начиная с инструкции, следующей за командой «Вызов подпрограммы».

 

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

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

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

Границы блока строго определены. Например, в if-инструкции блок ограничен кодом BEGIN..END (в языке Паскаль) или фигурными скобками {…} (в языке C) или отступами (в языке Питон).

 

Принцип 6. Все перечисленные конструкции должны иметь один вход и один выход.  

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

 

Принцип 7. Разработка программы ведётся пошагово, методом «сверху вниз» (top-down method).

 

 

Задание 2. Основные принципы Дейкстры

Объясните своими словами следующие принципы структурного программирования и приведите по одному практическому примеру их применения:

 

  1. Принцип отказа от goto — почему этот оператор считался вредным и как современные языки решают те задачи, для которых раньше использовался goto?

 

Пример для анализа: Как можно заменить типичное использование goto для обработки ошибок в языке C структурными конструкциями?

 

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

 

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

 

  1. Принцип одного входа и одного выхода — как этот принцип влияет на тестируемость и поддерживаемость кода?

 

Пример для анализа: Сравните функцию с несколькими return в разных местах и функцию с одним return в конце. Как это влияет на покрытие тестами?

 

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

 

Пример для анализа: Приведите пример фрагмента кода из 15 строк, который выполняет одну задачу (например, валидацию email) и объясните, почему его стоит выделить в отдельную функцию.

 

  1. Принцип пошаговой разработки (сверху вниз) — как этот принцип помогает управлять сложностью больших программ?

 

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

 

Здание 3. Сравнение с другими парадигмами

Заполните таблицу, сравнивая структурное программирование с другими парадигмами:

 

Принцип/Характеристика

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

Объектно-ориентированное

Функциональное

Базовая единица программы

Управление состоянием

Основной механизм абстракции

Отношение к побочным эффектам

Подход к обработке ошибок

Критерии декомпозиции

Поддержка параллелизма



 

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

 

Распространены две методики (стратегии) разработки программ, относящиеся к структурному программированию:

– программирование «сверху вниз»;

– программирование «снизу вверх».

 

2.2.6 Метод «сверху вниз»  (Top-Down)

 

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

 

Процесс:

 

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

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

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

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

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

4. Разработка заканчивается тогда, когда не останется ни одной заглушки.

 

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

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

 

Как отмечал Тони Хоар, принципы структурного программирования применимы как при разработке «сверху вниз», так и «снизу вверх».

 

2.2.7 Метод «снизу вверх»

 

Разработка программ «снизу вверх» (восходящее программирование) – это подход, при котором разработка начинается с создания небольших базовых алгоритмов (подпрограмм), выполняющих отдельные элементарные задачи, которые затем объединяются для создания более сложных алгоритмов и в конечном итоге для решения всей поставленной задачи

 

Подпрограммы бывают двух видов – процедуры и функции.

 

Процедура - выполняет группу операторов,

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

 

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

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

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

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

 

. Преимущества метода:

‒ базовые алгоритмы можно многократно использовать в разных частях алгоритма (программы), что уменьшает его длину;

‒ алгоритм состоит из небольших модулей, что облегчает понимание и отладку;

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

‒ базовые алгоритмы (подпрограммы) можно объединять в библиотеки и использовать в других проектах.

 

Недостатки метода:

‒ требуется чёткое понимание общей структуры задачи;

‒ сложность контроля прогресса;

‒ возможность отклонения от цели: легко увлечься разработкой отдельных модулей и забыть о главной цели.

 

Когда следует использовать метод «снизу вверх»:

 ‒ есть чёткое понимание базовых операций, необходимых для решения задачи;

‒ нужно создать библиотеку повторно используемых компонентов;

‒ задача предполагает много повторяющихся действий.

 

Задание 4: Сравните две методологии структурного программирования:

Критерий сравнения

Программирование «сверху вниз»

Программирование «снизу вверх»

Основная идея

Первый шаг разработки

Процесс проектирования

 

 

Преимущества

Недостатки

Когда предпочтительнее использовать



 

 

2.8 Подпрограмма

 

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

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

 

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

 

Выделение набора действий в подпрограмму и вызов её по мере необходимости позволяет:

  •  Логически выделить целостную подзадачу.
  • Централизованно вносить изменения: правка в подпрограмме автоматически применяется ко всем её вызовам, в отличие от дублированного кода, где правки нужно вносить в каждом месте.

 

 

2.9. Применение трёх базовых структур управления

 

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

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

 

Блгоритм

Свойства алгоритма

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

Условные обозначения в алгоритмах

 

 

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

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

 

Последовательность

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

Некоторые особенности:

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

 

 

Привести примеры на java  и других языках

 

Ветвление

 

Ветвление — однократное выполнение одной из двух или более операций в зависимости от выполнения заданного условия. 

 

Условные операторы, такие как if, switch, позволяют выбирать между несколькими вариантами действий, основываясь на текущем состоянии данных.

 

Некоторые особенности:

  • Используется, когда выполнение программы может измениться в зависимости от результата проверки условия и пойти двумя разными (альтернативными) путями.
  • Условие может быть истинным или ложным (принимать значение TRUE или FALSE).
  • Каждый из путей ведёт к общему выходу, так что работа алгоритма будет продолжаться независимо от того, какой путь будет выбран.

 

 

Она содержит логический элемент проверки условия Р и два функциональных

блока S1 и S2. При исполнении алгоритма сначала вычисляется значение логи-

ческого выражения (проверяется условие), если оно истинно, то выполняется

блок S1, иначе (если ложно) блок S2. Такой вид развилки называется полной

условной конструкцией.

 

 

Структура развилка используется также в неполной форме. В этом случае,

если значение логического выражения ложно, никакое действие не выполняет-

ся. Такой вид развилки называется неполной условной конструкцией.

Структура неполной развилки имеет вид:

 


 

 

 

 

Цикл

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

 

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

 

Некоторые типы циклов:

  • Цикл с предусловием — пока условие истинно, выполняется серия, образующая тело цикла. Проверка условия перед выполнением тела цикла.

Структура цикла с предусловием состоит из логического элемента проверки условия Р и функционального блока S, называемого телом цикла. Она имеет

вид:

Цикл с предусловием выполняется так: сначала проверяется условие (отсюда название - цикл с предусловием), т.е. вычисляется значение логического выражения. Если оно истинно, то выполняется тело цикла, и снова проверяется условие. Выполнение цикла завершается, когда значение логического выражения становится ложным. Для этого необходимо, чтобы в теле цикла существовала команда, которая влияла бы на условие.

 

\

 

  • Цикл с постусловием — тело цикла предшествует условию цикла, тело цикла повторяет своё выполнение, если условие ложно, повторение кончается, когда условие станет истинным.

 

Структура цикла с постусловием также состоит из логического элемента

проверки условия Р и функционального блока S – тела цикла.

 

 

Цикл с постусловием выполняется так: сначала выполняется команда (ко-

манды) в теле цикла, затем проверяется условие, т.е. вычисляется значение ло-

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

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

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

теле цикла существовала команда, влияющая на условие.

 

Различие между циклами не только в том, что один с постусловием, а дру-

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

блок S может ни разу не выполниться, если условие Р при первой проверке

окажется ложным.

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

бы один раз выполнится

 

 

 

Преимущества и недостатки структурного программирования

 

Преимущества:

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

  Упрощённое тестирование, отладка. Разбивка софта на отдельные модули, которые могут быть протестированы независимо. Это упрощает обнаружение и устранение ошибок, поскольку каждая часть проверяется отдельно. Модули, легко заменяемые и тестируемые, значительно снижают вероятность ошибок при изменении кода.

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

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

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

  Лёгкость в модификациях. Когда программа организована в виде модулей, изменения в одной части не влияют на остальные её компоненты. Это позволяет без значительных усилий обновлять или расширять систему, обеспечивая гибкость и удобство в поддержке и добавлении новых функциональных возможностей.

Недостатки

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

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

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

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

  Невозможность полноценной многозадачности. Это может создавать проблемы при разработке многозадачных приложений или при работе с потоками данных.

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

 

2.10 концепции структурного программирования в Java

 

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

 

Концепция

Суть принципа

Реализация в Java (как "структура")

Линейная последовательность

Код выполняется сверху вниз, инструкция за инструкцией.

Порядок операторов внутри метода main() или любого другого метода

Ветвление (выбор)

Принятие решений в программе.

Операторы ifif-elseswitch

Циклы (повторение)

Многократное выполнение блока кода.

Операторы forwhiledo-while.

Модульность / Нисходящее проектирование

Разделение сложной задачи на подзадачи (модули).

Методы: логически обособленные блоки кода внутри класса
Классы: основной строительный блок Java-программы, объединяющий данные (поля) и поведение (методы)

Структурированные данные

Организация данных для эффективного доступа и управления.

Массивы: базовый тип
Коллекции (ArrayList, HashMap и др.): гибкие структуры из пакета 
java.util для хранения наборов объектов

Отказ от безусловных переходов (goto)

Улучшение читаемости и предсказуемости кода.

В Java оператора goto нет. Управление потоком осуществляется только через структурные элементы (ветвления, циклы, вызовы методов).

 

 

В Java вы можете использовать те же самые операторы структурного программирования, что и языке программирования С, а именно:

 

Оператор

Для чего применяется

if, else

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

for

Оператор цикла. Проверка условия завершения, а также итерация выполняется в начале цикла

while

Оператор цикла с проверкой условия завершения, выполнямой в начале цикла

do-while

Оператор цикла с проверкой условия завершения, выполнямой в конце цикла

continue

Продолжение выполнения цикла с его начала

break

Прерывание выполнения цикла

switch

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

 

Оператор if-else

В начале фрагмента программы, демонстрирующего применение оператора if-else, мы создаем три переменных:

int i = 5;
int j = 6;
boolean f;

Программа вычисляет выражение (i - j)*2 и сравнивает его с нулем в операторе if:

if((i - j) * 2 > 0)
  System.out.println("(" + i + " - " 
    + j + ") * 2 > 0"); 
else
{
  System.out.println("(" + i + " - " 
    + j + ") * 2 <= 0"); 
      
  f = (i == i);
  if(f)
  {
    System.out.println("i == i"); 
  }
}

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

(5 - 6) * 2 <= 0

Второй оператор if выполняется только в том случае, если выражение (i - j)*2 меньше нуля. В этом операторе анализируется содержимое логической переменной f.

Если эта переменная равна true, то на консоль выводится текстовая строка, показанная ниже:

i == i

Переменная f вычисляется следующим образом:

f = (i == i);

Здесь в переменную f записывается результат операции сравнения переменной i самой с собой. Он всегда равен true.Оператор for

Цикл for в нашей программе выглядит следующим образом:

for(i = 0; i < 10; i++)
{
  System.out.print(i + " "); 
}

Здесь переменная i используется в качестве переменной цикла. Перед началом цикла ей присваивается нулевое значение.

Затем содержимое i сравнивается с числом 10. Если i меньше 10, тело цикла выполняется один раз. Вслед за этим значение i увеличивается на единицу.

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

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

Вот что приведенный выше фрагмент программы выведет на консоль:

0 1 2 3 4 5 6 7 8 9

 

Оператор break

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

for(i = 0; i < 10; i++)
{
  if(i > 5)
    break;
  System.out.print(i + " "); 
}

В результате на консоль будут выведены цифры от 0 до 5:

0 1 2 3 4 5

Оператор while

Оператор while проверяет условие завершения цикла перед выполнением тела цикла:

i = 0;
while(i < 10)
{
  System.out.print(i + " "); 
  i++;    
}

В отличие от оператора for оператор while никак не изменяет значение переменной цикла, поэтому мы должны позаботиться об этом сами.

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

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

Цикл будет прерван, как только значение переменной i превысит 10.

 

Оператор continue

Ниже мы показали цикл, в котором используется оператор continue:

i = 0;
while(true)
{
  i++;
  System.out.print(i + " "); 
      
  if(i < 9)
    continue;
  else
    break;
}

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

Когда указанное значение будет достигнуто, выполнение цикла будет прервано оператором break.

 

Оператор do-while

При использовании оператора do-while условие завершения цикла проверяется после выполнения его тела:

i = 0;
do
{
  System.out.print(i + " "); 
  i++;    
} while(i < 10)

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

Как только это значение достигнет 10, цикл будет прерван.

 

Оператор switch

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

i = 2;
    
switch(i)
{
  case 1:
  {
    System.out.println("case 1");
    break; 
  }
  case 2:
  {
    System.out.println("case 2"); 
    break; 
  }
  case 3:
  {
    System.out.println("case 3"); 
    break; 
  }
  default:
  {
    System.out.println("default"); 
    break; 
  }
}

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

 

 

Контрольные вопросы:

 

  1. Что такое парадигма программирования?
  2. Какое определение парадигмы дал Роберт Мартин?
  3. Чем отличается подход к коду 20 лет назад от современного?
  4. Как парадигма влияет на архитектуру программы?
  5. Может ли язык программирования поддерживать несколько парадигм? Приведите пример.
  6. Что такое императивная парадигма?
  7. Какие черты характерны для императивного программирования?
  8. Что такое “чистый императивный код”?
  9. Какие языки относятся к императивной парадигме?
  10. Что такое декларативная парадигма?
  11. Какой вопрос решает декларативное программирование?
  12. Какие преимущества у декларативного подхода?
  13. Какие языки относятся к декларативной парадигме?
  14. Почему декларативное программирование не может полностью заменить императивное?
  15. Для каких задач лучше подходит императивная парадигма?
  16. Для каких задач лучше подходит декларативная парадигма?
  17. Что такое функциональное программирование и к какой парадигме оно относится?
  18. Что такое логическое программирование и где оно применяется?
  19. Что такое объектно-ориентированное программирование и к какой парадигме оно относится?
  20. Какие ещё подходы и приёмы программирования вы знаете? (перечислите несколько из списка в задании)
  1. Что такое структурное программирование?
  2. Какие три базовые управляющие конструкции лежат в основе структурного программирования?
  3. Кто автор статьи “О вреде оператора goto”?
  4. Что такое “спагетти-код”?
  5. Как оператор goto может привести к “спагетти-коду”?
  6. Какая теорема лежит в основе структурного программирования?
  7. Кто такие Бём и Якопини?
  8. Какие три структуры доказаны в теореме Бёма-Якопини?
  9. Что означает “один вход и один выход” для управляющей конструкции?
  10. Какой принцип структурного программирования связан с отказом от goto?
  11. Что такое подпрограмма и какова её роль в структурном программировании?
  12. Какие два вида подпрограмм существуют?
  13. Что такое рекурсия и чем она опасна?
  14. Что такое блок в структурном программировании?
  15. Какие два метода разработки программ используются в структурном программировании?
  16. В чём суть метода “сверху вниз”?
  17. Что такое “заглушка” в методе “сверху вниз”?
  18. В чём суть метода “снизу вверх”?
  19. Какие преимущества у метода “снизу вверх”?
  20. Какие недостатки у метода “снизу вверх”?
  1. Какие три базовые управляющие конструкции используются в структурном программировании?
  2. Что такое последовательность?
  3. Что такое ветвление? Приведите пример оператора.
  4. Что такое цикл? Какие типы циклов вы знаете?
  5. Чем цикл с предусловием отличается от цикла с постусловием?
  6. Какие операторы в Java соответствуют базовым конструкциям структурного программирования?
  7. Как оператор break влияет на выполнение цикла?
  8. Как оператор continue влияет на выполнение цикла?
  9. Как работает оператор switch?
  10. Какие преимущества и недостатки структурного программирования вы можете назвать?