@rafaoe !
@JavierCane "
⛑ Aprende a convivir con el
monolito legacy
(o no)
Volumen II
Todo lo que veréis en esta
charla HA PASADO
Los hechos, nombres, y tips
son semi-REALES
En algunos tips
esta charla podría
HERIR SENSIBILIDADES
Compartimos
aprendizajes reales
La realidad y el legacy no
entienden de sensibilidades
@rafaoe @JavierCane
@rafaoe @JavierCane
$
Comencem
Ey, ey.
Hay código… pero no hay test
UserController.java
package com.codely.controller;
import com.codely.model.User;
import com.codely.repository.UserRepository;
import com.codely.service.CacheService;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Optional;
@RestController
@RequestMapping("/user")
public class UserController {
@GetMapping("/{id}")
public ResponseEntity<User> getUser(@PathVariable("id") Long id) {
UserController.java
@RequestMapping("/user")
public class UserController {
@GetMapping("/{id}")
public ResponseEntity<User> getUser(@PathVariable("id") Long id) {
CacheService cacheService = CacheService.getInstance();
String cacheKey = "user_" + id;
User user = cacheService.get(cacheKey, User.class);
if (user != null) {
return new ResponseEntity<>(user, HttpStatus.OK);
}
UserRepository userRepository = UserRepository.getInstance();
Optional<User> userOptional = userRepository.findById(id);
if (userOptional.isEmpty()) {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
user = userOptional.get();
cacheService.put(cacheKey, user);
@RequestMapping("/user")
public class UserController {
@GetMapping("/{id}")
public ResponseEntity<User> getUser(@PathVariable("id") Long id) {
CacheService cacheService = CacheService.getInstance();
String cacheKey = "user_" + id;
User user = cacheService.get(cacheKey, User.class);
if (user != null) {
return new ResponseEntity<>(user, HttpStatus.OK);
}
UserRepository userRepository = UserRepository.getInstance();
Optional<User> userOptional = userRepository.findById(id);
if (userOptional.isEmpty()) {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
user = userOptional.get();
cacheService.put(cacheKey, user);
%
%
UserController.java
Flujo de una petición
&
Infraestructura
Aplicación
Dominio
Flujo de una petición
&
Unit test Integration test
I
A
D
Repository
Controller UseCase
Service
Implementation
Acceptance test
Flujo de una petición
&
Repository
Controller UseCase
Service
Unit test Integration test
Implementation
I
A
D
Acceptance test
'
(
)
Flujo de una petición
&
Repository
Controller UseCase
Service
Unit test Integration test
Implementation
Acceptance test
I
A
D
*
Flujo de una petición
&
Repository
Controller UseCase
Service
Unit test Integration test
Implementation
Acceptance test
I
A
D
$
Aprendizajes
⏩
, No hay tests → Aceptación
⬇ Dump diario de la BD de prod
. Dump selectivo
/ Datos al vuelo
bit.ly/commitconf23
⏩ Pasan 3 años
Primera tarea en lo nuevo
SELECT
*
FROM (
SELECT
t.user_id,
t.country_id,
t.highScore,
RANK() OVER (PARTITION BY t.country_id
ORDER BY t.highScore DESC) AS countryRank,
RANK() OVER (ORDER BY t.highScore DESC) AS globalRank
FROM (
SELECT
user_id,
country_id,
MAX(score) AS highScore
SELECT
*
FROM (
SELECT
t.user_id,
t.country_id,
t.highScore,
RANK() OVER (PARTITION BY t.country_id
ORDER BY t.highScore DESC) AS countryRank,
RANK() OVER (ORDER BY t.highScore DESC) AS globalRank
FROM (
SELECT
user_id,
country_id,
MAX(score) AS highScore
FROM (
SELECT
*
FROM (
SELECT
t.user_id,
t.country_id,
t.highScore,
RANK() OVER (PARTITION BY t.country_id
ORDER BY t.highScore DESC) AS countryRank,
RANK() OVER (ORDER BY t.highScore DESC) AS globalRank
FROM (
SELECT
user_id,
country_id,
MAX(score) AS highScore
FROM (
SELECT
*
FROM (
SELECT
t.user_id,
t.country_id,
t.highScore,
RANK() OVER (PARTITION BY t.country_id
ORDER BY t.highScore DESC) AS countryRank,
RANK() OVER (ORDER BY t.highScore DESC) AS globalRank
FROM (
SELECT
user_id,
country_id,
MAX(score) AS highScore
FROM (
SELECT
*
FROM (
SELECT
t.user_id,
t.country_id,
t.highScore,
RANK() OVER (PARTITION BY t.country_id
ORDER BY t.highScore DESC) AS countryRank,
RANK() OVER (ORDER BY t.highScore DESC) AS globalRank
FROM (
SELECT
user_id,
country_id,
MAX(score) AS highScore
FROM score
WHERE topic_id = 101
GROUP BY user_id, country_id
) AS t
) AS rt
WHERE
rt.user_id = ?
)
WHERE topic_id = 101
GROUP BY user_id, country_id
) AS t
) AS rt
WHERE
rt.user_id = ?
)
WHERE topic_id = 101
GROUP BY user_id, country_id
) AS t
) AS rt
WHERE
rt.user_id = ?
)
WHERE topic_id = 101
GROUP BY user_id, country_id
) AS t
) AS rt
WHERE
rt.user_id = ?
SELECT
*
FROM (
SELECT
t.user_id,
t.country_id,
t.highScore,
RANK() OVER (PARTITION BY t.country_id
ORDER BY t.highScore DESC) AS countryRank,
RANK() OVER (ORDER BY t.highScore DESC) AS globalRank
FROM (
SELECT
user_id,
country_id,
MAX(score) AS highScore
FROM (
SELECT
*
FROM (
SELECT
t.user_id,
t.country_id,
t.highScore,
RANK() OVER (PARTITION BY t.country_id
ORDER BY t.highScore DESC) AS countryRank,
RANK() OVER (ORDER BY t.highScore DESC) AS globalRank
FROM (
SELECT
user_id,
country_id,
MAX(score) AS highScore
FROM (
SELECT
*
FROM (
SELECT
t.user_id,
t.country_id,
t.highScore,
RANK() OVER (PARTITION BY t.country_id
ORDER BY t.highScore DESC) AS countryRank,
RANK() OVER (ORDER BY t.highScore DESC) AS globalRank
FROM (
SELECT
user_id,
country_id,
MAX(score) AS highScore
FROM (
SELECT
*
FROM (
SELECT
t.user_id,
t.country_id,
t.highScore,
RANK() OVER (PARTITION BY t.country_id
ORDER BY t.highScore DESC) AS countryRank,
RANK() OVER (ORDER BY t.highScore DESC) AS globalRank
FROM (
SELECT
user_id,
country_id,
MAX(score) AS highScore
FROM score
WHERE topic_id = 101
GROUP BY user_id, country_id
) AS t
) AS rt
WHERE
rt.user_id = ?
)
WHERE topic_id = 101
GROUP BY user_id, country_id
) AS t
) AS rt
WHERE
rt.user_id = ?
)
WHERE topic_id = 101
GROUP BY user_id, country_id
) AS t
) AS rt
WHERE
rt.user_id = ?
)
WHERE topic_id = 101
GROUP BY user_id, country_id
) AS t
) AS rt
WHERE
rt.user_id = ?
SELECT
*
FROM (
SELECT
t.user_id,
t.country_id,
t.highScore,
RANK() OVER (PARTITION BY t.country_id
ORDER BY t.highScore DESC) AS countryRank,
RANK() OVER (ORDER BY t.highScore DESC) AS globalRank
FROM (
SELECT
user_id,
country_id,
MAX(score) AS highScore
FROM (
SELECT
*
FROM (
SELECT
t.user_id,
t.country_id,
t.highScore,
RANK() OVER (PARTITION BY t.country_id
ORDER BY t.highScore DESC) AS countryRank,
RANK() OVER (ORDER BY t.highScore DESC) AS globalRank
FROM (
SELECT
user_id,
country_id,
MAX(score) AS highScore
FROM (
SELECT
*
FROM (
SELECT
t.user_id,
t.country_id,
t.highScore,
RANK() OVER (PARTITION BY t.country_id
ORDER BY t.highScore DESC) AS countryRank,
RANK() OVER (ORDER BY t.highScore DESC) AS globalRank
FROM (
SELECT
user_id,
country_id,
MAX(score) AS highScore
FROM (
SELECT
*
FROM (
SELECT
t.user_id,
t.country_id,
t.highScore,
RANK() OVER (PARTITION BY t.country_id
ORDER BY t.highScore DESC) AS countryRank,
RANK() OVER (ORDER BY t.highScore DESC) AS globalRank
FROM (
SELECT
user_id,
country_id,
MAX(score) AS highScore
FROM score
WHERE topic_id = 101
GROUP BY user_id, country_id
) AS t
) AS rt
WHERE
rt.user_id = ?
)
WHERE topic_id = 101
GROUP BY user_id, country_id
) AS t
) AS rt
WHERE
rt.user_id = ?
)
WHERE topic_id = 101
GROUP BY user_id, country_id
) AS t
) AS rt
WHERE
rt.user_id = ?
)
WHERE topic_id = 101
GROUP BY user_id, country_id
) AS t
) AS rt
WHERE
rt.user_id = ?
SELECT
*
FROM (
SELECT
t.user_id,
t.country_id,
t.highScore,
RANK() OVER (PARTITION BY t.country_id
ORDER BY t.highScore DESC) AS countryRank,
RANK() OVER (ORDER BY t.highScore DESC) AS globalRank
FROM (
SELECT
user_id,
country_id,
MAX(score) AS highScore
FROM (
SELECT
*
FROM (
SELECT
t.user_id,
t.country_id,
t.highScore,
RANK() OVER (PARTITION BY t.country_id
ORDER BY t.highScore DESC) AS countryRank,
RANK() OVER (ORDER BY t.highScore DESC) AS globalRank
FROM (
SELECT
user_id,
country_id,
MAX(score) AS highScore
FROM (
SELECT
*
FROM (
SELECT
t.user_id,
t.country_id,
t.highScore,
RANK() OVER (PARTITION BY t.country_id
ORDER BY t.highScore DESC) AS countryRank,
RANK() OVER (ORDER BY t.highScore DESC) AS globalRank
FROM (
SELECT
user_id,
country_id,
MAX(score) AS highScore
FROM (
SELECT
*
FROM (
SELECT
t.user_id,
t.country_id,
t.highScore,
RANK() OVER (PARTITION BY t.country_id
ORDER BY t.highScore DESC) AS countryRank,
RANK() OVER (ORDER BY t.highScore DESC) AS globalRank
FROM (
SELECT
user_id,
country_id,
MAX(score) AS highScore
FROM score
WHERE topic_id = 101
GROUP BY user_id, country_id
) AS t
) AS rt
WHERE
rt.user_id = ?
)
WHERE topic_id = 101
GROUP BY user_id, country_id
) AS t
) AS rt
WHERE
rt.user_id = ?
)
WHERE topic_id = 101
GROUP BY user_id, country_id
) AS t
) AS rt
WHERE
rt.user_id = ?
)
WHERE topic_id = 101
GROUP BY user_id, country_id
) AS t
) AS rt
WHERE
rt.user_id = ?
SELECT
*
FROM (
SELECT
t.user_id,
t.country_id,
t.highScore,
RANK() OVER (PARTITION BY t.country_id
ORDER BY t.highScore DESC) AS countryRank,
RANK() OVER (ORDER BY t.highScore DESC) AS globalRank
FROM (
SELECT
user_id,
country_id,
MAX(score) AS highScore
FROM (
SELECT
*
FROM (
SELECT
t.user_id,
t.country_id,
t.highScore,
RANK() OVER (PARTITION BY t.country_id
ORDER BY t.highScore DESC) AS countryRank,
RANK() OVER (ORDER BY t.highScore DESC) AS globalRank
FROM (
SELECT
user_id,
country_id,
MAX(score) AS highScore
FROM (
SELECT
*
FROM (
SELECT
t.user_id,
t.country_id,
t.highScore,
RANK() OVER (PARTITION BY t.country_id
ORDER BY t.highScore DESC) AS countryRank,
RANK() OVER (ORDER BY t.highScore DESC) AS globalRank
FROM (
SELECT
user_id,
country_id,
MAX(score) AS highScore
FROM (
SELECT
*
FROM (
SELECT
t.user_id,
t.country_id,
t.highScore,
RANK() OVER (PARTITION BY t.country_id
ORDER BY t.highScore DESC) AS countryRank,
RANK() OVER (ORDER BY t.highScore DESC) AS globalRank
FROM (
SELECT
user_id,
country_id,
MAX(score) AS highScore
FROM score
WHERE topic_id = 101
GROUP BY user_id, country_id
) AS t
) AS rt
WHERE
rt.user_id = ?
)
WHERE topic_id = 101
GROUP BY user_id, country_id
) AS t
) AS rt
WHERE
rt.user_id = ?
)
WHERE topic_id = 101
GROUP BY user_id, country_id
) AS t
) AS rt
WHERE
rt.user_id = ?
)
WHERE topic_id = 101
GROUP BY user_id, country_id
) AS t
) AS rt
WHERE
rt.user_id = ?
SELECT
*
FROM (
SELECT
t.user_id,
t.country_id,
t.highScore,
RANK() OVER (PARTITION BY t.country_id
ORDER BY t.highScore DESC) AS countryRank,
RANK() OVER (ORDER BY t.highScore DESC) AS globalRank
FROM (
SELECT
user_id,
country_id,
MAX(score) AS highScore
FROM (
SELECT
*
FROM (
SELECT
t.user_id,
t.country_id,
t.highScore,
RANK() OVER (PARTITION BY t.country_id
ORDER BY t.highScore DESC) AS countryRank,
RANK() OVER (ORDER BY t.highScore DESC) AS globalRank
FROM (
SELECT
user_id,
country_id,
MAX(score) AS highScore
FROM (
SELECT
*
FROM (
SELECT
t.user_id,
t.country_id,
t.highScore,
RANK() OVER (PARTITION BY t.country_id
ORDER BY t.highScore DESC) AS countryRank,
RANK() OVER (ORDER BY t.highScore DESC) AS globalRank
FROM (
SELECT
user_id,
country_id,
MAX(score) AS highScore
FROM (
SELECT
*
FROM (
SELECT
t.user_id,
t.country_id,
t.highScore,
RANK() OVER (PARTITION BY t.country_id
ORDER BY t.highScore DESC) AS countryRank,
RANK() OVER (ORDER BY t.highScore DESC) AS globalRank
FROM (
SELECT
user_id,
country_id,
MAX(score) AS highScore
FROM score
WHERE topic_id = 101
GROUP BY user_id, country_id
) AS t
) AS rt
WHERE
rt.user_id = ?
)
WHERE topic_id = 101
GROUP BY user_id, country_id
) AS t
) AS rt
WHERE
rt.user_id = ?
)
WHERE topic_id = 101
GROUP BY user_id, country_id
) AS t
) AS rt
WHERE
rt.user_id = ?
)
WHERE topic_id = 101
GROUP BY user_id, country_id
) AS t
) AS rt
WHERE
rt.user_id = ?
SELECT
*
FROM (
SELECT
t.user_id,
t.country_id,
t.highScore,
RANK() OVER (PARTITION BY t.country_id
ORDER BY t.highScore DESC) AS countryRank,
RANK() OVER (ORDER BY t.highScore DESC) AS globalRank
FROM (
SELECT
user_id,
country_id,
MAX(score) AS highScore
FROM (
SELECT
*
FROM (
SELECT
t.user_id,
t.country_id,
t.highScore,
RANK() OVER (PARTITION BY t.country_id
ORDER BY t.highScore DESC) AS countryRank,
RANK() OVER (ORDER BY t.highScore DESC) AS globalRank
FROM (
SELECT
user_id,
country_id,
MAX(score) AS highScore
FROM (
SELECT
*
FROM (
SELECT
t.user_id,
t.country_id,
t.highScore,
RANK() OVER (PARTITION BY t.country_id
ORDER BY t.highScore DESC) AS countryRank,
RANK() OVER (ORDER BY t.highScore DESC) AS globalRan
FROM (
SELECT
user_id,
country_id,
MAX(score) AS highScore
FROM (
SELECT
*
FROM (
SELECT
t.user_id,
t.country_id,
t.highScore,
RANK() OVER (PARTITION BY
ORDER BY t.highScore
RANK() OVER (ORDER BY t.h
FROM (
SELECT
user_id,
country_id,
MAX(score) AS hi
FROM score
WHERE topic_id = 101
GROUP BY user_id, co
) AS t
) AS rt
WHERE
rt.user_id = ?
)
WHERE topic_id = 101
GROUP BY user_id, country_id
) AS t
) AS rt
WHERE
rt.user_id = ?
)
WHERE topic_id = 101
GROUP BY user_id, country_id
) AS t
) AS rt
WHERE
rt.user_id = ?
)
WHERE topic_id = 101
GROUP BY user_id, country_id
) AS t
) AS rt
WHERE
rt.user_id = ?
Flujo de una petición
&
Repository
Controller UseCase
Service
Unit test Integration test
Implementation
Acceptance test
I
A
D
*
Flujo de una petición
&
Repository
Controller UseCase
Service
Unit test Integration test
Implementation
Acceptance test
I
A
D
TopGamesRepository
interface TopGamesRepository {
public save(TopGame[] games): void;
public searchAll(): TopGame[];
}
Cómo hacer que sea un éxito
Ey, ey.
He gamificado la migración
MySqlRepository.php
abstract class MySqlRepository {
public function search($query, $tag) {
$taggedQuery = "/*"!999999 $tag */$ $query";
// ...
}
}
OtherSqlRepository.php
abstract class OtherSqlRepository {
public function search($query, $tag) {
$taggedQuery = "IF('$tag' = '', 1, 0) AS tagged $query";
// ...
}
}
⏩ Pasan 10 años
0
1
Evolución tamaño instancias EC2
2
r6a.metal
r6a.48xlarge
r6a.48large
r6a.large r6a.xlarge
4
5
♻
7
8
Sincronización entre sistema legacy y el nuevo
♻
Legacy New
TubiAPIradora
legacy
domain_events
new
replicate_from_legacy
new
domain_events
legacy
replicate_from_new
Publica evento
Replica
Consume
Publica evento
Replica
Consume
Invoca API
9
¿Fantasía en los nombres de proyecto?
☝
Sí No
TubiAPIradora vs CDC
☝
Change Data Capture Pattern
Consume
Trigger BD
TubiAPIradora
bit.ly/codely-eda
TubiAPIradora vs CDC
☝
Change Data Capture Pattern
Consume
Trigger BD
TubiAPIradora
bit.ly/codely-eda
Cómo hacer que sea un éxito
LegacyEventBus
public publish(array $event): void
{
Publisher.publish(
add(
$event,
['metadata' =>& ['from_legacy' =>& true]]
)
);
}
Aprende a convivir con el
monolito legacy (o no)
Aprende a convivir con el
monolito legacy
Resultados encuesta
¿Nombres fantasiosos para proyectos?
2
0
25
50
75
100
0
100
No Sí
bit.ly/hiring-codely
¡Muchas gracias!
Nos vemos en Codely

Aprende a convivir con legacy (o no) - Vol. 2

  • 1.
    @rafaoe ! @JavierCane " ⛑Aprende a convivir con el monolito legacy (o no) Volumen II
  • 2.
    Todo lo queveréis en esta charla HA PASADO
  • 3.
    Los hechos, nombres,y tips son semi-REALES
  • 4.
    En algunos tips estacharla podría HERIR SENSIBILIDADES
  • 5.
  • 6.
    La realidad yel legacy no entienden de sensibilidades
  • 7.
  • 8.
  • 9.
  • 14.
    Ey, ey. Hay código…pero no hay test
  • 16.
    UserController.java package com.codely.controller; import com.codely.model.User; importcom.codely.repository.UserRepository; import com.codely.service.CacheService; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.Optional; @RestController @RequestMapping("/user") public class UserController { @GetMapping("/{id}") public ResponseEntity<User> getUser(@PathVariable("id") Long id) {
  • 17.
    UserController.java @RequestMapping("/user") public class UserController{ @GetMapping("/{id}") public ResponseEntity<User> getUser(@PathVariable("id") Long id) { CacheService cacheService = CacheService.getInstance(); String cacheKey = "user_" + id; User user = cacheService.get(cacheKey, User.class); if (user != null) { return new ResponseEntity<>(user, HttpStatus.OK); } UserRepository userRepository = UserRepository.getInstance(); Optional<User> userOptional = userRepository.findById(id); if (userOptional.isEmpty()) { return new ResponseEntity<>(HttpStatus.NOT_FOUND); } user = userOptional.get(); cacheService.put(cacheKey, user);
  • 18.
    @RequestMapping("/user") public class UserController{ @GetMapping("/{id}") public ResponseEntity<User> getUser(@PathVariable("id") Long id) { CacheService cacheService = CacheService.getInstance(); String cacheKey = "user_" + id; User user = cacheService.get(cacheKey, User.class); if (user != null) { return new ResponseEntity<>(user, HttpStatus.OK); } UserRepository userRepository = UserRepository.getInstance(); Optional<User> userOptional = userRepository.findById(id); if (userOptional.isEmpty()) { return new ResponseEntity<>(HttpStatus.NOT_FOUND); } user = userOptional.get(); cacheService.put(cacheKey, user); % % UserController.java
  • 19.
    Flujo de unapetición & Infraestructura Aplicación Dominio
  • 20.
    Flujo de unapetición & Unit test Integration test I A D Repository Controller UseCase Service Implementation Acceptance test
  • 21.
    Flujo de unapetición & Repository Controller UseCase Service Unit test Integration test Implementation I A D Acceptance test ' ( )
  • 22.
    Flujo de unapetición & Repository Controller UseCase Service Unit test Integration test Implementation Acceptance test I A D *
  • 23.
    Flujo de unapetición & Repository Controller UseCase Service Unit test Integration test Implementation Acceptance test I A D $
  • 24.
    Aprendizajes ⏩ , No haytests → Aceptación ⬇ Dump diario de la BD de prod . Dump selectivo / Datos al vuelo
  • 25.
  • 26.
  • 27.
  • 28.
    SELECT * FROM ( SELECT t.user_id, t.country_id, t.highScore, RANK() OVER(PARTITION BY t.country_id ORDER BY t.highScore DESC) AS countryRank, RANK() OVER (ORDER BY t.highScore DESC) AS globalRank FROM ( SELECT user_id, country_id, MAX(score) AS highScore
  • 29.
    SELECT * FROM ( SELECT t.user_id, t.country_id, t.highScore, RANK() OVER(PARTITION BY t.country_id ORDER BY t.highScore DESC) AS countryRank, RANK() OVER (ORDER BY t.highScore DESC) AS globalRank FROM ( SELECT user_id, country_id, MAX(score) AS highScore FROM ( SELECT * FROM ( SELECT t.user_id, t.country_id, t.highScore, RANK() OVER (PARTITION BY t.country_id ORDER BY t.highScore DESC) AS countryRank, RANK() OVER (ORDER BY t.highScore DESC) AS globalRank FROM ( SELECT user_id, country_id, MAX(score) AS highScore FROM ( SELECT * FROM ( SELECT t.user_id, t.country_id, t.highScore, RANK() OVER (PARTITION BY t.country_id ORDER BY t.highScore DESC) AS countryRank, RANK() OVER (ORDER BY t.highScore DESC) AS globalRank FROM ( SELECT user_id, country_id, MAX(score) AS highScore FROM ( SELECT * FROM ( SELECT t.user_id, t.country_id, t.highScore, RANK() OVER (PARTITION BY t.country_id ORDER BY t.highScore DESC) AS countryRank, RANK() OVER (ORDER BY t.highScore DESC) AS globalRank FROM ( SELECT user_id, country_id, MAX(score) AS highScore FROM score WHERE topic_id = 101 GROUP BY user_id, country_id ) AS t ) AS rt WHERE rt.user_id = ? ) WHERE topic_id = 101 GROUP BY user_id, country_id ) AS t ) AS rt WHERE rt.user_id = ? ) WHERE topic_id = 101 GROUP BY user_id, country_id ) AS t ) AS rt WHERE rt.user_id = ? ) WHERE topic_id = 101 GROUP BY user_id, country_id ) AS t ) AS rt WHERE rt.user_id = ?
  • 30.
    SELECT * FROM ( SELECT t.user_id, t.country_id, t.highScore, RANK() OVER(PARTITION BY t.country_id ORDER BY t.highScore DESC) AS countryRank, RANK() OVER (ORDER BY t.highScore DESC) AS globalRank FROM ( SELECT user_id, country_id, MAX(score) AS highScore FROM ( SELECT * FROM ( SELECT t.user_id, t.country_id, t.highScore, RANK() OVER (PARTITION BY t.country_id ORDER BY t.highScore DESC) AS countryRank, RANK() OVER (ORDER BY t.highScore DESC) AS globalRank FROM ( SELECT user_id, country_id, MAX(score) AS highScore FROM ( SELECT * FROM ( SELECT t.user_id, t.country_id, t.highScore, RANK() OVER (PARTITION BY t.country_id ORDER BY t.highScore DESC) AS countryRank, RANK() OVER (ORDER BY t.highScore DESC) AS globalRank FROM ( SELECT user_id, country_id, MAX(score) AS highScore FROM ( SELECT * FROM ( SELECT t.user_id, t.country_id, t.highScore, RANK() OVER (PARTITION BY t.country_id ORDER BY t.highScore DESC) AS countryRank, RANK() OVER (ORDER BY t.highScore DESC) AS globalRank FROM ( SELECT user_id, country_id, MAX(score) AS highScore FROM score WHERE topic_id = 101 GROUP BY user_id, country_id ) AS t ) AS rt WHERE rt.user_id = ? ) WHERE topic_id = 101 GROUP BY user_id, country_id ) AS t ) AS rt WHERE rt.user_id = ? ) WHERE topic_id = 101 GROUP BY user_id, country_id ) AS t ) AS rt WHERE rt.user_id = ? ) WHERE topic_id = 101 GROUP BY user_id, country_id ) AS t ) AS rt WHERE rt.user_id = ? SELECT * FROM ( SELECT t.user_id, t.country_id, t.highScore, RANK() OVER (PARTITION BY t.country_id ORDER BY t.highScore DESC) AS countryRank, RANK() OVER (ORDER BY t.highScore DESC) AS globalRank FROM ( SELECT user_id, country_id, MAX(score) AS highScore FROM ( SELECT * FROM ( SELECT t.user_id, t.country_id, t.highScore, RANK() OVER (PARTITION BY t.country_id ORDER BY t.highScore DESC) AS countryRank, RANK() OVER (ORDER BY t.highScore DESC) AS globalRank FROM ( SELECT user_id, country_id, MAX(score) AS highScore FROM ( SELECT * FROM ( SELECT t.user_id, t.country_id, t.highScore, RANK() OVER (PARTITION BY t.country_id ORDER BY t.highScore DESC) AS countryRank, RANK() OVER (ORDER BY t.highScore DESC) AS globalRank FROM ( SELECT user_id, country_id, MAX(score) AS highScore FROM ( SELECT * FROM ( SELECT t.user_id, t.country_id, t.highScore, RANK() OVER (PARTITION BY t.country_id ORDER BY t.highScore DESC) AS countryRank, RANK() OVER (ORDER BY t.highScore DESC) AS globalRank FROM ( SELECT user_id, country_id, MAX(score) AS highScore FROM score WHERE topic_id = 101 GROUP BY user_id, country_id ) AS t ) AS rt WHERE rt.user_id = ? ) WHERE topic_id = 101 GROUP BY user_id, country_id ) AS t ) AS rt WHERE rt.user_id = ? ) WHERE topic_id = 101 GROUP BY user_id, country_id ) AS t ) AS rt WHERE rt.user_id = ? ) WHERE topic_id = 101 GROUP BY user_id, country_id ) AS t ) AS rt WHERE rt.user_id = ? SELECT * FROM ( SELECT t.user_id, t.country_id, t.highScore, RANK() OVER (PARTITION BY t.country_id ORDER BY t.highScore DESC) AS countryRank, RANK() OVER (ORDER BY t.highScore DESC) AS globalRank FROM ( SELECT user_id, country_id, MAX(score) AS highScore FROM ( SELECT * FROM ( SELECT t.user_id, t.country_id, t.highScore, RANK() OVER (PARTITION BY t.country_id ORDER BY t.highScore DESC) AS countryRank, RANK() OVER (ORDER BY t.highScore DESC) AS globalRank FROM ( SELECT user_id, country_id, MAX(score) AS highScore FROM ( SELECT * FROM ( SELECT t.user_id, t.country_id, t.highScore, RANK() OVER (PARTITION BY t.country_id ORDER BY t.highScore DESC) AS countryRank, RANK() OVER (ORDER BY t.highScore DESC) AS globalRank FROM ( SELECT user_id, country_id, MAX(score) AS highScore FROM ( SELECT * FROM ( SELECT t.user_id, t.country_id, t.highScore, RANK() OVER (PARTITION BY t.country_id ORDER BY t.highScore DESC) AS countryRank, RANK() OVER (ORDER BY t.highScore DESC) AS globalRank FROM ( SELECT user_id, country_id, MAX(score) AS highScore FROM score WHERE topic_id = 101 GROUP BY user_id, country_id ) AS t ) AS rt WHERE rt.user_id = ? ) WHERE topic_id = 101 GROUP BY user_id, country_id ) AS t ) AS rt WHERE rt.user_id = ? ) WHERE topic_id = 101 GROUP BY user_id, country_id ) AS t ) AS rt WHERE rt.user_id = ? ) WHERE topic_id = 101 GROUP BY user_id, country_id ) AS t ) AS rt WHERE rt.user_id = ? SELECT * FROM ( SELECT t.user_id, t.country_id, t.highScore, RANK() OVER (PARTITION BY t.country_id ORDER BY t.highScore DESC) AS countryRank, RANK() OVER (ORDER BY t.highScore DESC) AS globalRank FROM ( SELECT user_id, country_id, MAX(score) AS highScore FROM ( SELECT * FROM ( SELECT t.user_id, t.country_id, t.highScore, RANK() OVER (PARTITION BY t.country_id ORDER BY t.highScore DESC) AS countryRank, RANK() OVER (ORDER BY t.highScore DESC) AS globalRank FROM ( SELECT user_id, country_id, MAX(score) AS highScore FROM ( SELECT * FROM ( SELECT t.user_id, t.country_id, t.highScore, RANK() OVER (PARTITION BY t.country_id ORDER BY t.highScore DESC) AS countryRank, RANK() OVER (ORDER BY t.highScore DESC) AS globalRank FROM ( SELECT user_id, country_id, MAX(score) AS highScore FROM ( SELECT * FROM ( SELECT t.user_id, t.country_id, t.highScore, RANK() OVER (PARTITION BY t.country_id ORDER BY t.highScore DESC) AS countryRank, RANK() OVER (ORDER BY t.highScore DESC) AS globalRank FROM ( SELECT user_id, country_id, MAX(score) AS highScore FROM score WHERE topic_id = 101 GROUP BY user_id, country_id ) AS t ) AS rt WHERE rt.user_id = ? ) WHERE topic_id = 101 GROUP BY user_id, country_id ) AS t ) AS rt WHERE rt.user_id = ? ) WHERE topic_id = 101 GROUP BY user_id, country_id ) AS t ) AS rt WHERE rt.user_id = ? ) WHERE topic_id = 101 GROUP BY user_id, country_id ) AS t ) AS rt WHERE rt.user_id = ? SELECT * FROM ( SELECT t.user_id, t.country_id, t.highScore, RANK() OVER (PARTITION BY t.country_id ORDER BY t.highScore DESC) AS countryRank, RANK() OVER (ORDER BY t.highScore DESC) AS globalRank FROM ( SELECT user_id, country_id, MAX(score) AS highScore FROM ( SELECT * FROM ( SELECT t.user_id, t.country_id, t.highScore, RANK() OVER (PARTITION BY t.country_id ORDER BY t.highScore DESC) AS countryRank, RANK() OVER (ORDER BY t.highScore DESC) AS globalRank FROM ( SELECT user_id, country_id, MAX(score) AS highScore FROM ( SELECT * FROM ( SELECT t.user_id, t.country_id, t.highScore, RANK() OVER (PARTITION BY t.country_id ORDER BY t.highScore DESC) AS countryRank, RANK() OVER (ORDER BY t.highScore DESC) AS globalRank FROM ( SELECT user_id, country_id, MAX(score) AS highScore FROM ( SELECT * FROM ( SELECT t.user_id, t.country_id, t.highScore, RANK() OVER (PARTITION BY t.country_id ORDER BY t.highScore DESC) AS countryRank, RANK() OVER (ORDER BY t.highScore DESC) AS globalRank FROM ( SELECT user_id, country_id, MAX(score) AS highScore FROM score WHERE topic_id = 101 GROUP BY user_id, country_id ) AS t ) AS rt WHERE rt.user_id = ? ) WHERE topic_id = 101 GROUP BY user_id, country_id ) AS t ) AS rt WHERE rt.user_id = ? ) WHERE topic_id = 101 GROUP BY user_id, country_id ) AS t ) AS rt WHERE rt.user_id = ? ) WHERE topic_id = 101 GROUP BY user_id, country_id ) AS t ) AS rt WHERE rt.user_id = ? SELECT * FROM ( SELECT t.user_id, t.country_id, t.highScore, RANK() OVER (PARTITION BY t.country_id ORDER BY t.highScore DESC) AS countryRank, RANK() OVER (ORDER BY t.highScore DESC) AS globalRank FROM ( SELECT user_id, country_id, MAX(score) AS highScore FROM ( SELECT * FROM ( SELECT t.user_id, t.country_id, t.highScore, RANK() OVER (PARTITION BY t.country_id ORDER BY t.highScore DESC) AS countryRank, RANK() OVER (ORDER BY t.highScore DESC) AS globalRank FROM ( SELECT user_id, country_id, MAX(score) AS highScore FROM ( SELECT * FROM ( SELECT t.user_id, t.country_id, t.highScore, RANK() OVER (PARTITION BY t.country_id ORDER BY t.highScore DESC) AS countryRank, RANK() OVER (ORDER BY t.highScore DESC) AS globalRan FROM ( SELECT user_id, country_id, MAX(score) AS highScore FROM ( SELECT * FROM ( SELECT t.user_id, t.country_id, t.highScore, RANK() OVER (PARTITION BY ORDER BY t.highScore RANK() OVER (ORDER BY t.h FROM ( SELECT user_id, country_id, MAX(score) AS hi FROM score WHERE topic_id = 101 GROUP BY user_id, co ) AS t ) AS rt WHERE rt.user_id = ? ) WHERE topic_id = 101 GROUP BY user_id, country_id ) AS t ) AS rt WHERE rt.user_id = ? ) WHERE topic_id = 101 GROUP BY user_id, country_id ) AS t ) AS rt WHERE rt.user_id = ? ) WHERE topic_id = 101 GROUP BY user_id, country_id ) AS t ) AS rt WHERE rt.user_id = ?
  • 31.
    Flujo de unapetición & Repository Controller UseCase Service Unit test Integration test Implementation Acceptance test I A D *
  • 32.
    Flujo de unapetición & Repository Controller UseCase Service Unit test Integration test Implementation Acceptance test I A D
  • 33.
    TopGamesRepository interface TopGamesRepository { publicsave(TopGame[] games): void; public searchAll(): TopGame[]; }
  • 34.
    Cómo hacer quesea un éxito Ey, ey. He gamificado la migración
  • 36.
    MySqlRepository.php abstract class MySqlRepository{ public function search($query, $tag) { $taggedQuery = "/*"!999999 $tag */$ $query"; // ... } }
  • 37.
    OtherSqlRepository.php abstract class OtherSqlRepository{ public function search($query, $tag) { $taggedQuery = "IF('$tag' = '', 1, 0) AS tagged $query"; // ... } }
  • 38.
  • 39.
    0 1 Evolución tamaño instanciasEC2 2 r6a.metal r6a.48xlarge r6a.48large r6a.large r6a.xlarge 4 5 ♻ 7 8
  • 40.
    Sincronización entre sistemalegacy y el nuevo ♻ Legacy New TubiAPIradora legacy domain_events new replicate_from_legacy new domain_events legacy replicate_from_new Publica evento Replica Consume Publica evento Replica Consume Invoca API 9
  • 41.
    ¿Fantasía en losnombres de proyecto? ☝ Sí No
  • 42.
    TubiAPIradora vs CDC ☝ ChangeData Capture Pattern Consume Trigger BD TubiAPIradora bit.ly/codely-eda
  • 43.
    TubiAPIradora vs CDC ☝ ChangeData Capture Pattern Consume Trigger BD TubiAPIradora bit.ly/codely-eda
  • 44.
    Cómo hacer quesea un éxito
  • 45.
    LegacyEventBus public publish(array $event):void { Publisher.publish( add( $event, ['metadata' =>& ['from_legacy' =>& true]] ) ); }
  • 47.
    Aprende a convivircon el monolito legacy (o no)
  • 48.
    Aprende a convivircon el monolito legacy
  • 49.
    Resultados encuesta ¿Nombres fantasiosospara proyectos? 2 0 25 50 75 100 0 100 No Sí bit.ly/hiring-codely ¡Muchas gracias! Nos vemos en Codely