Разделы презентаций


Быть в 10 раз эффективнее благодаря Groovy

Содержание

Smart1: система бронирования ТВ-рекламыВся реклама на телеканалах 1+1, 2+2, ТЕТ, CITI продается через Smart1Месячный оборот 00 000 000 гр.Информация о 1 300 000 размещениях рекламыСложная модель продаж - аукцион Отчеты Интеграция с внешними

Слайды и текст этой презентации

Слайд 1Быть в 10 раз эффективнее благодаря Groovy
Евгений Компаниец

Быть в 10 раз эффективнее благодаря GroovyЕвгений Компаниец

Слайд 2Smart1: система бронирования ТВ-рекламы
Вся реклама на телеканалах 1+1, 2+2, ТЕТ,

CITI продается через Smart1
Месячный оборот 00 000 000 гр.
Информация о

1 300 000 размещениях рекламы
Сложная модель продаж - аукцион 
Отчеты 
Интеграция с внешними системами: GFK Mark Data Media Workstation, 1C
2 разработчика; 1,5 года; внедрено на втором месяце разработки
Smart1: система бронирования ТВ-рекламыВся реклама на телеканалах 1+1, 2+2, ТЕТ, CITI продается через Smart1Месячный оборот 00 000

Слайд 4Архитектура
CentOS 4.1.2
PostgreSQL 8.4.4
Tomcat 6.0.20
Hibernate 3.3.x
Ehcache 2.1.0
Java 1.6 64-Bit server
GWT 2.3.0
GWT

2.3.0 RPC Servlet
Groovy 1.8.0
Daemon
Servlets

АрхитектураCentOS 4.1.2PostgreSQL 8.4.4Tomcat 6.0.20Hibernate 3.3.xEhcache 2.1.0Java 1.6 64-Bit serverGWT 2.3.0GWT 2.3.0 RPC ServletGroovy 1.8.0DaemonServlets

Слайд 5Разработка
Java 1.6 64-Bit server
IntelliJ IDEA 10
GIT
Maven 2
Jetbrains TeamCity 6.0.3
Selenium 1.0.2
710

Тестов
Время сборки 40 мин
Установка на рабочий сервер 2 раза в

неделю
РазработкаJava 1.6 64-Bit serverIntelliJ IDEA 10GITMaven 2Jetbrains TeamCity 6.0.3Selenium 1.0.2710 ТестовВремя сборки 40 минУстановка на рабочий сервер

Слайд 6Производительность
Денормализация структуры БД
Тяжелые отчеты обновляются по расписанию
Ряд задач выполняется только

ночью  
HP Proliant DL360G6
2xQuad CPU
12G RAM
Пиковая нагрузка 40 gwt rpc

запросов в секунду

ПроизводительностьДенормализация структуры БДТяжелые отчеты обновляются по расписаниюРяд задач выполняется только ночью  HP Proliant DL360G62xQuad CPU12G RAMПиковая нагрузка

Слайд 7Строки кода

Строки кода

Слайд 8От Java к Groovy
Smart1 - наш второй groovy проект
До перехода

сомнения:
что такого принципиального может дать groovy?
зачем терять часть возможностей IDE?
огромный

тормоз
После перехода:
сожаление, что gwt не позволяет использовать groovy, чтобы полностью отказаться от java

От Java к GroovySmart1 - наш второй groovy проектДо перехода сомнения:что такого принципиального может дать groovy?зачем терять

Слайд 9Опрос: Насколько Groovy эффективнее Java?
4-6 раз, коллеги
Я бы сказал 2-3 раза, Алекс

Ткачман
Я обычно продуктивнее в 2 с лишним. Иногда groovy действительно

упрощает проблему и я становлюсь в 3-5 раз продуктивнее. Давид Кларк
Моя продуктивность легко достигает 10 раз. Jochen Theodorou  
Опрос: Насколько Groovy эффективнее Java?4-6 раз, коллегиЯ бы сказал 2-3 раза, Алекс ТкачманЯ обычно продуктивнее в 2 с лишним.

Слайд 10Groovy - это гораздо больше, чем убрать из Java ; и типы!
значительно

меньше кода
код значительно читабельнее
значительно выше повторное использование
легко создаются DSL
не нужен

псевдокод
Groovy - это гораздо больше, чем убрать из Java ; и типы!значительно меньше кодакод значительно читабельнеезначительно выше повторное использованиелегко

Слайд 11Коротко и выразительно!
Взять все проходящие размещения и отсортировать сначала по

цене, потом по дате создания







placements.findAll { it.booked }
.sort

{p1, p2 -> 
        p2.wPrice <=> p1.wPrice ?: 
            p1.creationDate <=> p2.creationDate }
Коротко и выразительно!Взять все проходящие размещения и отсортировать сначала по цене, потом по дате созданияplacements.findAll { it.booked

Слайд 12List bookedPlacements = new ArrayList();
for (Placement placement : placements) {

if (placement.isBooked()) {
       bookedPlacements.add(placement);
  

   }
}
Collections.sort(bookedPlacements, new Comparator() {
            public int compare(Placement p1, Placement p2) {
                int r = p1.getwPrice().compareTo(p2.getwPrice());
                if (r == 0) {
                    r = p1.getCreationDate()
.compareTo(p2.getCreationDate());
                }
                return r;
            }
});
List bookedPlacements = new ArrayList();for (Placement placement : placements) {   if (placement.isBooked()) {      

Слайд 13Коротко и выразительно!
Вернуть короткие названия бюджетных месяцев

def monthNames =

budgets*.month*.shortName
List monthNames = new ArrayList();
for (MonthBudget budget: budgets) {

monthNames.add(budget.getMonth().getShortName());
}
Коротко и выразительно!Вернуть короткие названия бюджетных месяцев def monthNames = budgets*.month*.shortNameList monthNames = new ArrayList();for (MonthBudget budget:

Слайд 14Коротко и выразительно!
Эфирное время конца программы – это время начала

первого из послепрограмных блоков, либо время конца программы
blocks.findAll { it.position

== AFTER }*.startTime.min() ?: endTime

Коротко и выразительно!Эфирное время конца программы – это время начала первого из послепрограмных блоков, либо время конца

Слайд 15List afterBlocks = new ArrayList ();
for (Block block : blocks)

{
if (block.getPosition() == AFTER) {

afterBlocks.add(block);
}
}
if (afterBlocks.isEmpty()) {
return endTime;
}
Time minTime = new Time(0);
for (Block block : afterBlocks) {
if (block.getStartTime().isBefore(minTime)) {
minTime = block.getStartTime();
}
}
return minTime;
List afterBlocks = new ArrayList ();for (Block block : blocks) {  if (block.getPosition() == AFTER) {

Слайд 16Коротко и выразительно!
Если плательщик задан, то вернуть его, иначе взять

плательщика из прошлого периода. Если в прошлом периоде нет плательщиков,

то взять любого из агентства.

payee ?: prevInYear?.payee ?: (agency.payees as List)[0]

Коротко и выразительно!Если плательщик задан, то вернуть его, иначе взять плательщика из прошлого периода. Если в прошлом

Слайд 17if (payee != null) {
return payee;
}
if (getPrevInYear()

!= null
&& getPrevInYear().getPayee()

!= null) {
return prevInYear.getPayee();
}
return getAgency().getPayees().iterator().next();
if (payee != null) {   return payee;}if (getPrevInYear() != null

Слайд 18Немного сложнее?
Взять размещения из самой популярной категории
placements.groupBy { it.category }.collect

{it}
                .sort {it.value.size()}.last().value

Немного сложнее?Взять размещения из самой популярной категорииplacements.groupBy { it.category }.collect {it}                .sort {it.value.size()}.last().value

Слайд 19Java, с использованием «библиотечных» groupBy и last:
List groupsList = new

ArrayList((Util.groupBy(placements,
new GroupSelector() {

public CopyCategory getProperty(Placement p) {
return p.getCopyCategory();
}
})).entrySet());
Collections.sort(groupsList,
new Comparator>>() {
public int compare(Map.Entry> o1,
Map.Entry> o2) {
return ((Integer) o1.getValue().size())
.compareTo(o2.getValue().size());
}
});
return (List) ((Map.Entry) Util.last(groupsList)).getValue();
Java, с использованием «библиотечных» groupBy и last:List groupsList = new ArrayList((Util.groupBy(placements,    new GroupSelector() {

Слайд 20Java, прямая реализация:
Map categoryPlacements = new HashMap();
for (Placement

placement : placements) {
List _placements =

categoryPlacements.get(placement.getCategory());
if (_placements == null) {
_placements = new ArrayList();
categoryPlacements.put(placement.getCategory(), _placements);
}
_placements.add(placement);
}
CopyCategory popularCategory = null;
int maxSize = 0;
for (CopyCategory category : categoryPlacements.keySet()) {
if (categoryPlacements.get(category).size() > maxSize) {
maxSize = categoryPlacements.get(category).size();
popularCategory = category;
}
}
return categoryPlacements.get(popularCategory);

Java, прямая реализация:Map categoryPlacements = new HashMap();for (Placement placement : placements) {    List _placements

Слайд 21Сила Closure
Настоящие возможности открываются, когда мы понимаем что такое Closure

sort,

findAll, groupBy и т.п – все навсего методы принимающие Closure

и мы можем делать такие свои

Сила ClosureНастоящие возможности открываются, когда мы понимаем что такое Closuresort, findAll, groupBy и т.п – все навсего

Слайд 22Сила Closure
Получить Map время, на название (названия уникальны для времени)
placements.mapUnique(‘time’)

{ it.name }
Map timePlacements =

new HashMap();
for (GfkPlacement placement: placements) {
timePlacements.put(placement.time, placement.name);
}
Сила ClosureПолучить Map время, на название (названия уникальны для времени)placements.mapUnique(‘time’) { it.name }Map timePlacements =

Слайд 23Расширение существующих классов
Мы можем добавлять методы и поля к уже

написанным классам без наследования.

Наш mapUnique можно вызывать на любой коллекции
robot.grp

= 22.centi
scheduleMonth.month = 2009.jan
block.startTime = /17:59/.time


Расширение существующих классовМы можем добавлять методы и поля к уже написанным классам без наследования.Наш mapUnique можно вызывать

Слайд 24Расширение существующих классов
Методы у Object дают нам следующий синтаксис:


transaction {
new

User(‘New User’).dbStore()
}

Расширение существующих классовМетоды у Object дают нам следующий синтаксис:transaction {	new User(‘New User’).dbStore()}

Слайд 25Расширение существующих классов
Сделаем немного удобнее Hibernate Criteria API:
def clientGroups =
RobotGroup.dbQuery.with

{
eq('deleted', false)
createCriteria('copy').eq('_client', client)
}.list()

Расширение существующих классовСделаем немного удобнее Hibernate Criteria API:def clientGroups =	RobotGroup.dbQuery.with {	  eq('deleted', false)	  createCriteria('copy').eq('_client', client)	}.list()

Слайд 26DSL делается легко
count = 0
new SwingBuilder().edt {
frame(title: 'Frame',

size: [300, 300], show: true) {
borderLayout()

textlabel = label(text: "Click the button!",
constraints: NORTH)
button(text: 'Click Me',
actionPerformed: {
count++
textlabel.text = "Clicked ${count} time(s)."
}, constraints: SOUTH)
}
}

DSL делается легкоcount = 0new SwingBuilder().edt {  frame(title: 'Frame', size: [300, 300], show: true) {

Слайд 27JFrame frame = new JFrame("Frame");
frame.setSize(300, 300);
frame.setLayout(new BorderLayout());
final JLabel label =

new JLabel("Click the button");
frame.add(label, NORTH);
final JButton button = new JButton("Click

Me");
final int[] counter = {0};
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
counter[0]++;
label.setText("Clicked " + counter[0] + “ time(s).");
}
});
frame.add(button, SOUTH);
frame.setVisible(true);

JFrame frame = new JFrame(

Слайд 28DSL делается легко
shopList(client, 2011, 'Test ShopList', primePercent: 70) {
       discount(offPrime:

-10.disc)
       channelSl(channel, lowDiscount: -30.disc) {
          

 monthSl(JAN, seasonal: -30.disc) {
                stdSl(100.centi)
                lowSl(400.centi)
            }
       }
}

DSL делается легкоshopList(client, 2011, 'Test ShopList', primePercent: 70) {       discount(offPrime: -10.disc)       channelSl(channel, lowDiscount: -30.disc) {    

Слайд 29Selenium junit тест
void testPlace_SpotClient() {
runTest(
   agent, {
  

    chooseCampaigns 'XC'
         placeClick getBlock(1),

'XC'
         waitForError 'No Shop List for Volvo in 2009'
      },
      sale, clients, {
       changeToPerSpot 'Volvo'
      },
      ...
)
}

Selenium junit тестvoid testPlace_SpotClient() {  runTest(    agent, {        chooseCampaigns 'XC'      

Слайд 30Динамика
Динамическое программирование позволяет нам понять что такое повторное использование по

настоящему!

Например давайте перестанем каждый раз делать одно и тоже для

Bidirectional Association и Lazy Initialization:
ДинамикаДинамическое программирование позволяет нам понять что такое повторное использование по настоящему!Например давайте перестанем каждый раз делать одно

Слайд 31Bidirectional Association
class Program {
@OneToMany (mappedBy = "_program")
    Set

_blocks = []
}
class Block {
@ManyToOne
    Program _program
}




Слайд 32Bidirectional Association
И теперь мы сразу можем работать:

def p = new

Program()
def b = new Block()
p

b.program

Bidirectional AssociationИ теперь мы сразу можем работать:def p = new Program()def b = new Block()p

Слайд 33Bidirectional Association
Этого писать не нужно:
class Program {
...
void addBlock(Block

b) {
  b._program = this
 }
  
void removeBlock(Block b) {
  

b._program = null
}
}

class Block {
...
void setProgram(Program p) {
if (_program != null) {
   _program.friendBlocks
.remove(this)
  }
  _program = p
  if (_program != null) {
   _program.friendBlocks
.add(this)
    }
}
}



Bidirectional AssociationЭтого писать не нужно:class Program { ... void addBlock(Block b) {   b._program = this }   void

Слайд 34Lazy initialization
Этого писать не нужно:
class MonthBudget {
 ...
 Centi __actualBudget() {
    ...

 calculation
 }
}
class MonthBudget {
...
 Centi _actualBudget

 def getActualBudget() {
   if (_actualBudget ==

null) {
      _actualBudget = ...  
   }
 }

}

println new MonthBudget().actualBudget

Lazy initializationЭтого писать не нужно:class MonthBudget { ... Centi __actualBudget() {    ...  calculation }}class MonthBudget { ... Centi _actualBudget def getActualBudget() {  

Слайд 35Но не все так хорошо
Скорость?
IDE?

Но не все так хорошоСкорость?IDE?

Слайд 36Реально тормоз!
Groovy работает в 10 раз медленнее Java

Реально тормоз!Groovy работает в 10 раз медленнее Java

Слайд 37Benchmark Groovy, Grovy++, Java
https://github.com/alextkachman/fib-benchmark

Benchmark Groovy, Grovy++, Javahttps://github.com/alextkachman/fib-benchmark

Слайд 38Но на этом можно работать
Groovy работает также как Python, Ruby,

PHP и т.п.

Но на этом можно работатьGroovy работает также как Python, Ruby, PHP и т.п.

Слайд 39Benchmark Java, Python, Ruby
http://shootout.alioth.debian.org/

Benchmark Java, Python, Rubyhttp://shootout.alioth.debian.org/

Слайд 40Скорость Groovy
не забываем, что часто узкое место база данных
любой фрагмент

можно переписать на java
любой фрагмент можно переписать сделать Groovy++

Скорость Groovyне забываем, что часто узкое место база данныхлюбой фрагмент можно переписать на javaлюбой фрагмент можно переписать

Слайд 41Groovy++
Статически типизированное расширение Groovy
По скорости выполнения почти не уступает Java
Может

рассматриваться как альтернатива Scala
Пишется небольшой группой энтузиастов (один хакер?), мало

используется
Groovy++Статически типизированное расширение GroovyПо скорости выполнения почти не уступает JavaМожет рассматриваться как альтернатива ScalaПишется небольшой группой энтузиастов

Слайд 42IDEA
IDEA в целом очень хорошо поддерживает groovy:
Для работы с динамическими

методами и полями в IDEA есть Dynamic properties
Работает выведение типов,

в основном 

Тем не менее:
Для динамики мы теряем автоматический рефакторинг и высокоуровневый поиск (findUsages)
В отладчике иногда сильно тормозит Step Into

IDEAIDEA в целом очень хорошо поддерживает groovy:Для работы с динамическими методами и полями в IDEA есть Dynamic

Слайд 43Спасибо
evgenyk@gmail.com

Спасибоevgenyk@gmail.com

Обратная связь

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

Email: Нажмите что бы посмотреть 

Что такое TheSlide.ru?

Это сайт презентации, докладов, проектов в PowerPoint. Здесь удобно  хранить и делиться своими презентациями с другими пользователями.


Для правообладателей

Яндекс.Метрика