Глава 22. Рецепт програми
остаточного терміну. Вийняти, вивалити і дати охолонути, перед тим як подавати клієнтові.
Мені відомо, принаймні, чотири рецепта бісквіта. Їх разли% чия визначаються вашими уподобаннями - чи хочете ви бісквіт без масла або бісквіт без яєць - і способом приготування. Програм% ми пишуться таким же чином. Не існує рецепта або магич% ської формули; одну і ту ж систему можна побудувати різними спосо% бами, кожен з яких може бути не кращий за інший. Можна ви% брати різні інгредієнти для процесу розробки і різні методи. Так чи інакше, в результаті можуть спекти трохи розрізняються пироги - щодо функцій, структури, стабільності, розширює% мости, сопровождаемости і т. П. Рецепти описують життєвий цикл програмного продукту. етапи розробки від початкового (заступники% сіл програми) до остаточного (припинення експлуатації).
Ми, програмісти, повинні передбачуваним (і в який% мірі воспро% ізводімим) чином створювати програмне забезпечення, слідуючи визна% поділеній процедурі. Ми повинні залучити собі на допомогу таку про% цедуру розробки, яка дозволить нам створювати кращі з можли% них програм. У цьому розділі ми вивчимо деякі рецепти створення програм; ми будемо їх порівнювати, протиставляти, критикувати і дивитися, як вони впливають на створюваний нами код.
Хороші програмісти знають, як програмувати - володіють методами і прийомами роботи.
Які ж ці рецепти програмування?
Стиль програмування описує, як планується рішення заду% чи, як воно ділиться на частини і моделюється на обраною мовою. Ми повинні створювати моделі рішень, тому що корисна система не може цілком вміститися в голові розробника. Стиль программи% вання визначає, яким чином ми розбиваємо проект на управ% ляемая частини; це парадигма проектування, що служить вираженню завдань вашого коду.
Різних мов програмування відповідають різні стилі про% граммірованія. Одні стилі підігнані під конкретну мову, інші
• Процедурні мови дозволяють точно задати послідовність кроків, які призводять до отримання результату. Це те, до чого звикла більшість програмістів.
• Описові мови описують зв'язки між змінними на мові правил виведення (або функцій), а для отримання результату виконавча система мови застосовує до цих правил який% то фіксований алгоритм. (Це опис може стати більш по% нятним після того, як ми розглянемо функціональний і логічні% ське програмування.)
Вибір мови програмування частково визначає стиль. (Краще все ж вибирати мову, підтримує той стиль, який ви хоти% ті використовувати.) Однак вибір мови програмування - не найголовніше. Цілком можна писати структурований код на об'єктно% орієнтованої мови, точно так же, як можна написати відверни% вальний код на будь-якій мові. У кількох наступних розділах описуються популярні стилі програмування.
структурне програмування
В цьому стандартному методі процедурного проектування застосовує% ся алгоритмічна декомпозиція - процес розбиття системи на частини, кожна з яких являє собою невеликий крок в більшому процесі. Проектні рішення спрямовані на потік управ% ня і створюють ієрархічну функціональну структуру. Як писав Дейкстра: «Ієрархічні системи володіють тією властивістю, що сущ% ність, що вважається неподільною на одному рівні, розглядається як складений об'єкт на наступному, більш низькому рівні деталізації; в результаті природні гранули простору або часу, примі% німие на кожному рівні, зменшуються на порядок, коли ми пере% полягають свою увагу на черговий нижчий рівень. Ми гово% рим про стінах в термінах цегли, про цеглинах - в термінах кристал% лов, про кристалах - в термінах молекул, і т. Д. »Так Дейкстра попу% лярізіровал структурне програмування в своїй класичній статті« Go To Statement Considered Harmful » (Оператор Go To шкідливий). (Dijkstra 68)
Структурне програмування - це модель, зосереджена на управ% лении і наступна низхідній моделі проектування. Ви начина% ете з того, що замислюється цілком всю програму (наприклад, зро лать_покупкі), потім розкладається її в серію подблоков (наприклад, соста віть_спісок_покупок, вийті_із_дома, дойті_до_магазіна, вибрать_покупкі, рас платіться_в_кассе, вернуться_домой). У свою чергу кожен подблок розкладається на частини, поки не буде досягнутий такий рівень, на якому легко написати реалізацію в коді. Блоки збираються в це% лое, і на цьому проект закінчується.
Глава 22. Рецепт програми
Структурний підхід має наступні наслідки:
• Кожен крок декомпозиції повинен бути в межах розумного по% нимания програмістом. (Дейкстра сказав: «Я пропоную ограни% читься проектуванням і реалізацією програм, що розуміються ра% зумом».)
• Потік управління потрібно ретельно контролювати: уникайте жахливого оператора goto (неструктурованого переходу в вироб% вільне місце програми) і пишіть функції з одним входом і од% ним виходом (так званий код SESE).
• Структурність коду забезпечується циклічними конструкціями і умовними операторами всередині функціональних блоків. Відно% шення до дострокових виходів в середині циклу або з вкладеного блоку таке ж обурене, як до goto.
Поширені мови структурного програмування - C, Pascal, BASIC і давніші, типу Fortran і COBOL. За допомогою большинст% ва процедурних мов легко пишеться структурний код, хоча це не їх спеціалізація; структурні програмісти часто приймають але% вомодние мови, не беручи нових ідіом. 1
Буч так описує ГО% програмування: «Метод реалізації, при якому програми організовані у вигляді взаємодіючих між собою об'єктів, кожен з яких представляє собою екземпляр не% якого класу, а класи утворюють ієрархічну структуру, осно% ванну на відносинах спадкування.» (Booch 94 ) Це теж процедур% ий стиль, але він дозволяє більш природним способом моделювати реальність; ми направляємо свою увагу на що моделюються взаємо% діючі суті, а не на конкретний потік виконання.
Ця модель в значній мірі будується навколо даних (на відміну від структурного програмування, де в центрі знаходяться процес% си). Ми цікавимося тут життям даних і їх переміщенням, а не послідовністю дій, які потрібно виконати, щоб ре% шити завдання. У об'єктів (даних) є поведінка (вони що% то роблять) і стан (яке змінюється в результаті дій). На рівні мови це реалізовано у вигляді методів класів об'єктів. ГО% програм% ми розглядаються як набори взаємодіючих програмних компонент, а не монолітні списки команд ЦП. ГО% проектування дозволило нам ефективно моделювати великі системи.
В об'єктно% орієнтованому програмуванні застосовуються сле% дмуть поняття комп'ютерної науки:
1 Це необов'язково погано, якщо тільки програміст не вважає, що вийшов за межі структурного кодування, не змінюючи свого способу розробки коду.
Подання Дейкстрой ієрархії (поверніться до нього і прочитайте знову) відкрило певний вид абстракції.
Инкапсуляцией називають приміщення пов'язаних один з одним ис% виконуваних блоків в один пакет, доступ до якого здійснюється тільки через чітко визначений API: капсулу для коду. Користування земельними діл% ки цієї капсули можуть лише звертатися до заданого API, але не мають прямого доступу до внутрішнього стану. Це забезпечує чіткий поділ обов'язків, дає можливість поміркувати над метафізичними питаннями типу «Що є об'єкт? »І дає деякі гарантії того, що ніякої зловмисник не зможе поколупатися в вашому коді, коли ви відвернетеся.
Це механізм для створення об'єктів, які є особливою версією батьківських. Нехай батьківський тип називається Фігура, а Насл% дмуть йому Квадрат, Круг і Трикутник. Спадкоємці мають більш де% тальний і спеціалізованим поведінкою (наприклад, вони знають, скільки сторін у фігури). Як і будь-які ідеї в програмуванні, спадкування може служити основою для створення незрозумілих і дивних програм, а може застосовуватися в логічно пра% ном, елегантному коді. Хороші ГО% програмісти вміють створювати ефективні спадкові ієрархії.
Це властивість дозволяє одному і тому ж коду діяти з данни% ми різних типів (які в ГО% мовах зазвичай називаються класу% ми), використовуючи контекст, в якому виконується код. Ця техноло% гия особливо виділяє програмування згідно явно заданим ін% терфейс, а не неявним реалізацій - поліморфізм забезпечує чіткий поділ обов'язків при написанні коду. Поліморфізм буває двох видів: динамічний і статичний.
Динамічний поліморфізм відповідно до своєї назви визначає фактичну операцію на етапі виконання - в зависи% мости від типу операнда або цільового об'єкта. При цьому часто ис% користується ієрархія наслідування: клієнт, який працює з типом Фігура, може в конкретному випадку працювати з об'єктами типу Квад рат або Трикутник, що визначається під час прогону.