Спонсоры сайта:

Наличие этой страницы в поиске?

Информеры ТИЦ и PR

  Yandex ТИЦ:  
   Google PR:  

Путешественникам, меломанам, бизнесменам, вебмастерам, новости.

Содержание | <<< | >>>

Проектирование сверху вниз





Без сомнения, главнейшее условие успешного создания крупных программ заключается в применении надежных методов проектирования. Широкое распространение при написании программ получили следующие три метода: нисходящий (сверху вниз), восходящий (снизу вверх) и специальный (на данный конкретный случай). В случае нисходящего метода вы начинаете созидательный процесс с программы высокого уровня и спускаетесь до подпрограмм низкого уровня. Восходящий метод работает в обратном направлении: вы начинаете с отдельных специальных подпрограмм, постепенно строите на их основе более сложные конструкции и заканчиваете самым верхним уровнем программы. Специальный подход не имеет заранее установленного метода.

Поскольку С является структурированным языком программирования, то лучше всего он сочетается с нисходящим методом проектирования. Подход сверху вниз позволяет производить ясный, легко читаемый программный код, который в дальнейшем не вызовет трудностей и при сопровождении. К тому же данный подход помогает прояснить и сделать понятной всю структуру программы в целом до кодирования функций более низкого уровня. Такой подход позволяет уменьшить потери времени, обусловленные неудачными или ошибочными начинаниями.

Структурирование программы

Как и для любой общей схемы, при применении нисходящего метода начинают с общего описания программы, а затем переходят к проработке ее конкретных элементов. На практике при разработке программы лучше всего сначала точно определить, что программа будет делать на самом высоком уровне, и только после этого погружаться в подробности, касающиеся каждого действия. Предположим, к примеру, что необходимо написать программу, предназначенную для ведения списка рассылки. Во-первых, необходимо составить перечень действий, которые будет выполнять такая программа. Каждая строчка данного перечня должна содержать только один функциональный элемент. (На этом этапе под функциональным элементом понимается "черный ящик", который выполняет только одну задачу.) Тогда такой перечень может быть представлен примерно в следующем виде:

  • Ввести новый адрес
  • Удалить новый адрес
  • Печать списка
  • Найти имя
  • Сохранить список
  • Загрузить список
  • Завершить выполнение программы

После того как вы определили все функциональные возможности программы, можно в общих чертах описать подробные свойства каждого функционального модуля, начиная с основного цикла. Ниже приведен один из возможных вариантов такого представления, позволяющий реализовать основной цикл программы работы со списком рассылки:

main loop
{
  do {
    вывести меню
    определить выбор пользователя
    выполнить выбранное действие
  } while выбор != quit
}

Такая разновидность алгоритмического представления (иногда называемая псевдокодом) может помочь внести ясность в общую структуру программы; ее необходимо выполнить до кодирования. С-подобный синтаксис был использован по той простой причине, что он вам уже знаком, но можно воспользоваться и любым другим подходящим синтаксисом.

Аналогичные определения необходимо дать каждому функциональному элементу. Например, вы можете описать функцию, которая осуществляет запись списка рассылки в файл на диске примерно следующим образом:

save to disk {
  open disk file
  while есть данные write {
    write данные на диск
  }
close disk file
}

На этом уровне абстракции функция "записать-на-диск" обращается к новым функциональным модулям более низкого уровня. Эти модули открывают файл на диске, записывают на него данные, а затем закрывают дисковый файл. В дальнейшем необходимо будет еще определить и каждый из этих модулей. Если при их описании будут создаваться новые функциональные элементы, они также должны быть определены и т.д. Этот процесс закончится, когда при описании больше не будет создан ни один новый функциональный элемент. Тогда остается всего лишь сесть и написать реальный С-код, который реализует эти действия. Например, модуль, который закрывает дисковый файл, вероятно, будет транслирован в вызов функции fclose().

Обратите внимание, что при подобном определении совсем ничего не упоминается о структуре данных и переменных. Это сделано умышленно, потому что до сих пор вы хотели определить только то, что должна делать ваша программа, но не то, каким образом она реально будет это осуществлять. Такой описательный процесс помогает выбрать эффективную структуру данных. (Естественно, структуру данных необходимо будет описать перед кодированием функциональных элементов.)

Выбор структуры данных

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

Список рассылки, как правило, содержит следующую информацию: имена, названия улиц, городов, штатов и почтовые индексы. При нисходящем подходе это немедленно предполагает применение определенной структуры для хранения этой информации. И тут же возникает вопрос: а как такие структуры будут храниться и обрабатываться? Для программы, работающей со списком рассылки, можно было бы использовать массив структур фиксированного размера. Но массив фиксированного размера имеет один серьезный недостаток: размер массива жестко и безапелляционно ограничивает длину списка рассылки. Более удачное решение заключается в динамическом выделении памяти для каждого адреса. Тогда каждый адрес будет сохраняться в динамической структуре данных определенной формы (например, в связном списке), которая может при необходимости расти или уменьшаться. В таком случае список может быть огромным или очень маленьким в зависимости от конкретных обстоятельств.

Хотя на данном этапе мы отдали предпочтение динамическому распределению памяти, а не массиву фиксированного размера, все же точная модель представления данных все еще не определена. Существует несколько возможных вариантов. Можно использовать однонаправленный связный список, двунаправленный связный список, двоичное дерево и даже метод хэширования. Каждый из этих методов имеет свои достоинства и недостатки. Ограничим круг обсуждения и предположим, что конкретно нашему приложению, обрабатывающему список рассылки, предъявляется требование достичь минимального времени поиска. Исходя из этого, мы выбираем двоичное дерево. Теперь можно определить структуру, которая содержит в списке каждое имя и адрес, как показано ниже:

struct addr {
char name[30] ;
char street[40];
char city[20];
char state[3];
char zip[ll];
struct addr *left;   /* указатель  на  левое  поддерево */
struct addr *right;  /* указатель  на  правое  поддерево */
};

Теперь, после определения структуры данных, можно приступить к кодированию всей программы. Для этого надо всего лишь определить все подробности, описанные в общей структуре созданного ранее псевдокода. Если вы последуете нисходящему методу, программы будут не только легко читаться, но и потребуют меньше времени на разработку и сопровождение.


Содержание | <<< | >>>

C++ исходники. Все примеры - рабочие:

часы:

Dev C++ WinAPI Стрелочные часы Analog Clock

Dev C++ WinAPI Цифровые прозрачные часы. Текст на рабочем столе. Digital transparent clock. Text on desktop

Dev C++ OLE WinApi CALENDAR and DIGITAL CLOCK (15kb). Календарь и цифровые часы

Dev C++ OLE WinAPI Календарь и цифровые часы почти Vista SideBar всего 21kb

плееры:

Microsoft Visual C++ 2008 Direct Show DVD Mini Player 10.5kb

Dev C++ WinAPI Микро медиа плеер 3.5kb

Dev C++ WinAPI Мини медиа плеер 4.5kb

Dev C++ WinAPI Hint Всплывающая подсказка

Dev C++ WinAPI RECT - имитатор кнопки

Dev C++ WinAPI Заполнить ListBox

Dev C++ WinAPI Заполнить, редактировать, сохранить, загрузить ListBox (PlayList)

Dev C++ WinAPI Индикатор уровня

Dev C++ WinAPI MP3 Микро плеер Открыть с помощью...

Dev C++ WinAPI Своя кнопка

изображения:

Dev C++ GDI+ WinAPI Mini FotoResizer (16kb), изменяет размеры всех фото (JPG) до указанного размера в выбраной папке и её подпапках

Dev C++ WinAPI Сохранить BITMAP экрана, десктопа, окна, клиентской области.

Dev C++ WinAPI Изменить размер изображения BMP RESIZE. Загрузка изображений из ФАЙЛА, вывод на экран и сохранение в файл.

Dev C++ WinAPI Загрузка изображений из РЕСУРСОВ и вывод на экран.

Dev C++ GDI+ WinAPI. Преобразовать изображения из одного формата в другой (JPG в BMP, GIF, PNG и обратно ), используя дополнительные библиотеки GDI+. Загрузка изображений из файла и сохранение в файл.

Dev C++ GDI+ WinAPI масштабирование JPG RESIZE

Dev C++ OLE WinAPI. Преобразовать изображения из JPG в BMP, используя дополнительные библиотеки OLE. Загрузка изображений из РЕСУРСОВ и сохранение в файл.

Dev C++ OLE WinAPI преобразовать JPG в BMP, используя дополнительные библиотеки OLE. Загрузка изображений из ФАЙЛА и сохранение в файл.

Dev C++ OLE WinAPI масштабирование BMP RESIZE

разное:

Dev C++ WinAPI Dev C++ Преобразовать цвет точки экрана в HTML код

Dev C++ WinAPI NOTIFYICONDATA WS_EX_TOOLWINDOW Иконка в области уведомлений (notification area, tray, трей). Удалить с панели задач (taskbar).

Dev C++ WinAPI ShellExecute Создать ссылку на WEB сайт

Dev C++ WinAPI ShellExecute Создать окно со ссылкой на WEB сайт

Dev C++ WinAPI CreateProcess ShellExecute WinExec Запуск приложения из приложения

Dev C++ OLE WinAPI Создать регион Regions PopUp Меню Menu

Dev C++ FindFiles. Поиск файлов заданного типа (в примере *.JPG) в папке и её подпапках

библиотеки:

Скачать библиотеку GDI+ для Dev C++

Скачать справочнник с примерами языка C.