Arquitetando com buzzwords
-
Upload
fabiano-modos -
Category
Software
-
view
69 -
download
0
Transcript of Arquitetando com buzzwords
![Page 1: Arquitetando com buzzwords](https://reader031.fdocumentos.tips/reader031/viewer/2022021503/5a6560577f8b9a2c6e8b4729/html5/thumbnails/1.jpg)
Arquitetando com BuzzwordsFabiano Guizellini Modos
Arquiteto de Software na HBSIS
@fmodos
![Page 2: Arquitetando com buzzwords](https://reader031.fdocumentos.tips/reader031/viewer/2022021503/5a6560577f8b9a2c6e8b4729/html5/thumbnails/2.jpg)
Por que Arquitetando com Buzzwords?
![Page 3: Arquitetando com buzzwords](https://reader031.fdocumentos.tips/reader031/viewer/2022021503/5a6560577f8b9a2c6e8b4729/html5/thumbnails/3.jpg)
Contextualização
• Objetivo do sistemaInformatizar mais de 600 planilhas Excel
• Tamanho do sistema atualmente~200 tipos de entidades (tabela)~600 relacionamentos entre as tabelas~3000 colunas (~1500 colunas são fórmulas customizáveis)~1 tela de cadastro por entidade (~200 telas)
• Usuários podem Adicionar, Editar e Excluir registros
![Page 4: Arquitetando com buzzwords](https://reader031.fdocumentos.tips/reader031/viewer/2022021503/5a6560577f8b9a2c6e8b4729/html5/thumbnails/4.jpg)
Cache
Qual a vantagem?
Acesso rápido a dados e economia de CPU
Qual a desvantagem?
Risco de acessar dados inconsistentes/desatualizados
![Page 5: Arquitetando com buzzwords](https://reader031.fdocumentos.tips/reader031/viewer/2022021503/5a6560577f8b9a2c6e8b4729/html5/thumbnails/5.jpg)
Gânglio Basal – cache do cérebro
![Page 6: Arquitetando com buzzwords](https://reader031.fdocumentos.tips/reader031/viewer/2022021503/5a6560577f8b9a2c6e8b4729/html5/thumbnails/6.jpg)
Local Cache Shared Cache
Como lidar com Cache em serviços distribuídos?
Menos concorrênciaCache menorRisco maior de dado desatualizado
Mais fácil para manter consistênciaDifícil identificar quem é o DONO da informação
![Page 7: Arquitetando com buzzwords](https://reader031.fdocumentos.tips/reader031/viewer/2022021503/5a6560577f8b9a2c6e8b4729/html5/thumbnails/7.jpg)
Onde utilizamos Local Cache?
Fórmula modo edição:
Fórmula traduzida para o usuário:
![Page 8: Arquitetando com buzzwords](https://reader031.fdocumentos.tips/reader031/viewer/2022021503/5a6560577f8b9a2c6e8b4729/html5/thumbnails/8.jpg)
Como mantemos dados consistentes usando Local Cache?
Publish Subscribe Message Pattern
Fonte: http://www.enterpriseintegrationpatterns.com/patterns/messaging/PublishSubscribeChannel.html
![Page 9: Arquitetando com buzzwords](https://reader031.fdocumentos.tips/reader031/viewer/2022021503/5a6560577f8b9a2c6e8b4729/html5/thumbnails/9.jpg)
Como utilizamos PubSub para atualizar LocalCache?
Publisher
Subscriber
Subscriber
![Page 10: Arquitetando com buzzwords](https://reader031.fdocumentos.tips/reader031/viewer/2022021503/5a6560577f8b9a2c6e8b4729/html5/thumbnails/10.jpg)
CRUD -> C(reate) R(ead) U(pdate) D(delete)@Path("/cadeira")public class CadeiraRest {
@InjectCadeiraService cadeiraService;
@POSTpublic Response novaCadeira(CadeiraVO cadeiraVo) {
return Response.status(Status.CREATED).entity(cadeiraService.save(cadeiraVo)).build(); }
@GETpublic Response buscarTodasCadeiras() {
return Response.status(Status.OK).entity(cadeiraService.findAll()).build();}
@PUTpublic Response alterarCadeira(CadeiraVO cadeiraVo) {
return Response.status(Status.OK).entity(cadeiraService.alterarCadeira(cadeiraVo)).build();}
@DELETE@Path("{id}")public Response excluirCadeira(@PathParam("id")Integer id) {
cadeiraService.excluirCadeira(id);return Response.status(204).build();
}}
@Servicepublic class CadeiraService {
@InjectCadeiraRepository cadeiraRepository;
public Cadeira novaCadeira(CadeiraVO cadeiraVo) {return cadeiraRepository.insert(Cadeira.of(cadeiraVo));
}
public List<Cadeira> findAll() {return cadeiraRepository.findAll();
}
public Cadeira alterarCadeira(CadeiraVO cadeiraVo) {return cadeiraRepository.save(Cadeira.of(cadeiraVo));
}
public void excluirCadeira(@PathParam("id")Integer id) {cadeiraRepository.delete(id);
}}
![Page 11: Arquitetando com buzzwords](https://reader031.fdocumentos.tips/reader031/viewer/2022021503/5a6560577f8b9a2c6e8b4729/html5/thumbnails/11.jpg)
CQRS -> Command Query Resource SegregationA forma que tu grava o dado é diferente da forma que tu lê.
http://www.kennybastani.com/2017/01/building-event-driven-microservices.html
![Page 12: Arquitetando com buzzwords](https://reader031.fdocumentos.tips/reader031/viewer/2022021503/5a6560577f8b9a2c6e8b4729/html5/thumbnails/12.jpg)
Pontos Ken Pontos Modos
100 50
Source Target Golpe
Ken Modos Haduken
Source Target Golpe Pontos Data/Hora
Ken Modos Haduken -50 03-05-2017 00:47:00
Command
Event
Snapshot
Command -> uma intenção
Event -> algo que ocorreu
Snapshot -> salva o valor atual do
agregado
![Page 13: Arquitetando com buzzwords](https://reader031.fdocumentos.tips/reader031/viewer/2022021503/5a6560577f8b9a2c6e8b4729/html5/thumbnails/13.jpg)
CQRS - Exemplos de código
• https://github.com/sdaschner/scalable-coffee-shop
• https://github.com/cer/event-sourcing-examples
• https://github.com/gregoryyoung/m-r
![Page 14: Arquitetando com buzzwords](https://reader031.fdocumentos.tips/reader031/viewer/2022021503/5a6560577f8b9a2c6e8b4729/html5/thumbnails/14.jpg)
To CRUD or to CQRS?
![Page 15: Arquitetando com buzzwords](https://reader031.fdocumentos.tips/reader031/viewer/2022021503/5a6560577f8b9a2c6e8b4729/html5/thumbnails/15.jpg)
Como utilizamos CQRS
ChangeRequestCommand:
{
modelId : ‘123’,
table : ‘cadeira’,
field : ‘valor’,
value : ‘50’
}
Command
Event Publica
Calcula Fórmulas
Atualiza Valor Fórmulas
![Page 16: Arquitetando com buzzwords](https://reader031.fdocumentos.tips/reader031/viewer/2022021503/5a6560577f8b9a2c6e8b4729/html5/thumbnails/16.jpg)
Event SourcingLog de todas operações executadas em um aggregate
public void testEventSourcing(){
long fightID = 123;
Fight fight = fightService.getById(fightID);
Fight tempFight = new Fight():
Assert.assertNotEquals(fight.getPointsPlayer1(), tempFight.getPointsPlayer1());
Assert.assertNotEquals(fight.getPointsPlayer2(), tempFight.getPointsPlayer2());
List<FightEvent> fightEvents = fightEventService.getEventsByFightID(fightID);
for(FightEvent event : fightEvents){
tempFight.apply(FightCommand.of(event));
}
Assert.assertEquals(fight.getPointsPlayer1(), tempFight.getPointsPlayer1());
Assert.assertEquals(fight.getPointsPlayer2(), tempFight.getPointsPlayer2());
}
![Page 17: Arquitetando com buzzwords](https://reader031.fdocumentos.tips/reader031/viewer/2022021503/5a6560577f8b9a2c6e8b4729/html5/thumbnails/17.jpg)
SQL NOSQL
![Page 18: Arquitetando com buzzwords](https://reader031.fdocumentos.tips/reader031/viewer/2022021503/5a6560577f8b9a2c6e8b4729/html5/thumbnails/18.jpg)
Diagrama Classe Diagrama Relacional Diagrama NoSQL
-Deve permitir cadastro de Dish informando nome, descrição e lista de ingredientes. -Deve permitir que usuários logados através do email e senha insiram comentários em um Dish.
Estudo de Caso
![Page 19: Arquitetando com buzzwords](https://reader031.fdocumentos.tips/reader031/viewer/2022021503/5a6560577f8b9a2c6e8b4729/html5/thumbnails/19.jpg)
Consulta de Dados
SQL NoSQL
select d.name, d.description from dish d where id=1
select i.name from ingredient i where i.dish_id=1
select c.text, u.nickname, u.name from comment c, useru where c.user_id = u.id and c.dish_id = 1
db.getCollection(‘Dish’).find({_id : 1})
![Page 20: Arquitetando com buzzwords](https://reader031.fdocumentos.tips/reader031/viewer/2022021503/5a6560577f8b9a2c6e8b4729/html5/thumbnails/20.jpg)
Inconsistência de DadosO que acontece se o usuário “JOSÉ” atualizar o nickname para “JOÃO”?
SQL NoSQL
update user set nickname = ‘JOÃO’ where id=1 db.getCollection(‘User’).update({_id : 1}, {$set : {nickname : ‘JOÃO’}})
{name: “Dish Test”
ingredients : [“arroz”],
comments : Array[
{
text : ‘Comentario do José’
user : {
nickname : ‘JOSÉ’
}
]
Como resolvemos?
-Utilizando o Visitor Design Pattern que veremos nos próximos capítulos
![Page 21: Arquitetando com buzzwords](https://reader031.fdocumentos.tips/reader031/viewer/2022021503/5a6560577f8b9a2c6e8b4729/html5/thumbnails/21.jpg)
Concorrência de alteração
SQL NoSQL
public void addComment(Dish dish, User user, String text){Comment comment = Comment.of(dish, user, text);commentRepository.insert(dish);
}
public void addComment(Dish dish, User user, String text){Comment comment = Comment.of(user, text);
dish.addComment(comment);dishRepository.save(dish);
}
• Syncronized??? Please nosyncronized(dish.getId(){
Comment comment = Comment.of(user, text);dish.addComment(comment);dishRepository.save(dish);
}
![Page 22: Arquitetando com buzzwords](https://reader031.fdocumentos.tips/reader031/viewer/2022021503/5a6560577f8b9a2c6e8b4729/html5/thumbnails/22.jpg)
• Codigo com update do mongodbmongoTemplate.updateFirst(queryId(dish.getId()), new Update().addToSet(comment), “Dish”)
• Fila de processamento
Como resolvemos?
-Devido uma regra de negócio toda alteração somente pode ser atualizada na planilha em datas pré definidas, dessa forma possuímos serviços agendados que atualizam os Snapshots(Planilha) de forma síncrona.
Concorrência de alteração
![Page 23: Arquitetando com buzzwords](https://reader031.fdocumentos.tips/reader031/viewer/2022021503/5a6560577f8b9a2c6e8b4729/html5/thumbnails/23.jpg)
Controle Transação MongoDB???
“Aquilo que você conhece não pode te machucar” – Livro: A lógica do cisne negro
Como resolvemos?
-Agrupamos todas as informações em um registro
-Processos batch, temos um controle de execução que gera log de cada step e consegue continuar de onde parou
![Page 24: Arquitetando com buzzwords](https://reader031.fdocumentos.tips/reader031/viewer/2022021503/5a6560577f8b9a2c6e8b4729/html5/thumbnails/24.jpg)
Como alterar registros de um agregado não estruturado?
Visitor Design Pattern
class ApplyChangeVisitor implements Visitor{ChangeRequestCommand change = ...
public void visit(Entidade e){if(e.getId().equals(change.getModelId()){
e.setFieldValue(change.getField(), change.getValue());}
}}
class abstract Entidade {public void accept(Visitor visitor){
visitor.visit(this);//busca associações e invoca accept
refEntidade.accept(visitor);}
}
Entidade planilha = ....ChangeRequestCommand change = ....planilha.accept(new ApplyChangeVisitor(change));
![Page 25: Arquitetando com buzzwords](https://reader031.fdocumentos.tips/reader031/viewer/2022021503/5a6560577f8b9a2c6e8b4729/html5/thumbnails/25.jpg)
Editing/Publishing Pattern
https://martinfowler.com/articles/two-stack-cms/#edit-publish
![Page 26: Arquitetando com buzzwords](https://reader031.fdocumentos.tips/reader031/viewer/2022021503/5a6560577f8b9a2c6e8b4729/html5/thumbnails/26.jpg)
Como utilizamos Editing/Publishing
• Criamos um conceito de View por cada usuário
• Comandos de alteração são armazenados no Editing da View do usuário
• Publishing é a versão aprovada compartilhada por todos usuários
View Usuário = Comandos Editing + Versão Publishing
![Page 27: Arquitetando com buzzwords](https://reader031.fdocumentos.tips/reader031/viewer/2022021503/5a6560577f8b9a2c6e8b4729/html5/thumbnails/27.jpg)
"My feeling is that when we prepare a program, it can be like composing poetry or music; as Andrei Ershov has said [9], programming can give us both intellectual and emotional satisfaction, because it is a real achievement to master complexity and to establish a system of consistent rules." Computer Programming as an Art Donald Knuth, 1974
![Page 28: Arquitetando com buzzwords](https://reader031.fdocumentos.tips/reader031/viewer/2022021503/5a6560577f8b9a2c6e8b4729/html5/thumbnails/28.jpg)
Obrigado!@fmodos
![Page 29: Arquitetando com buzzwords](https://reader031.fdocumentos.tips/reader031/viewer/2022021503/5a6560577f8b9a2c6e8b4729/html5/thumbnails/29.jpg)
Referências
• http://www.kennybastani.com/2017/01/building-event-driven-microservices.html
• http://cqrs.nu/Faq
• http://www.enterpriseintegrationpatterns.com/ramblings/eip1_examples_updated.html
• https://martinfowler.com/articles/201701-event-driven.html
• https://pt.wikipedia.org/wiki/Visitor_Pattern
• https://twitter.com/gregyoung
• https://docs.mongodb.com/manual/
• https://martinfowler.com/articles/two-stack-cms/#edit-publish