hexagonale architektur...die domain reine fachklassen- und funktionen product sku price productname...

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

Upload: others

Post on 01-Jan-2020

5 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Hexagonale Architektur...Die Domain Reine Fachklassen- und Funktionen Product SKU Price ProductName simple Fachtypen: syntaktische- und semantische Validierung zusammengesetzter Fachtyp

Hexagonale ArchitekturDomain zentrierte Microservices

Javaland 2019 - 19.03.2019

Christian Iwanzik@chrisIwanzik

[email protected]

Page 2: Hexagonale Architektur...Die Domain Reine Fachklassen- und Funktionen Product SKU Price ProductName simple Fachtypen: syntaktische- und semantische Validierung zusammengesetzter Fachtyp

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...Die Domain Reine Fachklassen- und Funktionen Product SKU Price ProductName simple Fachtypen: syntaktische- und semantische Validierung zusammengesetzter Fachtyp

Wir Bauen wir 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...Die Domain Reine Fachklassen- und Funktionen Product SKU Price ProductName simple Fachtypen: syntaktische- und semantische Validierung zusammengesetzter Fachtyp

Wir Bauen wir 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...Die Domain Reine Fachklassen- und Funktionen Product SKU Price ProductName simple Fachtypen: syntaktische- und semantische Validierung zusammengesetzter Fachtyp

… 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...Die Domain Reine Fachklassen- und Funktionen Product SKU Price ProductName simple Fachtypen: syntaktische- und semantische Validierung zusammengesetzter Fachtyp

… 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...Die Domain Reine Fachklassen- und Funktionen Product SKU Price ProductName simple Fachtypen: syntaktische- und semantische Validierung zusammengesetzter Fachtyp

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...Die Domain Reine Fachklassen- und Funktionen Product SKU Price ProductName simple Fachtypen: syntaktische- und semantische Validierung zusammengesetzter Fachtyp

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...Die Domain Reine Fachklassen- und Funktionen Product SKU Price ProductName simple Fachtypen: syntaktische- und semantische Validierung zusammengesetzter Fachtyp

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...Die Domain Reine Fachklassen- und Funktionen Product SKU Price ProductName simple Fachtypen: syntaktische- und semantische Validierung zusammengesetzter Fachtyp

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...Die Domain Reine Fachklassen- und Funktionen Product SKU Price ProductName simple Fachtypen: syntaktische- und semantische Validierung zusammengesetzter Fachtyp

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...Die Domain Reine Fachklassen- und Funktionen Product SKU Price ProductName simple Fachtypen: syntaktische- und semantische Validierung zusammengesetzter Fachtyp

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...Die Domain Reine Fachklassen- und Funktionen Product SKU Price ProductName simple Fachtypen: syntaktische- und semantische Validierung zusammengesetzter Fachtyp

Saube Schichten. Verteilte FachlichkeitController

Servicelayer

DB-Repository HTTP Client

Formatvalidierung

Objektkomposition

Überprüfung von Invarianten

Page 14: Hexagonale Architektur...Die Domain Reine Fachklassen- und Funktionen Product SKU Price ProductName simple Fachtypen: syntaktische- und semantische Validierung zusammengesetzter Fachtyp

Ein paar Wochen später:

BIG BALL OF

MUD

Wo wird noch mal der Warenkorbwert berechnet?

Page 15: Hexagonale Architektur...Die Domain Reine Fachklassen- und Funktionen Product SKU Price ProductName simple Fachtypen: syntaktische- und semantische Validierung zusammengesetzter Fachtyp

Die IDee !

Erzähl mal!

Ich hab mal was von Hexagonaler Architektur gehört.

Page 16: Hexagonale Architektur...Die Domain Reine Fachklassen- und Funktionen Product SKU Price ProductName simple Fachtypen: syntaktische- und semantische Validierung zusammengesetzter Fachtyp

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...Die Domain Reine Fachklassen- und Funktionen Product SKU Price ProductName simple Fachtypen: syntaktische- und semantische Validierung zusammengesetzter Fachtyp

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...Die Domain Reine Fachklassen- und Funktionen Product SKU Price ProductName simple Fachtypen: syntaktische- und semantische Validierung zusammengesetzter Fachtyp

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...Die Domain Reine Fachklassen- und Funktionen Product SKU Price ProductName simple Fachtypen: syntaktische- und semantische Validierung zusammengesetzter Fachtyp

Das Hexagon - Datenfluss

User Interface Infrastructure

Product-Service

DB

Domain

Application

Ports

Page 20: Hexagonale Architektur...Die Domain Reine Fachklassen- und Funktionen Product SKU Price ProductName simple Fachtypen: syntaktische- und semantische Validierung zusammengesetzter Fachtyp

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...Die Domain Reine Fachklassen- und Funktionen Product SKU Price ProductName simple Fachtypen: syntaktische- und semantische Validierung zusammengesetzter Fachtyp

Die Application

≪ Aggregate ≫ShoppingCart

putProductInto

CommandService

≪ interface ≫ServiceInterface

Aufrufer

≪ interface ≫Repository

Aufgeru-fener

≪ implements ≫

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

@Serviceclass CommandService(val shoppingCartRepositoryPort: ...): ServiceInterface {

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

Page 22: Hexagonale Architektur...Die Domain Reine Fachklassen- und Funktionen Product SKU Price ProductName simple Fachtypen: syntaktische- und semantische Validierung zusammengesetzter Fachtyp

Ports And Adapter

Application

Ports

REST

UI

Product-Service

DBUser Interface Infrastructure

Domain

Driver Adapters

● Technische Frameworks

● Keine Fachlogik!

Page 23: Hexagonale Architektur...Die Domain Reine Fachklassen- und Funktionen Product SKU Price ProductName simple Fachtypen: syntaktische- und semantische Validierung zusammengesetzter Fachtyp

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...Die Domain Reine Fachklassen- und Funktionen Product SKU Price ProductName simple Fachtypen: syntaktische- und semantische Validierung zusammengesetzter Fachtyp

Ports And Adapter

Application

Ports

Product-Service

DB

REST

User Interface Infrastructure

Domain

ViewsController

HTTP

SQL

RESTController

HTTP Client

OR Mapper

Page 25: Hexagonale Architektur...Die Domain Reine Fachklassen- und Funktionen Product SKU Price ProductName simple Fachtypen: syntaktische- und semantische Validierung zusammengesetzter Fachtyp

Ports And Adapter

≪ Aggregate ≫ShoppingCart

putProductInto

CommandService

≪ interface ≫ServiceInterface

≪ interface ≫Repository

≪ implements ≫

≪ implements ≫

≪ adapter ≫ShoppingCartController

≪ adapter ≫JPARepository

≪ port ≫SpringBootMVC

≪ port ≫Hibernate

Page 26: Hexagonale Architektur...Die Domain Reine Fachklassen- und Funktionen Product SKU Price ProductName simple Fachtypen: syntaktische- und semantische Validierung zusammengesetzter Fachtyp

Hatten wir das nicht schon mal?ShoppingCartController

CommandService

JPARepository

top down

ShoppingCart Product

0..n1

Page 27: Hexagonale Architektur...Die Domain Reine Fachklassen- und Funktionen Product SKU Price ProductName simple Fachtypen: syntaktische- und semantische Validierung zusammengesetzter Fachtyp

Hexagonale Architektur

Application

Ports

Product-Service

DB

REST

User Interface Infrastructure

Domain

ViewsController

HTTP

SQL

RESTController

HTTP Client

OR Mapper

Srv

Page 28: Hexagonale Architektur...Die Domain Reine Fachklassen- und Funktionen Product SKU Price ProductName simple Fachtypen: syntaktische- und semantische Validierung zusammengesetzter Fachtyp

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...Die Domain Reine Fachklassen- und Funktionen Product SKU Price ProductName simple Fachtypen: syntaktische- und semantische Validierung zusammengesetzter Fachtyp

Wie geht es weiter?

Product-Service

DB

Component

Page 30: Hexagonale Architektur...Die Domain Reine Fachklassen- und Funktionen Product SKU Price ProductName simple Fachtypen: syntaktische- und semantische Validierung zusammengesetzter Fachtyp

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...Die Domain Reine Fachklassen- und Funktionen Product SKU Price ProductName simple Fachtypen: syntaktische- und semantische Validierung zusammengesetzter Fachtyp

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...Die Domain Reine Fachklassen- und Funktionen Product SKU Price ProductName simple Fachtypen: syntaktische- und semantische Validierung zusammengesetzter Fachtyp

● 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

Beispiel:

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

Page 33: Hexagonale Architektur...Die Domain Reine Fachklassen- und Funktionen Product SKU Price ProductName simple Fachtypen: syntaktische- und semantische Validierung zusammengesetzter Fachtyp

Vielen Dank!