SlideShare ist ein Scribd-Unternehmen logo
1 von 43
Быть в 10 раз эффективнее благодаря Groovy Евгений Компаниец
Smart1: система бронирования ТВ-рекламы Вся реклама на телеканалах 1+1, 2+2, ТЕТ, CITI продается через Smart1 Месячный оборот 00 000 000 гр. Информация о 1 300 000 размещениях рекламы Сложная модель продаж - аукцион  Отчеты  Интеграция с внешними системами: GFK Mark Data Media Workstation, 1C 2 разработчика; 1,5 года; внедрено на втором месяце разработки
Архитектура CentOS 4.1.2 Java 1.6 64-Bit server Tomcat 6.0.20 Groovy 1.8.0 GWT 2.3.0 RPC Servlet Daemon Servlets GWT 2.3.0 Hibernate 3.3.x Ehcache 2.1.0 PostgreSQL 8.4.4
Разработка Java 1.6 64-Bit server Maven 2 IntelliJ IDEA 10 GIT Selenium 1.0.2 Jetbrains TeamCity 6.0.3 ,[object Object]
Время сборки 40 мин
Установка на рабочий сервер 2 раза в неделю,[object Object]
Строки кода
От Java к Groovy Smart1 - наш второй groovy проект До перехода сомнения: что такого принципиального может дать groovy? зачем терять часть возможностей IDE? огромный тормоз После перехода: сожаление, что gwt не позволяет использовать groovy, чтобы полностью отказаться от java
Опрос: Насколько Groovy эффективнее Java? 4-6 раз, коллеги Я бы сказал 2-3 раза, Алекс Ткачман Я обычно продуктивнее в 2 с лишним. Иногда groovy действительно упрощает проблему и я становлюсь в 3-5 раз продуктивнее. Давид Кларк Моя продуктивность легко достигает 10 раз. JochenTheodorou  
Groovy - это гораздо больше, чем убрать из Java ; и типы! значительно меньше кода код значительно читабельнее значительно выше повторное использование легко создаются DSL не нужен псевдокод
Коротко и выразительно! Взять все проходящие размещения и отсортировать сначала по цене, потом по дате создания placements.findAll { it.booked }     .sort {p1, p2 ->          p2.wPrice <=> p1.wPrice ?:              p1.creationDate <=> p2.creationDate }
List bookedPlacements = new ArrayList(); for (Placement placement : placements) { if (placement.isBooked()) {            bookedPlacements.add(placement);       } } Collections.sort(bookedPlacements, new Comparator<Placement>() {             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;             } });
Коротко и выразительно! Вернуть короткие названия бюджетных месяцев  def monthNames = budgets*.month*.shortName List monthNames = new ArrayList(); for (MonthBudget budget: budgets) {      monthNames.add(budget.getMonth().getShortName()); }
Коротко и выразительно! Эфирное время конца программы – это время начала первого из послепрограмных блоков, либо время конца программы blocks.findAll { it.position == AFTER }*.startTime.min() ?:         								endTime
List afterBlocks = newArrayList (); for (Block block : blocks) { if (block.getPosition() == AFTER) { afterBlocks.add(block); }  } if (afterBlocks.isEmpty()) { returnendTime; } Time minTime = new Time(0); for (Block block : afterBlocks) { if (block.getStartTime().isBefore(minTime)) { minTime = block.getStartTime(); } } returnminTime;
Коротко и выразительно! Если плательщик задан, то вернуть его, иначе взять плательщика из прошлого периода. Если в прошлом периоде нет плательщиков, то взять любого из агентства.  payee ?: prevInYear?.payee ?: (agency.payees as List)[0]
if (payee != null) { return payee; } if (getPrevInYear() != null              && getPrevInYear().getPayee() != null) { returnprevInYear.getPayee(); } returngetAgency().getPayees().iterator().next();
Немного сложнее? Взять размещения из самой популярной категории placements.groupBy { it.category }.collect {it}                 .sort {it.value.size()}.last().value
Java, с использованием «библиотечных» groupBy и last: List groupsList = new ArrayList((Util.groupBy(placements,  new GroupSelector<CopyCategory, Placement>() { public CopyCategory getProperty(Placement p) { return p.getCopyCategory();                 }             })).entrySet()); Collections.sort(groupsList,     newComparator<Map.Entry<CopyCategory, List<Placement>>>() { public int compare(Map.Entry<CopyCategory, List<Placement>> o1,                            Map.Entry<CopyCategory, List<Placement>> o2) { return((Integer) o1.getValue().size())                         .compareTo(o2.getValue().size());             }         }); return (List<Placement>) ((Map.Entry) Util.last(groupsList)).getValue();
Java, прямая реализация: Map<CopyCategory, List<Placement>> categoryPlacements = new HashMap<CopyCategory, 	List<Placement>>(); 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);
Сила Closure Настоящие возможности открываются, когда мы понимаем что такое Closure sort, findAll, groupByи т.п – все навсего методы принимающие Closure и мы можем делать такие свои
Сила Closure Получить Mapвремя, на название (названия уникальны для времени) placements.mapUnique(‘time’) { it.name } Map<Time, String> timePlacements =                          newHashMap<Time, String>(); for (GfkPlacement placement: placements) {       timePlacements.put(placement.time, placement.name); }
Расширение существующих классов Мы можем добавлять методы и поля к уже написанным классам без наследования. Наш mapUnique можно вызывать на любой коллекции robot.grp = 22.centi scheduleMonth.month = 2009.jan block.startTime = /17:59/.time
Расширение существующих классов Методы у Object дают нам следующий синтаксис: transaction { new User(‘New User’).dbStore() }
Расширение существующих классов Сделаем немного удобнее Hibernate Criteria API: def clientGroups = RobotGroup.dbQuery.with {    eq('deleted', false) 	   createCriteria('copy').eq('_client', client) }.list()
DSL делается легко 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)     } }
JFrame 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"); finalint[] 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);
DSL делается легко shopList(client, 2011, 'TestShopList', primePercent: 70) {        discount(offPrime: -10.disc)        channelSl(channel, lowDiscount: -30.disc) {             monthSl(JAN, seasonal: -30.disc) {                 stdSl(100.centi)                 lowSl(400.centi)             }        } }
Selenium junit тест void testPlace_SpotClient() {    runTest(       agent, {          chooseCampaigns 'XC'          placeClick getBlock(1), 'XC'          waitForError 'No Shop List for Volvo in 2009'       },       sale, clients, {          changeToPerSpot 'Volvo'       },       ...    ) }
Динамика Динамическое программирование позволяет нам понять что такое повторное использование по настоящему! Например давайте перестанем каждый раз делать одно и тоже для Bidirectional Association и Lazy Initialization:
Bidirectional Association class Program {     @OneToMany (mappedBy = "_program")     Set<Block> _blocks = [] } class Block {     @ManyToOne     Program _program }
Bidirectional Association И теперь мы сразу можем работать: def p = new Program() def b = new Block() p << b p.addBlock(b) p.removeBlock(b) //valid properties: p.blocks (unmodifiable set), b.program
Bidirectional Association Этого писать не нужно: class Program {  ...  voidaddBlock(Block b) {     b._program = this  }     voidremoveBlock(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)     }   } }
Lazy initialization Этого писать не нужно: class MonthBudget {  ...  Centi __actualBudget() {     ...  calculation  } } class MonthBudget {  ...  Centi _actualBudget  defgetActualBudget() {   if(_actualBudget == null) {       _actualBudget = ...     }  } } println new MonthBudget().actualBudget
Но не все так хорошо Скорость? IDE?
Реально тормоз! Groovy работает в 10 раз медленнее Java
Benchmark Groovy, Grovy++, Java https://github.com/alextkachman/fib-benchmark
Но на этом можно работать Groovy работает также как Python, Ruby, PHP и т.п.
Benchmark Java, Python, Ruby http://shootout.alioth.debian.org/
Скорость Groovy не забываем, что часто узкое место база данных любой фрагмент можно переписать на java любой фрагмент можно переписать сделать Groovy++
Groovy++ Статически типизированное расширение Groovy По скорости выполнения почти не уступает Java Может рассматриваться как альтернатива Scala Пишется небольшой группой энтузиастов (один хакер?), мало используется
IDEA IDEA в целом очень хорошо поддерживает groovy: Для работы с динамическими методами и полями в IDEA есть Dynamic properties Работает выведение типов, в основном  Тем не менее: Для динамики мы теряем автоматический рефакторинги высокоуровневый поиск (findUsages) В отладчике иногда сильно тормозит Step Into

Weitere ähnliche Inhalte

Was ist angesagt?

8 встреча — Язык программирования Python (В. Ананьев)
8 встреча — Язык программирования Python (В. Ананьев)8 встреча — Язык программирования Python (В. Ананьев)
8 встреча — Язык программирования Python (В. Ананьев)Smolensk Computer Science Club
 
Магия метаклассов
Магия метаклассовМагия метаклассов
Магия метаклассовAndrey Zakharevich
 
Подробная презентация JavaScript 6 в 1
Подробная презентация JavaScript 6 в 1Подробная презентация JavaScript 6 в 1
Подробная презентация JavaScript 6 в 1Vasya Petrov
 
Реализация шаблонов корпоративных приложений в Magento
Реализация шаблонов корпоративных приложений в MagentoРеализация шаблонов корпоративных приложений в Magento
Реализация шаблонов корпоративных приложений в MagentoMagecom Ukraine
 
Григорий Демченко, Универсальный адаптер
Григорий Демченко, Универсальный адаптерГригорий Демченко, Универсальный адаптер
Григорий Демченко, Универсальный адаптерSergey Platonov
 
Фитнес для вашего кода: как держать его в форме
Фитнес для вашего кода: как держать его в формеФитнес для вашего кода: как держать его в форме
Фитнес для вашего кода: как держать его в формеIlia Shishkov
 
Pyton – пробуем функциональный стиль
Pyton – пробуем функциональный стильPyton – пробуем функциональный стиль
Pyton – пробуем функциональный стильPython Meetup
 
DevConf. Дмитрий Сошников - ECMAScript 6
DevConf. Дмитрий Сошников - ECMAScript 6DevConf. Дмитрий Сошников - ECMAScript 6
DevConf. Дмитрий Сошников - ECMAScript 6Dmitry Soshnikov
 
Оптимизация производительности Python
Оптимизация производительности PythonОптимизация производительности Python
Оптимизация производительности PythonPyNSK
 
Разработка расширяемых приложений на Django
Разработка расширяемых приложений на DjangoРазработка расширяемых приложений на Django
Разработка расширяемых приложений на DjangoMoscowDjango
 
Индексирование в Magento
Индексирование в MagentoИндексирование в Magento
Индексирование в MagentoMagecom Ukraine
 
MongoDB - About Performance Optimization, Ivan Griga - Smart Gamma
MongoDB - About Performance Optimization, Ivan Griga - Smart GammaMongoDB - About Performance Optimization, Ivan Griga - Smart Gamma
MongoDB - About Performance Optimization, Ivan Griga - Smart GammaEvgeniy Kuzmin
 
Нейронные сети и Keras. Часть 2
Нейронные сети и Keras. Часть 2Нейронные сети и Keras. Часть 2
Нейронные сети и Keras. Часть 2PyNSK
 
Язык программирования Scala / Владимир Успенский (TCS Bank)
Язык программирования Scala / Владимир Успенский (TCS Bank)Язык программирования Scala / Владимир Успенский (TCS Bank)
Язык программирования Scala / Владимир Успенский (TCS Bank)Ontico
 
Догнать и перегнать boost::lexical_cast
Догнать и перегнать boost::lexical_castДогнать и перегнать boost::lexical_cast
Догнать и перегнать boost::lexical_castRoman Orlov
 
Нейронные сети и Keras. Часть 1
Нейронные сети и Keras. Часть 1Нейронные сети и Keras. Часть 1
Нейронные сети и Keras. Часть 1PyNSK
 
Школа-студия разработки приложений для iOS. Лекция 1. Objective-C
Школа-студия разработки приложений для iOS. Лекция 1. Objective-CШкола-студия разработки приложений для iOS. Лекция 1. Objective-C
Школа-студия разработки приложений для iOS. Лекция 1. Objective-CГлеб Тарасов
 
GAE - плюсы/минусы/подводные камни
GAE - плюсы/минусы/подводные камниGAE - плюсы/минусы/подводные камни
GAE - плюсы/минусы/подводные камниYehor Nazarkin
 
Очень вкусный фрукт Guava
Очень вкусный фрукт GuavaОчень вкусный фрукт Guava
Очень вкусный фрукт GuavaEgor Chernyshev
 

Was ist angesagt? (20)

8 встреча — Язык программирования Python (В. Ананьев)
8 встреча — Язык программирования Python (В. Ананьев)8 встреча — Язык программирования Python (В. Ананьев)
8 встреча — Язык программирования Python (В. Ананьев)
 
Charming python sc2-8
Charming python sc2-8Charming python sc2-8
Charming python sc2-8
 
Магия метаклассов
Магия метаклассовМагия метаклассов
Магия метаклассов
 
Подробная презентация JavaScript 6 в 1
Подробная презентация JavaScript 6 в 1Подробная презентация JavaScript 6 в 1
Подробная презентация JavaScript 6 в 1
 
Реализация шаблонов корпоративных приложений в Magento
Реализация шаблонов корпоративных приложений в MagentoРеализация шаблонов корпоративных приложений в Magento
Реализация шаблонов корпоративных приложений в Magento
 
Григорий Демченко, Универсальный адаптер
Григорий Демченко, Универсальный адаптерГригорий Демченко, Универсальный адаптер
Григорий Демченко, Универсальный адаптер
 
Фитнес для вашего кода: как держать его в форме
Фитнес для вашего кода: как держать его в формеФитнес для вашего кода: как держать его в форме
Фитнес для вашего кода: как держать его в форме
 
Pyton – пробуем функциональный стиль
Pyton – пробуем функциональный стильPyton – пробуем функциональный стиль
Pyton – пробуем функциональный стиль
 
DevConf. Дмитрий Сошников - ECMAScript 6
DevConf. Дмитрий Сошников - ECMAScript 6DevConf. Дмитрий Сошников - ECMAScript 6
DevConf. Дмитрий Сошников - ECMAScript 6
 
Оптимизация производительности Python
Оптимизация производительности PythonОптимизация производительности Python
Оптимизация производительности Python
 
Разработка расширяемых приложений на Django
Разработка расширяемых приложений на DjangoРазработка расширяемых приложений на Django
Разработка расширяемых приложений на Django
 
Индексирование в Magento
Индексирование в MagentoИндексирование в Magento
Индексирование в Magento
 
MongoDB - About Performance Optimization, Ivan Griga - Smart Gamma
MongoDB - About Performance Optimization, Ivan Griga - Smart GammaMongoDB - About Performance Optimization, Ivan Griga - Smart Gamma
MongoDB - About Performance Optimization, Ivan Griga - Smart Gamma
 
Нейронные сети и Keras. Часть 2
Нейронные сети и Keras. Часть 2Нейронные сети и Keras. Часть 2
Нейронные сети и Keras. Часть 2
 
Язык программирования Scala / Владимир Успенский (TCS Bank)
Язык программирования Scala / Владимир Успенский (TCS Bank)Язык программирования Scala / Владимир Успенский (TCS Bank)
Язык программирования Scala / Владимир Успенский (TCS Bank)
 
Догнать и перегнать boost::lexical_cast
Догнать и перегнать boost::lexical_castДогнать и перегнать boost::lexical_cast
Догнать и перегнать boost::lexical_cast
 
Нейронные сети и Keras. Часть 1
Нейронные сети и Keras. Часть 1Нейронные сети и Keras. Часть 1
Нейронные сети и Keras. Часть 1
 
Школа-студия разработки приложений для iOS. Лекция 1. Objective-C
Школа-студия разработки приложений для iOS. Лекция 1. Objective-CШкола-студия разработки приложений для iOS. Лекция 1. Objective-C
Школа-студия разработки приложений для iOS. Лекция 1. Objective-C
 
GAE - плюсы/минусы/подводные камни
GAE - плюсы/минусы/подводные камниGAE - плюсы/минусы/подводные камни
GAE - плюсы/минусы/подводные камни
 
Очень вкусный фрукт Guava
Очень вкусный фрукт GuavaОчень вкусный фрукт Guava
Очень вкусный фрукт Guava
 

Andere mochten auch

Grails report, JEEConf 2012
Grails report, JEEConf 2012Grails report, JEEConf 2012
Grails report, JEEConf 2012Sergiy Korzh
 
Скриптовой язык Groovy и его применение в рамках разработки ПО
Скриптовой язык Groovy и его применение в рамках разработки ПОСкриптовой язык Groovy и его применение в рамках разработки ПО
Скриптовой язык Groovy и его применение в рамках разработки ПОFedor Malyshkin
 
Система обработки бизнес-логики server-side приложения на Groovy
Система обработки бизнес-логики server-side приложения на GroovyСистема обработки бизнес-логики server-side приложения на Groovy
Система обработки бизнес-логики server-side приложения на GroovyRegn
 
How to Become a Thought Leader in Your Niche
How to Become a Thought Leader in Your NicheHow to Become a Thought Leader in Your Niche
How to Become a Thought Leader in Your NicheLeslie Samuel
 

Andere mochten auch (6)

Grails & Groovy
Grails & GroovyGrails & Groovy
Grails & Groovy
 
Groovy
GroovyGroovy
Groovy
 
Grails report, JEEConf 2012
Grails report, JEEConf 2012Grails report, JEEConf 2012
Grails report, JEEConf 2012
 
Скриптовой язык Groovy и его применение в рамках разработки ПО
Скриптовой язык Groovy и его применение в рамках разработки ПОСкриптовой язык Groovy и его применение в рамках разработки ПО
Скриптовой язык Groovy и его применение в рамках разработки ПО
 
Система обработки бизнес-логики server-side приложения на Groovy
Система обработки бизнес-логики server-side приложения на GroovyСистема обработки бизнес-логики server-side приложения на Groovy
Система обработки бизнес-логики server-side приложения на Groovy
 
How to Become a Thought Leader in Your Niche
How to Become a Thought Leader in Your NicheHow to Become a Thought Leader in Your Niche
How to Become a Thought Leader in Your Niche
 

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

Декораторы в Python и их практическое использование
Декораторы в Python и их практическое использование Декораторы в Python и их практическое использование
Декораторы в Python и их практическое использование Sergey Schetinin
 
Статический и динамический полиморфизм в C++, Дмитрий Леванов
Статический и динамический полиморфизм в C++, Дмитрий ЛевановСтатический и динамический полиморфизм в C++, Дмитрий Леванов
Статический и динамический полиморфизм в C++, Дмитрий ЛевановYandex
 
Встреча №9. Алгоритмы и коллекции стандартных библиотек C++, C#, Java, Object...
Встреча №9. Алгоритмы и коллекции стандартных библиотек C++, C#, Java, Object...Встреча №9. Алгоритмы и коллекции стандартных библиотек C++, C#, Java, Object...
Встреча №9. Алгоритмы и коллекции стандартных библиотек C++, C#, Java, Object...CocoaHeads
 
ASP.NET MVC - как построить по-настоящему гибкое веб-приложение
ASP.NET MVC - как построить по-настоящему гибкое веб-приложениеASP.NET MVC - как построить по-настоящему гибкое веб-приложение
ASP.NET MVC - как построить по-настоящему гибкое веб-приложениеAlexander Byndyu
 
Web осень 2013 лекция 6
Web осень 2013 лекция 6Web осень 2013 лекция 6
Web осень 2013 лекция 6Technopark
 
2015-12-06 Максим Юнусов - Проектирование REST приложения, или нужно ли прогр...
2015-12-06 Максим Юнусов - Проектирование REST приложения, или нужно ли прогр...2015-12-06 Максим Юнусов - Проектирование REST приложения, или нужно ли прогр...
2015-12-06 Максим Юнусов - Проектирование REST приложения, или нужно ли прогр...HappyDev
 
Functional Programming Dev Club 2009 - final
Functional Programming Dev Club 2009 - finalFunctional Programming Dev Club 2009 - final
Functional Programming Dev Club 2009 - finalAndrei Solntsev
 
Groovy presentation.
Groovy presentation.Groovy presentation.
Groovy presentation.Infinity
 
Sergii Tsypanov "Performance 1001 Tips"
Sergii Tsypanov "Performance 1001 Tips"Sergii Tsypanov "Performance 1001 Tips"
Sergii Tsypanov "Performance 1001 Tips"LogeekNightUkraine
 
Шаблоны проектирования 1
Шаблоны проектирования 1Шаблоны проектирования 1
Шаблоны проектирования 1Constantin Kichinsky
 
[JAM 1.1] Clean Code (Paul Malikov)
[JAM 1.1] Clean Code (Paul Malikov)[JAM 1.1] Clean Code (Paul Malikov)
[JAM 1.1] Clean Code (Paul Malikov)Evgeny Kaziak
 
ZFConf 2011: Разделение труда: Организация многозадачной, распределенной сист...
ZFConf 2011: Разделение труда: Организация многозадачной, распределенной сист...ZFConf 2011: Разделение труда: Организация многозадачной, распределенной сист...
ZFConf 2011: Разделение труда: Организация многозадачной, распределенной сист...ZFConf Conference
 
Объектное и прототипное программирование в Javascript
Объектное и прототипное программирование в JavascriptОбъектное и прототипное программирование в Javascript
Объектное и прототипное программирование в JavascriptDenis Latushkin
 
Архитектура корпоративных систем
Архитектура корпоративных системАрхитектура корпоративных систем
Архитектура корпоративных системConstantin Kichinsky
 
Time series data in a relational database. TimescaleDB and PipelineDB extensi...
Time series data in a relational database. TimescaleDB and PipelineDB extensi...Time series data in a relational database. TimescaleDB and PipelineDB extensi...
Time series data in a relational database. TimescaleDB and PipelineDB extensi...Ivan Muratov
 
Статический и динамический полиморфизм в C++, Дмитрий Леванов
Статический и динамический полиморфизм в C++, Дмитрий ЛевановСтатический и динамический полиморфизм в C++, Дмитрий Леванов
Статический и динамический полиморфизм в C++, Дмитрий ЛевановYandex
 
Разработка крупного Standalone проекта на юнити: улучшаем производительность
Разработка крупного Standalone проекта на юнити: улучшаем производительностьРазработка крупного Standalone проекта на юнити: улучшаем производительность
Разработка крупного Standalone проекта на юнити: улучшаем производительностьВадим Воробьев
 

Ähnlich wie Быть в 10 раз эффективнее благодаря Groovy (20)

Декораторы в Python и их практическое использование
Декораторы в Python и их практическое использование Декораторы в Python и их практическое использование
Декораторы в Python и их практическое использование
 
Net 3.0 & Linq
Net 3.0 & LinqNet 3.0 & Linq
Net 3.0 & Linq
 
Статический и динамический полиморфизм в C++, Дмитрий Леванов
Статический и динамический полиморфизм в C++, Дмитрий ЛевановСтатический и динамический полиморфизм в C++, Дмитрий Леванов
Статический и динамический полиморфизм в C++, Дмитрий Леванов
 
Встреча №9. Алгоритмы и коллекции стандартных библиотек C++, C#, Java, Object...
Встреча №9. Алгоритмы и коллекции стандартных библиотек C++, C#, Java, Object...Встреча №9. Алгоритмы и коллекции стандартных библиотек C++, C#, Java, Object...
Встреча №9. Алгоритмы и коллекции стандартных библиотек C++, C#, Java, Object...
 
ASP.NET MVC - как построить по-настоящему гибкое веб-приложение
ASP.NET MVC - как построить по-настоящему гибкое веб-приложениеASP.NET MVC - как построить по-настоящему гибкое веб-приложение
ASP.NET MVC - как построить по-настоящему гибкое веб-приложение
 
Web осень 2013 лекция 6
Web осень 2013 лекция 6Web осень 2013 лекция 6
Web осень 2013 лекция 6
 
Clojure #2 (2014)
Clojure #2 (2014)Clojure #2 (2014)
Clojure #2 (2014)
 
2015-12-06 Максим Юнусов - Проектирование REST приложения, или нужно ли прогр...
2015-12-06 Максим Юнусов - Проектирование REST приложения, или нужно ли прогр...2015-12-06 Максим Юнусов - Проектирование REST приложения, или нужно ли прогр...
2015-12-06 Максим Юнусов - Проектирование REST приложения, или нужно ли прогр...
 
Functional Programming Dev Club 2009 - final
Functional Programming Dev Club 2009 - finalFunctional Programming Dev Club 2009 - final
Functional Programming Dev Club 2009 - final
 
Groovy presentation.
Groovy presentation.Groovy presentation.
Groovy presentation.
 
Sergii Tsypanov "Performance 1001 Tips"
Sergii Tsypanov "Performance 1001 Tips"Sergii Tsypanov "Performance 1001 Tips"
Sergii Tsypanov "Performance 1001 Tips"
 
Android service
Android serviceAndroid service
Android service
 
Шаблоны проектирования 1
Шаблоны проектирования 1Шаблоны проектирования 1
Шаблоны проектирования 1
 
[JAM 1.1] Clean Code (Paul Malikov)
[JAM 1.1] Clean Code (Paul Malikov)[JAM 1.1] Clean Code (Paul Malikov)
[JAM 1.1] Clean Code (Paul Malikov)
 
ZFConf 2011: Разделение труда: Организация многозадачной, распределенной сист...
ZFConf 2011: Разделение труда: Организация многозадачной, распределенной сист...ZFConf 2011: Разделение труда: Организация многозадачной, распределенной сист...
ZFConf 2011: Разделение труда: Организация многозадачной, распределенной сист...
 
Объектное и прототипное программирование в Javascript
Объектное и прототипное программирование в JavascriptОбъектное и прототипное программирование в Javascript
Объектное и прототипное программирование в Javascript
 
Архитектура корпоративных систем
Архитектура корпоративных системАрхитектура корпоративных систем
Архитектура корпоративных систем
 
Time series data in a relational database. TimescaleDB and PipelineDB extensi...
Time series data in a relational database. TimescaleDB and PipelineDB extensi...Time series data in a relational database. TimescaleDB and PipelineDB extensi...
Time series data in a relational database. TimescaleDB and PipelineDB extensi...
 
Статический и динамический полиморфизм в C++, Дмитрий Леванов
Статический и динамический полиморфизм в C++, Дмитрий ЛевановСтатический и динамический полиморфизм в C++, Дмитрий Леванов
Статический и динамический полиморфизм в C++, Дмитрий Леванов
 
Разработка крупного Standalone проекта на юнити: улучшаем производительность
Разработка крупного Standalone проекта на юнити: улучшаем производительностьРазработка крупного Standalone проекта на юнити: улучшаем производительность
Разработка крупного Standalone проекта на юнити: улучшаем производительность
 

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

  • 1. Быть в 10 раз эффективнее благодаря Groovy Евгений Компаниец
  • 2. Smart1: система бронирования ТВ-рекламы Вся реклама на телеканалах 1+1, 2+2, ТЕТ, CITI продается через Smart1 Месячный оборот 00 000 000 гр. Информация о 1 300 000 размещениях рекламы Сложная модель продаж - аукцион  Отчеты  Интеграция с внешними системами: GFK Mark Data Media Workstation, 1C 2 разработчика; 1,5 года; внедрено на втором месяце разработки
  • 3.
  • 4. Архитектура CentOS 4.1.2 Java 1.6 64-Bit server Tomcat 6.0.20 Groovy 1.8.0 GWT 2.3.0 RPC Servlet Daemon Servlets GWT 2.3.0 Hibernate 3.3.x Ehcache 2.1.0 PostgreSQL 8.4.4
  • 5.
  • 7.
  • 9. От Java к Groovy Smart1 - наш второй groovy проект До перехода сомнения: что такого принципиального может дать groovy? зачем терять часть возможностей IDE? огромный тормоз После перехода: сожаление, что gwt не позволяет использовать groovy, чтобы полностью отказаться от java
  • 10. Опрос: Насколько Groovy эффективнее Java? 4-6 раз, коллеги Я бы сказал 2-3 раза, Алекс Ткачман Я обычно продуктивнее в 2 с лишним. Иногда groovy действительно упрощает проблему и я становлюсь в 3-5 раз продуктивнее. Давид Кларк Моя продуктивность легко достигает 10 раз. JochenTheodorou  
  • 11. Groovy - это гораздо больше, чем убрать из Java ; и типы! значительно меньше кода код значительно читабельнее значительно выше повторное использование легко создаются DSL не нужен псевдокод
  • 12. Коротко и выразительно! Взять все проходящие размещения и отсортировать сначала по цене, потом по дате создания placements.findAll { it.booked } .sort {p1, p2 ->          p2.wPrice <=> p1.wPrice ?:              p1.creationDate <=> p2.creationDate }
  • 13. List bookedPlacements = new ArrayList(); for (Placement placement : placements) { if (placement.isBooked()) {        bookedPlacements.add(placement);       } } Collections.sort(bookedPlacements, new Comparator<Placement>() {             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;             } });
  • 14. Коротко и выразительно! Вернуть короткие названия бюджетных месяцев def monthNames = budgets*.month*.shortName List monthNames = new ArrayList(); for (MonthBudget budget: budgets) { monthNames.add(budget.getMonth().getShortName()); }
  • 15. Коротко и выразительно! Эфирное время конца программы – это время начала первого из послепрограмных блоков, либо время конца программы blocks.findAll { it.position == AFTER }*.startTime.min() ?: endTime
  • 16. List afterBlocks = newArrayList (); for (Block block : blocks) { if (block.getPosition() == AFTER) { afterBlocks.add(block); } } if (afterBlocks.isEmpty()) { returnendTime; } Time minTime = new Time(0); for (Block block : afterBlocks) { if (block.getStartTime().isBefore(minTime)) { minTime = block.getStartTime(); } } returnminTime;
  • 17. Коротко и выразительно! Если плательщик задан, то вернуть его, иначе взять плательщика из прошлого периода. Если в прошлом периоде нет плательщиков, то взять любого из агентства. payee ?: prevInYear?.payee ?: (agency.payees as List)[0]
  • 18. if (payee != null) { return payee; } if (getPrevInYear() != null && getPrevInYear().getPayee() != null) { returnprevInYear.getPayee(); } returngetAgency().getPayees().iterator().next();
  • 19. Немного сложнее? Взять размещения из самой популярной категории placements.groupBy { it.category }.collect {it}                 .sort {it.value.size()}.last().value
  • 20. Java, с использованием «библиотечных» groupBy и last: List groupsList = new ArrayList((Util.groupBy(placements, new GroupSelector<CopyCategory, Placement>() { public CopyCategory getProperty(Placement p) { return p.getCopyCategory(); } })).entrySet()); Collections.sort(groupsList, newComparator<Map.Entry<CopyCategory, List<Placement>>>() { public int compare(Map.Entry<CopyCategory, List<Placement>> o1, Map.Entry<CopyCategory, List<Placement>> o2) { return((Integer) o1.getValue().size()) .compareTo(o2.getValue().size()); } }); return (List<Placement>) ((Map.Entry) Util.last(groupsList)).getValue();
  • 21. Java, прямая реализация: Map<CopyCategory, List<Placement>> categoryPlacements = new HashMap<CopyCategory, List<Placement>>(); 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);
  • 22. Сила Closure Настоящие возможности открываются, когда мы понимаем что такое Closure sort, findAll, groupByи т.п – все навсего методы принимающие Closure и мы можем делать такие свои
  • 23. Сила Closure Получить Mapвремя, на название (названия уникальны для времени) placements.mapUnique(‘time’) { it.name } Map<Time, String> timePlacements = newHashMap<Time, String>(); for (GfkPlacement placement: placements) { timePlacements.put(placement.time, placement.name); }
  • 24. Расширение существующих классов Мы можем добавлять методы и поля к уже написанным классам без наследования. Наш mapUnique можно вызывать на любой коллекции robot.grp = 22.centi scheduleMonth.month = 2009.jan block.startTime = /17:59/.time
  • 25. Расширение существующих классов Методы у Object дают нам следующий синтаксис: transaction { new User(‘New User’).dbStore() }
  • 26. Расширение существующих классов Сделаем немного удобнее Hibernate Criteria API: def clientGroups = RobotGroup.dbQuery.with { eq('deleted', false) createCriteria('copy').eq('_client', client) }.list()
  • 27. DSL делается легко 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) } }
  • 28. JFrame 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"); finalint[] 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);
  • 29. DSL делается легко shopList(client, 2011, 'TestShopList', primePercent: 70) {        discount(offPrime: -10.disc)        channelSl(channel, lowDiscount: -30.disc) {             monthSl(JAN, seasonal: -30.disc) {                 stdSl(100.centi)                 lowSl(400.centi)             }        } }
  • 30. Selenium junit тест void testPlace_SpotClient() { runTest(    agent, {        chooseCampaigns 'XC'          placeClick getBlock(1), 'XC'          waitForError 'No Shop List for Volvo in 2009'       },       sale, clients, {        changeToPerSpot 'Volvo'       },       ... ) }
  • 31. Динамика Динамическое программирование позволяет нам понять что такое повторное использование по настоящему! Например давайте перестанем каждый раз делать одно и тоже для Bidirectional Association и Lazy Initialization:
  • 32. Bidirectional Association class Program { @OneToMany (mappedBy = "_program")     Set<Block> _blocks = [] } class Block { @ManyToOne     Program _program }
  • 33. Bidirectional Association И теперь мы сразу можем работать: def p = new Program() def b = new Block() p << b p.addBlock(b) p.removeBlock(b) //valid properties: p.blocks (unmodifiable set), b.program
  • 34. Bidirectional Association Этого писать не нужно: class Program { ... voidaddBlock(Block b) {   b._program = this  }    voidremoveBlock(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)     } } }
  • 35. Lazy initialization Этого писать не нужно: class MonthBudget {  ...  Centi __actualBudget() {     ...  calculation  } } class MonthBudget { ...  Centi _actualBudget  defgetActualBudget() {   if(_actualBudget == null) {       _actualBudget = ...     }  } } println new MonthBudget().actualBudget
  • 36. Но не все так хорошо Скорость? IDE?
  • 37. Реально тормоз! Groovy работает в 10 раз медленнее Java
  • 38. Benchmark Groovy, Grovy++, Java https://github.com/alextkachman/fib-benchmark
  • 39. Но на этом можно работать Groovy работает также как Python, Ruby, PHP и т.п.
  • 40. Benchmark Java, Python, Ruby http://shootout.alioth.debian.org/
  • 41. Скорость Groovy не забываем, что часто узкое место база данных любой фрагмент можно переписать на java любой фрагмент можно переписать сделать Groovy++
  • 42. Groovy++ Статически типизированное расширение Groovy По скорости выполнения почти не уступает Java Может рассматриваться как альтернатива Scala Пишется небольшой группой энтузиастов (один хакер?), мало используется
  • 43. IDEA IDEA в целом очень хорошо поддерживает groovy: Для работы с динамическими методами и полями в IDEA есть Dynamic properties Работает выведение типов, в основном  Тем не менее: Для динамики мы теряем автоматический рефакторинги высокоуровневый поиск (findUsages) В отладчике иногда сильно тормозит Step Into