Eclipse в eBay: Часть 1. Оптимизация Eclipse для архитектуры eBay

Участник проекта объясняет, как eBay использует Eclipse и специальные плагины для создания гигантского аукционного сайта нового поколения

Первоначально платформа Eclipse стала популярной как интегрированная среда разработки (integrated development environment - IDE) для Java. Важным фактором успеха стала архитектура плагинов Eclipse. Существует множество популярных плагинов, и их очень легко создавать. Эти две особенности делают Eclipse идеальным для систем со специализированными архитектурами, таких как eBay. В данной статье, первой в серии из двух статей, посвященных использованию Eclipse в eBay, мы рассмотрим архитектуру eBay и то, как eBay приспособил к своей архитектуре Eclipse. Хотя статья посвящена eBay, содержащиеся в ней сведения можно использовать для применения Eclipse в архитектуре любой системы.

Майкл Галпин, инженер по программному обеспечению, Vitria Technology

Майкл Галпин (Michael Galpin) имеет учёную степень по математике в Калифорнийском Технологическом институте. Он является Java-разработчиком с конца 90-х гг. и работает инженером по программному обеспечению в Vitria Technology, в Саннивейл, Калифорния.



20.02.2009

Данная статья предполагает элементарное знакомство с Eclipse. Мы будем говорить о среде eBay Development Environment (EDE), которая основана на Eclipse V3.2 и требует JDK V5.0 или более позднюю версию (см. Ресурсы). Некоторое знакомство с Web-разработкой, включая HTML, JavaScript и CSS, полезно, но не обязательно.

Eclipse представляет собой IDE Java с обширной системой плагинов. Версия Eclipse V3.3 (Europa) принесла с собой ряд специализированных дистрибутивов Eclipse. В их числе Eclipse для разработчиков Java и Eclipse для разработчиков Java EE. Кроме того, можно использовать Eclipse C/C++ Development Toolkit (CDT) и Eclipse PHP Development Toolkit (PDT).

Все эти дистрибутивы состоят из основной платформы Eclipse и некоторого набора плагинов. В этом все преимущество Eclipse. Все обычные инструменты разработки Java, которые большинство пользователей считает составной частью Eclipse, на самом деле – просто плагины. Если вы занимаетесь разработкой РНР, вам не нужно возиться с компоновщиком Java. Java, C++ и PHP — все это языки программирования и, следовательно, сами требуют широких знаний. Однако ваша конкретная система ограничена некоторыми требованиями, довольно узкими по сравнению с другими системами, которые могут использовать тот же язык программирования.

Почему бы не оптимизировать свою среду разработки под собственную систему? Именно такой подход предлагает Eclipse, и eBay использует этот принцип для создания EDE на основе Eclipse. Рассмотрим архитектуру eBay, чтобы понять ее специфические требования и разобраться, как eBay удовлетворяет их при помощи Eclipse.

Архитектура eBay

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

История

eBay открылся в 1995 году под именем AuctionWeb. Первоначально сайт был написан на Perl. По мере роста его ядро (back end) переписали на C++, а интерфейсную часть (front-end) – с применением XSL. В конце 1990-х годов использование XSL для генерации HTML считалось очень прогрессивным. В 1998 году eBay стал публичной компанией и продолжал экспоненциальный рост.

Постоянно нарастающее давление трафика вынудило в 2001 году переписать ядро eBay на языке программирования Java. Архитектура интерфейса не изменилась. Архитектура Java+XSL имеет внутреннее название «архитектура V3»: под V1 подразумевается Perl, а под V2 — C++/XSL. Архитектура V3 оказалась наращиваемой в широких пределах, что позволило eBay вырасти до своего современного размера и стать одним из самых посещаемых сайтов в мире. Это не просто сайт с большим трафиком, а сайт с интенсивной обработкой транзакций, на котором миллионы людей выставляют на продажу, делают ставки и покупают товары в десятках стран по всему миру. Конечно, ни одно решение не идеально, и для системы, которая постоянно растет, такой как eBay, это особенно справедливо.

Проблемы

С точки зрения ядра архитектура V3 решила некоторые самые сложные из проблем, какие только может создать Web-приложение. С точки зрения данных eBay можно описать как гигантское число часто производимых операций записи и считывания с чрезвычайно низким допуском ошибки или противоречий. Ведь мы имеем дело с деньгами людей. Ошибку в поисковом индексе или сборщике новостей мало кто заметит, но когда дело касается ставки на аукционе, большинство людей сразу забьет тревогу. Аналогично, можно допустить труднопредсказуемое время доставки сообщения e-mail или IM, но о том, что их ставка на аукционе перебита, люди ходят узнавать немедленно. Архитектура V3 решила эти невероятно трудные проблемы, но у такого успешного сайта, как eBay, существует и множество других, не менее трудных проблем, связанных с интерфейсом.

Например, при таком гигантском, расползающемся Web-сайте становятся достаточно сложными, казалось бы, тривиальные вещи вроде управления всеми изображениями. Допустим, нужно произвести чистку и удалить старую картинку. Как узнать, используется ли она? В системе на базе XSL придется производить поиск по миллионам строк текста. Но и этого недостаточно, так как XSL может легко соединять строки, так что результирующая строка, отображающая эту картинку, за один проход может и не обнаружиться. Это справедливо не только для XSL, но и для любой архитектуры интерфейса, основанной на тексте/сценариях.

Изображения – только вершина айсберга. В процессе модернизации eBay становится все тяжелее и тяжелее использовать таблицы стилей (Cascading Style Sheets - CSS). Часто бывает эффективнее не включать CSS в страницу, а поместить в отдельный внешний файл, чтобы браузер мог сохранять их в буфере. Еще лучше, если можно многократно использовать эти файлы CSS для разных страниц, опять же получая преимущество от буфера браузера. Но как быть, если нужно изменить стиль на единственной странице? Что нужно сделать, чтобы это не повлияло на другие страницы? Приведенный выше сценарий можно представить и для JavaScript.

Вы когда-нибудь перемещали страницы на Web-сайте? Нужно гарантировать, что будут изменены все ссылки на эту страницу. Теперь представьте себе, что это надо сделать для сайта размеров eBay. Опять же, все упирается в массовый текстовый поиск любых изменений строк, соответствующих данной ссылке.

Помните время, когда пошла мода на порталы? Во многом это были предтечи современных машапов — вроде локальных машапов. Типичные страницы портального типа содержат элементы других страниц, а это, как правило, означает CSS и JavaScript. Теперь представьте возможность конфликта: одно и то же название стиля может использоваться в нескольких местах, но с разными значениями. Аналогично, в нескольких местах могут быть определены одни и те же функции или переменные JavaScript. Даже и без конфликтов можно столкнуться с дублированием, когда в точности одни и те же данные (CSS или JavaScript) появляются на странице два, три или более раз. В старой архитектуре интерфейса eBay на основе XSL решить подобные проблемы нелегко. Приходится опираться только на текстовый поиск.

Наконец, возможно, самая большая проблема — локализация. Глобальный Web-сайт, такой как eBay, переводится более чем на 30 языков. Даже при поверхностном рассмотрении ясно, что система на основе XSL требует локализации каждого файла XSL. Вы можете с улыбкой подумать: «Достаточно использовать свойства файлов, такие как ResourceBundles в Java». Подумайте еще раз. А как вы учтете склонение по родам в разных языках? Или даже окончания при числительных, такие как «1 ставка» и «2 ставки». А как локализовать изображения? Как локализовать то, что требует разной разметки (вроде размещения ссылки внутри предложения)?

Все эти факторы вынудили eBay локализовывать каждый файл XSL отдельно. Не забудьте, что XSL – это код, так что нечто тривиальное вроде замены текста на странице требует выпуска нового кода и его установки на тысячи серверов.

Немногие Web-сайты справляются с подобными проблемами. Это неудивительно, так как ни одна среда open source не решает всех этих проблем. eBay пришлось создавать чрезвычайно интеллектуальный, чрезвычайно специализированный инструмент.

V4

Точно так же, как он решил серьезные проблемы масштабируемости ядра при помощи архитектуры V3, eBay взялся за решение проблем масштабируемости интерфейса при помощи новой архитектуры, названной V4. Подход архитектуры V4 состоит в том, что все, что должно отображаться в интерфейсе, должно быть представлено в ядре строго типизированными объектами Java. На странице используется изображение? Значит у этой страницы должен быть Java-объект. Если это изображение нужно удалить, то сделать это не проще и не труднее, чем удалить любой другой класс Java. То же относится к ссылкам, CSS и JavaScript. V4 не использует сервлетов или JSP для создания HTML. Вместо этого, актуальный HTML DOM представляется на языке Java, так что CSS и JavaScript можно связать между собой на сервере.

А как насчет труднейшей из всех проблем — проблемы контента? Система контента V4 уникальна и мощна. Она использует собственный язык на основе XML для создания контрактов контента. Слово контракт выбрано не случайно. Контракты определяют, какого рода данные требуются для создания любой вариации того или иного элемента (единицы) контента. Например, определенный элемент может содержать целое число и строку на английском (например, "Raymond has 4 cars"), но на другом языке требует двух целых и строки. Может быть несколько вариантов склонения по родам и по числам. Контракт определяет все это на языке XML. Затем контракт реализуется для каждого из языков, поддерживаемых определенным приложением/страницей/компонентом. И, конечно же, он должен быть представлен как строго типизированный объект Java, для использования которого требуется предоставление всех динамических данных (вроде "Raymond" и "4" в приведенном выше примере). Так как все выражено строго типизированными Java-объектами, все устанавливается на этапе компиляции. Если разработчик приложения не указал в своем коде Java эти два параметра, код не скомпилируется.

Такое Java-представление всего и вся гладко выглядит на бумаге. Однако можно вообразить, какого труда будет стоить создание нового класса Java в каждом случае использования изображения или сценария JavaScript на странице. Вот здесь-то и приходит на помощь Eclipse.


Eclipse и V4

Теперь, когда мы оценили пространство проблем и знаем желаемое решение, можно рассмотреть, как Eclipse помог eBay в реализации этого решения. Значительную часть описанного выше кода — код для представления изображений, ссылок, стилей и сценариев JavaScript — можно считать шаблонами, по крайней мере частично. Это общая проблема всех сред разработки. Они требуют написания некоторого кода, который в основном нужен только самой среде. Некоторые среды используют для этого объекты-посредники или манипулируют байт-кодом. Это может усложнить отладку или ухудшить производительность. Среда V4 использует другой метод — инструменты генерации кода. Если для представления JavaScript нужен объект Java, хорошо иметь этот объект уже готовым, но еще лучше, если для него вообще не надо писать никакого кода. Пусть этим занимается плагин Eclipse.

Использование генераторов кода

В редакциях для Java и Java EE Eclipse интенсивно использует генераторы кода. Как правило, они выполнены в виде мастеров, генерирующих многочисленные артефакты. Например, если нужно использовать Java EE, можно воспользоваться мастером New Dynamic Web Application. Он создаст структуры каталогов и файл web.xml для вашего Web-приложения, так что его можно легко зашить в файл WAR и передать в Web-контейнер. Генераторы кода, созданные eBay, служат аналогичной цели: они создают за разработчика код шаблонов, позволяя ему сосредоточиться на коде самого приложения, или, как ее часто называют, на «бизнес-логике» этого приложения.

Рассмотрим пару плагинов генерации кода Eclipse, созданных eBay в качестве инструментов для среды V4.

JavaScript

JavaScript — это язык для Web, и в V4 он чрезвычайно важен. Среда V4 позволяет писать сценарии JavaScript обычным способом, но с некоторыми мелкими ограничениями. Она использует объектно-ориентированный синтаксис, стандартный для JavaScript, но не обязательный. Она использует также синтаксис комментированного кода из проекта open source JsDoc для определения дополнительных метаданных о классах JavaScript. Эти два элемента позволяют создать класс JavaScript reference (JsRef) для каждого класса JavaScript. Это класс Java, на который можно ссылаться внутри любого дерева V4 DOM. Рассмотрим пример (листинг 1).

Листинг 1. Класс JavaScript eBay
vjo.needs("vjo.samples.classes.Person");
vjo.type("vjo.samples.classes.HelloPerson")
.props({
     /**       
       * @return boolean
       * @access public
      */
     helloPerson:function(){
          var person1 = new vjo.samples.classes.Person();
          person1.setName("John");
          alert("Hello " + person1.getName());
          return false;
     }
});

Различные конструкции vjo.* имитируют конструкции декларации файла классов Java. Аннотации JsDoc гарантируют строгую типизацию, которую JavaScript обеспечить не может. Это позволяет плагину Eclipse сгенерировать JsRef для класса JavaScript, как показано в листинге 2.

Листинг 2. Соответствующий JsRef
package vjo.samples.classes;

import com.ebay.dsf.resource.pattern.js.JsType;
import com.ebay.dsf.spec.component.BaseComponentSpec;
import com.ebay.dsf.aggregator.jsref.internals.JsCmpMeta;
import com.ebay.dsf.spec.component.IComponentSpec;
import vjo.bootstrap.VjBootstrap;
import com.ebay.dsf.resource.pattern.js.JsResource;
import com.ebay.dsf.aggregator.jsref.JsObj;
import com.ebay.dsf.aggregator.jsref.JsFunc;
import com.ebay.dsf.jstojava.codegen.JsRefGenerator23;
import com.ebay.dsf.resource.pattern.js.IJsResourceRef;
import com.ebay.kernel.CodeGenerated;
/*
 Generator: JsRefGenerator23 version: 2.3
 Generated: Mon Jan 28 11:01:13 PST 2008
 Source URL: file:/D:/Views/v4flash/v4samplecode/VjoSample/src/vjo/samples/
                                                     classes/HelloPerson.js
*/

/** 

 * <pre>vjo.needs("vjo.samples.classes.Person");
 * vjo.type("vjo.samples.classes.HelloPerson")
 * .props({
 *      //*       
 *        * @return boolean
 *        * @access public
 *       //
 *      helloPerson:function(){
 *           var person1 = new vjo.samples.classes.Person();
 *           person1.setName("John");
 *           alert("Hello " + person1.getName());
 *           return false;
 *      }
 * });
 * </pre>
*/


@com.ebay.dsf.resource.utils.CodeGen(JsRefGenerator23.class)


@com.ebay.dsf.jstojava.codegen.JsRefGeneratorVersion(2.3)

public class HelloPersonJsr extends JsObj  implements CodeGenerated{
private static final long serialVersionUID = 1L;

public static final JsResource RESOURCE = JsResource.viaName("HelloPerson");
public static class ResourceSpec extends BaseComponentSpec{
     public static final IJsResourceRef REF = jsRef(RESOURCE, JsType.DefOnly);
     private static volatile IComponentSpec s_instance;
     public static IComponentSpec getInstance() {
     if (s_instance != null) {
               return s_instance;
     }
     synchronized (
     ResourceSpec.class) {
               if (s_instance == null) {
                         s_instance = new ResourceSpec();
               }
     }
     return s_instance;
     }
     
     private 
     ResourceSpec() {
          addJsRef(jsRef(RESOURCE, JsType.DefOnly));
          addDependentComponent(VjBootstrap.ResourceSpec.getInstance());
          addDependentComponent(vjo.samples.classes.PersonJsr.ResourceSpec.
		                                                    getInstance());
     }
}

protected HelloPersonJsr(JsCmpMeta cmpMeta, boolean isProto) {
     super(cmpMeta, isProto);
}

/** 

 * @return boolean
@access public
 * @jsfunc helloPerson
 * 
 * function () {
 *     var person1 = new vjo.samples.classes.Person();
 *     person1.setName("John");
 *     alert("Hello " + person1.getName());
 *     return false;
 * }
*/


public static final  JsFunc<Boolean> helloPerson(){
JsFunc<Boolean>  func = new JsFunc<Boolean> (getInstance(), 
                                              "helloPerson",true,true);
return func;
}
public static final JsCmpMeta META = new JsCmpMeta("vjo.samples.classes.HelloPerson", 
                                          "HelloPerson", ResourceSpec.getInstance());
     private static volatile HelloPersonJsr s_instance;

private static HelloPersonJsr getInstance(){
     addResourceSpec(ResourceSpec.getInstance());if (s_instance !=null){
          return s_instance;
     }
     synchronized (HelloPersonJsr.class){
          if (s_instance == null) {
               s_instance = new HelloPersonJsr(META,false);}return s_instance;}
}
}

Все это упрощает разработчику использование инструментов Eclipse. Достаточно просто щелкнуть правой кнопкой мыши на файле JavaScript, чтобы сгенерировать необходимый код Java, как показано на рисунке 1.

Рисунок 1. Использование Eclipse для генерации JsRef
Использование Eclipse для генерации JsRef

Затем можно программно использовать JsRef в коде Java. Это облегчает передачу JavaScript в код Java. Например, можно вызвать приведенный выше сценарий JavaScript для проверки формы, когда пользователь нажимает кнопку (листинг 3).

Листинг 3. Передача клиентских событий на сервер
DButton button = new DButton("Hello Person - click me");
button.add(EventType.CLICK, HelloPersonJsr.helloPerson());

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

JavaScript — это просто один из элементов Web-приложения, которым структура eBay V4 и плагины Eclipse, помогающие разработчикам применять V4, управляют определенным образом. Другой важный пример — это CSS.

CSS

Подход V4 к использованию JavaScript состоит в том, чтобы сохранить стандартный JavaScript, только обращаться к нему посредством кода Java. Подход к использованию CSS немного иной. JavaScript – это сложный язык программирования. Таблицы CSS тоже могут быть сложными, но определенно не в той степени, что JavaScript. При использовании CSS файлы CSS служат только отправной точкой. Они применяются для создания класса Java, который используется на этапе выполнения для генерации CSS. Первоначальный файл CSS можно выбросить. Именно класс Java становится частью элемента управления исходным кодом, тогда как на самом деле это внедренный файл JavaScript, а JsRef сгенерирован Eclipse на системе разработчика или системе компоновки кода при пуске в эксплуатацию. И все же, возможно, по каким-то соображениям визуальной проверки, часто кажется более естественным начать с CSS.

Итак, eBay построил плагины Eclipse для работы с CSS и для «самообеспечения» создания Java-CSS (JCSS). В листинге 4 приводится пример типичного файла CSS.

Листинг 4. Файл CSS
* {
     margin: 0;
     padding: 0;
}

body {
     font-size: 100.01%;
     font-family: Verdana,sans-serif;
     padding: 10px;
     text-align: center;
}

h1, h2, h3, h4, h5 {
     font-family: Georgia,serif;
}

h1 {
     color: #9A351D;
     background-color: transparent;
     margin: 1em 0;
}

h3 {
     font-size: .9em;
}

div h3 {
     color: #58B;
     text-transform: uppercase;
     font-size: .7em;
}

div h3:before {
     content: "by";
     font-style: italic;
     text-transform: none;
     color: #000;
     display: block;
     margin-bottom: 1em;
}

h4 {
     text-align: center;
     font-style: italic;
     color: #666;
     margin: 2em 0 0 0;
     font-size: .7em;
     font-weight: normal;
}

.footer {
     color: #999;
     font-size: .5em;
     font-family: Verdana,sans-serif;
     font-weight: normal;
}

Опять же, можно щелкнуть правой кнопкой в Eclipse, чтобы получить доступ к плагину JCSS и создать класс JCSS (рисунок 2).

Рисунок 2. Использование плагина JCSS
Using the JCSS plug-in

Это ведет к созданию класса Java (листинг 5).

Листинг 5. Соответствующий класс JCSS
package com.ebay.css.example;

import com.ebay.dsf.css.CssClassConstant;
import com.ebay.dsf.javatocss.JCssDef;
import com.ebay.dsf.javatocss.JCssStyleRule;
import com.ebay.dsf.javatocss.prop.BackgroundColor;
import com.ebay.dsf.javatocss.prop.Display;
import com.ebay.dsf.javatocss.prop.FontStyle;
import com.ebay.dsf.javatocss.prop.FontWeight;
import com.ebay.dsf.javatocss.prop.TextAlign;
import com.ebay.dsf.javatocss.prop.TextTransform;
import com.ebay.kernel.CodeGenerated;


/*
 Generator: class com.ebay.dsf.csscodegen.generator.def.JCssDefGenerator 
                                                            version: 1.0
 Generated: Mon Jan 28 17:37:36 PST 2008
 Source: com.ebay.css.example cover.css
*/

/**
 * <pre>
* {margin:0; padding:0}
body {font-size:100.01%; font-family:Verdana, sans-serif; padding:10px; 
                                                     text-align:center}
h1, h2, h3, h4, h5 {font-family:Georgia, serif}
h1 {color:#9a351d; background-color:transparent; margin:1em 0}
h3 {font-size:0.9em}
div h3 {color:#58b; text-transform:uppercase; font-size:0.7em}
div h3:before {content:"by"; font-style:italic; text-transform:none; 
                        color:#000; display:block; margin-bottom:1em}
h4 {text-align:center; font-style:italic; color:#666; margin:2em 0 0 0; 
                                   font-size:0.7em; font-weight:normal}
.footer {color:#999; font-size:0.5em; font-family:Verdana, sans-serif; 
                                                   font-weight:normal}
 * </pre>
 */
public class CoverJCssDef extends JCssDef implements CodeGenerated {

     private static final String SCOPE_NAME = "";

     public interface Clz {
          /**
           * <pre>
           * .footer {color:#999; font-size:0.5em; 
           font-family:Verdana, sans-serif;
		                                                      
		                   
	                         font-weight:normal}
           * </pre>
           */
          CssClassConstant footer_ = new CssClassConstant
          (SCOPE_NAME, "footer");
     }

     private static CoverJCssDef s_instance= new CoverJCssDef();

     public static CoverJCssDef getInstance(){
          return s_instance;
     }


     public static interface DEFAULT {

          public static final JCssStyleRule STYLE_RULE_1 = s_instance.rule()
               .select(any)
               .set( properties()
                    .margin("0")
                    .padding("0"));

          public static final JCssStyleRule STYLE_RULE_2 = s_instance.rule()
               .select(body)
               .set( properties()
                    .fontSize("100.01%")
                    .fontFamily("Verdana, sans-serif")
                    .padding("10px")
                    .textAlign(TextAlign.CENTER));

          public static final JCssStyleRule STYLE_RULE_3 = s_instance.rule()
               .select(h1)
               .select(h2)
               .select(h3)
               .select(h4)
               .select(h5)
               .set( properties()
                    .fontFamily("Georgia, serif"));

          public static final JCssStyleRule STYLE_RULE_4 = s_instance.rule()
               .select(h1)
               .set( properties()
                    .color("#9a351d")
                    .backgroundColor(BackgroundColor.TRANSPARENT)
                    .margin("1em 0"));

          public static final JCssStyleRule STYLE_RULE_5 = s_instance.rule()
               .select(h3)
               .set( properties()
                    .fontSize("0.9em"));

          public static final JCssStyleRule STYLE_RULE_6 = s_instance.rule()
               .select(div.desc(h3))
               .set( properties()
                    .color("#58b")
                    .textTransform(TextTransform.UPPERCASE)
                    .fontSize("0.7em"));

          public static final JCssStyleRule STYLE_RULE_7 = s_instance.rule()
               .select(div.desc(h3.pseudoBefore()))
               .set( properties()
                    .content("\"by\"")
                    .fontStyle(FontStyle.ITALIC)
                    .textTransform(TextTransform.NONE)
                    .color("#000")
                    .display(Display.BLOCK)
                    .marginBottom("1em"));

          public static final JCssStyleRule STYLE_RULE_8 = s_instance.rule()
               .select(h4)
               .set( properties()
                    .textAlign(TextAlign.CENTER)
                    .fontStyle(FontStyle.ITALIC)
                    .color("#666")
                    .margin("2em 0 0 0")
                    .fontSize("0.7em")
                    .fontWeight(FontWeight.NORMAL));

          public static final JCssStyleRule STYLE_RULE_9 = s_instance.rule()
               .select(any.with(Clz.footer_))
               .set( properties()
                    .color("#999")
                    .fontSize("0.5em")
                    .fontFamily("Verdana, sans-serif")
                    .fontWeight(FontWeight.NORMAL));
     }
}

Этот файл содержит наши определения стилей. В целях разделения ответственности для реализации CSS в документе HTML используется отдельный класс. Конечно, этот класс тоже генерируется плагином Eclipse (рисунок 3).

Рисунок 3. Использование плагина для генерации реализатора CSS
Использование плагина для генерации реализатора CSS

В листинге 6 приведен пример сгенерированного плагином реализатора класса.

Листинг 6. Сгенерированный реализатор CSS
package com.ebay.css.example;

import com.ebay.css.example.CoverJCssDef;
import com.ebay.dsf.css.CssClassConstant;
import com.ebay.dsf.csscodegen.generator.realizer.CssRealizerGenerator;
import com.ebay.dsf.csscommon.BaseCssRealizer;
import com.ebay.dsf.html.dom.BaseCoreHtmlElement;
import com.ebay.dsf.resource.pattern.css.CssResource;
import com.ebay.kernel.CodeGenerated;


/*
 Generator: class com.ebay.dsf.csscodegen.generator.realizer.CssRealizerGenerator 
                                                                     version: 2.0
 Generated: Tue Jan 29 15:20:08 PST 2008
 Source: com.ebay.css.example.CoverJCssDef
*/

/**
 * <pre>
* {margin:0; padding:0}
body {font-size:100.01%; font-family:Verdana, sans-serif; padding:10px; 
                                                      text-align:center}
h1, h2, h3, h4, h5 {font-family:Georgia, serif}
h1 {color:#9a351d; background-color:transparent; margin:1em 0}
h3 {font-size:0.9em}
div h3 {color:#58b; text-transform:uppercase; font-size:0.7em}
div h3:before {content:"by"; font-style:italic; text-transform:none; 
                       color:#000; display:block; margin-bottom:1em}
h4 {text-align:center; font-style:italic; color:#666; margin:2em 0 0 0; 
                                    font-size:0.7em; font-weight:normal}
.footer {color:#999; font-size:0.5em; font-family:Verdana, sans-serif; 
                                                     font-weight:normal}
 * </pre>
 */
@com.ebay.dsf.resource.utils.CodeGen(CssRealizerGenerator.class)
public class CoverCssr extends BaseCssRealizer implements CodeGenerated {

    /** Answers the actual text this realizer was genned from */
    public static final String gentext = 
"* {margin:0; padding:0}\n"
+ "body {font-size:100.01%; font-family:Verdana, sans-serif; padding:10px; 
                                                     text-align:center}\n"
+ "h1, h2, h3, h4, h5 {font-family:Georgia, serif}\n"
+ "h1 {color:#9a351d; background-color:transparent; margin:1em 0}\n"
+ "h3 {font-size:0.9em}\n"
+ "div h3 {color:#58b; text-transform:uppercase; font-size:0.7em}\n"
+ "div h3:before {content:\"by\"; font-style:italic; text-transform:none; 
                           color:#000; display:block; margin-bottom:1em}\n"
+ "h4 {text-align:center; font-style:italic; color:#666; margin:2em 0 0 0; 
                                   font-size:0.7em; font-weight:normal}\n"
+ ".footer {color:#999; font-size:0.5em; font-family:Verdana, sans-serif; 
                                                   font-weight:normal}\n"
;
    public static final CssResource src = CssResource.viaDef(
	                                CoverJCssDef.getInstance());
    public static final Classes classes = new Classes() ;
    public static final Utils utils = new Utils() ;

    /**
     * <pre>
     * .footer {color:#999; font-size:0.5em; font-family:Verdana, sans-serif; 
	                                                      font-weight:normal}
     * </pre>
     */
    public static final class Classes {
        private Classes() { /* prevent instantiation */ }
        private static final CssClassConstant s_footer = new CssClassConstant("footer");
        /**
         * <pre>
         * .footer {color:#999; font-size:0.5em; font-family:Verdana, sans-serif; 
		                                                      font-weight:normal}
         * </pre>
         */
        public final CssClassConstant footer = s_footer;
    }

    public static final class Utils {
        private Utils() { /* prevent instantiation */ }
        /**
         * <pre>
         * .footer {color:#999; font-size:0.5em; font-family:Verdana, sans-serif; 
		                                                      font-weight:normal}
         * </pre>
         */
        public Utils addClass_footer(final BaseCoreHtmlElement element) {
            addCssClass(element, Classes.s_footer);
            return this;
        }

        /**
         * <pre>
         * .footer {color:#999; font-size:0.5em; font-family:Verdana, sans-serif; 
		                                                      font-weight:normal}
         * </pre>
         */
        public Utils setClass_footer(final BaseCoreHtmlElement element) {
            setCssClass(element, Classes.s_footer);
            return this;
        }

    }

}

Реализатор облегчает присвоение стилей любому визуальному элементу. Иначе, можно зарегистрировать одно или более определений JCSS на странице, чтобы определить стили по умолчанию. В листинге 7 приводятся примеры обоих этих методов.

Листинг 7. Использование JCSS
// Create a div, attach a style to it
DDiv footer = new DDiv();
CoverCssr.utils.addClass_footer(footer);
// create DOM, register the CSS for it
HtmlDisplayer2 doc = new HtmlDisplayer2(footer);
doc.registerCss(CoverJCssDef.getInstance());

Опять же, мы получаем преимущества наличия пространства имен (пакет JCSS), так что на этапе исполнения наша таблица CSS не будет конфликтовать ни с какой другой CSS. Мы получаем это преимущество, сохраняя возможность использовать «стандартную» CSS. Ключ — в применении плагина Eclipse для наведения моста между CSS и JCSS.

Итак, картина прояснилась. V4 нужны все эти строго типизированные конструкции, и Eclipse значительно облегчает их создание и работу с ними. Мы упомянули наиболее проблематичный тип ресурса в V4 — контент. Давайте посмотрим, как Eclipse помогает и здесь.

Контент

Система контента V4 опирается на конструкции контента. У них свой собственный язык XML, но опять же, только применение плагина Eclipse позволило создать для этих конструкций интуитивно-понятный редактор (рисунок 4).

Рисунок 4. Структурированный редактор контента V4
Структурированный редактор контента V4

Нам нужно сгенерировать код Java для представления контракта контента, и снова Eclipse готов сгенерировать его для нас (рисунок 5).

Рисунок 5. Генерация кода Java для контракта контента
Генерация кода Java для контракта контента

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

Мы видели, что во многих сценариях eBay использует преимущества плагинов Eclipse для генерации кода. Это не единственный тип плагинов, написанных eBay. Рассмотрим некоторые другие типы, используемые eBay, и задачи, которые они решают.

Другие плагины V4

Система V4 предлагает также уникальные способы исполнения приложений и их отладки благодаря специфическому способу использования Java для представления всех элементов Web-страницы. Это может обеспечить существенный выигрыш в производительности труда, облегчая разработку приложений и их отладку.


Исполнение Web-приложений из Eclipse

Вам никогда не хотелось иметь возможность исполнять Web-страницу без необходимости устанавливать и запускать или перезапускать Web-сервер? Благодаря плагинам eBay V4 для Eclipse такая возможность появилась (рисунок 6).

Рисунок 6. Исполнение Web-страницы как "дервлета"
Исполнение Web-страницы как дервлета

Вы спросите, что такое дервлет (dervlet)? Как следует из названия, это аналог сервлета. Среда V4 позволяет использовать их в качестве самонастраиваемых классов для быстрого создания прототипа и тестирования Web-приложений. Это все равно, что иметь класс, главный метод которого используется для тестирования других классов из пакета. Все что нужно, это нажать правую кнопку мыши и выбрать Run as dervlet. Очевидно, можно выбрать и Debug as dervlet и исполнить код по шагам, как любой другой исполняемый код. За сценой плагин Eclipse запускает встроенную версию контейнера Jetty servlet, затем открывает в Web-браузере URL, обслуживаемый Jetty.

Этот плагин Eclipse облегчает отладку приложения V4 в процессе разработки. Среда V4 и Eclipse могут пойти еще дальше, облегчая отладки приложения в процессе эксплуатации.


Отладка рабочего приложения посредством Eclipse

Среда V4 — это компонентная среда. Когда все представлено в виде классов Java, естественным следующим объектно-ориентированным шагом является инкапсуляция этих классов, чтобы они работали совместно как один компонент. Это позволяет создавать многократно используемые компоненты и может еще больше повысить производительность труда разработчика. Глядя на Web-страницу eBay (рисунок 7), вы смотрите на набор компонентов V4. Это отличный способ не только быстрого создания приложений, но и анализа работающего приложения.

Рисунок 7. Страница eBay «под микроскопом»
Рисунок 6. Страница eBay под микроскопом

Видите все эти красные рамки? Каждая из них – компонент V4. Если навести курсор на любую из них, видно подлинное имя компонента. Если на странице что-то не так, очень легко понять, какой кусок кода (компонент) вызвал проблему. V4 идет еще на шаг дальше, помогая немедленно попасть в этот код. Обратите внимание на ссылки в голубых рамках. Разработчики eBay могут попасть прямо в Eclipse из любой рабочей страницы eBay V4. Попробуйте сделать нечто подобное с XSL, JSP или чем-то еще. Это достигается путем исполнения сервера listener из Eclipse. Listener — это еще один плагин, написанный eBay, который использует архитектуру eBay, чтобы помочь разработчикам использовать Eclipse.


Заключение

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

Ресурсы

Научиться

Получить продукты и технологии

Обсудить

Комментарии

developerWorks: Войти

Обязательные поля отмечены звездочкой (*).


Нужен IBM ID?
Забыли Ваш IBM ID?


Забыли Ваш пароль?
Изменить пароль

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Профиль создается, когда вы первый раз заходите в developerWorks. Информация в вашем профиле (имя, страна / регион, название компании) отображается для всех пользователей и будет сопровождать любой опубликованный вами контент пока вы специально не укажите скрыть название вашей компании. Вы можете обновить ваш IBM аккаунт в любое время.

Вся введенная информация защищена.

Выберите имя, которое будет отображаться на экране



При первом входе в developerWorks для Вас будет создан профиль и Вам нужно будет выбрать Отображаемое имя. Оно будет выводиться рядом с контентом, опубликованным Вами в developerWorks.

Отображаемое имя должно иметь длину от 3 символов до 31 символа. Ваше Имя в системе должно быть уникальным. В качестве имени по соображениям приватности нельзя использовать контактный e-mail.

Обязательные поля отмечены звездочкой (*).

(Отображаемое имя должно иметь длину от 3 символов до 31 символа.)

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Вся введенная информация защищена.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=40
Zone=Open source
ArticleID=371023
ArticleTitle=Eclipse в eBay: Часть 1. Оптимизация Eclipse для архитектуры eBay
publish-date=02202009