SlideShare a Scribd company logo
1 of 40
Download to read offline
Refatorando com a API
funcional do Java
Giovane Liberato @ JUG Vale 14
Agenda
● Introdução ao Refactoring
● Catálogo de Refactorings
○ Ouça (ou leia) sua IDE
○ Composição de regras com
Predicates
○ Optionals - Quando (não)
usar
○ Inversão de dependências
com Suppliers
○ Funções idiomáticas
Giovane Liberato
Senior Software Engineer no *
Foco em arquitetura de micro serviços, desenvolvimento seguro e
práticas ágeis. Interesse em privacidade digital e criptografia.
about.me/giovaneliberato
* Temos vagas! (E são remotas)
Introdução ao
Refactoring
Refactoring is a controlled technique for improving the
design of an existing code base.
Its essence is applying a series of small
behavior-preserving transformations, each of which "too
small to be worth doing".
Martin Fowler,
autor do livro “Refactoring Improving the Design of Existing Code”
Mudanças pequenas e
constantes que geram enorme
benefício a longo prazo
Objetivos e focados em melhoria
de arquitetura, legibilidade e na
redução de débitos técnicos
Cercado de testes para garantir
que não há quebra de
comportamento
Red -> Green -> Refactor
Evoluir a codebase para
acomodar novas features e
reduzir acoplamento entre
componentes do sistema
Como fazer
Catálogo de
Refactorings
Lembrete
Isso não é o refactoring mais grandioso do mundo,
isso é apenas um tributo
Ouça (ou leia) sua IDE
Composição de regras com Predicates
Cenário
Dado um usuário que contém uma lista de tags, definir qual o valor do cupom de
desconto gerado
Atores
Account, VoucherService e VoucherPredicates
Code smells
Implementação obstruindo legibilidade, lógicas binárias encadeadas no mesmo
IF
public Voucher getVoucherForAccount(Account account) {
if (account.getTags().contains("new")) {
return Voucher.of(15);
}
if (account.getTags().contains("lover")) {
return Voucher.of(20);
}
if (account.getTags().contains("veg")
&& account.getTags().contains("new")) {
return Voucher.of(25);
}
if (account.getTags().contains("lover")
&& (account.getTags().contains("pizza_lover")
|| account.getTags().contains("burger_lover"))) {
return Voucher.of(35);
}
return Voucher.none();
}
public static BiPredicate<Account, String> containsTag =
(account, tag)-> account.getTags().contains(tag);
public static Predicate<Account> IS_NEW =
(account) -> containsTag.test(account, "new");
public static Predicate<Account> IS_LOVER =
(account) -> containsTag.test(account, "lover");
public static Predicate<Account> IS_VEG =
(account) -> containsTag.test(account, "veg");
public static Predicate<Account> IS_PIZZA_LOVER =
(account) -> containsTag.test(account, "pizza_lover");
public static Predicate<Account> IS_BURGER_LOVER =
(account) -> containsTag.test(account, "burger_lover");
public Voucher getVoucherForAccount(Account account) {
if (IS_NEW.test(account)) {
return Voucher.of(15);
}
if (IS_LOVER.test(account)) {
return Voucher.of(20);
}
if (IS_VEG.and(IS_NEW).test(account)) {
return Voucher.of(25);
}
if (IS_LOVER.and(IS_PIZZA_LOVER.or(IS_BURGER_LOVER)).test(account)) {
return Voucher.of(35);
}
return Voucher.none();
}
Optionals - Quando (não) usar
Cenário
Um usuário pode favoritar e bloquear restaurantes do seu menu. Ambas as listas
podem ser vazias.
Atores
Account, Restaurant, RestaurantService e RestaurantRepository
Code smells
Optional como atributo de classe, chamada dos métodos .isPresent e .get,
Optional representando estado domínio
public class Account {
private Optional<List<Restaurant>> starredRestaurants;
private Optional<List<Restaurant>> blockedRestaurants;
public Optional<List<Restaurant>> getBlockedRestaurants() {
return blockedRestaurants;
}
public Optional<List<Restaurant>> getStarredRestaurants() {
return starredRestaurants;
}
}
public List<Restaurant> getRestaurantsForAccount(Account account) {
var restaurants = RestaurantRepository.getAll();
if (account.getBlockedRestaurants().isPresent()) {
var blocked = account.getBlockedRestaurants().get();
restaurants = restaurants
.stream()
.filter((r -> blocked.contains(r)))
.collect(toList());
}
if (account.getStarredRestaurants().isPresent()) {
restaurants.addAll(account.getStarredRestaurants().get());
}
return restaurants;
}
Optionals - usando .orElse
public List<Restaurant> getRestaurantsForAccount(Account account) {
var restaurants = RestaurantRepository.getAll();
var blocked = account.getBlockedRestaurants().orElse(emptyList());
restaurants = restaurants
.stream()
.filter((r -> blocked.contains(r)))
.collect(toList());
restaurants.addAll(account.getStarredRestaurants().orElse(emptyList()));
return restaurants;
}
Optionals - removendo das classes
public class Account {
private List<Restaurant> starredRestaurants;
private List<Restaurant> blockedRestaurants;
public List<Restaurant> getBlockedRestaurants() {
return blockedRestaurants != null ?
blockedRestaurants : emptyList();
}
public List<Restaurant> getStarredRestaurants() { ... }
}
public List<Restaurant> getRestaurantsForAccount(Account account) {
var restaurantList = RestaurantRepository.getAll();
var blocked = account.getBlockedRestaurants();
var starred = account.getStarredRestaurants();
return Stream.concat(
starred.stream(),
restaurantList
.stream()
.filter((blocked::contains)))
.collect(toList());
}
Inversão de dependência com suppliers
Cenário
Criação de objetos complexos baseado em diferentes fontes de dados
Atores
Account, Driver, CampaignService e CampaignFactory
Code smells
Inveja de funcionalidade (feature envy) e assinatura de métodos parcialmente
repetidas
public class Account {
private String pushNotificationId;
public String getPushNotificationId() { … }
}
-----------------------------------------------------------------
public class Driver {
private String pushNotificationId;
public String getPushNotificationId() { … }
}
public class CampaignFactory {
private AccountRepository accountRepository;
private DriversRepository driversRepository;
public Campaign buildCampaignForNewUsers(Country country, Message message) { … }
public Campaign buildCampaign(Country country, Message message) { … }
public Campaign buildCampaign(List<Account> accounts,Message message) { … }
public Campaign buildCampaignForDrivers(Country country, Message message) { … }
}
public Campaign buildCampaignForNewUsers(
Country country, Message message) {
var pushIds = accountRepository
.findNewUsersByCountry(country)
.stream()
.map(Account::getPushNotificationId)
.collect(toList());
return Campaign
.builder()
.pushNotificationIds(pushIds)
.message(message)
.build();
}
public Campaign buildCampaignForDrivers(
Country country, Message message) {
var pushIds = driversRepository
.findDriversByCountry(country)
.stream()
.map(Driver::getPushNotificationId)
.collect(toList());
return Campaign
.builder()
.pushNotificationIds(pushIds)
.message(message)
.build();
}
public Campaign buildCampaign(List<Account> accounts, Message message) {
var pushIds = accounts
.stream()
.map(Account::getPushNotificationId)
.collect(toList());
return Campaign
.builder()
.pushNotificationIds(pushIds)
.message(message)
.build();
}
public class CampaignService {
CampaignFactory campaignFactory;
public Campaign createCampaignForNewUsers(Country country) {
var message = new Message("welcome");
return campaignFactory.buildCampaignForNewUsers(country, message);
}
public Campaign createCampaignForAllUsers(Country country) {
var message = new Message("#lanches");
return campaignFactory.buildCampaign(country, message);
}
public Campaign createCampaignForUsers(List<Account> accounts) {
var message = new Message("#lanches");
return campaignFactory.buildCampaign(accounts, message);
}
public Campaign createCampaignForAllDrivers(Country country) {
var message = new Message("bonus!");
return campaignFactory.buildCampaignForDrivers(country, message);
}
}
public class CampaignService {
CampaignFactory campaignFactory;
private AccountRepository accountRepository;
private DriversRepository driversRepository;
public Campaign createCampaignForNewUsers(Country country) { .. }
public Campaign createCampaignForAllDrivers(Country country) { .. }
// ...
}
Invertendo dependência
public class CampaignFactory {
public Campaign buildCampaign(
Supplier<List<String>> idsSupplier, Message message) {
return Campaign
.builder()
.pushNotificationIds(idsSupplier.get())
.message(message)
.build();
}
}
public Campaign createCampaignForNewUsers(Country country) {
var message = new Message("welcome");
Supplier<List<String>> ids = () ->
accountRepository.findNewUsersByCountry(country)
.stream()
.map(Account::getPushNotificationId)
.collect(toList());
return campaignFactory.buildCampaign(ids, message);
}
public Campaign createCampaignForAllDrivers(Country country) {
var message = new Message("bonus!");
Supplier<List<String>> ids = () ->
driversRepository.findDriversByCountry(country)
.stream()
.map(Driver::getPushNotificationId)
.collect(toList());
return campaignFactory.buildCampaign(ids, message);
}
Funções idiomáticas
Cenário
Para usar funções customizadas, o contra-exemplo implementa a interface
Function sem necessidade.
Atores
Account, AccountToNameConverter
Code smells
Implementando interfaces funcionais para casos simples. Múltiplas classes para
contextos parecidos
public class AccountToNameConverter
implements Function<Account, String> {
@Override
public String apply(Account account) {
return String.format("%s %s",
account.getFirstName(), account.getLastName());
}
public class AccountService {
private AccountToNameConverter converter =
new AccountToNameConverter();
public List<String> getEveryonesName(List<Account> accounts) {
return accounts
.stream()
.map(converter)
.collect(toList());
}
}
public class AccountToNameConverter {
public static String convert(Account acc) {
return String.format("%s%s",
acc.getFirstName(), acc.getLastName());
}
public static String convertLastFirst(Account acc) {
return String.format("%s %s",
acc.getLastName(), acc.getFirstName());
}
}
public class AccountService {
public List<String> getEveryonesName(List<Account> accounts) {
return accounts
.stream()
.map(AccountToNameConverter::convert) // ou___
.map(AccountToNameConverter::convertLastFirst)
.collect(toList());
}
Referências
Refactoring - Improving the Design of Existing Code (Martin Fowler)
Effective Java, Third Edition Keepin' it Effective (J. Bloch)
Optional - The Mother of All Bikesheds (Stuart Marks)
Understanding the Economics of Refactoring (Leitch, Stroulia)
The Financial Implications of Technical Debt (Erik Frederick)
Códigos disponíveis em
https://github.com/giovaneliberato/refactoring-java-8plus
Obrigado!
about.me/giovaneliberato

More Related Content

Similar to Refatorando com a API funcional do Java

IAP auto renewable in practice
IAP auto renewable  in practiceIAP auto renewable  in practice
IAP auto renewable in practiceHokila Jan
 
Velocity 2014: Accelerate Your User Experience With Client-side JavaScript
Velocity 2014: Accelerate Your User Experience With Client-side JavaScriptVelocity 2014: Accelerate Your User Experience With Client-side JavaScript
Velocity 2014: Accelerate Your User Experience With Client-side JavaScriptIntuit Inc.
 
Wave Analytics: Developing Predictive Business Intelligence Apps
Wave Analytics: Developing Predictive Business Intelligence AppsWave Analytics: Developing Predictive Business Intelligence Apps
Wave Analytics: Developing Predictive Business Intelligence AppsSalesforce Developers
 
Audit¢rio 09 mercado envios - novas funcionalidades - bruno elia
Audit¢rio 09   mercado envios - novas funcionalidades - bruno eliaAudit¢rio 09   mercado envios - novas funcionalidades - bruno elia
Audit¢rio 09 mercado envios - novas funcionalidades - bruno eliafsolari
 
Opticon 2015 - Getting Started with the Optimizely Developer Platform
Opticon 2015 - Getting Started with the Optimizely Developer PlatformOpticon 2015 - Getting Started with the Optimizely Developer Platform
Opticon 2015 - Getting Started with the Optimizely Developer PlatformOptimizely
 
Introduction to Domain driven design (LaravelBA #5)
Introduction to Domain driven design (LaravelBA #5)Introduction to Domain driven design (LaravelBA #5)
Introduction to Domain driven design (LaravelBA #5)guiwoda
 
Intershop Commerce Management with Microsoft SQL Server
Intershop Commerce Management with Microsoft SQL ServerIntershop Commerce Management with Microsoft SQL Server
Intershop Commerce Management with Microsoft SQL ServerMauro Boffardi
 
How AdWords UI maps into adwords api
How AdWords UI maps into adwords apiHow AdWords UI maps into adwords api
How AdWords UI maps into adwords apisupergigas
 
A Practical Approach to Building a Streaming Processing Pipeline for an Onlin...
A Practical Approach to Building a Streaming Processing Pipeline for an Onlin...A Practical Approach to Building a Streaming Processing Pipeline for an Onlin...
A Practical Approach to Building a Streaming Processing Pipeline for an Onlin...Databricks
 
ATAGTR2017 Test Approach for Re-engineering Legacy Applications based on Micr...
ATAGTR2017 Test Approach for Re-engineering Legacy Applications based on Micr...ATAGTR2017 Test Approach for Re-engineering Legacy Applications based on Micr...
ATAGTR2017 Test Approach for Re-engineering Legacy Applications based on Micr...Agile Testing Alliance
 
How to Leverage APIs for SEO #TTTLive2019
How to Leverage APIs for SEO #TTTLive2019How to Leverage APIs for SEO #TTTLive2019
How to Leverage APIs for SEO #TTTLive2019Paul Shapiro
 
Making Service Portal Widgets Work Together
Making Service Portal Widgets Work TogetherMaking Service Portal Widgets Work Together
Making Service Portal Widgets Work TogetherTravisToulson
 
Let's your users share your App with Friends: App Invites for Android
 Let's your users share your App with Friends: App Invites for Android Let's your users share your App with Friends: App Invites for Android
Let's your users share your App with Friends: App Invites for AndroidWilfried Mbouenda Mbogne
 
Optimizing Code Reusability for SharePoint using Linq to SharePoint & the MVP...
Optimizing Code Reusability for SharePoint using Linq to SharePoint & the MVP...Optimizing Code Reusability for SharePoint using Linq to SharePoint & the MVP...
Optimizing Code Reusability for SharePoint using Linq to SharePoint & the MVP...Sparkhound Inc.
 
PHPUnit Episode iv.iii: Return of the tests
PHPUnit Episode iv.iii: Return of the testsPHPUnit Episode iv.iii: Return of the tests
PHPUnit Episode iv.iii: Return of the testsMichelangelo van Dam
 
SH 1 - SES 8 - Stitch_Overview_TLV.pptx
SH 1 - SES 8 - Stitch_Overview_TLV.pptxSH 1 - SES 8 - Stitch_Overview_TLV.pptx
SH 1 - SES 8 - Stitch_Overview_TLV.pptxMongoDB
 
Agados-based Application Design Demo
Agados-based Application Design Demo Agados-based Application Design Demo
Agados-based Application Design Demo Yongkyoo Park
 
AwReporting Update
AwReporting UpdateAwReporting Update
AwReporting Updatemarcwan
 
Simplify Feature Engineering in Your Data Warehouse
Simplify Feature Engineering in Your Data WarehouseSimplify Feature Engineering in Your Data Warehouse
Simplify Feature Engineering in Your Data WarehouseFeatureByte
 

Similar to Refatorando com a API funcional do Java (20)

IAP auto renewable in practice
IAP auto renewable  in practiceIAP auto renewable  in practice
IAP auto renewable in practice
 
Velocity 2014: Accelerate Your User Experience With Client-side JavaScript
Velocity 2014: Accelerate Your User Experience With Client-side JavaScriptVelocity 2014: Accelerate Your User Experience With Client-side JavaScript
Velocity 2014: Accelerate Your User Experience With Client-side JavaScript
 
Wave Analytics: Developing Predictive Business Intelligence Apps
Wave Analytics: Developing Predictive Business Intelligence AppsWave Analytics: Developing Predictive Business Intelligence Apps
Wave Analytics: Developing Predictive Business Intelligence Apps
 
Audit¢rio 09 mercado envios - novas funcionalidades - bruno elia
Audit¢rio 09   mercado envios - novas funcionalidades - bruno eliaAudit¢rio 09   mercado envios - novas funcionalidades - bruno elia
Audit¢rio 09 mercado envios - novas funcionalidades - bruno elia
 
Opticon 2015 - Getting Started with the Optimizely Developer Platform
Opticon 2015 - Getting Started with the Optimizely Developer PlatformOpticon 2015 - Getting Started with the Optimizely Developer Platform
Opticon 2015 - Getting Started with the Optimizely Developer Platform
 
Introduction to Domain driven design (LaravelBA #5)
Introduction to Domain driven design (LaravelBA #5)Introduction to Domain driven design (LaravelBA #5)
Introduction to Domain driven design (LaravelBA #5)
 
Intershop Commerce Management with Microsoft SQL Server
Intershop Commerce Management with Microsoft SQL ServerIntershop Commerce Management with Microsoft SQL Server
Intershop Commerce Management with Microsoft SQL Server
 
How AdWords UI maps into adwords api
How AdWords UI maps into adwords apiHow AdWords UI maps into adwords api
How AdWords UI maps into adwords api
 
A Practical Approach to Building a Streaming Processing Pipeline for an Onlin...
A Practical Approach to Building a Streaming Processing Pipeline for an Onlin...A Practical Approach to Building a Streaming Processing Pipeline for an Onlin...
A Practical Approach to Building a Streaming Processing Pipeline for an Onlin...
 
ATAGTR2017 Test Approach for Re-engineering Legacy Applications based on Micr...
ATAGTR2017 Test Approach for Re-engineering Legacy Applications based on Micr...ATAGTR2017 Test Approach for Re-engineering Legacy Applications based on Micr...
ATAGTR2017 Test Approach for Re-engineering Legacy Applications based on Micr...
 
How to Leverage APIs for SEO #TTTLive2019
How to Leverage APIs for SEO #TTTLive2019How to Leverage APIs for SEO #TTTLive2019
How to Leverage APIs for SEO #TTTLive2019
 
Making Service Portal Widgets Work Together
Making Service Portal Widgets Work TogetherMaking Service Portal Widgets Work Together
Making Service Portal Widgets Work Together
 
Let's your users share your App with Friends: App Invites for Android
 Let's your users share your App with Friends: App Invites for Android Let's your users share your App with Friends: App Invites for Android
Let's your users share your App with Friends: App Invites for Android
 
Apigee Demo: API Platform Overview
Apigee Demo: API Platform OverviewApigee Demo: API Platform Overview
Apigee Demo: API Platform Overview
 
Optimizing Code Reusability for SharePoint using Linq to SharePoint & the MVP...
Optimizing Code Reusability for SharePoint using Linq to SharePoint & the MVP...Optimizing Code Reusability for SharePoint using Linq to SharePoint & the MVP...
Optimizing Code Reusability for SharePoint using Linq to SharePoint & the MVP...
 
PHPUnit Episode iv.iii: Return of the tests
PHPUnit Episode iv.iii: Return of the testsPHPUnit Episode iv.iii: Return of the tests
PHPUnit Episode iv.iii: Return of the tests
 
SH 1 - SES 8 - Stitch_Overview_TLV.pptx
SH 1 - SES 8 - Stitch_Overview_TLV.pptxSH 1 - SES 8 - Stitch_Overview_TLV.pptx
SH 1 - SES 8 - Stitch_Overview_TLV.pptx
 
Agados-based Application Design Demo
Agados-based Application Design Demo Agados-based Application Design Demo
Agados-based Application Design Demo
 
AwReporting Update
AwReporting UpdateAwReporting Update
AwReporting Update
 
Simplify Feature Engineering in Your Data Warehouse
Simplify Feature Engineering in Your Data WarehouseSimplify Feature Engineering in Your Data Warehouse
Simplify Feature Engineering in Your Data Warehouse
 

More from Giovane Liberato

Front end para back enders: Dicas de como se virar no universo paralelo
Front end para back enders: Dicas de como se virar no universo paraleloFront end para back enders: Dicas de como se virar no universo paralelo
Front end para back enders: Dicas de como se virar no universo paraleloGiovane Liberato
 
Front end pra back enders: dicas pra se virar no universo paralelo
Front end pra back enders: dicas pra se virar no universo paraleloFront end pra back enders: dicas pra se virar no universo paralelo
Front end pra back enders: dicas pra se virar no universo paraleloGiovane Liberato
 
Google App Engine e NoSQL: Alta disponibilidade
Google App Engine e NoSQL: Alta disponibilidadeGoogle App Engine e NoSQL: Alta disponibilidade
Google App Engine e NoSQL: Alta disponibilidadeGiovane Liberato
 
Sistemas de recomendação na educação
Sistemas de recomendação na educaçãoSistemas de recomendação na educação
Sistemas de recomendação na educaçãoGiovane Liberato
 
A cobra vai fumar(e tomar um golinho de café) - Jython
A cobra vai fumar(e tomar um golinho de café) - JythonA cobra vai fumar(e tomar um golinho de café) - Jython
A cobra vai fumar(e tomar um golinho de café) - JythonGiovane Liberato
 
Jython - "A cobra vai fumar (e tomar um golinho de café)"
Jython - "A cobra vai fumar (e tomar um golinho de café)"Jython - "A cobra vai fumar (e tomar um golinho de café)"
Jython - "A cobra vai fumar (e tomar um golinho de café)"Giovane Liberato
 
Um site em 5 minutos com bottle.py
Um site em 5 minutos com bottle.pyUm site em 5 minutos com bottle.py
Um site em 5 minutos com bottle.pyGiovane Liberato
 
OWASP Top 10 - A web security cookbook
OWASP Top 10 - A web security cookbookOWASP Top 10 - A web security cookbook
OWASP Top 10 - A web security cookbookGiovane Liberato
 

More from Giovane Liberato (9)

Functional Python
Functional PythonFunctional Python
Functional Python
 
Front end para back enders: Dicas de como se virar no universo paralelo
Front end para back enders: Dicas de como se virar no universo paraleloFront end para back enders: Dicas de como se virar no universo paralelo
Front end para back enders: Dicas de como se virar no universo paralelo
 
Front end pra back enders: dicas pra se virar no universo paralelo
Front end pra back enders: dicas pra se virar no universo paraleloFront end pra back enders: dicas pra se virar no universo paralelo
Front end pra back enders: dicas pra se virar no universo paralelo
 
Google App Engine e NoSQL: Alta disponibilidade
Google App Engine e NoSQL: Alta disponibilidadeGoogle App Engine e NoSQL: Alta disponibilidade
Google App Engine e NoSQL: Alta disponibilidade
 
Sistemas de recomendação na educação
Sistemas de recomendação na educaçãoSistemas de recomendação na educação
Sistemas de recomendação na educação
 
A cobra vai fumar(e tomar um golinho de café) - Jython
A cobra vai fumar(e tomar um golinho de café) - JythonA cobra vai fumar(e tomar um golinho de café) - Jython
A cobra vai fumar(e tomar um golinho de café) - Jython
 
Jython - "A cobra vai fumar (e tomar um golinho de café)"
Jython - "A cobra vai fumar (e tomar um golinho de café)"Jython - "A cobra vai fumar (e tomar um golinho de café)"
Jython - "A cobra vai fumar (e tomar um golinho de café)"
 
Um site em 5 minutos com bottle.py
Um site em 5 minutos com bottle.pyUm site em 5 minutos com bottle.py
Um site em 5 minutos com bottle.py
 
OWASP Top 10 - A web security cookbook
OWASP Top 10 - A web security cookbookOWASP Top 10 - A web security cookbook
OWASP Top 10 - A web security cookbook
 

Recently uploaded

Maximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxMaximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxOnBoard
 
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 MenDelhi Call girls
 
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024BookNet Canada
 
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 MenDelhi Call girls
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitecturePixlogix Infotech
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationSafe Software
 
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...gurkirankumar98700
 
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Alan Dix
 
Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Paola De la Torre
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfEnterprise Knowledge
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slidespraypatel2
 
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersEnhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersThousandEyes
 
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 SolutionsEnterprise Knowledge
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Allon Mureinik
 
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 MenDelhi Call girls
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Servicegiselly40
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Igalia
 
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 slidevu2urc
 
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024BookNet Canada
 
Google AI Hackathon: LLM based Evaluator for RAG
Google AI Hackathon: LLM based Evaluator for RAGGoogle AI Hackathon: LLM based Evaluator for RAG
Google AI Hackathon: LLM based Evaluator for RAGSujit Pal
 

Recently uploaded (20)

Maximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxMaximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptx
 
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
 
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
 
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
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC Architecture
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
 
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
 
Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slides
 
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersEnhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
 
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
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)
 
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
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
 
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
 
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
 
Google AI Hackathon: LLM based Evaluator for RAG
Google AI Hackathon: LLM based Evaluator for RAGGoogle AI Hackathon: LLM based Evaluator for RAG
Google AI Hackathon: LLM based Evaluator for RAG
 

Refatorando com a API funcional do Java

  • 1. Refatorando com a API funcional do Java Giovane Liberato @ JUG Vale 14
  • 2. Agenda ● Introdução ao Refactoring ● Catálogo de Refactorings ○ Ouça (ou leia) sua IDE ○ Composição de regras com Predicates ○ Optionals - Quando (não) usar ○ Inversão de dependências com Suppliers ○ Funções idiomáticas
  • 3. Giovane Liberato Senior Software Engineer no * Foco em arquitetura de micro serviços, desenvolvimento seguro e práticas ágeis. Interesse em privacidade digital e criptografia. about.me/giovaneliberato * Temos vagas! (E são remotas)
  • 5. Refactoring is a controlled technique for improving the design of an existing code base. Its essence is applying a series of small behavior-preserving transformations, each of which "too small to be worth doing". Martin Fowler, autor do livro “Refactoring Improving the Design of Existing Code”
  • 6. Mudanças pequenas e constantes que geram enorme benefício a longo prazo Objetivos e focados em melhoria de arquitetura, legibilidade e na redução de débitos técnicos Cercado de testes para garantir que não há quebra de comportamento Red -> Green -> Refactor Evoluir a codebase para acomodar novas features e reduzir acoplamento entre componentes do sistema Como fazer
  • 7.
  • 8.
  • 10. Lembrete Isso não é o refactoring mais grandioso do mundo, isso é apenas um tributo
  • 11. Ouça (ou leia) sua IDE
  • 12. Composição de regras com Predicates Cenário Dado um usuário que contém uma lista de tags, definir qual o valor do cupom de desconto gerado Atores Account, VoucherService e VoucherPredicates Code smells Implementação obstruindo legibilidade, lógicas binárias encadeadas no mesmo IF
  • 13. public Voucher getVoucherForAccount(Account account) { if (account.getTags().contains("new")) { return Voucher.of(15); } if (account.getTags().contains("lover")) { return Voucher.of(20); } if (account.getTags().contains("veg") && account.getTags().contains("new")) { return Voucher.of(25); } if (account.getTags().contains("lover") && (account.getTags().contains("pizza_lover") || account.getTags().contains("burger_lover"))) { return Voucher.of(35); } return Voucher.none(); }
  • 14. public static BiPredicate<Account, String> containsTag = (account, tag)-> account.getTags().contains(tag); public static Predicate<Account> IS_NEW = (account) -> containsTag.test(account, "new"); public static Predicate<Account> IS_LOVER = (account) -> containsTag.test(account, "lover"); public static Predicate<Account> IS_VEG = (account) -> containsTag.test(account, "veg"); public static Predicate<Account> IS_PIZZA_LOVER = (account) -> containsTag.test(account, "pizza_lover"); public static Predicate<Account> IS_BURGER_LOVER = (account) -> containsTag.test(account, "burger_lover");
  • 15. public Voucher getVoucherForAccount(Account account) { if (IS_NEW.test(account)) { return Voucher.of(15); } if (IS_LOVER.test(account)) { return Voucher.of(20); } if (IS_VEG.and(IS_NEW).test(account)) { return Voucher.of(25); } if (IS_LOVER.and(IS_PIZZA_LOVER.or(IS_BURGER_LOVER)).test(account)) { return Voucher.of(35); } return Voucher.none(); }
  • 16. Optionals - Quando (não) usar Cenário Um usuário pode favoritar e bloquear restaurantes do seu menu. Ambas as listas podem ser vazias. Atores Account, Restaurant, RestaurantService e RestaurantRepository Code smells Optional como atributo de classe, chamada dos métodos .isPresent e .get, Optional representando estado domínio
  • 17. public class Account { private Optional<List<Restaurant>> starredRestaurants; private Optional<List<Restaurant>> blockedRestaurants; public Optional<List<Restaurant>> getBlockedRestaurants() { return blockedRestaurants; } public Optional<List<Restaurant>> getStarredRestaurants() { return starredRestaurants; } }
  • 18. public List<Restaurant> getRestaurantsForAccount(Account account) { var restaurants = RestaurantRepository.getAll(); if (account.getBlockedRestaurants().isPresent()) { var blocked = account.getBlockedRestaurants().get(); restaurants = restaurants .stream() .filter((r -> blocked.contains(r))) .collect(toList()); } if (account.getStarredRestaurants().isPresent()) { restaurants.addAll(account.getStarredRestaurants().get()); } return restaurants; }
  • 19. Optionals - usando .orElse public List<Restaurant> getRestaurantsForAccount(Account account) { var restaurants = RestaurantRepository.getAll(); var blocked = account.getBlockedRestaurants().orElse(emptyList()); restaurants = restaurants .stream() .filter((r -> blocked.contains(r))) .collect(toList()); restaurants.addAll(account.getStarredRestaurants().orElse(emptyList())); return restaurants; }
  • 20. Optionals - removendo das classes public class Account { private List<Restaurant> starredRestaurants; private List<Restaurant> blockedRestaurants; public List<Restaurant> getBlockedRestaurants() { return blockedRestaurants != null ? blockedRestaurants : emptyList(); } public List<Restaurant> getStarredRestaurants() { ... } }
  • 21. public List<Restaurant> getRestaurantsForAccount(Account account) { var restaurantList = RestaurantRepository.getAll(); var blocked = account.getBlockedRestaurants(); var starred = account.getStarredRestaurants(); return Stream.concat( starred.stream(), restaurantList .stream() .filter((blocked::contains))) .collect(toList()); }
  • 22. Inversão de dependência com suppliers Cenário Criação de objetos complexos baseado em diferentes fontes de dados Atores Account, Driver, CampaignService e CampaignFactory Code smells Inveja de funcionalidade (feature envy) e assinatura de métodos parcialmente repetidas
  • 23. public class Account { private String pushNotificationId; public String getPushNotificationId() { … } } ----------------------------------------------------------------- public class Driver { private String pushNotificationId; public String getPushNotificationId() { … } }
  • 24. public class CampaignFactory { private AccountRepository accountRepository; private DriversRepository driversRepository; public Campaign buildCampaignForNewUsers(Country country, Message message) { … } public Campaign buildCampaign(Country country, Message message) { … } public Campaign buildCampaign(List<Account> accounts,Message message) { … } public Campaign buildCampaignForDrivers(Country country, Message message) { … } }
  • 25. public Campaign buildCampaignForNewUsers( Country country, Message message) { var pushIds = accountRepository .findNewUsersByCountry(country) .stream() .map(Account::getPushNotificationId) .collect(toList()); return Campaign .builder() .pushNotificationIds(pushIds) .message(message) .build(); }
  • 26. public Campaign buildCampaignForDrivers( Country country, Message message) { var pushIds = driversRepository .findDriversByCountry(country) .stream() .map(Driver::getPushNotificationId) .collect(toList()); return Campaign .builder() .pushNotificationIds(pushIds) .message(message) .build(); }
  • 27. public Campaign buildCampaign(List<Account> accounts, Message message) { var pushIds = accounts .stream() .map(Account::getPushNotificationId) .collect(toList()); return Campaign .builder() .pushNotificationIds(pushIds) .message(message) .build(); }
  • 28. public class CampaignService { CampaignFactory campaignFactory; public Campaign createCampaignForNewUsers(Country country) { var message = new Message("welcome"); return campaignFactory.buildCampaignForNewUsers(country, message); } public Campaign createCampaignForAllUsers(Country country) { var message = new Message("#lanches"); return campaignFactory.buildCampaign(country, message); } public Campaign createCampaignForUsers(List<Account> accounts) { var message = new Message("#lanches"); return campaignFactory.buildCampaign(accounts, message); } public Campaign createCampaignForAllDrivers(Country country) { var message = new Message("bonus!"); return campaignFactory.buildCampaignForDrivers(country, message); } }
  • 29. public class CampaignService { CampaignFactory campaignFactory; private AccountRepository accountRepository; private DriversRepository driversRepository; public Campaign createCampaignForNewUsers(Country country) { .. } public Campaign createCampaignForAllDrivers(Country country) { .. } // ... } Invertendo dependência
  • 30. public class CampaignFactory { public Campaign buildCampaign( Supplier<List<String>> idsSupplier, Message message) { return Campaign .builder() .pushNotificationIds(idsSupplier.get()) .message(message) .build(); } }
  • 31. public Campaign createCampaignForNewUsers(Country country) { var message = new Message("welcome"); Supplier<List<String>> ids = () -> accountRepository.findNewUsersByCountry(country) .stream() .map(Account::getPushNotificationId) .collect(toList()); return campaignFactory.buildCampaign(ids, message); }
  • 32. public Campaign createCampaignForAllDrivers(Country country) { var message = new Message("bonus!"); Supplier<List<String>> ids = () -> driversRepository.findDriversByCountry(country) .stream() .map(Driver::getPushNotificationId) .collect(toList()); return campaignFactory.buildCampaign(ids, message); }
  • 33. Funções idiomáticas Cenário Para usar funções customizadas, o contra-exemplo implementa a interface Function sem necessidade. Atores Account, AccountToNameConverter Code smells Implementando interfaces funcionais para casos simples. Múltiplas classes para contextos parecidos
  • 34. public class AccountToNameConverter implements Function<Account, String> { @Override public String apply(Account account) { return String.format("%s %s", account.getFirstName(), account.getLastName()); }
  • 35. public class AccountService { private AccountToNameConverter converter = new AccountToNameConverter(); public List<String> getEveryonesName(List<Account> accounts) { return accounts .stream() .map(converter) .collect(toList()); } }
  • 36. public class AccountToNameConverter { public static String convert(Account acc) { return String.format("%s%s", acc.getFirstName(), acc.getLastName()); } public static String convertLastFirst(Account acc) { return String.format("%s %s", acc.getLastName(), acc.getFirstName()); } }
  • 37. public class AccountService { public List<String> getEveryonesName(List<Account> accounts) { return accounts .stream() .map(AccountToNameConverter::convert) // ou___ .map(AccountToNameConverter::convertLastFirst) .collect(toList()); }
  • 38. Referências Refactoring - Improving the Design of Existing Code (Martin Fowler) Effective Java, Third Edition Keepin' it Effective (J. Bloch) Optional - The Mother of All Bikesheds (Stuart Marks) Understanding the Economics of Refactoring (Leitch, Stroulia) The Financial Implications of Technical Debt (Erik Frederick)