Долгие годы я был фанатом разработки под Windows, о чем немало писал в этот вот лучший компьютерный журнал всех времен и народов. Со временем я перешел под Mac OS и UNIX. Работая под макосью, я озадачился выбором тулзы для создания платформонезависмых программ. Что же предпочесть? Java? Mono? Слишком скучно. Я выбрал… Eiffel. И вот почему.

Eiffel

Все началось тогда, когда на глаза мне попалась публикация профессора питерского университета ИТМО Бертрана Мейера, по совместительству автора и создателя языка Eiffel. Язык этот вызвал у меня неподдельный интерес. Бертран Мейер считается одним из ведущих специалистов по объектным технологиям, более того, он стоял у их истоков и написал на эту тему множество книг. Но главная его заслуга заключается в создании ОО-языка с фичей контрактного программирования — Eiffel, который он разработал в далеком 1985 году. Этот язык обладает механизмом управления памятью (сборкой мусора), множественным наследованием, обобщенным программированием, статической типизацией, агентами (механизмами замыкания и лямбда-выражениями). В том же году Бертран организовал компанию ISE (Interactive Software Engineering), которая стала заниматься развитием и поддержкой языка, позже (1993 год) компания была переименована в Eiffel Software. Компания входит в список 500 самых успешных независимых бизнес-компаний в мире. При этом надо учитывать, что она занимается только развитием и продажей языка и инструментов программирования на нем. Отсюда следует, что популярность этого языка довольно низкая. Ведь самые известные языки программирования — это открытые и/или свободные технологии: Python — open source продукт; C/C++ с момента своего рождения широко известны, благодаря мегакомпании, где были созданы, — AT&T (Bell Labs), которая распространяла их бесплатно (так как на тот момент не имела права продавать софт); Pascal, Lua — результаты исследований университетских групп и потому свободные... С другой стороны, коммерческие языки из-за своей закрытости мало распространены, исключением служит разве что Objective-C, который был лицензирован сначала NeXT, затем, по наследству, Apple.

Eiffel используется в серьезных разработках, от которых зависят жизни людей: в аэрокосмической отрасли, в банковско-финансовой сфере… Клиентами Eiffel Sofware являются Boeing, Rosenberg и EMC.

В оригинальной реализации языка (от Eiffel Software, которую мы будем рассматривать в дальнейшем в статье) код, проходя промежуточный уровень, преобразуется в текст на языке C и только потом компилятор последнего создает двоичный код исполняемой программы; именно такой подход и позволил добиться платформонезависимости языка. Между тем существуют реализации, генерирующие двоичный код непосредственно из языка Eiffel. Например, этим занимается open source проект Visual Eiffel, однако он прекратил свое развитие еще в 2007 году. Кроме языка, программисту поставляется мощная интегрированная среда разработки — EiffelStudio. Эта система включает интегрированные инструменты для работы с кодом, присущие современным средам программирования, библиотеки на все случаи жизни и другое. Очевидно, что Бертран, следуя за своим старшим коллегой — Никлаусом Виртом, применил в своем языке выразительность, присущую языкам последнего: Pascal, Ada, Oberon. И это прекрасно! Однако самая главная вкусность языка заключается в возможности контрактного программирования. Устоялось мнение, что программный продукт не может быть свободен от багов, если, конечно, это не «Hello, World». Между тем разработчики Eiffel утверждают, что созданное с помощью их средств ПО может быть таким. Для подтверждения они приводят механизм контрактного программирования. Его основа (что ясно из названия) — взаимодействие по контракту, подобное бизнес-отношениям. Так, клиент (client), запросив что-то у исполнителя (supplier), обязуется выполнить предусловия, тогда как исполнитель должен осуществить постусловия. Например, клиент должен быть уверен, что таблица не пустая и ключевое поле не пустое, тогда он может обновить таблицу, вставив элемент, ассоциированный с данным ключом. С другой стороны, исполнитель должен записать полученный элемент, ассоциированный с переданным ключом, в таблицу, также в том случае, если она полностью заполнена, он ничего не должен делать. Получается двойная проверка. Это позволяет удобным образом документировать исходники, для чего в EiffelStudio предусмотрены специальные средства. Предусловия или постусловия могут содержаться в одном классе, который для этого и создан. Это так называемые инварианты. Инвариант может содержать одно или более условий. Они полезны при регрессионном тестировании и управлении конфигурацией. Таким образом, контрактное программирование представляет собой следующую реализацию (надстройку) над привычным ООП: объекты имеют более тесные связи в программной среде. Из этого разговора вытекает следующая фича EiffelStudio под названием AutoTest. Все знакомы с техникой разработки программного обеспечения через тестирование, введенной Кентом Беком в 1999 году, применяя которую программист перед написанием рабочего кода программы должен написать тест для этого кода. Все это хорошо и проходило на ура. Но с развитием технологий подходы должны улучшаться. В связи с необходимостью создания более сложного программного обеспечения программисту надо больше концентрироваться на центральной задаче разрабатываемого приложения, а не кода, тестирующего его. Механизм AutoTest выполняет за программиста процедуру создания тестов, таким образом, он автоматически проводит регрессионное тестирование, избавляя программиста от лишних забот. Нулевые указатели — бич разработки объектно ориентированного программного обеспечения. Используя язык Eiffel, разработчик может не беспокоиться о них. То есть если car равен nullptr, то следующий код не приведет к краху приложения (и концу света) car->drive();. Компилятор Эйфеля гарантирует, что car не будет равен nullptr ни при каких обстоятельствах. Поэтому разыменование происходит без проблем, а компилятор выдаст предупреждение о том, что произошло маленькое недоразумение. Такая возможность языка называется Void Safety. Какое бы количество новых и разнообразных поточных фреймворков и библиотек ни выходило для таких процедурных языков, как C/C++, C# или Java, проблема параллельных вычислений остается острой, способной оставить разработчика без сна в глубокой отладке. Современность и будущее требуют параллельной обработки, но она содержит гонки, дид- и лайфлоки, трудности в отладке и другие прелести. Но и в этом случае Eiffel может упростить нам жизнь! Благодаря расширению языка — SCOOP (Simple Concurrent Object-Oriented Programming) Eiffel позволяет разрабатывать устойчивые, не подверженные конкурентным ситуациям многопоточные приложения. Таким образом, EiffelStudio позволяет вести «бесшовную» разработку. Это значит, что для проектирования (в том числе создания UML-диаграмм), построения пользовательского интерфейса, собственно написания Eiffel-кода, ведения документации, тестирования и развертывания готового приложения используется одна среда разработки, которая содержит все перечисленные инструменты, позволяя разработчику не пользоваться внешними средствами.

Сила в библиотеках

Чтобы увидеть мощь Eiffel, взглянем на стандартные библиотеки языка. В общей сложности их 12 штук, в большинстве своем они независимы от платформы, хотя и есть исключения. Самая важная библиотека — базовая EiffelBase, она содержит базовые структуры и алгоритмы. Короче говоря, эта либа включает в себя классы, составляющие ядро Eiffel-системы: они служат для арифметических операций и обработки исключений. EiffelVision 2 — кросс-платформенная графическая библиотека, позволяющая строить расширенный пользовательский интерфейс для приложений, работающих в любой мало-мальски распространенной операционной системе: Windows, UNIX, Linux, VMS и других. Следующие две либы платформозависимые — работают только в Windows. WEL (Windows Eiffel Library) основывается на Win32 API (отсюда зависимость) и позволяет строить приложения, используя средства последней: окна, диалоги, элементы управления, присущие Win-приложениям, а также многое другое. EiffelCOM упрощает разработку приложений, использующих компонентную модель Microsoft (что понятно из названия либы). Клиент-серверная библиотека EiffelNet позволяет обмениваться структурами данных между компьютерами по сети. EiffelTime реализует разностороннюю работу с датой и временем. При включении библиотеки EiffelStore в приложение оно получает возможность работы с данными различных баз данных через драйвер ODBC, среди них: Oracle, SQL, Ingres, Sysbase. EiffelThread реализует в приложении поддержку многопоточности, при этом оно остается независимым от аппаратного и программного окружения и в равной степени поддерживается во всех Windows NT, UNIX системах на процессорах x86/64, SGI рабочих станциях и суперкомпьютерах Cray. Eiffel2Java создает интерфейс между программой, написанной на Eiffel, и Java-приложением, таким образом, из первой можно вызвать вторую. С помощью EiffelWeb можно на языке Eiffel разрабатывать динамические HTML-страницы, содержащие формы, обрабатываемые CGI-скриптами. Библиотеки EiffelLex и EiffelParse используются для создания текстовых и синтаксических анализаторов. Они могут быть применены для разработки трансляторов самых разных видов, в том числе компиляторов и интерпретаторов. И это только те библиотеки, которые входят в стандартную поставку Эйфеля! Можно пополнить этот набор, купив необходимую либу у Eiffel Software, или попытать счастья, поискав в сообществе Open Source.

Инсталляция EiffelStudio

EiffelStudio — оригинальная среда программирования на языке Eiffel. Для ее установки предлагаются два варианта: версия EiffelStudio — Enterprise Evolution Edition и версия под лицензией GPL. Средства разработки я предпочитаю ставить под свободной лицензией, потому что испытательного срока мне хватит вряд ли. При таком раскладе удобнее установить EiffelStudio из терминала. Но сначала... Перед установкой EiffelStudio надо установить Xcode — сомневаюсь, что его у тебя нет, а вот тулзы командной строки для него могут отсутствовать. В таком случае перейди на сайт Apple в раздел Downloads for Apple Developers (чтобы зайти туда, понадобится активный Apple ID), затем, проведя небольшой рисеч, скачай оттуда Command Line Tools (OS X 10.9) for Xcode, последняя версия тулз на момент написания статьи была Late December 2014.

Веб-страница скачивания тулз командной строки
Веб-страница скачивания тулз командной строки

В результате на жесткий диск твоего мака будет слит пакет — образ диска для установки утилит командной строки. Установка стандартная и не представляет трудностей. Обрати внимание, после установки тулз надо хотя бы раз запустить Xcode, чтобы принять условия лицензии; если этого не сделать, в будущем по «непонятной» причине может не работать компиляция кода из EiffelStudio. После этого необходимо установить юниксовую оконную подсистему X11. В настоящее время она не входит в стандартную поставку операционной системы, однако имеется в пакете XQuartz, разрабатываемом Apple. Забегая вперед: этот пакет нужен для прорисовки оконного интерфейса Eiffel IDE, вместе с ним устанавливается терминал XTerm, который предпочтительно использовать во время установки языка и студии. Скачай XQuartz с сайта. Он представляет собой обычный пакет для установки. Последняя на момент сдачи статьи версия — 2.7.7. Вдобавок надо установить MacPorts, представляющий собой репозиторий UNIX-приложений для OS X. Среди них мы найдем EiffelStudio. Чтобы установить MacPorts, надо скачать содержащий его пакет по следующей ссылке. Я предполагаю, что у тебя последняя на данный момент версия яблочно-десктопной операционной системы. Содержимое пакета «вываливается» стандартным образом. Наконец подготовительные этапы выполнены, и мы приступаем к установке языка и системы Eiffel. Открой предварительно установленный XTerm и введи в него: sudo port install eiffelstudio. Запустится процесс установки, будут скачаны все необходимые библиотеки и разрешены зависимости. Все это тянется довольно долго, поэтому ты всяко успеешь «откинуться на спинку кресла», а то и заварить чайку. Когда процесс будет завершен, надо произвести некоторые настройки, без них ничего работать не будет. Коротко говоря, если в XTerm ты используешь bash (по умолчанию так и есть), надо внести изменения в его профиль. Для этого, оставаясь в XTerm, открой профиль для редактирования, введя и выполнив: cat >> ~/.bash_profile. Затем в открытый файл надо вбить четыре следующие строки:

export ISE_PLATFORM=macosx-x86-64 
export ISE_EIFFEL=/Applications/MacPorts/Eiffel_13.11
export GOBO=$ISE_EIFFEL/library/gobo/svn
export PATH=$PATH:$ISE_EIFFEL/studio/spec/$ISE_PLATFORM/bin:$GOBO/../spec/$ISE_PLATFORM/bin

Теперь, перейдя на последующую строку, нажатием заверши ввод. Чтобы изменения вступили в силу, надо перезагрузить профиль bash, для этого выполни: source ~/.bash_profile. Установка и конфигурирование завершены, поздравляю! Теперь можно запустить EiffelStudio, для этого в командной строке введи estudio. Если предварительные шаги выполнены верно, пошуршав винчестером, твой мак запустит студию! Обрати внимание, если запустить студию под рутом, она не будет функционировать. Запускать надо из-под обычного пользователя.

Копаемся в EiffelStudio

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

Окно создания/выбора проекта
Окно создания/выбора проекта

В верхней части окна отображаются две заготовки для проекта, в зависимости от операционной системы и установленных фреймворков их число может отличаться. Первая — Basic application (no graphics library included) — это заготовка для консольного приложения, вторая — Graphics application, multi platform, with EiffelVision 2 — создает оконный интерфейс, используя указанную библиотеку. По традиции создадим приложение первого типа, выбрав в этом списке соответствующий пункт и нажав активизировавшуюся кнопку Create. Откроется диалог задания имени проекта, его корневого класса и расположения. Так как во время создания каждого проекта EiffelStudio должна скомпилировать заголовочные файлы, убедись, что отмечен флажок Compile Project, далее жми OK. Появится вопрос, который предлагает подтвердить компиляцию заголовков.

Соглашаемся, жмем OK, EiffelStudio запустит процедуру трансляции. Взглянем на исходник Eiffel-программы (в панели Groups справа выбери пункт APPLICATION). Как и ожидалось, для консольного приложения он невелик:

note
        description : "consoleproject1 application root class"
        date        : "$Date$"
        revision    : "$Revision$"
class
        APPLICATION
inherit
        ARGUMENTS
create
        make
feature {NONE} -- Initialization
        make
                        -- Run application.
                do
                        --| Add your code here
                        print ("Hello Eiffel World!%N")
                end
end

Но выглядит странно. Рассмотрим основные моменты. После ключевого слова note следуют комментарии — описание проекта, и, соответственно, этот текст пропускается компилятором. С ключевого слова class начинается описание класса. Поскольку Eiffel поддерживает множественное наследование, в блоке inherit может содержаться несколько родительских классов. В области create описываются конструкторы класса, их может быть несколько, впрочем, это неудивительно. После ключевого слова feature находятся описания свойств и методов. Следующее за ним слово в фигурных скобках (в данном случае NONE) определяет видимость свойств и методов класса по отношению к другим частям программы. Так, слово NONE эквивалентно private из C++, то есть означает закрытые члены. Также на этом месте могут находиться слова: ANY — эквивалент public (открытые члены) и CHILD — protected (доступ только для детей класса, включая его самого). Эти же ключевые слова могут использоваться при осуществлении наследования классов (модификаторы доступа для ключевого слова inherit). В примере выше в области feature находится описание процедуры make (конструктора). Тело процедуры начинается с ключевого слова do, а заканчивается по традиции паскаля словом end. Как видно, точка с запятой в Eiffel не требуется, однако этот символ не запрещается. Внутри процедуры вызывается функция print, которая традиционно выводит в консоль переданный в параметре текст. Однострочные комментарии здесь начинаются с символа двойного тире (--). После обзора кода самое время его запустить на выполнение, для этого финализируй проект, выбрав в меню Project пункт Finalize. Последовательно запустятся шесть этапов компиляции и финализация, которая предполагает непосредственный перевод C-кода в машинные команды. Текущий проект выполнится незаметно, а в консоли отобразится текст «Hello Eiffel World!».

Результат нескольких запусков программы
Результат нескольких запусков программы

После финализации проекта в папке с ним образуется исполняемый файл с расширением *.e.

Файлы

Не отходя от кассы, на основе текущего проекта посмотрим на работу с файлами. Сперва в подкаталоге с проектом (там, где файл application.e) создай текстовый файл input.rtf (OS Х не любит txt) с любым содержимым. В коде в начале блока feature объяви две переменные:

input_file: PLAIN_TEXT_FILE
output_file: PLAIN_TEXT_FILE

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

create input_file.make_open_read ("input.rtf")
create output_file.make_open_write ("output.rtf")

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

            from
                input_file.read_character
            until
                input_file.exhausted
            loop
                output_file.put (input_file.last_character)
                input_file.read_character
            end

Ключевое слово from знаменует блок инициализации. После выполнения метода read_character свойство last_character объекта input_file будет содержать прочитанный символ. Блок until содержит условие прекращения выполнения цикла. В нашем случае, пока свойство exhausted объекта, представляющего читаемый файл, не станет истинным (то есть пока файл не закончится), будет выполняться тело, следующее за меткой loop. Здесь происходит запись считанного ранее символа в файл вывода и чтение следующего символа из файла ввода. В конце программы методом close надо закрыть оба файла:

input_file.close
output_file.close

Программа готова, протестируй. Если все верно, то в папке с исполняемым файлом появится текстовый файл вывода, содержащий текст, введенный в файл ввода.

Оконный интерфейс

Под занавес взглянем на вторую заготовку приложения в EiffelStudio — Graphic application, multi-platform, with EiffelVision 2. В момент создания, проходя по шагам визарда, указываем имя и расположение будущего проекта, отмечаем минимальный набор визуальных элементов: главное меню, панель инструментов и прочее.

Основным классом приложений, использующих библиотеку EiffelVision, является EV_APPLICATION. Кроме того что этот класс инициализирует оконную подсистему, используемую на платформе, под которую ты компилируешь проект (по умолчанию в большинстве операционных систем используется GTK), вдобавок этот класс организует главный цикл для обработки системных событий. Для своей работы EV_APPLICATION использует функциональность других классов, к примеру EV_TIMEOUT периодически (через определенный интервал) с помощью агентов вызывает события; с другой стороны, объект класса EV_COLOR занимается закраской виджетов и элементов. Главное окно представляется объектом first_window класса MAIN_WINDOW. Сначала в конструкторе make_and_launch вызывается метод default_create, который подготавливается EV_APPLICATION, затем в процедуре prepare создается и отображается окно (объект класса MAIN_WINDOW), наконец, методом launch приложение запускается на выполнение, в результате чего мы видим окно программы.

Заключение

Eiffel содержит огромное количество синтаксических отличий от стандартных (C-подобных) языков: объявление классов, переменных, методов, массивов; условные, циклические конструкции; предусловия, постусловия, классовые инварианты; взаимоотношения клиента и поставщика и многие другие языковые конструкции содержатся в Эйфеле. В совокупности все они призваны улучшить качество разрабатываемого программного обеспечения, сделав его более безопасным и надежным. Эти шаги предприняты разработчиками языка для того, чтобы сделать работу прикладных программистов более продуктивной. Хотя статья подошла к концу, нам не удалось рассмотреть все фичи языка Eiffel. Оно и понятно, автор языка посвящает его описанию тома объемом в тысячу страниц! Язык мощный, сложный и при этом интересный. Он представляет собой новый взгляд на разработку программного обеспечения, новый инструментарий, свежий подход. Большую помощь в изучении языка, конечно же, оказывают примеры. Eiffel не стал в этом плане исключением, в папке Eiffel_Examples находится огромная подборка самых разных примеров: от консольного калькулятора до оконного веб-браузера. Eiffel непосредственно повлиял на множество современных языков, среди которых Delphi, C#, Ruby и другие. И хотя этот язык испытал на себе влияние паскаля, алгола, между тем он имеет такие конструкции, которые не встречаются в других языках программирования. Как утверждает Бертран Мейер, «C не тот язык, на котором программист должен писать приложения, влияющие на человеческие жизни, по крайней мере C должен выполнять лишь промежуточную роль, которая создается более безопасным и естественным языком».

  • Подпишись на наc в Telegram!

    Только важные новости и лучшие статьи

    Подписаться

  • Подписаться
    Уведомить о
    1 Комментарий
    Старые
    Новые Популярные
    Межтекстовые Отзывы
    Посмотреть все комментарии