Программирование. Принципы и практика использования C++ Исправленное издание
Шрифт:
4.1. Вычисления
Входная информация может поступать с клавиатуры, от мыши, с сенсорного экрана, из файлов, от других устройств ввода и других частей программы. К категории “другие устройства ввода” относятся наиболее интересные источники данных: музыкальные клавишные пульты, устройства
5
От английского слова compute — вычислять. — Примеч. ред.
Для обработки входной информации программы обычно используют специальные данные, которые называют структурами данных (data structures) или их состояниями (states). Например, программа, имитирующая календарь, может содержать списки праздничных дней в разных странах и список ваших деловых свиданий. Некоторые из этих данных с самого начала являются частью программы, а другие возникают, когда программа считывает данные и извлекает из них полезную информацию. Например, программа, имитирующая календарь, может создавать список ваших деловых встреч по мере того, как вы будете вводить их в нее. В этом случае основной входной информацией являются запросы месяца и дня встречи (возможно, с помощью щелчка мышью) и ввод данных о деловых встречах (возможно, с помощью клавиатуры). Устройством вывода для этой программы является экран, на котором высвечиваются календарь и данные о назначенных встречах, а также кнопки и приглашения для ввода, которые программа может выводить на экран самостоятельно.
Входная информация может поступать от самых разных источников. Аналогично, результаты могут выводиться на разные устройства: на экран, в другие программы или части программы. К устройствам вывода относятся также сетевые интерфейсы, музыкальные синтезаторы, электрические моторы, генераторы энергии, обогреватели и т.п.
С программистской точки зрения наиболее важными и интересными категориями ввода-вывода являются “в другую программу” и “в другие части программы”. Большая часть настоящей книги посвящена последней категории: как представить программу в виде взаимодействующих частей и как обеспечить взаимный доступ к данным и обмен информацией. Это ключевые вопросы программирования. Проиллюстрируем их графически.
Аббревиатура I/O означает ввод-вывод. В данном случае вывод из одной части программы является вводом в следующую часть. Эти части программы имеют доступ к данным, хранящимся в основной памяти, на постоянном устройстве хранения данных (например, на диске) или передающимся через сетевые соединения. Под частями программы мы подразумеваем сущности, такие как функция, вычисляющая результат на основе полученных аргументов (например, извлекающая корень квадратный из числа с плавающей точкой), функция, выполняющая действия над физическими объектами (например, рисующая линию на экране), или функция, модифицирующая некую таблицу в программе (например, добавляющая имя в таблицу клиентов).
Когда мы говорим “ввод” и “вывод”, обычно подразумеваем, что в компьютер вводится или из компьютера выводится некая информация, но, как вы вскоре увидите, мы можем использовать эти термины и для информации, переданной другой части программы или полученной от нее. Информацию, которая является вводом в часть программы, часто называют аргументом, а данные, поступающие от части программы, — результатом.
Вычислением мы называем некое действие, создающее определенные результаты и основанное на определенных входных данных, например порождение результата (вывода), равного 49, на основе аргумента (ввода), равного 7, с помощью вычисления (функции) извлечения квадратного корня (см. раздел 4.5). Как курьезный факт, напомним, что до 1950-х годов компьютером [6] в США назывался человек, выполнявший вычисления, например бухгалтер, навигатор, физик. В настоящее время мы просто перепоручили большинство вычислений компьютерам (машинам), среди которых простейшими являются калькуляторы.
6
Вычислителем. — Примеч. ред.
4.2. Цели и средства
• правильно;
• просто;
• эффективно.
Пожалуйста, запомните порядок этих целей: неважно, как быстро работает ваша программа, если она выдает неправильные результаты. Аналогично, правильная и эффективная программа может оказаться настолько сложной, что ее придется отклонить или полностью переписать в виде новой версии. Помните, что полезные программы всегда должны допускать модификации, чтобы учитывать новые потребности, новые аппаратные устройства и т.д. Для этого программа — и любая ее часть — должны
• Абстракция. Этот способ предполагает сокрытие деталей, которые не являются необходимыми для работы с программой (детали реализации) за удобным и универсальным интерфейсом. Например, вместо изучения деталей сортировки телефонной книги (о методах сортировки написано множество толстых книг), мы можем просто вызвать алгоритм сортировки из стандартной библиотеки языка С++. Все, что нам нужно для сортировки, — знать, как вызывается этот алгоритм, так что мы можем написать инструкцию
• “Разделяй и властвуй”. Этот способ подразумевает разделение большой задачи на несколько меньших задач. Например, если требуется создать словарь, то работу можно разделить на три части: чтение, сортировка и вывод данных. Каждая из новых задач намного меньше исходной.
Мы просто не в состоянии писать и поддерживать работу крупных монолитных программ. Оставшуюся часть книги можно рассматривать как длинный ряд примеров задач, которые необходимо разбить на более мелкие части, а также методов и способов, используемых для этого.
Рассматривая процесс разбиения программ, мы всегда учитываем, какие инструменты помогают выделить эти части и обеспечить взаимодействие между ними. Хорошая библиотека, содержащая полезные средства для выражения идей, может существенно повлиять на распределение функциональных свойств между разными частями программы. Мы не можем просто сидеть и фантазировать, как получше разбить программу на части; мы должны учитывать, какие библиотеки находятся в нашем распоряжении и как их можно использовать. Пока вы находитесь в начале пути, но вскоре увидите, что использование существующих библиотек, таких как стандартная библиотека языка С++, позволяет сэкономить много сил не только на этапе программирования, но и на этапах тестирования и документации. Например, потоки ввода-вывода позволяют нам не вникать в детали устройства аппаратных портов ввода-вывода. Это первый пример разделения программы на части с помощью абстракции. В следующих главах мы приведем новые примеры.