Как проектировать программы: Книга: «Как проектировать программы» — Фелляйзен, Финдлер, Флэтт. Купить книгу, читать рецензии | How to Design Programs | ISBN 978-5-97060-926-2
Как проектировать программы (HtDP) / Хабр
Следующая статья о том, как писать игры на Scheme
Учебник HtDP (How to Design Programs), посвящен программированию на языке Scheme в среде drRacket.
drRacket можно скачать с сайта.
Вводная часть учебника содержит описание функции empty-scene, предназначенной для работы с изображениями. Например, эта программа создает пустую сцену
#lang racket (require 2htdp/image) ;библиотека для работы с изображениями (empty-scene 100 60) ;сцена (канвас) размером 100х60
А эта помещает на сцену зеленый круг.
#lang racket (require 2htdp/image) (place-image (circle 5 "solid" "green") ;поместить изображение 50 80 ;координаты изображения (empty-scene 100 100)) ;пустая сцена (канвас)
Для создания анимации используется функция animate.
#lang racket (require 2htdp/image) ;библиотека для работы с изображением (require 2htdp/universe) ;библиотека для работы с анимацией (define (picture-of-circle height) (place-image (circle 5 "solid" "green") 50 height (empty-scene 100 60))) (animate picture-of-circle)
1. Функция animate запускает таймер и подсчитывает количество тактов.
2. Таймер срабатывает 28 раз в секунду.
3. Каждый раз, когда таймер «тикает», animane отправляет в picture-of-circle текущий такт; и
4. сцена отображается на канвасе.
Это означает, что круг сначала появляется в кооринате 0, затем 1, затем 2 и т. д. Поэтому круг опускается сверху вниз. Т.е. эта программа за 3,5 секунд создает около 100 изображений, что и позволяет создать эффект движения.
В первой части учебника приводится описание функции big-bang, а все программы, использующие big-bang, называются в дальнейшем world-программами.
Эта программа рисует красный квадрат 100х100 (Параграф 2.5).#lang racket (require 2htdp/image) (require 2htdp/universe) (define (number->square s) (square s "solid" "red")) (big-bang 100 [to-draw number->square])
Если изменить значение параметра, функция нарисует квадрат другого размера.
(big-bang 50 [to-draw number->square]) ; квадрат 50х50 (big-bang 100 [to-draw number->square]) ; квадрат 100х100 (big-bang 150 [to-draw number->square]) ; квадрат 150х150
Механизм передачи параметров, используемый функцией big-bang, можно рассмотреть
на примере алгоритма реализации функций CONS,CAR,CDR из учебника SICP.
(define (f-cons x y) (define (dispatch m) (cond ((= m 0) x) ((= m 1) y) (else (error "Аргумент не 0 или 1 -- CONS" m)))) dispatch) (define (f-car z) (z 0)) (define (f-cdr z) (z 1))
Проверим результат работы этих функций.
(define a 1) (define b 2) (display (f-car (f-cons a b))) ; получаем 1 (display (f-cdr (f-cons a b))) ; получаем 2
Создадим функцию f-cr:
(define (f-cr x y) (y x))
Теперь функция f-cr может передавать любые значения.
Изображение
По аналогии создадим функцию big-bang-1:
(define (big-bang-1 x y) (y x))
и функцию to-draw-1, инкапсулирующую render-1:
(define (to-draw-1 x) (define (render-1 y) (place-image (x y) y y (empty-scene (* 2 y) (* 2 y))) ) render-1)
Реализуем алгоритм передачи параметров (значений):
Изображение
Далее в учебнике рассматривается конструкция вида:
(big-bang cw0 [on-tick tock] [on-key ke-h] [on-mouse me-h] [to-draw render] [stop-when end?] . ..)
которая позволяет обрабатывать нажатие клавиш, таймер, координаты движения объекта. Далее (Figure 13) приведен листинг программы, использующей эту конструкцию.
(define BACKGROUND (empty-scene 100 100)) (define DOT (circle 3 "solid" "red")) (define (main y) (big-bang y [on-tick sub1] [stop-when zero?] [to-draw place-dot-at] [on-key stop])) (define (place-dot-at y) (place-image DOT 50 y BACKGROUND)) (define (stop y ke) 0)
Запустить программу можно в режиме «Начинающий студент» (Верхнее меню → Язык → Выбрать язык… → Начинающий студент), добавив пакеты (Верхнее меню → Язык → Добавить учебный пакет…) для работы с изображениями (image.rkt) и анимацией (universe.rkt).
Параграф 3 называется «Как проектировать программы» (How to Design Programs). Здесь говорится о том, что программы представляют информацию в виде данных. Это означает, что числа могут представлять из себя как количество тактов, отсчитываемых таймером, так и координаты объекта, его цвет, размер и т. п. Программа должна производить запись этих чисел в память и осуществлять преобразование этих числел обратно в координаты объекта, его цвет, размер и т.д.
На рис. 14 изображена диаграмма, иллюстрирующая эту идею.
Параграф 3.6 посвящен проектированию world-программ. На рисунке 17 представлена упрощенная схема библиотеки 2htdp/universe.
Далее описывается 3 основных этапа по созданию big-bang-программ (параграф 3.7):
1. Для всех величин, которые остаются неизменными, надо создать константы.
a. «Физические» константы привязаны к таким атрибутам объекта, как скорость, цвет,
ширина, высота и т.д.
(define WHEEL-RADIUS 5)
b. «Графические» константы.
(define WHEEL
(circle WHEEL-RADIUS «solid» «black»))
2. Те свойства, которые изменяются с течением времени в ответ на нажатие клавиш,
таймер и т.д. надо представить в виде состояний объекта управления.
3. При получении набора состояний всех объектов, надо вызвать big-bang для отображения этих объектов. Далее следуют упражнения, в которых необходимо использовать функцию big-bang.
В параграфе 4.3 обсуждается вопрос обработки событий, генерируемых клавиатурой и мышкой. На рис. 20 представлена условная конструкция, обрабатывающая клавиши «left» и «right».
(define (keh p k) (cond [(string=? "left" k) (- p 5)] [(string=? "right" k) (+ p 5)] [else p]))
Добавлю, что если также необходимо обрабатывать клавиши «up» и «down», то координаты объекта следует хранить в списке:
(define coord-xy (list 50 50) ) ; x=50 ; y=50
и передавать этот список в big-bang:
(big-bang coord-xy [to-draw place-dot-at] [on-key keh])
функция place-dot-at «разбирает» список на части:
(define (place-dot-at xy ) (place-image DOT (car xy) (cdr xy) MTS)) ; (car(cdr xy))
а функция keh «разбирает» список, изменяет одну из координат, и собирает обратно:
(list (-(car p)5) (cdr p) ) ; (car (cdr p))
Далее предлагается разработать программу-светофор.
(check-expect (traffic-light-next "red") "green") (define (traffic-light-next s) (cond [(string=? "red" s) "green"] [(string=? "green" s) "yellow"] [(string=? "yellow" s) "red"]))
Добавлю, что светофор переключается очень быстро (каждый такт). Чтобы этого избежать, надо изменить время срабатывания таймера.
[on-tick traffic-light-next rate-expr]
Теперь таймер будет срабатывать каждые rate-expr секунд (on-tick tick-expr rate-expr).
Также в тексте дана ссылка на страницу с world-программами. Запустить программы можно в режиме «Начинающий студент», добавив необходимые пакеты.
Параграф 5 (Adding Structure) содержит определение структур данных (Пример)
#lang racket (define-struct posn (x y)) (define a (make-posn 10 34)) (posn-x a) (posn-y a) (posn? (posn 10 34))
В параграфе 5.4 автор дает определение структуры: структура, фактически, определяет другие функции. В частности:
1. Конструктор, который создает экземпляр структуры.
2. Селектор, который имеет доступ к полям экземпляра структуры.
3. Структурный предикат, который, подобно обычным предикатам, проверяет,
является ли аргумент экземпляром структуры.
make-posn — это конструктор
posn-x и posn-y — селекторы
posn? — предикат
Подробнее об этом написано в Документации (Structures)
Параграф 5.5. Программу из упражнения 71 предлагается запустить по-шагам (step-by-step) в отладчике. Запускать надо в режиме «Начинающий студент», добавив учебные пакеты.
В параграфе 5.6 автор делает поэтапное описание программы для покадровой анимации (перемещение объекта вдоль одной из осей). Теперь в программе используются структуры для определения координат объекта.
Вот эта программа
(require 2htdp/image) (require 2htdp/universe) ; (define-struct posn (x y)) (define MTS (empty-scene 100 100)) (define DOT (circle 3 "solid" "red")) ; A Posn represents the state of the world. (define (x+ p) (make-posn (+ (posn-x p) 3) (posn-y p))) (define (scene+dot p) (place-image DOT (posn-x p) (posn-y p) MTS) ) (define (reset-dot p x y me) (cond [(mouse=? me "button-down") (make-posn x y)] [else p])) ; Posn -> Posn (define (main p0) (big-bang p0 [on-tick x+] [on-mouse reset-dot] [to-draw scene+dot])) (main (make-posn 1 20))
В параграфе 5.11 приводится пример обработки изображения.
В параграфе 6.1 делается поэтапное описание игры Space invanders.
В параграфе 6.2 предлагается дополнить программу из параграфа 4.3 (светофор).
P.S.
ссылка на статью об этом учебнике
в этой статье обсуждается вопрос объектного программирования на языке Scheme
эта статья для тех, кто уже справился с Python и теперь планирует изучить Erlang или Haskell
Проектирование ПО для начинающих методом снежинки / Хабр
Публикация может быть полезной скорее начинающим программистам, чем тем, кто знаком с разработкой и проектированием ПО (не нужно знать каких либо продуктов для проектирования ПО).
Я думаю, знающие согласятся, что их первый опыт программирования реального приложения (не Hello World) свелся с простому вопросу: с чего, собственно, начать? Как начать проектирование программы? Что писать-то?!
И, как правило, первый опыт — это куча кода, который потом либо забывался, либо переписывался полностью, в зависимости от нужности программы.
Я долгое время шарил по интернету в поисках рецепта проектирования, но везде все сводили к определенным моделям, которые как шаблоны, нужно было применить и на них натянуть свою программу. Для примера можно взять MVC — все знают, что это, но рекомендации, как реализовывать ее, разнятся кардинально.
И вот, однажды утром, мне пришла в голову простая мысль: а что, если программу проектировать по методу снежинки?
Что я сделал:
1. Нарисовал на листке бумаги, как выглядит программа (для консолей особой разницы нет, поймете по ходу повествования). Для примера, возьмем калькулятор.
2. Условно разделил лист бумаги на две части, в одной я начну описывать интерфейс, в другой — что собственно программа умеет делать, ее модель (бизнес-логика). Уже на этом этапе видно, что мы разделили программу на 2 части: представление и логику. При этом, если программа консольная, в представление у нас попадут команды, на которые реагирует программа и вывод, который она возвращает.
Контроллер же — это связь между частью интерфейса и моделью программы.
3. Для описания интерфейса первым делом перечисляются все однотипные элементы (например, кнопки, лейблы и прочее). Получается, уже на этом этапе мы описываем классы-родители. Например, калькулятор:
Красным я обвел одинаковые элементы, это меню, лейбл, текстовое поле, кнопки и радио.
Дальше я смотрю, можно ли разбить эти элементы на более конкретные? (Что, естественно, можно, так как у нас не одна кнопка). Соответственно, от кнопки я стараюсь образовать как можно меньше общих групп или, чтобы было понятнее, классов: это число-буквенные (не вычисляют, только вводят данные) и оперативные (нажатие на них может привести к вычислениям или иным операциям). Чем меньше мы образуем одновременных классов, тем больше уровень абстракции получаем, что весьма полезно может быть в будущем, я думаю все согласны с этим (удобнее будет дополнять функционал, всегда есть от чего наследовать).
Продолжая дальше разбивать на группы, мы придем к определению каждого окончательного класса, когда разбиение уже невозможно. А цепочка от него до нашей начальной программы будет цепочкой наследования. Если нас что то не устраивает, например, куда деть кнопку стирания последнего символа — мы всегда можем пройтись по дереву наследования и изменить ветвление или деление на классы. Описав интерфейс — мы получим шпаргалку для дальнейшего проектирования(мы же, в конце концов, не будем лепить пустые элементы на форму).
4. Аналогично поступаем с логикой, начиная от общего класса, все больше конкретизируя операции.
Если у нас есть какая-либо операция, уже известная, но не классифицированная, ее достаточно добавить, а потом уже вписать в выстраивающуюся модель.
Получится что-то вроде этого:
5. При расширении нашей программы — модификация проходит достаточно легко. Например, нам потребовалось, чтобы программа сперва читала строку, а потом уже вычисляла. Т. е. появляется парсер, который использует класс вычислений (уже реализованный) и контроллер (который читает строку, занося ее в текстовое поле при вводе и передавая после парсеру). Модификации уложатся едва ли не в три строки, плюс класс, описывающий парсер.
Если программа очень большая, сложная — всегда можно взять отдельный элемент и описать по вышеуказанному методу. Например, для многооконного приложения можно нарисовать снежинку для каждого окна. Для сложной логики — выделить глобальные операции, и поступить аналогично. К тому же, подобный метод работает не только от общего к частному, но и наоборот. Сперва мы набираем всё, что нам придет в голову, в виде кирпичиков или небольших деревьев. Если можем объединить во что то общее — мы получаем родительский класс. Если можем разбить на категории, мы получаем подклассы. И так, пока не останется кирпичиков без связей, не будет возможности разбить на подклассы и не получится снежинка.
Когда все будет сделано — можно начинать писать код. Но как его писать, это уже другая история… Впрочем, еще на этапе проектирования уже можно давать имена классам и кратко описывать их функционал.
P.S.
Из плюсов — ничего не надо знать, нужны только лист бумаги, ручка (или векторный редактор) и базовые знания языка, на котором будет писаться программа (я опирался на Java). Получается очень наглядно и довольно легко, особенно для начинающих.
Из минусов — упрощенность, возможно некоторые особенности проектирования теряются, но это уже вопрос к тем, кто этим занимается давно и может что-либо подсказать или дополнить.
Как разрабатывать программы
- $60.00 Мягкая обложка
- электронная книга
- Аренда электронного учебника
792 стр. , 8 x 9 дюймов, 194 ч/б иллюстр.
- Мягкая обложка
- 9780262534802
- Опубликовано: 4 мая 2018 г.
- Издатель: The MIT Press
60,00 $
- Электронная книга
- 9780262344128
- Опубликовано: 18 мая 2018 г.
- Издательство: MIT Press
59,99 $
- Случайный дом пингвинов
- Амазонка
- Барнс и Ноубл
- Книжный магазин.org
- Индивидуальный
- Индиго
- Книг на миллион
Другие розничные продавцы:
- Amazon. co.uk
- Блэкуэллс
- Книжный магазин.org
- Фойлз
- Улей
- Водные камни
- Случайный дом пингвинов
- Амазонка
- Барнс и Ноубл
- Книжный магазин. org
- Индивидуальный
- Индиго
- Книг на миллион
Как разработать новую программу
Разработка новой программы может быть сложной и полезной. Сложно, потому что трудно понять, правильно ли вы его разработали. Вознаграждение, если ваша программа в конечном итоге работает (или обескураживание, если она в конечном итоге не работает!).
Существует множество руководств по разработке программ, таких как эти от МФКК и ПРООН. Проблема в том, что, хотя большинство руководств подходят для крупномасштабных программ, они могут быть «лишними» для небольших программ или ситуаций, когда у вас ограниченное время и ресурсы.
В этом руководстве описаны минимальные шаги, которые необходимо выполнить при разработке новой программы. Шаги можно выполнять в порядке, отличном от представленного здесь, или даже параллельно, если это подходит для вашей ситуации.
Узнайте, в чем проблема
Первый шаг — понять, какую проблему вы хотите решить. Обычно это включает в себя некоторый тип «оценки потребностей», когда вы проводите опрос, интервью, фокус-группы и/или встречи с бенефициарами, чтобы выяснить, с какими проблемами они сталкиваются, масштаб проблемы и насколько важной, по их мнению, является проблема. .
Как только вы решите, что определили проблему, может быть полезно провести анализ дерева проблем, чтобы исследовать причины и следствия. Начните с написания основной проблемы в середине доски или флип-чарта. Затем спросите себя: в чем причина этой проблемы? И какова причина этой причины? Продолжайте перечислять причины вниз по странице, чтобы они стали корнями дерева, пока вы не решите, что достигли самой нижней первопричины. Затем вернитесь к основной проблеме и спросите: каковы последствия этой проблемы? И каковы последствия этих эффектов? Перечислите их вверх по странице, чтобы они стали ветвями дерева. Результат будет выглядеть примерно так, как показано в примере ниже.
Когда вы проводите анализ дерева проблем, лучше всего привлечь всех членов команды, а также некоторых представителей бенефициаров, которым вы пытаетесь помочь. Я часто обнаруживаю, что люди могут иметь очень разные мнения о причинах и следствиях проблемы.
Также очень важно убедиться, что проблемы в вашем дереве проблем действительно существуют. Это можно сделать с помощью опроса или путем сбора других количественных данных. Например, я когда-то работала над программой, в рамках которой представители сообщества считали, что одной из основных причин незапланированной беременности было то, что мужья не позволяли своим женам использовать методы планирования семьи. Однако после того, как мы провели опрос, чтобы проверить это, мы обнаружили, что только у 2% женщин была эта проблема. Поэтому мы удалили его из дерева проблем.
Узнайте, кто является заинтересованным лицом
Ни одна программа не работает в вакууме. Поэтому очень важно, чтобы в процессе проектирования вы определили все другие заинтересованные стороны, которые могут быть вовлечены. Причудливое название для этого — «картирование заинтересованных сторон» или «анализ заинтересованных сторон». Начните с мозгового штурма всех заинтересованных сторон, которые могут быть связаны с вашим проектом. Сюда входят правительство, бенефициары, другие НПО и даже ключевые лица в целевых сообществах.
Затем проведите встречу с каждым из заинтересованных лиц вместе или по отдельности. К концу встреч вы должны быть в состоянии ответить на следующие вопросы о каждой заинтересованной стороне (вы можете записать ответы в таблицу):
- Проблема: С какими ключевыми проблемами они сталкиваются?
- Мотивация: Что ими движет? Чем они интересуются?
- Потенциал: Как они могут помочь в решении выявленных проблем?
- Взаимодействие: Как лучше с ними взаимодействовать? (например, через встречи, отчеты, телефонные звонки и т. д.)
Подумайте, какие ресурсы и навыки у вас есть в наличии
В рамках процесса проектирования вам также необходимо учитывать возможности вашей собственной организации и команды. Какие ресурсы у вас есть? Какие навыки есть у команды на данный момент? Эта информация поможет определить типы программ, которые вы действительно можете реализовать. Например, нет смысла разрабатывать микрофинансовую интервенцию, если в вашей организации нет специалистов по микрофинансированию.
Одним из инструментов, который некоторые люди любят использовать на этом этапе, является SWOT-анализ, который определяет сильные и слабые стороны, возможности и угрозы для организации. Хотя этот инструмент может быть полезен, он ни в коем случае не является обязательным для выполнения этого шага. Часто бывает достаточно откровенного обсуждения со всеми членами команды, чтобы определить ресурсы и навыки, доступные для запуска программы.
Узнайте, какие вмешательства эффективны
Это один из самых важных шагов, который чаще всего пропускают. Вероятно, вы не первая организация, пытающаяся решить проблему, над которой вы работаете. На самом деле вполне вероятно, что многие другие организации уже пробовали различные подходы. Существует несколько веб-сайтов и баз данных, где вы можете найти результаты этих предыдущих программ. Это поможет вам узнать, сработает ли тот или иной подход, прежде чем тратить деньги на его попытки.
На этом этапе вы также должны проверить, существуют ли какие-либо теории изменений, связанные с вашей проблемой. Теория изменений определяет все возможные пути, которые могут привести к изменениям, и причины, по которым они ведут к изменениям. Наличие хорошей теории изменений, основанной на предыдущих исследованиях, может быть очень полезным для определения возможных целей и вмешательств, что является следующим шагом. Если вы не знаете, как выглядит теория изменений, ознакомьтесь с этими примерами из DFID.
Выберите цель и способ ее измерения
Как только вы узнаете, в чем проблема, кто является заинтересованными сторонами, какие навыки и ресурсы у вас есть в наличии, и что люди уже пробовали ранее, теперь можно решить, какова должна быть цель вашей программы. У вас может быть только одна цель или одна цель плюс несколько подцелей или результатов.
Один из способов определить цель и возможные задачи — просто поменять местами утверждения в дереве проблем с отрицательных утверждений на положительные. Например, «отсутствие осведомленности» становится «повышенной осведомленностью», «увеличение обезлесения» становится «уменьшением обезлесения». Пример этого показан ниже. Этот пример был создан путем обращения операторов в предыдущем дереве задач.
Еще один способ определить возможные цели и задачи — обратиться к Теории изменений. Это может помочь вам определить, какие изменения потребуются, чтобы повлиять на проблему.
Обычно рекомендуется начать с определения всех возможных целей и задач, а затем выбрать наиболее актуальные и достижимые с учетом имеющихся данных и ресурсов вашей организации. На этом этапе вам также необходимо решить, как вы будете измерять прогресс в достижении цели и задач. Это станет частью вашей системы мониторинга и оценки.
Определите, какие действия, скорее всего, приведут к цели
Когда вы узнаете, каковы цель и задачи программы, возникает следующий вопрос: какие действия на самом деле приведут к цели? На этом этапе вам следует внимательно изучить деятельность и результаты предыдущих программ, проводимых другими организациями. Например, если предыдущая программа обнаружила, что аутрич-работники смогли увеличить использование удобрений среди мелких фермеров, возможно, стоит попробовать это действие. Однако, если несколько предыдущих программ обнаружили, что аутрич-работники не повлияли на использование удобрений, возможно, лучше попробовать другой подход.
Хотя это кажется достаточно простым, на практике многие организации не удосуживаются просмотреть предыдущие доказательства, прежде чем выбрать свою деятельность. В результате много денег и времени тратится на вмешательства, которые, как известно, не работают. Конечно, в некоторых случаях может не быть каких-либо предыдущих доказательств или, возможно, вы придумали совершенно новый подход, который ранее не применялся. В этом случае вы всегда можете протестировать подход, чтобы увидеть, работает ли он, прежде чем масштабировать его.
Для каждого действия обычно требуется идентифицировать само действие, а также результат действия. Например, если их деятельность заключается в проведении 10 учебных занятий для 30 человек каждое, то на выходе будет 300 обученных человек.
Создание документации
Последним шагом в этом процессе является создание документов, необходимых для описания программы. Эти документы обычно требуются донорам, но они также полезны для объяснения того, как работает программа, заинтересованным сторонам и членам команды. Ниже приведен список основных документов, которые необходимо заполнить, со ссылками на шаблоны:
- Логическая структура: здесь описывается, как программные мероприятия приведут к немедленным результатам и как они приведут к задачам/результатам и цели.
- Система мониторинга и оценки: здесь описываются показатели, которые используются для измерения успешности программы.
- Рабочий план: здесь показаны все действия, связанные с программой, кто несет ответственность за каждое действие и когда действия будут завершены.
Лично мне нравится помещать все эти ключевые документы вместе с деревом проблем, сведениями о заинтересованных сторонах и Теорией изменений в единое Руководство по программе. Затем это становится «библией» для программы.
Будьте гибкими
Теперь, когда ваша программа разработана, вы готовы к следующему шагу – реализации. Самое главное, что нужно помнить во время реализации, — это быть гибким. Если что-то идет не по плану, или вы не получаете ожидаемых результатов, то меняйте дизайн программы. Нет смысла тратить время и деньги на программу, которая не работает.
К сожалению, многие организации жестко придерживаются своих первоначальных планов, потому что боятся, что доноры отнимут финансирование, если они изменят свой подход. Хотя это, безусловно, может быть правдой для некоторых доноров, по моему опыту, большинство доноров будут рады, если вы измените дизайн программы, если что-то не работает, если вы сообщите им об этом заранее.
Добавить комментарий