
I wrote a free book about TDD and clean architecture in Python - thedigicat
Hey HN,<p>I just published on Leanpub a free book, &quot;Clean Architectures in Python&quot;. It&#x27;s a humble attempt to organise and expand some posts I published on my blog in the last years.<p>You can find it here: https:&#x2F;&#x2F;leanpub.com&#x2F;clean-architectures-in-python<p>The main content is divided in two parts, this is a brief overview of the table of contents<p>* Part 1 - Tools
  - Chapter 1 - Introduction to TDD
  - Chapter 2 - On unit testing
  - Chapter 3 - Mocks<p>* Part 2 - The clean architecture
  - Chapter 1 - Components of a clean architecture
  - Chapter 2 - A basic example
  - Chapter 3 - Error management
  - Chapter 4 - Database repositories<p>Some highlights:<p>- The book is written with beginners in mind<p>- It contains 3 full projects, two small ones to introduce TDD and mocks, a bigger one to describe the clean architecture approach<p>- Each project is explained step-by-step, and each step is linked to a tag in a companion repository on GitHub<p>The book is free, but if you want to contribute I will definitely appreciate the help.
My target is to encourage the discussion about software architectures, both in the Python community and outside it.<p>I hope you will enjoy the book! Please spread the news on your favourite social network
======
maxnoe
I really don't get the mantra of "implement only the shortest solution that
makes the test pass"

I would add a very important second part here "you think is correct".

An introduction to TDD that starts by implementing a function called `add`
with `pass` or `return 9` is somehow deeply irritating to me.

The example would be so much closer to real world usage if you started with `a
+ b` and then realized the tests also require you to support 3 arguments.

Also: you introduced the test for three arguments _after_ you wrote the first
code for `add`.

~~~
mpweiher
> "you think is correct".

> `add` with `pass` or `return 9` is somehow deeply irritating

Similar to others, I understand this feeling. And I would urge you to get over
it.

First, technically returning 9 for a test of add(4,5) _is_ correct. Your tests
define what the function does, not the name. If you are thinking "a correct
add adds all numbers", then that isn't wrong, but it is bringing your tacit
world knowledge into the code without that knowledge being expressed in the
code. And that's Not a Good Thing™.

It also seems to me that what you meant here was not "correct" (because it is
correct), but "general". And that's one of the points of XP/TDD: as
programmers we have a terrible tendency to over-generalise. Really horrible.
"Write only the code to make the test pass" works against that tendency (and
also has the nice gamification effect mentioned elsewhere).

The other point is when to generalise. The first answer is "not", the second
is "not yet". Generalise only when you have several instances, otherwise your
generalisation will, what's the technical term, _suck_.

Last not least is _how_ to generalise. TDD/XP essentially say that you
generalise only as a refactoring, that is a behavior-preserving
transformation.

So when you add the add(10,2) test case, the really pedantic way of doing it
would be to handle the extra case with an if-check, then once the additional
test passes refactor the add method to handle all those cases with less code,
by removing the case-handling and doing arithmetic.

What that means is that you separate the coding that gets the tests to pass
from the more challenging bits of coding where you need to generalise, with
the latter always under full test coverage.

It's a _really_ nice way to make progress.

And of course: use your own judgement. If things get to tedious, it's OK to
leave out steps. At some point you will probably find that you are running
into problems, at that point you want to slow down and re-introduce more of
the intermediate steps.

~~~
ocharles
> First, technically returning 9 for a test of add(4,5) is correct. Your tests
> define what the function does, not the name. If you are thinking "a correct
> add adds all numbers", then that isn't wrong, but it is bringing your tacit
> world knowledge into the code without that knowledge being expressed in the
> code. And that's Not a Good Thing™.

How do you feel about just starting with tests that are actually more of a
specification? For example, I'm starting to feel that unit tests aren't
something we should be writing, but are something we should be _generating_.
We should be writing things like QuickCheck specifications. So the first test
I'd probably write is:

given x. y. add(x, y) == x + y

This is a specification that is essentially tested against a "model" (native
addition, in this case).

~~~
mpweiher
> How do you feel about just starting with tests that are actually more of a
> specification?

Tempted and conflicted. Yes, it's tempting, because "yay, more general and
comprehensive", the mathematician inside me says.

On the other hand, the beauty of these sorts of tests is often precisely their
concreteness/specificity. Tests should be so simple that their correctness is
obvious by inspection. (One of my problems with specifications was always that
to me it was no clearer that the specification captured what I wanted than
that the code did).

The other side of the equation is that although theoretically such concrete
tests are seriously flawed, because they only test one set of values, in
practice that is actually usually quite sufficient.

> we should be generating

Again, sounds very reasonable, but now you have to trust (a) your generator
and (b) your specification of those tests. I'd rather have a concrete test.

Now I do think there is some use for this sort of thing, for example in
ferreting out edge cases that you might otherwise miss. I wouldn't want to
rely on it.

------
thedigicat
I just published version 1.0.2 of the book. Some readers spotted typos and bad
grammar and submitted pull requests (kudos are in the changelog). You can
download it from Leanpub. Happy reading!

~~~
MrSaints
BTW, I think it might be worth including "commands" in the usecases, and
repository (looking quickly at the code on GitHub). At the moment, the only
usecase is fetching data.

~~~
thedigicat
Yes you are right. I planned to add that part in a future release. Thanks a
lot for the suggestion!

------
peteretep
Unrelated: I'm a very experienced developer, and I want to learn Python, and
I'm yet to find a book that's sufficiently challenging and doesn't start too
slowly to hold my interest.

I guess what I'm looking for is something like: "here's a list of array
operations. Now do Towers of Hanoi". Any recommendations?

~~~
jventura
Well, you can try my "Full Speed Python" book [1].

Each chapter shows the minimal syntax needed for the chapter content, and then
it has some exercises to get you going. I use it to teach Python to my
Distributed Computing course students (2nd year students, which come mostly
from a Java and C background).

The first chapters are mostly for beginners, so I guess you can skip them if
you want. I also talk about more advanced concepts on the later chapters (such
as iterators, generators, coroutines and asyncio). You can get the epubs/pdfs
from [2]..

[1] [https://github.com/joaoventura/full-speed-
python/](https://github.com/joaoventura/full-speed-python/)

[2] [https://github.com/joaoventura/full-speed-
python/releases/](https://github.com/joaoventura/full-speed-python/releases/)

~~~
peteretep
This looks absolutely perfect!

------
git-pull
I'm the author of a book also available on Leanpub.

I love this service as a publishing solution. You can write markdown and get
your book updated to dropbox (while you write it/push it to VCS) and then
publish directly through them to epub/PDF. But the other nice thing is they
can export Amazon-compatible files so you can publish to Kindle.

They also offer a very fair and transparent royalty structure. I found Amazon
could be a bit greedy. The reason why is when a book goes above 9.99, they
increase the royalty significantly.

The only other tidbit I have to say is:

I also considered using sphinx-doc as a route to build the book. I haven't
found a way to offer an appealing LaTeX (theme? template?) that'd work with
it. If you do know LaTeX well, and have time on your side, maybe sphinx-doc
could be down your alley. It can build to HTML, PDF, and epub.

As far as distribution goes: My experience with Apple's book store was very
cumbersome. Difficult to get support, and in one case there was a glitch that
unpublished the book.

~~~
thedigicat
Thank you for your comment. I considered using LaTeX or other tools, but in
the end Leanpub is very easy and straightforward and, at least for the time
being, I'm OK with it. Thanks for sharing your experience with Amazon and
Apple

------
MrSaints
Awesome. I've always been curious over examples of clean architecture in
Python. I had a cursory glance. As a suggestion, I think the `Room` domain
model could be improved with dataclasses
([https://docs.python.org/3/library/dataclasses.html](https://docs.python.org/3/library/dataclasses.html)).

~~~
BerislavLopac
Or even more by attrs:
[https://www.attrs.org/en/stable/](https://www.attrs.org/en/stable/)

~~~
jimbo1qaz
Try @attr.dataclass. It uses the cleaner 3.6+ dataclass syntax, but is more
flexible (supports kw-only classes).

~~~
thedigicat
Thank you both for your suggestions, I will consider using one of these in the
next versions of the book. Python is a moving target, so I will have to update
the examples.

~~~
MrSaints
I've recently also come across [https://pydantic-
docs.helpmanual.io/](https://pydantic-docs.helpmanual.io/) which appears to be
useful for enforcing simple constraints on domain entities.

------
jciochon
Hey, thanks for doing this! I wonder, is there a way to get the book without
leanpub? I’m not too keen on making an account to check out.

~~~
BerislavLopac
One nice thing about LeanPub is that it doesn't have to be free, you can pay
as much as you want instead: that way we can support the author.

~~~
thedigicat
Yes indeed this is the reason why I prefer to leave it on that platform. I
haven't published the book to make money, but support is appreciated and
covers the publication cost and other things like the blog. Thanks!

------
lunchladydoris
I haven't looked at it yet but I wanted to say thanks anyway. Your blog has
been really useful for picking up some more core software development
practices in Python. Looking forward to going through this!

~~~
thedigicat
Thank you for reading the blog and the book! Let me know what you think about
the book

------
vertline3
Thanks, I will read. And hopefully I will review. Hope I can hold myself
accountable to that.

~~~
thedigicat
Thank you for reading the book. Let me know if you have comments

------
throwaway98121
Just downloaded and started reading the first chapter. Thank you!

~~~
thedigicat
You are welcome. Thanks for reading my book

------
zsoltkacsandi
Hi,

thanks for writing the book.

What software did you use to writing?

~~~
thedigicat
Leanpub produces the book starting from Markdown/Markua files. Markua is a
dialect/fork of Markdown that implements book-related features like footnotes.
So I just wrote it with an editor. You can find the source code of the book
here
[https://github.com/pycabook/pycabook](https://github.com/pycabook/pycabook).
Thank you for reading the book

~~~
peteradio
Is it possible to compile the book source on my computer with some tool?

~~~
thedigicat
I don't know. I believe the Markua specification is still in progress and
while it is open Leanpub is the company that pushes it the most obviously. I
haven't found any Markua compiler, but for this book a Markdown compiler
should cover 90% of the formatting.

------
dskrvk
s/^/Show HN: / ?

~~~
thedigicat
You know what? I wasn't aware AT ALL of the "Show HN:" thing. Sorry. Next time
I'll do, I believe now it's late, isn't it?

~~~
dskrvk
I was hoping a mod would notice and update the title.

