# Көмекші бағдарлама

**Көмекші (бағыныңқы) бағдарлама** (*Вспомогательная программа (подпрограмма); subroutine*) — басқа бағдарламаның құрамына кіретін, оның бір блогы ретінде қарастырылатын, бағдарламалау тілінің ережелеріңе сөйкес жазылған қосалқы бағдарлама.

## Кіші (ішкі) бағдарлама (функция)

Компьютерлік бағдарламаларда(computer programming) ішкі бағдарлама - бұл белгілі бір міндетті орындайтын, біртұтас бағдарламалық нұсқаулықтардың жүйелілігі. Бұл блокты қандай да бір нақты міндет орындалатын бағдарламаларда қолдануға болады.

Кіші бағдарламалар бағдарламалардың ішінде немесе программалар кітапханасы бөлек көптеген бағдарламалармен айқындалуы мүмкін. Әр түрлі бағдарламалау тілдерінде бағдарлама процедура(procedure), функция(function), әдіс (method) немесе кіші бағдарлама (subprogram) деп аталуы мүмкін. Кейде "шақырылатын бірлік"(callable unit) жалпы термині қолданылады.

Кіші бағдарлама атауы екі мағына ұсынады:ішкі бағдарламаның ірі бағдарламада бір қадам ретінде пайдаланылатын компьютерлік бағдарлама сияқты немесе басқа кіші бағдарламада шамамен бірдей қызмет атқарады. Кіші бағдарлама жиі осындай тәртіппен кодталады:бірнеше рет және бағдарламаны бір орындау кезінде бірнеше орындардан, соның ішінде басқа да кіші бағдарламалардан, бағдарлама міндетті жүзеге асырылғаннан кейін келесі нұсқауға фунция шақырылғаннан соң(function call) кері қарай оралуы (return).

Кіші бағдарлама идеясы алғашында Джон Маучли ENIAC үстінде жұмыс істеу кезінде ойлап тапты және "EDVAC типті машиналарға арналған есептерді дайындау" тақырыбы бойынша 1947 жылдың қаңтарында Гарвард симпозиумында осы туралы жазған.Морис Уилкс, Дэвид Уиллер және Стэнли Джилл әдетте тұжырымдаманың ресми өнертабыскерлері болып есептеледі. Aшық кіші немесе немесе микробағдарламалау бағдарламаға қарағанда олар тұжырымды жабық кіші бағдарлама атауын берген.

Бағдарлама- бағдарламалаудың қуатты құралы, және көптеген бағдарламалау тілі синтаксисi оларды жазу мен пайдалануды қамтиды. Кіші бағдарламаларды ақылға қонымды пайдалану (мысалы, құрылымдалған бағдарламалау(structured programming) тәсілі арқылы) үлкен бағдарламаны әзірлеуге және қызмет көрсетуге жұмсалатын шығындарды жиі төмендетеді, сонымен қатар оның сапасы мен сенімділігін арттырады. Кітапханаларда жиі жиналған кіші бағдарламалар бағдарламалық қамтамасыз етуді бірлесіп пайдалану және сату үшін маңызды тетік болып табылады. Объектіге-бағытталған бағдарламалау(object-oriented programming) пәні обьект (бағдарламалау) мен әдістерге негізделген (бұл объектілер(objects) немесе объектілер класстарына(object classes) бекітілген кіші бағдарламалар болып табылады).

Ағын коды(threaded code) атауын алған компилятор(compiling) әдісінде орындалатын бағдарлама негізінен бағдарлама шақыруларының тізбегі болып табылады.

## Негізгі тұжырымдамалар

Бағдарлама мазмұны оның денесі болып табылады, ол бағдарлама шақырғанда немесе шақырғанда орындалатын бағдарламалық кодтың фрагменті болып табылады.
Бағдарлама шақырушы бағдарламалардан (оның параметрлерін(parameters) немесе формальды параметрлерін(formal parameters) ауыстыру үшін) бір немесе бірнеше аргументтер(arguments) мәнін алуды күтуге болатындай жазылуы мүмкін. Шақырушы бағдарлама аргументтер деп аталатын осы параметрлерге нақты мәндерді береді. Түрлі бағдарламалау тілдері аргументтерді жіберу үшін түрлі келісімдерді пайдалана алады:

| Келісім | Сипаттамасы | Жалпы пайдаланымы |
| --- | --- | --- |
| Мәні бойынша шақыру | Аргумент есептеледі және мән кіші бағдарламаға беріледі | Algol 60 кейін көптеген Алгол тектес тілдер әдепкі бойынша default, мысалы Pascal(Паскаль), Delphi, Similar, CPL, PL/M, Modula, Oberon, Ada және т.б. C, C++, Java (нысандар мен массивтерге сілтеме мәні бойынша беріледі) |
| Сілтеме бойынша шақыру | Дәлелге сілтеме, әдетте, оның мекенжайы беріледі | Algol 68, Pascal, Delphi, Similar, CPL, PL/M, Modula, Oberon, Ada және т.б. сияқты көптеген Алголға ұқсас тілдер ALGOL 60 кейін таңдалады. C++, Fortran, PL / I |
| Нәтиже бойынша шақыру | Параметр мәні функциядан қайтару кезінде аргументке кері көшірілген | Ada OUT параметрлері |
| Нәтиже-мәні бойынша шақыру | Параметр мәні кіші бағдарлама кіргенде және қайта қайтарылғанда көшіріледі | Algol |
| Атауы бойынша шақыру | Макро ретінде – параметрлерді бағаланбаған аргумент өрнектермен ауыстыру | Algol, Scala |
| Тұрақты мәні бойынша шақыру | Мәні бойынша шақыру сияқты бірақ параметр константа ретінде қарастырылады | PL/I БАҒАЛАНБАЙТЫН параметрлері, Ada IN параметрлері |

Кіші бағдарлама шақырушы объектіге есептелген мәнді (оның қайтарылатын мәнін(return value) ) қайтаруы немесе әртүрлі нәтиже беретін мәндерді немесе шығыс параметрлерін беруі мүмкін. Шын мәнінде, кіші бағдарламаларды жалпы пайдалану функция (математика) жүзеге асыру болып табылады, онда кіші бағдарламаның мақсаты тек бір немесе бірнеше нәтижелерді есептеу болып табылады, олардың мәндері толық берілген кіші бағдарламаға берілетін аргументтермен айқындалады. (Мысалдар санның логарифмін немесе матрица (математика) анықтауыш (математика)(determinant of a matrix) есептеуді қамтуы мүмкін.)

Бағдарлама шақыруы, сондай-ақ, компьютерлік жадындағы мәліметтер құрылымын(data structures) өзгерту, сыртқы (шалғай) жабдық (peripheral device) оқу немесе жазу, файлды жасау, бағдарламаны немесе машинаны тоқтату немесе белгілі бір уақытта бағдарламаны орындауды кідірту сияқты жанама әсерлері болуы мүмкін. Жанама әсерлері бар кіші бағдарлама ол сол дәлелдермен байланысты болса да, шақырылған сайын әр түрлі нәтижелерді қайтаруы мүмкін. Мысал ретінде көптеген тілдерде қол жетімді кездейсоқ сандардың функциясы(random number function) бола алады, ол әр түрлі жалған кездейсоқ сандарды шаққан сайын қайтарады. Жанама әсерлері бар кіші бағдарламаларды кеңінен пайдалану императивті бағдарламалау(imperative programming) тілдерінің тән ерекшелігі болып табылады.

Кіші бағдарлама өз міндеттерін орындау үшін бір немесе бірнеше жерде өзін рекурсивті тудыратындай етіп кодтауға болады. Бұл әдіс математикалық индукциямен және рекурсивті алгоритмдермен анықталған функцияларды(divide and conquer algorithm) тікелей жүзеге асыруға мүмкіндік береді.
Бір логикалық функцияны есептеуге арналған кіші бағдарлама (яғни "Иә/Жоқ" сұрағына жауап беру үшін) кейде предикат деп аталады. Логикалық программалау тілдерінде жиі [шашыраңқы] барлық кіші бағдарламалар предикаттар деп аталады, өйткені олар бірінші кезекте [шашыраңқы] табысқа немесе сәтсіздікке байланысты.

## Тілдік қолдау

Жоғары деңгейлі бағдарламалау тілдері әдетте белгілі бір құрылымдарды қамтиды:

* Кіші бағдарламаны құрайтын бағдарламаның бөлігін (денесін) бөлy
* Кіші идентификатор (аты)
* Оның параметрлері мен қайтарылатын мәндер деректерінің атын және мәліметтер типін көрсету
* Уақытша айнымалы үшін жеке атау аймағын беру
* Ішкі қол жетімді ішкі бағдарламадан тыс айнымалыларды анықтау
* Кіші бағдарламаны шақыру
* Параметрлерге мән беру
* Негізгі бағдарлама кіші бағдарлама адресін қамтиды
* Кіші бағдарлама негізгі бағдарламадағы функциялардың келесі шақыру нұсқаулығының адресін қамтиды
* Денеден қайтарылатын мәндерді көрсету
* Шақырушы бағдарламаға қайтару
* Шақыру қайтарылатын мәндерді жою
* Шақыру кезінде туындаған кез келген ерекше жағдайларды өңдеу
* Кіші бағдарламаларды модульге, программалар кітапханасы, обьект (бағдарламалау) немесе классқа буып-түйю

 Паскаль (бағдарламалау тілі), Фортран, Ада (ADA) сияқты кейбір бағдарламалау тілдері және көптеген BASIC( Бейсик) диалектілері, шақырушы бағдарламаның анық қайтарылатын мәнін беретін функцияларды немесе функционалдық кіші бағдарламаларды және мұны жасамайтын кіші бағдарламаларды немесе рәсімдерді ажыратады. Бұл тілдерде функциялардың шақырулары әдетте өрнектерде орнатылған (мысалы, sqrt функциясы y = z + sqrt(x)). ретінде туындауы мүмкін).
Процедуралар шақырулары немесе операторлар ретінде синтаксистік түрде (мысалы, print процедурасы if x > 0 then print(x) немесе CALL немесе GOSUB (мысалы, call print(x)).) сияқты оператормен айқын шақырылуы мүмкін. C бағдарламалау тілі және Lisp сияқты басқа тілдер функциялар мен кіші бағдарламалар арасында айырмашылықтар жасамайды.
Haskell( Мәтінді автоматты өңдеу) сияқты қатаң функционалдық бағдарламалау тілдерінде, бағдарлама ешқандай жанама әсерлері болуы мүмкін емес, бұл бағдарламаның әр түрлі ішкі күйлері өзгертілмейді дегенді білдіреді. Функциялар әрқашан бірдей дәлелдермен қайта қоңырау шалу кезінде бірдей нәтижені қайтарады. Мұндай тілдер, әдетте, тек функцияларды ғана қолдайды, себебі мәні қайтарылмайтын кіші бағдарламалар, егер олар жанама әсерді тудыруы мүмкін болмаса, ешқандай пайдасы жоқ.
C, C++ және C#( C Sharp) сияқты бағдарламалау тілдерінде, сондай-ақ, бағдарламалар жай ғана функциялармен аталады, әртүрлі ұғымдар болып табылатын математикалық функциялармен(Функция (математика)) немесе функционалдық бағдарламалармен шатастырмауы қажет.
Kіші бағдарламалар оларды шақыратын бағдарламалардан бөлек компиляциялануы мүмкін үшін тіл компиляторы әдетте процедуралар шақыруларын аударады және шақыру туралы нақты белгіленген келісімге сәйкес машина нұсқауларына қайтарады. Call және return операторларына сәйкес келетін нұсқаулардың реттілігі пролог және эпилог процедуралар деп аталады.

## Артықшылықтары

Бағдарламаны кіші бағдарламаларға бөлу артықшылықтары:

* Қарапайым кезеңдерге бағдарламалаудың күрделі есебінің декомпозициясы(decomposing): бұл мәліметтер құрылымымен(data structure) қатар құрылымдалған бағдарламалаудың(structured programming) екі негізгі құралдарының бірі
* Бағдарламадағы код дубликаттарының(duplicate code) санын қысқарту
* Бірнеше бағдарламаларда кодты қайта пайдалануды қосу
* Әр түрлі бағдарламашылар немесе жобаның әр түрлі кезеңдері арасында үлкен бағдарламалау есебін бөлу
* Кіші бағдарламаны пайдаланушылардан жүзеге асыру бөлшектерін жасыру
* Код блогының функцияның сипаттамалық атауы код блогын сипаттау үшін қызмет ететін кодты шақырумен ауыстыру арқылы кодтың оқылуын жақсарту. Бұл функция қайта пайдалануға арналмаған болса да, қысқа және оқылатын кодты жасайды.
* Қадағалаудың(traceability) жақсаруы (яғни көптеген тілдер іске қосылған кіші бағдарламалардың аттарын және файлдар мен жолдар нөмірлері сияқты көп ақпаратты қамтитын шақыруларды тарту тәсілдерін ұсынады); егер кодты кіші бағдарламаларға бөлмесе, баптау(debugging) қатты бұзылатын болады

## Кемшіліктері

* Ішкі кодты пайдаланумен салыстырғанда, кіші бағдарлама шақыруы кейбір есептеу шығындарын(computational overhead) шақыру механизміне салады.
* Кіші бағдарлама әдетте housekeeping стандартты кодын талап етеді-функцияға кірген кезде де, одан шыққан кезде де (функцияның прологы мен эпилог – әдетте жалпы мақсаттағы процессор регистрі(general purpose and registers) және кері адресті(return address) сақтау).

## Тарихы

Бағдарлама идеясы есептеу машиналары біраз уақыт бойы болған соң әзірленді. Ауысудың арифметикалық және шартты нұсқаулары алдын ала жоспарланған және салыстырмалы түрде аз өзгерді; бірақ процедураларды шақыру үшін пайдаланылатын арнайы нұсқаулар осы жылдар ішінде қатты өзгерді. Manchester Baby және RCA 1802 сияқты ең ерте компьютерлер мен микропроцессорлар кіші бағдарламаларды шақырудың бірыңғай нұсқаулықтары болған жоқ. Бағдарлама іске асырылуы мүмкін, бірақ олар программистерден шақырулар тізбегін-нұсқаулықтар сериясын-әрбір шақыру торабында(call site) пайдалануды талап етті.

Кіші бағдарлама Z4 Конрада Зузе 1945 жылы іске асырылды.
1946 жылы Алан Тьюринг "жерлеу"(bury) және " қайта қазып алу"(unbury) терминдерін шақыру және кіші бағдарламалардан қайтару құралы ретінде пайдаланды.
Джон Маучли 1947 жылдың қаңтар айында Гарвард университеті және Құрама Штаттардың Әскери-теңіз флотының оқ-дәрі бюросымен бірлесіп ұйымдастырған ірі масштабты сандық есептеу машиналарының симпозиумында жалпы ескертулерді ұсынды. Мұнда ол дәйекті және параллель операцияны талқылайды.
...машинаның құрылымы бірде-бір битке күрделенбеуі тиіс. Бұл процедураға қажетті барлық логикалық сипаттамалар бар болғандықтан, машинада белгілі орындарда жадта кіші бағдарламаларды орналастыру және кодтаушы нұсқауды оңай қолданыла алатындай үшін әзірлеуге болатындай істеді.

Басқа сөзбен айтқанда, А кіші бағдарламасын бөлу ретінде, ал В кіші бағдарламасы-күрделі көбейту ретінде, ал С кіші бағдарламасы-нақты міндет үшін қажетті кіші бағдарламалардың тізімі бойынша сандардың реттілігінің стандартты қатесін бағалау ретінде белгілеуге болады. ... Барлық кіші бағдарламалар содан кейін машинада сақталады, және олар кодтауда көрсетілген нөмірі бойынша оларға қысқаша сілтеме жасау керек.
Кей Макналти ENIAC командасында Джон Мочлимен тығыз байланыста және екінші дүниежүзілік соғыс кезінде бағдарламаланған ENIAC компьютеріне арналған кіші бағдарлама идеясын әзірледі. Ол және ENIAC басқа программистері осы кіші бағдарламаларды зымыран траекторияларын есептеу үшін пайдаланды.

Гольдстайн және Джон фон Нейман 1948 жылдың 16 тамызындағы мақаланы жазды, онда кіші бағдарламалардың пайдалылығы талқыланды.
IBM 1620, Intel 4004 және Intel 8008 сияқты кейбір өте ерте компьютерлер мен микропроцессорлар, сондай-ақ PIC микроконтроллерлері кері адрестерді сақтау үшін бөлінген аппараттық стекті пайдаланатын бір нұсқаулықпен кіші бағдарлама шақыруы бар-мұндай жабдық тек бірнеше кіші бағдарламаларды қолдайды, бірақ рекурсивті кіші бағдарламаларды да қолдай алады. 1960—шы жылдардың ортасына дейінгі машиналар—UNIVAC I, PDP-1 және IBM 1130 сияқты-әдетте шақыратын кіші бағдарламаның бірінші жадында командалардың санауышын сақтайтын шақыру туралы келісімді пайдаланады. Бұл бағдарлама кірістілігінің еркін терең деңгейін пайдалануға мүмкіндік береді, бірақ рекурсивті кіші бағдарламаларды қолдамайды. PDP-11(1970) - бұл кіші бағдарламаның итергіш стекаларын шақыру нұсқаулығы бар алғашқы компьютерлердің бірі; бұл функция кіші бағдарламалардың еркін терең салынуын да, рекурсивті кіші бағдарламаларды да қолдайды.

## Тіл қолдауы

Алғашқы ассемблерлерде кіші бағдарламаларды қолдау шектеулі болды. Кіші бағдарламалар бір-бірінен немесе негізгі бағдарламадан анық бөлінген жоқ, және шын мәнінде, кіші бағдарламаның бастапқы коды басқа кіші бағдарламалардың бастапқы кодымен ауыстырылуы мүмкін болған. Кейбір ассемблерлер шақыру және қайтару тізбектерін жасау үшін алдын ала анықталған микробағдарламалауды ұсынады. 1960 жылға қарай ассемблерлер әдетте кіріктірілген, сондай-ақ оларды бірге байлауға болатындай ,жеке жиналған кіші бағдарламаларды әлдеқайда күрделі қолдауға ие болды.

## Кіші бағдарламалар кітапханалары

Тіпті мұндай қиындық тудыратын тәсілде кіші бағдарлама өте пайдалы болды. Біріншіден, олар көптеген түрлі бағдарламаларда бірдей кодты пайдалануға мүмкіндік берді. Сонымен қатар, жады ерте компьютерлерде өте тапшы ресурс болды және кіші бағдарламалар бағдарлама көлемін айтарлықтай үнемдеуге мүмкіндік берді.
Көптеген ерте компьютерлер бағдарлама нұсқауларын тесімтаспадан жадқа жүктеді. Сонымен қатар, әр бағдарлама негізгі бағдарламаға (немесе "mainline") дейін немесе кейін жүктелген немесе жалғастырылған лентаның жеке бумасымен қамтамасыз етілуі мүмкін; және де кіші бағдарламаның сол лентасы көптеген түрлі бағдарламалармен пайдаланылуы мүмкін. Осындай тәсіл өзінің негізгі енгізу үшін тесімкарталарды пайдаланған компьютерлерде де қолданылды. "Кіші бағдарламалар кітапханасы" атауы алдымен ұжымдық пайдалану үшін таспалардың индекстелген коллекцияларын немесе карта колодын сақтаған кітапхананы білдіреді.

## Қайтару жанама өту

Өз бетінше өзгеретін кодтың(self-modifying code) қажеттілігін жою үшін, компьютерлерді әзірлеушілер ақырында жанама өту(indirect jump командасын ұсынды, оның операндасы кері адрестің(return address) орнына айнымалы немесе қайтару адресті қамтитын процессор регистрінің(processor register) орналасқан жері болды.
Бұл компьютерлерде кіші бағдарламаның кері ауысуын өзгертудің орнына шақырушы бағдарлама кері адресті айнымалы етіп сақтайды, сондықтан Кіші Бағдарламаны орындау аяқталғаннан кейін ол жанама ауысуды орындайды, ол орындауды алдын ала анықталған айнымалы(predefined variable) берілген орынға жібереді.

## Кіші бағдарламаға өту

Сонымен қатар, қосымша шығындарды барынша азайтып, кері мекенжайды сақтауды біріктірген кіші бағдарлама нұсқаулығына ауысу алға тағы бір қадам болды.
Мысалы, процедураларды шақыруға арналған IBM System / 360 bal немесе BALR тармақтарындағы нұсқаулар 14 регистр шарты бойынша нұсқаулықта көрсетілген процессордың регистріндегі кері адресті сақтап қалады. Кері оралу үшін, бағдарлама тек осы регистр арқылы (BR) тармақтардың жанама нұсқаулығын орындауы тиіс болды. Егер кіші бағдарлама осы регистрге қандай да бір басқа мақсат үшін қажет болса (мысалы, басқа кіші бағдарламаны шақыру үшін), ол регистрдің мазмұнын жеке жадында немесе регистрлердің стекінде сақтап қалады.
HP 2100 сияқты жүйелерде JSB нұсқауы, кері мекен-жай тармақтардың мақсаты болған жад ұяшығында сақталғанын қоспағанда, ұқсас тапсырманы орындалған еді.
Процедураны орындау келесі жад орнында басталады. Мысалы, HP 2100 ассемблері тілінде жазуға болады:

```
      ...
      JSB MYSUB    (Calls subroutine MYSUB.)
BB    ...          (Will return here after MYSUB is done.)
```

негізгі бағдарламадан менің қосалқы бағдарламам туындаған кіші бағдарламаны шақыру үшін. Кіші бағдарлама келесідей кодталады:
MYSUB NOP (Storage for MYSUB's return address.)

```
AA    ...          (Start of MYSUB's body.)
      ...
      JMP MYSUB,I  (Returns to the calling program.)
```

## Шақыру стэгі(Call stack)

Қазіргі заманғы шақыруларды жүзеге асыру көптеген бағдарламалар қоңырау стекін, жеке деректер стек құрылымын пайдаланады, шақыруларды іске асыру және кіші бағдарламаларды қайтару үшін. Процедураның әрбір шақыруы стек жақтауы деп аталатын жаңа жазба жасайды; процедура қайтарылғанда, оның стек жақтауы стектен жойылады және оның кеңістігі процедураның басқа шақырулары үшін пайдаланылуы мүмкін. Стектің әр кадрында әдетте процедуралар параметрлері мен ішкі айнымалыларды, сондай-ақ кері адресті қамтитын тиісті шақырудың жеке мәліметтері бар.

Шақырулар тізбегі қарапайым нұсқаулардың (reduced instruction set computing (RISC) және very long instruction word (VLIW) сәулетінде әлі де пайдаланылатын тәсіл) реттілігімен жүзеге асырылуы мүмкін, бірақ 1960-шы жылдардың соңында әзірленген көптеген дәстүрлі машиналар осы мақсат үшін арнайы нұсқауларды қамтиды.
Қоңырау стегі әдетте үздіксіз жады аймағы ретінде іске асырылады. Бұл дизайн еркін таңдау, стек төменгі бөлігі осы саладағы ең төмен немесе ең жоғары мекен-жайы болып табылады ма, сондықтан стек жадында алға немесе артқа өсуі мүмкін; алайда көптеген сәулет соңғысын таңдады.

Кейбір конструкцияларда, әсіресе кейбір төртінші іске асыруда екі бөлек стек пайдаланылды, біреуі негізінен басқару ақпаратына (мысалы, кері адрестер мен циклдердің есептеуіштері), екіншісі-деректер үшін. Бірінші қоңырау стек ретінде жұмыс істеді және басқа тіл конструкциялары арқылы бағдарламашы жанама қол жетімді болды, ал екінші тікелей қол жетімді болды.
Стек негізінде процедуралардың шақырулары алғаш рет пайда болған кезде, маңызды ынталандыру қымбат жадты сақтау болды.бұл схеманы пайдалану кезінде компилятор әрбір процедураның жеке деректері үшін (Параметрлер, кері мекенжай және жергілікті айнымалы) жадындағы жеке кеңістікті резервте сақтау қажет емес. Кез келген уақытта стек тек жеке қоңырау деректері бар, олар қазіргі уақытта белсенді (атап айтқанда, шақырылған, бірақ қайта оралмаған). Бағдарламалар әдетте кітапханалардан жиналған болғандықтан (және әлі күнге дейін қалады) мыңдаған кіші бағдарламаларды қамтитын бағдарламаларды табу сирек болмады, олардың тек бірнешеуі қазіргі уақытта белсенді.мұндай бағдарламалар үшін қоңырау соғу механизмі жад көлемін үнемдеуі мүмкін. Шын мәнінде, қоңырау стегінің механизмін жадыны автоматты басқарудың ең ерте және қарапайым әдісі ретінде қарастыруға болады.

Алайда, шақырулар стегінің тағы бір артықшылығы-ол кіші бағдарламаларды рекурсивті функция шақыруға жол береді,өйткені бір процедураға салынған әрбір шақырудың жеке мәліметтерін алады.

## Стэк кідірісі(Delayed stacking)

Шақырулар стек тетігінің кемшіліктерінің бірі процедураны шақырудың жоғары құны және оны тиісті қайтару болып табылады.қосымша шығындар стек көрсеткішін ұлғайту және азайту (және, кейбір архитектураларда, стектің толып кетуін тексеру), сондай-ақ абсолюттік мекен-жайлар бойынша емес, фреймнің салыстырмалы мекен-жайлары бойынша жергілікті айнымалы және параметрлерге қол жеткізуді қамтиды. Құны орындау уақытын ұлғайту, немесе процессордың күрделілігін арттыру, немесе екі жағдайда да іске асырылуы мүмкін.

Бұл үстеме шығындар ең айқын және парақтық процедураларда немесе парақтық функцияларда қажет емес, олар процедуралардың өзінің қандай да бір шақыруларын орындамай қайтарылады.осы үстеме шығындарды азайту үшін, көптеген қазіргі заманғы компиляторлар ол шын мәнінде қажет болғанша шақыру стегін пайдалануды кідіртуге тырысады.мысалы, p процедурасын шақыру процессордың белгілі бір тіркелімдерінде кері мекен-жайы мен шақырылатын процедураның параметрлерін сақтай алады және процедураның денесін басқаруды қарапайым жүктеу арқылы бере алады. Егер p процедурасы кез келген басқа қоңырауды орындамай қайтарылса, қоңырау белгішесі мүлдем пайдаланылмайды. Егер P басқа Q процедурасын шақыру қажет болса, ол Q қайтарылғаннан кейін қажет болатын кез келген регистрлердің мазмұнын (мысалы, кері адресті) сақтау үшін қоңырау стегін пайдаланатын болады.қосымша шығындар стек көрсеткішін ұлғайту және азайту (және, кейбір архитектураларда, стектің толып кетуін тексеру), сондай-ақ абсолюттік мекен-жайлар бойынша емес, фреймнің салыстырмалы мекен-жайлары бойынша жергілікті айнымалы және параметрлерге қол жеткізуді қамтиды. Құны орындау уақытын ұлғайту, немесе процессордың күрделілігін арттыру, немесе екі жағдайда да іске асырылуы мүмкін.

## C және C++ үлгілері

C және C++ бағдарламалау тілдерінде кіші бағдарлама функциялары деп аталады (бұдан әрі, олар класпен байланысты болған кезде мүше функциялар ретінде немесе бос функциялар болмаған кезде жіктеледі). Бұл тілдер функциясы ешқандай мәнді қайтармайды деп көрсету үшін арнайы void кілт сөзін қолданады. C/C++ функциясының параметрлері ретінде берілетін кез келген айнымалыларды өзгертуді қоса алғанда, жанама әсерлері болуы мүмкін екенін ескеріңіз. Мысалдар:
void Function1() { /\* some code \*/ }
Функция мәнді қайтармайды және автономды функция ретінде таңдалуы керек,мысалы Function1();
int Function2() {

```
 return 5;
```

}
Бұл функция нәтижені қайтарады (5 саны) және шақыру өрнектің бөлігі болуы мүмкін,мысалы x + Function2()
char Function3(int number) {

```
 char selection[] = {'S', 'M', 'T', 'W', 'T', 'F', 'S'};
 return selection[number];
```

}
Бұл функция 0-ден 6-ға дейінгі санды аптаның тиісті күнінің бастапқы әрпіне түрлендіреді, атап айтқанда 0-ден "S" - ге, 1-ден "M" - ге дейін..., 6-дан "С"дейін. Шақыру нәтижесі айнымалы берілуі мүмкін,мысалы: num\_day =Function3(number);.
void Function4(int\* pointer\_to\_var) {

```
 (*pointer_to_var)++;
```

}
Бұл функция мәнді қайтармайды, бірақ мекен-жайы параметр ретінде берілетін айнымалыны өзгертеді; ол Function4(&variable\_to\_increment);. арқылы шақырылады

## Жергілікті айнымалы, Рекурсия және реентерабельділік

Кіші бағдарлама бос кеңістіктің белгілі бір санын, яғни аралық нәтижелерді сақтау үшін осы Кіші Бағдарламаны орындау кезінде пайдаланылатын жадты пайдалы деп есептеуі мүмкін. Бұл уақытша кеңістікте сақталған айнымалылар жергілікті айнымалы деп аталады,ал уақытша кеңістік-белсендіру жазбасы. Іске қосу жазбасында, әдетте, бағдарлама аяқталғанда, кері басқаруды қай жерге жіберуді көрсететін қайтару мекен-жайы бар.
Кіші бағдарлама кез келген шақыру сайттарының саны мен сипаты болуы мүмкін. Егер рекурсия қолдау көрсетілсе, кіші бағдарлама өзін тудыруы мүмкін, соның нәтижесінде оны орындау тоқтатыла тұрады,ал сол кіші бағдарламаның басқа салынған орындалуы орын алады. Рекурсия кейбір күрделі алгоритмдерді оңайлату және күрделі есептерді бөлшектеу үшін пайдалы құрал болып табылады. Рекурсивті тілдер әдетте әрбір шақыруда жергілікті айнымалылардың жаңа көшірмесін ұсынады. Егер бағдарламашы жергілікті айнымалылардың мәні қоңыраулардың арасында өзгеріссіз қалғанын қалғысы келсе, олар кейбір тілдерде статикалық болып жариялануы мүмкін немесе жаһандық мәндер немесе жалпы аймақтар пайдаланылуы мүмкін. Мұнда Фибоначчи сандарды іздеу үшін C / C++ рекурсивті бағдарлама мысалы:
int Fib(int n) {

```
 if (n <= 1) {
   return n;
 }
 return Fib(n - 1) + Fib(n - 2);
```

}
Fortran сияқты ерте тілдер бастапқыда рекурсияны қолдамады, өйткені айнымалылар статикалық түрде бөлінген, сондай-ақ кері мекен-жайға арналған орын. Көптеген компьютерлер 1960 жылдардың соңына дейін PDP-8 сияқты аппараттық әйнек регистрлерінің қолдауына ие болған жоқ.
Мұндай PL/I және C сияқты ALGOL(Алгол) кейін қазіргі заманғы тілдер, әдетте әрбір Кіші Бағдарламаны орындау үшін іске қосудың жаңа жазбасын қамтамасыз ету үшін қазіргі заманғы компьютерлік командалардың көпшілігі қолдайтын стек әрқашан дерлік пайдаланады. Осылайша, салынған орындау басқа тоқтатылған операцияларға әсер ету туралы алаңдамай, өзінің жергілікті айнымалыларын еркін өзгерте алады. Салынған қоңыраулардың жиналуына қарай, әрбір кідіртілген бағдарлама үшін бір іске қосу жазбасынан тұратын қоңырау стегінің құрылымы қалыптасады. Шын мәнінде, стектің бұл құрылымы барлық жерде, сондықтан активтендіру жазбалары әдетте стек кадрлары(stack frames) деп аталады.
Pascal, PL/I және Ada(Ада) сияқты кейбір тілдер, сондай-ақ ішкі (Бас) кіші бағдарламаның әрекет ету аумағы шегінде ғана шақырылатын кіші бағдарламалар болып табылатын ішкі кіші бағдарламаларды қолдайды. Ішкі кіші бағдарламалар жергілікті сыртқы кіші айнымалы қол жетімді, ол оларды тудырды. Бұл қосу жазбасында қосымша контекстік ақпаратты сақтау арқылы қол жеткізіледі, сондай-ақ дисплей деп аталады.

Егер кіші бағдарлама сол кіші бағдарламаның басқа орындалуы орындалса да дұрыс орындалуы мүмкін болса, онда бұл кіші бағдарлама реентерабельді деп аталады. Рекурсивті кіші бағдарлама реентерабельді болуы тиіс. Реентерабельді кіші бағдарламалар көп ағынды жағдайларда да пайдалы, өйткені бірнеше ағын бір-біріне араласудан қорықпай, сол бір Кіші Бағдарламаны тудыруы мүмкін. IBM(International Business Machines) CICS транзакцияларды өңдеу жүйесінде квази-реентерабельділік біршама қатаң, бірақ көптеген ағындармен бөлінген қолданбалы бағдарламалар үшін ұқсас талап болды.
Көп ағынды ортада әдетте бірнеше стегі бар. Тең бағдарлама(сопрограмма) немесе жалқау бағаны толығымен қолдайтын орта, іске қосу жазбаларын сақтау үшін шыныдан өзгеше деректер құрылымын пайдалана алады.

## Шамадан артық жүктеме(Overloading)

Қатаң типтелген тілдерде кейде аты бірдей, бірақ әр түрлі деректер түрінде жұмыс істейтін немесе әр түрлі параметрлер профилі бар бірнеше функциялардың болуы қажет. Мысалы, квадраттық түбірдің функциясы релелермен, кешенді мәндермен немесе матрицалармен жұмыс істеу үшін анықталуы мүмкін. Әрбір жағдайда қолданылатын Алгоритм әртүрлі және қайтарылатын нәтиже әртүрлі болуы мүмкін. Бірдей аты бар үш жеке функцияларды жазу арқылы программист деректердің әр түріне әр түрлі аттарды есте сақтауға ыңғайлылығы бар. Одан әрі, егер реалдар үшін оң және теріс реалдарды бөлу үшін подтипті анықтауға болатын болса, реалдар үшін екі функцияны жазуға болады: біреуі параметр оң болған кезде заттай мәнді, ал екіншісі параметр теріс болған кезде кешенді мәнді қайтарады.
Объектілі-бағытталған бағдарламалауда, бірдей атымен бірнеше функциялар әр түрлі параметрлердің профильдерін немесе әр түрлі параметрлерді қабылдай алатын болса, функциялардың әрқайсысы шамадан тыс жүктелген болып саналады.
Мұнда С++-тегі бағдарлама шамадан артық жүктеу үлгісі:

```
 #include <iostream>
 double Area(double h, double w) { return h * w; }
 double Area(double r) { return r * r * 3.14; }
 int main() {
 double rectangle_area = Area(3, 4);
 double circle_area = Area(5);
 std::cout << "Area of a rectangle is " << rectangle_area << std::endl;
 std::cout << "Area of a circle is " << circle_area << std::endl;
 }
```

Бұл кодта бірдей аты бар екі функция бар, бірақ олар әртүрлі параметрлерге ие.
Басқа мысал ретінде, бағдарлама бағыттарын қабылдайтын және экрандағы осы нүктелерге өз жолын қадағалайтын нысанды құра алады. Конструкторға берілуі мүмкін көптеген параметрлер бар (трассалау түсі, X және y бастапқы координаттары, трассалау жылдамдығы). Егер программист конструктор тек түс параметрін қабылдай алғысы келсе, онда ол басқа барлық параметрлер үшін әдепкі мәндерді беретін барлық параметрлері бар конструктор шақыратын түс қана қабылдайтын басқа конструкторды шақыруы мүмкін (X және Y әдетте экранда орталықтандырылады немесе координаттардың басына орналастырылады, ал жылдамдық кодерді таңдау бойынша басқа мәнге орнатылады).
PL / I әр түрлі аргументтер типтерімен шақырылған жазбаларға сілтемелерді теру үшін ортақ атауды анықтау үшін GENERIC атрибуты бар. Мысал:
DECLARE gen\_name GENERIC(

```
                     fbname  WHEN(FIXED BINARY),
                     flname  WHEN(FLOAT),
                     othname OTHERWISE
                          );
```

Әрбір жазу үшін бірнеше дәлелдер анықтамасы берілуі мүмкін. "Gen\_name "шақыруы" fbname" шақыруына әкеледі, егер аргумент FIXED BINARY," filename", FLOAT және т.б. болса.

## Жапқыштар(Closures)

Жапқыш-ол құрылған ортадан алынған кейбір айнымалы мәндерімен бірге кіші бағдарлама. Тұйықталу Джон Маккарти енгізген Lisp бағдарламалау тілінің айқын ерекшелігі болды. Іске асыруға байланысты, жабу жанама әсерлері үшін механизмі болуы мүмкін.

## Конвенциялар(Conventions)

Кіші бағдарламаларды кодтау үшін көптеген шартты белгілер жасалды. Олардың аттарына келетін болсақ, көптеген әзірлеушілер кіші бағдарлама Атауы белгілі бір міндетті орындаған кезде етістік болуы тиіс, ол кейбір сұрау жасаған кезде сын есім, және ол айнымалы ауыстыру үшін пайдаланылған кезде зат.
Кейбір программистер кіші бағдарлама тек бір ғана міндетті орындауы тиіс деп болжайды және егер кіші бағдарлама біреуден артық міндетті орындайтын болса, ол бірнеше кіші бағдарламаға бөлінуі тиіс. Олар бағдарлама кодқа қызмет көрсетудің(code maintenance) негізгі компоненттері болып табылады және олардың бағдарламадағы рөлі әр түрлі болуы тиіс.
Модульдік бағдарламалаудың жақтастары (modularizing code) әрбір кіші бағдарлама кодтың басқа бөлшектеріне ең аз тәуелділікке ие болуы тиіс деп мәлімдейді. Мысалы, жаһандық айнымалыларды пайдалану, әдетте, бұл көзқарастың ақылсыз жақтастары болып саналады, өйткені ол кіші бағдарлама мен осы жаһандық айнымалылардың арасындағы тығыз байланысты қосады. Егер мұндай байланыс қажет болмаса, олардың кеңесі оның орнына берілген параметрлерді қабылдау үшін кіші бағдарламаларды рефакторингте тұрады. Алайда, бағдарлама бойынша берілетін параметрлер санының артуы кодтың оқылуына әсер етуі мүмкін.

## Қайтару кодтары(Return codes)

Негізгі немесе қалыпты әсерден басқа, кіші бағдарлама оны орындау кезінде туындауы мүмкін ерекше шарттар туралы шақырушы бағдарламаға хабарлау талап етілуі мүмкін. Кейбір тілдер мен бағдарламалау стандарттарында бұл жиі қайтару коды, қалыпты және ерекше жағдайларды кодтайтын кейбір стандартты жерде кіші бағдарлама орналастырылған бүтін мәні арқылы жасалады.
IBM System / 360, мұнда қайтару коды кіші бағдарламадан күтілген, қайтарылатын мән жиі 4 есе есептелген—сондықтан оны қосымша шартты тесттерді болдырмау үшін шақыру нұсқаулығынан кейін жиі орналасқан тармақ кестесіне тармақтардың тікелей индексі ретінде пайдалануға болады, бұл одан да көп тиімділікті арттырады. Мысалы, асемблерде System / 360 жазуға болады:
BAL 14,SUBRTN01 go to subroutine, storing return address in R14

```
          B    TABLE(15)      use returned value in reg 15 to index the branch table,
```

* branching to the appropriate branch instr.

```
                                 TABLE
          B    OK             return code =00   GOOD                  }
          B    BAD            return code =04   Invalid input         } Branch table
          B    ERROR          return code =08   Unexpected condition  }
```

## Кіші бағдарламаларды шақыруларды оңтайландыру

Қосымша шығындар жиі процессордың белгілі бір регистрлерін сақтау және қалпына келтіру, қоңырау кадрларының жадын бөлу және қалпына келтіру және т. б. қамтиды.. Кейбір тілдерде әрбір бағдарлама қоңырауы, сондай-ақ, бағдарлама қайтару кодын автоматты түрде тексеруді немесе ол тудыруы мүмкін ерекшеліктерді өңдеуді білдіреді. Объектілі-бағытталған тілдерде үстеме шығындардың маңызды көзі болып әдістерді шақырудың қарқынды қолданылатын динамикалық диспетчерленуі табылады.
Процедуралар жанама әсерлері болуы мүмкін, егер кейбір айқын оңтайландыру процедуралар қолданылуы мүмкін емес рәсімдер бар. Мысалы, мәнде(f(x)-1)/(f(x)+1) f функциясы екі рет шақырылуы тиіс, себебі бұл екі қоңырау әр түрлі нәтижелерді қайтаруы мүмкін. Сонымен қатар, x мәні екінші қоңырау алдында қайта алынуы керек, себебі бірінші қоңырау оны өзгерте алады. Кіші бағдарламаның жанама әсері болуы мүмкін бе, өте қиын (тіпті шешілмейтін).осылайша, бұл оңтайландыру таза функционалдық бағдарламалау тілдерінде қауіпсіз болғанымен, типтік императивті бағдарламалау компиляторлары әдетте нашар болуы тиіс.

## Кірістіру(Inlining)

Осы қосымша шығындарды жою үшін қолданылатын әдіс - бұл әрбір байланыс торабында кіші бағдарлама денесінің кіріктірілген кеңеюі(inlining expansion) немесе инлайнингі (кіші бағдарлама тармағына және кері қайтқан концептке қарағанда). Бұл тек шақыруға арналған шақыру шығындарды болдырмау ғана емес, сонымен қатар компиляторға шақыруда контекст пен дәлелдерді назарға ала отырып, процедураның денесін тиімді оңтайландыруға(optimize) мүмкіндік береді. Салынған денені компилятор оңтайландыруы мүмкін. Алайда, кірістіру әдетте код мөлшерін арттырады, егер бағдарлама тек бір ғана бағдарлама шақыруын немесе ішкі бағдарлама денесін қамтымайтын болса, онда қосымша шақыру шығынынан аз код жоқ.

## Дереккөздер