Domain-Driven Design in PHP
eBook - ePub

Domain-Driven Design in PHP

Carlos Buenosvinos, Christian Soronellas, Keyvan Akbary

Share book
  1. 394 pages
  2. English
  3. ePUB (mobile friendly)
  4. Available on iOS & Android
eBook - ePub

Domain-Driven Design in PHP

Carlos Buenosvinos, Christian Soronellas, Keyvan Akbary

Book details
Book preview
Table of contents
Citations

About This Book

Real examples written in PHP showcasing DDD Architectural Styles, Tactical Design, and Bounded Context IntegrationAbout This Book• Focuses on practical code rather than theory• Full of real-world examples that you can apply to your own projects• Shows how to build PHP apps using DDD principlesWho This Book Is ForThis book is for PHP developers who want to apply a DDD mindset to their code. You should have a good understanding of PHP and some knowledge of DDD. This book doesn't dwell on the theory, but instead gives you the code that you need.What You Will Learn• Correctly design all design elements of Domain-Driven Design with PHP• Learn all tactical patterns to achieve a fully worked-out Domain-Driven Design• Apply hexagonal architecture within your application• Integrate bounded contexts in your applications• Use REST and Messaging approachesIn DetailDomain-Driven Design (DDD) has arrived in the PHP community, but for all the talk, there is very little real code. Without being in a training session and with no PHP real examples, learning DDD can be challenging. This book changes all that. It details how to implement tactical DDD patterns and gives full examples of topics such as integrating Bounded Contexts with REST, and DDD messaging strategies. In this book, the authors show you, with tons of details and examples, how to properly design Entities, Value Objects, Services, Domain Events, Aggregates, Factories, Repositories, Services, and Application Services with PHP. They show how to apply Hexagonal Architecture within your application whether you use an open source framework or your own.Style and approachThis highly practical book shows developers how to apply domain-driven design principles to PHP. It is full of solid code examples to work through.

Frequently asked questions

How do I cancel my subscription?
Simply head over to the account section in settings and click on “Cancel Subscription” - it’s as simple as that. After you cancel, your membership will stay active for the remainder of the time you’ve paid for. Learn more here.
Can/how do I download books?
At the moment all of our mobile-responsive ePub books are available to download via the app. Most of our PDFs are also available to download and we're working on making the final remaining ones downloadable now. Learn more here.
What is the difference between the pricing plans?
Both plans give you full access to the library and all of Perlego’s features. The only differences are the price and subscription period: With the annual plan you’ll save around 30% compared to 12 months on the monthly plan.
What is Perlego?
We are an online textbook subscription service, where you can get access to an entire online library for less than the price of a single book per month. With over 1 million books across 1000+ topics, we’ve got you covered! Learn more here.
Do you support text-to-speech?
Look out for the read-aloud symbol on your next book to see if you can listen to it. The read-aloud tool reads text aloud for you, highlighting the text as it is being read. You can pause it, speed it up and slow it down. Learn more here.
Is Domain-Driven Design in PHP an online PDF/ePUB?
Yes, you can access Domain-Driven Design in PHP by Carlos Buenosvinos, Christian Soronellas, Keyvan Akbary in PDF and/or ePUB format, as well as other popular books in Computer Science & Programming in PHP. We have over one million books available in our catalogue for you to explore.

Information

Year
2017
ISBN
9781787288461
Edition
1

Aggregates

Aggregates are probably the most difficult building blocks of Domain-Driven Design. They're hard to understand, and they're even harder to properly design. But don't worry; we're here to help you. However, before jumping into Aggregates, there are some key concepts we need to go through first: transactions and concurrency strategies.

Introduction

If you've worked with e-commerce applications, it's likely you've faced bugs related to data inconsistencies in your database. For example, consider a shopping order with a total amount of $99.99, which doesn't match with the sum of the amounts of each line in the order, $89.99. Where did that extra $10 come from?
Or, consider a website that sells tickets for the cinema. There's a movie theater with 100 available seats, and after a successful movie promotion, everyone is on the website waiting for the tickets to become available for purchase. Once you open the sales, everything happens fast and you somehow end up selling 102 tickets. You may have specified that there are only 100 seats, but for some reason you exceeded that threshold.
You might even have experience with tracking systems such as JIRA or Redmine. Think about a team of Developers, QAs, and a Product Owner. What could happen if everyone sorts and moves around user stories during a planning meeting and then saves? The final backlog or sprint prioritization would be the one from the team member who saved last.
In general, data inconsistencies occur when we deal with our persistence mechanism in a non-atomic way. An example of this is when you send three queries to a database and some of them work and some don't. The final state of the database is inconsistent. Sometimes, you want these three queries to succeed or fail all together, and that can be fixed with transactions. However, be careful, because as you will see in this chapter, not all inconsistencies are fixed with transactions. In fact, sometimes other data inconsistencies need locking or concurrency strategies. These kinds of tools might come up against your application performance, so be aware that there's a tradeoff involved.
You may think that these kinds of data inconsistencies only occur in databases, but that's not true. For example, if we use a document-oriented database such as Elasticsearch, we can have data inconsistency between two documents. Furthermore, most of the NoSQL persistence storage systems don't support ACID transactions. This means you can't persist or update more than one document in a single operation. So, if we make different requests to Elasticsearch, one may fail, leaving the data persisted in Elasticsearch inconsistent.
Keeping data consistent is a challenge. Not leaking infrastructure issues into the Domain is a bigger challenge. Aggregates aim to help you with both of these things.

Key Concepts

Persistence engines — and databases in particular — have some features for fighting data inconsistencies: ACID, constraints, referential integrity, locking, concurrency controls, and transactions. Let's review these concepts before working with Aggregates.
Most of these concepts are on the Internet and available to the public. We want to thank the people at Oracle, PostgreSQL, and Doctrine for doing amazing work with their documentation. They have carefully defined and explained these important terms, and rather than reinvent the wheel, we've compiled some of these official explanations to share with you.

ACID

As discussed in a previous section, ACID stands for atomicity, consistency, isolation, and durability. According to the MySQL Glossary:
These properties are all desirable in a database system, and are all closely tied to the notion of a transaction. For example, the transactional features of MySQL InnoDB engine adhere to the ACID principles.
Transactions are atomic units of work that can be committed or rolled back. When a transaction makes multiple changes to the database, either all the changes succeed when the transaction is committed, or all the changes are undone when the transaction is rolled back.
The database remains in a consistent state at all times, after each commit or rollback, and while transactions are in progress. If related data is being updated across multiple tables, queries see either all old values or all new values, not a mix of old and new values.
Transactions are protected isolated from each other while they are in progress. They cannot interfere with each other or see each other's uncommitted data. This isolation is achieved through the locking mechanism. Experienced users can adjust the isolation level, trading off less protection in favor of increased performance and concurrency, when they can be sure that the transactions really do not interfere with each other.
The results of transactions are durable: once a commit operation succeeds, the changes made by that transaction are safe from power failures, system crashes, race conditions, or other potential dangers that many non-database applications are vulnerable to. Durability typically involves writing to disk storage, with a certain amount of redundancy to protect against power failures or software crashes during write operations.

Transactions

According to the PostgreSQL 8.2.23 Documentation:
Transactions are a fundamental concept of all database systems. The essential point of a transaction is that it bundles multiple steps into a single, all-or-nothing operation. The intermediate states between the steps are not visible to other concurrent transactions, and if some failure occurs that prevents the transaction from completing, then none of the steps affect the database at all.
For example, consider a bank database that contains balances for various customer accounts, as well as total deposit balances for branches. Suppose that we want to record a payment of $100.00 from Alice's account to Bob's account. Simplifying outrageously, the SQL commands for this might look like:
 UPDATE accounts
SET balance = balance - 100.00
WHERE name = 'Alice';

UPDATE branches
SET balance = balance - 100.00
WHERE name = (SELECT branch_name FROM accounts WHERE name ='Alice');

UPDATE accounts
SET balance = balance + 100.00
WHERE name = 'Bob';

UPDATE branches
SET balance = balance + 100.00
WHERE name = (SELECT branch_name FROM accounts WHERE name ='Bob');
The details of these commands are not important here. The important point is that there are several separate updates involved to accomplish this rather simple operation. Our bank's officers will want to be assured that either all these updates happen, or none of them happen. It would certainly not do for a system failure to result in Bob receiving $100.00 that was not debited from Alice. Nor would Alice long remain a happy customer if she was debited without Bob being credited. We need a guarantee that if something goes wrong partway through the operation, none of the steps executed so far will take effect. Grouping the updates into a transaction gives us this guarantee. A transaction is said to be atomic: from the point of view of other transactions, it either happens completely or not at all.
We also want a guarantee that once a transaction is completed and acknowledged by the database system, it has indeed been permanently recorded and won't be lost even if a crash ensues shortly thereafter. For example, if we are recording a cash withdrawal by Bob, we do not want any chance that the debit to his account will disappear in a crash just after he walks out the bank door. A transactional database guarantees that all the updates made by a transaction are logged in permanent storage (That is: on disk) before the transaction is reported complete.
Another important property of transactional databases is closely related to the notion of atomic updates: when multiple transactions are running concurrently, each one should not be able to see the incomplete changes made by others. For example, if one transaction is busy totalling all the branch balances, it would not do for it to include the debit from Alice's branch but not the credit to Bob's branch, nor vice versa. So transactions must be all-or-nothing not only in terms of their permanent effect on the database, but also in terms of their visibility as they happen. The updates made so far by an open transaction are invisible to other transactions until the transaction completes, whereupon all the updates become visible simultaneously.
In PostgreSQL, for example, a transaction is set up by surrounding the SQL commands of the transaction with BEGIN and COMMIT commands. So our banking transaction would actually look like:
 BEGIN;
UPDATE accou...

Table of contents