diff --git a/content/books/things-i-learnt/_index.md b/content/books/things-i-learnt/_index.md index 2b90585..8372f7f 100644 --- a/content/books/things-i-learnt/_index.md +++ b/content/books/things-i-learnt/_index.md @@ -12,3 +12,9 @@ template = "section-contentless.html" * [Write Steps as Comments](steps-as-comments) * [Gherkin Is Your Friend to Understand Expectations](gherkin) * [Unit Tests Are Good, Integration Tests Are Gooder](integration-tests) + * [Tests Make Better APIs](tests-apis) + * [Make Tests That You Know How To Run on the Command line](tests-in-the-command-line) + * [Be Ready To Throw Your Code Away](throw-away) + * [Good Languages Come With Tests](languages-tests) + * [Future Thinking Is Future Trashing](future-trashing) + * [Documentation Is a Love Letter To Your Future Self](document-it) diff --git a/content/books/things-i-learnt/document-it/index.md b/content/books/things-i-learnt/document-it/index.md new file mode 100644 index 0000000..7203d5f --- /dev/null +++ b/content/books/things-i-learnt/document-it/index.md @@ -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. + + + +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") }} diff --git a/content/books/things-i-learnt/future-trashing/index.md b/content/books/things-i-learnt/future-trashing/index.md new file mode 100644 index 0000000..1b7874b --- /dev/null +++ b/content/books/things-i-learnt/future-trashing/index.md @@ -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. + + + +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") }} diff --git a/content/books/things-i-learnt/integration-tests/index.md b/content/books/things-i-learnt/integration-tests/index.md index 3d65867..77c5b50 100644 --- a/content/books/things-i-learnt/integration-tests/index.md +++ b/content/books/things-i-learnt/integration-tests/index.md @@ -66,4 +66,4 @@ parts. [^1]: There is no "unit" in "unit tests". "Unit test" means the test _is_ a unit, indivisible and dependent only on itself. -{{ chapters(prev_chapter_link="/books/things-i-learnt/gherkin", prev_chapter_title="Gherkin Is Your Friend to Understand Expectations") }} +{{ chapters(prev_chapter_link="/books/things-i-learnt/gherkin", prev_chapter_title="Gherkin Is Your Friend to Understand Expectations", next_chapter_title="Tests Make Better APIs", next_chapter_link="/books/things-i-learnt/tests-apis") }} diff --git a/content/books/things-i-learnt/languages-tests/index.md b/content/books/things-i-learnt/languages-tests/index.md new file mode 100644 index 0000000..2f0d7e1 --- /dev/null +++ b/content/books/things-i-learnt/languages-tests/index.md @@ -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. + + + +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") }} diff --git a/content/books/things-i-learnt/tests-apis/index.md b/content/books/things-i-learnt/tests-apis/index.md new file mode 100644 index 0000000..425b2ed --- /dev/null +++ b/content/books/things-i-learnt/tests-apis/index.md @@ -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. + + + +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") }} diff --git a/content/books/things-i-learnt/tests-in-the-command-line/index.md b/content/books/things-i-learnt/tests-in-the-command-line/index.md new file mode 100644 index 0000000..964bbf0 --- /dev/null +++ b/content/books/things-i-learnt/tests-in-the-command-line/index.md @@ -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? + + + +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") }} diff --git a/content/books/things-i-learnt/throw-away/index.md b/content/books/things-i-learnt/throw-away/index.md new file mode 100644 index 0000000..3f3a84b --- /dev/null +++ b/content/books/things-i-learnt/throw-away/index.md @@ -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. + + + +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") }} diff --git a/content/thoughts/things-i-learnt-the-hard-way.md b/content/thoughts/things-i-learnt-the-hard-way.md index 9e1ee19..fbc8c2a 100644 --- a/content/thoughts/things-i-learnt-the-hard-way.md +++ b/content/thoughts/things-i-learnt-the-hard-way.md @@ -171,7 +171,7 @@ you can finally kill the original function. function as deprecated and _add a sleep at the start of the function_, in a way that people using the old function are forced to update.) -### Good languages come with integration documentation +### Good languages come with integrated documentation If the language comes with its own way of documenting functions/classes/modules/whatever and it comes even with the simplest doc