SlideShare a Scribd company logo
1 of 58
REFACTORING CODE
DOMAIN DRIVEN DESIGN WAY
Supported By:
Supported By:
I’M ANDI PANGERAN
@andi_pangeran
cybercoding.wordpress.com
Supported By:
AGENDA
 PRACTICE HOW TO REFACTORING CODE BASED ON DOMAIN
DRIVEN DESIGN MINDSET
 PRACTICE HOW TO WRITE UNIT TESTING
Supported By:
JOKO
Individual who has significant expertise in the
domain of the system being developed.
DOMAIN EXPERT
MEET OUR ACTOR
Supported By:
BENTO
Individual who has spend all of his life for coding.
PROGRAMMER
MEET OUR ACTOR
Supported By:
PRACTICE
Supported By:
Protect your invariants
REFACTORING
Supported By:
JOKO
PRACTICE
“A customer must
always have an
email address.”
Supported By:
PRACTICE
BENTO
public class Customer {
private String email;
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
Supported By:
PRACTICE
BENTO
public class CostumerTest {
@Test
public void should_always_have_an_email() {
Customer customer = new Customer();
assertEquals(customer.getEmail(), "andi.pangeran@jtravl.com");
}
}
TEST FAIL
Supported By:
PRACTICE
BENTO
public class CostumerTest {
@Test
public void should_always_have_an_email() {
Customer customer = new Customer();
customer.setEmail("andi.pangeran@jtravl.com");
assertEquals(customer.getEmail(), "andi.pangeran@jtravl.com");
}
}
TEST PASSED
Supported By:
PRACTICE
BENTO
public class Customer {
private String email;
public Customer(String email) {
this.email = email;
}
}
Supported By:
PRACTICE
BENTO
public class CostumerTest {
@Test
public void should_always_have_an_email() {
Customer customer = new Customer("andi.pangeran@jtravl.com");
assertEquals(customer.getEmail(), "andi.pangeran@jtravl.com");
}
}
TEST PASSED
Supported By:
Use object as concistency boundaries
REFACTORING
Supported By:
JOKO
PRACTICE
“later prospective customer can be
upgraded to paying customer“
“Paying customer must have phone
number”
“we have two type of customer,
prospective and paying customer.”
Supported By:
PRACTICE
BENTO
public class ProspectiveCustomer extends Customer {
/* other attribute */
}
public class PayingCustomer extends Customer {
/* other attribute */
private String phone;
public PayingCustomer(String email, String phone) {
super(email);
this.phone = phone;
}
}
Supported By:
PRACTICE
BENTO
@Test
public void upgraded_prospective_paying() {
ProspectiveCustomer pcustomer = new
ProspectiveCustomer("andi.pangeran@jtravl.com");
assertEquals(pcustomer.getEmail(), "andi.pangeran@jtravl.com");
PayingCustomer payCustomer =
new PayingCustomer(pcustomer.getName(), “0852xxx”);
assertEquals(payCustomer.getEmail(), "andi.pangeran@jtravl.com");
assertEquals(payCustomer.getPhone(), " 0852xxx");
}
TEST FAIL
Supported By:
PRACTICE
BENTO
@Test
public void upgraded_prospective_paying() {
ProspectiveCustomer pcustomer = new
ProspectiveCustomer("andi.pangeran@jtravl.com");
assertEquals(pcustomer.getEmail(), "andi.pangeran@jtravl.com");
PayingCustomer payCustomer =
new PayingCustomer(pcustomer.getEmail(), “0852xxx”);
assertEquals(payCustomer.getEmail(), "andi.pangeran@jtravl.com");
assertEquals(payCustomer.getPhone(), " 0852xxx");
}
TEST PASSED
Supported By:
PRACTICE
BENTO
public class ProspectiveCustomer extends Customer {
/* other attribute */
public PayingCustomer upgradeToPayingCustomer(String phone) {
return new PayingCustomer(this.email, phone);
}
}
public class PayingCustomer extends Customer {
/* other attribute */
private String phone;
public PayingCustomer(String email, String phone) {
super(email);
this.phone = phone;
}
}
Supported By:
PRACTICE
BENTO
@Test
public void upgraded_prospective_paying() {
ProspectiveCustomer pcustomer = new
ProspectiveCustomer("andi.pangeran@jtravl.com");
assertEquals(pcustomer.getEmail(), "andi.pangeran@jtravl.com");
PayingCustomer payCustomer = pcostumer.upgradeToPaying(“0852xxx”);
assertEquals(payCustomer.getEmail(), "andi.pangeran@jtravl.com");
assertEquals(payCustomer.getPhone(), " 0852xxx");
}
TEST PASSED
Supported By:
JOKO
PRACTICE
“Paying customer must always have a
valid phone number”
Supported By:
PRACTICE
BENTO
@Test
public void upgraded_prospective_paying() {
PayingCustomer payCustomer =
new PayingCustomer(“test@mail.com", “badphonenumber”);
exception.expect(IllegalArgumentException.class);
}
TEST FAIL
Supported By:
PRACTICE
BENTO
public class PayingCustomer extends Customer {
/* other attribute */
private String phone;
public PayingCustomer(String email, String phone) {
super(email);
if (/* validation stuff of phone*/ ) {
throw new IllegalArgumentException();
}
this.phone = phone;
}
}
TEST PASSED
Supported By:
PRACTICE
BENTO
public class PayingCustomer extends Customer {
/* other attribute */
private String phone;
public PayingCustomer(String email, String phone) {
super(email);
if (/* validation stuff of phone*/ ) {
throw new IllegalArgumentException();
}
this.phone = phone;
}
}
TEST PASSED
Supported By:
Encapulate state and behavior with
value object
REFACTORING
Supported By:
PRACTICE
 Intro to value object
 Intro to immutable object
Supported By:
PRACTICE
BENTO
public class PhoneNumber {
private final String phone;
public PhoneNumber(String phone) {
if (/* validation stuff of phone*/ ) {
throw new IllegalArgumentException();
}
this.phone = phone;
}
public String getPhone() {
{
return this.phone;
}
}
Supported By:
PRACTICE
BENTO
public class PayingCustomer extends Customer {
/* other attribute */
private PhoneNumber phone;
public PayingCustomer(String email, PhoneNumber phone) {
super(email);
this.phone = phone;
}
}
TEST PASSED
Supported By:
PRACTICE
BENTO
@Test
public void upgraded_prospective_paying() {
PayingCustomer payCustomer =
new PayingCustomer(“test@mail.com", new
PhoneNumber(“badphonenumber”));
exception.expect(IllegalArgumentException.class);
}
TEST PASSED
Supported By:
Encapulate Operations
REFACTORING
Supported By:
JOKO
PRACTICE
“a Customer orders product and pays for
them”
Supported By:
Service.create
BENTO
Order order = new Order();
order.setCustomer(customer);
order.setProducts(products);
order.setStatus(PAYMENTSTATUS.UNPAID);
order.setPaidAmount(500);
order.setPaidCurrency(CURRENCY.IDR);
order.setStatus(PAYMENTSTATUS.PAID);
PRACTICE
Service.pay
Supported By:
Service.create
BENTO
Order order = new Order();
order.setCustomer(customer);
order.setProducts(products);
order.setStatus(new PaymentStatus(PAYMENTSTATUS.UNPAID));
order.setPaidAmount(500);
order.setPaidCurrency(CURRENCY.IDR);
order.setStatus(new PaymentStatus(PAYMENTSTATUS.PAID));
PRACTICE
Service.pay
Supported By:
Service.create
BENTO
Order order = new Order();
order.setCustomer(customer);
order.setProducts(products);
order.setStatus(new PaymentStatus(PAYMENTSTATUS.UNPAID));
order.setPaidMonetary(new Money(500, CURRENCY.IDR));
order.setStatus(new PaymentStatus(PAYMENTSTATUS.PAID));
PRACTICE
Service.pay
Supported By:
Service.create
BENTO
Order order = new Order(customer, products);
//set payment status in order constructor
order.setPaidMonetary(new Money(500, CURRENCY.IDR));
order.setStatus(new PaymentStatus(PAYMENTSTATUS.PAID));
PRACTICE
Service.pay
Supported By:
Service.create
BENTO
Order order = new Order(customer, products);
//set payment status in order constructor
order.pay (new Money(500, CURRENCY.IDR));
//set payment status in pay procedure
PRACTICE
Service.pay
Supported By:
Use Spefication
REFACTORING
Supported By:
JOKO
PRACTICE
“premium customers get special offers”
Supported By:
Service.premium
BENTO
If (customer.isPremium()) {
//send offer
}
PRACTICE
Supported By:
JOKO
PRACTICE
“order 3 times to become premium
customer”
Supported By:
Specification Interface
BENTO
public interface Specification<T> {
boolean isSatisfiedBy(T t);
Class<T> getType();
}
PRACTICE
Specification Abstract
abstract public class AbstractSpecification<T> implements
Specification<T> {
@Override
public boolean isSatisfiedBy(T t) {
throw new NotImplementedException();
}
/othercode
}
Supported By:
BENTO
public class CustomerIsPremium extends
AbstractSpecification<Customer> {
private OrderRepository orderRepository
public CustomerIsPremium(OrderRepository orderRepository) {
this.orderRepository = orderRepository;
}
@Override
public boolean isSatisfiedBy(Customer customer) {
int count =
this.orderRepository.countByCustomer(customer.getId);
return (count > 3);
}
}
PRACTICE
Supported By:
PRACTICE
BENTO
@Test
public void specification_customer_premium() {
CustomerIsPremium<Customer> spec= new CustomerIsPremium();
customer2order = …
customer3order = …
assertFalse(spec.isSatisfiedBy(customer2order));
assertTrue(spec.isSatisfiedBy(customer3order));
}
TEST PASSED
Supported By:
JOKO
PRACTICE
“different rules apply for different
tenants.”
Supported By:
BENTO
public class CustomerWith3OrdersIsPremium implement
CustomerIsPremium {}
public class CustomerWith500kPremium implement
CustomerIsPremium {}
public class CustomerWithSpecialRequiredmentPremium
implement CustomerIsPremium {}
PRACTICE
Specification Interface
public interface CustomerIsPremium extends
Specification<Customer> {
boolean isSatisfiedBy(Customer cust);
}
Supported By:
BENTO
PRACTICE
public class SpecialOfferSender {
private CustomerIsPremium premiumSpec
public SpecialOfferSende(CustomerIsPremium premiumSpec) {
this.orderRepository = orderRepository;
}
public void sendOffersTo(Customer customer) {
if (this.premiumSpec.isSatisfiedBy(customer)) {
//send offers
}
}
}
Supported By:
Use Spefication for Object Selection
REFACTORING
Supported By:
JOKO
PRACTICE
“get a list of all premium customers”
Supported By:
PRACTICE
 Intro to predicate pattern
 Collection predicate
 JPA predicate
Supported By:
BENTO
PRACTICE
Specification Interface
public interface Specification<T> {
boolean isSatisfiedBy(T t);
Predicate toCollectionPredicate();
}
@Override
public Predicate toCollectionPredicate(Customer customer) {
Predicate<Customer> predicate =
new predicate<Customer>() {
@Override
public boolean apply(Customer input) {
return this.isSatisfiedBy(input);
}
};
return predicate;
}
Supported By:
BENTO
PRACTICE
CustomerIsPremium<Customer> spec= new CustomerIsPremium();
List<Customer> allCustomer = …
Collection<Customer> result =
Collections2.filter(
allCustomer,
spec.toCollectionPredicate()
);
assertArrayEquals(result, … testarray);
TEST PASSED
Supported By:
BENTO
PRACTICE
Specification Interface
public interface Specification<T> {
boolean isSatisfiedBy(T t);
Predicate toCollectionPredicate();
Predicate toPredicate(Root<T> root, CriteriaBuilder cb);
}
@Override
public Predicate toPredicate
(Root<Customer> root, CriteriaBuilder cb) {
return
cb.and (cb.greaterThan(root.get(Customer_.order),3)
);
}
Supported By:
BENTO
PRACTICE
public class DBRepository {
private EntityManager entityManager = ...
public <T> List<T> findAllBySpecification(Specification<T> specification) {
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
// use specification.getType() to create a Root<T> instance
CriteriaQuery<T> criteriaQuery = criteriaBuilder.createQuery(specification.getType());
Root<T> root = criteriaQuery.from(specification.getType());
// get predicate from specification
Predicate predicate = specification.toPredicate(root, criteriaBuilder);
// set predicate and execute query
criteriaQuery.where(predicate);
return entityManager.createQuery(criteriaQuery).getResultList();
}
}
Supported By:
BENTO
PRACTICE
CustomerIsPremium<Customer> spec= new CustomerIsPremium();
List<Customer> Customer = DBRepository.
findAllBySpecification(spec);
assertArrayEquals(result, … testarray);
TEST PASSED
Supported By:
SUMMARY
 Protect your invariants
 Use object as consistency boundaries
 Encapulate state and behavior with value object
 Encapulate Operations
 Use specification pattern
 Use predicate pattern
Supported By:
Questions ?
Supported By:
Identity CTM for Refactoring,
each monday
REFACTORING
Supported By:
Thanks

More Related Content

Viewers also liked

Our way to microservices
Our way to microservicesOur way to microservices
Our way to microservicesAndi Pangeran
 
Liquidating database frustrations with liquibase
Liquidating database frustrations with liquibaseLiquidating database frustrations with liquibase
Liquidating database frustrations with liquibasePaul Churchward
 
Unbreakable Domain Models - DPC13
Unbreakable Domain Models - DPC13Unbreakable Domain Models - DPC13
Unbreakable Domain Models - DPC13Mathias Verraes
 
Modularity and Domain Driven Design; a killer combination?
Modularity and Domain Driven Design; a killer combination?Modularity and Domain Driven Design; a killer combination?
Modularity and Domain Driven Design; a killer combination?ACA IT-Solutions
 
DDD Basics - Context mapping
DDD Basics - Context mappingDDD Basics - Context mapping
DDD Basics - Context mappingStijn Volders
 
Towards Modelling Processes
Towards Modelling ProcessesTowards Modelling Processes
Towards Modelling ProcessesMathias Verraes
 
Liquibase – a time machine for your data
Liquibase – a time machine for your dataLiquibase – a time machine for your data
Liquibase – a time machine for your dataNeev Technologies
 
Liquibase migration for data bases
Liquibase migration for data basesLiquibase migration for data bases
Liquibase migration for data basesRoman Uholnikov
 
How Symfony Changed My Life
How Symfony Changed My LifeHow Symfony Changed My Life
How Symfony Changed My LifeMatthias Noback
 
Integrating Bounded Contexts - Mini-workshop
Integrating Bounded Contexts - Mini-workshopIntegrating Bounded Contexts - Mini-workshop
Integrating Bounded Contexts - Mini-workshopMatthias Noback
 
Programming with Cmdr. Chris Hadfield
Programming with Cmdr. Chris HadfieldProgramming with Cmdr. Chris Hadfield
Programming with Cmdr. Chris HadfieldMatthias Noback
 
Tactical DDD (just better OOP?) - PHPBenelux 2017
Tactical DDD (just better OOP?) - PHPBenelux 2017Tactical DDD (just better OOP?) - PHPBenelux 2017
Tactical DDD (just better OOP?) - PHPBenelux 2017Matthias Noback
 

Viewers also liked (18)

Our way to microservices
Our way to microservicesOur way to microservices
Our way to microservices
 
Liquidating database frustrations with liquibase
Liquidating database frustrations with liquibaseLiquidating database frustrations with liquibase
Liquidating database frustrations with liquibase
 
Unbreakable Domain Models - DPC13
Unbreakable Domain Models - DPC13Unbreakable Domain Models - DPC13
Unbreakable Domain Models - DPC13
 
Modularity and Domain Driven Design; a killer combination?
Modularity and Domain Driven Design; a killer combination?Modularity and Domain Driven Design; a killer combination?
Modularity and Domain Driven Design; a killer combination?
 
DDD Basics - Context mapping
DDD Basics - Context mappingDDD Basics - Context mapping
DDD Basics - Context mapping
 
Towards Modelling Processes
Towards Modelling ProcessesTowards Modelling Processes
Towards Modelling Processes
 
Domain Driven Design
Domain Driven DesignDomain Driven Design
Domain Driven Design
 
Liquibase – a time machine for your data
Liquibase – a time machine for your dataLiquibase – a time machine for your data
Liquibase – a time machine for your data
 
Liquibase migration for data bases
Liquibase migration for data basesLiquibase migration for data bases
Liquibase migration for data bases
 
How Symfony Changed My Life
How Symfony Changed My LifeHow Symfony Changed My Life
How Symfony Changed My Life
 
Integrating Bounded Contexts - Mini-workshop
Integrating Bounded Contexts - Mini-workshopIntegrating Bounded Contexts - Mini-workshop
Integrating Bounded Contexts - Mini-workshop
 
Context Mapping In Action
Context Mapping In ActionContext Mapping In Action
Context Mapping In Action
 
Liquibase
LiquibaseLiquibase
Liquibase
 
Programming with Cmdr. Chris Hadfield
Programming with Cmdr. Chris HadfieldProgramming with Cmdr. Chris Hadfield
Programming with Cmdr. Chris Hadfield
 
Tactical DDD (just better OOP?) - PHPBenelux 2017
Tactical DDD (just better OOP?) - PHPBenelux 2017Tactical DDD (just better OOP?) - PHPBenelux 2017
Tactical DDD (just better OOP?) - PHPBenelux 2017
 
LiquiBase
LiquiBaseLiquiBase
LiquiBase
 
reveal.js 3.0.0
reveal.js 3.0.0reveal.js 3.0.0
reveal.js 3.0.0
 
Build Features, Not Apps
Build Features, Not AppsBuild Features, Not Apps
Build Features, Not Apps
 

Similar to Refactoring domain driven design way

ASP.NET MVC 3.0 Validation
ASP.NET MVC 3.0 ValidationASP.NET MVC 3.0 Validation
ASP.NET MVC 3.0 ValidationEyal Vardi
 
Restaurant Server.pdf
Restaurant Server.pdfRestaurant Server.pdf
Restaurant Server.pdfShaiAlmog1
 
ngMess: AngularJS Dependency Injection
ngMess: AngularJS Dependency InjectionngMess: AngularJS Dependency Injection
ngMess: AngularJS Dependency InjectionDzmitry Ivashutsin
 
Creating an Uber Clone - Part XIII - Transcript.pdf
Creating an Uber Clone - Part XIII - Transcript.pdfCreating an Uber Clone - Part XIII - Transcript.pdf
Creating an Uber Clone - Part XIII - Transcript.pdfShaiAlmog1
 
Jakość dostarczanego oprogramowania oparta o testy
Jakość dostarczanego oprogramowania oparta o testyJakość dostarczanego oprogramowania oparta o testy
Jakość dostarczanego oprogramowania oparta o testyPaweł Tekliński
 
Vaadin DevDay 2017 - Data Binding in Vaadin 8
Vaadin DevDay 2017 - Data Binding in Vaadin 8Vaadin DevDay 2017 - Data Binding in Vaadin 8
Vaadin DevDay 2017 - Data Binding in Vaadin 8Peter Lehto
 
How to test complex SaaS applications - The family july 2014
How to test complex SaaS applications - The family july 2014How to test complex SaaS applications - The family july 2014
How to test complex SaaS applications - The family july 2014Guillaume POTIER
 
"Auth for React.js APP", Nikita Galkin
"Auth for React.js APP", Nikita Galkin"Auth for React.js APP", Nikita Galkin
"Auth for React.js APP", Nikita GalkinFwdays
 
Building a Pyramid: Symfony Testing Strategies
Building a Pyramid: Symfony Testing StrategiesBuilding a Pyramid: Symfony Testing Strategies
Building a Pyramid: Symfony Testing StrategiesCiaranMcNulty
 
Creating a Whatsapp Clone - Part XIV - Transcript.pdf
Creating a Whatsapp Clone - Part XIV - Transcript.pdfCreating a Whatsapp Clone - Part XIV - Transcript.pdf
Creating a Whatsapp Clone - Part XIV - Transcript.pdfShaiAlmog1
 
Automatically Repairing Test Cases for Evolving Method Declarations
Automatically Repairing Test Cases for Evolving Method DeclarationsAutomatically Repairing Test Cases for Evolving Method Declarations
Automatically Repairing Test Cases for Evolving Method DeclarationsICSM 2010
 
WordPress Realtime - WordCamp São Paulo 2015
WordPress Realtime - WordCamp São Paulo 2015WordPress Realtime - WordCamp São Paulo 2015
WordPress Realtime - WordCamp São Paulo 2015Fernando Daciuk
 
Refactoring using Codeception
Refactoring using CodeceptionRefactoring using Codeception
Refactoring using CodeceptionJeroen van Dijk
 
Crafting beautiful software
Crafting beautiful softwareCrafting beautiful software
Crafting beautiful softwareJorn Oomen
 
Udi Dahan Intentions And Interfaces
Udi Dahan Intentions And InterfacesUdi Dahan Intentions And Interfaces
Udi Dahan Intentions And Interfacesdeimos
 
Unit testing with zend framework tek11
Unit testing with zend framework tek11Unit testing with zend framework tek11
Unit testing with zend framework tek11Michelangelo van Dam
 
Pruebas unitarias con django
Pruebas unitarias con djangoPruebas unitarias con django
Pruebas unitarias con djangoTomás Henríquez
 

Similar to Refactoring domain driven design way (20)

ASP.NET MVC 3.0 Validation
ASP.NET MVC 3.0 ValidationASP.NET MVC 3.0 Validation
ASP.NET MVC 3.0 Validation
 
Restaurant Server.pdf
Restaurant Server.pdfRestaurant Server.pdf
Restaurant Server.pdf
 
ngMess: AngularJS Dependency Injection
ngMess: AngularJS Dependency InjectionngMess: AngularJS Dependency Injection
ngMess: AngularJS Dependency Injection
 
Creating an Uber Clone - Part XIII - Transcript.pdf
Creating an Uber Clone - Part XIII - Transcript.pdfCreating an Uber Clone - Part XIII - Transcript.pdf
Creating an Uber Clone - Part XIII - Transcript.pdf
 
Jakość dostarczanego oprogramowania oparta o testy
Jakość dostarczanego oprogramowania oparta o testyJakość dostarczanego oprogramowania oparta o testy
Jakość dostarczanego oprogramowania oparta o testy
 
Domain Driven Design
Domain Driven DesignDomain Driven Design
Domain Driven Design
 
Vaadin DevDay 2017 - Data Binding in Vaadin 8
Vaadin DevDay 2017 - Data Binding in Vaadin 8Vaadin DevDay 2017 - Data Binding in Vaadin 8
Vaadin DevDay 2017 - Data Binding in Vaadin 8
 
How to test complex SaaS applications - The family july 2014
How to test complex SaaS applications - The family july 2014How to test complex SaaS applications - The family july 2014
How to test complex SaaS applications - The family july 2014
 
"Auth for React.js APP", Nikita Galkin
"Auth for React.js APP", Nikita Galkin"Auth for React.js APP", Nikita Galkin
"Auth for React.js APP", Nikita Galkin
 
Building a Pyramid: Symfony Testing Strategies
Building a Pyramid: Symfony Testing StrategiesBuilding a Pyramid: Symfony Testing Strategies
Building a Pyramid: Symfony Testing Strategies
 
Creating a Whatsapp Clone - Part XIV - Transcript.pdf
Creating a Whatsapp Clone - Part XIV - Transcript.pdfCreating a Whatsapp Clone - Part XIV - Transcript.pdf
Creating a Whatsapp Clone - Part XIV - Transcript.pdf
 
SOLID Principles
SOLID PrinciplesSOLID Principles
SOLID Principles
 
Automatically Repairing Test Cases for Evolving Method Declarations
Automatically Repairing Test Cases for Evolving Method DeclarationsAutomatically Repairing Test Cases for Evolving Method Declarations
Automatically Repairing Test Cases for Evolving Method Declarations
 
WordPress Realtime - WordCamp São Paulo 2015
WordPress Realtime - WordCamp São Paulo 2015WordPress Realtime - WordCamp São Paulo 2015
WordPress Realtime - WordCamp São Paulo 2015
 
Refactoring using Codeception
Refactoring using CodeceptionRefactoring using Codeception
Refactoring using Codeception
 
Crafting beautiful software
Crafting beautiful softwareCrafting beautiful software
Crafting beautiful software
 
Vaadin7
Vaadin7Vaadin7
Vaadin7
 
Udi Dahan Intentions And Interfaces
Udi Dahan Intentions And InterfacesUdi Dahan Intentions And Interfaces
Udi Dahan Intentions And Interfaces
 
Unit testing with zend framework tek11
Unit testing with zend framework tek11Unit testing with zend framework tek11
Unit testing with zend framework tek11
 
Pruebas unitarias con django
Pruebas unitarias con djangoPruebas unitarias con django
Pruebas unitarias con django
 

Recently uploaded

WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?WSO2
 
WSO2Con2024 - Hello Choreo Presentation - Kanchana
WSO2Con2024 - Hello Choreo Presentation - KanchanaWSO2Con2024 - Hello Choreo Presentation - Kanchana
WSO2Con2024 - Hello Choreo Presentation - KanchanaWSO2
 
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...WSO2
 
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital TransformationWSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital TransformationWSO2
 
Driving Innovation: Scania's API Revolution with WSO2
Driving Innovation: Scania's API Revolution with WSO2Driving Innovation: Scania's API Revolution with WSO2
Driving Innovation: Scania's API Revolution with WSO2WSO2
 
WSO2Con2024 - Facilitating Broadband Switching Services for UK Telecoms Provi...
WSO2Con2024 - Facilitating Broadband Switching Services for UK Telecoms Provi...WSO2Con2024 - Facilitating Broadband Switching Services for UK Telecoms Provi...
WSO2Con2024 - Facilitating Broadband Switching Services for UK Telecoms Provi...WSO2
 
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...WSO2
 
Artyushina_Guest lecture_YorkU CS May 2024.pptx
Artyushina_Guest lecture_YorkU CS May 2024.pptxArtyushina_Guest lecture_YorkU CS May 2024.pptx
Artyushina_Guest lecture_YorkU CS May 2024.pptxAnnaArtyushina1
 
WSO2Con2024 - Software Delivery in Hybrid Environments
WSO2Con2024 - Software Delivery in Hybrid EnvironmentsWSO2Con2024 - Software Delivery in Hybrid Environments
WSO2Con2024 - Software Delivery in Hybrid EnvironmentsWSO2
 
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024VictoriaMetrics
 
WSO2CON 2024 - Designing Event-Driven Enterprises: Stories of Transformation
WSO2CON 2024 - Designing Event-Driven Enterprises: Stories of TransformationWSO2CON 2024 - Designing Event-Driven Enterprises: Stories of Transformation
WSO2CON 2024 - Designing Event-Driven Enterprises: Stories of TransformationWSO2
 
WSO2Con2024 - Organization Management: The Revolution in B2B CIAM
WSO2Con2024 - Organization Management: The Revolution in B2B CIAMWSO2Con2024 - Organization Management: The Revolution in B2B CIAM
WSO2Con2024 - Organization Management: The Revolution in B2B CIAMWSO2
 
WSO2CON 2024 - Architecting AI in the Enterprise: APIs and Applications
WSO2CON 2024 - Architecting AI in the Enterprise: APIs and ApplicationsWSO2CON 2024 - Architecting AI in the Enterprise: APIs and Applications
WSO2CON 2024 - Architecting AI in the Enterprise: APIs and ApplicationsWSO2
 
Evolving Data Governance for the Real-time Streaming and AI Era
Evolving Data Governance for the Real-time Streaming and AI EraEvolving Data Governance for the Real-time Streaming and AI Era
Evolving Data Governance for the Real-time Streaming and AI Eraconfluent
 
WSO2CON 2024 - Navigating API Complexity: REST, GraphQL, gRPC, Websocket, Web...
WSO2CON 2024 - Navigating API Complexity: REST, GraphQL, gRPC, Websocket, Web...WSO2CON 2024 - Navigating API Complexity: REST, GraphQL, gRPC, Websocket, Web...
WSO2CON 2024 - Navigating API Complexity: REST, GraphQL, gRPC, Websocket, Web...WSO2
 
WSO2Con2024 - Low-Code Integration Tooling
WSO2Con2024 - Low-Code Integration ToolingWSO2Con2024 - Low-Code Integration Tooling
WSO2Con2024 - Low-Code Integration ToolingWSO2
 
WSO2Con2024 - Navigating the Digital Landscape: Transforming Healthcare with ...
WSO2Con2024 - Navigating the Digital Landscape: Transforming Healthcare with ...WSO2Con2024 - Navigating the Digital Landscape: Transforming Healthcare with ...
WSO2Con2024 - Navigating the Digital Landscape: Transforming Healthcare with ...WSO2
 
WSO2Con2024 - Simplified Integration: Unveiling the Latest Features in WSO2 L...
WSO2Con2024 - Simplified Integration: Unveiling the Latest Features in WSO2 L...WSO2Con2024 - Simplified Integration: Unveiling the Latest Features in WSO2 L...
WSO2Con2024 - Simplified Integration: Unveiling the Latest Features in WSO2 L...WSO2
 
WSO2CON 2024 - How to Run a Security Program
WSO2CON 2024 - How to Run a Security ProgramWSO2CON 2024 - How to Run a Security Program
WSO2CON 2024 - How to Run a Security ProgramWSO2
 

Recently uploaded (20)

WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?
 
WSO2Con2024 - Hello Choreo Presentation - Kanchana
WSO2Con2024 - Hello Choreo Presentation - KanchanaWSO2Con2024 - Hello Choreo Presentation - Kanchana
WSO2Con2024 - Hello Choreo Presentation - Kanchana
 
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
 
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital TransformationWSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
 
Driving Innovation: Scania's API Revolution with WSO2
Driving Innovation: Scania's API Revolution with WSO2Driving Innovation: Scania's API Revolution with WSO2
Driving Innovation: Scania's API Revolution with WSO2
 
WSO2Con2024 - Facilitating Broadband Switching Services for UK Telecoms Provi...
WSO2Con2024 - Facilitating Broadband Switching Services for UK Telecoms Provi...WSO2Con2024 - Facilitating Broadband Switching Services for UK Telecoms Provi...
WSO2Con2024 - Facilitating Broadband Switching Services for UK Telecoms Provi...
 
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
 
Artyushina_Guest lecture_YorkU CS May 2024.pptx
Artyushina_Guest lecture_YorkU CS May 2024.pptxArtyushina_Guest lecture_YorkU CS May 2024.pptx
Artyushina_Guest lecture_YorkU CS May 2024.pptx
 
WSO2Con2024 - Software Delivery in Hybrid Environments
WSO2Con2024 - Software Delivery in Hybrid EnvironmentsWSO2Con2024 - Software Delivery in Hybrid Environments
WSO2Con2024 - Software Delivery in Hybrid Environments
 
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
 
WSO2CON 2024 - Designing Event-Driven Enterprises: Stories of Transformation
WSO2CON 2024 - Designing Event-Driven Enterprises: Stories of TransformationWSO2CON 2024 - Designing Event-Driven Enterprises: Stories of Transformation
WSO2CON 2024 - Designing Event-Driven Enterprises: Stories of Transformation
 
WSO2Con2024 - Organization Management: The Revolution in B2B CIAM
WSO2Con2024 - Organization Management: The Revolution in B2B CIAMWSO2Con2024 - Organization Management: The Revolution in B2B CIAM
WSO2Con2024 - Organization Management: The Revolution in B2B CIAM
 
WSO2CON 2024 - Architecting AI in the Enterprise: APIs and Applications
WSO2CON 2024 - Architecting AI in the Enterprise: APIs and ApplicationsWSO2CON 2024 - Architecting AI in the Enterprise: APIs and Applications
WSO2CON 2024 - Architecting AI in the Enterprise: APIs and Applications
 
Evolving Data Governance for the Real-time Streaming and AI Era
Evolving Data Governance for the Real-time Streaming and AI EraEvolving Data Governance for the Real-time Streaming and AI Era
Evolving Data Governance for the Real-time Streaming and AI Era
 
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
 
WSO2CON 2024 - Navigating API Complexity: REST, GraphQL, gRPC, Websocket, Web...
WSO2CON 2024 - Navigating API Complexity: REST, GraphQL, gRPC, Websocket, Web...WSO2CON 2024 - Navigating API Complexity: REST, GraphQL, gRPC, Websocket, Web...
WSO2CON 2024 - Navigating API Complexity: REST, GraphQL, gRPC, Websocket, Web...
 
WSO2Con2024 - Low-Code Integration Tooling
WSO2Con2024 - Low-Code Integration ToolingWSO2Con2024 - Low-Code Integration Tooling
WSO2Con2024 - Low-Code Integration Tooling
 
WSO2Con2024 - Navigating the Digital Landscape: Transforming Healthcare with ...
WSO2Con2024 - Navigating the Digital Landscape: Transforming Healthcare with ...WSO2Con2024 - Navigating the Digital Landscape: Transforming Healthcare with ...
WSO2Con2024 - Navigating the Digital Landscape: Transforming Healthcare with ...
 
WSO2Con2024 - Simplified Integration: Unveiling the Latest Features in WSO2 L...
WSO2Con2024 - Simplified Integration: Unveiling the Latest Features in WSO2 L...WSO2Con2024 - Simplified Integration: Unveiling the Latest Features in WSO2 L...
WSO2Con2024 - Simplified Integration: Unveiling the Latest Features in WSO2 L...
 
WSO2CON 2024 - How to Run a Security Program
WSO2CON 2024 - How to Run a Security ProgramWSO2CON 2024 - How to Run a Security Program
WSO2CON 2024 - How to Run a Security Program
 

Refactoring domain driven design way

  • 1. REFACTORING CODE DOMAIN DRIVEN DESIGN WAY Supported By:
  • 2. Supported By: I’M ANDI PANGERAN @andi_pangeran cybercoding.wordpress.com
  • 3. Supported By: AGENDA  PRACTICE HOW TO REFACTORING CODE BASED ON DOMAIN DRIVEN DESIGN MINDSET  PRACTICE HOW TO WRITE UNIT TESTING
  • 4. Supported By: JOKO Individual who has significant expertise in the domain of the system being developed. DOMAIN EXPERT MEET OUR ACTOR
  • 5. Supported By: BENTO Individual who has spend all of his life for coding. PROGRAMMER MEET OUR ACTOR
  • 7. Supported By: Protect your invariants REFACTORING
  • 8. Supported By: JOKO PRACTICE “A customer must always have an email address.”
  • 9. Supported By: PRACTICE BENTO public class Customer { private String email; public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } }
  • 10. Supported By: PRACTICE BENTO public class CostumerTest { @Test public void should_always_have_an_email() { Customer customer = new Customer(); assertEquals(customer.getEmail(), "andi.pangeran@jtravl.com"); } } TEST FAIL
  • 11. Supported By: PRACTICE BENTO public class CostumerTest { @Test public void should_always_have_an_email() { Customer customer = new Customer(); customer.setEmail("andi.pangeran@jtravl.com"); assertEquals(customer.getEmail(), "andi.pangeran@jtravl.com"); } } TEST PASSED
  • 12. Supported By: PRACTICE BENTO public class Customer { private String email; public Customer(String email) { this.email = email; } }
  • 13. Supported By: PRACTICE BENTO public class CostumerTest { @Test public void should_always_have_an_email() { Customer customer = new Customer("andi.pangeran@jtravl.com"); assertEquals(customer.getEmail(), "andi.pangeran@jtravl.com"); } } TEST PASSED
  • 14. Supported By: Use object as concistency boundaries REFACTORING
  • 15. Supported By: JOKO PRACTICE “later prospective customer can be upgraded to paying customer“ “Paying customer must have phone number” “we have two type of customer, prospective and paying customer.”
  • 16. Supported By: PRACTICE BENTO public class ProspectiveCustomer extends Customer { /* other attribute */ } public class PayingCustomer extends Customer { /* other attribute */ private String phone; public PayingCustomer(String email, String phone) { super(email); this.phone = phone; } }
  • 17. Supported By: PRACTICE BENTO @Test public void upgraded_prospective_paying() { ProspectiveCustomer pcustomer = new ProspectiveCustomer("andi.pangeran@jtravl.com"); assertEquals(pcustomer.getEmail(), "andi.pangeran@jtravl.com"); PayingCustomer payCustomer = new PayingCustomer(pcustomer.getName(), “0852xxx”); assertEquals(payCustomer.getEmail(), "andi.pangeran@jtravl.com"); assertEquals(payCustomer.getPhone(), " 0852xxx"); } TEST FAIL
  • 18. Supported By: PRACTICE BENTO @Test public void upgraded_prospective_paying() { ProspectiveCustomer pcustomer = new ProspectiveCustomer("andi.pangeran@jtravl.com"); assertEquals(pcustomer.getEmail(), "andi.pangeran@jtravl.com"); PayingCustomer payCustomer = new PayingCustomer(pcustomer.getEmail(), “0852xxx”); assertEquals(payCustomer.getEmail(), "andi.pangeran@jtravl.com"); assertEquals(payCustomer.getPhone(), " 0852xxx"); } TEST PASSED
  • 19. Supported By: PRACTICE BENTO public class ProspectiveCustomer extends Customer { /* other attribute */ public PayingCustomer upgradeToPayingCustomer(String phone) { return new PayingCustomer(this.email, phone); } } public class PayingCustomer extends Customer { /* other attribute */ private String phone; public PayingCustomer(String email, String phone) { super(email); this.phone = phone; } }
  • 20. Supported By: PRACTICE BENTO @Test public void upgraded_prospective_paying() { ProspectiveCustomer pcustomer = new ProspectiveCustomer("andi.pangeran@jtravl.com"); assertEquals(pcustomer.getEmail(), "andi.pangeran@jtravl.com"); PayingCustomer payCustomer = pcostumer.upgradeToPaying(“0852xxx”); assertEquals(payCustomer.getEmail(), "andi.pangeran@jtravl.com"); assertEquals(payCustomer.getPhone(), " 0852xxx"); } TEST PASSED
  • 21. Supported By: JOKO PRACTICE “Paying customer must always have a valid phone number”
  • 22. Supported By: PRACTICE BENTO @Test public void upgraded_prospective_paying() { PayingCustomer payCustomer = new PayingCustomer(“test@mail.com", “badphonenumber”); exception.expect(IllegalArgumentException.class); } TEST FAIL
  • 23. Supported By: PRACTICE BENTO public class PayingCustomer extends Customer { /* other attribute */ private String phone; public PayingCustomer(String email, String phone) { super(email); if (/* validation stuff of phone*/ ) { throw new IllegalArgumentException(); } this.phone = phone; } } TEST PASSED
  • 24. Supported By: PRACTICE BENTO public class PayingCustomer extends Customer { /* other attribute */ private String phone; public PayingCustomer(String email, String phone) { super(email); if (/* validation stuff of phone*/ ) { throw new IllegalArgumentException(); } this.phone = phone; } } TEST PASSED
  • 25. Supported By: Encapulate state and behavior with value object REFACTORING
  • 26. Supported By: PRACTICE  Intro to value object  Intro to immutable object
  • 27. Supported By: PRACTICE BENTO public class PhoneNumber { private final String phone; public PhoneNumber(String phone) { if (/* validation stuff of phone*/ ) { throw new IllegalArgumentException(); } this.phone = phone; } public String getPhone() { { return this.phone; } }
  • 28. Supported By: PRACTICE BENTO public class PayingCustomer extends Customer { /* other attribute */ private PhoneNumber phone; public PayingCustomer(String email, PhoneNumber phone) { super(email); this.phone = phone; } } TEST PASSED
  • 29. Supported By: PRACTICE BENTO @Test public void upgraded_prospective_paying() { PayingCustomer payCustomer = new PayingCustomer(“test@mail.com", new PhoneNumber(“badphonenumber”)); exception.expect(IllegalArgumentException.class); } TEST PASSED
  • 31. Supported By: JOKO PRACTICE “a Customer orders product and pays for them”
  • 32. Supported By: Service.create BENTO Order order = new Order(); order.setCustomer(customer); order.setProducts(products); order.setStatus(PAYMENTSTATUS.UNPAID); order.setPaidAmount(500); order.setPaidCurrency(CURRENCY.IDR); order.setStatus(PAYMENTSTATUS.PAID); PRACTICE Service.pay
  • 33. Supported By: Service.create BENTO Order order = new Order(); order.setCustomer(customer); order.setProducts(products); order.setStatus(new PaymentStatus(PAYMENTSTATUS.UNPAID)); order.setPaidAmount(500); order.setPaidCurrency(CURRENCY.IDR); order.setStatus(new PaymentStatus(PAYMENTSTATUS.PAID)); PRACTICE Service.pay
  • 34. Supported By: Service.create BENTO Order order = new Order(); order.setCustomer(customer); order.setProducts(products); order.setStatus(new PaymentStatus(PAYMENTSTATUS.UNPAID)); order.setPaidMonetary(new Money(500, CURRENCY.IDR)); order.setStatus(new PaymentStatus(PAYMENTSTATUS.PAID)); PRACTICE Service.pay
  • 35. Supported By: Service.create BENTO Order order = new Order(customer, products); //set payment status in order constructor order.setPaidMonetary(new Money(500, CURRENCY.IDR)); order.setStatus(new PaymentStatus(PAYMENTSTATUS.PAID)); PRACTICE Service.pay
  • 36. Supported By: Service.create BENTO Order order = new Order(customer, products); //set payment status in order constructor order.pay (new Money(500, CURRENCY.IDR)); //set payment status in pay procedure PRACTICE Service.pay
  • 40. Supported By: JOKO PRACTICE “order 3 times to become premium customer”
  • 41. Supported By: Specification Interface BENTO public interface Specification<T> { boolean isSatisfiedBy(T t); Class<T> getType(); } PRACTICE Specification Abstract abstract public class AbstractSpecification<T> implements Specification<T> { @Override public boolean isSatisfiedBy(T t) { throw new NotImplementedException(); } /othercode }
  • 42. Supported By: BENTO public class CustomerIsPremium extends AbstractSpecification<Customer> { private OrderRepository orderRepository public CustomerIsPremium(OrderRepository orderRepository) { this.orderRepository = orderRepository; } @Override public boolean isSatisfiedBy(Customer customer) { int count = this.orderRepository.countByCustomer(customer.getId); return (count > 3); } } PRACTICE
  • 43. Supported By: PRACTICE BENTO @Test public void specification_customer_premium() { CustomerIsPremium<Customer> spec= new CustomerIsPremium(); customer2order = … customer3order = … assertFalse(spec.isSatisfiedBy(customer2order)); assertTrue(spec.isSatisfiedBy(customer3order)); } TEST PASSED
  • 44. Supported By: JOKO PRACTICE “different rules apply for different tenants.”
  • 45. Supported By: BENTO public class CustomerWith3OrdersIsPremium implement CustomerIsPremium {} public class CustomerWith500kPremium implement CustomerIsPremium {} public class CustomerWithSpecialRequiredmentPremium implement CustomerIsPremium {} PRACTICE Specification Interface public interface CustomerIsPremium extends Specification<Customer> { boolean isSatisfiedBy(Customer cust); }
  • 46. Supported By: BENTO PRACTICE public class SpecialOfferSender { private CustomerIsPremium premiumSpec public SpecialOfferSende(CustomerIsPremium premiumSpec) { this.orderRepository = orderRepository; } public void sendOffersTo(Customer customer) { if (this.premiumSpec.isSatisfiedBy(customer)) { //send offers } } }
  • 47. Supported By: Use Spefication for Object Selection REFACTORING
  • 48. Supported By: JOKO PRACTICE “get a list of all premium customers”
  • 49. Supported By: PRACTICE  Intro to predicate pattern  Collection predicate  JPA predicate
  • 50. Supported By: BENTO PRACTICE Specification Interface public interface Specification<T> { boolean isSatisfiedBy(T t); Predicate toCollectionPredicate(); } @Override public Predicate toCollectionPredicate(Customer customer) { Predicate<Customer> predicate = new predicate<Customer>() { @Override public boolean apply(Customer input) { return this.isSatisfiedBy(input); } }; return predicate; }
  • 51. Supported By: BENTO PRACTICE CustomerIsPremium<Customer> spec= new CustomerIsPremium(); List<Customer> allCustomer = … Collection<Customer> result = Collections2.filter( allCustomer, spec.toCollectionPredicate() ); assertArrayEquals(result, … testarray); TEST PASSED
  • 52. Supported By: BENTO PRACTICE Specification Interface public interface Specification<T> { boolean isSatisfiedBy(T t); Predicate toCollectionPredicate(); Predicate toPredicate(Root<T> root, CriteriaBuilder cb); } @Override public Predicate toPredicate (Root<Customer> root, CriteriaBuilder cb) { return cb.and (cb.greaterThan(root.get(Customer_.order),3) ); }
  • 53. Supported By: BENTO PRACTICE public class DBRepository { private EntityManager entityManager = ... public <T> List<T> findAllBySpecification(Specification<T> specification) { CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); // use specification.getType() to create a Root<T> instance CriteriaQuery<T> criteriaQuery = criteriaBuilder.createQuery(specification.getType()); Root<T> root = criteriaQuery.from(specification.getType()); // get predicate from specification Predicate predicate = specification.toPredicate(root, criteriaBuilder); // set predicate and execute query criteriaQuery.where(predicate); return entityManager.createQuery(criteriaQuery).getResultList(); } }
  • 54. Supported By: BENTO PRACTICE CustomerIsPremium<Customer> spec= new CustomerIsPremium(); List<Customer> Customer = DBRepository. findAllBySpecification(spec); assertArrayEquals(result, … testarray); TEST PASSED
  • 55. Supported By: SUMMARY  Protect your invariants  Use object as consistency boundaries  Encapulate state and behavior with value object  Encapulate Operations  Use specification pattern  Use predicate pattern
  • 57. Supported By: Identity CTM for Refactoring, each monday REFACTORING