Skip to content

Commit 94298f1

Browse files
committed
up and running with milligram and pygments. done command handler blog
1 parent 546d2c9 commit 94298f1

10 files changed

Lines changed: 980 additions & 744 deletions

blog/2017-09-07-introducing-command-handler.md

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -123,11 +123,12 @@ concept of a Controller in an MVC architecture.
123123

124124
First, we create a Command object.
125125

126+
```python
126127
class ReportIssueCommand(NamedTuple):
127128
reporter_name: str
128129
reporter_email: str
129130
problem_description: str
130-
131+
```
131132

132133
A command object is a small object that represents a state-changing action that
133134
can happen in the system. Commands have no behaviour, they're pure data
@@ -167,6 +168,7 @@ model. This has two major benefits:
167168

168169
In order to process our new command, we'll need to create a command handler.
169170

171+
```python
170172
class ReportIssueCommandHandler:
171173
def __init__(self, issue_log):
172174
self.issue_log = issue_log
@@ -177,7 +179,7 @@ class ReportIssueCommandHandler:
177179
cmd.reporter_email)
178180
issue = Issue(reported_by, cmd.problem_description)
179181
self.issue_log.add(issue)
180-
182+
```
181183

182184

183185
Command handlers are stateless objects that orchestrate the behaviour of a
@@ -201,6 +203,7 @@ Since our command handlers are just glue code, we won't put any business logic
201203
into them - they shouldn't be making any business decisions. For example, let's
202204
skip ahead a little to a new command handler:
203205

206+
```python
204207
class MarkIssueAsResolvedHandler:
205208
def __init__(self, issue_log):
206209
self.issue_log = issue_log
@@ -210,7 +213,7 @@ class MarkIssueAsResolvedHandler:
210213
# the following line encodes a business rule
211214
if (issue.state != IssueStatus.Resolved):
212215
issue.mark_as_resolved(cmd.resolution)
213-
216+
```
214217

215218
This handler violates our glue-code principle because it encodes a business
216219
rule: "If an issue is already resolved, then it can't be resolved a second
@@ -222,21 +225,23 @@ reason to prefer a class is that it can make dependency management a little
222225
easier, but the two approaches are completely equivalent. For example, we could
223226
rewrite our ReportIssueHandler like this:
224227

228+
```python
225229
def ReportIssue(issue_log, cmd):
226230
reported_by = IssueReporter(
227231
cmd.reporter_name,
228232
cmd.reporter_email)
229233
issue = Issue(reported_by, cmd.problem_description)
230234
issue_log.add(issue)
231-
235+
```
232236

233237
If magic methods make you feel queasy, you can define a handler to be a class
234238
that exposes a handle method like this:
235239

240+
```python
236241
class ReportIssueHandler:
237242
def handle(self, cmd):
238243
...
239-
244+
```
240245

241246
However you structure them, the important ideas of commands and handlers are:
242247

@@ -257,6 +262,7 @@ other languages - Java, C#, C++ - I would usually have a single binary for each
257262
layer. Splitting the packages up this way makes it easier to understand how the
258263
dependencies work.
259264

265+
```python
260266
from typing import NamedTuple
261267
from expects import expect, have_len, equal
262268

@@ -345,7 +351,7 @@ class When_reporting_an_issue:
345351

346352
def it_should_have_recorded_the_description(self):
347353
expect(self.issues[0].description).to(equal(desc))
348-
354+
```
349355

350356
There's not a lot of functionality here, and our issue log has a couple of
351357
problems, firstly there's no way to see the issues in the log yet, and secondly

generate-html.py

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

1313
def main():
1414
posts = glob.glob("blog/*.md")
15-
extensions = ['extra', 'smarty', 'meta']
15+
extensions = ['extra', 'smarty', 'meta', 'codehilite']
1616
_md = markdown.Markdown(extensions=extensions, output_format='html5')
1717

1818
loader = jinja2.FileSystemLoader(searchpath="./")

index.html

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
<!DOCTYPE html>
12
<html lang=en>
23
<head>
34
<meta charset="utf-8">
@@ -7,6 +8,7 @@
78
<link rel="stylesheet" href="//fonts.googleapis.com/css?family=Roboto:300,300italic,700,700italic">
89
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/normalize/5.0.0/normalize.css">
910
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/milligram/1.3.0/milligram.css">
11+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/pygments-css@1.0.0/friendly.css">
1012
</head>
1113
<body>
1214
<main class="wrapper">
@@ -19,7 +21,7 @@ <h1 class="title">Cosmic Python</h1>
1921
</section>
2022
</nav>
2123

22-
<section class="container" id="examples">
24+
<section class="container">
2325
<h1 class="title">Cosmic Python</h1>
2426
<p>Simple patterns for building complex applications</p>
2527

posts/2017-09-07-introducing-command-handler.html

Lines changed: 168 additions & 111 deletions
Large diffs are not rendered by default.

posts/2017-09-08-repository-and-unit-of-work-pattern-in-python.html

Lines changed: 130 additions & 91 deletions
Large diffs are not rendered by default.

posts/2017-09-13-commands-and-queries-handlers-and-views.html

Lines changed: 112 additions & 84 deletions
Large diffs are not rendered by default.

posts/2017-09-19-why-use-domain-events.html

Lines changed: 245 additions & 198 deletions
Large diffs are not rendered by default.

posts/2020-01-25-testing_external_api_calls.html

Lines changed: 278 additions & 242 deletions
Large diffs are not rendered by default.

rss.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
Simple patterns for building complex apps
88
</description>
99
<link>https://cosmicpython.com</link>
10-
<lastBuildDate>Tue, 10 Mar 2020 19:28:16 -0000</lastBuildDate>
10+
<lastBuildDate>Sun, 15 Mar 2020 18:58:55 -0000</lastBuildDate>
1111
<pubDate>Sat, 4 Jan 2020 19:15:54 -0500</pubDate>
1212
<atom:link href="https://cosmicpython.com/rss.xml" rel="self" type="application/rss+xml" />
1313

templates/blog_post_template.html

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,36 @@
11
<!DOCTYPE html>
22
<html lang="en">
33

4-
<head>
5-
</head>
4+
<head>
5+
<meta charset="utf-8">
6+
<meta name="viewport" content="width=device-width, initial-scale=1">
7+
<meta name="author" content="Harry Percival and Bob Gregory">
8+
<meta name="description" content="">
9+
<link rel="stylesheet" href="//fonts.googleapis.com/css?family=Roboto:300,300italic,700,700italic">
10+
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/normalize/5.0.0/normalize.css">
11+
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/milligram/1.3.0/milligram.css">
12+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/pygments-css@1.0.0/friendly.css">
13+
</head>
614

7-
<body>
8-
<h1> {{ blog_heading[0] }}</h1>
9-
<p>by {{blog_author[0]}}, {{blog_publish_date[0]}}</p>
15+
<body>
16+
<main class="wrapper">
1017

11-
<div class="content">
12-
{{content}}
13-
</div>
14-
</body>
18+
<nav class="navigation">
19+
<section class="container">
20+
<a class="navigation-title" href="https://cosmicpython.com">
21+
<h1 class="title">Cosmic Python</h1>
22+
</a>
23+
</section>
24+
</nav>
25+
26+
<section class="container">
27+
<h1> {{ blog_heading[0] }}</h1>
28+
<p>by {{blog_author[0]}}, {{blog_publish_date[0]}}</p>
29+
30+
<div class="content">
31+
{{content}}
32+
</div>
33+
</section>
34+
</main>
35+
</body>
1536
</html>

0 commit comments

Comments
 (0)