Статьи

Гонка производительности: Ruby on Rails против JPA на OX3

Эта статья пытается продемонстрировать, что Java может быть более продуктивной, чем Ruby. Мы собираемся разработать то же приложение из статьи Rolling with Ruby on Rails Revisited ( часть 1 и часть 2 ), но с использованием POJO, аннотированных JPA и Model Driven Framework, в данном случае OpenXava . В результате с меньшим количеством кода и меньшим временем вы получаете более мощное приложение.

Рубин и рельсы: регрессивный каркас

Рубин на рельсах такой элегантный, такой легкий, такой продуктивный. Я не могу не читать и постоянно слышать эти комментарии. Например, статья Билла Уолтона «Возвращение к Ruby on Rails» говорит:

« Что бы вы подумали, если бы я сказал вам, что вы можете разрабатывать веб-приложения по крайней мере в десять раз быстрее с Rails, чем с типичной средой Java?»

К сожалению! В десять раз быстрее!

Что ж, после этих комментариев я решил изучить Ruby on Rails. Мне нужно знать истинный ключ производительности и счастья программиста.

После того, как я попробовал RnR, я обнаружил, что это очень классический фреймворк со старыми техниками:

  • Ruby — это динамически типизированный язык, такой как Smalltalk . Я предпочитаю статически типизированные языки.

  • Scaffolding — это пассивная генерация кода, как мастера IDE или AppFuse . Я предпочитаю активную генерацию кода или, что еще лучше, генерацию кода вообще нет.

  • Ориентированность на реляционную базу данных: генераторы кода и ActiveRecord продвигают концепцию сначала в таблицах, а затем в классах. Я предпочитаю более чистый OO, как Hibernate , JPA или даже ODBMS .

  • MVC : я ищу что-то более новое и лучшее, чем старая платформа MVC.

Проблема Java: разработчики Java

Производительность в мире Java — это культурная, а не техническая проблема. То есть это не ошибка Java, это наша ошибка, нам, разработчикам Java, необходимо спроектировать очень красивые архитектуры, применять везде шаблоны GoF , делать все повторно используемое, размещать 3 уровня во всех наших системах и использовать веб. услуги для всех. Мы не ищем простоты, поэтому не нашли ее. Но Java — это очень элегантный язык, который позволяет упростить подход к разработке программного обеспечения.

Производительность Java: другой путь

Способ повышения производительности — использование подхода, управляемого моделями. То есть разработать часть модели и только часть модели нашего приложения и использовать инфраструктуру для создания из нее всего приложения. MDA , OpenXava , Trails , NakedObjects , RomaFramework и JMatter являются примерами этого подхода.

Цель

Это основной экран нужного приложения:

Наша цель!

По сути, приложение должно делать три вещи:

  • Показать список всех рецептов.

  • Создание новых рецептов и редактирование существующих рецептов.

  • Присвойте рецепт категории (например, «десерт» или «суп»).

Ruby on Rails первый спринт

Первый шаг с использованием RnR — это создание нового проекта, из командной строки вы должны написать:

$ rails cookbook2 

Теперь вы должны создать и настроить базу данных.

Затем пришло время написать ваш первый код, в данном случае код SQL:

drop table if exists recipes;
drop table if exists categories;
create table categories (
id int not null auto_increment,
name varchar(100) not null default '',
primary key(id)
) engine=InnoDB;

create table recipes (
id int not null auto_increment,
category_id int not null,
title varchar(100) not null default '',
description varchar(255) null,
date date null,
instructions text null,
constraint fk_recipes_categories foreign key (category_id) references categories(id),
primary key(id)
) engine=InnoDB;

Очевидно, вы должны выполнить эти предложения в вашей базе данных.

И последний шаг — генерация кода Ruby, вам нужно всего лишь выполнить следующую команду в оболочке вашей ОС:

$ ruby script\generate scaffold recipe recipe
$ ruby script\generate scaffold category category

Да. У вас есть самая первая версия вашего RnR-приложения, готовая к запуску.

Да, очень мало работы, простая «создание таблицы» и выполнение мастера. Посмотрим результат.

Результат Rails

Это результирующее приложение:

Страница ввода новой категории

Новая категория добавлена!

Новая страница входа в рецептуру

Маленькая работа. Маленький результат


JPA на OX первый спринт

Продолжайте использовать OpenXava . Первый шаг с использованием OpenXava — создание нового проекта:

$ ant CreateNewProject.xml -Dproject=CookBook 

Теперь вы должны создать и настроить базу данных.

Затем пришло время написать ваш первый код, в данном случае код Java:

Recipe.java:

package org.openxava.cookbook.model;

import java.util.*;
import javax.persistence.*;
import org.openxava.annotations.*;

@Entity
@View(members="title; description; date; instructions")
public class Recipe {

@Id @GeneratedValue @Hidden
private Integer id;

@Required @Column(length=100)
private String title;

@Column(length=255)
private String description;

private Date date;

@Stereotype("HTML_TEXT")
private String instructions;

public Integer getId() {
return id;
}

public void setId(Integer id) {
this.id = id;
}

public String getTitle() {
return title;
}

public void setTitle(String title) {
this.title = title;
}

public String getDescription() {
return description;
}

public void setDescription(String description) {
this.description = description;
}

public Date getDate() {
return date;
}

public void setDate(Date date) {
this.date = date;
}

public String getInstructions() {
return instructions;
}

public void setInstructions(String instructions) {
this.instructions = instructions;
}

}

Category.java:

package org.openxava.cookbook.model;

import java.util.*;

import javax.persistence.*;

import org.openxava.annotations.*;

@Entity
public class Category {

@Id @GeneratedValue @Hidden
private Integer id;

@Required @Column(length=100)
private String name;

public Integer getId() {
return id;
}

public void setId(Integer id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

}

И последний шаг — создание схемы dababase, вам нужно только выполнить следующую цель ant из вашего проекта:

$ ant updateSchema

Да. У вас есть самая первая версия приложения OpenXava, готовая к запуску.

Да, очень мало работы, простые POJO и выполнение updateSchema. Посмотрим результат.

Результат OpenXava

Это результирующее приложение:

Обратите внимание, что пользователь может создавать, обновлять, удалять, генерировать PDF из списка, экспортировать список в Excel, упорядочивать по каждому столбцу, разбивать на страницы с поддержкой больших наборов результатов и фильтровать данные. Более того, вы можете развертывать напрямую, без кода, только выполняя цель ant, ваше приложение на портале JSR-168 , а внешний вид портлета OpenXava адаптируется к внешнему виду портала.

Это первое приложение, готовое к производству.

Маленькая работа, отточенный результат.

С философской точки зрения разница между RnR и OX заключается в том, что в RnR вы сначала пишете таблицы, а в OpenXava — сначала классы.


Контроллеры

Rails сгенерировал для вас логику контроллера для базового CRUD, вы можете увидеть его здесь:

RnR контроллер

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

То есть для контроллеров Rails использует сгенерированный код, в то время как OX использует общий код.

Вы можете узнать больше о контроллерах OX в вики OpenXava .

Добавление отношений

Для добавления отношения из категории в рецепт в Ruby вы должны написать следующий код в category.rb :

Тип отношений Rnr к рецепту

и этот в recipe.rb :

Рнр отношение рецепт к категории

Да, довольно просто. Но у вас есть больше работы. Вы должны отредактировать cookbook2 \ app \ views \ recipe \ _form.rhtml и добавить следующий код:

<p><label
for="recipe_category_id">Category</label><br/>
<%= select("recipe", "category_id", Category.find(:all).collect
{|c| [c.name, c.id] }) %></p>

Результат:

Рнр рецепт с категорией

Со своей стороны, в OpenXava вы должны определить отношения, используя JPA в Category.java :

@ManyToOne(optional=false) @DescriptionsList
private Category category;

и в Recipe.java :

 @OneToMany(mappedBy="category")
private Collection<Recipe> recipes;

И вам не нужно трогать любой HTML-подобный код. Ваше приложение покажет только это:

У вас есть ссылка для изменения или создания новых категорий отсюда.

Без добавления какого-либо дополнительного кода, если пользователь перейдет в модуль «Категория», он получит набор рецептов в каждой категории, как показано ниже:

На данный момент RnR-приложение по-прежнему не имеет этих функций, вам нужно написать несколько Ruby и HTML в коде, чтобы получить тот же эффект.

Основное различие между RnR и OX здесь заключается в том, что в OX вы не пишете HTML-подобный код, в действительности вы вообще не пишете код пользовательского интерфейса.

Расчет начального значения

Следующим шагом в учебнике по Ruby on Rails является создание начального значения для свойства. В RnR вы должны отредактировать код контроллера, чтобы добиться этого. Давай увидим это:

Вы изменяете метод new и update, добавляя строку:

@recipe.date = Time.now

Эквивалентом в OX является добавление аннотации @DefaultValueCalculator в модель:

@DefaultValueCalculator(CurrentDateCalculator.class)
private Date date;

Вы получаете тот же эффект более декларативным способом.

Что, в то время как в RnR вы помещаете код на контроллер, в OX код для вычисления начальных значений, для валидаций и для бизнес-логики в целом находится на модели. OX способствует перемещению бизнес-логики от контроллера к модели.

Любопытно, что в статье RnR говорится: «Я изменил файлы модели, поэтому мне нужно перезапустить наш веб-сервер». При использовании Eclipse WTP мне нужно всего лишь нажать Ctrl-B и нажать кнопку обновления в моем браузере, чтобы увидеть изменение моей модели в моем приложении OpenXava.

Вывод

Основное различие между Ruby on Rails и OpenXava заключается в том, что RnR — это инфраструктура MVC, вам нужно написать модель, представление и контроллеры, а OX — это управляемая моделью среда, вам нужно только написать модель. Результат — меньше кода для лучшего приложения.

Другое большое отличие состоит в том, что RnR использует пассивную генерацию кода; то есть он генерирует код для вас, но после него, если вы хотите расширить или уточнить код, вы должны отредактировать сгенерированный код. OpenXava не использует генерацию кода, единственный код, который у вас есть, это код, который вы пишете.

Вы можете найти производительность во вселенной Java.

Рекомендации