SlideShare a Scribd company logo
1 of 179
Download to read offline
Dlaczego DDD pomaga
skutecznie zapobiegać
chorobie legacy
Szymon Janikowski
Marcin Markowski
https://github.com/itlibrium
Szymon: @szjanikowski
Marcin: @technites_pl
http://itlibrium.com @itlibriun
Szymon Janikowski
@szjanikowski
https://github.com/itlibrium
http://itlibrium.com
Marcin Markowski
@technites_pl
Legacy - zespół chorób,
na który chorują całe
organizacje
WSPÓŁPRACA DDD
KOMPLEKSOWA OCHRONA PRZECIW LEGACY!
AGENDA
• OBJAWY

• WYSTĘPOWANIE (DOMENA)

• ZAPOBIEGANIE

• WSPÓŁPRACA MIĘDZY BIZNESEM i IT

• DOMAIN DRIVEN DESIGN

• CASE STUDY
OBJAWY
- po stronie biznesu
CORAZ TRUDNIEJ
MYŚLEĆ O KLIENTACH
JĘZYK TECHNICZNY
W ROZMOWACH
TRUDNO WDROŻYĆ
ZMIANY
AWARIE NA
PRODUKCJI
ROTACJA I
ROSNĄCE KOSZTY
OBJAWY
- po stronie IT
CHAOS W KODZIE
STRACH PRZED
WDRAŻANIEM ZMIAN
NISKIE MORALE
AIR-CON-SYS
AIR-CON-SYS
AIR-CON-SYS
AIR-CON-SYS
GWARANCJE
AIR-CON-SYS
GW
AIR-CON-SYS
GW
AIR-CON-SYS
GW
AIR-CON-SYS
GW
UMOWY
SERWISOWE
AIR-CON-SYS
UMOWA

SERWIS.
AIR-CON-SYS
AIR-CON-SYS
AIR-CON-SYS
F-VAT ?
AIR-CON-SYS
TANIE-ZLECENIA.PL
$$CHEAP-DEVS.COM
Po próbnym sprincie
public class ServiceService {
[…]
public void finish(int serviceId, Collection<Integer> sparePartIds)
throws BusinessException {
Service service = serviceRepository.Get(serviceId);
if (service.getStatus() != ServiceStatus.Scheduled) {
throw new BusinessException("Nieprawidłowy status usługi");
}
List<SparePart> spareParts = new ArrayList<>();
for (int sparePartId : sparePartIds) {
spareParts.add(sparePartRepository.Get(sparePartId));
}
service.setSpareParts(spareParts);
BigDecimal sparePartsCost = BigDecimal.valueOf(0);
for (SparePart sparePart : service.getSpareParts()) {
sparePartsCost = sparePartsCost.add(sparePart.Price);
}
PricingCategory pricingCategory =
service.getClient().getEquipmentModel().getPricingCategory();
BigDecimal labourCost = pricingCategory.getPricePerHour()
.multiply(BigDecimal.valueOf(service.getDuration()));
service.setPrice(pricingCategory.getMinPrice().max(labourCost)
.add(sparePartsCost));
service.setStatus(ServiceStatus.Done);
serviceRepository.Save(service);
}
}
Kilka sprintów
później…
JAK TO NIE DA SIĘ 

WPROWADZIĆ PŁATNEJ 

NAPRAWY PODCZAS 

PRZEGLĄDU
GWARANCYJNEGO !!!
JAK TO NIE DA SIĘ 

WPROWADZIĆ PŁATNEJ 

NAPRAWY PODCZAS 

PRZEGLĄDU
GWARANCYJNEGO !!!
blic void finish(int serviceId, Collection<Integer> sparePartIds) throws BusinessException {
Service service = serviceRepository.Get(serviceId);
if (service.getStatus() != ServiceStatus.Scheduled)
throw new BusinessException("Nieprawidłowy status usługi");
List<SparePart> spareParts = new ArrayList<>();
for (int sparePartId : sparePartIds)
{
spareParts.add(sparePartRepository.Get(sparePartId));
}
service.setSpareParts(spareParts);
BigDecimal price = BigDecimal.ZERO;
if (service.isWarranty())
{
price = BigDecimal.valueOf(0);
}
else
{
EquipmentModel equipmentModel = service.getClient().getEquipmentModel();
PricingCategory pricingCategory = equipmentModel.getPricingCategory();
Contract contract = service.getClient().getContract();
BigDecimal sparePartsCost = BigDecimal.valueOf(0);
for (SparePart sparePart : service.getSpareParts())
{
sparePartsCost = sparePartsCost.add(sparePart.Price);
}
if (contract == null)
{
price = pricingCategory.getMinPrice().max(pricingCategory.getPricePerHour()
.multiply(BigDecimal.valueOf(service.getDuration()))).add(sparePartsCost);
}
else
{
blic void finish(int serviceId, Collection<Integer> sparePartIds) throws BusinessException {
Service service = serviceRepository.Get(serviceId);
if (service.getStatus() != ServiceStatus.Scheduled)
throw new BusinessException("Nieprawidłowy status usługi");
List<SparePart> spareParts = new ArrayList<>();
for (int sparePartId : sparePartIds)
{
spareParts.add(sparePartRepository.Get(sparePartId));
}
service.setSpareParts(spareParts);
BigDecimal price = BigDecimal.ZERO;
if (service.isWarranty())
{
price = BigDecimal.valueOf(0);
}
else
{
EquipmentModel equipmentModel = service.getClient().getEquipmentModel();
PricingCategory pricingCategory = equipmentModel.getPricingCategory();
Contract contract = service.getClient().getContract();
BigDecimal sparePartsCost = BigDecimal.valueOf(0);
for (SparePart sparePart : service.getSpareParts())
{
sparePartsCost = sparePartsCost.add(sparePart.Price);
}
if (contract == null)
{
price = pricingCategory.getMinPrice().max(pricingCategory.getPricePerHour()
.multiply(BigDecimal.valueOf(service.getDuration()))).add(sparePartsCost);
}
else
{
CHEAP-DEVS
BIZNES IT
WYMAGANIA
WIEDZA
WIZJA
SPÓJNOŚĆ
I
MOŻLIWOŚCI
TECHNICZNE
PRODUKT
REALIZACJAREVIEW
ŹLE
ESTYMATY
BIZNES IT
WIEDZA
WIZJA
MOŻLIWOŚCI
TECHNICZNE
PRODUKT
REALIZACJA
REVIEW
DOBRZE!
SPÓJNOŚĆ
OGRANICZENIA
ŚRODKI
SOFTWARE
CRAFTSMANSHIP
BRAK ZAUFANIA
BRAK ZAUFANIA
OBAWA PRZED KONFLIKTEM
BRAK ZAUFANIA
OBAWA PRZED KONFLIKTEM
BRAK ZAANGAŻOWANIA
BRAK ZAUFANIA
OBAWA PRZED KONFLIKTEM
BRAK ZAANGAŻOWANIA
UNIKANIE
ODPOWIEDZIALNOŚCI
BRAK ZAUFANIA
OBAWA PRZED KONFLIKTEM
BRAK ZAANGAŻOWANIA
UNIKANIE
ODPOWIEDZIALNOŚCI
BRAK
DBAŁOŚCI
O WYNIKI
Model
Biznes
Bounded Context
Ubiquitous
Language
Model
Biznes
Bounded Context
Ubiquitous
Language
BOUNDED CONTEXT
LOGIKA DOMENOWA
LOGIKA APLIKACYJNA
BUILDING BLOCKS
AGREGAT
STANREGUŁY
ZACHOWANIA
AGREGAT AGREGAT!=
TAKIE SAME != TE SAME
VALUE OBJECT
VALUE OBJECT VALUE OBJECT==
TAKIE SAME
TE SAME
PRICE POLICY
f(x)
POLITYKA
INPUT OUTPUT
PRICE
POLICYf(x)
FABRYKA POLITYK
KONTEKST
POLITYKA
PRZERWA :)
SPRINT 1
Big Picture
+
Tactical
UMAWIANIE
TERMINÓW
OPERACJE
ROZLICZENIA
IoT
CRM
WYCENA
Interwencję można
zakończyć jeśli wszystkie
czynności serwisowe są
wycenione.
Interwencję można
zakończyć jeśli wszystkie
czynności serwisowe są
wycenione.
AGREGAT
Czynności serwisowe to w
tej chwili
przegląd i
naprawa
Czynności serwisowe to w
tej chwili
przegląd i
naprawa
VALUE
OBJECT
Wycena czynności zależy od
robocizny i kosztu części
zamiennych
Wycena czynności zależy od
robocizny i kosztu części
zamiennych
PRICE
POLICYf(x)
Ogólnie eksperymentujemy z
różnymi sposobami wyceny.
Ogólnie eksperymentujemy z
różnymi sposobami wyceny.
AGREGAT
VALUE
OBJECT
PRICE
POLICYf(x)
INTERWENCJA
CZYNNOŚĆ
SERWISOWA
POLITYKA
WYCENY
FABRYKA
POLITYK WYCENY
INTERVENTION
SERVICE ACTION
PRICE POLICY
PRICE POLICY FACTORY
POLICY FACTORY
INTERVENTION
PARTS
POLICY
LABOUR
POLICY
FINISH
POLICY FACTORY
INTERVENTION
PARTS
POLICY
LABOUR
POLICY
FINISH
SPRINT 1 - REVIEW
–Alberto Brandolini
„Software development is a LEARNING
PROCESS
Working code is a SIDE EFFECT”
CZY ZAPOBIEGAMY LEGACY ?
CZY DZIAŁAMY JAK ZESPÓŁ ?
• WYMIANA WIEDZY 

• POZNANIE ORGANIZACJI

• USTALENIE JĘZYKA!!
SPRINT 2
TEST FIRST!
def "Labour cost calculated correctly"() {
given:
_minPrice = minPrice;
_pricePerHour = pph;
_sparePartsPrices = [ 158 : Money.fromDouble(30),
333 : Money.fromDouble(40)];
_duration = duration;
_usedParts = usedPartsIds;
_actionType = actionType;
when:
serviceIsFinished();
then:
getInterventionPrice() == Money.fromDouble(price);
where:
minPrice | pph | duration | usedPartsIds | actionType || price
200 | 100 | 4 | [] | Review || 400
200 | 100 | 1 | [158, 333] | Repair || 270
200 | 100 | 1 | [] | Review || 200
200 | 100 | 0 | [333] | Repair || 240
300 | 100 | 0 | [] | Review || 300
400 | 0 | 10 | [158] | Repair || 430
}
POLICY FACTORY
INTERVENTION
PARTS
POLICY
LABOUR
POLICY
FINISH
POLICY FACTORY
INTERVENTION
PARTS
POLICY
LABOUR
POLICY
FINISH
public class FinishInterventionHandler {
[…]
public void finish(FinishInterventionCommand command) throws BusinessException {
Intervention intervention = interventionRepository
.get(command.getInterventionId());
PricePolicy pricePolicy = this.pricePolicyFactory.createFor(intervention);
intervention.finish(command.getServiceActions(), pricePolicy);
interventionRepository.save(intervention);
}
}
DDD v1
POLICY FACTORY
INTERVENTION
PARTS
POLICY
LABOUR
POLICY
PRICE
POLICY
PRICE
POLICY
FINISH
public class Intervention {
[…]
public void finish(Collection<ServiceAction> serviceActions, PricePolicy pricePolicy)
throws BusinessException {
if (this.serviceActions != null)
throw new BusinessException("Nie można zakończyć interwencji więcej niż raz");
this.serviceActions = new ArrayList<>(serviceActions);
price = this.serviceActions.stream()
.map(pricePolicy::apply)
.reduce(Money.ZERO, Money::sum);
}
}
DDD v1
POLICY FACTORY
INTERVENTION
PARTS
POLICY
LABOUR
POLICY
PRICE
POLICY
PRICE
POLICY
FINISH
public class PricePolicies {
public static PricePolicy labour(Money pricePerHour, Money minPrice) {
return serviceAction ->
Money.max(
Money.multiply(pricePerHour, serviceAction.getDuration().getHours()),
minPrice);
}
public static PricePolicy sparePartsCost(Map<Integer, Money> sparePartPrices) {
return serviceAction ->
serviceAction.getSparePartIds().stream()
.map(sparePartPrices::get)
.reduce(Money.ZERO, Money::sum);
}
[…]
}
DDD v1
POLICY FACTORY
INTERVENTION
PARTS
POLICY
LABOUR
POLICY
PRICE
POLICY
PRICE
POLICY
FINISH
public class PricePolicyFactory implements IPricePolicyFactory {
[…]
public PricePolicy createFor(Intervention intervention) {
[…]
return PricePolicies.sum(
PricePolicies.labour(
Money.fromDecimal(pricingCategory.getPricePerHour()),
Money.fromDecimal(pricingCategory.getMinPrice())),
PricePolicies.sparePartsCost(sparePartPrices));
}
}
DDD v1
SPRINT 2 - REVIEW
CZY ZAPOBIEGAMY LEGACY ?
CZY DZIAŁAMY JAK ZESPÓŁ ?
• POGŁĘBIENIE WIEDZY

• REALIZACJA WIZJI (ZAUFANIE)
SPRINT 3
GWARANCJE
AIR-CON-SYS
GW
AIR-CON-SYS
GW
AIR-CON-SYS
GW
AIR-CON-SYS
GW
Dodajemy 2 nowe
CZYNNOŚCI SERWISOWE:
PRZEGLĄD GWARANCYJNY
NAPRAWA GWARANCYJNA
TEST FIRST!
def "Labour cost calculated correctly"() {
given:
_minPrice = minPrice;
_pricePerHour = pph;
_sparePartsPrices = [ 158 : Money.fromDouble(30),
333 : Money.fromDouble(40)];
_duration = duration;
_usedParts = usedPartsIds;
_actionType = actionType;
when:
serviceIsFinished();
then:
getInterventionPrice() == Money.fromDouble(price);
where:
minPrice | pph | duration | usedPartsIds | actionType || price
200 | 100 | 4 | [] | Review || 400
200 | 100 | 1 | [158, 333] | Repair || 270
200 | 100 | 1 | [] | Review || 200
200 | 100 | 0 | [333] | Repair || 240
300 | 100 | 0 | [] | Review || 300
400 | 0 | 10 | [158] | Repair || 430
400 | 0 | 1 | [] | WarrantyReview || 0
200 | 100 | 2 | [158] | WarrantyRepair || 0
}
POLICY FACTORY
INTERVENTION
PARTS
POLICY
LABOUR
POLICY
FINISH
FREE
POLICY
PRICE
POLICY
PARTS
POLICY
PRICE
POLICY
public class PricePolicies {
public static PricePolicy labour(Money pricePerHour, Money minPrice) {
return serviceAction ->
Money.max(
Money.multiply(pricePerHour, serviceAction.getDuration().getHours()),
minPrice);
}
public static PricePolicy sparePartsCost(Map<Integer, Money> sparePartPrices) {
return serviceAction ->
serviceAction.getSparePartIds().stream()
.map(sparePartPrices::get)
.reduce(Money.ZERO, Money::sum);
}
public static PricePolicy free() {
return serviceAction -> Money.ZERO;
}
}
DDD v2
public class PricePolicies {
public static PricePolicy labour(Money pricePerHour, Money minPrice) {
return serviceAction ->
Money.max(
Money.multiply(pricePerHour, serviceAction.getDuration().getHours()),
minPrice);
}
public static PricePolicy sparePartsCost(Map<Integer, Money> sparePartPrices) {
return serviceAction ->
serviceAction.getSparePartIds().stream()
.map(sparePartPrices::get)
.reduce(Money.ZERO, Money::sum);
}
public static PricePolicy free() {
return serviceAction -> Money.ZERO;
}
}
JEDNA NOWA
POLITYKA
DDD v2
POLICY FACTORY
INTERVENTION
PARTS
POLICY
LABOUR
POLICY
FINISH
FREE
POLICY
PRICE
POLICY
PARTS
POLICY
PRICE
POLICY
DDD v2
public class PricePolicyFactory implements IPricePolicyFactory {
[…]
public PricePolicy CreateFor(Intervention intervention) {
[…]
return PricePolicies.sum(
PricePolicies.when(
PricePolicyFactory::isRegularAction,
PricePolicies.sum(
PricePolicies.labour(
pricingCategory.getPricePerHour(),
pricingCategory.getMinPrice(),
PricePolicies.sparePartsCost(sparePartPrices))),
PricePolicies.when(
PricePolicyFactory::isWarrantyAction,
PricePolicies.free()));
}
}
DDD v2
public class PricePolicyFactory implements IPricePolicyFactory {
[…]
public PricePolicy CreateFor(Intervention intervention) {
[…]
return PricePolicies.sum(
PricePolicies.when(
PricePolicyFactory::isRegularAction,
PricePolicies.sum(
PricePolicies.labour(
pricingCategory.getPricePerHour(),
pricingCategory.getMinPrice(),
PricePolicies.sparePartsCost(sparePartPrices))),
PricePolicies.when(
PricePolicyFactory::isWarrantyAction,
PricePolicies.free()));
}
}
SPRINT 3 - REVIEW
CZY ZAPOBIEGAMY LEGACY ?
CZY DZIAŁAMY JAK ZESPÓŁ ?
• BARDZO SZYBKIE DOSTARCZENIE

• WYKORZYSTANIE ELASTYCZNOŚCI 

MODELU

• WZROST ZAUFANIA
SPRINT 4
UMOWY SERWISOWE
AIR-CON-SYS
UMOWA

SERWIS.
AIR-CON-SYS
F-VAT ?
Umowa
serwisowa
Zakończenie
interwencji
może obniżyć cenę
wykorzystuje limity
POLICY FACTORY
INTERVENTION
PARTS
POLICY
LABOUR
POLICY
FINISH
FREE
POLICY
PRICE
POLICY
PARTS
POLICY
PRICE
POLICY
?
public class PricePolicies {
public static PricePolicy labour(Money pricePerHour, Money minPrice) {
return serviceAction ->
Money.max(
Money.multiply(pricePerHour, serviceAction.getDuration().getHours()),
minPrice);
}
public static PricePolicy sparePartsCost(Map<Integer, Money> sparePartPrices) {
return serviceAction ->
serviceAction.getSparePartIds().stream()
.map(sparePartPrices::get)
.reduce(Money.ZERO, Money::sum);
}
public static PricePolicy free() {
return fixed(Money.ZERO);
}
public static PricePolicy fixed(BigDecimal value) {
return fixed(Money.fromDecimal(value));
}
public static PricePolicy fixed(Money value) {
return serviceAction -> value;
}
}
DDD v2
public class PricePolicies {
public static PricePolicy labour(Money pricePerHour, Money minPrice) {
return serviceAction ->
Money.max(
Money.multiply(pricePerHour, serviceAction.getDuration().getHours()),
minPrice);
}
public static PricePolicy sparePartsCost(Map<Integer, Money> sparePartPrices) {
return serviceAction ->
serviceAction.getSparePartIds().stream()
.map(sparePartPrices::get)
.reduce(Money.ZERO, Money::sum);
}
public static PricePolicy free() {
return fixed(Money.ZERO);
}
public static PricePolicy fixed(BigDecimal value) {
return fixed(Money.fromDecimal(value));
}
public static PricePolicy fixed(Money value) {
return serviceAction -> value;
}
}
POLITYKA
ZMIENIAJĄCA
UMOWĘ?
DDD v2
public class PricePolicies {
public static PricePolicy labour(Money pricePerHour, Money minPrice) {
return serviceAction ->
Money.max(
Money.multiply(pricePerHour, serviceAction.getDuration().getHours()),
minPrice);
}
public static PricePolicy sparePartsCost(Map<Integer, Money> sparePartPrices) {
return serviceAction ->
serviceAction.getSparePartIds().stream()
.map(sparePartPrices::get)
.reduce(Money.ZERO, Money::sum);
}
public static PricePolicy free() {
return fixed(Money.ZERO);
}
public static PricePolicy fixed(BigDecimal value) {
return fixed(Money.fromDecimal(value));
}
public static PricePolicy fixed(Money value) {
return serviceAction -> value;
}
}
DDD v2
?
WYCENA interwencji i
aktualizacja 

UMOWY SERWISOWEJ
są niezależne
PRZEŁOM!
POLICY FACTORY
INTERVENTION
PARTS
POLICY
LABOUR
POLICY
FINISH
FREE
POLICY
CONTRACT
PRICING SERVICE
LIMITS
USAGE
POLICY FACTORY
INTERVENTION
PARTS
POLICY
LABOUR
POLICY
FINISH
FREE
POLICY
CONTRACT
PRICING SERVICE
LIMITS
USAGE
POLICY FACTORY
INTERVENTION
PARTS
POLICY
LABOUR
POLICY
FINISH
FREE
POLICY
CONTRACT
PRICING SERVICE
LIMITS
USAGE
AGREGAT
VALUE
OBJECT
UMOWA SERWISOWA
LIMITY UMOWY
WYCENA
INTERWENCJI
SERWIS
WYCENIAJĄCY
CONTRACT
CONTRACT LIMITS
INTERVENTION
PRICING
PRICING
SERVICE
VALUE
OBJECT
SERWIS
DOMENOWY
SPRINT 4 - REVIEW
CZY ZAPOBIEGAMY LEGACY ?
CZY DZIAŁAMY JAK ZESPÓŁ ?
• PRZECHODZENIE PRZEZ KONFLIKT

• PRÓBA ZAUFANIA

• NIE DOPUSZCZAMY DO ROZWIĄZANIA 

„NA KRÓTKO”
SPRINT 5…
TEST FIRST!
def "Contracts allows certain number of free interventions"() {
given:
_interventionsLimit = i10nsLimit;
_interventionsUsed = i10nsUsedBefore;
_actionType = actionType;
when:
serviceIsFinished();
then:
getInterventionPrice() == Money.fromDouble(total);
getInterventionsLimitUsed() == i10sUsedAfter;
where:
i10nsLimit | i10nsUsedBefore | actionType || total | i10sUsedAfter
2 | 0 | Repair || 0 | 1
2 | 0 | WarrantyReview || 0 | 0
2 | 2 | Repair || 300 | 2
0 | 0 | Repair || 300 | 0
}
def "Contracts allows spare parts usage up to a limit"() {
given:
_sparePartsPrices = [ 5 : Money.fromDouble(50),
2 : Money.fromDouble(20)]
_sparePartsLimit = partsLimit
_sparePartsLimitUsed = limitBefore
labourIsFree()
_usedParts = usedParts;
_actionType = actionType;
when:
serviceIsFinished();
then:
getInterventionPrice() == Money.fromDouble(total);
getSparePartsLimitUsed() == Money.fromDouble(limitAfter);
where:
partsLimit | limitBefore | actionType | usedParts || total |limitAfter
100 | 0 | Repair | [5,5] || 0 | 100
100 | 0 | Repair | [5,5,2] || 20 | 100
100 | 20 | Repair | [2] || 0 | 40
100 | 50 | WarrantyRepair| [5] || 0 | 50
0 | 0 | Repair | [5,2] || 70 | 0
}
POLICY FACTORY
INTERVENTION
PARTS
POLICY
LABOUR
POLICY
FINISH
FREE
POLICY
CONTRACT
PRICING SERVICE
LIMITS
PRICING
USAGE
PRICING
PRICE
POLICY
PARTS
POLICY
PRICE
POLICY
DDD v3
public class Intervention {
[…]
public void Finish(Collection<ServiceAction> serviceActions,
InterventionPricing interventionPricing)
throws BusinessException {
if (this.serviceActions != null)
throw new BusinessException("Nie można zakończyć interwencji więcej niż raz");
this.serviceActions = new ArrayList<>(serviceActions);
price = interventionPricing.getTotalPrice();
}
}
DDD v3
public class Intervention {
[…]
public void Finish(Collection<ServiceAction> serviceActions,
InterventionPricing interventionPricing)
throws BusinessException {
if (this.serviceActions != null)
throw new BusinessException("Nie można zakończyć interwencji więcej niż raz");
this.serviceActions = new ArrayList<>(serviceActions);
price = interventionPricing.getTotalPrice();
}
}
ZMIANA PARAMETRU
POLICY FACTORY
INTERVENTION
PARTS
POLICY
LABOUR
POLICY
FINISH
FREE
POLICY
CONTRACT
PRICING SERVICE
LIMITS
PRICING
USAGE
PRICING
PRICE
POLICY
PARTS
POLICY
PRICE
POLICY
public class PricingService implements IPricingService {
private IPricePolicyFactory pricePolicyFactory;
public PricingService(IPricePolicyFactory pricePolicyFactory) {
this.pricePolicyFactory = pricePolicyFactory;
}
public InterventionPricing GetPricingFor(Intervention intervention,
Collection<ServiceAction> serviceActions,
ContractLimits contractLimits) {
PricePolicy pricePolicy = pricePolicyFactory.CreateFor(intervention);
Money totalPrice = Money.ZERO;
for (ServiceAction serviceAction : serviceActions) {
PricingContext context = new PricingContext(serviceAction, contractLimits);
Pricing pricing = pricePolicy.apply(context);
contractLimits = pricing.getContractLimits();
totalPrice = Money.sum(totalPrice, pricing.getValue());
}
return new InterventionPricing(totalPrice, contractLimits);
}
}
DDD v3
POLICY FACTORY
INTERVENTION
PARTS
POLICY
LABOUR
POLICY
FINISH
FREE
POLICY
CONTRACT
PRICING SERVICE
LIMITS
PRICING
USAGE
PRICING
PRICE
POLICY
PARTS
POLICY
PRICE
POLICY
public static PricePolicy labour(Money pricePerHour, Money minPrice,
InterventionDuration freeInterventionTimeLimit) {
return context ->
{
FreeInterventionsLimit freeInterventionsLimit =
context.getContractLimits().getFreeInterventionsLimit();
if (freeInterventionsLimit.usedInCurrentIntervention()) {
Money labourOverLimit =
labourOverLimit(context, pricePerHour, freeInterventionTimeLimit);
return new Pricing(context.getContractLimits(), labourOverLimit);
}
if (freeInterventionsLimit.canUse()) {
ContractLimits modifiedContractLimits =
context.getContractLimits().UseFreeIntervention();
Money labourOverLimit =
labourOverLimit(context, pricePerHour, freeInterventionTimeLimit);
return new Pricing(modifiedContractLimits, labourOverLimit);
}
Money labour = labour(context, pricePerHour, minPrice);
return new Pricing(context.getContractLimits(), labour);
};
}
DDD v3
POLICY FACTORY
INTERVENTION
PARTS
POLICY
LABOUR
POLICY
FINISH
FREE
POLICY
CONTRACT
PRICING SERVICE
LIMITS
PRICING
USAGE
PRICING
PRICE
POLICY
PARTS
POLICY
PRICE
POLICY
public class PricePolicyFactory implements IPricePolicyFactory {
[…]
public PricePolicy CreateFor(Intervention intervention) {
[…]
return PricePolicies.sum(
PricePolicies.when(
PricePolicyFactory::isRegularAction,
PricePolicies.sum(
PricePolicies.labour(
pricingCategory.getPricePerHour(),
pricingCategory.getMinPrice(),
freeInterventionTimeLimit,
PricePolicies.sparePartsCost(sparePartPrices))),
PricePolicies.when(
PricePolicyFactory::isWarrantyAction,
PricePolicies.free()));
}
}
DDD v3
public class PricePolicyFactory implements IPricePolicyFactory {
[…]
public PricePolicy CreateFor(Intervention intervention) {
[…]
return PricePolicies.sum(
PricePolicies.when(
PricePolicyFactory::isRegularAction,
PricePolicies.sum(
PricePolicies.labour(
pricingCategory.getPricePerHour(),
pricingCategory.getMinPrice(),
freeInterventionTimeLimit,
PricePolicies.sparePartsCost(sparePartPrices))),
PricePolicies.when(
PricePolicyFactory::isWarrantyAction,
PricePolicies.free()));
}
}
DDD v3
POLICY FACTORY
INTERVENTION
PARTS
POLICY
LABOUR
POLICY
FINISH
FREE
POLICY
CONTRACT
PRICING SERVICE
LIMITS
USAGE
POLICY FACTORY
INTERVENTION
PARTS
POLICY
LABOUR
POLICY
FINISH
FREE
POLICY
CONTRACT
PRICING SERVICE
LIMITS
USAGE
POLICY FACTORY
INTERVENTION
PARTS
POLICY
LABOUR
POLICY
FINISH
FREE
POLICY
CONTRACT
PRICING SERVICE
LIMITS
USAGE
public void finish(FinishInterventionCommand command) throws BusinessException {
Intervention intervention = interventionRepository.Get(command.getInterventionId());
IContract contract = contractRepository.GetForClient(intervention.getClientId());
ContractLimits contractLimits = contract.GetContractLimits();
InterventionPricing interventionPricing =
pricingService.GetPricingFor(intervention, command.getServiceActions(),
contractLimits);
intervention.Finish(command.getServiceActions(), interventionPricing);
interventionRepository.Save(intervention);
contract.AddUsage(interventionPricing.getContractLimits());
contractRepository.Save(contract);
}
DDD v3
public void finish(FinishInterventionCommand command) throws BusinessException {
Intervention intervention = interventionRepository.Get(command.getInterventionId());
IContract contract = contractRepository.GetForClient(intervention.getClientId());
ContractLimits contractLimits = contract.GetContractLimits();
InterventionPricing interventionPricing =
pricingService.GetPricingFor(intervention, command.getServiceActions(),
contractLimits);
intervention.Finish(command.getServiceActions(), interventionPricing);
interventionRepository.Save(intervention);
contract.AddUsage(interventionPricing.getContractLimits());
contractRepository.Save(contract);
}
DDD v3
2 AGREGATY
W TRANSAKCJI ?
SPRINT 5 - REVIEW
CZY ZAPOBIEGAMY LEGACY ?
CZY DZIAŁAMY JAK ZESPÓŁ ?
• SPRAWDZENIE SIĘ W 

TRUDNEJ SYTUACJI

• POTWIERDZENIE WSPÓLNYCH

CELÓW
WSPÓŁPRACA DDD
KOMPLEKSOWA OCHRONA PRZECIW LEGACY!
BIZNES IT
WIEDZA
WIZJA
MOŻLIWOŚCI
TECHNICZNE
PRODUKT
REALIZACJA
REVIEW
DOBRZE!
SPÓJNOŚĆ
OGRANICZENIA
BIZNES - PODSUMOWANIE
• BUDOWANIE ZAUFANIA I
PRZEJRZYSTOŚCI

• WSPÓLNY JĘZYK W KOMUNIKACJI

• WSPÓLNE CELE Z IT
IT - PODSUMOWANIE
• SKUPIENIE NA ABSTRAKCJACH
BIZNESOWYCH

• PORZĄDEK I STRUKTURA W KODZIE

• WSPÓLNE CELE Z BIZNESEM
https://github.com/itlibrium
Dzięki!
Szymon: @szjanikowski
Marcin: @technites_pl
https://github.com/itlibrium
Pytania?
Szymon: @szjanikowski
Marcin: @technites_pl
Szymon Janikowski
@szjanikowski
https://github.com/itlibrium
http://itlibrium.com
Marcin Markowski
@technites_pl
Postaci SouthPark - SP-STUDIO.DE

Flooded office:

http://cdn.abclocal.go.com/content/wtvd/images/cms/automation/vod/991300_1280x720.jpg

AIR CONDITIONING PHOTOS:

https://commons.wikimedia.org/wiki/File:Industrial_air_conditioning_unit_(DFdB).JPG#filelinks

https://commons.wikimedia.org/wiki/File:2008-08-23_Durham_Regional_Hospital_air_conditioner.jpg

https://commons.wikimedia.org/wiki/File:2008-07-11_Air_conditioners_at_UNC-CH.jpg

https://commons.wikimedia.org/wiki/File:Centralized_Air_conditioning.jpg

Icons made by:

• http://www.freepik.com

• https://www.flaticon.com/authors/nikita-golubev

• https://www.flaticon.com/authors/smashicons

More Related Content

Similar to Dlaczego DDD skutecznie zapobiega chorobie legacy ?

Maximal: Comparison of Optimization Modeling Software for Python - Oct 2012
Maximal: Comparison of Optimization Modeling Software for Python - Oct 2012Maximal: Comparison of Optimization Modeling Software for Python - Oct 2012
Maximal: Comparison of Optimization Modeling Software for Python - Oct 2012
Bjarni Kristjánsson
 

Similar to Dlaczego DDD skutecznie zapobiega chorobie legacy ? (20)

Spring AOP
Spring AOPSpring AOP
Spring AOP
 
Implementing Clean Architecture
Implementing Clean ArchitectureImplementing Clean Architecture
Implementing Clean Architecture
 
Bootiful Development with Spring Boot and React - Dublin JUG 2018
Bootiful Development with Spring Boot and React - Dublin JUG 2018Bootiful Development with Spring Boot and React - Dublin JUG 2018
Bootiful Development with Spring Boot and React - Dublin JUG 2018
 
Good code
Good codeGood code
Good code
 
Wcf data services
Wcf data servicesWcf data services
Wcf data services
 
Is writing performant code too expensive?
Is writing performant code too expensive? Is writing performant code too expensive?
Is writing performant code too expensive?
 
Service Oriented Architecture in Magento 2
Service Oriented Architecture in Magento 2Service Oriented Architecture in Magento 2
Service Oriented Architecture in Magento 2
 
Biz Talk Server Certification
Biz Talk Server CertificationBiz Talk Server Certification
Biz Talk Server Certification
 
Einführung in mdx
Einführung in mdxEinführung in mdx
Einführung in mdx
 
Maximal: Comparison of Optimization Modeling Software for Python - Oct 2012
Maximal: Comparison of Optimization Modeling Software for Python - Oct 2012Maximal: Comparison of Optimization Modeling Software for Python - Oct 2012
Maximal: Comparison of Optimization Modeling Software for Python - Oct 2012
 
Adopting F# at SBTech
Adopting F# at SBTechAdopting F# at SBTech
Adopting F# at SBTech
 
Intalio|Cloud Presentation
Intalio|Cloud PresentationIntalio|Cloud Presentation
Intalio|Cloud Presentation
 
Bootiful Development with Spring Boot and React
Bootiful Development with Spring Boot and ReactBootiful Development with Spring Boot and React
Bootiful Development with Spring Boot and React
 
Automated Design Validation The Solid Works Api
Automated Design Validation The Solid Works ApiAutomated Design Validation The Solid Works Api
Automated Design Validation The Solid Works Api
 
Enforce Consistency through Application Infrastructure
Enforce Consistency through Application InfrastructureEnforce Consistency through Application Infrastructure
Enforce Consistency through Application Infrastructure
 
Web components in Angular (Angular Elements) | Walkingtree Technologies
Web components in Angular (Angular Elements) | Walkingtree TechnologiesWeb components in Angular (Angular Elements) | Walkingtree Technologies
Web components in Angular (Angular Elements) | Walkingtree Technologies
 
Lviv MDDay 2014. Ігор Коробка “забезпечення базової безпеки в андроїд аплікац...
Lviv MDDay 2014. Ігор Коробка “забезпечення базової безпеки в андроїд аплікац...Lviv MDDay 2014. Ігор Коробка “забезпечення базової безпеки в андроїд аплікац...
Lviv MDDay 2014. Ігор Коробка “забезпечення базової безпеки в андроїд аплікац...
 
C# Tutorial MSM_Murach chapter-13-slides
C# Tutorial MSM_Murach chapter-13-slidesC# Tutorial MSM_Murach chapter-13-slides
C# Tutorial MSM_Murach chapter-13-slides
 
Events on the outside, on the inside and at the core (jfokus jfokus2016)
Events on the outside, on the inside and at the core (jfokus jfokus2016)Events on the outside, on the inside and at the core (jfokus jfokus2016)
Events on the outside, on the inside and at the core (jfokus jfokus2016)
 
Policy Injection in ASP.NET using Enterprise Library 3.0
Policy Injection in ASP.NET using Enterprise Library 3.0Policy Injection in ASP.NET using Enterprise Library 3.0
Policy Injection in ASP.NET using Enterprise Library 3.0
 

Recently uploaded

Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
vu2urc
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
Joaquim Jorge
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
Enterprise Knowledge
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
Earley Information Science
 

Recently uploaded (20)

Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdf
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 

Dlaczego DDD skutecznie zapobiega chorobie legacy ?