Writing code for people
Alexey Ivanov, Evil Martians
Evil Martians
Evil Martians
Do you know how to write?
- Know how to write letters?
- Know how to write words?
- Know how to write sentences?
-
Do you write emails, Line messages, or tweets every day?
- Do you write books?
Have you been in these situations?
-
You open your code from one year ago and can't remember how it works.
-
You spend half of the day adding
debug
and
console.log
to functions to see what they are doing.
-
You tried to read another person's code and can't understand it.
-
^ BTW. Others probably thought the same about your code too.
This is a common situation
Most of programming tutorials and books teach how to write code that can
be understood by the computer and do some stuff with it.
Very few books and tutorials teach how to write code that other people
can read and understand.
But it's not a good situation
You write code once. But you and other people will be reading and
modifying it tens or even hundreds of times after that.
So it's crucial to write code that is readable,
reusable, and refactorable.
It's a skill that can be learned
As with any other skill, if you will be mindful of what you are writing
and spend enough time training, you will become better at this.
Talk structure
-
Writing the code - principles, rules, style guides,
and linters.
-
Reading the code - how to train yourself to become a
better writer.
Writing the code
- Clean code.
- Easy to understand code.
- Code that shares context.
Clean code
- Select one code style.
- Automate it.
- Forget about it.
Clean code Select a code style
There are tons of existing style guides:
Choose any of them. It's not important which one. Don't spend time on
that.
Clean code Add linters
Linters usually have excellent documentation about when and why to use
each rule.
Clean code Add standard config for linters
The good thing about using a popular style guide is the fact that
it is already automated.
Clean code Enable automatic linting and fixing
- Add
prettier
and linter plugins to your editor.
- Enable automatic fixing in
prettier
.
- Add precommit hook that automatically format/lint your code.
- Run your checks in CI (CircleCI or TravisCI will do).
Easy to understand code
- Readability.
- Complexity.
- Reading flow.
Readability Use meaningful and pronounceable variable names
Bad:
const yyyymmdstr = moment().format("YYYY/MM/DD");
Good:
const currentDate = moment().format("YYYY/MM/DD");
Readability Use searchable names
Bad:
setTimeout(blastOff, 86400000);
Good:
const MILLISECONDS_IN_A_DAY = 86_400_000;
setTimeout(blastOff, MILLISECONDS_IN_A_DAY);
Readability Function arguments (2 or fewer ideally)
Bad:
function createMenu(title, body, buttonText, cancellable) {
// ...
}
createMenu("Foo", "Bar", "Baz", true);
Readability Function arguments (2 or fewer ideally)
Good:
function createMenu({ title, body, buttonText, cancellable })
// ...
}
createMenu({
title: "Foo", body: "Bar", buttonText: "Baz", cancellable: true
});
Readability Further reading
Complexity Automation
You can automate detection of such things. For example with Eslint:
complexity
- Cyclomatic Complexity
max-depth
max-statements
max-nested-callbacks
Be careful. Following these rules blindly can produce
harder to read code.
Reading flow
-
How often do you go back and forth between functions and methods in
the file?
-
How many files do you need to open to understand how something works?
-
Are the files that you are switching between are close to each other
or do you need to go to different nested folders?
Sometimes it is better to break complexity rules to make the reading
flow easier.
Reading flow Place things close to each other
dropdown/
locale/
en.json
jp.json
index.js
index.test.js
readme.md
styles.css
Example Replacing GA with GTM
Old code:
window.ga("send", {
hitType: "event",
eventCategory: "Videos",
eventAction: "play",
eventLabel: "Fall Campaign",
eventValue: 10
});
Example Replacing GA with GTM
Old code:
window.ga("send", {
hitType: "event",
eventCategory: "Page",
eventAction: "Navigate",
});
Example Replacing GA with GTM
New code:
window.dataLayer.push({
category: "Videos",
action: "play",
label: "Fall Campaign",
value: 10
});
Example Replacing GA with GTM
New code:
window.dataLayer.push({
category: "Page",
action: "Navigate",
});
Example Replacing GA with GTM
Solution:
const event = { /* ... */ }
const eventPlaceholder = {
label: undefined, value: underfined
};
window.dataLayer.push({ ...eventPlaceholder, ...event });
But how do you share this knowledge?
-
You can't just leave the code" as is" – next developer can delete
it while refactoring, and then they will spend eight more hours
debugging it.
-
You can't ask other people to review this code without telling them
what it is doing and why.
- Other people can't update and maintain this code.
/*
GTM sets all event fields as global variables inside itself,
so until we rewrite them, they will have old values. Because
label and value are optional fields, we need to unset them
for the next events explicitly. Relevant docs:
- https://developers.google.com/tag-manager/devguide
- https://support.google.com/tagmanager/answer/6164391?hl=en
*/
What is context?
Code can't explain why the program is being written, and the rationale
for choosing this or that method. Code cannot discuss the reasons
certain alternative approaches were taken.
Jeff Raskin
What is context?
For example:
/* A binary search turned out to be slower than the
Boyer-Moore algorithm for the data sets of interest,
thus we have used the more complex, but faster method
even though this problem does not at first seem
amenable to a string search technique. */
Jeff Raskin
CSS example
@media (--sm-scr) {
.input {
font-size: 16px; /* prevents iOS auto-scale on focus */
}
}
When to comment
-
The reader needs a context that can't be expressed using other means.
-
The code exists because of the environment issues. Browser bugs,
for example.
-
The ugly solution is chosen because of speed optimization reasons.
Summary of the first part
- Clean code.
-
Easy to understand code.
- Readability.
- Complexity.
- Reading flow.
- Code that shares context.
Reading the code
- Code reading.
- Code reviews.
- Pair Programming.
Code reading
Code reading
Crockford's method:
- Do it every day.
- Discuss approaches, patterns, and possible solutions.
- Don't judge. Don't use results as metrics.
Code reading
Who should read:
-
Reading by the author - faster to do, better at
describing context, but fewer chances to find problems.
-
Reading by the other person - slower, requires more
steps, more useful feedback on writing.
Code reading
You can use methodology from usability testings for the additional
effect:
-
Think aloud. Make assumptions about what variables and functions will
do.
- Check if these assumptions were correct.
- See how much time you spend on each block.
-
See how often you switch between files and sections inside the file.
Read more:
Thinking Aloud: The #1 Usability Tool
Code reading
Read the code from open-source projects that you use together in the
same way:
- You will have a better understanding of how they work.
-
You will see which approaches to writing code works and which don't.
Some projects to start from
Code review
Principles of the clean code apply to commits and PRs as well:
- Short, <200LOC PRs.
- Do only one thing.
- Describe the context.
Code review Split to many small PRs
If you have large PR - split them to the smaller parts:
- Refactoring filenames? Create PR.
-
Changing the React component that is used in multiple places? Create
PR.
- Making new utility for everyone to use? Create PR.
Code review Describe context
You can (and should) use commit messages and PR description to describe
the task's context:
- What was the task?
- Why did you choose to solve it in this way and not another?
Code review Advance preparation
Things that should be done before code review:
-
Discuss the PR process and decide who and how fast should review them.
- Chose style guide and enable linters.
- Discuss the new APIs before starting writing code for them.
Code review Can't split to different PRs?
-
Split large PRs that need to be merged all at once in the separate
commits that only do one thing.
- Give each commit a meaningful name.
-
Before pushing to upstream, make your commit history beautiful:
Squash, rename, and clean up your commits.
Pair programing
How to use to become a better writer:
- Discuss the plan and make a basic structure.
- Split tasks so both sides can program and not only listen.
- Comment what you are trying to do now.
- Give real-time feedback and ask questions.
Summary of the talk
Writing:
- Clean code.
-
Easy to understand code.
- Readability.
- Complexity.
- Reading flow.
- Code that shares context.
Reading:
- Code reading.
- Code reviews.
- Pair Programming.