41
From CRUD to messages a true story…

From CRUD to messages: a true story

Embed Size (px)

Citation preview

Page 1: From CRUD to messages: a true story

From CRUD to messages…a true story…

Page 2: From CRUD to messages: a true story

Alessandro Melchiori

@amelchiori

[email protected]

m

http://melkio.codiceplastico.co

m

Page 3: From CRUD to messages: a true story

…il contesto…

• Applicazione “finanziaria”

• Circa 70 (230) utenti

• 137.000+ (1.000.000+) aziende

• 420.000+ (4.500.000+) bilanci

• 38.000.000+ (650.000.000+) voci di bilancio

• 16.000+ (85.000+) call/mese

• “Pluggato” a servizi di terze parti

• Picchi di lavoro “temporali”

Page 4: From CRUD to messages: a true story

Pre

sen

tati

on

Lay

er

Serv

ice/

Ap

plic

atio

n L

ayer

Do

mai

n M

od

el

Storage

Page 5: From CRUD to messages: a true story
Page 6: From CRUD to messages: a true story

public interface ICompanyDossierService

{

void CloseCompanyFile(Guid id);

void SetInCharge(Guid id);

void SetAnalysisInCharge(Guid id);

IEnumerable<CompanyDossier> Search(Int16[] statuses, ...);

Guid Save(Guid companyFileId, String description, ...);

void DeleteAttachment(Guid id);

AttachmentStream GetAttachmentStream(Guid id);

...

}

Page 7: From CRUD to messages: a true story
Page 8: From CRUD to messages: a true story
Page 9: From CRUD to messages: a true story

ANY PROBLEM?

Page 10: From CRUD to messages: a true story

• Logica (mal) sparpagliata

• Contesti non definiti

• Modello “fragile” e poco propenso alle

evoluzioni

• Un unico modello per la lettura e per la

scrittura

• Prestazioni

• UI “generazionalista”

Page 11: From CRUD to messages: a true story
Page 12: From CRUD to messages: a true story

An object model of the domain that

incorporates both behavior and data

[Martin Fowler - http://martinfowler.com/eaaCatalog/domainModel.html]

Page 13: From CRUD to messages: a true story

Use aggregates as unit of

consistency

across your domain model

Protect your model with clearly

defined bounded context

Eric Evans

Page 14: From CRUD to messages: a true story

Use aggregates as unit of

consistency

across your domain model

Protect your model with clearly

defined bounded context

Eric Evans

Page 15: From CRUD to messages: a true story

Use aggregates as unit of

consistency

across your domain model

Protect your model with clearly

defined bounded context

Eric Evans

Page 16: From CRUD to messages: a true story

A single model cannot be appropriate for

reporting, searching and transactional

behavior

Greg Young

Page 17: From CRUD to messages: a true story

Pre

sen

tati

on

Lay

er

Serv

ice

Laye

r

Do

mai

n M

od

el

Write storage

Read storage

Page 18: From CRUD to messages: a true story

State transition are an important part of our

problem space and should be modeled

within our domain

Greg Young, 2008

Page 19: From CRUD to messages: a true story
Page 20: From CRUD to messages: a true story

{

"_id" : {

"BucketId" : "Documents/Type",

"StreamId" : "1",

"CommitSequence" : 1

}

"CheckpointNumber" : NumberLong(9460),

"CommitId" : LUUID("5aeae871-8a94-294a-88b1-b2487e5d88d6"),

"CommitStamp" : ISODate("2013-11-21T14:58:08.500Z"),

"Dispatched" : true,

"Events" : [ {

"StreamRevision" : 1,

"Payload" : {

”Code" : ”SITBNC",

”Name" : "Situazione bancaria”,

“Enabled” : true,

“Metadata” : []

}

}],

"Headers" : {

"who" : "guest",

"when" : "2013112115580858",

"when/ticks" : NumberLong(635206462884868984),

"correlation" : "230b5b33-a2ce-4f7e-aa4e-a885c3f05274”

}

}

Page 21: From CRUD to messages: a true story

It’s really become clear to me in the last

couple of years that we need a new building

block and that is the domain events

Eric Evans

Page 22: From CRUD to messages: a true story

It’s really become clear to me

in the last couple of years

that we need a new building block

and that is the domain events

Eric Evans

Page 23: From CRUD to messages: a true story

Pre

sen

tati

on

Lay

er

Serv

ice

Laye

r

Do

mai

n M

od

el

Write storage

Read storage

Page 24: From CRUD to messages: a true story

CONTACT CENTER FINANCE

Compute Ratings

Command

Appointment

Reserved

Page 25: From CRUD to messages: a true story

class ComputeRatingsCommandActivator :

IConsumer<AppointmentReserved>

{

public async Task Consume(

ConsumeContext<AppointmentReserved> context)

{

// COLLECT INFOS AND INITIALIZE THE COMMAND

var endpoint =

await context.GetSendEndpoint(“MyCommandEndpoint”);

endpoint.Send(command);

}

}

Page 26: From CRUD to messages: a true story

CONTACT CENTER

FINANCE

Compute Ratings

Command

Appointment

Reserved

CONSULTANT

Reserve Slot

Command

Appointment

Reserved

Appointment

Reserved

Page 27: From CRUD to messages: a true story

class MachineInstance : SagaStateMachineInstance

{

public Guid CorrelationId { get; private set; }

public State CurrentState { get; private set; }

public Boolean ConsultantCommandResponse { get; set; }

public Boolean FinanceCommandResponse { get; set; }

}

class StateMachine : MassTransitStateMachine<MachineInstance>

{

public StateMachine()

{

// MASSTRANSIT’S DSL TO DEFINE SAGA

}

public State Running { get; set; }

public Event<AppointmentActivated>

AppointmentActivated { get; private set; }

public Event<ConsultantCommandExecuted>

ConsultantCommandExecuted { get; private set; }

public Event<FinanceCommandExecuted>

FinanceCommandExecuted { get; private set; }

}

Page 28: From CRUD to messages: a true story

GOOD / BAD

Page 29: From CRUD to messages: a true story

CONTACT CENTER

FINANCE

Compute Ratings

Command

State Transition

Happened

CONSULTANT

Reserve Slot

Command

Resource

Changed

Resource

Changed

Resource

Changed

Page 30: From CRUD to messages: a true story

CONTACT CENTER

FINANCE

CONSULTANT

Page 31: From CRUD to messages: a true story

class ComputeRatingsCommandActivator :

IConsumer<AppointmentReserved>

{

public async Task Consume(

ConsumeContext<AppointmentReserved> context)

{

// COLLECT INFOS AND INITIALIZE THE COMMAND

var endpoint =

await context.GetSendEndpoint(“MyCommandEndpoint”);

endpoint.Send(command);

}

}

Page 32: From CRUD to messages: a true story

REST (HTTP)

TO THE RESCUE

Page 33: From CRUD to messages: a true story

class ComputeRatingsCommandActivator :

IConsumer<AppointmentReserved>

{

public async Task Consume(

ConsumeContext<AppointmentReserved> context)

{

// USE API (MICROSERVICE?) TO COLLECT INFOS

// AND INITIALIZE THE COMMAND

var endpoint =

await context.GetSendEndpoint(“MyCommandEndpoint”);

endpoint.Send(command);

}

}

Page 34: From CRUD to messages: a true story

> GET /api/appointments/13

< 200 Ok

< ETag: 686897696a7c876b7e

< Last-Modified: Thu, 05 Jul 2012 15:31:30

GMT

Page 35: From CRUD to messages: a true story

> GET /api/appointments/13

< 301 Moved permanently

< Location: http://...

Page 36: From CRUD to messages: a true story

DEPLOY?

Page 37: From CRUD to messages: a true story

SONO UNA CAGATA PAZZESCA!!!

I MICROSERVICES…

Page 38: From CRUD to messages: a true story
Page 39: From CRUD to messages: a true story

WHEN?Tackling complexity in the heart of software

Page 40: From CRUD to messages: a true story

WHEN?

Tackling complexity in the

heart of software

Page 41: From CRUD to messages: a true story