Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Технологии и методы программирования. Учебное пособие-1

.pdf
Скачиваний:
0
Добавлен:
07.09.2026
Размер:
2 Мб
Скачать
Класс – это тип, описывающий структуру объектов. Объектэто экземпляр класса. Обычно классы разрабатывают таким образом, чтобы их объекты соответствовали реальным или виртуальным объектам предметной области.
Структура объекта включает атрибуты и методы:
атрибуты – это переменные, конкретные характеристики объекта;.
методы – это функции, которые описаны внутри класса. Они поз-
воляют взаимодействовать объекту
с другими объектами.
Множество атрибутов и методов, доступных извне, рассматривается как интерфейс для доступа к объекту.
ПРИНЦИПЫ ООП
Объектно-ориентированное программирование определяют через четыре принципа, по которым можно понять основы работы.
Абстракция (абстрагирование) – это способ выделить минималь­ный набор наиболее важных атрибутов и методов, позволяющих решить поставленную задачу.
Абстрактный класс – класс, в котором реализация методов неопре­деленна. Это позволяет создавать конкретные классы, не описывая реа­лизацию методов заранее (
в этом суть абстракции), а предоставляя ба-
зовый шаблон для дальнейших надстроек.
Инкапсуляция – класс объединяет описание свойств объектов и их поведения в единое целое, так что невозможно напрямую получить до­ступ к внутренней структуре объекта (сокрытие реализации). Инкапсу­ляция вытекает из самой идеи объектно-ориентированного программи­рования.
Наследование позволяет реализовывать
сложную иерархию клас­сов «от общего к частному». Дочерние классы наследуют особенности родительских, дополняя или в определенной степени модифицируя их характеристики. Преимущество, которое дает концепция наследования в программировании, – отсутствие повторения кода в разных частях программы. Это облегчает понимание и масштабирование кода. Как правило, рассматривается одиночное наследование (от одного роди­тельского класса
), но возможно и множественное наследование (от не-
скольких родителей). Варианты множественного наследования:
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
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]