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

Презентация:



Advertisements
Похожие презентации
Контейнеры Сортировка Метод sort() Интерфейс Comparable метод int compareTo(Object o) вызов: Arrays.sort(a) Интерфейс Comparator метод int compare(Object.
Advertisements

Трансляция кода из Groovy в Java в IntelliJ IDEA Дипломная работа Медведева Максима Научный руководитель: Громов П. С.
Ассоциативные списки Поиск данных происходит не по индексу или положению объекта, а по его ассоциативной связи: public interface Map { // Доступ к объектам.
САОД кафедра ОСУ 1 Основные абстрактные типы данных Схема процесса создания программ для решения прикладных задач ВУ.
Java Collections Framework (JCF) in Java Tutorial for students of universities Author: Oxana Dudnik.
Коллекции классов Лекция 12. С помощью коллекций вместо создания структур данных программист использует готовые структуры данных, не заботясь об их реализации.
Перегрузка операторов x = a + b результат 1-й операнд2-й операнд оператор По количеству операндов операторы делятся на: унарные (один операнд) бинарные.
Д.з Язык С++ - занятие 31. Задача 1: 1/1 + 1/3 + 1/5 … #include using namespace std; int main() { int n; cin >> n; double sum = 0;// Сумма for.
Практическое программирование на Java к.ф.-м.н. Козлов Дмитрий Дмитриевич Кафедра АСВК, Лаборатория Вычислительных комплексов.
Mock-объекты mock (англ.) – ложный, фиктивный, мнимый, фальшивый, поддельный.
Лекция 2.Основы объектной модели Java 1. Содержание 1.Основы ООП. 2.Понятия «класс» и «объект». 3.Поля и методы класса. Спецификаторы доступа: public,
АССОЦИАТИВНЫЕ КОЛЛЕКЦИИ Лекция 6 1. Отличие от последовательных 2 В последовательной коллекции каждый элемент ассоциируется с номером, начиная с 0. В.
Практическое программирование на Java к.ф.-м.н. Козлов Дмитрий Дмитриевич Кафедра АСВК, Лаборатория Вычислительных комплексов.
Идентификация типа во время выполнения RTTI. Механизм состоит из нескольких частей: Базовые средства RTTI лежат в основе механизма полиморфизма. При первом.
Статические поля класса Статические поля хранят данные, общие для всех элементов класса. Статическое поле существует в единственном экземпляре для всех.
Делегаты Как созданные объекты могут посылать сообщения тем объектам, которые их породили? При программировании под Windows на С и C++ основное средство.
Презентация к дипломной работе Разработка многопрофильной системы информационного поиска.
1 Java 10. КОЛЛЕКЦИИ Основные концепции. Интерфейсы. Списки.
Java : массивы и коллекции. Массивы Массивы простых типов: int []a = new int[10]; int []b = new int[]{ 0, 1, 2, 3, 4, 5 }; Массивы ссылочных типов (reference.
Учебный курс Объектно-ориентированный анализ и программирование Лекция 7 Методы как средство реализации операций Лекции читает кандидат технических наук.
Транксрипт:

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

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

Архитектура CentOS PostgreSQL Tomcat Hibernate 3.3.x Ehcache Java Bit server GWT GWT RPC Servlet Groovy DaemonServlets

Разработка Java Bit server IntelliJ IDEA 10 GIT Maven 2 Jetbrains TeamCity Selenium Тестов Время сборки 40 мин Установка на рабочий сервер 2 раза в неделю

Производительность Денормализация структуры БД Тяжелые отчеты обновляются по расписанию Ряд задач выполняется только ночью HP Proliant DL360G6 2xQuad CPU 12G RAM Пиковая нагрузка 40 gwt rpc запросов в секунду

Строки кода

От Java к Groovy Smart1 - наш второй groovy проект До перехода сомнения: –что такого принципиального может дать groovy? –зачем терять часть возможностей IDE? –огромный тормоз После перехода: –сожаление, что gwt не позволяет использовать groovy, чтобы полностью отказаться от java

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

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

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

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

Коротко и выразительно! Эфирное время конца программы – это время начала первого из послепрограмных блоков, либо время конца программы blocks.findAll { it.position == AFTER }*.startTime.min() ?: endTime

List 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) { 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;

Коротко и выразительно! Если плательщик задан, то вернуть его, иначе взять плательщика из прошлого периода. Если в прошлом периоде нет плательщиков, то взять любого из агентства. payee ?: prevInYear?.payee ?: (agency.payees as List)[0]

if (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 && getPrevInYear().getPayee() != null) { return prevInYear.getPayee(); } return getAgency().getPayees().iterator().next();

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

Java, с использованием «библиотечных» 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(); 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, прямая реализация: 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); 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);

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

Сила Closure Получить Map время, на название (названия уникальны для времени) placements.mapUnique(time) { it.name } Map timePlacements = new HashMap (); for (GfkPlacement placement: placements) { timePlacements.put(placement.time, placement.name); } Map timePlacements = new HashMap (); 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() } transaction { new User(New User).dbStore() }

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

DSL делается легко 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) } 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) }

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' },... ) } 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 (mappedBy = "_program") Set _blocks = [] } class Block Program _program } class Program (mappedBy = "_program") Set _blocks = [] } class Block Program _program }

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

Bidirectional Association Этого писать не нужно: class Program {... void addBlock(Block b) { b._program = this } void removeBlock(Block b) { b._program = null } 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) } 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() {... calculation } class MonthBudget {... Centi _actualBudget def getActualBudget() { if (_actualBudget == null) { _actualBudget =... } class MonthBudget {... Centi _actualBudget def getActualBudget() { if (_actualBudget == null) { _actualBudget =... } println new MonthBudget().actualBudget

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

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

Benchmark Groovy, Grovy++, Java

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

Benchmark Java, Python, Ruby

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

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

IDEA IDEA в целом очень хорошо поддерживает groovy: Для работы с динамическими методами и полями в IDEA есть Dynamic properties Работает выведение типов, в основном Тем не менее: Для динамики мы теряем автоматический рефакторинг и высокоуровневый поиск (findUsages) В отладчике иногда сильно тормозит Step Into

Спасибо