logo search
Языки программирования

2.8. Модули

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

Возможно, вам говорили, что отдельная подпрограмма не должна превы­шать 40 или 50 строк, потому что программисту трудно читать и понимать большие сегменты кода. Согласно тому же критерию, должно быть понятно взаимодействие 40 или 50 подпрограмм. Отсюда следует очевидный вывод: любую программу, в которой больше 1600 — 2500 строк, трудно понять! Так как в полезных программах могут быть десятки тысяч строк и нередки систе­мы из сотен тысяч строк, то очевидно, что необходимы дополнительные структуры для создания больших систем.

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

Есть две потенциальные трудности применения модулей на практике.

• Необходима мощная среда, разработки программ, чтобы отслеживать «истории», модулей и проверять интерфейсы. ;

• Разбиение на модули поощряет использование большого числа неболь­ших подпрограмм с соответствующим увеличением времени выполне­ния из-за накладных расходов на вызовы подпрограмм.

Однако это больше не является проблемой: ресурсов среднего персональ­ного компьютера более чем достаточно для поддержки среды языков C++ или Ada, а современная архитектура вычислительной системы и методы компиля­ции минимизируют издержки обращений.

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

Несмотря на тот факт, что невозможно научить здравому смыслу в проек­тировании программ, есть некоторые принципы, которые можно изучить. Одним из основных методов декомпозиции программы является объектно-ориентированное программирование (ООП), опирающееся на концепцию типа, рассмотренную выше. Согласно ООП, модуль следует создавать для любого реального или абстрактного «объекта», который может представляться набо­ром данных и операций над этими данными. В главах 14 и 15 детально обсуж­дается языковая поддержка ООП.