Temos ouvido falar em várias técnicas e tendências que surgem/ressurgem constantemente na nossa área. Tais como Arquitetura Reativa, CQRS, Event Sourcing, Modelagem NoSQL, Pub/Sub, Design Patterns, etc... Nesta palestra irei falar sobre um caso real onde essas técnicas foram utilizadas para atender requisitos do sistema. Detalhar os motivos, tecnologias, complexidade, ganhos/perdas e lições aprendidas.
3. Contextualização
• Objetivo do sistema
Informatizar 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
4. Cache
Qual a vantagem?
Acesso rápido a dados e economia de CPU
Qual a desvantagem?
Risco de acessar dados inconsistentes/desatualizados
6. Local Cache Shared Cache
Como lidar com Cache em serviços
distribuídos?
Menos concorrência
Cache menor
Risco maior de dado desatualizado
Mais fácil para manter consistência
Difícil identificar quem é o DONO
da informação
8. Como mantemos dados consistentes usando
Local Cache?
Publish Subscribe Message Pattern
Fonte: http://www.enterpriseintegrationpatterns.com/patterns/messaging/PublishSubscribeChannel.html
10. CRUD -> C(reate) R(ead) U(pdate) D(delete)
@Path("/cadeira")
public class CadeiraRest {
@Inject
CadeiraService cadeiraService;
@POST
public Response novaCadeira(CadeiraVO cadeiraVo) {
return Response.status(Status.CREATED).entity(cadeiraService.save(cadeiraVo)).build();
}
@GET
public Response buscarTodasCadeiras() {
return Response.status(Status.OK).entity(cadeiraService.findAll()).build();
}
@PUT
public 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();
}
}
@Service
public class CadeiraService {
@Inject
CadeiraRepository 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);
}
}
11. CQRS -> Command Query Resource Segregation
A forma que tu grava o dado é diferente da forma que tu lê.
http://www.kennybastani.com/2017/01/building-event-driven-
microservices.html
12. 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
18. 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
19. 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, user
u where c.user_id = u.id and c.dish_id = 1
db.getCollection(‘Dish’).find({_id : 1})
20. Inconsistência de Dados
O 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
21. 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 no
syncronized(dish.getId(){
Comment comment = Comment.of(user, text);
dish.addComment(comment);
dishRepository.save(dish);
}
22. • Codigo com update do mongodb
mongoTemplate.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
23. 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
24. 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));
26. 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
27. "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