« Сложные интерфейсы на javascript вместе Yahoo UI. Часть 20 | Наводим порядок в разработке ПО вместе с maven. Часть 2 » |
Наводим порядок в разработке ПО вместе с maven. Часть 1
Разработка программного обеспечения не самая простая наука. В общем объеме времени, отданного на создание продукта, написание, непосредственно, программного кода занимает далеко не самую большую долю. По мере увеличения сложности создаваемого продукта, финансовых и временных затрат, опережающими темпами растут затраты на анализ требований, планирование и организацию коллективной работы, на повышение качества. Почти года назад я написал несколько серий статей посвященных не, собственно, программированию, а различным технологиям и инструментам, поддерживающим процесс разработки ПО. Это были статьи, рассказывающие об управлении версиями документов (SVN и perforce), ведения списка задачи и багов в JIRA, хоть и поверхностно, но я прошелся и по вопросам тестирования веб-проектов с помощью badboy и jmeter. Сегодня пришло время раскрыть еще один инструмент (maven), с помощью которого ход разработки ПО должен стать более управляемым.Я не хотел бы начинать рассказ об maven и том, что это такое, с какой-то цитаты или описания maven взятого с wikipedia или сайта maven.apache.org. За сухой официальной формулировкой легко потерять главное – те конкретные плюсы, в реальных житейских ситуациях, которые вы получите, если будете использовать maven. Поэтому я расскажу об истории своих взаимоотношений с maven и о том, как он шаг за шагом завоевывал мое уважение. Хотя основная сфера моей деятельности связана с java и веб-технологиями и maven считается java-инструментом, но надеюсь что идеи, которые я расскажу, пригодятся и тем, кто работает с .net, php и другими языками и платформами (разработчики на flash/flex, внимание: maven уже идет к вам).
В далеком 2006 г я частенько посещал один из российских форумов, посвященных программированию и java в частности. Читая чужие вопросы и ответы, можно узнать много нового, а если уж попробовать отвечать на них, то рост знаний и навыков просто обеспечен. Единственная проблема была в том, что часто люди, у которых возникали затруднения с каким-то кодом, помимо словесного описания, что у них есть, что нужно получить, и что не работает, прикладывали к сообщениям форума и файлы с архивами своих проектов (точнее, каких-то выжимок из них). В этих архивах были файлы с исходными кодами на java и файлы проекта. Файлы проекта - это особые файлы, нужные для правильной работы IDE (intellij idea, eclipse, netbeans). В файлах проекта помимо всякой малополезной ерунды, вроде настроек шрифтов, списка открытых окон, были еще и сведения о библиотеках используемых для компиляции и запуска проекта. Я не открою большой тайны, если скажу что для java (да и для любого другого языка) характерно огромное количество библиотек, framework-ов, для web, для работы с базами данных, веб-сервисами. Библиотек этих много, много и их версий (ведь библиотеки развиваются). Теперь представим себе последовательность шагов, которые должен был бы выполнить я, чтобы просмотреть чей-то проект и быстро (ведь это все на голом энтузиазме) найти ошибку. Я загружаю архив, распаковываю его, смотрю содержимое и должен угадать на основании расширения файлов, то в какой ide его нужно открыть. Предположим, что это intellij idea, даже предположим, что у меня такая же версия intellij idea, как и та которой пользуется тот, кто отправил мне архив проекта. Если же проект сделан не в intellij idea, а, например, в eclipse, то я трачу время на то, чтобы создать проект и импортировать в него файлы. Импорт файлов не так прост, как кажется: давайте рассмотрим его на примере веб-приложения. Хотя есть sun-стандарт, описывающий то какая должна быть структура каталогов и файлов в конечном приложении (размещаемом на сервере), но вот стандарта того, как должны быть организованы (опять таки в каких каталогах и подкаталогах должны) исходные файлы проекта, такого стандарта нет. Если каталог с java-файлами худо-бедно, но во всех ide называется src, то каталог с выходными файлами может называться out, output, classes. По-разному могут называться и размещаться в каталоге проекта и папки, хранящие файлы графических ресурсов, css-файлов и файлов с javascript-ом и шаблоны html-страниц. Но сложности, связанные с необходимостью создания нового проекта и “раскладки” файлов из старого проекта по новым правилам, кажутся совсем незначительными, если мы подумаем о зависимостях проекта, т.е. о том какие библиотеки нужны для его работы.
Итак, я загрузил файл проекта, запустил его на компиляцию и получаю множество ошибок вида: “не найдена библиотека X, не известен класс Y”. Когда создавался проект в IDE, то программист определил в составе проекта некоторую логическую абстракцию – библиотеку, то как ее понимает IDE. В состав этой библиотеки входит множество файлов с расширениями jar (реальные архивы библиотек java). Эти файлы загружены программистом на свой компьютер, например, в папку “c:\java_libs”. Таким образом, библиотека в понятии IDE – это множество путей вида: “c:\java_libs\hibernate.jar ”. А у меня на компьютере нет этих библиотек. Даже если я открыл настройки чужого проекта и увидел там файл с именем hibernate.jar, то это мне ничем не поможет т.к. библиотека hibernate имеет множество версий, и я просто не знаю, какой файл добавить к проекту чтобы он скомпилировался и запустился. Напоминаю, что я решил потратить не больше 10 минут на то, чтобы помочь кому-то разобраться с его ошибкой, я не будут тратить свое время на совершение рутинных подготовительных операций. Даже если забыть об истории с форумом и моим желанием разобраться в чужом коде, то представьте ту же ситуацию, когда на работе вы создаете в коллективе некоторый java-продукт. Т.к. над проектом работает несколько человек и у каждого из них своя предпочитаемая среда разработки (одному нравится eclipse, другому idea) с разными настройками, с разными путями к файлам библиотек и проектов. Следовательно, мы не можем хранить в CVS файлы проекта – они слишком “личные”. Но ведь этот проект должен регулярно извлекаться из репозитория, компилироваться, развертываться на тестовом сервере, чтобы затем команда тестеров могла регулярно проверять сделанную вами за день работу и завести в jira десяток-другой багов. Следовательно, в репозитории должна храниться информация о проекте, о том какие модули входят в его состав, какой модуль зависит от какого – и все это в максимально абстрактном виде. Т.е. нам нужен такой стандарт представления проекта, который бы не зависел от среды разработки (читай, поддерживался бы ими всеми). Та же беда и с библиотеками, нужными для компиляции проекта: где их хранить? Единственное приемлемое решение – поместить их также внутрь cvs-репозитория. Таким образом, java-проект представляет в репозитории максимально самодостаточную единицу: он содержит и файлы с исходным кодом и библиотеки нужные для их компиляции и некий супер-скрипт, который выполняет компиляцию проекта и подготовку его к развертыванию на “боевом” веб-сервере.
Возникает естественный вопрос: неужели до сих пор не появился какой-то инструмент решающий эту задачу. Задачу представления проекта, и составляющих его модулей в форме не зависимой от конкретной среды разработки, инструмента содержащего средства записать сценарий как нужно компилировать и собирать проект. Инструмент позволяющего вынести все используемые для разработки библиотеки в отдельное хранилище (например, отдельный сервер) и позволяющего условно сказать: “для сборки проекта нужна библиотека hibernate версии 3.2.1”. Инструмент, известный, популярный, такой чтобы, если у вас возникнет какая-то проблема, связанная с его применением, то можно было бы положиться на развитое community. Желательно, чтобы проект был opensource, чтобы включал в себя api, позволяющее создавать собственные расширения, плагины. Итак, первое лицо maven – это инструмент для декларативного описания структуры проекта и нужных для его работы зависимостей (библиотек). Таким образом, после миграции проекта на maven, набор шагов по компиляции проекта будет следующим: извлечь из cvs исходные коды проекта и файл проекта maven, запуск проекта на сборку, в ходе которой maven найдет правильный порядок сборки модулей образующих проект (по ходу их зависимостей друг от друга), загрузит со специального сервера нужные для компиляции библиотеки (если их еще нет на вашем компьютере) и завершит компиляцию проекта. Важно, что один и тот же файл будет использоваться всеми участниками команды, как программистами, так и тестерами. Тестеры ни вообще ничего не знают о структуре проекта и его зависимостях, они знают только то, что если запустить вот этот maven-файл на выполнение то, само собой получится исполняемый файл, который можно и проверять на предмет ошибок.
Теперь перейдем к “немножко попрограммировать” и я опишу процесс создания проекта с помощью maven. Предполагается, что вы загрузили с сайта http://maven.apache.org архив с maven-ом. Т.к. maven появился уже достаточно давно, то в настоящий момент есть две ветви его разработки: 1x (больше не развивается) и 2x. Прогресс при переходе от версий 1x к 2x был очень большой так, что я не вижу ни какой причины, почему вам следует использовать maven 1. Сам я уже довольно давно “сижу” на maven 2.0.9 и единственная причина, почему я не перешел недавно вышедшую 2.0.10 так это моя лень и то, что в девятке меня все устраивает. Распаковав архив с maven, нужно создать пару переменных среды окружения для удобства последующей работы с maven из командной строки. Сначала создадим переменную M2_HOME, указывающую на каталог с maven. Еще в самый конец переменной PATH я добавил путь к каталогу %M2_HOME%/bin. Проверьте работоспособность maven, набрав в командной строке “m2 -v”, и в ответ вы должны получить строку “Maven version: 2.0.9.”. Значит, maven установлен и работает, а мы идем дальше. Проект в терминологии maven – это каталог со стандартизированной структурой. Хоть, путь и де де-факто, но maven предлагает стандарт именования каталогов с исходными кодами, каталога, где находятся ресурсы, и каталога, куда будут помещены результаты компиляции проекта. В корне каталога проекта находится файл pom.xml. За счет того, что maven создан в соответствии идеологии “соглашения превыше конфигурирования”, то размер файла pom.xml может быть совсем маленьким. Например, если вы решили изменить имена и структуру каталогов проекта, то это придется указать в pom-файле, а если решили следовать правилам maven, то ничего делать не нужно. Более того, в maven есть понятие archetypes (или шаблонов проектов). Количество различных программ, которые можно написать на java бесконечно, однако количество типов этих приложений довольно ограничено: обычные java, web-приложения, ejb-модули, ear-приложения – это первое что приходит на память. Более того, maven настолько популярен, что разработчики различных известных и не очень framework-ов, например, spring, jsf, tapestry, seam создали для maven новые виды archetypes. Следовательно, вы получаете возможность “быстрого старта” с maven и archetype. Более подробно об archetypes, какие они бывают и откуда их брать я расскажу попозже, сейчас давайте создадим “ручками” maven-style структуру каталогов. Пологая, что мой проект называется testartifact1 (почему в названии присутствует слово artifact опять требует уточнений – но позже), я создал каталог testartifact1, а в нем подкаталоги src и target. В первом из них будут храниться исходные коды проекта, а во второй будет помещаться результат компиляции. Т.к. современная разработка ПО не мыслима без тестов, то в каталоге src были созданы еще два подкаталога: main и test. В первом из них хранится код приложения, а во втором тесты для него. Это еще не все: кроме исходного кода в виде файлов java, проект часто включает ресурсы: это могут быть файлы properties с различным настройками и конфигурационными переменными нужным для запуска создаваемой программы, или это могут быть файлы картинок для интерфейса. В любом случае каталог main состоит из двух подкаталогов: java и resources. Такое же деление характерно и для каталога test. В конечном счете, я получил дерево каталогов, показанное на рис. 1.
Теперь нужно наполнить эти каталоги содержимым. Так я создал простенький класс HelloBean, единственным назначением которого будет “приветствовать пользователя” (имя пользователя передается как параметр конструктора класса). Файл размещен в каталоге “src/main/java/blackzorro”:
package blackzorro;
public class HelloBean {
private String name;
public HelloBean(String name) {
this.name = name;
}
public String sayHello() {
return "Hello, " + name;
}
}
public class HelloMaven {
public static void main(String [] args) {
System.out.println(new HelloBean("Maven").sayHello());
}
}
public class TestHelloBean extends TestCase {
public void testSimpleMessage() {
String message = new HelloBean("Maven 2").sayHello();
Assert.assertEquals("Test Hello Machine", "Hello, Maven 2", message);
}
}
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>blackzorro</groupId>
<artifactId>testartifact1</artifactId>
<packaging>jar</packaging>
<version>1.0</version>
<name>Simple Maven 2 Artifact</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.2</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
В следующий раз я продолжу рассказ об maven, и мы познакомимся с тем, как maven позволяет декларативно записать зависимости проекта от других артефактов, как работают транзитивные зависимости, что такое области видимости зависимостей и многое другое.
« Сложные интерфейсы на javascript вместе Yahoo UI. Часть 20 | Наводим порядок в разработке ПО вместе с maven. Часть 2 » |