Julio Biason
6 years ago
9 changed files with 207 additions and 2 deletions
@ -0,0 +1,28 @@
|
||||
+++ |
||||
title = "Things I Learnt The Hard Way - Documentation Is a Love Letter To Your Future Self" |
||||
date = 2019-06-21 |
||||
|
||||
[taxonomies] |
||||
tags = ["en-au", "books", "things i learnt", "documentation"] |
||||
+++ |
||||
|
||||
We all know writing the damn docs for functions and classes and modules is a |
||||
pain in the backside. But realizing what you were thinking when you wrote the |
||||
function will save your butt in the future. |
||||
|
||||
<!-- more --> |
||||
|
||||
When I say that it will save your butt, I don't mean the documentation will |
||||
tell you something like "Here are the lotto numbers in 2027"[^1] or "If John |
||||
complains about your future code review, here is some shit he did in the |
||||
past". |
||||
|
||||
I mean, it will explain how the _flow_ of your code is expected to do. Imaging |
||||
this: pick your code and replace every function call to its documentation. Can |
||||
you understand what it is expected by reading that? If you can, |
||||
congratulations, you won't have a problem in the future; if you can't... well, |
||||
I have some bad news for you... |
||||
|
||||
[^1]: Please, don't make me revise this in 2027... :( |
||||
|
||||
{{ chapters(prev_chapter_link="/books/things-i-learnt/future-trashing", prev_chapter_title="Future Thinking is Future Trashing") }} |
@ -0,0 +1,26 @@
|
||||
+++ |
||||
title = "Things I Learnt The Hard Way - Future Thinking is Future Trashing" |
||||
date = 2019-06-21 |
||||
|
||||
[taxonomies] |
||||
tags = ["en-au", "books", "things i learnt", "design", "solution"] |
||||
+++ |
||||
|
||||
When developers try to solve a problem, they sometimes try to find a way that |
||||
will solve all the problems, including the ones that may appear in the future. |
||||
|
||||
<!-- more --> |
||||
|
||||
Trying to solve the problems that will appear in the future comes with a hefty |
||||
tax: future problems future will never come -- and, believe me, they _never_ |
||||
come -- and you'll end up either having to maintain a huge behemoth of code |
||||
that will never be fully used or you'll end up rewriting the whole thing |
||||
'cause there is a shitton of unused stuff. |
||||
|
||||
Solve the problem you have right now. Then solve the next one. And the next |
||||
one. At one point, you'll realize there is a pattern emerging from those |
||||
solutions and _then_ you'll find your "solve everything". This pattern is the |
||||
_abstraction_ you're looking for and _then_ you'll be able to solve it in a |
||||
simple way. |
||||
|
||||
{{ chapters(prev_chapter_link="/books/things-i-learnt/languages-tests", prev_chapter_title="Good Languages Come With Tests", next_chapter_link="/books/things-i-learnt/document-id", next_chapter_title="Documentation Is a Love Letter To Your Future Self") }} |
@ -0,0 +1,25 @@
|
||||
+++ |
||||
title = "Things I Learnt The Hard Way - Good Languages Come With Tests" |
||||
date = 2019-06-20 |
||||
|
||||
[taxonomies] |
||||
tags = ["en-au", "books", "things i learnt", "programming languages", "tests"] |
||||
+++ |
||||
|
||||
You can be sure that if a language brings a testing framework -- even minimal |
||||
-- in its standard library, the ecosystem around it will have better tests |
||||
than a language that doesn't carry a testing framework, no matter how good the |
||||
external testing frameworks for the language are. |
||||
|
||||
<!-- more --> |
||||
|
||||
The reason is kinda obvious on this one: When the language itself brings a |
||||
testing framework, it reduces the friction for people to start writing tests, |
||||
and that includes the authors of the language itself and the community. |
||||
|
||||
Sure, better frameworks may come along, and languages that don't have a |
||||
testing framework in their standard library may have options with better |
||||
support and easier access but, again, when they are there from the start, the |
||||
start is better and the final result is better. |
||||
|
||||
{{ chapters(prev_chapter_link="/books/things-i-learnt/throw-away", prev_chapter_title="Be Ready To Throw Your Code Away", next_chapter_link="/books/things-i-learnt/future-trashing", next_chapter_title="Future Thinking is Future Trashing") }} |
@ -0,0 +1,45 @@
|
||||
+++ |
||||
title = "Things I Learnt The Hard Way - Tests Make Better APIs" |
||||
date = 2019-06-19 |
||||
|
||||
[taxonomies] |
||||
tags = ["en-au", "book", "things i learnt", "unit tests", "layers", "apis"] |
||||
+++ |
||||
|
||||
Testing things in isolation may give a better view of your APIs. |
||||
|
||||
<!-- more --> |
||||
|
||||
When I spoke about [integration |
||||
tests](/books/things-i-learnt/integration-tests) you may end up with the |
||||
impression that I don't like unit tests[^1]. |
||||
|
||||
Actually, I think they provide some good intrinsic values. |
||||
|
||||
For example, as mentioned before, they can provide a better look at the |
||||
adherence to the design. |
||||
|
||||
But, at the same time, they give a better view of your internal -- and even |
||||
external -- APIs. |
||||
|
||||
For example, you're writing the tests for the view layer -- 'cause, you know, |
||||
we write everything in layers; layers on top of layers -- and you're noticing |
||||
that you have to keep a lot of data (state) around to be able to make the |
||||
calls to the controller. That's a sign that you may have to take a better look |
||||
at the controller API. |
||||
|
||||
Not only that, but take, for example, the fact that you're working on a |
||||
library -- which will be called by someone else -- and you're writing tests |
||||
for the most external layer, the layer that will be exposed by the library. |
||||
And, again, you're noticing that you have to keep a lot of context around, |
||||
lots of variables, variables coming from different places and similar calls |
||||
using parameters in different ways. Your tests will look like a mess, don't |
||||
they? That's because the API _is_ a mess. |
||||
|
||||
Unit testing your layers makes you the _user_ of that layer API, and then you |
||||
can see how much one would suffer -- or, hopefully, enjoy -- using that. |
||||
|
||||
[^1]: Again, let's ignore for a second that there are no "unit" in "unit |
||||
tests"... |
||||
|
||||
{{ chapters(prev_chapter_link="/books/things-i-learnt/integration-tests", prev_chapter_title="Unit Tests Are Good, Integration Tests Are Gooder", next_chapter_link="/books/things-i-learnt/tests-in-the-command-line", next_chapter_title="Make Tests That You Know How To Run on the Command line") }} |
@ -0,0 +1,37 @@
|
||||
+++ |
||||
title = "Things I Learnt The Hard Way - Make Tests That You Know How To Run on the Command line" |
||||
date = 2019-06-19 |
||||
|
||||
[taxonomies] |
||||
tags = ["en-au", "book", "things i learnt", "tests", "command line"] |
||||
+++ |
||||
|
||||
You know that "Play" with a little something on your IDE that runs only the |
||||
tests? Do you know what it does? |
||||
|
||||
<!-- more --> |
||||
|
||||
A long time ago I read the story about a professor that taught his students to |
||||
code. He preferred to teach using an IDE, 'cause then "students have to just |
||||
press a button to run the tests". |
||||
|
||||
I get the idea, but I hate the execution. |
||||
|
||||
When we get into professional field, we start using things like [continuous |
||||
integration](https://en.wikipedia.org/wiki/Continuous_integration) which, |
||||
basically, is "run tests every time something changes" (it's a bit more than |
||||
that, but that's the basic idea). |
||||
|
||||
Now, let me ask you this: Do you think the students of the professor above |
||||
would know how to add the command to run the tests in a continuous |
||||
integration system? |
||||
|
||||
I know I'm being too picky (one could even call me "pricky" about this) but |
||||
the fact is that whatever we do today, at some point can be automated: our |
||||
tests can be run in an automated form, our deployment can be run in an |
||||
automated form, our validation can be run in an automated form and so on. If |
||||
you have no idea how those things "happen", you'll need the help of someone |
||||
else to actually build this kind of stuff, instead of having the knowledge |
||||
(well, half knowledge, the other half is the CI tool) with you all the time. |
||||
|
||||
{{ chapters(prev_chapter_link="/books/things-i-learnt/tests-apis", prev_chapter_title="Tests Make Better APIs", next_chapter_link="/books/things-i-learnt/throw-away", next_chapter_title="Be Ready To Throw Your Code Away") }} |
@ -0,0 +1,38 @@
|
||||
+++ |
||||
title = "Things I Learnt The Hard Way - Be Ready To Throw Your Code Away" |
||||
date = 2019-06-19 |
||||
|
||||
[taxonomies] |
||||
tags = ["en-au", "book", "things i learnt", "code"] |
||||
+++ |
||||
|
||||
A lot of people, when they start with TDD, get annoyed when you say that you |
||||
may have to rewrite a lot of stuff, including whatever your already wrote. |
||||
|
||||
<!-- more --> |
||||
|
||||
TDD was _designed_ to throw code away: The more you learn about your problem, |
||||
the more you understand that, whatever you wrote, won't solve the problem in |
||||
the long run. |
||||
|
||||
You shouldn't worry about this. Your code is not a wall: if you have to throw |
||||
it always, it is not wasted material. Surely it means your time writing code |
||||
was lost, but you got a better understanding about the problem now. |
||||
|
||||
Not only that, but as you progress through your project, solving problems and |
||||
getting "acquainted" with the problem, you'll also notice that the |
||||
[spec](/books/things-i-learnt/spec-first) will also change. This means that the problem you solved |
||||
wasn't exactly the problem you _needed_ to solve; your code is trying to solve |
||||
something that isn't exactly the problem. |
||||
|
||||
Also, this is really common -- the spec changing, not throwing the code away, |
||||
that is. One thing that you can be sure is that it won't change _everywhere_. |
||||
Some of the things you solved will stay the same, some others will be |
||||
completely removed and some others added. And you will see that you'll |
||||
refactor your code a lot, and throw a lot of code away. And not just code that |
||||
solves the problem, but also the tests for that code. |
||||
|
||||
... unless you focus mostly on [integration |
||||
tests](/books/things-i-learnt/integration-tests). |
||||
|
||||
{{ chapters(prev_chapter_link="/books/things-i-learnt/tests-in-the-command-line", prev_chapter_title="Make Tests That You Know How To Run on the Command line", next_chapter_link="/books/things-i-learnt/language-tests", next_chapter_title="Good Languages Come With Tests") }} |
Loading…
Reference in new issue