Добавил:
ivanov666
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Технологии и методы программирования. Учебное пособие-1
.pdf
Класс – это тип, описывающий структуру объектов. Объект – это
экземпляр класса. Обычно классы разрабатывают таким образом, чтобы
их объекты соответствовали реальным или виртуальным объектам
предметной области.
Структура объекта включает атрибуты и методы:
атрибуты – это переменные, конкретные характеристики объекта;.
методы – это функции, которые описаны внутри класса. Они поз-
воляют взаимодействовать объекту
с другими объектами.
Множество атрибутов и методов, доступных извне, рассматривается
как интерфейс для доступа к объекту.
ПРИНЦИПЫ ООП
Объектно-ориентированное программирование определяют через
четыре принципа, по которым можно понять основы работы.
Абстракция (абстрагирование) – это способ выделить минимальный набор наиболее важных атрибутов и методов, позволяющих решить
поставленную задачу.
Абстрактный класс – класс, в котором реализация методов неопределенна. Это позволяет создавать конкретные классы, не описывая реализацию методов заранее (
в этом суть абстракции), а предоставляя ба-
зовый шаблон для дальнейших надстроек.
Инкапсуляция – класс объединяет описание свойств объектов и их
поведения в единое целое, так что невозможно напрямую получить доступ к внутренней структуре объекта (сокрытие реализации). Инкапсуляция вытекает из самой идеи объектно-ориентированного программирования.
Наследование позволяет реализовывать
сложную иерархию классов «от общего к частному». Дочерние классы наследуют особенности
родительских, дополняя или в определенной степени модифицируя их
характеристики. Преимущество, которое дает концепция наследования
в программировании, – отсутствие повторения кода в разных частях
программы. Это облегчает понимание и масштабирование кода. Как
правило, рассматривается одиночное наследование (от одного родительского класса
), но возможно и множественное наследование (от не-
скольких родителей). Варианты множественного наследования:
1) наследование от интерфейсов. Интерфейс – класс (разновидность
абстрактного), описывающий набор методов, но не имеющий данных
и реализации;
51

2) наследование от полноценных классов. Это тип множественного
наследования может создавать неоднозначности в дочерних классах
и сильные зависимости в коде, поэтому его желательно использовать
только с интерфейсами.
Полиморфизм – это представление одного интерфейса для разных
типов данных, т. е. один из вариантов разделения интерфейса и реализации (ЧТО от КАК). Практически это
означает возможность для объектов разных классов, связанных наследованием, реагировать различным способом при обращении к одному и тому же методу.
Родительские классы могут определять и реализовывать виртуальные методы, а дочерние классы могут переопределять их; это означает,
что они предоставляют собственное определение и реализацию.
Декларативное программирование – это парадигма программиро-
вания
, основанная на том, что в программе описывается определенный
класс проблем в виде некоторых ограничений и правил (спецификация
задачи), на основе которых генерируется способ получения результата.
Другими словами, в программе указывается, что должно быть выполнено, без указания того, как это должно быть реализовано.
Применение декларативного стиля в таких областях человеческой
деятельности, как создание систем искусственного интеллекта, автоматическое доказательство теорем, разработка экспертных систем и тому
подобное, позволяет достичь значительно большей скорости разработки
приложений, уменьшить размер исходного кода, создать более понятные но сравнению с императивными языками программы.
Этот подход существенно проще и прозрачнее формализуется математическими средствами, поэтому программы легче тестировать
и ве-
рифицировать.
К декларативному стилю в первую очередь относятся функциональный и логический подход к программированию.
Функциональное программирование (ФП) [56–59] – парадигма
программирования, в которой процесс вычисления рассматривается как
вычисление значений функций в математическом понимании последних (в отличие от функций как подпрограмм в процедурном программировании). Другими словами, функция
определяется не как подпро-
грамма, а как соответствие между множествами.
Функциональный подход сводится к составлению решения задачи
в виде набора функций, которые должны быть выполнены. Разработчик
52

подробно определяет вход каждой функции и возвращаемые ею результаты. Компиляторы функциональных языков используют технологию
отложенных вычислений. Компилятор сам решает, какие функции выполнять, а какие отложить на потом, какие выполнять в многозадачном
режиме. Это оптимизирует выполнение программы, влияя на увеличение скорости.
Важнейшей характеристикой функционального подхода является то
обстоятельство, что
всякая программа, разработанная на языке функционального программирования, может рассматриваться как функция, аргументы которой, возможно, также являются функциями.
Функция – это конструкция, которая возвращает выходные данные
при наличии входных данных. Фактически она сопоставляет элемент из
одного набора с другим набором. Это самое важное понятие в функциональном программировании.
Выражение – это
конструкция, возвращающая значения. В отличие
от инструкций, выполняющих действия, выражение можно рассматривать как действие с возвратом значения. Выражение можно заменить
вызовом функции.
Композиция функций – построение новых функций из ранее определенных путем передачи результата одной функции в качестве аргумента другой функции.
Замыкание. При определение функции в контексте (теле)
другой
функции локальная функция имеет доступ к данным родительской,
а также переопределяется при каждом ее вызове.
Каррирование. При вызове функции с несколькими аргументами
происходит ее каррирование – преобразование функции от многих аргументов в набор вложенных функций, каждая из которых является
функцией от одного аргумента.
ОСОБЕННОСТИ ФУНКЦИОНАЛЬНОГО ПОДХОДА [60]
1. Отсутствие жесткой последовательности. Разработчик задает
правила, а компилятор кода сам решает, в какой последовательности их
выполнять. Жесткий порядок действий программист не задает. Его выбирает сама программа (компилятор).
2. Анонимность функций. Анонимные функции – это функции,
у которых нет уникального имени. Они определяются только со списком аргументов в месте выполнения
.
53

3. Использование только чистых функций. Чистые функции –
это такие, которые удовлетворяют двум условиям:
при одинаковых входных данных функция всегда вернет одина-
ковый результат;
во время выполнения функции не возникает побочных эффектов –
так называют действия, которые влияют на что-то за ее пределами.
Например, изменение переменной, чтение данных или вывод в консоль – это побочные эффекты.
4. Использование функций только первого класса и высшего по-
рядка:
функция первого класса – это такая, которую можно представить
как переменную, т. е. ее можно передавать как аргумент другим функциям, возвращать как результат работы других функций, сохранять
в переменную или структуру данных;
функция высшего порядка – такая, которая принимает в качестве
аргументов функции или возвращает их в качестве результата.
5. Неизменяемость переменных. В функциональном программи-
ровании нет переменных в
привычном виде. Фактически переменная –
это константа. Если нужно изменить значение переменной (в результате
вычислений), она не получает нового значения, а создается новая переменная, и результат вычислений записывается в нее. Исходная остается
прежней – ее значение не меняется. Имена могут даваться значениям
аргументов функций, которые остаются постоянными на протяжении
всего вычисления
результата.
6. Относительная прозрачность. Относительная прозрачность
функции означает, что вызов функции можно заменить на возвращаемое значение – и от этого ничего не изменится.
7. Рекурсия вместо циклов. В классическом функциональном программировании повторное выполнение одной и той же части кода подряд реализовано как рекурсия. Рекурсивная функция – функция, которая
при выполнении
вызывает саму себя с другими аргументами до сраба-
тывания условия завершения.
8. Лямбда-исчисление (λ-исчисление). Это формальная система,
которая используется в функциональных языках программирования
[61]:
лямбда-функция – это анонимная функция, или лямбда-выраже-
ние (сокращенная запись функции), объявляемое в том месте контекста,
54

где она будет применяться. Не идентифицируется именем и вызывается
автоматически другими функциями;
в λ-исчислении есть две основные операции: аппликация и аб-
стракция. Первая – это вызов функции к заданному значению. Вторая –
построение функции по имеющимся выражениям.
Дополнительной особенностью функциональных языков является
конкурентность вычислений, при которой процессы выполняются
в многопоточном режиме
, что дает возможность выполнять несколько
процессов параллельно, обеспечивая быстродействие программ.
Благодаря своим особенностям функциональное программирование
и функциональные языки полезны в таких областях, как DataScience
BigData
2
и создание систем искусственного интеллекта. Эти области
1
требуют огромного количества сложных вычислений за короткий промежуток времени.
К языкам, поддерживающим исключительно функциональную парадигму, относятся Haskell, F# [62–64].
Императивные языки, такие как JavaScript, Python, C++, C#, включают языковые конструкции, позволяющие создавать программы в
функциональном стиле для большей гибкости и производительности
кода в целом [65].
Логическое программирование [66, 67] –
парадигма программирования с автоматическим доказательством теорем и использованием механизмов логического вывода информации на основе заданных фактов
и правил вывода.
Вместо описания алгоритма решения в программе описывается
предметная область задачи: объекты, их свойства и отношения между
ними, т. е. создается своего рода база данных о предметной области задачи, содержащая
набор фактов и правил, на основании которых могут
быть получены новые отношения путем логического вывода.
1
DataScience – это междисциплинарная область на стыке статистики, мате-
матики, системного анализа и машинного обучения, которая охватывает все
этапы работы с данными. Она предполагает исследование и анализ сверхбольших массивов информации и ориентирована в первую очередь на получение
практических результатов.
2
BigData – это разнообразные по структуре данные, поступающие с более
высокой скоростью, объем которых постоянно растет. Таким образом, три основных свойства больших данных – это разнообразие, высокая скорость поступления и большой объем (3V – variety, velocity, volume).
,
55

Язык Пролог и логическое программирование широко используются для создания баз знаний и экспертных систем и исследований
в сфере искусственного интеллекта на основе логических моделей баз
знаний и логических процедур вывода и принятия решений.
МНОГОПОТОЧНОЕ ПРОГРАММИРОВАНИЕ
Работа многих современных операционных систем основана на вытесняющей многозадачности. Многозадачность – свойство операционной системы обеспечивать возможность параллельной (или псевдопараллельной) обработки нескольких задач (программ).
Многозадачный режим – режим, который предусматривает параллельную работу или чередующееся выполнение двух или более задач [3].
Вытесняющая многозадачность – это вид многозадачности, при которой операционная система принимает
решение о переключении
между задачами (переключении процессора с выполнения одного процесса на другой) по истечении некоторого отрезка (кванта) времени (см.
раздел «Невытесняющая многозадачность» [68]). Если эти отрезки времени достаточно малы и компьютер не перегружен слишком большим
числом программ, то пользователю кажется, что все эти программы выполняются параллельно.
Существует
два типа многозадачности [69].
Процессная многозадачность (основанная на процессах – одновре-
менно выполняющихся программах). Здесь программа – наименьший
элемент, разделяющий время процессора.
Поточная многозадачность (основанная на потоках). Наименьший
элемент – поток (одна программа может выполнять две и более задачи
одновременно (псевдопараллельно)).
Процесс – программа, определяемая в операционной системе контекстом
3
и находящаяся в одном из определенных состояний, выпол-
няемая в текущий момент. Процесс включает в себя загруженную
в оперативную память исполняемую программу, виртуальное адресное
пространство, системные и пользовательские ресурсы, выделенные
3
Контекст программы – в каждой конкретный момент выполнения про-
граммы содержимое всех переменных элементов (регистров, ячеек памяти), которое требуется установить/восстановить, чтобы стало возможным запустить
выполнение программы с этого момента.
56

программе. Операционная система использует процессы для разделения исполняемых приложений.
Поток – процесс внутри другого процесса, использующий ресурсы
последнего [3].
Все процессы имеют, по крайней мере, один поток управления, который обычно называется основным, поскольку именно с этого потока
начинается выполнение программы. Из основного можно создать и другие потоки.
Поток может находиться
в одном из нескольких состояний. Он может выполняться или быть готовым к выполнению (как только получит
время процессора). Выполняющийся поток может быть приостановлен,
т. е. его выполнение временно прекращается. Позже оно может быть
возобновлено. Поток может быть заблокирован в ожидании необходимого ресурса. Наконец, поток может завершиться, в этом
случае его вы-
полнение окончено и продолжению (возобновлению) не подлежит.
Многопоточность – свойство операционной системы или приложения, состоящее в том, что процесс, порожденный в операционной системе, может состоять из нескольких потоков, выполняющихся «параллельно», т. е. без предписанного порядка во времени. Многопоточность
позволяет увеличивать скорость реагирования приложения и, если
приложение работает в многопроцессорной или многоядерной системе, то
пропускную способность и более эффективное использование ресурсов
вычислительной машины.
Многопоточность – это специализированная форма многозадачности. В многозадачной ОС Windows единицей многозадачности является поток, а не процесс. Все программы в этой ОС выполняются в
потоках.
Каждый поток имеет приоритет планирования и набор структур
в которых система сохраняет контекст потока, когда выполнение потока
приостановлено. Контекст потока содержит все сведения, позволяющие
потоку безболезненно возобновить выполнение, в том числе набор регистров процессора и стек потока. Несколько потоков могут выполняться в контексте процесса. Все потоки процесса используют общий
диапазон виртуальных адресов
4
. Поток может исполнять любую часть
4
Виртуальный адрес – адрес, идентифицирующий локализацию байта
в виртуальном адресном пространстве. Блок управления памятью транслирует
виртуальный адрес в физический.
,
57

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

3.
Более эффективное использование мультипроцессирования: как
правило, приложения, реализующие параллелизм через потоки, не
должны учитывать число доступных процессоров. Производительность
приложения равномерно растет при наличии дополнительных процессоров.
4. Улучшенная структура программы: некоторые программы более
эффективно представляются в виде нескольких независимых или полуавтономных единиц, чем в виде единой монолитной программы. Многопоточные программы легче адаптировать к изменениям требований
пользователя.
5. Эффективное использование ресурсов системы: программы, ис-
пользующие два процесса или более, которые имеют доступ к общим
данным через разделяемую память, содержат более одного потока
управления. При этом каждый процесс имеет полное адресное пространство и состояние в операционной системе. Стоимость создания
и поддержания большого количества служебной информации делает
каждый процесс более
затратным, чем поток. Кроме того, разделение
работы между процессами может потребовать от программиста значительных усилий, чтобы обеспечить связь между потоками в различных
процессах или синхронизировать их действия.
Однако многопоточность программы требует дополнительных усилий разработчика, потому что многопоточность программы реализуется
только программистом, а не операционной системой. Операционная система
лишь распределяет выполнение потоков по степени их важности,
но не формирует потоки отдельных процессов.
Разработчикам приходится создавать специальные алгоритмы, которые могут эффективно распределять задачи между ядрами процессора.
Если алгоритмы не будут оптимизированы, то производительность
устройства может быть даже меньше, чем при использовании обычного
процессора.
ПАРАЛЛЕЛЬНОЕ И РАСПРЕДЕЛЕННОЕ ПРОГРАММИРОВАНИЕ
Параллелизм – возможность выполнения различных частей или команд программы, алгоритма или задачи вне очереди или в частичном
порядке, не влияющем на конечный результат.
Параллелизм задач – метод вычислений, при котором вычислительную задачу разделяют на несколько самостоятельных подзадач [70].
59

Параллелизация программы – это нелегкая задача для разработчика,
поскольку необходимо решать, какие части программы могут выполняться одновременно, какую схему параллелизации выбрать, как эти части будут взаимодействовать.
Параллельное и распределенное программирование – это два базовых подхода к достижению параллельного выполнения составляющих
программного обеспечения. Они представляют собой две различные парадигмы
программирования, которые иногда пересекаются [71–74].
Методы параллельного программирования позволяют распределить работу программы между двумя (или больше) процессорами или
ядрами в рамках одного физического или одного виртуального компьютера.
Методы распределенного программирования позволяют распределить работу программы между двумя (или больше) процессами, причем процессы могут существовать на одном и том же
компьютере или
на разных. Другими словами, части распределенной программы нередко
выполняются на разных компьютерах, связываемых по сети, или, по
крайней мере, в различных процессах.
Программу, содержащую параллелизм, можно разбить на процессы
или потоки. Распределенные программы разбиваются только на процессы.
Параллельное программирование – это модель программирова-
ния, которая позволяет создавать программы,
эффективно использующие вычислительные ресурсы за счет одновременного исполнения кода
на нескольких процессорах или ядрах. Современные многопроцессорные и многоядерные ЭВМ представляют собой мощные вычислительные средства, и они используются неэффективно, если программное
обеспечение для них представляют собой обычные последовательные
программы.
Преимущества параллельного программирования:
возможность выполнения нескольких задач в один
момент;
программы, надлежащее качество проектирования которых поз-
воляет воспользоваться преимуществами параллелизма, могут выполняться быстрее, чем их последовательные эквиваленты, что повышает
их рыночную стоимость;
эффективность использования вычислительных ресурсов. Боль-
шинство современных компьютеров имеет аппаратное обеспечение,
60
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
