Skip to content

Commit d5bf789

Browse files
authored
Spelling, grammar and broken example fixes. (#21)
* Fix incorrect example return type. * Grammar, spelling and example fixes. * Grammar fix. * Fix missing word.
1 parent beaf2a9 commit d5bf789

File tree

7 files changed

+25
-25
lines changed

7 files changed

+25
-25
lines changed

docs/domains.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,21 +15,21 @@ What this styleguide calls a `domain` is roughly an extension of what Django wou
1515

1616
This guide tries to keep the key benefits of Django's `app` pattern - namely Django's [models](https://docs.djangoproject.com/en/2.1/topics/db/models/) to represent tables in a datastore, but with an emphasis on **skinny models**.
1717

18-
This guide also retain Django's ability to *package apps as installable components in other applications*. This allows domains to be easily migrated to different codebases or completely different projects.
18+
This guide also retains Django's ability to *package apps as installable components in other applications*. This allows domains to be easily migrated to different codebases or completely different projects.
1919

2020
## Domain rules
2121

2222
There are two major rules around domains:
2323

2424
1. You **should** split a domain if it becomes too big to work on.
2525

26-
A domain should allow between 4-6 developers (3 pairs) to comfortably work on it. If you find your developers being blocked by each other then it is time to consider splitting the domain or checking the software has not diverged too far from the styleguide.
26+
A domain should allow between 4-6 developers (3 pairs) to comfortably work on it. If you find your developers being blocked by each other then it is time to consider splitting the domain or checking whether the software has not diverged too far from the styleguide.
2727

2828
---
2929

3030
2. You **should** adhere to the styleguide patterns in this document in order to maintain strong bounded contexts between your domains.
3131

32-
This applies even in situations where you extract one domain into two domains to increase velocity, but they still have to maintain a dependency between each other. We have found that if you relax the bounded context between domains, the boundary will erode and you will lose the ability to work on them independent of each other.
32+
This applies even in situations where you extract one domain into two domains to increase velocity, but they still have to maintain a dependency between one another. We have found that if you relax the bounded context between domains, the boundary will erode and you will lose the ability to work on them independent of each other.
3333

3434

3535
---

docs/examples.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
Let's start with a basic example - a project that has two domains. They both expose APIs for a Frontend service, and they also communicate to each other.
44
Communicating to the Frontend service is simple - they have defined a REST API in their API layer and the Frontend calls it.
55

6-
When talking to each other, they both _interface_ (hence the naming choice) with each other through the appropriate layers. Sometimes we call the this "API to interface path".
6+
When talking to each other, they both _interface_ (hence the naming choice) with each other through the appropriate layers. Sometimes we call this the "API to interface path".
77

8-
Let's imagine that the owners of Domain B decide they want to move their software into another web server on the other side of the world. The first thing they might do is make a copy of the software of Domain B. They might spin up that copy in the new world, and slowly port the data over from the old Domain B.
8+
Let's imagine that the owners of Domain B decide they want to move their software into another web server on the other side of the world. The first thing they might do is make a copy of the software of Domain B. They might spin that copy up in the new world, and slowly port the data over from the old Domain B.
99

1010
During this time, Domain A is still talking to the old Domain B. When the new Domain B is ready to go, they inform the team that owns Domain A. The Domain A team will then update their interfaces.py to point to the new Domain B instance. Because they have not leaked Domain B's logic throughout Domain A, the change is isolated to a single file (and hopefully a single git commit).
1111

docs/files.md

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11

22
### Examples on this page
33

4-
In the examples below we imagine a service with two domains - one for books, and one for authors. The abstraction between books and authors is only present to demonstrate the concepts in the styleguide. You could argue that Books and Authors can live in one domain. In our example **we also assume a book can only have one author.** It's a strange world.
4+
In the examples below we imagine a service with two domains - one for books, and one for authors. The abstraction between books and authors is only present to demonstrate the concepts in the styleguide. You could argue that Books and Authors can live in one domain. In our example **we also assume that a book can only have one author.** It's a strange world.
55

66
## Models
77

8-
Models defines how a data model/ database table looks. This is a Django convention that remains mostly unchanged. The key difference here is that you use _skinny models_. No complex functional logic should live here.
8+
_Models_ defines how a data model / database table looks. This is a Django convention that remains mostly unchanged. The key difference here is that you use _skinny models_. No complex functional logic should live here.
99

10-
In the past Django has recommended an [active record](https://docs.djangoproject.com/en/2.1/misc/design-philosophies/#models) style for it's models. In practice, we have found that this encourages developers to make `models.py` bloated and do too much - often binding the presentation and functional logic of a domain too tightly. This makes it very hard to have abstract presentations of the data in a domain. Putting all the logic in one place also makes it difficult to scale the number of developers working in this part of the codebase. See the [_"Which logic lives where?"_](/styleguide/#which-logic-lives-where) section for clarification.
10+
In the past Django has recommended an [active record](https://docs.djangoproject.com/en/2.1/misc/design-philosophies/#models) style for its models. In practice, we have found that this encourages developers to bloat `models.py`, making it do too much and often binding the presentation and functional logic of a domain too tightly. This makes it very hard to have abstract presentations of the data in a domain. Putting all the logic in one place also makes it difficult to scale the number of developers working in this part of the codebase. See the [_"Which logic lives where?"_](/styleguide/#which-logic-lives-where) section for clarification.
1111

1212
A models.py file can look like:
1313

@@ -39,9 +39,9 @@ class Book(models.Model):
3939

4040
## APIs
4141

42-
APIs defines the external API interface for your domain. Anyone using the APIs defined here is called a _consumer_. The API can be either an HTTP API using [GraphQL](https://github.com/graphql-python) or [REST](https://www.django-rest-framework.org/) for consumers over the web, or a software API for internal consumers. APIs is defined in `apis.py` which is agnostic to the implementation you choose, and you can even put more than one API in a domain. For example - you might want to wrap a GraphQL API _and_ a REST API around your domain for different consumers.
42+
_APIs_ defines the external API interface for your domain. Anyone using the APIs defined here is called a _consumer_. The API can be either an HTTP API using [GraphQL](https://github.com/graphql-python) or [REST](https://www.django-rest-framework.org/) for consumers over the web, or a software API for internal consumers. APIs is defined in `apis.py` which is agnostic to the implementation you choose, you can even put more than one API in a domain. For example - you might want to wrap a GraphQL API _and_ a REST API around your domain for different consumers.
4343

44-
An apis.py file that defines a simple software API can look like:
44+
An `apis.py` file that defines a simple software API can look like:
4545

4646
```python
4747
import logging
@@ -79,13 +79,13 @@ class BookAPI:
7979

8080
## Interfaces
8181

82-
Your domain may need to communicate with another domain. That domain can be in another web server across the web, or it could be within the same server. It could even be a third-party service. When your domain needs to talk to other domains, you should define **all interactions with it in the `interfaces.py` file**. Combined with APIs (see above), this forms the bounded context of the domain, and prevents domain logic leaking in.
82+
Your domain may need to communicate with another domain. That domain can be in another web server across the web, or it could be within the same server. It could even be a third-party service. When your domain needs to talk to other domains, you should define **all interactions to the other domain in the `interfaces.py` file**. Combined with APIs (see above), this forms the bounded context of the domain and prevents domain logic from leaking in.
8383

84-
Consider interfaces.py like a mini _Anti-Corruption Layer_. Most of the time it won't change and it'll just pass on arguments to an API function. But when the other domain moves - say you extract it into it's own web service, your domain only needs to update the code in `interfaces.py` to reflect the change. No complex refactoring needed, woohoo!
84+
Consider `interfaces.py` like a mini _Anti-Corruption Layer_. Most of the time it won't change and it'll just pass on arguments to an API function. But when the other domain moves - say you extract it into its own web service, your domain only needs to update the code in `interfaces.py` to reflect the change. No complex refactoring needed, woohoo!
8585

86-
It's worth noting that some guides would consider this implementation a code smell because it has the potential for creating shallow methods or pass-through methods. This is somewhat true, and leads us back to the [pragmatism](/using/#be-pragmatic) point in our guide. If you find your `interfaces.py` is redundant, then you probably don't need it. That said: **we recommend starting with it and removing it later**.
86+
It's worth noting that some guides would consider this implementation a 'code smell' because it has the potential for creating shallow methods or pass-through methods. This is somewhat true, and leads us back to the [pragmatism](/using/#be-pragmatic) point in our guide. If you find your `interfaces.py` is redundant, then you probably don't need it. That said: **we recommend starting with it and removing it later**.
8787

88-
An interfaces.py may look like:
88+
An `interfaces.py` may look like:
8989

9090
```python
9191
import uuid
@@ -133,15 +133,15 @@ class AuthorInterface:
133133

134134
Everything in a domain comes together in Services.
135135

136-
Services gather all the business value for this domain. What type of logic should live here? Here are a few examples:
136+
_Services_ gather all the business value for this domain. What type of logic should live here? Here are a few examples:
137137

138138
- When creating a new instance of a model, we need to compute a field on it before saving.
139139
- When querying some content, we need to collect it from a few different places and gather it together in a python object.
140140
- When deleting an instance we need to send a signal to another domain so it can do it's own logic.
141141

142-
Anything that is specific to the domain problem and **not** basic informational logic should live in Services. As most API projects expose single functional actions such as Create, Read, Update, and Delete, Services has been designed specifically to compliment stateless, single-action functions.
142+
Anything that is specific to the domain problem and **not** basic informational logic should live in Services. As most API projects expose single functional actions such as Create, Read, Update, and Delete, _Services_ has been designed specifically to compliment stateless, single-action functions.
143143

144-
A services.py file could look like:
144+
A `services.py` file could look like:
145145

146146
```python
147147
import logging
@@ -155,7 +155,7 @@ logger = logging.getLogger(__name__)
155155

156156

157157
# Plain example
158-
def get_book(*, id: uuid.UUID) -> Book:
158+
def get_book(*, id: uuid.UUID) -> Dict:
159159
book = Book.objects.get(id=id)
160160
author = AuthorInterface.get_author(id=book.author_id)
161161
return {
@@ -212,4 +212,4 @@ class PGMNodeService:
212212
- If you are using a class, it **must** use the naming convention `MyDomainService`.
213213
- Functions in services.py **must** use type annotations.
214214
- Functions in services.py **must** use keyword arguments.
215-
- You **should** be logging in services.py.
215+
- You **should** be logging in `services.py`.

docs/plugins.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
We recommend the following plugins for use with this guide.
1+
We recommend the following plugins for use with this guide:
22

33
## Django REST Framework
44

@@ -19,7 +19,7 @@ Additional ruling for DRF:
1919

2020
[Graphene-Django](https://docs.graphene-python.org/projects/django/en/latest/) is the recommended framework for creating [GraphQL](https://graphql.org/) APIs with Django.
2121

22-
When using Graphen-Django, we can organis the logic in a domain this way:
22+
When using Graphen-Django, we can organise the logic in a domain this way:
2323

2424
- `apis.py` - Queries and Mutations.
2525

docs/styleguide.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ from .rest import * # noqa
3636
from .graphql import * # noqa
3737
```
3838

39-
Then, any other file can then import from apis like so:
39+
Then, any other file can import from apis like so:
4040

4141
```python
4242
# example.py
@@ -105,7 +105,7 @@ Logic around information.
105105

106106
### Interfaces
107107

108-
Logic handling the transformation of data from other domains.
108+
Logic for handling the transformation of data from other domains.
109109

110110
---
111111

docs/using.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
In software we often specify a version of a project to use. For example - `requests==1.2` - this says _"we want to use requests version 1.2"_.
44

5-
For this guide we recommend the following: picking a specific version and working against it. Just like software; future versions of this guide could change and that could cause conflicting issues with the styleguide in your project.
5+
For this guide we recommend the following: picking a specific version and working against it. Just like software; future versions of this guide could change, potentially causing conflicts with the styleguide in your project.
66

77
You can see the released versions [here](https://github.com/phalt/django-api-domains/releases) and by clicking on the tag icon you can view historical versions. The published version at [https://phalt.github.io/django-api-domains](https://phalt.github.io/django-api-domains) will always be the latest version.
88

example_domain/services.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010

1111
# Plain example
12-
def get_book(*, id: uuid.UUID) -> Book:
12+
def get_book(*, id: uuid.UUID) -> Dict:
1313
book = Book.objects.get(id=id)
1414
author = AuthorInterface.get_author(id=book.author_id)
1515
return {

0 commit comments

Comments
 (0)