Головна Головна -> Підручники -> Підручник Вивчаємо FrontPage скачати онлайн-> 7. Поняття програми

7. Поняття програми



Програма, яка повинна виконуватися, записана в машинних кодах, тобто машинною мовою. Машинна мова передбачає запис інструкцій та операндів у вигляді послідовностей нулів та одиниць. Кажуть, що машинна мова є мовою низького рівня. Програма в машинних кодах являє собою послідовність команд, які процесор може сприйняти і виконати безпосередньо.Кожний тип машин має свою машинну мову. Машинний код, написаний для однієї машини, не може бути виконаний на іншій без використання спеціального програмного забезпечення.
Програмування в машинних кодах є дуже марудною справою. Програми є надто громіздкими і нерозбірливими. Важко тримати в пам’яті машинні коди і дуже легко припуститися помилки. Крім того, при переході на іншу машину все програмне забезпечення доводиться переписувати заново.
Але виявилося, що можна програмувати мовою, більш сприйнятною для людини, якщо автоматизувати процес перекладу з цієї мови на машинну. Ця ідея лягла в основу мов високого рівня.

Мови програмування високого рівня

Мови програмування високого рівня дозволяють писати програми в формі, більш наближеній до звичайної мови. Програму, написаною мовою високого рівня, можна більш легко читати і модифікувати, і вони значно полегшують роботу програміста порівняно з написанням машинного коду.Для перекладу програм, написаних мовою високого рівня, в машинні коди, повинні існувати спеціальні програми. Такі програми називаються трансляторами.
Важливою особливістю мов високого рівня є їх відносна незалежність від машини. Це означає, що правила запису програм не залежать або мало залежать від особливостей конкретної машини. Тоді для перенесення програми на іншу машину програму не обов’язково переписувати заново, достатньо лише віддтранслювати її в коди, специфічні для цієї машини. В крайньому разі, зміни в програмі повинні бути мінімальними.Слід відмітити, що повна незалежність від машини буває не завжди, на практиці програми не завжди можна переносити без змін з машини на машину. Часто доводиться здійснювати доробки, інколи досить значні.
Кожна мова високого рівня повинна мати формальний опис. У цьому описі повинні бути визначені правила запису програмних конструкцій (синтаксис) і те, яким чином ці конструкції виконуються (семантика). Транслятори пишуться у відповідності до цього формального опису. Формальний опис надає розробникам трансляторів певну свободу, і транслятори можуть бути реалізовані по-різному. Кажуть про те, що мова високого рівня може мати різні реалізації. Різні реалізації мови можуть мати відмінності в синтаксисі. Тоді може виникати ситуація, коли один транслятор сприймає програму нормально, а інший видає повідомлення про помилку.
Авторським варіантом мови називається опис мови у тому вигляді, у якому він був запропонований розробником (однією людиною або комітетом).
Важливе значення має поняття стандарту. Стандартизація мов програмування здійснюється авторитетними міжнародними комітетами, і стандартизації підлягають, як правило, найбільш вдалі і популярні мови. Якщо опублікований стандарт, тобто стандартний опис мови, всі подальші реалізації повинні підпорядковуватися цьому стандарту. Втім, розробники часто доповнюють стандарти власними модифікаціями. У такому випадку, якщо автор програми використовує в ній лише можливості, визначені стандартом, програма може бути перенесена без змін на будь-яку іншу машину. Якщо ж програміст використовує особливості, специфічні для даної реалізації, перенесення без змін на іншу машину не гарантується.
Виділяють два типи трансляторів – компілятори та інтерпретатори.
Компілятором називається програма, яка сприймає програму, написану мовою високого рівня, і генерує відповідний машинний код. Цей машинний код надалі може виконуватися незалежно від компілятора.
Інтерпретатор сприймає кожну інструкцію програми окремо, перетворює її на деякий проміжний код, і негайно виконує цей код. Незалежний машинний код при цьому не створюється.
Надалі ми будемо розглядати лише транслятори компілюючого типу.

Різні погляди на програмування і різні парадигми програмування

Програма визначається як “алгоритм, тобто послідовність інструкцій, який записаною мовою, що зрозуміла комп’ютерові”. Це визначення є класичним, але воно явно акцентує увагу лише на одному аспекті програмування: програма є деяка послідовність операцій. Не менш важливими є й інші аспекти, наприклад:

·                      програма є відображенням f: X → Y, яке ставить у відповідність елементам деякого простору вхідних даних X елементи з простору вихідних даних; це відображення можна розглядати як звичайний математичний оператор, хоч і з деякими специфічними властивостями;

·                      програма є кібернетичною системою, яка існує в певному середовищі і взаємодіє з цим середовищем, тобто сприймає від нього певні подразники і визначеним чином реагує на ці подразники; програма складається з підсистем, що певним чином взаємодіють між собою;

·                      програма являє собою певну модель, яка описує з деяким наближенням закономірності реального світу;

·                      програма є сукупністю правил, які дозволяють отримувати різноманітні наслідки (вихідні дані) з відомих передумов (вхідні дані);

·                      програма є засобом для вирішення конкретних практичних задач.

Відповідно до цього можна підходити до програмування як до процесу конструювання програм з різних точок зору. Існують різні парадигми програмування, тобто різні принципи, за якими будуються програми. Виділяють чотири основні парадигми програмування:

1.                   Процедурне програмування. Концепція процедурного програмування є історично першою та найбільш близькою до класичного визначення програми. В основі програми, побудованої за процедурними принципами, лежить послідовна зміна вхідних даних, поки не буде отриманий результат, причому кожна операція розписується в явному вигляді. Дані, з якими оперує програма, зберігаються в іменованих ділянках оперативної пам’яті, які називаються змінними. Найбільш відомими процедурними мовами є Паскаль і Сі в їх авторських варіантах.

2.                   Функціональне програмування. Виконання програми розглядається як виклик деякої функції, яка, в свою чергу, може викликати інші функції. Найбільш відомим представником цієї парадигми є Лісп.

3.                   Логічне програмування. В основі виконання програми лежить механізм автоматичного доведення теорем на основі логічного виведення. Найбільш відомий представник – Пролог.

4.                   Об’єктно-орієнтоване програмування. Ця парадигма є на сьогодні найбільш популярною і стрімко розвивається. Об’єктна програма розглядається як сукупність паралельно існуючих сутностей (об’єктів), які взаємодіють між собою. Кожний об’єкт вміє виконувати певні операції та характеризується певною поведінкою. Історично першою об’єктною мовою вважається Smalltalk. Найбільш відомими представниками цієї парадигми є C++; Object Pascal, що лежить в основі системи візуального програмування Delphi; Java.

Як окремий напрямок слід виділити мови програмування баз даних, призначені для маніпуляції великими централізованими масивами даних і отримання з них інформації.
Багато з цих мов (Access, FoxPro, 4GL та ін.) мають розвинені процедурні елементи. Фактичним стандартом стала мова запитів до баз даних SQL.

Написання програми

Компілятор сприймає програму, написану мовою високого рівня. Текст цієї програми називається початковим кодом. Результатом роботи компілятора є об’єктний код.
Різні частини програми можуть компілюватися незалежно. Програма, яка збирає в єдине ціле незалежно відкомпільовані об’єктні модулі, називається редактором зв’язків. При цьому відбувається налаштування програми на реальні машинні адреси, з якими вона буде працювати.
Результатом роботи редактора зв’язків є програма, готова до виконання (часто вона називається завантажувальним модулем). Ця програма може бути негайно виконана, а може бути збережена на диску.
Програма, яка завантажує готову програму в оперативну пам’ять і забезпечує її запуск на виконання, називається завантажувачем. Завантажувач у найбільш типовому випадку є частиною операційної системи. Він повинен розмістити програму в оперативну пам’ять і передати їй керування (це означає встановлення програмного лічильника на першу команду програми, що виконується).
Розрізняють абсолютні і налаштовуючі завантажувачі.
Абсолютний завантажувач розміщує програму за жорстко заданими адресами. Для цього в об’єктному і завантажувальному коді повинні бути визначені конкретні адреси комірок пам’яті, з якими буде працювати програма. Налаштовуючий завантажник важче реалізувати, але він є значно більш гнучким. Він може розмістити програму в довільному місці пам’яті. При цьому в завантажувальному коді вказуються не явні адреси, а зміщення відносно початку програми.

Асемблери

Слід розрізняти поняття мови асемблеру і власне асемблери.
Мовою асемблеру прийнято називати машинно-орієнтовану мову низького рівня (хоча і більш високого, ніж машинний код). Мова асемблеру має такі характерні особливості:

·                      одна команда асемблеру відповідає одній машинній команді. Певні послаблення цього принципу пов’язані з використанням макрокоманд, які на етапі підготовки програми автоматично замінюються деякою послідовністю машинних команд;

·                      на відміну від машинного коду, в мові асемблеру використовуються символічні позначення команд. Це робить програми, написані мовою асемблеру, придатними для сприйняття людиною, а сам процес програмування – більш простим і більш захищеним від помилок.

Асемблером називається програма, призначена для перекладу вихідних текстів програм, написаних мовою асемблера, в машинні коди. Сам процес перекладу називається асемблюванням. Зрозуміло, що асемблювання є набагато простішим, ніж трансляція з мов високого рівня.Втім, мови асемблеру часто також називають асемблерами. З контексту, як правило, зрозуміло, про що йде мова.Оскільки існує чітка відповідність між асемблерними інструкціями та машинними командами, досить легкою задачею виявляється зворотній переклад з машинної мови на мову асемблера. Така операція називається дизасемблюванням.
Незважаючи на більш високу читабельність асемблерних програм порівняно з машинним кодом, програмування мовою асемблеру все-таки залишається досить марудною справою. Але доцільність використання асемблеру диктується такими основними міркуваннями:

·                      ефективність. Компілятори з мов високого рівня не завжди генерують код, що є раціональним з точки зору швидкодії або використання пам’яті. Якщо програму зразу написати мовою асемблера, вона може стати значно більш ефективною;

·                      необхідність використання в програмах низькорівневих операцій з пам’яттю, зовнішніми пристроями і т.п. Якщо мова високого рівня не надає відповідних можливостей, програмування на асемблері залишається єдиним виходом.

На сучасному етапі рідко хто програмує на чистому асемблері. Програми в основному пишуться мовами високого рівня; асемблер використовується для програмування лише окремих критичних операцій. Ряд мов високого рівня надають у розпорядження програміста вбудовані асемблери, які дозволяють органічно інтегрувати асемблерні фрагменти до програм, основна частина яких пишеться цими мовами.

Основні вимоги до програм

Типова програма реалізує так званий IPO-принцип (Input – Processing – Output). Програма вводить деякі вхідні дані, обробляє їх відповідно до заданого алгоритму і видає вихідні дані, тобто результат. Велике значення мають інтерактивні програми, які в ході своєї роботи можуть сприймати команди від користувача і здійснювати з ним діалго.
Інтерактивними є, зокрема, сучасні операційні системи і переважна більшість прикладних програм загального призначення (текстові та графічні редактори, електронні таблиці та бази даних тощо).
Оскільки програма по суті являє собою алгоритм, записаний мовою, зрозумілою для комп’ютера, програма має всі властивості, характерні для алгоритмів. Але програма є конкретною реалізацією алгоритма, призначеною для практичного використання, і властивості програм розглядають саме з цієї точки зору.
Можна виділяти такі вимоги до програм:

1. Правильність.

Програма повинна видавати правильні результати для будь-яких даних з заздалегідь визначеного припустимого діапазону. Це звучить банально, але з цим пов’язана дуже серйозна проблема. Якщо програма є достатньо складною, навіть найкваліфікованіший програміст навряд чи зможе з першого разу написати її без помилок. Ці помилки можуть бути найрізноманітніші: від суто механічних (“забув поставити крапку з комою”) до неналежного використання програмних конструкцій або навіть помилок в самому алгоритмі.
Загальноприйнятою є така класифікація програмних помилок:

·                      синтаксичні, які пов’язані з порушенням формальних граматичних правил написання програм. Синтаксичні помилки виявляються на етапі компіляції;

·                      помилки часу виконання. Ці помилки знову ж-таки поділяються на такі категорії:

§                       аварійні зупинки. Пов’язані з операціями, які неможливо виконати (ділення на нуль, звернення до неіснуючих файлів тощо). У таких випадках програма зупиняється;

§                       програма не доходить до кінця. Вона працює нескінченно довго або зависає;

§                       програма видає неправильні результати.

Помилки повинні бути виявлені та виправлені (цей процес називається відлагодженням). Крім того, необхідно переконатися, що програма працює правильно на деяких тестових прикладах (цей процес називається тестуванням). Відомо, що саме на відлагодження і тестування припадає левова частина роботи над програмою. Деякі приховані помилки так і залишаються невиправленими і час від часу проявляють себе уже в процесі експлуатації програми. Це можуть бути несподівані повідомлення на екрані, зависання і т.п. Але наслідки програмних помилок можуть бути і значно більш серйозними. Відповідальність за виявлення і знешкодження помилок повністю лежить на авторі програми. Але і майбутньому користувачеві, якщо він не бажає ризикувати, варто перевірити правильність функціонування програми.

2. Ефективність.

Програма повинна видавати результати за прийнятний час і не бути надто ресурсоємкою. Різні програми, які призначені для вирішення однієї й тієї самої задачі, можуть мати різну ефективність, і за інших рівних умов природно надавати перевагу більш ефективній програмі.

3. Надійність.

Користувач повинен довіряти програмі і не боятися її використовувати. Надійна програма повинна бути правильною; якщо ж залишаються помилки, вони не повинні призводити до серйозних програм. Самої лише правильності програми замало. Якщо користувач вводить неправильні дані, програма повинна повідомити його про це. Якщо програма сприймає неправильні дані і видає неправильні результати – це набагато гірше, ніж якщо вона взагалі не працює. За будь-яких умов використання програми не повинно призводити до фатальних, невиправних або важковиправних наслідків.

4. Універсальність.

Програма повинна бути розрахована на широкий діапазон вхідних даних і при можливості – на широкий спектр задач.

5. Функціональність.

Програма повинна забезпечувати всі основні потреби користувача і не реалізовувати можливостей, що є для нього непотрібними.

6. Зручність у використанні.

Програма повинна бути зручною в засвоєнні і використанні, а програмний інтерфейс повинен бути інтуїтивно зрозумілим. Відомо, що за останні десять років був зроблений величезний крок у цьому напрямку.

7. Стандартизованість.

Різні програмні продукти повинні мати однотипні засоби керування і однотипний інтерфейс для того, щоб користувач, який має досвід роботи з однією програмою, мав якнайменше незручностей при переході до іншої.

8. Переносимість.

Повинна забезпечуватися можливість перенесення програм з однієї машини на іншу без змін або з мінімальними змінами.

9. Читабельність.

Тексти програм повинні бути максимально простими для сприйняття і розуміння людиною.

10. Модифікованість.

Програма повинна передбачати можливість для змін і доповнень.

11. Документованість.

Кожна програма повинна супроводжуватися інструкціями щодо її використання, і ці інструкції повинні бути доступними і зрозумілими. В самій програмі повинні використовуватися коментарі, які пояснюють суть самої програми та основних її елементів.

Традиційна каскадна модель життєвого циклу програми

З самого початку розвитку теорії і практики програмування розроблялися технології, що були орієнтовані на певну традиційну схему програмування. Ця схема передбачає певні етапи роботи, що до останнього часу були характерними для переважної більшості програмних продуктів. Цю схему часто називають каскадною (або водоспадною) моделлю.
Каскадна модель виділяє такі основні етапи життєвого циклу програм:

1.                   Аналіз проблеми, постановка задачі і специфікація вимог до майбутньої програми. Як правило, цей етап повинен передбачати взаємодію між виконавцем та замовником. Результатом повинно бути технічне замовлення, сформульоване в письмовому вигляді.

2.                   Проектування. Повинен бути вибраний метод вирішення задачі та спроектований відповідний алгоритм.

3.                   Кодування, яке полягає в написанні тексту програми відповідно до розробленого алгоритму.

4.                   Відлагодження, яке полягає у виявлення та виправленні помилок.

5.                   Тестування, що передбачає перевірку правильності програми на тестових прикладах – спеціально підібраних наборів вхідних даних. Для цих наборів даних повинні бути відомими правильні відповіді. Якщо відповіді програми на всіх тестових прикладах співпадають з очікуваними, програма вважається правильною.
Тестування повинно бути якомога більш повним, і правильний підбір тестових прикладів часто є дуже непростою задачею. Повинні бути перевірені всі типи вхідних даних і всі можливі варіанти виконання програми. Повинен бути проведений тест в нормальних умовах (дані, характерні для реальних умов фунціонування), тест в екстремальних умовах (перевірка функціонування програми в крайніх випадках, коли вхідні дані перебувають на межі припустимого діапазону) і тест за виняткових обставин (коли вхідні дані виходять за рамки припустимого діапазону).

6.                   Впровадження і експлуатація.

7.                   Модифікація програми у випадку необхідності. Необхідність модифікації програми може бути пов’язана, наприклад, зі зміною умов її функціонування або з посиленням вимог до неї.

8.                   Зняття з експлуатації.

Обмеженість каскадної моделі. Спіральна модель

Каскадна модель життєвого циклу програми є задовільною у випадку, якщо з самого початку вдається визначити чіткі вимоги і розробити повноцінний проект. Але так буває далеко не завжди. Часто замовник сам не до кінця уявляє, що йому потрібно, і може уточнити вимоги лише після певного досвіду використання програми. Особливо це стосується великих, в тому числі наукомістких проектів. Часто замовника в класичному розумінні цього слова взагалі немає. Програмний продукт може бути призначений для масового ринку та конкурувати з іншими аналогічними продуктами. Тоді його переваги та недоліки проявляються лише в процесі реальної експлуатації. Ці та інші обставини призводять до того, що переважна частина помилок робиться на ранніх етапах – аналіз задачі, розробка вимог, проектування. Виправити ж ці помилки тоді, коли вони уже втілені в програмному продукті, дуже важко.
У зв’язку з цим на зміну традиційній каскадній моделі приходить спіральна модель життєвого циклу програм, яка передбачає ітераційну розробку програмного забезпечення. Спочатку розробляється прототип – найпростіший варіант програми, який ілюструє основні можливості інтерфейсу та основні функціональні можливості. Прототип використовується для дослідження якості проекту та доцільності його подальшого розвитку. Сучасні технології та інструментальні засоби програмування істотно полегшують створення таких прототипів.








Популярні глави цього підручника:



Всі глави цього підручника:

Вивчаємо FrontPage