Palestra realizada no www.qconsp.com em 2010, mostrando diversas definições para arquitetura e design e depois dando exemplos reais de como o Design também é de extrema importância para poder flexibilizar suas decisões arquiteturais e respectivos tradeoffs.
Porque você deveria usar CDI nos seus projetos Java! - JavaOne LA 2012 - Sérg...
Arquitetura e Design QCon2010 - Paulo Silveira - Caelum
1. O impacto do design Paulo Silveira
paulo.silveira@caelum.com.br
na sua arquitetura @paulo_caelum
1
2. de programador a designer a arquiteto?
Então você quer ser um arquiteto Java?
http://bit.ly/arquitetoJava
Martin Fowler, Who needs an Architect?
http://bit.ly/fowlerArchitect
4. Alguns padrões são arquiteturais, outros são de design,
ajudando a arquitetura... eu não separo os dois já que o que
é arquitetural ou não é subjetivo.
Martin Fowler, Patterns of Enterprise Application
Architecture
10. Arquitetura são os principais
elementos
do sistema, as peças que são
difíceis de mudar.
11. Arquitetura são os principais
elementos
do sistema, as peças que são
difíceis de mudar.
Arquitetura são as decisões que
gostaríamos de ter tomado no começo
do projeto.
Ralph Johnson (do GoF) e Martin Fowler
Who needs an Architect?
12. meu artigo recebeu vários
comentários, inclusive essas críticas:
“Martin Fowler não sabe nada”
13. meu artigo recebeu vários
comentários, inclusive essas críticas:
“Martin Fowler não sabe nada”
“Você é poético, não sabe nada”
14. meu artigo recebeu vários
comentários, inclusive essas críticas:
“Martin Fowler não sabe nada”
“Você é poético, não sabe nada”
“Ralph Johnson não sabe nada”
15. meu artigo recebeu vários
comentários, inclusive essas críticas:
“Martin Fowler não sabe nada”
“Você é poético, não sabe nada”
“Ralph Johnson não sabe nada”
“CMU-SEI são professores, não sabem nada”
17. Arquitetura é toda decisão que impactam em
grandes trade-offs e que podem ou não
serem difíceis de mudar.
Resolvi então também dar minha opinião pessoal
18. Arquitetura é toda decisão que impactam em
grandes trade-offs e que podem ou não
serem difíceis de mudar.
E ela pode ser evolutiva
Last Responsible Moment
Resolvi então também dar minha opinião pessoal
19. E como tornar essas
decisões “mais” possíveis
de mudar?
21. Arquitetura
x
Arquitetura Java
...você precisa de pelo menos um arquiteto com
enorme experiência prática na plataforma
escolhida.
Joel Spoelsky, Language Wars
28. Site da Caelum
qual é a implementação?
repository.adiciona(noticia);
29. 1. Hibernate
public class NoticiaDao implements NoticiaRepository {
private final Session session;
public NoticiaDao(Session session) {
this.session = session;
}
public void adiciona(Noticia noticia) {
session.save(noticia);
}
@SuppressWarnings("unchecked")
public List<Noticia> todasNoticias() {
return session.createCriteria(Noticia.class)
.addOrder(Order.desc("data")).list();
}
30. o que mudamos quando
2. JPA/BigTable migramos para o cloud
31. o que mudamos quando
2. JPA/BigTable migramos para o cloud
public class NoticiaDao implements NoticiaRepository {
private final EntityManager manager;
public NoticiaDao(EntityManager manager) {
this.manager = manager;
}
public void adiciona(Noticia noticia) {
manager.persist(noticia);
}
@SuppressWarnings("unchecked")
public List<Noticia> todasNoticias() {
return manager.createQuery("select n from Noticia
n")).getResultList();
}
33. 3. Objectify
public class NoticiaDao implements NoticiaRepository {
private final Objectify objectify;
public NoticiaDao(Objectify objectify) {
this.objectify = objectify;
}
public void adiciona(Noticia noticia) {
objectify.put(noticia);
}
public List<Noticia> noticiasVisiveis() {
return objectify.query(Noticia.class).filter("ordem >",
0).order("ordem").list();
}
34. lento e
3. Objectify não muito disponível
public class NoticiaDao implements NoticiaRepository {
private final Objectify objectify;
public NoticiaDao(Objectify objectify) {
this.objectify = objectify;
}
public void adiciona(Noticia noticia) {
objectify.put(noticia);
}
public List<Noticia> noticiasVisiveis() {
return objectify.query(Noticia.class).filter("ordem >",
0).order("ordem").list();
}
36. 4. Objectify + Memcache
public class NoticiaDao implements NoticiaRepository {
private final Cache cache;
private final Objectify objectify;
public NoticiaDao(Objectify objectify, Cache cache) {
this.objectify = objectify;
this.cache = cache;
}
public void adiciona(Noticia noticia) {
objectify.put(noticia);
cache.remove(CACHE_ROOT, NOTICIAS_VISIVEIS);
}
public List<Noticia> noticiasVisiveis() {
List<Noticia> noticias = cache.get(CACHE_ROOT, NOTICIAS_VISIVEIS);
if (cached == null) {
noticias = objectify.query(Noticia.class).filter("ordem >",0).order
("ordem").list();
cache.put(CACHE_ROOT, NOTICIAS_VISIVEIS, noticias);
}
return noticias;
}
37. Relembrando IoC e DI
NoticiaRepository repository = new NoticiaRepository(???);
repository.adiciona(noticia);
38. Relembrando IoC e DI
NoticiaRepository repository = new NoticiaRepository(???);
repository.adiciona(noticia);
Ter feito o design com IoC e DI facilitou
mudanças arquiteturais:
hibernate -> JPA no Cloud -> Objectify -> Memcached
39. WebChat Ajax
Mudando de Comet com long polling
para Comet streaming com Servlets 3 AsyncContext
40. collections sem DI?
long polling como fazer blocante?
public class Agent {
// ...
private final Queue<Update> updates =
new ConcurrentLinkedQueue<Update>();
public Agent(RoomFactory roomFactory, ClientQueue queue, Tenant tenant) {
this.roomFactory = roomFactory;
this.queue = queue;
this.tenant = tenant;
}
public void addUpdate(Update update) {
updates.add(update);
}
public Update updates() {
createAndRemoveRooms();
return updates.poll();
}
41. streaming segurando conexão
thread per request no comet = bad
public class Agent {
// ...
private final BlockingQueue<Update> updates =
new LinkedBlockingQueue<Update>();
public Agent(RoomFactory roomFactory, ClientQueue queue, Tenant tenant) {
this.roomFactory = roomFactory;
this.queue = queue;
this.tenant = tenant;
}
public void addUpdate(Update update) {
updates.add(update);
}
public Update updates() {
createAndRemoveRooms();
return updates.take();
}
42. streaming não blocante
para isso a fila de eventos precisaria ser única
private BlockingQueue<Update> updates = new LinkedBlockingQueue<Update>();
// ...
while (true) {
final Update update = updates.take();
for (final AsyncContext ctx : clients.get(update.getRoom())) {
PrintWriter writer = ctx.getResponse()
.getWriter();
writer.println(update.getMessage());
writer.flush();
}
}
43. queue tb por DI e dá para voltar
pro long polling facilmente!
public class Agent {
// ...
private final Queue<Update> updates;
Agent(RoomFactory roomFactory, ClientQueue queue, Tenant tenant
Queue<Update> updates) {
this.roomFactory = roomFactory;
this.queue = queue;
this.tenant = tenant;
this.updates = updates;
}
public void addUpdate(Update update) {
updates.add(update);
}
public Update updates() {
createAndRemoveRooms();
return updates.take();
}
44. Exemplo bônus:
Nick Kallen, arquiteto
do Twitter
no #qconsp com #Scala
FIFO/LIFO
blocante/não blocante
usando IoC+DI
45. Nos 3 exemplos:
• IoC facilitou evolução arquitetural
• possibilita decisão no “last responsible
moment”
• e com isso podemos trocar trade-offs
• código, design e arquitetura muito
próximos
47. para obter isso (em JAVA!):
Boas práticas de OO (construtores)
48. para obter isso (em JAVA!):
Boas práticas de OO (construtores)
IoC e DI (mesmo sem framework)
49. para obter isso (em JAVA!):
Boas práticas de OO (construtores)
IoC e DI (mesmo sem framework)
Testes te “forçam” a DI
50. para obter isso (em JAVA!):
Boas práticas de OO (construtores)
IoC e DI (mesmo sem framework)
Testes te “forçam” a DI
Desacoplamento (generalização)