Hexagonale Architektur - FrOSCon · Hexagonale Architektur Domain zentrierte Microservices Javaland...

34
Hexagonale Architektur Domain zentrierte Microservices Javaland 2019 - 19.03.2019 Christian Iwanzik @chrisIwanzik [email protected]

Transcript of Hexagonale Architektur - FrOSCon · Hexagonale Architektur Domain zentrierte Microservices Javaland...

Page 1: Hexagonale Architektur - FrOSCon · Hexagonale Architektur Domain zentrierte Microservices Javaland 2019 - 19.03.2019 Christian Iwanzik @chrisIwanzik c.iwanzik@tarent.de

Hexagonale ArchitekturDomain zentrierte Microservices

Javaland 2019 - 19.03.2019

Christian Iwanzik@chrisIwanzik

[email protected]

Page 2: Hexagonale Architektur - FrOSCon · Hexagonale Architektur Domain zentrierte Microservices Javaland 2019 - 19.03.2019 Christian Iwanzik @chrisIwanzik c.iwanzik@tarent.de

Christian Iwanzik (33)SoftwareentwicklerDipl-Inf. (FH) - FH Köln

Steckenpferde:➢ JVM

○ Kotlin○ Scala○ auch java ;-)

➢ Domain Driven Design➢ Microservicearchitekturen

Seit 2010 bei tarent Solutions in Bonn

www.tarent.de

Page 3: Hexagonale Architektur - FrOSCon · Hexagonale Architektur Domain zentrierte Microservices Javaland 2019 - 19.03.2019 Christian Iwanzik @chrisIwanzik c.iwanzik@tarent.de

Wir Bauen einen Warenkorb!

DB

Shoppingcart - Service Product-Service

GET /products/{sku}

GET /shoppingcart/{uuid}PUT /shoppingcart/{uuid}/items

Produktbild: http://tinobusiness.com/wp-content/uploads/2015/09/CONSUMER-PRODUCTS-e1442909155136.jpg

Page 4: Hexagonale Architektur - FrOSCon · Hexagonale Architektur Domain zentrierte Microservices Javaland 2019 - 19.03.2019 Christian Iwanzik @chrisIwanzik c.iwanzik@tarent.de

Wir Bauen einen Warenkorb!Controller

Servicelayer

DB-Repository HTTP Client

top down

Separation of concerns!

Wenn wir mal die DB austauschen: Kein Problem!

Decoupling!

Dependency Inversion!

Page 5: Hexagonale Architektur - FrOSCon · Hexagonale Architektur Domain zentrierte Microservices Javaland 2019 - 19.03.2019 Christian Iwanzik @chrisIwanzik c.iwanzik@tarent.de

… und dann kam die FachlogikMaximaler Warenkorb-wert: 120€

Maximale Produktanzahl im Warenkorb: 50

Maximale Anzahl pro Produkt: 10

SKU (Stock Keeping Unit): alphanumerisch von 5 - 20 Zeichen

Page 6: Hexagonale Architektur - FrOSCon · Hexagonale Architektur Domain zentrierte Microservices Javaland 2019 - 19.03.2019 Christian Iwanzik @chrisIwanzik c.iwanzik@tarent.de

… und dann kam die Fachlogik

0..n1

Controller

Servicelayer

DB-Repository HTTP Client

Klar: Hier im Service! Da ist die Logik!

Product

sku: String price: Int

ShoppingCart

products: Map <Product, Int>

Page 7: Hexagonale Architektur - FrOSCon · Hexagonale Architektur Domain zentrierte Microservices Javaland 2019 - 19.03.2019 Christian Iwanzik @chrisIwanzik c.iwanzik@tarent.de

Bob kommt neu ins TeamWas bauen wir denn hier?Ein

Warenkorb-service!

Ein µService mit Spring Boot!

Alles in Kotlin. Voll cool!

Oh und JPA und so!

Ja… Aber was MACHT denn der Service!?

Page 8: Hexagonale Architektur - FrOSCon · Hexagonale Architektur Domain zentrierte Microservices Javaland 2019 - 19.03.2019 Christian Iwanzik @chrisIwanzik c.iwanzik@tarent.de

Was macht denn der Service?fun putProduct(@PathVariable uuid: String, sku: String): ResponseEntity<*> { val skuRegex = "[\\w\\d]{1,20}".toRegex()

return if(skuRegex.matches(sku)) {

val cart = service.addProduct(uuid, sku) … } else { ResponseEntity.badRequest().body("sku is not valid") }}

Controller

Also hier wird erst mal die SKU validiert. Beim Fehler geben wir HTTP 400 zurück.

Page 9: Hexagonale Architektur - FrOSCon · Hexagonale Architektur Domain zentrierte Microservices Javaland 2019 - 19.03.2019 Christian Iwanzik @chrisIwanzik c.iwanzik@tarent.de

Was macht denn der Service?fun addProduct(uuid: String, sku: String): ShoppingCart? { val optionalCart = shoppingCartRepo.findById(uuid) return if(optionalCart.isPresent) { val cart = optionalCart.get() val product: Product = productServiceClient.getProduct(sku)

if(product != null) { cart.products?.add(ShoppingCartItem(product.sku, product, 1)) shoppingCartRepo.save(cart) } return cart

} else { null }}

Controller

ServicelayerUnd hier geben wir dann dem Warenkorb das gefundene Produkt.

Was sind denn● ShoppingCart● ShoppingCartItem● Product?

Hier holen wir ein Produkt beim Productservice ab.

Page 10: Hexagonale Architektur - FrOSCon · Hexagonale Architektur Domain zentrierte Microservices Javaland 2019 - 19.03.2019 Christian Iwanzik @chrisIwanzik c.iwanzik@tarent.de

Was macht denn der Service?@Entitydata class ShoppingCart ( @Id var uuid: String?,

var amount: Int?,

@OneToMany(cascade = [ALL]) var products: MutableList<ShoppingCartItem>?)

Controller

Servicelayer

Was sind denn● ShoppingCart● ShoppingCartItem● Product?

Achso. Das sind die Entities für den OR Mapper. Die nutzen wir aber auch im Client.

ShoppingCart

Page 11: Hexagonale Architektur - FrOSCon · Hexagonale Architektur Domain zentrierte Microservices Javaland 2019 - 19.03.2019 Christian Iwanzik @chrisIwanzik c.iwanzik@tarent.de

Was macht denn der Service?@Entitydata class ShoppingCartItem( @Id var sku: String?,

@OneToOne(cascade = [ALL]) var product: Product?,

var quantity: Int?)

Aber ShoppingCartItem kommt doch im Modell gar nicht vor?

Ja, das brauchen wir aber für den ORM wegen der Quantity

ShoppingCart Product

0..n1

Page 12: Hexagonale Architektur - FrOSCon · Hexagonale Architektur Domain zentrierte Microservices Javaland 2019 - 19.03.2019 Christian Iwanzik @chrisIwanzik c.iwanzik@tarent.de

DB-Repository

Was macht denn der Service?-- schema.sqlALTER TABLE SHOPPING_CART_ITEM ADD CONSTRAINT max_quantity CHECK QUANTITY <= 10

Controller

Servicelayer

Von einem Produkt darf man doch nur maximal 10 haben.Wo wird das denn geprüft?

Na in der `schema.sql`

ShoppingCart

Ähem… Anna? Wo war noch mal der Constraint?

DB-Repository

Page 13: Hexagonale Architektur - FrOSCon · Hexagonale Architektur Domain zentrierte Microservices Javaland 2019 - 19.03.2019 Christian Iwanzik @chrisIwanzik c.iwanzik@tarent.de

Saubere Schichten. Verteilte FachlichkeitController

Servicelayer

DB-Repository HTTP Client

Formatvalidierung

Objektkomposition

Überprüfung von Invarianten

Page 14: Hexagonale Architektur - FrOSCon · Hexagonale Architektur Domain zentrierte Microservices Javaland 2019 - 19.03.2019 Christian Iwanzik @chrisIwanzik c.iwanzik@tarent.de

Ein paar Wochen später:

BIG BALL OF

MUD

Wo wird noch mal der Warenkorbwert berechnet?

Page 15: Hexagonale Architektur - FrOSCon · Hexagonale Architektur Domain zentrierte Microservices Javaland 2019 - 19.03.2019 Christian Iwanzik @chrisIwanzik c.iwanzik@tarent.de

Die IDee !

Erzähl mal!

Ich hab mal was von Hexagonaler Architektur gehört.

Page 16: Hexagonale Architektur - FrOSCon · Hexagonale Architektur Domain zentrierte Microservices Javaland 2019 - 19.03.2019 Christian Iwanzik @chrisIwanzik c.iwanzik@tarent.de

Das Hexagon - Die Schichten

Domain

Application

Ports

Product-Service

DB

● Fachlogik● Modell● “Das Herz der Software”● keine Technik● Domain Driven Design

● Usecases ● Komposition

● Technische “Anhängsel”● Controller● Queue Publisher● SQL Client

Page 17: Hexagonale Architektur - FrOSCon · Hexagonale Architektur Domain zentrierte Microservices Javaland 2019 - 19.03.2019 Christian Iwanzik @chrisIwanzik c.iwanzik@tarent.de

Die Domain

Reine Fachklassen- und Funktionen

Product

SKU

Price

ProductName

simple Fachtypen:syntaktische- und semantische Validierung

zusammengesetzter Fachtyp

<< Aggregate >>ShoppingCart Quantity

AggregateRoot- Interface nach außen- alle Fachlogik- Invarianten- immer gültig!

putProductInto

amount

quantityOfProduct

checkMaximumProductCount

Nur diese Teile reden mit der Außenwelt!

WICHTIG: Nach außen gegebene Objekte, dürfen keinen Einfluss mehr auf die Domäne haben!Kopieren!

Page 18: Hexagonale Architektur - FrOSCon · Hexagonale Architektur Domain zentrierte Microservices Javaland 2019 - 19.03.2019 Christian Iwanzik @chrisIwanzik c.iwanzik@tarent.de

Die Domaindata class Product(val sku: SKU, val price: Price, val name: Name)

Product(SKU("132456"), Price(4, 99), Name("Brot"))

data class SKU(val value: String) { private val regex = "[\\w\\d]{1,20}".toRegex()

init { if(!regex.matches(value)) throw IllegalArgumentException("...") }}

fun putProductInto(product: Product, quantity: Quantity): ShoppingCart {

checkMaximumProductCount()

val newAmount: ShoppingCartAmount = overallAmount + (product.price * quantity) val existingQuantity: Quantity? = cartItems[product]

if(existingQuantity == null) { cartItems[product] = quantity } else { cartItems[product] = existingQuantity.copy(value = existingQuantity.value + quantity.value) }

overallAmount = newAmount

return this}

Page 19: Hexagonale Architektur - FrOSCon · Hexagonale Architektur Domain zentrierte Microservices Javaland 2019 - 19.03.2019 Christian Iwanzik @chrisIwanzik c.iwanzik@tarent.de

Das Hexagon - Datenfluss

User Interface Infrastructure

Product-Service

DB

Domain

Application

Ports

Page 20: Hexagonale Architektur - FrOSCon · Hexagonale Architektur Domain zentrierte Microservices Javaland 2019 - 19.03.2019 Christian Iwanzik @chrisIwanzik c.iwanzik@tarent.de

Die Application

Application

Product-Service

DBUser Interface Infrastructure

Domain

CommandService

Report

Service

Usecaseinterface

Usecase interface

Repositoryport

Port

● Usecases.● Komposition der Ports und

Domains. ● Keine Fachlogik!

Page 21: Hexagonale Architektur - FrOSCon · Hexagonale Architektur Domain zentrierte Microservices Javaland 2019 - 19.03.2019 Christian Iwanzik @chrisIwanzik c.iwanzik@tarent.de

Die Application

≪ Aggregate ≫ShoppingCart

putProductInto

AppShoppingCartService

≪ interface ≫ShoppingCartService

Aufrufer

≪ interface ≫ShoppingCartRepositoryPort

Aufgeru-fener

≪ implements ≫

≪ implements ≫interface ShoppingCartService { fun putProductIntoShoppingCart(shoppingCartUuid: ShoppingCartUuid,...) ...}

@Serviceclass AppShoppingCartService(val shoppingCartRepositoryPort: ...): ShoppingCartService {

override fun putProductIntoShoppingCart(shoppingCartUuid ...): Optional<ShoppingCart> { shoppingCartRepositoryPort.load(shoppingCartUuid) .map { shoppingCart -> shoppingCart.putProductInto(...) } …. }

Page 22: Hexagonale Architektur - FrOSCon · Hexagonale Architektur Domain zentrierte Microservices Javaland 2019 - 19.03.2019 Christian Iwanzik @chrisIwanzik c.iwanzik@tarent.de

Ports And Adapter

Application

Ports

REST

UI

Product-Service

DBUser Interface Infrastructure

Domain

Driver Adapters

● Technische Frameworks● Keine Fachlogik!

Page 23: Hexagonale Architektur - FrOSCon · Hexagonale Architektur Domain zentrierte Microservices Javaland 2019 - 19.03.2019 Christian Iwanzik @chrisIwanzik c.iwanzik@tarent.de

Ports And Adapter

Application

Ports

Product-Service

DB

REST

User Interface Infrastructure

Domain

Driver Adapters

HTTP

SQL

Driven Adapters

REST

UI

Page 24: Hexagonale Architektur - FrOSCon · Hexagonale Architektur Domain zentrierte Microservices Javaland 2019 - 19.03.2019 Christian Iwanzik @chrisIwanzik c.iwanzik@tarent.de

Ports And Adapter

Application

Ports

Product-Service

DB

REST

Driver Driven

Domain

ViewsController

HTTP

SQL

RESTController

HTTP Client

OR Mapper

Page 25: Hexagonale Architektur - FrOSCon · Hexagonale Architektur Domain zentrierte Microservices Javaland 2019 - 19.03.2019 Christian Iwanzik @chrisIwanzik c.iwanzik@tarent.de

Ports And Adapter

≪ Aggregate ≫ShoppingCart

putProductInto

AppShoppingCartService

≪ interface ≫ShoppingCartService

≪ interface ≫ShoppingCartRepositoryPort

≪ implements ≫

≪ implements ≫

≪ adapter ≫ShoppingCartController

≪ adapter ≫JPARepository

≪ port ≫SpringBootMVC

≪ port ≫Hibernate

Page 26: Hexagonale Architektur - FrOSCon · Hexagonale Architektur Domain zentrierte Microservices Javaland 2019 - 19.03.2019 Christian Iwanzik @chrisIwanzik c.iwanzik@tarent.de

Hatten wir das nicht schon mal?ShoppingCartController

CommandService

JPARepository

top down

ShoppingCart Product

0..n1

Page 27: Hexagonale Architektur - FrOSCon · Hexagonale Architektur Domain zentrierte Microservices Javaland 2019 - 19.03.2019 Christian Iwanzik @chrisIwanzik c.iwanzik@tarent.de

Hexagonale Architektur

Application

Ports

Product-Service

DB

REST

Driver Driven

Domain

ViewsController

HTTP

SQL

RESTController

HTTP Client

OR Mapper

Service

Page 28: Hexagonale Architektur - FrOSCon · Hexagonale Architektur Domain zentrierte Microservices Javaland 2019 - 19.03.2019 Christian Iwanzik @chrisIwanzik c.iwanzik@tarent.de

Klaus kommt neu ins TeamWas bauen wir denn hier?

Hier ist der Domainkern und hier die Tests dazu.

Wow! Das ist echt sauber und verständlich.

Die Umsysteme findest du unter Ports.

Page 29: Hexagonale Architektur - FrOSCon · Hexagonale Architektur Domain zentrierte Microservices Javaland 2019 - 19.03.2019 Christian Iwanzik @chrisIwanzik c.iwanzik@tarent.de

Wie geht es weiter?

Product-Service

DB

Component

Page 30: Hexagonale Architektur - FrOSCon · Hexagonale Architektur Domain zentrierte Microservices Javaland 2019 - 19.03.2019 Christian Iwanzik @chrisIwanzik c.iwanzik@tarent.de

Wann sollte ich es einsetzen?● Man hat generell eine Fachlogik (Domain)

● Die Domain hat Invarianten

● Viele Umsysteme, bzw. APIs

● Verschiedene fachliche Sichten

● Kein Fachmodell

● Keine Invarianten

● simples CRUD

Page 31: Hexagonale Architektur - FrOSCon · Hexagonale Architektur Domain zentrierte Microservices Javaland 2019 - 19.03.2019 Christian Iwanzik @chrisIwanzik c.iwanzik@tarent.de

Vor- und Nachteile● Macht die Domainkomplexität handhabbarer,

da zentralisiert.

● Einzelne Schichten lassen sich besser testen.

● Einführung eines neuen Umsystems ist einfacher.

● Neue Kollegen sehen sich den Kern an und wissen, was passiert. Die Wahrheit steht im Code. Diesmal wirklich. ;-)

● Overhead - Domainobjekte müssen oft in neue Modelle umgewandelt werden.

● Manche Frameworks machen einem ein Strich durch die Rechnung. Aufwand von Sonderlockenhier: Hibernate und Jackson

Page 32: Hexagonale Architektur - FrOSCon · Hexagonale Architektur Domain zentrierte Microservices Javaland 2019 - 19.03.2019 Christian Iwanzik @chrisIwanzik c.iwanzik@tarent.de

● https://fideloper.com/hexagonal-architecture

● https://herbertograca.com/2017/11/16/explicit-architecture-01-ddd-hexa

gonal-onion-clean-cqrs-how-i-put-it-all-together/

● https://marcus-biel.com/hexagonal-architecture/

● https://web.archive.org/web/20060711220612/http://alistair.cockburn.us:80/index.php/Main_Page

Literatur

Beispiele:

https://gitlab.com/Iwanzik/hexagonal-service

https://gitlab.com/Iwanzik/muddy-service

Page 33: Hexagonale Architektur - FrOSCon · Hexagonale Architektur Domain zentrierte Microservices Javaland 2019 - 19.03.2019 Christian Iwanzik @chrisIwanzik c.iwanzik@tarent.de

12. April 2019 10 - 17 Uhr

Page 34: Hexagonale Architektur - FrOSCon · Hexagonale Architektur Domain zentrierte Microservices Javaland 2019 - 19.03.2019 Christian Iwanzik @chrisIwanzik c.iwanzik@tarent.de

Vielen Dank!