Sachpazis Costas: Geotechnical Engineering: A student's Perspective Introduction
Â
How to write good quality code
1. Code Quality
A brief introduction to writing code that is
scalable, shareable and usable.
Wednesday, 18th May 2016
2. Hayden Bleasel
Product Designer, Entrepreneur &
Full-Stack Developer. Previously
at Zookal, Sumry and Palantir.
@haydenbleasel on Twitter,
GitHub and pretty much
everywhere else.
Nice to meet you.
3. What languages do you write and how
do you ensure code quality?
Quick Question
4. ⢠Bad code: use once, copied from StackOverďŹow, thrown
away after or used to hotďŹx a bug
⢠Good code: used multiple times over several projects,
maybe a small plugin
⢠Great code: well-thought-out, up to date, unit tested and
maybe even open-sourced and built by the community
⢠We need to measure and enforce quality code.
What is âQuality Codeâ?
5. ⢠Clear and understandable design and implementation.
⢠Well deďŹned interfaces.
⢠Ease of build and use.
⢠Ease of extensibility.
⢠Minimum extra dependencies.
⢠Tests and examples.
⢠Great documentation or self-explaining code.
⢠Up to date means to contact the developer.
Goals of Quality Code
6. ⢠European Space Agency took 10 years and $8
billion dollars to develop Ariane 5 (heavy lift
launch rocket).
⢠On June 4, 1996, it took its ďŹrst voyage with $500
million cargo. In 40 seconds its inertial reference
system failed.
⢠64-bit ďŹoating point number representing the
horizontal velocity of the rocket was converted
into 16-bit signed integer â conversion failed
because of overďŹow.
Why bother with quality?
7. ⢠Finding, ďŹxing problem in production is 100 times more expensive than during
requirements / design phase.
⢠40-50% of effort on projects is on avoidable rework.
⢠~80% of avoidable rework comes from 20% of defects.
⢠~80% of defects come from 20% of modules; about half the modules are defect free.
⢠~90% of downtime comes from at most 10% of defects.
⢠Peer reviews catch 60% of defects.
⢠Perspective-based reviews catch 35% more defects than nondirected reviews.
⢠Disciplined personal practices can reduce defect introduction rates by up to 75%.
⢠~40-50% of user programs have nontrivial defects.
But seriously, why bother?
8. ⢠Nobody has time to check their code, weâre all
busy trying to make amazing things.
⢠You need 2 things:
A. To know how to write good code (you think
you do but you really donât).
B. To start using an array of tools and workďŹow
to your advantage.
But I donât have time to check code!
9. ⢠Not really. The QA is meant to go over your output
and look for bugs in runtime and edge cases, not
to browse your junk code and make incremental
improvements.
⢠The only thing that does is gives the QA a reason
to yell at you about writing janky code and youâll
go back to the drawing board (that, or more likely
itâll leak into production and hilarity ensues).
Isnât this the job of a QA?
10. This is basically a giant to-do list for when you go home,
things you can add to your product, startup or app.
Practical Implementation
12. ⢠Writing code with style
⢠Keeping code in check
⢠Making code less confusing
Overview
⢠Managing dependencies
⢠Git and GitHub
⢠Automation and Testing
14. ⢠Donât give variables cryptic names e.g.
Meaningful Variable Names
001. Writing code with style
x1 = 60;
x2 = 24;
x12 = x1 * x2;
⢠They donât save space - you can compress the
output using a miniďŹer. Might as well just use:
minutesPerHour = 60;
hoursPerDay = 24;
minutesPerDay = minutesPerHour * hoursPerDay;
15. ⢠This doesnât lead to scalable code:
Using Constants
001. Writing code with style
coffee = makeCoffee(2)
⢠What does 2 mean? What does this function even
accept? We can introduce constants here:
SIZES = { small: 1, large: 2 };
coffee = makeCoffee(SIZES.large)
⢠We generally use uppercase for constants.
16. ⢠This function utilises itâs purpose stringently:
Flexible functions
001. Writing code with style
makeGrid = function (width) {
for (var i = 0; i < 12; i++) {
makeColumn(12 / width, 30);
}
}
⢠We can make this a bit more ďŹexible:
makeGrid = function (width, columns, gutter) {
for (var i = 0; i < columns; i++) {
makeColumn(columns / width, gutter);
}
}
makeGrid(1170)
makeGrid(1170, 12, 30)
17. ⢠Itâs pretty simple stuff, just go through all your
code and ďŹnd thing to improve or ďŹx.
⢠Look for runtime errors (overďŹows, type checking,
overwriting variables, memory leaks, etc).
⢠Look for syntax errors (missing a bracket or
semicolon, using 1 ampersand instead of 2)
⢠Look for logic errors (passing in the wrong
number, calling the wrong function).
Code Analysis
001. Writing code with style
18. ⢠There are two pretty fundamental things you
should avoid when writing large projects
(especially for open-source):
⢠Black boxes: Functions where parameters go
into, pure magic happens and an output comes
out, but we have no idea how it works.
⢠TODOs and Hacky Workarounds: Avoid them.
However, if youâve got hacks or unďŹnished
code, document them somewhere outsite the
codebase, like GitHub issues.
Avoid Black Boxes and Hacks
001. Writing code with style
19. ⢠More lines of code typically means less code
quality. In each ďŹle or function, pick one thing and
do it really well, a bit like running a startup.
⢠Repeated lines of code or code that looks
incredibly similar in terms of structure and
purpose can be rewritten as a function.
⢠Seperate your code out into different ďŹles. Make
sure each ďŹle handles a small part of your app.
Refactoring and LOC
001. Writing code with style
20. ⢠If your linter, terminal or whatever throws a
warning, donât ignore it.
⢠Warnings can outline hidden problems that youâll
run into severely later on.
⢠Use the compiler or linter to treat warnings as
errors and youâll be writing amazing code.
⢠If absolutely necessary (legacy code or
something), you can suppress warnings.
Treat Warnings as Errors
001. Writing code with style
21. ⢠Some languages, like Javascript and Perl, have a Strict mode that
you can enable.
⢠It makes several changes to normal language semantics.
⢠In JavaScript for example, Strict Mode:
⢠Eliminates some silent errors by changing them to throw errors.
⢠Fixes mistakes that make it difďŹcult for JavaScript engines to
perform optimisations: strict mode code can sometimes be
made to run faster than identical code that's not strict mode.
⢠Prohibits some syntax likely to be deďŹned in future versions of
ECMAScript.
Strict Mode
001. Writing code with style
23. ⢠A giant report documenting how you
and your collaborators should write
code on a particular project.
⢠Google has a massive one covering
every language they use: https://
github.com/google/styleguide
⢠Useful for when youâre running a
company or agency where heaps of
people are touching the same code.
Style Guides
002. Keeping code in check
24. ⢠Everything weâve just discussed - thatâs a lot of
work. Checking, refactoring, rewritingâŚ
⢠Wouldnât it be better if the code just checked
itself? (before it wrecked itself)
⢠Welcome to the wonderful world of rules. You
want your codebase to have rules, such as âmake
sure every ďŹle ends with a newlineâ and âmake
sure I use anonymous function callbacks all the
timeâ. The possibilities are endless.
Automagical code checking
002. Keeping code in check
25. ⢠Check it out at http://
editorconďŹg.org/
⢠Comes as a plugin for almost
every text editor and IDE
imaginable.
⢠DeďŹne extension-based rules
like newlines, charsets and
indenting.
⢠Runs and ďŹxes on ďŹle save.
.editorconďŹg
002. Keeping code in check
root = true
[*]
end_of_line = lf
insert_final_newline = true
charset = utf-8
indent_style = space
indent_size = 4
[*.json]
indent_size = 2
26. ⢠My absolute favourite part of
this topic on code quality.
⢠Linters are absolutely
amazing and indispensable.
⢠They check your code as
youâre writing it.
⢠They literally enforce your
style on everyone else.
Linting
002. Keeping code in check
27. ⢠Some languages, like Javascript, have lots of
linters to choose from: JSLint, ESLint, JSHint, etc.
All of these can be conďŹgured, but the default
options and extensibility varies.
⢠ESLint is the one shown in these examples. Itâs
the newest, most extensible linter for Javascript.
⢠You can most linters via CLI, automation module
(Gulp or Grunt) and text editor plugin.
Choosing a Linter
002. Keeping code in check
28. "comma-dangle": [2, "never"],
"no-cond-assign": [2, "always"],
"no-console": 0,
"no-constant-condition": 2,
"no-control-regex": 2,
"no-debugger": 2,
"no-dupe-args": 2,
"no-dupe-keys": 2,
"no-duplicate-case": 2,
"no-empty-character-class": 2,
"no-empty": 2,
Linter ConďŹguration
002. Keeping code in check
⢠ConďŹguring your linter is a tedious process.
My .eslintrc is 350 lines long:â¨
eslint.haydenbleasel.com
29. How I use my linter
002. Keeping code in check
brew cask install atom
apm install linter linter-eslint
npm install -g eslint
⢠Getting a Linter set up is mad easy. Just install the
module and plugins:
⢠Thatâs it! Just start writing code and save!
31. ⢠Text editors can massively affect code quality,
from default intent style to external plugins.
⢠I use Atom, a text editor by GitHub. It comes with
an inbuilt package manager.
⢠Packages like linter (+eslint), atom-beautify and
editorconďŹg address things weâve talked about.
Text Editors and Plugins
002. Keeping code in check
33. ⢠Coupling determines how much one component
of your code knows about the inner workings of
another. We want to aim for LOW coupling.
⢠Ex: iPods are a good example of tight coupling:
once the battery dies you might as well buy a new
iPod because the battery is soldered ďŹxed and
wonât come loose, thus making replacing very
expensive. A loosely coupled player would allow
effortlessly changing the battery.
Coupling
003. Making code less confusing
34. ⢠Cohesion refers to the extent that a component
of your code is focused only on what it should be
doing. We want to aim for HIGH cohesion.
Cohesion
003. Making code less confusing
function main (a, b) {
var x = (a * b) / 3;
var body = $(âbodyâ);
body.appendChild(x);
}
main(1,2);
function multiply (a, b) {
return (a * b) / 3;
}
function append (number) {
var body = $(âbodyâ);
body.appendChild(number);
}
var number = multiply(1,2);
append(number);
35. ⢠There are two main ways to minimise the complexity of
your code. Neither should be your ultimatum, but rather
a great referencing guide:
1. Pretty simple: just minimise the number of
parameters, depth (nesting) and statements per
function
2. Run a cyclomatic complexity test. It calculates
the overall intricacy of a function and to give a
score that reďŹects itâs complexity. Lower is better.
Complexity
003. Making code less confusing
37. ⢠A common pitfall that results in loss of code quality,
even in large organisations, is poor dependency
management.
⢠Vendor code is downloaded, chucked in a random
folder and modiďŹed to the core if it doesnât work the
way you want it to.
⢠This results in all sorts of bugs and creates a generally
crap work environment for the developer.
Dependency Management
004. Managing dependencies
38. ⢠Bower is a package
management system
developed by Twitter.
⢠Bower is used to download
and manage front-end
development packages like
jQuery and Bootstrap.
⢠For example:
Bower
004. Managing dependencies
bower install jquery --save
39. ⢠Server-side applications also have dependency
management, except much better.
⢠Node.js has NPM, Ruby has Bundler and PHP has
Composer. There are plenty of dependency
management tools out there for any language.
⢠Rather than messing around with ďŹles and versions,
just get the latest version of Request with:
NPM / Bundler / Composer
004. Managing dependencies
npm install request --save-dev
40. ⢠If youâre not using a dependency manager but still want
to maintain the integrity and separation of your
codebase from third-party components, CDNJS is a
good option.
⢠Again, front-end components. Doesnât have everything
but should have 99% of what you need.
⢠Just throw in a script tag like:
CDNJS
004. Managing dependencies
<script src=âhttps://cdnjs.cloudflare.com/ajax/libs/jquery/
3.0.0-beta1/jquery.min.js"></script>
42. ⢠You should kinda know this already. Git tracks version
history so you can see what youâve done, revert
changes and blame mistakes on other people.
⢠Remember to check in your code in small batches,
frequently. Reverting massive amounts of unrelated
code is a nightmare plus it helps avoid merge conďŹicts.
⢠Version control is also helpful for semver integrity.
Version Control
005. Git and GitHub
43. ⢠GitHub is the best platform ever for developers.
⢠Use Issues to track your TODOs, hacky workarounds,
suggestions from others, etc. Keep the discussion out
of your codebase.
⢠Use PRs to ďŹlter external changes to your code. PRs
allow for Code Reviews where you can go through
every change in the diff and add comments.
Issues and PRs
005. Git and GitHub
44. ⢠Can happen in a variety of ways, but likely when you
gather all the homies together and start reviewing
code that youâve written or thatâs in your codebase.
⢠Great way to pick up and debate really small things that
might lead to a signiďŹcant improvement in
performance, or maybe just be really pedantic.
⢠Theoretically, youâre meant to be positive i.e. instead of
âthatâs lousy long methodâ say, âwhy donât you split
that methodâŚâ but TBH most of us are savages.
Code Reviews
005. Git and GitHub
46. ⢠The original task-runner.
⢠Their architectural concept
sucks (pickup and put-down)
but itâs pretty widely used.
⢠Stop writing production code
in source, focus on quality of
source code and let your
automation handle the rest.
Grunt
006. Automation and Testing
47. ⢠Best task runner available -
unix streaming ideology
inside the JS ecosystem.
⢠Set up a bunch of tasks and
send ďŹles through the
pipeline (stream) without
touching the ďŹle system.
⢠Compile languages, remove
debug code, whatever.
Gulp
006. Automation and Testing
48. ⢠Write a script to test your
app. Can be as simple as
ânpm startâ which just runs
the app.
⢠Will automatically run this
every time you push to
GitHub.
⢠Also tests GitHub PRs - test
new code before you merge.
Travis CI
006. Automation and Testing
49. ⢠So youâve written unit tests for your code, but how
much have you written in the scheme of things?
⢠JS has Mocha, Chai, Istanbul and other libraries to
handle this sort of things.
⢠Itâs called test coverage - TL;DR it will give you a report
on how much of your codebase is covered by unit tests.
Most of them compute statement, line, function and
branch coverage with module loader hooks.
Coverage
006. Automation and Testing
50. Go forth and stop writing bad code.
Thatâs everything
http://codequality.haydenbleasel.com/