Created
May 21, 2013 20:36
-
-
Save raykolbe/5623035 to your computer and use it in GitHub Desktop.
CQRS is simple!
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace CQRSSample\Domain\Model | |
{ | |
/** | |
* Please read this. It may be interesting to you. You can ridicule me ONLY if you read the whole thing. | |
* | |
* CQRS is NOT about different data sources and is NOT about Event Sourcing. | |
* CQRS IS about breaking out your reads and writes. It's powerful and simple! | |
* | |
* That being said, you can use CQRS virtually everywhere. Think about when you use a repository (DDD Repository). A | |
* DDD repository is used to deal with your domain models. A lot of people tack on pagination for handling large data | |
* sets, custom find methods for application-specific reasons, etc. A DDD repository SHOULD only be used for domain- | |
* specific reasons. Do you REALLY have a business need for pagination, searchability on ANY attribute of a domain- | |
* object, etc? Your APPLICATION and UI specify these needs but your business rules probably do not. | |
* | |
* Maybe I'm crazy. | |
*/ | |
class Person /* Note: We assume Name is the identifier for Person. It is unique. Just like mom says I am. */ | |
{ | |
private $name = null; | |
private $contactInformation = null; | |
public function __construct(Name $name, ContactInformation $contactInfo) | |
{ | |
$this->name = $name; | |
$this->contactInformation = $contactInfo; | |
} | |
} | |
class PersonRepository /* Assume concrete implementation w/persistence store attached to it (duh). */ | |
{ | |
public function personWithName(Name $name) | |
{ | |
// @todo Search for a person and return the hydrated aggregate. | |
// In the real-world this would probably be personWithId($id) or findById($id) (not expressive; total crap!). | |
} | |
public function store(Person $person) | |
{ | |
// @todo Add to unit of work. Remember, transactions happen in application layer (Application Services, Controller, etc.) | |
} | |
} | |
/* Value Objects */ | |
class Name | |
{ | |
// @todo Implement | |
} | |
class ContactInformation | |
{ | |
public function __construct(EmailAddress $email, PhoneNumber $phone) | |
{ | |
// @todo Implement | |
} | |
} | |
class EmailAddress | |
{ | |
// @todo Implement | |
} | |
class PhoneNumber | |
{ | |
// @todo Implement | |
} | |
} | |
namespace CQRSSample\Application; | |
use Doctrine\DBAL\Connection; | |
{ | |
class PersonSearchApplicationService | |
{ | |
private $connection = null; | |
public function __construct(Connection $connection) | |
{ | |
$this->connection = $connection; | |
} | |
public function allPeopleWithNameStartingWith($namePart, PagingOptions $paginationOptions) | |
{ | |
// @todo Implement. We use Connection here to work with lower-level SQL...or whatever persistence store. | |
// We return a paginated list. An alternative would be to return a lazy-loaded collection that we can | |
// pass to some pagination service or framework (e.g. Zend Paginator/Doctrine Paginator, etc.). | |
// Note that you can: | |
// 1) Return the aggregates used from the repository (meh) or | |
// 2) Return a new read-model (booya!). This is a better option because now we remove any weird eager/lazy fetching | |
// rules, AND we can be very specific about what data to return, AND it's a read-only model, so you don't have to | |
// do any DTO transformations in your controller. Also makes for searializing objects for storage or transfer | |
// much nicer (also PHPers, stop adding toArray() on your aggregates, it's not appropriate.). | |
} | |
public function allPeople() | |
{ | |
// @todo Implement. Assuming it returns a lazy-loaded collection of some sort. | |
} | |
} | |
} | |
/** | |
* Okay, that's all. Harass me on Twitter - twitter.com/raykolbe | |
* | |
* I really would like the PHP community to talk more about DDD/CQRS. For those who have not been practicing it, don't | |
* be scared. Hit me up and we can talk (IRC, IRL (beer++), email, carrier pigeon (not Pidgin)). | |
* | |
* Oh ya, check out http://cqrs.files.wordpress.com/2010/11/cqrs_documents.pdf for more CQRS stuff. Also the Googler (obv.) | |
*/ | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment