from crud to messages: a true story

Post on 18-Jul-2015

126 Views

Category:

Technology

2 Downloads

Preview:

Click to see full reader

TRANSCRIPT

From CRUD to messages…a true story…

Alessandro Melchiori

@amelchiori

alessandro@codiceplastico.co

m

http://melkio.codiceplastico.co

m

…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”

Pre

sen

tati

on

Lay

er

Serv

ice/

Ap

plic

atio

n L

ayer

Do

mai

n M

od

el

Storage

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);

...

}

ANY PROBLEM?

• 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”

An object model of the domain that

incorporates both behavior and data

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

Use aggregates as unit of

consistency

across your domain model

Protect your model with clearly

defined bounded context

Eric Evans

Use aggregates as unit of

consistency

across your domain model

Protect your model with clearly

defined bounded context

Eric Evans

Use aggregates as unit of

consistency

across your domain model

Protect your model with clearly

defined bounded context

Eric Evans

A single model cannot be appropriate for

reporting, searching and transactional

behavior

Greg Young

Pre

sen

tati

on

Lay

er

Serv

ice

Laye

r

Do

mai

n M

od

el

Write storage

Read storage

State transition are an important part of our

problem space and should be modeled

within our domain

Greg Young, 2008

{

"_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”

}

}

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

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

Pre

sen

tati

on

Lay

er

Serv

ice

Laye

r

Do

mai

n M

od

el

Write storage

Read storage

CONTACT CENTER FINANCE

Compute Ratings

Command

Appointment

Reserved

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);

}

}

CONTACT CENTER

FINANCE

Compute Ratings

Command

Appointment

Reserved

CONSULTANT

Reserve Slot

Command

Appointment

Reserved

Appointment

Reserved

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; }

}

GOOD / BAD

CONTACT CENTER

FINANCE

Compute Ratings

Command

State Transition

Happened

CONSULTANT

Reserve Slot

Command

Resource

Changed

Resource

Changed

Resource

Changed

CONTACT CENTER

FINANCE

CONSULTANT

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);

}

}

REST (HTTP)

TO THE RESCUE

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);

}

}

> GET /api/appointments/13

< 200 Ok

< ETag: 686897696a7c876b7e

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

GMT

> GET /api/appointments/13

< 301 Moved permanently

< Location: http://...

DEPLOY?

SONO UNA CAGATA PAZZESCA!!!

I MICROSERVICES…

WHEN?Tackling complexity in the heart of software

WHEN?

Tackling complexity in the

heart of software

top related