2014 iforum - grails in startup

72
Grails - как эффективно использовать Java в стартапе? Богдан Данилюк iForum | апрель 2014 | @bogdand

Upload: bogdan-danilyuk

Post on 06-May-2015

251 views

Category:

Engineering


1 download

TRANSCRIPT

Page 1: 2014 iForum - Grails in Startup

Grails - как эффективно использовать Java в стартапе?

Богдан Данилюк

iForum | апрель 2014 | @bogdand

Page 2: 2014 iForum - Grails in Startup

Кто я?

● C Grails начиная с 2008 года

● Преподаватель курса Groovy / Grails в проекте

GeekHub

● В TransferWise со стадии MVP

Page 3: 2014 iForum - Grails in Startup

О проекте

TransferWise

Page 4: 2014 iForum - Grails in Startup

TransferWise

Page 5: 2014 iForum - Grails in Startup

Проблема

Потребности бизнеса разные на разных этапах

Page 6: 2014 iForum - Grails in Startup

Этапы развития проекта

Proof of concept

Page 7: 2014 iForum - Grails in Startup

Proof of concept

Page 8: 2014 iForum - Grails in Startup

Этапы развития проекта

MVP

Page 9: 2014 iForum - Grails in Startup

Этапы развития проекта

Эксперементирование и наращивание функциональности

Page 10: 2014 iForum - Grails in Startup

Этапы развития проекта

От скорости к качеству

Page 11: 2014 iForum - Grails in Startup

Этапы развития проекта

Отказоустойчивость и масштабируемость

Page 12: 2014 iForum - Grails in Startup

Grails

Page 13: 2014 iForum - Grails in Startup

Что такое Grails?Groovy / Java web framework который:

● Rapid● Dynamic● Robust

Page 14: 2014 iForum - Grails in Startup

Быстрая разработка

C Grails вы получаете функционирующее web

приложение через 6 секунд :)

Page 15: 2014 iForum - Grails in Startup

Grails

Структура папок

Page 16: 2014 iForum - Grails in Startup

Grailsбыстрая разработка

Page 17: 2014 iForum - Grails in Startup

Быстрая разработка

Groovy - динамический язык с опциональной типизацией

обратно совместимый с Java

Page 18: 2014 iForum - Grails in Startup

Groovy

Обилие синтаксического сахараdef foo = nulldef bar = foo?.something?.myMethod()assert bar == null

assert 'a' == bar ?: 'a'

assert -1 == 3 <=> 4

assert 3 == [1, 2, 3].find {it > 2}

Page 19: 2014 iForum - Grails in Startup

Groovypublic 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"));

Page 20: 2014 iForum - Grails in Startup

Groovypublic 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"));

Точки с запятыми

Page 21: 2014 iForum - Grails in Startup

Groovypublic 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"))

Page 22: 2014 iForum - Grails in Startup

Groovypublic 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"))

Скобки

Page 23: 2014 iForum - Grails in Startup

Groovypublic 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")

Page 24: 2014 iForum - Grails in Startup

Groovypublic 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

Page 25: 2014 iForum - Grails in Startup

Groovypublic 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")

Page 26: 2014 iForum - Grails in Startup

Groovypublic 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

Page 27: 2014 iForum - Grails in Startup

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")

Page 28: 2014 iForum - Grails in Startup

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")

Опциональная типизация

Page 29: 2014 iForum - Grails in Startup

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")

Page 30: 2014 iForum - Grails in Startup

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

Page 31: 2014 iForum - Grails in Startup

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")

Page 32: 2014 iForum - Grails in Startup

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")

поле класса

Page 33: 2014 iForum - Grails in Startup

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")

Page 34: 2014 iForum - Grails in Startup

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")

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

Page 35: 2014 iForum - Grails in Startup

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")

Page 36: 2014 iForum - Grails in Startup

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")

Именованные аргументы

Page 37: 2014 iForum - Grails in Startup

Groovy class User { String name

String greet(String guest) { "Hello " + name + ", I am " + guest }}def user = new User(name: "Vasya")

println user.greet("Petya")

Page 38: 2014 iForum - Grails in Startup

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

Page 39: 2014 iForum - Grails in Startup

Groovy class User { String name

String greet(String guest) { "Hello ${name}, I am ${guest}" }}def user = new User(name: "Vasya")

println user.greet("Petya")

Page 40: 2014 iForum - Grails in Startup

Groovy class User { String name

String greet(String guest) { "Hello ${name}, I am ${guest}" }}def user = new User(name: "Vasya")

println user.greet("Petya")

Уберем пробелы

Page 41: 2014 iForum - Grails in Startup

Groovyclass User { String name

String greet(String guest) { "Hello ${name}, I am ${guest}" }}

def user = new User(name: "Vasya")println user.greet("Petya")

Page 42: 2014 iForum - Grails in Startup

Groovypublic 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"));

Page 43: 2014 iForum - Grails in Startup

Groovyclass User { String name

String greet(String guest) { "Hello ${name}, I am ${guest}" }}

def user = new User(name: "Vasya")println user.greet("Petya")

Page 44: 2014 iForum - Grails in Startup

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))

Page 45: 2014 iForum - Grails in Startup

Groovy

Идеален для создания DSLhtml { head { title 'Simple document' } body(id: 'main') { h1 'Building HTML the Groovy Way' p { strong 'Some bold text' } a href: 'more.html', 'Read more...' }}

Page 46: 2014 iForum - Grails in Startup

Groovy

Узнать больше о Groovy

http://www.infoq.com/presentations/groovy-2-1-2gx

Page 47: 2014 iForum - Grails in Startup

Быстрая разработка

Принципы Grails● DRY● Convention over Configuration

Page 48: 2014 iForum - Grails in Startup

Быстрая разработка

GORM

package org.example

class Book {

static constraints = { }}

Page 49: 2014 iForum - Grails in Startup

Быстрая разработка

package org.example

class Book { String title

static constraints = { title blank: false }}

Page 50: 2014 iForum - Grails in Startup

Быстрая разработка

Мощный скаффолдинг

package org.example

class BookController {

def index() { }}

Page 51: 2014 iForum - Grails in Startup

Быстрая разработка

package org.example

class BookController { def scaffold = Book

def index() { }}

Page 52: 2014 iForum - Grails in Startup

Быстрая разработка

Page 53: 2014 iForum - Grails in Startup

Быстрая разработка

1к+ плагинов

Page 54: 2014 iForum - Grails in Startup

Быстрая разработка

● GORM● Security● OpenId / Facebook / LinkedIn● Cache● CMS● Rich client

Плагины

Page 55: 2014 iForum - Grails in Startup

Grailsкачественная разработка

Page 56: 2014 iForum - Grails in Startup

Качественная разработка

Вектор архитектуры● Реализован набор паттернов● Явное разделение

обязанностей● Набор устоявшихся практик

Page 57: 2014 iForum - Grails in Startup

Качественная разработка

Построен на плечах титанов

Page 58: 2014 iForum - Grails in Startup

Качественная разработка

Тестирование в крови

Page 59: 2014 iForum - Grails in Startup

Качественная разработка

Хорошо проработанное Unit тестирование

Page 60: 2014 iForum - Grails in Startup

Качественная разработка

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()}

Тестирование динамических методов домена

Page 61: 2014 iForum - Grails in Startup

Качественная разработка

Spock

● BDD / Specifications● Data Driven Testing● Mock / Stub / Spy● Расширяемый

плагинами

Page 62: 2014 iForum - Grails in Startup

Качественная разработка

Spock пример Data Driven Testingclass 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 }}

Page 63: 2014 iForum - Grails in Startup

Качественная разработка

Инструменты мониторнига

● JavaMelody Grails Plugin● Health Control● Application Info plugin ● Perf4J Integration Plugin● NewRelic

Page 64: 2014 iForum - Grails in Startup

Качественная разработка

Инструменты контроля качества

● CodeNarc● GMetrics● SONAR● Cobertura

Page 65: 2014 iForum - Grails in Startup

Grailsмасштабируемость

Page 66: 2014 iForum - Grails in Startup

Масштабируемость

Горизонтальное масштабирование

Page 67: 2014 iForum - Grails in Startup

Масштабируемоcть

Admin web appGrails app

Android iOSWeb Frontend

AngularJS

Database

3rd party

ServicesGrails app

Consumer REST APIGrails app

Monitoring APIs

Куда мы идем

CDN

Page 68: 2014 iForum - Grails in Startup

Масштабируемоcть

Вариаанты подключения плагинов

Из репозитория

// grails-app/conf/BuildConfig.groovy

plugins {

build ":tomcat:7.0.52.1"

}

Из локальной папки

// grails-app/conf/BuildConfig.groovy

grails.plugin.location.blog = "../blog"

Page 69: 2014 iForum - Grails in Startup

В чем подвох?

Page 70: 2014 iForum - Grails in Startup

● У мета фреймворка - мета баги● Лучше бы знать что внутри● Медленные интеграционные

тесты● Скорость старта

Недостатки

Page 71: 2014 iForum - Grails in Startup

Спасибо за внимание!

Page 72: 2014 iForum - Grails in Startup

Вопросы