Browse Source

Merge branch 'release/20190715'

master 20190715
Julio Biason 5 years ago
parent
commit
ff2136f771
  1. 6
      content/books/things-i-learnt/_index.md
  2. 2
      content/books/things-i-learnt/always-vcs/index.md
  3. 37
      content/books/things-i-learnt/config-file/index.md
  4. 2
      content/books/things-i-learnt/languages-are-more/index.md
  5. 48
      content/books/things-i-learnt/libraries/index.md
  6. 2
      content/books/things-i-learnt/log-events/index.md
  7. 29
      content/books/things-i-learnt/monitoring/index.md
  8. 39
      content/books/things-i-learnt/one-change-commit/index.md
  9. 84
      content/books/things-i-learnt/project-organization/index.md
  10. 2
      content/books/things-i-learnt/throw-away/index.md

6
content/books/things-i-learnt/_index.md

@ -32,6 +32,11 @@ template = "section-contentless.html"
* [Good Languages Come With Integrated Documentation](languages-docs)
* Source Control
* [Always Use A Version Control System](always-vcs)
* [One Commit Per Change](one-change-commit)
* Project Organization
* [Organize Your Code by Data/Type, Not Functionality](project-organization)
* [Create Libraries](libraries)
* [The Config File Is Friend](config-file)
* Writing code
* [Be Ready To Throw Your Code Away](throw-away)
* [Future Thinking Is Future Trashing](future-trashing)
@ -47,6 +52,7 @@ template = "section-contentless.html"
* [Always Use Timezones With Your Dates](use-timezones)
* [Always Use UTF-8 For Your Strings](use-utf8)
* [Logs Are For Events, Not User Interface](log-events)
* [Learn To Monitor](monitoring)
* Community/Teams
* [A Language Is Much More Than A Language](languages-are-more)
* [Understand And Stay Away From Cargo Cult](cargo-cult)

2
content/books/things-i-learnt/always-vcs/index.md

@ -30,4 +30,4 @@ change.
And, in the long, since you'll end up with working in team and will be
required to use a VCS, you'll be used to using one.
{{ chapters(prev_chapter_link="/books/things-i-learnt/languages-docs", prev_chapter_title="Good Languages Come With Integrated Documentation", next_chapter_link="/books/things-i-learnt/throw-away", next_chapter_title="Be Ready To Throw Your Code Away") }}
{{ chapters(prev_chapter_link="/books/things-i-learnt/languages-docs", prev_chapter_title="Good Languages Come With Integrated Documentation", next_chapter_link="/books/things-i-learnt/one-change-commit", next_chapter_title="One Commit Per Change") }}

37
content/books/things-i-learnt/config-file/index.md

@ -0,0 +1,37 @@
+++
title = "Things I Learnt The Hard Way - The Config File Is Friend"
date = 2019-07-15
[taxonomies]
tags = ["en-au", "books", "things i learnt", "configuration", "config file"]
+++
Do not ignore the power of configuration files.
<!-- more -->
Imagine you wrote a function that you have to pass a value for it to start
processing (say, a twitter user account id). But then you have to do that with
two values and you just call the function again with the other value.
It makes more sense to use a config file and just run the application twice
with two different config files 'cause, this way, you have a single, small,
testable application instead of two, or a very complex application that does a
lot of stuff.
We can even jump into the idea of [creating
libraries](/books/things-i-learnt/libraries) and say that, instead of
splitting your e-commerce application into smaller parts and making a big one
by grouping these smaller parts, you could simply have one e-commerce
application and, for each of your clients, you would have a different
configuration file, pointing to different assets. This way, even the assets
may reside in the same repository in the same branch, 'cause all that
identifies which assets should be used are defined in the configuration file.
"But which one should I use?" you may ask. Well, "it depends". It may make
sense to have one single application with different configuration files if
most of its can be used all the time. If the intersection of used things is
very small, it may make more sense to split into different libraries and just
"pick and chose" what to use.
{{ chapters(prev_chapter_link="/books/things-i-learnt/libraries", prev_chapter_title="Create Libraries", next_chapter_link="/books/things-i-learnt/throw-away", next_chapter_title="Be Ready To Throw Your Code Away") }}

2
content/books/things-i-learnt/languages-are-more/index.md

@ -54,4 +54,4 @@ And picking a language for something _above_ the syntax is even worse.
tool." So, basically, the community ignored whatever the community was
using.
{{ chapters(prev_chapter_link="/books/things-i-learnt/log-events", prev_chapter_title="Logs Are For Events, Not User Interface", next_chapter_link="/books/things-i-learnt/outside-project", next_chapter_title="Don't Mess With Things Outside Your Project") }}
{{ chapters(prev_chapter_link="/books/things-i-learnt/monitoring", prev_chapter_title="Learn To Monitor", next_chapter_link="/books/things-i-learnt/outside-project", next_chapter_title="Don't Mess With Things Outside Your Project") }}

48
content/books/things-i-learnt/libraries/index.md

@ -0,0 +1,48 @@
+++
title = "Things I Learnt The Hard Way - Create Libraries"
date = 2019-07-15
[taxonomies]
tags = ["en-au", "books", "things i learnt", "libraries", "project organization"]
+++
One thing you must learn is how to break your project into smaller libraries,
to avoid doing rounds to deal with "the same, but a bit different".
<!-- more -->
I've seen a lot of projects that use things like branches for different
things. Say, you have an e-commerce page. But you also have different clients,
and they all have different colours and logo. Some people would take this
scenario and, using the VCS properties, use the main branch for the main code
and a branch for each client, merge from main branch from time to time -- and,
thus, the branches are never merged back.
This is suboptimal, 'cause that's not how VCS are supposed to be used.
But you can, for example, break the main code into a library/framework and
have one project for each client, with their assets and you just reference the
library/framework in each.
Simple and clean.
But stop there for a second. Although this makes the code cleaner, avoids
duplication and uses a VCS in the way it was supposed to be used, you can't
start this way.
Remember that [future thinking is future
trashing](/books/things-i-learnt/future-trashing). What you can do is actually
break your project by functionality, [making modules related to their
data](/books/things-i-learnt/project-organization) and then, when you get a
reasonable number of clients, you'll notice what can be reused in each, what
modules make sense for one client and not for another. And then you'll have a
good way to deal with those.
One project that may appear when creating libraries is "How do I create my own
library repository?" 'Cause all modern languages today have support for
importing external libraries and, even if your libraries will never be out of
your control, they are external to the project. So you may need to learn how
to deal with this before creating the libraries. And, unfortunately, each
language and build tool has its own way to manage this.
{{ chapters(prev_chapter_link="/books/things-i-learnt/project-organization", prev_chapter_title="Organize Your Code by Data/Type, Not Functionality", next_chapter_link="/books/things-i-learnt/config-file", next_chapter_title="The Config File Is Friend") }}

2
content/books/things-i-learnt/log-events/index.md

@ -43,4 +43,4 @@ could have the values to try to figure out why it failed -- surely, logging
why it failed also helps, but you know what I mean. This is an example of
something that makes complete sense in logs, but not in user interfaces.
{{ chapters(prev_chapter_link="/books/things-i-learnt/use-utf8", prev_chapter_title="Always Use UTF-8 For Your Strings", next_chapter_link="/books/things-i-learnt/languages-are-more", next_chapter_title="A Language Is Much More Than A Language") }}
{{ chapters(prev_chapter_link="/books/things-i-learnt/use-utf8", prev_chapter_title="Always Use UTF-8 For Your Strings", next_chapter_link="/books/things-i-learnt/monitoring", next_chapter_title=Learn To Monitor"") }}

29
content/books/things-i-learnt/monitoring/index.md

@ -0,0 +1,29 @@
+++
title = "Things I Learnt The Hard Way - Logs Are For Events, Not User Interface"
date = 2019-07-15
[taxonomies]
tags = ["en-au", "books", "things i learnt", "monitoring"]
+++
On a previous life, to understand how a system behaved, I added a ton of
metrics: how fast things were going in, how fast things were going out, how
many things were in the middle, how many the job processed... Not doing it so
makes me feel... naked.
<!-- more -->
Monitoring your project performance give you a really good view of how a
system is behaving. Is the speed going down? Is the system taking longer to
process an input? Are no inputs being processed?
If you have this kind of information, you can check what is going on in the
system and understand why. Is it normal? Did a change around the system (the
other system that produces the input, the system that consumes in the output)
affected the results?
If you're not measuring, you'll have no idea.
Also, "If you can not measure it, you can not improve it", as Lord Kevin said.
{{ chapters(prev_chapter_link="/books/things-i-learnt/log-events", prev_chapter_title="Logs Are For Events, Not User Interface", next_chapter_link="/books/things-i-learnt/languages-are-more", next_chapter_title="A Language Is Much More Than A Language") }}

39
content/books/things-i-learnt/one-change-commit/index.md

@ -0,0 +1,39 @@
+++
title = "Things I Learnt The Hard Way - One Commit Per Change"
date = 2019-07-09
[taxonomies]
tags = ["en-au", "books", "things i learnt", "source control", "commits"]
+++
When working with source control tools, keep one change per commit. Avoid
bundling more than one change in a single commit just to "save time".
<!-- more -->
I've seen my fair share of commits with messages like "Fix issues #1, #2
and #3". This is not something you should do. One commit for fixing issue #1,
another for #2 and yet another for #3.
Just note that I said "one commit per change", not "one commit per file".
Sometimes, to make a single change, you may need to change more than one file
-- it may point that you have a coupling problem, but that's a different
issue. You could, for example, make one commit which adds a new field in model
without adding a change in the controller to load this field; after all, the
controller won't (or, at least, shouldn't) break due the added field, and the
model won't break (or, at least, shouldn't) break because the controller is
not touching the field[^1].
When making a commit, think this: "In case something goes wrong, can I undo
this commit without breaking other stuff?" Commit history is stacked, so
obviously you'd have to undo the commits on top of that one. And that's
alright.
**BONUS TIP**! If you're using `git`, you can use `git add -p` in case you
"overchange". It will allow you to pick parts of a file, instead of adding all
the changes in the file before committing.
[^1]: Ok, it _may_ have some issues if the field can't be null, but you get
what I meant, right?
{{ chapters(prev_chapter_link="/books/things-i-learnt/always-vcs", prev_chapter_title="Always Use A Version Control System", next_chapter_link="/books/things-i-learnt/project-organization", next_chapter_title="Organize Your Code by Data/Type, Not Functionality") }}

84
content/books/things-i-learnt/project-organization/index.md

@ -0,0 +1,84 @@
+++
title = "Things I Learnt The Hard Way - Organize Your Code by Data/Type, Not Functionality"
date = 2019-07-15
[taxonomies]
tags = ["en-au", "books", "things i learnt", "project", "project organization"]
+++
A lot of projects assume that you'll put things with the same functionality in
the same place, no matter what data they deal with. This makes things harder
to break apart later.
<!-- more -->
Most projects keep organized by the functionality each component do. For
example, all the models are in the same place, all the functions that convert
one model into an internal structure/DTO are kept together, and so on.
Something like this:
```
.
+-- IncomingModels
| +-- DataTypeInterface
| +-- DataType1
| +-- DataType2
| +-- DataType3
+-- Filters
| +-- FilterInterface
| +-- FilterValidDataType2
+-- Processors
| +-- ProcessorInterface
| +-- ConvertDataType1ToDto1
| +-- ConvertDataType2ToDto2
+-- OutgoingModels
+-- DtoInterface
+-- Dto1
+-- Dto2
```
This is fine and works. But when you organize by data, it'll make a lot easier
to split your project in smaller projects -- 'cause, at some point, you may
want to do almost the same thing as you're doing right now, but with small
differences.
```
.
+-- Base
| +-- IncomingModels
| | +-- DataTypeInterface
| +-- Filters
| | +-- FilterInterface
| +-- Processors
| | +-- ProcessorInterface
| +-- OutgoingModels
| +-- DtoInterface
+-- Data1
| +-- IncomingModels
| | +-- DataType1
| +-- Processors
| | +-- ConvertDataType1ToDto1
| +-- OutgoingModels
| +-- Dto1
...
```
Now you can make a module that deals _only_ with Data1, another that works
only with Data2 and so on. And then you can break them into isolated modules.
And then when you have another project that also have Data1 but also deals
with Data3, you can reuse most of the stuff in the Data1 module.
And I do understand that this creates an explosion of directories/packages,
which may seem a bit unnecessary.
Believe me, I also thought the idea of keeping things by functionality made
more sense. But in one project, I got a requirement to do almost the same
thing as I was doing before, but with a small change, which would require one
less step/transformation (in our example, you can think as the new requirement
as doing exactly what the Data1, Data2 and Data3 did, with their
transformations and such, but without the Data3 part). By breaking by their
types, I managed to create small modules for each one and the new project
would simply reference Data1 and Data2, but not Data3.
{{ chapters(prev_chapter_link="/books/things-i-learnt/one-change-commit", prev_chapter_title="One Commit Per Change", next_chapter_link="/books/things-i-learnt/libraries", next_chapter_title="Create Libraries") }}

2
content/books/things-i-learnt/throw-away/index.md

@ -39,4 +39,4 @@ 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/always-vcs", prev_chapter_title="Always Use A Version Control System", next_chapter_link="/books/things-i-learnt/future-trashing", next_chapter_title="Future Thinking Is Future Trashing") }}
{{ chapters(prev_chapter_link="/books/things-i-learnt/config-file", prev_chapter_title="The Config File Is Friend", next_chapter_link="/books/things-i-learnt/future-trashing", next_chapter_title="Future Thinking Is Future Trashing") }}

Loading…
Cancel
Save