Grails - как эффективно
использовать Java в стартапе?
Богдан Данилюк
iForum | апрель 2014 | @bogdand
Кто я?
● C Grails начиная с 2008 года
● Преподаватель курса Groovy / Grails в проекте
GeekHub
● В TransferWise со стадии MVP
О проекте
TransferWise
TransferWise
Проблема
Потребности бизнеса разные на
разных этапах
Этапы развития проекта
Proof of concept
Proof of concept
Этапы развития проекта
MVP
Этапы развития проекта
Эксперементирование и
наращивание функциональности
Этапы развития проекта
От скорости к качеству
Этапы развития проекта
Отказоустойчивость и
масштабируемость
Grails
Что такое Grails?
Groovy / Java web framework который:
● Rapid
● Dynamic
● Robust
Быстрая разработка
C Grails вы получаете
функционирующее web
приложение через 6 секунд :)
Grails
Структура папок
Grails
быстрая разработка
Быстрая разработка
Groovy - динамический язык с
опциональной типизацией
обратно совместимый с Java
Groovy
Обилие синтаксического сахара
def foo = null
def bar = foo?.something?.myMethod()
assert bar == null
assert 'a' == bar ?: 'a'​​
assert -1 == 3 <=> 4​
assert 3 == ​[1, 2, 3].find {it > 2}​
Groovy
public class User {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String greet(String guest) {
return "Hello " + name + ", I am " + guest;
}
}
User user = new User();
user.setName("Vasya");
System.out.println(user.greet("Petya"));
Groovy
public class User {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String greet(String guest) {
return "Hello " + name + ", I am " + guest;
}
}
User user = new User();
user.setName("Vasya");
System.out.println(user.greet("Petya"));
Точки с запятыми
Groovy
public class User {
private String name
public String getName() {
return name
}
public void setName(String name) {
this.name = name
}
public String greet(String guest) {
return "Hello " + name + ", I am " + guest
}
}
User user = new User()
user.setName("Vasya")
System.out.println(user.greet("Petya"))
Groovy
public class User {
private String name
public String getName() {
return name
}
public void setName(String name) {
this.name = name
}
public String greet(String guest) {
return "Hello " + name + ", I am " + guest
}
}
User user = new User()
user.setName("Vasya")
System.out.println(user.greet("Petya"))
Скобки
Groovy
public class User {
private String name
public String getName() {
return name
}
public void setName(String name) {
this.name = name
}
public String greet(String guest) {
return "Hello " + name + ", I am " + guest
}
}
User user = new User()
user.setName "Vasya"
System.out.println user.greet("Petya")
Groovy
public class User {
private String name
public String getName() {
return name
}
public void setName(String name) {
this.name = name
}
public String greet(String guest) {
return "Hello " + name + ", I am " + guest
}
}
User user = new User()
user.setName "Vasya"
System.out.println user.greet("Petya")
return
Groovy
public class User {
private String name
public String getName() {
name
}
public void setName(String name) {
this.name = name
}
public String greet(String guest) {
"Hello " + name + ", I am " + guest
}
}
User user = new User()
user.setName "Vasya"
System.out.println user.greet("Petya")
Groovy
public class User {
private String name
public String getName() {
name
}
public void setName(String name) {
this.name = name
}
public String greet(String guest) {
"Hello " + name + ", I am " + guest
}
}
User user = new User()
user.setName "Vasya"
System.out.println user.greet("Petya")
public
Groovy
class User {
private String name
String getName() {
name
}
void setName(String name) {
this.name = name
}
String greet(String guest) {
"Hello " + name + ", I am " + guest
}
}
User user = new User()
user.setName "Vasya"
System.out.println user.greet("Petya")
Groovy
class User {
private String name
String getName() {
name
}
void setName(String name) {
this.name = name
}
String greet(String guest) {
"Hello " + name + ", I am " + guest
}
}
User user = new User()
user.setName "Vasya"
System.out.println user.greet("Petya")
Опциональная типизация
Groovy
class User {
private String name
String getName() {
name
}
void setName(String name) {
this.name = name
}
String greet(String guest) {
"Hello " + name + ", I am " + guest
}
}
def user = new User()
user.setName "Vasya"
System.out.println user.greet("Petya")
Groovy
class User {
private String name
String getName() {
name
}
void setName(String name) {
this.name = name
}
String greet(String guest) {
"Hello " + name + ", I am " + guest
}
}
def user = new User()
user.setName "Vasya"
System.out.println user.greet("Petya")
println
Groovy
class User {
private String name
String getName() {
name
}
void setName(String name) {
this.name = name
}
String greet(String guest) {
"Hello " + name + ", I am " + guest
}
}
def user = new User()
user.setName "Vasya"
println user.greet("Petya")
Groovy
class User {
private String name
String getName() {
name
}
void setName(String name) {
this.name = name
}
String greet(String guest) {
"Hello " + name + ", I am " + guest
}
}
def user = new User()
user.setName "Vasya"
println user.greet("Petya")
поле класса
Groovy
class User {
String name
String greet(String guest) {
"Hello " + name + ", I am " + guest
}
}
def user = new User()
user.setName "Vasya"
println user.greet("Petya")
Groovy
class User {
String name
String greet(String guest) {
"Hello " + name + ", I am " + guest
}
}
def user = new User()
user.setName "Vasya"
println user.greet("Petya")
Использование сеттера
Groovy
class User {
String name
String greet(String guest) {
"Hello " + name + ", I am " + guest
}
}
def user = new User()
user.name = "Vasya"
println user.greet("Petya")
Groovy
class User {
String name
String greet(String guest) {
"Hello " + name + ", I am " + guest
}
}
def user = new User()
user.name = "Vasya"
println user.greet("Petya")
Именованные
аргументы
Groovy
class User {
String name
String greet(String guest) {
"Hello " + name + ", I am " + guest
}
}
def user = new User(name: "Vasya")
println user.greet("Petya")
Groovy
class User {
String name
String greet(String guest) {
"Hello " + name + ", I am " + guest
}
}
def user = new User(name: "Vasya")
println user.greet("Petya")
GString
Groovy
class User {
String name
String greet(String guest) {
"Hello ${name}, I am ${guest}"
}
}
def user = new User(name: "Vasya")
println user.greet("Petya")
Groovy
class User {
String name
String greet(String guest) {
"Hello ${name}, I am ${guest}"
}
}
def user = new User(name: "Vasya")
println user.greet("Petya")
Уберем пробелы
Groovy
class User {
String name
String greet(String guest) {
"Hello ${name}, I am ${guest}"
}
}
def user = new User(name: "Vasya")
println user.greet("Petya")
Groovy
public class User {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String greet(String guest) {
return "Hello " + name + ", I am " + guest;
}
}
User user = new User();
user.setName("Vasya");
System.out.println(user.greet("Petya"));
Groovy
class User {
String name
String greet(String guest) {
"Hello ${name}, I am ${guest}"
}
}
def user = new User(name: "Vasya")
println user.greet("Petya")
Groovy
Замыкания
def finder = {it > 2}
assert 3 == [1, 2, 3].find(finder)
def dynamicFinder = {limit ->
{ var ->
var > limit
}
}
assert 4 == [1, 2, 3, 4].find(dynamicFinder(3))
Groovy
Идеален для создания DSL
html {
head {
title 'Simple document'
}
body(id: 'main') {
h1 'Building HTML the Groovy Way'
p {
strong 'Some bold text'
}
a href: 'more.html', 'Read more...'
}
}
Groovy
Узнать больше о Groovy
http://www.infoq.com/presentations/groovy-2-1-2gx
Быстрая разработка
Принципы Grails
● DRY
● Convention over Configuration
Быстрая разработка
GORM
package org.example
class Book {
static constraints = {
}
}
Быстрая разработка
package org.example
class Book {
String title
static constraints = {
title blank: false
}
}
Быстрая разработка
Мощный скаффолдинг
package org.example
class BookController {
def index() { }
}
Быстрая разработка
package org.example
class BookController {
def scaffold = Book
def index() { }
}
Быстрая разработка
Быстрая разработка
1к+ плагинов
Быстрая разработка
● GORM
● Security
● OpenId / Facebook / LinkedIn
● Cache
● CMS
● Rich client
Плагины
Grails
качественная разработка
Качественная разработка
Вектор архитектуры
● Реализован набор паттернов
● Явное разделение
обязанностей
● Набор устоявшихся практик
Качественная разработка
Построен на плечах титанов
Качественная разработка
Тестирование в крови
Качественная разработка
Хорошо проработанное Unit
тестирование
Качественная разработка
void testMockDomain() {
def jdoe = new User(name:"John Doe", role:"user")
def suziq = new User(name:"Suzi Q", role:"admin")
def jsmith = new User(name:"Jane Smith", role:"user")
mockDomain(User, [jdoe, suziq, jsmith])
def list = User.findAllByRole("admin")
assertEquals 1, list.size()
}
Тестирование динамических
методов домена
Качественная разработка
Spock
● BDD / Specifications
● Data Driven Testing
● Mock / Stub / Spy
● Расширяемый
плагинами
Качественная разработка
Spock пример Data Driven Testing
class MathSpec extends Specification {
def "maximum of two numbers"() {
expect:
Math.max(a, b) == c
where:
a | b || c
1 | 3 || 3
7 | 4 || 4
0 | 0 || 0
}
}
Качественная разработка
Инструменты мониторнига
● JavaMelody Grails Plugin
● Health Control
● Application Info plugin
● Perf4J Integration Plugin
● NewRelic
Качественная разработка
Инструменты контроля качества
● CodeNarc
● GMetrics
● SONAR
● Cobertura
Grails
масштабируемость
Масштабируемость
Горизонтальное масштабирование
Масштабируемоcть
Admin web app
Grails app
Android iOS
Web
Frontend
AngularJS
Database
3rd party
Services
Grails app
Consumer REST API
Grails app
Monitoring APIs
Куда мы идем
CDN
Масштабируемоcть
Вариаанты подключения
плагинов
Из репозитория
// grails-app/conf/BuildConfig.groovy
plugins {
build ":tomcat:7.0.52.1"
}
Из локальной папки
// grails-app/conf/BuildConfig.groovy
grails.plugin.location.blog = "../blog"
В чем подвох?
● У мета фреймворка - мета баги
● Лучше бы знать что внутри
● Медленные интеграционные
тесты
● Скорость старта
Недостатки
Спасибо за внимание!
Вопросы

More Related Content

PDF
2014 Jeeconf - Geb Spock
PPT
CodeFest 2013. Никонов Г. — Как мы разрабатываем приложения для Windows Phone...
PPTX
Игорь Любин - PowerShell - ConfeT&QA 2011
PPTX
PPTX
Windows Azure and node js
PPTX
Быть в 10 раз эффективнее благодаря Groovy
PDF
CSS глазами машин
PDF
Практическое применение HTML5 в Я.Почте
2014 Jeeconf - Geb Spock
CodeFest 2013. Никонов Г. — Как мы разрабатываем приложения для Windows Phone...
Игорь Любин - PowerShell - ConfeT&QA 2011
Windows Azure and node js
Быть в 10 раз эффективнее благодаря Groovy
CSS глазами машин
Практическое применение HTML5 в Я.Почте

Similar to 2014 iForum - Grails in Startup (20)

PPTX
Groovy и Grails. Быстро и обо всём
PDF
Groovy presentation.
PPT
Groovy
PDF
How IntelliJ IDEA plugin can help you in QA Automation
PPTX
Зачем нужна Scala?
PDF
2015-12-06 Максим Юнусов - Проектирование REST приложения, или нужно ли прогр...
PPS
Groovy presentation on Exception #7 conference
PDF
Grails & Groovy
PPTX
JavaScript как объектно-ориентированный язык программирования
PDF
"Basis.js - Production Ready SPA Framework" Сергей Мелюков (Avito)
PDF
Basis.js - Production Ready SPA Framework
PDF
Basis.js - Production Ready Framework
KEY
Курсы по мобильной разработке. 1 лекция. Знакомство с iOS
PPTX
Бодрящий микс из Selenium и TestNG- регрессионное тестирование руками разрабо...
PPTX
JavaScript: хороший тон клиентской разработки
PDF
Как писать под Android программы, а не код
PPT
Что нового в PHP-5.3
PDF
Groovy jug-moscow-part 1
PPTX
вебинар - функциональное тестирование с использованием Selenium 2 и TestNG
PPT
ZFConf 2010: What News Zend Framework 2.0 Brings to Us
Groovy и Grails. Быстро и обо всём
Groovy presentation.
Groovy
How IntelliJ IDEA plugin can help you in QA Automation
Зачем нужна Scala?
2015-12-06 Максим Юнусов - Проектирование REST приложения, или нужно ли прогр...
Groovy presentation on Exception #7 conference
Grails & Groovy
JavaScript как объектно-ориентированный язык программирования
"Basis.js - Production Ready SPA Framework" Сергей Мелюков (Avito)
Basis.js - Production Ready SPA Framework
Basis.js - Production Ready Framework
Курсы по мобильной разработке. 1 лекция. Знакомство с iOS
Бодрящий микс из Selenium и TestNG- регрессионное тестирование руками разрабо...
JavaScript: хороший тон клиентской разработки
Как писать под Android программы, а не код
Что нового в PHP-5.3
Groovy jug-moscow-part 1
вебинар - функциональное тестирование с использованием Selenium 2 и TestNG
ZFConf 2010: What News Zend Framework 2.0 Brings to Us
Ad

2014 iForum - Grails in Startup