Три из шести больших статей номера посвящены разным проблемам инженерии программного обеспечения. И хотя эту часть номера нельзя считать полноценной тематической подборкой (слишком широка тематика, отсутствует приглашенный редактор), свой обзор я начну с этих трех статей.
Первая из них называется «Бездефектные системы: да, мы можем добиться этого!» («Faultless Systems: Yes We Can!») и написана Жаном-Реймондом Эбриэлем (Jean-Raymond Abrial, Swiss Federal Institute of Technology, Zurich, Switzerland ).
Статья умышленно названа провокационным образом. Все знают, что бездефектные системы невозможны, иначе их давно бы производили. И что такое «дефект»?
Автор призывает не считать себя очередным гуру, пытающимся представить читателям некую универсальную панацею. Он стремится всего лишь напомнить несколько простых фактов и идей, которые могут пригодиться разработчикам программного обеспечения.
При возникновении ужасной ситуации проявления дефектов в программной системе (а эта ситуация действительно ужасна для разработчиков программных систем) можно было бы попытаться радикально изменить положение вещей, но это никогда не получается. Философия автора состоит в поэтапном применении некоторых простых приемов, которые в совокупности позволяют, в конце концов, глобально облегчить ситуацию.
Прежде всего, для создания корректных систем необходимо строго определить способ оценки корректности. В этом состоит основное назначение документа, описывающего требования к системе. Такой документ должен быть тщательно написан до того, как предпринимаются какие-либо шаги к разработке системы.
Однако в конце фазы документирования требований к будущей системе отсутствуют гарантии их удовлетворения. Ошибкой является немедленный переход к фазе программирования. Программирование состоит в создании некоторого фрагмента формального текста, указывающего компьютеру, как следует выполнять определенные задачи. Но целью разработчиков является построение системы, в которой будет присутствовать много таких взаимодействующих фрагментов. Разработчикам нужно понять, как будет функционировать система в целом, и для этого необходимо выполнить ее полное моделирование, включая программное обеспечение и среду его выполнения.
Моделирование обеспечивает формализацию мысленного представления будущей системы, но, кроме того, позволяет доказать, что это представление обеспечивает определенные свойства, установленные неформальным образом в документе, в котором устанавливаются требования к системе. Для выполнения этой общей задачи симуляции и доказательств используется простой формализм дискретных систем переходов. Другими словами, компоненты будущих систем всегда представляются посредством последовательности состояний, тесно сплетенных со скачкообразными переходами, называемыми также событиями.
С модельной точки зрения нет существенной разницы между человеком, нажимающим на некоторую кнопку, запуском или остановкой мотора или фрагментом программного обеспечения, выполняющим некоторые задачи, все эти события происходят в одной и той же системе. Каждая из этих активностей является некоторой дискретной системой переходов, работающей сама по себе и взаимодействующей с другими активностями, как это показано на рис. 1. Эта простая парадигма оказывается исключительно полезной. В частности, задача доказательства частично решается путем демонстрации того, что переходы в любом компоненте не нарушают некоторые общие свойства системы. Эти свойства называются инвариантами, а соответствующие доказательства – доказательствами сохранности инвариантов.
Рис. 1. Три взаимодействующие дискретные системы переходов
Чтобы доказать, что программа будет отвечать требованиям, нужно конструировать эту программу путем моделирования проблемы. Требуемые свойства должны закладываться в модель с самого начала, и корректность результирующей программы должна следовать из корректности модели.
На вопрос, внедрены ли в практику обсуждаемые в статье простые и известные идеи, автор отвечает умеренно положительно: бездефектные системы существуют. Однако требуется ряд дополнительных шагов, чтобы эти идеи были более широко осознаны и приняты к действию. И на это направлен европейский проект Deploy.
Авторами следующей статьи являются Сью Блэк, Пол Бока, Джонатан Боуен, Джейсон Горман и Майк Хинчи ( Sue Black, University of Westminster, Paul P. Boca, Hornbill Systems, Ltd, Jonathan P. Bowen, Museophile Ltd, Jason Gorman, Codemanship Ltd, Mike Hinchey, University of Limerick, Ireland). Статья называется «Формальные и быстрые методы: выживут наиболее пригодные?» («Formal Versus Agile: Survival of the Fittest?»).
Инженерия программного обеспечения как отдельная дисциплина прошла в своем развитии несколько фаз. Барри Боем (Barry Boehm) в своем недавнем обзоре отмечает:
- переход от инженерии аппаратного оборудования в 1950-е гг. к кустарному программированию в 1960-е гг.;
- введение формализованности и каскадного процесса (waterfall process) разработки программного обеспечения в 1970-е гг.;
- появление приемов повышения производительности и масштабируемости труда программистов в 1980-е гг.;
- введение параллельных процессов (concurrent process) разработки в 1990-е гг.;
- и возникновение быстрых (agile) процессов в 2000-е гг.
Каждая следующая фаза оказывалась развитием предыдущей фазы или реакцией на ее недостатки.
По утверждению авторов, появление формальных методов следует связывать с работами Чарльза Бэббиджа (Charles Babbage) и Ады Лавлейс (Ada Lovelace) над разностными и аналитическими машинами. Понятие корректности присутствовало уже на этой доэлектронной фазе – Бэббидж писал о «верификации формул, размещенных на технологических картах». Алан Тьюринг (Alan Turing) одним из первых воспользовался формальными методами в своей статье о корректности программ. Однако в терминологию инженерии программного обеспечения формальные методы вошли только в 1970-е гг.
По сравнению с формальными методами, методология быстрой разработки (agile methods) сравнительно нова. В 2001 г. в Agile Manifesto (http://agilemanifesto.org) были выдвинуты четыре основных принципа этого подхода:
реагировать на изменения важнее, чем следовать плану;
люди и их взаимодействие важнее процессов и средств;
работающее программное обеспечение важнее исчерпывающей документации;
сотрудничество с заказчиком важнее обсуждения условий контракта.
Возникновение методологии быстрой разработки можно считать реакцией на предыдущую громоздкую каскадную модель, которая фокусировалась на формализации требований заказчика в начале жизненного цикла программного продукта и доставке готового продукта в конце этого цикла, без каких-либо взаимодействий с заказчиком в середине цикла. Считалось, что быстрые методы лучше всего подходят для небольших групп умных программистов, но это слишком ограничивает область их применения.
Сравнительно недавно возникло направление исследований по интеграции формальных и быстрых методов. На прошедшем в 2003 г. Первом Южноевропейском симпозиуме по формальным методам обсуждались новые формальные методы, интеграция формальных и быстрых методов и проблемы оценки «быстроты» формальных методов.
Последняя статья тематической подборки представлена Бертраном Мейером, Арно Фивой, Илинкой Чупа, Андреасом Лейтнером, Йи Веем и Эммануэлем Стапфом (Bertrand Meyer, Arno Fiva, Ilinca Ciupa, Andreas Leitner, Yi Wei, ETH Zurich (Swiss Federal Institute of Technology), Zurich, Switzerland, Emmanuel Stapf, Eiffel Software) и называется «Программы, которые сами себя тестируют» («Programs That Test Themselves»).
Современные технические продукты – от самолетов, автомашин и промышленных установок до холодильников и кофеварок – регулярно тестируют сами себя во время эксплуатации. Цель этого тестирования состоит в том, чтобы выявлять возможные дефекты и избегать инцидентов, предупреждая пользователей о потребности технического обслуживания. Эта возможность самотестирования закладывается в подобные устройства с самого начала их разработки.
Чтобы добиться такой возможности, нужно придерживаться принципа проектирования в расчете на тестируемость продуктов. Этот принцип не всегда принимался. Например, в автомобилях раньше обычно отсутствовали какие-либо индикаторы (за исключением масломера), указывающие на неизбежность серьезных механических проблем. При желании узнать больше о состоянии своего автомобиля, нужно было обращаться к механику, который проверял все компоненты, не зная, что в действительности происходило во время эксплуатации. В отличие от этого, сегодняшние автомобили наполнены датчиками и индикаторами, производящими непрерывное тестирование и собирающими данные для технического обслуживания.
Хотя программное обеспечение не изнашивается физически в ходе эксплуатации, при его разработке требуется обширное тестирование (или другие формы верификации). Тем не менее, при проектировании программного обеспечения потребностям тестирования уделяется недостаточное внимание. Разработчики программного обеспечения оказываются глухи к урокам других областей производства: конструирование и верификация программного обеспечения являются, по существу, раздельными активностями, происходящими без учета взаимных потребностей. В результате тестирование, несмотря на совершенствование инструментальных средств, остается трудоемким процессом.
AutoTest – это набор инструментальных средств, которые автоматизируют процесс тестирования на основе использования программ, содержащих приспособления для своей собственной верификации. Эти приспособления имеют форму контрактов – спецификаций классов и их методов. Три основных компонента AutoTest затрагивают взаимосвязанные аспекты тестирования:
- Компонент генерации тестов автоматически создает и выполняет тестовые сценарии без потребности в тестовых сценариях и оракулах, подготовленных вручную.
- Компонент выявления тестов автоматически производит тестовые сценарии на основе сбойных ситуаций времени исполнения. Идея выявления тестов заключается в том, что некоторые важнейшие тестовые сценарии, по существу, невозможно придумать: они возникают, когда разработчик неформально испытывает программу в ходе ее разработки, но при ее выполнении происходят сбои. Сбойные ситуации представляют интерес, в частности, для будущего регрессионного тестирования, но обычно они не запоминаются. Разработчик устраняет проблему и движется дальше. На основе таких сбойных ситуаций компонент выявления тестов создает тестовые сценарии, которые могут воспроизводиться в будущих тестовых кампаниях.
- Компонент интеграции тестов, создаваемых вручную, поддерживает разработку таких тестов и управление ими. В отличие от первых двух компонентов, здесь используются общепринятые методы и отсутствуют какие-либо новшества, но обеспечивается единообразное автоматическое управление всеми тестами независимо от их происхождения.
Эти механизмы, исходно разработанные в ETH Zurich для исследовательских целей, теперь интегрированы в среду EiffelStudio. Доступен как их вариант с открытыми кодами, так и коммерческий продукт. Продолжаются исследования теории и методов.
Первую из трех статей, не входящих в тематическую подборку, – «Динамическая конфиденциальность при общественных видеонаблюдениях» («Dynamic Privacy in Public Surveillance») – написали Саймон Монкрайф, Света Венкатеш и Джеф Вест (Simon Moncrieff, Svetha Venkatesh, Geoff A.W. West, Curtin University of Technology).
В последние годы среди исследователей происходило много обсуждений относительно конфиденциальности и ее влияния на повсеместную компьютеризацию. Хотя никто не спорит с тем, что поддержка конфиденциальности в системах «вездесущного компьютинга» (ubiquitous computing) необходима, эта область все еще находится в зачаточном состоянии. В нескольких разрабатываемых системах этого рода защита конфиденциальности реализуется, но сравнительно редко речь идет о системах, в которых, по-видимому, впервые были использованы идеи вездесущного компьютинга, – в системах наблюдения. Наиболее известна система Privacy Protected Video Surveillance (Privacy Cam), разработанная Эндрю Сениором (Andrew Senior) и его коллегами.
Однако скоро эта ситуация изменится. Последние достижения в технологии видеонаблюдений, такие как цифровые сетевые видеокамеры и решения для длительного хранения видеоданных, расширяют область применения сред видеонаблюдения, превращая зафиксированные фрагменты видео в индексируемые данные, над которыми можно производить поиск. Это приведет к усилению посягательств на конфиденциальность, что, в свою очередь, повысит потребность в реализации средств поддержки конфиденциальности, контролирующих доступ к данным видеонаблюдений.
Рис. 2. Более всего телевизионные системы с закрытой передачей распространены в Великобритании
Для обеспечения эффективности такие средства должны быть интегрированы в общую конструкцию системы видеонаблюдений. Кроме того, политики конфиденциальности, применяемые в данным видеонаблюдений, должны динамически изменяться в зависимости от обстановки, чтобы обеспечивать максимальную конфиденциальность, не препятствуя достижению основных целей системы.
Авторами статьи «Применение принципов Парнаса на новом уровне: разработка декларативного языка» («Taking Parnas’s Principles to the Next Level: Declarative Language Design») являются Дэниэль Кук и Дж. Нельсон Раштон (Daniel E. Cooke, J. Nelson Rushton, Texas Tech University).
В течение последних 17 лет авторы экспериментировали с декларативными подходами к организации вычислений над нескалярными значениями. Эти исследования завершились теоретическими результатами, приведшими к разработке языка SequenceL. Этот язык полон по Тьюрингу и компактен (12 грамматических правил по сравнению c более чем 120 в языке Java), а семантика языка основывается на двух вычислительных законах CSP-NT: «потребляй-упрощай-производи» (consume-simplify-produce) и «нормализуй-преобразуй» (normalize-transpose). За это время было разработано около десятка интерпретаторов и четыре кодогенератора для компиляции SequenceL в C и C++. SequenceL-код всех примеров, приводимых в этой статье, был пропущен и проверен на интерпретаторе SequenceL.
Один из последних кодогенераторов использовался для приложений дистанционного наведения, навигации и управления в симуляторе NASA шатла и пилотируемого космического аппарата Orion. Генератор код SequenceL обеспечивает производительность рабочих программ, сравнимую с производительностью тех же приложений, написанных инженерами NASA вручную. В лучших случаях откомпилированные SequenceL-программы выполняются быстрее своих двойников на C; в худших – проигрывают им в производительности в 2,1 раза. В настоящее время один из интерпретаторов перерабатывается с целью генерации многопотокового кода для многоядерных процессоров.
В последнее время авторы принимают участие в эксперименте по переписыванию приложений одной из крупных компаний, специализирующейся на управлении производственными процессами. Этот эксперимент должен продемонстрировать повышение производительности труда программистов по причине декларативного характера SequenceL и рост эффективности приложений из-за параллельного выполнения программ.
В этой статье авторы сосредотачиваются на основных абстракциях SequenceL и на своей цели разработки языка на основе принципов сокрытия информации Дэвида Парнаса (David Parnas) (). Сокрытие информации в программных моделях основывается на двух принципах: обеспечении предполагаемых пользователей только информацией, требуемой для корректного использования модулей, и обеспечении разработчика только информацией, требуемой для корректной реализации модулей.
Демонстрируется, как эти принципы можно применить к разработке языка, обеспечивая программиста только всей информацией, требуемой для корректного использования языка, и обеспечивая разработчика языка только информацией, требуемой для его реализации. Первую цель можно считать успешно достигнутой, если программисту не требуется знание операционной семантики языка для его использования, а вторую – если язык не разрабатывается в расчете на конкретную область приложений. Для этого в SequenceL авторы фокусируются на абстракциях и усовершенствованиях, не основанных на семантике, таких как применение правил CSP-NT, которые позволяют описывать алгоритмы решения произвольной заданной проблемы.
По мнению авторов, при разработке SequenceL и принципов использования языка заметно быстрое продвижение к достижению этих целей. Если проводить аналогию, в статье обсуждается, как можно вести машину (использовать язык), не зная, что происходит под капотом (как производится процедурное решение требуемой проблемы).
Последняя большая статья номера называется «Обеспечение безопасности в небесах: мы верим в требования» («Securing the Skies: In Requirements We Trust»). Ее авторами являются Башар Нузейбех, Чарльз Хейли и Крейг Фостер (Bashar Nuseibeh, Charles B. Haley, Open University, Milton Keynes, UK, Craig Foster, NATS).
Нас регулярно засыпают сообщениями о происшествиях в системах безопасности: нарушение конфиденциальности информации, нарушение целостности объектов, недоступность продуктов и услуг. В ответ на это мы должны быстро выявить дефекты в своих системах, включая негодные пароли, отсутствие шифрования, взломанный контроль доступа, слабые организационные процедуры и т.д. И это вполне справедливо – в конце концов, безопасность направлена на защиту наших систем от нанесения ущерба.
Тем не менее, как считают авторы, чрезмерное внимание уделяется защите – механизмам реализации безопасности. Безопасность настолько же касается контекста функционирования систем, насколько самих этих систем. При разработке безопасного программного обеспечения наше внимание должно быть направлено на более масштабные системы, в которых программное обеспечение является лишь одной из частей. И именно в этих более крупных социотехнических системах возникают угрозы, и может быть причинен вред.
Социотехническая система включает аппаратуру, программное обеспечение и организационные структуры, в которых функционируют эти объекты. Она также включает людей, и разработчиков, и пользователей. Хотя компьютерные системы действительно подвергаются атакам, вред наносится пользователям и их активам, неважно, является ли этот вред физическим, финансовым, информационным или социальным. Поэтому организациям нужно понять, что они пытаются защищать, почему нужно защищать именно это, и какими могут быть последствия несовершенной защиты. Ответы на эти вопросы не только влияют на разработку программного обеспечения, но, что более важно, связывают эту разработку с пользователями, которые либо более всего выиграют от применения программной системы, либо понесут наибольший ущерб.
Набор видов деятельности, помогающих ответить на эти вопросы, называется инженерией требований к безопасности (security requirements engineering). Авторы разрабатывали инфраструктуру и соответствующие инструментальные средства для поддержки этих видов деятельности. В исследовании, проводимом Национальной службой воздушного движения Великобритании (UK-NATS), эта инфраструктура использовалась для анализа проблем безопасности в новой технологии, предназначавшейся для интеграции существующих систем управления воздушным движением.