Абстракция (компютърни науки)

от Уикипедия, свободната енциклопедия
Jump to navigation Jump to search

В компютърните науки абстракцията е техника за управление сложността на компютърните системи. Тя работи като създава ниво на сложност, на което човек комуникира със системата, оставяйки по-сложните детайли под това ниво. Програмистът работи с идеализиран интерфейс (обикновено добре дефиниран) и може да добавя различни нива на функционалност, които биха били прекалено сложни за управление без различните нива на абстракция. Например, програмист, пишещ код, който включва числови оператори, може да не се интересува от начина, по който числата са представени в хардуера (например дали са 16 битов или 32 битов целочислен тип) и къде са скрити тези детайли. Може да се каже, че данните за цифрите са абстрахирани, оставяйки само числата, с които програмистът може да работи. Задачата да се изпрати електронна поща между континентите би била изключително сложна, ако се започне от парче оптичен кабел и основни хардуерни компоненти. Чрез използване на нива за сложност, които са създадени, за да се абстрахира човек от физическите кабели и мрежата, и предоставяйки виртуален канал за данни, задачата е осъществима. Абстракцията е механизъм, с който една сложна концепция се свежда до няколко прости инструмента, с които се борави лесно. Използването на абстракции при създаването на компютърни програми дава възможност за сложните обекти да се мисли като за прости такива. Абстракциите лежат в основата на обектно-ориентираното програмиране.

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

Можем да разглеждаме идеята за обект като начин да обединим абстракцията на данни и код. Същата дефиниция може да бъде използвана като общ интерфейс за семейство от обекти с различна имплементация и поведение, но които споделят едно общо значение. Механизмът за наследяване в обектно-ориентираното програмиране може да бъде използван за дефиниране на абстрактен клас като общ интерфейс. Препоръката програмистите да използват абстракция, когато е подходящо, е не само с цел да се избягва повторението на код, а и защото това води до повишаване издръжливостта на програмата срещу промени, които могат да изникнат на по-късен етап от нейното съществуване. Изискването един език за програмиране да предоставя подходяща абстракция се нарича принцип на абстракцията.

Фундаменти[редактиране | редактиране на кода]

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

Централна форма на абстракция в света на софтуера е абстракцията на езика: новите изкуствени езици са разработени, за да изразяват специфичните аспекти на дадена система. Компютърните езици могат да бъдат реализирани само с компютър. Пример за този процес на абстракция е последователното разработване на програмни езици от машинен език към език за програмиране на ниско ниво (асемблерен език) и език за програмиране на високо ниво. Всяка фаза на развитие може да бъде използвана като стъпало към следващото ниво. Абстракцията на езика продължава например в скриптовите езици.

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

Някои абстракции се опитват да ограничат концепциите, от които програмистът има нужда, като скриват напълно начина, по който са построени. Софтуерният инженер Джоел Сполски критикува тези усилия, като заявява, че всички абстракции са „изпускащи“ – т.е те никога няма напълно да скрият детайлите отдолу[1], но това не отрича полезността на абстракцията. Някои абстракции са моделирани да са взаимозаменяеми с други. Например програмният език може да съдържа чужди функционални интерфейси (може да извика интерфейс от друг програмен език), за да направи обръщение към програмен език от по-ниско ниво. Абстракцията на данни е отделянето на спецификацията на обект от данни от неговата имплементация.

Характеристики на езика[редактиране | редактиране на кода]

Езици за програмиране[редактиране | редактиране на кода]

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

  • В обектно-ориентираните програмни езици като C++, Object Pascal, или Java, понятието абстракция само по себе си е декларативно твърдение – използвайки ключовите думи виртуален (при C++) или абстракция и интерфейс (при Java). След подобно деклариране, програмистът трябва да имплементира (реализира) клас, за да инициализира обекта на декларацията;
  • Функционалните програмни езици често показват абстракции свързани с функции, като например ламбда абстракцията (превръщайки даден израз във функция на някои променливи), по-висока степен на функционалност (параметрите са функции), абстракции в скоби (превръщайки израза във функция на променлива);
  • Съвременните Лисп езици за програмиране като Clojure, Scheme и Common Lisp подпомагат макро системите, за да позволят синтактична абстракция. Това позволява на програмиста работещ с Lisp да елиминира така наречения шаблонен код, да отделя еднообразните функции наречени поредици, да имплементира нови контролирани структурни потоци, да имплементира или дори построи така наречените домейн специфични езици, които позволяват специфичните понятия да бъдат изразявани по някакъв оптимизиран начин. Всичко това, когато се използва по правилния начин, подобрява ефективността на програмиста и яснотата на кода като прави желаната цел по-ясна. Освен това, в резултат на синтактичната абстракция, когато всеки един Lisp диалект и всъщност почти всеки програмен език, може да бъде имплементиран в съвременния Lisp език със значително намаленo усилие в сравнение с традиционните програмни езици като Python, C или Java.

Методи на спецификация[редактиране | редактиране на кода]

Аналитици са разработили разнообразни методи за интегриране на официалните софтуерни системи. Някои методи включват:

  • Метод базиран на абстрактни модели;
  • Алгебрични техники;
  • Техники базирани на процеси;
  • Техники базирани на проследяване;
  • Техники базирани на познания.

Езици за спецификация[редактиране | редактиране на кода]

Езиците за спецификация обикновено разчитат на абстракции от един или друг вид, тъй като спецификациите се дефинират по-рано в даден проект, (и на по-абстрактно ниво) отколкото евентуална имплементация. UML езикът за спецификация, например позволява дефиницията на абстрактни класове, които остават абстрактни по време на построяването/архитектурата и фазата на техническото задание на даден проект

Абстракция за контрол[редактиране | редактиране на кода]

Контрол на потока[редактиране | редактиране на кода]

Абстракцията за контрол е една от основните цели на програмните езици, които я предлагат. Компютърните машини разбират операции на много ниско ниво като преместване на няколко бита от една локация в паметта в друга и произвеждат сумата на две поредици от битове. Програмните езици позволяват това да се случва на едно по-високо ниво. Например, изразът записан в Паскал:

a := (1 + 2) * 5

За човек това изглежда доста проста и очевидна калкулация (1 + 2 е равно на 3, умножено по 5 е 15). Стъпките на ниско ниво необходими да се изпълни този израз, да върне 15 и след това тази стойност да се присвои на променливата "а" всъщност са скрити и сложни. Стойностите трябва да бъдат конвертирани в двоичния им вид (често това е много по-сложна задача отколкото човек може да си представи) и калкулациите раздробени на съставните има части (от компилатор или интерпретатор) в асемблер инструкции (отново по-малко интуитивни за програмиращия: операции като местене на бинарен регистър на ляво или добавяне на бинарен компонент(бит) в съдържанието от един регистър в друг, като това не е начина по който един човек мисли за абстрактните аритметични операции за добавяне и умножаване). И накрая, присвояването на крайната стойност „15“ към променливата наречена „а“, така че „а“ да може да бъде използвана на по-късен етап, включва допълнителни „задкулисни“ стъпки на преглед на променливата и крайното и местоположение във физическата или виртуалната памет, запазвайки бинарното представяне на стойността „15“ на определено място в паметта.

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

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

Структурно програмиране[редактиране | редактиране на кода]

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

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

При по-голяма система, това може да включва разбиването на сложните задачи на много различни модули. Например система, която се занимава с плащания на кораби на пристанищен офис:

  • Най-високото ниво може да включва меню от типични операции за крайните потребители;
  • Заедно с това могат да бъдат обособени самостоятелни библиотеки за задачи като например назначаването или освобождаването на служители или отпечатване на чекове;
  • В рамките на всеки един от тези самостоятелни компоненти може да има многобройни различни изходни файлове, всеки от които съдържащ програмен код решаващ даден проблем, само с избрани интерфейси достъпни за други части на програмата. В програмата може да има изходни файлове за всяко постъпване на данни и интерфейс базиран на база данни (който сам по себе си може да бъде самостоятелна трета библиотека или статично свързан списък съдържащ поредица библиотеки).

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

Тези слоеве произвеждат ефекта на изолиране на изпълнимите елементи на един компонент от останалите вътрешни методи. Обектно-ориентираното програмиране обхваща и развива това понятие.


Абстракция на данни[редактиране | редактиране на кода]

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

Например, някой би могъл да дефинира абстрактен тип данни наречен "lookup table", който свързва по уникален начин ключове и стойности, при което стойностите биха могли да бъдат извличани чрез посочването на съответстващия им ключ. Подобна lookup table би могла да бъде имплементирана в различни случаи: като хеш-таблица или двоично дърво за търсене от двойки ключ-стойност. Доколкото това се отнася до кода на клиента, абстрактните свойства на типа данни са еднакви във всеки от случаите.

Разбира се, всичко това разчита на първо място на правилното взимане на детайли от страна на интерфейса, след като всяка промяна там би могла да окаже сериозно влияние върху кода на клиента. Това може да бъде погледнато по следния начин – интерфейсът формира договореност за определено поведение между типа данни и кода на клиента, всичко което не е упоменато в тази договореност е предмет на промяна без да се обявява.

Езици, които имплементират абстракцията на данни включват Ада (език за програмиране) и Модула-2 (език за програмиране). За обектно-ориентирани езици най-често се посочват такива, които предлагат абстракция на данни, въпреки че концепцията на тяхното наследяване се грижи да поставя информация в интерфейса, която повече подхожда да е в имплементацията. Освен това промените в тази информация оказват влияние върху кода на клиента, водейки до т.нар. Fragile binary interface problem.

Абстракция в обектно-ориентираното програмиране[редактиране | редактиране на кода]

В обектно-ориентираното програмиране абстракцията включва умението да се дефинират обекти, представляващи абстрактни „лица“, които могат да извършват действия, да дават информация, да променят своето състояние и да комуникират с други обекти в системата. Понятието енкапсулация е началото на абстракцията. То е свързвано със скриването на данни за състоянието на обектите и продължава концепцията за типовете данни от ранните езици за програмиране, да се обвърже поведението с данните и стандартизирането на пътя за взаимодействие на различните типове данни. Когато абстракцията преминава в дефинирането на операции, които позволяват обекти от различен тип да бъдат заменяни, това се нарича полиморфизъм. Когато тя протича в противоположна посока, вътре в типовете или класовете, структурирайки ги с цел да се опростят сложните връзки между тях, абстракцията се нарича делегиране или наследяване.

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

Common Lisp Object System или Self например, включват по-малко инстанциране на класове и повече употреба на делегирането при полиморфизъм. Индивидуалните обекти и функции са по-гъвкави на абстрактно ниво, с цел по-добро съответствие и функционално наследяване от Lisp.

C++ от своя страна попада в друга крайност. При него се залага силно на темплейти, претоварване и други статични връзки при компилиране, което в случая не е толкова гъвкаво.

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

Нека разгледаме следният Java код, който представя някои "животни" на ниво на абстракция подходящо за моделирането на отделни техни аспекти като глад и хранене. Дефиниран е класът Animal, който представлява състоянието на "животното" и неговите функционалности:


public class Animal extends LivingThing
{
     private Location loc;
     private double energyReserves;

     public boolean isHungry() {
         return energyReserves < 2.5;
     }
     public void eat(Food food) {
         // Consume food
         energyReserves += food.getCalories();
     }
     public void moveTo(Location location) {
         // Move to new location
         this.loc = location;
     }
}


Чрез горната дефиниция бихме могли да създадем обекти от клас Animal и да извикаме техните методи по следния начин:


thePig = new Animal();
theCow = new Animal();
if (thePig.isHungry()) {
    thePig.eat(tableScraps);
}
if (theCow.isHungry()) {
    theCow.eat(grass);
}
theCow.moveTo(theBarn);


Обектно-ориентиран дизайн[редактиране | редактиране на кода]

Решенията относно това кое да бъде абстракция и кое да се остави под контрола на програмиста са предмет на обектно-ориентирания дизайн — а определянето на съответните взаимовръзки в реалния свят е цел на обектно-ориентирания или наследствения анализ.

Най-общо за определяне на подходящата абстракция трябва да се вземат множество дребни решения за полето на видимост на променливите, да се определи с какви други системи ще си взаимодейства приложението, след което да бъде направен подробен обектно-ориентиран анализ, който да е съобразен с времето и бюджета на проекта под формата на обектно-ориентиран дизайн. В нашия пример полето на видимост е the barnyard, животните pigs и cows и техните хранителни навици са наследствените ограничения, а детайлният анализ е, че програмистите би трябвало да имат възможността да хранят животните с това, което е налично и не е необходимо да задават типа на храната в съответен клас, а дизайнът от своя страна е всеки един клас животни, от който pigs и cows са инстанции с еднакви функционалности. Решение за разделението на DairyAnimal би променило детайлния анализ, но полето на видимост и наследствения анализ биха останали непроменени – това е изцяло под контрола на програмиста, а ние разглеждаме абстракцията в обектно-ориентираното програмиране като отделна от тази в полето на видимост или наследствен анализ.


Съображения[редактиране | редактиране на кода]

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

Абстракцията може да бъде точна спрямо характеристика, ако може да отговори на въпроса, дали дадената характеристика достатъчно добре отговаря както на абстрактно, така и на конкретно ниво.

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

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

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

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

Нива на абстракция[редактиране | редактиране на кода]

Kомпютърните науки често представят нива (или слоеве) на абстракция, където всяко едно ниво образува различен модел на една и съща информация или процес, но използва система за изразяване на уникално множество от обекти и композиции, които се прилагат на конкретен домейн[2]. Всяко едно сравнително абстрактно („високо”) ниво съдържа конкретно („ниско”) ниво, което се представя в по-детайлен вид. Например в машинен език от бинарен код, в език на програмиране от машинен език, в приложение и операционна система от език за програмиране. Всяко едно ниво е разграничено от другите и е неопределено спрямо тези под него, правейки го самостойно.

Системи за бази данни[редактиране | редактиране на кода]

На голяма част от потребителите на системи от бази данни липсват „дълбоки” познания в областта на компютърните структури от данни, разработчиците на сървъри за бази данни най-често използват тези нива, за да скрият сложността.

Физическо ниво: Най-ниското ниво на абстракция, обясняващо как всъщност системата действително запазва информацията. Това ниво обяснява сложността на запазване в детайлност.

Логическо ниво: По-високо ниво на абстракция, описващо каква информация се съдържа и какви са взаимовръзките между нея. По този начин логическо ниво обяснява цялостната система бази данни от гледна точка на малкото на брой относително прости структури от данни. Въпреки че имплементацията на простите структури може да крие доста голяма ниво на сложност, потребителят, използващ логическото ниво не трябва да бъде наясно с нея. Това се обяснява като независимост на физическата информация. Администраторите на бази данни използват логическото ниво, за да определят каква информация да се пази в базата.

Ниво на изглед: Най-високата част на абстракцията, показваща само част от цялата база данни. Въпреки че логическото ниво използва прости структури, сложността остава заради разнообразието от информация, събрана в базата. Много от потребителите нямат нужда от цялата информация - вместо това те имат нужда само от част от осигурената информация. Нивото на изглед съществува, за да опрости взаимодействието между потребителя и системата. Самата система може да има няколко различни изгледа за една и съща система.

Архитектура на слоеве[редактиране | редактиране на кода]

Възможността да предоставиш дизайн на различни нива на абстракция може да:

  • опрости много дизайна
  • да позволи на различни потребители да работят ефективно в различните нива на абстракция
  • подпомага преносимоста на софтуерните артефакти(само за мобилни устройства)

Системният и бизнес дизайн може да го използват. Някои процеси за създаване на дизайни конкретно може да генерират дизайни, съдържащи различни нива на абстракция.

Архитектура съставена от слоеве разделя отговорнoстите на приложението в така наречените "събрани групи"(слоеве). Това е техника, използвана в изграждането на дизайн за компютърен софтуер, хардуер и комуникации, в които системата или мрежовите компоненти са изолирани в слоеве, които могат да се променят без това да оказва влияние на другите.

Източници[редактиране | редактиране на кода]

Външни препратки[редактиране | редактиране на кода]

  • SimArch example of layered architecture for distributed simulation systems.
Криейтив Комънс - Признание - Споделяне на споделеното Лиценз за свободна документация на ГНУ Тази страница частично или изцяло представлява превод на страницата „Abstraction“ в Уикипедия на английски. Оригиналният текст, както и този превод, са защитени от Лиценза „Криейтив Комънс - Признание - Споделяне на споделеното“, а за съдържание, създадено преди юни 2009 година — от Лиценза за свободна документация на ГНУ. Прегледайте историята на редакциите на оригиналната страница, както и на преводната страница. Вижте източниците на оригиналната статия, състоянието ѝ при превода, и списъка на съавторите.