"The Ubiquitous Language is a shared language developed by the team—a team comprised of both domain experts and software developers."
interface User
{
public function changePersonalName(string firstName, string lastName);
public function relocateTo(PostalAddress changedPostalAddress);
public function changeHomeTelephone(Telephone telephone);
public function changeMobileTelephone(Telephone telephone);
}
Product
Customer
Address
Shop
Inventory
Image
PhoneNumber
Cart
Order
Article
Order
Shipping
BankAccount
class User
{
/** @var Uuid */
private $id;
/** @var string */
private $name;
// ...
}
class EmailAddress
{
/** @var string */
private $email;
// ...
}
class User
{
public function changeName(NameChange $nameChange)
{
$this->name = $nameChange->getName();
}
}
class EmailAddress
{
public function withEmail(string $email): EmailAddress
{
$self = clone $self;
$self->email = $email;
return $self;
}
}
class ProductController
{
public function redirectToNewUrl(ServerRequestInterface $request, ResponseInterface $response)
{
$response = $response->withStatus(301);
$response = $response->withHeader("Location", "https://example.com/products/123");
return $response;
}
}
https://github.com/moneyphp/money
$jim_price = $hannah_price = Money::EUR(2500);
$coupon = Money::EUR(500);
$jim_price = $jim_price->subtract($coupon);
// $jim_price->subtract($coupon);
$jim_price->lessThan($hannah_price); // true
$jim_price->equals(Money::EUR(2000)); // true
class User
{
/** @var EmailAddress[] */
private $emails = [];
public function addEmailAddress(NewEmailAddress $newEmail): void
{
$email = $newEmail->getEmailAddress();
if (isset($this->emails[$email->__toString()])) {
throw new EmailAddressAlreadyExists();
}
if (count($this->emails) >= 15) {
throw new TooManyEmailAddresses();
}
$this->emails[$email->__toString()] = $email;
}
public function removeEmailAddress(EmailAddress $email): void
{
if (isset($this->emails[$email->__toString()]) === false) {
throw new EmailAddressNotFound();
}
if (count($this->emails) <= 1) {
throw new TooFewEmailAddresses();
}
if ($email->isPrimary()) {
throw new EmailAddressCantBeRemoved();
}
unset($this->emails[$email->__toString()]);
}
}
interface ProductRepositoryInterface
{
public function getProductBySku(string $sku): Product;
public function getProductList(ProductListing $productListing): ProductList;
public function saveProduct(Product $product); //public function addProduct(Product $product);
public function deleteProduct(Product $product); //public function removeProduct(Product $product);
}
class EloquentProductRepository implements ProductRepositoryInterface
{
// ...
}
class FakeProductRepository implements ProductRepositoryInterface
{
// ...
}
interface ProductRepositoryInterface
{
public function getProductBySku(string $sku): Product;
// ...
}
interface RepositoryInterface
{
public function getModelById($id): AbstractModel;
// ...
}
Windows, Virtualbox, Docker
PHP 7 + Opcache
~200 KB of JSON response
50 main entity
4 relationships by entity
Without Identity Map:
With Identity Map:
class AddEmailAddress extends AbstractService
{
/** @var MeRepositoryInterface */
protected $meRepository;
/** @var EmailAddressVerificationRepositoryInterface */
protected $verificationRepository;
/** @var EmailServiceInterface */
protected $emailService;
public function execute(JsonApi $jsonApi): ResponseInterface
{
$userId = $this->config->getCurrentUser()->getId();
$newEmailAddress = new NewEmailAddress($jsonApi->request->getResourceAttribute("email_address", ""));
// Add email address
$me = $this->meRepository->getMeById($userId);
$me->addEmailAddress($newEmailAddress);
$this->meRepository->saveMe($me);
// Create email verification token
$verification = EmailAddressVerification::generate($me, $newEmailAddress->getEmailAddress());
$this->verificationRepository->createVerification($verification);
// Send email verification email
$this->emailService->send(new EmailAddressVerificationEmail($verification));
// Respond with 204 No Content
return $jsonApi->respond()->noContent();
}
}