$30 off During Our Annual Pro Sale. View Details »

CQRS v rohlik.cz

CQRS v rohlik.cz

Ukázka použití CQRS v praxi, na projektu Rohlik.cz, který je postavený na Doctrine 2 ORM s MySQL a Elastic Search.

Filip Procházka

December 21, 2015
Tweet

More Decks by Filip Procházka

Other Decks in Technology

Transcript

  1. Co si povíme - Na čem běží Rohlik.cz - Co

    je ORM, a proč ho používat - Seznámení s Doctrine 2 - Seznámení s ElasticSearch - CQRS
  2. Na čem běžíme: platforma - PHP-FPM - NGINX - Percona

    (MySQL) - Redis - RabbitMQ - ElasticSearch
  3. Na čem běžíme: aplikace - Nette Framework - Doctrine 2

    ORM - Symfony komponenty - React.PHP
  4. Na čem běžíme: podpůrné technologie - NewRelic - Papertrail -

    Travis CI - GitHub - Slack - Composer - ...
  5. “Nejhloupější” modely class OrdersModel { private $db; function __construct(DbConnection $db)

    { $this->db = $db; } function findAll() { return $this->db->query("SELECT * FROM orders"); }
  6. ORM? Object-relational mapping is a programming technique for converting data

    between incompatible type systems in object-oriented programming languages. via https://en.wikipedia.org/wiki/Object-relational_mapping
  7. Pseudo-ORM class OrdersModel { private $db; function __construct(DbConnection $db) {

    $this->db = $db; } function findAll() { return $this->mapResult( $this->db->query("SELECT * FROM orders") ); }
  8. SOLID • Single responsibility principle • Open/closed principle • Liskov

    substitution principle • Interface segregation principle • Dependency inversion principle
  9. Data Mapper - Můžu mít kompletně objektový model - Entity

    jsou objekty, které se nestarají o persistenci - To že je entita uložena v DB je “detail”
  10. Doctrine: DBAL - Obálka nad PDO - Abstrakce mezi databázemi

    - Primitivní datové typy - Schéma - Snadnější DB migrace
  11. Doctrine: class Product { /** @var int */ private $id;

    /** @var string */ private $name; Entities
  12. Doctrine: /** @Entity @Table(name="products") **/ class Product { /** @Id

    @Column(type="integer") @GeneratedValue **/ private $id; /** @Column(type="string") **/ private $name; Entities
  13. Doctrine: Services - Logické jednotky a operace v aplikaci -

    Může být více services na jednu entitu - Může být více entit na jednu service
  14. Doctrine: DQL SELECT b, e, r FROM Bug b JOIN

    b.engineer e JOIN b.reporter r ORDER BY b.created DESC
  15. Doctrine: nevýhody - Je nutné chápat OOP - Je nutné

    chápat DataMapper a spol. - Leaky abstraction - Výkon
  16. ElasticSearch - obsahuje index - indexy obsahují typy - typy

    obsahují dokumenty - dokumenty mají id a fieldy GET /rohlikcz/product/123
  17. ElasticSearch: (de)normalizace - app -> databáze = normalizace - méně

    dat - méně duplikací - horší na dotazování - databáze -> ES = denormalizace - duplikace, duplikace, duplikace - so fucking fast
  18. ElasticSearch GET /megacorp/employee/_search?q=last_name:Smith { ... "hits": { "total": 2, "hits":

    [ { ... "_source": { "first_name": "John", "last_name": "Smith", "age": 25, "about": "I love to go rock climbing", "interests": [ "sports", "music" ] } },
  19. ElasticSearch + Doctrine - Entity se nemapují 1:1 na typy

    - Typy mají vlastní serializery - V serializerech můžu pokládat SQL dotazy - Synchronizace běží v RabbitMQ workeru
  20. ElasticSearch + Doctrine $product = $em->find(Product::class, 1); $product->name = 'Banán';

    $em->flush(); // volá se automaticky $searchSync->append($product);
  21. ElasticSearch + Doctrine class ProductSerializer { public function serialize($product) {

    return [ 'id' => $product->id, 'name' => $product->name, ]; }
  22. ElasticSearch + Doctrine $query = (new Query(...)) ->andMust(...); $resultSet =

    $searchManager ->search($query); $products = $productsMapper ->mapResult($resultSet);
  23. ElasticSearch + Doctrine function mapResult(ResultSet $resultSet) { $result = [];

    foreach ($resultSet->results as $item) { $result[$item->id] = new ProductDTO($item->id, $item->source); } return $result; }
  24. ElasticSearch + Doctrine class ProductDTO { private $id; private $source;

    public function __construct($id, $source) { $this->id = $id; $this->source = $source; }
  25. ElasticSearch + Doctrine class ProductDTO { // ... public function

    __get($field) { return $this->source[$field]; }
  26. CQS It states that every method should either be a

    command that performs an action, or a query that returns data to the caller, but not both. In other words, Asking a question should not change the answer. via https://en.wikipedia.org/wiki/Command%E2%80%93query_separation
  27. CQRS Applies the CQS principle by using separate Query and

    Command objects to retrieve and modify data, respectively. via https://en.wikipedia.org/wiki/Command%E2%80%93query_separation
  28. Shrnutí - ORM je super - S ORM je jednodušší

    se střelit do nohy - ElasticSearch je super - CQRS je super