В разработке программного обеспечения и информатике абстракция — это процесс обобщения конкретных деталей, [1] таких как атрибуты , вдали от изучения объектов и систем , чтобы сосредоточить внимание на более важных деталях. [2] Абстракция — фундаментальная концепция в информатике и разработке программного обеспечения , особенно в парадигме объектно-ориентированного программирования . [3] Примеры этого включают:
Суть абстракции заключается в сохранении информации, актуальной в данном контексте, и забвении информации, нерелевантной в этом контексте.
- Джон В. Гуттаг [5]
Вычисления в основном работают независимо от конкретного мира. Аппаратное обеспечение реализует модель вычислений , взаимозаменяемую с другими. [6] Архитектура программного обеспечения позволяет людям создавать огромные системы, концентрируясь на нескольких задачах одновременно. Эти архитектуры состоят из определенного выбора абстракций. Десятое правило Гринспана — это афоризм о том, что такая архитектура одновременно неизбежна и сложна.
Языковая абстракция — центральная форма абстракции в вычислительной технике: разрабатываются новые искусственные языки для выражения конкретных аспектов системы. Языки моделирования помогают в планировании. Компьютерные языки можно обрабатывать с помощью компьютера. Примером этого процесса абстракции является поколенческое развитие языка программирования от машинного языка до языка ассемблера и языка высокого уровня . Каждый этап можно использовать как трамплин для следующего этапа. Языковая абстракция продолжается, например, в языках сценариев и предметно-ориентированных языках программирования .
Некоторые функции языка программирования позволяют программисту создавать новые абстракции. К ним относятся подпрограммы , модули , полиморфизм и программные компоненты . Некоторые другие абстракции, такие как шаблоны проектирования программного обеспечения и архитектурные стили, остаются невидимыми для переводчика и действуют только при проектировании системы.
Некоторые абстракции пытаются ограничить диапазон понятий, которые должен знать программист, полностью скрывая абстракции, на которых они построены. Инженер-программист и писатель Джоэл Спольски раскритиковал эти усилия, заявив, что все абстракции негерметичны – что они никогда не смогут полностью скрыть детали, расположенные ниже; [7] однако это не отменяет полезности абстракции.
Некоторые абстракции предназначены для взаимодействия с другими абстракциями — например, язык программирования может содержать интерфейс внешней функции для выполнения вызовов языка более низкого уровня.
Различные языки программирования предоставляют разные типы абстракции в зависимости от предполагаемого применения языка. Например:
function(parameters) = 0;
abstract
interface
Аналитики разработали различные методы формальной спецификации программных систем. Некоторые известные методы включают в себя:
Языки спецификаций обычно полагаются на абстракции того или иного типа, поскольку спецификации обычно определяются в проекте раньше (и на более абстрактном уровне), чем конечная реализация. Например , язык спецификации UML позволяет определять абстрактные классы, которые в водопадном проекте остаются абстрактными на этапах архитектуры и спецификации проекта.
Языки программирования предлагают абстракцию управления как одну из основных целей своего использования. Компьютерные машины понимают операции на очень низком уровне, такие как перемещение некоторых битов из одного места памяти в другое и создание суммы двух последовательностей битов. Языки программирования позволяют сделать это на более высоком уровне. Например, рассмотрим этот оператор, написанный в стиле Паскаля :
a := (1 + 2) * 5
Человеку это кажется довольно простым и очевидным расчетом ( «один плюс два — три, умножить на пять — пятнадцать» ). Однако шаги низкого уровня, необходимые для выполнения этой оценки и возврата значения «15», а затем присвоения этого значения переменной «a», на самом деле довольно тонкие и сложные. Значения необходимо преобразовать в двоичное представление (часто это гораздо более сложная задача, чем можно было бы подумать), а вычисления разложить (компилятором или интерпретатором) на ассемблерные инструкции (опять же, которые гораздо менее интуитивно понятны программисту: такие операции, как сдвиг двоичного регистра влево или добавление двоичного дополнения содержимого одного регистра к другому — это просто не то, как люди думают об абстрактных арифметических операциях сложения или умножения). Наконец, присвоение результирующего значения «15» переменной с меткой «a», чтобы «a» можно было использовать позже, включает в себя дополнительные «закулисные» шаги по поиску метки переменной и ее результирующего местоположения в физической памяти. или виртуальную память, сохраняя двоичное представление «15» в этой ячейке памяти и т. д.
Без абстракции управления программисту пришлось бы указывать все шаги регистрового/двоичного уровня каждый раз, когда он просто хотел сложить или умножить пару чисел и присвоить результат переменной. Такое дублирование усилий имеет два серьезных негативных последствия:
Структурированное программирование предполагает разделение сложных программных задач на более мелкие части с четким управлением потоками и интерфейсами между компонентами, а также снижение потенциальной сложности для побочных эффектов.
В простой программе это может быть направлено на то, чтобы циклы имели единственную или очевидную точку выхода и (где это возможно) имели единственную точку выхода из функций и процедур.
В более крупной системе это может включать разбиение сложных задач на множество различных модулей. Рассмотрим систему расчета заработной платы на судах и в береговых офисах:
Эти уровни создают эффект изоляции деталей реализации одного компонента и его различных внутренних методов от других. Объектно-ориентированное программирование охватывает и расширяет эту концепцию.
Абстракция данных обеспечивает четкое разделение между абстрактными свойствами типа данных и конкретными деталями его реализации. Абстрактные свойства — это те, которые видны клиентскому коду, который использует тип данных (интерфейс к типу данных), в то время как конкретная реализация остается полностью конфиденциальной и действительно может меняться, например, для включения улучшений эффективности с течением времени. Идея состоит в том, что такие изменения не должны оказывать никакого влияния на клиентский код, поскольку они не влекут за собой никаких изменений в абстрактном поведении.
Например, можно определить абстрактный тип данных , называемый справочной таблицей , который уникальным образом связывает ключи со значениями и в котором значения можно получить, указав соответствующие им ключи. Такая таблица поиска может быть реализована различными способами: как хеш-таблица , двоичное дерево поиска или даже простой линейный список пар (ключ:значение). Что касается клиентского кода, абстрактные свойства типа в каждом случае одинаковы.
Конечно, все это в первую очередь зависит от правильного получения деталей интерфейса, поскольку любые изменения в нем могут иметь серьезные последствия для клиентского кода. Один из способов взглянуть на это так: интерфейс формирует контракт о согласованном поведении между типом данных и клиентским кодом; все, что не указано в договоре, может быть изменено без предварительного уведомления.
Хотя большая часть абстракции данных происходит с помощью информатики и автоматизации, бывают случаи, когда этот процесс выполняется вручную и без вмешательства программирования. Один из способов понять это — абстракция данных в процессе проведения систематического обзора литературы. В этой методологии данные абстрагируются одним или несколькими абстракторами при проведении метаанализа , при этом ошибки уменьшаются за счет двойной абстракции данных с последующей независимой проверкой, известной как судебное решение . [11]
В теории объектно-ориентированного программирования абстракция включает в себя возможность определять объекты, которые представляют собой абстрактных «актеров», которые могут выполнять работу, сообщать о своем состоянии и изменять его, а также «общаться» с другими объектами в системе. Термин «инкапсуляция» относится к сокрытию деталей состояния , но расширение концепции типа данных из более ранних языков программирования для наиболее тесной связи поведения с данными и стандартизации способа взаимодействия различных типов данных является началом абстракции . Когда абстракция переходит в определенные операции, позволяющие заменять объекты разных типов, это называется полиморфизмом . Когда оно происходит в противоположном направлении, внутри типов или классов, структурируя их для упрощения сложного набора отношений, это называется делегированием или наследованием .
Различные языки объектно-ориентированного программирования предлагают схожие возможности абстракции, и все это для поддержки общей стратегии полиморфизма в объектно-ориентированном программировании, которая включает замену одного типа другим в той же или аналогичной роли. Хотя конфигурация, образ или пакет обычно не поддерживаются, они могут предопределить очень многие из этих привязок во время компиляции , времени компоновки или времени загрузки . В результате во время выполнения будет изменяться лишь минимум таких привязок .
Например, в Common Lisp Object System или Self меньше различий между классами и экземплярами, а больше используется делегирование для полиморфизма . Отдельные объекты и функции абстрагируются более гибко, чтобы лучше соответствовать общему функциональному наследию Lisp .
C++ иллюстрирует другую крайность: он сильно полагается на шаблоны , перегрузку и другие статические привязки во время компиляции, что, в свою очередь, имеет определенные проблемы с гибкостью.
Хотя эти примеры предлагают альтернативные стратегии достижения той же абстракции, они принципиально не меняют необходимость поддержки абстрактных существительных в коде — все программирование опирается на способность абстрагировать глаголы как функции, существительные как структуры данных или как процессы.
Рассмотрим, например, пример фрагмента Java , представляющий некоторых обычных сельскохозяйственных «животных» на уровне абстракции, подходящем для моделирования простых аспектов их голода и кормления. Он определяет Animal
класс для представления как состояния животного, так и его функций:
общественный класс Animal расширяет LivingThing { частное местоположение loc ; частные двойные энергетические резервы ; public boolean isHungry () { return EnergyReserves < 2.5 ; } public void eat ( Food food ) { // Потребляем еду EnergyReserves += food . Получить калории (); } public void moveTo ( Местоположение ) { // Переместить в новое место this . лок = местоположение ; } }
Используя приведенное выше определение, можно создавать объекты типаЖивотноеи вызовите их методы следующим образом:
thePig = новое животное (); theCow = новое животное (); если ( thePig . isHungry ()) { thePig . съесть ( tableScraps ); } Если ( theCow . isHungry ()) { theCow . есть ( траву ); } Корова . переместитьTo ( theBaRN );
В приведенном выше примере класс Animal
представляет собой абстракцию, используемую вместо реального животного, и LivingThing
является дальнейшей абстракцией (в данном случае обобщением) класса Animal
.
Если требуется более дифференцированная иерархия животных – чтобы отличить, скажем, тех, кто дает молоко, от тех, кто не дает ничего, кроме мяса в конце своей жизни – это промежуточный уровень абстракции, вероятно DairyAnimal (коровы, козы), который бы есть продукты, подходящие для получения хорошего молока, и мясных животных (свиньи, бычки), которые едят продукты, обеспечивающие лучшее качество мяса.
Такая абстракция может избавить программиста приложения от необходимости указывать тип пищи, и вместо этого они смогут сосредоточиться на графике кормления. Эти два класса могут быть связаны с помощью наследования или использоваться отдельно, и программист может определить различные степени полиморфизма между этими двумя типами. Эти возможности, как правило, сильно различаются в зависимости от языка, но в целом каждый из них может достичь всего, что возможно с любым другим. Множество перегрузок операций, тип данных за типом данных, могут иметь тот же эффект во время компиляции, что и любая степень наследования или другие средства достижения полиморфизма. Обозначение класса — это просто удобство программиста.
Решения относительно того, что абстрагировать, а что оставить под контролем программиста, становятся основной задачей объектно-ориентированного проектирования и анализа предметной области — фактически определение соответствующих отношений в реальном мире является задачей объектно-ориентированного анализа или анализа наследия.
В общем, чтобы определить подходящую абстракцию, необходимо принять множество небольших решений относительно объема (анализ предметной области), определить, с какими другими системами необходимо сотрудничать (анализ наследия), а затем выполнить подробный объектно-ориентированный анализ, который выражается в рамках времени и бюджета проекта. ограничения как объектно-ориентированный дизайн. В нашем простом примере доменом является скотный двор, живые свиньи и коровы, а также их пищевые привычки являются устаревшими ограничениями, детальный анализ показывает, что программисты должны иметь возможность кормить животных тем, что доступно, и, следовательно, нет смысла писать код. тип еды в сам класс, а дизайн представляет собой один простой класс Animal, экземплярами которого являются свиньи и коровы с одинаковыми функциями. Решение о дифференциации DairyAnimal изменило бы подробный анализ, но анализ предметной области и наследия останется неизменным - таким образом, он полностью находится под контролем программиста и называется абстракцией в объектно-ориентированном программировании в отличие от абстракции в предметной области или наследии. анализ.
При обсуждении формальной семантики языков программирования , формальных методов или абстрактной интерпретации абстракция относится к рассмотрению менее подробного, но безопасного определения наблюдаемого поведения программы. Например, можно наблюдать только конечный результат выполнения программы вместо того, чтобы рассматривать все промежуточные этапы выполнения. Абстракция определяется конкретной (более точной) моделью выполнения.
Абстракция может быть точной или верной в отношении свойства, если можно одинаково хорошо ответить на вопрос о свойстве на конкретной или абстрактной модели. Например, если кто-то хочет знать, сколько стоит результат вычисления математического выражения, включающего только целые числа +, -, ×, по модулю n , то нужно только выполнить все операции по модулю n (знакомая форма этой абстракции - приведение вне девяток ).
Однако абстракции, хотя и не обязательно точные , должны быть обоснованными . То есть от них должно быть возможно получить обоснованные ответы, даже несмотря на то, что абстракция может просто дать результат неразрешимости . Например, учащихся в классе можно абстрагировать по их минимальному и максимальному возрасту; если спросить, принадлежит ли определенный человек к этому классу, можно просто сравнить возраст этого человека с минимальным и максимальным возрастом; если его возраст лежит за пределами диапазона, можно смело ответить, что человек не принадлежит к классу; если нет, можно ответить только «не знаю».
Уровень абстракции, включенный в язык программирования, может влиять на его общее удобство использования . Структура когнитивных измерений включает в себя концепцию градиента абстракции в формализме. Эта структура позволяет разработчику языка программирования изучать компромиссы между абстракцией и другими характеристиками проекта, а также то, как изменения в абстракции влияют на удобство использования языка.
Абстракции могут оказаться полезными при работе с компьютерными программами, поскольку нетривиальные свойства компьютерных программ по существу неразрешимы (см. теорему Райса ). Как следствие, автоматические методы получения информации о поведении компьютерных программ должны либо отказаться от завершения (в некоторых случаях они могут дать сбой, выйти из строя или вообще не дать результата), либо от надежности (они могут предоставлять ложную информацию), либо от точности (они могут предоставлять ложную информацию). на некоторые вопросы они могут ответить «Я не знаю»).
Абстракция – это основная концепция абстрактной интерпретации . Проверка модели обычно происходит на абстрактных версиях изучаемых систем.
Информатика обычно представляет уровни (или, реже, слои ) абстракции, где каждый уровень представляет собой отдельную модель одной и той же информации и процессов, но с разным количеством деталей. На каждом уровне используется система выражения, включающая уникальный набор объектов и композиций, применимых только к определенной области. [12] Каждый относительно абстрактный, «более высокий» уровень основывается на относительно конкретном, «более низком» уровне, который имеет тенденцию обеспечивать все более «детализированное» представление. Например, вентили построены на электронных схемах, двоичные данные — на вентилях, машинный язык — на двоичном коде, язык программирования — на машинном языке, приложения и операционные системы — на языках программирования. Каждый уровень воплощается, но не определяется уровнем, находящимся под ним, что делает его языком описания, который в некоторой степени самодостаточен.
Поскольку многие пользователи систем баз данных недостаточно хорошо знакомы с компьютерными структурами данных, разработчики баз данных часто скрывают сложность за счет следующих уровней:
Физический уровень. Самый низкий уровень абстракции описывает, как система фактически хранит данные. Физический уровень подробно описывает сложные низкоуровневые структуры данных.
Логический уровень. Следующий более высокий уровень абстракции описывает, какие данные хранятся в базе данных и какие отношения существуют между этими данными. Таким образом, логический уровень описывает всю базу данных в терминах небольшого числа относительно простых структур. Хотя реализация простых структур на логическом уровне может включать сложные структуры физического уровня, пользователю логического уровня не обязательно знать об этой сложности. Это называется физической независимостью данных . Администраторы баз данных , которые должны решить, какую информацию хранить в базе данных, используют логический уровень абстракции.
Уровень представления: самый высокий уровень абстракции описывает только часть всей базы данных. Несмотря на то, что на логическом уровне используются более простые структуры, сложность остается из-за разнообразия информации, хранящейся в большой базе данных. Многим пользователям системы баз данных не нужна вся эта информация; вместо этого им нужен доступ только к части базы данных. Уровень абстракции представления существует для упрощения их взаимодействия с системой. Система может предоставлять множество представлений для одной и той же базы данных.
Возможность обеспечить проектирование различных уровней абстракции может
Это можно использовать как при проектировании систем , так и при проектировании бизнес-процессов . Некоторые процессы проектирования специально создают проекты, содержащие различные уровни абстракции.
Многоуровневая архитектура разделяет задачи приложения на составные группы (уровни). Это метод, используемый при разработке компьютерного программного обеспечения, оборудования и средств связи, при котором системные или сетевые компоненты изолируются по уровням, чтобы изменения можно было вносить на одном уровне, не затрагивая другие.