Architecture Patterns with Python 1st Edition Harry Percival pdf download
Architecture Patterns with Python 1st Edition Harry Percival pdf download
https://ebookmeta.com/product/architecture-patterns-with-
python-1st-edition-harry-percival/
https://ebookmeta.com/product/test-driven-development-with-
python-2nd-edition-harry-j-w-percival/
https://ebookmeta.com/product/python-programming-with-design-
patterns-1st-edition-james-cooper/
https://ebookmeta.com/product/software-architecture-patterns-
understanding-common-architecture-patterns-and-when-to-use-
them-3rd-edition-mark-richards/
https://ebookmeta.com/product/desire-1st-edition-misty-vixen/
Reflections on Slope Stability Engineering 1st Edition
Edward N. Bromhead
https://ebookmeta.com/product/reflections-on-slope-stability-
engineering-1st-edition-edward-n-bromhead/
https://ebookmeta.com/product/the-things-they-carried-tim-o-
brien/
https://ebookmeta.com/product/the-age-of-migration-international-
population-movements-in-the-modern-world-6th-edition-hein-de-
haas/
https://ebookmeta.com/product/handbook-of-personality-theory-and-
research-4th-edition-oliver-p-john/
https://ebookmeta.com/product/the-insiders-guide-to-legal-
skills-2nd-edition-emily-allbon/
The Neglected Dimension of Global Security A Framework
to Counter Infectious Disease Crises 1st Edition
Secretariat National Academy Of Medicine
https://ebookmeta.com/product/the-neglected-dimension-of-global-
security-a-framework-to-counter-infectious-disease-crises-1st-
edition-secretariat-national-academy-of-medicine/
Architecture
Patterns
with Python
Enabling Test-Driven Development,
Domain-Driven Design, and Event-Driven
Microservices
The O’Reilly logo is a registered trademark of O’Reilly Media, Inc. Architecture Patterns with Python, the
cover image, and related trade dress are trademarks of O’Reilly Media, Inc.
The views expressed in this work are those of the authors and do not represent the publisher’s views.
While the publisher and the authors have used good faith efforts to ensure that the information and
instructions contained in this work are accurate, the publisher and the authors disclaim all responsibility
for errors or omissions, including without limitation responsibility for damages resulting from the use of
or reliance on this work. Use of the information and instructions contained in this work is at your own
risk. If any code samples or other technology this work contains or describes is subject to open source
licenses or the intellectual property rights of others, it is your responsibility to ensure that your use
thereof complies with such licenses and/or rights.
978-1-492-05220-3
[LSI]
Table of Contents
Preface. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ix
Introduction. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xvii
2. Repository Pattern. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
Persisting Our Domain Model 24
Some Pseudocode: What Are We Going to Need? 24
Applying the DIP to Data Access 25
Reminder: Our Model 26
The “Normal” ORM Way: Model Depends on ORM 27
Inverting the Dependency: ORM Depends on Model 28
Introducing the Repository Pattern 31
The Repository in the Abstract 32
What Is the Trade-Off? 33
Building a Fake Repository for Tests Is Now Trivial! 37
iii
What Is a Port and What Is an Adapter, in Python? 37
Wrap-Up 38
iv | Table of Contents
Explicit Versus Implicit Commits 90
Examples: Using UoW to Group Multiple Operations into an Atomic Unit 91
Example 1: Reallocate 91
Example 2: Change Batch Quantity 91
Tidying Up the Integration Tests 92
Wrap-Up 93
Table of Contents | v
Wrap-Up 130
vi | Table of Contents
Post/Redirect/Get and CQS 179
Hold On to Your Lunch, Folks 181
Testing CQRS Views 182
“Obvious” Alternative 1: Using the Existing Repository 182
Your Domain Model Is Not Optimized for Read Operations 183
“Obvious” Alternative 2: Using the ORM 184
SELECT N+1 and Other Performance Considerations 184
Time to Completely Jump the Shark 185
Updating a Read Model Table Using an Event Handler 186
Changing Our Read Model Implementation Is Easy 188
Wrap-Up 189
Epilogue. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 211
E. Validation. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 255
Index. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 265
You may be wondering who we are and why we wrote this book.
At the end of Harry’s last book, Test-Driven Development with Python (O’Reilly), he
found himself asking a bunch of questions about architecture, such as, What’s the
best way of structuring your application so that it’s easy to test? More specifically, so
that your core business logic is covered by unit tests, and so that you minimize the
number of integration and end-to-end tests you need? He made vague references to
“Hexagonal Architecture” and “Ports and Adapters” and “Functional Core, Impera‐
tive Shell,” but if he was honest, he’d have to admit that these weren’t things he really
understood or had done in practice.
And then he was lucky enough to run into Bob, who has the answers to all these
questions.
Bob ended up a software architect because nobody else on his team was doing it. He
turned out to be pretty bad at it, but he was lucky enough to run into Ian Cooper, who
taught him new ways of writing and thinking about code.
ix
Getting the timing right is a tricky balancing act when goods take three months to
arrive by container ship. Along the way, things get broken or water damaged, storms
cause unexpected delays, logistics partners mishandle goods, paperwork goes miss‐
ing, customers change their minds and amend their orders, and so on.
We solve those problems by building intelligent software representing the kinds of
operations taking place in the real world so that we can automate as much of the busi‐
ness as possible.
Why Python?
If you’re reading this book, we probably don’t need to convince you that Python is
great, so the real question is “Why does the Python community need a book like
this?” The answer is about Python’s popularity and maturity: although Python is
probably the world’s fastest-growing programming language and is nearing the top of
the absolute popularity tables, it’s only just starting to take on the kinds of problems
that the C# and Java world has been working on for years. Startups become real busi‐
nesses; web apps and scripted automations are becoming (whisper it) enterprise
software.
In the Python world, we often quote the Zen of Python: “There should be one—and
preferably only one—obvious way to do it.”1 Unfortunately, as project size grows, the
most obvious way of doing things isn’t always the way that helps you manage com‐
plexity and evolving requirements.
None of the techniques and patterns we discuss in this book are new, but they are
mostly new to the Python world. And this book isn’t a replacement for the classics in
the field such as Eric Evans’s Domain-Driven Design or Martin Fowler’s Patterns of
Enterprise Application Architecture (both published by Addison-Wesley Professional)
—which we often refer to and encourage you to go and read.
But all the classic code examples in the literature do tend to be written in Java or
C++/#, and if you’re a Python person and haven’t used either of those languages in a
long time (or indeed ever), those code listings can be quite…trying. There’s a reason
the latest edition of that other classic text, Fowler’s Refactoring (Addison-Wesley Pro‐
fessional), is in JavaScript.
x | Preface
TDD, DDD, and Event-Driven Architecture
In order of notoriety, we know of three tools for managing complexity:
1. Test-driven development (TDD) helps us to build code that is correct and enables
us to refactor or add new features, without fear of regression. But it can be hard
to get the best out of our tests: How do we make sure that they run as fast as pos‐
sible? That we get as much coverage and feedback from fast, dependency-free
unit tests and have the minimum number of slower, flaky end-to-end tests?
2. Domain-driven design (DDD) asks us to focus our efforts on building a good
model of the business domain, but how do we make sure that our models aren’t
encumbered with infrastructure concerns and don’t become hard to change?
3. Loosely coupled (micro)services integrated via messages (sometimes called reac‐
tive microservices) are a well-established answer to managing complexity across
multiple applications or business domains. But it’s not always obvious how to
make them fit with the established tools of the Python world—Flask, Django,
Celery, and so on.
Don’t be put off if you’re not working with (or interested in) micro‐
services. The vast majority of the patterns we discuss, including
much of the event-driven architecture material, is absolutely appli‐
cable in a monolithic architecture.
Our aim with this book is to introduce several classic architectural patterns and show
how they support TDD, DDD, and event-driven services. We hope it will serve as a
reference for implementing them in a Pythonic way, and that people can use it as a
first step toward further research in this field.
Preface | xi
feel a little strange at the beginning, but we hope you’ll soon get used to seeing code
“being used” (i.e., from the outside) before you see how it’s built on the inside.
We use some specific Python frameworks and technologies, including Flask, SQL‐
Alchemy, and pytest, as well as Docker and Redis. If you’re already familiar with
them, that won’t hurt, but we don’t think it’s required. One of our main aims with this
book is to build an architecture for which specific technology choices become minor
implementation details.
xii | Preface
Part II, Event-Driven Architecture
Event-driven architecture (Chapters 8–11)
We introduce three more mutually reinforcing patterns: the Domain Events,
Message Bus, and Handler patterns. Domain events are a vehicle for capturing the
idea that some interactions with a system are triggers for others. We use a mes‐
sage bus to allow actions to trigger events and call appropriate handlers. We move
on to discuss how events can be used as a pattern for integration between services
in a microservices architecture. Finally, we distinguish between commands and
events. Our application is now fundamentally a message-processing system.
Command-query responsibility segregation (Chapter 12)
We present an example of command-query responsibility segregation, with and
without events.
Dependency injection (Chapter 13)
We tidy up our explicit and implicit dependencies and implement a simple
dependency injection framework.
Addtional Content
How do I get there from here? (Epilogue)
Implementing architectural patterns always looks easy when you show a simple
example, starting from scratch, but many of you will probably be wondering how
to apply these principles to existing software. We’ll provide a few pointers in the
epilogue and some links to further reading.
Preface | xiii
Exploring the Variety of Random
Documents with Different Content
CHAPTER XIX
Waterloo
(1815)
T
he British General had already sent word to Blücher that he
was prepared to fight Napoleon if the Prussian Commander
could see his way to send him one army-corps, the
assistance of which he deemed imperative. He did not receive a
reply until the early hours of the 18th, and it was in the affirmative.
He promised Bülow’s corps, which would march at daybreak against
Napoleon’s right, followed by that of Pirch. Those of Thielmann and
Ziethen would also be sent provided the presence of Grouchy did not
prevent. As events turned out, Thielmann’s corps was sufficient for
this purpose of defending the Dyle against the French Marshal. The
first report from Grouchy received by Napoleon on the 18th was sent
from Gembloux, and contained news up to 10 o’clock on the
previous night, namely, that part of the Prussians had retired
towards Wavre, that Blücher with their centre had fallen back on
Perwez, and a column with artillery had moved in the direction of
92
Namur.
From another source Napoleon gathered that three bodies of the
Prussians were concentrating at Wavre, vital information which, for
some inexplicable reason, he did not dispatch to Grouchy until 10
a.m. We have it on the authority of Foy, who had fought in Spain,
that at daybreak Napoleon was told that the junction of Wellington
and Blücher was possible. This he refused to believe, stating that
such an event could not take place before the 20th. Grouchy was
ordered to keep up his communications with Napoleon, pushing
before him “those bodies of Prussians which have taken this
direction and which may have stopped at Wavre.” In addition, he
was to “follow those columns which have gone to your right.” Dr
Holland Rose pronounces these instructions as far from clear:
“Grouchy was not bidden to throw all his efforts on the side of
Wavre; and he was not told whether he must attack the enemy at
that town, or interpose a wedge between them and Wellington, or
support Napoleon’s right. Now Napoleon would certainly have
prescribed an immediate concentration of Grouchy’s force towards
the north-west for one of the last two objects, had he believed
Blücher about to attempt a flank march against the chief French
army. Obviously it had not yet entered his thoughts that so daring a
step would be taken by a foe whom he pictured as scattered and
93
demoralized by defeat.”
As Houssaye, one of the most painstaking of historians, says, “It
is necessary to walk over the ground, to perceive its constantly
undulating formation, similar to the billows of a swelling sea.” I have
followed his advice for the purposes of the present volume. The
configuration of the land near the ridge, which was at first the right
centre of the Allies, has been altered somewhat by the excavation of
earth for the celebrated but unsightly Lion Mound, otherwise the
field is much the same as it was in 1815. Major Cotton, who fought
at Waterloo, tells us that on the day of the battle there were
“splendid crops of rye, wheat, barley, oats, beans, peas, potatoes,
tares, and clover; some of these were of great height. There were a
few patches of ploughed ground.” Exactly the same is true now. The
soil which covers the mouldering bones of many a hero yields a
mighty harvest. Practically every inch of it is either pasture or under
cultivation.
By far the most interesting point is the château and farm-house
of Hougoumont. The buildings were then over two centuries old, and
were erected with a view to defence, the garden being strongly
walled on the south and east sides. In 1815 it was replete with
orchard, outbuildings, banked-up hedges, and a chapel. Additional
loop-holes were made by Wellington’s orders, a scaffold was erected
so that the troops could discharge their muskets over the wall, and
the flooring over the south gateway hastily taken up “to enable our
men to fire down upon the enemy should they force the gate which
had been blocked up.” This strong strategic position before the right
flank of the allied line was admirably defended by the light
companies of the second battalions of Coldstream and Foot Guards.
The battle began with a protracted but successful attack by
Napoleon’s brother, Jerome, on the Nassauer and Hanoverian troops,
which held the wood in front of the château. Proud of his triumph,
and contrary to the Emperor’s orders, three attempts to assault the
grim building were made and failed. At length Napoleon made up his
mind to bombard Hougoumont, which he did to some effect, the
chapel and barn blazing fiercely, but its brave defenders never
surrendered. Four days after the battle, Major W. E. Frye visited the
spot. “At Hougoumont,” he says, “where there is an orchard, every
tree is pierced with bullets. The barns are all burned down, and in
the courtyard it is said they have been obliged to burn upwards of a
thousand carcases, an awful holocaust to the War-Demon.”
On one of the outside walls of the little chapel, within which
many gallant soldiers breathed their last, is a bronze tablet erected
in 1907, “to the memory of the brave dead by His Britannic Majesty’s
94
Brigade of Guards and by Comte Charles van der Burch.” The
sacred building has been thoroughly repaired, and the interior white-
washed. The latter is to be regretted, but was incumbent owing to
the vandalism of visitors whose one aim in life apparently is to carve
or scrawl their names upon monuments and buildings.
Within easy distance is the farm of La Haye Sainte, still used for
the purpose for which it was originally built. If the thick wall which
abuts the road to the Belgian capital is not so strong as it was—and
there are signs of recent repair—the most cursory examination is
sufficient to prove that it offered a strong resistance. La Haye Sainte
was the key of the allied position. It was Napoleon’s ambition to
secure it, together with the farm of Mont St Jean, so that the
enemy’s communications with Brussels and Blücher might be cut off.
Wellington had unwisely left the defence of La Haye Sainte to a
mere handful of men, 376 in all, of the King’s German Legion. The
buildings were attacked on all sides during the eventful day, and it
was not until 6.30 p.m., or thereabouts, when ammunition was
exhausted, that the place fell. Professor Oman points out that the
Emperor should have sent the Guard “to the front en masse” the
moment that happened. This he did not do, and a golden
opportunity was irretrievably lost.
1. Farm of Mont St. Jean
2. Château of Hougoumont
3. La Belle Alliance Inn
4. Farm of La Haye Sainte
Photographs by C. Hamilton, Hornsey
Six battalions of the Middle Guard and two battalions of the Old
101
Guard were at last sent forward. As they crossed the open ground
between Hougoumont and the high road the artillery played sad
havoc with some of them, but behind the crest of the ridge was
Maitland’s brigade of the Foot Guards, led by Wellington, himself.
“Up, Guards, and make ready!” he shouted, and ere the first column
was upon them the British infantry had dealt a deadly fire into its
ranks which made it pause. The second column was caught in flank
by Adam’s Brigade. Then two brigades of British cavalry charged,
and although the celebrated Imperial Guards endeavoured to hold
their own they were forced back. Blücher, who had arrived at a most
opportune moment, carried the position occupied by the French right
at Papelotte and La Haye with Ziethen’s corps. The whole Allied line
then advanced, the heights were carried, and Napoleon’s last army,
on the victory of which he had staked his all, was scattered. The
battle of Waterloo was won. “My plan,” said the Commander-in-
Chief, “was to keep my ground until the Prussians appeared, and
then to attack the French position; and I executed my plan.”
Throughout the night the Prussians followed up the defeated
legions, which got across the Sambre on the 19th. Some 30,000 of
Napoleon’s men were killed or wounded, and 13,000 of the Allied
army, more than half of whom were British. On the 22nd June 1815,
the fallen Emperor abdicated in favour of his son; on the 7th July the
Allies entered Paris in triumph, and eight days later Napoleon
surrendered to Captain Maitland, of H.M.S. Bellerophon.
“It is the duty of all to look our difficulties in the face and to lay the
ground for getting the better of them.”
Wellington.
W
hile the good folk of London were listening to the guns of
the Tower and of the Park, which told of the Waterloo
victory, and the joyful news was percolating to the
smallest hamlet, Wellington was fighting a battle in which neither
sword nor gun was involved. It was one of diplomacy, and he proved
the conqueror. Blücher, armed with the Declaration of the 13th
March 1815 to the effect that “Napoleon Bonaparte is put beyond
the pale of social and civil relations, and as enemy and disturber of
the repose of the world, he is delivered over to public vengeance,”
was for seizing the fallen Emperor and shooting him as an outlaw at
102
Vincennes, the scene of the Duc d’Enghien tragedy. The
bloodthirsty Prussian asked for Wellington’s views on the matter. He
received them without delay, and expressed in such a way that
Blücher must have felt thoroughly ashamed of himself, if only for a
passing moment. “They had both acted too distinguished a part in
the recent transactions to become executioners,” the Duke wrote.
This single sentence reveals the sterling uprightness of the man and
his hatred of unnecessary bloodshed. Even supposing that he had
received authority for the carrying out of such a measure, it is
extremely doubtful whether Wellington would have concurred in his
colleague’s wish. Blücher sneered—and accepted the decision.
Wellington also found himself in disagreement with the Prussian
view regarding the bridge of Jena at Paris, which commemorated the
crushing Prussian defeat of October 1806. Blücher, with true patriotic
zeal as it seemed to him, was for blowing it to pieces. Wellington
regarded the idea as foolish, and he carried his point. It would have
been a bitter day for the Capital had Blücher been allowed to work
his will. The Prussian Commander insisted on levying a contribution
on the city of Paris of 100,000,000 francs. Wellington upset the
scheme by insisting that the question was one for the Allied
sovereigns to arrange. For the third time vindictive Blücher had to
give in.