- •Розділ 1.Технологія створення програм Етапи рішення прикладних задач з використанням комп'ютерів
- •Кроки роботи з програмою
- •Короткий огляд мов програмування
- •Створення програмного проекту
- •Засоби і методика відладки програм
- •Програмна реалізація алгоритмів лінійної структури
- •Програмна реалізація алгоритмів розгалужених структур
- •Програмна реалізація алгоритмів циклічних структур
Створення програмного проекту
Структурний підхід до програмування, як уже згадувалося, охоплює всі стадії розробки проекту: специфікацію, проектування, власне програмування і тестування. Завдання, які при цьому ставляться, - зменшення числа можливих помилок за рахунок застосування тільки допустимих структур, можливо більш раннє виявлення помилок і спрощення процесу їх виправлення. Ключовими ідеями структурного підходу є спадна розробка, структурне програмування і спадний тестування. Наведені нижче етапи створення програм розраховані на досить великі проекти, що розробляються колективом програмістів. Для програми невеликого обсягу кожен етап спрощується, але зміст і послідовність етапів не змінюються.
I етап. Створення будь-якої програми починається з постановки задачі. Спочатку завдання ставиться в термінах предметної області, і необхідно перевести її в терміни, більш близькі до програмування. Оскільки програміст рідко досконально розбирається в предметній області, а замовник - в програмуванні (простий приклад: потрібно написати бухгалтерську програму), постановка завдання може стати вельми непростим ітераційним процесом. Крім того, при постановці завдання замовник найчастіше не може чітко і повно сформулювати свої вимоги і критерії. В якості ілюстрації наведу карикатуру «Гойдалки» (рис. 3.1), яка з'явилася 1973 році в інформаційному бюлетені обчислювального центру Лондонського університету і відразу стала широко відомої, оскільки дуже точно відображала процес створення програми. Постановка завдання завершується створенням технічного завдання, а потім зовнішньої специфікації програми, що включає в себе:
- опис вихідних даних і результатів (типи, формати, точність, спосіб передачі, обмеження); -опис завдання, реалізованої програмою;
- спосіб звернення до програми;
- опис можливих аварійних ситуацій і помилок користувача.
Таким чином, програма розглядається як чорний ящик, для якого визначена функція.
II етап. Розробка внутрішніх структур даних. Більшість алгоритмів залежить від того, яким чином організовані дані, тому інтуїтивно ясно, що починати проектування програми треба не з алгоритмів, а з розробки структур, необхідних для представлення вхідних, вихідних і проміжних даних. При цьому беруться до уваги багато чинників, наприклад, обмеження на розмір даних, необхідна точність, вимоги до швидкодії програми. Структури даних можуть бути статичними або динамічними (динамічні структури розглядаються в наступному розділі).
Как
было спроектировано
Как
было реализовано
ведущим
системным специалистом
программистами
III етап. Проектування (визначення загальної структури та взаємодії модулей). На цьому етапі застосовується технологія спадного проектування програми, основна ідея якого теоретично проста: розбиття задачі на підзадачі меншої складності, які можна розглядати окремо. При цьому використовується метод покрокової деталізації. Можна уявити собі цей процес так, що спочатку програма пишеться на мові деякої гіпотетичної машини, яка здатна розуміти самі узагальнені дії, а потім кожне з них описується на більш низькому рівні абстракції, і так далі. Дуже важливою на цьому етапі є специфікація інтерфейсів, тобто способів взаємодії підзадач. Для кожної підзадачі складається зовнішня специфікація, аналогічна наведеної вище. На цьому ж етапі вирішуються питання розбиття програми на модулі, головний критерій - мінімізація їх взаємодії. Одна задача може реалізовуватися за допомогою декількох модулів і навпаки, в одному модулі може вирішуватися кілька завдань. На більш низький рівень проектування переходять тільки після закінчення проектування верхнього рівня. Алгоритми записують в узагальненій формі - наприклад, словесної, у вигляді узагальнених блок-схем або іншими способами. Якщо виникають труднощі із записом алгоритму, він, швидше за все, погано продуманий. На етапі проектування слід враховувати можливість майбутніх модифікацій програми і прагнути проектувати програму таким чином, щоб вносити зміни було можливо простіше. Оскільки невідомо, які зміни доведеться виконати, це побажання нагадує створення «загальної теорії всього»; на практиці треба обмежитися розумними компромісами. Програміст, виходячи зі свого досвіду і здорового глузду, вирішує, які саме властивості програми може знадобитися змінити або вдосконалити у майбутньому.
Процес проектування є ітераційним, оскільки в програмах реального розміру неможливо продумати всі деталі з першого разу.
IV етап. Структурне програмування. Процес програмування також організуєтся за принципом «згори донизу»: спочатку кодуються модулі самого верхнього рівня і складаються тестові приклади для їх налагодження, при цьому на місці ще не написаних модулів наступного рівня ставляться «заглушки» - тимчасові програми. «Заглушки» в простому випадку просто видають повідомлення про те, що їм передано управління, а потім повертають його в викликає модуль. В інших випадках «заглушка» може видавати значення, задані заздалегідь або обчислені за спрощеним алгоритмом.
Таким чином, спочатку створюється логічний скелет програми, який потім обростає плоттю коду. Здавалося б, більш логічно застосовувати до процесу програмування висхідну технологію - написати й налагодити спочатку модулі нижнього рівня, а потім об'єднувати їх в більш великі фрагменти, але цей підхід має ряд недоліків. По-перше, в процесі кодування верхнього рівня можуть бути розкриті ті або інші труднощі проектування більш низьких рівнів програми (просто тому що при написанні програми її логіка продумується більш ретельно, ніж при проектуванні). Наш подібна помилка виявляється в останню чергу, потрібні додаткові витрати на переробку вже готових модулів нижнього рівня. По-друге, для налагодження кожного модуля, а потім більших фрагментів програми потрібно кожного разу складати свої тестові приклади, і програміст часто змушений імітувати те оточення, в якому повинен працювати модуль. Низхідна ж технологія програмування забезпечує природний порядок створення тестів - можливість низхідній налагодження, яка розглянута далі. Рекомендації по запису алгоритмів на С ++ (більшість з цих рекомендацій справедливі і для інших мов високого рівня) наведені в попередньому розділі. Нагадаю, що головні цілі - читаність і простота структури програми Б цілому і будь-який з складових її функцій. При програмуванні слід відокремлювати інтерфейс (функції, модуля, класу) від його реалізації і обмежувати доступ до непотрібної інформації. Недбале навіть у дрібницях програмування може призвести до величезних витрат па пошук помилок па етапі налагодження. Етапи проектування та програмування суміщені у часі: в ідеалі спочатку проектується і кодується верхній рівень, потім - наступний, і так далі. Така стратегія застосовується тому, що в процесі кодування може виникнути необхідність внести зміни, що відбиваються на модулях низького рівня. V етап. Спадний тестування. Цей етап записаний останнім, але це не значить, що тестування не повинно проводитися на попередніх етапах. Проектування та програмування обов'язково повинні супроводжуватися написанням набору тестів - перевірочних вихідних даних і відповідних їм наборів еталонних реакцій. Необхідно розрізняти процеси тестування та налагодження програми. Тестування - процес, за допомогою якого перевіряється правильність програми. Тестування носить позитивний характер, його мета - показати, що програма працює правильно і задовольняє всім проектним специфікаціям. Відладка - процес виправлення помилок у програмі, при цьому мета виправити всі помилки не ставиться. Виправляють помилки, виявлені при тестуванні. При плануванні слід враховувати, що процес виявлення помилок підчиняється закону насичення, тобто більшість помилок виявляється на ранніх стадіях тестування, і чим менше в програмі залишилося помилок, тим довше шукати кожну з них. Для вичерпного тестування програми необхідно перевірити кожну з гілок алгоритму. Загальне число гілок визначається комбінацією всіх альтернатив па кожному етапі. Це кінцеве число, але воно може бути дуже великим, тому програма розбивається па фрагменти, після вичерпного тестування яких вони розглядаються як елементарні вузли більш довгих гілок. Крім даних, що забезпечують виконання операторів в необхідної послідовності, тести повинні містити перевірку граничних умов (наприклад, перехід але умові х> 10 повинен перевірятися для значень, більших, менших і рівних 10). Окремо перевіряється реакція програми на помилкові вихідні дані. Ідея низхідного тестування припускає, що до тестування програми приступають ще до того, як завершено її проектування. Це дозволяє раніше випробувати основні міжмодульні інтерфейси, а також переконатися в тому, що програма в основному задовольняє потреби користувача. Тільки після того як логічне ядро випробувано настільки, що з'являється впевненість у правильності реалізації основних інтерфейсів, приступають до кодування і тестування наступного рівня програми. Природно, повне тестування програми, поки вона представлена у вигляді скелета, неможливо, проте додавання кожного наступного рівня дозволяє поступово розширювати область тестування.
