jboss drools expert -...

44
ВИКТОР ПОЛИЩУК JBoss Drools Expert

Upload: ngonguyet

Post on 18-Mar-2018

247 views

Category:

Documents


5 download

TRANSCRIPT

Page 1: JBoss Drools Expert - 2013.jokerconf.com2013.jokerconf.com/presentations/...viktor_jboss_drools_expert_ru.pdf · 3+ лет программирования на Drools

ВИКТОР ПОЛИЩУК

JBoss Drools Expert

Page 2: JBoss Drools Expert - 2013.jokerconf.com2013.jokerconf.com/presentations/...viktor_jboss_drools_expert_ru.pdf · 3+ лет программирования на Drools

Виктор Полищук

10+ лет коммерческой разработки

8+ лет работы с Java

3+ лет программирования на Drools

Участвовал/видел 50+ «проблемных» (из-за высокой нагружености логикой) проектов

0 из 9 «провальных» проектов на Drools

Технический лидер в Infopulse, Ukraine

Контрактор в BICS, Belgium

Page 3: JBoss Drools Expert - 2013.jokerconf.com2013.jokerconf.com/presentations/...viktor_jboss_drools_expert_ru.pdf · 3+ лет программирования на Drools

«Простой» «Хитрый»

2.00

за SMS

0.00

за первые 10 SMS/день

1.50

за SMS внутри сети

2.50

за SMS

JokerMobile™

Page 4: JBoss Drools Expert - 2013.jokerconf.com2013.jokerconf.com/presentations/...viktor_jboss_drools_expert_ru.pdf · 3+ лет программирования на Drools

Модель Данных: Customer

public class Customer {

String number;

Tariff tariff;

}

Page 5: JBoss Drools Expert - 2013.jokerconf.com2013.jokerconf.com/presentations/...viktor_jboss_drools_expert_ru.pdf · 3+ лет программирования на Drools

Модель Данных: SMS

public class Sms {

String sender;

String receiver;

DateTime sent;

}

Page 6: JBoss Drools Expert - 2013.jokerconf.com2013.jokerconf.com/presentations/...viktor_jboss_drools_expert_ru.pdf · 3+ лет программирования на Drools

Модель Данных: BillingRecord

public class BillingRecord {

Customer customer;

BigDecimal price;

Sms sms;

}

Page 7: JBoss Drools Expert - 2013.jokerconf.com2013.jokerconf.com/presentations/...viktor_jboss_drools_expert_ru.pdf · 3+ лет программирования на Drools

Java FTW

Пишем God класс

Делим логику на стратегии по тарифам

Делим логику на атомарные стратегии

Что-то еще

Page 8: JBoss Drools Expert - 2013.jokerconf.com2013.jokerconf.com/presentations/...viktor_jboss_drools_expert_ru.pdf · 3+ лет программирования на Drools

API

public interface TariffStrategy {

Collection<BillingRecord> calculate(

Customer customer,

Interval interval

);

}

Page 9: JBoss Drools Expert - 2013.jokerconf.com2013.jokerconf.com/presentations/...viktor_jboss_drools_expert_ru.pdf · 3+ лет программирования на Drools

«Хитрая» Стратегия: стр. 1

Collection<Sms> messages = dao.findBySender(customer.getNumber(), interval); Collection<SmsBillingRecord> records = new ArrayList<SmsBillingRecord>(); Map<DateTime, List<Sms>> dailyMap = new HashMap<DateTime, List<Sms>>(); for (Sms sms : messages) { DateTime date = sms.getSent().withMillisOfDay(0); List<Sms> collection = dailyMap.get(date); if (collection == null) { collection = new ArrayList<Sms>(); dailyMap.put(date, collection); } collection.add(sms); }

Page 10: JBoss Drools Expert - 2013.jokerconf.com2013.jokerconf.com/presentations/...viktor_jboss_drools_expert_ru.pdf · 3+ лет программирования на Drools

«Хитрая» Стратегия: стр. 2

for (List<Sms> value : dailyMap.values()) { Collections.sort(value, SMSComparator.INSTANCE); for (int i = 0; i < value.size(); i++) { Sms sms = value.get(i); if (i < 10) { records.add(new BillingRecord(customer, BigDecimal.ZERO, sms)); } else if (dao.findByNumber(sms.getReceiver()) != null) { records.add(new BillingRecord(customer, new BigDecimal("1.5"), sms)); } else { records.add(new BillingRecord(customer, new BigDecimal("2.5"), sms)); } } } return records;

Page 11: JBoss Drools Expert - 2013.jokerconf.com2013.jokerconf.com/presentations/...viktor_jboss_drools_expert_ru.pdf · 3+ лет программирования на Drools

ПРАЗДНИК

Полный Успех

Page 12: JBoss Drools Expert - 2013.jokerconf.com2013.jokerconf.com/presentations/...viktor_jboss_drools_expert_ru.pdf · 3+ лет программирования на Drools

Бонус

Может быть применен к любому тарифу

Могут складываться друг с другом

Правила наложения могут быть уникальны

Page 13: JBoss Drools Expert - 2013.jokerconf.com2013.jokerconf.com/presentations/...viktor_jboss_drools_expert_ru.pdf · 3+ лет программирования на Drools

Модель Данных: Customer+

public class Customer {

String number;

Tariff tariff;

Collection<Bonus> bonuses;

}

Page 14: JBoss Drools Expert - 2013.jokerconf.com2013.jokerconf.com/presentations/...viktor_jboss_drools_expert_ru.pdf · 3+ лет программирования на Drools

Бонус: «Двадцать»

Платеж 100.00 в месяц

Скидка 20% на все SMS

Page 15: JBoss Drools Expert - 2013.jokerconf.com2013.jokerconf.com/presentations/...viktor_jboss_drools_expert_ru.pdf · 3+ лет программирования на Drools

Модель Данных: BillingRecord+

public abstract class BillingRecord { Customer customer; BigDecimal price; } public class SmsBillingRecord extends BillingRecord { Sms sms; } public class FixedBillingRecord extends BillingRecord { }

Page 16: JBoss Drools Expert - 2013.jokerconf.com2013.jokerconf.com/presentations/...viktor_jboss_drools_expert_ru.pdf · 3+ лет программирования на Drools

Java FTW

Растим God класс

Пишем все в стратегии

Выносим цены в некий PriceManager

Создаем слой модифицирующий BillingRecord

Что-то еще

Page 17: JBoss Drools Expert - 2013.jokerconf.com2013.jokerconf.com/presentations/...viktor_jboss_drools_expert_ru.pdf · 3+ лет программирования на Drools

БЕСПОКОЙСТВО

Частичный Успех

Page 18: JBoss Drools Expert - 2013.jokerconf.com2013.jokerconf.com/presentations/...viktor_jboss_drools_expert_ru.pdf · 3+ лет программирования на Drools

Бонус: «Два по Пятьдесят»

После порога в 50 SMS в день:

Удваиваем количество бесплатных SMS

Скидка 50% на последующие SMS до конца дня

Page 19: JBoss Drools Expert - 2013.jokerconf.com2013.jokerconf.com/presentations/...viktor_jboss_drools_expert_ru.pdf · 3+ лет программирования на Drools

Java WTF

Убиваемся о God класс

Меняем PriceManager

Добавляем LimitManager

Меняем «модифицирующий» слой: Передаем доп.информацию про стратегии и бонусы

Усложняем логику

Начинаем сначала

Что-то еще

Page 20: JBoss Drools Expert - 2013.jokerconf.com2013.jokerconf.com/presentations/...viktor_jboss_drools_expert_ru.pdf · 3+ лет программирования на Drools

ДЕПРЕССИЯ... НЕНАВИСТЬ... РАЗДРАЖЕНИЕ... МИЗАНТРОПИЯ... ЗАМКНУТОСТЬ...

УСТАЛОСТЬ... АПАТИЯ...

Я Сделал Все Что Мог

Page 21: JBoss Drools Expert - 2013.jokerconf.com2013.jokerconf.com/presentations/...viktor_jboss_drools_expert_ru.pdf · 3+ лет программирования на Drools

Drools Expert

Продукционная экспертная система

Построена на базе «Rete-сети»

Отличная документация

Открытый код

Бесплатная

Поддерживается JBoss

Page 22: JBoss Drools Expert - 2013.jokerconf.com2013.jokerconf.com/presentations/...viktor_jboss_drools_expert_ru.pdf · 3+ лет программирования на Drools

Глоссарий

Working Memory

Rule Engine

Knowledge Base

Fact Fact Fact

Rule Rule Rule

Page 23: JBoss Drools Expert - 2013.jokerconf.com2013.jokerconf.com/presentations/...viktor_jboss_drools_expert_ru.pdf · 3+ лет программирования на Drools

Базовый Синтаксис

rule “<Имя правила>”

<опции>

when

<условие или LHS>

then

<следствие или RHS>

end

Page 24: JBoss Drools Expert - 2013.jokerconf.com2013.jokerconf.com/presentations/...viktor_jboss_drools_expert_ru.pdf · 3+ лет программирования на Drools

Drools: Тариф «Простой»

rule “Billing: charge -Simple-”

when

$customer : Customer(tariff==Tariff.SIMPLE)

Charge($sms : sms, customer==$customer)

then

log.info(“Charge {} as {}”, $sms, 2.0);

insertLogical(

new SmsBillingRecord($customer,2.0,$sms)

);

end

Page 25: JBoss Drools Expert - 2013.jokerconf.com2013.jokerconf.com/presentations/...viktor_jboss_drools_expert_ru.pdf · 3+ лет программирования на Drools

Charge?

public class Charge {

Customer customer;

Sms sms;

}

<или>

declare Charge

customer : Customer @key

sms : Sms @key

end

Page 26: JBoss Drools Expert - 2013.jokerconf.com2013.jokerconf.com/presentations/...viktor_jboss_drools_expert_ru.pdf · 3+ лет программирования на Drools

Drools: А Кто Платить Будет!?…

rule “Default: sender is in charge” when $period : Interval() $sms : Sms($sender : sender, $period.contains(sent)) $customer : Customer(number==$sender) not Charge(customer!=$customer, sms==$sms) then log.info(“Mark {} as regular”, $sms); insertLogical(new Charge($customer, $sms)); end

Page 27: JBoss Drools Expert - 2013.jokerconf.com2013.jokerconf.com/presentations/...viktor_jboss_drools_expert_ru.pdf · 3+ лет программирования на Drools

Drools: Тариф «Хитрый» стр. 1

rule “Tariff -Smart-: free SMS” when Day($period : interval) $customer : Customer(tariff==Tariff.SMART) Charge($sms : sms, customer==$customer, $period.contains(sms.sent)) accumulate($c : Charge(customer==$customer, $period.contains(sms.sent), !sms.sent.isAfter($sms.sent)); $count : count( $c ); $count<=10) then log.info(“Mark {} as free”, $sms); insertLogical(new ChargeAsFree($customer, $sms)); end

Page 28: JBoss Drools Expert - 2013.jokerconf.com2013.jokerconf.com/presentations/...viktor_jboss_drools_expert_ru.pdf · 3+ лет программирования на Drools

Drools : Тариф «Хитрый» стр. 2

rule “Tariff -Smart-: local SMS” when Day($period : interval) $customer : Customer(tariff==Tariff.SMART) Charge($sms : sms, customer==$customer, $period.contains(sms.sent)) not ChargeAsFree(customer==$customer, sms==$sms) exists Customer(number==$sms.receiver) then log.info(“Mark {} as local”, $sms); insertLogical(new ChargeAsLocal($customer, $sms)); end

Page 29: JBoss Drools Expert - 2013.jokerconf.com2013.jokerconf.com/presentations/...viktor_jboss_drools_expert_ru.pdf · 3+ лет программирования на Drools

Drools: Тариф «Хитрый» стр. 3

rule “Billing: free of charge” when $customer : Customer() ChargeAsFree($sms : sms, $customer==customer) then log.info(“Charge {} as {}”, $sms, 0.0); insertLogical( new SmsBillingRecord($customer, 0.0, $sms) ); end

Page 30: JBoss Drools Expert - 2013.jokerconf.com2013.jokerconf.com/presentations/...viktor_jboss_drools_expert_ru.pdf · 3+ лет программирования на Drools

Drools: Тариф «Хитрый» стр. 4

rule “Billing: charge local in –Smart-” when $customer : Customer(tariff==Tariff.SMART) ChargeAsLocal($sms : sms, customer==$customer) not ChargeAsFree(sms==$sms) then log.info(“Charge {} as {}”, $sms, 1.5); insertLogical( new SmsBillingRecord($customer, 1.5, $sms) ); end

Page 31: JBoss Drools Expert - 2013.jokerconf.com2013.jokerconf.com/presentations/...viktor_jboss_drools_expert_ru.pdf · 3+ лет программирования на Drools

Drools: Тариф «Хитрый» стр. 5

rule “Billing: charge others in –Smart-” when $customer : Customer(tariff==Tariff.SMART) Charge($sms : sms, customer==$customer) not ChargeAsFree(sms==$sms) not ChargeAsLocal(sms==$sms) then log.info(“Charge {} as {}”, $sms, 2.5); insertLogical( new SmsBillingRecord($customer, 2.5, $sms) ); end

Page 32: JBoss Drools Expert - 2013.jokerconf.com2013.jokerconf.com/presentations/...viktor_jboss_drools_expert_ru.pdf · 3+ лет программирования на Drools

Drools: Бонус «Двадцать»

rule “Subscription -20%-: refund” when $customer : Customer(bonuses contains Bonus.TWENTY) Charge($sms : sms, customer==$customer) not ChargeAsFree(sms==$sms) not Modifier(sms==$sms, modifier<0.8) then log.info(“Add modifier {} to {}”, 0.8, $sms); insertLogical(new Modifier($sms, 0.8)); end

Page 33: JBoss Drools Expert - 2013.jokerconf.com2013.jokerconf.com/presentations/...viktor_jboss_drools_expert_ru.pdf · 3+ лет программирования на Drools

Drools: Тариф «Хитрый» стр. 4+

rule “Billing: charge local in –Smart-” when $customer : Customer(tariff==Tariff.SMART) ChargeAsLocal($sms : sms, customer==$customer) not ChargeAsFree(sms==$sms) Modifier($modifier : modifier, sms==$sms) then BigDecimal price = $modifier * 1.5; log.info(“Charge {} as {}”, $sms, price); insertLogical( new SmsBillingRecord($customer, price, $sms) ); end

Page 34: JBoss Drools Expert - 2013.jokerconf.com2013.jokerconf.com/presentations/...viktor_jboss_drools_expert_ru.pdf · 3+ лет программирования на Drools

ВЫ ЧТО, ВСЕ ЕЩЕ КОДИТЕ БИЗНЕС -ПРАВИЛА?

Domain Specific Language

Page 35: JBoss Drools Expert - 2013.jokerconf.com2013.jokerconf.com/presentations/...viktor_jboss_drools_expert_ru.pdf · 3+ лет программирования на Drools

Drools: Тариф «Хитрый» стр. 4+

rule “Billing: charge local in –Smart-” when $customer : Customer(tariff==Tariff.SMART) ChargeAsLocal($sms : sms, customer==$customer) not ChargeAsFree(customer==$customer, sms==$sms) Modifier($modifier : modifier, sms==$sms) then BigDecimal price = $modifier * 1.5; log.info(“Charge {} as {}”, $sms, price); insertLogical( new SmsBillingRecord($customer, price, $sms) ); end

Page 36: JBoss Drools Expert - 2013.jokerconf.com2013.jokerconf.com/presentations/...viktor_jboss_drools_expert_ru.pdf · 3+ лет программирования на Drools

DSL: Тариф «Хитрый» стр. 4+

rule “Billing: charge local in –Smart-” when Find a customer - with Tariff.SMART Find customer’s local SMS Proceed only if it is not free Find an SMS modifier then Create SMS billing record with base price: 1.5 end

Page 37: JBoss Drools Expert - 2013.jokerconf.com2013.jokerconf.com/presentations/...viktor_jboss_drools_expert_ru.pdf · 3+ лет программирования на Drools

DSL Словарь

[when] Find a customer = $customer : Customer() [when] - with {tariff} = tariff=={tariff} [when] Find customer’s local SMS = ChargeAsLocal($sms : sms, customer==$customer)

...

...

...

...

... [then] Create SMS billing record with base price: {base} = BigDecimal price = $modifier * {base}; log.info(“Charge {} as {}”, $sms, price); insertLogical(new SmsBillingRecord($customer, price, $sms));

Page 38: JBoss Drools Expert - 2013.jokerconf.com2013.jokerconf.com/presentations/...viktor_jboss_drools_expert_ru.pdf · 3+ лет программирования на Drools

ЛЕКАРСТВО ОТ РАБСТВА

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

Page 39: JBoss Drools Expert - 2013.jokerconf.com2013.jokerconf.com/presentations/...viktor_jboss_drools_expert_ru.pdf · 3+ лет программирования на Drools

Подсказки

Работаем с production knowledge base

Готовим крошечные тестовые данные

Выбираем дружелюбные критерии прохождения

Тестируем business case, а не Drools

Performance тесты тоже важны

Page 40: JBoss Drools Expert - 2013.jokerconf.com2013.jokerconf.com/presentations/...viktor_jboss_drools_expert_ru.pdf · 3+ лет программирования на Drools

Тестируем Drools:

private final Customer callee = new Customer(“007”, Tariff.SIMPLE); private final Interval billingPeriod = new Interval( new DateTime(2013, 9, 1, 0, 0, 0, 0), new DateTime(2013, 10, 1, 0, 0, 0, 0) ); @Test public void testSimple() { DateTime instant = new DateTime(2013, 9, 20, 4, 40, 11); BigDecimal expectedResult = new BigDecimal(“2.0”); BigDecimal actualResult = executeGetAmount(callee, generateSMS(“007”, “any”, instant, 0, 1), billingPeriod, callee ); assertEquals(expectedResult, actualResult); }

Page 41: JBoss Drools Expert - 2013.jokerconf.com2013.jokerconf.com/presentations/...viktor_jboss_drools_expert_ru.pdf · 3+ лет программирования на Drools

ЕЩЕ ЧУТЬ-ЧУТЬ И ПЕРЕРЫВ

Итоги

Page 42: JBoss Drools Expert - 2013.jokerconf.com2013.jokerconf.com/presentations/...viktor_jboss_drools_expert_ru.pdf · 3+ лет программирования на Drools

Достоинства

Отделение логики от «бизнес-логики»

Независимые правила

Менять правила может даже аналитик

Тесты свободные от Mock-ов

«Теплый, ламповый» Java код

Приемлемая производительность

... и другая куча «плюшек»

Page 44: JBoss Drools Expert - 2013.jokerconf.com2013.jokerconf.com/presentations/...viktor_jboss_drools_expert_ru.pdf · 3+ лет программирования на Drools

ЗА ВНИМАНИЕ

Спасибо