Slide 1

Slide 1 text

No content

Slide 2

Slide 2 text

When something is painful but you can't avoid doing it… postpone it

Slide 3

Slide 3 text

When something is painful but you can't avoid doing it… delegate it

Slide 4

Slide 4 text

When something is painful but you can't avoid doing it… Do It More Often! "Bring The Pain Forward!"

Slide 5

Slide 5 text

Continuous Integration Pair Programming Continuous Refactoring TDD XP "Bring The Pain Forward!"

Slide 6

Slide 6 text

Victor Rentea 14 years of Java Clean Code Evangelist VictorRentea.ro 30+ talks, 12 meetups .NET Lead Architect Tech Team Lead and Consultant Software Craftsman XP: Pair Programming, Refactoring, TDD

Slide 7

Slide 7 text

VictorRentea.ro @victorrentea [email protected] Independent Technical Trainer & Coach Hibernate Spring Java 8 Architecture, DDD Design Patterns Clean Code Unit Testing, TDD Java Performance and much more… Scala 180+ days 1300 devs 6 years VictorRentea.ro [email protected] 30 companies Posting daily on

Slide 8

Slide 8 text

No content

Slide 9

Slide 9 text

No content

Slide 10

Slide 10 text

No content

Slide 11

Slide 11 text

No content

Slide 12

Slide 12 text

26 The most important principle in programming?

Slide 13

Slide 13 text

27 Single Responsibility Principle EmployeeManager -read/persist -compute pay-roll -generate PDF report -manage projects vs

Slide 14

Slide 14 text

28 Coupling vs

Slide 15

Slide 15 text

29 Don’t Repeat Yourself

Slide 16

Slide 16 text

30 Keep It Short & Simple Premature encapsulation is the root of all evil Overengineering – Adam Bien

Slide 17

Slide 17 text

31 Keep It Short & Simple Premature encapsulation is the root of all evil Overengineering Simpler code Developer Happiness

Slide 18

Slide 18 text

32 Invisible Magic to reduce effort and risk Protect the Developers ... Avoid building an intrusive Custom Framework (bugs to learn) Developer Comfort

Slide 19

Slide 19 text

33 Request/Thread Scope @Autowired private MyRequestContext requestContext; ... { entity.setModifiedBy(requestContext.getCurrentUser()); } @Component @Scope(value = "request", proxyMode = TARGET_CLASS) class MyRequestContext { ... } Request Metadata

Slide 20

Slide 20 text

Fear Kills Creativity Simplify Unit Testing - Strong regression defense Protect the Developers 34 Developer Safety

Slide 21

Slide 21 text

Always Think Regular Brainstorming 35 Continuous Refactoring There are NO boring tasks automate them

Slide 22

Slide 22 text

36

Slide 23

Slide 23 text

39 Keep Struggling for a Can you predict the future ? What features will grow super-complex in time? Simple Design At all times!

Slide 24

Slide 24 text

40 - Kent Beck https://martinfowler.com/bliki/BeckDesignRules.html 2. Reveals Intention 3. No Duplication 4. Fewest Elements 1. Passes the Tests Rules of Simple Design

Slide 25

Slide 25 text

41 A Simple Architecture that Evolves to Match the Growing Complexity This talk is about…

Slide 26

Slide 26 text

42 Core Principles Modeling Data Organizing Logic The Onion Architecture Tests. Fear. Agenda VictorRentea.ro

Slide 27

Slide 27 text

You control them! Entities = your persistent data 43 Entity They simplify your logic

Slide 28

Slide 28 text

44 Put small bits of highly reusable domain logic in your Domain Entities public class Customer { [...] public String getFullName() { return firstName + " " + lastName; } public void activate(User user) { if (status != Status.DRAFT) { throw new IllegalStateException(); } status = Status.ACTIVE; activatedBy = user; activatedDate = new Date(); } public boolean isActive() { return status == Status.ACTIVE; } public boolean canPlaceOrders() { return status == Status.ACTIVE && !isBann }

Slide 29

Slide 29 text

45 activatedBy = user; activatedDate = new Date(); } public boolean isActive() { return status == Status.ACTIVE; } public boolean canPlaceOrders() { return status == Status.ACTIVE && !isBann } public void addAddress(Address address) { address.setCustomer(this); addresses.add(address); } public List
getAddresses() { return Collections.unmodifiableList( addresses); } } public String toExportString() { return String.format("%s;%s;%d", firstName, lastName, isActive()?1:0); } BlOAt dAnGeR Fit Put small bits of highly reusable domain logic in your Domain Entities

Slide 30

Slide 30 text

Entity id 46 Small Immutable Lombok? No persistent ID unlike an Entity Equal by value of all fields Embeddable In larger entities Value Object: a grouping of domain data VO public class Money { private final Currency currency; private final BigDecimal amount; public Money(Currency currency, BigDecimal amount) { this.currency = currency; this.amount = amount; } public Currency getCurrency() { return currency; } public BigDecimal getAmount() { return amount; } public boolean equals(Object other) { ... } } validate();

Slide 31

Slide 31 text

Then, you start exposing data to UI (SPA, WS, JSF, desktop) UI has different goals They want data structures to match their screens. Never expose your Entities in your API 47 isDeletable: true (to show/hide the Delete button)

Slide 32

Slide 32 text

I like dumb DTOs (you'll see soon why) public fields ?! ! !.. VO Entity id Logic public class CustomerDto { private String fullName; private String phoneNumber; private Date birthDate; public final String getFullName return fullName; } public final void setFullName(S this.fullName = fullName; } public final String getPhoneNum return phoneNumber; } public final void setPhoneNumbe this.phoneNumber = phoneNumbe } public final Date getBirthDate( return birthDate; } public final void setBirthDate( this.birthDate = birthDate; } } 48 Form/Request View/Response DTO SearchCriteria/SearchResult Data Transfer Objects DTO Instead, expose in your API public class CustomerDto { public String fullName; public String phoneNumber; public Date birthDate; } dto.fullName = customer.getFullName();

Slide 33

Slide 33 text

49 Core Principles Modeling Data Organizing Logic The Onion Architecture Tests. Fear. Agenda

Slide 34

Slide 34 text

50 Complex Conversion? Extract Mappers VO Entity id DTO Mapper Logic API Domain CustomerDto dto = new CustomerDto(); dto.fullName = customer.getFullName(); dto.birthDate = customer.getBirthDate(); dto.phoneNumber = customer.getPhoneNumber(); CustomerDto dto = new CustomerDto(customer);

Slide 35

Slide 35 text

61 Start implementing all domain logic in a Facade Mapper VO Entity id DTO Facade Facade Domain Service Domain Service Domain Services This approach is detailed in Java EE Patterns - Rethinking Best Practices, by Adam Bien Then extract logic into -To hide complexity: SRP -For Reuse: DRY ▪ (across Facades or Services) ≈ Application Service [DDD]

Slide 36

Slide 36 text

63 Keep DTOs out! (parameters and return types) Mapper VO Entity id DTO Facade Facade Domain Service Domain Service Domain Services speak your Domain Model Convert them to your Domain Objects ASAP DTOs are fragile (under enemy control) * I like them dumb (no methods)

Slide 37

Slide 37 text

Fç Validate Data Façade Convert Data Implement Logic Aspects - Transactions - Logging - Exception Handling* - Access Control* 64 Facade Roles DTO Validator Mapper Domain Service VO Entity id

Slide 38

Slide 38 text

65 What do you mean ? When a class grows too big (>~200 lines?) ➔ break it Extract when it Grows How? Look for a good class name to summarize some of its methods Huh? If I find a good name, I extract? That’s it? Exactly! Piece a cake! A Good Name He-he!☺ “There are only two things hard in programming: Cache Invalidation and Naming Things”

Slide 39

Slide 39 text

66 CustomerFacade saveCustomer() getCustomer() searchCustomer() saveCustomerPreferences() getCustomerPreferences() validateAddress() resetPassword() checkPassworStrength() CustomerPreferecesFacade saveCustomerPreferences() getCustomerPreferences() validateAddress() resetPassword() checkPassworStrength() CustomerFacade saveCustomer() getCustomer() searchCustomer() Extract when it Grows at the same level of abstraction Horizontal Splitting > 300 lines

Slide 40

Slide 40 text

AlertService CompositeOrder Service 67 Separation by Layers of Abstraction OrderService DeliveryService Extract when it Grows Vertical Extraction more abstract, more higher-level

Slide 41

Slide 41 text

69 Duplication Pair Programming Imposed repeat in .js the validations from .java Rush/Lazy Inadvertent you forget and implement it again Inter-developer you didn't knew that was already implemented bus factor =2

Slide 42

Slide 42 text

Practice Pair Programming

Slide 43

Slide 43 text

71

Slide 44

Slide 44 text

Developer Comfort is essential for Emerging Architectures

Slide 45

Slide 45 text

74

Slide 46

Slide 46 text

75 Core Principles Modeling Data Organizing Logic The Onion Architecture Tests. Fear. Agenda VictorRentea.ro

Slide 47

Slide 47 text

76 VO Entity id Domain Service Domain Service What code would you protect? Put it in the domain module Priceless Domain Logic Domain Objects domain

Slide 48

Slide 48 text

Façade DTO Validator Mapper F application 77 domain depends on domain VO Entity id Domain Service Domain Service

Slide 49

Slide 49 text

78 External Service DTO Domain Service Domain Service domain

Slide 50

Slide 50 text

79 External Service DTO Adapter Domain Service Domain Service domain infrastructure A huge Adapter® Pattern - Hide their ugly API - Handle their Exceptions - Decouple their DTOs  your Entities - Validate their evil data

Slide 51

Slide 51 text

80 External Service DTO IAdapter Adapter implements class OrderRepository implements IOrderRepo { public Order getById(id){ ... } } interface IOrderRepo { Order getById(id); } class OrderService { @Autowired IOrderRepository repo; ... { repo.getById(id); } } express your need in a domain interface… and implement it in a lower-level module… When you need to call outside… so nothing foreign enters your domain. Domain Service Domain Service domain infrastructure

Slide 52

Slide 52 text

81 calls Dependency Inversion Principle higher-level module lower-level module "Best of OOP" - Uncle Bob Abstractions should not depend on details Low level classes are not visible

Slide 53

Slide 53 text

infra Adapter 83 External Service XML, JSON IAdapter implements HTTP, RMI, … FTP JMS domain DB DTO

Slide 54

Slide 54 text

84

Slide 55

Slide 55 text

85 BUT…

Slide 56

Slide 56 text

86 VO Entity id Domain Service Domain Service IExtSrv Adapter IRepo What code would you protect? Put it in the domain module Interfaces for External Services you consume Interfaces for Repositories Priceless Domain Logic Domain Objects

Slide 57

Slide 57 text

infra ExtSrv Adapter Repo implem 87 Façade DTO Validator Mapper VO Entity id Domain Service Domain Service IExtSrv Adapter IRepo F application The Onion Architecture Behold, a.k.a. Clean, Hexagonal, Ports-and-Adapters

Slide 58

Slide 58 text

98 Façade DTO Validator Mapper VO Entity id Domain Service Domain Service IRepo Repo implem F application infra IExtSrv Adapter Adapter WS Interface DTO

Slide 59

Slide 59 text

99 Façade DTO Validator Mapper VO Entity id Domain Service Domain Service IRepo Repo implem F application IExtSrv Adapter Adapter WS Interface DTO domain Pragmatic for decent apps, 2 modules are enough

Slide 60

Slide 60 text

Use-case Optimal Query 100 CALLS DEPENDS Breaking into Bounded Contexts DTO Facade Infra Tip: Measure boundary violations com.myapp.order. … com.myapp.product. … EVENT TX FK? SELECT MICRO… "Light CQRS" consistency

Slide 61

Slide 61 text

102

Slide 62

Slide 62 text

103 tardigrade

Slide 63

Slide 63 text

104 fitness function

Slide 64

Slide 64 text

105 coupling performance scalability fitness function security source code size

Slide 65

Slide 65 text

108 Core Principles Modeling Data Organizing Logic The Onion Architecture Tests. Fear. Agenda VictorRentea.ro

Slide 66

Slide 66 text

109 Lots of Unit Tests are Good ! A sense of confidence Developer Courage Continuous Refactoring (It’s still a single )

Slide 67

Slide 67 text

110 As you fight to write Unit Tests, the Production code gets simpler

Slide 68

Slide 68 text

112 First couple of unit tests : The most valuable Test no. difficulty

Slide 69

Slide 69 text

Maintainable Tests Pure Functions No side effects. No dependencies. Mock-based Less readable In-memory Emulation or JPQL tests on H2/* db Fragile data fixtures On Real Systems Eg: Connecting to a real DB 113 , = 2 + 2

Slide 70

Slide 70 text

infrastructure domain side effects 116 pure logic

Slide 71

Slide 71 text

▪ 7 Virtutes of a Good Object ▪ NULL – the worst mistake in IT - https://dzone.com/articles/the-worst-mistake-of-computer-science-1 ▪ The Clean Architecture: - http://blog.8thlight.com/uncle-bob/2012/08/13/the-clean-architecture.html ▪ Some ☺ Programming Jargon - http://blog.codinghorror.com/new-programming-jargon/ ▪ Code quality: WTFs/minute - http://commadot.com/wtf-per-minute/ ▪ SOLID is WRONG - https://speakerdeck.com/tastapod/why-every-element-of-solid-is-wrong ▪ Good software is written 3 times - http://www.javaworld.com/article/2072651/becoming-a-great-programmer-- use-your-trash-can.html ▪ Prezi-like effect in PowerPoint 2016: “Morph” ▪ Value Objects vs Entity - http://enterprisecraftsmanship.com/2016/01/11/entity-vs-value-object-the- ultimate-list-of-differences/ ▪ Extends is bad - http://www.yegor256.com/2016/09/13/inheritance-is-procedural.html ▪ “Measure Don’t Ask” is TM of Kirk Pepperdine Further Reading 121

Slide 72

Slide 72 text

122 Agenda VictorRentea.ro Core Principles Modeling Data Organizing Logic The Onion Architecture Tests. Fear.

Slide 73

Slide 73 text

123 Core Principles VictorRentea.ro Modeling Data Organizing Logic The Onion Architecture Tests. Fear. Agenda Takeaways

Slide 74

Slide 74 text

124 VictorRentea.ro Tests. Fear. Organizing Logic The Onion Architecture Modeling Data KISS: Avoid overengineering Magic to protect your Developers Takeaways

Slide 75

Slide 75 text

125 VictorRentea.ro Tests. Fear. Organizing Logic The Onion Architecture Enemy data KISS: Avoid overengineering Magic to protect your Developers in your DTOs: keep them out Takeaways

Slide 76

Slide 76 text

126 VictorRentea.ro Tests. Fear. Extract when it Grows The Onion Architecture KISS: Avoid overengineering Magic to protect your Developers : for SRP or DRY Enemy data in your DTOs: keep them out Takeaways

Slide 77

Slide 77 text

127 VictorRentea.ro Extract when it Grows The Onion KISS: Avoid overengineering Magic to protect your Developers : for SRP or DRY Enemy data in your DTOs: keep them out , DIP: domain agnostic to externals Tests. Fear. Takeaways (Adapt® them)

Slide 78

Slide 78 text

128 VictorRentea.ro Extract when it Grows The Onion KISS: Avoid overengineering Magic to protect your Developers : for SRP or DRY Enemy data in your DTOs: keep them out , DIP: domain agnostic to externals Tests: let them smash your design Takeaways (Adapt® them)

Slide 79

Slide 79 text

129 KISS

Slide 80

Slide 80 text

130 Keep It simple

Slide 81

Slide 81 text

136 Put Passion In All That You Do!!

Slide 82

Slide 82 text

Thank You!!