НАПРЯЖЕННОЕ СОСТОЯНИЕ В ТОЧКЕ. ТЕНЗОР НАПРЯЖЕНИЙ

Классификация языков программирования

По способу выполнения языки программирования делятся на компилируемые, интерпретируемые, компилируемые на основе псевдокода и совмещенные.

□ Компилируемые языки. К этой группе относят языки программирования, исходный код которых преобразуется специальной программой-компилятором в объектные модули, которые затем собираются при помощи программы сборки (линковщика) в единый загружаемый модуль. Этот модуль представляет собой выполняемую программу. Компилируемыми являются языки С, C++, Object Pascal.

□ Интерпретируемые языки. К этой группе относят языки программирования, исходный код которых считывается и выполняется специальной программой- интерпретатором инструкция за инструкцией. Интерпретируемыми являются большинство версий языков Basic и Forth.

□ Языки, компилируемые на основе псевдокода («шитого» кода). В этих языках исходный код программы компилируется и выполняется как последовательность вызовов подпрограмм из существующих библиотек. Таковыми являются некоторые версии Basic.

□ Совмещенные языки. В совмещенных языках исходный код проходит две стадии обработки. На первой стадии происходит компиляция исходного кода до уровня промежуточного языка (байт-код в Java или язык MSIL в технологии .NET). На второй стадии происходит интерпретация промежуточного кода (в Java этим занимается виртуальная машина Java) или докомпиляция промежуточного кода до выполняемого машинного кода (эту функцию осуществляет среда вы¬полнения CLR в технологии .NET).

По факту созданию процесса языки программирования делятся на создающие процесс и сценарные.

□ Языки, создающие процесс. После запуска программы создается отдельный процесс выполнения этой программы. Так происходит в языках С, C++, Oblect Pascal.

□ Сценарные языки. Сценарий, или скрипт, — это программа, которую выполняет другая программа. В качестве примером можно привести скрипты оболочки в UNIX, программы на языках РНР, Python, Ruby.

По степени автономности языки программирования делятся на автономные и встроенные.

□ Автономные языки программирования (С, C++, Java) являются автономным инструментом для создания программ.

□ Встроенные языки программирования являются частью какой-то системы и позволяют создавать программы, предназначенные для работы только в этой системе. Пример наиболее известного встроенного языка — VBA (Visual Basic for Application), который используется только внутри приложений Microsoft Office для автоматизации и расширения их функциональности. Встроенными являются также язык программирования системы 1C и язык JavaScript, который выполняется только внутри интернет-приложений.

По уровню отдаленности языка программирования от естественных языков их делят на низкоуровневые и высокоуровневые.

□ Языки низкого уровня ближе к логике процессора вычислительной машины, например, машинный язык, ассемблер.

□ Языки высокого уровня ближе лингвистически к человеческому языку Это все остальные языки программирования.

По парадигмам языки программирования делятся на императивные (процедурные), функциональные, логические и объектно-ориентированные.

□ Императивные (процедурные) языки описывают решение задачи как последовательность процедур. К императивным относится большинство современных языков программирования.

□ Функциональные языки описывают требуемый результат в виде набора вложенных друг в друга функций (Haskell).

□ Логические языки описывают требуемый результат в виде суммы логических операций (Prolog).

□ Объектно-ориентированные языки способны определять абстрактные типы данных и реализовывать основные парадигмы объектно-ориентированного программирования (ООП): инкапсуляцию, наследование и полиморфизм (C++, Java, Object Pascal, и др.).

Краткая история языков программирования

Первый этап — машинные коды

Появление первых языков программирования можно отнести к периоду 20- 40-х гг. XX в. Самые первые опыты программирования, когда в память вычисли¬тельной машины вводились инструкции на машинном языке сначала с помощью перемычек, а потом — набора тумблеров, сегодня могут вызывать только улыбку. Это была очень тяжелая и непроизводительная работа.-Появление терминала и клавиатуры упростило процесс ввода, но не процесс программирования.

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

 

Второй этап — языки высокого уровня

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

Третий этап — структурное программирование

Однако программные проекты на языках программирования высокого уровня оставляли желать лучшего: сроки выполнения проектов были очень велики, а материальные издержки выходили за самые пессимистические прогнозы. Наступило время смены уже не языков, а самого подхода к программированию. Программирование «снизу вверх», когда вначале разрабатывались подпрограммы, а затем эти подпрограммы объединялись в единое целое при помощи инструкций перехода, не оправдало себя. Код получался запутанным, неэкономичным и сложным в отладке. Требовалось изменить саму методологию программирования, вместо программирования «снизу вверх» надо было ввести программирование «сверху вниз», при котором сначала определялись стратегические параметры программного обеспечения, вырабатывался наиболее общий алгоритм работы программы, а затем производилась декомпозиция этого алгоритма до уровня подпрограмм размером в 50-70 строк кода. Далее подпрограммы объединялись в единую программу. Такой подход требовал усовершенствований в самих языках программирования на уровне команд управления ходом выполнения программы. Такие усовершенствования были внесены в языки ALGOL-68, С и Pascal, а сама новая методология получила название структурного программирования.

Четвертый этап — модульное программирование

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

Пятый этап — объектно-ориентированный подход

Алгоритмические языки предыдущих этапов, в основном, обеспечивали реализацию функциональности. При объектно-ориентированном подходе программист должен думать в терминах объектов окружающего мира, нашедших свое абстрактное отражение в сложных типах данных, называемых классами. А языки программирования призваны были давать возможность отображать в коде объекты внешнего мира с их свойствами и поведением. Этот этап можно смело назвать революционным по значимости, поскольку все остальные новации в программировании продолжают основываться на принципах объектно-ориентированного программирования (ООП). Яркими представителями языков, поддерживающих ООП, являются C++, Java, Object Pascal и все семейство языков в технологии Microsoft .NET. Именно объектно-ориентированный подход лежит в основе создания средств визуального проектирования и быстрой разработки программ, таких как Borland Delphi, Borland J Builder и Microsoft Visual Studio.

Шестой этап — компонентный подход

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

Наиболее известными технологиями, реализующими компонентный подход, являются COM, CORBA и .NET.

Седьмой этап — архитектура, управляемая моделью

Этот этап развития технологий программирования пока еще не достиг своего логического завершения, да и сама идея архитектуры, управляемой моделью (Model Driving Architecture, MDA), продолжает развиваться и совершенствоваться, в частности, в рамках технологии ECO для .NET. Смысл технологии MDA — исключить этап кодирования из процесса разработки программного обеспечения. Для того чтобы создать завершенное приложение, достаточно построить его модель на языке UML, а все остальное за вас сделает среда разработки: сгенерирует классы данных, процедуры их обработки, способы подключения к данным, пользовательский интерфейс. Хотя это направление развития является весьма многообещающим, на сегодняшний день основным способом создания программного обеспечения все- таки остается ручное кодирование.

Концепция объектно-ориентированного программирования

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

Абстракция

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

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

 

 

Методы классов

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

 

 

 

 

Полиморфизм

 

 

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

Инкапсуляция

Инкапсуляция реализуется в объектно-ориентированном программировании при помощи областей видимости. Области видимости обозначаются в структуре класса специальными служебными словами. Например, слово private означает, что все поля и методы, объявленные в этой области видимости, невидимы для внешнего мира, a public, наоборот, — что все, объявленное в этой зоне, для внешнего мира открыто. Таким образом, у класса появляется своего рода защитный корпус, предохраняющий от излишней перегрузки программы объявленными именами и методами. Наружу класс экспонирует только то, что составляет его интерфейс и предназначено для внешнего взаимодействия. Все остальные поля и методы он скрывает внутри, помещая их в область видимости private.

 

Инструментальные средства и среды разработки программного обеспечения

Система программирования включает в себя следующий набор инструментов:

□ транслятор (компилятор или интерпретатор);

□ отладчик;

□ средства оптимизации кода (профилировщик);

□ редактор связей (линковщик);

□ набор библиотек;

□ сервисные средства (утилиты).

Об инструментальной среде пользователя можно говорить в случае, когда средства программирования включаются в прикладной программный пакет (например, СУБД). В этом случае состав инструментов может быть таким:

□ библиотека функций, процедур, объектов и методов обработки;

□ макрокоманды;

□ клавиатурные макросы;

□ языковые макросы;

□ конструкторы экранных форм;

□ генераторы приложений;

□ языки запросов высокого уровня;

□ конструкторы запросов по шаблонам.

Интегрированные среды разработки (Integrated Development Environment, IDE) объединяют в одном приложении все или большинство инструментальных средств с целью ускорения разработки программ и удобства использования инструментов на разных этапах создания программного обеспечения. Обычно отличительной чертой современных интегрированных сред разработки является наличие большого количества различных сервисных возможностей, позволяющих программисту максимально сосредоточиться на реализации алгоритма работы программы. К таким возможностям относятся:

□ инструменты визуального создания пользовательского интерфейса;

□ средства разметки кода;

□ средства облегчения редактирования (автоматическое завершение имен и служебных слов, автоматическая вставка конструкций языка и шаблонов кода, подсветка синтаксиса, синтаксическая проверка во время ввода и пр.);

□ интегрированные средства отладки с детальной настройкой точек останова и разными режимами отслеживания значений переменных и объектов;

□ встроенные средства документирования исходного кода и проекта в целом;

□ средства переработки написанного кода с целью улучшения его внутренней структуры, расширения функциональности или приведения в соответствие с изменениями в модели, разработанной системным архитектором;

□ средства интеграции с инструментами жизненного цикла ПО;

□ средства коллективной разработки;

Наиболее известными интегрированными средами разработки в операционной системе Microsoft Windows являются Microsoft Visual Studio и CodeGear RAD Studio.

На сегодняшний день Microsoft Visual Studio является общепризнанным лидером и лучшей интегрированной средой разработки для семейства операционных систем Windows . Богатый набор визуальных компонентов и возможность одинаково эффективно создавать приложения на любом языке программирования делает Microsoft Visual Studio поистине уникальным продуктом.

 

19.5. Жизненный цикл программного обеспечения

Основными этапами жизненного цикла программного обеспечения являются:

□ определение требований и разработка спецификаций;

□ проектирование;

□ кодирование;

□ тестирование;

□ внедрение и сопровождение.

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

В модели водопада к пройденному однажды этапу уже не возвращаются. Каж¬дый предыдущий этап должен быть полностью выполнен, после чего управление проектом передается на последующий этап. Модель водопада представлена на рис. 19.10.

В итерационной модели возврат на предыдущую ступень разработки программ¬ного обеспечения возможен на любом этапе (рис. 19.11).

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

 

 

Анализ требований и разработка спецификаций

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

Лица у которых собираются требования:

□ заказчик (инвестор);

□ руководитель подразделения, в котором будет внедряться создаваемая про-грамма;

□ потенциальные пользователи программы;

□ исполнители программного проекта;

□ потенциальные пользователи результатов работы программы;

□ консультанты.

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

□ выработать соглашение о наличии проблемы;

□ выделить основные причины возникновения проблемы;

□ выявить заинтересованных лиц и пользователей;

□ определить границы системы решений;

□ выявить ограничения, которые необходимо наложить на решение.

Несмотря на то, что требования формируются до начала программного проекта, нужно помнить, что они будут сопровождать работу на каждом этапе разработки ПО. Поэтому требования должны строго документироваться. Лучше всего использовать для этого специальное программное обеспечение управления требованиями, например, Borland CaliberRM. Эта программа позволяет не только документировать требования, но и декомпозировать их до конкретных специфи¬каций и метрик, а также вывести граф метрик, показывающий сбалансированность собранных требований. Кроме того, Borland CaliberRM поддерживает режим кол¬лективной работы над требованиями на протяжении всего жизненного цикла ПО (рис. 19.13).

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

 

 

Проектирование

Работу по проектированию при объектно-ориентированном подходе выполняет системный архитектор средствами языка UML. Задачи проектирования включают в себя две составляющие: разработку физической и логической структур. Логическое проектирование заключается в разработке классов для реализации их экземпляров — объектов. Для этого требуется подробное описание полей и методов классов, а также связей между ними. Статические диаграммы классов и пакетов являются основными в UML-проектировании, поскольку именно они обеспечивают генерацию шаблонов исходного кода для следующего этапа, кодирования. Динамические диаграммы предназначены для более полного понимания программистом логики функционирования системы и взаимоотношения классов. Для проектирования физической структуры, предназначены UML-диаграммы компонентов развертывания. Эти диаграммы описывают физическое размещение компонентов системы на аппаратном обеспечении заказчика.

Для повышения эффективности этапа проектирования нужно, чтобы программный пакет создания архитектуры был совместим со средством разработки кода. Если в качестве среды разработки выбрана Delphi, то системный архитектор может использовать пакет Together производства Borland, полностью совместимый с этой средой (рис. 19.14).

 

. Кодирование и тестирование

Разработка исходного кода ведется в интегрированной среде быстрой разработки, такой как Delphi или Microsoft Visual Studio, на основе полученных от системного архитектора UML-диаграмм и автоматически сгенерированного по этим диаграммам шаблонам исходного кода.

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

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

Тестирование подразделяется на три стадии: автономное, комплексное и си¬стемное.

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

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

Системное, или оценочное, тестирование завершает этап проверки системы, то есть завершает испытание системы в целом при помощи независимых тестов. Независимость тестов является существенным обстоятельством. Заказчик при приемке может настоять на проведении собственного системного тестирования. Для случая, когда сравниваются характеристики нескольких систем (например, когда требуемое ПО поставляется несколькими изготовителями), такая процедура известна как сравнительное тестирование.

Важные критерии тестирования:

□ для программы необходимо располагать набором тестовых данных, позволяю-щих установить, что программа работает правильно по любой ветви;

□ каждая инструкция программы должна быть выполнена по крайней мере один раз для заданного набора тестовых данных;

□ каждая ветвь в программе должна быть испытана хоть один раз с использова-нием набора тестовых данных.

Вектор напряженийpn является физическим объектом, имеющим длину, направление и точку приложения. В этом смысле он обладает векторными свойствами. Однако этому объекту присущи некоторые свойства, не характерные для векторов. В частности, величина и направление вектора напряжений зависят от ориентации вектора n нормали бесконечно малого элемента поверхности dF. Совокупность всех возможных пар векторовп, рn в точке определяет напряженное состояние в данной точке. Однако для полного описания напряженного состояния в точке нет необходимости задавать бесконечное множество направлений вектораn, достаточно определить векторы напряжений на трех взаимно перпендикулярных элементарных площадках. Напряжения на произвольно ориентированных площадках могут быть выражены через эти три вектора напряжений. В дальнейшем лектор умышленно меняет ориентацию координат. Так, что ось Z – продольная ось бруса, а X и Y – координаты любой точки его поперечного сечения.

Проведем через точку М три взаимно перпендикулярных плоскости с векторами нормалей, направления которых совпадают с направлениями координатных осей. Элементарные площадки образуем дополнительными сечениями, параллельными исходным плоскостям и отстоящими от них на бесконечно малые расстояния dx, dy, dz. В результате в окрестности точки М получим бесконечно малый параллелепипед, поверхность которого образована элементарными площадками dFх=dydz, dFн==dxdz, dFя=dxdy. Векторы напряжений px,py, pz, действующие на элементарных площадках, показаны на рис. 5.

Разложим каждый вектор напряжений на составляющие вдоль координатных осей (рис. 6). На каждой площадке действует одно нормальное напряжение, , , где индекс обозначает направление вектора нормали к площадке и два касательных напряжения с двумя индексами, из которых первый указывает направление действия компоненты напряжения, второй—направление вектора нормали к площадке.

 

Рис. 5. Равновесное состояние бесконечно-малого параллелепипеда

 

Рис.6. Компоненты тензора напряженного состояния

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

 

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