С увеличением объема программы становится
невозможным удерживать в памяти все детали. Естественным способом борьбы со
сложностью любой задачи является ее разбиение на части. В C++ задача может быть
разделена на более простые и обозримые с помощью функций, после чего программу
можно рассматривать в более укрупненном виде – на уровне взаимодействия функций.
Это важно, поскольку человек способен помнить ограниченное количество фактов.
Использование функций является первым шагом к повышению степени абстракции
программы и ведет к упрощению ее структуры.
Разделение программы на функции позволяет
также избежать избыточности кода, поскольку функцию записывают один раз, а
вызывать ее на выполнение можно многократно из разных точек программы. Процесс
отладки программы, содержащей функции, можно лучше структурировать. Часто используемые
функции можно помещать в библиотеки. Таким образом, создаются более простые в
отладке и сопровождении программы.
Следующим шагом в повышении уровня
абстракции программы является группировка функций и связанных с ними данных в
отдельные файлы (модули), компилируемые раздельно. Получившиеся в результате
компиляции объектные модули объединяются в исполняемую программу с помощью
компоновщика. Разбиение на модули уменьшает время перекомпиляции и облегчает
процесс отладки, скрывая несущественные детали за интерфейсом модуля и позволяя
отлаживать программу по частям (или разными программистами).
Модуль содержит данные и функции их
обработки. Другим модулям нежелательно иметь собственные средства обработки
этих данных, они должны пользоваться для этого функциями первого модуля. Для
того чтобы использовать модуль, нужно знать только его интерфейс, а не все
детали его реализации. Чем более независимы модули, тем легче отлаживать
программу. Это уменьшает общий объем информации, которую необходимо одновременно
помнить при отладке. Разделение программы на максимально обособленные части
является сложной задачей, которая должна решаться на этапе проектирования
программы.
Скрытие деталей реализации называется
инкапсуляцией. Инкапсуляция является ключевой идеей как структурного, так и
объектно-ориентированного программирования. Пример инкапсуляции – помещение
фрагмента кода в функцию и передача всех необходимых ей данных в качестве
параметров. Чтобы использовать такую функцию, требуется знать только ее
интерфейс, определяемый заголовком (имя, тип возвращаемого значения и типы
параметров). Интерфейсом модуля являются заголовки всех функций и описания
доступных извне типов, переменных и констант. Описания глобальных программных
объектов во всех модулях программы должны быть согласованы.
Модульность в языке C++ поддерживается с
помощью директив препроцессора, пространств имен, классов памяти, исключений и
раздельной компиляции (строго говоря, раздельная компиляция не является
элементом языка, а относится к его реализации).
|