Skip to content

Commit 5ec9b3a

Browse files
committed
Merge remote-tracking branch 'atlas/master' into indexing
2 parents d20a6b4 + 69fba02 commit 5ec9b3a

23 files changed

Lines changed: 632 additions & 521 deletions

appendix_csvs.asciidoc

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
== Swapping Out the Infrastructure: pass:[<span class="keep-together">Do Everything with CSVs</span>]
44

55
This appendix is intended as a little illustration of the benefits of the
6-
Repository, Unit of Work, and Service Layer patterns. It's intended to
6+
Repository, Unit of Work, and Service Layer patterns.((("CSVs, doing everyting with", id="ix_CSV"))) It's intended to
77
follow from <<chapter_06_uow>>.
88

99
Just as we finish building out our Flask API and getting it ready for release,
@@ -178,7 +178,7 @@ with CSVs underlying them instead of a database. And as you'll see, it really is
178178
=== Implementing a Repository and Unit of Work for CSVs
179179

180180

181-
Here's what a CSV-based repository could look like. It abstracts away all the
181+
Here's what a CSV-based repository could look like.((("repositories", "CSV-based repository"))) It abstracts away all the
182182
logic for reading CSVs from disk, including the fact that it has to read _two
183183
different CSVs_, one for batches and one for allocations, and it just gives us
184184
the familiar `.list()` API, which gives us the illusion of an in-memory
@@ -235,7 +235,7 @@ class CsvRepository(repository.AbstractRepository):
235235
// TODO (hynek) re self._load(): DUDE! no i/o in init!
236236

237237

238-
And here's what a UoW for CSVs would look like:
238+
And here's((("Unit of Work pattern", "UoW for CSVs"))) what a UoW for CSVs would look like:
239239

240240

241241

@@ -289,7 +289,7 @@ def main(folder):
289289
====
290290

291291

292-
Ta-da! _Now are y'all impressed or what_?
292+
Ta-da! _Now are y'all impressed or what_?((("CSVs, doing everyting with", startref="ix_CSV")))
293293

294294
Much love,
295295

appendix_django.asciidoc

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
== Repository and Unit of Work pass:[<span class="keep-together">Patterns with Django</span>]
44

55
Suppose you wanted to use Django instead of SQLAlchemy and Flask. How
6-
might things look?
6+
might things look?((("Django", id="ix_Django")))
77

8-
The first thing is to choose where to install it. We put it in a separate
8+
The first thing is to choose where to install it.((("Django", "installing"))) We put it in a separate
99
package next to our main allocation code:
1010

1111

@@ -64,7 +64,7 @@ git checkout appendix_django
6464

6565
We used a plug in called
6666
https://github.com/pytest-dev/pytest-django[`pytest-django`] to help with test
67-
database management.
67+
database management.((("Repository pattern", "with Django", id="ix_RepoDjango")))((("Django", "Repository pattern with", id="ix_DjangoRepo")))
6868

6969
Rewriting the first repository test was a minimal change, just rewriting
7070
some raw SQL with a call to the Django ORM/QuerySet language:
@@ -160,7 +160,7 @@ help minimize boilerplate for this sort of thing.]
160160

161161
==== Custom Methods on Django ORM Classes to Translate to/from Our Domain Model
162162

163-
Those custom methods look something like this:
163+
Those custom methods ((("object-relational mappers (ORMs)", "Django, custom methods to translate to/from domain model")))((("domain model", "Django custom ORM methods for conversion")))look something like this:
164164

165165
[[django_models]]
166166
.Django ORM with custom methods for domain model conversion (src/djangoproject/alloc/models.py)
@@ -220,14 +220,14 @@ class OrderLine(models.Model):
220220

221221

222222
NOTE: As in <<chapter_02_repository>>, we use dependency inversion.
223-
The ORM (Django) depends on the model, and not the other way around.
223+
The ORM (Django) depends on the model, and not the other way around.((("Repository pattern", "with Django", startref="ix_RepoDjango")))((("Django", "Repository pattern with", startref="ix_DjangoRepo")))
224224

225225

226226

227227
=== Unit of Work Pattern with Django
228228

229229

230-
The tests don't change too much:
230+
The tests((("Unit of Work pattern", "with Django", id="ix_UoWDjango")))((("Django", "Unit of Work pattern with", id="ix_DjangoUoW"))) don't change too much:
231231

232232
[[test_uow_django]]
233233
.Adapted UoW tests (tests/integration/test_uow.py)
@@ -318,13 +318,13 @@ class DjangoUnitOfWork(AbstractUnitOfWork):
318318
instrumenting the domain model instances themselves, the
319319
`commit()` command needs to explicitly go through all the
320320
objects that have been touched by every repository and manually
321-
update them back to the ORM.
321+
update them back to the ORM.((("Unit of Work pattern", "with Django", startref="ix_UoWDjango")))((("Django", "Unit of Work pattern with", startref="ix_DjangoUoW")))
322322

323323

324324

325325
=== API: Django Views Are Adapters
326326

327-
The Django _views.py_ file ends up being almost identical to the
327+
The Django _views.py_ file ends ((("views", "Django views as adapters")))((("adapters", "Django views")))((("Django", "views are adapters")))((("APIs", "Django views as adapters")))up being almost identical to the
328328
old _flask_app.py_, because our architecture means it's a very
329329
thin wrapper around our service layer (which didn't change at all, by the way):
330330

@@ -370,7 +370,7 @@ def allocate(request):
370370
=== Why Was This All So Hard?
371371

372372
OK, it works, but it does feel like more effort than Flask/SQLAlchemy. Why is
373-
that?
373+
that?((("Django", "using, difficulty of")))
374374

375375
The main reason at a low level is because Django's ORM doesn't work in the same
376376
way. We don't have an equivalent of the SQLAlchemy classical mapper, so our
@@ -397,7 +397,7 @@ around the workflow of state changes. The Django admin bypasses all of that.
397397
=== What to Do If You Already Have Django
398398

399399
So what should you do if you want to apply some of the patterns in this book
400-
to a Django app? We'd say the following:
400+
to a Django app?((("Django", "applying patterns to Django app"))) We'd say the following:
401401

402402
* The Repository and Unit of Work patterns are going to be quite a lot of work. The
403403
main thing they will buy you in the short term is faster unit tests, so
@@ -430,7 +430,7 @@ your _models.py_, which you can then keep as minimal as possible.
430430
Suppose you're working on a Django project that you're not sure is going
431431
to get complex enough to warrant the patterns we recommend, but you still
432432
want to put a few steps in place to make your life easier, both in the medium
433-
term, and if you want to migrate to some of our patterns later. Consider the following:
433+
term, and if you want to migrate to some of our patterns later.((("Django", "applying patterns to Django app", "steps along the way"))) Consider the following:
434434

435435
* One piece of advice we've heard is to put a __logic.py__ into every Django app,
436436
from day one. This gives you a place to put business logic, and to keep your
@@ -454,5 +454,5 @@ NOTE: We'd like to give a shout out to David Seddon and Ashia Zawaduk for
454454
stop us from saying anything really stupid about a topic we don't really
455455
have enough personal experience of, but they may have failed.
456456

457-
For more thoughts and actual lived experience dealing with existing
457+
For more ((("Django", startref="ix_Django")))thoughts and actual lived experience dealing with existing
458458
applications, refer to the <<epilogue_1_how_to_get_there_from_here>>.

appendix_ds1_table.asciidoc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
[appendix]
33
== Summary Diagram and Table
44

5-
Here's what our architecture looks like by the end of the book:
5+
Here's what our architecture looks((("architecture, summary diagram and table", id="ix_archsumm"))) like by the end of the book:
66

77
[[recap_diagram]]
88
image::images/apwp_aa01.png["diagram showing all components: flask+eventconsumer, service layer, adapters, domain etc"]
@@ -53,6 +53,6 @@ __Translate external inputs into calls into the service layer.__
5353
| Web | Receives web requests and translates them into Commands, passing them to the Internal Message Bus.
5454
| Event consumer | Reads events from the external message bus and translates them into commands, passing them to the internal message bus.
5555

56-
| N/A | External message bus (message broker) | A piece of infrastructure that different services use to intercommunicate, via events.
56+
| N/A | External message bus (message broker) | A piece of infrastructure that different services use to intercommunicate, via events.((("architecture, summary diagram and table", startref="ix_archsumm")))
5757
|===
5858

appendix_project_structure.asciidoc

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
Around <<chapter_04_service_layer>>, we moved from just having
66
everything in one folder to a more structured tree, and we thought it might
7-
be of interest to outline the moving parts.
7+
be of interest to outline the moving parts.((("projects", "template project structure", id="ix_prjstrct")))
88

99
[TIP]
1010
====
@@ -354,7 +354,7 @@ TIP: One thing to note is that we install things in the order of how frequently
354354

355355
=== Tests
356356

357-
Our tests are kept alongside everything else, as shown here:
357+
Our tests ((("testing", "tests folder tree")))are kept alongside everything else, as shown here:
358358

359359
[[tests_folder]]
360360
.Tests folder tree
@@ -396,4 +396,4 @@ These are our basic building blocks:
396396
* A Makefile for useful command-line, um, commands
397397

398398
We doubt that anyone will end up with _exactly_ the same solutions we did, but we hope you
399-
find some inspiration here.
399+
find some inspiration here.((("projects", "template project structure", startref="ix_prjstrct")))

appendix_validation.asciidoc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
[appendix]
33
== Validation
44

5-
Whenever we're teaching and talking about these techniques, one question that
5+
Whenever we're ((("validation", id="ix_valid")))teaching and talking about these techniques, one question that
66
comes up over and over is "Where should I do validation? Does that belong with
77
my business logic, in the domain model, or is that an infrastructural concern?"
88

@@ -514,5 +514,5 @@ Locate each of the three types of validation in the right place::
514514
TIP: Once you've validated the syntax and semantics of your commands
515515
at the edges of your system, the domain is the place for the rest
516516
of your validation. Validation of pragmatics is often a core part
517-
of your business rules.
517+
of your business rules.((("validation", startref="ix_valid")))
518518

0 commit comments

Comments
 (0)